Event
This commit is contained in:
@@ -55,6 +55,7 @@ add_subdirectory(debug)
|
|||||||
add_subdirectory(display)
|
add_subdirectory(display)
|
||||||
add_subdirectory(engine)
|
add_subdirectory(engine)
|
||||||
add_subdirectory(error)
|
add_subdirectory(error)
|
||||||
|
add_subdirectory(event)
|
||||||
add_subdirectory(input)
|
add_subdirectory(input)
|
||||||
add_subdirectory(item)
|
add_subdirectory(item)
|
||||||
add_subdirectory(locale)
|
add_subdirectory(locale)
|
||||||
|
|||||||
10
src/event/CMakeLists.txt
Normal file
10
src/event/CMakeLists.txt
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# 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
|
||||||
|
)
|
||||||
106
src/event/event.c
Normal file
106
src/event/event.c
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
/**
|
||||||
|
* 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"
|
||||||
|
|
||||||
|
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 eventSubscribe(
|
||||||
|
event_t *event,
|
||||||
|
const eventcallback_t callback,
|
||||||
|
const void *user
|
||||||
|
) {
|
||||||
|
assertNotNull(event, "Event cannot be NULL");
|
||||||
|
assertNotNull(callback, "Callback cannot be NULL");
|
||||||
|
assertTrue(
|
||||||
|
event->listenerCount < event->maxListeners,
|
||||||
|
"Maximum number of listeners reached"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Gen a new ID
|
||||||
|
eventsub_t id = event->nextId++;
|
||||||
|
// Did we wrap?
|
||||||
|
assertTrue(event->nextId != 0, "Event subscription ID overflow");
|
||||||
|
|
||||||
|
// Append listener
|
||||||
|
eventlistener_t *listener = &event->listenerArray[event->listenerCount++];
|
||||||
|
memoryZero(listener, sizeof(eventlistener_t));
|
||||||
|
listener->callback = callback;
|
||||||
|
listener->user = (void*)user;
|
||||||
|
listener->id = id;
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
// Find listener
|
||||||
|
uint16_t index = 0;
|
||||||
|
do {
|
||||||
|
if(event->listenerArray[index].id == id) {
|
||||||
|
// Found it, remove by swapping with last and reducing count
|
||||||
|
event->listenerArray[index] = event->listenerArray[--event->listenerCount];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
} while(index < event->listenerCount);
|
||||||
|
|
||||||
|
// Did we find it?
|
||||||
|
if(index == event->listenerCount) return;
|
||||||
|
|
||||||
|
// Shift remaining listeners down (if any)
|
||||||
|
if(index < event->listenerCount - 1) {
|
||||||
|
memoryMove(
|
||||||
|
&event->listenerArray[index],
|
||||||
|
&event->listenerArray[index + 1],
|
||||||
|
sizeof(eventlistener_t) * (event->listenerCount - index - 1)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
event->listenerCount--;
|
||||||
|
}
|
||||||
|
|
||||||
|
void eventInvoke(event_t *event, const void *eventParams) {
|
||||||
|
assertNotNull(event, "Event cannot be NULL");
|
||||||
|
|
||||||
|
if(event->listenerCount == 0) return;
|
||||||
|
|
||||||
|
event->isInvoking = true;
|
||||||
|
|
||||||
|
uint16_t i = 0;
|
||||||
|
eventdata_t data ={
|
||||||
|
.event = event,
|
||||||
|
.eventParams = eventParams,
|
||||||
|
};
|
||||||
|
|
||||||
|
do {
|
||||||
|
data.user = event->listenerArray[i].user;
|
||||||
|
event->listenerArray[i].callback(&data);
|
||||||
|
i++;
|
||||||
|
} while(i < event->listenerCount);
|
||||||
|
|
||||||
|
event->isInvoking = false;
|
||||||
|
}
|
||||||
79
src/event/event.h
Normal file
79
src/event/event.h
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
/**
|
||||||
|
* 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 event_s event_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
void *user;
|
||||||
|
const void *eventParams;
|
||||||
|
const event_t *event;
|
||||||
|
} eventdata_t;
|
||||||
|
|
||||||
|
typedef void (*eventcallback_t)(eventdata_t *data);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
eventcallback_t callback;
|
||||||
|
void *user;
|
||||||
|
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 callback The callback function to invoke.
|
||||||
|
* @param user User data 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
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoke an event, calling all subscribed listeners.
|
||||||
|
*
|
||||||
|
* @param event The event to invoke.
|
||||||
|
* @param eventParams Parameters to pass to the event listeners.
|
||||||
|
*/
|
||||||
|
void eventInvoke(event_t *event, const void *eventParams);
|
||||||
29
src/script/module/moduletime.h
Normal file
29
src/script/module/moduletime.h
Normal file
@@ -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/scriptcontext.h"
|
||||||
|
#include "time/time.h"
|
||||||
|
|
||||||
|
int moduleTimeGetDelta(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL");
|
||||||
|
lua_pushnumber(L, TIME.delta);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleTimeGetTime(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL");
|
||||||
|
lua_pushnumber(L, TIME.time);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void moduleTime(scriptcontext_t *ctx) {
|
||||||
|
assertNotNull(ctx, "Script context cannot be NULL");
|
||||||
|
|
||||||
|
scriptContextRegFunc(ctx, "timeGetDelta", moduleTimeGetDelta);
|
||||||
|
scriptContextRegFunc(ctx, "timeGetTime", moduleTimeGetTime);
|
||||||
|
}
|
||||||
@@ -12,6 +12,7 @@
|
|||||||
#include "script/module/modulescene.h"
|
#include "script/module/modulescene.h"
|
||||||
#include "script/module/moduleitem.h"
|
#include "script/module/moduleitem.h"
|
||||||
#include "script/module/modulelocale.h"
|
#include "script/module/modulelocale.h"
|
||||||
|
#include "script/module/moduletime.h"
|
||||||
|
|
||||||
const scriptmodule_t SCRIPT_MODULE_LIST[] = {
|
const scriptmodule_t SCRIPT_MODULE_LIST[] = {
|
||||||
{ .name = "system", .callback = moduleSystem },
|
{ .name = "system", .callback = moduleSystem },
|
||||||
@@ -20,6 +21,7 @@ const scriptmodule_t SCRIPT_MODULE_LIST[] = {
|
|||||||
{ .name = "scene", .callback = moduleScene },
|
{ .name = "scene", .callback = moduleScene },
|
||||||
{ .name = "item", .callback = moduleItem },
|
{ .name = "item", .callback = moduleItem },
|
||||||
{ .name = "locale", .callback = moduleLocale },
|
{ .name = "locale", .callback = moduleLocale },
|
||||||
|
{ .name = "time", .callback = moduleTime },
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SCRIPT_MODULE_COUNT ( \
|
#define SCRIPT_MODULE_COUNT ( \
|
||||||
|
|||||||
Reference in New Issue
Block a user