summaryrefslogtreecommitdiffhomepage
path: root/src/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core.c')
-rw-r--r--src/core.c169
1 files changed, 95 insertions, 74 deletions
diff --git a/src/core.c b/src/core.c
index 50666335..c84610ba 100644
--- a/src/core.c
+++ b/src/core.c
@@ -175,11 +175,9 @@
#include <GLFW/glfw3native.h> // Required for: glfwGetX11Window()
#elif defined(__APPLE__)
#include <unistd.h> // Required for: usleep()
- #include <objc/message.h> // Required for: objc_msgsend(), sel_registerName()
//#define GLFW_EXPOSE_NATIVE_COCOA // WARNING: Fails due to type redefinition
- #define GLFW_EXPOSE_NATIVE_NSGL
- #include <GLFW/glfw3native.h> // Required for: glfwGetCocoaWindow(), glfwGetNSGLContext()
+ #include <GLFW/glfw3native.h> // Required for: glfwGetCocoaWindow()
#endif
#endif
@@ -277,10 +275,6 @@ static bool windowReady = false; // Check if window has been init
static bool windowMinimized = false; // Check if window has been minimized
static const char *windowTitle = NULL; // Window text title...
-#if defined(__APPLE__)
-static int windowNeedsUpdating = 2; // Times the Cocoa window needs to be updated initially
-#endif
-
static unsigned int displayWidth, displayHeight;// Display width and height (monitor, device-screen, LCD, ...)
static int screenWidth, screenHeight; // Screen width and height (used render area)
static int renderWidth, renderHeight; // Framebuffer width and height (render area, including black bars if required)
@@ -311,7 +305,7 @@ extern EGLNativeWindowType uwpWindow; // Native EGL window handler for
static struct android_app *androidApp; // Android activity
static struct android_poll_source *source; // Android events polling source
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 contextRebindRequired = false; // Used to know context rebind required
@@ -332,8 +326,9 @@ static int defaultKeyboardMode; // Used to store default keyboar
#endif
// Mouse states
-static Vector2 mousePosition; // Mouse position on screen
-static float mouseScale = 1.0f; // Mouse default scale
+static Vector2 mousePosition = { 0.0f, 0.0f }; // Mouse position on screen
+static Vector2 mouseScale = { 1.0f, 1.0f }; // Mouse scaling
+static Vector2 mouseOffset = { 0.0f, 0.0f }; // Mouse offset
static bool cursorHidden = false; // Track if cursor is hidden
static bool cursorOnScreen = false; // Tracks if cursor is inside client area
static Vector2 touchPosition[MAX_TOUCH_POINTS]; // Touch position on screen
@@ -1485,12 +1480,6 @@ Color Fade(Color color, float alpha)
return (Color){color.r, color.g, color.b, (unsigned char)(255.0f*alpha)};
}
-// Activate raylib logo at startup (can be done with flags)
-void ShowLogo(void)
-{
- showLogo = true;
-}
-
// Setup window configuration flags (view FLAGS)
void SetConfigFlags(unsigned char flags)
{
@@ -1503,17 +1492,32 @@ void SetConfigFlags(unsigned char flags)
// NOTE TraceLog() function is located in [utils.h]
// 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)
{
-#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI)
unsigned char *imgData = rlReadScreenPixels(renderWidth, renderHeight);
-
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);
-
- 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
+
+ TraceLog(LOG_INFO, "Screenshot taken: %s", path);
}
// Check if the file exists
@@ -1522,11 +1526,10 @@ bool FileExists(const char *fileName)
bool result = false;
#if defined(_WIN32)
- if (_access(fileName, 0) != -1)
+ if (_access(fileName, 0) != -1) result = true;
#else
- if (access(fileName, F_OK) != -1)
+ if (access(fileName, F_OK) != -1) result = true;
#endif
- result = true;
return result;
}
@@ -1539,7 +1542,7 @@ bool IsFileExtension(const char *fileName, const char *ext)
if ((fileExt = strrchr(fileName, '.')) != NULL)
{
- #if defined(_WIN32)
+#if defined(_WIN32)
result = true;
int extLen = strlen(ext);
@@ -1555,9 +1558,9 @@ bool IsFileExtension(const char *fileName, const char *ext)
}
}
else result = false;
- #else
+#else
if (strcmp(fileExt, ext) == 0) result = true;
- #endif
+#endif
}
return result;
@@ -1759,7 +1762,7 @@ void StorageSaveValue(int position, int value)
{
FILE *storageFile = NULL;
- char path[128];
+ char path[512] = { 0 };
#if defined(PLATFORM_ANDROID)
strcpy(path, internalDataPath);
strcat(path, "/");
@@ -1799,7 +1802,7 @@ int StorageLoadValue(int position)
{
int value = 0;
- char path[128];
+ char path[512] = { 0 };
#if defined(PLATFORM_ANDROID)
strcpy(path, internalDataPath);
strcat(path, "/");
@@ -1844,7 +1847,9 @@ void OpenURL(const char *url)
if (strchr(url, '\'') != NULL)
{
TraceLog(LOG_WARNING, "Provided URL does not seem to be valid.");
- } else {
+ }
+ else
+ {
char *cmd = calloc(strlen(url) + 10, sizeof(char));
#if defined(_WIN32)
@@ -2100,7 +2105,7 @@ int GetMouseX(void)
#if defined(PLATFORM_ANDROID)
return (int)touchPosition[0].x;
#else
- return (int)(mousePosition.x*mouseScale);
+ return (int)((mousePosition.x + mouseOffset.x)*mouseScale.x);
#endif
}
@@ -2110,7 +2115,7 @@ int GetMouseY(void)
#if defined(PLATFORM_ANDROID)
return (int)touchPosition[0].x;
#else
- return (int)(mousePosition.y*mouseScale);
+ return (int)((mousePosition.y + mouseOffset.y)*mouseScale.y);
#endif
}
@@ -2120,27 +2125,32 @@ Vector2 GetMousePosition(void)
#if defined(PLATFORM_ANDROID)
return GetTouchPosition(0);
#else
- return (Vector2){ mousePosition.x*mouseScale, mousePosition.y*mouseScale };
+ return (Vector2){ (mousePosition.x + mouseOffset.x)*mouseScale.x, (mousePosition.y + mouseOffset.y)*mouseScale.y };
#endif
}
// Set mouse position XY
-void SetMousePosition(Vector2 position)
+void SetMousePosition(int x, int y)
{
- mousePosition = position;
+ mousePosition = (Vector2){ (float)x, (float)y };
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
// NOTE: emscripten not implemented
- glfwSetCursorPos(window, position.x, position.y);
+ glfwSetCursorPos(window, mousePosition.x, mousePosition.y);
#endif
}
+// Set mouse offset
+// NOTE: Useful when rendering to different size targets
+void SetMouseOffset(int offsetX, int offsetY)
+{
+ mouseOffset = (Vector2){ (float)offsetX, (float)offsetY };
+}
+
// Set mouse scaling
// NOTE: Useful when rendering to different size targets
-void SetMouseScale(float scale)
+void SetMouseScale(float scaleX, float scaleY)
{
-#if !defined(PLATFORM_ANDROID)
- mouseScale = scale;
-#endif
+ mouseScale = (Vector2){ scaleX, scaleY };
}
// Returns mouse wheel movement Y
@@ -2278,8 +2288,8 @@ static bool InitGraphicsDevice(int width, int height)
if (configFlags & FLAG_WINDOW_RESIZABLE) glfwWindowHint(GLFW_RESIZABLE, GL_TRUE); // Resizable window
else glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); // Avoid window being resizable
- if (configFlags & FLAG_WINDOW_UNDECORATED) glfwWindowHint(GLFW_DECORATED, GL_FALSE); // Border and buttons on Window
- else glfwWindowHint(GLFW_DECORATED, GL_TRUE); // Decorated window
+ if (configFlags & FLAG_WINDOW_UNDECORATED) glfwWindowHint(GLFW_DECORATED, GLFW_FALSE); // Border and buttons on Window
+ else glfwWindowHint(GLFW_DECORATED, GLFW_TRUE); // Decorated window
// FLAG_WINDOW_TRANSPARENT not supported on HTML5 and not included in any released GLFW version yet
#if defined(GLFW_TRANSPARENT_FRAMEBUFFER)
if (configFlags & FLAG_WINDOW_TRANSPARENT) glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE); // Transparent framebuffer
@@ -2295,21 +2305,28 @@ static bool InitGraphicsDevice(int width, int height)
// Check selection OpenGL version
if (rlGetVersion() == OPENGL_21)
{
- glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2); // Choose OpenGL major version (just hint)
- glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); // Choose OpenGL minor version (just hint)
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2); // Choose OpenGL major version (just hint)
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); // Choose OpenGL minor version (just hint)
}
else if (rlGetVersion() == OPENGL_33)
{
- glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // Choose OpenGL major version (just hint)
- glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); // Choose OpenGL minor version (just hint)
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // Choose OpenGL major version (just hint)
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); // Choose OpenGL minor version (just hint)
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // Profiles Hint: Only 3.3 and above!
// Values: GLFW_OPENGL_CORE_PROFILE, GLFW_OPENGL_ANY_PROFILE, GLFW_OPENGL_COMPAT_PROFILE
#if defined(__APPLE__)
- glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // OSX Requires fordward compatibility
+ glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE); // OSX Requires fordward compatibility
#else
- glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_FALSE); // Fordward Compatibility Hint: Only 3.3 and above!
+ glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_FALSE); // Fordward Compatibility Hint: Only 3.3 and above!
#endif
- //glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE); // Request OpenGL DEBUG context
+ //glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE); // Request OpenGL DEBUG context
+ }
+ else if (rlGetVersion() == OPENGL_ES_20) // Request OpenGL ES 2.0 context
+ {
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
+ glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
+ glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_NATIVE_CONTEXT_API); // Alternative: GLFW_EGL_CONTEXT_API (ANGLE)
}
if (fullscreen)
@@ -2402,7 +2419,9 @@ static bool InitGraphicsDevice(int width, int height)
// Try to disable GPU V-Sync by default, set framerate using SetTargetFPS()
// NOTE: V-Sync can be enabled by graphic driver configuration
+#if !defined(PLATFORM_WEB)
glfwSwapInterval(0);
+#endif
#if defined(PLATFORM_DESKTOP)
// Load OpenGL 3.3 extensions
@@ -3138,16 +3157,6 @@ static void SwapBuffers(void)
{
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
glfwSwapBuffers(window);
-#if __APPLE__
- // Workaround for missing/erroneous initial rendering on macOS
- if (windowNeedsUpdating)
- {
- // Desugared version of Objective C: [glfwGetNSGLContext(window) update]
- ((id (*)(id, SEL))objc_msgSend)(glfwGetNSGLContext(window), sel_registerName("update"));
-
- windowNeedsUpdating--;
- }
-#endif
#endif
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) || defined(PLATFORM_UWP)
@@ -3173,20 +3182,25 @@ static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, i
{
if (key == exitKey && action == GLFW_PRESS)
{
- glfwSetWindowShouldClose(window, GL_TRUE);
+ glfwSetWindowShouldClose(window, GLFW_TRUE);
// NOTE: Before closing window, while loop must be left!
}
-#if defined(PLATFORM_DESKTOP)
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 (gifRecording)
{
GifEnd();
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");
}
@@ -3194,25 +3208,32 @@ static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, i
{
gifRecording = true;
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
// 10 game frames and each frame trakes 16.6ms (60fps), delay between gif frames should be ~16.6*10.
- GifBegin(FormatText("screenrec%03i.gif", screenshotCounter), screenWidth, screenHeight, (int)(GetFrameTime()*10.0f), 8, false);
+ GifBegin(path, screenWidth, screenHeight, (int)(GetFrameTime()*10.0f), 8, false);
screenshotCounter++;
- TraceLog(LOG_INFO, "Begin animated GIF recording: %s", FormatText("screenrec%03i.gif", screenshotCounter));
+ TraceLog(LOG_INFO, "Begin animated GIF recording: %s", TextFormat("screenrec%03i.gif", screenshotCounter));
}
}
else
- #endif // SUPPORT_GIF_RECORDING
- #if defined(SUPPORT_SCREEN_CAPTURE)
+#endif // SUPPORT_GIF_RECORDING
+#if defined(SUPPORT_SCREEN_CAPTURE)
{
- TakeScreenshot(FormatText("screenshot%03i.png", screenshotCounter));
+ TakeScreenshot(TextFormat("screenshot%03i.png", screenshotCounter));
screenshotCounter++;
}
- #endif // SUPPORT_SCREEN_CAPTURE
+#endif // SUPPORT_SCREEN_CAPTURE
}
-#endif // PLATFORM_DESKTOP
else
{
currentKeyState[key] = action;
@@ -3394,11 +3415,11 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
// Init hi-res timer
InitTimer();
- #if defined(SUPPORT_DEFAULT_FONT)
+ #if defined(SUPPORT_DEFAULT_FONT)
// Load default font
// NOTE: External function (defined in module: text)
LoadDefaultFont();
- #endif
+ #endif
// TODO: GPU assets reload in case of lost focus (lost context)
// NOTE: This problem has been solved just unbinding and rebinding context from display
@@ -4246,10 +4267,10 @@ static void *EventThread(void *arg)
// Screen confinement
if (mousePosition.x < 0) mousePosition.x = 0;
- if (mousePosition.x > screenWidth/mouseScale) mousePosition.x = screenWidth/mouseScale;
+ if (mousePosition.x > screenWidth/mouseScale.x) mousePosition.x = screenWidth/mouseScale.x;
if (mousePosition.y < 0) mousePosition.y = 0;
- if (mousePosition.y > screenHeight/mouseScale) mousePosition.y = screenHeight/mouseScale;
+ if (mousePosition.y > screenHeight/mouseScale.y) mousePosition.y = screenHeight/mouseScale.y;
// Gesture update
if (GestureNeedsUpdate)
@@ -4475,7 +4496,7 @@ static void LogoAnimation(void)
DrawRectangle(screenWidth/2 - 112, screenHeight/2 - 112, 224, 224, Fade(RAYWHITE, alpha));
- DrawText(SubText("raylib", 0, lettersCount), screenWidth/2 - 44, screenHeight/2 + 48, 50, Fade(BLACK, alpha));
+ DrawText(TextSubtext("raylib", 0, lettersCount), screenWidth/2 - 44, screenHeight/2 + 48, 50, Fade(BLACK, alpha));
}
EndDrawing();