Support screenshots and GIF capturing on Android and Web
This commit is contained in:
parent
490e930665
commit
a41cc08f9b
74
src/core.c
74
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,10 +3174,9 @@ 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)
|
||||||
@ -3169,6 +3184,12 @@ static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, i
|
|||||||
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");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -3176,24 +3197,31 @@ 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
|
#endif // SUPPORT_GIF_RECORDING
|
||||||
#if defined(SUPPORT_SCREEN_CAPTURE)
|
#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
|
||||||
|
Loading…
Reference in New Issue
Block a user