Overhaul lovr.event;

This commit is contained in:
bjorn 2016-11-28 22:59:27 -08:00
parent 40eeeabcff
commit e3c1dcfa54
8 changed files with 194 additions and 64 deletions

View File

@ -1,11 +1,53 @@
#include "event/event.h"
#include "lovr.h"
#include "glfw.h"
#include <stdlib.h>
void lovrEventPoll() {
glfwPollEvents();
static EventState state;
static void onClose(GLFWwindow* _window) {
if (_window == window) {
EventType type = EVENT_QUIT;
EventData data = { .quit = { 0 } };
Event event = { .type = type, .data = data };
lovrEventPush(event);
}
}
void lovrEventQuit(int exitCode) {
lovrDestroy(exitCode);
void lovrEventInit() {
vec_init(&state.pumps);
vec_init(&state.events);
lovrEventAddPump(glfwPollEvents);
glfwSetWindowCloseCallback(window, onClose);
}
void lovrEventDestroy() {
vec_deinit(&state.pumps);
vec_deinit(&state.events);
}
void lovrEventAddPump(EventPump pump) {
vec_push(&state.pumps, pump);
}
void lovrEventPump() {
int i; EventPump pump;
vec_foreach(&state.pumps, pump, i) {
pump();
}
}
void lovrEventPush(Event event) {
vec_insert(&state.events, 0, event);
}
Event* lovrEventPoll() {
if (state.events.length == 0) {
return NULL;
}
return &vec_pop(&state.events);
}
void lovrEventClear() {
vec_clear(&state.events);
}

View File

@ -1,2 +1,41 @@
void lovrEventPoll();
void lovrEventQuit(int exitCode);
#include <vendor/vec/vec.h>
#ifndef LOVR_EVENT_TYPES
#define LOVR_EVENT_TYPES
typedef enum {
EVENT_QUIT
} EventType;
typedef struct {
int exitCode;
} QuitEvent;
typedef union {
QuitEvent quit;
} EventData;
typedef struct {
EventType type;
EventData data;
} Event;
typedef void (*EventPump)(void);
typedef vec_t(EventPump) vec_pump_t;
typedef vec_t(Event) vec_event_t;
typedef struct {
vec_pump_t pumps;
vec_event_t events;
} EventState;
#endif
void lovrEventInit();
void lovrEventDestroy();
void lovrEventAddPump(void (*pump)(void));
void lovrEventPump();
void lovrEventPush(Event event);
Event* lovrEventPoll();
void lovrEventClear();

View File

@ -3,7 +3,11 @@
#include <stdio.h>
#include <stdlib.h>
void initGlfw(GLFWerrorfun onError, GLFWwindowclosefun onClose, void* userPointer) {
static void onError(int code, const char* description) {
error(description);
}
void initGlfw() {
glfwSetErrorCallback(onError);
if (!glfwInit()) {
@ -14,7 +18,6 @@ void initGlfw(GLFWerrorfun onError, GLFWwindowclosefun onClose, void* userPointe
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
//glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
window = glfwCreateWindow(800, 600, "Window", NULL, NULL);
@ -23,8 +26,6 @@ void initGlfw(GLFWerrorfun onError, GLFWwindowclosefun onClose, void* userPointe
error("Could not create window");
}
glfwSetWindowCloseCallback(window, onClose);
glfwSetWindowUserPointer(window, userPointer);
glfwMakeContextCurrent(window);
#ifdef _WIN32

View File

@ -8,4 +8,4 @@
GLFWwindow* window;
void initGlfw(GLFWerrorfun onError, GLFWwindowclosefun onClose, void* userPointer);
void initGlfw();

View File

@ -4,13 +4,27 @@
#include "lovr/graphics.h"
#include "lovr/headset.h"
#include "lovr/timer.h"
#include "glfw.h"
#include "util.h"
#include <stdlib.h>
void lovrInit(lua_State* L, int argc, char** argv) {
static int handleLuaError(lua_State* L) {
const char* message = luaL_checkstring(L, -1);
lua_getglobal(L, "lovr");
lua_getfield(L, -1, "errhand");
// Set up GLFW
initGlfw(lovrOnGlfwError, lovrOnClose, L);
if (lua_isfunction(L, -1)) {
lua_pushstring(L, message);
lua_call(L, 1, 0);
} else {
error(message);
}
return 0;
}
void lovrInit(lua_State* L, int argc, char** argv) {
initGlfw();
// arg global
lua_newtable(L);
@ -71,10 +85,24 @@ void lovrInit(lua_State* L, int argc, char** argv) {
"lovr.filesystem.setIdentity(conf.identity or 'default') "
"lovr.handlers = setmetatable({ "
" quit = function() end "
"}, { "
" __index = function(self, event) "
" error('Unknown event: ', event) "
" end "
"}) "
"function lovr.run() "
" if lovr.load then lovr.load() end "
" while true do "
" lovr.event.poll() "
" lovr.event.pump() "
" for name, a, b, c, d in lovr.event.poll() do "
" if name == 'quit' and (not lovr.quit or not lovr.quit()) then "
" return a "
" end "
" lovr.handlers[name](a, b, c, d) "
" end "
" local dt = lovr.timer.step() "
" if lovr.update then lovr.update(dt) end "
" lovr.graphics.clear() "
@ -93,7 +121,7 @@ void lovrInit(lua_State* L, int argc, char** argv) {
"function lovr.errhand(message, layer) "
" local stackTrace = debug.traceback('Error: ' .. tostring(message), 1 + (layer or 1)) "
" print((stackTrace:gsub('\\n[^\\n]+$', ''))) "
" print((stackTrace:gsub('\\n[^\\n]+$', ''):gsub('stack traceback', 'Stack'))) "
"end "
"if lovr.filesystem.isFile('main.lua') then "
@ -106,7 +134,7 @@ void lovrInit(lua_State* L, int argc, char** argv) {
error("Unable to bootstrap LOVR: %s", message);
}
lua_atpanic(L, lovrOnLuaError);
lua_atpanic(L, handleLuaError);
}
void lovrDestroy(int exitCode) {
@ -119,44 +147,9 @@ void lovrRun(lua_State* L) {
// lovr.run()
lua_getglobal(L, "lovr");
lua_getfield(L, -1, "run");
lua_call(L, 0, 0);
}
int lovrOnLuaError(lua_State* L) {
const char* message = luaL_checkstring(L, -1);
lua_getglobal(L, "lovr");
lua_getfield(L, -1, "errhand");
if (lua_isfunction(L, -1)) {
lua_pushstring(L, message);
lua_call(L, 1, 0);
} else {
error(message);
}
return 0;
}
void lovrOnGlfwError(int code, const char* description) {
error(description);
}
void lovrOnClose(GLFWwindow* _window) {
if (_window == window) {
lua_State* L = (lua_State*) glfwGetWindowUserPointer(window);
// lovr.quit()
lua_getglobal(L, "lovr");
lua_getfield(L, -1, "quit");
if (!lua_isnil(L, -1)) {
lua_call(L, 0, 0);
}
if (glfwWindowShouldClose(window)) {
glfwDestroyWindow(window);
lovrDestroy(0);
}
}
lua_call(L, 0, 1);
// Exit with return value from lovr.run
int exitCode = luaL_optint(L, -1, 0);
lovrDestroy(exitCode);
}

View File

@ -1,4 +1,3 @@
#include "glfw.h"
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
@ -7,5 +6,3 @@ void lovrInit(lua_State* L, int argc, char** argv);
void lovrDestroy(int exitCode);
void lovrRun(lua_State* L);
int lovrOnLuaError(lua_State* L);
void lovrOnGlfwError(int code, const char* description);
void lovrOnClose(GLFWwindow* window);

View File

@ -1,8 +1,30 @@
#include "lovr/event.h"
#include "event/event.h"
#include "util.h"
static int nextEvent(lua_State* L) {
Event* event = lovrEventPoll();
if (!event) {
return 0;
}
switch (event->type) {
case EVENT_QUIT:
lua_pushstring(L, "quit");
lua_pushnumber(L, event->data.quit.exitCode);
return 2;
default:
return 0;
}
}
const luaL_Reg lovrEvent[] = {
{ "clear", l_lovrEventClear },
{ "poll", l_lovrEventPoll },
{ "pump", l_lovrEventPump },
{ "push", l_lovrEventPush },
{ "quit", l_lovrEventQuit },
{ NULL, NULL }
};
@ -10,16 +32,46 @@ const luaL_Reg lovrEvent[] = {
int l_lovrEventInit(lua_State* L) {
lua_newtable(L);
luaL_register(L, NULL, lovrEvent);
map_init(&EventTypes);
map_set(&EventTypes, "quit", EVENT_QUIT);
lovrEventInit();
return 1;
}
int l_lovrEventClear(lua_State* L) {
lovrEventClear();
return 0;
}
int l_lovrEventPoll(lua_State* L) {
lovrEventPoll();
lua_pushcclosure(L, nextEvent, 0);
return 1;
}
int l_lovrEventPump(lua_State* L) {
lovrEventPump();
return 0;
}
int l_lovrEventPush(lua_State* L) {
EventType type = *(EventType*) luax_checkenum(L, 1, &EventTypes, "event type");
EventData data;
switch (type) {
case EVENT_QUIT:
data.quit.exitCode = luaL_optint(L, 2, 0);
break;
}
Event event = { .type = type, .data = data };
lovrEventPush(event);
return 0;
}
int l_lovrEventQuit(lua_State* L) {
int exitCode = luaL_optint(L, 1, 0);
lovrEventQuit(exitCode);
return 0;
lua_settop(L, 0);
lua_pushliteral(L, "quit");
lua_pushinteger(L, exitCode);
return l_lovrEventPush(L);
}

View File

@ -1,8 +1,14 @@
#include "vendor/map/map.h"
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
map_int_t EventTypes;
extern const luaL_Reg lovrEvent[];
int l_lovrEventInit(lua_State* L);
int l_lovrEventClear(lua_State* L);
int l_lovrEventPoll(lua_State* L);
int l_lovrEventPump(lua_State* L);
int l_lovrEventPush(lua_State* L);
int l_lovrEventQuit(lua_State* L);