diff --git a/assets/scripts/overworldscene.js b/assets/scripts/OverworldScene.js similarity index 100% rename from assets/scripts/overworldscene.js rename to assets/scripts/OverworldScene.js diff --git a/assets/scripts/init.js b/assets/scripts/init.js index c6ead742..ff7e021e 100644 --- a/assets/scripts/init.js +++ b/assets/scripts/init.js @@ -1,5 +1,5 @@ require('./input.js'); -var OverworldScene = require('./overworldscene.js'); +var OverworldScene = require('./OverworldScene.js'); Scene.set(new OverworldScene()); \ No newline at end of file diff --git a/src/dusk/script/module/CMakeLists.txt b/src/dusk/script/module/CMakeLists.txt index 1dc53ad2..856d7105 100644 --- a/src/dusk/script/module/CMakeLists.txt +++ b/src/dusk/script/module/CMakeLists.txt @@ -15,3 +15,4 @@ add_subdirectory(display) add_subdirectory(time) add_subdirectory(console) add_subdirectory(input) +add_subdirectory(ui) diff --git a/src/dusk/script/module/modulelist.c b/src/dusk/script/module/modulelist.c index bff0ff4e..ae6ce14e 100644 --- a/src/dusk/script/module/modulelist.c +++ b/src/dusk/script/module/modulelist.c @@ -16,6 +16,7 @@ #include "script/module/scene/modulescene.h" #include "script/module/console/moduleconsole.h" #include "script/module/input/moduleinput.h" +#include "script/module/ui/moduleui.h" void moduleListInit(void) { modulePlatform(); @@ -24,6 +25,7 @@ void moduleListInit(void) { moduleTimeInit(); moduleConsoleInit(); moduleInputInit(); + moduleUiInit(); moduleComponentInit(); moduleComponentListInit(); moduleEntityInit(); @@ -35,6 +37,7 @@ void moduleListDispose(void) { moduleEntityDispose(); moduleComponentListDispose(); moduleComponentDispose(); + moduleUiDispose(); moduleInputDispose(); moduleConsoleDispose(); moduleTimeDispose(); diff --git a/src/dusk/script/module/modulelist.h b/src/dusk/script/module/modulelist.h index ca4e0850..1c24b597 100644 --- a/src/dusk/script/module/modulelist.h +++ b/src/dusk/script/module/modulelist.h @@ -9,8 +9,8 @@ /** * Registers every script module (Component + its typed per-type - * wrappers, Entity, Scene, require(), Mesh, Time, Console, Input, the - * platform globals). Called once by scriptManagerInit(). + * wrappers, Entity, Scene, require(), Mesh, Time, Console, Input, UI, + * the platform globals). Called once by scriptManagerInit(). */ void moduleListInit(void); diff --git a/src/dusk/script/module/ui/CMakeLists.txt b/src/dusk/script/module/ui/CMakeLists.txt new file mode 100644 index 00000000..a2c2bf0f --- /dev/null +++ b/src/dusk/script/module/ui/CMakeLists.txt @@ -0,0 +1,9 @@ +# Copyright (c) 2026 Dominic Masters +# +# This software is released under the MIT License. +# https://opensource.org/licenses/MIT + +target_sources(${DUSK_LIBRARY_TARGET_NAME} + PUBLIC + moduleui.c +) diff --git a/src/dusk/script/module/ui/moduleui.c b/src/dusk/script/module/ui/moduleui.c new file mode 100644 index 00000000..16034273 --- /dev/null +++ b/src/dusk/script/module/ui/moduleui.c @@ -0,0 +1,64 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "moduleui.h" +#include "script/module/modulebase.h" +#include "console/console.h" + +// Stub: stringify " " (like Console.print) and forward to +// consolePrint(), so UI.add/UI.remove are visibly wired up before there's +// any real UI system behind them. +static jerry_value_t moduleUiLogCall( + const char_t *name, + const jerry_value_t args[], + const jerry_length_t argc +) { + char_t buffer[CONSOLE_LINE_MAX]; + size_t pos = strlen(name); + if(pos >= CONSOLE_LINE_MAX) pos = CONSOLE_LINE_MAX - 1; + memoryCopy(buffer, name, pos); + + for(jerry_length_t i = 0; i < argc; i++) { + jerry_value_t strVal = jerry_value_to_string(args[i]); + if(jerry_value_is_exception(strVal)) return strVal; + + if(pos + 1 < CONSOLE_LINE_MAX) buffer[pos++] = ' '; + + jerry_size_t written = jerry_string_to_buffer( + strVal, JERRY_ENCODING_UTF8, + (jerry_char_t *)(buffer + pos), (jerry_size_t)(CONSOLE_LINE_MAX - pos - 1) + ); + jerry_value_free(strVal); + pos += written; + } + buffer[pos] = '\0'; + + // Fixed "%s" format -- buffer is arbitrary JS-provided text and must + // never be used as the format string itself. + consolePrint("%s", buffer); + + return jerry_undefined(); +} + +moduleBaseFunction(moduleUiAddFn) { + return moduleUiLogCall("UI.add", args, argc); +} + +moduleBaseFunction(moduleUiRemoveFn) { + return moduleUiLogCall("UI.remove", args, argc); +} + +void moduleUiInit(void) { + jerry_value_t uiObj = jerry_object(); + moduleBaseDefineMethod(uiObj, "add", moduleUiAddFn); + moduleBaseDefineMethod(uiObj, "remove", moduleUiRemoveFn); + moduleBaseSetValue("UI", uiObj); + jerry_value_free(uiObj); +} + +void moduleUiDispose(void) { +} diff --git a/src/dusk/script/module/ui/moduleui.h b/src/dusk/script/module/ui/moduleui.h new file mode 100644 index 00000000..0b636fd5 --- /dev/null +++ b/src/dusk/script/module/ui/moduleui.h @@ -0,0 +1,21 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once + +/** + * Registers the global `UI` object, exposing `UI.add(...)` and + * `UI.remove(...)`. Both are stubs for now -- they stringify and + * space-join their arguments (like Console.print) and forward the + * result to consolePrint(), prefixed with the called method's name. + */ +void moduleUiInit(void); + +/** + * Disposes the UI module's script resources. + */ +void moduleUiDispose(void); diff --git a/test/script/CMakeLists.txt b/test/script/CMakeLists.txt index d47d4bb0..21287129 100644 --- a/test/script/CMakeLists.txt +++ b/test/script/CMakeLists.txt @@ -19,3 +19,5 @@ dusktest(test_scriptinput.c) target_compile_definitions(test_scriptinput PRIVATE DUSK_ASSETS_DIR="${DUSK_ASSETS_DIR}" ) + +dusktest(test_moduleui.c) diff --git a/test/script/test_moduleui.c b/test/script/test_moduleui.c new file mode 100644 index 00000000..8d30fea3 --- /dev/null +++ b/test/script/test_moduleui.c @@ -0,0 +1,83 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "dusktest.h" +#include "console/console.h" +#include "script/scriptmanager.h" +#include "util/memory.h" + +static int ui_setup(void **state) { + consoleInit(); + + errorret_t ret = scriptManagerInit(); + if(errorIsNotOk(ret)) { errorCatch(ret); return -1; } + + return 0; +} + +static int ui_teardown(void **state) { + errorret_t ret = scriptManagerDispose(); + if(errorIsNotOk(ret)) errorCatch(ret); + + consoleDispose(); + return 0; +} + +static void test_ui_add_logs_prefixed_args(void **state) { + jerry_value_t result; + errorret_t ret = scriptManagerExec( + "UI.add('button', 1, true);", &result + ); + assert_true(errorIsOk(ret)); + jerry_value_free(result); + + assert_string_equal( + CONSOLE.line[CONSOLE_HISTORY_MAX - 1], "UI.add button 1 true" + ); + + assert_int_equal(memoryGetAllocatedCount(), 0); +} + +static void test_ui_remove_logs_prefixed_args(void **state) { + jerry_value_t result; + errorret_t ret = scriptManagerExec("UI.remove('button');", &result); + assert_true(errorIsOk(ret)); + jerry_value_free(result); + + assert_string_equal( + CONSOLE.line[CONSOLE_HISTORY_MAX - 1], "UI.remove button" + ); + + assert_int_equal(memoryGetAllocatedCount(), 0); +} + +static void test_ui_add_no_args_logs_just_the_name(void **state) { + jerry_value_t result; + errorret_t ret = scriptManagerExec("UI.add();", &result); + assert_true(errorIsOk(ret)); + jerry_value_free(result); + + assert_string_equal(CONSOLE.line[CONSOLE_HISTORY_MAX - 1], "UI.add"); + + assert_int_equal(memoryGetAllocatedCount(), 0); +} + +int main(void) { + assertInit(); + const struct CMUnitTest tests[] = { + cmocka_unit_test_setup_teardown( + test_ui_add_logs_prefixed_args, ui_setup, ui_teardown + ), + cmocka_unit_test_setup_teardown( + test_ui_remove_logs_prefixed_args, ui_setup, ui_teardown + ), + cmocka_unit_test_setup_teardown( + test_ui_add_no_args_logs_just_the_name, ui_setup, ui_teardown + ), + }; + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/types/index.d.ts b/types/index.d.ts index d4d9ad81..a22b0abb 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -15,3 +15,4 @@ /// /// /// +/// diff --git a/types/ui/ui.d.ts b/types/ui/ui.d.ts new file mode 100644 index 00000000..5ba0c548 --- /dev/null +++ b/types/ui/ui.d.ts @@ -0,0 +1,15 @@ +// Copyright (c) 2026 Dominic Masters +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +/** + * Stub for now: both methods just stringify and space-join their + * arguments (like console.log) and forward the result to the engine's + * console, prefixed with the called method's name. No real UI element + * system exists behind this yet. + */ +declare const UI: { + add(...args: any[]): void; + remove(...args: any[]): void; +};