# HG changeset patch # User David Demelier # Date 1604945250 -3600 # Node ID ebbcfb31482d5b017c5008f5329f0df1000e5a87 # Parent d6f217a5e4b16745adf18ad5fefa4d776c029131 js: enable Molko.Animation API diff -r d6f217a5e4b1 -r ebbcfb31482d molko-js/CMakeLists.txt --- a/molko-js/CMakeLists.txt Mon Nov 09 13:24:49 2020 +0100 +++ b/molko-js/CMakeLists.txt Mon Nov 09 19:07:30 2020 +0100 @@ -20,6 +20,8 @@ set( SOURCES + ${molko-js_SOURCE_DIR}/src/js-animation.c + ${molko-js_SOURCE_DIR}/src/js-animation.h ${molko-js_SOURCE_DIR}/src/js-clock.c ${molko-js_SOURCE_DIR}/src/js-clock.h ${molko-js_SOURCE_DIR}/src/js-event.c diff -r d6f217a5e4b1 -r ebbcfb31482d molko-js/src/js-animation.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/molko-js/src/js-animation.c Mon Nov 09 19:07:30 2020 +0100 @@ -0,0 +1,159 @@ +/* + * js-animation.c -- basic animations (Javascript bindings) + * + * Copyright (c) 2020 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 +#include + +#include "js.h" +#include "js-animation.h" +#include "js-sprite.h" +#include "js_p.h" + +#define SYMBOL DUK_HIDDEN_SYMBOL("molko::animation") +#define SPRITE_REF DUK_HIDDEN_SYMBOL("molko::animation::sprite") + +static struct animation * +js_animation_this(duk_context *ctx) +{ + struct animation *an; + + duk_push_this(ctx); + duk_get_prop_string(ctx, -1, SYMBOL); + an = duk_to_pointer(ctx, -1); + duk_pop_n(ctx, 2); + + if (!an) + duk_error(ctx, DUK_ERR_TYPE_ERROR, "Not an Animation object"); + + return an; +} + +static duk_ret_t +js_animation_completed(duk_context *ctx) +{ + duk_push_boolean(ctx, animation_completed(js_animation_this(ctx))); + + return 1; +} + +static duk_ret_t +js_animation_new(duk_context *ctx) +{ + struct animation *anim; + struct sprite *sprite; + unsigned int delay; + + if (!duk_is_constructor_call(ctx)) + duk_error(ctx, DUK_ERR_TYPE_ERROR, "Animation must be new-constructed"); + + sprite = js_sprite_require(js_self(ctx), 0); + delay = duk_require_uint(ctx, 1); + + anim = alloc_zero(1, sizeof (*anim)); + animation_init(anim, sprite, delay); + + duk_push_this(ctx); + duk_push_pointer(ctx, anim); + duk_put_prop_string(ctx, -2, SYMBOL); + duk_push_string(ctx, "completed"); + duk_push_c_function(ctx, js_animation_completed, 0); + duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_GETTER); + + /* We store the texture into the sprite to avoid being collected. */ + duk_dup(ctx, 0); + duk_put_prop_string(ctx, -2, SPRITE_REF); + duk_pop(ctx); + + return 0; +} + +static duk_ret_t +js_animation_finish(duk_context *ctx) +{ + duk_get_prop_string(ctx, 0, SYMBOL); + free(duk_to_pointer(ctx, -1)); + duk_pop(ctx); + duk_del_prop_string(ctx, 0, SYMBOL); + duk_del_prop_string(ctx, 0, SPRITE_REF); + + return 0; +} + +static duk_ret_t +js_animation_update(duk_context *ctx) +{ + struct animation *anim = js_animation_this(ctx); + unsigned int ticks = duk_require_uint(ctx, 0); + + duk_push_boolean(ctx, animation_update(anim, ticks)); + + return 1; +} + +static duk_ret_t +js_animation_draw(duk_context *ctx) +{ + struct animation *anim = js_animation_this(ctx); + int x, y; + + if (duk_get_top(ctx) == 2) { + x = duk_require_int(ctx, 0); + y = duk_require_int(ctx, 1); + } else if (duk_get_top(ctx) == 1) { + duk_require_object(ctx, 0); + duk_get_prop_string(ctx, 0, "x"); + x = duk_get_int(ctx, -1); + duk_get_prop_string(ctx, 0, "y"); + y = duk_get_int(ctx, -1); + duk_pop_n(ctx, 2); + } else + return duk_error(ctx, DUK_ERR_ERROR, "Object or 2 numbers expected"); + + if (!animation_draw(anim, x, y)) + return duk_error(ctx, DUK_ERR_ERROR, "%s", error()); + + return 0; +} + +static duk_function_list_entry methods[] = { + { "update", js_animation_update, 1 }, + { "draw", js_animation_draw, DUK_VARARGS }, + { NULL, NULL, 0 } +}; + +void +js_animation_load(struct js *js) +{ + assert(js); + + duk_push_global_object(js->handle); + duk_get_prop_string(js->handle, -1, "Molko"); + duk_push_c_function(js->handle, js_animation_new, 3); + duk_push_object(js->handle); + duk_put_function_list(js->handle, -1, methods); + duk_push_c_function(js->handle, js_animation_finish, 1); + duk_set_finalizer(js->handle, -2); + duk_put_prop_string(js->handle, -2, "prototype"); + duk_put_prop_string(js->handle, -2, "Animation"); + duk_pop_n(js->handle, 2); +} diff -r d6f217a5e4b1 -r ebbcfb31482d molko-js/src/js-animation.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/molko-js/src/js-animation.h Mon Nov 09 19:07:30 2020 +0100 @@ -0,0 +1,27 @@ +/* + * js-animation.h -- basic animations (Javascript bindings) + * + * Copyright (c) 2020 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 MOLKO_JS_ANIMATION_H +#define MOLKO_JS_ANIMATION_H + +struct js; + +void +js_animation_load(struct js *js); + +#endif /* !MOLKO_JS_ANIMATION_H */ diff -r d6f217a5e4b1 -r ebbcfb31482d molko-js/src/js-painter.c --- a/molko-js/src/js-painter.c Mon Nov 09 13:24:49 2020 +0100 +++ b/molko-js/src/js-painter.c Mon Nov 09 19:07:30 2020 +0100 @@ -25,6 +25,9 @@ #include "js.h" #include "js-painter.h" +#define SYMBOL DUK_HIDDEN_SYMBOL("molko::sprite") +#define TEXTURE_REF DUK_HIDDEN_SYMBOL("molko::sprite::texture") + static duk_ret_t js_painter_getColor(duk_context *ctx) { diff -r d6f217a5e4b1 -r ebbcfb31482d molko-js/src/js-sprite.c --- a/molko-js/src/js-sprite.c Mon Nov 09 13:24:49 2020 +0100 +++ b/molko-js/src/js-sprite.c Mon Nov 09 19:07:30 2020 +0100 @@ -148,10 +148,25 @@ } static const duk_function_list_entry methods[] = { - { "draw", js_sprite_draw, 1 }, - { NULL, NULL, 0 } + { "draw", js_sprite_draw, DUK_VARARGS }, + { NULL, NULL, 0 } }; +struct sprite * +js_sprite_require(struct js *js, unsigned int index) +{ + struct sprite *sp; + + duk_get_prop_string(js->handle, index, SYMBOL); + sp = duk_to_pointer(js->handle, -1); + duk_pop(js->handle); + + if (!sp) + duk_error(js->handle, DUK_ERR_TYPE_ERROR, "Sprite expected on argument #%u", index); + + return sp; +} + void js_sprite_load(struct js *js) { diff -r d6f217a5e4b1 -r ebbcfb31482d molko-js/src/js-sprite.h --- a/molko-js/src/js-sprite.h Mon Nov 09 13:24:49 2020 +0100 +++ b/molko-js/src/js-sprite.h Mon Nov 09 19:07:30 2020 +0100 @@ -24,4 +24,7 @@ void js_sprite_load(struct js *js); +struct sprite * +js_sprite_require(struct js *js, unsigned int index); + #endif /* !MOLKO_JS_SPRITE_H */ diff -r d6f217a5e4b1 -r ebbcfb31482d molko-js/src/js.c --- a/molko-js/src/js.c Mon Nov 09 13:24:49 2020 +0100 +++ b/molko-js/src/js.c Mon Nov 09 19:07:30 2020 +0100 @@ -30,12 +30,13 @@ #include #include "js.h" +#include "js-animation.h" #include "js-clock.h" #include "js-event.h" #include "js-font.h" #include "js-painter.h" +#include "js-sprite.h" #include "js-texture.h" -#include "js-sprite.h" #include "js-util.h" #include "js-window.h" @@ -139,7 +140,7 @@ /* Store a reference to this pointer. */ duk_push_global_stash(js->handle); duk_push_pointer(js->handle, js); - duk_put_prop_string(js->handle, -2, DUK_HIDDEN_SYMBOL("js.pointer")); + duk_put_prop_string(js->handle, -2, DUK_HIDDEN_SYMBOL("molko::pointer")); duk_pop(js->handle); } @@ -181,6 +182,7 @@ { assert(js); + js_animation_load(js); js_clock_load(js); js_event_load(js); js_font_load(js); diff -r d6f217a5e4b1 -r ebbcfb31482d molko-js/src/js_p.c --- a/molko-js/src/js_p.c Mon Nov 09 13:24:49 2020 +0100 +++ b/molko-js/src/js_p.c Mon Nov 09 19:07:30 2020 +0100 @@ -24,7 +24,7 @@ struct js *self; duk_push_global_stash(ctx); - duk_get_prop_string(ctx, -1, DUK_HIDDEN_SYMBOL("js.pointer")); + duk_get_prop_string(ctx, -1, DUK_HIDDEN_SYMBOL("molko::pointer")); self = duk_to_pointer(ctx, -1); duk_pop_n(ctx, 2);