mirror of https://github.com/bjornbytes/lovr.git
Restart-without-quit support: lovr.event.quit("restart") and return-from-run() both support the string "restart" in place of an exit code. When this happens, the program reruns itself in a new, isolated environment. In Emscripten, no reboot occurs and the program only quits.
This commit is contained in:
parent
9ece4a3b09
commit
8052896b33
|
@ -15,7 +15,10 @@ static int nextEvent(lua_State* L) {
|
|||
switch (event.type) {
|
||||
case EVENT_QUIT: {
|
||||
lua_pushstring(L, "quit");
|
||||
lua_pushnumber(L, event.data.quit.exitCode);
|
||||
if (event.data.quit.restart)
|
||||
lua_pushliteral(L, "restart");
|
||||
else
|
||||
lua_pushnumber(L, event.data.quit.exitCode);
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
@ -125,11 +128,22 @@ int l_lovrEventPush(lua_State* L) {
|
|||
}
|
||||
|
||||
int l_lovrEventQuit(lua_State* L) {
|
||||
int exitCode = luaL_optint(L, 1, 0);
|
||||
lua_settop(L, 0);
|
||||
lua_pushliteral(L, "quit");
|
||||
lua_pushinteger(L, exitCode);
|
||||
return l_lovrEventPush(L);
|
||||
EventData data;
|
||||
|
||||
int argType = lua_type(L, 1);
|
||||
if (argType == LUA_TSTRING && 0 == strcmp("restart", lua_tostring(L, 1))) {
|
||||
data.quit.restart = true;
|
||||
data.quit.exitCode = 0;
|
||||
} else if (argType == LUA_TNUMBER || lua_isnoneornil(L, 1)) {
|
||||
data.quit.restart = false;
|
||||
data.quit.exitCode = luaL_optint(L, 1, 0);
|
||||
} else {
|
||||
return luaL_argerror (L, 1, "number, nil or the exact string 'restart' expected");
|
||||
}
|
||||
|
||||
EventType type = EVENT_QUIT;
|
||||
Event event = { .type = type, .data = data };
|
||||
lovrEventPush(event);
|
||||
}
|
||||
|
||||
const luaL_Reg lovrEvent[] = {
|
||||
|
|
|
@ -3,10 +3,16 @@
|
|||
#include "math/quat.h"
|
||||
#include "util.h"
|
||||
#include <stdlib.h>
|
||||
#include "lovr.h"
|
||||
|
||||
static AudioState state;
|
||||
static bool audioAlreadyInit = false;
|
||||
|
||||
void lovrAudioInit() {
|
||||
if (audioAlreadyInit) { // During a reload, bring down the audio device then recreate it
|
||||
lovrAudioDestroy();
|
||||
}
|
||||
|
||||
ALCdevice* device = alcOpenDevice(NULL);
|
||||
lovrAssert(device, "Unable to open default audio device");
|
||||
|
||||
|
@ -31,7 +37,10 @@ void lovrAudioInit() {
|
|||
vec3_set(state.position, 0, 0, 0);
|
||||
vec3_set(state.velocity, 0, 0, 0);
|
||||
|
||||
atexit(lovrAudioDestroy);
|
||||
if (!audioAlreadyInit) {
|
||||
atexit(lovrAudioDestroy);
|
||||
audioAlreadyInit = true;
|
||||
}
|
||||
}
|
||||
|
||||
void lovrAudioDestroy() {
|
||||
|
|
|
@ -3,12 +3,18 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
static EventState state;
|
||||
bool eventAlreadyInit = false;
|
||||
|
||||
void lovrEventInit() {
|
||||
if (eventAlreadyInit)
|
||||
lovrEventDestroy();
|
||||
vec_init(&state.pumps);
|
||||
vec_init(&state.events);
|
||||
lovrEventAddPump(glfwPollEvents);
|
||||
atexit(lovrEventDestroy);
|
||||
if (!eventAlreadyInit) {
|
||||
atexit(lovrEventDestroy);
|
||||
eventAlreadyInit = true;
|
||||
}
|
||||
}
|
||||
|
||||
void lovrEventDestroy() {
|
||||
|
|
|
@ -14,6 +14,7 @@ typedef enum {
|
|||
} EventType;
|
||||
|
||||
typedef struct {
|
||||
bool restart;
|
||||
int exitCode;
|
||||
} QuitEvent;
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <physfs.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "lovr.h"
|
||||
#ifdef __APPLE__
|
||||
#include <mach-o/dyld.h>
|
||||
#endif
|
||||
|
@ -20,7 +21,13 @@
|
|||
|
||||
static FilesystemState state;
|
||||
|
||||
bool filesystemAlreadyInit = false;
|
||||
|
||||
void lovrFilesystemInit(const char* arg0, const char* arg1) {
|
||||
if (filesystemAlreadyInit) // Do not change settings during a reload, and don't try to initialize PhysFS twice
|
||||
return;
|
||||
filesystemAlreadyInit = true;
|
||||
|
||||
if (!PHYSFS_init(arg0)) {
|
||||
lovrThrow("Could not initialize filesystem: %s", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "lovr.h"
|
||||
|
||||
static GraphicsState state;
|
||||
|
||||
|
@ -164,8 +165,16 @@ void lovrGraphicsPrepare(Material* material, float* pose) {
|
|||
lovrShaderBind(shader);
|
||||
}
|
||||
|
||||
static bool graphicsAlreadyInit = false;
|
||||
|
||||
void lovrGraphicsCreateWindow(int w, int h, bool fullscreen, int msaa, const char* title, const char* icon) {
|
||||
lovrAssert(!state.window, "Window is already created");
|
||||
if (graphicsAlreadyInit) {
|
||||
lovrGraphicsReset();
|
||||
return;
|
||||
} else {
|
||||
lovrAssert(!state.window, "Window is already created");
|
||||
graphicsAlreadyInit = true;
|
||||
}
|
||||
|
||||
#ifdef EMSCRIPTEN
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
|
||||
|
|
|
@ -7,6 +7,7 @@ void lovrControllerDestroy(const Ref* ref) {
|
|||
}
|
||||
|
||||
static HeadsetInterface* headset = NULL;
|
||||
static bool headsetAlreadyInit = false;
|
||||
|
||||
void lovrHeadsetInit(HeadsetDriver* drivers, int count) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
|
@ -28,9 +29,10 @@ void lovrHeadsetInit(HeadsetDriver* drivers, int count) {
|
|||
}
|
||||
}
|
||||
|
||||
if (headset) {
|
||||
if (!headsetAlreadyInit && headset) {
|
||||
headset->init();
|
||||
atexit(lovrHeadsetDestroy);
|
||||
headsetAlreadyInit = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "lualib.h"
|
||||
#include "lauxlib.h"
|
||||
#include <enet/enet.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define check_host(l, idx)\
|
||||
*(ENetHost**)luaL_checkudata(l, idx, "enet_host")
|
||||
|
@ -768,9 +769,14 @@ static const struct luaL_Reg enet_peer_funcs [] = {
|
|||
{NULL, NULL}
|
||||
};
|
||||
|
||||
static bool enitAlreadyInit = false;
|
||||
|
||||
int luaopen_enet(lua_State *l) {
|
||||
enet_initialize();
|
||||
atexit(enet_deinitialize);
|
||||
if (!enitAlreadyInit) {
|
||||
atexit(enet_deinitialize);
|
||||
enitAlreadyInit = true;
|
||||
}
|
||||
|
||||
// create metatables
|
||||
luaL_newmetatable(l, "enet_host");
|
||||
|
|
30
src/lovr.c
30
src/lovr.c
|
@ -63,6 +63,8 @@ static int lovrSetConf(lua_State* L) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool glfwAlreadyInit = false;
|
||||
|
||||
void lovrInit(lua_State* L, int argc, char** argv) {
|
||||
if (argc > 1 && strcmp(argv[1], "--version") == 0) {
|
||||
printf("LOVR %d.%d.%d (%s)\n", LOVR_VERSION_MAJOR, LOVR_VERSION_MINOR, LOVR_VERSION_PATCH, LOVR_VERSION_ALIAS);
|
||||
|
@ -72,9 +74,10 @@ void lovrInit(lua_State* L, int argc, char** argv) {
|
|||
glfwSetTime(0);
|
||||
glfwSetErrorCallback(onGlfwError);
|
||||
|
||||
if (!glfwInit()) {
|
||||
if (!glfwAlreadyInit && !glfwInit()) {
|
||||
lovrThrow("Error initializing glfw");
|
||||
}
|
||||
glfwAlreadyInit = true;
|
||||
|
||||
// arg global
|
||||
lua_newtable(L);
|
||||
|
@ -141,7 +144,7 @@ static void emscriptenLoop(void* arg) {
|
|||
lua_call(L, 0, 0);
|
||||
}
|
||||
|
||||
void lovrRun(lua_State* L) {
|
||||
bool lovrRun(lua_State* L) {
|
||||
|
||||
// lovr.load
|
||||
lua_getglobal(L, "lovr");
|
||||
|
@ -158,9 +161,10 @@ void lovrRun(lua_State* L) {
|
|||
}
|
||||
|
||||
emscripten_set_main_loop_arg(emscriptenLoop, (void*) L, 0, 1);
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
void lovrRun(lua_State* L) {
|
||||
bool lovrRun(lua_State* L) {
|
||||
lovrCatch = malloc(sizeof(jmp_buf));
|
||||
|
||||
// Global error handler
|
||||
|
@ -175,7 +179,7 @@ void lovrRun(lua_State* L) {
|
|||
lua_pushstring(L, lovrErrorMessage);
|
||||
lua_pcall(L, 1, 1, 0);
|
||||
handleError(L, lua_tostring(L, -1));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// lovr.run()
|
||||
|
@ -187,9 +191,21 @@ void lovrRun(lua_State* L) {
|
|||
}
|
||||
|
||||
// Exit with return value from lovr.run
|
||||
int exitCode = luaL_optint(L, -1, 0);
|
||||
lua_pop(L, 2);
|
||||
int exitCode = 0;
|
||||
int returnType = lua_type(L, -1);
|
||||
bool reloading = false;
|
||||
if (returnType == LUA_TSTRING && 0 == strcmp("restart", lua_tostring(L, -1))) {
|
||||
reloading = true; // Treat "restart" as special
|
||||
} else if (returnType == LUA_TNUMBER || lua_isnoneornil(L, -1)) {
|
||||
exitCode = luaL_optint(L, -1, 0);
|
||||
} else {
|
||||
luaL_argerror (L, -1, "number or the exact string 'restart' expected");
|
||||
}
|
||||
|
||||
free(lovrCatch);
|
||||
lovrDestroy(exitCode);
|
||||
lovrCatch = NULL;
|
||||
if (!reloading)
|
||||
lovrDestroy(exitCode);
|
||||
return reloading;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "luax.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#define LOVR_VERSION_MAJOR 0
|
||||
#define LOVR_VERSION_MINOR 9
|
||||
|
@ -7,4 +8,4 @@
|
|||
|
||||
void lovrInit(lua_State* L, int argc, char** argv);
|
||||
void lovrDestroy(int exitCode);
|
||||
void lovrRun(lua_State* L);
|
||||
bool lovrRun(lua_State* L); // Returns true to request continue
|
||||
|
|
11
src/main.c
11
src/main.c
|
@ -1,11 +1,14 @@
|
|||
#include "lovr.h"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
lua_State* L = luaL_newstate();
|
||||
luaL_openlibs(L);
|
||||
bool reloading;
|
||||
do {
|
||||
lua_State* L = luaL_newstate();
|
||||
luaL_openlibs(L);
|
||||
|
||||
lovrInit(L, argc, argv);
|
||||
lovrRun(L);
|
||||
lovrInit(L, argc, argv);
|
||||
reloading = lovrRun(L);
|
||||
} while (reloading);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -3,14 +3,19 @@
|
|||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
static RandomGenerator* generator;
|
||||
bool mathAlreadyInit = false;
|
||||
|
||||
void lovrMathInit() {
|
||||
generator = lovrRandomGeneratorCreate();
|
||||
Seed seed = { .b64 = (uint64_t) time(0) };
|
||||
lovrRandomGeneratorSetSeed(generator, seed);
|
||||
atexit(lovrMathDestroy);
|
||||
if (!mathAlreadyInit) {
|
||||
atexit(lovrMathDestroy);
|
||||
mathAlreadyInit = true;
|
||||
}
|
||||
}
|
||||
|
||||
void lovrMathDestroy() {
|
||||
|
|
|
@ -28,9 +28,15 @@ static void raycastCallback(void* data, dGeomID a, dGeomID b) {
|
|||
}
|
||||
}
|
||||
|
||||
static bool odeAlreadyInit = false;
|
||||
|
||||
void lovrPhysicsInit() {
|
||||
if (odeAlreadyInit)
|
||||
return;
|
||||
|
||||
dInitODE();
|
||||
atexit(lovrPhysicsDestroy);
|
||||
odeAlreadyInit = true;
|
||||
}
|
||||
|
||||
void lovrPhysicsDestroy() {
|
||||
|
|
Loading…
Reference in New Issue