mirror of https://github.com/bjornbytes/lovr.git
Make modules more restartable;
Except headset. Screw you, headset.
This commit is contained in:
parent
9d42d7737a
commit
f5fa9a4e5c
|
@ -5,12 +5,9 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
static AudioState state;
|
||||
static bool audioAlreadyInit = false;
|
||||
|
||||
void lovrAudioInit() {
|
||||
if (audioAlreadyInit) { // During a reload, bring down the audio device then recreate it
|
||||
lovrAudioDestroy();
|
||||
}
|
||||
if (state.initialized) return;
|
||||
|
||||
ALCdevice* device = alcOpenDevice(NULL);
|
||||
lovrAssert(device, "Unable to open default audio device");
|
||||
|
@ -35,18 +32,16 @@ void lovrAudioInit() {
|
|||
quat_set(state.orientation, 0, 0, 0, -1);
|
||||
vec3_set(state.position, 0, 0, 0);
|
||||
vec3_set(state.velocity, 0, 0, 0);
|
||||
|
||||
if (!audioAlreadyInit) {
|
||||
atexit(lovrAudioDestroy);
|
||||
audioAlreadyInit = true;
|
||||
}
|
||||
state.initialized = true;
|
||||
}
|
||||
|
||||
void lovrAudioDestroy() {
|
||||
if (!state.initialized) return;
|
||||
alcMakeContextCurrent(NULL);
|
||||
alcDestroyContext(state.context);
|
||||
alcCloseDevice(state.device);
|
||||
vec_deinit(&state.sources);
|
||||
memset(&state, 0, sizeof(AudioState));
|
||||
}
|
||||
|
||||
void lovrAudioUpdate() {
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#pragma once
|
||||
|
||||
typedef struct {
|
||||
bool initialized;
|
||||
ALCdevice* device;
|
||||
ALCcontext* context;
|
||||
vec_void_t sources;
|
||||
|
|
|
@ -3,23 +3,21 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
static EventState state;
|
||||
bool eventAlreadyInit = false;
|
||||
|
||||
void lovrEventInit() {
|
||||
if (eventAlreadyInit)
|
||||
lovrEventDestroy();
|
||||
if (state.initialized) return;
|
||||
vec_init(&state.pumps);
|
||||
vec_init(&state.events);
|
||||
lovrEventAddPump(glfwPollEvents);
|
||||
if (!eventAlreadyInit) {
|
||||
atexit(lovrEventDestroy);
|
||||
eventAlreadyInit = true;
|
||||
}
|
||||
atexit(lovrEventDestroy);
|
||||
state.initialized = true;
|
||||
}
|
||||
|
||||
void lovrEventDestroy() {
|
||||
if (!state.initialized) return;
|
||||
vec_deinit(&state.pumps);
|
||||
vec_deinit(&state.events);
|
||||
memset(&state, 0, sizeof(EventState));
|
||||
}
|
||||
|
||||
void lovrEventAddPump(EventPump pump) {
|
||||
|
|
|
@ -68,6 +68,7 @@ typedef vec_t(EventPump) vec_pump_t;
|
|||
typedef vec_t(Event) vec_event_t;
|
||||
|
||||
typedef struct {
|
||||
bool initialized;
|
||||
vec_pump_t pumps;
|
||||
vec_event_t events;
|
||||
} EventState;
|
||||
|
|
|
@ -20,12 +20,9 @@
|
|||
|
||||
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 (state.initialized) return;
|
||||
state.initialized = true;
|
||||
|
||||
if (!PHYSFS_init(arg0)) {
|
||||
lovrThrow("Could not initialize filesystem: %s", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
|
@ -43,23 +40,22 @@ void lovrFilesystemInit(const char* arg0, const char* arg1) {
|
|||
if (arg1) {
|
||||
strncpy(state.source, arg1, LOVR_PATH_MAX);
|
||||
if (!lovrFilesystemMount(state.source, NULL, 1)) {
|
||||
goto mounted;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
free(state.source);
|
||||
state.source = NULL;
|
||||
}
|
||||
|
||||
mounted:
|
||||
atexit(lovrFilesystemDestroy);
|
||||
}
|
||||
|
||||
void lovrFilesystemDestroy() {
|
||||
if (!state.initialized) return;
|
||||
free(state.source);
|
||||
free(state.savePathFull);
|
||||
free(state.savePathRelative);
|
||||
PHYSFS_deinit();
|
||||
memset(&state, 0, sizeof(FilesystemState));
|
||||
}
|
||||
|
||||
int lovrFilesystemCreateDirectory(const char* path) {
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
typedef int getDirectoryItemsCallback(void* userdata, const char* dir, const char* file);
|
||||
|
||||
typedef struct {
|
||||
bool initialized;
|
||||
char* source;
|
||||
const char* identity;
|
||||
char* savePathRelative;
|
||||
|
|
|
@ -40,6 +40,7 @@ void lovrGraphicsInit() {
|
|||
}
|
||||
|
||||
void lovrGraphicsDestroy() {
|
||||
if (!state.initialized) return;
|
||||
lovrGraphicsSetShader(NULL);
|
||||
lovrGraphicsSetFont(NULL);
|
||||
for (int i = 0; i < DEFAULT_SHADER_COUNT; i++) {
|
||||
|
@ -53,6 +54,7 @@ void lovrGraphicsDestroy() {
|
|||
glDeleteBuffers(1, &state.streamIBO);
|
||||
vec_deinit(&state.streamData);
|
||||
vec_deinit(&state.streamIndices);
|
||||
memset(&state, 0, sizeof(GraphicsState));
|
||||
}
|
||||
|
||||
void lovrGraphicsReset() {
|
||||
|
@ -185,15 +187,13 @@ 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) {
|
||||
if (graphicsAlreadyInit) {
|
||||
lovrAssert(!state.window, "Window is already created");
|
||||
|
||||
if (!state.initialized && (state.window = glfwGetCurrentContext()) != NULL) {
|
||||
lovrGraphicsReset();
|
||||
state.initialized = true;
|
||||
return;
|
||||
} else {
|
||||
lovrAssert(!state.window, "Window is already created");
|
||||
graphicsAlreadyInit = true;
|
||||
}
|
||||
|
||||
#ifdef EMSCRIPTEN
|
||||
|
@ -257,7 +257,7 @@ void lovrGraphicsCreateWindow(int w, int h, bool fullscreen, int msaa, const cha
|
|||
vec_init(&state.streamData);
|
||||
vec_init(&state.streamIndices);
|
||||
lovrGraphicsReset();
|
||||
atexit(lovrGraphicsDestroy);
|
||||
state.initialized = true;
|
||||
}
|
||||
|
||||
int lovrGraphicsGetWidth() {
|
||||
|
|
|
@ -95,6 +95,7 @@ typedef struct {
|
|||
} GraphicsStats;
|
||||
|
||||
typedef struct {
|
||||
bool initialized;
|
||||
GLFWwindow* window;
|
||||
Shader* defaultShaders[DEFAULT_SHADER_COUNT];
|
||||
DefaultShader defaultShader;
|
||||
|
|
17
src/lovr.c
17
src/lovr.c
|
@ -1,4 +1,21 @@
|
|||
#include "lovr.h"
|
||||
#include "audio/audio.h"
|
||||
#include "event/event.h"
|
||||
#include "filesystem/filesystem.h"
|
||||
#include "graphics/graphics.h"
|
||||
#include "math/math.h"
|
||||
#include "physics/physics.h"
|
||||
#include "timer/timer.h"
|
||||
|
||||
void lovrDestroy() {
|
||||
lovrAudioDestroy();
|
||||
lovrEventDestroy();
|
||||
lovrFilesystemDestroy();
|
||||
lovrGraphicsDestroy();
|
||||
lovrMathDestroy();
|
||||
lovrPhysicsDestroy();
|
||||
lovrTimerDestroy();
|
||||
}
|
||||
|
||||
const char* lovrGetOS() {
|
||||
#ifdef _WIN32
|
||||
|
|
|
@ -3,5 +3,6 @@
|
|||
#define LOVR_VERSION_PATCH 1
|
||||
#define LOVR_VERSION_ALIAS "Fluffy Cuttlefish"
|
||||
|
||||
void lovrDestroy();
|
||||
const char* lovrGetOS();
|
||||
void lovrGetVersion(int* major, int* minor, int* patch);
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
static int errorCount = 0;
|
||||
|
||||
static void destroy(int exitCode) {
|
||||
lovrDestroy();
|
||||
glfwTerminate();
|
||||
exit(exitCode);
|
||||
}
|
||||
|
@ -131,6 +132,7 @@ int main(int argc, char** argv) {
|
|||
int exitCode = 0;
|
||||
int returnType = lua_type(L, -1);
|
||||
if (returnType == LUA_TSTRING && 0 == strcmp("restart", lua_tostring(L, -1))) {
|
||||
lovrDestroy();
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,27 +3,25 @@
|
|||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
static RandomGenerator* generator;
|
||||
bool mathAlreadyInit = false;
|
||||
static MathState state;
|
||||
|
||||
void lovrMathInit() {
|
||||
generator = lovrRandomGeneratorCreate();
|
||||
if (state.initialized) return;
|
||||
state.generator = lovrRandomGeneratorCreate();
|
||||
Seed seed = { .b64 = (uint64_t) time(0) };
|
||||
lovrRandomGeneratorSetSeed(generator, seed);
|
||||
if (!mathAlreadyInit) {
|
||||
atexit(lovrMathDestroy);
|
||||
mathAlreadyInit = true;
|
||||
}
|
||||
lovrRandomGeneratorSetSeed(state.generator, seed);
|
||||
state.initialized = true;
|
||||
}
|
||||
|
||||
void lovrMathDestroy() {
|
||||
lovrRandomGeneratorDestroy(&generator->ref);
|
||||
if (!state.initialized) return;
|
||||
lovrRandomGeneratorDestroy(&state.generator->ref);
|
||||
memset(&state, 0, sizeof(MathState));
|
||||
}
|
||||
|
||||
RandomGenerator* lovrMathGetRandomGenerator() {
|
||||
return generator;
|
||||
return state.generator;
|
||||
}
|
||||
|
||||
void lovrMathOrientationToDirection(float angle, float ax, float ay, float az, vec3 v) {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "lib/vec/vec.h"
|
||||
#include "randomGenerator.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#pragma once
|
||||
|
||||
|
@ -12,6 +13,11 @@ typedef float* quat;
|
|||
typedef float* mat4;
|
||||
typedef vec_t(mat4) vec_mat4_t;
|
||||
|
||||
typedef struct {
|
||||
bool initialized;
|
||||
RandomGenerator* generator;
|
||||
} MathState;
|
||||
|
||||
void lovrMathInit();
|
||||
void lovrMathDestroy();
|
||||
RandomGenerator* lovrMathGetRandomGenerator();
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "physics.h"
|
||||
#include "math/quat.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
static void defaultNearCallback(void* data, dGeomID a, dGeomID b) {
|
||||
lovrWorldCollide((World*) data, dGeomGetData(a), dGeomGetData(b), -1, -1);
|
||||
|
@ -28,19 +29,18 @@ static void raycastCallback(void* data, dGeomID a, dGeomID b) {
|
|||
}
|
||||
}
|
||||
|
||||
static bool odeAlreadyInit = false;
|
||||
static bool initialized = false;
|
||||
|
||||
void lovrPhysicsInit() {
|
||||
if (odeAlreadyInit)
|
||||
return;
|
||||
|
||||
if (initialized) return;
|
||||
dInitODE();
|
||||
atexit(lovrPhysicsDestroy);
|
||||
odeAlreadyInit = true;
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
void lovrPhysicsDestroy() {
|
||||
if (!initialized) return;
|
||||
dCloseODE();
|
||||
initialized = false;
|
||||
}
|
||||
|
||||
World* lovrWorldCreate(float xg, float yg, float zg, bool allowSleep, const char** tags, int tagCount) {
|
||||
|
|
|
@ -6,12 +6,15 @@
|
|||
static ThreadState state;
|
||||
|
||||
void lovrThreadInit() {
|
||||
if (state.initialized) return;
|
||||
map_init(&state.channels);
|
||||
atexit(lovrThreadDeinit);
|
||||
state.initialized = true;
|
||||
}
|
||||
|
||||
void lovrThreadDeinit() {
|
||||
if (!state.initialized) return;
|
||||
map_deinit(&state.channels);
|
||||
state.initialized = false;
|
||||
}
|
||||
|
||||
Channel* lovrThreadGetChannel(const char* name) {
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#pragma once
|
||||
|
||||
typedef struct {
|
||||
bool initialized;
|
||||
map_void_t channels;
|
||||
} ThreadState;
|
||||
|
||||
|
|
|
@ -2,17 +2,21 @@
|
|||
#include "lib/glfw.h"
|
||||
#include "util.h"
|
||||
|
||||
static TimerState timerState;
|
||||
static TimerState state;
|
||||
|
||||
void lovrTimerInit() {
|
||||
timerState.tickIndex = 0;
|
||||
for (int i = 0; i < TICK_SAMPLES; i++) {
|
||||
timerState.tickBuffer[i] = 0.;
|
||||
}
|
||||
if (state.initialized) return;
|
||||
lovrTimerDestroy();
|
||||
state.initialized = true;
|
||||
}
|
||||
|
||||
void lovrTimerDestroy() {
|
||||
if (!state.initialized) return;
|
||||
memset(&state, 0, sizeof(TimerState));
|
||||
}
|
||||
|
||||
double lovrTimerGetDelta() {
|
||||
return timerState.dt;
|
||||
return state.dt;
|
||||
}
|
||||
|
||||
double lovrTimerGetTime() {
|
||||
|
@ -20,26 +24,26 @@ double lovrTimerGetTime() {
|
|||
}
|
||||
|
||||
double lovrTimerStep() {
|
||||
timerState.lastTime = timerState.time;
|
||||
timerState.time = glfwGetTime();
|
||||
timerState.dt = timerState.time - timerState.lastTime;
|
||||
timerState.tickSum -= timerState.tickBuffer[timerState.tickIndex];
|
||||
timerState.tickSum += timerState.dt;
|
||||
timerState.tickBuffer[timerState.tickIndex] = timerState.dt;
|
||||
timerState.averageDelta = timerState.tickSum / TICK_SAMPLES;
|
||||
timerState.fps = (int) (1 / (timerState.tickSum / TICK_SAMPLES) + .5);
|
||||
if (++timerState.tickIndex == TICK_SAMPLES) {
|
||||
timerState.tickIndex = 0;
|
||||
state.lastTime = state.time;
|
||||
state.time = glfwGetTime();
|
||||
state.dt = state.time - state.lastTime;
|
||||
state.tickSum -= state.tickBuffer[state.tickIndex];
|
||||
state.tickSum += state.dt;
|
||||
state.tickBuffer[state.tickIndex] = state.dt;
|
||||
state.averageDelta = state.tickSum / TICK_SAMPLES;
|
||||
state.fps = (int) (1 / (state.tickSum / TICK_SAMPLES) + .5);
|
||||
if (++state.tickIndex == TICK_SAMPLES) {
|
||||
state.tickIndex = 0;
|
||||
}
|
||||
return timerState.dt;
|
||||
return state.dt;
|
||||
}
|
||||
|
||||
double lovrTimerGetAverageDelta() {
|
||||
return timerState.averageDelta;
|
||||
return state.averageDelta;
|
||||
}
|
||||
|
||||
int lovrTimerGetFPS() {
|
||||
return timerState.fps;
|
||||
return state.fps;
|
||||
}
|
||||
|
||||
void lovrTimerSleep(double seconds) {
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
#include <stdbool.h>
|
||||
|
||||
#pragma once
|
||||
|
||||
#define TICK_SAMPLES 90
|
||||
|
||||
typedef struct {
|
||||
bool initialized;
|
||||
double lastTime;
|
||||
double time;
|
||||
double dt;
|
||||
|
@ -14,6 +17,7 @@ typedef struct {
|
|||
} TimerState;
|
||||
|
||||
void lovrTimerInit();
|
||||
void lovrTimerDestroy();
|
||||
double lovrTimerGetDelta();
|
||||
double lovrTimerGetTime();
|
||||
double lovrTimerStep();
|
||||
|
|
Loading…
Reference in New Issue