Some adjustments

This commit is contained in:
2026-05-01 13:44:51 -05:00
parent 1efa9a9f7b
commit d373de7a29
30 changed files with 436 additions and 925 deletions
+2
View File
@@ -1,3 +1,5 @@
Console.visible = true;
// Default input bindings. // Default input bindings.
if (typeof PSP !== 'undefined') { if (typeof PSP !== 'undefined') {
Input.bind("up", INPUT_ACTION_UP); Input.bind("up", INPUT_ACTION_UP);
+6
View File
@@ -9,6 +9,11 @@ function CubeScene() {
this.cam.position.lookAt(new Vec3(0, 0, 0)); this.cam.position.lookAt(new Vec3(0, 0, 0));
this.cube = new CubeEntity(); 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); CubeScene.prototype = Object.create(Scene.prototype);
@@ -21,6 +26,7 @@ CubeScene.prototype.update = function() {
CubeScene.prototype.dispose = function() { CubeScene.prototype.dispose = function() {
this.cam.dispose(); this.cam.dispose();
this.cube.dispose(); this.cube.dispose();
this.spriteEnt.dispose();
}; };
module = CubeScene; module = CubeScene;
+1 -7
View File
@@ -1,15 +1,9 @@
# Copyright (c) 2025 Dominic Masters # Copyright (c) 2026 Dominic Masters
# #
# This software is released under the MIT License. # This software is released under the MIT License.
# https://opensource.org/licenses/MIT # https://opensource.org/licenses/MIT
# Sources
target_sources(${DUSK_LIBRARY_TARGET_NAME} target_sources(${DUSK_LIBRARY_TARGET_NAME}
PUBLIC PUBLIC
console.c console.c
consolecmd.c
consolevar.c
) )
# Subdirectories
add_subdirectory(cmd)
-9
View File
@@ -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
)
-45
View File
@@ -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: <key> <command]");
return;
}
inputbutton_t button = inputButtonGetByName(exec->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);
}
-18
View File
@@ -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: <message>");
return;
}
consolePrint("%s", exec->argv[0]);
}
-25
View File
@@ -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]);
}
-14
View File
@@ -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;
}
-27
View File
@@ -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]);
}
-14
View File
@@ -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);
}
+40 -336
View File
@@ -1,5 +1,5 @@
/** /**
* Copyright (c) 2025 Dominic Masters * Copyright (c) 2026 Dominic Masters
* *
* This software is released under the MIT License. * This software is released under the MIT License.
* https://opensource.org/licenses/MIT * https://opensource.org/licenses/MIT
@@ -12,40 +12,16 @@
#include "input/input.h" #include "input/input.h"
#include "log/log.h" #include "log/log.h"
#include "engine/engine.h" #include "engine/engine.h"
#include "script/scriptmanager.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 "display/shader/shaderunlit.h" #include "display/shader/shaderunlit.h"
#include "display/text/text.h" #include "display/text/text.h"
#include "display/spritebatch/spritebatch.h" #include "display/spritebatch/spritebatch.h"
console_t CONSOLE; console_t CONSOLE;
void consoleInit() { void consoleInit(void) {
memoryZero(&CONSOLE, sizeof(console_t)); 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 #ifdef DUSK_CONSOLE_POSIX
threadInit(&CONSOLE.thread, consoleInputThread); threadInit(&CONSOLE.thread, consoleInputThread);
threadMutexInit(&CONSOLE.execMutex); threadMutexInit(&CONSOLE.execMutex);
@@ -54,68 +30,6 @@ void consoleInit() {
#endif #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, ...) { void consolePrint(const char_t *message, ...) {
char_t buffer[CONSOLE_LINE_MAX]; char_t buffer[CONSOLE_LINE_MAX];
@@ -128,19 +42,12 @@ void consolePrint(const char_t *message, ...) {
threadMutexLock(&CONSOLE.printMutex); threadMutexLock(&CONSOLE.printMutex);
#endif #endif
// Move all lines back
memoryMove( memoryMove(
CONSOLE.line[0], CONSOLE.line[0],
CONSOLE.line[1], CONSOLE.line[1],
(CONSOLE_HISTORY_MAX - 1) * CONSOLE_LINE_MAX (CONSOLE_HISTORY_MAX - 1) * CONSOLE_LINE_MAX
); );
memoryCopy(CONSOLE.line[CONSOLE_HISTORY_MAX - 1], buffer, len + 1);
// Copy the new line
memoryCopy(
CONSOLE.line[CONSOLE_HISTORY_MAX - 1],
buffer,
len + 1
);
#ifdef DUSK_CONSOLE_POSIX #ifdef DUSK_CONSOLE_POSIX
threadMutexUnlock(&CONSOLE.printMutex); threadMutexUnlock(&CONSOLE.printMutex);
@@ -150,272 +57,75 @@ void consolePrint(const char_t *message, ...) {
} }
void consoleExec(const char_t *line) { void consoleExec(const char_t *line) {
assertNotNull(line, "line must not be NULL");
#ifdef DUSK_CONSOLE_POSIX #ifdef DUSK_CONSOLE_POSIX
threadMutexLock(&CONSOLE.execMutex); threadMutexLock(&CONSOLE.execMutex);
#endif #endif
assertNotNull(line, "line must not be NULL");
assertTrue( assertTrue(
CONSOLE.execBufferCount < CONSOLE_EXEC_BUFFER_MAX, CONSOLE.execBufferCount < CONSOLE_EXEC_BUFFER_MAX,
"Too many commands in the buffer." "Console exec buffer is full"
); );
char_t buffer[CONSOLE_LINE_MAX]; stringCopy(
char_t pendingPrint[CONSOLE_LINE_MAX]; CONSOLE.execBuffer[CONSOLE.execBufferCount],
size_t i = 0, j = 0; line,
char_t c; CONSOLE_LINE_MAX
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++; CONSOLE.execBufferCount++;
break;
default:
assertUnreachable("Invalid state.");
break;
}
}
#ifdef DUSK_CONSOLE_POSIX #ifdef DUSK_CONSOLE_POSIX
threadMutexUnlock(&CONSOLE.execMutex); threadMutexUnlock(&CONSOLE.execMutex);
#endif #endif
if(pendingPrint[0] != '\0') consolePrint("%s", pendingPrint);
} }
void consoleUpdate() { void consoleUpdate(void) {
#ifdef DUSK_TIME_DYNAMIC #ifdef DUSK_TIME_DYNAMIC
if(TIME.dynamicUpdate) return; if(TIME.dynamicUpdate) return;
#endif #endif
if(inputPressed(INPUT_ACTION_CONSOLE)) {
CONSOLE.visible = !CONSOLE.visible;
}
if(CONSOLE.execBufferCount == 0) return;
#ifdef DUSK_CONSOLE_POSIX #ifdef DUSK_CONSOLE_POSIX
threadMutexLock(&CONSOLE.execMutex); threadMutexLock(&CONSOLE.execMutex);
#endif #endif
// Toggle console char_t execBuffer[CONSOLE_EXEC_BUFFER_MAX][CONSOLE_LINE_MAX];
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];
uint32_t execBufferCount = CONSOLE.execBufferCount; uint32_t execBufferCount = CONSOLE.execBufferCount;
memoryCopy( memoryCopy(execBuffer, CONSOLE.execBuffer, sizeof(execBuffer));
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.
CONSOLE.execBufferCount = 0; CONSOLE.execBufferCount = 0;
#ifdef DUSK_CONSOLE_POSIX #ifdef DUSK_CONSOLE_POSIX
threadMutexUnlock(&CONSOLE.execMutex); threadMutexUnlock(&CONSOLE.execMutex);
#endif #endif
// Exec pending buffer.
for(uint32_t i = 0; i < execBufferCount; i++) { for(uint32_t i = 0; i < execBufferCount; i++) {
consolecmdexec_t *exec = &execBuffer[i]; jerry_value_t result = 0;
assertNotNull(exec->cmd, "Command execution has no command."); errorret_t err = scriptManagerExec(execBuffer[i], &result);
exec->cmd->function(exec); 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() { errorret_t consoleDraw(void) {
if(!consoleVarGetBool("console", false)) { if(!CONSOLE.visible) errorOk();
errorOk();
}
for(uint32_t i = 0; i < CONSOLE_HISTORY_MAX; i++) { for(uint32_t i = 0; i < CONSOLE_HISTORY_MAX; i++) {
errorChain(textDraw( errorChain(textDraw(
@@ -454,29 +164,23 @@ void consoleDispose(void) {
if(rc == 0) continue; if(rc == 0) continue;
if(rc < 0) { if(rc < 0) {
if(errno == EINTR) continue; // Interrupted by signal, retry if(errno == EINTR) continue;
assertUnreachable("poll() failed with unexpected error."); assertUnreachable("poll() failed with unexpected error.");
} }
// Check for errors or input
if(pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) break; if(pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) break;
if(!(pfd.revents & POLLIN)) { if(!(pfd.revents & POLLIN)) {
pfd.revents = 0; pfd.revents = 0;
continue; continue;
} }
// Read a line from stdin
if(!fgets(line, CONSOLE_LINE_MAX, stdin)) { if(!fgets(line, CONSOLE_LINE_MAX, stdin)) {
if(feof(stdin)) break; if(feof(stdin)) break;
clearerr(stdin); clearerr(stdin);
continue; continue;
} }
// Did we read a full line or did it get truncated?
size_t len = strlen(line); 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')) { while(len && (line[len - 1] == '\n' || line[len - 1] == '\r')) {
line[--len] = '\0'; line[--len] = '\0';
} }
+16 -110
View File
@@ -1,14 +1,14 @@
/** /**
* Copyright (c) 2025 Dominic Masters * Copyright (c) 2026 Dominic Masters
* *
* This software is released under the MIT License. * This software is released under the MIT License.
* https://opensource.org/licenses/MIT * https://opensource.org/licenses/MIT
*/ */
#pragma once #pragma once
#include "consolevar.h" #include "consoledefs.h"
#include "consolecmd.h"
#include "error/error.h" #include "error/error.h"
#include "dusk.h"
#ifdef DUSK_CONSOLE_POSIX #ifdef DUSK_CONSOLE_POSIX
#include "thread/thread.h" #include "thread/thread.h"
@@ -17,37 +17,14 @@
#define CONSOLE_POSIX_POLL_RATE 75 #define CONSOLE_POSIX_POLL_RATE 75
#endif #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 { 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]; 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; uint32_t execBufferCount;
consolecmd_t *cmdGet;
consolecmd_t *cmdSet;
#ifdef DUSK_CONSOLE_POSIX #ifdef DUSK_CONSOLE_POSIX
char_t inputBuffer[CONSOLE_LINE_MAX];
thread_t thread; thread_t thread;
threadmutex_t execMutex; threadmutex_t execMutex;
threadmutex_t printMutex; threadmutex_t printMutex;
@@ -59,104 +36,33 @@ extern console_t CONSOLE;
/** /**
* Initializes the console. * Initializes the console.
*/ */
void consoleInit(); void consoleInit(void);
/** /**
* Registers a console command. * Prints a message to the console history.
* *
* @param name The name of the command. * @param message The message to print (printf-style).
* @param function The function to execute when the command is called.
* @return The registered command.
*/ */
consolecmd_t * consoleRegCmd(const char_t *name, consolecmdfunc_t function); void consolePrint(const char_t *message, ...);
/** /**
* Registers a console variable. * Queues a JS string for execution on the main thread. Thread-safe.
* *
* @param name The name of the variable. * @param line The JS source line to execute.
* @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.
*/ */
void consoleExec(const char_t *line); 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. * @return The error return value.
*/ */
errorret_t consoleDraw(); errorret_t consoleDraw(void);
/** /**
* Disposes of the console. * Disposes of the console.
@@ -165,7 +71,7 @@ void consoleDispose(void);
#ifdef DUSK_CONSOLE_POSIX #ifdef DUSK_CONSOLE_POSIX
/** /**
* Input thread handler for posix input. * Input thread handler for POSIX stdin.
* *
* @param thread The thread that is running. * @param thread The thread that is running.
*/ */
-27
View File
@@ -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;
}
-39
View File
@@ -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
);
+2 -12
View File
@@ -1,5 +1,5 @@
/** /**
* Copyright (c) 2025 Dominic Masters * Copyright (c) 2026 Dominic Masters
* *
* This software is released under the MIT License. * This software is released under the MIT License.
* https://opensource.org/licenses/MIT * https://opensource.org/licenses/MIT
@@ -7,16 +7,6 @@
#pragma once #pragma once
#define CONSOLE_CMD_NAME_MAX 16 #define CONSOLE_LINE_MAX 512
#define CONSOLE_CMD_ARGC_MAX 16
#define CONSOLE_COMMANDS_MAX 32
#define CONSOLE_VARIABLES_MAX 64
#define CONSOLE_LINE_MAX 128
#define CONSOLE_HISTORY_MAX 16 #define CONSOLE_HISTORY_MAX 16
#define CONSOLE_EXEC_BUFFER_MAX 32 #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
-64
View File
@@ -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;
}
-65
View File
@@ -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);
+191 -76
View File
@@ -57,16 +57,7 @@ errorret_t sceneRender(void) {
mat4 view, proj, model; mat4 view, proj, model;
if(camCount > 0) { // For each camera
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++) { for(entityid_t camIndex = 0; camIndex < camCount; camIndex++) {
entityid_t camEnt = camEnts[camIndex]; entityid_t camEnt = camEnts[camIndex];
componentid_t camComp = camComps[camIndex]; componentid_t camComp = camComps[camIndex];
@@ -79,88 +70,212 @@ errorret_t sceneRender(void) {
entityCameraGetProjection(camEnt, camComp, proj); entityCameraGetProjection(camEnt, camComp, proj);
entityPositionGetTransform(camEnt, camPos, view); entityPositionGetTransform(camEnt, camPos, view);
for(entityid_t meshIndex = 0; meshIndex < meshCount; meshIndex++) { // For each entity
entityid_t meshEnt = meshEnts[meshIndex]; for(entityid_t entityId = 0; entityId < ENTITY_COUNT_MAX; entityId++) {
componentid_t meshComp = meshComps[meshIndex]; // Does this entity have a material?
mesh_t *mesh = entityMeshGetMesh(meshEnt, meshComp); componentid_t matComp = entityGetComponent(
if(mesh == NULL) continue; 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;
}
// 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( componentid_t meshPos = entityGetComponent(
meshEnt, COMPONENT_TYPE_POSITION entityId, COMPONENT_TYPE_POSITION
); );
if(meshPos == 0xFF) { if(meshPos == 0xFF) {
logError("Mesh entity without entity position found\n"); glm_mat4_identity(model);
continue; } else {
entityPositionGetTransform(entityId, meshPos, model);
} }
componentid_t meshMat = entityGetComponent( // Render the mesh.
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(shaderBind(shader));
errorChain(shaderSetMatrix(shader, SHADER_UNLIT_PROJECTION, proj)); errorChain(shaderSetMatrix(shader, SHADER_UNLIT_PROJECTION, proj));
errorChain(shaderSetMatrix(shader, SHADER_UNLIT_VIEW, view)); errorChain(shaderSetMatrix(shader, SHADER_UNLIT_VIEW, view));
errorChain(shaderSetMatrix(shader, SHADER_UNLIT_MODEL, model)); errorChain(shaderSetMatrix(shader, SHADER_UNLIT_MODEL, model));
errorChain(shaderSetMaterial(shader, material)); errorChain(shaderSetMaterial(shader, material));
errorChain(meshDraw(mesh, 0, -1)); errorChain(meshDraw(mesh, 0, -1));
} continue;
}
}
} }
glm_ortho( // No, in future there may be other renderable types.
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(); 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) { errorret_t sceneSetImmediate(const char_t *scene) {
@@ -39,7 +39,7 @@ moduleBaseFunction(moduleConsolePrint) {
} }
moduleBaseFunction(moduleConsoleGetVisible) { moduleBaseFunction(moduleConsoleGetVisible) {
return jerry_boolean(consoleVarGetBool("console", false)); return jerry_boolean(CONSOLE.visible);
} }
moduleBaseFunction(moduleConsoleSetVisible) { moduleBaseFunction(moduleConsoleSetVisible) {
@@ -47,7 +47,7 @@ moduleBaseFunction(moduleConsoleSetVisible) {
if(!jerry_value_is_boolean(args[0])) { if(!jerry_value_is_boolean(args[0])) {
return moduleBaseThrow("Console.visible: expected boolean"); 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(); return jerry_undefined();
} }
@@ -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
);
}
@@ -80,6 +80,43 @@ static jerry_value_t moduleEntityGetComponent(
#include "entity/componentlist.h" #include "entity/componentlist.h"
#undef X #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 // Methods
moduleBaseFunction(moduleEntityConstructor) { moduleBaseFunction(moduleEntityConstructor) {
entityscript_t *inst = (entityscript_t*)memoryAllocate( entityscript_t *inst = (entityscript_t*)memoryAllocate(
@@ -130,6 +167,8 @@ static void moduleEntity(void) {
moduleEntityConstructor moduleEntityConstructor
); );
scriptProtoDefineToString(&MODULE_ENTITY_PROTO, moduleEntityToString);
// Entity Methods // Entity Methods
scriptProtoDefineFunc( scriptProtoDefineFunc(
&MODULE_ENTITY_PROTO, "add", moduleEntityAddComponent &MODULE_ENTITY_PROTO, "add", moduleEntityAddComponent
+18
View File
@@ -156,6 +156,22 @@ moduleBaseFunction(moduleMatStaticLookAt) {
return scriptProtoCreateValue(&MODULE_MAT4_PROTO, r); 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]) { static inline jerry_value_t moduleMat4Push(float (*m)[4]) {
return scriptProtoCreateValue(&MODULE_MAT4_PROTO, m); return scriptProtoCreateValue(&MODULE_MAT4_PROTO, m);
} }
@@ -174,6 +190,8 @@ static void moduleMat4(void) {
&MODULE_MAT4_PROTO, "Mat4", sizeof(mat4), moduleMatConstructor &MODULE_MAT4_PROTO, "Mat4", sizeof(mat4), moduleMatConstructor
); );
scriptProtoDefineToString(&MODULE_MAT4_PROTO, moduleMatToString);
scriptProtoDefineFunc( scriptProtoDefineFunc(
&MODULE_MAT4_PROTO, "mul", moduleMatMul &MODULE_MAT4_PROTO, "mul", moduleMatMul
); );
+10
View File
@@ -142,6 +142,14 @@ moduleBaseFunction(moduleVec2Distance) {
return jerry_number(glm_vec2_distance(a, b)); 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) { static inline jerry_value_t moduleVec2Push(const float_t *v) {
return scriptProtoCreateValue(&MODULE_VEC2_PROTO, v); return scriptProtoCreateValue(&MODULE_VEC2_PROTO, v);
} }
@@ -166,6 +174,8 @@ static void moduleVec2(void) {
&MODULE_VEC2_PROTO, "y", moduleVec2GetY, moduleVec2SetY &MODULE_VEC2_PROTO, "y", moduleVec2GetY, moduleVec2SetY
); );
scriptProtoDefineToString(&MODULE_VEC2_PROTO, moduleVec2ToString);
scriptProtoDefineFunc(&MODULE_VEC2_PROTO, "dot", moduleVec2Dot); scriptProtoDefineFunc(&MODULE_VEC2_PROTO, "dot", moduleVec2Dot);
scriptProtoDefineFunc(&MODULE_VEC2_PROTO, "length", moduleVec2Length); scriptProtoDefineFunc(&MODULE_VEC2_PROTO, "length", moduleVec2Length);
scriptProtoDefineFunc(&MODULE_VEC2_PROTO, "lengthSq", moduleVec2LengthSq); scriptProtoDefineFunc(&MODULE_VEC2_PROTO, "lengthSq", moduleVec2LengthSq);
+10
View File
@@ -165,6 +165,14 @@ moduleBaseFunction(moduleVec3Distance) {
return jerry_number(glm_vec3_distance(a, b)); 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) { static inline jerry_value_t moduleVec3Push(const float_t *v) {
return scriptProtoCreateValue(&MODULE_VEC3_PROTO, v); return scriptProtoCreateValue(&MODULE_VEC3_PROTO, v);
} }
@@ -193,6 +201,8 @@ static void moduleVec3(void) {
&MODULE_VEC3_PROTO, "z", moduleVec3GetZ, moduleVec3SetZ &MODULE_VEC3_PROTO, "z", moduleVec3GetZ, moduleVec3SetZ
); );
scriptProtoDefineToString(&MODULE_VEC3_PROTO, moduleVec3ToString);
scriptProtoDefineFunc(&MODULE_VEC3_PROTO, "dot", moduleVec3Dot); scriptProtoDefineFunc(&MODULE_VEC3_PROTO, "dot", moduleVec3Dot);
scriptProtoDefineFunc(&MODULE_VEC3_PROTO, "cross", moduleVec3Cross); scriptProtoDefineFunc(&MODULE_VEC3_PROTO, "cross", moduleVec3Cross);
scriptProtoDefineFunc(&MODULE_VEC3_PROTO, "length", moduleVec3Length); scriptProtoDefineFunc(&MODULE_VEC3_PROTO, "length", moduleVec3Length);
@@ -74,6 +74,17 @@ moduleBaseFunction(moduleVec3RefSetZ) {
return jerry_undefined(); 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( static inline jerry_value_t moduleVec3RefPush(
float_t *data, void (*onChange)(void *), void *ctx float_t *data, void (*onChange)(void *), void *ctx
) { ) {
@@ -98,6 +109,8 @@ static void moduleVec3Ref(void) {
scriptProtoInit( scriptProtoInit(
&MODULE_VEC3_REF_PROTO, NULL, sizeof(vec3ref_t), NULL &MODULE_VEC3_REF_PROTO, NULL, sizeof(vec3ref_t), NULL
); );
scriptProtoDefineToString(&MODULE_VEC3_REF_PROTO, moduleVec3RefToString);
scriptProtoDefineProp( scriptProtoDefineProp(
&MODULE_VEC3_REF_PROTO, "x", &MODULE_VEC3_REF_PROTO, "x",
moduleVec3RefGetX, moduleVec3RefSetX moduleVec3RefGetX, moduleVec3RefSetX
+13
View File
@@ -199,6 +199,17 @@ moduleBaseFunction(moduleVec4Lerp) {
return scriptProtoCreateValue(&MODULE_VEC4_PROTO, r); 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) { static inline jerry_value_t moduleVec4Push(const float_t *v) {
return scriptProtoCreateValue(&MODULE_VEC4_PROTO, v); return scriptProtoCreateValue(&MODULE_VEC4_PROTO, v);
} }
@@ -243,6 +254,8 @@ static void moduleVec4(void) {
&MODULE_VEC4_PROTO, "v1", moduleVec4GetV1, moduleVec4SetV1 &MODULE_VEC4_PROTO, "v1", moduleVec4GetV1, moduleVec4SetV1
); );
scriptProtoDefineToString(&MODULE_VEC4_PROTO, moduleVec4ToString);
scriptProtoDefineFunc(&MODULE_VEC4_PROTO, "dot", moduleVec4Dot); scriptProtoDefineFunc(&MODULE_VEC4_PROTO, "dot", moduleVec4Dot);
scriptProtoDefineFunc(&MODULE_VEC4_PROTO, "length", moduleVec4Length); scriptProtoDefineFunc(&MODULE_VEC4_PROTO, "length", moduleVec4Length);
scriptProtoDefineFunc(&MODULE_VEC4_PROTO, "lengthSq", moduleVec4LengthSq); scriptProtoDefineFunc(&MODULE_VEC4_PROTO, "lengthSq", moduleVec4LengthSq);
+2
View File
@@ -16,6 +16,7 @@
#include "script/module/display/modulescreen.h" #include "script/module/display/modulescreen.h"
#include "script/module/scene/modulescene.h" #include "script/module/scene/modulescene.h"
#include "script/module/console/moduleconsole.h" #include "script/module/console/moduleconsole.h"
#include "script/module/engine/moduleengine.h"
static void moduleRegister(void) { static void moduleRegister(void) {
moduleInclude(); moduleInclude();
@@ -28,4 +29,5 @@ static void moduleRegister(void) {
moduleScreen(); moduleScreen();
moduleScene(); moduleScene();
moduleConsole(); moduleConsole();
moduleEngine();
} }
+5 -1
View File
@@ -39,7 +39,7 @@ errorret_t scriptManagerInit(void) {
errorOk(); 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"); assertNotNull(script, "Script cannot be NULL");
jerry_value_t result = jerry_eval( jerry_value_t result = jerry_eval(
@@ -62,7 +62,11 @@ errorret_t scriptManagerExec(const char_t *script) {
errorThrow("Failed to execute script: %s", buf); errorThrow("Failed to execute script: %s", buf);
} }
if(resultOut != NULL) {
*resultOut = result;
} else {
jerry_value_free(result); jerry_value_free(result);
}
errorOk(); errorOk();
} }
+4 -1
View File
@@ -37,9 +37,12 @@ errorret_t scriptManagerInit(void);
* Execute a JS string in the active script context. * 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. * @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. * Execute a JS file in the active script context.
@@ -9,5 +9,5 @@
#include "script/scriptmanager.h" #include "script/scriptmanager.h"
void modulePlatformVita(void) { void modulePlatformVita(void) {
scriptManagerExec("VITA = true\n"); scriptManagerExec("VITA = true\n", NULL);
} }