Mercurial > molko
changeset 371:8ac282bd5935
js: add action bindings
author | David Demelier <markand@malikania.fr> |
---|---|
date | Mon, 25 Oct 2021 12:43:09 +0200 |
parents | ea7a24c814e4 |
children | 3c378be73844 |
files | src/libmlk-core-js/CMakeLists.txt src/libmlk-core-js/core/js-action-stack.c src/libmlk-core-js/core/js-action-stack.h src/libmlk-core-js/core/js-action.c src/libmlk-core-js/core/js-action.h src/libmlk-core-js/core/js-drawable-stack.c src/libmlk-core-js/core/js-drawable.c src/libmlk-core-js/core/js-event.c src/libmlk-core-js/core/js-event.h src/libmlk-core/core/sys.c src/mlk-run/main.c |
diffstat | 11 files changed, 464 insertions(+), 12 deletions(-) [+] |
line wrap: on
line diff
--- a/src/libmlk-core-js/CMakeLists.txt Sun Oct 24 17:38:01 2021 +0200 +++ b/src/libmlk-core-js/CMakeLists.txt Mon Oct 25 12:43:09 2021 +0200 @@ -20,6 +20,10 @@ set( SOURCES + ${libmlk-core-js_SOURCE_DIR}/core/js-action-stack.c + ${libmlk-core-js_SOURCE_DIR}/core/js-action-stack.h + ${libmlk-core-js_SOURCE_DIR}/core/js-action.c + ${libmlk-core-js_SOURCE_DIR}/core/js-action.h ${libmlk-core-js_SOURCE_DIR}/core/js-animation.c ${libmlk-core-js_SOURCE_DIR}/core/js-animation.h ${libmlk-core-js_SOURCE_DIR}/core/js-clock.c @@ -28,10 +32,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-stack.c + ${libmlk-core-js_SOURCE_DIR}/core/js-drawable-stack.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 @@ -44,8 +48,6 @@ ${libmlk-core-js_SOURCE_DIR}/core/js-painter.h ${libmlk-core-js_SOURCE_DIR}/core/js-panic.c ${libmlk-core-js_SOURCE_DIR}/core/js-panic.h - ${libmlk-core-js_SOURCE_DIR}/core/js-trace.c - ${libmlk-core-js_SOURCE_DIR}/core/js-trace.h ${libmlk-core-js_SOURCE_DIR}/core/js-sound.c ${libmlk-core-js_SOURCE_DIR}/core/js-sound.h ${libmlk-core-js_SOURCE_DIR}/core/js-sprite.c @@ -54,6 +56,8 @@ ${libmlk-core-js_SOURCE_DIR}/core/js-state.h ${libmlk-core-js_SOURCE_DIR}/core/js-texture.c ${libmlk-core-js_SOURCE_DIR}/core/js-texture.h + ${libmlk-core-js_SOURCE_DIR}/core/js-trace.c + ${libmlk-core-js_SOURCE_DIR}/core/js-trace.h ${libmlk-core-js_SOURCE_DIR}/core/js-window.c ${libmlk-core-js_SOURCE_DIR}/core/js-window.h )
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/libmlk-core-js/core/js-action-stack.c Mon Oct 25 12:43:09 2021 +0200 @@ -0,0 +1,143 @@ +/* + * js-drawable-stack.h -- core drawable_stack binding + * + * Copyright (c) 2020-2021 David Demelier <markand@malikania.fr> + * + * 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 <assert.h> + +#include <core/action.h> +#include <core/action-stack.h> +#include <core/alloc.h> + +#include "js-event.h" +#include "js-action-stack.h" +#include "js-action.h" + +#define SIGNATURE DUK_HIDDEN_SYMBOL("Mlk.ActionStack") + +static inline struct action_stack * +self(duk_context *ctx) +{ + struct action_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) + return (void)duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a ActionStack object"), NULL; + + return sf; +} + +static duk_ret_t +ActionStack_constructor(duk_context *ctx) +{ + duk_push_this(ctx); + duk_push_pointer(ctx, alloc_new0(sizeof (struct action_stack))); + duk_put_prop_string(ctx, -2, SIGNATURE); + duk_pop(ctx); + + return 0; +} + +static duk_ret_t +ActionStack_destructor(duk_context *ctx) +{ + struct action_stack *st; + + duk_get_prop_string(ctx, 0, SIGNATURE); + + if ((st = duk_to_pointer(ctx, -1))) { + action_stack_finish(st); + free(st); + } + + duk_pop(ctx); + duk_del_prop_string(ctx, 0, SIGNATURE); + + return 0; +} + +static duk_ret_t +ActionStack_add(duk_context *ctx) +{ + struct action_stack *st = self(ctx); + struct js_action *act = js_action_require(ctx, 0); + + if (action_stack_add(st, &act->act) < 0) + action_finish(&act->act); + else { + duk_push_this(ctx); + act->parent = duk_get_heapptr(ctx, -1); + duk_push_sprintf(ctx, "%p", act); + duk_dup(ctx, 0); + duk_put_prop(ctx, -3); + duk_pop(ctx); + } + + return 0; +} + +static duk_ret_t +ActionStack_handle(duk_context *ctx) +{ + action_stack_handle(self(ctx), js_event_require(ctx, 0)); + + return 0; +} + +static duk_ret_t +ActionStack_update(duk_context *ctx) +{ + struct action_stack *st = self(ctx); + const unsigned int ticks = duk_require_uint(ctx, 0); + + duk_push_uint(ctx, action_stack_update(st, ticks)); + + return 1; +} + +static duk_ret_t +ActionStack_draw(duk_context *ctx) +{ + action_stack_draw(self(ctx)); + + return 0; +} + +static duk_function_list_entry methods[] = { + { "add", ActionStack_add, 1 }, + { "handle", ActionStack_handle, 1 }, + { "update", ActionStack_update, 1 }, + { "draw", ActionStack_draw, 0 }, + { NULL, NULL, 0 } +}; + +void +js_action_stack_bind(duk_context *ctx) +{ + assert(ctx); + + duk_push_c_function(ctx, ActionStack_constructor, 0); + duk_push_object(ctx); + duk_put_function_list(ctx, -1, methods); + duk_push_c_function(ctx, ActionStack_destructor, 1); + duk_set_finalizer(ctx, -2); + duk_put_prop_string(ctx, -2, "prototype"); + duk_put_global_string(ctx, "ActionStack"); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/libmlk-core-js/core/js-action-stack.h Mon Oct 25 12:43:09 2021 +0200 @@ -0,0 +1,27 @@ +/* + * js-action-stack.h -- core action_stack binding + * + * Copyright (c) 2020-2021 David Demelier <markand@malikania.fr> + * + * 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_ACTION_STACK_H +#define MLK_CORE_JS_ACTION_STACK_H + +#include <duktape.h> + +void +js_action_stack_bind(duk_context *); + +#endif /* !MLK_CORE_JS_ACTION_STACK_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/libmlk-core-js/core/js-action.c Mon Oct 25 12:43:09 2021 +0200 @@ -0,0 +1,193 @@ +/* + * js-action.c -- core action binding + * + * Copyright (c) 2020-2021 David Demelier <markand@malikania.fr> + * + * 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 <assert.h> +#include <stdlib.h> + +#include <core/alloc.h> +#include <core/action.h> + +#include "js-action.h" +#include "js-event.h" + +#define SIGNATURE DUK_HIDDEN_SYMBOL("Mlk.Action") + +static inline duk_context * +callable(struct js_action *data, const char *prop) +{ + duk_context *ctx; + + if (!data->ptr) + return NULL; + + duk_push_heapptr(data->ctx, data->ptr); + duk_get_prop_string(data->ctx, -1, prop); + duk_pull(data->ctx, -2); + + if (duk_is_callable(data->ctx, -2)) + ctx = data->ctx; + else { + ctx = NULL; + duk_pop_n(data->ctx, 2); + } + + return ctx; +} + +static void +handle(struct action *data, const union event *ev) +{ + duk_context *ctx; + + if ((ctx = callable(data->data, "handle"))) { + js_event_push(ctx, ev); + duk_call_method(ctx, 1); + duk_pop(ctx); + } +} + +static int +update(struct action *data, unsigned int ticks) +{ + duk_context *ctx; + int ret = 0; + + if ((ctx = callable(data->data, "update"))) { + duk_push_uint(ctx, ticks); + duk_call_method(ctx, 1); + ret = duk_to_int(ctx, -1); + duk_pop(ctx); + } + + return ret; +} + +static void +draw(struct action *data) +{ + duk_context *ctx; + + if ((ctx = callable(data->data, "draw"))) { + duk_call_method(ctx, 0); + duk_pop(ctx); + } +} + +static void +end(struct action *data) +{ + duk_context *ctx; + + if ((ctx = callable(data->data, "end"))) { + duk_call_method(ctx, 0); + duk_pop(ctx); + } +} + +static void +finish(struct action *act) +{ + struct js_action *data = act->data; + + /* I must not be called anymore. */ + data->ptr = NULL; + + /* Remove myself from parent stack if any. */ + if (data->parent) { + duk_push_heapptr(data->ctx, data->parent); + duk_push_sprintf(data->ctx, "%p", data); + duk_del_prop(data->ctx, -2); + duk_pop(data->ctx); + data->parent = NULL; + } + + if (--data->refc == 0) + free(data); +} + +static duk_ret_t +Action_constructor(duk_context *ctx) +{ + struct js_action *data; + + data = alloc_new0(sizeof (*data)); + data->ctx = ctx; + data->refc = 1; + data->act.data = data; + data->act.handle = handle; + data->act.update = update; + data->act.finish = finish; + data->act.draw = draw; + data->act.end = end; + + duk_push_this(ctx); + data->ptr = duk_get_heapptr(ctx, -1); + duk_push_pointer(ctx, data); + duk_put_prop_string(ctx, -2, SIGNATURE); + duk_pop(ctx); + + return 0; +} + +static duk_ret_t +Action_destructor(duk_context *ctx) +{ + struct js_action *data; + + duk_get_prop_string(ctx, 0, SIGNATURE); + + if ((data = duk_to_pointer(ctx, -1))) + action_finish(&data->act); + + duk_del_prop_string(ctx, 0, SIGNATURE); + duk_pop(ctx); + + return 0; +} + +void +js_action_bind(duk_context *ctx) +{ + assert(ctx); + + duk_push_c_function(ctx, Action_constructor, 0); + duk_push_object(ctx); + duk_push_c_function(ctx, Action_destructor, 1); + duk_set_finalizer(ctx, -2); + duk_put_prop_string(ctx, -2, "prototype"); + duk_put_global_string(ctx, "Action"); +} + +struct js_action * +js_action_require(duk_context *ctx, duk_idx_t idx) +{ + struct js_action *act = NULL; + + if (duk_is_object(ctx, idx)) { + duk_get_prop_string(ctx, idx, SIGNATURE); + act = duk_to_pointer(ctx, -1); + duk_pop(ctx); + } + + if (!act) + return (void)duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a Action object"), NULL; + + act->refc++; + + return act; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/libmlk-core-js/core/js-action.h Mon Oct 25 12:43:09 2021 +0200 @@ -0,0 +1,40 @@ +/* + * js-action.h -- core action binding + * + * Copyright (c) 2020-2021 David Demelier <markand@malikania.fr> + * + * 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_ACTION_H +#define MLK_CORE_JS_ACTION_H + +#include <duktape.h> + +#include <core/action.h> + +struct js_action { + duk_context *ctx; + void *ptr; + void *parent; + unsigned int refc; + struct action act; +}; + +void +js_action_bind(duk_context *); + +struct js_action * +js_action_require(duk_context *, duk_idx_t); + +#endif /* !MLK_CORE_JS_ACTION_H */
--- a/src/libmlk-core-js/core/js-drawable-stack.c Sun Oct 24 17:38:01 2021 +0200 +++ b/src/libmlk-core-js/core/js-drawable-stack.c Mon Oct 25 12:43:09 2021 +0200 @@ -38,7 +38,7 @@ duk_pop_2(ctx); if (!sf) - duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a DrawableStack object"); + return (void)duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a DrawableStack object"), NULL; return sf; } @@ -60,12 +60,12 @@ 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);
--- a/src/libmlk-core-js/core/js-drawable.c Sun Oct 24 17:38:01 2021 +0200 +++ b/src/libmlk-core-js/core/js-drawable.c Mon Oct 25 12:43:09 2021 +0200 @@ -43,7 +43,7 @@ duk_pop_2(ctx); if (!sf) - duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a Drawable object"); + return (void)duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a Drawable object"), NULL; return sf; } @@ -225,7 +225,7 @@ } if (!sf) - duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a Drawable object"); + return (void)duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a Drawable object"), NULL; sf->refc++;
--- a/src/libmlk-core-js/core/js-event.c Sun Oct 24 17:38:01 2021 +0200 +++ b/src/libmlk-core-js/core/js-event.c Mon Oct 25 12:43:09 2021 +0200 @@ -18,10 +18,13 @@ #include <assert.h> +#include <core/alloc.h> #include <core/event.h> #include "js-event.h" +#define SIGNATURE DUK_HIDDEN_SYMBOL("Mlk.Event") + static void push_click(duk_context *ctx, const union event *ev) { @@ -262,6 +265,17 @@ { NULL, 0 } }; +static duk_ret_t +Event_destructor(duk_context *ctx) +{ + duk_get_prop_string(ctx, 0, SIGNATURE); + free(duk_to_pointer(ctx, -1)); + duk_del_prop_string(ctx, 0, SIGNATURE); + duk_pop(ctx); + + return 0; +} + void js_event_bind(duk_context *ctx) { @@ -272,7 +286,7 @@ duk_put_function_list(ctx, -1, functions); duk_push_object(ctx); duk_put_number_list(ctx, -1, types); - duk_put_prop_string(ctx, -2, "type"); + duk_put_prop_string(ctx, -2, "Type"); duk_push_object(ctx); duk_put_number_list(ctx, -1, keys); duk_put_prop_string(ctx, -2, "key"); @@ -289,8 +303,33 @@ void js_event_push(duk_context *ctx, const union event *ev) { + assert(ctx); + duk_push_object(ctx); + duk_push_c_function(ctx, Event_destructor, 1); + duk_set_finalizer(ctx, -2); + duk_push_pointer(ctx, alloc_dup(ev, sizeof (*ev))); + duk_put_prop_string(ctx, -2, SIGNATURE); duk_push_int(ctx, ev->type); - duk_put_prop_string(ctx, -2, "Type"); + duk_put_prop_string(ctx, -2, "type"); push[ev->type](ctx, ev); } + +union event * +js_event_require(duk_context *ctx, duk_idx_t idx) +{ + assert(ctx); + + union event *ev = NULL; + + if (duk_is_object(ctx, idx)) { + duk_get_prop_string(ctx, idx, SIGNATURE); + ev = duk_to_pointer(ctx, -1); + duk_pop(ctx); + } + + if (!ev) + return (void)duk_error(ctx, DUK_ERR_TYPE_ERROR, "not an Event object"), NULL; + + return ev; +}
--- a/src/libmlk-core-js/core/js-event.h Sun Oct 24 17:38:01 2021 +0200 +++ b/src/libmlk-core-js/core/js-event.h Mon Oct 25 12:43:09 2021 +0200 @@ -29,4 +29,7 @@ void js_event_push(duk_context *, const union event *); +union event * +js_event_require(duk_context *, duk_idx_t); + #endif /* !MLK_CORE_JS_EVENT_H */
--- a/src/libmlk-core/core/sys.c Sun Oct 24 17:38:01 2021 +0200 +++ b/src/libmlk-core/core/sys.c Mon Oct 25 12:43:09 2021 +0200 @@ -131,7 +131,6 @@ * from: /usr/local/bin * to: /usr/local */ - printf("base=%s\n", base); port_strlcpy(path, base, sizeof (path)); SDL_free(base);
--- a/src/mlk-run/main.c Sun Oct 24 17:38:01 2021 +0200 +++ b/src/mlk-run/main.c Mon Oct 25 12:43:09 2021 +0200 @@ -26,6 +26,8 @@ #include <core/vfs-zip.h> #include <core/vfs.h> +#include <core/js-action.h> +#include <core/js-action-stack.h> #include <core/js-animation.h> #include <core/js-clock.h> #include <core/js-color.h> @@ -65,6 +67,8 @@ /* Brings Mlk global object. */ js_core_bind(ctx, &vfs); + js_action_bind(ctx); + js_action_stack_bind(ctx); js_animation_bind(ctx); js_clock_bind(ctx); js_color_bind(ctx);