diff --git a/src/api.h b/src/api.h index 1ee2d87d..dcd1dff3 100644 --- a/src/api.h +++ b/src/api.h @@ -1,5 +1,6 @@ #include "luax.h" #include "data/blob.h" +#include "event/event.h" #include "graphics/mesh.h" #include "math/math.h" #include "math/randomGenerator.h" @@ -111,3 +112,5 @@ void luax_setvertex(lua_State* L, int index, VertexPointer* vertex, VertexFormat int luax_readtransform(lua_State* L, int index, mat4 transform, int scaleComponents); Blob* luax_readblob(lua_State* L, int index, const char* debug); Seed luax_checkrandomseed(lua_State* L, int index); +void luax_checkvariant(lua_State* L, int index, Variant* variant); +int luax_pushvariant(lua_State* L, Variant* variant); diff --git a/src/api/event.c b/src/api/event.c index 722eaac2..1136f9cb 100644 --- a/src/api/event.c +++ b/src/api/event.c @@ -14,6 +14,53 @@ const char* EventTypes[] = { static _Thread_local int pollRef; +void luax_checkvariant(lua_State* L, int index, Variant* variant) { + int type = lua_type(L, index); + switch (type) { + case LUA_TNIL: + variant->type = TYPE_NIL; + break; + + case LUA_TBOOLEAN: + variant->type = TYPE_BOOLEAN; + variant->value.boolean = lua_toboolean(L, index); + break; + + case LUA_TNUMBER: + variant->type = TYPE_NUMBER; + variant->value.number = lua_tonumber(L, index); + break; + + case LUA_TSTRING: + variant->type = TYPE_STRING; + size_t length; + const char* string = lua_tolstring(L, index, &length); + variant->value.string = malloc(length + 1); + strcpy(variant->value.string, string); + break; + + case LUA_TUSERDATA: + variant->type = TYPE_OBJECT; + variant->value.ref = lua_touserdata(L, index); + lovrRetain(variant->value.ref); + break; + + default: + lovrThrow("Bad type for Channel:push: %s", lua_typename(L, type)); + return; + } +} + +int luax_pushvariant(lua_State* L, Variant* variant) { + switch (variant->type) { + case TYPE_NIL: lua_pushnil(L); return 1; + case TYPE_BOOLEAN: lua_pushboolean(L, variant->value.boolean); return 1; + case TYPE_NUMBER: lua_pushnumber(L, variant->value.number); return 1; + case TYPE_STRING: lua_pushstring(L, variant->value.string); free(variant->value.string); return 1; + case TYPE_OBJECT: luax_pushobject(L, variant->value.ref); lovrRelease(variant->value.ref); return 1; + } +} + static int nextEvent(lua_State* L) { Event event; @@ -21,7 +68,11 @@ static int nextEvent(lua_State* L) { return 0; } - lua_pushstring(L, EventTypes[event.type]); + if (event.type == EVENT_CUSTOM) { + lua_pushstring(L, event.data.custom.name); + } else { + lua_pushstring(L, EventTypes[event.type]); + } switch (event.type) { case EVENT_QUIT: @@ -57,6 +108,12 @@ static int nextEvent(lua_State* L) { lua_pushstring(L, ControllerButtons[event.data.controller.button]); return 3; + case EVENT_CUSTOM: + for (int i = 0; i < event.data.custom.count; i++) { + luax_pushvariant(L, &event.data.custom.data[i]); + } + return event.data.custom.count + 1; + default: return 1; } @@ -90,47 +147,15 @@ int l_lovrEventPump(lua_State* L) { } int l_lovrEventPush(lua_State* L) { - EventType type = luaL_checkoption(L, 1, NULL, EventTypes); - EventData data; - - switch (type) { - case EVENT_QUIT: - if (lua_type(L, 2) == LUA_TSTRING) { - data.quit.restart = lua_toboolean(L, 2); - } else { - data.quit.exitCode = luaL_optint(L, 2, 0); - } - break; - - case EVENT_FOCUS: - case EVENT_MOUNT: - data.boolean.value = lua_toboolean(L, 2); - break; - -#ifdef EMSCRIPTEN - case EVENT_THREAD_ERROR: - break; -#else - case EVENT_THREAD_ERROR: - data.thread.thread = luax_checktype(L, 2, Thread); - data.thread.error = luaL_checkstring(L, 3); - break; -#endif - - case EVENT_CONTROLLER_ADDED: - case EVENT_CONTROLLER_REMOVED: - data.controller.controller = luax_checktype(L, 2, Controller); - break; - - case EVENT_CONTROLLER_PRESSED: - case EVENT_CONTROLLER_RELEASED: - data.controller.controller = luax_checktype(L, 2, Controller); - data.controller.button = luaL_checkoption(L, 3, NULL, ControllerButtons); - break; + CustomEvent eventData; + const char* name = luaL_checkstring(L, 1); + strncpy(eventData.name, name, MAX_EVENT_NAME_LENGTH - 1); + eventData.count = MIN(lua_gettop(L) - 1, 4); + for (int i = 0; i < eventData.count; i++) { + luax_checkvariant(L, 2 + i, &eventData.data[i]); } - Event event = { .type = type, .data = data }; - lovrEventPush(event); + lovrEventPush((Event) { .type = EVENT_CUSTOM, .data.custom = eventData }); return 0; } diff --git a/src/api/types/channel.c b/src/api/types/channel.c index 046cd91f..03e4484f 100644 --- a/src/api/types/channel.c +++ b/src/api/types/channel.c @@ -1,53 +1,6 @@ #include "api.h" #include "thread/channel.h" -static void luax_checkvariant(lua_State* L, int index, Variant* variant) { - int type = lua_type(L, index); - switch (type) { - case LUA_TNIL: - variant->type = TYPE_NIL; - break; - - case LUA_TBOOLEAN: - variant->type = TYPE_BOOLEAN; - variant->value.boolean = lua_toboolean(L, index); - break; - - case LUA_TNUMBER: - variant->type = TYPE_NUMBER; - variant->value.number = lua_tonumber(L, index); - break; - - case LUA_TSTRING: - variant->type = TYPE_STRING; - size_t length; - const char* string = lua_tolstring(L, index, &length); - variant->value.string = malloc(length + 1); - strcpy(variant->value.string, string); - break; - - case LUA_TUSERDATA: - variant->type = TYPE_OBJECT; - variant->value.ref = lua_touserdata(L, index); - lovrRetain(variant->value.ref); - break; - - default: - lovrThrow("Bad type for Channel:push: %s", lua_typename(L, type)); - return; - } -} - -static int luax_pushvariant(lua_State* L, Variant* variant) { - switch (variant->type) { - case TYPE_NIL: lua_pushnil(L); return 1; - case TYPE_BOOLEAN: lua_pushboolean(L, variant->value.boolean); return 1; - case TYPE_NUMBER: lua_pushnumber(L, variant->value.number); return 1; - case TYPE_STRING: lua_pushstring(L, variant->value.string); free(variant->value.string); return 1; - case TYPE_OBJECT: luax_pushobject(L, variant->value.ref); lovrRelease(variant->value.ref); return 1; - } -} - static void luax_checktimeout(lua_State* L, int index, double* timeout) { switch (lua_type(L, index)) { case LUA_TNONE: diff --git a/src/event/event.h b/src/event/event.h index 6ac506b5..efa695b6 100644 --- a/src/event/event.h +++ b/src/event/event.h @@ -7,6 +7,8 @@ #pragma once +#define MAX_EVENT_NAME_LENGTH 32 + typedef enum { EVENT_QUIT, EVENT_FOCUS, @@ -15,9 +17,32 @@ typedef enum { EVENT_CONTROLLER_ADDED, EVENT_CONTROLLER_REMOVED, EVENT_CONTROLLER_PRESSED, - EVENT_CONTROLLER_RELEASED + EVENT_CONTROLLER_RELEASED, + EVENT_CUSTOM } EventType; +typedef enum { + TYPE_NIL, + TYPE_BOOLEAN, + TYPE_NUMBER, + TYPE_STRING, + TYPE_OBJECT +} VariantType; + +typedef union { + bool boolean; + double number; + char* string; + Ref* ref; +} VariantValue; + +typedef struct { + VariantType type; + VariantValue value; +} Variant; + +typedef vec_t(Variant) vec_variant_t; + typedef struct { bool restart; int exitCode; @@ -39,6 +64,12 @@ typedef struct { ControllerButton button; } ControllerEvent; +typedef struct { + char name[MAX_EVENT_NAME_LENGTH]; + Variant data[4]; + int count; +} CustomEvent; + typedef union { QuitEvent quit; BoolEvent boolean; @@ -46,6 +77,7 @@ typedef union { ThreadEvent thread; #endif ControllerEvent controller; + CustomEvent custom; } EventData; typedef struct { diff --git a/src/thread/channel.h b/src/thread/channel.h index fe2843a9..4b32b9e0 100644 --- a/src/thread/channel.h +++ b/src/thread/channel.h @@ -1,3 +1,4 @@ +#include "event/event.h" #include "util.h" #include "lib/tinycthread/tinycthread.h" #include "lib/vec/vec.h" @@ -6,36 +7,14 @@ #pragma once -typedef enum { - TYPE_NIL, - TYPE_BOOLEAN, - TYPE_NUMBER, - TYPE_STRING, - TYPE_OBJECT -} VariantType; - -typedef union { - bool boolean; - double number; - char* string; - Ref* ref; -} VariantValue; - -typedef struct { - VariantType type; - VariantValue value; -} Variant; - -typedef vec_t(Variant) vec_variant_t; - -typedef struct { +struct Channel { Ref ref; mtx_t lock; cnd_t cond; vec_variant_t messages; uint64_t sent; uint64_t received; -} Channel; +}; Channel* lovrChannelCreate(); void lovrChannelDestroy(void* ref); diff --git a/src/thread/thread.c b/src/thread/thread.c index ea045182..5489cc79 100644 --- a/src/thread/thread.c +++ b/src/thread/thread.c @@ -1,4 +1,5 @@ #include "thread/thread.h" +#include "thread/channel.h" #include static ThreadState state; diff --git a/src/thread/thread.h b/src/thread/thread.h index 24cda67f..8c6595a7 100644 --- a/src/thread/thread.h +++ b/src/thread/thread.h @@ -1,4 +1,3 @@ -#include "thread/channel.h" #include "util.h" #include "lib/tinycthread/tinycthread.h" #include "lib/map/map.h" @@ -6,6 +5,8 @@ #pragma once +typedef struct Channel Channel; + typedef struct { bool initialized; map_void_t channels; @@ -23,7 +24,7 @@ typedef struct { void lovrThreadInit(); void lovrThreadDeinit(); -Channel* lovrThreadGetChannel(const char* name); +struct Channel* lovrThreadGetChannel(const char* name); Thread* lovrThreadCreate(int (*runner)(void*), const char* body); void lovrThreadDestroy(void* ref);