Nuke the old input system, use the new UI system
This commit is contained in:
@@ -62,7 +62,6 @@ add_subdirectory(log)
|
||||
add_subdirectory(engine)
|
||||
add_subdirectory(entity)
|
||||
add_subdirectory(error)
|
||||
add_subdirectory(event)
|
||||
add_subdirectory(input)
|
||||
add_subdirectory(locale)
|
||||
add_subdirectory(physics)
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
# 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
|
||||
event.c
|
||||
)
|
||||
@@ -1,239 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "event.h"
|
||||
#include "assert/assert.h"
|
||||
#include "util/memory.h"
|
||||
#include "console/console.h"
|
||||
|
||||
void eventInit(
|
||||
event_t *event,
|
||||
eventlistener_t *array,
|
||||
const uint16_t maxListeners
|
||||
) {
|
||||
assertNotNull(event, "Event cannot be NULL");
|
||||
assertNotNull(array, "Listener array cannot be NULL");
|
||||
assertTrue(maxListeners > 0, "Max listeners must be greater than 0");
|
||||
|
||||
memoryZero(event, sizeof(event_t));
|
||||
|
||||
event->listenerArray = array;
|
||||
event->maxListeners = maxListeners;
|
||||
}
|
||||
|
||||
eventsub_t eventSubscribeUser(
|
||||
event_t *event,
|
||||
const eventtype_t type,
|
||||
const eventuserdata_t user
|
||||
) {
|
||||
assertNotNull(event, "Event cannot be NULL");
|
||||
assertTrue(
|
||||
event->listenerCount < event->maxListeners,
|
||||
"Maximum number of listeners reached"
|
||||
);
|
||||
|
||||
if(type == EVENT_TYPE_C) {
|
||||
assertNotNull(
|
||||
user.c.callback,
|
||||
"C event listener callback cannot be NULL"
|
||||
);
|
||||
} else if(type == EVENT_TYPE_SCRIPT) {
|
||||
assertNotNull(
|
||||
user.script.context,
|
||||
"Script event listener context cannot be NULL"
|
||||
);
|
||||
assertTrue(
|
||||
user.script.funcValue != 0,
|
||||
"Script event listener function reference is invalid"
|
||||
);
|
||||
} else {
|
||||
assertUnreachable("Unknown event listener type");
|
||||
}
|
||||
|
||||
eventsub_t id = event->nextId++;
|
||||
assertTrue(event->nextId != 0, "Event subscription ID overflow");
|
||||
|
||||
eventlistener_t *listener = &event->listenerArray[event->listenerCount++];
|
||||
memoryZero(listener, sizeof(eventlistener_t));
|
||||
listener->user = user;
|
||||
listener->id = id;
|
||||
listener->type = type;
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
eventsub_t eventSubscribe(
|
||||
event_t *event,
|
||||
const eventcallback_t callback,
|
||||
const void *user
|
||||
) {
|
||||
return eventSubscribeUser(
|
||||
event,
|
||||
EVENT_TYPE_C,
|
||||
(eventuserdata_t){ .c = { .callback = callback, .user = (void *)user } }
|
||||
);
|
||||
}
|
||||
|
||||
eventsub_t eventSubscribeScriptContext(
|
||||
event_t *event,
|
||||
scriptmanager_t *context,
|
||||
jerry_value_t funcValue
|
||||
) {
|
||||
assertNotNull(context, "Script context cannot be NULL");
|
||||
assertTrue(funcValue != 0, "Script function value is invalid");
|
||||
|
||||
bool_t alreadySubbed = false;
|
||||
uint8_t i = 0;
|
||||
do {
|
||||
if(context->subscribedEvents[i] == event) {
|
||||
alreadySubbed = true;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
} while(i < SCRIPT_MANAGER_MAX_EVENT_SUBSCRIPTIONS);
|
||||
|
||||
if(!alreadySubbed) {
|
||||
i = 0;
|
||||
do {
|
||||
if(context->subscribedEvents[i] == NULL) {
|
||||
context->subscribedEvents[i] = event;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
} while(i < SCRIPT_MANAGER_MAX_EVENT_SUBSCRIPTIONS);
|
||||
|
||||
assertTrue(
|
||||
i < SCRIPT_MANAGER_MAX_EVENT_SUBSCRIPTIONS,
|
||||
"Script context has reached maximum event subscriptions"
|
||||
);
|
||||
}
|
||||
|
||||
return eventSubscribeUser(
|
||||
event,
|
||||
EVENT_TYPE_SCRIPT,
|
||||
(eventuserdata_t){
|
||||
.script = {
|
||||
.context = context,
|
||||
.funcValue = funcValue
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
void eventUnsubscribe(event_t *event, const eventsub_t id) {
|
||||
assertNotNull(event, "Event cannot be NULL");
|
||||
assertFalse(event->isInvoking, "Cannot unsubscribe while invoking event");
|
||||
|
||||
if(event->listenerCount == 0) return;
|
||||
|
||||
uint16_t index = 0;
|
||||
do {
|
||||
if(event->listenerArray[index].id != id) {
|
||||
index++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(event->listenerArray[index].type == EVENT_TYPE_SCRIPT) {
|
||||
jerry_value_t funcVal = event->listenerArray[index].user.script.funcValue;
|
||||
if(funcVal != 0) {
|
||||
jerry_value_free(funcVal);
|
||||
}
|
||||
}
|
||||
|
||||
event->listenerArray[index] = event->listenerArray[--event->listenerCount];
|
||||
return;
|
||||
} while(index < event->listenerCount);
|
||||
}
|
||||
|
||||
void eventUnsubscribeScriptContext(
|
||||
event_t *event,
|
||||
const scriptmanager_t *ctx
|
||||
) {
|
||||
assertNotNull(event, "Event cannot be NULL");
|
||||
assertNotNull(ctx, "Script context cannot be NULL");
|
||||
|
||||
if(event->listenerCount == 0) return;
|
||||
|
||||
uint16_t i = 0;
|
||||
do {
|
||||
eventlistener_t *listener = &event->listenerArray[i];
|
||||
if(
|
||||
listener->type != EVENT_TYPE_SCRIPT ||
|
||||
listener->user.script.context != ctx
|
||||
) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
eventUnsubscribe(event, listener->id);
|
||||
} while(i < event->listenerCount);
|
||||
}
|
||||
|
||||
void eventInvoke(
|
||||
event_t *event,
|
||||
const void *eventParams,
|
||||
const char_t *metatableName
|
||||
) {
|
||||
assertNotNull(event, "Event cannot be NULL");
|
||||
|
||||
if(event->listenerCount == 0) return;
|
||||
|
||||
event->isInvoking = true;
|
||||
|
||||
eventdata_t data = {
|
||||
.event = event,
|
||||
.eventParams = eventParams,
|
||||
};
|
||||
|
||||
uint16_t i = 0;
|
||||
do {
|
||||
eventlistener_t *listener = &event->listenerArray[i];
|
||||
|
||||
if(listener->type == EVENT_TYPE_C) {
|
||||
listener->user.c.callback(&data, listener->user.c);
|
||||
} else if(listener->type == EVENT_TYPE_SCRIPT) {
|
||||
jerry_value_t funcVal = listener->user.script.funcValue;
|
||||
assertNotNull((void *)(uintptr_t)funcVal, "Script function value is NULL");
|
||||
|
||||
jerry_value_t callArgs[1];
|
||||
jerry_length_t argCount = 0;
|
||||
|
||||
if(eventParams != NULL) {
|
||||
callArgs[0] = jerry_object();
|
||||
jerry_object_set_native_ptr(
|
||||
callArgs[0], &JS_PTR_NATIVE_INFO, (void *)eventParams
|
||||
);
|
||||
argCount = 1;
|
||||
}
|
||||
|
||||
jerry_value_t result = jerry_call(
|
||||
funcVal, jerry_undefined(), callArgs, argCount
|
||||
);
|
||||
|
||||
if(argCount > 0) jerry_value_free(callArgs[0]);
|
||||
|
||||
if(jerry_value_is_exception(result)) {
|
||||
jerry_value_t errStr = jerry_value_to_string(
|
||||
jerry_exception_value(result, false)
|
||||
);
|
||||
char_t buf[256];
|
||||
jerry_size_t len = jerry_string_to_buffer(
|
||||
errStr, JERRY_ENCODING_UTF8, (jerry_char_t *)buf, sizeof(buf) - 1
|
||||
);
|
||||
buf[len] = '\0';
|
||||
jerry_value_free(errStr);
|
||||
consolePrint("Error invoking script event listener:\n%s\n", buf);
|
||||
}
|
||||
|
||||
jerry_value_free(result);
|
||||
} else {
|
||||
assertUnreachable("Unknown event listener type");
|
||||
}
|
||||
i++;
|
||||
} while(i < event->listenerCount);
|
||||
|
||||
event->isInvoking = false;
|
||||
}
|
||||
@@ -1,124 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "eventuser.h"
|
||||
|
||||
typedef struct event_s event_t;
|
||||
|
||||
typedef struct eventdata_s {
|
||||
const void *eventParams;
|
||||
const event_t *event;
|
||||
} eventdata_t;
|
||||
|
||||
typedef struct eventlistener_s {
|
||||
eventuserdata_t user;
|
||||
eventtype_t type;
|
||||
uint16_t id;
|
||||
} eventlistener_t;
|
||||
|
||||
typedef uint16_t eventsub_t;
|
||||
|
||||
typedef struct event_s {
|
||||
eventlistener_t *listenerArray;
|
||||
uint16_t listenerCount;
|
||||
uint16_t maxListeners;
|
||||
eventsub_t nextId;
|
||||
|
||||
bool_t isInvoking;
|
||||
} event_t;
|
||||
|
||||
/**
|
||||
* Initialize an event structure.
|
||||
*
|
||||
* @param event The event to initialize.
|
||||
* @param array The array to hold event listeners.
|
||||
* @param maxListeners The maximum number of listeners.
|
||||
*/
|
||||
void eventInit(
|
||||
event_t *event,
|
||||
eventlistener_t *array,
|
||||
const uint16_t maxListeners
|
||||
);
|
||||
|
||||
/**
|
||||
* Subscribe to an event.
|
||||
*
|
||||
* @param event The event to subscribe to.
|
||||
* @param type The type of the event (C or Lua).
|
||||
* @param user User data to pass to the callback.
|
||||
* @return The subscription ID, used to unsubscribe later.
|
||||
*/
|
||||
eventsub_t eventSubscribeUser(
|
||||
event_t *event,
|
||||
const eventtype_t type,
|
||||
const eventuserdata_t user
|
||||
);
|
||||
|
||||
/**
|
||||
* Subscribe to an event with a C function callback.
|
||||
*
|
||||
* @param event The event to subscribe to.
|
||||
* @param callback The C function callback.
|
||||
* @param user User data pointer to pass to the callback.
|
||||
* @return The subscription ID, used to unsubscribe later.
|
||||
*/
|
||||
eventsub_t eventSubscribe(
|
||||
event_t *event,
|
||||
const eventcallback_t callback,
|
||||
const void *user
|
||||
);
|
||||
|
||||
/**
|
||||
* Subscribe to an event with a script function callback.
|
||||
*
|
||||
* @param event The event to subscribe to.
|
||||
* @param context The script context.
|
||||
* @param functionIndex The index of the Lua function on the stack.
|
||||
* @return The subscription ID, used to unsubscribe later.
|
||||
*/
|
||||
eventsub_t eventSubscribeScriptContext(
|
||||
event_t *event,
|
||||
scriptmanager_t *context,
|
||||
jerry_value_t funcValue
|
||||
);
|
||||
|
||||
/**
|
||||
* Unsubscribe from an event.
|
||||
*
|
||||
* @param event The event to unsubscribe from.
|
||||
* @param subscription The subscription ID to remove.
|
||||
*/
|
||||
void eventUnsubscribe(event_t *event, const eventsub_t subscription);
|
||||
|
||||
/**
|
||||
* Unsubscribe all event listeners associated with a script context.
|
||||
*
|
||||
* @param event The event to unsubscribe from.
|
||||
* @param context The script context whose listeners should be removed.
|
||||
*/
|
||||
void eventUnsubscribeScriptContext(
|
||||
event_t *event,
|
||||
const scriptmanager_t *ctx
|
||||
);
|
||||
|
||||
/**
|
||||
* Invoke an event, calling all subscribed listeners. Optionally provide event
|
||||
* parameters, and if desired pass a metatable name. Event listeners will be
|
||||
* able to read event params, and if metatable name is provided the script
|
||||
* listeners will lookup metatable information matching that name to access the
|
||||
* params as a structure within the script.
|
||||
*
|
||||
* @param event The event to invoke.
|
||||
* @param eventParams Parameters to pass to the event listeners.
|
||||
* @param metatableName Metatable name. See details.
|
||||
*/
|
||||
void eventInvoke(
|
||||
event_t *event,
|
||||
const void *eventParams,
|
||||
const char_t *metatableName
|
||||
);
|
||||
@@ -1,14 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "dusk.h"
|
||||
|
||||
typedef struct eventdata_s eventdata_t;
|
||||
typedef struct eventc_s eventc_t;
|
||||
|
||||
typedef void (*eventcallback_t)(eventdata_t *data, eventc_t user);
|
||||
@@ -1,30 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "eventcallback.h"
|
||||
#include "script/scriptmanager.h"
|
||||
|
||||
typedef enum {
|
||||
EVENT_TYPE_C = 0,
|
||||
EVENT_TYPE_SCRIPT = 1
|
||||
} eventtype_t;
|
||||
|
||||
typedef struct {
|
||||
scriptmanager_t *context;
|
||||
jerry_value_t funcValue;
|
||||
} eventscript_t;
|
||||
|
||||
typedef struct eventc_s {
|
||||
void *user;
|
||||
eventcallback_t callback;
|
||||
} eventc_t;
|
||||
|
||||
typedef union eventuserdata_u {
|
||||
eventscript_t script;
|
||||
eventc_t c;
|
||||
} eventuserdata_t;
|
||||
@@ -27,13 +27,6 @@ errorret_t inputInit(void) {
|
||||
errorChain(inputInitPlatform());
|
||||
#endif
|
||||
|
||||
eventInit(
|
||||
&INPUT.eventPressed, INPUT.pressedListeners, INPUT_LISTENER_PRESSED_MAX
|
||||
);
|
||||
eventInit(
|
||||
&INPUT.eventReleased, INPUT.releasedListeners, INPUT_LISTENER_RELEASED_MAX
|
||||
);
|
||||
|
||||
errorOk();
|
||||
}
|
||||
|
||||
@@ -94,28 +87,6 @@ void inputUpdate(void) {
|
||||
#ifdef DUSK_TIME_DYNAMIC
|
||||
if(TIME.dynamicUpdate) return;
|
||||
#endif
|
||||
|
||||
// if(INPUT.eventPressed.listenerCount > 0) {
|
||||
// action = &INPUT.actions[0];
|
||||
// do {
|
||||
// if(inputPressed(action->action)) {
|
||||
// inputevent_t inputEvent = { .action = action->action };
|
||||
// eventInvoke(&INPUT.eventPressed, &inputEvent, "input_mt");
|
||||
// }
|
||||
// action++;
|
||||
// } while(action < &INPUT.actions[INPUT_ACTION_COUNT]);
|
||||
// }
|
||||
|
||||
// if(INPUT.eventReleased.listenerCount > 0) {
|
||||
// action = &INPUT.actions[0];
|
||||
// do {
|
||||
// if(inputReleased(action->action)) {
|
||||
// inputevent_t inputEvent = { .action = action->action };
|
||||
// eventInvoke(&INPUT.eventReleased, &inputEvent, "input_mt");
|
||||
// }
|
||||
// action++;
|
||||
// } while(action < &INPUT.actions[INPUT_ACTION_COUNT]);
|
||||
// }
|
||||
}
|
||||
|
||||
float_t inputGetCurrentValue(const inputaction_t action) {
|
||||
|
||||
@@ -9,23 +9,13 @@
|
||||
#include "error/error.h"
|
||||
#include "inputbutton.h"
|
||||
#include "inputaction.h"
|
||||
#include "event/event.h"
|
||||
|
||||
#define INPUT_LISTENER_PRESSED_MAX 16
|
||||
#define INPUT_LISTENER_RELEASED_MAX INPUT_LISTENER_PRESSED_MAX
|
||||
|
||||
typedef struct {
|
||||
const inputaction_t action;
|
||||
} inputevent_t;
|
||||
|
||||
typedef struct {
|
||||
inputactiondata_t actions[INPUT_ACTION_COUNT];
|
||||
|
||||
eventlistener_t pressedListeners[INPUT_LISTENER_PRESSED_MAX];
|
||||
event_t eventPressed;
|
||||
eventlistener_t releasedListeners[INPUT_LISTENER_RELEASED_MAX];
|
||||
event_t eventReleased;
|
||||
|
||||
inputplatform_t platform;
|
||||
} input_t;
|
||||
|
||||
|
||||
+38
-162
@@ -11,14 +11,12 @@
|
||||
#include "display/screen/screen.h"
|
||||
#include "entity/entitymanager.h"
|
||||
#include "display/shader/shaderunlit.h"
|
||||
#include "display/mesh/cube.h"
|
||||
#include "display/spritebatch/spritebatch.h"
|
||||
#include "display/text/text.h"
|
||||
#include "display/screen/screen.h"
|
||||
#include "console/console.h"
|
||||
#include "util/string.h"
|
||||
#include "script/scriptmanager.h"
|
||||
#include "script/module/scene/modulescene.h"
|
||||
#include "ui/ui.h"
|
||||
|
||||
scene_t SCENE;
|
||||
|
||||
@@ -55,6 +53,7 @@ errorret_t sceneRender(void) {
|
||||
COMPONENT_TYPE_CAMERA, camEnts, camComps
|
||||
);
|
||||
|
||||
shader_t *shaderCurrent = NULL;
|
||||
mat4 view, proj, model;
|
||||
|
||||
// For each camera
|
||||
@@ -70,7 +69,8 @@ errorret_t sceneRender(void) {
|
||||
entityCameraGetProjection(camEnt, camComp, proj);
|
||||
entityPositionGetTransform(camEnt, camPos, view);
|
||||
|
||||
// For each entity
|
||||
// For each entity (I could iterate only over entities with mesh/material)
|
||||
// but in future I may have different renderable types.
|
||||
for(entityid_t entityId = 0; entityId < ENTITY_COUNT_MAX; entityId++) {
|
||||
// Does this entity have a material?
|
||||
componentid_t matComp = entityGetComponent(
|
||||
@@ -81,9 +81,13 @@ errorret_t sceneRender(void) {
|
||||
componentid_t meshComp = entityGetComponent(
|
||||
entityId, COMPONENT_TYPE_MESH
|
||||
);
|
||||
|
||||
if(meshComp == 0xFF) {
|
||||
logError("Entity with material component without mesh component found\n");
|
||||
logError("Entity with material but no mesh found\n");
|
||||
continue;
|
||||
}
|
||||
mesh_t *mesh = entityMeshGetMesh(entityId, meshComp);
|
||||
if(mesh == NULL) {
|
||||
logError("Entity with material but no mesh found\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -93,14 +97,7 @@ errorret_t sceneRender(void) {
|
||||
);
|
||||
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");
|
||||
logError("Entity with material but no shader found\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -115,9 +112,13 @@ errorret_t sceneRender(void) {
|
||||
}
|
||||
|
||||
// Render the mesh.
|
||||
errorChain(shaderBind(shader));
|
||||
if(shaderCurrent != shader) {
|
||||
shaderCurrent = shader;
|
||||
errorChain(shaderBind(shaderCurrent));
|
||||
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));
|
||||
@@ -128,154 +129,29 @@ errorret_t sceneRender(void) {
|
||||
}
|
||||
}
|
||||
|
||||
// UI Rendering
|
||||
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(uiRender());
|
||||
|
||||
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) {
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#pragma once
|
||||
#include "script/scriptmanager.h"
|
||||
#include "asset/assetfile.h"
|
||||
#include "event/event.h"
|
||||
|
||||
#define SCENE_EVENT_UPDATE_MAX 16
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#include "assert/assert.h"
|
||||
#include "asset/asset.h"
|
||||
#include "util/memory.h"
|
||||
#include "event/event.h"
|
||||
#include "asset/loader/script/assetscriptloader.h"
|
||||
#include "script/module/module.h"
|
||||
|
||||
@@ -79,12 +78,6 @@ errorret_t scriptManagerExecFile(
|
||||
}
|
||||
|
||||
errorret_t scriptManagerDispose(void) {
|
||||
for(uint8_t i = 0; i < SCRIPT_MANAGER_MAX_EVENT_SUBSCRIPTIONS; i++) {
|
||||
event_t *event = SCRIPT_MANAGER.subscribedEvents[i];
|
||||
if(event == NULL) continue;
|
||||
eventUnsubscribeScriptContext(event, &SCRIPT_MANAGER);
|
||||
}
|
||||
|
||||
jerry_cleanup();
|
||||
errorOk();
|
||||
}
|
||||
|
||||
@@ -9,12 +9,10 @@
|
||||
#include "error/error.h"
|
||||
#include "scriptvalue.h"
|
||||
|
||||
typedef struct event_s event_t;
|
||||
|
||||
#define SCRIPT_MANAGER_MAX_EVENT_SUBSCRIPTIONS 64
|
||||
|
||||
typedef struct {
|
||||
event_t *subscribedEvents[SCRIPT_MANAGER_MAX_EVENT_SUBSCRIPTIONS];
|
||||
void* nothing;
|
||||
} scriptmanager_t;
|
||||
|
||||
extern scriptmanager_t SCRIPT_MANAGER;
|
||||
|
||||
@@ -7,4 +7,5 @@
|
||||
target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
||||
PUBLIC
|
||||
ui.c
|
||||
uifps.c
|
||||
)
|
||||
+7
-8
@@ -10,6 +10,8 @@
|
||||
#include "assert/assert.h"
|
||||
#include "display/spritebatch/spritebatch.h"
|
||||
#include "display/screen/screen.h"
|
||||
#include "ui/uifps.h"
|
||||
#include "console/console.h"
|
||||
|
||||
ui_t UI;
|
||||
|
||||
@@ -26,15 +28,12 @@ errorret_t uiInit(void) {
|
||||
void uiUpdate(void) {
|
||||
}
|
||||
|
||||
void uiRender(void) {
|
||||
// UI.camera.orthographic.right = SCREEN.width;
|
||||
// UI.camera.orthographic.top = SCREEN.height;
|
||||
errorret_t uiRender(void) {
|
||||
errorChain(uiFPSDraw());
|
||||
errorChain(consoleDraw());
|
||||
errorChain(spriteBatchFlush());
|
||||
|
||||
// // cameraPushMatrix(&UI.camera);
|
||||
// spriteBatchClear();
|
||||
|
||||
// spriteBatchFlush();
|
||||
// // cameraPopMatrix();
|
||||
errorOk();
|
||||
}
|
||||
|
||||
void uiDispose(void) {
|
||||
|
||||
+3
-1
@@ -26,8 +26,10 @@ void uiUpdate(void);
|
||||
|
||||
/**
|
||||
* Renders the UI system.
|
||||
*
|
||||
* @return Any error that occurs.
|
||||
*/
|
||||
void uiRender(void);
|
||||
errorret_t uiRender(void);
|
||||
|
||||
/**
|
||||
* Disposes of the UI system.
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "uifps.h"
|
||||
#include "time/time.h"
|
||||
#include "display/spritebatch/spritebatch.h"
|
||||
#include "display/text/text.h"
|
||||
|
||||
uifps_t UIFPS;
|
||||
|
||||
errorret_t uiFPSDraw() {
|
||||
char_t fpsText[32];
|
||||
|
||||
// Get now.
|
||||
dusktimeepoch_t now = timeGetEpoch();
|
||||
double_t delta = now.time - UIFPS.lastTick.time;
|
||||
UIFPS.lastTick = now;
|
||||
|
||||
// Raw current FPS
|
||||
float_t fps = delta > 0 ? 1.0 / delta : 0.0;
|
||||
|
||||
// Average FPS using exponential moving average
|
||||
const float_t alpha = 0.1f; // Smoothing factor
|
||||
if(UIFPS.fpsAverage == 0.0f) {
|
||||
UIFPS.fpsAverage = fps; // Initialize average on first run
|
||||
} else {
|
||||
UIFPS.fpsAverage = alpha * fps + (1.0f - alpha) * UIFPS.fpsAverage;
|
||||
}
|
||||
|
||||
snprintf(
|
||||
fpsText,
|
||||
sizeof(fpsText),
|
||||
"%.1f/%.1fms",
|
||||
UIFPS.fpsAverage,
|
||||
delta * 1000.0f
|
||||
);
|
||||
|
||||
color_t textColor;
|
||||
if(fps >= 60.0f) {
|
||||
textColor = COLOR_GREEN;
|
||||
} else if(fps >= 45.0f) {
|
||||
textColor = COLOR_YELLOW;
|
||||
} else {
|
||||
textColor = COLOR_RED;
|
||||
}
|
||||
|
||||
errorChain(textDraw(
|
||||
0, 0,
|
||||
fpsText, textColor,
|
||||
&FONT_TILESET_DEFAULT, &FONT_TEXTURE_DEFAULT
|
||||
));
|
||||
|
||||
errorOk();
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "error/error.h"
|
||||
#include "time/timeepoch.h"
|
||||
|
||||
typedef struct {
|
||||
dusktimeepoch_t lastTick;
|
||||
float_t fpsAverage;
|
||||
} uifps_t;
|
||||
|
||||
extern uifps_t UIFPS;
|
||||
|
||||
/**
|
||||
* Draws the FPS counter on the screen, and also does the update (for now).
|
||||
*
|
||||
* @return Any error that occurs.
|
||||
*/
|
||||
errorret_t uiFPSDraw();
|
||||
Reference in New Issue
Block a user