diff --git a/examples/core/core_drop_files.c b/examples/core/core_drop_files.c
index 129ced105..0a1a71e90 100644
--- a/examples/core/core_drop_files.c
+++ b/examples/core/core_drop_files.c
@@ -22,8 +22,7 @@ int main(void)
 
     InitWindow(screenWidth, screenHeight, "raylib [core] example - drop files");
 
-    int count = 0;
-    char **droppedFiles = { 0 };
+    FilePathList droppedFiles = { 0 };
 
     SetTargetFPS(60);               // Set our game to run at 60 frames-per-second
     //--------------------------------------------------------------------------------------
@@ -35,7 +34,11 @@ int main(void)
         //----------------------------------------------------------------------------------
         if (IsFileDropped())
         {
-            droppedFiles = LoadDroppedFiles(&count);
+            // Is some files have been previously loaded, unload them
+            if (droppedFiles.count > 0) UnloadDroppedFiles(droppedFiles);
+            
+            // Load new dropped files
+            droppedFiles = LoadDroppedFiles();
         }
         //----------------------------------------------------------------------------------
 
@@ -55,7 +58,7 @@ int main(void)
                     if (i%2 == 0) DrawRectangle(0, 85 + 40*i, screenWidth, 40, Fade(LIGHTGRAY, 0.5f));
                     else DrawRectangle(0, 85 + 40*i, screenWidth, 40, Fade(LIGHTGRAY, 0.3f));
 
-                    DrawText(droppedFiles[i], 120, 100 + 40*i, 10, GRAY);
+                    DrawText(droppedFiles.paths[i], 120, 100 + 40*i, 10, GRAY);
                 }
 
                 DrawText("Drop new files...", 100, 110 + 40*count, 20, DARKGRAY);
@@ -67,7 +70,7 @@ int main(void)
 
     // De-Initialization
     //--------------------------------------------------------------------------------------
-    UnloadDroppedFiles();    // Clear internal buffers
+    UnloadDroppedFiles(droppedFiles); // Unload files memory
 
     CloseWindow();          // Close window and OpenGL context
     //--------------------------------------------------------------------------------------
diff --git a/examples/models/models_loading.c b/examples/models/models_loading.c
index 7d4543cdc..ee3811ee4 100644
--- a/examples/models/models_loading.c
+++ b/examples/models/models_loading.c
@@ -67,35 +67,34 @@ int main(void)
         // Load new models/textures on drag&drop
         if (IsFileDropped())
         {
-            int count = 0;
-            char **droppedFiles = LoadDroppedFiles(&count);
+            FilePathList droppedFiles = LoadDroppedFiles();
 
-            if (count == 1) // Only support one file dropped
+            if (droppedFiles.count == 1) // Only support one file dropped
             {
-                if (IsFileExtension(droppedFiles[0], ".obj") ||
-                    IsFileExtension(droppedFiles[0], ".gltf") ||
-                    IsFileExtension(droppedFiles[0], ".glb") ||
-                    IsFileExtension(droppedFiles[0], ".vox") ||
-                    IsFileExtension(droppedFiles[0], ".iqm"))       // Model file formats supported
+                if (IsFileExtension(droppedFiles.paths[0], ".obj") ||
+                    IsFileExtension(droppedFiles.paths[0], ".gltf") ||
+                    IsFileExtension(droppedFiles.paths[0], ".glb") ||
+                    IsFileExtension(droppedFiles.paths[0], ".vox") ||
+                    IsFileExtension(droppedFiles.paths[0], ".iqm"))       // Model file formats supported
                 {
-                    UnloadModel(model);                     // Unload previous model
-                    model = LoadModel(droppedFiles[0]);     // Load new model
+                    UnloadModel(model);                         // Unload previous model
+                    model = LoadModel(droppedFiles.paths[0]);   // Load new model
                     model.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = texture; // Set current map diffuse texture
 
                     bounds = GetMeshBoundingBox(model.meshes[0]);
 
                     // TODO: Move camera position from target enough distance to visualize model properly
                 }
-                else if (IsFileExtension(droppedFiles[0], ".png"))  // Texture file formats supported
+                else if (IsFileExtension(droppedFiles.paths[0], ".png"))  // Texture file formats supported
                 {
                     // Unload current model texture and load new one
                     UnloadTexture(texture);
-                    texture = LoadTexture(droppedFiles[0]);
+                    texture = LoadTexture(droppedFiles.paths[0]);
                     model.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = texture;
                 }
             }
 
-            UnloadDroppedFiles();    // Clear internal buffers
+            UnloadDroppedFiles(droppedFiles);    // Unload filepaths from memory
         }
 
         // Select model on mouse click
diff --git a/examples/models/models_skybox.c b/examples/models/models_skybox.c
index b5e0102d7..88202aeea 100644
--- a/examples/models/models_skybox.c
+++ b/examples/models/models_skybox.c
@@ -97,18 +97,17 @@ int main(void)
         // Load new cubemap texture on drag&drop
         if (IsFileDropped())
         {
-            int count = 0;
-            char **droppedFiles = LoadDroppedFiles(&count);
+            FilePathList droppedFiles = LoadDroppedFiles();
 
-            if (count == 1)         // Only support one file dropped
+            if (droppedFiles.count == 1)         // Only support one file dropped
             {
-                if (IsFileExtension(droppedFiles[0], ".png;.jpg;.hdr;.bmp;.tga"))
+                if (IsFileExtension(droppedFiles.paths[0], ".png;.jpg;.hdr;.bmp;.tga"))
                 {
                     // Unload current cubemap texture and load new one
                     UnloadTexture(skybox.materials[0].maps[MATERIAL_MAP_CUBEMAP].texture);
                     if (useHDR)
                     {
-                        Texture2D panorama = LoadTexture(droppedFiles[0]);
+                        Texture2D panorama = LoadTexture(droppedFiles.paths[0]);
 
                         // Generate cubemap from panorama texture
                         skybox.materials[0].maps[MATERIAL_MAP_CUBEMAP].texture = GenTextureCubemap(shdrCubemap, panorama, 1024, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8);
@@ -116,7 +115,7 @@ int main(void)
                     }
                     else
                     {
-                        Image img = LoadImage(droppedFiles[0]);
+                        Image img = LoadImage(droppedFiles.paths[0]);
                         skybox.materials[0].maps[MATERIAL_MAP_CUBEMAP].texture = LoadTextureCubemap(img, CUBEMAP_LAYOUT_AUTO_DETECT);
                         UnloadImage(img);
                     }
@@ -125,7 +124,7 @@ int main(void)
                 }
             }
 
-            UnloadDroppedFiles();    // Clear internal buffers
+            UnloadDroppedFiles(droppedFiles);    // Unload filepaths from memory
         }
         //----------------------------------------------------------------------------------
 
diff --git a/examples/text/text_draw_3d.c b/examples/text/text_draw_3d.c
index c82629dec..d4b057ec4 100644
--- a/examples/text/text_draw_3d.c
+++ b/examples/text/text_draw_3d.c
@@ -141,22 +141,22 @@ int main(void)
         // Handle font files dropped
         if (IsFileDropped())
         {
-            int count = 0;
-            char **droppedFiles = LoadDroppedFiles(&count);
+            FilePathList droppedFiles = LoadDroppedFiles();
 
             // NOTE: We only support first ttf file dropped
-            if (IsFileExtension(droppedFiles[0], ".ttf"))
+            if (IsFileExtension(droppedFiles.paths[0], ".ttf"))
             {
                 UnloadFont(font);
-                font = LoadFontEx(droppedFiles[0], fontSize, 0, 0);
+                font = LoadFontEx(droppedFiles.paths[0], fontSize, 0, 0);
             }
-            else if (IsFileExtension(droppedFiles[0], ".fnt"))
+            else if (IsFileExtension(droppedFiles.paths[0], ".fnt"))
             {
                 UnloadFont(font);
-                font = LoadFont(droppedFiles[0]);
+                font = LoadFont(droppedFiles.paths[0]);
                 fontSize = font.baseSize;
             }
-            UnloadDroppedFiles();
+            
+            UnloadDroppedFiles(droppedFiles);    // Unload filepaths from memory
         }
 
         // Handle Events
diff --git a/examples/text/text_font_filters.c b/examples/text/text_font_filters.c
index 5fb8fc471..32ae11a6b 100644
--- a/examples/text/text_font_filters.c
+++ b/examples/text/text_font_filters.c
@@ -79,16 +79,16 @@ int main(void)
         // Load a dropped TTF file dynamically (at current fontSize)
         if (IsFileDropped())
         {
-            int count = 0;
-            char **droppedFiles = LoadDroppedFiles(&count);
+            FilePathList droppedFiles = LoadDroppedFiles();
 
             // NOTE: We only support first ttf file dropped
-            if (IsFileExtension(droppedFiles[0], ".ttf"))
+            if (IsFileExtension(droppedFiles.paths[0], ".ttf"))
             {
                 UnloadFont(font);
-                font = LoadFontEx(droppedFiles[0], (int)fontSize, 0, 0);
-                UnloadDroppedFiles();
+                font = LoadFontEx(droppedFiles.paths[0], (int)fontSize, 0, 0);
             }
+            
+            UnloadDroppedFiles(droppedFiles);    // Unload filepaths from memory
         }
         //----------------------------------------------------------------------------------
 
diff --git a/src/raylib.h b/src/raylib.h
index f71f41050..488f6e43e 100644
--- a/src/raylib.h
+++ b/src/raylib.h
@@ -482,6 +482,12 @@ typedef struct VrStereoConfig {
     float scaleIn[2];               // VR distortion scale in
 } VrStereoConfig;
 
+// File path list
+typedef struct FilePathList {
+    unsigned int count;             // Filepaths entries count
+    char **paths;                   // Filepaths entries
+} FilePathList;
+
 //----------------------------------------------------------------------------------
 // Enumerators Definition
 //----------------------------------------------------------------------------------
@@ -891,8 +897,8 @@ typedef enum {
 typedef void (*TraceLogCallback)(int logLevel, const char *text, va_list args);  // Logging: Redirect trace log messages
 typedef unsigned char *(*LoadFileDataCallback)(const char *fileName, unsigned int *bytesRead);      // FileIO: Load binary data
 typedef bool (*SaveFileDataCallback)(const char *fileName, void *data, unsigned int bytesToWrite);  // FileIO: Save binary data
-typedef char *(*LoadFileTextCallback)(const char *fileName);       // FileIO: Load text data
-typedef bool (*SaveFileTextCallback)(const char *fileName, char *text);     // FileIO: Save text data
+typedef char *(*LoadFileTextCallback)(const char *fileName);            // FileIO: Load text data
+typedef bool (*SaveFileTextCallback)(const char *fileName, char *text); // FileIO: Save text data
 
 //------------------------------------------------------------------------------------
 // Global Variables Definition
@@ -1059,11 +1065,13 @@ RLAPI const char *GetPrevDirectoryPath(const char *dirPath);      // Get previou
 RLAPI const char *GetWorkingDirectory(void);                      // Get current working directory (uses static string)
 RLAPI const char *GetApplicationDirectory(void);                  // Get the directory if the running application (uses static string)
 RLAPI bool ChangeDirectory(const char *dir);                      // Change working directory, return true on success
-RLAPI char **LoadDirectoryFiles(const char *dirPath, int *count); // Load directory filepaths
-RLAPI void UnloadDirectoryFiles(void);                            // Unload directory filepaths
+RLAPI bool IsPathFile(const char *path);                          // Check if a given path is a file or a directory
+RLAPI FilePathList LoadDirectoryFiles(const char *dirPath);       // Load directory filepaths
+RLAPI FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool scanSubdirs); // Load directory filepaths with extension filtering and recursive directory scan
+RLAPI void UnloadDirectoryFiles(FilePathList files);              // Unload filepaths
 RLAPI bool IsFileDropped(void);                                   // Check if a file has been dropped into window
-RLAPI char **LoadDroppedFiles(int *count);                        // Load dropped filepaths
-RLAPI void UnloadDroppedFiles(void);                              // Unload dropped filepaths
+RLAPI FilePathList LoadDroppedFiles(void);                        // Load dropped filepaths
+RLAPI void UnloadDroppedFiles(FilePathList files);                // Unload dropped filepaths
 RLAPI long GetFileModTime(const char *fileName);                  // Get file modification time (last write time)
 
 // Compression/Encoding functionality
diff --git a/src/rcore.c b/src/rcore.c
index 44fd96c1e..8e32e2c20 100644
--- a/src/rcore.c
+++ b/src/rcore.c
@@ -183,7 +183,12 @@
 #include <time.h>                   // Required for: time() [Used in InitTimer()]
 #include <math.h>                   // Required for: tan() [Used in BeginMode3D()], atan2f() [Used in LoadVrStereoConfig()]
 
-#include <sys/stat.h>               // Required for: stat() [Used in GetFileModTime()]
+#define _CRT_INTERNAL_NONSTDC_NAMES  1
+#include <sys/stat.h>               // Required for: stat(), S_ISREG [Used in GetFileModTime(), IsFilePath()]
+
+#if !defined(S_ISREG) && defined(S_IFMT) && defined(S_IFREG)
+    #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
+#endif
 
 #if defined(PLATFORM_DESKTOP) && defined(_WIN32) && (defined(_MSC_VER) || defined(__TINYC__))
     #define DIRENT_MALLOC RL_MALLOC
@@ -294,11 +299,7 @@
 #endif
 
 #ifndef MAX_FILEPATH_LENGTH
-    #if defined(__linux__)
-        #define MAX_FILEPATH_LENGTH     4096        // Maximum length for filepaths (Linux PATH_MAX default value)
-    #else
-        #define MAX_FILEPATH_LENGTH      512        // Maximum length supported for filepaths
-    #endif
+    #define MAX_FILEPATH_LENGTH         4096        // Maximum length for filepaths (Linux PATH_MAX default value)
 #endif
 
 #ifndef MAX_KEYBOARD_KEYS
@@ -404,8 +405,8 @@ typedef struct CoreData {
         Point renderOffset;                 // Offset from render area (must be divided by 2)
         Matrix screenScale;                 // Matrix to scale screen (framebuffer rendering)
 
-        char **dropFilepaths;               // Store dropped files paths as strings
-        int dropFileCount;                  // Count dropped files strings
+        const char **dropFilepaths;         // Store dropped files paths pointers (provided by GLFW)
+        unsigned int dropFileCount;         // Count dropped files strings
 
     } Window;
 #if defined(PLATFORM_ANDROID)
@@ -501,13 +502,10 @@ typedef struct CoreData {
 //----------------------------------------------------------------------------------
 // Global Variables Definition
 //----------------------------------------------------------------------------------
-static CoreData CORE = { 0 };               // Global CORE state context
-
-static char **dirFilesPath = NULL;          // Store directory files paths as strings
-static int dirFileCount = 0;                // Count directory files strings
-
 const char *raylibVersion = RAYLIB_VERSION; // raylib version symbol, it could be required for some bindings
 
+static CoreData CORE = { 0 };               // Global CORE state context
+
 #if defined(SUPPORT_SCREEN_CAPTURE)
 static int screenshotCounter = 0;           // Screenshots counter
 #endif
@@ -622,6 +620,9 @@ static bool InitGraphicsDevice(int width, int height);  // Initialize graphics d
 static void SetupFramebuffer(int width, int height);    // Setup main framebuffer
 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);   // Scan all files and directories in a base path
+static void ScanDirectoryFilesRecursively(const char *basePath, FilePathList *list, const char *filter);  // Scan all files and directories recursively from a base path
+
 #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
 static void ErrorCallback(int error, const char *description);                             // GLFW3 Error Callback, runs on GLFW3 error
 // Window callbacks events
@@ -1418,6 +1419,13 @@ void SetWindowState(unsigned int flags)
     {
         TRACELOG(LOG_WARNING, "WINDOW: High DPI can only by configured before window initialization");
     }
+    
+    // State change: FLAG_WINDOW_MOUSE_PASSTHROUGH
+    if (((CORE.Window.flags & FLAG_WINDOW_MOUSE_PASSTHROUGH) != (flags & FLAG_WINDOW_MOUSE_PASSTHROUGH)) && ((flags & FLAG_WINDOW_MOUSE_PASSTHROUGH) > 0))
+    {
+        glfwSetWindowAttrib(CORE.Window.handle, GLFW_MOUSE_PASSTHROUGH, GLFW_TRUE);
+        CORE.Window.flags |= FLAG_WINDOW_MOUSE_PASSTHROUGH;
+    }
 
     // State change: FLAG_MSAA_4X_HINT
     if (((CORE.Window.flags & FLAG_MSAA_4X_HINT) != (flags & FLAG_MSAA_4X_HINT)) && ((flags & FLAG_MSAA_4X_HINT) > 0))
@@ -1519,6 +1527,13 @@ void ClearWindowState(unsigned int flags)
     {
         TRACELOG(LOG_WARNING, "WINDOW: High DPI can only by configured before window initialization");
     }
+    
+    // State change: FLAG_WINDOW_MOUSE_PASSTHROUGH
+    if (((CORE.Window.flags & FLAG_WINDOW_MOUSE_PASSTHROUGH) > 0) && ((flags & FLAG_WINDOW_MOUSE_PASSTHROUGH) > 0))
+    {
+        glfwSetWindowAttrib(CORE.Window.handle, GLFW_MOUSE_PASSTHROUGH, GLFW_FALSE);
+        CORE.Window.flags &= ~FLAG_WINDOW_MOUSE_PASSTHROUGH;
+    }
 
     // State change: FLAG_MSAA_4X_HINT
     if (((CORE.Window.flags & FLAG_MSAA_4X_HINT) > 0) && ((flags & FLAG_MSAA_4X_HINT) > 0))
@@ -3106,51 +3121,75 @@ const char *GetApplicationDirectory(void)
 }
 
 // Load directory filepaths
-// NOTE: Files count is returned by parameters pointer
-char **LoadDirectoryFiles(const char *dirPath, int *fileCount)
+// NOTE: Base path is prepended to the scanned filepaths
+// WARNING: Directory is scanned twice, first time to get files count
+// No recursive scanning is done!
+FilePathList LoadDirectoryFiles(const char *dirPath)
 {
-    UnloadDirectoryFiles();
-
-    int counter = 0;
+    FilePathList files = { 0 };
+    unsigned int fileCounter = 0;
+    
     struct dirent *entity;
     DIR *dir = opendir(dirPath);
 
     if (dir != NULL) // It's a directory
     {
-        // Count files
-        while ((entity = readdir(dir)) != NULL) counter++;
-
-        dirFileCount = counter;
-        *fileCount = dirFileCount;
+        // SCAN 1: Count files
+        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)) fileCounter++;
+        }
 
         // Memory allocation for dirFileCount
-        dirFilesPath = (char **)RL_MALLOC(dirFileCount*sizeof(char *));
-        for (int i = 0; i < dirFileCount; i++) dirFilesPath[i] = (char *)RL_MALLOC(MAX_FILEPATH_LENGTH*sizeof(char));
-
-        // Reset our position in the directory to the beginning
-        rewinddir(dir);
-
-        // Read file names
-        for (int i = 0; (entity = readdir(dir)) != NULL; i++) strcpy(dirFilesPath[i], entity->d_name);
+        files.paths = (char **)RL_MALLOC(fileCounter*sizeof(char *));
+        for (int i = 0; i < fileCounter; i++) files.paths[i] = (char *)RL_MALLOC(MAX_FILEPATH_LENGTH*sizeof(char));
 
         closedir(dir);
+        
+        // SCAN 2: Read filepaths
+        // NOTE: Directory paths are also registered
+        ScanDirectoryFiles(dirPath, &files, NULL);
+        
+        // Security check: read files.count should match fileCounter
+        if (files.count != fileCounter) TRACELOG(LOG_WARNING, "FILEIO: Read files count do not match memory allocated");
     }
     else TRACELOG(LOG_WARNING, "FILEIO: Failed to open requested directory");  // Maybe it's a file...
+    
+    
+    
+    return files;
+}
+
+// Load directory filepaths with extension filtering and recursive directory scan
+FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool scanSubdirs)
+{
+    #define MAX_FILEPATH_COUNT         8192     // Maximum file paths scanned
+
+    FilePathList files = { 0 };
+
+    files.paths = (char **)RL_CALLOC(MAX_FILEPATH_COUNT, sizeof(char *));
+    for (int i = 0; i < MAX_FILEPATH_COUNT; i++) files.paths[i] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char));
 
-    return dirFilesPath;
+    // WARNING: basePath is always prepended to scanned paths
+    if (scanSubdirs) ScanDirectoryFilesRecursively(basePath, &files, filter);
+    else ScanDirectoryFiles(basePath, &files, filter);
+    
+    // TODO: Filepath filtering
+    //if (IsFileExtension(files.paths[i], filter))
+
+    return files;
 }
 
 // Unload directory filepaths
-void UnloadDirectoryFiles(void)
+void UnloadDirectoryFiles(FilePathList files)
 {
-    if (dirFileCount > 0)
+    if (files.count > 0)
     {
-        for (int i = 0; i < dirFileCount; i++) RL_FREE(dirFilesPath[i]);
+        for (int i = 0; i < files.count; i++) RL_FREE(files.paths[i]);
 
-        RL_FREE(dirFilesPath);
+        RL_FREE(files.paths);
     }
-
-    dirFileCount = 0;
 }
 
 // Change working directory, returns true on success
@@ -3163,6 +3202,15 @@ bool ChangeDirectory(const char *dir)
     return (result == 0);
 }
 
+// Check if a given path point to a file
+bool IsPathFile(const char *path)
+{
+    struct stat pathStat = { 0 };
+    stat(path, &pathStat);
+
+    return S_ISREG(pathStat.st_mode);
+}
+
 // Check if a file has been dropped into window
 bool IsFileDropped(void)
 {
@@ -3171,22 +3219,37 @@ bool IsFileDropped(void)
 }
 
 // Load dropped filepaths
-char **LoadDroppedFiles(int *count)
+FilePathList LoadDroppedFiles(void)
 {
-    *count = CORE.Window.dropFileCount;
-    return CORE.Window.dropFilepaths;
+    FilePathList files = { 0 };
+
+    if (CORE.Window.dropFileCount > 0)
+    {
+        files.count = CORE.Window.dropFileCount;
+        files.paths = (char **)RL_CALLOC(files.count, sizeof(char *));
+        
+        for (int i = 0; i < files.count; i++) 
+        {
+            files.paths[i] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char));
+            strcpy(files.paths[i], CORE.Window.dropFilepaths[i]);
+        }
+        
+        // WARNING: We reset drop file count after loading the stored paths,
+        // despite internally GLFW probably keeps the pointers until next drop
+        CORE.Window.dropFileCount;
+    }
+
+    return files;
 }
 
 // Unload dropped filepaths
-void UnloadDroppedFiles(void)
+void UnloadDroppedFiles(FilePathList files)
 {
-    if (CORE.Window.dropFileCount > 0)
+    if (files.count > 0)
     {
-        for (int i = 0; i < CORE.Window.dropFileCount; i++) RL_FREE(CORE.Window.dropFilepaths[i]);
-
-        RL_FREE(CORE.Window.dropFilepaths);
+        for (int i = 0; i < files.count; i++) RL_FREE(files.paths[i]);
 
-        CORE.Window.dropFileCount = 0;
+        RL_FREE(files.paths);
     }
 }
 
@@ -5168,6 +5231,90 @@ void PollInputEvents(void)
 #endif
 }
 
+// Scan all files and directories in a base path
+// WARNING: files.paths[] must be previously allocated and 
+// contain enough space to store all required paths
+static void ScanDirectoryFiles(const char *basePath, FilePathList *files, const char *filter)
+{
+    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)
+        {
+            if ((strcmp(dp->d_name, ".") != 0) &&
+                (strcmp(dp->d_name, "..") != 0))
+            {
+                sprintf(path, "%s/%s", basePath, dp->d_name);
+                
+                if (filter != NULL)
+                {
+                    if (IsFileExtension(path, filter))
+                    {
+                        strcpy(files->paths[files->count], path);
+                        files->count++;
+                    }
+                }
+                else
+                {
+                    strcpy(files->paths[files->count], path);
+                    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
+static void ScanDirectoryFilesRecursively(const char *basePath, FilePathList *files, const char *filter)
+{
+    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)
+        {
+            if ((strcmp(dp->d_name, ".") != 0) && (strcmp(dp->d_name, "..") != 0))
+            {
+                // Construct new path from our base path
+                sprintf(path, "%s/%s", basePath, dp->d_name);
+
+                if (IsPathFile(path))
+                {
+                    if (filter != NULL)
+                    {
+                        if (IsFileExtension(path, filter))
+                        {
+                            strcpy(files->paths[files->count], path);
+                            files->count++;
+                        }
+                    }
+                    else
+                    {
+                        strcpy(files->paths[files->count], path);
+                        files->count++;
+                    }
+                }
+                else ScanDirectoryFilesRecursively(path, files, filter);
+            }
+        }
+
+        closedir(dir);
+    }
+    else TRACELOG(LOG_WARNING, "FILEIO: Directory cannot be opened (%s)", basePath);
+}
+
 #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
 // GLFW3 Error Callback, runs on GLFW3 error
 static void ErrorCallback(int error, const char *description)
@@ -5418,16 +5565,7 @@ static void CursorEnterCallback(GLFWwindow *window, int enter)
 // Everytime new files are dropped, old ones are discarded
 static void WindowDropCallback(GLFWwindow *window, int count, const char **paths)
 {
-    UnloadDroppedFiles();
-
-    CORE.Window.dropFilepaths = (char **)RL_MALLOC(count*sizeof(char *));
-
-    for (int i = 0; i < count; i++)
-    {
-        CORE.Window.dropFilepaths[i] = (char *)RL_MALLOC(MAX_FILEPATH_LENGTH*sizeof(char));
-        strcpy(CORE.Window.dropFilepaths[i], paths[i]);
-    }
-
+    CORE.Window.dropFilepaths = paths;
     CORE.Window.dropFileCount = count;
 }
 #endif