Mercurial > molko
changeset 642:05b585720d3b
core: reimplement most of js
line wrap: on
line diff
--- a/CMakeLists.txt Sun Oct 01 09:18:01 2023 +0200 +++ b/CMakeLists.txt Sun Dec 17 09:50:36 2023 +0100 @@ -120,6 +120,10 @@ add_subdirectory(examples) endif () +if (MLK_WITH_JAVASCRIPT) + add_subdirectory(mlk-run) +endif () + configure_file( ${molko_SOURCE_DIR}/cmake/MlkOptions.install.cmake ${molko_BINARY_DIR}/cmake/MlkOptions.cmake
--- a/libmlk-core/CMakeLists.txt Sun Oct 01 09:18:01 2023 +0200 +++ b/libmlk-core/CMakeLists.txt Sun Dec 17 09:50:36 2023 +0100 @@ -153,6 +153,28 @@ if (MLK_WITH_JAVASCRIPT) set( JS_SOURCES + ${libmlk-core_SOURCE_DIR}/mlk/core/js/js-animation.c + ${libmlk-core_SOURCE_DIR}/mlk/core/js/js-animation.h + ${libmlk-core_SOURCE_DIR}/mlk/core/js/js-clock.c + ${libmlk-core_SOURCE_DIR}/mlk/core/js/js-clock.h + ${libmlk-core_SOURCE_DIR}/mlk/core/js/js-event.c + ${libmlk-core_SOURCE_DIR}/mlk/core/js/js-event.h + ${libmlk-core_SOURCE_DIR}/mlk/core/js/js-font.c + ${libmlk-core_SOURCE_DIR}/mlk/core/js/js-font.h + ${libmlk-core_SOURCE_DIR}/mlk/core/js/js-music.c + ${libmlk-core_SOURCE_DIR}/mlk/core/js/js-music.h + ${libmlk-core_SOURCE_DIR}/mlk/core/js/js-painter.c + ${libmlk-core_SOURCE_DIR}/mlk/core/js/js-painter.h + ${libmlk-core_SOURCE_DIR}/mlk/core/js/js-sound.c + ${libmlk-core_SOURCE_DIR}/mlk/core/js/js-sound.h + ${libmlk-core_SOURCE_DIR}/mlk/core/js/js-sprite.c + ${libmlk-core_SOURCE_DIR}/mlk/core/js/js-sprite.h + ${libmlk-core_SOURCE_DIR}/mlk/core/js/js-texture.c + ${libmlk-core_SOURCE_DIR}/mlk/core/js/js-texture.h + ${libmlk-core_SOURCE_DIR}/mlk/core/js/js-util.c + ${libmlk-core_SOURCE_DIR}/mlk/core/js/js-util.h + ${libmlk-core_SOURCE_DIR}/mlk/core/js/js-window.c + ${libmlk-core_SOURCE_DIR}/mlk/core/js/js-window.h ${libmlk-core_SOURCE_DIR}/mlk/core/js/js.c ${libmlk-core_SOURCE_DIR}/mlk/core/js/js.h )
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmlk-core/libmlk-core-js-config.cmake Sun Dec 17 09:50:36 2023 +0100 @@ -0,0 +1,23 @@ +# +# libmlk-core-js-config.cmake -- export file for libmlk-core-js +# +# Copyright (c) 2020-2023 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(CMakeFindDependencyMacro) + +find_dependency(libmlk-core) + +include("${CMAKE_CURRENT_LIST_DIR}/libmlk-core-js-targets.cmake")
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmlk-core/mlk/core/js/js-animation.c Sun Dec 17 09:50:36 2023 +0100 @@ -0,0 +1,158 @@ +/* + * js-animation.c -- basic animations (Javascript bindings) + * + * Copyright (c) 2020-2023 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 <mlk/core/alloc.h> +#include <mlk/core/err.h> +#include <mlk/core/animation.h> + +#include "js-animation.h" +#include "js-sprite.h" +#include "js.h" + +#define SYMBOL DUK_HIDDEN_SYMBOL("mlk::animation") +#define SPRITE_REF DUK_HIDDEN_SYMBOL("mlk::animation::sprite") + +static struct mlk_animation * +mlk_js_animation_this(duk_context *ctx) +{ + struct mlk_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 +mlk_js_animation_completed(duk_context *ctx) +{ + duk_push_boolean(ctx, mlk_animation_completed(mlk_js_animation_this(ctx))); + + return 1; +} + +static duk_ret_t +mlk_js_animation_new(duk_context *ctx) +{ + struct mlk_animation *anim; + struct mlk_sprite *sprite; + unsigned int delay; + + if (!duk_is_constructor_call(ctx)) + return duk_error(ctx, DUK_ERR_TYPE_ERROR, "Animation must be new-constructed"); + + sprite = mlk_js_sprite_require(ctx, 0); + delay = duk_require_uint(ctx, 1); + + anim = mlk_alloc_new0(1, sizeof (*anim)); + anim->sprite = sprite; + anim->delay = delay; + mlk_animation_start(anim); + + 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, mlk_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 +mlk_js_animation_finish(duk_context *ctx) +{ + duk_get_prop_string(ctx, 0, SYMBOL); + mlk_alloc_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 +mlk_js_animation_update(duk_context *ctx) +{ + struct mlk_animation *anim = mlk_js_animation_this(ctx); + unsigned int ticks = duk_require_uint(ctx, 0); + + duk_push_boolean(ctx, mlk_animation_update(anim, ticks)); + + return 1; +} + +static duk_ret_t +mlk_js_animation_draw(duk_context *ctx) +{ + struct mlk_animation *anim = mlk_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 (!mlk_animation_draw(anim, x, y)) + return duk_error(ctx, DUK_ERR_ERROR, "%s", mlk_err()); + + return 0; +} + +static duk_function_list_entry methods[] = { + { "update", mlk_js_animation_update, 1 }, + { "draw", mlk_js_animation_draw, DUK_VARARGS }, + { NULL, NULL, 0 } +}; + +void +mlk_js_animation_load(duk_context *ctx) +{ + assert(ctx); + + duk_push_global_object(ctx); + duk_get_prop_string(ctx, -1, "Mlk"); + duk_push_c_function(ctx, mlk_js_animation_new, 3); + duk_push_object(ctx); + duk_put_function_list(ctx, -1, methods); + duk_push_c_function(ctx, mlk_js_animation_finish, 1); + duk_set_finalizer(ctx, -2); + duk_put_prop_string(ctx, -2, "prototype"); + duk_put_prop_string(ctx, -2, "Animation"); + duk_pop_n(ctx, 2); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmlk-core/mlk/core/js/js-animation.h Sun Dec 17 09:50:36 2023 +0100 @@ -0,0 +1,35 @@ +/* + * js-animation.h -- basic animations (Javascript bindings) + * + * Copyright (c) 2020-2023 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_ANIMATION_H +#define MLK_CORE_JS_ANIMATION_H + +#include <duktape.h> + +#if defined(__cplusplus) +extern "C" { +#endif + +void +mlk_js_animation_load(duk_context *ctx); + +#if defined(__cplusplus) +} +#endif + +#endif /* !MLK_CORE_JS_ANIMATION_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmlk-core/mlk/core/js/js-clock.c Sun Dec 17 09:50:36 2023 +0100 @@ -0,0 +1,110 @@ +/* + * js-clock.c -- track elapsed time (Javascript bindings) + * + * Copyright (c) 2020-2023 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 <mlk/core/alloc.h> +#include <mlk/core/clock.h> + +#include "js-window.h" +#include "js.h" + +#define SYMBOL DUK_HIDDEN_SYMBOL("mlk::clock") + +static struct mlk_clock * +mlk_js_clock_this(duk_context *ctx) +{ + struct mlk_clock *clock; + + duk_push_this(ctx); + duk_get_prop_string(ctx, -1, SYMBOL); + clock = duk_to_pointer(ctx, -1); + duk_pop_n(ctx, 2); + + if (!clock) + duk_error(ctx, DUK_ERR_TYPE_ERROR, "Not a Clock object"); + + return clock; +} + +static duk_ret_t +mlk_js_clock_getElapsed(duk_context *ctx) +{ + duk_push_uint(ctx, mlk_clock_elapsed(mlk_js_clock_this(ctx))); + + return 1; +} + +static duk_ret_t +mlk_js_clock_new(duk_context *ctx) +{ + if (!duk_is_constructor_call(ctx)) + return duk_error(ctx, DUK_ERR_TYPE_ERROR, "Clock must be new-constructed"); + + duk_push_this(ctx); + duk_push_pointer(ctx, mlk_alloc_new0(1, sizeof (struct mlk_clock))); + duk_put_prop_string(ctx, -2, SYMBOL); + duk_push_string(ctx, "elapsed"); + duk_push_c_function(ctx, mlk_js_clock_getElapsed, 0); + duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_GETTER); + duk_pop(ctx); + + return 0; +} + +static duk_ret_t +mlk_js_clock_start(duk_context *ctx) +{ + mlk_clock_start(mlk_js_clock_this(ctx)); + + return 0; +} + +static duk_ret_t +mlk_js_clock_finish(duk_context *ctx) +{ + duk_get_prop_string(ctx, 0, SYMBOL); + mlk_alloc_free(duk_to_pointer(ctx, -1)); + duk_pop(ctx); + duk_del_prop_string(ctx, 0, SYMBOL); + + return 0; +} + +static const duk_function_list_entry methods[] = { + { "start", mlk_js_clock_start, 0 }, + { NULL, NULL, 0 } +}; + +void +mlk_js_clock_load(duk_context *ctx) +{ + assert(ctx); + + duk_push_global_object(ctx); + duk_get_prop_string(ctx, -1, "Mlk"); + duk_push_c_function(ctx, mlk_js_clock_new, 0); + duk_push_object(ctx); + duk_put_function_list(ctx, -1, methods); + duk_push_c_function(ctx, mlk_js_clock_finish, 1); + duk_set_finalizer(ctx, -2); + duk_put_prop_string(ctx, -2, "prototype"); + duk_put_prop_string(ctx, -2, "Clock"); + duk_pop_n(ctx, 2); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmlk-core/mlk/core/js/js-clock.h Sun Dec 17 09:50:36 2023 +0100 @@ -0,0 +1,35 @@ +/* + * js-clock.h -- track elapsed time (Javascript bindings) + * + * Copyright (c) 2020-2023 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_CLOCK_H +#define MLK_CORE_JS_CLOCK_H + +#include <duktape.h> + +#if defined(__cplusplus) +extern "C" { +#endif + +void +mlk_js_clock_load(duk_context *ctx); + +#if defined(__cplusplus) +} +#endif + +#endif /* !MLK_CORE_JS_CLOCK_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmlk-core/mlk/core/js/js-event.c Sun Dec 17 09:50:36 2023 +0100 @@ -0,0 +1,103 @@ +/* + * js-event.c -- event management (Javascript bindings) + * + * Copyright (c) 2020-2023 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 <duktape.h> + +#include <mlk/core/event.h> + +#include "js-event.h" +#include "js.h" + +static duk_ret_t +push(duk_context *ctx, const union mlk_event *ev) +{ + duk_push_object(ctx); + duk_push_int(ctx, ev->type); + duk_put_prop_string(ctx, -2, "type"); + + switch (ev->type) { + case MLK_EVENT_CLICKDOWN: + case MLK_EVENT_CLICKUP: + duk_push_int(ctx, ev->click.button); + duk_put_prop_string(ctx, -2, "button"); + duk_push_int(ctx, ev->click.x); + duk_put_prop_string(ctx, -2, "x"); + duk_push_int(ctx, ev->click.y); + duk_put_prop_string(ctx, -2, "y"); + break; + case MLK_EVENT_KEYDOWN: + case MLK_EVENT_KEYUP: + duk_push_int(ctx, ev->key.key); + duk_put_prop_string(ctx, -2, "key"); + break; + case MLK_EVENT_MOUSE: + duk_push_int(ctx, ev->mouse.buttons); + duk_put_prop_string(ctx, -2, "buttons"); + duk_push_int(ctx, ev->mouse.x); + duk_put_prop_string(ctx, -2, "x"); + duk_push_int(ctx, ev->mouse.y); + duk_put_prop_string(ctx, -2, "y"); + break; + default: + break; + } + + return 1; +} + +static duk_ret_t +mlk_js_event_poll(duk_context *ctx) +{ + union mlk_event ev; + + if (!mlk_event_poll(&ev)) + return 0; + + return push(ctx, &ev); +} + +static const duk_number_list_entry types[] = { + { "CLICK_DOWN", MLK_EVENT_CLICKDOWN }, + { "CLICK_UP", MLK_EVENT_CLICKUP }, + { "KEY_DOWN", MLK_EVENT_KEYDOWN }, + { "KEY_UP", MLK_EVENT_KEYUP }, + { "MOUSE", MLK_EVENT_MOUSE }, + { "QUIT", MLK_EVENT_QUIT }, + { NULL, 0 } +}; + +static const duk_function_list_entry functions[] = { + { "poll", mlk_js_event_poll, 0 }, + { NULL, NULL, 0 } +}; + +void +mlk_js_event_load(duk_context *ctx) +{ + assert(ctx); + + duk_push_global_object(ctx); + duk_get_prop_string(ctx, -1, "Mlk"); + duk_push_object(ctx); + duk_put_number_list(ctx, -1, types); + duk_put_function_list(ctx, -1, functions); + duk_put_prop_string(ctx, -2, "Event"); + duk_pop_n(ctx, 1); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmlk-core/mlk/core/js/js-event.h Sun Dec 17 09:50:36 2023 +0100 @@ -0,0 +1,35 @@ +/* + * js-event.h -- event management (Javascript bindings) + * + * Copyright (c) 2020-2023 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_EVENT_H +#define MLK_CORE_JS_EVENT_H + +#include <duktape.h> + +#if defined(__cplusplus) +extern "C" { +#endif + +void +mlk_js_event_load(duk_context *ctx); + +#if defined(__cplusplus) +} +#endif + +#endif /* !MLK_CORE_JS_EVENT_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmlk-core/mlk/core/js/js-font.c Sun Dec 17 09:50:36 2023 +0100 @@ -0,0 +1,164 @@ +/* + * js-font.c -- basic font management (Javascript bindings) + * + * Copyright (c) 2020-2023 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 <duktape.h> + +#include <mlk/core/alloc.h> +#include <mlk/core/err.h> +#include <mlk/core/font.h> +#include <mlk/core/texture.h> + +#include "js-font.h" +#include "js-texture.h" +#include "js.h" + +#define SYMBOL DUK_HIDDEN_SYMBOL("mlk::font") +#define PROTO DUK_HIDDEN_SYMBOL("mlk::font::prototype") + +static struct mlk_font * +mlk_js_font_this(duk_context *ctx) +{ + struct mlk_font *font; + + duk_push_this(ctx); + duk_get_prop_string(ctx, -1, SYMBOL); + font = duk_to_pointer(ctx, -1); + duk_pop_n(ctx, 2); + + if (!font) + duk_error(ctx, DUK_ERR_TYPE_ERROR, "Not a Font object"); + + return font; +} + +static duk_ret_t +mlk_js_font_getHeight(duk_context *ctx) +{ + duk_push_uint(ctx, mlk_font_height(mlk_js_font_this(ctx))); + + return 1; +} + +static duk_ret_t +mlk_js_font_fromPath(duk_context *ctx) +{ + struct mlk_font font; + const char *path = duk_require_string(ctx, 0); + unsigned int size = duk_require_uint(ctx, 1); + + if (!mlk_font_open(&font, path, size)) + duk_error(ctx, DUK_ERR_ERROR, "%s", mlk_err()); + + duk_push_object(ctx); + duk_push_global_stash(ctx); + duk_get_prop_string(ctx, -1, PROTO); + duk_remove(ctx, -2); + duk_push_pointer(ctx, mlk_alloc_dup(&font, 1, sizeof (font))); + duk_put_prop_string(ctx, -3, SYMBOL); + duk_set_prototype(ctx, -2); + duk_push_string(ctx, "height"); + duk_push_c_function(ctx, mlk_js_font_getHeight, 0); + duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_GETTER); + + return 1; +} + +static duk_ret_t +mlk_js_font_render(duk_context *ctx) +{ + struct mlk_font *font = mlk_js_font_this(ctx); + struct mlk_texture tex; + const char *text = duk_require_string(ctx, 0); + unsigned long color = duk_require_number(ctx, 1); + + if (mlk_font_render(font, &tex, text, color) < 0) + return duk_error(ctx, DUK_ERR_ERROR, "%s", mlk_err()); + + mlk_js_texture_push(ctx, &tex); + + return 1; +} + +static duk_ret_t +mlk_js_font_query(duk_context *ctx) +{ + struct mlk_font *font = mlk_js_font_this(ctx); + const char *text = duk_require_string(ctx, 0); + unsigned int w, h; + + if (mlk_font_query(font, text, &w, &h) < 0) + return duk_error(ctx, DUK_ERR_ERROR, "%s", mlk_err()); + + duk_push_object(ctx); + duk_push_uint(ctx, w); + duk_put_prop_string(ctx, -2, "w"); + duk_push_uint(ctx, h); + duk_put_prop_string(ctx, -2, "h"); + + return 1; +} + +static duk_ret_t +mlk_js_font_finish(duk_context *ctx) +{ + struct mlk_font *font; + + duk_get_prop_string(ctx, 0, SYMBOL); + font = duk_to_pointer(ctx, -1); + duk_pop(ctx); + duk_del_prop_string(ctx, 0, SYMBOL); + + if (font) { + mlk_font_finish(font); + mlk_alloc_free(font); + } + + return 0; +} + +static const duk_function_list_entry functions[] = { + { "fromPath", mlk_js_font_fromPath, 2 }, + { NULL, NULL, 0 } +}; + +static const duk_function_list_entry methods[] = { + { "render", mlk_js_font_render, 2 }, + { "query", mlk_js_font_query, 1 }, + { NULL, NULL, 0 } +}; + +void +mlk_js_font_load(duk_context *ctx) +{ + assert(ctx); + + duk_push_global_object(ctx); + duk_get_prop_string(ctx, -1, "Mlk"); + duk_push_object(ctx); + duk_put_function_list(ctx, -1, functions); + duk_put_prop_string(ctx, -2, "Font"); + duk_push_global_stash(ctx); + duk_push_object(ctx); + duk_put_function_list(ctx, -1, methods); + duk_push_c_function(ctx, mlk_js_font_finish, 1); + duk_set_finalizer(ctx, -2); + duk_put_prop_string(ctx, -2, PROTO); + duk_pop_n(ctx, 3); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmlk-core/mlk/core/js/js-font.h Sun Dec 17 09:50:36 2023 +0100 @@ -0,0 +1,35 @@ +/* + * js-font.h -- basic font management (Javascript bindings) + * + * Copyright (c) 2020-2023 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_FONT_H +#define MLK_CORE_JS_FONT_H + +#include <duktape.h> + +#if defined(__cplusplus) +extern "C" { +#endif + +void +mlk_js_font_load(duk_context *ctx); + +#if defined(__cplusplus) +} +#endif + +#endif /* !MLK_CORE_JS_FONT_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmlk-core/mlk/core/js/js-music.c Sun Dec 17 09:50:36 2023 +0100 @@ -0,0 +1,156 @@ +/* + * js-music.c -- music support (Javascript bindings) + * + * Copyright (c) 2020-2023 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 <mlk/core/alloc.h> +#include <mlk/core/err.h> +#include <mlk/core/music.h> + +#include "js-music.h" + +#define SYMBOL DUK_HIDDEN_SYMBOL("mlk::music") + +static struct mlk_music * +mlk_js_music_this(duk_context *ctx) +{ + struct mlk_music *mus; + + duk_push_this(ctx); + duk_get_prop_string(ctx, -1, SYMBOL); + mus = duk_to_pointer(ctx, -1); + duk_pop_n(ctx, 2); + + if (!mus) + duk_error(ctx, DUK_ERR_TYPE_ERROR, "Not a Music object"); + + return mus; +} + +static duk_ret_t +mlk_js_music_new(duk_context *ctx) +{ + struct mlk_music mus; + const char *path; + + if (!duk_is_constructor_call(ctx)) + return duk_error(ctx, DUK_ERR_TYPE_ERROR, "Music must be new-constructed"); + + path = duk_require_string(ctx, 0); + + if (mlk_music_open(&mus, path) < 0) + return duk_error(ctx, DUK_ERR_ERROR, "%s", mlk_err()); + + duk_push_this(ctx); + duk_push_pointer(ctx, mlk_alloc_dup(&mus, 1, sizeof (mus))); + duk_put_prop_string(ctx, -2, SYMBOL); + duk_pop(ctx); + + return 0; +} + +static duk_ret_t +mlk_js_music_pause(duk_context *ctx) +{ + mlk_music_pause(mlk_js_music_this(ctx)); + + return 0; +} + +static duk_ret_t +mlk_js_music_resume(duk_context *ctx) +{ + mlk_music_resume(mlk_js_music_this(ctx)); + + return 0; +} + +static duk_ret_t +mlk_js_music_stop(duk_context *ctx) +{ + mlk_music_stop(mlk_js_music_this(ctx)); + + return 0; +} + +static duk_ret_t +mlk_js_music_play(duk_context *ctx) +{ + struct mlk_music *mus = mlk_js_music_this(ctx); + enum mlk_music_flags flags = duk_get_uint(ctx, 0); + + if (mlk_music_play(mus, flags) < 0) + return duk_error(ctx, DUK_ERR_ERROR, "%s", mlk_err()); + + return 0; +} + +static duk_ret_t +mlk_js_music_finish(duk_context *ctx) +{ + struct mlk_music *mus; + + duk_get_prop_string(ctx, 0, SYMBOL); + + if ((mus = duk_to_pointer(ctx, -1))) { + mlk_music_finish(mus); + mlk_alloc_free(mus); + } + + duk_pop(ctx); + duk_del_prop_string(ctx, 0, SYMBOL); + + return 0; +} + +static const duk_number_list_entry flags[] = { + { "NONE", MLK_MUSIC_NONE }, + { "LOOP", MLK_MUSIC_LOOP }, + { NULL, 0 } +}; + +static const duk_function_list_entry functions[] = { + { "pause", mlk_js_music_pause, 0 }, + { "resume", mlk_js_music_resume, 0 }, + { "stop", mlk_js_music_stop, DUK_VARARGS }, + { NULL, NULL, 0 } +}; + +static const duk_function_list_entry methods[] = { + { "play", mlk_js_music_play, DUK_VARARGS }, + { NULL, NULL, 0 } +}; + +void +mlk_js_music_load(duk_context *ctx) +{ + assert(ctx); + + duk_push_global_object(ctx); + duk_get_prop_string(ctx, -1, "Mlk"); + duk_push_c_function(ctx, mlk_js_music_new, 3); + duk_put_function_list(ctx, -1, functions); + duk_put_number_list(ctx, -1, flags); + duk_push_object(ctx); + duk_put_function_list(ctx, -1, methods); + duk_push_c_function(ctx, mlk_js_music_finish, 1); + duk_set_finalizer(ctx, -2); + duk_put_prop_string(ctx, -2, "prototype"); + duk_put_prop_string(ctx, -2, "Music"); + duk_pop_n(ctx, 2); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmlk-core/mlk/core/js/js-music.h Sun Dec 17 09:50:36 2023 +0100 @@ -0,0 +1,35 @@ +/* + * js-music.h -- music support (Javascript bindings) + * + * Copyright (c) 2020-2023 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_MUSIC_H +#define MLK_CORE_JS_MUSIC_H + +#include <duktape.h> + +#if defined(__cplusplus) +extern "C" { +#endif + +void +mlk_js_music_load(duk_context *ctx); + +#if defined(__cplusplus) +} +#endif + +#endif /* !MLK_JS_MUSIC_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmlk-core/mlk/core/js/js-painter.c Sun Dec 17 09:50:36 2023 +0100 @@ -0,0 +1,211 @@ +/* + * js-painter.c -- basic drawing routines (Javascript bindings) + * + * Copyright (c) 2020-2023 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 <duktape.h> + +#include <mlk/core/painter.h> + +#include "js.h" +#include "js-painter.h" + +#define SYMBOL DUK_HIDDEN_SYMBOL("mlk::sprite") +#define TEXTURE_REF DUK_HIDDEN_SYMBOL("mlk::sprite::texture") + +static duk_ret_t +mlk_js_painter_getColor(duk_context *ctx) +{ + duk_push_number(ctx, mlk_painter_get_color()); + + return 1; +} + +static duk_ret_t +mlk_js_painter_setColor(duk_context *ctx) +{ + mlk_painter_set_color(duk_require_number(ctx, 0)); + + return 0; +} + +static duk_ret_t +mlk_js_painter_new(duk_context *ctx) +{ + if (!duk_is_constructor_call(ctx)) + return duk_error(ctx, DUK_ERR_TYPE_ERROR, "Painter must be new-constructed"); + + + return 0; +} + +static duk_ret_t +mlk_js_painter_clear(duk_context *ctx) +{ + (void)ctx; + + mlk_painter_clear(); + + return 0; +} + +static duk_ret_t +mlk_js_painter_drawLine(duk_context *ctx) +{ + int x1, y1, x2, y2; + + if (duk_get_top(ctx) == 4) { + x1 = duk_require_int(ctx, 0); + y1 = duk_require_int(ctx, 1); + x2 = duk_require_int(ctx, 2); + y2 = duk_require_int(ctx, 3); + } else if (duk_get_top(ctx) == 1) { + duk_require_object(ctx, 0); + duk_get_prop_string(ctx, 0, "x1"); + x1 = duk_require_int(ctx, -1); + duk_get_prop_string(ctx, 0, "y1"); + y1 = duk_require_int(ctx, -1); + duk_get_prop_string(ctx, 0, "x2"); + x2 = duk_require_int(ctx, -1); + duk_get_prop_string(ctx, 0, "y2"); + y2 = duk_require_int(ctx, -1); + duk_pop_n(ctx, 4); + } else + return duk_error(ctx, DUK_ERR_ERROR, "Object or 4 numbers expected"); + + mlk_painter_draw_line(x1, y2, x2, y2); + + return 0; +} + +static duk_ret_t +mlk_js_painter_drawPoint(duk_context *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_require_int(ctx, -1); + duk_get_prop_string(ctx, 0, "y"); + y = duk_require_int(ctx, -1); + duk_pop_n(ctx, 2); + } else + return duk_error(ctx, DUK_ERR_ERROR, "Object or 2 numbers expected"); + + mlk_painter_draw_point(x, y); + + return 0; +} + +static duk_ret_t +mlk_js_painter_drawRectangle(duk_context *ctx) +{ + int x, y; + unsigned int w, h; + + if (duk_get_top(ctx) == 4) { + x = duk_require_int(ctx, 0); + y = duk_require_int(ctx, 1); + w = duk_require_uint(ctx, 2); + h = duk_require_uint(ctx, 3); + } else if (duk_get_top(ctx) == 1) { + duk_require_object(ctx, 0); + duk_get_prop_string(ctx, 0, "x"); + x = duk_require_int(ctx, -1); + duk_get_prop_string(ctx, 0, "y"); + y = duk_require_int(ctx, -1); + duk_get_prop_string(ctx, 0, "w"); + w = duk_require_uint(ctx, -1); + duk_get_prop_string(ctx, 0, "h"); + h = duk_require_uint(ctx, -1); + duk_pop_n(ctx, 4); + } else + return duk_error(ctx, DUK_ERR_ERROR, "Object or 4 numbers expected"); + + mlk_painter_draw_rectangle(x, y, w, h); + + return 0; +} + +static duk_ret_t +mlk_js_painter_drawCircle(duk_context *ctx) +{ + int x, y; + double r; + + if (duk_get_top(ctx) == 3) { + x = duk_require_int(ctx, 0); + y = duk_require_int(ctx, 1); + r = duk_require_number(ctx, 2); + } else if (duk_get_top(ctx) == 1) { + duk_require_object(ctx, 0); + duk_get_prop_string(ctx, 0, "x"); + x = duk_require_int(ctx, -1); + duk_get_prop_string(ctx, 0, "y"); + y = duk_require_int(ctx, -1); + duk_get_prop_string(ctx, 0, "r"); + r = duk_require_number(ctx, -1); + duk_pop_n(ctx, 3); + } else + return duk_error(ctx, DUK_ERR_ERROR, "Object or 3 numbers expected"); + + mlk_painter_draw_circle(x, y, r); + + return 0; +} + +static duk_ret_t +mlk_js_painter_present(duk_context *ctx) +{ + (void)ctx; + + mlk_painter_present(); + + return 0; +} + +static const duk_function_list_entry methods[] = { + { "clear", mlk_js_painter_clear, 0 }, + { "drawLine", mlk_js_painter_drawLine, DUK_VARARGS }, + { "drawPoint", mlk_js_painter_drawPoint, DUK_VARARGS }, + { "drawRectangle", mlk_js_painter_drawRectangle, DUK_VARARGS }, + { "drawCircle", mlk_js_painter_drawCircle, DUK_VARARGS }, + { "present", mlk_js_painter_present, 0 }, + { NULL, NULL, 0 } +}; + +void +js_painter_load(duk_context *ctx) +{ + assert(ctx); + + duk_push_global_object(ctx); + duk_get_prop_string(ctx, -1, "Mlk"); + duk_push_object(ctx); + duk_push_string(ctx, "color"); + duk_push_c_function(ctx, mlk_js_painter_getColor, 0); + duk_push_c_function(ctx, mlk_js_painter_setColor, 1); + duk_def_prop(ctx, -4, DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_HAVE_SETTER); + duk_put_function_list(ctx, -1, methods); + duk_put_prop_string(ctx, -2, "Painter"); + duk_pop(ctx); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmlk-core/mlk/core/js/js-painter.h Sun Dec 17 09:50:36 2023 +0100 @@ -0,0 +1,35 @@ +/* + * js-painter.h -- basic drawing routines (Javascript bindings) + * + * Copyright (c) 2020-2023 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_PAINTER_H +#define MLK_CORE_JS_PAINTER_H + +#include <duktape.h> + +#if defined(__cplusplus) +extern "C" { +#endif + +void +mlk_js_painter_load(duk_context *ctx); + +#if defined(__cplusplus) +} +#endif + +#endif /* !MLK_CORE_JS_PAINTER_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmlk-core/mlk/core/js/js-sound.c Sun Dec 17 09:50:36 2023 +0100 @@ -0,0 +1,143 @@ +/* + * js-sound.c -- sound support (Javascript bindings) + * + * Copyright (c) 2020-2023 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 <mlk/core/alloc.h> +#include <mlk/core/err.h> +#include <mlk/core/sound.h> + +#include "js-sound.h" + +#define SYMBOL DUK_HIDDEN_SYMBOL("mlk::sound") + +static struct mlk_sound * +mlk_js_sound_this(duk_context *ctx) +{ + struct mlk_sound *snd; + + duk_push_this(ctx); + duk_get_prop_string(ctx, -1, SYMBOL); + snd = duk_to_pointer(ctx, -1); + duk_pop_n(ctx, 2); + + if (!snd) + duk_error(ctx, DUK_ERR_TYPE_ERROR, "Not a Sound object"); + + return snd; +} + +static duk_ret_t +mlk_js_sound_new(duk_context *ctx) +{ + struct mlk_sound snd; + const char *path; + + if (!duk_is_constructor_call(ctx)) + return duk_error(ctx, DUK_ERR_TYPE_ERROR, "Sound must be new-constructed"); + + path = duk_require_string(ctx, 0); + + if (mlk_sound_open(&snd, path) < 0) + return duk_error(ctx, DUK_ERR_ERROR, "%s", mlk_err()); + + duk_push_this(ctx); + duk_push_pointer(ctx, mlk_alloc_dup(&snd, 1, sizeof (snd))); + duk_put_prop_string(ctx, -2, SYMBOL); + duk_pop(ctx); + + return 0; +} + +static duk_ret_t +mlk_js_sound_play(duk_context *ctx) +{ + struct mlk_sound *snd = mlk_js_sound_this(ctx); + + if (mlk_sound_play(snd) < 0) + return duk_error(ctx, DUK_ERR_ERROR, "%s", mlk_err()); + + return 0; +} + +static duk_ret_t +mlk_js_sound_pause(duk_context *ctx) +{ + mlk_sound_pause(mlk_js_sound_this(ctx)); + + return 0; +} + +static duk_ret_t +mlk_js_sound_resume(duk_context *ctx) +{ + mlk_sound_resume(mlk_js_sound_this(ctx)); + + return 0; +} + +static duk_ret_t +mlk_js_sound_stop(duk_context *ctx) +{ + mlk_sound_stop(mlk_js_sound_this(ctx)); + + return 0; +} + +static duk_ret_t +mlk_js_sound_finish(duk_context *ctx) +{ + struct mlk_sound *snd; + + duk_get_prop_string(ctx, 0, SYMBOL); + + if ((snd = duk_to_pointer(ctx, -1))) { + mlk_sound_finish(snd); + mlk_alloc_free(snd); + } + + duk_pop(ctx); + duk_del_prop_string(ctx, 0, SYMBOL); + + return 0; +} + +static const duk_function_list_entry methods[] = { + { "play", mlk_js_sound_play, DUK_VARARGS }, + { "pause", mlk_js_sound_pause, 0 }, + { "resume", mlk_js_sound_resume, 0 }, + { "stop", mlk_js_sound_stop, DUK_VARARGS }, + { NULL, NULL, 0 } +}; + +void +mlk_js_sound_load(duk_context *ctx) +{ + assert(ctx); + + duk_push_global_object(ctx); + duk_get_prop_string(ctx, -1, "Mlk"); + duk_push_c_function(ctx, mlk_js_sound_new, 3); + duk_push_object(ctx); + duk_put_function_list(ctx, -1, methods); + duk_push_c_function(ctx, mlk_js_sound_finish, 1); + duk_set_finalizer(ctx, -2); + duk_put_prop_string(ctx, -2, "prototype"); + duk_put_prop_string(ctx, -2, "Sound"); + duk_pop_n(ctx, 2); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmlk-core/mlk/core/js/js-sound.h Sun Dec 17 09:50:36 2023 +0100 @@ -0,0 +1,35 @@ +/* + * js-sound.h -- sound support (Javascript bindings) + * + * Copyright (c) 2020-2023 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_SOUND_H +#define MLK_CORE_JS_SOUND_H + +#include <duktape.h> + +#if defined(__cplusplus) +extern "C" { +#endif + +void +mlk_js_sound_load(duk_context *ctx); + +#if defined(__cplusplus) +} +#endif + +#endif /* !MLK_CORE_JS_SOUND_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmlk-core/mlk/core/js/js-sprite.c Sun Dec 17 09:50:36 2023 +0100 @@ -0,0 +1,178 @@ +/* + * js-sprite.c -- image sprites (Javascript bindings) + * + * Copyright (c) 2020 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 <mlk/core/alloc.h> +#include <mlk/core/sprite.h> +#include <mlk/core/texture.h> + +#include "js-sprite.h" +#include "js-texture.h" +#include "js.h" + +#define SYMBOL DUK_HIDDEN_SYMBOL("mlk::sprite") +#define TEXTURE_REF DUK_HIDDEN_SYMBOL("mlk::sprite::texture") + +static struct mlk_sprite * +mlk_js_sprite_this(duk_context *ctx) +{ + struct mlk_sprite *sprite; + + duk_push_this(ctx); + duk_get_prop_string(ctx, -1, SYMBOL); + sprite = duk_to_pointer(ctx, -1); + duk_pop_n(ctx, 2); + + if (!sprite) + duk_error(ctx, DUK_ERR_TYPE_ERROR, "Not a Sprite object"); + + return sprite; +} + +static duk_ret_t +mlk_js_sprite_getRowCount(duk_context *ctx) +{ + duk_push_uint(ctx, mlk_js_sprite_this(ctx)->nrows); + + return 1; +} + +static duk_ret_t +mlk_js_sprite_getColumnCount(duk_context *ctx) +{ + duk_push_uint(ctx, mlk_js_sprite_this(ctx)->ncols); + + return 1; +} + +static duk_ret_t +mlk_js_sprite_new(duk_context *ctx) +{ + struct mlk_sprite sprite; + + if (!duk_is_constructor_call(ctx)) + duk_error(ctx, DUK_ERR_TYPE_ERROR, "Sprite must be new-constructed"); + + sprite.texture = mlk_js_texture_require(ctx, 0); + sprite.cellw = duk_require_int(ctx, 1); + sprite.cellh = duk_require_int(ctx, 2); + mlk_sprite_init(&sprite); + + duk_push_this(ctx); + duk_push_pointer(ctx, mlk_alloc_dup(&sprite, 1, sizeof (sprite))); + duk_put_prop_string(ctx, -2, SYMBOL); + + /* + * Put rowCount/columnCount properties. + */ + duk_push_string(ctx, "rowCount"); + duk_push_c_function(ctx, mlk_js_sprite_getRowCount, 0); + duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_GETTER); + + duk_push_string(ctx, "columnCount"); + duk_push_c_function(ctx, mlk_js_sprite_getColumnCount, 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, TEXTURE_REF); + duk_pop(ctx); + + return 0; +} + +static duk_ret_t +mlk_js_sprite_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, TEXTURE_REF); + + return 0; +} + +static duk_ret_t +mlk_js_sprite_draw(duk_context *ctx) +{ + struct sprite *sprite = mlk_js_sprite_this(ctx); + unsigned int r, c; + int x, y; + + if (duk_get_top(ctx) == 4) { + r = duk_require_uint(ctx, 0); + c = duk_require_uint(ctx, 1); + x = duk_require_int(ctx, 2); + y = duk_require_int(ctx, 3); + } else if (duk_get_top(ctx) == 1) { + duk_require_object(ctx, 0); + duk_get_prop_string(ctx, 0, "row"); + r = duk_to_int(ctx, -1); + duk_get_prop_string(ctx, 0, "column"); + c = duk_to_int(ctx, -1); + duk_get_prop_string(ctx, 0, "x"); + x = duk_to_int(ctx, -1); + duk_get_prop_string(ctx, 0, "y"); + y = duk_to_int(ctx, -1); + duk_pop_n(ctx, 4); + } else + return duk_error(ctx, DUK_ERR_ERROR, "Object or 4 numbers expected"); + + mlk_sprite_draw(sprite, r, c, x, y); + + return 0; +} + +static const duk_function_list_entry methods[] = { + { "draw", mlk_js_sprite_draw, DUK_VARARGS }, + { NULL, NULL, 0 } +}; + +struct mlk_sprite * +mlk_js_sprite_require(duk_context *ctx, duk_idx_t index) +{ + struct sprite *sp; + + duk_get_prop_string(ctx, index, SYMBOL); + sp = duk_to_pointer(ctx, -1); + duk_pop(ctx); + + if (!sp) + duk_error(ctx, DUK_ERR_TYPE_ERROR, "Sprite expected on argument #%u", index); + + return sp; +} + +void +mlk_js_sprite_load(duk_context *ctx) +{ + assert(ctx); + + duk_push_global_object(ctx); + duk_get_prop_string(ctx, -1, "Molko"); + duk_push_c_function(ctx, mlk_js_sprite_new, 3); + duk_push_object(ctx); + duk_put_function_list(ctx, -1, methods); + duk_push_c_function(ctx, mlk_js_sprite_finish, 1); + duk_set_finalizer(ctx, -2); + duk_put_prop_string(ctx, -2, "prototype"); + duk_put_prop_string(ctx, -2, "Sprite"); + duk_pop_n(ctx, 2); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmlk-core/mlk/core/js/js-sprite.h Sun Dec 17 09:50:36 2023 +0100 @@ -0,0 +1,40 @@ +/* + * js-sprite.h -- image sprites (Javascript bindings) + * + * Copyright (c) 2020-2023 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_SPRITE_H +#define MLK_CORE_JS_SPRITE_H + +#include <duktape.h> + +struct mlk_sprite; + +#if defined(__cplusplus) +extern "C" { +#endif + +void +mlk_js_sprite_load(duk_context *ctx); + +struct mlk_sprite * +mlk_js_sprite_require(duk_context *ctx, duk_idx_t index); + +#if defined(__cplusplus) +} +#endif + +#endif /* !MLK_CORE_JS_SPRITE_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmlk-core/mlk/core/js/js-texture.c Sun Dec 17 09:50:36 2023 +0100 @@ -0,0 +1,294 @@ +/* + * js-texture.c -- basic texture management (Javascript bindings) + * + * Copyright (c) 2020-2023 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 <mlk/core/alloc.h> +#include <mlk/core/err.h> +#include <mlk/core/image.h> +#include <mlk/core/texture.h> + +#include "js-texture.h" +#include "js.h" + +#define SYMBOL DUK_HIDDEN_SYMBOL("mlk::texture") +#define PROTO DUK_HIDDEN_SYMBOL("mlk::texture::proto") + +static struct mlk_texture * +mlk_js_texture_this(duk_context *ctx) +{ + struct mlk_texture *tex; + + duk_push_this(ctx); + duk_get_prop_string(ctx, -1, SYMBOL); + tex = duk_to_pointer(ctx, -1); + duk_pop_n(ctx, 2); + + if (!tex) + duk_error(ctx, DUK_ERR_TYPE_ERROR, "Not a Texture object"); + + return tex; +} + +static duk_ret_t +mlk_js_texture_getWidth(duk_context *ctx) +{ + duk_push_uint(ctx, mlk_js_texture_this(ctx)->w); + + return 1; +} + +static duk_ret_t +mlk_js_texture_getHeight(duk_context *ctx) +{ + duk_push_uint(ctx, mlk_js_texture_this(ctx)->h); + + return 1; +} + +static duk_ret_t +mlk_js_texture_setBlendMode(duk_context *ctx) +{ + struct mlk_texture *tex = mlk_js_texture_this(ctx); + enum mlk_texture_blend blend = duk_require_int(ctx, 0); + + if (blend < 0 || blend >= MLK_TEXTURE_BLEND_MODULATE) + return duk_error(ctx, DUK_ERR_ERROR, "invalid blend mode: %d", blend); + if (mlk_texture_set_blend_mode(tex, blend) < 0) + return duk_error(ctx, DUK_ERR_ERROR, "%s", mlk_err()); + + return 0; +} + +static duk_ret_t +mlk_js_texture_setAlphaMod(duk_context *ctx) +{ + struct mlk_texture *tex = mlk_js_texture_this(ctx); + unsigned int alpha = duk_require_uint(ctx, 0); + + if (alpha > 255) + return duk_error(ctx, DUK_ERR_RANGE_ERROR, "%u is out of range [0..255]", alpha); + if (mlk_texture_set_alpha_mod(tex, alpha) < 0) + return duk_error(ctx, DUK_ERR_ERROR, "%s", mlk_err()); + + return 0; +} + +static duk_ret_t +mlk_js_texture_setColorMod(duk_context *ctx) +{ + struct mlk_texture *tex = mlk_js_texture_this(ctx); + unsigned long color = duk_require_number(ctx, 0); + + if (mlk_texture_set_color_mod(tex, color) < 0) + return duk_error(ctx, DUK_ERR_ERROR, "%s", mlk_err()); + + return 0; +} + +static duk_ret_t +mlk_js_texture_new(duk_context *ctx) +{ + struct mlk_texture tex; + unsigned int w = duk_require_uint(ctx, 0); + unsigned int h = duk_require_uint(ctx, 1); + + if (!duk_is_constructor_call(ctx)) + return duk_error(ctx, DUK_ERR_TYPE_ERROR, "Texture must be new-constructed"); + if (mlk_texture_init(&tex, w, h) < 0) + return duk_error(ctx, DUK_ERR_ERROR, "%s", mlk_err()); + + duk_push_this(ctx); + duk_push_pointer(ctx, mlk_alloc_dup(&tex, 1, sizeof (tex))); + duk_put_prop_string(ctx, -2, SYMBOL); + duk_pop(ctx); + + return 0; +} + +static duk_ret_t +mlk_js_texture_draw(duk_context *ctx) +{ + struct mlk_texture *tex = mlk_js_texture_this(ctx); + int x, y; + + duk_require_object(ctx, 0); + duk_get_prop_string(ctx, 0, "x"); + x = duk_to_int(ctx, -1); + duk_get_prop_string(ctx, 0, "y"); + y = duk_to_int(ctx, -1); + duk_pop_n(ctx, 2); + + if (mlk_texture_draw(tex, x, y) < 0) + return duk_error(ctx, DUK_ERR_ERROR, "%s", mlk_err()); + + return 0; +} + +static duk_ret_t +mlk_js_texture_scale(duk_context *ctx) +{ + struct mlk_texture *tex = mlk_js_texture_this(ctx); + int srcx, srcy, dstx, dsty; + unsigned int srcw, srch, dstw, dsth; + double angle; + + /* Source rectangle. */ + duk_require_object(ctx, 0); + duk_get_prop_string(ctx, 0, "x"); + srcx = duk_to_int(ctx, -1); + duk_get_prop_string(ctx, 0, "y"); + srcy = duk_to_int(ctx, -1); + duk_get_prop_string(ctx, 0, "w"); + srcw = duk_is_number(ctx, -1) ? duk_to_uint(ctx, -1) : tex->w; + duk_get_prop_string(ctx, 0, "h"); + srch = duk_is_number(ctx, -1) ? duk_to_uint(ctx, -1) : tex->h; + duk_pop_n(ctx, 4); + + /* Destination rectangle. */ + duk_require_object(ctx, 1); + duk_get_prop_string(ctx, 1, "x"); + dstx = duk_to_int(ctx, -1); + duk_get_prop_string(ctx, 1, "y"); + dsty = duk_to_int(ctx, -1); + duk_get_prop_string(ctx, 1, "w"); + dstw = duk_is_number(ctx, -1) ? duk_to_uint(ctx, -1) : tex->w; + duk_get_prop_string(ctx, 1, "h"); + dsth = duk_is_number(ctx, -1) ? duk_to_uint(ctx, -1) : tex->h; + duk_pop_n(ctx, 4); + + /* Angle. */ + angle = duk_to_number(ctx, 2); + + if (mlk_texture_scale(tex, srcx, srcy, srcw, srch, dstx, dsty, dstw, dsth, angle) < 0) + return duk_error(ctx, DUK_ERR_ERROR, "%s", mlk_err()); + + return 0; +} + +static duk_ret_t +mlk_js_texture_finish(duk_context *ctx) +{ + struct mlk_texture *tex; + + duk_get_prop_string(ctx, 0, SYMBOL); + tex = duk_to_pointer(ctx, -1); + duk_pop(ctx); + duk_del_prop_string(ctx, 0, SYMBOL); + + if (tex) { + mlk_texture_finish(tex); + mlk_alloc_free(tex); + } + + return 0; +} + +static duk_ret_t +mlk_js_texture_fromImage(duk_context *ctx) +{ + const char *path = duk_require_string(ctx, 0); + struct mlk_texture tex; + + if (mlk_image_open(&tex, path) < 0) + return duk_error(ctx, DUK_ERR_ERROR, "%s", mlk_err()); + + mlk_js_texture_push(ctx, &tex); + + return 1; +} + +static const duk_function_list_entry methods[] = { + { "draw", mlk_js_texture_draw, 1 }, + { "scale", mlk_js_texture_scale, 3 }, + { NULL, NULL, 0 } +}; + +static const duk_function_list_entry functions[] = { + { "fromImage", mlk_js_texture_fromImage, 1 }, + { NULL, NULL, 0 } +}; + +struct mlk_texture * +mlk_js_texture_require(duk_context *ctx, duk_idx_t index) +{ + struct mlk_texture *tex; + + duk_get_prop_string(ctx, index, SYMBOL); + tex = duk_to_pointer(ctx, -1); + duk_pop(ctx); + + if (!tex) + duk_error(ctx, DUK_ERR_TYPE_ERROR, "Texture expected on argument #%u", index); + + return tex; +} + +void +mlk_js_texture_push(duk_context *ctx, const struct mlk_texture *tex) +{ + assert(ctx); + assert(tex); + + duk_push_object(ctx); + duk_push_global_stash(ctx); + duk_get_prop_string(ctx, -1, PROTO); + duk_remove(ctx, -2); + duk_push_pointer(ctx, mlk_alloc_dup(tex, 1, sizeof (*tex))); + duk_put_prop_string(ctx, -3, SYMBOL); + duk_set_prototype(ctx, -2); + + /* Put some properties. */ + duk_push_string(ctx, "width"); + duk_push_c_function(ctx, mlk_js_texture_getWidth, 0); + duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_GETTER); + duk_push_string(ctx, "height"); + duk_push_c_function(ctx, mlk_js_texture_getHeight, 0); + duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_GETTER); + duk_push_string(ctx, "blendMode"); + duk_push_c_function(ctx, mlk_js_texture_setBlendMode, 1); + duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_SETTER); + duk_push_string(ctx, "alphaMod"); + duk_push_c_function(ctx, mlk_js_texture_setAlphaMod, 1); + duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_SETTER); + duk_push_string(ctx, "colorMod"); + duk_push_c_function(ctx, mlk_js_texture_setColorMod, 1); + duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_SETTER); +} + +void +mlk_js_texture_load(duk_context *ctx) +{ + assert(ctx); + + duk_push_global_object(ctx); + duk_get_prop_string(ctx, -1, "Mlk"); + duk_push_c_function(ctx, mlk_js_texture_new, 2); + duk_put_function_list(ctx, -1, functions); + duk_push_object(ctx); + duk_put_function_list(ctx, -1, methods); + duk_push_c_function(ctx, mlk_js_texture_finish, 1); + duk_set_finalizer(ctx, -2); + duk_push_global_stash(ctx); + duk_dup(ctx, -2); + duk_put_prop_string(ctx, -2, PROTO); + duk_pop(ctx); + duk_put_prop_string(ctx, -2, "prototype"); + duk_put_prop_string(ctx, -2, "Texture"); + duk_pop_n(ctx, 2); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmlk-core/mlk/core/js/js-texture.h Sun Dec 17 09:50:36 2023 +0100 @@ -0,0 +1,43 @@ +/* + * js-texture.h -- basic texture management (Javascript bindings) + * + * Copyright (c) 2020-2023 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_TEXTURE_H +#define MLK_CORE_JS_TEXTURE_H + +#include <duktape.h> + +struct mlk_texture; + +#if defined(__cplusplus) +extern "C" { +#endif + +struct mlk_texture * +mlk_js_texture_require(duk_context *ctx, duk_idx_t index); + +void +mlk_js_texture_push(duk_context *ctx, const struct mlk_texture *tex); + +void +mlk_js_texture_load(duk_context *ctx); + +#if defined(__cplusplus) +} +#endif + +#endif /* !MLK_CORE_JS_TEXTURE_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmlk-core/mlk/core/js/js-util.c Sun Dec 17 09:50:36 2023 +0100 @@ -0,0 +1,50 @@ +/* + * js-util.c -- utilities (Javascript bindings) + * + * Copyright (c) 2020-2023 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 <mlk/core/util.h> + +#include "js-util.h" +#include "js.h" + +static duk_ret_t +mlk_js_util_sleep(duk_context *ctx) +{ + mlk_util_sleep(duk_require_uint(ctx, 0)); + + return 0; +} + +static const duk_function_list_entry functions[] = { + { "sleep", mlk_js_util_sleep, 1 }, + { NULL, NULL, 0 } +}; + +void +mlk_js_util_load(duk_context *ctx) +{ + assert(ctx); + + duk_push_global_object(ctx); + duk_get_prop_string(ctx, -1, "Mlk"); + duk_push_object(ctx); + duk_put_function_list(ctx, -1, functions); + duk_put_prop_string(ctx, -2, "Util"); + duk_pop_n(ctx, 2); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmlk-core/mlk/core/js/js-util.h Sun Dec 17 09:50:36 2023 +0100 @@ -0,0 +1,35 @@ +/* + * js-util.h -- utilities (Javascript bindings) + * + * Copyright (c) 2020-2023 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_UTIL_H +#define MLK_CORE_JS_UTIL_H + +#include <duktape.h> + +#if defined(__cplusplus) +extern "C" { +#endif + +void +mlk_js_util_load(duk_context *ctx); + +#if defined(__cplusplus) +} +#endif + +#endif /* !MLK_CORE_JS_UTIL_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmlk-core/mlk/core/js/js-window.c Sun Dec 17 09:50:36 2023 +0100 @@ -0,0 +1,85 @@ +/* + * js-window.c -- basic window management (Javascript bindings) + * + * Copyright (c) 2020 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 <mlk/core/err.h> +#include <mlk/core/window.h> + +#include "js-window.h" +#include "js.h" + +static duk_ret_t +mlk_js_window_setCursor(duk_context *ctx) +{ + enum mlk_window_cursor cursor = duk_require_int(ctx, 0); + + if (cursor < 0 || cursor > MLK_WINDOW_CURSOR_LAST) + return duk_error(ctx, DUK_ERR_TYPE_ERROR, "invalid cursor type: %d", cursor); + + mlk_window_set_cursor(cursor); + + return 0; +} + +static duk_ret_t +mlk_js_window_new(duk_context *ctx) +{ + const char *str = duk_require_string(ctx, 0); + unsigned int w = duk_require_int(ctx, 1); + unsigned int h = duk_require_int(ctx, 2); + + if (!duk_is_constructor_call(ctx)) + return duk_error(ctx, DUK_ERR_TYPE_ERROR, "Window must be new-constructed"); + if (mlk_window_open(str, w, h) < 0) + duk_error(ctx, DUK_ERR_ERROR, "%s", mlk_err()); + + duk_push_this(ctx); + duk_push_string(ctx, "cursor"); + duk_push_c_function(ctx, mlk_js_window_setCursor, 1); + duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_SETTER); + duk_pop(ctx); + + return 0; +} + +static const duk_number_list_entry cursors[] = { + { "ARROW", MLK_WINDOW_CURSOR_ARROW }, + { "EDIT", MLK_WINDOW_CURSOR_EDIT }, + { "WAIT", MLK_WINDOW_CURSOR_WAIT }, + { "CROSS_HAIR", MLK_WINDOW_CURSOR_CROSSHAIR }, + { "SIZE", MLK_WINDOW_CURSOR_SIZE }, + { "NO", MLK_WINDOW_CURSOR_NO }, + { "HAND", MLK_WINDOW_CURSOR_HAND }, + { NULL, 0 } +}; + +void +mlk_js_window_load(duk_context *ctx) +{ + assert(ctx); + + duk_push_global_object(ctx); + duk_get_prop_string(ctx, -1, "Mlk"); + duk_push_c_function(ctx, mlk_js_window_new, 3); + duk_push_object(ctx); + duk_put_number_list(ctx, -1, cursors); + duk_put_prop_string(ctx, -2, "Cursor"); + duk_put_prop_string(ctx, -2, "Window"); + duk_pop_n(ctx, 2); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmlk-core/mlk/core/js/js-window.h Sun Dec 17 09:50:36 2023 +0100 @@ -0,0 +1,35 @@ +/* + * js-window.h -- basic window management (Javascript bindings) + * + * Copyright (c) 2020-2023 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_WINDOW_H +#define MLK_CORE_JS_WINDOW_H + +#include <duktape.h> + +#if defined(__cplusplus) +extern "C" { +#endif + +void +mlk_js_window_load(duk_context *ctx); + +#if defined(__cplusplus) +} +#endif + +#endif /* !MLK_CORE_JS_WINDOW_H */
--- a/libmlk-core/mlk/core/js/js.c Sun Oct 01 09:18:01 2023 +0200 +++ b/libmlk-core/mlk/core/js/js.c Sun Dec 17 09:50:36 2023 +0100 @@ -137,6 +137,7 @@ duk_pop(js->handle); } +#if 0 static void setup_base(struct mlk_js *js, const char *path) { @@ -150,6 +151,7 @@ duk_put_prop_string(js->handle, -2, DUK_HIDDEN_SYMBOL("mlk::base")); duk_pop(js->handle); } +#endif int js_init(struct mlk_js *js)
--- a/libmlk-core/mlk/core/js/js.h Sun Oct 01 09:18:01 2023 +0200 +++ b/libmlk-core/mlk/core/js/js.h Sun Dec 17 09:50:36 2023 +0100 @@ -23,10 +23,18 @@ void *handle; }; +#if defined(__cplusplus) +extern "C" { +#endif + int mlk_js_init(struct mlk_js *js); void mlk_js_finish(struct mlk_js *js); +#if defined(__cplusplus) +} +#endif + #endif /* !MLK_CORE_JS_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmlk-core/mlk/core/js/main.c Sun Dec 17 09:50:36 2023 +0100 @@ -0,0 +1,165 @@ +/* + * main.c -- main Javascript loader + * + * Copyright (c) 2020 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 <errno.h> +#include <setjmp.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdnoreturn.h> +#include <string.h> + +#include <core/alloc.h> +#include <core/core.h> +#include <core/error.h> +#include <core/event.h> +#include <core/painter.h> +#include <core/panic.h> +#include <core/window.h> + +#include <ui/label.h> +#include <ui/ui.h> + +#include <rpg/rpg.h> + +#include "js.h" + +static jmp_buf panic_buf; + +static noreturn void +jump(void) +{ + longjmp(panic_buf, 1); +} + +static noreturn void +usage(void) +{ + fprintf(stderr, "usage: molko-js main.js\n"); + exit(1); +} + +static noreturn void +die(void) +{ + fprintf(stderr, "abort: %s\n", error()); + exit(1); +} + +static void +init(void) +{ + if (!core_init() || !ui_init() || !rpg_init()) + panic(); + + panic_handler = jump; +} + +static void +draw_info(void) +{ + struct label label = { + .text = "An unexpected error happened, game must stops.", + .x = 10, + .y = 10, + .flags = LABEL_FLAGS_SHADOW + }; + + label_draw(&label); +} + +static void +draw_error(void) +{ + struct label label = { + .text = error(), + .x = 10, + .y = 40, + .flags = LABEL_FLAGS_SHADOW + }; + + label_draw(&label); +} + +static void +run_panic(void) +{ + panic_handler = die; + + for (;;) { + union event ev; + + while (event_poll(&ev)) { + switch (ev.type) { + case EVENT_QUIT: + return; + default: + break; + } + } + + painter_set_color(0x752438ff); + painter_clear(); + draw_info(); + draw_error(); + painter_present(); + } +} + +static void +run(const char *path) +{ + struct js js; + + if (setjmp(panic_buf) == 0) { + if (!js_init(&js)) + panic(); + + js_core_load(&js); + + if (!js_open(&js, path)) + panic(); + } else { + /* TODO: change once we have window_ok function. */ + if (window.w && window.h) + run_panic(); + else + die(); + } +} + +static void +quit(void) +{ + rpg_finish(); + ui_finish(); + core_finish(); +} + +int +main(int argc, char **argv) +{ + --argc; + ++argv; + + if (argc == 0) + usage(); + + init(); + run(argv[0]); + quit(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mlk-run/CMakeLists.txt Sun Dec 17 09:50:36 2023 +0100 @@ -0,0 +1,34 @@ +# +# CMakeLists.txt -- CMake build system for Molko's Engine +# +# Copyright (c) 2020-2023 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. +# + +project(mlk-run) + +set( + SOURCES + ${mlk-run_SOURCE_DIR}/mlk-run.c +) + +mlk_executable( + NAME mlk-run + SOURCES ${SOURCES} + LIBRARIES libmlk-core-js + INSTALL + FOLDER tools +) + +add_executable(mlk::mlk-run ALIAS mlk-run)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mlk-run/mlk-run.c Sun Dec 17 09:50:36 2023 +0100 @@ -0,0 +1,197 @@ +/* + * main.c -- main mlk-run file + * + * Copyright (c) 2020-2023 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 <stdio.h> +#include <stdlib.h> +#include <limits.h> + +#include <duktape.h> +#include <duk_module.h> + +#include <mlk/util/util.h> + +#include <mlk/core/core.h> +#include <mlk/core/err.h> +#include <mlk/core/panic.h> +#include <mlk/core/vfs-dir.h> +#include <mlk/core/vfs-zip.h> +#include <mlk/core/vfs.h> + +union { + struct mlk_vfs_dir dir; + +#if defined(MLK_WITH_ZIP) + struct mlk_vfs_zip zip; +#endif +} iface; + +/* VFS loader to support zip and directories when loading game. */ +static struct mlk_vfs *vfs; + +/* Javascript context. */ +static duk_context *ctx; + +static duk_ret_t +modsearch(duk_context *ctx) +{ + char path[MLK_PATH_MAX] = {}, *data; + struct mlk_vfs_file *file; + size_t datasz; + + snprintf(path, sizeof (path), "%s.js", duk_require_string(ctx, 0)); + + if ((file = mlk_vfs_open(vfs, path, "r")) < 0) + return duk_error(ctx, DUK_ERR_ERROR, "%s", mlk_err()); + if (!(data = mlk_vfs_file_read_all(file, &datasz))) { + mlk_vfs_file_finish(file); + return duk_error(ctx, DUK_ERR_ERROR, "%s", mlk_err()); + } + + mlk_vfs_file_finish(file); + duk_push_lstring(ctx, data, datasz); + free(data); + + return 1; +} + +static void +core_bind(duk_context *ctx) +{ +#if 0 + /* Brings Mlk global object. */ + mlk_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); + js_drawable_bind(ctx); + js_drawable_stack_bind(ctx); + js_event_bind(ctx); + js_font_bind(ctx); + js_game_bind(ctx); + js_music_bind(ctx); + js_painter_bind(ctx); + js_panic_bind(ctx); + js_sound_bind(ctx); + js_sprite_bind(ctx); + js_state_bind(ctx); + js_texture_bind(ctx); + js_trace_bind(ctx); + js_window_bind(ctx); +#endif +} + +static void +init(void) +{ + /* TODO: this is temporary. */ + if (mlk_core_init("fr.malikania", "mlk-run") < 0) + mlk_panic(); + + /* Fireup Javascript. */ + ctx = duk_create_heap_default(); + core_bind(ctx); + + /* Setup module loader. */ + duk_module_duktape_init(ctx); + duk_get_global_string(ctx, "Duktape"); + duk_push_c_function(ctx, modsearch, 4); + duk_put_prop_string(ctx, -2, "modSearch"); + duk_pop(ctx); +} + +static void +startup(void) +{ + struct mlk_vfs_file *file; + char *code; + + if (!(file = mlk_vfs_open(vfs, "main.js", "r"))) + mlk_panic(); + if (!(code = mlk_vfs_file_read_all(file, NULL))) { + mlk_vfs_file_finish(file); + mlk_panic(); + } + + mlk_vfs_file_finish(file); + + if (duk_peval_string(ctx, code)) + mlk_panicf("%s", duk_safe_to_string(ctx, -1)); + + free(code); +} + +static void +finish(void) +{ + mlk_vfs_finish(vfs); + duk_destroy_heap(ctx); +} + +static void +loadzip(const char *path) +{ +#if 0 + if (vfs_zip(&vfs, path, "r") < 0) + panic(); +#endif +} + +static void +loaddirectory(const char *path) +{ +#if 0 + vfs_directory(&vfs, path); +#endif +} + +static void +load(const char *path) +{ + /* TODO: improve this. */ + if (strstr(path, ".mlk")) + loadzip(path); + else + loaddirectory(path); + + startup(); +} + +static void +run(int argc, char **argv) +{ + if (argc < 0) { + fprintf(stderr, "usage: mlk-run game\n"); + exit(1); + } + + load(argv[0]); +} + +int +main(int argc, char **argv) +{ + --argc; + ++argv; + + init(); + run(argc, argv); + finish(); +}