|
|
@ -267,9 +267,15 @@ |
|
|
#define MAX_AUTOMATION_EVENTS 16384 // Maximum number of automation events to record |
|
|
#define MAX_AUTOMATION_EVENTS 16384 // Maximum number of automation events to record |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
|
|
|
#ifndef DIRECTORY_FILTER_TAG |
|
|
|
|
|
#define DIRECTORY_FILTER_TAG "DIR" // Name tag used to request directory inclusion on directory scan |
|
|
|
|
|
#endif // NOTE: Used in ScanDirectoryFiles(), ScanDirectoryFilesRecursively() and LoadDirectoryFilesEx() |
|
|
|
|
|
|
|
|
#ifndef FILE_FILTER_TAG_ALL |
|
|
|
|
|
#define FILE_FILTER_TAG_ALL "*.*" // Filter to include all file types and directories on directory scan |
|
|
|
|
|
#endif // NOTE: Used in ScanDirectoryFiles(), LoadDirectoryFilesEx() and GetDirectoryFileCountEx() |
|
|
|
|
|
#ifndef FILE_FILTER_TAG_FILE_ONLY |
|
|
|
|
|
#define FILE_FILTER_TAG_FILE_ONLY "FILES*" // Filter to include all file types on directory scan |
|
|
|
|
|
#endif // NOTE: Used in ScanDirectoryFiles(), LoadDirectoryFilesEx() and GetDirectoryFileCountEx() |
|
|
|
|
|
#ifndef FILE_FILTER_TAG_DIR_ONLY |
|
|
|
|
|
#define FILE_FILTER_TAG_DIR_ONLY "DIR*" // Filter to include directories on directory scan |
|
|
|
|
|
#endif // NOTE: Used in ScanDirectoryFiles(), LoadDirectoryFilesEx() and GetDirectoryFileCountEx() |
|
|
|
|
|
|
|
|
// Flags operation macros |
|
|
// Flags operation macros |
|
|
#define FLAG_SET(n, f) ((n) |= (f)) |
|
|
#define FLAG_SET(n, f) ((n) |= (f)) |
|
|
@ -505,8 +511,7 @@ extern void ClosePlatform(void); // Close platform |
|
|
static void InitTimer(void); // Initialize timer, hi-resolution if available (required by InitPlatform()) |
|
|
static void InitTimer(void); // Initialize timer, hi-resolution if available (required by InitPlatform()) |
|
|
static void SetupViewport(int width, int height); // Set viewport for a provided width and height |
|
|
static void SetupViewport(int width, int height); // Set viewport for a provided width and height |
|
|
|
|
|
|
|
|
static void ScanDirectoryFiles(const char *basePath, FilePathList *list, const char *filter, unsigned int fileCount); // Scan all files and directories in a base path |
|
|
|
|
|
static void ScanDirectoryFilesRecursively(const char *basePath, FilePathList *list, const char *filter, unsigned int fileCount); // Scan all files and directories recursively from a base path |
|
|
|
|
|
|
|
|
static void ScanDirectoryFiles(const char *basePath, FilePathList *list, const char *filter, unsigned int fileCount, bool scanSubdirs); // Scan all files and directories in a base path |
|
|
|
|
|
|
|
|
#if defined(SUPPORT_AUTOMATION_EVENTS) |
|
|
#if defined(SUPPORT_AUTOMATION_EVENTS) |
|
|
static void RecordAutomationEvent(void); // Record frame events (to internal events array) |
|
|
static void RecordAutomationEvent(void); // Record frame events (to internal events array) |
|
|
@ -2753,31 +2758,7 @@ const char *GetApplicationDirectory(void) |
|
|
// No recursive scanning is done! |
|
|
// No recursive scanning is done! |
|
|
FilePathList LoadDirectoryFiles(const char *dirPath) |
|
|
FilePathList LoadDirectoryFiles(const char *dirPath) |
|
|
{ |
|
|
{ |
|
|
FilePathList files = { 0 }; |
|
|
|
|
|
|
|
|
|
|
|
if (DirectoryExists(dirPath)) // It's a directory |
|
|
|
|
|
{ |
|
|
|
|
|
// SCAN 1: Count files |
|
|
|
|
|
unsigned int fileCounter = GetDirectoryFileCount(dirPath); |
|
|
|
|
|
|
|
|
|
|
|
// Memory allocation for dirFileCount |
|
|
|
|
|
files.paths = (char **)RL_CALLOC(fileCounter, sizeof(char *)); |
|
|
|
|
|
for (unsigned int i = 0; i < fileCounter; i++) files.paths[i] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char)); |
|
|
|
|
|
|
|
|
|
|
|
// SCAN 2: Read filepaths |
|
|
|
|
|
// NOTE: Directory paths are also registered |
|
|
|
|
|
ScanDirectoryFiles(dirPath, &files, NULL, fileCounter); |
|
|
|
|
|
|
|
|
|
|
|
// Security check: read files.count should match fileCounter |
|
|
|
|
|
if (files.count != fileCounter) |
|
|
|
|
|
{ |
|
|
|
|
|
TRACELOG(LOG_WARNING, "FILEIO: Read files count (%u) does not match capacity allocated (%u)", files.count, fileCounter); |
|
|
|
|
|
files.count = fileCounter; // Avoid memory leak when unloading this FilePathList |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
else TRACELOG(LOG_WARNING, "FILEIO: Failed to open requested directory"); // Maybe it's a file... |
|
|
|
|
|
|
|
|
|
|
|
return files; |
|
|
|
|
|
|
|
|
return LoadDirectoryFilesEx(dirPath, FILE_FILTER_TAG_ALL, false); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Load directory filepaths with extension filtering and recursive directory scan |
|
|
// Load directory filepaths with extension filtering and recursive directory scan |
|
|
@ -2797,8 +2778,7 @@ FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool |
|
|
|
|
|
|
|
|
// SCAN 2: Read filepaths |
|
|
// SCAN 2: Read filepaths |
|
|
// WARNING: basePath is always prepended to scanned paths |
|
|
// WARNING: basePath is always prepended to scanned paths |
|
|
if (scanSubdirs) ScanDirectoryFilesRecursively(basePath, &files, filter, fileCounter); |
|
|
|
|
|
else ScanDirectoryFiles(basePath, &files, filter, fileCounter); |
|
|
|
|
|
|
|
|
ScanDirectoryFiles(basePath, &files, filter, fileCounter, scanSubdirs); |
|
|
|
|
|
|
|
|
// Security check: read files.count should match fileCounter |
|
|
// Security check: read files.count should match fileCounter |
|
|
if (files.count != fileCounter) |
|
|
if (files.count != fileCounter) |
|
|
@ -2807,7 +2787,7 @@ FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool |
|
|
files.count = fileCounter; // Avoid memory leak when unloading this FilePathList |
|
|
files.count = fileCounter; // Avoid memory leak when unloading this FilePathList |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
else TRACELOG(LOG_WARNING, "FILEIO: Failed to open requested directory"); // Maybe it's a file... |
|
|
|
|
|
|
|
|
else TRACELOG(LOG_WARNING, "FILEIO: Directory cannot be opened (%s)", basePath); // Maybe it's a file... |
|
|
|
|
|
|
|
|
return files; |
|
|
return files; |
|
|
} |
|
|
} |
|
|
@ -2977,43 +2957,10 @@ void UnloadDroppedFiles(FilePathList files) |
|
|
// Get the file count in a directory |
|
|
// Get the file count in a directory |
|
|
unsigned int GetDirectoryFileCount(const char *dirPath) |
|
|
unsigned int GetDirectoryFileCount(const char *dirPath) |
|
|
{ |
|
|
{ |
|
|
unsigned int fileCounter = 0; |
|
|
|
|
|
|
|
|
|
|
|
static char path[MAX_FILEPATH_LENGTH] = { 0 }; |
|
|
|
|
|
memset(path, 0, MAX_FILEPATH_LENGTH); |
|
|
|
|
|
|
|
|
|
|
|
struct dirent *entity; |
|
|
|
|
|
DIR *dir = opendir(dirPath); |
|
|
|
|
|
|
|
|
|
|
|
if (dir != NULL) // It's a directory |
|
|
|
|
|
{ |
|
|
|
|
|
while ((entity = readdir(dir)) != NULL) |
|
|
|
|
|
{ |
|
|
|
|
|
// NOTE: We skip '.' (current dir) and '..' (parent dir) filepaths |
|
|
|
|
|
if ((strcmp(entity->d_name, ".") != 0) && (strcmp(entity->d_name, "..") != 0)) |
|
|
|
|
|
{ |
|
|
|
|
|
// Construct new path from our base path |
|
|
|
|
|
#if defined(_WIN32) |
|
|
|
|
|
int pathLength = snprintf(path, MAX_FILEPATH_LENGTH - 1, "%s\\%s", dirPath, entity->d_name); |
|
|
|
|
|
#else |
|
|
|
|
|
int pathLength = snprintf(path, MAX_FILEPATH_LENGTH - 1, "%s/%s", dirPath, entity->d_name); |
|
|
|
|
|
#endif |
|
|
|
|
|
// Don't add to count if path too long |
|
|
|
|
|
if ((pathLength < 0) || (pathLength >= MAX_FILEPATH_LENGTH)) |
|
|
|
|
|
{ |
|
|
|
|
|
TRACELOG(LOG_WARNING, "FILEIO: Path longer than %d characters (%s...)", MAX_FILEPATH_LENGTH, dirPath); |
|
|
|
|
|
} |
|
|
|
|
|
else fileCounter++; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
closedir(dir); |
|
|
|
|
|
} |
|
|
|
|
|
else TRACELOG(LOG_WARNING, "FILEIO: Failed to open requested directory"); // Maybe it's a file... |
|
|
|
|
|
return fileCounter; |
|
|
|
|
|
|
|
|
return GetDirectoryFileCountEx(dirPath, FILE_FILTER_TAG_ALL, false); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Get the file count in a directory with extension filtering and recursive directory scan. Use 'DIR' in the filter string to include directories in the result |
|
|
|
|
|
|
|
|
// Get the file count in a directory with extension filtering and recursive directory scan. Use 'FILE_FILTER_TAG_DIR_ONLY' in the filter string to include directories in the result |
|
|
unsigned int GetDirectoryFileCountEx(const char *basePath, const char *filter, bool scanSubdirs) |
|
|
unsigned int GetDirectoryFileCountEx(const char *basePath, const char *filter, bool scanSubdirs) |
|
|
{ |
|
|
{ |
|
|
unsigned int fileCounter = 0; |
|
|
unsigned int fileCounter = 0; |
|
|
@ -3045,17 +2992,18 @@ unsigned int GetDirectoryFileCountEx(const char *basePath, const char *filter, b |
|
|
} |
|
|
} |
|
|
else if (IsPathFile(path)) |
|
|
else if (IsPathFile(path)) |
|
|
{ |
|
|
{ |
|
|
if (filter == NULL || IsFileExtension(path, filter)) fileCounter++; |
|
|
|
|
|
|
|
|
if ((filter == NULL) || (strstr(filter, FILE_FILTER_TAG_ALL) != NULL) || |
|
|
|
|
|
(strstr(filter, FILE_FILTER_TAG_FILE_ONLY) != NULL) || IsFileExtension(path, filter)) fileCounter++; |
|
|
} |
|
|
} |
|
|
else |
|
|
else |
|
|
{ |
|
|
{ |
|
|
if ((filter != NULL) && (strstr(filter, DIRECTORY_FILTER_TAG) != NULL)) fileCounter++; |
|
|
|
|
|
|
|
|
if ((filter != NULL) && (p">(strstr(filter, FILE_FILTER_TAG_ALL) != NULL) || (strstr(filter, FILE_FILTER_TAG_DIR_ONLY) != NULL))) fileCounter++; |
|
|
if (scanSubdirs) fileCounter += GetDirectoryFileCountEx(path, filter, scanSubdirs); |
|
|
if (scanSubdirs) fileCounter += GetDirectoryFileCountEx(path, filter, scanSubdirs); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
else TRACELOG(LOG_WARNING, "FILEIO: Failed to open requested directory"); // Maybe it's a file... |
|
|
|
|
|
|
|
|
else TRACELOG(LOG_WARNING, "FILEIO: Directory cannot be opened (%s)", basePath); // Maybe it's a file... |
|
|
return fileCounter; |
|
|
return fileCounter; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -4322,68 +4270,7 @@ void SetupViewport(int width, int height) |
|
|
// Scan all files and directories in a base path |
|
|
// Scan all files and directories in a base path |
|
|
// WARNING: files.paths[] must be previously allocated and |
|
|
// WARNING: files.paths[] must be previously allocated and |
|
|
// contain enough space to store all required paths |
|
|
// contain enough space to store all required paths |
|
|
static void ScanDirectoryFiles(const char *basePath, FilePathList *files, const char *filter, unsigned int fileCount) |
|
|
|
|
|
{ |
|
|
|
|
|
static char path[MAX_FILEPATH_LENGTH] = { 0 }; |
|
|
|
|
|
memset(path, 0, MAX_FILEPATH_LENGTH); |
|
|
|
|
|
|
|
|
|
|
|
struct dirent *dp = NULL; |
|
|
|
|
|
DIR *dir = opendir(basePath); |
|
|
|
|
|
|
|
|
|
|
|
if (dir != NULL) |
|
|
|
|
|
{ |
|
|
|
|
|
while (((dp = readdir(dir)) != NULL) && (files->count < fileCount)) |
|
|
|
|
|
{ |
|
|
|
|
|
if ((strcmp(dp->d_name, ".") != 0) && |
|
|
|
|
|
(strcmp(dp->d_name, "..") != 0)) |
|
|
|
|
|
{ |
|
|
|
|
|
// Construct new path from our base path |
|
|
|
|
|
#if defined(_WIN32) |
|
|
|
|
|
int pathLength = snprintf(path, MAX_FILEPATH_LENGTH - 1, "%s\\%s", basePath, dp->d_name); |
|
|
|
|
|
#else |
|
|
|
|
|
int pathLength = snprintf(path, MAX_FILEPATH_LENGTH - 1, "%s/%s", basePath, dp->d_name); |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
if ((pathLength < 0) || (pathLength >= MAX_FILEPATH_LENGTH)) |
|
|
|
|
|
{ |
|
|
|
|
|
TRACELOG(LOG_WARNING, "FILEIO: Path longer than %d characters (%s...)", MAX_FILEPATH_LENGTH, basePath); |
|
|
|
|
|
} |
|
|
|
|
|
else if (filter != NULL) |
|
|
|
|
|
{ |
|
|
|
|
|
if (IsPathFile(path)) |
|
|
|
|
|
{ |
|
|
|
|
|
if (IsFileExtension(path, filter)) |
|
|
|
|
|
{ |
|
|
|
|
|
strncpy(files->paths[files->count], path, MAX_FILEPATH_LENGTH - 1); |
|
|
|
|
|
files->count++; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
if (strstr(filter, DIRECTORY_FILTER_TAG) != NULL) |
|
|
|
|
|
{ |
|
|
|
|
|
strncpy(files->paths[files->count], path, MAX_FILEPATH_LENGTH - 1); |
|
|
|
|
|
files->count++; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
strncpy(files->paths[files->count], path, MAX_FILEPATH_LENGTH - 1); |
|
|
|
|
|
files->count++; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
closedir(dir); |
|
|
|
|
|
} |
|
|
|
|
|
else TRACELOG(LOG_WARNING, "FILEIO: Directory cannot be opened (%s)", basePath); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Scan all files and directories recursively from a base path |
|
|
|
|
|
// WARNING: files.paths[] must be previously allocated and |
|
|
|
|
|
// contain enough space to store all required paths |
|
|
|
|
|
static void ScanDirectoryFilesRecursively(const char *basePath, FilePathList *files, const char *filter, unsigned int fileCount) |
|
|
|
|
|
|
|
|
static void ScanDirectoryFiles(const char *basePath, FilePathList *files, const char *filter, unsigned int fileCount, bool scanSubdirs) |
|
|
{ |
|
|
{ |
|
|
// WARNING: Path can not be static or it will be reused between recursive function calls! |
|
|
// WARNING: Path can not be static or it will be reused between recursive function calls! |
|
|
char path[MAX_FILEPATH_LENGTH] = { 0 }; |
|
|
char path[MAX_FILEPATH_LENGTH] = { 0 }; |
|
|
@ -4411,15 +4298,8 @@ static void ScanDirectoryFilesRecursively(const char *basePath, FilePathList *fi |
|
|
} |
|
|
} |
|
|
else if (IsPathFile(path)) |
|
|
else if (IsPathFile(path)) |
|
|
{ |
|
|
{ |
|
|
if (filter != NULL) |
|
|
|
|
|
{ |
|
|
|
|
|
if (IsFileExtension(path, filter)) |
|
|
|
|
|
{ |
|
|
|
|
|
strncpy(files->paths[files->count], path, MAX_FILEPATH_LENGTH - 1); |
|
|
|
|
|
files->count++; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
|
|
|
if ((filter == NULL) || (strstr(filter, FILE_FILTER_TAG_ALL) != NULL) || |
|
|
|
|
|
(strstr(filter, FILE_FILTER_TAG_FILE_ONLY) != NULL) || IsFileExtension(path, filter)) |
|
|
{ |
|
|
{ |
|
|
strncpy(files->paths[files->count], path, MAX_FILEPATH_LENGTH - 1); |
|
|
strncpy(files->paths[files->count], path, MAX_FILEPATH_LENGTH - 1); |
|
|
files->count++; |
|
|
files->count++; |
|
|
@ -4427,20 +4307,20 @@ static void ScanDirectoryFilesRecursively(const char *basePath, FilePathList *fi |
|
|
} |
|
|
} |
|
|
else |
|
|
else |
|
|
{ |
|
|
{ |
|
|
if ((filter != NULL) && (strstr(filter, DIRECTORY_FILTER_TAG) != NULL)) |
|
|
|
|
|
|
|
|
if ((filter != NULL) && (p">(strstr(filter, FILE_FILTER_TAG_DIR_ONLY) != NULL) || (strstr(filter, FILE_FILTER_TAG_ALL) != NULL))) |
|
|
{ |
|
|
{ |
|
|
strncpy(files->paths[files->count], path, MAX_FILEPATH_LENGTH - 1); |
|
|
strncpy(files->paths[files->count], path, MAX_FILEPATH_LENGTH - 1); |
|
|
files->count++; |
|
|
files->count++; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
ScanDirectoryFilesRecursively(path, files, filter, fileCount); |
|
|
|
|
|
|
|
|
k">if (scanSubdirs) ScanDirectoryFiles(path, files, filter, fileCount, scanSubdirs); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
closedir(dir); |
|
|
closedir(dir); |
|
|
} |
|
|
} |
|
|
else TRACELOG(LOG_WARNING, "FILEIO: Directory cannot be opened (%s)", basePath); |
|
|
|
|
|
|
|
|
else TRACELOG(LOG_WARNING, "FILEIO: Directory cannot be opened (%s)", basePath); // Maybe it's a file... |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
#if defined(SUPPORT_AUTOMATION_EVENTS) |
|
|
#if defined(SUPPORT_AUTOMATION_EVENTS) |
|
|
|