Merge branch 'master' into mikes-input
This commit is contained in:
commit
32576c398c
|
|
@ -81,6 +81,7 @@ Some people ported raylib to other languages in form of bindings or wrappers to
|
||||||
| rayed-bqn | **auto** | [BQN](https://mlochbaum.github.io/BQN/) | MIT | https://github.com/Brian-ED/rayed-bqn |
|
| rayed-bqn | **auto** | [BQN](https://mlochbaum.github.io/BQN/) | MIT | https://github.com/Brian-ED/rayed-bqn |
|
||||||
| rayjs | 4.6-dev | [QuickJS](https://bellard.org/quickjs/) | MIT | https://github.com/mode777/rayjs |
|
| rayjs | 4.6-dev | [QuickJS](https://bellard.org/quickjs/) | MIT | https://github.com/mode777/rayjs |
|
||||||
| raylib-raku | **auto** | [Raku](https://www.raku.org/) | Artistic License 2.0 | https://github.com/vushu/raylib-raku |
|
| raylib-raku | **auto** | [Raku](https://www.raku.org/) | Artistic License 2.0 | https://github.com/vushu/raylib-raku |
|
||||||
|
| Raylib.lean | 4.5 | [Lean4](https://lean-lang.org/) | BSD-3-Clause | https://github.com/KislyjKisel/Raylib.lean |
|
||||||
|
|
||||||
### Utility Wrapers
|
### Utility Wrapers
|
||||||
These are utility wrappers for specific languages, they are not required to use raylib in the language but may adapt the raylib API to be more inline with the language's pardigm.
|
These are utility wrappers for specific languages, they are not required to use raylib in the language but may adapt the raylib API to be more inline with the language's pardigm.
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const raylib = @import("src/build.zig");
|
const raylib = @import("src/build.zig");
|
||||||
|
|
||||||
// This has been tested to work with zig master branch as of commit 87de821 or May 14 2023
|
// This has been tested to work with zig 0.11.0 (67709b6, Aug 4 2023)
|
||||||
pub fn build(b: *std.Build) void {
|
pub fn build(b: *std.Build) void {
|
||||||
raylib.build(b);
|
raylib.build(b);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
|
|
||||||
// This has been tested to work with zig master branch as of commit 87de821 or May 14 2023
|
// This has been tested to work with zig 0.11.0 (67709b6, Aug 4 2023)
|
||||||
fn add_module(comptime module: []const u8, b: *std.Build, target: std.zig.CrossTarget, optimize: std.builtin.OptimizeMode) !*std.Build.Step {
|
fn add_module(comptime module: []const u8, b: *std.Build, target: std.zig.CrossTarget, optimize: std.builtin.OptimizeMode) !*std.Build.Step {
|
||||||
if (target.getOsTag() == .emscripten) {
|
if (target.getOsTag() == .emscripten) {
|
||||||
@panic("Emscripten building via Zig unsupported");
|
@panic("Emscripten building via Zig unsupported");
|
||||||
|
|
@ -11,7 +11,7 @@ fn add_module(comptime module: []const u8, b: *std.Build, target: std.zig.CrossT
|
||||||
const dir = try std.fs.cwd().openIterableDir(module, .{});
|
const dir = try std.fs.cwd().openIterableDir(module, .{});
|
||||||
var iter = dir.iterate();
|
var iter = dir.iterate();
|
||||||
while (try iter.next()) |entry| {
|
while (try iter.next()) |entry| {
|
||||||
if (entry.kind != .File) continue;
|
if (entry.kind != .file) continue;
|
||||||
const extension_idx = std.mem.lastIndexOf(u8, entry.name, ".c") orelse continue;
|
const extension_idx = std.mem.lastIndexOf(u8, entry.name, ".c") orelse continue;
|
||||||
const name = entry.name[0..extension_idx];
|
const name = entry.name[0..extension_idx];
|
||||||
const path = try std.fs.path.join(b.allocator, &.{ module, entry.name });
|
const path = try std.fs.path.join(b.allocator, &.{ module, entry.name });
|
||||||
|
|
@ -24,26 +24,26 @@ fn add_module(comptime module: []const u8, b: *std.Build, target: std.zig.CrossT
|
||||||
.target = target,
|
.target = target,
|
||||||
.optimize = optimize,
|
.optimize = optimize,
|
||||||
});
|
});
|
||||||
exe.addCSourceFile(path, &[_][]const u8{});
|
exe.addCSourceFile(.{ .file = .{ .path = path }, .flags = &.{} });
|
||||||
exe.linkLibC();
|
exe.linkLibC();
|
||||||
exe.addObjectFile(switch (target.getOsTag()) {
|
exe.addObjectFile(switch (target.getOsTag()) {
|
||||||
.windows => "../src/zig-out/lib/raylib.lib",
|
.windows => .{ .path = "../zig-out/lib/raylib.lib" },
|
||||||
.linux => "../src/zig-out/lib/libraylib.a",
|
.linux => .{ .path = "../zig-out/lib/libraylib.a" },
|
||||||
.macos => "../src/zig-out/lib/libraylib.a",
|
.macos => .{ .path = "../zig-out/lib/libraylib.a" },
|
||||||
.emscripten => "../src/zig-out/lib/libraylib.a",
|
.emscripten => .{ .path = "../zig-out/lib/libraylib.a" },
|
||||||
else => @panic("Unsupported OS"),
|
else => @panic("Unsupported OS"),
|
||||||
});
|
});
|
||||||
|
|
||||||
exe.addIncludePath("../src");
|
exe.addIncludePath(.{ .path = "../src" });
|
||||||
exe.addIncludePath("../src/external");
|
exe.addIncludePath(.{ .path = "../src/external" });
|
||||||
exe.addIncludePath("../src/external/glfw/include");
|
exe.addIncludePath(.{ .path = "../src/external/glfw/include" });
|
||||||
|
|
||||||
switch (target.getOsTag()) {
|
switch (target.getOsTag()) {
|
||||||
.windows => {
|
.windows => {
|
||||||
exe.linkSystemLibrary("winmm");
|
exe.linkSystemLibrary("winmm");
|
||||||
exe.linkSystemLibrary("gdi32");
|
exe.linkSystemLibrary("gdi32");
|
||||||
exe.linkSystemLibrary("opengl32");
|
exe.linkSystemLibrary("opengl32");
|
||||||
exe.addIncludePath("external/glfw/deps/mingw");
|
exe.addIncludePath(.{ .path = "external/glfw/deps/mingw" });
|
||||||
|
|
||||||
exe.defineCMacro("PLATFORM_DESKTOP", null);
|
exe.defineCMacro("PLATFORM_DESKTOP", null);
|
||||||
},
|
},
|
||||||
|
|
@ -71,11 +71,15 @@ fn add_module(comptime module: []const u8, b: *std.Build, target: std.zig.CrossT
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
b.installArtifact(exe);
|
const install_cmd = b.addInstallArtifact(exe, .{});
|
||||||
var run = b.addRunArtifact(exe);
|
|
||||||
run.cwd = module;
|
const run_cmd = b.addRunArtifact(exe);
|
||||||
b.step(name, name).dependOn(&run.step);
|
run_cmd.step.dependOn(&install_cmd.step);
|
||||||
all.dependOn(&exe.step);
|
|
||||||
|
const run_step = b.step(name, name);
|
||||||
|
run_step.dependOn(&run_cmd.step);
|
||||||
|
|
||||||
|
all.dependOn(&install_cmd.step);
|
||||||
}
|
}
|
||||||
return all;
|
return all;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,18 @@
|
||||||
/*******************************************************************************************
|
/*******************************************************************************************
|
||||||
*
|
*
|
||||||
* raylib [core] example - Gamepad information
|
* raylib [core] example - Gamepad information
|
||||||
*
|
*
|
||||||
* NOTE: This example requires a Gamepad connected to the system
|
* NOTE: This example requires a Gamepad connected to the system
|
||||||
* Check raylib.h for buttons configuration
|
* Check raylib.h for buttons configuration
|
||||||
*
|
*
|
||||||
* Example originally created with raylib 4.6, last time updated with raylib 4.6
|
* Example originally created with raylib 4.6, last time updated with raylib 4.6
|
||||||
*
|
*
|
||||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||||
* BSD-like license that allows static linking with closed source software
|
* BSD-like license that allows static linking with closed source software
|
||||||
*
|
*
|
||||||
* Copyright (c) 2013-2023 Ramon Santamaria (@raysan5)
|
* Copyright (c) 2013-2023 Ramon Santamaria (@raysan5)
|
||||||
*
|
*
|
||||||
********************************************************************************************/
|
********************************************************************************************/
|
||||||
|
|
||||||
#include "raylib.h"
|
#include "raylib.h"
|
||||||
|
|
||||||
|
|
@ -26,14 +26,14 @@ int main(void)
|
||||||
const int screenWidth = 800;
|
const int screenWidth = 800;
|
||||||
const int screenHeight = 450;
|
const int screenHeight = 450;
|
||||||
|
|
||||||
SetConfigFlags(FLAG_MSAA_4X_HINT); // Set MSAA 4X hint before windows creation
|
SetConfigFlags(FLAG_MSAA_4X_HINT); // Set MSAA 4X hint before windows creation
|
||||||
|
|
||||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - gamepad information");
|
InitWindow(screenWidth, screenHeight, "raylib [core] example - gamepad information");
|
||||||
|
|
||||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||||
|
|
||||||
// Main game loop
|
// Main game loop
|
||||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||||
{
|
{
|
||||||
int y = 10;
|
int y = 10;
|
||||||
|
|
||||||
|
|
@ -69,6 +69,6 @@ int main(void)
|
||||||
|
|
||||||
// De-Initialization
|
// De-Initialization
|
||||||
//--------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------
|
||||||
CloseWindow(); // Close window and OpenGL context
|
CloseWindow(); // Close window and OpenGL context
|
||||||
//--------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------
|
||||||
}
|
}
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
// This has been tested to work with zig master branch as of commit 87de821 or May 14 2023
|
// This has been tested to work with zig 0.11.0 (67709b6, Aug 4 2023)
|
||||||
pub fn addRaylib(b: *std.Build, target: std.zig.CrossTarget, optimize: std.builtin.OptimizeMode, options: Options) *std.Build.CompileStep {
|
pub fn addRaylib(b: *std.Build, target: std.zig.CrossTarget, optimize: std.builtin.OptimizeMode, options: Options) *std.Build.CompileStep {
|
||||||
const raylib_flags = &[_][]const u8{
|
const raylib_flags = &[_][]const u8{
|
||||||
"-std=gnu99",
|
"-std=gnu99",
|
||||||
|
|
|
||||||
2634
src/external/stb_image_resize.h
vendored
2634
src/external/stb_image_resize.h
vendored
File diff suppressed because it is too large
Load Diff
10303
src/external/stb_image_resize2.h
vendored
Normal file
10303
src/external/stb_image_resize2.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
|
|
@ -981,14 +981,14 @@ void UnloadSoundAlias(Sound alias)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update sound buffer with new data
|
// Update sound buffer with new data
|
||||||
void UpdateSound(Sound sound, const void *data, int sampleCount)
|
void UpdateSound(Sound sound, const void *data, int frameCount)
|
||||||
{
|
{
|
||||||
if (sound.stream.buffer != NULL)
|
if (sound.stream.buffer != NULL)
|
||||||
{
|
{
|
||||||
StopAudioBuffer(sound.stream.buffer);
|
StopAudioBuffer(sound.stream.buffer);
|
||||||
|
|
||||||
// TODO: May want to lock/unlock this since this data buffer is read at mixing time
|
// TODO: May want to lock/unlock this since this data buffer is read at mixing time
|
||||||
memcpy(sound.stream.buffer->data, data, sampleCount*ma_get_bytes_per_frame(sound.stream.buffer->converter.formatIn, sound.stream.buffer->converter.channelsIn));
|
memcpy(sound.stream.buffer->data, data, frameCount*ma_get_bytes_per_frame(sound.stream.buffer->converter.formatIn, sound.stream.buffer->converter.channelsIn));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
18
src/raylib.h
18
src/raylib.h
|
|
@ -986,14 +986,6 @@ RLAPI const char *GetClipboardText(void); // Get clipboa
|
||||||
RLAPI void EnableEventWaiting(void); // Enable waiting for events on EndDrawing(), no automatic event polling
|
RLAPI void EnableEventWaiting(void); // Enable waiting for events on EndDrawing(), no automatic event polling
|
||||||
RLAPI void DisableEventWaiting(void); // Disable waiting for events on EndDrawing(), automatic events polling
|
RLAPI void DisableEventWaiting(void); // Disable waiting for events on EndDrawing(), automatic events polling
|
||||||
|
|
||||||
// Custom frame control functions
|
|
||||||
// NOTE: Those functions are intended for advance users that want full control over the frame processing
|
|
||||||
// By default EndDrawing() does this job: draws everything + SwapScreenBuffer() + manage frame timing + PollInputEvents()
|
|
||||||
// To avoid that behaviour and control frame processes manually, enable in config.h: SUPPORT_CUSTOM_FRAME_CONTROL
|
|
||||||
RLAPI void SwapScreenBuffer(void); // Swap back buffer with front buffer (screen drawing)
|
|
||||||
RLAPI void PollInputEvents(void); // Register all input events
|
|
||||||
RLAPI void WaitTime(double seconds); // Wait for some time (halt program execution)
|
|
||||||
|
|
||||||
// Cursor-related functions
|
// Cursor-related functions
|
||||||
RLAPI void ShowCursor(void); // Shows cursor
|
RLAPI void ShowCursor(void); // Shows cursor
|
||||||
RLAPI void HideCursor(void); // Hides cursor
|
RLAPI void HideCursor(void); // Hides cursor
|
||||||
|
|
@ -1049,9 +1041,17 @@ RLAPI Vector2 GetWorldToScreen2D(Vector2 position, Camera2D camera); // Get the
|
||||||
|
|
||||||
// Timing-related functions
|
// Timing-related functions
|
||||||
RLAPI void SetTargetFPS(int fps); // Set target FPS (maximum)
|
RLAPI void SetTargetFPS(int fps); // Set target FPS (maximum)
|
||||||
RLAPI int GetFPS(void); // Get current FPS
|
|
||||||
RLAPI float GetFrameTime(void); // Get time in seconds for last frame drawn (delta time)
|
RLAPI float GetFrameTime(void); // Get time in seconds for last frame drawn (delta time)
|
||||||
RLAPI double GetTime(void); // Get elapsed time in seconds since InitWindow()
|
RLAPI double GetTime(void); // Get elapsed time in seconds since InitWindow()
|
||||||
|
RLAPI int GetFPS(void); // Get current FPS
|
||||||
|
|
||||||
|
// Custom frame control functions
|
||||||
|
// NOTE: Those functions are intended for advance users that want full control over the frame processing
|
||||||
|
// By default EndDrawing() does this job: draws everything + SwapScreenBuffer() + manage frame timing + PollInputEvents()
|
||||||
|
// To avoid that behaviour and control frame processes manually, enable in config.h: SUPPORT_CUSTOM_FRAME_CONTROL
|
||||||
|
RLAPI void SwapScreenBuffer(void); // Swap back buffer with front buffer (screen drawing)
|
||||||
|
RLAPI void PollInputEvents(void); // Register all input events
|
||||||
|
RLAPI void WaitTime(double seconds); // Wait for some time (halt program execution)
|
||||||
|
|
||||||
// Misc. functions
|
// Misc. functions
|
||||||
RLAPI int GetRandomValue(int min, int max); // Get a random value between min and max (both included)
|
RLAPI int GetRandomValue(int min, int max); // Get a random value between min and max (both included)
|
||||||
|
|
|
||||||
312
src/rcore.c
312
src/rcore.c
|
|
@ -322,18 +322,15 @@ const char *TextFormat(const char *text, ...); // Formatting of text with
|
||||||
//void InitWindow(int width, int height, const char *title)
|
//void InitWindow(int width, int height, const char *title)
|
||||||
//void CloseWindow(void)
|
//void CloseWindow(void)
|
||||||
//bool WindowShouldClose(void)
|
//bool WindowShouldClose(void)
|
||||||
//bool IsWindowHidden(void)
|
|
||||||
//bool IsWindowMinimized(void)
|
|
||||||
//bool IsWindowMaximized(void)
|
|
||||||
//bool IsWindowFocused(void)
|
|
||||||
//bool IsWindowResized(void)
|
|
||||||
//void ToggleFullscreen(void)
|
//void ToggleFullscreen(void)
|
||||||
|
//void ToggleBorderlessWindowed(void)
|
||||||
//void MaximizeWindow(void)
|
//void MaximizeWindow(void)
|
||||||
//void MinimizeWindow(void)
|
//void MinimizeWindow(void)
|
||||||
//void RestoreWindow(void)
|
//void RestoreWindow(void)
|
||||||
//void ToggleBorderlessWindowed(void)
|
|
||||||
//void SetWindowState(unsigned int flags)
|
//void SetWindowState(unsigned int flags)
|
||||||
//void ClearWindowState(unsigned int flags)
|
//void ClearWindowState(unsigned int flags)
|
||||||
|
|
||||||
//void SetWindowIcon(Image image)
|
//void SetWindowIcon(Image image)
|
||||||
//void SetWindowIcons(Image *images, int count)
|
//void SetWindowIcons(Image *images, int count)
|
||||||
//void SetWindowTitle(const char *title)
|
//void SetWindowTitle(const char *title)
|
||||||
|
|
@ -345,25 +342,27 @@ const char *TextFormat(const char *text, ...); // Formatting of text with
|
||||||
//void SetWindowOpacity(float opacity)
|
//void SetWindowOpacity(float opacity)
|
||||||
//void SetWindowFocused(void)
|
//void SetWindowFocused(void)
|
||||||
//void *GetWindowHandle(void)
|
//void *GetWindowHandle(void)
|
||||||
|
//Vector2 GetWindowPosition(void)
|
||||||
|
//Vector2 GetWindowScaleDPI(void)
|
||||||
|
|
||||||
//int GetMonitorCount(void)
|
//int GetMonitorCount(void)
|
||||||
//int GetCurrentMonitor(void)
|
//int GetCurrentMonitor(void)
|
||||||
//Vector2 GetMonitorPosition(int monitor)
|
|
||||||
//int GetMonitorWidth(int monitor)
|
//int GetMonitorWidth(int monitor)
|
||||||
//int GetMonitorHeight(int monitor)
|
//int GetMonitorHeight(int monitor)
|
||||||
//int GetMonitorPhysicalWidth(int monitor)
|
//int GetMonitorPhysicalWidth(int monitor)
|
||||||
//int GetMonitorPhysicalHeight(int monitor)
|
//int GetMonitorPhysicalHeight(int monitor)
|
||||||
//int GetMonitorRefreshRate(int monitor)
|
//int GetMonitorRefreshRate(int monitor)
|
||||||
|
//Vector2 GetMonitorPosition(int monitor)
|
||||||
//const char *GetMonitorName(int monitor)
|
//const char *GetMonitorName(int monitor)
|
||||||
//Vector2 GetWindowPosition(void)
|
|
||||||
//Vector2 GetWindowScaleDPI(void)
|
|
||||||
//void SetClipboardText(const char *text)
|
//void SetClipboardText(const char *text)
|
||||||
//const char *GetClipboardText(void)
|
//const char *GetClipboardText(void)
|
||||||
|
|
||||||
//void ShowCursor(void)
|
//void ShowCursor(void)
|
||||||
//void HideCursor(void)
|
//void HideCursor(void)
|
||||||
//void EnableCursor(void)
|
//void EnableCursor(void)
|
||||||
//void DisableCursor(void)
|
//void DisableCursor(void)
|
||||||
|
|
||||||
|
|
||||||
// Check if window has been initialized successfully
|
// Check if window has been initialized successfully
|
||||||
bool IsWindowReady(void)
|
bool IsWindowReady(void)
|
||||||
{
|
{
|
||||||
|
|
@ -376,6 +375,36 @@ bool IsWindowFullscreen(void)
|
||||||
return CORE.Window.fullscreen;
|
return CORE.Window.fullscreen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if window is currently hidden
|
||||||
|
bool IsWindowHidden(void)
|
||||||
|
{
|
||||||
|
return ((CORE.Window.flags & FLAG_WINDOW_HIDDEN) > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if window has been minimized
|
||||||
|
bool IsWindowMinimized(void)
|
||||||
|
{
|
||||||
|
return ((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if window has been maximized
|
||||||
|
bool IsWindowMaximized(void)
|
||||||
|
{
|
||||||
|
return ((CORE.Window.flags & FLAG_WINDOW_MAXIMIZED) > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if window has the focus
|
||||||
|
bool IsWindowFocused(void)
|
||||||
|
{
|
||||||
|
return ((CORE.Window.flags & FLAG_WINDOW_UNFOCUSED) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if window has been resizedLastFrame
|
||||||
|
bool IsWindowResized(void)
|
||||||
|
{
|
||||||
|
return CORE.Window.resizedLastFrame;
|
||||||
|
}
|
||||||
|
|
||||||
// Check if one specific window flag is enabled
|
// Check if one specific window flag is enabled
|
||||||
bool IsWindowState(unsigned int flag)
|
bool IsWindowState(unsigned int flag)
|
||||||
{
|
{
|
||||||
|
|
@ -394,13 +423,13 @@ int GetScreenHeight(void)
|
||||||
return CORE.Window.screen.height;
|
return CORE.Window.screen.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get current render width which is equal to screen width * dpi scale
|
// Get current render width which is equal to screen width*dpi scale
|
||||||
int GetRenderWidth(void)
|
int GetRenderWidth(void)
|
||||||
{
|
{
|
||||||
return CORE.Window.render.width;
|
return CORE.Window.render.width;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get current screen height which is equal to screen height * dpi scale
|
// Get current screen height which is equal to screen height*dpi scale
|
||||||
int GetRenderHeight(void)
|
int GetRenderHeight(void)
|
||||||
{
|
{
|
||||||
return CORE.Window.render.height;
|
return CORE.Window.render.height;
|
||||||
|
|
@ -430,15 +459,6 @@ bool IsCursorOnScreen(void)
|
||||||
return CORE.Input.Mouse.cursorOnScreen;
|
return CORE.Input.Mouse.cursorOnScreen;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
// Module Functions Definition: Custom frame control
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// NOTE: Functions with a platform-specific implementation on rcore_<platform>.c
|
|
||||||
//void SwapScreenBuffer(void);
|
|
||||||
//void PollInputEvents(void);
|
|
||||||
//void WaitTime(double seconds);
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module Functions Definition: Screen Drawing
|
// Module Functions Definition: Screen Drawing
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
@ -1236,6 +1256,60 @@ float GetFrameTime(void)
|
||||||
return (float)CORE.Time.frame;
|
return (float)CORE.Time.frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Module Functions Definition: Custom frame control
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// NOTE: Functions with a platform-specific implementation on rcore_<platform>.c
|
||||||
|
//void SwapScreenBuffer(void);
|
||||||
|
//void PollInputEvents(void);
|
||||||
|
|
||||||
|
// Wait for some time (stop program execution)
|
||||||
|
// NOTE: Sleep() granularity could be around 10 ms, it means, Sleep() could
|
||||||
|
// take longer than expected... for that reason we use the busy wait loop
|
||||||
|
// Ref: http://stackoverflow.com/questions/43057578/c-programming-win32-games-sleep-taking-longer-than-expected
|
||||||
|
// Ref: http://www.geisswerks.com/ryan/FAQS/timing.html --> All about timing on Win32!
|
||||||
|
void WaitTime(double seconds)
|
||||||
|
{
|
||||||
|
if (seconds < 0) return;
|
||||||
|
|
||||||
|
#if defined(SUPPORT_BUSY_WAIT_LOOP) || defined(SUPPORT_PARTIALBUSY_WAIT_LOOP)
|
||||||
|
double destinationTime = GetTime() + seconds;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(SUPPORT_BUSY_WAIT_LOOP)
|
||||||
|
while (GetTime() < destinationTime) { }
|
||||||
|
#else
|
||||||
|
#if defined(SUPPORT_PARTIALBUSY_WAIT_LOOP)
|
||||||
|
double sleepSeconds = seconds - seconds*0.05; // NOTE: We reserve a percentage of the time for busy waiting
|
||||||
|
#else
|
||||||
|
double sleepSeconds = seconds;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// System halt functions
|
||||||
|
#if defined(_WIN32)
|
||||||
|
Sleep((unsigned long)(sleepSeconds*1000.0));
|
||||||
|
#endif
|
||||||
|
#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__EMSCRIPTEN__)
|
||||||
|
struct timespec req = { 0 };
|
||||||
|
time_t sec = sleepSeconds;
|
||||||
|
long nsec = (sleepSeconds - sec)*1000000000L;
|
||||||
|
req.tv_sec = sec;
|
||||||
|
req.tv_nsec = nsec;
|
||||||
|
|
||||||
|
// NOTE: Use nanosleep() on Unix platforms... usleep() it's deprecated.
|
||||||
|
while (nanosleep(&req, &req) == -1) continue;
|
||||||
|
#endif
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
usleep(sleepSeconds*1000000.0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(SUPPORT_PARTIALBUSY_WAIT_LOOP)
|
||||||
|
while (GetTime() < destinationTime) { }
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module Functions Definition: Misc
|
// Module Functions Definition: Misc
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
@ -2023,8 +2097,6 @@ void SetExitKey(int key)
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
// NOTE: Functions with a platform-specific implementation on rcore_<platform>.c
|
// NOTE: Functions with a platform-specific implementation on rcore_<platform>.c
|
||||||
//int GetGamepadAxisCount(int gamepad) **
|
|
||||||
//const char *GetGamepadName(int gamepad) **
|
|
||||||
//int SetGamepadMappings(const char *mappings)
|
//int SetGamepadMappings(const char *mappings)
|
||||||
|
|
||||||
// Check if a gamepad is available
|
// Check if a gamepad is available
|
||||||
|
|
@ -2038,10 +2110,10 @@ bool IsGamepadAvailable(int gamepad)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get gamepad internal name id
|
// Get gamepad internal name id
|
||||||
//const char *GetGamepadName(int gamepad)
|
const char *GetGamepadName(int gamepad)
|
||||||
//{
|
{
|
||||||
// return CORE.Input.Gamepad.ready[gamepad];
|
return CORE.Input.Gamepad.name[gamepad];
|
||||||
//}
|
}
|
||||||
|
|
||||||
// Check if a gamepad button has been pressed once
|
// Check if a gamepad button has been pressed once
|
||||||
bool IsGamepadButtonPressed(int gamepad, int button)
|
bool IsGamepadButtonPressed(int gamepad, int button)
|
||||||
|
|
@ -2094,10 +2166,10 @@ int GetGamepadButtonPressed(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get gamepad axis count
|
// Get gamepad axis count
|
||||||
//int GetGamepadAxisCount(int gamepad)
|
int GetGamepadAxisCount(int gamepad)
|
||||||
//{
|
{
|
||||||
// return CORE.Input.Gamepad.axisCount;
|
return CORE.Input.Gamepad.axisCount;
|
||||||
//}
|
}
|
||||||
|
|
||||||
// Get axis movement vector for a gamepad
|
// Get axis movement vector for a gamepad
|
||||||
float GetGamepadAxisMovement(int gamepad, int axis)
|
float GetGamepadAxisMovement(int gamepad, int axis)
|
||||||
|
|
@ -2115,11 +2187,7 @@ float GetGamepadAxisMovement(int gamepad, int axis)
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
// NOTE: Functions with a platform-specific implementation on rcore_<platform>.c
|
// NOTE: Functions with a platform-specific implementation on rcore_<platform>.c
|
||||||
//int GetMouseX(void) **
|
|
||||||
//int GetMouseY(void) **
|
|
||||||
//Vector2 GetMousePosition(void) **
|
|
||||||
//void SetMousePosition(int x, int y)
|
//void SetMousePosition(int x, int y)
|
||||||
//float GetMouseWheelMove(void) **
|
|
||||||
//void SetMouseCursor(int cursor)
|
//void SetMouseCursor(int cursor)
|
||||||
|
|
||||||
// Check if a mouse button has been pressed once
|
// Check if a mouse button has been pressed once
|
||||||
|
|
@ -2174,6 +2242,29 @@ bool IsMouseButtonUp(int button)
|
||||||
return up;
|
return up;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get mouse position X
|
||||||
|
int GetMouseX(void)
|
||||||
|
{
|
||||||
|
return (int)((CORE.Input.Mouse.currentPosition.x + CORE.Input.Mouse.offset.x)*CORE.Input.Mouse.scale.x);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get mouse position Y
|
||||||
|
int GetMouseY(void)
|
||||||
|
{
|
||||||
|
return (int)((CORE.Input.Mouse.currentPosition.y + CORE.Input.Mouse.offset.y)*CORE.Input.Mouse.scale.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get mouse position XY
|
||||||
|
Vector2 GetMousePosition(void)
|
||||||
|
{
|
||||||
|
Vector2 position = { 0 };
|
||||||
|
|
||||||
|
position.x = (CORE.Input.Mouse.currentPosition.x + CORE.Input.Mouse.offset.x)*CORE.Input.Mouse.scale.x;
|
||||||
|
position.y = (CORE.Input.Mouse.currentPosition.y + CORE.Input.Mouse.offset.y)*CORE.Input.Mouse.scale.y;
|
||||||
|
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
// Get mouse delta between frames
|
// Get mouse delta between frames
|
||||||
Vector2 GetMouseDelta(void)
|
Vector2 GetMouseDelta(void)
|
||||||
{
|
{
|
||||||
|
|
@ -2199,6 +2290,17 @@ void SetMouseScale(float scaleX, float scaleY)
|
||||||
CORE.Input.Mouse.scale = (Vector2){ scaleX, scaleY };
|
CORE.Input.Mouse.scale = (Vector2){ scaleX, scaleY };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get mouse wheel movement Y
|
||||||
|
float GetMouseWheelMove(void)
|
||||||
|
{
|
||||||
|
float result = 0.0f;
|
||||||
|
|
||||||
|
if (fabsf(CORE.Input.Mouse.currentWheelMove.x) > fabsf(CORE.Input.Mouse.currentWheelMove.y)) result = (float)CORE.Input.Mouse.currentWheelMove.x;
|
||||||
|
else result = (float)CORE.Input.Mouse.currentWheelMove.y;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// Get mouse wheel movement X/Y as a vector
|
// Get mouse wheel movement X/Y as a vector
|
||||||
Vector2 GetMouseWheelMoveV(void)
|
Vector2 GetMouseWheelMoveV(void)
|
||||||
{
|
{
|
||||||
|
|
@ -2213,10 +2315,29 @@ Vector2 GetMouseWheelMoveV(void)
|
||||||
// Module Functions Definition: Input Handling: Touch
|
// Module Functions Definition: Input Handling: Touch
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
// NOTE: Functions with a platform-specific implementation on rcore_<platform>.c
|
// Get touch position X for touch point 0 (relative to screen size)
|
||||||
//int GetTouchX(void)
|
int GetTouchX(void)
|
||||||
//int GetTouchY(void)
|
{
|
||||||
//Vector2 GetTouchPosition(int index)
|
return (int)CORE.Input.Touch.position[0].x;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get touch position Y for touch point 0 (relative to screen size)
|
||||||
|
int GetTouchY(void)
|
||||||
|
{
|
||||||
|
return (int)CORE.Input.Touch.position[0].y;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get touch position XY for a touch point index (relative to screen size)
|
||||||
|
// TODO: Touch position should be scaled depending on display size and render size
|
||||||
|
Vector2 GetTouchPosition(int index)
|
||||||
|
{
|
||||||
|
Vector2 position = { -1.0f, -1.0f };
|
||||||
|
|
||||||
|
if (index < MAX_TOUCH_POINTS) position = CORE.Input.Touch.position[index];
|
||||||
|
else TRACELOG(LOG_WARNING, "INPUT: Required touch point out of range (Max touch points: %i)", MAX_TOUCH_POINTS);
|
||||||
|
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
// Get touch point identifier for given index
|
// Get touch point identifier for given index
|
||||||
int GetTouchPointId(int index)
|
int GetTouchPointId(int index)
|
||||||
|
|
@ -2238,8 +2359,32 @@ int GetTouchPointCount(void)
|
||||||
// Module Internal Functions Definition
|
// Module Internal Functions Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Platform-specific functions
|
// NOTE: Functions with a platform-specific implementation on rcore_<platform>.c
|
||||||
//static bool InitGraphicsDevice(int width, int height)
|
//static bool InitPlatform(void)
|
||||||
|
|
||||||
|
// Initialize hi-resolution timer
|
||||||
|
void InitTimer(void)
|
||||||
|
{
|
||||||
|
// Setting a higher resolution can improve the accuracy of time-out intervals in wait functions.
|
||||||
|
// However, it can also reduce overall system performance, because the thread scheduler switches tasks more often.
|
||||||
|
// High resolutions can also prevent the CPU power management system from entering power-saving modes.
|
||||||
|
// Setting a higher resolution does not improve the accuracy of the high-resolution performance counter.
|
||||||
|
#if defined(_WIN32) && defined(SUPPORT_WINMM_HIGHRES_TIMER) && !defined(SUPPORT_BUSY_WAIT_LOOP)
|
||||||
|
timeBeginPeriod(1); // Setup high-resolution timer to 1ms (granularity of 1-2 ms)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__EMSCRIPTEN__)
|
||||||
|
struct timespec now = { 0 };
|
||||||
|
|
||||||
|
if (clock_gettime(CLOCK_MONOTONIC, &now) == 0) // Success
|
||||||
|
{
|
||||||
|
CORE.Time.base = (unsigned long long int)now.tv_sec*1000000000LLU + (unsigned long long int)now.tv_nsec;
|
||||||
|
}
|
||||||
|
else TRACELOG(LOG_WARNING, "TIMER: Hi-resolution timer not available");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
CORE.Time.previous = GetTime(); // Get time as double
|
||||||
|
}
|
||||||
|
|
||||||
// Set viewport for a provided width and height
|
// Set viewport for a provided width and height
|
||||||
void SetupViewport(int width, int height)
|
void SetupViewport(int width, int height)
|
||||||
|
|
@ -2348,76 +2493,6 @@ void SetupFramebuffer(int width, int height)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize hi-resolution timer
|
|
||||||
void InitTimer(void)
|
|
||||||
{
|
|
||||||
// Setting a higher resolution can improve the accuracy of time-out intervals in wait functions.
|
|
||||||
// However, it can also reduce overall system performance, because the thread scheduler switches tasks more often.
|
|
||||||
// High resolutions can also prevent the CPU power management system from entering power-saving modes.
|
|
||||||
// Setting a higher resolution does not improve the accuracy of the high-resolution performance counter.
|
|
||||||
#if defined(_WIN32) && defined(SUPPORT_WINMM_HIGHRES_TIMER) && !defined(SUPPORT_BUSY_WAIT_LOOP)
|
|
||||||
timeBeginPeriod(1); // Setup high-resolution timer to 1ms (granularity of 1-2 ms)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__EMSCRIPTEN__)
|
|
||||||
struct timespec now = { 0 };
|
|
||||||
|
|
||||||
if (clock_gettime(CLOCK_MONOTONIC, &now) == 0) // Success
|
|
||||||
{
|
|
||||||
CORE.Time.base = (unsigned long long int)now.tv_sec*1000000000LLU + (unsigned long long int)now.tv_nsec;
|
|
||||||
}
|
|
||||||
else TRACELOG(LOG_WARNING, "TIMER: Hi-resolution timer not available");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
CORE.Time.previous = GetTime(); // Get time as double
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for some time (stop program execution)
|
|
||||||
// NOTE: Sleep() granularity could be around 10 ms, it means, Sleep() could
|
|
||||||
// take longer than expected... for that reason we use the busy wait loop
|
|
||||||
// Ref: http://stackoverflow.com/questions/43057578/c-programming-win32-games-sleep-taking-longer-than-expected
|
|
||||||
// Ref: http://www.geisswerks.com/ryan/FAQS/timing.html --> All about timing on Win32!
|
|
||||||
void WaitTime(double seconds)
|
|
||||||
{
|
|
||||||
if (seconds < 0) return;
|
|
||||||
|
|
||||||
#if defined(SUPPORT_BUSY_WAIT_LOOP) || defined(SUPPORT_PARTIALBUSY_WAIT_LOOP)
|
|
||||||
double destinationTime = GetTime() + seconds;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(SUPPORT_BUSY_WAIT_LOOP)
|
|
||||||
while (GetTime() < destinationTime) { }
|
|
||||||
#else
|
|
||||||
#if defined(SUPPORT_PARTIALBUSY_WAIT_LOOP)
|
|
||||||
double sleepSeconds = seconds - seconds*0.05; // NOTE: We reserve a percentage of the time for busy waiting
|
|
||||||
#else
|
|
||||||
double sleepSeconds = seconds;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// System halt functions
|
|
||||||
#if defined(_WIN32)
|
|
||||||
Sleep((unsigned long)(sleepSeconds*1000.0));
|
|
||||||
#endif
|
|
||||||
#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__EMSCRIPTEN__)
|
|
||||||
struct timespec req = { 0 };
|
|
||||||
time_t sec = sleepSeconds;
|
|
||||||
long nsec = (sleepSeconds - sec)*1000000000L;
|
|
||||||
req.tv_sec = sec;
|
|
||||||
req.tv_nsec = nsec;
|
|
||||||
|
|
||||||
// NOTE: Use nanosleep() on Unix platforms... usleep() it's deprecated.
|
|
||||||
while (nanosleep(&req, &req) == -1) continue;
|
|
||||||
#endif
|
|
||||||
#if defined(__APPLE__)
|
|
||||||
usleep(sleepSeconds*1000000.0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(SUPPORT_PARTIALBUSY_WAIT_LOOP)
|
|
||||||
while (GetTime() < destinationTime) { }
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
||||||
|
|
@ -2737,7 +2812,7 @@ static void RecordAutomationEvent(unsigned int frame)
|
||||||
// INPUT_GAMEPAD_CONNECT
|
// INPUT_GAMEPAD_CONNECT
|
||||||
/*
|
/*
|
||||||
if ((CORE.Input.Gamepad.currentState[gamepad] != CORE.Input.Gamepad.previousState[gamepad]) &&
|
if ((CORE.Input.Gamepad.currentState[gamepad] != CORE.Input.Gamepad.previousState[gamepad]) &&
|
||||||
(CORE.Input.Gamepad.currentState[gamepad] == true)) // Check if changed to ready
|
(CORE.Input.Gamepad.currentState[gamepad])) // Check if changed to ready
|
||||||
{
|
{
|
||||||
// TODO: Save gamepad connect event
|
// TODO: Save gamepad connect event
|
||||||
}
|
}
|
||||||
|
|
@ -2746,7 +2821,7 @@ static void RecordAutomationEvent(unsigned int frame)
|
||||||
// INPUT_GAMEPAD_DISCONNECT
|
// INPUT_GAMEPAD_DISCONNECT
|
||||||
/*
|
/*
|
||||||
if ((CORE.Input.Gamepad.currentState[gamepad] != CORE.Input.Gamepad.previousState[gamepad]) &&
|
if ((CORE.Input.Gamepad.currentState[gamepad] != CORE.Input.Gamepad.previousState[gamepad]) &&
|
||||||
(CORE.Input.Gamepad.currentState[gamepad] == false)) // Check if changed to not-ready
|
(!CORE.Input.Gamepad.currentState[gamepad])) // Check if changed to not-ready
|
||||||
{
|
{
|
||||||
// TODO: Save gamepad disconnect event
|
// TODO: Save gamepad disconnect event
|
||||||
}
|
}
|
||||||
|
|
@ -2894,12 +2969,21 @@ const char *TextFormat(const char *text, ...)
|
||||||
|
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, text);
|
va_start(args, text);
|
||||||
vsnprintf(currentBuffer, MAX_TEXT_BUFFER_LENGTH, text, args);
|
int requiredByteCount = vsnprintf(currentBuffer, MAX_TEXT_BUFFER_LENGTH, text, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
|
// If requiredByteCount is larger than the MAX_TEXT_BUFFER_LENGTH, then overflow occured
|
||||||
|
if (requiredByteCount >= MAX_TEXT_BUFFER_LENGTH)
|
||||||
|
{
|
||||||
|
// Inserting "..." at the end of the string to mark as truncated
|
||||||
|
char *truncBuffer = buffers[index] + MAX_TEXT_BUFFER_LENGTH - 4; // Adding 4 bytes = "...\0"
|
||||||
|
sprintf(truncBuffer, "...");
|
||||||
|
}
|
||||||
|
|
||||||
index += 1; // Move to next buffer for next function call
|
index += 1; // Move to next buffer for next function call
|
||||||
if (index >= MAX_TEXTFORMAT_BUFFERS) index = 0;
|
if (index >= MAX_TEXTFORMAT_BUFFERS) index = 0;
|
||||||
|
|
||||||
return currentBuffer;
|
return currentBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // !SUPPORT_MODULE_RTEXT
|
#endif // !SUPPORT_MODULE_RTEXT
|
||||||
|
|
|
||||||
|
|
@ -127,8 +127,6 @@ typedef struct CoreData {
|
||||||
Point renderOffset; // Offset from render area (must be divided by 2)
|
Point renderOffset; // Offset from render area (must be divided by 2)
|
||||||
Size screenMin; // Screen minimum width and height (for resizable window)
|
Size screenMin; // Screen minimum width and height (for resizable window)
|
||||||
Size screenMax; // Screen maximum width and height (for resizable window)
|
Size screenMax; // Screen maximum width and height (for resizable window)
|
||||||
Size windowMin; // Window minimum width and height
|
|
||||||
Size windowMax; // Window maximum width and height
|
|
||||||
Matrix screenScale; // Matrix to scale screen (framebuffer rendering)
|
Matrix screenScale; // Matrix to scale screen (framebuffer rendering)
|
||||||
|
|
||||||
char **dropFilepaths; // Store dropped files paths pointers (provided by GLFW)
|
char **dropFilepaths; // Store dropped files paths pointers (provided by GLFW)
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,8 @@ static PlatformData platform = { 0 }; // Platform specific data
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module Internal Functions Declaration
|
// Module Internal Functions Declaration
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
static bool InitGraphicsDevice(int width, int height); // Initialize graphics device
|
static int InitPlatform(void); // Initialize platform (graphics, inputs and more)
|
||||||
|
static void ClosePlatform(void); // Close platform
|
||||||
|
|
||||||
static void AndroidCommandCallback(struct android_app *app, int32_t cmd); // Process Android activity lifecycle commands
|
static void AndroidCommandCallback(struct android_app *app, int32_t cmd); // Process Android activity lifecycle commands
|
||||||
static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event); // Process Android inputs
|
static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event); // Process Android inputs
|
||||||
|
|
@ -172,81 +173,23 @@ void InitWindow(int width, int height, const char *title)
|
||||||
TRACELOG(LOG_INFO, " > raudio:.... not loaded (optional)");
|
TRACELOG(LOG_INFO, " > raudio:.... not loaded (optional)");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// NOTE: Keep internal pointer to input title string (no copy)
|
// Initialize window data
|
||||||
|
CORE.Window.screen.width = width;
|
||||||
|
CORE.Window.screen.height = height;
|
||||||
|
CORE.Window.eventWaiting = false;
|
||||||
|
CORE.Window.screenScale = MatrixIdentity(); // No draw scaling required by default
|
||||||
if ((title != NULL) && (title[0] != 0)) CORE.Window.title = title;
|
if ((title != NULL) && (title[0] != 0)) CORE.Window.title = title;
|
||||||
|
|
||||||
// Initialize global input state
|
// Initialize global input state
|
||||||
memset(&CORE.Input, 0, sizeof(CORE.Input));
|
memset(&CORE.Input, 0, sizeof(CORE.Input)); // Reset CORE.Input structure to 0
|
||||||
CORE.Input.Keyboard.exitKey = KEY_ESCAPE;
|
CORE.Input.Keyboard.exitKey = KEY_ESCAPE;
|
||||||
CORE.Input.Mouse.scale = (Vector2){ 1.0f, 1.0f };
|
CORE.Input.Mouse.scale = (Vector2){ 1.0f, 1.0f };
|
||||||
CORE.Input.Mouse.cursor = MOUSE_CURSOR_ARROW;
|
CORE.Input.Mouse.cursor = MOUSE_CURSOR_ARROW;
|
||||||
CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN
|
CORE.Input.Gamepad.lastButtonPressed = GAMEPAD_BUTTON_UNKNOWN;
|
||||||
CORE.Window.eventWaiting = false;
|
|
||||||
|
|
||||||
CORE.Window.screen.width = width;
|
// Initialize platform
|
||||||
CORE.Window.screen.height = height;
|
|
||||||
CORE.Window.currentFbo.width = width;
|
|
||||||
CORE.Window.currentFbo.height = height;
|
|
||||||
|
|
||||||
// Platform specific init window
|
|
||||||
//--------------------------------------------------------------
|
//--------------------------------------------------------------
|
||||||
// Set desired windows flags before initializing anything
|
InitPlatform();
|
||||||
ANativeActivity_setWindowFlags(platform.app->activity, AWINDOW_FLAG_FULLSCREEN, 0); //AWINDOW_FLAG_SCALED, AWINDOW_FLAG_DITHER
|
|
||||||
|
|
||||||
int orientation = AConfiguration_getOrientation(platform.app->config);
|
|
||||||
|
|
||||||
if (orientation == ACONFIGURATION_ORIENTATION_PORT) TRACELOG(LOG_INFO, "ANDROID: Window orientation set as portrait");
|
|
||||||
else if (orientation == ACONFIGURATION_ORIENTATION_LAND) TRACELOG(LOG_INFO, "ANDROID: Window orientation set as landscape");
|
|
||||||
|
|
||||||
// TODO: Automatic orientation doesn't seem to work
|
|
||||||
if (width <= height)
|
|
||||||
{
|
|
||||||
AConfiguration_setOrientation(platform.app->config, ACONFIGURATION_ORIENTATION_PORT);
|
|
||||||
TRACELOG(LOG_WARNING, "ANDROID: Window orientation changed to portrait");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
AConfiguration_setOrientation(platform.app->config, ACONFIGURATION_ORIENTATION_LAND);
|
|
||||||
TRACELOG(LOG_WARNING, "ANDROID: Window orientation changed to landscape");
|
|
||||||
}
|
|
||||||
|
|
||||||
//AConfiguration_getDensity(platform.app->config);
|
|
||||||
//AConfiguration_getKeyboard(platform.app->config);
|
|
||||||
//AConfiguration_getScreenSize(platform.app->config);
|
|
||||||
//AConfiguration_getScreenLong(platform.app->config);
|
|
||||||
|
|
||||||
// Initialize App command system
|
|
||||||
// NOTE: On APP_CMD_INIT_WINDOW -> InitGraphicsDevice(), InitTimer(), LoadFontDefault()...
|
|
||||||
platform.app->onAppCmd = AndroidCommandCallback;
|
|
||||||
|
|
||||||
// Initialize input events system
|
|
||||||
platform.app->onInputEvent = AndroidInputCallback;
|
|
||||||
|
|
||||||
// Initialize assets manager
|
|
||||||
InitAssetManager(platform.app->activity->assetManager, platform.app->activity->internalDataPath);
|
|
||||||
|
|
||||||
// Initialize base path for storage
|
|
||||||
CORE.Storage.basePath = platform.app->activity->internalDataPath;
|
|
||||||
|
|
||||||
TRACELOG(LOG_INFO, "PLATFORM: ANDROID: Application initialized successfully");
|
|
||||||
|
|
||||||
// Android ALooper_pollAll() variables
|
|
||||||
int pollResult = 0;
|
|
||||||
int pollEvents = 0;
|
|
||||||
|
|
||||||
// Wait for window to be initialized (display and context)
|
|
||||||
while (!CORE.Window.ready)
|
|
||||||
{
|
|
||||||
// Process events loop
|
|
||||||
while ((pollResult = ALooper_pollAll(0, NULL, &pollEvents, (void**)&platform.source)) >= 0)
|
|
||||||
{
|
|
||||||
// Process this event
|
|
||||||
if (platform.source != NULL) platform.source->process(platform.app, platform.source);
|
|
||||||
|
|
||||||
// NOTE: Never close window, native activity is controlled by the system!
|
|
||||||
//if (platform.app->destroyRequested != 0) CORE.Window.shouldClose = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//--------------------------------------------------------------
|
//--------------------------------------------------------------
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -272,28 +215,9 @@ void CloseWindow(void)
|
||||||
timeEndPeriod(1); // Restore time period
|
timeEndPeriod(1); // Restore time period
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Platform specific close window
|
// De-initialize platform
|
||||||
//--------------------------------------------------------------
|
//--------------------------------------------------------------
|
||||||
// Close surface, context and display
|
ClosePlatform();
|
||||||
if (platform.device != EGL_NO_DISPLAY)
|
|
||||||
{
|
|
||||||
eglMakeCurrent(platform.device, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
|
||||||
|
|
||||||
if (platform.surface != EGL_NO_SURFACE)
|
|
||||||
{
|
|
||||||
eglDestroySurface(platform.device, platform.surface);
|
|
||||||
platform.surface = EGL_NO_SURFACE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (platform.context != EGL_NO_CONTEXT)
|
|
||||||
{
|
|
||||||
eglDestroyContext(platform.device, platform.context);
|
|
||||||
platform.context = EGL_NO_CONTEXT;
|
|
||||||
}
|
|
||||||
|
|
||||||
eglTerminate(platform.device);
|
|
||||||
platform.device = EGL_NO_DISPLAY;
|
|
||||||
}
|
|
||||||
//--------------------------------------------------------------
|
//--------------------------------------------------------------
|
||||||
|
|
||||||
#if defined(SUPPORT_EVENTS_AUTOMATION)
|
#if defined(SUPPORT_EVENTS_AUTOMATION)
|
||||||
|
|
@ -311,42 +235,18 @@ bool WindowShouldClose(void)
|
||||||
else return true;
|
else return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if window is currently hidden
|
|
||||||
bool IsWindowHidden(void)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if window has been minimized
|
|
||||||
bool IsWindowMinimized(void)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if window has been maximized
|
|
||||||
bool IsWindowMaximized(void)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if window has the focus
|
|
||||||
bool IsWindowFocused(void)
|
|
||||||
{
|
|
||||||
return platform.appEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if window has been resizedLastFrame
|
|
||||||
bool IsWindowResized(void)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Toggle fullscreen mode
|
// Toggle fullscreen mode
|
||||||
void ToggleFullscreen(void)
|
void ToggleFullscreen(void)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "ToggleFullscreen() not available on target platform");
|
TRACELOG(LOG_WARNING, "ToggleFullscreen() not available on target platform");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Toggle borderless windowed mode
|
||||||
|
void ToggleBorderlessWindowed(void)
|
||||||
|
{
|
||||||
|
TRACELOG(LOG_WARNING, "ToggleBorderlessWindowed() not available on target platform");
|
||||||
|
}
|
||||||
|
|
||||||
// Set window state: maximized, if resizable
|
// Set window state: maximized, if resizable
|
||||||
void MaximizeWindow(void)
|
void MaximizeWindow(void)
|
||||||
{
|
{
|
||||||
|
|
@ -365,12 +265,6 @@ void RestoreWindow(void)
|
||||||
TRACELOG(LOG_WARNING, "RestoreWindow() not available on target platform");
|
TRACELOG(LOG_WARNING, "RestoreWindow() not available on target platform");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Toggle borderless windowed mode
|
|
||||||
void ToggleBorderlessWindowed(void)
|
|
||||||
{
|
|
||||||
TRACELOG(LOG_WARNING, "ToggleBorderlessWindowed() not available on target platform");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set window configuration state using flags
|
// Set window configuration state using flags
|
||||||
void SetWindowState(unsigned int flags)
|
void SetWindowState(unsigned int flags)
|
||||||
{
|
{
|
||||||
|
|
@ -416,15 +310,15 @@ void SetWindowMonitor(int monitor)
|
||||||
// Set window minimum dimensions (FLAG_WINDOW_RESIZABLE)
|
// Set window minimum dimensions (FLAG_WINDOW_RESIZABLE)
|
||||||
void SetWindowMinSize(int width, int height)
|
void SetWindowMinSize(int width, int height)
|
||||||
{
|
{
|
||||||
CORE.Window.windowMin.width = width;
|
CORE.Window.screenMin.width = width;
|
||||||
CORE.Window.windowMin.height = height;
|
CORE.Window.screenMin.height = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set window maximum dimensions (FLAG_WINDOW_RESIZABLE)
|
// Set window maximum dimensions (FLAG_WINDOW_RESIZABLE)
|
||||||
void SetWindowMaxSize(int width, int height)
|
void SetWindowMaxSize(int width, int height)
|
||||||
{
|
{
|
||||||
CORE.Window.windowMax.width = width;
|
CORE.Window.screenMax.width = width;
|
||||||
CORE.Window.windowMax.height = height;
|
CORE.Window.screenMax.height = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set window dimensions
|
// Set window dimensions
|
||||||
|
|
@ -635,18 +529,6 @@ void OpenURL(const char *url)
|
||||||
// Module Functions Definition: Inputs
|
// Module Functions Definition: Inputs
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Get gamepad internal name id
|
|
||||||
const char *GetGamepadName(int gamepad)
|
|
||||||
{
|
|
||||||
return CORE.Input.Gamepad.name[gamepad];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get gamepad axis count
|
|
||||||
int GetGamepadAxisCount(int gamepad)
|
|
||||||
{
|
|
||||||
return CORE.Input.Gamepad.axisCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set internal gamepad mappings
|
// Set internal gamepad mappings
|
||||||
int SetGamepadMappings(const char *mappings)
|
int SetGamepadMappings(const char *mappings)
|
||||||
{
|
{
|
||||||
|
|
@ -654,24 +536,6 @@ int SetGamepadMappings(const char *mappings)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get mouse position X
|
|
||||||
int GetMouseX(void)
|
|
||||||
{
|
|
||||||
return (int)CORE.Input.Touch.position[0].x;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get mouse position Y
|
|
||||||
int GetMouseY(void)
|
|
||||||
{
|
|
||||||
return (int)CORE.Input.Touch.position[0].y;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get mouse position XY
|
|
||||||
Vector2 GetMousePosition(void)
|
|
||||||
{
|
|
||||||
return GetTouchPosition(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set mouse position XY
|
// Set mouse position XY
|
||||||
void SetMousePosition(int x, int y)
|
void SetMousePosition(int x, int y)
|
||||||
{
|
{
|
||||||
|
|
@ -679,43 +543,12 @@ void SetMousePosition(int x, int y)
|
||||||
CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
|
CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get mouse wheel movement Y
|
|
||||||
float GetMouseWheelMove(void)
|
|
||||||
{
|
|
||||||
TRACELOG(LOG_WARNING, "GetMouseWheelMove() not implemented on target platform");
|
|
||||||
return 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set mouse cursor
|
// Set mouse cursor
|
||||||
void SetMouseCursor(int cursor)
|
void SetMouseCursor(int cursor)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "SetMouseCursor() not implemented on target platform");
|
TRACELOG(LOG_WARNING, "SetMouseCursor() not implemented on target platform");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get touch position X for touch point 0 (relative to screen size)
|
|
||||||
int GetTouchX(void)
|
|
||||||
{
|
|
||||||
return (int)CORE.Input.Touch.position[0].x;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get touch position Y for touch point 0 (relative to screen size)
|
|
||||||
int GetTouchY(void)
|
|
||||||
{
|
|
||||||
return (int)CORE.Input.Touch.position[0].y;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get touch position XY for a touch point index (relative to screen size)
|
|
||||||
// TODO: Touch position should be scaled depending on display size and render size
|
|
||||||
Vector2 GetTouchPosition(int index)
|
|
||||||
{
|
|
||||||
Vector2 position = { -1.0f, -1.0f };
|
|
||||||
|
|
||||||
if (index < MAX_TOUCH_POINTS) position = CORE.Input.Touch.position[index];
|
|
||||||
else TRACELOG(LOG_WARNING, "INPUT: Required touch point out of range (Max touch points: %i)", MAX_TOUCH_POINTS);
|
|
||||||
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Register all input events
|
// Register all input events
|
||||||
void PollInputEvents(void)
|
void PollInputEvents(void)
|
||||||
{
|
{
|
||||||
|
|
@ -774,25 +607,108 @@ void PollInputEvents(void)
|
||||||
// Module Internal Functions Definition
|
// Module Internal Functions Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Initialize platform: graphics, inputs and more
|
||||||
|
static int InitPlatform(void)
|
||||||
|
{
|
||||||
|
CORE.Window.currentFbo.width = CORE.Window.screen.width;
|
||||||
|
CORE.Window.currentFbo.height = CORE.Window.screen.height;
|
||||||
|
|
||||||
|
// Set desired windows flags before initializing anything
|
||||||
|
ANativeActivity_setWindowFlags(platform.app->activity, AWINDOW_FLAG_FULLSCREEN, 0); //AWINDOW_FLAG_SCALED, AWINDOW_FLAG_DITHER
|
||||||
|
|
||||||
|
int orientation = AConfiguration_getOrientation(platform.app->config);
|
||||||
|
|
||||||
|
if (orientation == ACONFIGURATION_ORIENTATION_PORT) TRACELOG(LOG_INFO, "ANDROID: Window orientation set as portrait");
|
||||||
|
else if (orientation == ACONFIGURATION_ORIENTATION_LAND) TRACELOG(LOG_INFO, "ANDROID: Window orientation set as landscape");
|
||||||
|
|
||||||
|
// TODO: Automatic orientation doesn't seem to work
|
||||||
|
if (CORE.Window.screen.width <= CORE.Window.screen.height)
|
||||||
|
{
|
||||||
|
AConfiguration_setOrientation(platform.app->config, ACONFIGURATION_ORIENTATION_PORT);
|
||||||
|
TRACELOG(LOG_WARNING, "ANDROID: Window orientation changed to portrait");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AConfiguration_setOrientation(platform.app->config, ACONFIGURATION_ORIENTATION_LAND);
|
||||||
|
TRACELOG(LOG_WARNING, "ANDROID: Window orientation changed to landscape");
|
||||||
|
}
|
||||||
|
|
||||||
|
//AConfiguration_getDensity(platform.app->config);
|
||||||
|
//AConfiguration_getKeyboard(platform.app->config);
|
||||||
|
//AConfiguration_getScreenSize(platform.app->config);
|
||||||
|
//AConfiguration_getScreenLong(platform.app->config);
|
||||||
|
|
||||||
|
// Initialize App command system
|
||||||
|
// NOTE: On APP_CMD_INIT_WINDOW -> InitGraphicsDevice(), InitTimer(), LoadFontDefault()...
|
||||||
|
platform.app->onAppCmd = AndroidCommandCallback;
|
||||||
|
|
||||||
|
// Initialize input events system
|
||||||
|
platform.app->onInputEvent = AndroidInputCallback;
|
||||||
|
|
||||||
|
// Initialize assets manager
|
||||||
|
InitAssetManager(platform.app->activity->assetManager, platform.app->activity->internalDataPath);
|
||||||
|
|
||||||
|
// Initialize base path for storage
|
||||||
|
CORE.Storage.basePath = platform.app->activity->internalDataPath;
|
||||||
|
|
||||||
|
// Set some default window flags
|
||||||
|
CORE.Window.flags &= ~FLAG_WINDOW_HIDDEN; // false
|
||||||
|
CORE.Window.flags &= ~FLAG_WINDOW_MINIMIZED; // false
|
||||||
|
CORE.Window.flags |= FLAG_WINDOW_MAXIMIZED; // true
|
||||||
|
CORE.Window.flags &= ~FLAG_WINDOW_UNFOCUSED; // false
|
||||||
|
|
||||||
|
TRACELOG(LOG_INFO, "PLATFORM: ANDROID: Application initialized successfully");
|
||||||
|
|
||||||
|
// Android ALooper_pollAll() variables
|
||||||
|
int pollResult = 0;
|
||||||
|
int pollEvents = 0;
|
||||||
|
|
||||||
|
// Wait for window to be initialized (display and context)
|
||||||
|
while (!CORE.Window.ready)
|
||||||
|
{
|
||||||
|
// Process events loop
|
||||||
|
while ((pollResult = ALooper_pollAll(0, NULL, &pollEvents, (void**)&platform.source)) >= 0)
|
||||||
|
{
|
||||||
|
// Process this event
|
||||||
|
if (platform.source != NULL) platform.source->process(platform.app, platform.source);
|
||||||
|
|
||||||
|
// NOTE: Never close window, native activity is controlled by the system!
|
||||||
|
//if (platform.app->destroyRequested != 0) CORE.Window.shouldClose = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close platform
|
||||||
|
static void ClosePlatform(void)
|
||||||
|
{
|
||||||
|
// Close surface, context and display
|
||||||
|
if (platform.device != EGL_NO_DISPLAY)
|
||||||
|
{
|
||||||
|
eglMakeCurrent(platform.device, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||||
|
|
||||||
|
if (platform.surface != EGL_NO_SURFACE)
|
||||||
|
{
|
||||||
|
eglDestroySurface(platform.device, platform.surface);
|
||||||
|
platform.surface = EGL_NO_SURFACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (platform.context != EGL_NO_CONTEXT)
|
||||||
|
{
|
||||||
|
eglDestroyContext(platform.device, platform.context);
|
||||||
|
platform.context = EGL_NO_CONTEXT;
|
||||||
|
}
|
||||||
|
|
||||||
|
eglTerminate(platform.device);
|
||||||
|
platform.device = EGL_NO_DISPLAY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize display device and framebuffer
|
// Initialize display device and framebuffer
|
||||||
// NOTE: width and height represent the screen (framebuffer) desired size, not actual display size
|
// NOTE: width and height represent the screen (framebuffer) desired size, not actual display size
|
||||||
// If width or height are 0, default display size will be used for framebuffer size
|
// If width or height are 0, default display size will be used for framebuffer size
|
||||||
// NOTE: returns false in case graphic device could not be created
|
// NOTE: returns false in case graphic device could not be created
|
||||||
static bool InitGraphicsDevice(int width, int height)
|
static bool InitGraphicsDevice(void)
|
||||||
{
|
{
|
||||||
CORE.Window.screen.width = width; // User desired width
|
|
||||||
CORE.Window.screen.height = height; // User desired height
|
|
||||||
CORE.Window.screenScale = MatrixIdentity(); // No draw scaling required by default
|
|
||||||
|
|
||||||
// Set the screen minimum and maximum default values to 0
|
|
||||||
CORE.Window.screenMin.width = 0;
|
|
||||||
CORE.Window.screenMin.height = 0;
|
|
||||||
CORE.Window.screenMax.width = 0;
|
|
||||||
CORE.Window.screenMax.height = 0;
|
|
||||||
|
|
||||||
// NOTE: Framebuffer (render area - CORE.Window.render.width, CORE.Window.render.height) could include black bars...
|
|
||||||
// ...in top-down or left-right to match display aspect ratio (no weird scaling)
|
|
||||||
|
|
||||||
CORE.Window.fullscreen = true;
|
CORE.Window.fullscreen = true;
|
||||||
CORE.Window.flags |= FLAG_FULLSCREEN_MODE;
|
CORE.Window.flags |= FLAG_FULLSCREEN_MODE;
|
||||||
|
|
||||||
|
|
@ -832,7 +748,7 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
if (platform.device == EGL_NO_DISPLAY)
|
if (platform.device == EGL_NO_DISPLAY)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "DISPLAY: Failed to initialize EGL device");
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to initialize EGL device");
|
||||||
return false;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the EGL device connection
|
// Initialize the EGL device connection
|
||||||
|
|
@ -840,7 +756,7 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
{
|
{
|
||||||
// If all of the calls to eglInitialize returned EGL_FALSE then an error has occurred.
|
// If all of the calls to eglInitialize returned EGL_FALSE then an error has occurred.
|
||||||
TRACELOG(LOG_WARNING, "DISPLAY: Failed to initialize EGL device");
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to initialize EGL device");
|
||||||
return false;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get an appropriate EGL framebuffer configuration
|
// Get an appropriate EGL framebuffer configuration
|
||||||
|
|
@ -854,7 +770,7 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
if (platform.context == EGL_NO_CONTEXT)
|
if (platform.context == EGL_NO_CONTEXT)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "DISPLAY: Failed to create EGL context");
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to create EGL context");
|
||||||
return false;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create an EGL window surface
|
// Create an EGL window surface
|
||||||
|
|
@ -883,7 +799,7 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
if (eglMakeCurrent(platform.device, platform.surface, platform.surface, platform.context) == EGL_FALSE)
|
if (eglMakeCurrent(platform.device, platform.surface, platform.surface, platform.context) == EGL_FALSE)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "DISPLAY: Failed to attach EGL rendering context to EGL surface");
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to attach EGL rendering context to EGL surface");
|
||||||
return false;
|
return -1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -903,19 +819,11 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
// NOTE: GL procedures address loader is required to load extensions
|
// NOTE: GL procedures address loader is required to load extensions
|
||||||
rlLoadExtensions(eglGetProcAddress);
|
rlLoadExtensions(eglGetProcAddress);
|
||||||
|
|
||||||
// Initialize OpenGL context (states and resources)
|
|
||||||
// NOTE: CORE.Window.currentFbo.width and CORE.Window.currentFbo.height not used, just stored as globals in rlgl
|
|
||||||
rlglInit(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
|
|
||||||
|
|
||||||
// Setup default viewport
|
|
||||||
// NOTE: It updated CORE.Window.render.width and CORE.Window.render.height
|
|
||||||
SetupViewport(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
|
|
||||||
|
|
||||||
CORE.Window.ready = true;
|
CORE.Window.ready = true;
|
||||||
|
|
||||||
if ((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) > 0) MinimizeWindow();
|
if ((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) > 0) MinimizeWindow();
|
||||||
|
|
||||||
return true;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ANDROID: Process activity lifecycle commands
|
// ANDROID: Process activity lifecycle commands
|
||||||
|
|
@ -958,25 +866,50 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
|
||||||
CORE.Window.display.height = ANativeWindow_getHeight(platform.app->window);
|
CORE.Window.display.height = ANativeWindow_getHeight(platform.app->window);
|
||||||
|
|
||||||
// Initialize graphics device (display device and OpenGL context)
|
// Initialize graphics device (display device and OpenGL context)
|
||||||
InitGraphicsDevice(CORE.Window.screen.width, CORE.Window.screen.height);
|
InitGraphicsDevice();
|
||||||
|
|
||||||
|
// Initialize OpenGL context (states and resources)
|
||||||
|
// NOTE: CORE.Window.currentFbo.width and CORE.Window.currentFbo.height not used, just stored as globals in rlgl
|
||||||
|
rlglInit(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
|
||||||
|
|
||||||
|
// Setup default viewport
|
||||||
|
// NOTE: It updated CORE.Window.render.width and CORE.Window.render.height
|
||||||
|
SetupViewport(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
|
||||||
|
|
||||||
// Initialize hi-res timer
|
// Initialize hi-res timer
|
||||||
InitTimer();
|
InitTimer();
|
||||||
|
|
||||||
// Initialize random seed
|
|
||||||
srand((unsigned int)time(NULL));
|
|
||||||
|
|
||||||
#if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT)
|
#if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT)
|
||||||
// Load default font
|
// Load default font
|
||||||
// WARNING: External function: Module required: rtext
|
// WARNING: External function: Module required: rtext
|
||||||
LoadFontDefault();
|
LoadFontDefault();
|
||||||
Rectangle rec = GetFontDefault().recs[95];
|
|
||||||
// NOTE: We setup a 1px padding on char rectangle to avoid pixel bleeding on MSAA filtering
|
|
||||||
#if defined(SUPPORT_MODULE_RSHAPES)
|
#if defined(SUPPORT_MODULE_RSHAPES)
|
||||||
SetShapesTexture(GetFontDefault().texture, (Rectangle){ rec.x + 1, rec.y + 1, rec.width - 2, rec.height - 2 }); // WARNING: Module required: rshapes
|
// Set font white rectangle for shapes drawing, so shapes and text can be batched together
|
||||||
|
// WARNING: rshapes module is required, if not available, default internal white rectangle is used
|
||||||
|
Rectangle rec = GetFontDefault().recs[95];
|
||||||
|
if (CORE.Window.flags & FLAG_MSAA_4X_HINT)
|
||||||
|
{
|
||||||
|
// NOTE: We try to maxime rec padding to avoid pixel bleeding on MSAA filtering
|
||||||
|
SetShapesTexture(GetFontDefault().texture, (Rectangle){ rec.x + 2, rec.y + 2, 1, 1 });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// NOTE: We set up a 1px padding on char rectangle to avoid pixel bleeding
|
||||||
|
SetShapesTexture(GetFontDefault().texture, (Rectangle){ rec.x + 1, rec.y + 1, rec.width - 2, rec.height - 2 });
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#if defined(SUPPORT_MODULE_RSHAPES)
|
||||||
|
// Set default texture and rectangle to be used for shapes drawing
|
||||||
|
// NOTE: rlgl default texture is a 1x1 pixel UNCOMPRESSED_R8G8B8A8
|
||||||
|
Texture2D texture = { rlGetTextureIdDefault(), 1, 1, 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 };
|
||||||
|
SetShapesTexture(texture, (Rectangle){ 0.0f, 0.0f, 1.0f, 1.0f }); // WARNING: Module required: rshapes
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Initialize random seed
|
||||||
|
SetRandomSeed((unsigned int)time(NULL));
|
||||||
|
|
||||||
// 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
|
||||||
/*
|
/*
|
||||||
|
|
@ -997,12 +930,14 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
|
||||||
case APP_CMD_GAINED_FOCUS:
|
case APP_CMD_GAINED_FOCUS:
|
||||||
{
|
{
|
||||||
platform.appEnabled = true;
|
platform.appEnabled = true;
|
||||||
|
CORE.Window.flags &= ~FLAG_WINDOW_UNFOCUSED;
|
||||||
//ResumeMusicStream();
|
//ResumeMusicStream();
|
||||||
} break;
|
} break;
|
||||||
case APP_CMD_PAUSE: break;
|
case APP_CMD_PAUSE: break;
|
||||||
case APP_CMD_LOST_FOCUS:
|
case APP_CMD_LOST_FOCUS:
|
||||||
{
|
{
|
||||||
platform.appEnabled = false;
|
platform.appEnabled = false;
|
||||||
|
CORE.Window.flags |= FLAG_WINDOW_UNFOCUSED;
|
||||||
//PauseMusicStream();
|
//PauseMusicStream();
|
||||||
} break;
|
} break;
|
||||||
case APP_CMD_TERM_WINDOW:
|
case APP_CMD_TERM_WINDOW:
|
||||||
|
|
@ -1234,6 +1169,8 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
|
||||||
{
|
{
|
||||||
gestureEvent.pointId[i] = CORE.Input.Touch.pointId[i];
|
gestureEvent.pointId[i] = CORE.Input.Touch.pointId[i];
|
||||||
gestureEvent.position[i] = CORE.Input.Touch.position[i];
|
gestureEvent.position[i] = CORE.Input.Touch.position[i];
|
||||||
|
gestureEvent.position[i].x /= (float)GetScreenWidth();
|
||||||
|
gestureEvent.position[i].y /= (float)GetScreenHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gesture data is sent to gestures system for processing
|
// Gesture data is sent to gestures system for processing
|
||||||
|
|
@ -1260,6 +1197,20 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
|
||||||
if (CORE.Input.Touch.pointCount > 0) CORE.Input.Touch.currentTouchState[MOUSE_BUTTON_LEFT] = 1;
|
if (CORE.Input.Touch.pointCount > 0) CORE.Input.Touch.currentTouchState[MOUSE_BUTTON_LEFT] = 1;
|
||||||
else CORE.Input.Touch.currentTouchState[MOUSE_BUTTON_LEFT] = 0;
|
else CORE.Input.Touch.currentTouchState[MOUSE_BUTTON_LEFT] = 0;
|
||||||
|
|
||||||
|
// Stores the previous position of touch[0] only while it's active to calculate the delta.
|
||||||
|
if (flags == AMOTION_EVENT_ACTION_MOVE)
|
||||||
|
{
|
||||||
|
CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CORE.Input.Mouse.previousPosition = CORE.Input.Touch.position[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map touch[0] as mouse input for convenience
|
||||||
|
CORE.Input.Mouse.currentPosition = CORE.Input.Touch.position[0];
|
||||||
|
CORE.Input.Mouse.currentWheelMove = (Vector2){ 0.0f, 0.0f };
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
*
|
*
|
||||||
* rcore_desktop - Functions to manage window, graphics device and inputs
|
* rcore_desktop - Functions to manage window, graphics device and inputs
|
||||||
*
|
*
|
||||||
* PLATFORM: DESKTOP
|
* PLATFORM: DESKTOP: GLFW
|
||||||
* - Windows (Win32, Win64)
|
* - Windows (Win32, Win64)
|
||||||
* - Linux (X11/Wayland desktop mode)
|
* - Linux (X11/Wayland desktop mode)
|
||||||
* - FreeBSD, OpenBSD, NetBSD, DragonFly (X11 desktop)
|
* - FreeBSD, OpenBSD, NetBSD, DragonFly (X11 desktop)
|
||||||
|
|
@ -111,7 +111,8 @@ static PlatformData platform = { 0 }; // Platform specific data
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module Internal Functions Declaration
|
// Module Internal Functions Declaration
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
static bool InitGraphicsDevice(int width, int height); // Initialize graphics device
|
static int InitPlatform(void); // Initialize platform (graphics, inputs and more)
|
||||||
|
static void ClosePlatform(void); // Close platform
|
||||||
|
|
||||||
// Error callback event
|
// Error callback event
|
||||||
static void ErrorCallback(int error, const char *description); // GLFW3 Error Callback, runs on GLFW3 error
|
static void ErrorCallback(int error, const char *description); // GLFW3 Error Callback, runs on GLFW3 error
|
||||||
|
|
@ -176,33 +177,31 @@ void InitWindow(int width, int height, const char *title)
|
||||||
TRACELOG(LOG_INFO, " > raudio:.... not loaded (optional)");
|
TRACELOG(LOG_INFO, " > raudio:.... not loaded (optional)");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// NOTE: Keep internal pointer to input title string (no copy)
|
// Initialize window data
|
||||||
|
CORE.Window.screen.width = width;
|
||||||
|
CORE.Window.screen.height = height;
|
||||||
|
CORE.Window.eventWaiting = false;
|
||||||
|
CORE.Window.screenScale = MatrixIdentity(); // No draw scaling required by default
|
||||||
if ((title != NULL) && (title[0] != 0)) CORE.Window.title = title;
|
if ((title != NULL) && (title[0] != 0)) CORE.Window.title = title;
|
||||||
|
|
||||||
// Initialize global input state
|
// Initialize global input state
|
||||||
memset(&CORE.Input, 0, sizeof(CORE.Input)); // Reset CORE structure to 0
|
memset(&CORE.Input, 0, sizeof(CORE.Input)); // Reset CORE.Input structure to 0
|
||||||
CORE.Input.Keyboard.exitKey = KEY_ESCAPE;
|
CORE.Input.Keyboard.exitKey = KEY_ESCAPE;
|
||||||
CORE.Input.Mouse.scale = (Vector2){ 1.0f, 1.0f };
|
CORE.Input.Mouse.scale = (Vector2){ 1.0f, 1.0f };
|
||||||
CORE.Input.Mouse.cursor = MOUSE_CURSOR_ARROW;
|
CORE.Input.Mouse.cursor = MOUSE_CURSOR_ARROW;
|
||||||
CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN
|
CORE.Input.Gamepad.lastButtonPressed = GAMEPAD_BUTTON_UNKNOWN;
|
||||||
CORE.Window.eventWaiting = false;
|
|
||||||
|
|
||||||
// Initialize graphics device
|
// Initialize platform
|
||||||
// NOTE: returns true if window and graphic device has been initialized successfully
|
//--------------------------------------------------------------
|
||||||
CORE.Window.ready = InitGraphicsDevice(width, height);
|
InitPlatform();
|
||||||
|
//--------------------------------------------------------------
|
||||||
|
|
||||||
// If graphic device is no properly initialized, we end program
|
// Initialize rlgl default data (buffers and shaders)
|
||||||
if (!CORE.Window.ready) { TRACELOG(LOG_FATAL, "PLATFORM: Failed to initialize graphic device"); return; }
|
// NOTE: CORE.Window.currentFbo.width and CORE.Window.currentFbo.height not used, just stored as globals in rlgl
|
||||||
else SetWindowPosition(GetMonitorWidth(GetCurrentMonitor())/2 - CORE.Window.screen.width/2, GetMonitorHeight(GetCurrentMonitor())/2 - CORE.Window.screen.height/2);
|
rlglInit(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
|
||||||
|
|
||||||
// Initialize hi-res timer
|
// Setup default viewport
|
||||||
InitTimer();
|
SetupViewport(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
|
||||||
|
|
||||||
// Initialize random seed
|
|
||||||
SetRandomSeed((unsigned int)time(NULL));
|
|
||||||
|
|
||||||
// Initialize base path for storage
|
|
||||||
CORE.Storage.basePath = GetWorkingDirectory();
|
|
||||||
|
|
||||||
#if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT)
|
#if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT)
|
||||||
// Load default font
|
// Load default font
|
||||||
|
|
@ -246,6 +245,9 @@ void InitWindow(int width, int height, const char *title)
|
||||||
CORE.Time.frameCounter = 0;
|
CORE.Time.frameCounter = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Initialize random seed
|
||||||
|
SetRandomSeed((unsigned int)time(NULL));
|
||||||
|
|
||||||
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP: Application initialized successfully");
|
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP: Application initialized successfully");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -267,14 +269,9 @@ void CloseWindow(void)
|
||||||
|
|
||||||
rlglClose(); // De-init rlgl
|
rlglClose(); // De-init rlgl
|
||||||
|
|
||||||
// Platform specific close window
|
// De-initialize platform
|
||||||
//--------------------------------------------------------------
|
//--------------------------------------------------------------
|
||||||
glfwDestroyWindow(platform.handle);
|
ClosePlatform();
|
||||||
glfwTerminate();
|
|
||||||
|
|
||||||
#if defined(_WIN32) && defined(SUPPORT_WINMM_HIGHRES_TIMER) && !defined(SUPPORT_BUSY_WAIT_LOOP)
|
|
||||||
timeEndPeriod(1); // Restore time period
|
|
||||||
#endif
|
|
||||||
//--------------------------------------------------------------
|
//--------------------------------------------------------------
|
||||||
|
|
||||||
#if defined(SUPPORT_EVENTS_AUTOMATION)
|
#if defined(SUPPORT_EVENTS_AUTOMATION)
|
||||||
|
|
@ -304,36 +301,6 @@ bool WindowShouldClose(void)
|
||||||
else return true;
|
else return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if window is currently hidden
|
|
||||||
bool IsWindowHidden(void)
|
|
||||||
{
|
|
||||||
return ((CORE.Window.flags & FLAG_WINDOW_HIDDEN) > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if window has been minimized
|
|
||||||
bool IsWindowMinimized(void)
|
|
||||||
{
|
|
||||||
return ((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if window has been maximized
|
|
||||||
bool IsWindowMaximized(void)
|
|
||||||
{
|
|
||||||
return ((CORE.Window.flags & FLAG_WINDOW_MAXIMIZED) > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if window has the focus
|
|
||||||
bool IsWindowFocused(void)
|
|
||||||
{
|
|
||||||
return ((CORE.Window.flags & FLAG_WINDOW_UNFOCUSED) == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if window has been resizedLastFrame
|
|
||||||
bool IsWindowResized(void)
|
|
||||||
{
|
|
||||||
return CORE.Window.resizedLastFrame;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Toggle fullscreen mode
|
// Toggle fullscreen mode
|
||||||
void ToggleFullscreen(void)
|
void ToggleFullscreen(void)
|
||||||
{
|
{
|
||||||
|
|
@ -380,35 +347,6 @@ void ToggleFullscreen(void)
|
||||||
if (CORE.Window.flags & FLAG_VSYNC_HINT) glfwSwapInterval(1);
|
if (CORE.Window.flags & FLAG_VSYNC_HINT) glfwSwapInterval(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set window state: maximized, if resizable
|
|
||||||
void MaximizeWindow(void)
|
|
||||||
{
|
|
||||||
if (glfwGetWindowAttrib(platform.handle, GLFW_RESIZABLE) == GLFW_TRUE)
|
|
||||||
{
|
|
||||||
glfwMaximizeWindow(platform.handle);
|
|
||||||
CORE.Window.flags |= FLAG_WINDOW_MAXIMIZED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set window state: minimized
|
|
||||||
void MinimizeWindow(void)
|
|
||||||
{
|
|
||||||
// NOTE: Following function launches callback that sets appropriate flag!
|
|
||||||
glfwIconifyWindow(platform.handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set window state: not minimized/maximized
|
|
||||||
void RestoreWindow(void)
|
|
||||||
{
|
|
||||||
if (glfwGetWindowAttrib(platform.handle, GLFW_RESIZABLE) == GLFW_TRUE)
|
|
||||||
{
|
|
||||||
// Restores the specified window if it was previously iconified (minimized) or maximized
|
|
||||||
glfwRestoreWindow(platform.handle);
|
|
||||||
CORE.Window.flags &= ~FLAG_WINDOW_MINIMIZED;
|
|
||||||
CORE.Window.flags &= ~FLAG_WINDOW_MAXIMIZED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Toggle borderless windowed mode
|
// Toggle borderless windowed mode
|
||||||
void ToggleBorderlessWindowed(void)
|
void ToggleBorderlessWindowed(void)
|
||||||
{
|
{
|
||||||
|
|
@ -484,6 +422,35 @@ void ToggleBorderlessWindowed(void)
|
||||||
else TRACELOG(LOG_WARNING, "GLFW: Failed to find selected monitor");
|
else TRACELOG(LOG_WARNING, "GLFW: Failed to find selected monitor");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set window state: maximized, if resizable
|
||||||
|
void MaximizeWindow(void)
|
||||||
|
{
|
||||||
|
if (glfwGetWindowAttrib(platform.handle, GLFW_RESIZABLE) == GLFW_TRUE)
|
||||||
|
{
|
||||||
|
glfwMaximizeWindow(platform.handle);
|
||||||
|
CORE.Window.flags |= FLAG_WINDOW_MAXIMIZED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set window state: minimized
|
||||||
|
void MinimizeWindow(void)
|
||||||
|
{
|
||||||
|
// NOTE: Following function launches callback that sets appropriate flag!
|
||||||
|
glfwIconifyWindow(platform.handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set window state: not minimized/maximized
|
||||||
|
void RestoreWindow(void)
|
||||||
|
{
|
||||||
|
if (glfwGetWindowAttrib(platform.handle, GLFW_RESIZABLE) == GLFW_TRUE)
|
||||||
|
{
|
||||||
|
// Restores the specified window if it was previously iconified (minimized) or maximized
|
||||||
|
glfwRestoreWindow(platform.handle);
|
||||||
|
CORE.Window.flags &= ~FLAG_WINDOW_MINIMIZED;
|
||||||
|
CORE.Window.flags &= ~FLAG_WINDOW_MAXIMIZED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Set window configuration state using flags
|
// Set window configuration state using flags
|
||||||
void SetWindowState(unsigned int flags)
|
void SetWindowState(unsigned int flags)
|
||||||
{
|
{
|
||||||
|
|
@ -1222,47 +1189,12 @@ void OpenURL(const char *url)
|
||||||
// Module Functions Definition: Inputs
|
// Module Functions Definition: Inputs
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Get gamepad internal name id
|
|
||||||
const char *GetGamepadName(int gamepad)
|
|
||||||
{
|
|
||||||
return CORE.Input.Gamepad.name[gamepad];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get gamepad axis count
|
|
||||||
int GetGamepadAxisCount(int gamepad)
|
|
||||||
{
|
|
||||||
return CORE.Input.Gamepad.axisCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set internal gamepad mappings
|
// Set internal gamepad mappings
|
||||||
int SetGamepadMappings(const char *mappings)
|
int SetGamepadMappings(const char *mappings)
|
||||||
{
|
{
|
||||||
return glfwUpdateGamepadMappings(mappings);
|
return glfwUpdateGamepadMappings(mappings);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get mouse position X
|
|
||||||
int GetMouseX(void)
|
|
||||||
{
|
|
||||||
return (int)((CORE.Input.Mouse.currentPosition.x + CORE.Input.Mouse.offset.x)*CORE.Input.Mouse.scale.x);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get mouse position Y
|
|
||||||
int GetMouseY(void)
|
|
||||||
{
|
|
||||||
return (int)((CORE.Input.Mouse.currentPosition.y + CORE.Input.Mouse.offset.y)*CORE.Input.Mouse.scale.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get mouse position XY
|
|
||||||
Vector2 GetMousePosition(void)
|
|
||||||
{
|
|
||||||
Vector2 position = { 0 };
|
|
||||||
|
|
||||||
position.x = (CORE.Input.Mouse.currentPosition.x + CORE.Input.Mouse.offset.x)*CORE.Input.Mouse.scale.x;
|
|
||||||
position.y = (CORE.Input.Mouse.currentPosition.y + CORE.Input.Mouse.offset.y)*CORE.Input.Mouse.scale.y;
|
|
||||||
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set mouse position XY
|
// Set mouse position XY
|
||||||
void SetMousePosition(int x, int y)
|
void SetMousePosition(int x, int y)
|
||||||
{
|
{
|
||||||
|
|
@ -1273,17 +1205,6 @@ void SetMousePosition(int x, int y)
|
||||||
glfwSetCursorPos(platform.handle, CORE.Input.Mouse.currentPosition.x, CORE.Input.Mouse.currentPosition.y);
|
glfwSetCursorPos(platform.handle, CORE.Input.Mouse.currentPosition.x, CORE.Input.Mouse.currentPosition.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get mouse wheel movement Y
|
|
||||||
float GetMouseWheelMove(void)
|
|
||||||
{
|
|
||||||
float result = 0.0f;
|
|
||||||
|
|
||||||
if (fabsf(CORE.Input.Mouse.currentWheelMove.x) > fabsf(CORE.Input.Mouse.currentWheelMove.y)) result = (float)CORE.Input.Mouse.currentWheelMove.x;
|
|
||||||
else result = (float)CORE.Input.Mouse.currentWheelMove.y;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set mouse cursor
|
// Set mouse cursor
|
||||||
void SetMouseCursor(int cursor)
|
void SetMouseCursor(int cursor)
|
||||||
{
|
{
|
||||||
|
|
@ -1296,32 +1217,6 @@ void SetMouseCursor(int cursor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get touch position X for touch point 0 (relative to screen size)
|
|
||||||
int GetTouchX(void)
|
|
||||||
{
|
|
||||||
return GetMouseX();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get touch position Y for touch point 0 (relative to screen size)
|
|
||||||
int GetTouchY(void)
|
|
||||||
{
|
|
||||||
return GetMouseY();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get touch position XY for a touch point index (relative to screen size)
|
|
||||||
// TODO: Touch position should be scaled depending on display size and render size
|
|
||||||
Vector2 GetTouchPosition(int index)
|
|
||||||
{
|
|
||||||
Vector2 position = { -1.0f, -1.0f };
|
|
||||||
|
|
||||||
// TODO: GLFW does not support multi-touch input just yet
|
|
||||||
// https://www.codeproject.com/Articles/668404/Programming-for-Multi-Touch
|
|
||||||
// https://docs.microsoft.com/en-us/windows/win32/wintouch/getting-started-with-multi-touch-messages
|
|
||||||
if (index == 0) position = GetMousePosition();
|
|
||||||
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Register all input events
|
// Register all input events
|
||||||
void PollInputEvents(void)
|
void PollInputEvents(void)
|
||||||
{
|
{
|
||||||
|
|
@ -1365,6 +1260,13 @@ void PollInputEvents(void)
|
||||||
// Reset touch positions
|
// Reset touch positions
|
||||||
//for (int i = 0; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.position[i] = (Vector2){ 0, 0 };
|
//for (int i = 0; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.position[i] = (Vector2){ 0, 0 };
|
||||||
|
|
||||||
|
// Map touch position to mouse position for convenience
|
||||||
|
// WARNING: If the target desktop device supports touch screen, this behavious should be reviewed!
|
||||||
|
// TODO: GLFW does not support multi-touch input just yet
|
||||||
|
// https://www.codeproject.com/Articles/668404/Programming-for-Multi-Touch
|
||||||
|
// https://docs.microsoft.com/en-us/windows/win32/wintouch/getting-started-with-multi-touch-messages
|
||||||
|
CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition;
|
||||||
|
|
||||||
// Check if gamepads are ready
|
// Check if gamepads are ready
|
||||||
// NOTE: We do it here in case of disconnection
|
// NOTE: We do it here in case of disconnection
|
||||||
for (int i = 0; i < MAX_GAMEPADS; i++)
|
for (int i = 0; i < MAX_GAMEPADS; i++)
|
||||||
|
|
@ -1454,25 +1356,9 @@ void PollInputEvents(void)
|
||||||
// Module Internal Functions Definition
|
// Module Internal Functions Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Initialize display device and framebuffer
|
// Initialize platform: graphics, inputs and more
|
||||||
// NOTE: width and height represent the screen (framebuffer) desired size, not actual display size
|
static int InitPlatform(void)
|
||||||
// If width or height are 0, default display size will be used for framebuffer size
|
|
||||||
// NOTE: returns false in case graphic device could not be created
|
|
||||||
static bool InitGraphicsDevice(int width, int height)
|
|
||||||
{
|
{
|
||||||
CORE.Window.screen.width = width; // User desired width
|
|
||||||
CORE.Window.screen.height = height; // User desired height
|
|
||||||
CORE.Window.screenScale = MatrixIdentity(); // No draw scaling required by default
|
|
||||||
|
|
||||||
// Set the screen minimum and maximum default values to 0
|
|
||||||
CORE.Window.screenMin.width = 0;
|
|
||||||
CORE.Window.screenMin.height = 0;
|
|
||||||
CORE.Window.screenMax.width = 0;
|
|
||||||
CORE.Window.screenMax.height = 0;
|
|
||||||
|
|
||||||
// NOTE: Framebuffer (render area - CORE.Window.render.width, CORE.Window.render.height) could include black bars...
|
|
||||||
// ...in top-down or left-right to match display aspect ratio (no weird scaling)
|
|
||||||
|
|
||||||
glfwSetErrorCallback(ErrorCallback);
|
glfwSetErrorCallback(ErrorCallback);
|
||||||
/*
|
/*
|
||||||
// TODO: Setup GLFW custom allocators to match raylib ones
|
// TODO: Setup GLFW custom allocators to match raylib ones
|
||||||
|
|
@ -1485,15 +1371,13 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
|
|
||||||
glfwInitAllocator(&allocator);
|
glfwInitAllocator(&allocator);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
glfwInitHint(GLFW_COCOA_CHDIR_RESOURCES, GLFW_FALSE);
|
glfwInitHint(GLFW_COCOA_CHDIR_RESOURCES, GLFW_FALSE);
|
||||||
#endif
|
#endif
|
||||||
|
// Initialize GLFW internal global state
|
||||||
if (!glfwInit())
|
int result = glfwInit();
|
||||||
{
|
if (result == GLFW_FALSE) { TRACELOG(LOG_WARNING, "GLFW: Failed to initialize GLFW"); return -1; }
|
||||||
TRACELOG(LOG_WARNING, "GLFW: Failed to initialize GLFW");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
glfwDefaultWindowHints(); // Set default windows hints
|
glfwDefaultWindowHints(); // Set default windows hints
|
||||||
//glfwWindowHint(GLFW_RED_BITS, 8); // Framebuffer red color component bits
|
//glfwWindowHint(GLFW_RED_BITS, 8); // Framebuffer red color component bits
|
||||||
|
|
@ -1615,7 +1499,7 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
if (!monitor)
|
if (!monitor)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "GLFW: Failed to get primary monitor");
|
TRACELOG(LOG_WARNING, "GLFW: Failed to get primary monitor");
|
||||||
return false;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const GLFWvidmode *mode = glfwGetVideoMode(monitor);
|
const GLFWvidmode *mode = glfwGetVideoMode(monitor);
|
||||||
|
|
@ -1704,7 +1588,7 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
{
|
{
|
||||||
glfwTerminate();
|
glfwTerminate();
|
||||||
TRACELOG(LOG_WARNING, "GLFW: Failed to initialize Window");
|
TRACELOG(LOG_WARNING, "GLFW: Failed to initialize Window");
|
||||||
return false;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set window callback events
|
// Set window callback events
|
||||||
|
|
@ -1770,22 +1654,37 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
|
|
||||||
// Load OpenGL extensions
|
// Load OpenGL extensions
|
||||||
// NOTE: GL procedures address loader is required to load extensions
|
// NOTE: GL procedures address loader is required to load extensions
|
||||||
|
|
||||||
rlLoadExtensions(glfwGetProcAddress);
|
rlLoadExtensions(glfwGetProcAddress);
|
||||||
|
|
||||||
// Initialize OpenGL context (states and resources)
|
|
||||||
// NOTE: CORE.Window.currentFbo.width and CORE.Window.currentFbo.height not used, just stored as globals in rlgl
|
|
||||||
rlglInit(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
|
|
||||||
|
|
||||||
// Setup default viewport
|
|
||||||
// NOTE: It updated CORE.Window.render.width and CORE.Window.render.height
|
|
||||||
SetupViewport(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
|
|
||||||
|
|
||||||
if ((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) > 0) MinimizeWindow();
|
if ((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) > 0) MinimizeWindow();
|
||||||
|
|
||||||
return true;
|
CORE.Window.ready = true; // TODO: Proper validation on windows/context creation
|
||||||
|
|
||||||
|
// If graphic device is no properly initialized, we end program
|
||||||
|
if (!CORE.Window.ready) { TRACELOG(LOG_FATAL, "PLATFORM: Failed to initialize graphic device"); return -1; }
|
||||||
|
else SetWindowPosition(GetMonitorWidth(GetCurrentMonitor())/2 - CORE.Window.screen.width/2, GetMonitorHeight(GetCurrentMonitor())/2 - CORE.Window.screen.height/2);
|
||||||
|
|
||||||
|
// Initialize hi-res timer
|
||||||
|
InitTimer();
|
||||||
|
|
||||||
|
// Initialize base path for storage
|
||||||
|
CORE.Storage.basePath = GetWorkingDirectory();
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Close platform
|
||||||
|
static void ClosePlatform(void)
|
||||||
|
{
|
||||||
|
glfwDestroyWindow(platform.handle);
|
||||||
|
glfwTerminate();
|
||||||
|
|
||||||
|
#if defined(_WIN32) && defined(SUPPORT_WINMM_HIGHRES_TIMER) && !defined(SUPPORT_BUSY_WAIT_LOOP)
|
||||||
|
timeEndPeriod(1); // Restore time period
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// GLFW3 Error Callback, runs on GLFW3 error
|
// GLFW3 Error Callback, runs on GLFW3 error
|
||||||
static void ErrorCallback(int error, const char *description)
|
static void ErrorCallback(int error, const char *description)
|
||||||
{
|
{
|
||||||
|
|
@ -2053,7 +1952,7 @@ static void MouseScrollCallback(GLFWwindow *window, double xoffset, double yoffs
|
||||||
// GLFW3 CursorEnter Callback, when cursor enters the window
|
// GLFW3 CursorEnter Callback, when cursor enters the window
|
||||||
static void CursorEnterCallback(GLFWwindow *window, int enter)
|
static void CursorEnterCallback(GLFWwindow *window, int enter)
|
||||||
{
|
{
|
||||||
if (enter == true) CORE.Input.Mouse.cursorOnScreen = true;
|
if (enter) CORE.Input.Mouse.cursorOnScreen = true;
|
||||||
else CORE.Input.Mouse.cursorOnScreen = false;
|
else CORE.Input.Mouse.cursorOnScreen = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
453
src/rcore_drm.c
453
src/rcore_drm.c
|
|
@ -155,12 +155,13 @@ static PlatformData platform = { 0 }; // Platform specific data
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module Internal Functions Declaration
|
// Module Internal Functions Declaration
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
static bool InitGraphicsDevice(int width, int height); // Initialize graphics device
|
static int InitPlatform(void); // Initialize platform (graphics, inputs and more)
|
||||||
|
static void ClosePlatform(void); // Close platform
|
||||||
|
|
||||||
static void InitKeyboard(void); // Initialize raw keyboard system
|
static void InitKeyboard(void); // Initialize raw keyboard system
|
||||||
static void RestoreKeyboard(void); // Restore keyboard system
|
static void RestoreKeyboard(void); // Restore keyboard system
|
||||||
#if defined(SUPPORT_SSH_KEYBOARD_RPI)
|
#if defined(SUPPORT_SSH_KEYBOARD_RPI)
|
||||||
static void ProcessKeyboard(void); // Process keyboard events
|
static void ProcessKeyboard(void); // Process keyboard events
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void InitDrmInput(void); // Initialize inputs for DRM platform
|
static void InitDrmInput(void); // Initialize inputs for DRM platform
|
||||||
|
|
@ -223,38 +224,31 @@ void InitWindow(int width, int height, const char *title)
|
||||||
TRACELOG(LOG_INFO, " > raudio:.... not loaded (optional)");
|
TRACELOG(LOG_INFO, " > raudio:.... not loaded (optional)");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// NOTE: Keep internal pointer to input title string (no copy)
|
// Initialize window data
|
||||||
|
CORE.Window.screen.width = width;
|
||||||
|
CORE.Window.screen.height = height;
|
||||||
|
CORE.Window.eventWaiting = false;
|
||||||
|
CORE.Window.screenScale = MatrixIdentity(); // No draw scaling required by default
|
||||||
if ((title != NULL) && (title[0] != 0)) CORE.Window.title = title;
|
if ((title != NULL) && (title[0] != 0)) CORE.Window.title = title;
|
||||||
|
|
||||||
// Initialize global input state
|
// Initialize global input state
|
||||||
memset(&CORE.Input, 0, sizeof(CORE.Input));
|
memset(&CORE.Input, 0, sizeof(CORE.Input)); // Reset CORE.Input structure to 0
|
||||||
CORE.Input.Keyboard.exitKey = KEY_ESCAPE;
|
CORE.Input.Keyboard.exitKey = KEY_ESCAPE;
|
||||||
CORE.Input.Mouse.scale = (Vector2){1.0f, 1.0f};
|
CORE.Input.Mouse.scale = (Vector2){ 1.0f, 1.0f };
|
||||||
CORE.Input.Mouse.cursor = MOUSE_CURSOR_ARROW;
|
CORE.Input.Mouse.cursor = MOUSE_CURSOR_ARROW;
|
||||||
CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN
|
CORE.Input.Gamepad.lastButtonPressed = GAMEPAD_BUTTON_UNKNOWN;
|
||||||
CORE.Window.eventWaiting = false;
|
|
||||||
|
|
||||||
for (int i = 0; i < MAX_GAMEPADS; i++)
|
// Initialize platform
|
||||||
{
|
//--------------------------------------------------------------
|
||||||
CORE.Input.Gamepad.ready[i] = false;
|
InitPlatform();
|
||||||
}
|
//--------------------------------------------------------------
|
||||||
|
|
||||||
// Initialize graphics device (display device and OpenGL context)
|
// Initialize rlgl default data (buffers and shaders)
|
||||||
// NOTE: returns true if window and graphic device has been initialized successfully
|
// NOTE: CORE.Window.currentFbo.width and CORE.Window.currentFbo.height not used, just stored as globals in rlgl
|
||||||
CORE.Window.ready = InitGraphicsDevice(width, height);
|
rlglInit(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
|
||||||
|
|
||||||
// If graphic device is no properly initialized, we end program
|
// Setup default viewport
|
||||||
if (!CORE.Window.ready) { TRACELOG(LOG_FATAL, "PLATFORM: Failed to initialize graphic device"); return; }
|
SetupViewport(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
|
||||||
else SetWindowPosition(GetMonitorWidth(GetCurrentMonitor()) / 2 - CORE.Window.screen.width / 2, GetMonitorHeight(GetCurrentMonitor()) / 2 - CORE.Window.screen.height / 2);
|
|
||||||
|
|
||||||
// Initialize hi-res timer
|
|
||||||
InitTimer();
|
|
||||||
|
|
||||||
// Initialize random seed
|
|
||||||
SetRandomSeed((unsigned int)time(NULL));
|
|
||||||
|
|
||||||
// Initialize base path for storage
|
|
||||||
CORE.Storage.basePath = GetWorkingDirectory();
|
|
||||||
|
|
||||||
#if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT)
|
#if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT)
|
||||||
// Load default font
|
// Load default font
|
||||||
|
|
@ -298,14 +292,8 @@ void InitWindow(int width, int height, const char *title)
|
||||||
CORE.Time.frameCounter = 0;
|
CORE.Time.frameCounter = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Platform specific init window
|
// Initialize random seed
|
||||||
//--------------------------------------------------------------
|
SetRandomSeed((unsigned int)time(NULL));
|
||||||
// Initialize raw input system
|
|
||||||
InitDrmInput(); // DRM platform input initialization
|
|
||||||
InitEvdevInput(); // Evdev inputs initialization
|
|
||||||
//InitGamepad(); // Gamepad init
|
|
||||||
InitKeyboard(); // Keyboard init (stdin)
|
|
||||||
//--------------------------------------------------------------
|
|
||||||
|
|
||||||
TRACELOG(LOG_INFO, "PLATFORM: DRM: Application initialized successfully");
|
TRACELOG(LOG_INFO, "PLATFORM: DRM: Application initialized successfully");
|
||||||
}
|
}
|
||||||
|
|
@ -332,93 +320,9 @@ void CloseWindow(void)
|
||||||
timeEndPeriod(1); // Restore time period
|
timeEndPeriod(1); // Restore time period
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Platform specific close window
|
// De-initialize platform
|
||||||
//--------------------------------------------------------------
|
//--------------------------------------------------------------
|
||||||
if (platform.prevFB)
|
ClosePlatform();
|
||||||
{
|
|
||||||
drmModeRmFB(platform.fd, platform.prevFB);
|
|
||||||
platform.prevFB = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (platform.prevBO)
|
|
||||||
{
|
|
||||||
gbm_surface_release_buffer(platform.gbmSurface, platform.prevBO);
|
|
||||||
platform.prevBO = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (platform.gbmSurface)
|
|
||||||
{
|
|
||||||
gbm_surface_destroy(platform.gbmSurface);
|
|
||||||
platform.gbmSurface = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (platform.gbmDevice)
|
|
||||||
{
|
|
||||||
gbm_device_destroy(platform.gbmDevice);
|
|
||||||
platform.gbmDevice = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (platform.crtc)
|
|
||||||
{
|
|
||||||
if (platform.connector)
|
|
||||||
{
|
|
||||||
drmModeSetCrtc(platform.fd, platform.crtc->crtc_id, platform.crtc->buffer_id,
|
|
||||||
platform.crtc->x, platform.crtc->y, &platform.connector->connector_id, 1, &platform.crtc->mode);
|
|
||||||
drmModeFreeConnector(platform.connector);
|
|
||||||
platform.connector = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
drmModeFreeCrtc(platform.crtc);
|
|
||||||
platform.crtc = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (platform.fd != -1)
|
|
||||||
{
|
|
||||||
close(platform.fd);
|
|
||||||
platform.fd = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close surface, context and display
|
|
||||||
if (platform.device != EGL_NO_DISPLAY)
|
|
||||||
{
|
|
||||||
if (platform.surface != EGL_NO_SURFACE)
|
|
||||||
{
|
|
||||||
eglDestroySurface(platform.device, platform.surface);
|
|
||||||
platform.surface = EGL_NO_SURFACE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (platform.context != EGL_NO_CONTEXT)
|
|
||||||
{
|
|
||||||
eglDestroyContext(platform.device, platform.context);
|
|
||||||
platform.context = EGL_NO_CONTEXT;
|
|
||||||
}
|
|
||||||
|
|
||||||
eglTerminate(platform.device);
|
|
||||||
platform.device = EGL_NO_DISPLAY;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for mouse and gamepad threads to finish before closing
|
|
||||||
// NOTE: Those threads should already have finished at this point
|
|
||||||
// because they are controlled by CORE.Window.shouldClose variable
|
|
||||||
|
|
||||||
CORE.Window.shouldClose = true; // Added to force threads to exit when the close window is called
|
|
||||||
|
|
||||||
// Close the evdev keyboard
|
|
||||||
if (platform.keyboardFd != -1)
|
|
||||||
{
|
|
||||||
close(platform.keyboardFd);
|
|
||||||
platform.keyboardFd = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < sizeof(platform.eventWorker)/sizeof(InputEventWorker); ++i)
|
|
||||||
{
|
|
||||||
if (platform.eventWorker[i].threadId)
|
|
||||||
{
|
|
||||||
pthread_join(platform.eventWorker[i].threadId, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (platform.gamepadThreadId) pthread_join(platform.gamepadThreadId, NULL);
|
|
||||||
//--------------------------------------------------------------
|
//--------------------------------------------------------------
|
||||||
|
|
||||||
#if defined(SUPPORT_EVENTS_AUTOMATION)
|
#if defined(SUPPORT_EVENTS_AUTOMATION)
|
||||||
|
|
@ -437,42 +341,18 @@ bool WindowShouldClose(void)
|
||||||
else return true;
|
else return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if window is currently hidden
|
|
||||||
bool IsWindowHidden(void)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if window has been minimized
|
|
||||||
bool IsWindowMinimized(void)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if window has been maximized
|
|
||||||
bool IsWindowMaximized(void)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if window has the focus
|
|
||||||
bool IsWindowFocused(void)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if window has been resizedLastFrame
|
|
||||||
bool IsWindowResized(void)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Toggle fullscreen mode
|
// Toggle fullscreen mode
|
||||||
void ToggleFullscreen(void)
|
void ToggleFullscreen(void)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "ToggleFullscreen() not available on target platform");
|
TRACELOG(LOG_WARNING, "ToggleFullscreen() not available on target platform");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Toggle borderless windowed mode
|
||||||
|
void ToggleBorderlessWindowed(void)
|
||||||
|
{
|
||||||
|
TRACELOG(LOG_WARNING, "ToggleBorderlessWindowed() not available on target platform");
|
||||||
|
}
|
||||||
|
|
||||||
// Set window state: maximized, if resizable
|
// Set window state: maximized, if resizable
|
||||||
void MaximizeWindow(void)
|
void MaximizeWindow(void)
|
||||||
{
|
{
|
||||||
|
|
@ -491,12 +371,6 @@ void RestoreWindow(void)
|
||||||
TRACELOG(LOG_WARNING, "RestoreWindow() not available on target platform");
|
TRACELOG(LOG_WARNING, "RestoreWindow() not available on target platform");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Toggle borderless windowed mode
|
|
||||||
void ToggleBorderlessWindowed(void)
|
|
||||||
{
|
|
||||||
TRACELOG(LOG_WARNING, "ToggleBorderlessWindowed() not available on target platform");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set window configuration state using flags
|
// Set window configuration state using flags
|
||||||
void SetWindowState(unsigned int flags)
|
void SetWindowState(unsigned int flags)
|
||||||
{
|
{
|
||||||
|
|
@ -542,15 +416,15 @@ void SetWindowMonitor(int monitor)
|
||||||
// Set window minimum dimensions (FLAG_WINDOW_RESIZABLE)
|
// Set window minimum dimensions (FLAG_WINDOW_RESIZABLE)
|
||||||
void SetWindowMinSize(int width, int height)
|
void SetWindowMinSize(int width, int height)
|
||||||
{
|
{
|
||||||
CORE.Window.windowMin.width = width;
|
CORE.Window.screenMin.width = width;
|
||||||
CORE.Window.windowMin.height = height;
|
CORE.Window.screenMin.height = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set window maximum dimensions (FLAG_WINDOW_RESIZABLE)
|
// Set window maximum dimensions (FLAG_WINDOW_RESIZABLE)
|
||||||
void SetWindowMaxSize(int width, int height)
|
void SetWindowMaxSize(int width, int height)
|
||||||
{
|
{
|
||||||
CORE.Window.windowMax.width = width;
|
CORE.Window.screenMax.width = width;
|
||||||
CORE.Window.windowMax.height = height;
|
CORE.Window.screenMax.height = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set window dimensions
|
// Set window dimensions
|
||||||
|
|
@ -764,18 +638,6 @@ void OpenURL(const char *url)
|
||||||
// Module Functions Definition: Inputs
|
// Module Functions Definition: Inputs
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Get gamepad internal name id
|
|
||||||
const char *GetGamepadName(int gamepad)
|
|
||||||
{
|
|
||||||
return CORE.Input.Gamepad.name[gamepad];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get gamepad axis count
|
|
||||||
int GetGamepadAxisCount(int gamepad)
|
|
||||||
{
|
|
||||||
return CORE.Input.Gamepad.axisCount[gamepad];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set internal gamepad mappings
|
// Set internal gamepad mappings
|
||||||
int SetGamepadMappings(const char *mappings)
|
int SetGamepadMappings(const char *mappings)
|
||||||
{
|
{
|
||||||
|
|
@ -783,29 +645,6 @@ int SetGamepadMappings(const char *mappings)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get mouse position X
|
|
||||||
int GetMouseX(void)
|
|
||||||
{
|
|
||||||
return (int)((CORE.Input.Mouse.currentPosition.x + CORE.Input.Mouse.offset.x)*CORE.Input.Mouse.scale.x);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get mouse position Y
|
|
||||||
int GetMouseY(void)
|
|
||||||
{
|
|
||||||
return (int)((CORE.Input.Mouse.currentPosition.y + CORE.Input.Mouse.offset.y)*CORE.Input.Mouse.scale.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get mouse position XY
|
|
||||||
Vector2 GetMousePosition(void)
|
|
||||||
{
|
|
||||||
Vector2 position = { 0 };
|
|
||||||
|
|
||||||
position.x = (CORE.Input.Mouse.currentPosition.x + CORE.Input.Mouse.offset.x)*CORE.Input.Mouse.scale.x;
|
|
||||||
position.y = (CORE.Input.Mouse.currentPosition.y + CORE.Input.Mouse.offset.y)*CORE.Input.Mouse.scale.y;
|
|
||||||
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set mouse position XY
|
// Set mouse position XY
|
||||||
void SetMousePosition(int x, int y)
|
void SetMousePosition(int x, int y)
|
||||||
{
|
{
|
||||||
|
|
@ -813,46 +652,12 @@ void SetMousePosition(int x, int y)
|
||||||
CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
|
CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get mouse wheel movement Y
|
|
||||||
float GetMouseWheelMove(void)
|
|
||||||
{
|
|
||||||
float result = 0.0f;
|
|
||||||
|
|
||||||
if (fabsf(CORE.Input.Mouse.currentWheelMove.x) > fabsf(CORE.Input.Mouse.currentWheelMove.y)) result = (float)CORE.Input.Mouse.currentWheelMove.x;
|
|
||||||
else result = (float)CORE.Input.Mouse.currentWheelMove.y;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set mouse cursor
|
// Set mouse cursor
|
||||||
void SetMouseCursor(int cursor)
|
void SetMouseCursor(int cursor)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "SetMouseCursor() not implemented on target platform");
|
TRACELOG(LOG_WARNING, "SetMouseCursor() not implemented on target platform");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get touch position X for touch point 0 (relative to screen size)
|
|
||||||
int GetTouchX(void)
|
|
||||||
{
|
|
||||||
return GetMouseX();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get touch position Y for touch point 0 (relative to screen size)
|
|
||||||
int GetTouchY(void)
|
|
||||||
{
|
|
||||||
return GetMouseY();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get touch position XY for a touch point index (relative to screen size)
|
|
||||||
Vector2 GetTouchPosition(int index)
|
|
||||||
{
|
|
||||||
Vector2 position = { -1.0f, -1.0f };
|
|
||||||
|
|
||||||
if (index < MAX_TOUCH_POINTS) position = CORE.Input.Touch.position[index];
|
|
||||||
else TRACELOG(LOG_WARNING, "INPUT: Required touch point out of range (Max touch points: %i)", MAX_TOUCH_POINTS);
|
|
||||||
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Register all input events
|
// Register all input events
|
||||||
void PollInputEvents(void)
|
void PollInputEvents(void)
|
||||||
{
|
{
|
||||||
|
|
@ -924,28 +729,9 @@ void PollInputEvents(void)
|
||||||
// Module Internal Functions Definition
|
// Module Internal Functions Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Initialize display device and framebuffer
|
// Initialize platform: graphics, inputs and more
|
||||||
// NOTE: width and height represent the screen (framebuffer) desired size, not actual display size
|
static int InitPlatform(void)
|
||||||
// If width or height are 0, default display size will be used for framebuffer size
|
|
||||||
// NOTE: returns false in case graphic device could not be created
|
|
||||||
static bool InitGraphicsDevice(int width, int height)
|
|
||||||
{
|
{
|
||||||
CORE.Window.screen.width = width; // User desired width
|
|
||||||
CORE.Window.screen.height = height; // User desired height
|
|
||||||
CORE.Window.screenScale = MatrixIdentity(); // No draw scaling required by default
|
|
||||||
|
|
||||||
// Set the window minimum and maximum default values to 0
|
|
||||||
CORE.Window.windowMin.width = 0;
|
|
||||||
CORE.Window.windowMin.height = 0;
|
|
||||||
CORE.Window.windowMax.width = 0;
|
|
||||||
CORE.Window.windowMax.height = 0;
|
|
||||||
|
|
||||||
// NOTE: Framebuffer (render area - CORE.Window.render.width, CORE.Window.render.height) could include black bars...
|
|
||||||
// ...in top-down or left-right to match display aspect ratio (no weird scaling)
|
|
||||||
|
|
||||||
CORE.Window.fullscreen = true;
|
|
||||||
CORE.Window.flags |= FLAG_FULLSCREEN_MODE;
|
|
||||||
|
|
||||||
platform.fd = -1;
|
platform.fd = -1;
|
||||||
platform.connector = NULL;
|
platform.connector = NULL;
|
||||||
platform.modeIndex = -1;
|
platform.modeIndex = -1;
|
||||||
|
|
@ -955,6 +741,9 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
platform.prevBO = NULL;
|
platform.prevBO = NULL;
|
||||||
platform.prevFB = 0;
|
platform.prevFB = 0;
|
||||||
|
|
||||||
|
CORE.Window.fullscreen = true;
|
||||||
|
CORE.Window.flags |= FLAG_FULLSCREEN_MODE;
|
||||||
|
|
||||||
#if defined(DEFAULT_GRAPHIC_DEVICE_DRM)
|
#if defined(DEFAULT_GRAPHIC_DEVICE_DRM)
|
||||||
platform.fd = open(DEFAULT_GRAPHIC_DEVICE_DRM, O_RDWR);
|
platform.fd = open(DEFAULT_GRAPHIC_DEVICE_DRM, O_RDWR);
|
||||||
#else
|
#else
|
||||||
|
|
@ -977,14 +766,14 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
if (platform.fd == -1)
|
if (platform.fd == -1)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "DISPLAY: Failed to open graphic card");
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to open graphic card");
|
||||||
return false;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
drmModeRes *res = drmModeGetResources(platform.fd);
|
drmModeRes *res = drmModeGetResources(platform.fd);
|
||||||
if (!res)
|
if (!res)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "DISPLAY: Failed get DRM resources");
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed get DRM resources");
|
||||||
return false;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACELOG(LOG_TRACE, "DISPLAY: Connectors found: %i", res->count_connectors);
|
TRACELOG(LOG_TRACE, "DISPLAY: Connectors found: %i", res->count_connectors);
|
||||||
|
|
@ -1013,7 +802,7 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "DISPLAY: No suitable DRM connector found");
|
TRACELOG(LOG_WARNING, "DISPLAY: No suitable DRM connector found");
|
||||||
drmModeFreeResources(res);
|
drmModeFreeResources(res);
|
||||||
return false;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
drmModeEncoder *enc = drmModeGetEncoder(platform.fd, platform.connector->encoder_id);
|
drmModeEncoder *enc = drmModeGetEncoder(platform.fd, platform.connector->encoder_id);
|
||||||
|
|
@ -1021,7 +810,7 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "DISPLAY: Failed to get DRM mode encoder");
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to get DRM mode encoder");
|
||||||
drmModeFreeResources(res);
|
drmModeFreeResources(res);
|
||||||
return false;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
platform.crtc = drmModeGetCrtc(platform.fd, enc->crtc_id);
|
platform.crtc = drmModeGetCrtc(platform.fd, enc->crtc_id);
|
||||||
|
|
@ -1030,7 +819,7 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
TRACELOG(LOG_WARNING, "DISPLAY: Failed to get DRM mode crtc");
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to get DRM mode crtc");
|
||||||
drmModeFreeEncoder(enc);
|
drmModeFreeEncoder(enc);
|
||||||
drmModeFreeResources(res);
|
drmModeFreeResources(res);
|
||||||
return false;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If InitWindow should use the current mode find it in the connector's mode list
|
// If InitWindow should use the current mode find it in the connector's mode list
|
||||||
|
|
@ -1045,7 +834,7 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
TRACELOG(LOG_WARNING, "DISPLAY: No matching DRM connector mode found");
|
TRACELOG(LOG_WARNING, "DISPLAY: No matching DRM connector mode found");
|
||||||
drmModeFreeEncoder(enc);
|
drmModeFreeEncoder(enc);
|
||||||
drmModeFreeResources(res);
|
drmModeFreeResources(res);
|
||||||
return false;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
CORE.Window.screen.width = CORE.Window.display.width;
|
CORE.Window.screen.width = CORE.Window.display.width;
|
||||||
|
|
@ -1073,7 +862,7 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
TRACELOG(LOG_WARNING, "DISPLAY: Failed to find a suitable DRM connector mode");
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to find a suitable DRM connector mode");
|
||||||
drmModeFreeEncoder(enc);
|
drmModeFreeEncoder(enc);
|
||||||
drmModeFreeResources(res);
|
drmModeFreeResources(res);
|
||||||
return false;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
CORE.Window.display.width = platform.connector->modes[platform.modeIndex].hdisplay;
|
CORE.Window.display.width = platform.connector->modes[platform.modeIndex].hdisplay;
|
||||||
|
|
@ -1098,7 +887,7 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
if (!platform.gbmDevice)
|
if (!platform.gbmDevice)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "DISPLAY: Failed to create GBM device");
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to create GBM device");
|
||||||
return false;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
platform.gbmSurface = gbm_surface_create(platform.gbmDevice, platform.connector->modes[platform.modeIndex].hdisplay,
|
platform.gbmSurface = gbm_surface_create(platform.gbmDevice, platform.connector->modes[platform.modeIndex].hdisplay,
|
||||||
|
|
@ -1106,7 +895,7 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
if (!platform.gbmSurface)
|
if (!platform.gbmSurface)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "DISPLAY: Failed to create GBM surface");
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to create GBM surface");
|
||||||
return false;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
EGLint samples = 0;
|
EGLint samples = 0;
|
||||||
|
|
@ -1146,7 +935,7 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
if (platform.device == EGL_NO_DISPLAY)
|
if (platform.device == EGL_NO_DISPLAY)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "DISPLAY: Failed to initialize EGL device");
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to initialize EGL device");
|
||||||
return false;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the EGL device connection
|
// Initialize the EGL device connection
|
||||||
|
|
@ -1154,13 +943,13 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
{
|
{
|
||||||
// If all of the calls to eglInitialize returned EGL_FALSE then an error has occurred.
|
// If all of the calls to eglInitialize returned EGL_FALSE then an error has occurred.
|
||||||
TRACELOG(LOG_WARNING, "DISPLAY: Failed to initialize EGL device");
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to initialize EGL device");
|
||||||
return false;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!eglChooseConfig(platform.device, NULL, NULL, 0, &numConfigs))
|
if (!eglChooseConfig(platform.device, NULL, NULL, 0, &numConfigs))
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "DISPLAY: Failed to get EGL config count: 0x%x", eglGetError());
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to get EGL config count: 0x%x", eglGetError());
|
||||||
return false;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACELOG(LOG_TRACE, "DISPLAY: EGL configs available: %d", numConfigs);
|
TRACELOG(LOG_TRACE, "DISPLAY: EGL configs available: %d", numConfigs);
|
||||||
|
|
@ -1169,7 +958,7 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
if (!configs)
|
if (!configs)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "DISPLAY: Failed to get memory for EGL configs");
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to get memory for EGL configs");
|
||||||
return false;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
EGLint matchingNumConfigs = 0;
|
EGLint matchingNumConfigs = 0;
|
||||||
|
|
@ -1177,7 +966,7 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "DISPLAY: Failed to choose EGL config: 0x%x", eglGetError());
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to choose EGL config: 0x%x", eglGetError());
|
||||||
free(configs);
|
free(configs);
|
||||||
return false;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACELOG(LOG_TRACE, "DISPLAY: EGL matching configs available: %d", matchingNumConfigs);
|
TRACELOG(LOG_TRACE, "DISPLAY: EGL matching configs available: %d", matchingNumConfigs);
|
||||||
|
|
@ -1207,7 +996,7 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
if (!found)
|
if (!found)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "DISPLAY: Failed to find a suitable EGL config");
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to find a suitable EGL config");
|
||||||
return false;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set rendering API
|
// Set rendering API
|
||||||
|
|
@ -1218,7 +1007,7 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
if (platform.context == EGL_NO_CONTEXT)
|
if (platform.context == EGL_NO_CONTEXT)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "DISPLAY: Failed to create EGL context");
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to create EGL context");
|
||||||
return false;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create an EGL window surface
|
// Create an EGL window surface
|
||||||
|
|
@ -1227,7 +1016,7 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
if (EGL_NO_SURFACE == platform.surface)
|
if (EGL_NO_SURFACE == platform.surface)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "DISPLAY: Failed to create EGL window surface: 0x%04x", eglGetError());
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to create EGL window surface: 0x%04x", eglGetError());
|
||||||
return false;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// At this point we need to manage render size vs screen size
|
// At this point we need to manage render size vs screen size
|
||||||
|
|
@ -1243,7 +1032,7 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
if (eglMakeCurrent(platform.device, platform.surface, platform.surface, platform.context) == EGL_FALSE)
|
if (eglMakeCurrent(platform.device, platform.surface, platform.surface, platform.context) == EGL_FALSE)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "DISPLAY: Failed to attach EGL rendering context to EGL surface");
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to attach EGL rendering context to EGL surface");
|
||||||
return false;
|
return -1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -1263,19 +1052,125 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
// NOTE: GL procedures address loader is required to load extensions
|
// NOTE: GL procedures address loader is required to load extensions
|
||||||
rlLoadExtensions(eglGetProcAddress);
|
rlLoadExtensions(eglGetProcAddress);
|
||||||
|
|
||||||
// Initialize OpenGL context (states and resources)
|
|
||||||
// NOTE: CORE.Window.currentFbo.width and CORE.Window.currentFbo.height not used, just stored as globals in rlgl
|
|
||||||
rlglInit(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
|
|
||||||
|
|
||||||
// Setup default viewport
|
|
||||||
// NOTE: It updated CORE.Window.render.width and CORE.Window.render.height
|
|
||||||
SetupViewport(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
|
|
||||||
|
|
||||||
if ((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) > 0) MinimizeWindow();
|
if ((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) > 0) MinimizeWindow();
|
||||||
|
|
||||||
return true;
|
CORE.Window.ready = true; // TODO: Proper validation on windows/context creation
|
||||||
|
|
||||||
|
// If graphic device is no properly initialized, we end program
|
||||||
|
if (!CORE.Window.ready) { TRACELOG(LOG_FATAL, "PLATFORM: Failed to initialize graphic device"); return -1; }
|
||||||
|
else SetWindowPosition(GetMonitorWidth(GetCurrentMonitor()) / 2 - CORE.Window.screen.width / 2, GetMonitorHeight(GetCurrentMonitor()) / 2 - CORE.Window.screen.height / 2);
|
||||||
|
|
||||||
|
// Set some default window flags
|
||||||
|
CORE.Window.flags &= ~FLAG_WINDOW_HIDDEN; // false
|
||||||
|
CORE.Window.flags &= ~FLAG_WINDOW_MINIMIZED; // false
|
||||||
|
CORE.Window.flags |= FLAG_WINDOW_MAXIMIZED; // true
|
||||||
|
CORE.Window.flags &= ~FLAG_WINDOW_UNFOCUSED; // false
|
||||||
|
|
||||||
|
// Initialize hi-res timer
|
||||||
|
InitTimer();
|
||||||
|
|
||||||
|
// Initialize base path for storage
|
||||||
|
CORE.Storage.basePath = GetWorkingDirectory();
|
||||||
|
|
||||||
|
// Initialize raw input system
|
||||||
|
InitEvdevInput(); // Evdev inputs initialization
|
||||||
|
InitGamepad(); // Gamepad init
|
||||||
|
InitKeyboard(); // Keyboard init (stdin)
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Close platform
|
||||||
|
static void ClosePlatform(void)
|
||||||
|
{
|
||||||
|
if (platform.prevFB)
|
||||||
|
{
|
||||||
|
drmModeRmFB(platform.fd, platform.prevFB);
|
||||||
|
platform.prevFB = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (platform.prevBO)
|
||||||
|
{
|
||||||
|
gbm_surface_release_buffer(platform.gbmSurface, platform.prevBO);
|
||||||
|
platform.prevBO = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (platform.gbmSurface)
|
||||||
|
{
|
||||||
|
gbm_surface_destroy(platform.gbmSurface);
|
||||||
|
platform.gbmSurface = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (platform.gbmDevice)
|
||||||
|
{
|
||||||
|
gbm_device_destroy(platform.gbmDevice);
|
||||||
|
platform.gbmDevice = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (platform.crtc)
|
||||||
|
{
|
||||||
|
if (platform.connector)
|
||||||
|
{
|
||||||
|
drmModeSetCrtc(platform.fd, platform.crtc->crtc_id, platform.crtc->buffer_id,
|
||||||
|
platform.crtc->x, platform.crtc->y, &platform.connector->connector_id, 1, &platform.crtc->mode);
|
||||||
|
drmModeFreeConnector(platform.connector);
|
||||||
|
platform.connector = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
drmModeFreeCrtc(platform.crtc);
|
||||||
|
platform.crtc = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (platform.fd != -1)
|
||||||
|
{
|
||||||
|
close(platform.fd);
|
||||||
|
platform.fd = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close surface, context and display
|
||||||
|
if (platform.device != EGL_NO_DISPLAY)
|
||||||
|
{
|
||||||
|
if (platform.surface != EGL_NO_SURFACE)
|
||||||
|
{
|
||||||
|
eglDestroySurface(platform.device, platform.surface);
|
||||||
|
platform.surface = EGL_NO_SURFACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (platform.context != EGL_NO_CONTEXT)
|
||||||
|
{
|
||||||
|
eglDestroyContext(platform.device, platform.context);
|
||||||
|
platform.context = EGL_NO_CONTEXT;
|
||||||
|
}
|
||||||
|
|
||||||
|
eglTerminate(platform.device);
|
||||||
|
platform.device = EGL_NO_DISPLAY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for mouse and gamepad threads to finish before closing
|
||||||
|
// NOTE: Those threads should already have finished at this point
|
||||||
|
// because they are controlled by CORE.Window.shouldClose variable
|
||||||
|
|
||||||
|
CORE.Window.shouldClose = true; // Added to force threads to exit when the close window is called
|
||||||
|
|
||||||
|
// Close the evdev keyboard
|
||||||
|
if (platform.keyboardFd != -1)
|
||||||
|
{
|
||||||
|
close(platform.keyboardFd);
|
||||||
|
platform.keyboardFd = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < sizeof(platform.eventWorker)/sizeof(InputEventWorker); ++i)
|
||||||
|
{
|
||||||
|
if (platform.eventWorker[i].threadId)
|
||||||
|
{
|
||||||
|
pthread_join(platform.eventWorker[i].threadId, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (platform.gamepadThreadId) pthread_join(platform.gamepadThreadId, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Initialize Keyboard system (using standard input)
|
// Initialize Keyboard system (using standard input)
|
||||||
static void InitKeyboard(void)
|
static void InitKeyboard(void)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/**********************************************************************************************
|
/**********************************************************************************************
|
||||||
*
|
*
|
||||||
* rcore_<platform> - Functions to manage window, graphics device and inputs
|
* rcore_<platform> template - Functions to manage window, graphics device and inputs
|
||||||
*
|
*
|
||||||
* PLATFORM: <PLATFORM>
|
* PLATFORM: <PLATFORM>
|
||||||
* - TODO: Define the target platform for the core
|
* - TODO: Define the target platform for the core
|
||||||
|
|
@ -73,7 +73,8 @@ static PlatformData platform = { 0 }; // Platform specific data
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module Internal Functions Declaration
|
// Module Internal Functions Declaration
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
static bool InitGraphicsDevice(int width, int height); // Initialize graphics device
|
static int InitPlatform(void); // Initialize platform (graphics, inputs and more)
|
||||||
|
static bool InitGraphicsDevice(void); // Initialize graphics device
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module Functions Declaration
|
// Module Functions Declaration
|
||||||
|
|
@ -128,8 +129,11 @@ void InitWindow(int width, int height, const char *title)
|
||||||
CORE.Input.Mouse.scale = (Vector2){ 1.0f, 1.0f };
|
CORE.Input.Mouse.scale = (Vector2){ 1.0f, 1.0f };
|
||||||
CORE.Input.Mouse.cursor = MOUSE_CURSOR_ARROW;
|
CORE.Input.Mouse.cursor = MOUSE_CURSOR_ARROW;
|
||||||
CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN
|
CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN
|
||||||
|
|
||||||
CORE.Window.eventWaiting = false;
|
CORE.Window.eventWaiting = false;
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: Platform specific init window
|
||||||
|
//--------------------------------------------------------------
|
||||||
CORE.Window.screen.width = width;
|
CORE.Window.screen.width = width;
|
||||||
CORE.Window.screen.height = height;
|
CORE.Window.screen.height = height;
|
||||||
CORE.Window.currentFbo.width = width;
|
CORE.Window.currentFbo.width = width;
|
||||||
|
|
@ -139,17 +143,15 @@ void InitWindow(int width, int height, const char *title)
|
||||||
// NOTE: returns true if window and graphic device has been initialized successfully
|
// NOTE: returns true if window and graphic device has been initialized successfully
|
||||||
CORE.Window.ready = InitGraphicsDevice(width, height);
|
CORE.Window.ready = InitGraphicsDevice(width, height);
|
||||||
|
|
||||||
// If graphic device is no properly initialized, we end program
|
|
||||||
if (!CORE.Window.ready) { TRACELOG(LOG_FATAL, "PLATFORM: Failed to initialize graphic device"); return; }
|
|
||||||
|
|
||||||
// Initialize hi-res timer
|
|
||||||
InitTimer();
|
|
||||||
|
|
||||||
// Initialize random seed
|
// Initialize OpenGL context (states and resources)
|
||||||
SetRandomSeed((unsigned int)time(NULL));
|
// NOTE: CORE.Window.currentFbo.width and CORE.Window.currentFbo.height not used, just stored as globals in rlgl
|
||||||
|
rlglInit(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
|
||||||
|
|
||||||
// Initialize base path for storage
|
// Setup default viewport
|
||||||
CORE.Storage.basePath = GetWorkingDirectory();
|
// NOTE: It updated CORE.Window.render.width and CORE.Window.render.height
|
||||||
|
SetupViewport(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
|
||||||
|
|
||||||
#if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT)
|
#if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT)
|
||||||
// Load default font
|
// Load default font
|
||||||
|
|
@ -193,10 +195,8 @@ void InitWindow(int width, int height, const char *title)
|
||||||
CORE.Time.frameCounter = 0;
|
CORE.Time.frameCounter = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// TODO: Platform specific init window
|
// Initialize random seed
|
||||||
//--------------------------------------------------------------
|
SetRandomSeed((unsigned int)time(NULL));
|
||||||
// ...
|
|
||||||
//--------------------------------------------------------------
|
|
||||||
|
|
||||||
TRACELOG(LOG_INFO, "PLATFORM: CUSTOM: Application initialized successfully");
|
TRACELOG(LOG_INFO, "PLATFORM: CUSTOM: Application initialized successfully");
|
||||||
}
|
}
|
||||||
|
|
@ -239,42 +239,18 @@ bool WindowShouldClose(void)
|
||||||
else return true;
|
else return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if window is currently hidden
|
|
||||||
bool IsWindowHidden(void)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if window has been minimized
|
|
||||||
bool IsWindowMinimized(void)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if window has been maximized
|
|
||||||
bool IsWindowMaximized(void)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if window has the focus
|
|
||||||
bool IsWindowFocused(void)
|
|
||||||
{
|
|
||||||
return platform.appEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if window has been resizedLastFrame
|
|
||||||
bool IsWindowResized(void)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Toggle fullscreen mode
|
// Toggle fullscreen mode
|
||||||
void ToggleFullscreen(void)
|
void ToggleFullscreen(void)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "ToggleFullscreen() not available on target platform");
|
TRACELOG(LOG_WARNING, "ToggleFullscreen() not available on target platform");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Toggle borderless windowed mode
|
||||||
|
void ToggleBorderlessWindowed(void)
|
||||||
|
{
|
||||||
|
TRACELOG(LOG_WARNING, "ToggleBorderlessWindowed() not available on target platform");
|
||||||
|
}
|
||||||
|
|
||||||
// Set window state: maximized, if resizable
|
// Set window state: maximized, if resizable
|
||||||
void MaximizeWindow(void)
|
void MaximizeWindow(void)
|
||||||
{
|
{
|
||||||
|
|
@ -293,12 +269,6 @@ void RestoreWindow(void)
|
||||||
TRACELOG(LOG_WARNING, "RestoreWindow() not available on target platform");
|
TRACELOG(LOG_WARNING, "RestoreWindow() not available on target platform");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Toggle borderless windowed mode
|
|
||||||
void ToggleBorderlessWindowed(void)
|
|
||||||
{
|
|
||||||
TRACELOG(LOG_WARNING, "ToggleBorderlessWindowed() not available on target platform");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set window configuration state using flags
|
// Set window configuration state using flags
|
||||||
void SetWindowState(unsigned int flags)
|
void SetWindowState(unsigned int flags)
|
||||||
{
|
{
|
||||||
|
|
@ -344,15 +314,15 @@ void SetWindowMonitor(int monitor)
|
||||||
// Set window minimum dimensions (FLAG_WINDOW_RESIZABLE)
|
// Set window minimum dimensions (FLAG_WINDOW_RESIZABLE)
|
||||||
void SetWindowMinSize(int width, int height)
|
void SetWindowMinSize(int width, int height)
|
||||||
{
|
{
|
||||||
CORE.Window.windowMin.width = width;
|
CORE.Window.screenMin.width = width;
|
||||||
CORE.Window.windowMin.height = height;
|
CORE.Window.screenMin.height = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set window maximum dimensions (FLAG_WINDOW_RESIZABLE)
|
// Set window maximum dimensions (FLAG_WINDOW_RESIZABLE)
|
||||||
void SetWindowMaxSize(int width, int height)
|
void SetWindowMaxSize(int width, int height)
|
||||||
{
|
{
|
||||||
CORE.Window.windowMax.width = width;
|
CORE.Window.screenMax.width = width;
|
||||||
CORE.Window.windowMax.height = height;
|
CORE.Window.screenMax.height = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set window dimensions
|
// Set window dimensions
|
||||||
|
|
@ -563,18 +533,6 @@ void OpenURL(const char *url)
|
||||||
// Module Functions Definition: Inputs
|
// Module Functions Definition: Inputs
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Get gamepad internal name id
|
|
||||||
const char *GetGamepadName(int gamepad)
|
|
||||||
{
|
|
||||||
return CORE.Input.Gamepad.name[gamepad];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get gamepad axis count
|
|
||||||
int GetGamepadAxisCount(int gamepad)
|
|
||||||
{
|
|
||||||
return CORE.Input.Gamepad.axisCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set internal gamepad mappings
|
// Set internal gamepad mappings
|
||||||
int SetGamepadMappings(const char *mappings)
|
int SetGamepadMappings(const char *mappings)
|
||||||
{
|
{
|
||||||
|
|
@ -582,30 +540,6 @@ int SetGamepadMappings(const char *mappings)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get mouse position X
|
|
||||||
int GetMouseX(void)
|
|
||||||
{
|
|
||||||
return (int)((CORE.Input.Mouse.currentPosition.x + CORE.Input.Mouse.offset.x)*CORE.Input.Mouse.scale.x);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get mouse position Y
|
|
||||||
int GetMouseY(void)
|
|
||||||
{
|
|
||||||
return (int)((CORE.Input.Mouse.currentPosition.y + CORE.Input.Mouse.offset.y)*CORE.Input.Mouse.scale.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get mouse position XY
|
|
||||||
Vector2 GetMousePosition(void)
|
|
||||||
{
|
|
||||||
Vector2 position = { 0 };
|
|
||||||
|
|
||||||
// NOTE: On canvas scaling, mouse position is proportionally returned
|
|
||||||
position.x = (CORE.Input.Mouse.currentPosition.x + CORE.Input.Mouse.offset.x)*CORE.Input.Mouse.scale.x;
|
|
||||||
position.y = (CORE.Input.Mouse.currentPosition.y + CORE.Input.Mouse.offset.y)*CORE.Input.Mouse.scale.y;
|
|
||||||
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set mouse position XY
|
// Set mouse position XY
|
||||||
void SetMousePosition(int x, int y)
|
void SetMousePosition(int x, int y)
|
||||||
{
|
{
|
||||||
|
|
@ -613,43 +547,12 @@ void SetMousePosition(int x, int y)
|
||||||
CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
|
CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get mouse wheel movement Y
|
|
||||||
float GetMouseWheelMove(void)
|
|
||||||
{
|
|
||||||
TRACELOG(LOG_WARNING, "GetMouseWheelMove() not implemented on target platform");
|
|
||||||
return 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set mouse cursor
|
// Set mouse cursor
|
||||||
void SetMouseCursor(int cursor)
|
void SetMouseCursor(int cursor)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "SetMouseCursor() not implemented on target platform");
|
TRACELOG(LOG_WARNING, "SetMouseCursor() not implemented on target platform");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get touch position X for touch point 0 (relative to screen size)
|
|
||||||
int GetTouchX(void)
|
|
||||||
{
|
|
||||||
return (int)CORE.Input.Touch.position[0].x;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get touch position Y for touch point 0 (relative to screen size)
|
|
||||||
int GetTouchY(void)
|
|
||||||
{
|
|
||||||
return (int)CORE.Input.Touch.position[0].y;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get touch position XY for a touch point index (relative to screen size)
|
|
||||||
// TODO: Touch position should be scaled depending on display size and render size
|
|
||||||
Vector2 GetTouchPosition(int index)
|
|
||||||
{
|
|
||||||
Vector2 position = { -1.0f, -1.0f };
|
|
||||||
|
|
||||||
if (index < MAX_TOUCH_POINTS) position = CORE.Input.Touch.position[index];
|
|
||||||
else TRACELOG(LOG_WARNING, "INPUT: Required touch point out of range (Max touch points: %i)", MAX_TOUCH_POINTS);
|
|
||||||
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Register all input events
|
// Register all input events
|
||||||
void PollInputEvents(void)
|
void PollInputEvents(void)
|
||||||
{
|
{
|
||||||
|
|
@ -694,25 +597,9 @@ void PollInputEvents(void)
|
||||||
// Module Internal Functions Definition
|
// Module Internal Functions Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Initialize display device and framebuffer
|
// Initialize platform: graphics, inputs and more
|
||||||
// NOTE: width and height represent the screen (framebuffer) desired size, not actual display size
|
static int InitPlatform(void)
|
||||||
// If width or height are 0, default display size will be used for framebuffer size
|
|
||||||
// NOTE: returns false in case graphic device could not be created
|
|
||||||
static bool InitGraphicsDevice(int width, int height)
|
|
||||||
{
|
{
|
||||||
CORE.Window.screen.width = width; // User desired width
|
|
||||||
CORE.Window.screen.height = height; // User desired height
|
|
||||||
CORE.Window.screenScale = MatrixIdentity(); // No draw scaling required by default
|
|
||||||
|
|
||||||
// Set the screen minimum and maximum default values to 0
|
|
||||||
CORE.Window.screenMin.width = 0;
|
|
||||||
CORE.Window.screenMin.height = 0;
|
|
||||||
CORE.Window.screenMax.width = 0;
|
|
||||||
CORE.Window.screenMax.height = 0;
|
|
||||||
|
|
||||||
// NOTE: Framebuffer (render area - CORE.Window.render.width, CORE.Window.render.height) could include black bars...
|
|
||||||
// ...in top-down or left-right to match display aspect ratio (no weird scaling)
|
|
||||||
|
|
||||||
CORE.Window.fullscreen = true;
|
CORE.Window.fullscreen = true;
|
||||||
CORE.Window.flags |= FLAG_FULLSCREEN_MODE;
|
CORE.Window.flags |= FLAG_FULLSCREEN_MODE;
|
||||||
|
|
||||||
|
|
@ -774,7 +661,7 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
if (platform.context == EGL_NO_CONTEXT)
|
if (platform.context == EGL_NO_CONTEXT)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "DISPLAY: Failed to create EGL context");
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to create EGL context");
|
||||||
return false;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create an EGL window surface
|
// Create an EGL window surface
|
||||||
|
|
@ -803,7 +690,7 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
if (eglMakeCurrent(platform.device, platform.surface, platform.surface, platform.context) == EGL_FALSE)
|
if (eglMakeCurrent(platform.device, platform.surface, platform.surface, platform.context) == EGL_FALSE)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "DISPLAY: Failed to attach EGL rendering context to EGL surface");
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to attach EGL rendering context to EGL surface");
|
||||||
return false;
|
return -1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -823,19 +710,24 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
// NOTE: GL procedures address loader is required to load extensions
|
// NOTE: GL procedures address loader is required to load extensions
|
||||||
rlLoadExtensions(eglGetProcAddress);
|
rlLoadExtensions(eglGetProcAddress);
|
||||||
|
|
||||||
// Initialize OpenGL context (states and resources)
|
|
||||||
// NOTE: CORE.Window.currentFbo.width and CORE.Window.currentFbo.height not used, just stored as globals in rlgl
|
|
||||||
rlglInit(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
|
|
||||||
|
|
||||||
// Setup default viewport
|
|
||||||
// NOTE: It updated CORE.Window.render.width and CORE.Window.render.height
|
|
||||||
SetupViewport(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
|
|
||||||
|
|
||||||
CORE.Window.ready = true;
|
CORE.Window.ready = true;
|
||||||
|
|
||||||
if ((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) > 0) MinimizeWindow();
|
// If graphic device is no properly initialized, we end program
|
||||||
|
if (!CORE.Window.ready) { TRACELOG(LOG_FATAL, "PLATFORM: Failed to initialize graphic device"); return -1; }
|
||||||
|
|
||||||
return true;
|
// Initialize hi-res timer
|
||||||
|
InitTimer();
|
||||||
|
|
||||||
|
// Initialize base path for storage
|
||||||
|
CORE.Storage.basePath = GetWorkingDirectory();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close platform
|
||||||
|
static void ClosePlatform(void)
|
||||||
|
{
|
||||||
|
// TODO: De-initialize graphics, inputs and more
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
338
src/rcore_web.c
338
src/rcore_web.c
|
|
@ -87,17 +87,18 @@ static PlatformData platform = { 0 }; // Platform specific data
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module Internal Functions Declaration
|
// Module Internal Functions Declaration
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
static bool InitGraphicsDevice(int width, int height); // Initialize graphics device
|
static int InitPlatform(void); // Initialize platform (graphics, inputs and more)
|
||||||
|
static void ClosePlatform(void); // Close platform
|
||||||
|
|
||||||
// Error callback event
|
// Error callback event
|
||||||
static void ErrorCallback(int error, const char *description); // GLFW3 Error Callback, runs on GLFW3 error
|
static void ErrorCallback(int error, const char *description); // GLFW3 Error Callback, runs on GLFW3 error
|
||||||
|
|
||||||
// Window callbacks events
|
// Window callbacks events
|
||||||
static void WindowSizeCallback(GLFWwindow *window, int width, int height); // GLFW3 WindowSize Callback, runs when window is resized
|
static void WindowSizeCallback(GLFWwindow *window, int width, int height); // GLFW3 WindowSize Callback, runs when window is resized
|
||||||
static void WindowIconifyCallback(GLFWwindow *window, int iconified); // GLFW3 WindowIconify Callback, runs when window is minimized/restored
|
static void WindowIconifyCallback(GLFWwindow *window, int iconified); // GLFW3 WindowIconify Callback, runs when window is minimized/restored
|
||||||
static void WindowMaximizeCallback(GLFWwindow *window, int maximized); // GLFW3 Window Maximize Callback, runs when window is maximized
|
static void WindowMaximizeCallback(GLFWwindow *window, int maximized); // GLFW3 Window Maximize Callback, runs when window is maximized
|
||||||
static void WindowFocusCallback(GLFWwindow *window, int focused); // GLFW3 WindowFocus Callback, runs when window get/lose focus
|
static void WindowFocusCallback(GLFWwindow *window, int focused); // GLFW3 WindowFocus Callback, runs when window get/lose focus
|
||||||
static void WindowDropCallback(GLFWwindow *window, int count, const char **paths); // GLFW3 Window Drop Callback, runs when drop files into window
|
static void WindowDropCallback(GLFWwindow *window, int count, const char **paths); // GLFW3 Window Drop Callback, runs when drop files into window
|
||||||
|
|
||||||
// Input callbacks events
|
// Input callbacks events
|
||||||
static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods); // GLFW3 Keyboard Callback, runs on key pressed
|
static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods); // GLFW3 Keyboard Callback, runs on key pressed
|
||||||
|
|
@ -107,11 +108,12 @@ static void MouseCursorPosCallback(GLFWwindow *window, double x, double y);
|
||||||
static void MouseScrollCallback(GLFWwindow *window, double xoffset, double yoffset); // GLFW3 Srolling Callback, runs on mouse wheel
|
static void MouseScrollCallback(GLFWwindow *window, double xoffset, double yoffset); // GLFW3 Srolling Callback, runs on mouse wheel
|
||||||
static void CursorEnterCallback(GLFWwindow *window, int enter); // GLFW3 Cursor Enter Callback, cursor enters client area
|
static void CursorEnterCallback(GLFWwindow *window, int enter); // GLFW3 Cursor Enter Callback, cursor enters client area
|
||||||
|
|
||||||
// Emscripten callback events
|
// Emscripten window callback events
|
||||||
static EM_BOOL EmscriptenFullscreenChangeCallback(int eventType, const EmscriptenFullscreenChangeEvent *event, void *userData);
|
static EM_BOOL EmscriptenFullscreenChangeCallback(int eventType, const EmscriptenFullscreenChangeEvent *event, void *userData);
|
||||||
static EM_BOOL EmscriptenWindowResizedCallback(int eventType, const EmscriptenUiEvent *event, void *userData);
|
static EM_BOOL EmscriptenWindowResizedCallback(int eventType, const EmscriptenUiEvent *event, void *userData);
|
||||||
static EM_BOOL EmscriptenResizeCallback(int eventType, const EmscriptenUiEvent *event, void *userData);
|
static EM_BOOL EmscriptenResizeCallback(int eventType, const EmscriptenUiEvent *event, void *userData);
|
||||||
|
|
||||||
|
// Emscripten input callback events
|
||||||
static EM_BOOL EmscriptenMouseCallback(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData);
|
static EM_BOOL EmscriptenMouseCallback(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData);
|
||||||
static EM_BOOL EmscriptenTouchCallback(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData);
|
static EM_BOOL EmscriptenTouchCallback(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData);
|
||||||
static EM_BOOL EmscriptenGamepadCallback(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData);
|
static EM_BOOL EmscriptenGamepadCallback(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData);
|
||||||
|
|
@ -160,33 +162,32 @@ void InitWindow(int width, int height, const char *title)
|
||||||
TRACELOG(LOG_INFO, " > raudio:.... not loaded (optional)");
|
TRACELOG(LOG_INFO, " > raudio:.... not loaded (optional)");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// NOTE: Keep internal pointer to input title string (no copy)
|
// Initialize window data
|
||||||
|
CORE.Window.screen.width = width;
|
||||||
|
CORE.Window.screen.height = height;
|
||||||
|
CORE.Window.eventWaiting = false;
|
||||||
|
CORE.Window.screenScale = MatrixIdentity(); // No draw scaling required by default
|
||||||
if ((title != NULL) && (title[0] != 0)) CORE.Window.title = title;
|
if ((title != NULL) && (title[0] != 0)) CORE.Window.title = title;
|
||||||
|
|
||||||
// Initialize global input state
|
// Initialize global input state
|
||||||
memset(&CORE.Input, 0, sizeof(CORE.Input));
|
memset(&CORE.Input, 0, sizeof(CORE.Input)); // Reset CORE.Input structure to 0
|
||||||
CORE.Input.Keyboard.exitKey = KEY_ESCAPE;
|
CORE.Input.Keyboard.exitKey = KEY_ESCAPE;
|
||||||
CORE.Input.Mouse.scale = (Vector2){1.0f, 1.0f};
|
CORE.Input.Mouse.scale = (Vector2){ 1.0f, 1.0f };
|
||||||
CORE.Input.Mouse.cursor = MOUSE_CURSOR_ARROW;
|
CORE.Input.Mouse.cursor = MOUSE_CURSOR_ARROW;
|
||||||
CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN
|
CORE.Input.Gamepad.lastButtonPressed = GAMEPAD_BUTTON_UNKNOWN;
|
||||||
CORE.Window.eventWaiting = false;
|
|
||||||
|
|
||||||
// Initialize graphics device (display device and OpenGL context)
|
// Initialize platform
|
||||||
// NOTE: returns true if window and graphic device has been initialized successfully
|
//--------------------------------------------------------------
|
||||||
CORE.Window.ready = InitGraphicsDevice(width, height);
|
InitPlatform();
|
||||||
|
//--------------------------------------------------------------
|
||||||
|
|
||||||
// If graphic device is no properly initialized, we end program
|
// Initialize OpenGL context (states and resources)
|
||||||
if (!CORE.Window.ready) { TRACELOG(LOG_FATAL, "PLATFORM: Failed to initialize graphic device"); return; }
|
// NOTE: CORE.Window.currentFbo.width and CORE.Window.currentFbo.height not used, just stored as globals in rlgl
|
||||||
else SetWindowPosition(GetMonitorWidth(GetCurrentMonitor())/2 - CORE.Window.screen.width/2, GetMonitorHeight(GetCurrentMonitor())/2 - CORE.Window.screen.height/2);
|
rlglInit(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
|
||||||
|
|
||||||
// Initialize hi-res timer
|
// Setup default viewport
|
||||||
InitTimer();
|
// NOTE: It updated CORE.Window.render.width and CORE.Window.render.height
|
||||||
|
SetupViewport(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
|
||||||
// Initialize random seed
|
|
||||||
SetRandomSeed((unsigned int)time(NULL));
|
|
||||||
|
|
||||||
// Initialize base path for storage
|
|
||||||
CORE.Storage.basePath = GetWorkingDirectory();
|
|
||||||
|
|
||||||
#if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT)
|
#if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT)
|
||||||
// Load default font
|
// Load default font
|
||||||
|
|
@ -230,37 +231,8 @@ void InitWindow(int width, int height, const char *title)
|
||||||
CORE.Time.frameCounter = 0;
|
CORE.Time.frameCounter = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Platform specific init window
|
// Initialize random seed
|
||||||
//--------------------------------------------------------------
|
SetRandomSeed((unsigned int)time(NULL));
|
||||||
// Setup callback functions for the DOM events
|
|
||||||
emscripten_set_fullscreenchange_callback("#canvas", NULL, 1, EmscriptenFullscreenChangeCallback);
|
|
||||||
|
|
||||||
// WARNING: Below resize code was breaking fullscreen mode for sample games and examples, it needs review
|
|
||||||
// Check fullscreen change events(note this is done on the window since most browsers don't support this on #canvas)
|
|
||||||
// emscripten_set_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, 1, EmscriptenResizeCallback);
|
|
||||||
// Check Resize event (note this is done on the window since most browsers don't support this on #canvas)
|
|
||||||
emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, 1, EmscriptenResizeCallback);
|
|
||||||
|
|
||||||
// Trigger this once to get initial window sizing
|
|
||||||
EmscriptenResizeCallback(EMSCRIPTEN_EVENT_RESIZE, NULL, NULL);
|
|
||||||
|
|
||||||
// Support keyboard events -> Not used, GLFW.JS takes care of that
|
|
||||||
// emscripten_set_keypress_callback("#canvas", NULL, 1, EmscriptenKeyboardCallback);
|
|
||||||
// emscripten_set_keydown_callback("#canvas", NULL, 1, EmscriptenKeyboardCallback);
|
|
||||||
|
|
||||||
// Support mouse events
|
|
||||||
emscripten_set_click_callback("#canvas", NULL, 1, EmscriptenMouseCallback);
|
|
||||||
|
|
||||||
// Support touch events
|
|
||||||
emscripten_set_touchstart_callback("#canvas", NULL, 1, EmscriptenTouchCallback);
|
|
||||||
emscripten_set_touchend_callback("#canvas", NULL, 1, EmscriptenTouchCallback);
|
|
||||||
emscripten_set_touchmove_callback("#canvas", NULL, 1, EmscriptenTouchCallback);
|
|
||||||
emscripten_set_touchcancel_callback("#canvas", NULL, 1, EmscriptenTouchCallback);
|
|
||||||
|
|
||||||
// Support gamepad events (not provided by GLFW3 on emscripten)
|
|
||||||
emscripten_set_gamepadconnected_callback(NULL, 1, EmscriptenGamepadCallback);
|
|
||||||
emscripten_set_gamepaddisconnected_callback(NULL, 1, EmscriptenGamepadCallback);
|
|
||||||
//--------------------------------------------------------------
|
|
||||||
|
|
||||||
TRACELOG(LOG_INFO, "PLATFORM: WEB: Application initialized successfully");
|
TRACELOG(LOG_INFO, "PLATFORM: WEB: Application initialized successfully");
|
||||||
}
|
}
|
||||||
|
|
@ -283,10 +255,9 @@ void CloseWindow(void)
|
||||||
|
|
||||||
rlglClose(); // De-init rlgl
|
rlglClose(); // De-init rlgl
|
||||||
|
|
||||||
// Platform specific close window
|
// De-initialize platform
|
||||||
//--------------------------------------------------------------
|
//--------------------------------------------------------------
|
||||||
glfwDestroyWindow(platform.handle);
|
ClosePlatform();
|
||||||
glfwTerminate();
|
|
||||||
//--------------------------------------------------------------
|
//--------------------------------------------------------------
|
||||||
|
|
||||||
#if defined(SUPPORT_EVENTS_AUTOMATION)
|
#if defined(SUPPORT_EVENTS_AUTOMATION)
|
||||||
|
|
@ -309,36 +280,6 @@ bool WindowShouldClose(void)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if window is currently hidden
|
|
||||||
bool IsWindowHidden(void)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if window has been minimized
|
|
||||||
bool IsWindowMinimized(void)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if window has been maximized
|
|
||||||
bool IsWindowMaximized(void)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if window has the focus
|
|
||||||
bool IsWindowFocused(void)
|
|
||||||
{
|
|
||||||
return ((CORE.Window.flags & FLAG_WINDOW_UNFOCUSED) == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if window has been resizedLastFrame
|
|
||||||
bool IsWindowResized(void)
|
|
||||||
{
|
|
||||||
return CORE.Window.resizedLastFrame;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Toggle fullscreen mode
|
// Toggle fullscreen mode
|
||||||
void ToggleFullscreen(void)
|
void ToggleFullscreen(void)
|
||||||
{
|
{
|
||||||
|
|
@ -410,6 +351,12 @@ void ToggleFullscreen(void)
|
||||||
CORE.Window.fullscreen = !CORE.Window.fullscreen; // Toggle fullscreen flag
|
CORE.Window.fullscreen = !CORE.Window.fullscreen; // Toggle fullscreen flag
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Toggle borderless windowed mode
|
||||||
|
void ToggleBorderlessWindowed(void)
|
||||||
|
{
|
||||||
|
TRACELOG(LOG_WARNING, "ToggleBorderlessWindowed() not available on target platform");
|
||||||
|
}
|
||||||
|
|
||||||
// Set window state: maximized, if resizable
|
// Set window state: maximized, if resizable
|
||||||
void MaximizeWindow(void)
|
void MaximizeWindow(void)
|
||||||
{
|
{
|
||||||
|
|
@ -428,12 +375,6 @@ void RestoreWindow(void)
|
||||||
TRACELOG(LOG_WARNING, "RestoreWindow() not available on target platform");
|
TRACELOG(LOG_WARNING, "RestoreWindow() not available on target platform");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Toggle borderless windowed mode
|
|
||||||
void ToggleBorderlessWindowed(void)
|
|
||||||
{
|
|
||||||
TRACELOG(LOG_WARNING, "ToggleBorderlessWindowed() not available on target platform");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set window configuration state using flags
|
// Set window configuration state using flags
|
||||||
void SetWindowState(unsigned int flags)
|
void SetWindowState(unsigned int flags)
|
||||||
{
|
{
|
||||||
|
|
@ -697,18 +638,6 @@ void OpenURL(const char *url)
|
||||||
// Module Functions Definition: Inputs
|
// Module Functions Definition: Inputs
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Get gamepad internal name id
|
|
||||||
const char *GetGamepadName(int gamepad)
|
|
||||||
{
|
|
||||||
return CORE.Input.Gamepad.name[gamepad];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get gamepad axis count
|
|
||||||
int GetGamepadAxisCount(int gamepad)
|
|
||||||
{
|
|
||||||
return CORE.Input.Gamepad.axisCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set internal gamepad mappings
|
// Set internal gamepad mappings
|
||||||
int SetGamepadMappings(const char *mappings)
|
int SetGamepadMappings(const char *mappings)
|
||||||
{
|
{
|
||||||
|
|
@ -717,30 +646,6 @@ int SetGamepadMappings(const char *mappings)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get mouse position X
|
|
||||||
int GetMouseX(void)
|
|
||||||
{
|
|
||||||
return (int)((CORE.Input.Mouse.currentPosition.x + CORE.Input.Mouse.offset.x)*CORE.Input.Mouse.scale.x);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get mouse position Y
|
|
||||||
int GetMouseY(void)
|
|
||||||
{
|
|
||||||
return (int)((CORE.Input.Mouse.currentPosition.y + CORE.Input.Mouse.offset.y)*CORE.Input.Mouse.scale.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get mouse position XY
|
|
||||||
Vector2 GetMousePosition(void)
|
|
||||||
{
|
|
||||||
Vector2 position = { 0 };
|
|
||||||
|
|
||||||
// NOTE: On canvas scaling, mouse position is proportionally returned
|
|
||||||
position.x = (CORE.Input.Mouse.currentPosition.x + CORE.Input.Mouse.offset.x)*CORE.Input.Mouse.scale.x;
|
|
||||||
position.y = (CORE.Input.Mouse.currentPosition.y + CORE.Input.Mouse.offset.y)*CORE.Input.Mouse.scale.y;
|
|
||||||
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set mouse position XY
|
// Set mouse position XY
|
||||||
void SetMousePosition(int x, int y)
|
void SetMousePosition(int x, int y)
|
||||||
{
|
{
|
||||||
|
|
@ -751,45 +656,37 @@ void SetMousePosition(int x, int y)
|
||||||
glfwSetCursorPos(platform.handle, CORE.Input.Mouse.currentPosition.x, CORE.Input.Mouse.currentPosition.y);
|
glfwSetCursorPos(platform.handle, CORE.Input.Mouse.currentPosition.x, CORE.Input.Mouse.currentPosition.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get mouse wheel movement Y
|
|
||||||
float GetMouseWheelMove(void)
|
|
||||||
{
|
|
||||||
float result = 0.0f;
|
|
||||||
|
|
||||||
if (fabsf(CORE.Input.Mouse.currentWheelMove.x) > fabsf(CORE.Input.Mouse.currentWheelMove.y)) result = (float)CORE.Input.Mouse.currentWheelMove.x;
|
|
||||||
else result = (float)CORE.Input.Mouse.currentWheelMove.y;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set mouse cursor
|
// Set mouse cursor
|
||||||
void SetMouseCursor(int cursor)
|
void SetMouseCursor(int cursor)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_INFO, "SetMouseCursor not implemented in rcore_web.c");
|
const char *cursorName;
|
||||||
}
|
switch (cursor)
|
||||||
|
{
|
||||||
|
case MOUSE_CURSOR_IBEAM: cursorName = "text"; break;
|
||||||
|
case MOUSE_CURSOR_CROSSHAIR: cursorName = "crosshair"; break;
|
||||||
|
case MOUSE_CURSOR_POINTING_HAND: cursorName = "pointer"; break;
|
||||||
|
case MOUSE_CURSOR_RESIZE_EW: cursorName = "ew-resize"; break;
|
||||||
|
case MOUSE_CURSOR_RESIZE_NS: cursorName = "ns-resize"; break;
|
||||||
|
case MOUSE_CURSOR_RESIZE_NWSE: cursorName = "nwse-resize"; break;
|
||||||
|
case MOUSE_CURSOR_RESIZE_NESW: cursorName = "nesw-resize"; break;
|
||||||
|
case MOUSE_CURSOR_RESIZE_ALL: cursorName = "move"; break;
|
||||||
|
case MOUSE_CURSOR_NOT_ALLOWED: cursorName = "not-allowed"; break;
|
||||||
|
|
||||||
// Get touch position X for touch point 0 (relative to screen size)
|
case MOUSE_CURSOR_ARROW: // can't find a name specifically for arrow cursor
|
||||||
int GetTouchX(void)
|
case MOUSE_CURSOR_DEFAULT:
|
||||||
{
|
{
|
||||||
return (int)CORE.Input.Touch.position[0].x;
|
cursorName = "default";
|
||||||
}
|
} break;
|
||||||
|
|
||||||
// Get touch position Y for touch point 0 (relative to screen size)
|
default:
|
||||||
int GetTouchY(void)
|
{
|
||||||
{
|
TRACELOG(LOG_WARNING, "Cursor value out of bound (%d). Setting to default", cursor);
|
||||||
return (int)CORE.Input.Touch.position[0].y;
|
cursorName = "default";
|
||||||
}
|
} break;
|
||||||
|
}
|
||||||
|
|
||||||
// Get touch position XY for a touch point index (relative to screen size)
|
// Set the cursor element on the CSS
|
||||||
// TODO: Touch position should be scaled depending on display size and render size
|
EM_ASM({document.body.style.cursor = UTF8ToString($0);}, cursorName);
|
||||||
Vector2 GetTouchPosition(int index)
|
|
||||||
{
|
|
||||||
Vector2 position = { -1.0f, -1.0f };
|
|
||||||
|
|
||||||
if (index < MAX_TOUCH_POINTS) position = CORE.Input.Touch.position[index];
|
|
||||||
else TRACELOG(LOG_WARNING, "INPUT: Required touch point out of range (Max touch points: %i)", MAX_TOUCH_POINTS);
|
|
||||||
|
|
||||||
return position;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register all input events
|
// Register all input events
|
||||||
|
|
@ -913,43 +810,14 @@ void PollInputEvents(void)
|
||||||
// Module Internal Functions Definition
|
// Module Internal Functions Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Initialize display device and framebuffer
|
// Initialize platform: graphics, inputs and more
|
||||||
// NOTE: width and height represent the screen (framebuffer) desired size, not actual display size
|
static int InitPlatform(void)
|
||||||
// If width or height are 0, default display size will be used for framebuffer size
|
|
||||||
// NOTE: returns false in case graphic device could not be created
|
|
||||||
static bool InitGraphicsDevice(int width, int height)
|
|
||||||
{
|
{
|
||||||
CORE.Window.screen.width = width; // User desired width
|
|
||||||
CORE.Window.screen.height = height; // User desired height
|
|
||||||
CORE.Window.screenScale = MatrixIdentity(); // No draw scaling required by default
|
|
||||||
|
|
||||||
// Set the screen minimum and maximum default values to 0
|
|
||||||
CORE.Window.screenMin.width = 0;
|
|
||||||
CORE.Window.screenMin.height = 0;
|
|
||||||
CORE.Window.screenMax.width = 0;
|
|
||||||
CORE.Window.screenMax.height = 0;
|
|
||||||
|
|
||||||
// NOTE: Framebuffer (render area - CORE.Window.render.width, CORE.Window.render.height) could include black bars...
|
|
||||||
// ...in top-down or left-right to match display aspect ratio (no weird scaling)
|
|
||||||
|
|
||||||
glfwSetErrorCallback(ErrorCallback);
|
glfwSetErrorCallback(ErrorCallback);
|
||||||
/*
|
|
||||||
// TODO: Setup GLFW custom allocators to match raylib ones
|
|
||||||
const GLFWallocator allocator = {
|
|
||||||
.allocate = MemAlloc,
|
|
||||||
.deallocate = MemFree,
|
|
||||||
.reallocate = MemRealloc,
|
|
||||||
.user = NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
glfwInitAllocator(&allocator);
|
// Initialize GLFW internal global state
|
||||||
*/
|
int result = glfwInit();
|
||||||
|
if (result == GLFW_FALSE) { TRACELOG(LOG_WARNING, "GLFW: Failed to initialize GLFW"); return -1; }
|
||||||
if (!glfwInit())
|
|
||||||
{
|
|
||||||
TRACELOG(LOG_WARNING, "GLFW: Failed to initialize GLFW");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
glfwDefaultWindowHints(); // Set default windows hints
|
glfwDefaultWindowHints(); // Set default windows hints
|
||||||
// glfwWindowHint(GLFW_RED_BITS, 8); // Framebuffer red color component bits
|
// glfwWindowHint(GLFW_RED_BITS, 8); // Framebuffer red color component bits
|
||||||
|
|
@ -1115,7 +983,7 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
{
|
{
|
||||||
glfwTerminate();
|
glfwTerminate();
|
||||||
TRACELOG(LOG_WARNING, "GLFW: Failed to initialize Window");
|
TRACELOG(LOG_WARNING, "GLFW: Failed to initialize Window");
|
||||||
return false;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// WARNING: glfwCreateWindow() title doesn't work with emscripten
|
// WARNING: glfwCreateWindow() title doesn't work with emscripten
|
||||||
|
|
@ -1137,6 +1005,12 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
|
|
||||||
glfwMakeContextCurrent(platform.handle);
|
glfwMakeContextCurrent(platform.handle);
|
||||||
|
|
||||||
|
// Load OpenGL extensions
|
||||||
|
// NOTE: GL procedures address loader is required to load extensions
|
||||||
|
rlLoadExtensions(glfwGetProcAddress);
|
||||||
|
|
||||||
|
if ((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) > 0) MinimizeWindow();
|
||||||
|
|
||||||
// Try to enable GPU V-Sync, so frames are limited to screen refresh rate (60Hz -> 60 FPS)
|
// Try to enable GPU V-Sync, so frames are limited to screen refresh rate (60Hz -> 60 FPS)
|
||||||
// NOTE: V-Sync can be enabled by graphic driver configuration, it doesn't need
|
// NOTE: V-Sync can be enabled by graphic driver configuration, it doesn't need
|
||||||
// to be activated on web platforms since VSync is enforced there.
|
// to be activated on web platforms since VSync is enforced there.
|
||||||
|
|
@ -1155,21 +1029,55 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
TRACELOG(LOG_INFO, " > Render size: %i x %i", CORE.Window.render.width, CORE.Window.render.height);
|
TRACELOG(LOG_INFO, " > Render size: %i x %i", CORE.Window.render.width, CORE.Window.render.height);
|
||||||
TRACELOG(LOG_INFO, " > Viewport offsets: %i, %i", CORE.Window.renderOffset.x, CORE.Window.renderOffset.y);
|
TRACELOG(LOG_INFO, " > Viewport offsets: %i, %i", CORE.Window.renderOffset.x, CORE.Window.renderOffset.y);
|
||||||
|
|
||||||
// Load OpenGL extensions
|
CORE.Window.ready = true; // TODO: Proper validation on windows/context creation
|
||||||
// NOTE: GL procedures address loader is required to load extensions
|
|
||||||
rlLoadExtensions(glfwGetProcAddress);
|
|
||||||
|
|
||||||
// Initialize OpenGL context (states and resources)
|
// If graphic device is no properly initialized, we end program
|
||||||
// NOTE: CORE.Window.currentFbo.width and CORE.Window.currentFbo.height not used, just stored as globals in rlgl
|
if (!CORE.Window.ready) { TRACELOG(LOG_FATAL, "PLATFORM: Failed to initialize graphic device"); return -1; }
|
||||||
rlglInit(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
|
else SetWindowPosition(GetMonitorWidth(GetCurrentMonitor())/2 - CORE.Window.screen.width/2, GetMonitorHeight(GetCurrentMonitor())/2 - CORE.Window.screen.height/2);
|
||||||
|
|
||||||
// Setup default viewport
|
// Initialize hi-res timer
|
||||||
// NOTE: It updated CORE.Window.render.width and CORE.Window.render.height
|
InitTimer();
|
||||||
SetupViewport(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
|
|
||||||
|
|
||||||
if ((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) > 0) MinimizeWindow();
|
// Initialize base path for storage
|
||||||
|
CORE.Storage.basePath = GetWorkingDirectory();
|
||||||
|
|
||||||
return true;
|
// Setup callback functions for the DOM events
|
||||||
|
emscripten_set_fullscreenchange_callback("#canvas", NULL, 1, EmscriptenFullscreenChangeCallback);
|
||||||
|
|
||||||
|
// WARNING: Below resize code was breaking fullscreen mode for sample games and examples, it needs review
|
||||||
|
// Check fullscreen change events(note this is done on the window since most browsers don't support this on #canvas)
|
||||||
|
// emscripten_set_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, 1, EmscriptenResizeCallback);
|
||||||
|
// Check Resize event (note this is done on the window since most browsers don't support this on #canvas)
|
||||||
|
emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, 1, EmscriptenResizeCallback);
|
||||||
|
|
||||||
|
// Trigger this once to get initial window sizing
|
||||||
|
EmscriptenResizeCallback(EMSCRIPTEN_EVENT_RESIZE, NULL, NULL);
|
||||||
|
|
||||||
|
// Support keyboard events -> Not used, GLFW.JS takes care of that
|
||||||
|
// emscripten_set_keypress_callback("#canvas", NULL, 1, EmscriptenKeyboardCallback);
|
||||||
|
// emscripten_set_keydown_callback("#canvas", NULL, 1, EmscriptenKeyboardCallback);
|
||||||
|
|
||||||
|
// Support mouse events
|
||||||
|
emscripten_set_click_callback("#canvas", NULL, 1, EmscriptenMouseCallback);
|
||||||
|
|
||||||
|
// Support touch events
|
||||||
|
emscripten_set_touchstart_callback("#canvas", NULL, 1, EmscriptenTouchCallback);
|
||||||
|
emscripten_set_touchend_callback("#canvas", NULL, 1, EmscriptenTouchCallback);
|
||||||
|
emscripten_set_touchmove_callback("#canvas", NULL, 1, EmscriptenTouchCallback);
|
||||||
|
emscripten_set_touchcancel_callback("#canvas", NULL, 1, EmscriptenTouchCallback);
|
||||||
|
|
||||||
|
// Support gamepad events (not provided by GLFW3 on emscripten)
|
||||||
|
emscripten_set_gamepadconnected_callback(NULL, 1, EmscriptenGamepadCallback);
|
||||||
|
emscripten_set_gamepaddisconnected_callback(NULL, 1, EmscriptenGamepadCallback);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close platform
|
||||||
|
static void ClosePlatform(void)
|
||||||
|
{
|
||||||
|
glfwDestroyWindow(platform.handle);
|
||||||
|
glfwTerminate();
|
||||||
}
|
}
|
||||||
|
|
||||||
// GLFW3 Error Callback, runs on GLFW3 error
|
// GLFW3 Error Callback, runs on GLFW3 error
|
||||||
|
|
@ -1218,7 +1126,7 @@ static void WindowIconifyCallback(GLFWwindow *window, int iconified)
|
||||||
// GLFW3 Window Maximize Callback, runs when window is maximized
|
// GLFW3 Window Maximize Callback, runs when window is maximized
|
||||||
static void WindowMaximizeCallback(GLFWwindow *window, int maximized)
|
static void WindowMaximizeCallback(GLFWwindow *window, int maximized)
|
||||||
{
|
{
|
||||||
|
// TODO.
|
||||||
}
|
}
|
||||||
|
|
||||||
// GLFW3 WindowFocus Callback, runs when window get/lose focus
|
// GLFW3 WindowFocus Callback, runs when window get/lose focus
|
||||||
|
|
@ -1256,7 +1164,6 @@ static void WindowDropCallback(GLFWwindow *window, int count, const char **paths
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// GLFW3 Keyboard Callback, runs on key pressed
|
// GLFW3 Keyboard Callback, runs on key pressed
|
||||||
static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods)
|
static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods)
|
||||||
{
|
{
|
||||||
|
|
@ -1435,11 +1342,10 @@ static void MouseScrollCallback(GLFWwindow *window, double xoffset, double yoffs
|
||||||
// GLFW3 CursorEnter Callback, when cursor enters the window
|
// GLFW3 CursorEnter Callback, when cursor enters the window
|
||||||
static void CursorEnterCallback(GLFWwindow *window, int enter)
|
static void CursorEnterCallback(GLFWwindow *window, int enter)
|
||||||
{
|
{
|
||||||
if (enter == true) CORE.Input.Mouse.cursorOnScreen = true;
|
if (enter) CORE.Input.Mouse.cursorOnScreen = true;
|
||||||
else CORE.Input.Mouse.cursorOnScreen = false;
|
else CORE.Input.Mouse.cursorOnScreen = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Register fullscreen change events
|
// Register fullscreen change events
|
||||||
static EM_BOOL EmscriptenFullscreenChangeCallback(int eventType, const EmscriptenFullscreenChangeEvent *event, void *userData)
|
static EM_BOOL EmscriptenFullscreenChangeCallback(int eventType, const EmscriptenFullscreenChangeEvent *event, void *userData)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
11
src/rtext.c
11
src/rtext.c
|
|
@ -1371,15 +1371,24 @@ const char *TextFormat(const char *text, ...)
|
||||||
|
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, text);
|
va_start(args, text);
|
||||||
vsnprintf(currentBuffer, MAX_TEXT_BUFFER_LENGTH, text, args);
|
int requiredByteCount = vsnprintf(currentBuffer, MAX_TEXT_BUFFER_LENGTH, text, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
|
// If requiredByteCount is larger than the MAX_TEXT_BUFFER_LENGTH, then overflow occured
|
||||||
|
if (requiredByteCount >= MAX_TEXT_BUFFER_LENGTH)
|
||||||
|
{
|
||||||
|
// Inserting "..." at the end of the string to mark as truncated
|
||||||
|
char *truncBuffer = buffers[index] + MAX_TEXT_BUFFER_LENGTH - 4; // Adding 4 bytes = "...\0"
|
||||||
|
sprintf(truncBuffer, "...");
|
||||||
|
}
|
||||||
|
|
||||||
index += 1; // Move to next buffer for next function call
|
index += 1; // Move to next buffer for next function call
|
||||||
if (index >= MAX_TEXTFORMAT_BUFFERS) index = 0;
|
if (index >= MAX_TEXTFORMAT_BUFFERS) index = 0;
|
||||||
|
|
||||||
return currentBuffer;
|
return currentBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Get integer value from text
|
// Get integer value from text
|
||||||
// NOTE: This function replaces atoi() [stdlib.h]
|
// NOTE: This function replaces atoi() [stdlib.h]
|
||||||
int TextToInteger(const char *text)
|
int TextToInteger(const char *text)
|
||||||
|
|
|
||||||
|
|
@ -213,7 +213,7 @@
|
||||||
#define STBIR_MALLOC(size,c) ((void)(c), RL_MALLOC(size))
|
#define STBIR_MALLOC(size,c) ((void)(c), RL_MALLOC(size))
|
||||||
#define STBIR_FREE(ptr,c) ((void)(c), RL_FREE(ptr))
|
#define STBIR_FREE(ptr,c) ((void)(c), RL_FREE(ptr))
|
||||||
#define STB_IMAGE_RESIZE_IMPLEMENTATION
|
#define STB_IMAGE_RESIZE_IMPLEMENTATION
|
||||||
#include "external/stb_image_resize.h" // Required for: stbir_resize_uint8() [ImageResize()]
|
#include "external/stb_image_resize2.h" // Required for: stbir_resize_uint8_linear() [ImageResize()]
|
||||||
|
|
||||||
#if defined(SUPPORT_FILEFORMAT_SVG)
|
#if defined(SUPPORT_FILEFORMAT_SVG)
|
||||||
#define NANOSVG_IMPLEMENTATION // Expands implementation
|
#define NANOSVG_IMPLEMENTATION // Expands implementation
|
||||||
|
|
@ -1624,10 +1624,10 @@ void ImageResize(Image *image, int newWidth, int newHeight)
|
||||||
|
|
||||||
switch (image->format)
|
switch (image->format)
|
||||||
{
|
{
|
||||||
case PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: stbir_resize_uint8((unsigned char *)image->data, image->width, image->height, 0, output, newWidth, newHeight, 0, 1); break;
|
case PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: stbir_resize_uint8_linear((unsigned char *)image->data, image->width, image->height, 0, output, newWidth, newHeight, 0, (stbir_pixel_layout)1); break;
|
||||||
case PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: stbir_resize_uint8((unsigned char *)image->data, image->width, image->height, 0, output, newWidth, newHeight, 0, 2); break;
|
case PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: stbir_resize_uint8_linear((unsigned char *)image->data, image->width, image->height, 0, output, newWidth, newHeight, 0, (stbir_pixel_layout)2); break;
|
||||||
case PIXELFORMAT_UNCOMPRESSED_R8G8B8: stbir_resize_uint8((unsigned char *)image->data, image->width, image->height, 0, output, newWidth, newHeight, 0, 3); break;
|
case PIXELFORMAT_UNCOMPRESSED_R8G8B8: stbir_resize_uint8_linear((unsigned char *)image->data, image->width, image->height, 0, output, newWidth, newHeight, 0, (stbir_pixel_layout)3); break;
|
||||||
case PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: stbir_resize_uint8((unsigned char *)image->data, image->width, image->height, 0, output, newWidth, newHeight, 0, 4); break;
|
case PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: stbir_resize_uint8_linear((unsigned char *)image->data, image->width, image->height, 0, output, newWidth, newHeight, 0, (stbir_pixel_layout)4); break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1643,7 +1643,7 @@ void ImageResize(Image *image, int newWidth, int newHeight)
|
||||||
Color *output = (Color *)RL_MALLOC(newWidth*newHeight*sizeof(Color));
|
Color *output = (Color *)RL_MALLOC(newWidth*newHeight*sizeof(Color));
|
||||||
|
|
||||||
// NOTE: Color data is cast to (unsigned char *), there shouldn't been any problem...
|
// NOTE: Color data is cast to (unsigned char *), there shouldn't been any problem...
|
||||||
stbir_resize_uint8((unsigned char *)pixels, image->width, image->height, 0, (unsigned char *)output, newWidth, newHeight, 0, 4);
|
stbir_resize_uint8_linear((unsigned char *)pixels, image->width, image->height, 0, (unsigned char *)output, newWidth, newHeight, 0, (stbir_pixel_layout)4);
|
||||||
|
|
||||||
int format = image->format;
|
int format = image->format;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user