Browse Source

Support screenshots and GIF capturing on Android and Web

raysan5 6 years ago
parent
commit
a41cc08f9b
1 changed files with 52 additions and 24 deletions
  1. 52 24
      src/core.c

+ 52 - 24
src/core.c

@@ -311,7 +311,7 @@ extern EGLNativeWindowType uwpWindow;           // Native EGL window handler for
 static struct android_app *androidApp;          // Android activity
 static struct android_app *androidApp;          // Android activity
 static struct android_poll_source *source;      // Android events polling source
 static struct android_poll_source *source;      // Android events polling source
 static int ident, events;                       // Android ALooper_pollAll() variables
 static int ident, events;                       // Android ALooper_pollAll() variables
-static const char *internalDataPath;            // Android internal data path to write data (/data/data/<package>/files)
+static const char *internalDataPath = NULL;     // Android internal data path to write data (/data/data/<package>/files)
 
 
 static bool appEnabled = true;                  // Used to detec if app is active
 static bool appEnabled = true;                  // Used to detec if app is active
 static bool contextRebindRequired = false;      // Used to know context rebind required
 static bool contextRebindRequired = false;      // Used to know context rebind required
@@ -1473,17 +1473,32 @@ void SetConfigFlags(unsigned char flags)
 // NOTE TraceLog() function is located in [utils.h]
 // NOTE TraceLog() function is located in [utils.h]
 
 
 // Takes a screenshot of current screen (saved a .png)
 // Takes a screenshot of current screen (saved a .png)
+// NOTE: This function could work in any platform but some platforms: PLATFORM_ANDROID and PLATFORM_WEB
+// have their own internal file-systems, to dowload image to user file-system some additional mechanism is required
 void TakeScreenshot(const char *fileName)
 void TakeScreenshot(const char *fileName)
 {
 {
-#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI)
     unsigned char *imgData = rlReadScreenPixels(renderWidth, renderHeight);
     unsigned char *imgData = rlReadScreenPixels(renderWidth, renderHeight);
-
     Image image = { imgData, renderWidth, renderHeight, 1, UNCOMPRESSED_R8G8B8A8 };
     Image image = { imgData, renderWidth, renderHeight, 1, UNCOMPRESSED_R8G8B8A8 };
-    ExportImage(image, fileName);
+    
+    char path[512] = { 0 };
+#if defined(PLATFORM_ANDROID)
+    strcpy(path, internalDataPath);
+    strcat(path, "/");
+    strcat(path, fileName);
+#else
+    strcpy(path, fileName);
+#endif
+    
+    ExportImage(image, path);
     free(imgData);
     free(imgData);
-
-    TraceLog(LOG_INFO, "Screenshot taken: %s", fileName);
+    
+#if defined(PLATFORM_WEB)
+    // Download file from MEMFS (emscripten memory filesystem)
+    // SaveFileFromMEMFSToDisk() function is defined in raylib/templates/web_shel/shell.html
+    emscripten_run_script(TextFormat("SaveFileFromMEMFSToDisk('%s','%s')", GetFileName(path), GetFileName(path)));
 #endif
 #endif
+
+    TraceLog(LOG_INFO, "Screenshot taken: %s", path);
 }
 }
 
 
 // Check if the file exists
 // Check if the file exists
@@ -1492,11 +1507,10 @@ bool FileExists(const char *fileName)
     bool result = false;
     bool result = false;
 
 
 #if defined(_WIN32)
 #if defined(_WIN32)
-    if (_access(fileName, 0) != -1)
+    if (_access(fileName, 0) != -1) result = true;
 #else
 #else
-    if (access(fileName, F_OK) != -1)
+    if (access(fileName, F_OK) != -1) result = true;
 #endif
 #endif
-        result = true;
 
 
     return result;
     return result;
 }
 }
@@ -1509,7 +1523,7 @@ bool IsFileExtension(const char *fileName, const char *ext)
 
 
     if ((fileExt = strrchr(fileName, '.')) != NULL)
     if ((fileExt = strrchr(fileName, '.')) != NULL)
     {
     {
-    #if defined(_WIN32)
+#if defined(_WIN32)
         result = true;
         result = true;
         int extLen = strlen(ext);
         int extLen = strlen(ext);
 
 
@@ -1525,9 +1539,9 @@ bool IsFileExtension(const char *fileName, const char *ext)
             }
             }
         }
         }
         else result = false;
         else result = false;
-    #else
+#else
         if (strcmp(fileExt, ext) == 0) result = true;
         if (strcmp(fileExt, ext) == 0) result = true;
-    #endif
+#endif
     }
     }
 
 
     return result;
     return result;
@@ -1729,7 +1743,7 @@ void StorageSaveValue(int position, int value)
 {
 {
     FILE *storageFile = NULL;
     FILE *storageFile = NULL;
 
 
-    char path[128];
+    char path[512] = { 0 };
 #if defined(PLATFORM_ANDROID)
 #if defined(PLATFORM_ANDROID)
     strcpy(path, internalDataPath);
     strcpy(path, internalDataPath);
     strcat(path, "/");
     strcat(path, "/");
@@ -1769,7 +1783,7 @@ int StorageLoadValue(int position)
 {
 {
     int value = 0;
     int value = 0;
 
 
-    char path[128];
+    char path[512] = { 0 };
 #if defined(PLATFORM_ANDROID)
 #if defined(PLATFORM_ANDROID)
     strcpy(path, internalDataPath);
     strcpy(path, internalDataPath);
     strcat(path, "/");
     strcat(path, "/");
@@ -1814,7 +1828,9 @@ void OpenURL(const char *url)
     if (strchr(url, '\'') != NULL)
     if (strchr(url, '\'') != NULL)
     {
     {
         TraceLog(LOG_WARNING, "Provided URL does not seem to be valid.");
         TraceLog(LOG_WARNING, "Provided URL does not seem to be valid.");
-    } else {
+    } 
+    else 
+    {
         char *cmd = calloc(strlen(url) + 10, sizeof(char));
         char *cmd = calloc(strlen(url) + 10, sizeof(char));
 
 
 #if defined(_WIN32)
 #if defined(_WIN32)
@@ -3158,16 +3174,21 @@ static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, i
 
 
         // NOTE: Before closing window, while loop must be left!
         // NOTE: Before closing window, while loop must be left!
     }
     }
-#if defined(PLATFORM_DESKTOP)
     else if (key == GLFW_KEY_F12 && action == GLFW_PRESS)
     else if (key == GLFW_KEY_F12 && action == GLFW_PRESS)
     {
     {
-    #if defined(SUPPORT_GIF_RECORDING)
+#if defined(SUPPORT_GIF_RECORDING)
         if (mods == GLFW_MOD_CONTROL)
         if (mods == GLFW_MOD_CONTROL)
         {
         {
             if (gifRecording)
             if (gifRecording)
             {
             {
                 GifEnd();
                 GifEnd();
                 gifRecording = false;
                 gifRecording = false;
+                
+            #if defined(PLATFORM_WEB)
+                // Download file from MEMFS (emscripten memory filesystem)
+                // SaveFileFromMEMFSToDisk() function is defined in raylib/templates/web_shel/shell.html
+                emscripten_run_script(TextFormat("SaveFileFromMEMFSToDisk('%s','%s')", TextFormat("screenrec%03i.gif", screenshotCounter - 1), TextFormat("screenrec%03i.gif", screenshotCounter - 1)));
+            #endif
 
 
                 TraceLog(LOG_INFO, "End animated GIF recording");
                 TraceLog(LOG_INFO, "End animated GIF recording");
             }
             }
@@ -3175,25 +3196,32 @@ static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, i
             {
             {
                 gifRecording = true;
                 gifRecording = true;
                 gifFramesCounter = 0;
                 gifFramesCounter = 0;
+                
+                char path[512] = { 0 };
+            #if defined(PLATFORM_ANDROID)
+                strcpy(path, internalDataPath);
+                strcat(path, TextFormat("/screenrec%03i.gif", screenshotCounter));
+            #else
+                strcpy(path, TextFormat("/screenrec%03i.gif", screenshotCounter));
+            #endif
 
 
                 // NOTE: delay represents the time between frames in the gif, if we capture a gif frame every
                 // NOTE: delay represents the time between frames in the gif, if we capture a gif frame every
                 // 10 game frames and each frame trakes 16.6ms (60fps), delay between gif frames should be ~16.6*10.
                 // 10 game frames and each frame trakes 16.6ms (60fps), delay between gif frames should be ~16.6*10.
-                GifBegin(TextFormat("screenrec%03i.gif", screenshotCounter), screenWidth, screenHeight, (int)(GetFrameTime()*10.0f), 8, false);
+                GifBegin(path, screenWidth, screenHeight, (int)(GetFrameTime()*10.0f), 8, false);
                 screenshotCounter++;
                 screenshotCounter++;
 
 
                 TraceLog(LOG_INFO, "Begin animated GIF recording: %s", TextFormat("screenrec%03i.gif", screenshotCounter));
                 TraceLog(LOG_INFO, "Begin animated GIF recording: %s", TextFormat("screenrec%03i.gif", screenshotCounter));
             }
             }
         }
         }
         else
         else
-    #endif  // SUPPORT_GIF_RECORDING
-    #if defined(SUPPORT_SCREEN_CAPTURE)
+#endif  // SUPPORT_GIF_RECORDING
+#if defined(SUPPORT_SCREEN_CAPTURE)
         {
         {
             TakeScreenshot(TextFormat("screenshot%03i.png", screenshotCounter));
             TakeScreenshot(TextFormat("screenshot%03i.png", screenshotCounter));
             screenshotCounter++;
             screenshotCounter++;
         }
         }
-    #endif  // SUPPORT_SCREEN_CAPTURE
+#endif  // SUPPORT_SCREEN_CAPTURE
     }
     }
-#endif  // PLATFORM_DESKTOP
     else
     else
     {
     {
         currentKeyState[key] = action;
         currentKeyState[key] = action;
@@ -3375,11 +3403,11 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
                     // Init hi-res timer
                     // Init hi-res timer
                     InitTimer();
                     InitTimer();
 
 
-                    #if defined(SUPPORT_DEFAULT_FONT)
+                #if defined(SUPPORT_DEFAULT_FONT)
                     // Load default font
                     // Load default font
                     // NOTE: External function (defined in module: text)
                     // NOTE: External function (defined in module: text)
                     LoadDefaultFont();
                     LoadDefaultFont();
-                    #endif
+                #endif
 
 
                     // TODO: GPU assets reload in case of lost focus (lost context)
                     // TODO: GPU assets reload in case of lost focus (lost context)
                     // NOTE: This problem has been solved just unbinding and rebinding context from display
                     // NOTE: This problem has been solved just unbinding and rebinding context from display