Skip to content

Commit c796fd9

Browse files
feat: add hot reload cmd line arg
1 parent f7d3c02 commit c796fd9

13 files changed

Lines changed: 159 additions & 79 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
data/
77
out/
88
out-temp/
9+
shader-temp/
910
user/
1011
game/
1112
app/

docs/changelog.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ away, please see git history for details.
77

88
- v0.5.1 (2025-XX-XX) add directory ops to FILE ext (v1.1.0)
99
fix string interning cleanup issue (v1.0.1)
10+
add "bHotReloadActive" to IO context (v1.1.0)
1011
- v0.5.0 (2025-06-17) new datatime extension (v1.0.0)
1112
new compression extension (v1.0.0)
1213
new pak file extension (v1.0.0)

docs/version.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ the API is complete. It just means we won't break what currently exists.
3636
* Data Registry v1.0.0 (pl.h)
3737
* Memory v1.0.2 (pl.h)
3838
* Extension Registry v1.1.0 (pl.h)
39-
* IO v1.0.1 (pl.h)
39+
* IO v1.1.0 (pl.h)
4040
* Window v1.0.0 (pl.h)
4141
* Library v1.0.2 (pl.h)
4242

editor/app.c

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,8 @@ pl_app_load(plApiRegistryI* ptApiRegistry, plAppData* ptAppData)
307307
gptVfs->mount_directory("/fonts", "../data/pilotlight-assets-master/fonts", PL_VFS_MOUNT_FLAGS_NONE);
308308
gptVfs->mount_directory("/environments", "../data/pilotlight-assets-master/environments", PL_VFS_MOUNT_FLAGS_NONE);
309309
gptVfs->mount_directory("/shaders", "../shaders", PL_VFS_MOUNT_FLAGS_NONE);
310-
gptVfs->mount_directory("/shaders-temp", "../out-temp", PL_VFS_MOUNT_FLAGS_NONE);
310+
gptVfs->mount_directory("/shader-temp", "../shader-temp", PL_VFS_MOUNT_FLAGS_NONE);
311+
gptFile->create_directory("../shader-temp");
311312

312313
// defaults
313314
ptAppData->tSelectedEntity.uData = UINT64_MAX;
@@ -336,12 +337,10 @@ pl_app_load(plApiRegistryI* ptApiRegistry, plAppData* ptAppData)
336337
},
337338
.apcDirectories = {
338339
"/shaders/",
339-
"/shaders-temp/",
340+
"/shader-temp/",
340341
},
341-
.pcCacheOutputDirectory = "/shaders-temp/",
342-
// .tFlags = PL_SHADER_FLAGS_AUTO_OUTPUT | PL_SHADER_FLAGS_INCLUDE_DEBUG | PL_SHADER_FLAGS_ALWAYS_COMPILE
343-
.tFlags = PL_SHADER_FLAGS_AUTO_OUTPUT | PL_SHADER_FLAGS_INCLUDE_DEBUG
344-
342+
.pcCacheOutputDirectory = "/shader-temp/",
343+
.tFlags = PL_SHADER_FLAGS_AUTO_OUTPUT | PL_SHADER_FLAGS_INCLUDE_DEBUG | PL_SHADER_FLAGS_ALWAYS_COMPILE
345344
};
346345
gptShader->initialize(&tDefaultShaderOptions);
347346

editor/editor.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,8 @@ pl_app_load(plApiRegistryI* ptApiRegistry, plAppData* ptAppData)
156156
gptVfs->mount_directory("/fonts", "../data/pilotlight-assets-master/fonts", PL_VFS_MOUNT_FLAGS_NONE);
157157
gptVfs->mount_directory("/environments", "../data/pilotlight-assets-master/environments", PL_VFS_MOUNT_FLAGS_NONE);
158158
gptVfs->mount_directory("/shaders", "../shaders", PL_VFS_MOUNT_FLAGS_NONE);
159-
gptVfs->mount_directory("/shaders-temp", "../out-temp", PL_VFS_MOUNT_FLAGS_NONE);
159+
gptVfs->mount_directory("/shader-temp", "../shader-temp", PL_VFS_MOUNT_FLAGS_NONE);
160+
gptFile->create_directory("../shader-temp");
160161

161162
// defaults
162163
ptAppData->tSelectedEntity.uData = UINT64_MAX;
@@ -182,8 +183,8 @@ pl_app_load(plApiRegistryI* ptApiRegistry, plAppData* ptAppData)
182183
static plShaderOptions tDefaultShaderOptions = PL_ZERO_INIT;
183184
tDefaultShaderOptions.apcIncludeDirectories[0] = "/shaders/";
184185
tDefaultShaderOptions.apcDirectories[0] = "/shaders/";
185-
tDefaultShaderOptions.apcDirectories[1] = "/shaders-temp/";
186-
tDefaultShaderOptions.pcCacheOutputDirectory = "/shaders-temp/";
186+
tDefaultShaderOptions.apcDirectories[1] = "/shader-temp/";
187+
tDefaultShaderOptions.pcCacheOutputDirectory = "/shader-temp/";
187188
tDefaultShaderOptions.tFlags = PL_SHADER_FLAGS_AUTO_OUTPUT | PL_SHADER_FLAGS_INCLUDE_DEBUG | PL_SHADER_FLAGS_ALWAYS_COMPILE;
188189
gptShader->initialize(&tDefaultShaderOptions);
189190

scripts/setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@
6969
lines.append(' "program": "${workspaceFolder}/out/pilot_light",')
7070

7171
lines.append(' "request": "launch",')
72-
lines.append(' "args": ["-a", "app"],')
72+
lines.append(' "args": ["-a", "app", "-hr"],')
7373
lines.append(' "stopAtEntry": false,')
7474
lines.append(' "cwd": "${workspaceFolder}/out/",')
7575
lines.append(' "environment": []')

src/pl.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ Index of this file:
3434

3535
#define plExtensionRegistryI_version {1, 1, 0}
3636
#define plMemoryI_version {1, 0, 2}
37-
#define plIOI_version {1, 0, 1}
37+
#define plIOI_version {1, 1, 0}
3838
#define plDataRegistryI_version {1, 0, 0}
3939
#define plWindowI_version {1, 0, 0}
4040
#define plLibraryI_version {1, 0, 2}
@@ -491,12 +491,13 @@ typedef struct _plIO
491491
// Input/Output
492492
//------------------------------------------------------------------
493493

494-
bool bRunning;
494+
bool bRunning;
495495

496496
//------------------------------------------------------------------
497497
// Output
498498
//------------------------------------------------------------------
499499

500+
bool bHotReloadActive;
500501
double dTime;
501502
float fFrameRate; // rough estimate(rolling average of fDeltaTime over 120 frames)
502503
bool bViewportSizeChanged;

src/pl_internal.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ Index of this file:
3131
// [SECTION] globals
3232
//-----------------------------------------------------------------------------
3333

34+
// options
35+
bool gbHotReloadActive = false;
36+
3437
// general
3538
plSharedLibrary* gptAppLibrary = NULL;
3639
void* gpUserData = NULL;

src/pl_main_glfw.cpp

Lines changed: 41 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,10 @@ int main(int argc, char *argv[])
201201
pcAppName = argv[i + 1];
202202
i++;
203203
}
204+
else if(strcmp(argv[i], "-hr") == 0 || strcmp(argv[i], "--hot-reload") == 0)
205+
{
206+
gbHotReloadActive = true;
207+
}
204208
else if(strcmp(argv[i], "--version") == 0)
205209
{
206210
printf("\nPilot Light - light weight game engine\n\n");
@@ -257,6 +261,8 @@ int main(int argc, char *argv[])
257261
printf("--apis %s\n", "Displays embedded apis.");
258262
printf("-a <app> %s\n", "Sets app to load. Default is 'editor'.");
259263
printf("--app <app> %s\n", "Sets app to load. Default is 'editor'.");
264+
printf("-hr %s\n", "Activates hot reloading.");
265+
printf("--hot-reload %s\n", "Activates hot reloading.");
260266
return 0;
261267
}
262268
}
@@ -281,6 +287,7 @@ int main(int argc, char *argv[])
281287
pl__load_core_apis();
282288

283289
gptIOCtx = gptIOI->get_io();
290+
gptIOCtx->bHotReloadActive = gbHotReloadActive;
284291

285292
// clipboard
286293
gptIOCtx->set_clipboard_text_fn = [](void* pUnused, const char* text) { glfwSetClipboardString(nullptr, text); };
@@ -448,7 +455,7 @@ int main(int argc, char *argv[])
448455
glfwPollEvents();
449456

450457
// reload library
451-
if(ptLibraryApi->has_changed(gptAppLibrary))
458+
if(gbHotReloadActive && ptLibraryApi->has_changed(gptAppLibrary))
452459
{
453460
pl_reload_library(gptAppLibrary);
454461
#ifdef _WIN32
@@ -1111,15 +1118,18 @@ pl_load_library(plLibraryDesc tDesc, plSharedLibrary** pptLibraryOut)
11111118
if(*pptLibraryOut == NULL)
11121119
{
11131120

1114-
DWORD dwAttrib = GetFileAttributes(pcCacheDirectory);
1115-
1116-
if(dwAttrib != INVALID_FILE_ATTRIBUTES && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY))
1117-
{
1118-
// do nothing
1119-
}
1120-
else
1121+
if(gbHotReloadActive)
11211122
{
1122-
CreateDirectoryA(pcCacheDirectory, NULL);
1123+
DWORD dwAttrib = GetFileAttributes(pcCacheDirectory);
1124+
1125+
if(dwAttrib != INVALID_FILE_ATTRIBUTES && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY))
1126+
{
1127+
// do nothing
1128+
}
1129+
else
1130+
{
1131+
CreateDirectoryA(pcCacheDirectory, NULL);
1132+
}
11231133
}
11241134

11251135
*pptLibraryOut = (plSharedLibrary*)PL_ALLOC(sizeof(plSharedLibrary));
@@ -1135,10 +1145,14 @@ pl_load_library(plLibraryDesc tDesc, plSharedLibrary** pptLibraryOut)
11351145
strncpy(ptLibrary->acFileExtension, gpcLibraryExtension, 16);
11361146

11371147
pl_sprintf(ptLibrary->acPath, "%s%s.%s", ptLibrary->acDirectory, ptLibrary->acName, ptLibrary->acFileExtension);
1138-
pl_sprintf(ptLibrary->acLockFile, "%s%s", ptLibrary->acDirectory, pcLockFile);
1139-
pl_sprintf(ptLibrary->acTransitionalPath, "%s/%s_", pcCacheDirectory, ptLibrary->acName);
1148+
1149+
if(gbHotReloadActive)
1150+
{
1151+
pl_sprintf(ptLibrary->acLockFile, "%s%s", ptLibrary->acDirectory, pcLockFile);
1152+
pl_sprintf(ptLibrary->acTransitionalPath, "%s/%s_", pcCacheDirectory, ptLibrary->acName);
1153+
}
11401154

1141-
if(!(tDesc.tFlags & PL_LIBRARY_FLAGS_RELOADABLE))
1155+
if(!gbHotReloadActive || !(tDesc.tFlags & PL_LIBRARY_FLAGS_RELOADABLE))
11421156
{
11431157

11441158
char acTemporaryName[PL_MAX_PATH_LENGTH] = {0};
@@ -1164,7 +1178,7 @@ pl_load_library(plLibraryDesc tDesc, plSharedLibrary** pptLibraryOut)
11641178
ptLibrary = *pptLibraryOut;
11651179

11661180

1167-
if(tDesc.tFlags & PL_LIBRARY_FLAGS_RELOADABLE)
1181+
if(gbHotReloadActive && tDesc.tFlags & PL_LIBRARY_FLAGS_RELOADABLE)
11681182
{
11691183

11701184
ptLibrary->bValid = false;
@@ -1235,10 +1249,13 @@ pl_load_library(plLibraryDesc tDesc, plSharedLibrary** pptLibraryOut)
12351249
strncpy(ptLibrary->acFileExtension, gpcLibraryExtension, 16);
12361250

12371251
pl_sprintf(ptLibrary->acPath, "%s%s.%s", ptLibrary->acDirectory, ptLibrary->acName, ptLibrary->acFileExtension);
1238-
pl_sprintf(ptLibrary->acLockFile, "%s%s", ptLibrary->acDirectory, pcLockFile);
1239-
pl_sprintf(ptLibrary->acTransitionalPath, "%s/%s_", pcCacheDirectory, ptLibrary->acName);
1252+
if(gbHotReloadActive)
1253+
{
1254+
pl_sprintf(ptLibrary->acLockFile, "%s%s", ptLibrary->acDirectory, pcLockFile);
1255+
pl_sprintf(ptLibrary->acTransitionalPath, "%s/%s_", pcCacheDirectory, ptLibrary->acName);
1256+
}
12401257

1241-
if(!(tDesc.tFlags & PL_LIBRARY_FLAGS_RELOADABLE))
1258+
if(!gbHotReloadActive || !(tDesc.tFlags & PL_LIBRARY_FLAGS_RELOADABLE))
12421259
{
12431260
ptLibrary->tLastWriteTime = pl__get_last_write_time(ptLibrary->acPath);
12441261
ptLibrary->handle = NULL;
@@ -1254,7 +1271,7 @@ pl_load_library(plLibraryDesc tDesc, plSharedLibrary** pptLibraryOut)
12541271
else
12551272
ptLibrary = *pptLibraryOut;
12561273

1257-
if(tDesc.tFlags & PL_LIBRARY_FLAGS_RELOADABLE)
1274+
if(gbHotReloadActive && tDesc.tFlags & PL_LIBRARY_FLAGS_RELOADABLE)
12581275
{
12591276
ptLibrary->bValid = false;
12601277

@@ -1320,10 +1337,13 @@ pl_load_library(plLibraryDesc tDesc, plSharedLibrary** pptLibraryOut)
13201337
strncpy(ptLibrary->acFileExtension, gpcLibraryExtension, 16);
13211338

13221339
pl_sprintf(ptLibrary->acPath, "%s%s.%s", ptLibrary->acDirectory, ptLibrary->acName, ptLibrary->acFileExtension);
1323-
pl_sprintf(ptLibrary->acLockFile, "%s%s", ptLibrary->acDirectory, pcLockFile);
1324-
pl_sprintf(ptLibrary->acTransitionalPath, "%s/%s_", pcCacheDirectory, ptLibrary->acName);
1340+
if(gbHotReloadActive)
1341+
{
1342+
pl_sprintf(ptLibrary->acLockFile, "%s%s", ptLibrary->acDirectory, pcLockFile);
1343+
pl_sprintf(ptLibrary->acTransitionalPath, "%s/%s_", pcCacheDirectory, ptLibrary->acName);
1344+
}
13251345

1326-
if(!(tDesc.tFlags & PL_LIBRARY_FLAGS_RELOADABLE))
1346+
if(!gbHotReloadActive || !(tDesc.tFlags & PL_LIBRARY_FLAGS_RELOADABLE))
13271347
{
13281348
ptLibrary->tLastWriteTime = pl__get_last_write_time(ptLibrary->acPath);
13291349
ptLibrary->handle = NULL;
@@ -1339,7 +1359,7 @@ pl_load_library(plLibraryDesc tDesc, plSharedLibrary** pptLibraryOut)
13391359
else
13401360
ptLibrary = *pptLibraryOut;
13411361

1342-
if(tDesc.tFlags & PL_LIBRARY_FLAGS_RELOADABLE)
1362+
if(gbHotReloadActive && tDesc.tFlags & PL_LIBRARY_FLAGS_RELOADABLE)
13431363
{
13441364
ptLibrary->bValid = false;
13451365

src/pl_main_macos.m

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,10 @@ int main(int argc, char *argv[])
160160
pcAppName = argv[i + 1];
161161
i++;
162162
}
163+
else if(strcmp(argv[i], "-hr") == 0 || strcmp(argv[i], "--hot-reload") == 0)
164+
{
165+
gbHotReloadActive = true;
166+
}
163167
else if(strcmp(argv[i], "--version") == 0)
164168
{
165169
printf("\nPilot Light - light weight game engine\n\n");
@@ -216,6 +220,8 @@ int main(int argc, char *argv[])
216220
printf("--apis %s\n", "Displays embedded apis.");
217221
printf("-a <app> %s\n", "Sets app to load. Default is 'app'.");
218222
printf("--app <app> %s\n", "Sets app to load. Default is 'app'.");
223+
printf("-hr %s\n", "Activates hot reloading.");
224+
printf("--hot-reload %s\n", "Activates hot reloading.");
219225
return 0;
220226
}
221227
}
@@ -235,6 +241,7 @@ int main(int argc, char *argv[])
235241

236242
// setup & retrieve io context
237243
gptIOCtx = gptIOI->get_io();
244+
gptIOCtx->bHotReloadActive = gbHotReloadActive;
238245

239246
// command line args
240247
gptIOCtx->iArgc = argc;
@@ -561,7 +568,7 @@ - (void)renderToMetalLayer:(nonnull CAMetalLayer *)layer
561568
gptIOCtx->bCursorChanged = false;
562569

563570
// reload library
564-
if(gptLibraryApi->has_changed(gptAppLibrary))
571+
if(gbHotReloadActive && gptLibraryApi->has_changed(gptAppLibrary))
565572
{
566573
pl_reload_library(gptAppLibrary);
567574
pl_app_load = (void* (__attribute__(()) *)(const plApiRegistryI*, void*)) gptLibraryApi->load_function(gptAppLibrary, "pl_app_load");
@@ -953,10 +960,13 @@ - (void)unmarkText
953960
strncpy(ptLibrary->acFileExtension, "dylib", 16);
954961

955962
pl_sprintf(ptLibrary->acPath, "%s%s.%s", ptLibrary->acDirectory, ptLibrary->acName, ptLibrary->acFileExtension);
956-
pl_sprintf(ptLibrary->acLockFile, "%s%s", ptLibrary->acDirectory, pcLockFile);
957-
pl_sprintf(ptLibrary->acTransitionalPath, "%s/%s_", pcCacheDirectory, ptLibrary->acName);
963+
if(gbHotReloadActive)
964+
{
965+
pl_sprintf(ptLibrary->acLockFile, "%s%s", ptLibrary->acDirectory, pcLockFile);
966+
pl_sprintf(ptLibrary->acTransitionalPath, "%s/%s_", pcCacheDirectory, ptLibrary->acName);
967+
}
958968

959-
if(!(tDesc.tFlags & PL_LIBRARY_FLAGS_RELOADABLE))
969+
if(!gbHotReloadActive || !(tDesc.tFlags & PL_LIBRARY_FLAGS_RELOADABLE))
960970
{
961971
ptLibrary->tLastWriteTime = pl__get_last_write_time(ptLibrary->acPath);
962972
ptLibrary->handle = NULL;
@@ -972,7 +982,7 @@ - (void)unmarkText
972982
else
973983
ptLibrary = *pptLibraryOut;
974984

975-
if(tDesc.tFlags & PL_LIBRARY_FLAGS_RELOADABLE)
985+
if(gbHotReloadActive && tDesc.tFlags & PL_LIBRARY_FLAGS_RELOADABLE)
976986
{
977987
ptLibrary->bValid = false;
978988

0 commit comments

Comments
 (0)