diff --git a/assets/init.js b/assets/init.js index 97efc1e4..da9b32ea 100644 --- a/assets/init.js +++ b/assets/init.js @@ -1,3 +1,5 @@ +Console.visible = true; + // Default input bindings. if (typeof PSP !== 'undefined') { Input.bind("up", INPUT_ACTION_UP); diff --git a/assets/scenes/cube.js b/assets/scenes/cube.js index 433f2d28..e8dc7b0f 100644 --- a/assets/scenes/cube.js +++ b/assets/scenes/cube.js @@ -9,6 +9,11 @@ function CubeScene() { this.cam.position.lookAt(new Vec3(0, 0, 0)); this.cube = new CubeEntity(); + + this.spriteEnt = new Entity(); + this.spriteEnt.add(POSITION); + this.spriteEnt.position.position = new Vec3(16, 16, 0); + // this.spriteEnt.sprite.setTexture('ui/minogram.png'); } CubeScene.prototype = Object.create(Scene.prototype); @@ -21,6 +26,7 @@ CubeScene.prototype.update = function() { CubeScene.prototype.dispose = function() { this.cam.dispose(); this.cube.dispose(); + this.spriteEnt.dispose(); }; module = CubeScene; diff --git a/src/dusk/console/CMakeLists.txt b/src/dusk/console/CMakeLists.txt index 42ade831..2668e0b3 100644 --- a/src/dusk/console/CMakeLists.txt +++ b/src/dusk/console/CMakeLists.txt @@ -1,15 +1,9 @@ -# Copyright (c) 2025 Dominic Masters -# +# Copyright (c) 2026 Dominic Masters +# # This software is released under the MIT License. # https://opensource.org/licenses/MIT -# Sources target_sources(${DUSK_LIBRARY_TARGET_NAME} PUBLIC console.c - consolecmd.c - consolevar.c ) - -# Subdirectories -add_subdirectory(cmd) \ No newline at end of file diff --git a/src/dusk/console/cmd/CMakeLists.txt b/src/dusk/console/cmd/CMakeLists.txt deleted file mode 100644 index 57c6ef05..00000000 --- a/src/dusk/console/cmd/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2025 Dominic Masters -# -# This software is released under the MIT License. -# https://opensource.org/licenses/MIT - -# Sources -target_sources(${DUSK_LIBRARY_TARGET_NAME} - PUBLIC -) \ No newline at end of file diff --git a/src/dusk/console/cmd/cmdbind.h b/src/dusk/console/cmd/cmdbind.h deleted file mode 100644 index 6e300bfc..00000000 --- a/src/dusk/console/cmd/cmdbind.h +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "console/console.h" -#include "input/input.h" - -void cmdBind(const consolecmdexec_t *exec) { - if(exec->argc < 1) { - consolePrint("Expected 1 argument: argv[0]); - if(button.type == INPUT_BUTTON_TYPE_NONE) { - consolePrint("Unknown button \"%s\"", exec->argv[0]); - return; - } - - if(exec->argc == 1) { - // Get the button data for this button. - inputbuttondata_t *data = inputButtonGetData(button); - assertNotNull(data, "Input button not found"); - - inputaction_t act = data->action; - if(act == INPUT_ACTION_NULL || act >= INPUT_ACTION_COUNT) { - consolePrint("%s is not bound.", data->name); - } else { - consolePrint("%s is bound to %s.", data->name, INPUT_ACTION_IDS[act]); - } - return; - } - - inputaction_t action = inputActionGetByName(exec->argv[1]); - if(action == INPUT_ACTION_COUNT) { - consolePrint("Unknown action \"%s\"", exec->argv[1]); - return; - } - - inputBind(button, action); -} \ No newline at end of file diff --git a/src/dusk/console/cmd/cmdecho.h b/src/dusk/console/cmd/cmdecho.h deleted file mode 100644 index 6bcd1593..00000000 --- a/src/dusk/console/cmd/cmdecho.h +++ /dev/null @@ -1,18 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "console/console.h" - -void cmdEcho(const consolecmdexec_t *exec) { - if(exec->argc < 1) { - consolePrint("Expected 1 argument: "); - return; - } - - consolePrint("%s", exec->argv[0]); -} \ No newline at end of file diff --git a/src/dusk/console/cmd/cmdget.h b/src/dusk/console/cmd/cmdget.h deleted file mode 100644 index 6b6cb138..00000000 --- a/src/dusk/console/cmd/cmdget.h +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "console/console.h" - -void cmdGet(const consolecmdexec_t *exec) { - assertTrue( - exec->argc >= 1, - "Get command requires 1 argument." - ); - - for(uint32_t i = 0; i < CONSOLE.variableCount; i++) { - consolevar_t *var = &CONSOLE.variables[i]; - if(stringCompare(var->name, exec->argv[0]) != 0) continue; - consolePrint("%s", var->value); - return; - } - - consolePrint("Error: Variable '%s' not found.", exec->argv[0]); -} \ No newline at end of file diff --git a/src/dusk/console/cmd/cmdquit.h b/src/dusk/console/cmd/cmdquit.h deleted file mode 100644 index d1e3474d..00000000 --- a/src/dusk/console/cmd/cmdquit.h +++ /dev/null @@ -1,14 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "console/console.h" -#include "engine/engine.h" - -void cmdQuit(const consolecmdexec_t *exec) { - ENGINE.running = false; -} \ No newline at end of file diff --git a/src/dusk/console/cmd/cmdset.h b/src/dusk/console/cmd/cmdset.h deleted file mode 100644 index 64816452..00000000 --- a/src/dusk/console/cmd/cmdset.h +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "console/console.h" - -void cmdSet(const consolecmdexec_t *exec) { - assertTrue(exec->argc >= 2, "set command requires 2 arguments."); - - for(uint32_t i = 0; i < CONSOLE.variableCount; i++) { - consolevar_t *var = &CONSOLE.variables[i]; - if(stringCompare(var->name, exec->argv[0]) != 0) continue; - consoleVarSetValue(var, exec->argv[1]); - // consolePrint("%s %s", var->name, var->value); - for(i = 0; i < var->eventCount; i++) { - assertNotNull(var->events[i], "Event is NULL"); - var->events[i](var); - } - return; - } - - consolePrint("Error: Variable '%s' not found.", exec->argv[0]); -} \ No newline at end of file diff --git a/src/dusk/console/cmd/cmdtime.h b/src/dusk/console/cmd/cmdtime.h deleted file mode 100644 index 5463bd2d..00000000 --- a/src/dusk/console/cmd/cmdtime.h +++ /dev/null @@ -1,14 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "console/console.h" -#include "time/time.h" - -void cmdTime(const consolecmdexec_t *exec) { - consolePrint("Time: %.2f", TIME.time); -} \ No newline at end of file diff --git a/src/dusk/console/console.c b/src/dusk/console/console.c index 0cd83d72..1ebc42b0 100644 --- a/src/dusk/console/console.c +++ b/src/dusk/console/console.c @@ -1,6 +1,6 @@ /** - * Copyright (c) 2025 Dominic Masters - * + * Copyright (c) 2026 Dominic Masters + * * This software is released under the MIT License. * https://opensource.org/licenses/MIT */ @@ -12,40 +12,16 @@ #include "input/input.h" #include "log/log.h" #include "engine/engine.h" - -#include "console/cmd/cmdecho.h" -#include "console/cmd/cmdset.h" -#include "console/cmd/cmdget.h" -#include "console/cmd/cmdquit.h" -#include "console/cmd/cmdbind.h" -#include "console/cmd/cmdtime.h" - +#include "script/scriptmanager.h" #include "display/shader/shaderunlit.h" #include "display/text/text.h" #include "display/spritebatch/spritebatch.h" console_t CONSOLE; -void consoleInit() { +void consoleInit(void) { memoryZero(&CONSOLE, sizeof(console_t)); - // Register vars - #define REG(name, value) consoleRegVar(name, value, NULL) - REG("console", "1"); - #undef REG - - // Register cmdss - CONSOLE.cmdGet = consoleRegCmd("get", cmdGet); - CONSOLE.cmdSet = consoleRegCmd("set", cmdSet); - - #define REG(name, func) consoleRegCmd(name, func) - REG("echo", cmdEcho); - REG("quit", cmdQuit); - REG("exit", cmdQuit); - REG("bind", cmdBind); - REG("time", cmdTime); - #undef REG - #ifdef DUSK_CONSOLE_POSIX threadInit(&CONSOLE.thread, consoleInputThread); threadMutexInit(&CONSOLE.execMutex); @@ -54,68 +30,6 @@ void consoleInit() { #endif } -consolecmd_t * consoleRegCmd(const char_t *name, consolecmdfunc_t function) { - consolecmd_t *cmd = &CONSOLE.commands[CONSOLE.commandCount++]; - consoleCmdInit(cmd, name, function); - return cmd; -} - -consolevar_t * consoleRegVar( - const char_t *name, - const char_t *value, - consolevarchanged_t event -) { - consolevar_t *var; - - // Existing? - var = consoleVarGet(name); - if(var != NULL) return var; - - assertTrue( - CONSOLE.variableCount < CONSOLE_VARIABLES_MAX, - "Too many console variables registered." - ); - - // Create - var = &CONSOLE.variables[CONSOLE.variableCount++]; - consoleVarInitListener(var, name, value, event); - return var; -} - -consolevar_t * consoleVarGet(const char_t *name) { - assertNotNull(name, "name must not be NULL"); - for(uint32_t i = 0; i < CONSOLE.variableCount; i++) { - consolevar_t *var = &CONSOLE.variables[i]; - if(stringCompare(var->name, name) == 0) return var; - } - return NULL; -} - -int32_t consoleVarGetInt(const char_t *name, const int32_t initial) { - consolevar_t *var = consoleVarGet(name); - if(var == NULL) return initial; - char *end; - int32_t value = (int32_t)strtol(var->value, &end, 10); - if(*end != '\0') return initial; - return value; -} - -bool_t consoleVarGetBool(const char_t *name, const bool_t initial) { - return consoleVarGetInt(name, initial ? 1 : 0) != 0; -} - -void consoleVarSetInt(const char_t *name, const int32_t value) { - consolevar_t *existing = consoleVarGet(name); - assertNotNull(existing, "Variable not found"); - char_t buffer[CONSOLE_VAR_VALUE_MAX]; - stringFormat(buffer, CONSOLE_VAR_VALUE_MAX, "%d", value); - consoleVarSetValue(existing, buffer); -} - -void consoleVarSetBool(const char_t *name, const bool_t value) { - consoleVarSetInt(name, value ? 1 : 0); -} - void consolePrint(const char_t *message, ...) { char_t buffer[CONSOLE_LINE_MAX]; @@ -128,19 +42,12 @@ void consolePrint(const char_t *message, ...) { threadMutexLock(&CONSOLE.printMutex); #endif - // Move all lines back memoryMove( CONSOLE.line[0], CONSOLE.line[1], (CONSOLE_HISTORY_MAX - 1) * CONSOLE_LINE_MAX ); - - // Copy the new line - memoryCopy( - CONSOLE.line[CONSOLE_HISTORY_MAX - 1], - buffer, - len + 1 - ); + memoryCopy(CONSOLE.line[CONSOLE_HISTORY_MAX - 1], buffer, len + 1); #ifdef DUSK_CONSOLE_POSIX threadMutexUnlock(&CONSOLE.printMutex); @@ -150,272 +57,75 @@ void consolePrint(const char_t *message, ...) { } void consoleExec(const char_t *line) { + assertNotNull(line, "line must not be NULL"); + #ifdef DUSK_CONSOLE_POSIX threadMutexLock(&CONSOLE.execMutex); #endif - assertNotNull(line, "line must not be NULL"); assertTrue( CONSOLE.execBufferCount < CONSOLE_EXEC_BUFFER_MAX, - "Too many commands in the buffer." + "Console exec buffer is full" ); - char_t buffer[CONSOLE_LINE_MAX]; - char_t pendingPrint[CONSOLE_LINE_MAX]; - size_t i = 0, j = 0; - char_t c; - consoleexecstate_t state = CONSOLE_EXEC_STATE_INITIAL; - consolecmdexec_t *exec = NULL; - - pendingPrint[0] = '\0'; - - while(state != CONSOLE_EXEC_STATE_FULLY_PARSED) { - c = line[i]; - - switch(state) { - case CONSOLE_EXEC_STATE_INITIAL: - assertTrue(j == 0, "Buffer not empty?"); - - if(c == '\0') { - state = CONSOLE_EXEC_STATE_FULLY_PARSED; - break; - } - - if(stringIsWhitespace(c) || c == ';') { - i++; - continue; - } - - state = CONSOLE_EXEC_STATE_PARSE_CMD; - break; - - case CONSOLE_EXEC_STATE_PARSE_CMD: - if(stringIsWhitespace(c) || c == '\0' || c == ';') { - state = CONSOLE_EXEC_STATE_CMD_PARSED; - continue; - } - - if(c == '"') { - // Can't handle quotes within the command. - stringCopy(pendingPrint, "Invalid command", CONSOLE_LINE_MAX); - while(c != '\0' && c != ';') c = line[++i]; - continue; - } - - buffer[j++] = c; - i++; - - if(j >= CONSOLE_LINE_MAX) { - stringCopy(pendingPrint, "Command too long", CONSOLE_LINE_MAX); - state = CONSOLE_EXEC_STATE_FULLY_PARSED; - continue; - } - break; - - case CONSOLE_EXEC_STATE_CMD_PARSED: - if(j == 0) { - state = CONSOLE_EXEC_STATE_INITIAL; - continue; - } - - // Create exec - assertNull(exec, "Existing command parsing?"); - - exec = &CONSOLE.execBuffer[CONSOLE.execBufferCount]; - memoryZero(exec, sizeof(consolecmdexec_t)); - - buffer[j] = '\0'; - stringCopy(exec->command, buffer, CONSOLE_LINE_MAX); - state = CONSOLE_EXEC_STATE_FIND_ARG; - - j = 0;// Free up buffer - break; - - case CONSOLE_EXEC_STATE_FIND_ARG: - if(c == '\0' || c == ';') { - state = CONSOLE_EXEC_STATE_CMD_FINISHED; - continue; - } - - if(stringIsWhitespace(c)) { - i++; - continue; - } - - if(c == '"') { - state = CONSOLE_EXEC_STATE_PARSE_ARG_QUOTED; - i++; - } else { - state = CONSOLE_EXEC_STATE_PARSE_ARG; - } - break; - - case CONSOLE_EXEC_STATE_PARSE_ARG: - if(stringIsWhitespace(c) || c == '\0' || c == ';') { - state = CONSOLE_EXEC_STATE_ARG_PARSED; - continue; - } - - buffer[j++] = c; - i++; - - if(j >= CONSOLE_LINE_MAX) { - stringCopy(pendingPrint, "Arg too long", CONSOLE_LINE_MAX); - state = CONSOLE_EXEC_STATE_FULLY_PARSED; - continue; - } - break; - - case CONSOLE_EXEC_STATE_PARSE_ARG_QUOTED: - if(c == '"') { - state = CONSOLE_EXEC_STATE_ARG_PARSED; - i++; - continue; - } - - if(c == '\0' || c == ';') { - stringCopy(pendingPrint, "Unterminated quote", CONSOLE_LINE_MAX); - state = CONSOLE_EXEC_STATE_FULLY_PARSED; - continue; - } - - if(c == '\\') { - c = line[++i]; - - if(c == '\0' || c == ';') { - stringCopy(pendingPrint, "Unterminated quote", CONSOLE_LINE_MAX); - state = CONSOLE_EXEC_STATE_FULLY_PARSED; - continue; - } - } - - buffer[j++] = c; - i++; - - if(j >= CONSOLE_LINE_MAX) { - stringCopy(pendingPrint, "Arg too long", CONSOLE_LINE_MAX); - state = CONSOLE_EXEC_STATE_FULLY_PARSED; - continue; - } - break; - - case CONSOLE_EXEC_STATE_ARG_PARSED: - buffer[j] = '\0'; - stringCopy(exec->argv[exec->argc++], buffer, CONSOLE_LINE_MAX); - state = CONSOLE_EXEC_STATE_FIND_ARG; - j = 0;// Free up buffer - break; - - case CONSOLE_EXEC_STATE_CMD_FINISHED: - assertNotNull(exec, "No command found?"); - - // Now, is there a command that matches? - for(uint32_t k = 0; k < CONSOLE.commandCount; k++) { - consolecmd_t *cmd = &CONSOLE.commands[k]; - if(stringCompare(cmd->name, exec->command) != 0) continue; - exec->cmd = cmd; - break; - } - - if(exec->cmd == NULL) { - // Command wasn't found, is there a variable that matches? - for(uint32_t k = 0; k < CONSOLE.variableCount; k++) { - consolevar_t *var = &CONSOLE.variables[k]; - if(stringCompare(var->name, exec->command) != 0) continue; - - // Matching variable found, is this a GET or a SET? - if(exec->argc == 0) { - exec->cmd = CONSOLE.cmdGet; - stringCopy(exec->argv[0], exec->command, CONSOLE_LINE_MAX); - exec->argc = 1; - } else { - exec->cmd = CONSOLE.cmdSet; - stringCopy(exec->argv[1], exec->argv[0], CONSOLE_LINE_MAX); - stringCopy(exec->argv[0], exec->command, CONSOLE_LINE_MAX); - exec->argc = 2; - } - break; - } - } - - if(exec->cmd == NULL) { - stringFormat( - pendingPrint, CONSOLE_LINE_MAX, - "Command \"%s\" not found", exec->command - ); - exec = NULL; - state = CONSOLE_EXEC_STATE_INITIAL; - } - - // Prep for next command. - exec = NULL; - state = CONSOLE_EXEC_STATE_INITIAL; - CONSOLE.execBufferCount++; - break; - - default: - assertUnreachable("Invalid state."); - break; - } - } + stringCopy( + CONSOLE.execBuffer[CONSOLE.execBufferCount], + line, + CONSOLE_LINE_MAX + ); + CONSOLE.execBufferCount++; #ifdef DUSK_CONSOLE_POSIX threadMutexUnlock(&CONSOLE.execMutex); #endif - - if(pendingPrint[0] != '\0') consolePrint("%s", pendingPrint); } -void consoleUpdate() { +void consoleUpdate(void) { #ifdef DUSK_TIME_DYNAMIC if(TIME.dynamicUpdate) return; #endif + if(inputPressed(INPUT_ACTION_CONSOLE)) { + CONSOLE.visible = !CONSOLE.visible; + } + + if(CONSOLE.execBufferCount == 0) return; + #ifdef DUSK_CONSOLE_POSIX threadMutexLock(&CONSOLE.execMutex); #endif - // Toggle console - if(inputPressed(INPUT_ACTION_CONSOLE)) { - consoleVarSetBool("console", !consoleVarGetBool("console", false)); - } - - // Anything to exec? - if(CONSOLE.execBufferCount == 0) { - #ifdef DUSK_CONSOLE_POSIX - threadMutexUnlock(&CONSOLE.execMutex); - #endif - return; - } - - // Copy the exec buffer, this allows exec command to work - consolecmdexec_t execBuffer[CONSOLE_EXEC_BUFFER_MAX]; + char_t execBuffer[CONSOLE_EXEC_BUFFER_MAX][CONSOLE_LINE_MAX]; uint32_t execBufferCount = CONSOLE.execBufferCount; - memoryCopy( - execBuffer, - CONSOLE.execBuffer, - sizeof(consolecmdexec_t) * execBufferCount - ); - - // Clear the exec buffer and unlock so new commands can be added while we - // process the current ones. + memoryCopy(execBuffer, CONSOLE.execBuffer, sizeof(execBuffer)); CONSOLE.execBufferCount = 0; + #ifdef DUSK_CONSOLE_POSIX threadMutexUnlock(&CONSOLE.execMutex); #endif - // Exec pending buffer. for(uint32_t i = 0; i < execBufferCount; i++) { - consolecmdexec_t *exec = &execBuffer[i]; - assertNotNull(exec->cmd, "Command execution has no command."); - exec->cmd->function(exec); + jerry_value_t result = 0; + errorret_t err = scriptManagerExec(execBuffer[i], &result); + if(err.code != ERROR_OK) { + consolePrint("Error: %s", err.state->message); + errorCatch(err); + } else if(!jerry_value_is_undefined(result)) { + jerry_value_t strVal = jerry_value_to_string(result); + char_t buf[CONSOLE_LINE_MAX]; + jerry_size_t len = jerry_string_to_buffer( + strVal, JERRY_ENCODING_UTF8, (jerry_char_t*)buf, sizeof(buf) - 1 + ); + buf[len] = '\0'; + jerry_value_free(strVal); + consolePrint("%s", buf); + } + if(result != 0) jerry_value_free(result); } } -errorret_t consoleDraw() { - if(!consoleVarGetBool("console", false)) { - errorOk(); - } +errorret_t consoleDraw(void) { + if(!CONSOLE.visible) errorOk(); for(uint32_t i = 0; i < CONSOLE_HISTORY_MAX; i++) { errorChain(textDraw( @@ -454,29 +164,23 @@ void consoleDispose(void) { if(rc == 0) continue; if(rc < 0) { - if(errno == EINTR) continue; // Interrupted by signal, retry + if(errno == EINTR) continue; assertUnreachable("poll() failed with unexpected error."); } - // Check for errors or input if(pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) break; if(!(pfd.revents & POLLIN)) { pfd.revents = 0; continue; } - - // Read a line from stdin + if(!fgets(line, CONSOLE_LINE_MAX, stdin)) { if(feof(stdin)) break; clearerr(stdin); continue; } - // Did we read a full line or did it get truncated? size_t len = strlen(line); - int32_t fullLine = len > 0 && line[len - 1] == '\n'; - - // Strip trailing newline/CR while(len && (line[len - 1] == '\n' || line[len - 1] == '\r')) { line[--len] = '\0'; } @@ -486,4 +190,4 @@ void consoleDispose(void) { pfd.revents = 0; } } -#endif \ No newline at end of file +#endif diff --git a/src/dusk/console/console.h b/src/dusk/console/console.h index c7a8a503..a8ef15d9 100644 --- a/src/dusk/console/console.h +++ b/src/dusk/console/console.h @@ -1,14 +1,14 @@ /** - * Copyright (c) 2025 Dominic Masters - * + * Copyright (c) 2026 Dominic Masters + * * This software is released under the MIT License. * https://opensource.org/licenses/MIT */ #pragma once -#include "consolevar.h" -#include "consolecmd.h" +#include "consoledefs.h" #include "error/error.h" +#include "dusk.h" #ifdef DUSK_CONSOLE_POSIX #include "thread/thread.h" @@ -17,37 +17,14 @@ #define CONSOLE_POSIX_POLL_RATE 75 #endif -typedef enum { - CONSOLE_EXEC_STATE_INITIAL, - CONSOLE_EXEC_STATE_PARSE_CMD, - CONSOLE_EXEC_STATE_CMD_PARSED, - - CONSOLE_EXEC_STATE_FIND_ARG, - CONSOLE_EXEC_STATE_PARSE_ARG, - CONSOLE_EXEC_STATE_PARSE_ARG_QUOTED, - CONSOLE_EXEC_STATE_ARG_PARSED, - - CONSOLE_EXEC_STATE_CMD_FINISHED, - CONSOLE_EXEC_STATE_FULLY_PARSED -} consoleexecstate_t; - typedef struct { - consolecmd_t commands[CONSOLE_COMMANDS_MAX]; - uint32_t commandCount; - - consolevar_t variables[CONSOLE_VARIABLES_MAX]; - uint32_t variableCount; - char_t line[CONSOLE_HISTORY_MAX][CONSOLE_LINE_MAX]; + bool_t visible; - consolecmdexec_t execBuffer[CONSOLE_EXEC_BUFFER_MAX]; + char_t execBuffer[CONSOLE_EXEC_BUFFER_MAX][CONSOLE_LINE_MAX]; uint32_t execBufferCount; - consolecmd_t *cmdGet; - consolecmd_t *cmdSet; - #ifdef DUSK_CONSOLE_POSIX - char_t inputBuffer[CONSOLE_LINE_MAX]; thread_t thread; threadmutex_t execMutex; threadmutex_t printMutex; @@ -59,104 +36,33 @@ extern console_t CONSOLE; /** * Initializes the console. */ -void consoleInit(); +void consoleInit(void); /** - * Registers a console command. - * - * @param name The name of the command. - * @param function The function to execute when the command is called. - * @return The registered command. + * Prints a message to the console history. + * + * @param message The message to print (printf-style). */ -consolecmd_t * consoleRegCmd(const char_t *name, consolecmdfunc_t function); +void consolePrint(const char_t *message, ...); /** - * Registers a console variable. - * - * @param name The name of the variable. - * @param value The initial value of the variable. - * @param event The event to register. - * @return The registered variable. - */ -consolevar_t * consoleRegVar( - const char_t *name, - const char_t *value, - consolevarchanged_t event -); - -/** - * Gets a console variable by name. - * - * @param name The name of the variable. - * @return The variable, or NULL if not found. - */ -consolevar_t * consoleVarGet(const char_t *name); - -/** - * Gets the value of a console variable as an int32_t. - * - * @param name The name of the variable. - * @param initial The default value to return if the variable is not found or - * invalid. - * @return The value of the variable, or default if not found or invalid. - */ -int32_t consoleVarGetInt(const char_t *name, const int32_t initial); - -/** - * Gets the value of a console variable as a bool_t. - * - * @param name The name of the variable. - * @param initial The default value to return if the variable is not found or - * invalid. - * @return The value of the variable, or default if not found or invalid. - */ -bool_t consoleVarGetBool(const char_t *name, const bool_t initial); - -/** - * Sets the value of a console variable as an int32_t. - * - * @param name The name of the variable. - * @param value The new value of the variable. - */ -void consoleVarSetInt(const char_t *name, const int32_t value); - -/** - * Sets the value of a console variable as a bool_t. - * - * @param name The name of the variable. - * @param value The new value of the variable. - */ -void consoleVarSetBool(const char_t *name, const bool_t value); - -/** - * Prints a message to the console. - * - * @param message The message to print. - */ -void consolePrint( - const char_t *message, - ... -); - -/** - * Executes a console command. This method is thread safe and can be called from - * any thread. - * - * @param line The line to execute. + * Queues a JS string for execution on the main thread. Thread-safe. + * + * @param line The JS source line to execute. */ void consoleExec(const char_t *line); /** - * Processes the console's pending commands. + * Processes pending queued script lines. Call once per frame from main thread. */ -void consoleUpdate(); +void consoleUpdate(void); /** - * Renders the console to the screen. This is in UI space. - * + * Renders the console history to the screen (UI space). + * * @return The error return value. */ -errorret_t consoleDraw(); +errorret_t consoleDraw(void); /** * Disposes of the console. @@ -165,9 +71,9 @@ void consoleDispose(void); #ifdef DUSK_CONSOLE_POSIX /** - * Input thread handler for posix input. - * + * Input thread handler for POSIX stdin. + * * @param thread The thread that is running. */ void consoleInputThread(thread_t *thread); -#endif \ No newline at end of file +#endif diff --git a/src/dusk/console/consolecmd.c b/src/dusk/console/consolecmd.c deleted file mode 100644 index f2923b9e..00000000 --- a/src/dusk/console/consolecmd.c +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "consolecmd.h" -#include "assert/assert.h" -#include "util/memory.h" -#include "util/string.h" - -void consoleCmdInit( - consolecmd_t *cmd, - const char_t *name, - consolecmdfunc_t function -) { - assertNotNull(cmd, "Command is NULL."); - assertNotNull(name, "Name is NULL."); - assertNotNull(function, "Function is NULL."); - assertStrLenMin(name, 1, "Name is empty."); - assertStrLenMax(name, CONSOLE_CMD_NAME_MAX, "Name is too long."); - - memoryZero(cmd, sizeof(consolecmd_t)); - stringCopy(cmd->name, name, CONSOLE_CMD_NAME_MAX); - cmd->function = function; -} \ No newline at end of file diff --git a/src/dusk/console/consolecmd.h b/src/dusk/console/consolecmd.h deleted file mode 100644 index 09a3c4f3..00000000 --- a/src/dusk/console/consolecmd.h +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "dusk.h" -#include "consoledefs.h" - -typedef struct consolecmd_s consolecmd_t; - -typedef struct { - consolecmd_t *cmd; - char_t command[CONSOLE_LINE_MAX]; - char_t argv[CONSOLE_CMD_ARGC_MAX][CONSOLE_LINE_MAX]; - uint32_t argc; -} consolecmdexec_t; - -typedef void (*consolecmdfunc_t)(const consolecmdexec_t *exec); - -typedef struct consolecmd_s { - char_t name[CONSOLE_CMD_NAME_MAX]; - consolecmdfunc_t function; -} consolecmd_t; - -/** - * Initializes a console command. - * - * @param cmd Pointer to the console command. - * @param name The name of the command. - * @param function The function to execute when the command is called. - */ -void consoleCmdInit( - consolecmd_t *cmd, - const char_t *name, - consolecmdfunc_t function -); \ No newline at end of file diff --git a/src/dusk/console/consoledefs.h b/src/dusk/console/consoledefs.h index c0a8773c..392dddcb 100644 --- a/src/dusk/console/consoledefs.h +++ b/src/dusk/console/consoledefs.h @@ -1,22 +1,12 @@ /** - * Copyright (c) 2025 Dominic Masters - * + * Copyright (c) 2026 Dominic Masters + * * This software is released under the MIT License. * https://opensource.org/licenses/MIT */ #pragma once -#define CONSOLE_CMD_NAME_MAX 16 -#define CONSOLE_CMD_ARGC_MAX 16 - -#define CONSOLE_COMMANDS_MAX 32 -#define CONSOLE_VARIABLES_MAX 64 -#define CONSOLE_LINE_MAX 128 +#define CONSOLE_LINE_MAX 512 #define CONSOLE_HISTORY_MAX 16 #define CONSOLE_EXEC_BUFFER_MAX 32 -#define CONSOLE_ALIAS_MAX 32 - -#define CONSOLE_VAR_NAME_MAX 32 -#define CONSOLE_VAR_VALUE_MAX 32 -#define CONSOLE_VAR_EVENTS_MAX 8 diff --git a/src/dusk/console/consolevar.c b/src/dusk/console/consolevar.c deleted file mode 100644 index e126c893..00000000 --- a/src/dusk/console/consolevar.c +++ /dev/null @@ -1,64 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "consolevar.h" -#include "assert/assert.h" -#include "util/memory.h" -#include "util/string.h" - -void consoleVarInit( - consolevar_t *var, - const char_t *name, - const char_t *value -) { - assertNotNull(var, "var must not be NULL"); - assertNotNull(name, "name must not be NULL"); - assertNotNull(value, "value must not be NULL"); - - assertStrLenMin(name, 1, "name must not be empty"); - assertStrLenMax(name, CONSOLE_VAR_NAME_MAX, "name is too long"); - assertStrLenMax(value, CONSOLE_VAR_VALUE_MAX, "value is too long"); - - memoryZero(var, sizeof(consolevar_t)); - stringCopy(var->name, name, CONSOLE_VAR_NAME_MAX); - stringCopy(var->value, value, CONSOLE_VAR_VALUE_MAX); -} - -void consoleVarInitListener( - consolevar_t *var, - const char_t *name, - const char_t *value, - consolevarchanged_t event -) { - consoleVarInit(var, name, value); - if(event) consoleVarListen(var, event); -} - -void consoleVarSetValue(consolevar_t *var, const char_t *value) { - assertNotNull(var, "var must not be NULL"); - assertNotNull(value, "value must not be NULL"); - assertStrLenMax(value, CONSOLE_VAR_VALUE_MAX, "value is too long"); - - stringCopy(var->value, value, CONSOLE_VAR_VALUE_MAX); - - uint8_t i = 0; - while (i < var->eventCount) { - var->events[i](var); - i++; - } -} - -void consoleVarListen(consolevar_t *var, consolevarchanged_t event) { - assertNotNull(var, "var must not be NULL"); - assertNotNull(event, "event must not be NULL"); - assertTrue( - var->eventCount < CONSOLE_VAR_EVENTS_MAX, - "Event count is too high" - ); - var->events[var->eventCount++] = event; -} - diff --git a/src/dusk/console/consolevar.h b/src/dusk/console/consolevar.h deleted file mode 100644 index af6a9df1..00000000 --- a/src/dusk/console/consolevar.h +++ /dev/null @@ -1,65 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "dusk.h" -#include "consoledefs.h" - -typedef struct consolevar_s consolevar_t; - -typedef void (*consolevarchanged_t)(const consolevar_t *var); - -typedef struct consolevar_s { - char_t name[CONSOLE_VAR_NAME_MAX]; - char_t value[CONSOLE_VAR_VALUE_MAX]; - consolevarchanged_t events[CONSOLE_VAR_EVENTS_MAX]; - uint8_t eventCount; -} consolevar_t; - -/** - * Initializes a console variable. - * - * @param var Pointer to the console variable. - * @param name The name of the variable. - * @param value The initial value of the variable. - */ -void consoleVarInit( - consolevar_t *var, - const char_t *name, - const char_t *value -); - -/** - * Initializes a console variable with a listener. - * - * @param var Pointer to the console variable. - * @param name The name of the variable. - * @param value The initial value of the variable. - * @param event The event to register. - */ -void consoleVarInitListener( - consolevar_t *var, - const char_t *name, - const char_t *value, - consolevarchanged_t event -); - -/** - * Sets the value of a console variable. - * - * @param var Pointer to the console variable. - * @param value The new value of the variable. - */ -void consoleVarSetValue(consolevar_t *var, const char_t *value); - -/** - * Registers an event to be called when the value of a console variable changes. - * - * @param var Pointer to the console variable. - * @param event The event to register. - */ -void consoleVarListen(consolevar_t *var, consolevarchanged_t event); \ No newline at end of file diff --git a/src/dusk/scene/scene.c b/src/dusk/scene/scene.c index 4f4ef63f..c2226d6d 100644 --- a/src/dusk/scene/scene.c +++ b/src/dusk/scene/scene.c @@ -57,110 +57,225 @@ errorret_t sceneRender(void) { mat4 view, proj, model; - if(camCount > 0) { - entityid_t meshEnts[ENTITY_COUNT_MAX]; - componentid_t meshComps[ENTITY_COUNT_MAX]; - entityid_t meshCount = componentGetEntitiesWithComponent( - COMPONENT_TYPE_MESH, meshEnts, meshComps - ); + // For each camera + for(entityid_t camIndex = 0; camIndex < camCount; camIndex++) { + entityid_t camEnt = camEnts[camIndex]; + componentid_t camComp = camComps[camIndex]; + componentid_t camPos = entityGetComponent(camEnt, COMPONENT_TYPE_POSITION); + if(camPos == 0xFF) { + logError("Camera entity without entity position found\n"); + continue; + } - if(meshCount > 0) { - errorChain(shaderBind(&SHADER_UNLIT)); + entityCameraGetProjection(camEnt, camComp, proj); + entityPositionGetTransform(camEnt, camPos, view); - for(entityid_t camIndex = 0; camIndex < camCount; camIndex++) { - entityid_t camEnt = camEnts[camIndex]; - componentid_t camComp = camComps[camIndex]; - componentid_t camPos = entityGetComponent(camEnt, COMPONENT_TYPE_POSITION); - if(camPos == 0xFF) { - logError("Camera entity without entity position found\n"); + // For each entity + for(entityid_t entityId = 0; entityId < ENTITY_COUNT_MAX; entityId++) { + // Does this entity have a material? + componentid_t matComp = entityGetComponent( + entityId, COMPONENT_TYPE_MATERIAL + ); + if(matComp != 0xFF) { + // Yes, get the mesh + componentid_t meshComp = entityGetComponent( + entityId, COMPONENT_TYPE_MESH + ); + + if(meshComp == 0xFF) { + logError("Entity with material component without mesh component found\n"); continue; } - entityCameraGetProjection(camEnt, camComp, proj); - entityPositionGetTransform(camEnt, camPos, view); - - for(entityid_t meshIndex = 0; meshIndex < meshCount; meshIndex++) { - entityid_t meshEnt = meshEnts[meshIndex]; - componentid_t meshComp = meshComps[meshIndex]; - mesh_t *mesh = entityMeshGetMesh(meshEnt, meshComp); - if(mesh == NULL) continue; - - componentid_t meshPos = entityGetComponent( - meshEnt, COMPONENT_TYPE_POSITION - ); - if(meshPos == 0xFF) { - logError("Mesh entity without entity position found\n"); - continue; - } - - componentid_t meshMat = entityGetComponent( - meshEnt, COMPONENT_TYPE_MATERIAL - ); - if(meshMat == 0xFF) { - logError("Mesh entity without material component found\n"); - continue; - } - - shadermaterial_t *material = entityMaterialGetShaderMaterial( - meshEnt, meshMat - ); - shader_t *shader = entityMaterialGetShader(meshEnt, meshMat); - if(shader == NULL) { - logError("Mesh entity with material component without shader found\n"); - continue; - } - - entityPositionGetTransform(meshEnt, meshPos, model); - - errorChain(shaderBind(shader)); - errorChain(shaderSetMatrix(shader, SHADER_UNLIT_PROJECTION, proj)); - errorChain(shaderSetMatrix(shader, SHADER_UNLIT_VIEW, view)); - errorChain(shaderSetMatrix(shader, SHADER_UNLIT_MODEL, model)); - errorChain(shaderSetMaterial(shader, material)); - errorChain(meshDraw(mesh, 0, -1)); + // Yes, get the material and shader. + shadermaterial_t *material = entityMaterialGetShaderMaterial( + entityId, matComp + ); + shader_t *shader = entityMaterialGetShader(entityId, matComp); + if(shader == NULL) { + logError("Entity with material component without shader found\n"); + continue; } + + // Get the mesh + mesh_t *mesh = entityMeshGetMesh(entityId, meshComp); + if(mesh == NULL) { + logError("Entity with material component without mesh found\n"); + continue; + } + + // Get the transform. + componentid_t meshPos = entityGetComponent( + entityId, COMPONENT_TYPE_POSITION + ); + if(meshPos == 0xFF) { + glm_mat4_identity(model); + } else { + entityPositionGetTransform(entityId, meshPos, model); + } + + // Render the mesh. + errorChain(shaderBind(shader)); + errorChain(shaderSetMatrix(shader, SHADER_UNLIT_PROJECTION, proj)); + errorChain(shaderSetMatrix(shader, SHADER_UNLIT_VIEW, view)); + errorChain(shaderSetMatrix(shader, SHADER_UNLIT_MODEL, model)); + errorChain(shaderSetMaterial(shader, material)); + errorChain(meshDraw(mesh, 0, -1)); + continue; } + + // No, in future there may be other renderable types. } } - glm_ortho( - 0.0f, SCREEN.width, - SCREEN.height, 0.0f, - 0.1f, 100.0f, - proj - ); - glm_lookat( - (vec3){ 0.0f, 0.0f, 1.0f }, - (vec3){ 0.0f, 0.0f, 0.0f }, - (vec3){ 0.0f, 1.0f, 0.0f }, - view - ); - glm_mat4_identity(model); - - errorChain(shaderBind(&SHADER_UNLIT)); - errorChain(shaderSetMatrix(&SHADER_UNLIT, SHADER_UNLIT_PROJECTION, proj)); - errorChain(shaderSetMatrix(&SHADER_UNLIT, SHADER_UNLIT_VIEW, view)); - errorChain(shaderSetMatrix(&SHADER_UNLIT, SHADER_UNLIT_MODEL, model)); - errorChain(consoleDraw()); - - // FPS - char_t fpsText[32]; - - dusktimeepoch_t now = timeGetEpoch(); - double_t delta = now.time - LAST.time; - LAST = now; - double_t fps = delta > 0 ? 1.0 / delta : 0.0; - snprintf(fpsText, sizeof(fpsText), "FPS: %.2f", fps); - - errorChain(spriteBatchFlush()); - errorChain(textDraw( - 0, 0, - fpsText, COLOR_WHITE, - &FONT_TILESET_DEFAULT, &FONT_TEXTURE_DEFAULT - )); - errorChain(spriteBatchFlush()); - errorOk(); + + // if(camCount > 0) { + // // For each entity + // for(entityid_t entityId = 0; entityId < ENTITY_COUNT_MAX; entityId++) { + + // } + + // entityid_t meshEnts[ENTITY_COUNT_MAX]; + // componentid_t meshComps[ENTITY_COUNT_MAX]; + // entityid_t meshCount = componentGetEntitiesWithComponent( + // COMPONENT_TYPE_MESH, meshEnts, meshComps + // ); + + // if(meshCount > 0) { + // errorChain(shaderBind(&SHADER_UNLIT)); + + // for(entityid_t camIndex = 0; camIndex < camCount; camIndex++) { + // entityid_t camEnt = camEnts[camIndex]; + // componentid_t camComp = camComps[camIndex]; + // componentid_t camPos = entityGetComponent(camEnt, COMPONENT_TYPE_POSITION); + // if(camPos == 0xFF) { + // logError("Camera entity without entity position found\n"); + // continue; + // } + + // entityCameraGetProjection(camEnt, camComp, proj); + // entityPositionGetTransform(camEnt, camPos, view); + + // for(entityid_t meshIndex = 0; meshIndex < meshCount; meshIndex++) { + // entityid_t meshEnt = meshEnts[meshIndex]; + // componentid_t meshComp = meshComps[meshIndex]; + // mesh_t *mesh = entityMeshGetMesh(meshEnt, meshComp); + // if(mesh == NULL) continue; + + // componentid_t meshPos = entityGetComponent( + // meshEnt, COMPONENT_TYPE_POSITION + // ); + // if(meshPos == 0xFF) { + // logError("Mesh entity without entity position found\n"); + // continue; + // } + + // componentid_t meshMat = entityGetComponent( + // meshEnt, COMPONENT_TYPE_MATERIAL + // ); + // if(meshMat == 0xFF) { + // logError("Mesh entity without material component found\n"); + // continue; + // } + + // shadermaterial_t *material = entityMaterialGetShaderMaterial( + // meshEnt, meshMat + // ); + // shader_t *shader = entityMaterialGetShader(meshEnt, meshMat); + // if(shader == NULL) { + // logError("Mesh entity with material component without shader found\n"); + // continue; + // } + + // entityPositionGetTransform(meshEnt, meshPos, model); + + // errorChain(shaderBind(shader)); + // errorChain(shaderSetMatrix(shader, SHADER_UNLIT_PROJECTION, proj)); + // errorChain(shaderSetMatrix(shader, SHADER_UNLIT_VIEW, view)); + // errorChain(shaderSetMatrix(shader, SHADER_UNLIT_MODEL, model)); + // errorChain(shaderSetMaterial(shader, material)); + // errorChain(meshDraw(mesh, 0, -1)); + // } + // } + // } + // } + + // glm_ortho( + // 0.0f, SCREEN.width, + // SCREEN.height, 0.0f, + // 0.1f, 100.0f, + // proj + // ); + // glm_lookat( + // (vec3){ 0.0f, 0.0f, 1.0f }, + // (vec3){ 0.0f, 0.0f, 0.0f }, + // (vec3){ 0.0f, 1.0f, 0.0f }, + // view + // ); + // glm_mat4_identity(model); + + // errorChain(shaderBind(&SHADER_UNLIT)); + // errorChain(shaderSetMatrix(&SHADER_UNLIT, SHADER_UNLIT_PROJECTION, proj)); + // errorChain(shaderSetMatrix(&SHADER_UNLIT, SHADER_UNLIT_VIEW, view)); + // errorChain(shaderSetMatrix(&SHADER_UNLIT, SHADER_UNLIT_MODEL, model)); + + // { + // entityid_t sprEnts[ENTITY_COUNT_MAX]; + // componentid_t sprComps[ENTITY_COUNT_MAX]; + // entityid_t sprCount = componentGetEntitiesWithComponent( + // COMPONENT_TYPE_SPRITE, sprEnts, sprComps + // ); + // for(entityid_t si = 0; si < sprCount; si++) { + // entitysprite_t *spr = entitySpriteGet(sprEnts[si], sprComps[si]); + // vec3 pos = { 0.0f, 0.0f, 0.0f }; + // componentid_t posComp = entityGetComponent( + // sprEnts[si], COMPONENT_TYPE_POSITION + // ); + // if(posComp != 0xFF) { + // entityPositionGetPosition(sprEnts[si], posComp, pos); + // } + // errorChain(shaderSetTexture( + // &SHADER_UNLIT, SHADER_UNLIT_TEXTURE, spr->texture + // )); + // #if !MESH_ENABLE_COLOR + // errorChain(shaderSetColor( + // &SHADER_UNLIT, SHADER_UNLIT_COLOR, spr->color + // )); + // #endif + // errorChain(spriteBatchPush( + // pos[0], pos[1], + // pos[0] + spr->width, pos[1] + spr->height, + // #if MESH_ENABLE_COLOR + // spr->color, + // #endif + // spr->uv[0], spr->uv[1], + // spr->uv[2], spr->uv[3] + // )); + // errorChain(spriteBatchFlush()); + // } + // } + + // errorChain(consoleDraw()); + + // // FPS + // char_t fpsText[32]; + + // dusktimeepoch_t now = timeGetEpoch(); + // double_t delta = now.time - LAST.time; + // LAST = now; + // double_t fps = delta > 0 ? 1.0 / delta : 0.0; + // snprintf(fpsText, sizeof(fpsText), "FPS: %.2f", fps); + + // errorChain(spriteBatchFlush()); + // errorChain(textDraw( + // 0, 0, + // fpsText, COLOR_WHITE, + // &FONT_TILESET_DEFAULT, &FONT_TEXTURE_DEFAULT + // )); + // errorChain(spriteBatchFlush()); + + // errorOk(); } errorret_t sceneSetImmediate(const char_t *scene) { diff --git a/src/dusk/script/module/console/moduleconsole.h b/src/dusk/script/module/console/moduleconsole.h index e1057dbd..23941b7f 100644 --- a/src/dusk/script/module/console/moduleconsole.h +++ b/src/dusk/script/module/console/moduleconsole.h @@ -39,7 +39,7 @@ moduleBaseFunction(moduleConsolePrint) { } moduleBaseFunction(moduleConsoleGetVisible) { - return jerry_boolean(consoleVarGetBool("console", false)); + return jerry_boolean(CONSOLE.visible); } moduleBaseFunction(moduleConsoleSetVisible) { @@ -47,7 +47,7 @@ moduleBaseFunction(moduleConsoleSetVisible) { if(!jerry_value_is_boolean(args[0])) { return moduleBaseThrow("Console.visible: expected boolean"); } - consoleVarSetBool("console", jerry_value_is_true(args[0])); + CONSOLE.visible = jerry_value_is_true(args[0]); return jerry_undefined(); } diff --git a/src/dusk/script/module/engine/moduleengine.h b/src/dusk/script/module/engine/moduleengine.h new file mode 100644 index 00000000..1f5855db --- /dev/null +++ b/src/dusk/script/module/engine/moduleengine.h @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "script/module/modulebase.h" +#include "script/scriptproto.h" +#include "engine/engine.h" + +static scriptproto_t MODULE_ENGINE_PROTO; + +moduleBaseFunction(moduleEngineExit) { + ENGINE.running = false; + return jerry_undefined(); +} + +static void moduleEngine(void) { + scriptProtoInit( + &MODULE_ENGINE_PROTO, "Engine", + sizeof(uint8_t), NULL + ); + + scriptProtoDefineStaticFunc( + &MODULE_ENGINE_PROTO, "exit", moduleEngineExit + ); +} diff --git a/src/dusk/script/module/entity/moduleentity.h b/src/dusk/script/module/entity/moduleentity.h index 2a1b0c58..cf6573c4 100644 --- a/src/dusk/script/module/entity/moduleentity.h +++ b/src/dusk/script/module/entity/moduleentity.h @@ -80,6 +80,43 @@ static jerry_value_t moduleEntityGetComponent( #include "entity/componentlist.h" #undef X +moduleBaseFunction(moduleEntityToString) { + entityscript_t *inst = (entityscript_t*)scriptProtoGetValue( + &MODULE_ENTITY_PROTO, callInfo->this_value + ); + if(!inst) return jerry_string_sz("Entity(?)"); + + char_t components[128]; + size_t clen = 0; + bool_t first = true; + + for(componenttype_t t = 1; t < COMPONENT_TYPE_COUNT; t++) { + if(entityGetComponent(inst->id, t) == 0xFF) continue; + if(!first) { + stringCopy(components + clen, ", ", sizeof(components) - clen); + clen += 2; + } + const char_t *name = COMPONENT_DEFINITIONS[t].enumName; + stringCopy(components + clen, name, sizeof(components) - clen); + clen += strlen(name); + first = false; + } + + char_t buf[256]; + if(first) { + stringFormat( + buf, sizeof(buf), + "{ \"id\": %d, \"components\": [] }", inst->id + ); + } else { + stringFormat( + buf, sizeof(buf), + "{ \"id\": %d, \"components\": [ %s ] }", inst->id, components + ); + } + return jerry_string_sz(buf); +} + // Methods moduleBaseFunction(moduleEntityConstructor) { entityscript_t *inst = (entityscript_t*)memoryAllocate( @@ -130,6 +167,8 @@ static void moduleEntity(void) { moduleEntityConstructor ); + scriptProtoDefineToString(&MODULE_ENTITY_PROTO, moduleEntityToString); + // Entity Methods scriptProtoDefineFunc( &MODULE_ENTITY_PROTO, "add", moduleEntityAddComponent diff --git a/src/dusk/script/module/math/modulemat4.h b/src/dusk/script/module/math/modulemat4.h index e98c5dc5..94adabf1 100644 --- a/src/dusk/script/module/math/modulemat4.h +++ b/src/dusk/script/module/math/modulemat4.h @@ -156,6 +156,22 @@ moduleBaseFunction(moduleMatStaticLookAt) { return scriptProtoCreateValue(&MODULE_MAT4_PROTO, r); } +moduleBaseFunction(moduleMatToString) { + float_t (*m)[4] = (float_t (*)[4])moduleMatGet(callInfo); + if(!m) return jerry_string_sz("Mat4(?)"); + char_t buf[256]; + stringFormat( + buf, sizeof(buf), + "Mat4([%g,%g,%g,%g], [%g,%g,%g,%g]," + " [%g,%g,%g,%g], [%g,%g,%g,%g])", + m[0][0], m[0][1], m[0][2], m[0][3], + m[1][0], m[1][1], m[1][2], m[1][3], + m[2][0], m[2][1], m[2][2], m[2][3], + m[3][0], m[3][1], m[3][2], m[3][3] + ); + return jerry_string_sz(buf); +} + static inline jerry_value_t moduleMat4Push(float (*m)[4]) { return scriptProtoCreateValue(&MODULE_MAT4_PROTO, m); } @@ -174,6 +190,8 @@ static void moduleMat4(void) { &MODULE_MAT4_PROTO, "Mat4", sizeof(mat4), moduleMatConstructor ); + scriptProtoDefineToString(&MODULE_MAT4_PROTO, moduleMatToString); + scriptProtoDefineFunc( &MODULE_MAT4_PROTO, "mul", moduleMatMul ); diff --git a/src/dusk/script/module/math/modulevec2.h b/src/dusk/script/module/math/modulevec2.h index c2615096..cf52440c 100644 --- a/src/dusk/script/module/math/modulevec2.h +++ b/src/dusk/script/module/math/modulevec2.h @@ -142,6 +142,14 @@ moduleBaseFunction(moduleVec2Distance) { return jerry_number(glm_vec2_distance(a, b)); } +moduleBaseFunction(moduleVec2ToString) { + float_t *v = moduleVec2Get(callInfo); + if(!v) return jerry_string_sz("Vec2(?, ?)"); + char_t buf[64]; + stringFormat(buf, sizeof(buf), "Vec2(%g, %g)", v[0], v[1]); + return jerry_string_sz(buf); +} + static inline jerry_value_t moduleVec2Push(const float_t *v) { return scriptProtoCreateValue(&MODULE_VEC2_PROTO, v); } @@ -166,6 +174,8 @@ static void moduleVec2(void) { &MODULE_VEC2_PROTO, "y", moduleVec2GetY, moduleVec2SetY ); + scriptProtoDefineToString(&MODULE_VEC2_PROTO, moduleVec2ToString); + scriptProtoDefineFunc(&MODULE_VEC2_PROTO, "dot", moduleVec2Dot); scriptProtoDefineFunc(&MODULE_VEC2_PROTO, "length", moduleVec2Length); scriptProtoDefineFunc(&MODULE_VEC2_PROTO, "lengthSq", moduleVec2LengthSq); diff --git a/src/dusk/script/module/math/modulevec3.h b/src/dusk/script/module/math/modulevec3.h index 72bdecef..98d9a0dc 100644 --- a/src/dusk/script/module/math/modulevec3.h +++ b/src/dusk/script/module/math/modulevec3.h @@ -165,6 +165,14 @@ moduleBaseFunction(moduleVec3Distance) { return jerry_number(glm_vec3_distance(a, b)); } +moduleBaseFunction(moduleVec3ToString) { + float_t *v = moduleVec3Get(callInfo); + if(!v) return jerry_string_sz("Vec3(?, ?, ?)"); + char_t buf[80]; + stringFormat(buf, sizeof(buf), "Vec3(%g, %g, %g)", v[0], v[1], v[2]); + return jerry_string_sz(buf); +} + static inline jerry_value_t moduleVec3Push(const float_t *v) { return scriptProtoCreateValue(&MODULE_VEC3_PROTO, v); } @@ -193,6 +201,8 @@ static void moduleVec3(void) { &MODULE_VEC3_PROTO, "z", moduleVec3GetZ, moduleVec3SetZ ); + scriptProtoDefineToString(&MODULE_VEC3_PROTO, moduleVec3ToString); + scriptProtoDefineFunc(&MODULE_VEC3_PROTO, "dot", moduleVec3Dot); scriptProtoDefineFunc(&MODULE_VEC3_PROTO, "cross", moduleVec3Cross); scriptProtoDefineFunc(&MODULE_VEC3_PROTO, "length", moduleVec3Length); diff --git a/src/dusk/script/module/math/modulevec3ref.h b/src/dusk/script/module/math/modulevec3ref.h index f4b03bb9..89e12cf2 100644 --- a/src/dusk/script/module/math/modulevec3ref.h +++ b/src/dusk/script/module/math/modulevec3ref.h @@ -74,6 +74,17 @@ moduleBaseFunction(moduleVec3RefSetZ) { return jerry_undefined(); } +moduleBaseFunction(moduleVec3RefToString) { + vec3ref_t *ref = moduleVec3RefGet(callInfo); + if(!ref) return jerry_string_sz("Vec3(?, ?, ?)"); + char_t buf[80]; + stringFormat( + buf, sizeof(buf), + "Vec3(%g, %g, %g)", ref->data[0], ref->data[1], ref->data[2] + ); + return jerry_string_sz(buf); +} + static inline jerry_value_t moduleVec3RefPush( float_t *data, void (*onChange)(void *), void *ctx ) { @@ -98,6 +109,8 @@ static void moduleVec3Ref(void) { scriptProtoInit( &MODULE_VEC3_REF_PROTO, NULL, sizeof(vec3ref_t), NULL ); + scriptProtoDefineToString(&MODULE_VEC3_REF_PROTO, moduleVec3RefToString); + scriptProtoDefineProp( &MODULE_VEC3_REF_PROTO, "x", moduleVec3RefGetX, moduleVec3RefSetX diff --git a/src/dusk/script/module/math/modulevec4.h b/src/dusk/script/module/math/modulevec4.h index a5b4a39e..0e32046e 100644 --- a/src/dusk/script/module/math/modulevec4.h +++ b/src/dusk/script/module/math/modulevec4.h @@ -199,6 +199,17 @@ moduleBaseFunction(moduleVec4Lerp) { return scriptProtoCreateValue(&MODULE_VEC4_PROTO, r); } +moduleBaseFunction(moduleVec4ToString) { + float_t *v = moduleVec4Get(callInfo); + if(!v) return jerry_string_sz("Vec4(?, ?, ?, ?)"); + char_t buf[96]; + stringFormat( + buf, sizeof(buf), + "Vec4(%g, %g, %g, %g)", v[0], v[1], v[2], v[3] + ); + return jerry_string_sz(buf); +} + static inline jerry_value_t moduleVec4Push(const float_t *v) { return scriptProtoCreateValue(&MODULE_VEC4_PROTO, v); } @@ -243,6 +254,8 @@ static void moduleVec4(void) { &MODULE_VEC4_PROTO, "v1", moduleVec4GetV1, moduleVec4SetV1 ); + scriptProtoDefineToString(&MODULE_VEC4_PROTO, moduleVec4ToString); + scriptProtoDefineFunc(&MODULE_VEC4_PROTO, "dot", moduleVec4Dot); scriptProtoDefineFunc(&MODULE_VEC4_PROTO, "length", moduleVec4Length); scriptProtoDefineFunc(&MODULE_VEC4_PROTO, "lengthSq", moduleVec4LengthSq); diff --git a/src/dusk/script/module/module.h b/src/dusk/script/module/module.h index 8776c654..c5dc9984 100644 --- a/src/dusk/script/module/module.h +++ b/src/dusk/script/module/module.h @@ -16,6 +16,7 @@ #include "script/module/display/modulescreen.h" #include "script/module/scene/modulescene.h" #include "script/module/console/moduleconsole.h" +#include "script/module/engine/moduleengine.h" static void moduleRegister(void) { moduleInclude(); @@ -28,4 +29,5 @@ static void moduleRegister(void) { moduleScreen(); moduleScene(); moduleConsole(); + moduleEngine(); } diff --git a/src/dusk/script/scriptmanager.c b/src/dusk/script/scriptmanager.c index 5ba512ac..c1827e9a 100644 --- a/src/dusk/script/scriptmanager.c +++ b/src/dusk/script/scriptmanager.c @@ -39,7 +39,7 @@ errorret_t scriptManagerInit(void) { errorOk(); } -errorret_t scriptManagerExec(const char_t *script) { +errorret_t scriptManagerExec(const char_t *script, jerry_value_t *resultOut) { assertNotNull(script, "Script cannot be NULL"); jerry_value_t result = jerry_eval( @@ -62,7 +62,11 @@ errorret_t scriptManagerExec(const char_t *script) { errorThrow("Failed to execute script: %s", buf); } - jerry_value_free(result); + if(resultOut != NULL) { + *resultOut = result; + } else { + jerry_value_free(result); + } errorOk(); } diff --git a/src/dusk/script/scriptmanager.h b/src/dusk/script/scriptmanager.h index d5e47584..f0b84887 100644 --- a/src/dusk/script/scriptmanager.h +++ b/src/dusk/script/scriptmanager.h @@ -36,10 +36,13 @@ errorret_t scriptManagerInit(void); /** * Execute a JS string in the active script context. * - * @param script The JS source to execute. + * @param script The JS source to execute. + * @param result Optional out-parameter for the script's return value. + * Caller must call jerry_value_free() on it when done. + * Pass NULL to discard the return value. * @return The error return value. */ -errorret_t scriptManagerExec(const char_t *script); +errorret_t scriptManagerExec(const char_t *script, jerry_value_t *result); /** * Execute a JS file in the active script context. diff --git a/src/duskvita/script/module/moduleplatformvita.h b/src/duskvita/script/module/moduleplatformvita.h index 7125d028..4d58a148 100644 --- a/src/duskvita/script/module/moduleplatformvita.h +++ b/src/duskvita/script/module/moduleplatformvita.h @@ -9,5 +9,5 @@ #include "script/scriptmanager.h" void modulePlatformVita(void) { - scriptManagerExec("VITA = true\n"); + scriptManagerExec("VITA = true\n", NULL); }