# HG changeset patch # User David Demelier # Date 1635062112 -7200 # Node ID c74ab1bbedecb7f2a3565d024163c63bb5a452e2 # Parent 12367bfc2df686251faaa7bad271a073736da2f8 js: add drawable bindings diff -r 12367bfc2df6 -r c74ab1bbedec src/libmlk-core-js/CMakeLists.txt --- a/src/libmlk-core-js/CMakeLists.txt Fri Oct 22 14:40:03 2021 +0200 +++ b/src/libmlk-core-js/CMakeLists.txt Sun Oct 24 09:55:12 2021 +0200 @@ -28,6 +28,10 @@ ${libmlk-core-js_SOURCE_DIR}/core/js-color.h ${libmlk-core-js_SOURCE_DIR}/core/js-core.c ${libmlk-core-js_SOURCE_DIR}/core/js-core.h + ${libmlk-core-js_SOURCE_DIR}/core/js-drawable.c + ${libmlk-core-js_SOURCE_DIR}/core/js-drawable.h + ${libmlk-core-js_SOURCE_DIR}/core/js-drawable-stack.c + ${libmlk-core-js_SOURCE_DIR}/core/js-drawable-stack.h ${libmlk-core-js_SOURCE_DIR}/core/js-event.c ${libmlk-core-js_SOURCE_DIR}/core/js-event.h ${libmlk-core-js_SOURCE_DIR}/core/js-font.c diff -r 12367bfc2df6 -r c74ab1bbedec src/libmlk-core-js/core/js-drawable-stack.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/libmlk-core-js/core/js-drawable-stack.c Sun Oct 24 09:55:12 2021 +0200 @@ -0,0 +1,124 @@ +/* + * js-drawable-stack.h -- core drawable_stack binding + * + * Copyright (c) 2020-2021 David Demelier + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include + +#include "js-drawable-stack.h" +#include "js-drawable.h" + +#define SIGNATURE DUK_HIDDEN_SYMBOL("Mlk.DrawableStack") + +static inline struct drawable_stack * +self(duk_context *ctx) +{ + struct drawable_stack *sf = NULL; + + duk_push_this(ctx); + duk_get_prop_string(ctx, -1, SIGNATURE); + sf = duk_to_pointer(ctx, -1); + duk_pop_2(ctx); + + if (!sf) + duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a DrawableStack object"); + + return sf; +} + +static duk_ret_t +DrawableStack_constructor(duk_context *ctx) +{ + duk_push_this(ctx); + duk_push_pointer(ctx, alloc_new0(sizeof (struct drawable_stack))); + duk_put_prop_string(ctx, -2, SIGNATURE); + duk_pop(ctx); + + return 0; +} + +static duk_ret_t +DrawableStack_destructor(duk_context *ctx) +{ + struct drawable_stack *st; + + duk_get_prop_string(ctx, 0, SIGNATURE); + + if ((st = duk_to_pointer(ctx, -1))) { + drawable_stack_finish(st); + free(st); + } + + duk_pop(ctx); + duk_del_prop_string(ctx, 0, SIGNATURE); + + return 0; +} + +static duk_ret_t +DrawableStack_add(duk_context *ctx) +{ + struct drawable_stack *st = self(ctx); + struct drawable *dw = js_drawable_require(ctx, 0); + + if (drawable_stack_add(st, dw) < 0) + drawable_finish(dw); + + return 0; +} + +static duk_ret_t +DrawableStack_update(duk_context *ctx) +{ + struct drawable_stack *st = self(ctx); + const unsigned int ticks = duk_require_uint(ctx, 0); + + duk_push_uint(ctx, drawable_stack_update(st, ticks)); + + return 1; +} + +static duk_ret_t +DrawableStack_draw(duk_context *ctx) +{ + drawable_stack_draw(self(ctx)); + + return 0; +} + +static duk_function_list_entry methods[] = { + { "add", DrawableStack_add, 1 }, + { "update", DrawableStack_update, 1 }, + { "draw", DrawableStack_draw, 0 }, + { NULL, NULL, 0 } +}; + +void +js_drawable_stack_bind(duk_context *ctx) +{ + assert(ctx); + + duk_push_c_function(ctx, DrawableStack_constructor, 0); + duk_push_object(ctx); + duk_put_function_list(ctx, -1, methods); + duk_push_c_function(ctx, DrawableStack_destructor, 1); + duk_set_finalizer(ctx, -2); + duk_put_prop_string(ctx, -2, "prototype"); + duk_put_global_string(ctx, "DrawableStack"); +} diff -r 12367bfc2df6 -r c74ab1bbedec src/libmlk-core-js/core/js-drawable-stack.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/libmlk-core-js/core/js-drawable-stack.h Sun Oct 24 09:55:12 2021 +0200 @@ -0,0 +1,27 @@ +/* + * js-drawable-stack.h -- core drawable_stack binding + * + * Copyright (c) 2020-2021 David Demelier + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef MLK_CORE_JS_DRAWABLE_STACK_H +#define MLK_CORE_JS_DRAWABLE_STACK_H + +#include + +void +js_drawable_stack_bind(duk_context *); + +#endif /* !MLK_CORE_JS_DRAWABLE_STACK_H */ diff -r 12367bfc2df6 -r c74ab1bbedec src/libmlk-core-js/core/js-drawable.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/libmlk-core-js/core/js-drawable.c Sun Oct 24 09:55:12 2021 +0200 @@ -0,0 +1,233 @@ +/* + * js-drawable.c -- core drawable binding + * + * Copyright (c) 2020-2021 David Demelier + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include + +#include "js-drawable.h" + +#define SIGNATURE DUK_HIDDEN_SYMBOL("Mlk.Drawable") + +struct self { + duk_context *ctx; + void *ptr; + struct drawable dw; + unsigned int refc; +}; + +static inline struct self * +self(duk_context *ctx) +{ + struct self *sf = NULL; + + duk_push_this(ctx); + duk_get_prop_string(ctx, -1, SIGNATURE); + sf = duk_to_pointer(ctx, -1); + duk_pop_2(ctx); + + if (!sf) + duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a Drawable object"); + + return sf; +} + +static inline int +callable(struct self *s, const char *prop, duk_context **ctx) +{ + int callable; + + if (!s->ptr) + return 0; + + duk_push_heapptr(s->ctx, s->ptr); + duk_get_prop_string(s->ctx, -1, prop); + duk_remove(s->ctx, -2); + + if (duk_is_callable(s->ctx, -1)) { + *ctx = s->ctx; + callable = 1; + } else { + *ctx = NULL; + callable = 0; + duk_pop(s->ctx); + } + + return callable; +} + +static int +update(struct drawable *dw, unsigned int ticks) +{ + duk_context *ctx; + int ret = 0; + + if (callable(dw->data, "update", &ctx)) { + duk_push_uint(ctx, ticks); + duk_call(ctx, 1); + ret = duk_to_int(ctx, -1); + } + + return ret; +} + +static void +draw(struct drawable *dw) +{ + duk_context *ctx; + + if (callable(dw->data, "draw", &ctx)) + duk_call(ctx, 0); +} + +static void +end(struct drawable *dw) +{ + duk_context *ctx; + + if (callable(dw->data, "end", &ctx)) + duk_call(ctx, 0); +} + +static void +finish(struct drawable *dw) +{ + struct self *sf = dw->data; + + if (!--sf->refc) + free(sf); +} + +static duk_ret_t +Drawable_getX(duk_context *ctx) +{ + duk_push_uint(ctx, self(ctx)->dw.x); + + return 1; +} + +static duk_ret_t +Drawable_setX(duk_context *ctx) +{ + self(ctx)->dw.x = duk_require_uint(ctx, 0); + + return 0; +} + +static duk_ret_t +Drawable_getY(duk_context *ctx) +{ + duk_push_uint(ctx, self(ctx)->dw.y); + + return 1; +} + +static duk_ret_t +Drawable_setY(duk_context *ctx) +{ + self(ctx)->dw.y = duk_require_uint(ctx, 0); + + return 0; +} + +static duk_ret_t +Drawable_constructor(duk_context *ctx) +{ + struct self *self; + const int x = duk_require_int(ctx, 0); + const int y = duk_require_int(ctx, 1); + + self = alloc_new0(sizeof (*self)); + self->refc = 1; + self->ctx = ctx; + self->dw.x = x; + self->dw.y = y; + self->dw.data = self; + self->dw.update = update; + self->dw.finish = finish; + self->dw.draw = draw; + self->dw.end = end; + + duk_push_this(ctx); + self->ptr = duk_get_heapptr(ctx, -1); + duk_push_pointer(ctx, self); + duk_put_prop_string(ctx, -2, SIGNATURE); + duk_push_string(ctx, "x"); + duk_push_c_function(ctx, Drawable_getX, 0); + duk_push_c_function(ctx, Drawable_setX, 1); + duk_def_prop(ctx, -4, DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_HAVE_SETTER); + duk_push_string(ctx, "y"); + duk_push_c_function(ctx, Drawable_getY, 0); + duk_push_c_function(ctx, Drawable_setY, 1); + duk_def_prop(ctx, -4, DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_HAVE_SETTER); + duk_pop(ctx); + + return 0; +} + +static duk_ret_t +Drawable_destructor(duk_context *ctx) +{ + struct self *sf; + + duk_get_prop_string(ctx, 0, SIGNATURE); + + if ((sf = duk_to_pointer(ctx, -1))) { + sf->ptr = NULL; + drawable_finish(&sf->dw); + } + + duk_del_prop_string(ctx, 0, SIGNATURE); + duk_pop(ctx); + + return 0; +} + + +void +js_drawable_bind(duk_context *ctx) +{ + assert(ctx); + + duk_push_c_function(ctx, Drawable_constructor, 2); + duk_push_object(ctx); + duk_push_c_function(ctx, Drawable_destructor, 1); + duk_set_finalizer(ctx, -2); + duk_put_prop_string(ctx, -2, "prototype"); + duk_put_global_string(ctx, "Drawable"); +} + +struct drawable * +js_drawable_require(duk_context *ctx, duk_idx_t idx) +{ + struct self *sf = NULL; + + if (duk_is_object(ctx, idx)) { + duk_get_prop_string(ctx, idx, SIGNATURE); + sf = duk_to_pointer(ctx, -1); + duk_pop(ctx); + } + + if (!sf) + duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a Drawable object"); + + sf->refc++; + + return &sf->dw; +} diff -r 12367bfc2df6 -r c74ab1bbedec src/libmlk-core-js/core/js-drawable.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/libmlk-core-js/core/js-drawable.h Sun Oct 24 09:55:12 2021 +0200 @@ -0,0 +1,32 @@ +/* + * js-drawable.h -- core drawable binding + * + * Copyright (c) 2020-2021 David Demelier + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef MLK_CORE_JS_DRAWABLE_H +#define MLK_CORE_JS_DRAWABLE_H + +#include + +struct drawable; + +void +js_drawable_bind(duk_context *); + +struct drawable * +js_drawable_require(duk_context *, duk_idx_t); + +#endif /* !MLK_CORE_JS_DRAWABLE_H */ diff -r 12367bfc2df6 -r c74ab1bbedec src/libmlk-core-js/core/js-state.c --- a/src/libmlk-core-js/core/js-state.c Fri Oct 22 14:40:03 2021 +0200 +++ b/src/libmlk-core-js/core/js-state.c Sun Oct 24 09:55:12 2021 +0200 @@ -26,11 +26,10 @@ #include "js-state.h" #define SIGNATURE DUK_HIDDEN_SYMBOL("Mlk.State") -#define SELF DUK_HIDDEN_SYMBOL("Mlk.State.self") struct self { duk_context *ctx; - void *selfptr; + void *ptr; struct state state; unsigned int refc; }; @@ -40,7 +39,10 @@ { int callable; - duk_push_heapptr(s->ctx, s->selfptr); + if (!s->ptr) + return 0; + + duk_push_heapptr(s->ctx, s->ptr); duk_get_prop_string(s->ctx, -1, prop); duk_remove(s->ctx, -2); @@ -140,28 +142,8 @@ { struct self *self = state->data; - if (!--self->refc) { - duk_push_heapptr(self->ctx, self->selfptr); - duk_del_prop_string(self->ctx, -1, SIGNATURE); - duk_pop(self->ctx); + if (!--self->refc) free(self); - } -} - -static inline struct self * -self(duk_context *ctx) -{ - struct self *data = NULL; - - duk_push_this(ctx); - duk_get_prop_string(ctx, -1, SIGNATURE); - data = duk_to_pointer(ctx, -1); - duk_pop_2(ctx); - - if (!data) - return (void)duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a State object"), NULL; - - return data; } static duk_ret_t @@ -183,9 +165,7 @@ self->state.finish = finish; duk_push_this(ctx); - self->selfptr = duk_get_heapptr(ctx, -1); - duk_dup(ctx, -1); - duk_put_prop_string(ctx, -2, SELF); + self->ptr = duk_get_heapptr(ctx, -1); duk_push_pointer(ctx, self); duk_put_prop_string(ctx, -2, SIGNATURE); duk_pop(ctx); @@ -200,8 +180,10 @@ duk_get_prop_string(ctx, 0, SIGNATURE); - if ((self = duk_to_pointer(ctx, -1))) + if ((self = duk_to_pointer(ctx, -1))) { + self->ptr = NULL; state_finish(&self->state); + } duk_pop(ctx); diff -r 12367bfc2df6 -r c74ab1bbedec src/mlk-run/main.c --- a/src/mlk-run/main.c Fri Oct 22 14:40:03 2021 +0200 +++ b/src/mlk-run/main.c Sun Oct 24 09:55:12 2021 +0200 @@ -30,6 +30,8 @@ #include #include #include +#include +#include #include #include #include @@ -66,6 +68,8 @@ js_animation_bind(ctx); js_clock_bind(ctx); js_color_bind(ctx); + js_drawable_bind(ctx); + js_drawable_stack_bind(ctx); js_event_bind(ctx); js_font_bind(ctx); js_game_bind(ctx);