|
|
@ -58,6 +58,10 @@ |
|
|
|
#define LOG(...) |
|
|
|
#endif |
|
|
|
|
|
|
|
#define REXM_MAX_BUFFER_SIZE (2*1024*1024) // 2MB |
|
|
|
|
|
|
|
#define REXM_MAX_RESOURCE_PATHS 256 |
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------- |
|
|
|
// Types and Structures Definition |
|
|
|
//---------------------------------------------------------------------------------- |
|
|
@ -125,6 +129,12 @@ static int ParseExampleInfoLine(const char *line, rlExampleInfo *entry); |
|
|
|
// WARNING: items[] pointers are reorganized |
|
|
|
static void SortExampleByName(rlExampleInfo *items, int count); |
|
|
|
|
|
|
|
// Scan resource paths in example file |
|
|
|
static char **ScanExampleResources(const char *filePath, int *resPathCount); |
|
|
|
|
|
|
|
// Clear resource paths scanned |
|
|
|
static void ClearExampleResources(char **resPaths); |
|
|
|
|
|
|
|
//------------------------------------------------------------------------------------ |
|
|
|
// Program main entry point |
|
|
|
//------------------------------------------------------------------------------------ |
|
|
@ -296,17 +306,68 @@ int main(int argc, char *argv[]) |
|
|
|
// Create: raylib/examples/<category>/<category>_example_name.png |
|
|
|
FileCopy(exTemplateScreenshot, TextFormat("%s/%s/%s.png", exBasePath, exCategory, exName)); // WARNING: To be updated manually! |
|
|
|
|
|
|
|
// Copy: raylib/examples/<category>/resources/... // WARNING: To be updated manually! |
|
|
|
// IDEA: Example to be added could be provided as a .zip, containing resources! |
|
|
|
|
|
|
|
// TODO: Copy provided resources to respective directories |
|
|
|
// Possible strategy: |
|
|
|
// 1. Scan code file for resources paths -> Resources list |
|
|
|
// Look for specific text: '.png"' |
|
|
|
// Look for full path, previous '"' |
|
|
|
// Be careful with shaders: '.vs"', '.fs"' -> Reconstruct path manually? |
|
|
|
// 2. Verify paths: resource files exist |
|
|
|
// 3. Copy files to required resource dir |
|
|
|
// Copy: raylib/examples/<category>/resources/... |
|
|
|
// ----------------------------------------------------------------------------------------- |
|
|
|
// Scan resources used in example to copy |
|
|
|
int resPathCount = 0; |
|
|
|
char **resPaths = ScanExampleResources(TextFormat("%s/%s/%s.png", exBasePath, exCategory, exName), &resPathCount); |
|
|
|
|
|
|
|
if (resPathCount > 0) |
|
|
|
{ |
|
|
|
for (int r = 0; r < resPathCount; r++) |
|
|
|
{ |
|
|
|
// WARNING: Special case to consider: shaders, resource paths could use conditions: "glsl%i" |
|
|
|
// In this case, multiple resources are required: glsl100, glsl120, glsl330 |
|
|
|
if (TextFindIndex(resPaths[r], "glsl%i") > -1) |
|
|
|
{ |
|
|
|
int glslVer[3] = { 100, 120, 330 }; |
|
|
|
|
|
|
|
for (int v = 0; v < 3; v++) |
|
|
|
{ |
|
|
|
char *resPathUpdated = TextReplace(resPaths[r], "glsl%i", TextFormat("glsl%i", glslVer[v])); |
|
|
|
|
|
|
|
LOG("INFO: Example resource required: %s\n", resPathUpdated); |
|
|
|
|
|
|
|
if (FileExists(TextFormat("%s/%s", GetDirectoryPath(inFileName), resPathUpdated))) |
|
|
|
{ |
|
|
|
// Verify the resources are placed in "resources" directory |
|
|
|
if (TextFindIndex(resPathUpdated, "resources/") > 0) |
|
|
|
{ |
|
|
|
// NOTE: Look for resources in the path of the provided .c to be added |
|
|
|
// To be copied to <category>/resources directory, extra dirs are automatically created if required |
|
|
|
FileCopy(TextFormat("%s/%s", GetDirectoryPath(inFileName), resPathUpdated), |
|
|
|
TextFormat("%s/%s/%s", exBasePath, exCategory, resPathUpdated)); |
|
|
|
} |
|
|
|
else LOG("WARNING: Example resource must be placed in 'resources' directory next to .c file\n"); |
|
|
|
} |
|
|
|
else LOG("WARNING: Example resource can not be found in: %s\n", TextFormat("%s/%s", GetDirectoryPath(inFileName), resPathUpdated)); |
|
|
|
|
|
|
|
RL_FREE(resPathUpdated); |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
LOG("INFO: Example resource required: %s\n", resPaths[r]); |
|
|
|
|
|
|
|
if (FileExists(TextFormat("%s/%s", GetDirectoryPath(inFileName), resPaths[r]))) |
|
|
|
{ |
|
|
|
// Verify the resources are placed in "resources" directory |
|
|
|
if (TextFindIndex(resPaths[r], "resources/") > 0) |
|
|
|
{ |
|
|
|
// NOTE: Look for resources in the path of the provided .c to be added |
|
|
|
// To be copied to <category>/resources directory, extra dirs are automatically created if required |
|
|
|
FileCopy(TextFormat("%s/%s", GetDirectoryPath(inFileName), resPaths[r]), |
|
|
|
TextFormat("%s/%s/%s", exBasePath, exCategory, resPaths[r])); |
|
|
|
} |
|
|
|
else LOG("WARNING: Example resource must be placed in 'resources' directory next to .c file\n"); |
|
|
|
} |
|
|
|
else LOG("WARNING: Example resource can not be found in: %s\n", TextFormat("%s/%s", GetDirectoryPath(inFileName), resPaths[r])); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
ClearExampleResources(resPaths); |
|
|
|
// ----------------------------------------------------------------------------------------- |
|
|
|
|
|
|
|
// Add example to the collection list, if not already there |
|
|
|
// NOTE: Required format: shapes;shapes_basic_shapes;⭐️☆☆☆;1.0;4.2;"Ray";@raysan5 |
|
|
@ -618,6 +679,7 @@ static int UpdateRequiredFiles(void) |
|
|
|
//------------------------------------------------------------------------------------------------ |
|
|
|
|
|
|
|
// Edit: raylib/examples/Makefile.Web --> Update from collection |
|
|
|
// NOTE: We avoid the "others" category on web building |
|
|
|
//------------------------------------------------------------------------------------------------ |
|
|
|
char *mkwText = LoadFileText(TextFormat("%s/Makefile.Web", exBasePath)); |
|
|
|
char *mkwTextUpdated = (char *)RL_CALLOC(2*1024*1024, 1); // Updated Makefile copy, 2MB |
|
|
@ -629,7 +691,8 @@ static int UpdateRequiredFiles(void) |
|
|
|
memcpy(mkwTextUpdated, mkwText, mkwListStartIndex); |
|
|
|
mkwIndex = sprintf(mkwTextUpdated + mkwListStartIndex, "#EXAMPLES_LIST_START\n"); |
|
|
|
|
|
|
|
for (int i = 0; i < MAX_EXAMPLE_CATEGORIES; i++) |
|
|
|
// NOTE: We avoid the "others" category on web building |
|
|
|
for (int i = 0; i < MAX_EXAMPLE_CATEGORIES - 1; i++) |
|
|
|
{ |
|
|
|
mkwIndex += sprintf(mkwTextUpdated + mkwListStartIndex + mkwIndex, TextFormat("%s = \\\n", TextToUpper(exCategories[i]))); |
|
|
|
|
|
|
@ -1018,3 +1081,75 @@ static void SortExampleByName(rlExampleInfo *items, int count) |
|
|
|
{ |
|
|
|
qsort(items, count, sizeof(rlExampleInfo), rlExampleInfoCompare); |
|
|
|
} |
|
|
|
|
|
|
|
// Scan resource paths in example file |
|
|
|
static char **ScanExampleResources(const char *filePath, int *resPathCount) |
|
|
|
{ |
|
|
|
#define MAX_RES_PATH_LEN 256 |
|
|
|
|
|
|
|
char **paths = (char **)RL_CALLOC(REXM_MAX_RESOURCE_PATHS, sizeof(char **)); |
|
|
|
for (int i = 0; i < REXM_MAX_RESOURCE_PATHS; i++) paths[i] = (char *)RL_CALLOC(MAX_RES_PATH_LEN, sizeof(char)); |
|
|
|
|
|
|
|
int resCounter = 0; |
|
|
|
char *code = LoadFileText(filePath); |
|
|
|
|
|
|
|
if (code != NULL) |
|
|
|
{ |
|
|
|
// Resources extensions to check |
|
|
|
const char *exts[] = { ".png", ".bmp", ".jpg", ".qoi", ".gif", ".raw", ".hdr", ".ttf", ".fnt", ".wav", ".ogg", ".mp3", ".flac", ".mod", ".qoa", ".qoa", ".obj", ".iqm", ".glb", ".m3d", ".vox", ".vs", ".fs" }; |
|
|
|
const int extCount = sizeof(exts)/sizeof(exts[0]); |
|
|
|
|
|
|
|
char *ptr = code; |
|
|
|
while ((ptr = strchr(ptr, '"')) != NULL) |
|
|
|
{ |
|
|
|
char *start = ptr + 1; |
|
|
|
char *end = strchr(start, '"'); |
|
|
|
if (!end) break; |
|
|
|
|
|
|
|
int len = end - start; |
|
|
|
if ((len > 0) && (len < MAX_RES_PATH_LEN)) |
|
|
|
{ |
|
|
|
char buffer[MAX_RES_PATH_LEN] = { 0 }; |
|
|
|
strncpy(buffer, start, len); |
|
|
|
buffer[len] = '\0'; |
|
|
|
|
|
|
|
// Check for known extensions |
|
|
|
for (int i = 0; i < extCount; i++) |
|
|
|
{ |
|
|
|
if (IsFileExtension(buffer, exts[i])) |
|
|
|
{ |
|
|
|
// Avoid duplicates |
|
|
|
bool found = false; |
|
|
|
for (int j = 0; j < resCounter; j++) |
|
|
|
{ |
|
|
|
if (TextIsEqual(paths[j], buffer)) { found = true; break; } |
|
|
|
} |
|
|
|
|
|
|
|
if (!found && (resCounter < REXM_MAX_RESOURCE_PATHS)) |
|
|
|
{ |
|
|
|
strcpy(paths[resCounter], buffer); |
|
|
|
resCounter++; |
|
|
|
} |
|
|
|
|
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
ptr = end + 1; |
|
|
|
} |
|
|
|
|
|
|
|
UnloadFileText(code); |
|
|
|
} |
|
|
|
|
|
|
|
*resPathCount = resCounter; |
|
|
|
return paths; |
|
|
|
} |
|
|
|
|
|
|
|
// Clear resource paths scanned |
|
|
|
static void ClearExampleResources(char **resPaths) |
|
|
|
{ |
|
|
|
for (int i = 0; i < REXM_MAX_RESOURCE_PATHS; i++) RL_FREE(resPaths[i]); |
|
|
|
|
|
|
|
RL_FREE(resPaths); |
|
|
|
} |