diff --git a/.github/workflows/webassembly.yml b/.github/workflows/webassembly.yml
index f9e51680d..f676877fd 100644
--- a/.github/workflows/webassembly.yml
+++ b/.github/workflows/webassembly.yml
@@ -29,7 +29,7 @@ jobs:
- name: Setup emsdk
uses: mymindstorm/setup-emsdk@v14
with:
- version: 3.1.54
+ version: 3.1.64
actions-cache-folder: 'emsdk-cache'
- name: Setup Release Version
diff --git a/BINDINGS.md b/BINDINGS.md
index 3e840d587..7fd0dfd93 100644
--- a/BINDINGS.md
+++ b/BINDINGS.md
@@ -83,6 +83,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers
| [raylib-raku](https://github.com/vushu/raylib-raku) | **auto** | [Raku](https://www.raku.org) | Artistic License 2.0 |
| [Raylib.lean](https://github.com/KislyjKisel/Raylib.lean) | 4.5 | [Lean4](https://lean-lang.org) | BSD-3-Clause |
| [raylib-cobol](https://codeberg.org/glowiak/raylib-cobol) | **auto** | [COBOL](https://gnucobol.sourceforge.io) | Public domain |
+| [raylib-apl](https://github.com/Brian-ED/raylib-apl) | **5.0** | [Dyalog APL](https://www.dyalog.com/) | MIT |
### Utility Wrapers
diff --git a/examples/audio/audio_mixed_processor.c b/examples/audio/audio_mixed_processor.c
index 2df381b26..df46edc4e 100644
--- a/examples/audio/audio_mixed_processor.c
+++ b/examples/audio/audio_mixed_processor.c
@@ -97,7 +97,7 @@ int main(void)
DrawRectangle(199, 199, 402, 34, LIGHTGRAY);
for (int i = 0; i < 400; i++)
{
- DrawLine(201 + i, 232 - (averageVolume[i] * 32), 201 + i, 232, MAROON);
+ DrawLine(201 + i, 232 - (int)(averageVolume[i] * 32), 201 + i, 232, MAROON);
}
DrawRectangleLines(199, 199, 402, 34, GRAY);
diff --git a/examples/core/core_automation_events.c b/examples/core/core_automation_events.c
index 319b013ba..64ca51fda 100644
--- a/examples/core/core_automation_events.c
+++ b/examples/core/core_automation_events.c
@@ -88,7 +88,7 @@ int main(void)
// Update
//----------------------------------------------------------------------------------
float deltaTime = 0.015f;//GetFrameTime();
-
+
// Dropped files logic
//----------------------------------------------------------------------------------
if (IsFileDropped())
@@ -157,11 +157,6 @@ int main(void)
}
else player.canJump = true;
- camera.zoom += ((float)GetMouseWheelMove()*0.05f);
-
- if (camera.zoom > 3.0f) camera.zoom = 3.0f;
- else if (camera.zoom < 0.25f) camera.zoom = 0.25f;
-
if (IsKeyPressed(KEY_R))
{
// Reset game state
@@ -176,12 +171,44 @@ int main(void)
}
//----------------------------------------------------------------------------------
+ // Events playing
+ // NOTE: Logic must be before Camera update because it depends on mouse-wheel value,
+ // that can be set by the played event... but some other inputs could be affected
+ //----------------------------------------------------------------------------------
+ if (eventPlaying)
+ {
+ // NOTE: Multiple events could be executed in a single frame
+ while (playFrameCounter == aelist.events[currentPlayFrame].frame)
+ {
+ PlayAutomationEvent(aelist.events[currentPlayFrame]);
+ currentPlayFrame++;
+
+ if (currentPlayFrame == aelist.count)
+ {
+ eventPlaying = false;
+ currentPlayFrame = 0;
+ playFrameCounter = 0;
+
+ TraceLog(LOG_INFO, "FINISH PLAYING!");
+ break;
+ }
+ }
+
+ playFrameCounter++;
+ }
+ //----------------------------------------------------------------------------------
+
// Update camera
//----------------------------------------------------------------------------------
camera.target = player.position;
camera.offset = (Vector2){ screenWidth/2.0f, screenHeight/2.0f };
float minX = 1000, minY = 1000, maxX = -1000, maxY = -1000;
+ // WARNING: On event replay, mouse-wheel internal value is set
+ camera.zoom += ((float)GetMouseWheelMove()*0.05f);
+ if (camera.zoom > 3.0f) camera.zoom = 3.0f;
+ else if (camera.zoom < 0.25f) camera.zoom = 0.25f;
+
for (int i = 0; i < MAX_ENVIRONMENT_ELEMENTS; i++)
{
EnvElement *element = &envElements[i];
@@ -200,8 +227,8 @@ int main(void)
if (min.y > 0) camera.offset.y = screenHeight/2 - min.y;
//----------------------------------------------------------------------------------
- // Toggle events recording
- if (IsKeyPressed(KEY_S))
+ // Events management
+ if (IsKeyPressed(KEY_S)) // Toggle events recording
{
if (!eventPlaying)
{
@@ -222,7 +249,7 @@ int main(void)
}
}
}
- else if (IsKeyPressed(KEY_A))
+ else if (IsKeyPressed(KEY_A)) // Toggle events playing (WARNING: Starts next frame)
{
if (!eventRecording && (aelist.count > 0))
{
@@ -241,32 +268,7 @@ int main(void)
camera.zoom = 1.0f;
}
}
-
- if (eventPlaying)
- {
- // NOTE: Multiple events could be executed in a single frame
- while (playFrameCounter == aelist.events[currentPlayFrame].frame)
- {
- TraceLog(LOG_INFO, "PLAYING: PlayFrameCount: %i | currentPlayFrame: %i | Event Frame: %i, param: %i",
- playFrameCounter, currentPlayFrame, aelist.events[currentPlayFrame].frame, aelist.events[currentPlayFrame].params[0]);
-
- PlayAutomationEvent(aelist.events[currentPlayFrame]);
- currentPlayFrame++;
- if (currentPlayFrame == aelist.count)
- {
- eventPlaying = false;
- currentPlayFrame = 0;
- playFrameCounter = 0;
-
- TraceLog(LOG_INFO, "FINISH PLAYING!");
- break;
- }
- }
-
- playFrameCounter++;
- }
-
if (eventRecording || eventPlaying) frameCounter++;
else frameCounter = 0;
//----------------------------------------------------------------------------------
diff --git a/examples/core/core_input_gamepad_info.c b/examples/core/core_input_gamepad_info.c
index 66fedda90..096294681 100644
--- a/examples/core/core_input_gamepad_info.c
+++ b/examples/core/core_input_gamepad_info.c
@@ -47,25 +47,25 @@ int main(void)
ClearBackground(RAYWHITE);
- for (int i = 0, y = 10; i < 4; i++) // MAX_GAMEPADS = 4
+ for (int i = 0, y = 5; i < 4; i++) // MAX_GAMEPADS = 4
{
if (IsGamepadAvailable(i))
{
- DrawText(TextFormat("Gamepad name: %s", GetGamepadName(i)), 10, y, 20, BLACK);
- y += 30;
- DrawText(TextFormat("\tAxis count: %d", GetGamepadAxisCount(i)), 10, y, 20, BLACK);
- y += 30;
+ DrawText(TextFormat("Gamepad name: %s", GetGamepadName(i)), 10, y, 10, BLACK);
+ y += 11;
+ DrawText(TextFormat("\tAxis count: %d", GetGamepadAxisCount(i)), 10, y, 10, BLACK);
+ y += 11;
for (int axis = 0; axis < GetGamepadAxisCount(i); axis++)
{
- DrawText(TextFormat("\tAxis %d = %f", axis, GetGamepadAxisMovement(i, axis)), 10, y, 20, BLACK);
- y += 30;
+ DrawText(TextFormat("\tAxis %d = %f", axis, GetGamepadAxisMovement(i, axis)), 10, y, 10, BLACK);
+ y += 11;
}
for (int button = 0; button < 32; button++)
{
- DrawText(TextFormat("\tButton %d = %d", button, IsGamepadButtonDown(i, button)), 10, y, 20, BLACK);
- y += 30;
+ DrawText(TextFormat("\tButton %d = %d", button, IsGamepadButtonDown(i, button)), 10, y, 10, BLACK);
+ y += 11;
}
}
}
@@ -80,4 +80,4 @@ int main(void)
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
-}
\ No newline at end of file
+}
diff --git a/examples/core/core_vr_simulator.c b/examples/core/core_vr_simulator.c
index c98fce931..021698edb 100644
--- a/examples/core/core_vr_simulator.c
+++ b/examples/core/core_vr_simulator.c
@@ -100,7 +100,7 @@ int main(void)
DisableCursor(); // Limit cursor to relative movement inside the window
- SetTargetFPS(90); // Set our game to run at 90 frames-per-second
+ SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
// Main game loop
diff --git a/examples/models/models_box_collisions.c b/examples/models/models_box_collisions.c
index 936f65f38..4d98a776a 100644
--- a/examples/models/models_box_collisions.c
+++ b/examples/models/models_box_collisions.c
@@ -109,7 +109,7 @@ int main(void)
EndMode3D();
- DrawText("Move player with cursors to collide", 220, 40, 20, GRAY);
+ DrawText("Move player with arrow keys to collide", 220, 40, 20, GRAY);
DrawFPS(10, 10);
diff --git a/examples/models/models_yaw_pitch_roll.c b/examples/models/models_yaw_pitch_roll.c
index 91a11f73c..5374c035e 100644
--- a/examples/models/models_yaw_pitch_roll.c
+++ b/examples/models/models_yaw_pitch_roll.c
@@ -114,6 +114,7 @@ int main(void)
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadModel(model); // Unload model data
+ UnloadTexture(texture); // Unload texture data
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
diff --git a/examples/shaders/shaders_basic_pbr.c b/examples/shaders/shaders_basic_pbr.c
index d025ab8a9..c3f2bad88 100644
--- a/examples/shaders/shaders_basic_pbr.c
+++ b/examples/shaders/shaders_basic_pbr.c
@@ -236,7 +236,7 @@ int main()
float emissiveIntensity = 0.01f;
SetShaderValue(shader, emissiveIntensityLoc, &emissiveIntensity, SHADER_UNIFORM_FLOAT);
- DrawModel(car, (Vector3){ 0.0f, 0.0f, 0.0f }, 0.005f, WHITE); // Draw car model
+ DrawModel(car, (Vector3){ 0.0f, 0.0f, 0.0f }, 0.25f, WHITE); // Draw car model
// Draw spheres to show the lights positions
for (int i = 0; i < MAX_LIGHTS; i++)
diff --git a/examples/shaders/shaders_lightmap.c b/examples/shaders/shaders_lightmap.c
index 01b80a6fb..91ed8bfd2 100644
--- a/examples/shaders/shaders_lightmap.c
+++ b/examples/shaders/shaders_lightmap.c
@@ -164,6 +164,8 @@ int main(void)
//--------------------------------------------------------------------------------------
UnloadMesh(mesh); // Unload the mesh
UnloadShader(shader); // Unload shader
+ UnloadTexture(texture); // Unload texture
+ UnloadTexture(light); // Unload texture
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
diff --git a/examples/shaders/shaders_texture_drawing.c b/examples/shaders/shaders_texture_drawing.c
index 52b8967f6..ada44299d 100644
--- a/examples/shaders/shaders_texture_drawing.c
+++ b/examples/shaders/shaders_texture_drawing.c
@@ -77,6 +77,7 @@ int main(void)
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadShader(shader);
+ UnloadTexture(texture);
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
diff --git a/examples/shaders/shaders_vertex_displacement.c b/examples/shaders/shaders_vertex_displacement.c
index c211d349f..207a237d0 100644
--- a/examples/shaders/shaders_vertex_displacement.c
+++ b/examples/shaders/shaders_vertex_displacement.c
@@ -110,6 +110,7 @@ int main(void)
//--------------------------------------------------------------------------------------
UnloadShader(shader);
UnloadModel(planeModel);
+ UnloadTexture(perlinNoiseMap);
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
diff --git a/examples/shapes/raygui.h b/examples/shapes/raygui.h
index 623115fce..16e01a28f 100644
--- a/examples/shapes/raygui.h
+++ b/examples/shapes/raygui.h
@@ -1,6 +1,6 @@
/*******************************************************************************************
*
-* raygui v4.0 - A simple and easy-to-use immediate-mode gui library
+* raygui v4.5-dev - A simple and easy-to-use immediate-mode gui library
*
* DESCRIPTION:
* raygui is a tools-dev-focused immediate-mode-gui library based on raylib but also
@@ -26,7 +26,7 @@
* NOTES:
* - WARNING: GuiLoadStyle() and GuiLoadStyle{Custom}() functions, allocate memory for
* font atlas recs and glyphs, freeing that memory is (usually) up to the user,
-* no unload function is explicitly provided... but note that GuiLoadStyleDefaulf() unloads
+* no unload function is explicitly provided... but note that GuiLoadStyleDefault() unloads
* by default any previously loaded font (texture, recs, glyphs).
* - Global UI alpha (guiAlpha) is applied inside GuiDrawRectangle() and GuiDrawText() functions
*
@@ -141,6 +141,24 @@
* Draw text bounds rectangles for debug
*
* VERSIONS HISTORY:
+* 4.5-dev (Sep-2024) Current dev version...
+* ADDED: guiControlExclusiveMode and guiControlExclusiveRec for exclusive modes
+* ADDED: GuiValueBoxFloat()
+* ADDED: GuiDropdonwBox() properties: DROPDOWN_ARROW_HIDDEN, DROPDOWN_ROLL_UP
+* ADDED: GuiListView() property: LIST_ITEMS_BORDER_WIDTH
+* ADDED: Multiple new icons
+* REVIEWED: GuiTabBar(), close tab with mouse middle button
+* REVIEWED: GuiScrollPanel(), scroll speed proportional to content
+* REVIEWED: GuiDropdownBox(), support roll up and hidden arrow
+* REVIEWED: GuiTextBox(), cursor position initialization
+* REVIEWED: GuiSliderPro(), control value change check
+* REVIEWED: GuiGrid(), simplified implementation
+* REVIEWED: GuiIconText(), increase buffer size and reviewed padding
+* REVIEWED: GuiDrawText(), improved wrap mode drawing
+* REVIEWED: GuiScrollBar(), minor tweaks
+* REVIEWED: Functions descriptions, removed wrong return value reference
+* REDESIGNED: GuiColorPanel(), improved HSV <-> RGBA convertion
+*
* 4.0 (12-Sep-2023) ADDED: GuiToggleSlider()
* ADDED: GuiColorPickerHSV() and GuiColorPanelHSV()
* ADDED: Multiple new icons, mostly compiler related
@@ -314,9 +332,9 @@
#define RAYGUI_H
#define RAYGUI_VERSION_MAJOR 4
-#define RAYGUI_VERSION_MINOR 0
+#define RAYGUI_VERSION_MINOR 5
#define RAYGUI_VERSION_PATCH 0
-#define RAYGUI_VERSION "4.0"
+#define RAYGUI_VERSION "4.5-dev"
#if !defined(RAYGUI_STANDALONE)
#include "raylib.h"
@@ -441,7 +459,6 @@
} Font;
#endif
-
// Style property
// NOTE: Used when exporting style as code for convenience
typedef struct GuiStyleProp {
@@ -546,7 +563,6 @@ typedef enum {
// TEXT_SIZE, TEXT_SPACING, TEXT_LINE_SPACING, TEXT_ALIGNMENT_VERTICAL, TEXT_WRAP_MODE are global and
// should be configured by user as needed while defining the UI layout
-
// Gui extended properties depend on control
// NOTE: RAYGUI_MAX_PROPS_EXTENDED properties (by default, max 8 properties)
//----------------------------------------------------------------------------------
@@ -562,12 +578,12 @@ typedef enum {
TEXT_ALIGNMENT_VERTICAL, // Text vertical alignment inside text bounds (after border and padding)
TEXT_WRAP_MODE // Text wrap-mode inside text bounds
//TEXT_DECORATION // Text decoration: 0-None, 1-Underline, 2-Line-through, 3-Overline
- //TEXT_DECORATION_THICK // Text decoration line thikness
+ //TEXT_DECORATION_THICK // Text decoration line thickness
} GuiDefaultProperty;
// Other possible text properties:
// TEXT_WEIGHT // Normal, Italic, Bold -> Requires specific font change
-// TEXT_INDENT // Text indentation -> Now using TEXT_PADDING...
+// TEXT_INDENT // Text indentation -> Now using TEXT_PADDING...
// Label
//typedef enum { } GuiLabelProperty;
@@ -615,7 +631,9 @@ typedef enum {
// DropdownBox
typedef enum {
ARROW_PADDING = 16, // DropdownBox arrow separation from border and items
- DROPDOWN_ITEMS_SPACING // DropdownBox items separation
+ DROPDOWN_ITEMS_SPACING, // DropdownBox items separation
+ DROPDOWN_ARROW_HIDDEN, // DropdownBox arrow hidden
+ DROPDOWN_ROLL_UP // DropdownBox roll up flag (default rolls down)
} GuiDropdownBoxProperty;
// TextBox/TextBoxMulti/ValueBox/Spinner
@@ -635,6 +653,7 @@ typedef enum {
LIST_ITEMS_SPACING, // ListView items separation
SCROLLBAR_WIDTH, // ListView scrollbar size (usually width)
SCROLLBAR_SIDE, // ListView scrollbar side (0-SCROLLBAR_LEFT_SIDE, 1-SCROLLBAR_RIGHT_SIDE)
+ LIST_ITEMS_BORDER_WIDTH // ListView items border width
} GuiListViewProperty;
// ColorPicker
@@ -698,7 +717,6 @@ RAYGUIAPI char **GuiLoadIcons(const char *fileName, bool loadIconsName); // Load
RAYGUIAPI void GuiDrawIcon(int iconId, int posX, int posY, int pixelSize, Color color); // Draw icon using pixel size at specified position
#endif
-
// Controls
//----------------------------------------------------------------------------------------------------------
// Container/separator controls, useful for controls organization
@@ -710,29 +728,30 @@ RAYGUIAPI int GuiTabBar(Rectangle bounds, const char **text, int count, int *act
RAYGUIAPI int GuiScrollPanel(Rectangle bounds, const char *text, Rectangle content, Vector2 *scroll, Rectangle *view); // Scroll Panel control
// Basic controls set
-RAYGUIAPI int GuiLabel(Rectangle bounds, const char *text); // Label control, shows text
+RAYGUIAPI int GuiLabel(Rectangle bounds, const char *text); // Label control
RAYGUIAPI int GuiButton(Rectangle bounds, const char *text); // Button control, returns true when clicked
-RAYGUIAPI int GuiLabelButton(Rectangle bounds, const char *text); // Label button control, show true when clicked
-RAYGUIAPI int GuiToggle(Rectangle bounds, const char *text, bool *active); // Toggle Button control, returns true when active
-RAYGUIAPI int GuiToggleGroup(Rectangle bounds, const char *text, int *active); // Toggle Group control, returns active toggle index
-RAYGUIAPI int GuiToggleSlider(Rectangle bounds, const char *text, int *active); // Toggle Slider control, returns true when clicked
+RAYGUIAPI int GuiLabelButton(Rectangle bounds, const char *text); // Label button control, returns true when clicked
+RAYGUIAPI int GuiToggle(Rectangle bounds, const char *text, bool *active); // Toggle Button control
+RAYGUIAPI int GuiToggleGroup(Rectangle bounds, const char *text, int *active); // Toggle Group control
+RAYGUIAPI int GuiToggleSlider(Rectangle bounds, const char *text, int *active); // Toggle Slider control
RAYGUIAPI int GuiCheckBox(Rectangle bounds, const char *text, bool *checked); // Check Box control, returns true when active
-RAYGUIAPI int GuiComboBox(Rectangle bounds, const char *text, int *active); // Combo Box control, returns selected item index
+RAYGUIAPI int GuiComboBox(Rectangle bounds, const char *text, int *active); // Combo Box control
-RAYGUIAPI int GuiDropdownBox(Rectangle bounds, const char *text, int *active, bool editMode); // Dropdown Box control, returns selected item
-RAYGUIAPI int GuiSpinner(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode); // Spinner control, returns selected value
+RAYGUIAPI int GuiDropdownBox(Rectangle bounds, const char *text, int *active, bool editMode); // Dropdown Box control
+RAYGUIAPI int GuiSpinner(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode); // Spinner control
RAYGUIAPI int GuiValueBox(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode); // Value Box control, updates input text with numbers
+RAYGUIAPI int GuiValueBoxFloat(Rectangle bounds, const char *text, char *textValue, float *value, bool editMode); // Value box control for float values
RAYGUIAPI int GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode); // Text Box control, updates input text
-RAYGUIAPI int GuiSlider(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue); // Slider control, returns selected value
-RAYGUIAPI int GuiSliderBar(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue); // Slider Bar control, returns selected value
-RAYGUIAPI int GuiProgressBar(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue); // Progress Bar control, shows current progress value
+RAYGUIAPI int GuiSlider(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue); // Slider control
+RAYGUIAPI int GuiSliderBar(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue); // Slider Bar control
+RAYGUIAPI int GuiProgressBar(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue); // Progress Bar control
RAYGUIAPI int GuiStatusBar(Rectangle bounds, const char *text); // Status Bar control, shows info text
RAYGUIAPI int GuiDummyRec(Rectangle bounds, const char *text); // Dummy control for placeholders
-RAYGUIAPI int GuiGrid(Rectangle bounds, const char *text, float spacing, int subdivs, Vector2 *mouseCell); // Grid control, returns mouse cell position
+RAYGUIAPI int GuiGrid(Rectangle bounds, const char *text, float spacing, int subdivs, Vector2 *mouseCell); // Grid control
// Advance controls set
-RAYGUIAPI int GuiListView(Rectangle bounds, const char *text, int *scrollIndex, int *active); // List View control, returns selected list item index
+RAYGUIAPI int GuiListView(Rectangle bounds, const char *text, int *scrollIndex, int *active); // List View control
RAYGUIAPI int GuiListViewEx(Rectangle bounds, const char **text, int count, int *scrollIndex, int *active, int *focus); // List View with extended parameters
RAYGUIAPI int GuiMessageBox(Rectangle bounds, const char *title, const char *message, const char *buttons); // Message Box control, displays a message
RAYGUIAPI int GuiTextInputBox(Rectangle bounds, const char *title, const char *message, const char *buttons, char *text, int textMaxSize, bool *secretViewActive); // Text Input Box control, ask for text, supports secret
@@ -741,10 +760,9 @@ RAYGUIAPI int GuiColorPanel(Rectangle bounds, const char *text, Color *color);
RAYGUIAPI int GuiColorBarAlpha(Rectangle bounds, const char *text, float *alpha); // Color Bar Alpha control
RAYGUIAPI int GuiColorBarHue(Rectangle bounds, const char *text, float *value); // Color Bar Hue control
RAYGUIAPI int GuiColorPickerHSV(Rectangle bounds, const char *text, Vector3 *colorHsv); // Color Picker control that avoids conversion to RGB on each call (multiple color controls)
-RAYGUIAPI int GuiColorPanelHSV(Rectangle bounds, const char *text, Vector3 *colorHsv); // Color Panel control that returns HSV color value, used by GuiColorPickerHSV()
+RAYGUIAPI int GuiColorPanelHSV(Rectangle bounds, const char *text, Vector3 *colorHsv); // Color Panel control that updates Hue-Saturation-Value color value, used by GuiColorPickerHSV()
//----------------------------------------------------------------------------------------------------------
-
#if !defined(RAYGUI_NO_ICONS)
#if !defined(RAYGUI_CUSTOM_ICONS)
@@ -972,14 +990,14 @@ typedef enum {
ICON_FOLDER = 217,
ICON_FILE = 218,
ICON_SAND_TIMER = 219,
- ICON_220 = 220,
- ICON_221 = 221,
- ICON_222 = 222,
- ICON_223 = 223,
- ICON_224 = 224,
- ICON_225 = 225,
- ICON_226 = 226,
- ICON_227 = 227,
+ ICON_WARNING = 220,
+ ICON_HELP_BOX = 221,
+ ICON_INFO_BOX = 222,
+ ICON_PRIORITY = 223,
+ ICON_LAYERS_ISO = 224,
+ ICON_LAYERS2 = 225,
+ ICON_MLAYERS = 226,
+ ICON_MAPS = 227,
ICON_228 = 228,
ICON_229 = 229,
ICON_230 = 230,
@@ -1290,14 +1308,14 @@ static unsigned int guiIcons[RAYGUI_ICON_MAX_ICONS*RAYGUI_ICON_DATA_ELEMENTS] =
0x00000000, 0x0042007e, 0x40027fc2, 0x40024002, 0x40024002, 0x40024002, 0x7ffe4002, 0x00000000, // ICON_FOLDER
0x3ff00000, 0x201c2010, 0x20042004, 0x20042004, 0x20042004, 0x20042004, 0x20042004, 0x00003ffc, // ICON_FILE
0x1ff00000, 0x20082008, 0x17d02fe8, 0x05400ba0, 0x09200540, 0x23881010, 0x2fe827c8, 0x00001ff0, // ICON_SAND_TIMER
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_220
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_221
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_222
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_223
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_224
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_225
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_226
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_227
+ 0x01800000, 0x02400240, 0x05a00420, 0x09900990, 0x11881188, 0x21842004, 0x40024182, 0x00003ffc, // ICON_WARNING
+ 0x7ffe0000, 0x4ff24002, 0x4c324ff2, 0x4f824c02, 0x41824f82, 0x41824002, 0x40024182, 0x00007ffe, // ICON_HELP_BOX
+ 0x7ffe0000, 0x41824002, 0x40024182, 0x41824182, 0x41824182, 0x41824182, 0x40024182, 0x00007ffe, // ICON_INFO_BOX
+ 0x01800000, 0x04200240, 0x10080810, 0x7bde2004, 0x0a500a50, 0x08500bd0, 0x08100850, 0x00000ff0, // ICON_PRIORITY
+ 0x01800000, 0x18180660, 0x80016006, 0x98196006, 0x99996666, 0x19986666, 0x01800660, 0x00000000, // ICON_LAYERS_ISO
+ 0x07fe0000, 0x1c020402, 0x74021402, 0x54025402, 0x54025402, 0x500857fe, 0x40205ff8, 0x00007fe0, // ICON_LAYERS2
+ 0x0ffe0000, 0x3ffa0802, 0x7fea200a, 0x402a402a, 0x422a422a, 0x422e422a, 0x40384e28, 0x00007fe0, // ICON_MLAYERS
+ 0x0ffe0000, 0x3ffa0802, 0x7fea200a, 0x402a402a, 0x5b2a512a, 0x512e552a, 0x40385128, 0x00007fe0, // ICON_MAPS
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_228
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_229
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_230
@@ -1328,7 +1346,7 @@ static unsigned int guiIcons[RAYGUI_ICON_MAX_ICONS*RAYGUI_ICON_DATA_ELEMENTS] =
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_255
};
-// NOTE: We keep a pointer to the icons array, useful to point to other sets if required
+// NOTE: A pointer to current icons array should be defined
static unsigned int *guiIconsPtr = guiIcons;
#endif // !RAYGUI_NO_ICONS && !RAYGUI_CUSTOM_ICONS
@@ -1363,8 +1381,8 @@ static unsigned int guiIconScale = 1; // Gui icon default scale (if ic
static bool guiTooltip = false; // Tooltip enabled/disabled
static const char *guiTooltipPtr = NULL; // Tooltip string pointer (string provided by user)
-static bool guiSliderDragging = false; // Gui slider drag state (no inputs processed except dragged slider)
-static Rectangle guiSliderActive = { 0 }; // Gui slider active bounds rectangle, used as an unique identifier
+static bool guiControlExclusiveMode = false; // Gui control exclusive mode (no inputs processed except current control)
+static Rectangle guiControlExclusiveRec = { 0 }; // Gui control exclusive bounds rectangle, used as an unique identifier
static int textBoxCursorIndex = 0; // Cursor index, shared by all GuiTextBox*()
//static int blinkCursorFrameCounter = 0; // Frame counter for cursor blinking
@@ -1450,6 +1468,7 @@ static bool CheckCollisionPointRec(Vector2 point, Rectangle rec); // Check if
static const char *TextFormat(const char *text, ...); // Formatting of text with variables to 'embed'
static const char **TextSplit(const char *text, char delimiter, int *count); // Split text into multiple strings
static int TextToInteger(const char *text); // Get integer value from text
+static float TextToFloat(const char *text); // Get float value from text
static int GetCodepointNext(const char *text, int *codepointSize); // Get next codepoint in a UTF-8 encoded text
static const char *CodepointToUTF8(int codepoint, int *byteSize); // Encode codepoint into UTF-8 text (char array size returned as parameter)
@@ -1744,6 +1763,9 @@ int GuiTabBar(Rectangle bounds, const char **text, int count, int *active)
if (toggle) *active = i;
}
+ // Close tab with middle mouse button pressed
+ if (CheckCollisionPointRec(GetMousePosition(), tabBounds) && IsMouseButtonPressed(MOUSE_MIDDLE_BUTTON)) result = i;
+
GuiSetStyle(TOGGLE, TEXT_PADDING, textPadding);
GuiSetStyle(TOGGLE, TEXT_ALIGNMENT, textAlignment);
@@ -1775,10 +1797,10 @@ int GuiScrollPanel(Rectangle bounds, const char *text, Rectangle content, Vector
{
#define RAYGUI_MIN_SCROLLBAR_WIDTH 40
#define RAYGUI_MIN_SCROLLBAR_HEIGHT 40
+ #define RAYGUI_MIN_MOUSE_WHEEL_SPEED 20
int result = 0;
GuiState state = guiState;
- float mouseWheelSpeed = 20.0f; // Default movement speed with mouse wheel
Rectangle temp = { 0 };
if (view == NULL) view = &temp;
@@ -1820,17 +1842,8 @@ int GuiScrollPanel(Rectangle bounds, const char *text, Rectangle content, Vector
};
// Make sure scroll bars have a minimum width/height
- // NOTE: If content >>> bounds, size could be very small or even 0
- if (horizontalScrollBar.width < RAYGUI_MIN_SCROLLBAR_WIDTH)
- {
- horizontalScrollBar.width = RAYGUI_MIN_SCROLLBAR_WIDTH;
- mouseWheelSpeed = 30.0f; // TODO: Calculate speed increment based on content.height vs bounds.height
- }
- if (verticalScrollBar.height < RAYGUI_MIN_SCROLLBAR_HEIGHT)
- {
- verticalScrollBar.height = RAYGUI_MIN_SCROLLBAR_HEIGHT;
- mouseWheelSpeed = 30.0f; // TODO: Calculate speed increment based on content.width vs bounds.width
- }
+ if (horizontalScrollBar.width < RAYGUI_MIN_SCROLLBAR_WIDTH) horizontalScrollBar.width = RAYGUI_MIN_SCROLLBAR_WIDTH;
+ if (verticalScrollBar.height < RAYGUI_MIN_SCROLLBAR_HEIGHT) verticalScrollBar.height = RAYGUI_MIN_SCROLLBAR_HEIGHT;
// Calculate view area (area without the scrollbars)
*view = (GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)?
@@ -1873,9 +1886,14 @@ int GuiScrollPanel(Rectangle bounds, const char *text, Rectangle content, Vector
#endif
float wheelMove = GetMouseWheelMove();
+ // Set scrolling speed with mouse wheel based on ratio between bounds and content
+ Vector2 mouseWheelSpeed = { content.width/bounds.width, content.height/bounds.height };
+ if (mouseWheelSpeed.x < RAYGUI_MIN_MOUSE_WHEEL_SPEED) mouseWheelSpeed.x = RAYGUI_MIN_MOUSE_WHEEL_SPEED;
+ if (mouseWheelSpeed.y < RAYGUI_MIN_MOUSE_WHEEL_SPEED) mouseWheelSpeed.y = RAYGUI_MIN_MOUSE_WHEEL_SPEED;
+
// Horizontal and vertical scrolling with mouse wheel
- if (hasHorizontalScrollBar && (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_LEFT_SHIFT))) scrollPos.x += wheelMove*mouseWheelSpeed;
- else scrollPos.y += wheelMove*mouseWheelSpeed; // Vertical scroll
+ if (hasHorizontalScrollBar && (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_LEFT_SHIFT))) scrollPos.x += wheelMove*mouseWheelSpeed.x;
+ else scrollPos.y += wheelMove*mouseWheelSpeed.y; // Vertical scroll
}
}
@@ -1921,7 +1939,7 @@ int GuiScrollPanel(Rectangle bounds, const char *text, Rectangle content, Vector
}
// Draw scrollbar lines depending on current state
- GuiDrawRectangle(bounds, GuiGetStyle(DEFAULT, BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER + (state*3))), BLANK);
+ GuiDrawRectangle(bounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER + (state*3))), BLANK);
// Set scrollbar slider size back to the way it was before
GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, slider);
@@ -1959,7 +1977,7 @@ int GuiButton(Rectangle bounds, const char *text)
// Update control
//--------------------------------------------------------------------
- if ((state != STATE_DISABLED) && !guiLocked && !guiSliderDragging)
+ if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode)
{
Vector2 mousePoint = GetMousePosition();
@@ -1997,7 +2015,7 @@ int GuiLabelButton(Rectangle bounds, const char *text)
// Update control
//--------------------------------------------------------------------
- if ((state != STATE_DISABLED) && !guiLocked && !guiSliderDragging)
+ if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode)
{
Vector2 mousePoint = GetMousePosition();
@@ -2020,7 +2038,7 @@ int GuiLabelButton(Rectangle bounds, const char *text)
return pressed;
}
-// Toggle Button control, returns true when active
+// Toggle Button control
int GuiToggle(Rectangle bounds, const char *text, bool *active)
{
int result = 0;
@@ -2031,7 +2049,7 @@ int GuiToggle(Rectangle bounds, const char *text, bool *active)
// Update control
//--------------------------------------------------------------------
- if ((state != STATE_DISABLED) && !guiLocked && !guiSliderDragging)
+ if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode)
{
Vector2 mousePoint = GetMousePosition();
@@ -2068,7 +2086,7 @@ int GuiToggle(Rectangle bounds, const char *text, bool *active)
return result;
}
-// Toggle Group control, returns toggled button codepointIndex
+// Toggle Group control
int GuiToggleGroup(Rectangle bounds, const char *text, int *active)
{
#if !defined(RAYGUI_TOGGLEGROUP_MAX_ITEMS)
@@ -2117,7 +2135,7 @@ int GuiToggleGroup(Rectangle bounds, const char *text, int *active)
return result;
}
-// Toggle Slider control extended, returns true when clicked
+// Toggle Slider control extended
int GuiToggleSlider(Rectangle bounds, const char *text, int *active)
{
int result = 0;
@@ -2211,7 +2229,7 @@ int GuiCheckBox(Rectangle bounds, const char *text, bool *checked)
// Update control
//--------------------------------------------------------------------
- if ((state != STATE_DISABLED) && !guiLocked && !guiSliderDragging)
+ if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode)
{
Vector2 mousePoint = GetMousePosition();
@@ -2256,7 +2274,7 @@ int GuiCheckBox(Rectangle bounds, const char *text, bool *checked)
return result;
}
-// Combo Box control, returns selected item codepointIndex
+// Combo Box control
int GuiComboBox(Rectangle bounds, const char *text, int *active)
{
int result = 0;
@@ -2279,7 +2297,7 @@ int GuiComboBox(Rectangle bounds, const char *text, int *active)
// Update control
//--------------------------------------------------------------------
- if ((state != STATE_DISABLED) && !guiLocked && (itemCount > 1) && !guiSliderDragging)
+ if ((state != STATE_DISABLED) && !guiLocked && (itemCount > 1) && !guiControlExclusiveMode)
{
Vector2 mousePoint = GetMousePosition();
@@ -2327,21 +2345,28 @@ int GuiDropdownBox(Rectangle bounds, const char *text, int *active, bool editMod
int result = 0;
GuiState state = guiState;
+ int temp = 0;
+ if (active == NULL) active = &temp;
+
int itemSelected = *active;
int itemFocused = -1;
+ int direction = 0; // Dropdown box open direction: down (default)
+ if (GuiGetStyle(DROPDOWNBOX, DROPDOWN_ROLL_UP) == 1) direction = 1; // Up
+
// Get substrings items from text (items pointers, lengths and count)
int itemCount = 0;
const char **items = GuiTextSplit(text, ';', &itemCount, NULL);
Rectangle boundsOpen = bounds;
boundsOpen.height = (itemCount + 1)*(bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING));
+ if (direction == 1) boundsOpen.y -= itemCount*(bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING)) + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING);
Rectangle itemBounds = bounds;
// Update control
//--------------------------------------------------------------------
- if ((state != STATE_DISABLED) && (editMode || !guiLocked) && (itemCount > 1) && !guiSliderDragging)
+ if ((state != STATE_DISABLED) && (editMode || !guiLocked) && (itemCount > 1) && !guiControlExclusiveMode)
{
Vector2 mousePoint = GetMousePosition();
@@ -2362,7 +2387,8 @@ int GuiDropdownBox(Rectangle bounds, const char *text, int *active, bool editMod
for (int i = 0; i < itemCount; i++)
{
// Update item rectangle y position for next item
- itemBounds.y += (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING));
+ if (direction == 0) itemBounds.y += (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING));
+ else itemBounds.y -= (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING));
if (CheckCollisionPointRec(mousePoint, itemBounds))
{
@@ -2406,7 +2432,8 @@ int GuiDropdownBox(Rectangle bounds, const char *text, int *active, bool editMod
for (int i = 0; i < itemCount; i++)
{
// Update item rectangle y position for next item
- itemBounds.y += (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING));
+ if (direction == 0) itemBounds.y += (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING));
+ else itemBounds.y -= (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING));
if (i == itemSelected)
{
@@ -2422,14 +2449,17 @@ int GuiDropdownBox(Rectangle bounds, const char *text, int *active, bool editMod
}
}
- // Draw arrows (using icon if available)
+ if (!GuiGetStyle(DROPDOWNBOX, DROPDOWN_ARROW_HIDDEN))
+ {
+ // Draw arrows (using icon if available)
#if defined(RAYGUI_NO_ICONS)
- GuiDrawText("v", RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - GuiGetStyle(DROPDOWNBOX, ARROW_PADDING), bounds.y + bounds.height/2 - 2, 10, 10 },
- TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3))));
+ GuiDrawText("v", RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - GuiGetStyle(DROPDOWNBOX, ARROW_PADDING), bounds.y + bounds.height/2 - 2, 10, 10 },
+ TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3))));
#else
- GuiDrawText("#120#", RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - GuiGetStyle(DROPDOWNBOX, ARROW_PADDING), bounds.y + bounds.height/2 - 6, 10, 10 },
- TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3)))); // ICON_ARROW_DOWN_FILL
+ GuiDrawText(direction? "#121#" : "#120#", RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - GuiGetStyle(DROPDOWNBOX, ARROW_PADDING), bounds.y + bounds.height/2 - 6, 10, 10 },
+ TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3)))); // ICON_ARROW_DOWN_FILL
#endif
+ }
//--------------------------------------------------------------------
*active = itemSelected;
@@ -2440,7 +2470,7 @@ int GuiDropdownBox(Rectangle bounds, const char *text, int *active, bool editMod
// Text Box control
// NOTE: Returns true on ENTER pressed (useful for data validation)
-int GuiTextBox(Rectangle bounds, char *text, int bufferSize, bool editMode)
+int GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode)
{
#if !defined(RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN)
#define RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN 40 // Frames to wait for autocursor movement
@@ -2456,7 +2486,10 @@ int GuiTextBox(Rectangle bounds, char *text, int bufferSize, bool editMode)
int wrapMode = GuiGetStyle(DEFAULT, TEXT_WRAP_MODE);
Rectangle textBounds = GetTextBounds(TEXTBOX, bounds);
- int textWidth = GetTextWidth(text) - GetTextWidth(text + textBoxCursorIndex);
+ int textLength = (int)strlen(text); // Get current text length
+ int thisCursorIndex = textBoxCursorIndex;
+ if (thisCursorIndex > textLength) thisCursorIndex = textLength;
+ int textWidth = GetTextWidth(text) - GetTextWidth(text + thisCursorIndex);
int textIndexOffset = 0; // Text index offset to start drawing in the box
// Cursor rectangle
@@ -2496,7 +2529,7 @@ int GuiTextBox(Rectangle bounds, char *text, int bufferSize, bool editMode)
if ((state != STATE_DISABLED) && // Control not disabled
!GuiGetStyle(TEXTBOX, TEXT_READONLY) && // TextBox not on read-only mode
!guiLocked && // Gui not locked
- !guiSliderDragging && // No gui slider on dragging
+ !guiControlExclusiveMode && // No gui slider on dragging
(wrapMode == TEXT_WRAP_NONE)) // No wrap mode
{
Vector2 mousePosition = GetMousePosition();
@@ -2505,6 +2538,8 @@ int GuiTextBox(Rectangle bounds, char *text, int bufferSize, bool editMode)
{
state = STATE_PRESSED;
+ if (textBoxCursorIndex > textLength) textBoxCursorIndex = textLength;
+
// If text does not fit in the textbox and current cursor position is out of bounds,
// we add an index offset to text for drawing only what requires depending on cursor
while (textWidth >= textBounds.width)
@@ -2517,19 +2552,16 @@ int GuiTextBox(Rectangle bounds, char *text, int bufferSize, bool editMode)
textWidth = GetTextWidth(text + textIndexOffset) - GetTextWidth(text + textBoxCursorIndex);
}
- int textLength = (int)strlen(text); // Get current text length
int codepoint = GetCharPressed(); // Get Unicode codepoint
if (multiline && IsKeyPressed(KEY_ENTER)) codepoint = (int)'\n';
- if (textBoxCursorIndex > textLength) textBoxCursorIndex = textLength;
-
// Encode codepoint as UTF-8
int codepointSize = 0;
const char *charEncoded = CodepointToUTF8(codepoint, &codepointSize);
// Add codepoint to text, at current cursor position
// NOTE: Make sure we do not overflow buffer size
- if (((multiline && (codepoint == (int)'\n')) || (codepoint >= 32)) && ((textLength + codepointSize) < bufferSize))
+ if (((multiline && (codepoint == (int)'\n')) || (codepoint >= 32)) && ((textLength + codepointSize) < textSize))
{
// Move forward data from cursor position
for (int i = (textLength + codepointSize); i > textBoxCursorIndex; i--) text[i] = text[i - codepointSize];
@@ -2564,6 +2596,7 @@ int GuiTextBox(Rectangle bounds, char *text, int bufferSize, bool editMode)
for (int i = textBoxCursorIndex; i < textLength; i++) text[i] = text[i + nextCodepointSize];
textLength -= codepointSize;
+ if (textBoxCursorIndex > textLength) textBoxCursorIndex = textLength;
// Make sure text last character is EOL
text[textLength] = '\0';
@@ -2583,6 +2616,8 @@ int GuiTextBox(Rectangle bounds, char *text, int bufferSize, bool editMode)
// Move backward text from cursor position
for (int i = (textBoxCursorIndex - prevCodepointSize); i < textLength; i++) text[i] = text[i + prevCodepointSize];
+ // TODO Check: >= cursor+codepointsize and <= length-codepointsize
+
// Prevent cursor index from decrementing past 0
if (textBoxCursorIndex > 0)
{
@@ -2653,7 +2688,7 @@ int GuiTextBox(Rectangle bounds, char *text, int bufferSize, bool editMode)
if (GetMousePosition().x >= (textBounds.x + textEndWidth - glyphWidth/2))
{
mouseCursor.x = textBounds.x + textEndWidth;
- mouseCursorIndex = (int)strlen(text);
+ mouseCursorIndex = textLength;
}
// Place cursor at required index on mouse click
@@ -2685,7 +2720,7 @@ int GuiTextBox(Rectangle bounds, char *text, int bufferSize, bool editMode)
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
{
- textBoxCursorIndex = (int)strlen(text); // GLOBAL: Place cursor index to the end of current text
+ textBoxCursorIndex = textLength; // GLOBAL: Place cursor index to the end of current text
result = 1;
}
}
@@ -2727,7 +2762,7 @@ int GuiTextBox(Rectangle bounds, char *text, int bufferSize, bool editMode)
/*
// Text Box control with multiple lines and word-wrap
// NOTE: This text-box is readonly, no editing supported by default
-bool GuiTextBoxMulti(Rectangle bounds, char *text, int bufferSize, bool editMode)
+bool GuiTextBoxMulti(Rectangle bounds, char *text, int textSize, bool editMode)
{
bool pressed = false;
@@ -2736,7 +2771,7 @@ bool GuiTextBoxMulti(Rectangle bounds, char *text, int bufferSize, bool editMode
GuiSetStyle(DEFAULT, TEXT_ALIGNMENT_VERTICAL, TEXT_ALIGN_TOP);
// TODO: Implement methods to calculate cursor position properly
- pressed = GuiTextBox(bounds, text, bufferSize, editMode);
+ pressed = GuiTextBox(bounds, text, textSize, editMode);
GuiSetStyle(DEFAULT, TEXT_ALIGNMENT_VERTICAL, TEXT_ALIGN_MIDDLE);
GuiSetStyle(DEFAULT, TEXT_WRAP_MODE, TEXT_WRAP_NONE);
@@ -2771,7 +2806,7 @@ int GuiSpinner(Rectangle bounds, const char *text, int *value, int minValue, int
// Update control
//--------------------------------------------------------------------
- if ((state != STATE_DISABLED) && !guiLocked && !guiSliderDragging)
+ if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode)
{
Vector2 mousePoint = GetMousePosition();
@@ -2846,7 +2881,7 @@ int GuiValueBox(Rectangle bounds, const char *text, int *value, int minValue, in
// Update control
//--------------------------------------------------------------------
- if ((state != STATE_DISABLED) && !guiLocked && !guiSliderDragging)
+ if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode)
{
Vector2 mousePoint = GetMousePosition();
@@ -2890,7 +2925,13 @@ int GuiValueBox(Rectangle bounds, const char *text, int *value, int minValue, in
//if (*value > maxValue) *value = maxValue;
//else if (*value < minValue) *value = minValue;
- if (IsKeyPressed(KEY_ENTER) || (!CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) result = 1;
+ if ((IsKeyPressed(KEY_ENTER) || IsKeyPressed(KEY_KP_ENTER)) || (!CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)))
+ {
+ if (*value > maxValue) *value = maxValue;
+ else if (*value < minValue) *value = minValue;
+
+ result = 1;
+ }
}
else
{
@@ -2930,55 +2971,152 @@ int GuiValueBox(Rectangle bounds, const char *text, int *value, int minValue, in
return result;
}
+// Floating point Value Box control, updates input val_str with numbers
+// NOTE: Requires static variables: frameCounter
+int GuiValueBoxFloat(Rectangle bounds, const char *text, char *textValue, float *value, bool editMode)
+{
+ #if !defined(RAYGUI_VALUEBOX_MAX_CHARS)
+ #define RAYGUI_VALUEBOX_MAX_CHARS 32
+ #endif
+
+ int result = 0;
+ GuiState state = guiState;
+
+ //char textValue[RAYGUI_VALUEBOX_MAX_CHARS + 1] = "\0";
+ //sprintf(textValue, "%2.2f", *value);
+
+ Rectangle textBounds = {0};
+ if (text != NULL)
+ {
+ textBounds.width = (float)GetTextWidth(text) + 2;
+ textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE);
+ textBounds.x = bounds.x + bounds.width + GuiGetStyle(VALUEBOX, TEXT_PADDING);
+ textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2;
+ if (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_LEFT) textBounds.x = bounds.x - textBounds.width - GuiGetStyle(VALUEBOX, TEXT_PADDING);
+ }
+
+ // Update control
+ //--------------------------------------------------------------------
+ if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode)
+ {
+ Vector2 mousePoint = GetMousePosition();
+
+ bool valueHasChanged = false;
+
+ if (editMode)
+ {
+ state = STATE_PRESSED;
+
+ int keyCount = (int)strlen(textValue);
+
+ // Only allow keys in range [48..57]
+ if (keyCount < RAYGUI_VALUEBOX_MAX_CHARS)
+ {
+ if (GetTextWidth(textValue) < bounds.width)
+ {
+ int key = GetCharPressed();
+ if (((key >= 48) && (key <= 57)) ||
+ (key == '.') ||
+ ((keyCount == 0) && (key == '+')) || // NOTE: Sign can only be in first position
+ ((keyCount == 0) && (key == '-')))
+ {
+ textValue[keyCount] = (char)key;
+ keyCount++;
+
+ valueHasChanged = true;
+ }
+ }
+ }
+
+ // Pressed backspace
+ if (IsKeyPressed(KEY_BACKSPACE))
+ {
+ if (keyCount > 0)
+ {
+ keyCount--;
+ textValue[keyCount] = '\0';
+ valueHasChanged = true;
+ }
+ }
+
+ if (valueHasChanged) *value = TextToFloat(textValue);
+
+ if ((IsKeyPressed(KEY_ENTER) || IsKeyPressed(KEY_KP_ENTER)) || (!CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) result = 1;
+ }
+ else
+ {
+ if (CheckCollisionPointRec(mousePoint, bounds))
+ {
+ state = STATE_FOCUSED;
+ if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) result = 1;
+ }
+ }
+ }
+ //--------------------------------------------------------------------
+
+ // Draw control
+ //--------------------------------------------------------------------
+ Color baseColor = BLANK;
+ if (state == STATE_PRESSED) baseColor = GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_PRESSED));
+ else if (state == STATE_DISABLED) baseColor = GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_DISABLED));
+
+ GuiDrawRectangle(bounds, GuiGetStyle(VALUEBOX, BORDER_WIDTH), GetColor(GuiGetStyle(VALUEBOX, BORDER + (state*3))), baseColor);
+ GuiDrawText(textValue, GetTextBounds(VALUEBOX, bounds), TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(VALUEBOX, TEXT + (state*3))));
+
+ // Draw cursor
+ if (editMode)
+ {
+ // NOTE: ValueBox internal text is always centered
+ Rectangle cursor = {bounds.x + GetTextWidth(textValue)/2 + bounds.width/2 + 1,
+ bounds.y + 2*GuiGetStyle(VALUEBOX, BORDER_WIDTH), 4,
+ bounds.height - 4*GuiGetStyle(VALUEBOX, BORDER_WIDTH)};
+ GuiDrawRectangle(cursor, 0, BLANK, GetColor(GuiGetStyle(VALUEBOX, BORDER_COLOR_PRESSED)));
+ }
+
+ // Draw text label if provided
+ GuiDrawText(text, textBounds,
+ (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT)? TEXT_ALIGN_LEFT : TEXT_ALIGN_RIGHT,
+ GetColor(GuiGetStyle(LABEL, TEXT + (state*3))));
+ //--------------------------------------------------------------------
+
+ return result;
+}
+
// Slider control with pro parameters
// NOTE: Other GuiSlider*() controls use this one
int GuiSliderPro(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue, int sliderWidth)
{
int result = 0;
- float oldValue = *value;
GuiState state = guiState;
float temp = (maxValue - minValue)/2.0f;
if (value == NULL) value = &temp;
-
- int sliderValue = (int)(((*value - minValue)/(maxValue - minValue))*(bounds.width - 2*GuiGetStyle(SLIDER, BORDER_WIDTH)));
+ float oldValue = *value;
Rectangle slider = { bounds.x, bounds.y + GuiGetStyle(SLIDER, BORDER_WIDTH) + GuiGetStyle(SLIDER, SLIDER_PADDING),
0, bounds.height - 2*GuiGetStyle(SLIDER, BORDER_WIDTH) - 2*GuiGetStyle(SLIDER, SLIDER_PADDING) };
- if (sliderWidth > 0) // Slider
- {
- slider.x += (sliderValue - sliderWidth/2);
- slider.width = (float)sliderWidth;
- }
- else if (sliderWidth == 0) // SliderBar
- {
- slider.x += GuiGetStyle(SLIDER, BORDER_WIDTH);
- slider.width = (float)sliderValue;
- }
-
// Update control
//--------------------------------------------------------------------
if ((state != STATE_DISABLED) && !guiLocked)
{
Vector2 mousePoint = GetMousePosition();
- if (guiSliderDragging) // Keep dragging outside of bounds
+ if (guiControlExclusiveMode) // Allows to keep dragging outside of bounds
{
if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
{
- if (CHECK_BOUNDS_ID(bounds, guiSliderActive))
+ if (CHECK_BOUNDS_ID(bounds, guiControlExclusiveRec))
{
state = STATE_PRESSED;
-
// Get equivalent value and slider position from mousePosition.x
- *value = ((maxValue - minValue)*(mousePoint.x - (float)(bounds.x + sliderWidth/2)))/(float)(bounds.width - sliderWidth) + minValue;
+ *value = (maxValue - minValue)*((mousePoint.x - bounds.x - sliderWidth/2)/(bounds.width-sliderWidth)) + minValue;
}
}
else
{
- guiSliderDragging = false;
- guiSliderActive = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 };
+ guiControlExclusiveMode = false;
+ guiControlExclusiveRec = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 };
}
}
else if (CheckCollisionPointRec(mousePoint, bounds))
@@ -2986,16 +3124,13 @@ int GuiSliderPro(Rectangle bounds, const char *textLeft, const char *textRight,
if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
{
state = STATE_PRESSED;
- guiSliderDragging = true;
- guiSliderActive = bounds; // Store bounds as an identifier when dragging starts
+ guiControlExclusiveMode = true;
+ guiControlExclusiveRec = bounds; // Store bounds as an identifier when dragging starts
if (!CheckCollisionPointRec(mousePoint, slider))
{
// Get equivalent value and slider position from mousePosition.x
- *value = ((maxValue - minValue)*(mousePoint.x - (float)(bounds.x + sliderWidth/2)))/(float)(bounds.width - sliderWidth) + minValue;
-
- if (sliderWidth > 0) slider.x = mousePoint.x - slider.width/2; // Slider
- else if (sliderWidth == 0) slider.width = (float)sliderValue; // SliderBar
+ *value = (maxValue - minValue)*((mousePoint.x - bounds.x - sliderWidth/2)/(bounds.width-sliderWidth)) + minValue;
}
}
else state = STATE_FOCUSED;
@@ -3006,17 +3141,22 @@ int GuiSliderPro(Rectangle bounds, const char *textLeft, const char *textRight,
}
// Control value change check
- if(oldValue == *value) result = 0;
+ if (oldValue == *value) result = 0;
else result = 1;
- // Bar limits check
+ // Slider bar limits check
+ float sliderValue = (((*value - minValue)/(maxValue - minValue))*(bounds.width - sliderWidth - 2*GuiGetStyle(SLIDER, BORDER_WIDTH)));
if (sliderWidth > 0) // Slider
{
+ slider.x += sliderValue;
+ slider.width = (float)sliderWidth;
if (slider.x <= (bounds.x + GuiGetStyle(SLIDER, BORDER_WIDTH))) slider.x = bounds.x + GuiGetStyle(SLIDER, BORDER_WIDTH);
else if ((slider.x + slider.width) >= (bounds.x + bounds.width)) slider.x = bounds.x + bounds.width - slider.width - GuiGetStyle(SLIDER, BORDER_WIDTH);
}
else if (sliderWidth == 0) // SliderBar
{
+ slider.x += GuiGetStyle(SLIDER, BORDER_WIDTH);
+ slider.width = sliderValue;
if (slider.width > bounds.width) slider.width = bounds.width - 2*GuiGetStyle(SLIDER, BORDER_WIDTH);
}
//--------------------------------------------------------------------
@@ -3171,7 +3311,7 @@ int GuiDummyRec(Rectangle bounds, const char *text)
// Update control
//--------------------------------------------------------------------
- if ((state != STATE_DISABLED) && !guiLocked && !guiSliderDragging)
+ if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode)
{
Vector2 mousePoint = GetMousePosition();
@@ -3238,7 +3378,7 @@ int GuiListViewEx(Rectangle bounds, const char **text, int count, int *scrollInd
// Update control
//--------------------------------------------------------------------
- if ((state != STATE_DISABLED) && !guiLocked && !guiSliderDragging)
+ if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode)
{
Vector2 mousePoint = GetMousePosition();
@@ -3291,6 +3431,8 @@ int GuiListViewEx(Rectangle bounds, const char **text, int count, int *scrollInd
// Draw visible items
for (int i = 0; ((i < visibleItems) && (text != NULL)); i++)
{
+ GuiDrawRectangle(itemBounds, GuiGetStyle(LISTVIEW, LIST_ITEMS_BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_NORMAL)), BLANK);
+
if (state == STATE_DISABLED)
{
if ((startIndex + i) == itemSelected) GuiDrawRectangle(itemBounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_DISABLED)), GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_DISABLED)));
@@ -3353,83 +3495,32 @@ int GuiListViewEx(Rectangle bounds, const char **text, int count, int *scrollInd
return result;
}
-// Color Panel control
+// Color Panel control - Color (RGBA) variant.
int GuiColorPanel(Rectangle bounds, const char *text, Color *color)
{
int result = 0;
- GuiState state = guiState;
- Vector2 pickerSelector = { 0 };
-
- const Color colWhite = { 255, 255, 255, 255 };
- const Color colBlack = { 0, 0, 0, 255 };
Vector3 vcolor = { (float)color->r/255.0f, (float)color->g/255.0f, (float)color->b/255.0f };
Vector3 hsv = ConvertRGBtoHSV(vcolor);
+ Vector3 prevHsv = hsv; // workaround to see if GuiColorPanelHSV modifies the hsv.
- pickerSelector.x = bounds.x + (float)hsv.y*bounds.width; // HSV: Saturation
- pickerSelector.y = bounds.y + (1.0f - (float)hsv.z)*bounds.height; // HSV: Value
+ GuiColorPanelHSV(bounds, text, &hsv);
- Vector3 maxHue = { hsv.x, 1.0f, 1.0f };
- Vector3 rgbHue = ConvertHSVtoRGB(maxHue);
- Color maxHueCol = { (unsigned char)(255.0f*rgbHue.x),
- (unsigned char)(255.0f*rgbHue.y),
- (unsigned char)(255.0f*rgbHue.z), 255 };
-
- // Update control
- //--------------------------------------------------------------------
- if ((state != STATE_DISABLED) && !guiLocked && !guiSliderDragging)
+ // Check if the hsv was changed, only then change the color.
+ // This is required, because the Color->HSV->Color conversion has precision errors.
+ // Thus the assignment from HSV to Color should only be made, if the HSV has a new user-entered value.
+ // Otherwise GuiColorPanel would often modify it's color without user input.
+ // TODO: GuiColorPanelHSV could return 1 if the slider was dragged, to simplify this check.
+ if (hsv.x != prevHsv.x || hsv.y != prevHsv.y || hsv.z != prevHsv.z)
{
- Vector2 mousePoint = GetMousePosition();
+ Vector3 rgb = ConvertHSVtoRGB(hsv);
- if (CheckCollisionPointRec(mousePoint, bounds))
- {
- if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
- {
- state = STATE_PRESSED;
- pickerSelector = mousePoint;
-
- // Calculate color from picker
- Vector2 colorPick = { pickerSelector.x - bounds.x, pickerSelector.y - bounds.y };
-
- colorPick.x /= (float)bounds.width; // Get normalized value on x
- colorPick.y /= (float)bounds.height; // Get normalized value on y
-
- hsv.y = colorPick.x;
- hsv.z = 1.0f - colorPick.y;
-
- Vector3 rgb = ConvertHSVtoRGB(hsv);
-
- // NOTE: Vector3ToColor() only available on raylib 1.8.1
- *color = RAYGUI_CLITERAL(Color){ (unsigned char)(255.0f*rgb.x),
- (unsigned char)(255.0f*rgb.y),
- (unsigned char)(255.0f*rgb.z),
- (unsigned char)(255.0f*(float)color->a/255.0f) };
-
- }
- else state = STATE_FOCUSED;
- }
+ // NOTE: Vector3ToColor() only available on raylib 1.8.1
+ *color = RAYGUI_CLITERAL(Color){ (unsigned char)(255.0f*rgb.x),
+ (unsigned char)(255.0f*rgb.y),
+ (unsigned char)(255.0f*rgb.z),
+ color->a };
}
- //--------------------------------------------------------------------
-
- // Draw control
- //--------------------------------------------------------------------
- if (state != STATE_DISABLED)
- {
- DrawRectangleGradientEx(bounds, Fade(colWhite, guiAlpha), Fade(colWhite, guiAlpha), Fade(maxHueCol, guiAlpha), Fade(maxHueCol, guiAlpha));
- DrawRectangleGradientEx(bounds, Fade(colBlack, 0), Fade(colBlack, guiAlpha), Fade(colBlack, guiAlpha), Fade(colBlack, 0));
-
- // Draw color picker: selector
- Rectangle selector = { pickerSelector.x - GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE)/2, pickerSelector.y - GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE)/2, (float)GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE), (float)GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE) };
- GuiDrawRectangle(selector, 0, BLANK, colWhite);
- }
- else
- {
- DrawRectangleGradientEx(bounds, Fade(Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.1f), guiAlpha), Fade(Fade(colBlack, 0.6f), guiAlpha), Fade(Fade(colBlack, 0.6f), guiAlpha), Fade(Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), 0.6f), guiAlpha));
- }
-
- GuiDrawRectangle(bounds, GuiGetStyle(COLORPICKER, BORDER_WIDTH), GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)), BLANK);
- //--------------------------------------------------------------------
-
return result;
}
@@ -3451,11 +3542,11 @@ int GuiColorBarAlpha(Rectangle bounds, const char *text, float *alpha)
{
Vector2 mousePoint = GetMousePosition();
- if (guiSliderDragging) // Keep dragging outside of bounds
+ if (guiControlExclusiveMode) // Allows to keep dragging outside of bounds
{
if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
{
- if (CHECK_BOUNDS_ID(bounds, guiSliderActive))
+ if (CHECK_BOUNDS_ID(bounds, guiControlExclusiveRec))
{
state = STATE_PRESSED;
@@ -3466,8 +3557,8 @@ int GuiColorBarAlpha(Rectangle bounds, const char *text, float *alpha)
}
else
{
- guiSliderDragging = false;
- guiSliderActive = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 };
+ guiControlExclusiveMode = false;
+ guiControlExclusiveRec = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 };
}
}
else if (CheckCollisionPointRec(mousePoint, bounds) || CheckCollisionPointRec(mousePoint, selector))
@@ -3475,8 +3566,8 @@ int GuiColorBarAlpha(Rectangle bounds, const char *text, float *alpha)
if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
{
state = STATE_PRESSED;
- guiSliderDragging = true;
- guiSliderActive = bounds; // Store bounds as an identifier when dragging starts
+ guiControlExclusiveMode = true;
+ guiControlExclusiveRec = bounds; // Store bounds as an identifier when dragging starts
*alpha = (mousePoint.x - bounds.x)/bounds.width;
if (*alpha <= 0.0f) *alpha = 0.0f;
@@ -3537,11 +3628,11 @@ int GuiColorBarHue(Rectangle bounds, const char *text, float *hue)
{
Vector2 mousePoint = GetMousePosition();
- if (guiSliderDragging) // Keep dragging outside of bounds
+ if (guiControlExclusiveMode) // Allows to keep dragging outside of bounds
{
if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
{
- if (CHECK_BOUNDS_ID(bounds, guiSliderActive))
+ if (CHECK_BOUNDS_ID(bounds, guiControlExclusiveRec))
{
state = STATE_PRESSED;
@@ -3552,8 +3643,8 @@ int GuiColorBarHue(Rectangle bounds, const char *text, float *hue)
}
else
{
- guiSliderDragging = false;
- guiSliderActive = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 };
+ guiControlExclusiveMode = false;
+ guiControlExclusiveRec = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 };
}
}
else if (CheckCollisionPointRec(mousePoint, bounds) || CheckCollisionPointRec(mousePoint, selector))
@@ -3561,8 +3652,8 @@ int GuiColorBarHue(Rectangle bounds, const char *text, float *hue)
if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
{
state = STATE_PRESSED;
- guiSliderDragging = true;
- guiSliderActive = bounds; // Store bounds as an identifier when dragging starts
+ guiControlExclusiveMode = true;
+ guiControlExclusiveRec = bounds; // Store bounds as an identifier when dragging starts
*hue = (mousePoint.y - bounds.y)*360/bounds.height;
if (*hue <= 0.0f) *hue = 0.0f;
@@ -3615,6 +3706,7 @@ int GuiColorBarHue(Rectangle bounds, const char *text, float *hue)
// float GuiColorBarAlpha(Rectangle bounds, float alpha)
// float GuiColorBarHue(Rectangle bounds, float value)
// NOTE: bounds define GuiColorPanel() size
+// NOTE: this picker converts RGB to HSV, which can cause the Hue control to jump. If you have this problem, consider using the HSV variant instead
int GuiColorPicker(Rectangle bounds, const char *text, Color *color)
{
int result = 0;
@@ -3627,6 +3719,7 @@ int GuiColorPicker(Rectangle bounds, const char *text, Color *color)
Rectangle boundsHue = { (float)bounds.x + bounds.width + GuiGetStyle(COLORPICKER, HUEBAR_PADDING), (float)bounds.y, (float)GuiGetStyle(COLORPICKER, HUEBAR_WIDTH), (float)bounds.height };
//Rectangle boundsAlpha = { bounds.x, bounds.y + bounds.height + GuiGetStyle(COLORPICKER, BARS_PADDING), bounds.width, GuiGetStyle(COLORPICKER, BARS_THICK) };
+ // NOTE: this conversion can cause low hue-resolution, if the r, g and b value are very similar, which causes the hue bar to shift around when only the GuiColorPanel is used.
Vector3 hsv = ConvertRGBtoHSV(RAYGUI_CLITERAL(Vector3){ (*color).r/255.0f, (*color).g/255.0f, (*color).b/255.0f });
GuiColorBarHue(boundsHue, NULL, &hsv.x);
@@ -3668,8 +3761,7 @@ int GuiColorPickerHSV(Rectangle bounds, const char *text, Vector3 *colorHsv)
return result;
}
-// Color Panel control, returns HSV color value in *colorHsv.
-// Used by GuiColorPickerHSV()
+// Color Panel control - HSV variant
int GuiColorPanelHSV(Rectangle bounds, const char *text, Vector3 *colorHsv)
{
int result = 0;
@@ -3690,15 +3782,47 @@ int GuiColorPanelHSV(Rectangle bounds, const char *text, Vector3 *colorHsv)
// Update control
//--------------------------------------------------------------------
- if ((state != STATE_DISABLED) && !guiLocked && !guiSliderDragging)
+ if ((state != STATE_DISABLED) && !guiLocked)
{
Vector2 mousePoint = GetMousePosition();
- if (CheckCollisionPointRec(mousePoint, bounds))
+ if (guiControlExclusiveMode) // Allows to keep dragging outside of bounds
+ {
+ if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
+ {
+ if (CHECK_BOUNDS_ID(bounds, guiControlExclusiveRec))
+ {
+ pickerSelector = mousePoint;
+
+ if (pickerSelector.x < bounds.x) pickerSelector.x = bounds.x;
+ if (pickerSelector.x > bounds.x + bounds.width) pickerSelector.x = bounds.x + bounds.width;
+ if (pickerSelector.y < bounds.y) pickerSelector.y = bounds.y;
+ if (pickerSelector.y > bounds.y + bounds.height) pickerSelector.y = bounds.y + bounds.height;
+
+ // Calculate color from picker
+ Vector2 colorPick = { pickerSelector.x - bounds.x, pickerSelector.y - bounds.y };
+
+ colorPick.x /= (float)bounds.width; // Get normalized value on x
+ colorPick.y /= (float)bounds.height; // Get normalized value on y
+
+ colorHsv->y = colorPick.x;
+ colorHsv->z = 1.0f - colorPick.y;
+
+ }
+ }
+ else
+ {
+ guiControlExclusiveMode = false;
+ guiControlExclusiveRec = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 };
+ }
+ }
+ else if (CheckCollisionPointRec(mousePoint, bounds))
{
if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
{
state = STATE_PRESSED;
+ guiControlExclusiveMode = true;
+ guiControlExclusiveRec = bounds;
pickerSelector = mousePoint;
// Calculate color from picker
@@ -3760,9 +3884,9 @@ int GuiMessageBox(Rectangle bounds, const char *title, const char *message, cons
int textWidth = GetTextWidth(message) + 2;
Rectangle textBounds = { 0 };
- textBounds.x = bounds.x + bounds.width/2 - textWidth/2;
+ textBounds.x = bounds.x + RAYGUI_MESSAGEBOX_BUTTON_PADDING;
textBounds.y = bounds.y + RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT + RAYGUI_MESSAGEBOX_BUTTON_PADDING;
- textBounds.width = (float)textWidth;
+ textBounds.width = bounds.width - RAYGUI_MESSAGEBOX_BUTTON_PADDING*2;
textBounds.height = bounds.height - RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - 3*RAYGUI_MESSAGEBOX_BUTTON_PADDING - RAYGUI_MESSAGEBOX_BUTTON_HEIGHT;
// Draw control
@@ -3905,7 +4029,7 @@ int GuiGrid(Rectangle bounds, const char *text, float spacing, int subdivs, Vect
// Update control
//--------------------------------------------------------------------
- if ((state != STATE_DISABLED) && !guiLocked && !guiSliderDragging)
+ if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode)
{
if (CheckCollisionPointRec(mousePoint, bounds))
{
@@ -3925,14 +4049,14 @@ int GuiGrid(Rectangle bounds, const char *text, float spacing, int subdivs, Vect
// Draw vertical grid lines
for (int i = 0; i < linesV; i++)
{
- Rectangle lineV = { bounds.x + spacing*i/subdivs, bounds.y, 1, bounds.height };
+ Rectangle lineV = { bounds.x + spacing*i/subdivs, bounds.y, 1, bounds.height + 1 };
GuiDrawRectangle(lineV, 0, BLANK, ((i%subdivs) == 0)? GuiFade(GetColor(color), RAYGUI_GRID_ALPHA*4) : GuiFade(GetColor(color), RAYGUI_GRID_ALPHA));
}
// Draw horizontal grid lines
for (int i = 0; i < linesH; i++)
{
- Rectangle lineH = { bounds.x, bounds.y + spacing*i/subdivs, bounds.width, 1 };
+ Rectangle lineH = { bounds.x, bounds.y + spacing*i/subdivs, bounds.width + 1, 1 };
GuiDrawRectangle(lineH, 0, BLANK, ((i%subdivs) == 0)? GuiFade(GetColor(color), RAYGUI_GRID_ALPHA*4) : GuiFade(GetColor(color), RAYGUI_GRID_ALPHA));
}
}
@@ -3954,7 +4078,6 @@ void GuiDisableTooltip(void) { guiTooltip = false; }
// Set tooltip string
void GuiSetTooltip(const char *tooltip) { guiTooltipPtr = tooltip; }
-
//----------------------------------------------------------------------------------
// Styles loading functions
//----------------------------------------------------------------------------------
@@ -3967,6 +4090,7 @@ void GuiLoadStyle(const char *fileName)
#define MAX_LINE_BUFFER_SIZE 256
bool tryBinary = false;
+ if (!guiStyleLoaded) GuiLoadStyleDefault();
// Try reading the files as text file first
FILE *rgsFile = fopen(fileName, "rt");
@@ -4600,7 +4724,7 @@ static int GetTextWidth(const char *text)
}
}
- if (textIconOffset > 0) textSize.x += (RAYGUI_ICON_SIZE - ICON_TEXT_PADDING);
+ if (textIconOffset > 0) textSize.x += (RAYGUI_ICON_SIZE + ICON_TEXT_PADDING);
}
return (int)textSize.x;
@@ -4773,6 +4897,7 @@ static void GuiDrawText(const char *text, Rectangle textBounds, int alignment, C
// Get text position depending on alignment and iconId
//---------------------------------------------------------------------------------
Vector2 textBoundsPosition = { textBounds.x, textBounds.y };
+ float textBoundsWidthOffset = 0.0f;
// NOTE: We get text size after icon has been processed
// WARNING: GetTextWidth() also processes text icon to get width! -> Really needed?
@@ -4798,6 +4923,8 @@ static void GuiDrawText(const char *text, Rectangle textBounds, int alignment, C
default: break;
}
+ if (textSizeX > textBounds.width && (lines[i] != NULL) && (lines[i][0] != '\0')) textBoundsPosition.x = textBounds.x;
+
switch (alignmentVertical)
{
// Only valid in case of wordWrap = 0;
@@ -4820,7 +4947,8 @@ static void GuiDrawText(const char *text, Rectangle textBounds, int alignment, C
{
// NOTE: We consider icon height, probably different than text size
GuiDrawIcon(iconId, (int)textBoundsPosition.x, (int)(textBounds.y + textBounds.height/2 - RAYGUI_ICON_SIZE*guiIconScale/2 + TEXT_VALIGN_PIXEL_OFFSET(textBounds.height)), guiIconScale, tint);
- textBoundsPosition.x += (RAYGUI_ICON_SIZE*guiIconScale + ICON_TEXT_PADDING);
+ textBoundsPosition.x += (float)(RAYGUI_ICON_SIZE*guiIconScale + ICON_TEXT_PADDING);
+ textBoundsWidthOffset = (float)(RAYGUI_ICON_SIZE*guiIconScale + ICON_TEXT_PADDING);
}
#endif
// Get size in bytes of text,
@@ -4829,9 +4957,15 @@ static void GuiDrawText(const char *text, Rectangle textBounds, int alignment, C
for (int c = 0; (lines[i][c] != '\0') && (lines[i][c] != '\n') && (lines[i][c] != '\r'); c++, lineSize++){ }
float scaleFactor = (float)GuiGetStyle(DEFAULT, TEXT_SIZE)/guiFont.baseSize;
+ int lastSpaceIndex = 0;
+ bool tempWrapCharMode = false;
+
int textOffsetY = 0;
float textOffsetX = 0.0f;
float glyphWidth = 0;
+
+ int ellipsisWidth = GetTextWidth("...");
+ bool textOverflow = false;
for (int c = 0, codepointSize = 0; c < lineSize; c += codepointSize)
{
int codepoint = GetCodepointNext(&lines[i][c], &codepointSize);
@@ -4839,36 +4973,51 @@ static void GuiDrawText(const char *text, Rectangle textBounds, int alignment, C
// NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)
// but we need to draw all of the bad bytes using the '?' symbol moving one byte
- if (codepoint == 0x3f) codepointSize = 1; // TODO: Review not recognized codepoints size
+ if (codepoint == 0x3f) codepointSize = 1; // TODO: Review not recognized codepoints size
- // Wrap mode text measuring to space to validate if it can be drawn or
- // a new line is required
+ // Get glyph width to check if it goes out of bounds
+ if (guiFont.glyphs[index].advanceX == 0) glyphWidth = ((float)guiFont.recs[index].width*scaleFactor);
+ else glyphWidth = (float)guiFont.glyphs[index].advanceX*scaleFactor;
+
+ // Wrap mode text measuring, to validate if
+ // it can be drawn or a new line is required
if (wrapMode == TEXT_WRAP_CHAR)
{
- // Get glyph width to check if it goes out of bounds
- if (guiFont.glyphs[index].advanceX == 0) glyphWidth = ((float)guiFont.recs[index].width*scaleFactor);
- else glyphWidth = (float)guiFont.glyphs[index].advanceX*scaleFactor;
-
// Jump to next line if current character reach end of the box limits
- if ((textOffsetX + glyphWidth) > textBounds.width)
+ if ((textOffsetX + glyphWidth) > textBounds.width - textBoundsWidthOffset)
{
textOffsetX = 0.0f;
textOffsetY += GuiGetStyle(DEFAULT, TEXT_LINE_SPACING);
+
+ if (tempWrapCharMode) // Wrap at char level when too long words
+ {
+ wrapMode = TEXT_WRAP_WORD;
+ tempWrapCharMode = false;
+ }
}
}
else if (wrapMode == TEXT_WRAP_WORD)
{
+ if (codepoint == 32) lastSpaceIndex = c;
+
// Get width to next space in line
int nextSpaceIndex = 0;
float nextSpaceWidth = GetNextSpaceWidth(lines[i] + c, &nextSpaceIndex);
- if ((textOffsetX + nextSpaceWidth) > textBounds.width)
+ int nextSpaceIndex2 = 0;
+ float nextWordSize = GetNextSpaceWidth(lines[i] + lastSpaceIndex + 1, &nextSpaceIndex2);
+
+ if (nextWordSize > textBounds.width - textBoundsWidthOffset)
+ {
+ // Considering the case the next word is longer than bounds
+ tempWrapCharMode = true;
+ wrapMode = TEXT_WRAP_CHAR;
+ }
+ else if ((textOffsetX + nextSpaceWidth) > textBounds.width - textBoundsWidthOffset)
{
textOffsetX = 0.0f;
textOffsetY += GuiGetStyle(DEFAULT, TEXT_LINE_SPACING);
}
-
- // TODO: Consider case: (nextSpaceWidth >= textBounds.width)
}
if (codepoint == '\n') break; // WARNING: Lines are already processed manually, no need to keep drawing after this codepoint
@@ -4881,7 +5030,23 @@ static void GuiDrawText(const char *text, Rectangle textBounds, int alignment, C
if (wrapMode == TEXT_WRAP_NONE)
{
// Draw only required text glyphs fitting the textBounds.width
- if (textOffsetX <= (textBounds.width - glyphWidth))
+ if (textSizeX > textBounds.width)
+ {
+ if (textOffsetX <= (textBounds.width - glyphWidth - textBoundsWidthOffset - ellipsisWidth))
+ {
+ DrawTextCodepoint(guiFont, codepoint, RAYGUI_CLITERAL(Vector2){ textBoundsPosition.x + textOffsetX, textBoundsPosition.y + textOffsetY }, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), GuiFade(tint, guiAlpha));
+ }
+ else if (!textOverflow)
+ {
+ textOverflow = true;
+
+ for (int j = 0; j < ellipsisWidth; j += ellipsisWidth/3)
+ {
+ DrawTextCodepoint(guiFont, '.', RAYGUI_CLITERAL(Vector2){ textBoundsPosition.x + textOffsetX + j, textBoundsPosition.y + textOffsetY }, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), GuiFade(tint, guiAlpha));
+ }
+ }
+ }
+ else
{
DrawTextCodepoint(guiFont, codepoint, RAYGUI_CLITERAL(Vector2){ textBoundsPosition.x + textOffsetX, textBoundsPosition.y + textOffsetY }, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), GuiFade(tint, guiAlpha));
}
@@ -4937,7 +5102,7 @@ static void GuiDrawRectangle(Rectangle rec, int borderWidth, Color borderColor,
// Draw tooltip using control bounds
static void GuiTooltip(Rectangle controlRec)
{
- if (!guiLocked && guiTooltip && (guiTooltipPtr != NULL) && !guiSliderDragging)
+ if (!guiLocked && guiTooltip && (guiTooltipPtr != NULL) && !guiControlExclusiveMode)
{
Vector2 textSize = MeasureTextEx(GuiGetFont(), guiTooltipPtr, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), (float)GuiGetStyle(DEFAULT, TEXT_SPACING));
@@ -5003,7 +5168,7 @@ static const char **GuiTextSplit(const char *text, char delimiter, int *count, i
buffer[i] = '\0'; // Set an end of string at this point
counter++;
- if (counter == RAYGUI_TEXTSPLIT_MAX_ITEMS) break;
+ if (counter > RAYGUI_TEXTSPLIT_MAX_ITEMS) break;
}
}
@@ -5163,8 +5328,11 @@ static int GuiScrollBar(Rectangle bounds, int value, int minValue, int maxValue)
if (value > maxValue) value = maxValue;
if (value < minValue) value = minValue;
- const int valueRange = maxValue - minValue;
+ int valueRange = maxValue - minValue;
+ if (valueRange <= 0) valueRange = 1;
+
int sliderSize = GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE);
+ if (sliderSize < 1) sliderSize = 1; // TODO: Consider a minimum slider size
// Calculate rectangles for all of the components
arrowUpLeft = RAYGUI_CLITERAL(Rectangle){
@@ -5205,13 +5373,13 @@ static int GuiScrollBar(Rectangle bounds, int value, int minValue, int maxValue)
{
Vector2 mousePoint = GetMousePosition();
- if (guiSliderDragging) // Keep dragging outside of bounds
+ if (guiControlExclusiveMode) // Allows to keep dragging outside of bounds
{
if (IsMouseButtonDown(MOUSE_LEFT_BUTTON) &&
!CheckCollisionPointRec(mousePoint, arrowUpLeft) &&
!CheckCollisionPointRec(mousePoint, arrowDownRight))
{
- if (CHECK_BOUNDS_ID(bounds, guiSliderActive))
+ if (CHECK_BOUNDS_ID(bounds, guiControlExclusiveRec))
{
state = STATE_PRESSED;
@@ -5221,8 +5389,8 @@ static int GuiScrollBar(Rectangle bounds, int value, int minValue, int maxValue)
}
else
{
- guiSliderDragging = false;
- guiSliderActive = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 };
+ guiControlExclusiveMode = false;
+ guiControlExclusiveRec = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 };
}
}
else if (CheckCollisionPointRec(mousePoint, bounds))
@@ -5236,8 +5404,8 @@ static int GuiScrollBar(Rectangle bounds, int value, int minValue, int maxValue)
// Handle mouse button down
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
{
- guiSliderDragging = true;
- guiSliderActive = bounds; // Store bounds as an identifier when dragging starts
+ guiControlExclusiveMode = true;
+ guiControlExclusiveRec = bounds; // Store bounds as an identifier when dragging starts
// Check arrows click
if (CheckCollisionPointRec(mousePoint, arrowUpLeft)) value -= valueRange/GuiGetStyle(SCROLLBAR, SCROLL_SPEED);
@@ -5437,6 +5605,37 @@ static int TextToInteger(const char *text)
return value*sign;
}
+// Get float value from text
+// NOTE: This function replaces atof() [stdlib.h]
+// WARNING: Only '.' character is understood as decimal point
+static float TextToFloat(const char *text)
+{
+ float value = 0.0f;
+ float sign = 1.0f;
+
+ if ((text[0] == '+') || (text[0] == '-'))
+ {
+ if (text[0] == '-') sign = -1.0f;
+ text++;
+ }
+
+ int i = 0;
+ for (; ((text[i] >= '0') && (text[i] <= '9')); i++) value = value*10.0f + (float)(text[i] - '0');
+
+ if (text[i++] != '.') value *= sign;
+ else
+ {
+ float divisor = 10.0f;
+ for (; ((text[i] >= '0') && (text[i] <= '9')); i++)
+ {
+ value += ((float)(text[i] - '0'))/divisor;
+ divisor = divisor*10.0f;
+ }
+ }
+
+ return value;
+}
+
// Encode codepoint into UTF-8 text (char array size returned as parameter)
static const char *CodepointToUTF8(int codepoint, int *byteSize)
{
@@ -5490,21 +5689,21 @@ static int GetCodepointNext(const char *text, int *codepointSize)
if (0xf0 == (0xf8 & ptr[0]))
{
// 4 byte UTF-8 codepoint
- if(((ptr[1] & 0xC0) ^ 0x80) || ((ptr[2] & 0xC0) ^ 0x80) || ((ptr[3] & 0xC0) ^ 0x80)) { return codepoint; } //10xxxxxx checks
+ if (((ptr[1] & 0xC0) ^ 0x80) || ((ptr[2] & 0xC0) ^ 0x80) || ((ptr[3] & 0xC0) ^ 0x80)) { return codepoint; } //10xxxxxx checks
codepoint = ((0x07 & ptr[0]) << 18) | ((0x3f & ptr[1]) << 12) | ((0x3f & ptr[2]) << 6) | (0x3f & ptr[3]);
*codepointSize = 4;
}
else if (0xe0 == (0xf0 & ptr[0]))
{
// 3 byte UTF-8 codepoint */
- if(((ptr[1] & 0xC0) ^ 0x80) || ((ptr[2] & 0xC0) ^ 0x80)) { return codepoint; } //10xxxxxx checks
+ if (((ptr[1] & 0xC0) ^ 0x80) || ((ptr[2] & 0xC0) ^ 0x80)) { return codepoint; } //10xxxxxx checks
codepoint = ((0x0f & ptr[0]) << 12) | ((0x3f & ptr[1]) << 6) | (0x3f & ptr[2]);
*codepointSize = 3;
}
else if (0xc0 == (0xe0 & ptr[0]))
{
// 2 byte UTF-8 codepoint
- if((ptr[1] & 0xC0) ^ 0x80) { return codepoint; } //10xxxxxx checks
+ if ((ptr[1] & 0xC0) ^ 0x80) { return codepoint; } //10xxxxxx checks
codepoint = ((0x1f & ptr[0]) << 6) | (0x3f & ptr[1]);
*codepointSize = 2;
}
@@ -5515,9 +5714,8 @@ static int GetCodepointNext(const char *text, int *codepointSize)
*codepointSize = 1;
}
-
return codepoint;
}
#endif // RAYGUI_STANDALONE
-#endif // RAYGUI_IMPLEMENTATION
+#endif // RAYGUI_IMPLEMENTATION
\ No newline at end of file
diff --git a/examples/shapes/shapes_bouncing_ball.c b/examples/shapes/shapes_bouncing_ball.c
index 7a3068163..df0c37c1c 100644
--- a/examples/shapes/shapes_bouncing_ball.c
+++ b/examples/shapes/shapes_bouncing_ball.c
@@ -62,7 +62,7 @@ int main(void)
ClearBackground(RAYWHITE);
DrawCircleV(ballPosition, (float)ballRadius, MAROON);
- //DrawText("PRESS SPACE to PAUSE BALL MOVEMENT", 10, GetScreenHeight() - 25, 20, LIGHTGRAY);
+ DrawText("PRESS SPACE to PAUSE BALL MOVEMENT", 10, GetScreenHeight() - 25, 20, LIGHTGRAY);
// On pause, we draw a blinking message
if (pause && ((framesCounter/30)%2)) DrawText("PAUSED", 350, 200, 30, GRAY);
diff --git a/examples/text/text_input_box.c b/examples/text/text_input_box.c
index eeb338f1f..c53057711 100644
--- a/examples/text/text_input_box.c
+++ b/examples/text/text_input_box.c
@@ -35,7 +35,7 @@ int main(void)
int framesCounter = 0;
- SetTargetFPS(10); // Set our game to run at 10 frames-per-second
+ SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
// Main game loop
diff --git a/examples/text/text_writing_anim.c b/examples/text/text_writing_anim.c
index 1e7cd569f..8e2820fc9 100644
--- a/examples/text/text_writing_anim.c
+++ b/examples/text/text_writing_anim.c
@@ -52,7 +52,7 @@ int main(void)
DrawText(TextSubtext(message, 0, framesCounter/10), 210, 160, 20, MAROON);
DrawText("PRESS [ENTER] to RESTART!", 240, 260, 20, LIGHTGRAY);
- DrawText("PRESS [SPACE] to SPEED UP!", 239, 300, 20, LIGHTGRAY);
+ DrawText("HOLD [SPACE] to SPEED UP!", 239, 300, 20, LIGHTGRAY);
EndDrawing();
//----------------------------------------------------------------------------------
diff --git a/examples/textures/textures_blend_modes.c b/examples/textures/textures_blend_modes.c
index 660aa57a7..d97432cb2 100644
--- a/examples/textures/textures_blend_modes.c
+++ b/examples/textures/textures_blend_modes.c
@@ -43,6 +43,9 @@ int main(void)
const int blendCountMax = 4;
BlendMode blendMode = 0;
+ SetTargetFPS(60); // Set our game to run at 60 frames-per-second
+ //---------------------------------------------------------------------------------------
+
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
diff --git a/examples/textures/textures_image_rotate.c b/examples/textures/textures_image_rotate.c
index 51724e037..94c42034b 100644
--- a/examples/textures/textures_image_rotate.c
+++ b/examples/textures/textures_image_rotate.c
@@ -43,6 +43,8 @@ int main(void)
textures[2] = LoadTextureFromImage(imageNeg90);
int currentTexture = 0;
+
+ SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//---------------------------------------------------------------------------------------
// Main game loop
diff --git a/examples/textures/textures_logo_raylib.c b/examples/textures/textures_logo_raylib.c
index f170dab48..35baa1223 100644
--- a/examples/textures/textures_logo_raylib.c
+++ b/examples/textures/textures_logo_raylib.c
@@ -27,6 +27,8 @@ int main(void)
// NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required)
Texture2D texture = LoadTexture("resources/raylib_logo.png"); // Texture loading
+
+ SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//---------------------------------------------------------------------------------------
// Main game loop
diff --git a/examples/textures/textures_raw_data.c b/examples/textures/textures_raw_data.c
index 38229f1ba..6fb41b143 100644
--- a/examples/textures/textures_raw_data.c
+++ b/examples/textures/textures_raw_data.c
@@ -63,6 +63,8 @@ int main(void)
Texture2D checked = LoadTextureFromImage(checkedIm);
UnloadImage(checkedIm); // Unload CPU (RAM) image data (pixels)
+
+ SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//---------------------------------------------------------------------------------------
// Main game loop
diff --git a/examples/textures/textures_sprite_explosion.c b/examples/textures/textures_sprite_explosion.c
index 06b4f1dad..a65426cb6 100644
--- a/examples/textures/textures_sprite_explosion.c
+++ b/examples/textures/textures_sprite_explosion.c
@@ -48,8 +48,8 @@ int main(void)
bool active = false;
int framesCounter = 0;
- SetTargetFPS(120);
- //--------------------------------------------------------------------------------------
+ SetTargetFPS(60); // Set our game to run at 60 frames-per-second
+ //---------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
diff --git a/examples/textures/textures_to_image.c b/examples/textures/textures_to_image.c
index 2d09623eb..e1d88c4cd 100644
--- a/examples/textures/textures_to_image.c
+++ b/examples/textures/textures_to_image.c
@@ -38,6 +38,8 @@ int main(void)
texture = LoadTextureFromImage(image); // Recreate texture from retrieved image data (RAM -> VRAM)
UnloadImage(image); // Unload retrieved image data from CPU memory (RAM)
+
+ SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//---------------------------------------------------------------------------------------
// Main game loop
diff --git a/parser/output/raylib_api.json b/parser/output/raylib_api.json
index f149d628f..c4ce91e87 100644
--- a/parser/output/raylib_api.json
+++ b/parser/output/raylib_api.json
@@ -5485,11 +5485,11 @@
},
{
"type": "Color",
- "name": "color1"
+ "name": "inner"
},
{
"type": "Color",
- "name": "color2"
+ "name": "outer"
}
]
},
@@ -5785,11 +5785,11 @@
},
{
"type": "Color",
- "name": "color1"
+ "name": "top"
},
{
"type": "Color",
- "name": "color2"
+ "name": "bottom"
}
]
},
@@ -5816,11 +5816,11 @@
},
{
"type": "Color",
- "name": "color1"
+ "name": "left"
},
{
"type": "Color",
- "name": "color2"
+ "name": "right"
}
]
},
@@ -5835,19 +5835,19 @@
},
{
"type": "Color",
- "name": "col1"
+ "name": "topLeft"
},
{
"type": "Color",
- "name": "col2"
+ "name": "bottomLeft"
},
{
"type": "Color",
- "name": "col3"
+ "name": "topRight"
},
{
"type": "Color",
- "name": "col4"
+ "name": "bottomRight"
}
]
},
diff --git a/parser/output/raylib_api.lua b/parser/output/raylib_api.lua
index 7c00fff33..3a9e2f04f 100644
--- a/parser/output/raylib_api.lua
+++ b/parser/output/raylib_api.lua
@@ -4697,8 +4697,8 @@ return {
{type = "int", name = "centerX"},
{type = "int", name = "centerY"},
{type = "float", name = "radius"},
- {type = "Color", name = "color1"},
- {type = "Color", name = "color2"}
+ {type = "Color", name = "inner"},
+ {type = "Color", name = "outer"}
}
},
{
@@ -4835,8 +4835,8 @@ return {
{type = "int", name = "posY"},
{type = "int", name = "width"},
{type = "int", name = "height"},
- {type = "Color", name = "color1"},
- {type = "Color", name = "color2"}
+ {type = "Color", name = "top"},
+ {type = "Color", name = "bottom"}
}
},
{
@@ -4848,8 +4848,8 @@ return {
{type = "int", name = "posY"},
{type = "int", name = "width"},
{type = "int", name = "height"},
- {type = "Color", name = "color1"},
- {type = "Color", name = "color2"}
+ {type = "Color", name = "left"},
+ {type = "Color", name = "right"}
}
},
{
@@ -4858,10 +4858,10 @@ return {
returnType = "void",
params = {
{type = "Rectangle", name = "rec"},
- {type = "Color", name = "col1"},
- {type = "Color", name = "col2"},
- {type = "Color", name = "col3"},
- {type = "Color", name = "col4"}
+ {type = "Color", name = "topLeft"},
+ {type = "Color", name = "bottomLeft"},
+ {type = "Color", name = "topRight"},
+ {type = "Color", name = "bottomRight"}
}
},
{
diff --git a/parser/output/raylib_api.txt b/parser/output/raylib_api.txt
index 73170c860..afa9b525d 100644
--- a/parser/output/raylib_api.txt
+++ b/parser/output/raylib_api.txt
@@ -2176,8 +2176,8 @@ Function 217: DrawCircleGradient() (5 input parameters)
Param[1]: centerX (type: int)
Param[2]: centerY (type: int)
Param[3]: radius (type: float)
- Param[4]: color1 (type: Color)
- Param[5]: color2 (type: Color)
+ Param[4]: inner (type: Color)
+ Param[5]: outer (type: Color)
Function 218: DrawCircleV() (3 input parameters)
Name: DrawCircleV
Return type: void
@@ -2278,8 +2278,8 @@ Function 229: DrawRectangleGradientV() (6 input parameters)
Param[2]: posY (type: int)
Param[3]: width (type: int)
Param[4]: height (type: int)
- Param[5]: color1 (type: Color)
- Param[6]: color2 (type: Color)
+ Param[5]: top (type: Color)
+ Param[6]: bottom (type: Color)
Function 230: DrawRectangleGradientH() (6 input parameters)
Name: DrawRectangleGradientH
Return type: void
@@ -2288,17 +2288,17 @@ Function 230: DrawRectangleGradientH() (6 input parameters)
Param[2]: posY (type: int)
Param[3]: width (type: int)
Param[4]: height (type: int)
- Param[5]: color1 (type: Color)
- Param[6]: color2 (type: Color)
+ Param[5]: left (type: Color)
+ Param[6]: right (type: Color)
Function 231: DrawRectangleGradientEx() (5 input parameters)
Name: DrawRectangleGradientEx
Return type: void
Description: Draw a gradient-filled rectangle with custom vertex colors
Param[1]: rec (type: Rectangle)
- Param[2]: col1 (type: Color)
- Param[3]: col2 (type: Color)
- Param[4]: col3 (type: Color)
- Param[5]: col4 (type: Color)
+ Param[2]: topLeft (type: Color)
+ Param[3]: bottomLeft (type: Color)
+ Param[4]: topRight (type: Color)
+ Param[5]: bottomRight (type: Color)
Function 232: DrawRectangleLines() (5 input parameters)
Name: DrawRectangleLines
Return type: void
diff --git a/parser/output/raylib_api.xml b/parser/output/raylib_api.xml
index 474bc0473..8a6560f48 100644
--- a/parser/output/raylib_api.xml
+++ b/parser/output/raylib_api.xml
@@ -1353,8 +1353,8 @@
-
-
+
+
@@ -1431,23 +1431,23 @@
-
-
+
+
-
-
+
+
-
-
-
-
+
+
+
+
diff --git a/src/Makefile b/src/Makefile
index c68a03797..4740f1f01 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -467,7 +467,7 @@ INCLUDE_PATHS = -I.
ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW)
INCLUDE_PATHS += -Iexternal/glfw/include
ifeq ($(PLATFORM_OS),BSD)
- INCLUDE_PATHS += -I/usr/local/include
+ INCLUDE_PATHS += -I/usr/local/include -I/usr/pkg/include -I/usr/X11R7/include
endif
endif
ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_SDL)
@@ -522,7 +522,7 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW)
LDFLAGS += -Wl,-soname,lib$(RAYLIB_LIB_NAME).so.$(RAYLIB_API_VERSION)
endif
ifeq ($(PLATFORM_OS),BSD)
- LDFLAGS += -Wl,-soname,lib$(RAYLIB_LIB_NAME).$(RAYLIB_API_VERSION).so -Lsrc -L/usr/local/lib
+ LDFLAGS += -Wl,-soname,lib$(RAYLIB_LIB_NAME).$(RAYLIB_API_VERSION).so -Lsrc -L/usr/local/lib -L/usr/pkg/lib -Wl,-R/usr/pkg/lib
endif
endif
ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_SDL)
diff --git a/src/build.zig b/src/build.zig
index 65379c03b..4e112d78f 100644
--- a/src/build.zig
+++ b/src/build.zig
@@ -59,15 +59,15 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
const content = try std.fs.cwd().readFileAlloc(b.allocator, file, std.math.maxInt(usize));
defer b.allocator.free(content);
- var lines = std.mem.split(u8, content, "\n");
+ var lines = std.mem.splitScalar(u8, content, '\n');
while (lines.next()) |line| {
if (!std.mem.containsAtLeast(u8, line, 1, "SUPPORT")) continue;
if (std.mem.startsWith(u8, line, "//")) continue;
- var flag = std.mem.trimLeft(u8, line, " \t"); // Trim whitespace
- flag = flag["#define ".len - 1 ..]; // Remove #define
- flag = std.mem.trimLeft(u8, flag, " \t"); // Trim whitespace
- flag = flag[0..std.mem.indexOf(u8, flag, " ").?]; // Flag is only one word, so capture till space
+ var flag = std.mem.trimLeft(u8, line, " \t"); // Trim whitespace
+ flag = flag["#define ".len - 1 ..]; // Remove #define
+ flag = std.mem.trimLeft(u8, flag, " \t"); // Trim whitespace
+ flag = flag[0..std.mem.indexOf(u8, flag, " ").?]; // Flag is only one word, so capture till space
flag = try std.fmt.allocPrint(b.allocator, "-D{s}", .{flag}); // Prepend with -D
// If user specifies the flag skip it
@@ -149,9 +149,8 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
raylib.addLibraryPath(.{ .cwd_relative = "/usr/lib" });
raylib.addIncludePath(.{ .cwd_relative = "/usr/include" });
if (options.linux_display_backend == .X11 or options.linux_display_backend == .Both) {
-
- raylib.defineCMacro("_GLFW_X11", null);
- raylib.linkSystemLibrary("X11");
+ raylib.defineCMacro("_GLFW_X11", null);
+ raylib.linkSystemLibrary("X11");
}
if (options.linux_display_backend == .Wayland or options.linux_display_backend == .Both) {
diff --git a/src/external/RGFW.h b/src/external/RGFW.h
index 5420ccab1..367a46fa6 100644
--- a/src/external/RGFW.h
+++ b/src/external/RGFW.h
@@ -57,6 +57,8 @@
#define RGFW_EXPORT - Use when building RGFW
#define RGFW_IMPORT - Use when linking with RGFW (not as a single-header)
+
+ #define RGFW_STD_INT - force the use stdint.h (for systems that might not have stdint.h (msvc))
*/
/*
@@ -81,6 +83,7 @@
Code-Nycticebus -> bug fixes
Rob Rohan -> X11 bugs and missing features, MacOS/Cocoa fixing memory issues/bugs
AICDG (@THISISAGOODNAME) -> vulkan support (example)
+ @Easymode -> support, testing/debugging, bug fixes and reviews
*/
#if _MSC_VER
@@ -93,6 +96,11 @@
#ifndef RGFW_MALLOC
#include
+
+ #ifndef __USE_POSIX199309
+ #define __USE_POSIX199309
+ #endif
+
#include
#define RGFW_MALLOC malloc
#define RGFW_CALLOC calloc
@@ -131,7 +139,7 @@
#endif
#ifndef RGFWDEF
- #ifdef __APPLE__
+ #ifdef __clang__
#define RGFWDEF static inline
#else
#define RGFWDEF inline
@@ -146,7 +154,7 @@
#define RGFW_UNUSED(x) (void)(x);
#endif
-#ifdef __cplusplus
+#if defined(__cplusplus) && !defined(__EMSCRIPTEN__)
extern "C" {
#endif
@@ -156,7 +164,7 @@
#define RGFW_HEADER
#if !defined(u8)
- #if defined(_MSC_VER) || defined(__SYMBIAN32__) /* MSVC might not have stdint.h */
+ #if ((defined(_MSC_VER) || defined(__SYMBIAN32__)) && !defined(RGFW_STD_INT)) /* MSVC might not have stdint.h */
typedef unsigned char u8;
typedef signed char i8;
typedef unsigned short u16;
@@ -182,10 +190,11 @@
#if !defined(b8) /* RGFW bool type */
typedef u8 b8;
typedef u32 b32;
- #define RGFW_TRUE 1
- #define RGFW_FALSE 0
#endif
+#define RGFW_TRUE 1
+#define RGFW_FALSE 0
+
/* thse OS macros looks better & are standardized */
/* plus it helps with cross-compiling */
@@ -242,6 +251,14 @@
#endif
#endif
+#elif defined(RGFW_WAYLAND)
+ #if !defined(RGFW_NO_API) && (!defined(RGFW_BUFFER) || defined(RGFW_OPENGL))
+ #define RGFW_EGL
+ #define RGFW_OPENGL
+ #include
+ #endif
+
+ #include
#elif (defined(__unix__) || defined(RGFW_MACOS_X11) || defined(RGFW_X11)) && !defined(RGFW_WEBASM)
#define RGFW_MACOS_X11
#define RGFW_X11
@@ -299,65 +316,65 @@
#define RGFW_NO_GPU_RENDER (1L<<14) /* don't render (using the GPU based API)*/
#define RGFW_NO_CPU_RENDER (1L<<15) /* don't render (using the CPU based buffer rendering)*/
+#define RGFW_WINDOW_HIDE (1L << 16)/* the window is hidden */
-/*! event codes */
-#define RGFW_keyPressed 2 /* a key has been pressed */
-#define RGFW_keyReleased 3 /*!< a key has been released*/
-/*! key event note
- the code of the key pressed is stored in
- RGFW_Event.keyCode
- !!Keycodes defined at the bottom of the RGFW_HEADER part of this file!!
+typedef RGFW_ENUM(u8, RGFW_event_types) {
+ /*! event codes */
+ RGFW_keyPressed = 1, /* a key has been pressed */
+ RGFW_keyReleased, /*!< a key has been released*/
+ /*! key event note
+ the code of the key pressed is stored in
+ RGFW_Event.keyCode
+ !!Keycodes defined at the bottom of the RGFW_HEADER part of this file!!
- while a string version is stored in
- RGFW_Event.KeyString
+ while a string version is stored in
+ RGFW_Event.KeyString
- RGFW_Event.lockState holds the current lockState
- this means if CapsLock, NumLock are active or not
-*/
-#define RGFW_mouseButtonPressed 4 /*!< a mouse button has been pressed (left,middle,right)*/
-#define RGFW_mouseButtonReleased 5 /*!< a mouse button has been released (left,middle,right)*/
-#define RGFW_mousePosChanged 6 /*!< the position of the mouse has been changed*/
-/*! mouse event note
- the x and y of the mouse can be found in the vector, RGFW_Event.point
+ RGFW_Event.lockState holds the current lockState
+ this means if CapsLock, NumLock are active or not
+ */
+ RGFW_mouseButtonPressed, /*!< a mouse button has been pressed (left,middle,right)*/
+ RGFW_mouseButtonReleased, /*!< a mouse button has been released (left,middle,right)*/
+ RGFW_mousePosChanged, /*!< the position of the mouse has been changed*/
+ /*! mouse event note
+ the x and y of the mouse can be found in the vector, RGFW_Event.point
- RGFW_Event.button holds which mouse button was pressed
-*/
-#define RGFW_jsButtonPressed 7 /*!< a joystick button was pressed */
-#define RGFW_jsButtonReleased 8 /*!< a joystick button was released */
-#define RGFW_jsAxisMove 9 /*!< an axis of a joystick was moved*/
-/*! joystick event note
- RGFW_Event.joystick holds which joystick was altered, if any
- RGFW_Event.button holds which joystick button was pressed
+ RGFW_Event.button holds which mouse button was pressed
+ */
+ RGFW_jsButtonPressed, /*!< a joystick button was pressed */
+ RGFW_jsButtonReleased, /*!< a joystick button was released */
+ RGFW_jsAxisMove, /*!< an axis of a joystick was moved*/
+ /*! joystick event note
+ RGFW_Event.joystick holds which joystick was altered, if any
+ RGFW_Event.button holds which joystick button was pressed
- RGFW_Event.axis holds the data of all the axis
- RGFW_Event.axisCount says how many axis there are
-*/
-#define RGFW_windowMoved 10 /*!< the window was moved (by the user) */
-#define RGFW_windowResized 11 /*!< the window was resized (by the user), [on webASM this means the browser was resized] */
+ RGFW_Event.axis holds the data of all the axis
+ RGFW_Event.axisCount says how many axis there are
+ */
+ RGFW_windowMoved, /*!< the window was moved (by the user) */
+ RGFW_windowResized, /*!< the window was resized (by the user), [on webASM this means the browser was resized] */
+ RGFW_focusIn, /*!< window is in focus now */
+ RGFW_focusOut, /*!< window is out of focus now */
+ RGFW_mouseEnter, /* mouse entered the window */
+ RGFW_mouseLeave, /* mouse left the window */
+ RGFW_windowRefresh, /* The window content needs to be refreshed */
-#define RGFW_focusIn 12 /*!< window is in focus now */
-#define RGFW_focusOut 13 /*!< window is out of focus now */
+ /* attribs change event note
+ The event data is sent straight to the window structure
+ with win->r.x, win->r.y, win->r.w and win->r.h
+ */
+ RGFW_quit, /*!< the user clicked the quit button*/
+ RGFW_dnd, /*!< a file has been dropped into the window*/
+ RGFW_dnd_init /*!< the start of a dnd event, when the place where the file drop is known */
+ /* dnd data note
+ The x and y coords of the drop are stored in the vector RGFW_Event.point
-#define RGFW_mouseEnter 14 /* mouse entered the window */
-#define RGFW_mouseLeave 15 /* mouse left the window */
+ RGFW_Event.droppedFilesCount holds how many files were dropped
-#define RGFW_windowRefresh 16 /* The window content needs to be refreshed */
-
-/* attribs change event note
- The event data is sent straight to the window structure
- with win->r.x, win->r.y, win->r.w and win->r.h
-*/
-#define RGFW_quit 33 /*!< the user clicked the quit button*/
-#define RGFW_dnd 34 /*!< a file has been dropped into the window*/
-#define RGFW_dnd_init 35 /*!< the start of a dnd event, when the place where the file drop is known */
-/* dnd data note
- The x and y coords of the drop are stored in the vector RGFW_Event.point
-
- RGFW_Event.droppedFilesCount holds how many files were dropped
-
- This is also the size of the array which stores all the dropped file string,
- RGFW_Event.droppedFiles
-*/
+ This is also the size of the array which stores all the dropped file string,
+ RGFW_Event.droppedFiles
+ */
+};
/*! mouse button codes (RGFW_Event.button) */
#define RGFW_mouseLeft 1 /*!< left mouse button is pressed*/
@@ -381,64 +398,72 @@
/*! joystick button codes (based on xbox/playstation), you may need to change these values per controller */
#ifndef RGFW_joystick_codes
typedef RGFW_ENUM(u8, RGFW_joystick_codes) {
- RGFW_JS_A = 0, /* or PS X button */
- RGFW_JS_B = 1, /* or PS circle button */
- RGFW_JS_Y = 2, /* or PS triangle button */
- RGFW_JS_X = 3, /* or PS square button */
- RGFW_JS_START = 9, /* start button */
- RGFW_JS_SELECT = 8, /* select button */
- RGFW_JS_HOME = 10, /* home button */
- RGFW_JS_UP = 13, /* dpad up */
- RGFW_JS_DOWN = 14, /* dpad down*/
- RGFW_JS_LEFT = 15, /* dpad left */
- RGFW_JS_RIGHT = 16, /* dpad right */
- RGFW_JS_L1 = 4, /* left bump */
- RGFW_JS_L2 = 5, /* left trigger*/
- RGFW_JS_R1 = 6, /* right bumper */
- RGFW_JS_R2 = 7, /* right trigger */
+ RGFW_JS_A = 0, /*!< or PS X button */
+ RGFW_JS_B = 1, /*!< or PS circle button */
+ RGFW_JS_Y = 2, /*!< or PS triangle button */
+ RGFW_JS_X = 3, /*!< or PS square button */
+ RGFW_JS_START = 9, /*!< start button */
+ RGFW_JS_SELECT = 8, /*!< select button */
+ RGFW_JS_HOME = 10, /*!< home button */
+ RGFW_JS_UP = 13, /*!< dpad up */
+ RGFW_JS_DOWN = 14, /*!< dpad down*/
+ RGFW_JS_LEFT = 15, /*!< dpad left */
+ RGFW_JS_RIGHT = 16, /*!< dpad right */
+ RGFW_JS_L1 = 4, /*!< left bump */
+ RGFW_JS_L2 = 5, /*!< left trigger*/
+ RGFW_JS_R1 = 6, /*!< right bumper */
+ RGFW_JS_R2 = 7, /*!< right trigger */
};
#endif
-/* basic vector type, if there's not already a point/vector type of choice */
+/*! basic vector type, if there's not already a point/vector type of choice */
#ifndef RGFW_point
typedef struct { i32 x, y; } RGFW_point;
#endif
- /* basic rect type, if there's not already a rect type of choice */
+/*! basic rect type, if there's not already a rect type of choice */
#ifndef RGFW_rect
typedef struct { i32 x, y, w, h; } RGFW_rect;
#endif
- /* basic area type, if there's not already a area type of choice */
+/*! basic area type, if there's not already a area type of choice */
#ifndef RGFW_area
typedef struct { u32 w, h; } RGFW_area;
#endif
-#define RGFW_POINT(x, y) (RGFW_point){x, y}
-#define RGFW_RECT(x, y, w, h) (RGFW_rect){x, y, w, h}
-#define RGFW_AREA(w, h) (RGFW_area){w, h}
+#ifndef __cplusplus
+#define RGFW_POINT(x, y) (RGFW_point){(i32)(x), (i32)(y)}
+#define RGFW_RECT(x, y, w, h) (RGFW_rect){(i32)(x), (i32)(y), (i32)(w), (i32)(h)}
+#define RGFW_AREA(w, h) (RGFW_area){(u32)(w), (u32)(h)}
+#else
+#define RGFW_POINT(x, y) {(i32)(x), (i32)(y)}
+#define RGFW_RECT(x, y, w, h) {(i32)(x), (i32)(y), (i32)(w), (i32)(h)}
+#define RGFW_AREA(w, h) {(u32)(w), (u32)(h)}
+#endif
#ifndef RGFW_NO_MONITOR
+ /*! structure for monitor data */
typedef struct RGFW_monitor {
- char name[128]; /* monitor name */
- RGFW_rect rect; /* monitor Workarea */
- float scaleX, scaleY; /* monitor content scale*/
- float physW, physH; /* monitor physical size */
+ char name[128]; /*!< monitor name */
+ RGFW_rect rect; /*!< monitor Workarea */
+ float scaleX, scaleY; /*!< monitor content scale*/
+ float physW, physH; /*!< monitor physical size */
} RGFW_monitor;
/*
- NOTE : Monitor functions should be ran only as many times as needed (not in a loop)
+ NOTE : Monitor functions should be ran only as many times as needed (not in a loop)
*/
- /* get an array of all the monitors (max 6) */
+ /*! get an array of all the monitors (max 6) */
RGFWDEF RGFW_monitor* RGFW_getMonitors(void);
- /* get the primary monitor */
+ /*! get the primary monitor */
RGFWDEF RGFW_monitor RGFW_getPrimaryMonitor(void);
#endif
/* NOTE: some parts of the data can represent different things based on the event (read comments in RGFW_Event struct) */
+/*! Event structure for checking/getting events */
typedef struct RGFW_Event {
- char keyName[16]; /* key name of event*/
+ char keyName[16]; /*!< key name of event*/
/*! drag and drop data */
/* 260 max paths with a max length of 260 */
@@ -452,67 +477,85 @@ typedef struct RGFW_Event {
u32 type; /*!< which event has been sent?*/
RGFW_point point; /*!< mouse x, y of event (or drop point) */
- u32 fps; /*the current fps of the window [the fps is checked when events are checked]*/
- u64 frameTime, frameTime2; /* this is used for counting the fps */
+ u8 keyCode; /*!< keycode of event !!Keycodes defined at the bottom of the RGFW_HEADER part of this file!! */
- u8 keyCode; /*!< keycode of event !!Keycodes defined at the bottom of the RGFW_HEADER part of this file!! */
-
- b8 inFocus; /*if the window is in focus or not (this is always true for MacOS windows due to the api being weird) */
+ b8 repeat; /*!< key press event repeated (the key is being held) */
+ b8 inFocus; /*!< if the window is in focus or not (this is always true for MacOS windows due to the api being weird) */
u8 lockState;
+
+ u8 button; /* !< which mouse button was pressed */
+ double scroll; /*!< the raw mouse scroll value */
- u16 joystick; /* which joystick this event applies to (if applicable to any) */
+ u16 joystick; /*! which joystick this event applies to (if applicable to any) */
+ u8 axisesCount; /*!< number of axises */
+ RGFW_point axis[2]; /*!< x, y of axises (-100 to 100) */
- u8 button; /*!< which mouse button has been clicked (0) left (1) middle (2) right OR which joystick button was pressed*/
- double scroll; /* the raw mouse scroll value */
-
- u8 axisesCount; /* number of axises */
- RGFW_point axis[2]; /* x, y of axises (-100 to 100) */
-} RGFW_Event; /*!< Event structure for checking/getting events */
-
-/* source data for the window (used by the APIs) */
+ u64 frameTime, frameTime2; /*!< this is used for counting the fps */
+} RGFW_Event;
+/*! source data for the window (used by the APIs) */
typedef struct RGFW_window_src {
#ifdef RGFW_WINDOWS
HWND window; /*!< source window */
HDC hdc; /*!< source HDC */
u32 hOffset; /*!< height offset for window */
-#if (defined(RGFW_OPENGL)) && !defined(RGFW_OSMESA) && !defined(RGFW_EGL)
+ #if (defined(RGFW_OPENGL)) && !defined(RGFW_OSMESA) && !defined(RGFW_EGL)
HGLRC ctx; /*!< source graphics context */
-#elif defined(RGFW_OSMESA)
+ #elif defined(RGFW_OSMESA)
OSMesaContext ctx;
-#elif defined(RGFW_DIRECTX)
+ #elif defined(RGFW_DIRECTX)
IDXGISwapChain* swapchain;
ID3D11RenderTargetView* renderTargetView;
ID3D11DepthStencilView* pDepthStencilView;
-#elif defined(RGFW_EGL)
+ #elif defined(RGFW_EGL)
EGLSurface EGL_surface;
EGLDisplay EGL_display;
EGLContext EGL_context;
-#endif
+ #endif
-#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)
+ #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)
HDC hdcMem;
HBITMAP bitmap;
-#endif
- RGFW_area maxSize, minSize; /* for setting max/min resize (RGFW_WINDOWS) */
+ #endif
+ RGFW_area maxSize, minSize; /*!< for setting max/min resize (RGFW_WINDOWS) */
#elif defined(RGFW_X11)
Display* display; /*!< source display */
Window window; /*!< source window */
-#if (defined(RGFW_OPENGL)) && !defined(RGFW_OSMESA) && !defined(RGFW_EGL)
+ #if (defined(RGFW_OPENGL)) && !defined(RGFW_OSMESA) && !defined(RGFW_EGL)
GLXContext ctx; /*!< source graphics context */
-#elif defined(RGFW_OSMESA)
+ #elif defined(RGFW_OSMESA)
OSMesaContext ctx;
-#elif defined(RGFW_EGL)
+ #elif defined(RGFW_EGL)
EGLSurface EGL_surface;
EGLDisplay EGL_display;
EGLContext EGL_context;
-#endif
+ #endif
#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)
XImage* bitmap;
GC gc;
#endif
+#elif defined(RGFW_WAYLAND)
+ struct wl_display* display;
+ struct wl_surface* surface;
+ struct wl_buffer* wl_buffer;
+ struct wl_keyboard* keyboard;
+
+ struct xdg_surface* xdg_surface;
+ struct xdg_toplevel* xdg_toplevel;
+ struct zxdg_toplevel_decoration_v1* decoration;
+ RGFW_Event events[20];
+ i32 eventLen;
+ size_t eventIndex;
+ #if defined(RGFW_EGL)
+ struct wl_egl_window* window;
+ EGLSurface EGL_surface;
+ EGLDisplay EGL_display;
+ EGLContext EGL_context;
+ #elif defined(RGFW_OSMESA)
+ OSMesaContext ctx;
+ #endif
#elif defined(RGFW_MACOS)
u32 display;
void* displayLink;
@@ -531,7 +574,7 @@ typedef struct RGFW_window_src {
void* view; /*apple viewpoint thingy*/
#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)
- void* bitmap; /* API's bitmap for storing or managing */
+ void* bitmap; /*!< API's bitmap for storing or managing */
void* image;
#endif
#elif defined(RGFW_WEBASM)
@@ -542,33 +585,34 @@ typedef struct RGFW_window_src {
typedef struct RGFW_window {
- RGFW_window_src src;
+ RGFW_window_src src; /*!< src window data */
#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)
- u8* buffer; /* buffer for non-GPU systems (OSMesa, basic software rendering) */
+ u8* buffer; /*!< buffer for non-GPU systems (OSMesa, basic software rendering) */
/* when rendering using RGFW_BUFFER, the buffer is in the RGBA format */
#endif
-
+ void* userPtr; /* ptr for usr data */
+
RGFW_Event event; /*!< current event */
- RGFW_rect r; /* the x, y, w and h of the struct */
+ RGFW_rect r; /*!< the x, y, w and h of the struct */
- RGFW_point _lastMousePoint; /* last cusor point (for raw mouse data) */
-
- u32 fpsCap; /*!< the fps cap of the window should run at (change this var to change the fps cap, 0 = no limit)*/
- /*[the fps is capped when events are checked]*/
-
- u32 _winArgs; /* windows args (for RGFW to check) */
+ RGFW_point _lastMousePoint; /*!< last cusor point (for raw mouse data) */
+
+ u32 _winArgs; /*!< windows args (for RGFW to check) */
} RGFW_window; /*!< Window structure for managing the window */
#if defined(RGFW_X11) || defined(RGFW_MACOS)
- typedef u64 RGFW_thread; /* thread type unix */
+ typedef u64 RGFW_thread; /*!< thread type unix */
#else
- typedef void* RGFW_thread; /* thread type for window */
+ typedef void* RGFW_thread; /*!< thread type for window */
#endif
-/* this has to be set before createWindow is called, else the fulscreen size is used */
-RGFWDEF void RGFW_setBufferSize(RGFW_area size); /* the buffer cannot be resized (by RGFW) */
+/** * @defgroup Window_management
+* @{ */
+
+/*! this has to be set before createWindow is called, else the fulscreen size is used */
+RGFWDEF void RGFW_setBufferSize(RGFW_area size); /*!< the buffer cannot be resized (by RGFW) */
RGFW_window* RGFW_createWindow(
const char* name, /* name of the window */
@@ -576,10 +620,10 @@ RGFW_window* RGFW_createWindow(
u16 args /* extra arguments (NULL / (u16)0 means no args used)*/
); /*!< function to create a window struct */
-/* get the size of the screen to an area struct */
+/*! get the size of the screen to an area struct */
RGFWDEF RGFW_area RGFW_getScreenSize(void);
-/*
+/*!
this function checks an *individual* event (and updates window structure attributes)
this means, using this function without a while loop may cause event lag
@@ -593,7 +637,7 @@ RGFWDEF RGFW_area RGFW_getScreenSize(void);
RGFW_Event* RGFW_window_checkEvent(RGFW_window* win); /*!< check current event (returns a pointer to win->event or NULL if there is no event)*/
-/*
+/*!
for RGFW_window_eventWait and RGFW_window_checkEvents
waitMS -> Allows th e function to keep checking for events even after `RGFW_window_checkEvent == NULL`
if waitMS == 0, the loop will not wait for events
@@ -605,16 +649,16 @@ typedef RGFW_ENUM(i32, RGFW_eventWait) {
RGFW_NO_WAIT = 0
};
-/* sleep until RGFW gets an event or the timer ends (defined by OS) */
+/*! sleep until RGFW gets an event or the timer ends (defined by OS) */
RGFWDEF void RGFW_window_eventWait(RGFW_window* win, i32 waitMS);
-/*
+/*!
check all the events until there are none left,
this should only be used if you're using callbacks only
*/
RGFWDEF void RGFW_window_checkEvents(RGFW_window* win, i32 waitMS);
-/*
+/*!
Tell RGFW_window_eventWait to stop waiting, to be ran from another thread
*/
RGFWDEF void RGFW_stopCheckEvents(void);
@@ -622,42 +666,42 @@ RGFWDEF void RGFW_stopCheckEvents(void);
/*! window managment functions*/
RGFWDEF void RGFW_window_close(RGFW_window* win); /*!< close the window and free leftover data */
-/* moves window to a given point */
+/*! moves window to a given point */
RGFWDEF void RGFW_window_move(RGFW_window* win,
- RGFW_point v/* new pos*/
+ RGFW_point v/*!< new pos*/
);
#ifndef RGFW_NO_MONITOR
- /* move to a specific monitor */
+ /*! move to a specific monitor */
RGFWDEF void RGFW_window_moveToMonitor(RGFW_window* win, RGFW_monitor m /* monitor */);
#endif
-/* resize window to a current size/area */
-RGFWDEF void RGFW_window_resize(RGFW_window* win,
- RGFW_area a/* new size*/
+/*! resize window to a current size/area */
+RGFWDEF void RGFW_window_resize(RGFW_window* win, /*!< source window */
+ RGFW_area a/*!< new size*/
);
-/* set the minimum size a user can shrink a window to a given size/area */
+/*! set the minimum size a user can shrink a window to a given size/area */
RGFWDEF void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a);
-/* set the minimum size a user can extend a window to a given size/area */
+/*! set the minimum size a user can extend a window to a given size/area */
RGFWDEF void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a);
-RGFWDEF void RGFW_window_maximize(RGFW_window* win); /* maximize the window size */
-RGFWDEF void RGFW_window_minimize(RGFW_window* win); /* minimize the window (in taskbar (per OS))*/
-RGFWDEF void RGFW_window_restore(RGFW_window* win); /* restore the window from minimized (per OS)*/
+RGFWDEF void RGFW_window_maximize(RGFW_window* win); /*!< maximize the window size */
+RGFWDEF void RGFW_window_minimize(RGFW_window* win); /*!< minimize the window (in taskbar (per OS))*/
+RGFWDEF void RGFW_window_restore(RGFW_window* win); /*!< restore the window from minimized (per OS)*/
-/* if the window should have a border or not (borderless) based on bool value of `border` */
+/*! if the window should have a border or not (borderless) based on bool value of `border` */
RGFWDEF void RGFW_window_setBorder(RGFW_window* win, b8 border);
-/* turn on / off dnd (RGFW_ALLOW_DND stil must be passed to the window)*/
+/*! turn on / off dnd (RGFW_ALLOW_DND stil must be passed to the window)*/
RGFWDEF void RGFW_window_setDND(RGFW_window* win, b8 allow);
#ifndef RGFW_NO_PASSTHROUGH
- /* turn on / off mouse passthrough */
+ /*!! turn on / off mouse passthrough */
RGFWDEF void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough);
#endif
-/* rename window to a given string */
+/*! rename window to a given string */
RGFWDEF void RGFW_window_setName(RGFW_window* win,
char* name
);
@@ -674,7 +718,7 @@ RGFWDEF void RGFW_window_setMouse(RGFW_window* win, u8* image, RGFW_area a, i32
/*!< sets the mouse to a standard API cursor (based on RGFW_MOUSE, as seen at the end of the RGFW_HEADER part of this file) */
RGFWDEF void RGFW_window_setMouseStandard(RGFW_window* win, u8 mouse);
-RGFWDEF void RGFW_window_setMouseDefault(RGFW_window* win); /* sets the mouse to the default mouse icon */
+RGFWDEF void RGFW_window_setMouseDefault(RGFW_window* win); /*!< sets the mouse to the default mouse icon */
/*
Locks cursor at the center of the window
win->event.point become raw mouse movement data
@@ -682,12 +726,12 @@ RGFWDEF void RGFW_window_setMouseDefault(RGFW_window* win); /* sets the mouse to
this is useful for a 3D camera
*/
RGFWDEF void RGFW_window_mouseHold(RGFW_window* win, RGFW_area area);
-/* stop holding the mouse and let it move freely */
+/*! stop holding the mouse and let it move freely */
RGFWDEF void RGFW_window_mouseUnhold(RGFW_window* win);
-/* hide the window */
+/*! hide the window */
RGFWDEF void RGFW_window_hide(RGFW_window* win);
-/* show the window */
+/*! show the window */
RGFWDEF void RGFW_window_show(RGFW_window* win);
/*
@@ -696,28 +740,32 @@ RGFWDEF void RGFW_window_show(RGFW_window* win);
*/
RGFWDEF void RGFW_window_setShouldClose(RGFW_window* win);
-/* where the mouse is on the screen */
+/*! where the mouse is on the screen */
RGFWDEF RGFW_point RGFW_getGlobalMousePoint(void);
-/* where the mouse is on the window */
+/*! where the mouse is on the window */
RGFWDEF RGFW_point RGFW_window_getMousePoint(RGFW_window* win);
-/* show the mouse or hide the mouse*/
+/*! show the mouse or hide the mouse*/
RGFWDEF void RGFW_window_showMouse(RGFW_window* win, i8 show);
-/* move the mouse to a set x, y pos*/
+/*! move the mouse to a set x, y pos*/
RGFWDEF void RGFW_window_moveMouse(RGFW_window* win, RGFW_point v);
-/* if the window should close (RGFW_close was sent or escape was pressed) */
+/*! if the window should close (RGFW_close was sent or escape was pressed) */
RGFWDEF b8 RGFW_window_shouldClose(RGFW_window* win);
-/* if window is fullscreen'd */
+/*! if window is fullscreen'd */
RGFWDEF b8 RGFW_window_isFullscreen(RGFW_window* win);
-/* if window is hidden */
+/*! if window is hidden */
RGFWDEF b8 RGFW_window_isHidden(RGFW_window* win);
-/* if window is minimized */
+/*! if window is minimized */
RGFWDEF b8 RGFW_window_isMinimized(RGFW_window* win);
-/* if window is maximized */
+/*! if window is maximized */
RGFWDEF b8 RGFW_window_isMaximized(RGFW_window* win);
+/** @} */
+
+/** * @defgroup Monitor
+* @{ */
#ifndef RGFW_NO_MONITOR
/*
@@ -725,17 +773,27 @@ scale the window to the monitor,
this is run by default if the user uses the arg `RGFW_SCALE_TO_MONITOR` during window creation
*/
RGFWDEF void RGFW_window_scaleToMonitor(RGFW_window* win);
-/* get the struct of the window's monitor */
+/*! get the struct of the window's monitor */
RGFWDEF RGFW_monitor RGFW_window_getMonitor(RGFW_window* win);
#endif
-/*!< make the window the current opengl drawing context */
-RGFWDEF void RGFW_window_makeCurrent(RGFW_window* win);
+/** @} */
+
+/** * @defgroup Input
+* @{ */
/*error handling*/
-RGFWDEF b8 RGFW_Error(void); /* returns true if an error has occurred (doesn't print errors itself) */
+RGFWDEF b8 RGFW_Error(void); /*!< returns true if an error has occurred (doesn't print errors itself) */
-/*!< if window == NULL, it checks if the key is pressed globally. Otherwise, it checks only if the key is pressed while the window in focus.*/
+/*! returns true if the key should be shifted */
+RGFWDEF b8 RGFW_shouldShift(u32 keycode, u8 lockState);
+
+/*! get char from RGFW keycode (using a LUT), uses shift'd version if shift = true */
+RGFWDEF char RGFW_keyCodeToChar(u32 keycode, b8 shift);
+/*! get char from RGFW keycode (using a LUT), uses lockState for shouldShift) */
+RGFWDEF char RGFW_keyCodeToCharAuto(u32 keycode, u8 lockState);
+
+/*! if window == NULL, it checks if the key is pressed globally. Otherwise, it checks only if the key is pressed while the window in focus.*/
RGFWDEF b8 RGFW_isPressed(RGFW_window* win, u8 key); /*!< if key is pressed (key code)*/
RGFWDEF b8 RGFW_wasPressed(RGFW_window* win, u8 key); /*!< if key was pressed (checks previous state only) (key code)*/
@@ -744,90 +802,100 @@ RGFWDEF b8 RGFW_isHeld(RGFW_window* win, u8 key); /*!< if key is held (key code)
RGFWDEF b8 RGFW_isReleased(RGFW_window* win, u8 key); /*!< if key is released (key code)*/
/* if a key is pressed and then released, pretty much the same as RGFW_isReleased */
-RGFWDEF b8 RGFW_isClicked(RGFW_window* win, u8 key /* key code*/);
+RGFWDEF b8 RGFW_isClicked(RGFW_window* win, u8 key /*!< key code*/);
-/* if a mouse button is pressed */
-RGFWDEF b8 RGFW_isMousePressed(RGFW_window* win, u8 button /* mouse button code */ );
-/* if a mouse button is held */
-RGFWDEF b8 RGFW_isMouseHeld(RGFW_window* win, u8 button /* mouse button code */ );
-/* if a mouse button was released */
-RGFWDEF b8 RGFW_isMouseReleased(RGFW_window* win, u8 button /* mouse button code */ );
-/* if a mouse button was pressed (checks previous state only) */
-RGFWDEF b8 RGFW_wasMousePressed(RGFW_window* win, u8 button /* mouse button code */ );
+/*! if a mouse button is pressed */
+RGFWDEF b8 RGFW_isMousePressed(RGFW_window* win, u8 button /*!< mouse button code */ );
+/*! if a mouse button is held */
+RGFWDEF b8 RGFW_isMouseHeld(RGFW_window* win, u8 button /*!< mouse button code */ );
+/*! if a mouse button was released */
+RGFWDEF b8 RGFW_isMouseReleased(RGFW_window* win, u8 button /*!< mouse button code */ );
+/*! if a mouse button was pressed (checks previous state only) */
+RGFWDEF b8 RGFW_wasMousePressed(RGFW_window* win, u8 button /*!< mouse button code */ );
+/** @} */
-/*! clipboard functions*/
+/** * @defgroup Clipboard
+* @{ */
RGFWDEF char* RGFW_readClipboard(size_t* size); /*!< read clipboard data */
-RGFWDEF void RGFW_clipboardFree(char* str); /* the string returned from RGFW_readClipboard must be freed */
+RGFWDEF void RGFW_clipboardFree(char* str); /*!< the string returned from RGFW_readClipboard must be freed */
RGFWDEF void RGFW_writeClipboard(const char* text, u32 textLen); /*!< write text to the clipboard */
+/** @} */
-/*
+/**
Event callbacks,
these are completely optional, you can use the normal
RGFW_checkEvent() method if you prefer that
+* @defgroup Callbacks
+* @{
*/
-/* RGFW_windowMoved, the window and its new rect value */
+/*! RGFW_windowMoved, the window and its new rect value */
typedef void (* RGFW_windowmovefunc)(RGFW_window* win, RGFW_rect r);
-/* RGFW_windowResized, the window and its new rect value */
+/*! RGFW_windowResized, the window and its new rect value */
typedef void (* RGFW_windowresizefunc)(RGFW_window* win, RGFW_rect r);
-/* RGFW_quit, the window that was closed */
+/*! RGFW_quit, the window that was closed */
typedef void (* RGFW_windowquitfunc)(RGFW_window* win);
-/* RGFW_focusIn / RGFW_focusOut, the window who's focus has changed and if its inFocus */
+/*! RGFW_focusIn / RGFW_focusOut, the window who's focus has changed and if its inFocus */
typedef void (* RGFW_focusfunc)(RGFW_window* win, b8 inFocus);
-/* RGFW_mouseEnter / RGFW_mouseLeave, the window that changed, the point of the mouse (enter only) and if the mouse has entered */
+/*! RGFW_mouseEnter / RGFW_mouseLeave, the window that changed, the point of the mouse (enter only) and if the mouse has entered */
typedef void (* RGFW_mouseNotifyfunc)(RGFW_window* win, RGFW_point point, b8 status);
-/* RGFW_mousePosChanged, the window that the move happened on and the new point of the mouse */
+/*! RGFW_mousePosChanged, the window that the move happened on and the new point of the mouse */
typedef void (* RGFW_mouseposfunc)(RGFW_window* win, RGFW_point point);
-/* RGFW_dnd_init, the window, the point of the drop on the windows */
+/*! RGFW_dnd_init, the window, the point of the drop on the windows */
typedef void (* RGFW_dndInitfunc)(RGFW_window* win, RGFW_point point);
-/* RGFW_windowRefresh, the window that needs to be refreshed */
+/*! RGFW_windowRefresh, the window that needs to be refreshed */
typedef void (* RGFW_windowrefreshfunc)(RGFW_window* win);
-/* RGFW_keyPressed / RGFW_keyReleased, the window that got the event, the keycode, the string version, the state of mod keys, if it was a press (else it's a release) */
+/*! RGFW_keyPressed / RGFW_keyReleased, the window that got the event, the keycode, the string version, the state of mod keys, if it was a press (else it's a release) */
typedef void (* RGFW_keyfunc)(RGFW_window* win, u32 keycode, char keyName[16], u8 lockState, b8 pressed);
-/* RGFW_mouseButtonPressed / RGFW_mouseButtonReleased, the window that got the event, the button that was pressed, the scroll value, if it was a press (else it's a release) */
+/*! RGFW_mouseButtonPressed / RGFW_mouseButtonReleased, the window that got the event, the button that was pressed, the scroll value, if it was a press (else it's a release) */
typedef void (* RGFW_mousebuttonfunc)(RGFW_window* win, u8 button, double scroll, b8 pressed);
-/* RGFW_jsButtonPressed / RGFW_jsButtonReleased, the window that got the event, the button that was pressed, the scroll value, if it was a press (else it's a release) */
+/*! RGFW_jsButtonPressed / RGFW_jsButtonReleased, the window that got the event, the button that was pressed, the scroll value, if it was a press (else it's a release) */
typedef void (* RGFW_jsButtonfunc)(RGFW_window* win, u16 joystick, u8 button, b8 pressed);
-/* RGFW_jsAxisMove, the window that got the event, the joystick in question, the axis values and the amount of axises */
+/*! RGFW_jsAxisMove, the window that got the event, the joystick in question, the axis values and the amount of axises */
typedef void (* RGFW_jsAxisfunc)(RGFW_window* win, u16 joystick, RGFW_point axis[2], u8 axisesCount);
-/* RGFW_dnd, the window that had the drop, the drop data and the amount files dropped */
+
+/*! RGFW_dnd, the window that had the drop, the drop data and the amount files dropped returns previous callback function (if it was set) */
#ifdef RGFW_ALLOC_DROPFILES
typedef void (* RGFW_dndfunc)(RGFW_window* win, char** droppedFiles, u32 droppedFilesCount);
#else
typedef void (* RGFW_dndfunc)(RGFW_window* win, char droppedFiles[RGFW_MAX_DROPS][RGFW_MAX_PATH], u32 droppedFilesCount);
#endif
-/* set callback for a window move event */
-RGFWDEF void RGFW_setWindowMoveCallback(RGFW_windowmovefunc func);
-/* set callbacksfor a window resize event */
-RGFWDEF void RGFW_setWindowResizeCallback(RGFW_windowresizefunc func);
-/* set callbacksfor a window quit event */
-RGFWDEF void RGFW_setWindowQuitCallback(RGFW_windowquitfunc func);
-/* set callbacksfor a mouse move event */
-RGFWDEF void RGFW_setMousePosCallback(RGFW_mouseposfunc func);
-/* set callbacksfor a window refresh event */
-RGFWDEF void RGFW_setWindowRefreshCallback(RGFW_windowrefreshfunc func);
-/* set callbacksfor a window focus change event */
-RGFWDEF void RGFW_setFocusCallback(RGFW_focusfunc func);
-/* set callbacksfor a mouse notify event */
-RGFWDEF void RGFW_setMouseNotifyCallBack(RGFW_mouseNotifyfunc func);
-/* set callbacksfor a drop event event */
-RGFWDEF void RGFW_setDndCallback(RGFW_dndfunc func);
-/* set callbacksfor a start of a drop event */
-RGFWDEF void RGFW_setDndInitCallback(RGFW_dndInitfunc func);
-/* set callbacksfor a key (press / release ) event */
-RGFWDEF void RGFW_setKeyCallback(RGFW_keyfunc func);
-/* set callbacksfor a mouse button (press / release ) event */
-RGFWDEF void RGFW_setMouseButtonCallback(RGFW_mousebuttonfunc func);
-/* set callbacksfor a controller button (press / release ) event */
-RGFWDEF void RGFW_setjsButtonCallback(RGFW_jsButtonfunc func);
-/* set callbacksfor a joystick axis mov event */
-RGFWDEF void RGFW_setjsAxisCallback(RGFW_jsAxisfunc func);
+/*! set callback for a window move event returns previous callback function (if it was set) */
+RGFWDEF RGFW_windowmovefunc RGFW_setWindowMoveCallback(RGFW_windowmovefunc func);
+/*! set callback for a window resize event returns previous callback function (if it was set) */
+RGFWDEF RGFW_windowresizefunc RGFW_setWindowResizeCallback(RGFW_windowresizefunc func);
+/*! set callback for a window quit event returns previous callback function (if it was set) */
+RGFWDEF RGFW_windowquitfunc RGFW_setWindowQuitCallback(RGFW_windowquitfunc func);
+/*! set callback for a mouse move event returns previous callback function (if it was set) */
+RGFWDEF RGFW_mouseposfunc RGFW_setMousePosCallback(RGFW_mouseposfunc func);
+/*! set callback for a window refresh event returns previous callback function (if it was set) */
+RGFWDEF RGFW_windowrefreshfunc RGFW_setWindowRefreshCallback(RGFW_windowrefreshfunc func);
+/*! set callback for a window focus change event returns previous callback function (if it was set) */
+RGFWDEF RGFW_focusfunc RGFW_setFocusCallback(RGFW_focusfunc func);
+/*! set callback for a mouse notify event returns previous callback function (if it was set) */
+RGFWDEF RGFW_mouseNotifyfunc RGFW_setMouseNotifyCallBack(RGFW_mouseNotifyfunc func);
+/*! set callback for a drop event event returns previous callback function (if it was set) */
+RGFWDEF RGFW_dndfunc RGFW_setDndCallback(RGFW_dndfunc func);
+/*! set callback for a start of a drop event returns previous callback function (if it was set) */
+RGFWDEF RGFW_dndInitfunc RGFW_setDndInitCallback(RGFW_dndInitfunc func);
+/*! set callback for a key (press / release ) event returns previous callback function (if it was set) */
+RGFWDEF RGFW_keyfunc RGFW_setKeyCallback(RGFW_keyfunc func);
+/*! set callback for a mouse button (press / release ) event returns previous callback function (if it was set) */
+RGFWDEF RGFW_mousebuttonfunc RGFW_setMouseButtonCallback(RGFW_mousebuttonfunc func);
+/*! set callback for a controller button (press / release ) event returns previous callback function (if it was set) */
+RGFWDEF RGFW_jsButtonfunc RGFW_setjsButtonCallback(RGFW_jsButtonfunc func);
+/*! set callback for a joystick axis mov event returns previous callback function (if it was set) */
+RGFWDEF RGFW_jsAxisfunc RGFW_setjsAxisCallback(RGFW_jsAxisfunc func);
+/** @} */
+
+/** * @defgroup Threads
+* @{ */
#ifndef RGFW_NO_THREADS
/*! threading functions*/
@@ -851,7 +919,10 @@ RGFWDEF void RGFW_setjsAxisCallback(RGFW_jsAxisfunc func);
RGFWDEF void RGFW_setThreadPriority(RGFW_thread thread, u8 priority); /*!< sets the priority priority */
#endif
-/*! gamepad/joystick functions (linux-only currently) */
+/** @} */
+
+/** * @defgroup joystick
+* @{ */
/*! joystick count starts at 0*/
/*!< register joystick to window based on a number (the number is based on when it was connected eg. /dev/js0)*/
@@ -860,27 +931,45 @@ RGFWDEF u16 RGFW_registerJoystickF(RGFW_window* win, char* file);
RGFWDEF u32 RGFW_isPressedJS(RGFW_window* win, u16 controller, u8 button);
+/** @} */
+
+/** * @defgroup graphics_API
+* @{ */
+
+/*!< make the window the current opengl drawing context
+
+ NOTE:
+ if you want to switch the graphics context's thread,
+ you have to run RGFW_window_makeCurrent(NULL); on the old thread
+ then RGFW_window_makeCurrent(valid_window) on the new thread
+*/
+RGFWDEF void RGFW_window_makeCurrent(RGFW_window* win);
+
+/*< updates fps / sets fps to cap (must by ran manually by the user at the end of a frame), returns current fps */
+RGFWDEF u32 RGFW_window_checkFPS(RGFW_window* win, u32 fpsCap);
+
/* supports openGL, directX, OSMesa, EGL and software rendering */
-RGFWDEF void RGFW_window_swapBuffers(RGFW_window* win); /* swap the rendering buffer */
+RGFWDEF void RGFW_window_swapBuffers(RGFW_window* win); /*!< swap the rendering buffer */
RGFWDEF void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval);
RGFWDEF void RGFW_window_setGPURender(RGFW_window* win, i8 set);
RGFWDEF void RGFW_window_setCPURender(RGFW_window* win, i8 set);
/*! native API functions */
-#ifdef RGFW_OPENGL
- /*! Get max OpenGL version */
- RGFWDEF u8* RGFW_getMaxGLVersion(void);
- /* OpenGL init hints */
- RGFWDEF void RGFW_setGLStencil(i32 stencil); /* set stencil buffer bit size (8 by default) */
- RGFWDEF void RGFW_setGLSamples(i32 samples); /* set number of sampiling buffers (4 by default) */
- RGFWDEF void RGFW_setGLStereo(i32 stereo); /* use GL_STEREO (GL_FALSE by default) */
- RGFWDEF void RGFW_setGLAuxBuffers(i32 auxBuffers); /* number of aux buffers (0 by default) */
+#if defined(RGFW_OPENGL) || defined(RGFW_EGL)
+ /*! OpenGL init hints */
+ RGFWDEF void RGFW_setGLStencil(i32 stencil); /*!< set stencil buffer bit size (8 by default) */
+ RGFWDEF void RGFW_setGLSamples(i32 samples); /*!< set number of sampiling buffers (4 by default) */
+ RGFWDEF void RGFW_setGLStereo(i32 stereo); /*!< use GL_STEREO (GL_FALSE by default) */
+ RGFWDEF void RGFW_setGLAuxBuffers(i32 auxBuffers); /*!< number of aux buffers (0 by default) */
- /*! Set OpenGL version hint */
- RGFWDEF void RGFW_setGLVersion(i32 major, i32 minor);
- RGFWDEF void* RGFW_getProcAddress(const char* procname); /* get native opengl proc address */
- RGFWDEF void RGFW_window_makeCurrent_OpenGL(RGFW_window* win); /* to be called by RGFW_window_makeCurrent */
+ /*! which profile to use for the opengl verion */
+ typedef RGFW_ENUM(u8, RGFW_GL_profile) { RGFW_GL_CORE = 0, RGFW_GL_COMPATIBILITY };
+ /*! Set OpenGL version hint (core or compatibility profile)*/
+ RGFWDEF void RGFW_setGLVersion(RGFW_GL_profile profile, i32 major, i32 minor);
+ RGFWDEF void RGFW_setDoubleBuffer(b8 useDoubleBuffer);
+ RGFWDEF void* RGFW_getProcAddress(const char* procname); /*!< get native opengl proc address */
+ RGFWDEF void RGFW_window_makeCurrent_OpenGL(RGFW_window* win); /*!< to be called by RGFW_window_makeCurrent */
#elif defined(RGFW_DIRECTX)
typedef struct {
IDXGIFactory* pFactory;
@@ -896,13 +985,15 @@ RGFWDEF void RGFW_window_setCPURender(RGFW_window* win, i8 set);
RGFWDEF RGFW_directXinfo* RGFW_getDirectXInfo(void);
#endif
-/*! Supporting functions */
-RGFWDEF void RGFW_window_checkFPS(RGFW_window* win); /*!< updates fps / sets fps to cap (ran by RGFW_window_checkEvent)*/
-RGFWDEF u64 RGFW_getTime(void); /* get time in seconds */
-RGFWDEF u64 RGFW_getTimeNS(void); /* get time in nanoseconds */
-RGFWDEF void RGFW_sleep(u64 milisecond); /* sleep for a set time */
+/** @} */
-/*
+/** * @defgroup Supporting
+* @{ */
+RGFWDEF u64 RGFW_getTime(void); /*!< get time in seconds */
+RGFWDEF u64 RGFW_getTimeNS(void); /*!< get time in nanoseconds */
+RGFWDEF void RGFW_sleep(u64 milisecond); /*!< sleep for a set time */
+
+/*!
key codes and mouse icon enums
*/
@@ -1019,6 +1110,7 @@ typedef RGFW_ENUM(u8, RGFW_Key) {
final_key,
};
+
typedef RGFW_ENUM(u8, RGFW_mouseIcons) {
RGFW_MOUSE_NORMAL = 0,
RGFW_MOUSE_ARROW,
@@ -1033,6 +1125,8 @@ typedef RGFW_ENUM(u8, RGFW_mouseIcons) {
RGFW_MOUSE_NOT_ALLOWED,
};
+/** @} */
+
#endif /* RGFW_HEADER */
/*
@@ -1092,15 +1186,18 @@ int main() {
*/
#ifdef RGFW_X11
- #define RGFW_OS_BASED_VALUE(l, w, m, a) l
+ #define RGFW_OS_BASED_VALUE(l, w, m, h, ww) l
#elif defined(RGFW_WINDOWS)
- #define RGFW_OS_BASED_VALUE(l, w, m, a) w
+ #define RGFW_OS_BASED_VALUE(l, w, m, h, ww) w
#elif defined(RGFW_MACOS)
- #define RGFW_OS_BASED_VALUE(l, w, m, a) m
+ #define RGFW_OS_BASED_VALUE(l, w, m, h, ww) m
#elif defined(RGFW_WEBASM)
- #define RGFW_OS_BASED_VALUE(l, w, m, a) a
+ #define RGFW_OS_BASED_VALUE(l, w, m, h, ww) h
+#elif defined(RGFW_WAYLAND)
+ #define RGFW_OS_BASED_VALUE(l, w, m, h, ww) ww
#endif
+
#ifdef RGFW_IMPLEMENTATION
#include
@@ -1119,120 +1216,147 @@ This is the start of keycode data
MacOS -> windows and linux already don't have keycodes as macros, so there's no point
*/
-u8 RGFW_keycodes[] = {
- [RGFW_OS_BASED_VALUE(49, 192, 50, DOM_VK_BACK_QUOTE)] = RGFW_Backtick,
- [RGFW_OS_BASED_VALUE(19, 0x30, 29, DOM_VK_0)] = RGFW_0,
- [RGFW_OS_BASED_VALUE(10, 0x31, 18, DOM_VK_1)] = RGFW_1,
- [RGFW_OS_BASED_VALUE(11, 0x32, 19, DOM_VK_2)] = RGFW_2,
- [RGFW_OS_BASED_VALUE(12, 0x33, 20, DOM_VK_3)] = RGFW_3,
- [RGFW_OS_BASED_VALUE(13, 0x34, 21, DOM_VK_4)] = RGFW_4,
- [RGFW_OS_BASED_VALUE(14, 0x35, 23, DOM_VK_5)] = RGFW_5,
- [RGFW_OS_BASED_VALUE(15, 0x36, 22, DOM_VK_6)] = RGFW_6,
- [RGFW_OS_BASED_VALUE(16, 0x37, 26, DOM_VK_7)] = RGFW_7,
- [RGFW_OS_BASED_VALUE(17, 0x38, 28, DOM_VK_8)] = RGFW_8,
- [RGFW_OS_BASED_VALUE(18, 0x39, 25, DOM_VK_9)] = RGFW_9,
- [RGFW_OS_BASED_VALUE(65, 0x20, 49, DOM_VK_SPACE)] = RGFW_Space,
+/*
+ the c++ compiler doesn't support setting up an array like,
+ we'll have to do it during runtime using a function & this messy setup
+*/
+#ifndef __cplusplus
+#define RGFW_NEXT ,
+#define RGFW_MAP
+#else
+#define RGFW_NEXT ;
+#define RGFW_MAP RGFW_keycodes
+#endif
- [RGFW_OS_BASED_VALUE(38, 0x41, 0, DOM_VK_A)] = RGFW_a,
- [RGFW_OS_BASED_VALUE(56, 0x42, 11, DOM_VK_B)] = RGFW_b,
- [RGFW_OS_BASED_VALUE(54, 0x43, 8, DOM_VK_C)] = RGFW_c,
- [RGFW_OS_BASED_VALUE(40, 0x44, 2, DOM_VK_D)] = RGFW_d,
- [RGFW_OS_BASED_VALUE(26, 0x45, 14, DOM_VK_E)] = RGFW_e,
- [RGFW_OS_BASED_VALUE(41, 0x46, 3, DOM_VK_F)] = RGFW_f,
- [RGFW_OS_BASED_VALUE(42, 0x47, 5, DOM_VK_G)] = RGFW_g,
- [RGFW_OS_BASED_VALUE(43, 0x48, 4, DOM_VK_H)] = RGFW_h,
- [RGFW_OS_BASED_VALUE(31, 0x49, 34, DOM_VK_I)] = RGFW_i,
- [RGFW_OS_BASED_VALUE(44, 0x4A, 38, DOM_VK_J)] = RGFW_j,
- [RGFW_OS_BASED_VALUE(45, 0x4B, 40, DOM_VK_K)] = RGFW_k,
- [RGFW_OS_BASED_VALUE(46, 0x4C, 37, DOM_VK_L)] = RGFW_l,
- [RGFW_OS_BASED_VALUE(58, 0x4D, 46, DOM_VK_M)] = RGFW_m,
- [RGFW_OS_BASED_VALUE(57, 0x4E, 45, DOM_VK_N)] = RGFW_n,
- [RGFW_OS_BASED_VALUE(32, 0x4F, 31, DOM_VK_O)] = RGFW_o,
- [RGFW_OS_BASED_VALUE(33, 0x50, 35, DOM_VK_P)] = RGFW_p,
- [RGFW_OS_BASED_VALUE(24, 0x51, 12, DOM_VK_Q)] = RGFW_q,
- [RGFW_OS_BASED_VALUE(27, 0x52, 15, DOM_VK_R)] = RGFW_r,
- [RGFW_OS_BASED_VALUE(39, 0x53, 1, DOM_VK_S)] = RGFW_s,
- [RGFW_OS_BASED_VALUE(28, 0x54, 17, DOM_VK_T)] = RGFW_t,
- [RGFW_OS_BASED_VALUE(30, 0x55, 32, DOM_VK_U)] = RGFW_u,
- [RGFW_OS_BASED_VALUE(55, 0x56, 9, DOM_VK_V)] = RGFW_v,
- [RGFW_OS_BASED_VALUE(25, 0x57, 13, DOM_VK_W)] = RGFW_w,
- [RGFW_OS_BASED_VALUE(53, 0x58, 7, DOM_VK_X)] = RGFW_x,
- [RGFW_OS_BASED_VALUE(29, 0x59, 16, DOM_VK_Y)] = RGFW_y,
- [RGFW_OS_BASED_VALUE(52, 0x5A, 6, DOM_VK_Z)] = RGFW_z,
+#ifdef RGFW_WAYLAND
+#include
+#endif
- [RGFW_OS_BASED_VALUE(60, 190, 47, DOM_VK_PERIOD)] = RGFW_Period,
- [RGFW_OS_BASED_VALUE(59, 188, 43, DOM_VK_COMMA)] = RGFW_Comma,
- [RGFW_OS_BASED_VALUE(61, 191, 44, DOM_VK_SLASH)] = RGFW_Slash,
- [RGFW_OS_BASED_VALUE(34, 219, 33, DOM_VK_OPEN_BRACKET)] = RGFW_Bracket,
- [RGFW_OS_BASED_VALUE(35, 221, 30, DOM_VK_CLOSE_BRACKET)] = RGFW_CloseBracket,
- [RGFW_OS_BASED_VALUE(47, 186, 41, DOM_VK_SEMICOLON)] = RGFW_Semicolon,
- [RGFW_OS_BASED_VALUE(48, 222, 39, DOM_VK_QUOTE)] = RGFW_Quote,
- [RGFW_OS_BASED_VALUE(51, 322, 42, DOM_VK_BACK_SLASH)] = RGFW_BackSlash,
+u8 RGFW_keycodes [RGFW_OS_BASED_VALUE(136, 337, 128, DOM_VK_WIN_OEM_CLEAR + 1, 130)] = {
+#ifdef __cplusplus
+ 0
+};
+void RGFW_init_keys(void) {
+#endif
+ RGFW_MAP [RGFW_OS_BASED_VALUE(49, 192, 50, DOM_VK_BACK_QUOTE, KEY_GRAVE)] = RGFW_Backtick RGFW_NEXT
+
+ RGFW_MAP [RGFW_OS_BASED_VALUE(19, 0x30, 29, DOM_VK_0, KEY_0)] = RGFW_0 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(10, 0x31, 18, DOM_VK_1, KEY_1)] = RGFW_1 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(11, 0x32, 19, DOM_VK_2, KEY_2)] = RGFW_2 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(12, 0x33, 20, DOM_VK_3, KEY_3)] = RGFW_3 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(13, 0x34, 21, DOM_VK_4, KEY_4)] = RGFW_4 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(14, 0x35, 23, DOM_VK_5, KEY_5)] = RGFW_5 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(15, 0x36, 22, DOM_VK_6, KEY_6)] = RGFW_6 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(16, 0x37, 26, DOM_VK_7, KEY_7)] = RGFW_7 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(17, 0x38, 28, DOM_VK_8, KEY_8)] = RGFW_8 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(18, 0x39, 25, DOM_VK_9, KEY_9)] = RGFW_9,
+
+ RGFW_MAP [RGFW_OS_BASED_VALUE(65, 0x20, 49, DOM_VK_SPACE, KEY_SPACE)] = RGFW_Space,
+
+ RGFW_MAP [RGFW_OS_BASED_VALUE(38, 0x41, 0, DOM_VK_A, KEY_A)] = RGFW_a RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(56, 0x42, 11, DOM_VK_B, KEY_B)] = RGFW_b RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(54, 0x43, 8, DOM_VK_C, KEY_C)] = RGFW_c RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(40, 0x44, 2, DOM_VK_D, KEY_D)] = RGFW_d RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(26, 0x45, 14, DOM_VK_E, KEY_E)] = RGFW_e RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(41, 0x46, 3, DOM_VK_F, KEY_F)] = RGFW_f RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(42, 0x47, 5, DOM_VK_G, KEY_G)] = RGFW_g RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(43, 0x48, 4, DOM_VK_H, KEY_H)] = RGFW_h RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(31, 0x49, 34, DOM_VK_I, KEY_I)] = RGFW_i RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(44, 0x4A, 38, DOM_VK_J, KEY_J)] = RGFW_j RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(45, 0x4B, 40, DOM_VK_K, KEY_K)] = RGFW_k RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(46, 0x4C, 37, DOM_VK_L, KEY_L)] = RGFW_l RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(58, 0x4D, 46, DOM_VK_M, KEY_M)] = RGFW_m RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(57, 0x4E, 45, DOM_VK_N, KEY_N)] = RGFW_n RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(32, 0x4F, 31, DOM_VK_O, KEY_O)] = RGFW_o RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(33, 0x50, 35, DOM_VK_P, KEY_P)] = RGFW_p RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(24, 0x51, 12, DOM_VK_Q, KEY_Q)] = RGFW_q RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(27, 0x52, 15, DOM_VK_R, KEY_R)] = RGFW_r RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(39, 0x53, 1, DOM_VK_S, KEY_S)] = RGFW_s RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(28, 0x54, 17, DOM_VK_T, KEY_T)] = RGFW_t RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(30, 0x55, 32, DOM_VK_U, KEY_U)] = RGFW_u RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(55, 0x56, 9, DOM_VK_V, KEY_V)] = RGFW_v RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(25, 0x57, 13, DOM_VK_W, KEY_W)] = RGFW_w RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(53, 0x58, 7, DOM_VK_X, KEY_X)] = RGFW_x RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(29, 0x59, 16, DOM_VK_Y, KEY_Y)] = RGFW_y RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(52, 0x5A, 6, DOM_VK_Z, KEY_Z)] = RGFW_z,
+
+ RGFW_MAP [RGFW_OS_BASED_VALUE(60, 190, 47, DOM_VK_PERIOD, KEY_DOT)] = RGFW_Period RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(59, 188, 43, DOM_VK_COMMA, KEY_COMMA)] = RGFW_Comma RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(61, 191, 44, DOM_VK_SLASH, KEY_SLASH)] = RGFW_Slash RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(34, 219, 33, DOM_VK_OPEN_BRACKET, KEY_LEFTBRACE)] = RGFW_Bracket RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(35, 221, 30, DOM_VK_CLOSE_BRACKET, KEY_RIGHTBRACE)] = RGFW_CloseBracket RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(47, 186, 41, DOM_VK_SEMICOLON, KEY_SEMICOLON)] = RGFW_Semicolon RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(48, 222, 39, DOM_VK_QUOTE, KEY_APOSTROPHE)] = RGFW_Quote RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(51, 322, 42, DOM_VK_BACK_SLASH, KEY_BACKSLASH)] = RGFW_BackSlash,
- [RGFW_OS_BASED_VALUE(36, 0x0D, 36, DOM_VK_RETURN)] = RGFW_Return,
- [RGFW_OS_BASED_VALUE(119, 0x2E, 118, DOM_VK_DELETE)] = RGFW_Delete,
- [RGFW_OS_BASED_VALUE(77, 0x90, 72, DOM_VK_NUM_LOCK)] = RGFW_Numlock,
- [RGFW_OS_BASED_VALUE(106, 0x6F, 82, DOM_VK_DIVIDE)] = RGFW_KP_Slash,
- [RGFW_OS_BASED_VALUE(63, 0x6A, 76, DOM_VK_MULTIPLY)] = RGFW_Multiply,
- [RGFW_OS_BASED_VALUE(82, 0x6D, 67, DOM_VK_SUBTRACT)] = RGFW_KP_Minus,
- [RGFW_OS_BASED_VALUE(87, 0x61, 84, DOM_VK_NUMPAD1)] = RGFW_KP_1,
- [RGFW_OS_BASED_VALUE(88, 0x62, 85, DOM_VK_NUMPAD2)] = RGFW_KP_2,
- [RGFW_OS_BASED_VALUE(89, 0x63, 86, DOM_VK_NUMPAD3)] = RGFW_KP_3,
- [RGFW_OS_BASED_VALUE(83, 0x64, 87, DOM_VK_NUMPAD4)] = RGFW_KP_4,
- [RGFW_OS_BASED_VALUE(84, 0x65, 88, DOM_VK_NUMPAD5)] = RGFW_KP_5,
- [RGFW_OS_BASED_VALUE(85, 0x66, 89, DOM_VK_NUMPAD6)] = RGFW_KP_6,
- [RGFW_OS_BASED_VALUE(79, 0x67, 90, DOM_VK_NUMPAD7)] = RGFW_KP_7,
- [RGFW_OS_BASED_VALUE(80, 0x68, 92, DOM_VK_NUMPAD8)] = RGFW_KP_8,
- [RGFW_OS_BASED_VALUE(81, 0x69, 93, DOM_VK_NUMPAD9)] = RGFW_KP_9,
- [RGFW_OS_BASED_VALUE(90, 0x60, 83, DOM_VK_NUMPAD0)] = RGFW_KP_0,
- [RGFW_OS_BASED_VALUE(91, 0x6E, 65, DOM_VK_DECIMAL)] = RGFW_KP_Period,
- [RGFW_OS_BASED_VALUE(104, 0x92, 77, 0)] = RGFW_KP_Return,
+ RGFW_MAP [RGFW_OS_BASED_VALUE(36, 0x0D, 36, DOM_VK_RETURN, KEY_ENTER)] = RGFW_Return RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(119, 0x2E, 118, DOM_VK_DELETE, KEY_DELETE)] = RGFW_Delete RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(77, 0x90, 72, DOM_VK_NUM_LOCK, KEY_NUMLOCK)] = RGFW_Numlock RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(106, 0x6F, 82, DOM_VK_DIVIDE, KEY_KPSLASH)] = RGFW_KP_Slash RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(63, 0x6A, 76, DOM_VK_MULTIPLY, KEY_KPASTERISK)] = RGFW_Multiply RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(82, 0x6D, 67, DOM_VK_SUBTRACT, KEY_KPMINUS)] = RGFW_KP_Minus RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(87, 0x61, 84, DOM_VK_NUMPAD1, KEY_KP1)] = RGFW_KP_1 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(88, 0x62, 85, DOM_VK_NUMPAD2, KEY_KP2)] = RGFW_KP_2 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(89, 0x63, 86, DOM_VK_NUMPAD3, KEY_KP3)] = RGFW_KP_3 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(83, 0x64, 87, DOM_VK_NUMPAD4, KEY_KP4)] = RGFW_KP_4 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(84, 0x65, 88, DOM_VK_NUMPAD5, KEY_KP5)] = RGFW_KP_5 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(85, 0x66, 89, DOM_VK_NUMPAD6, KEY_KP6)] = RGFW_KP_6 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(79, 0x67, 90, DOM_VK_NUMPAD7, KEY_KP7)] = RGFW_KP_7 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(80, 0x68, 92, DOM_VK_NUMPAD8, KEY_KP8)] = RGFW_KP_8 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(81, 0x69, 93, DOM_VK_NUMPAD9, KEY_KP9)] = RGFW_KP_9 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(90, 0x60, 83, DOM_VK_NUMPAD0, KEY_KP0)] = RGFW_KP_0 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(91, 0x6E, 65, DOM_VK_DECIMAL, KEY_KPDOT)] = RGFW_KP_Period RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(104, 0x92, 77, 0, KEY_KPENTER)] = RGFW_KP_Return,
- [RGFW_OS_BASED_VALUE(20, 189, 27, DOM_VK_HYPHEN_MINUS)] = RGFW_Minus,
- [RGFW_OS_BASED_VALUE(21, 187, 24, DOM_VK_EQUALS)] = RGFW_Equals,
- [RGFW_OS_BASED_VALUE(22, 8, 51, DOM_VK_BACK_SPACE)] = RGFW_BackSpace,
- [RGFW_OS_BASED_VALUE(23, 0x09, 48, DOM_VK_TAB)] = RGFW_Tab,
- [RGFW_OS_BASED_VALUE(66, 20, 57, DOM_VK_CAPS_LOCK)] = RGFW_CapsLock,
- [RGFW_OS_BASED_VALUE(50, 0xA0, 56, DOM_VK_SHIFT)] = RGFW_ShiftL,
- [RGFW_OS_BASED_VALUE(37, 0x11, 59, DOM_VK_CONTROL)] = RGFW_ControlL,
- [RGFW_OS_BASED_VALUE(64, 164, 58, DOM_VK_ALT)] = RGFW_AltL,
- [RGFW_OS_BASED_VALUE(133, 0x5B, 55, DOM_VK_WIN)] = RGFW_SuperL,
+ RGFW_MAP [RGFW_OS_BASED_VALUE(20, 189, 27, DOM_VK_HYPHEN_MINUS, KEY_MINUS)] = RGFW_Minus RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(21, 187, 24, DOM_VK_EQUALS, KEY_EQUAL)] = RGFW_Equals RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(22, 8, 51, DOM_VK_BACK_SPACE, KEY_BACKSPACE)] = RGFW_BackSpace RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(23, 0x09, 48, DOM_VK_TAB, KEY_TAB)] = RGFW_Tab RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(66, 20, 57, DOM_VK_CAPS_LOCK, KEY_CAPSLOCK)] = RGFW_CapsLock RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(50, 0x10, 56, DOM_VK_SHIFT, KEY_LEFTSHIFT)] = RGFW_ShiftL RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(37, 0x11, 59, DOM_VK_CONTROL, KEY_LEFTCTRL)] = RGFW_ControlL RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(64,0x12, 58, DOM_VK_ALT, KEY_LEFTALT)] = RGFW_AltL RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(133, 0x5B, 55, DOM_VK_WIN, KEY_LEFTMETA)] = RGFW_SuperL,
#if !defined(RGFW_WINDOWS) && !defined(RGFW_MACOS) && !defined(RGFW_WEBASM)
- [RGFW_OS_BASED_VALUE(105, 0x11, 59, 0)] = RGFW_ControlR,
- [RGFW_OS_BASED_VALUE(135, 0xA4, 55, 0)] = RGFW_SuperR,
+ RGFW_MAP [RGFW_OS_BASED_VALUE(105, 0x11, 59, 0, KEY_RIGHTCTRL)] = RGFW_ControlR RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(135, 0xA4, 55, 0, KEY_RIGHTMETA)] = RGFW_SuperR,
+ RGFW_MAP [RGFW_OS_BASED_VALUE(62, 0x5C, 56, 0, KEY_RIGHTSHIFT)] = RGFW_ShiftR RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(108, 165, 58, 0, KEY_RIGHTALT)] = RGFW_AltR,
#endif
- #if !defined(RGFW_MACOS) && !defined(RGFW_WEBASM)
- [RGFW_OS_BASED_VALUE(62, 0x5C, 56, 0)] = RGFW_ShiftR,
- [RGFW_OS_BASED_VALUE(108, 165, 58, 0)] = RGFW_AltR,
- #endif
-
- [RGFW_OS_BASED_VALUE(67, 0x70, 127, DOM_VK_F1)] = RGFW_F1,
- [RGFW_OS_BASED_VALUE(68, 0x71, 121, DOM_VK_F2)] = RGFW_F2,
- [RGFW_OS_BASED_VALUE(69, 0x72, 100, DOM_VK_F3)] = RGFW_F3,
- [RGFW_OS_BASED_VALUE(70, 0x73, 119, DOM_VK_F4)] = RGFW_F4,
- [RGFW_OS_BASED_VALUE(71, 0x74, 97, DOM_VK_F5)] = RGFW_F5,
- [RGFW_OS_BASED_VALUE(72, 0x75, 98, DOM_VK_F6)] = RGFW_F6,
- [RGFW_OS_BASED_VALUE(73, 0x76, 99, DOM_VK_F7)] = RGFW_F7,
- [RGFW_OS_BASED_VALUE(74, 0x77, 101, DOM_VK_F8)] = RGFW_F8,
- [RGFW_OS_BASED_VALUE(75, 0x78, 102, DOM_VK_F9)] = RGFW_F9,
- [RGFW_OS_BASED_VALUE(76, 0x79, 110, DOM_VK_F10)] = RGFW_F10,
- [RGFW_OS_BASED_VALUE(95, 0x7A, 104, DOM_VK_F11)] = RGFW_F11,
- [RGFW_OS_BASED_VALUE(96, 0x7B, 112, DOM_VK_F12)] = RGFW_F12,
- [RGFW_OS_BASED_VALUE(111, 0x26, 126, DOM_VK_UP)] = RGFW_Up,
- [RGFW_OS_BASED_VALUE(116, 0x28, 125, DOM_VK_DOWN)] = RGFW_Down,
- [RGFW_OS_BASED_VALUE(113, 0x25, 123, DOM_VK_LEFT)] = RGFW_Left,
- [RGFW_OS_BASED_VALUE(114, 0x27, 124, DOM_VK_RIGHT)] = RGFW_Right,
- [RGFW_OS_BASED_VALUE(118, 0x2D, 115, DOM_VK_INSERT)] = RGFW_Insert,
- [RGFW_OS_BASED_VALUE(115, 0x23, 120, DOM_VK_END)] = RGFW_End,
- [RGFW_OS_BASED_VALUE(112, 336, 117, DOM_VK_PAGE_UP)] = RGFW_PageUp,
- [RGFW_OS_BASED_VALUE(117, 325, 122, DOM_VK_PAGE_DOWN)] = RGFW_PageDown,
- [RGFW_OS_BASED_VALUE(9, 0x1B, 53, DOM_VK_ESCAPE)] = RGFW_Escape,
- [RGFW_OS_BASED_VALUE(110, 0x24, 116, DOM_VK_HOME)] = RGFW_Home,
+ RGFW_MAP [RGFW_OS_BASED_VALUE(67, 0x70, 127, DOM_VK_F1, KEY_F1)] = RGFW_F1 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(68, 0x71, 121, DOM_VK_F2, KEY_F2)] = RGFW_F2 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(69, 0x72, 100, DOM_VK_F3, KEY_F3)] = RGFW_F3 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(70, 0x73, 119, DOM_VK_F4, KEY_F4)] = RGFW_F4 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(71, 0x74, 97, DOM_VK_F5, KEY_F5)] = RGFW_F5 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(72, 0x75, 98, DOM_VK_F6, KEY_F6)] = RGFW_F6 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(73, 0x76, 99, DOM_VK_F7, KEY_F7)] = RGFW_F7 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(74, 0x77, 101, DOM_VK_F8, KEY_F8)] = RGFW_F8 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(75, 0x78, 102, DOM_VK_F9, KEY_F9)] = RGFW_F9 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(76, 0x79, 110, DOM_VK_F10, KEY_F10)] = RGFW_F10 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(95, 0x7A, 104, DOM_VK_F11, KEY_F11)] = RGFW_F11 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(96, 0x7B, 112, DOM_VK_F12, KEY_F12)] = RGFW_F12 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(111, 0x26, 126, DOM_VK_UP, KEY_UP)] = RGFW_Up RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(116, 0x28, 125, DOM_VK_DOWN, KEY_DOWN)] = RGFW_Down RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(113, 0x25, 123, DOM_VK_LEFT, KEY_LEFT)] = RGFW_Left RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(114, 0x27, 124, DOM_VK_RIGHT, KEY_RIGHT)] = RGFW_Right RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(118, 0x2D, 115, DOM_VK_INSERT, KEY_INSERT)] = RGFW_Insert RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(115, 0x23, 120, DOM_VK_END, KEY_END)] = RGFW_End RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(112, 336, 117, DOM_VK_PAGE_UP, KEY_PAGEUP)] = RGFW_PageUp RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(117, 325, 122, DOM_VK_PAGE_DOWN, KEY_PAGEDOWN)] = RGFW_PageDown RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(9, 0x1B, 53, DOM_VK_ESCAPE, KEY_ESC)] = RGFW_Escape RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(110, 0x24, 116, DOM_VK_HOME, KEY_HOME)] = RGFW_Home RGFW_NEXT
+#ifndef __cplusplus
};
+#else
+}
+#endif
+
+#undef RGFW_NEXT
+#undef RGFW_MAP
typedef struct {
b8 current : 1;
@@ -1244,6 +1368,12 @@ RGFW_keyState RGFW_keyboard[final_key] = { {0, 0} };
RGFWDEF u32 RGFW_apiKeyCodeToRGFW(u32 keycode);
u32 RGFW_apiKeyCodeToRGFW(u32 keycode) {
+ #ifdef __cplusplus
+ if (RGFW_OS_BASED_VALUE(49, 192, 50, DOM_VK_BACK_QUOTE, KEY_GRAVE) != RGFW_Backtick) {
+ RGFW_init_keys();
+ }
+ #endif
+
/* make sure the key isn't out of bounds */
if (keycode > sizeof(RGFW_keycodes) / sizeof(u8))
return 0;
@@ -1253,22 +1383,54 @@ u32 RGFW_apiKeyCodeToRGFW(u32 keycode) {
RGFWDEF void RGFW_resetKey(void);
void RGFW_resetKey(void) {
- size_t len = final_key; /* last_key == length */
+ size_t len = final_key; /*!< last_key == length */
- size_t i; /* reset each previous state */
+ size_t i; /*!< reset each previous state */
for (i = 0; i < len; i++)
RGFW_keyboard[i].prev = 0;
}
+b8 RGFW_shouldShift(u32 keycode, u8 lockState) {
+ #define RGFW_xor(x, y) (( (x) && (!(y)) ) || ((y) && (!(x)) ))
+ b8 caps4caps = (lockState & RGFW_CAPSLOCK) && ((keycode >= RGFW_a) && (keycode <= RGFW_z));
+ b8 shouldShift = RGFW_xor((RGFW_isPressed(NULL, RGFW_ShiftL) || RGFW_isPressed(NULL, RGFW_ShiftR)), caps4caps);
+ #undef RGFW_xor
+
+ return shouldShift;
+}
+
+char RGFW_keyCodeToChar(u32 keycode, b8 shift) {
+ static const char map[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '`', '0', '1', '2', '3', '4', '5', '6', '7', '8',
+ '9', '-', '=', 0, '\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, ' ', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '.', ',', '/', '[', ']', ';', '\n', '\'', '\\',
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '/', '*', '-', '1', '2', '3', '3', '5', '6', '7', '8', '9', '0', '\n'
+ };
+
+ static const char mapCaps[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '~', ')', '!', '@', '#', '$', '%', '^', '&', '*',
+ '(', '_', '+', 0, '0', 0, 0, 0, 0, 0, 0, 0, 0, 0, ' ', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
+ 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
+ 'X', 'Y', 'Z', '>', '<', '?', '{', '}', ':', '\n', '"', '|',
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '?', '*', '-', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+
+ if (shift == RGFW_FALSE)
+ return map[keycode];
+ return mapCaps[keycode];
+}
+
+char RGFW_keyCodeToCharAuto(u32 keycode, u8 lockState) { return RGFW_keyCodeToChar(keycode, RGFW_shouldShift(keycode, lockState)); }
+
/*
this is the end of keycode data
*/
/* joystick data */
-u8 RGFW_jsPressed[4][16]; /* if a key is currently pressed or not (per joystick) */
+u8 RGFW_jsPressed[4][16]; /*!< if a key is currently pressed or not (per joystick) */
-i32 RGFW_joysticks[4]; /* limit of 4 joysticks at a time */
-u16 RGFW_joystickCount; /* the actual amount of joysticks */
+i32 RGFW_joysticks[4]; /*!< limit of 4 joysticks at a time */
+u16 RGFW_joystickCount; /*!< the actual amount of joysticks */
/*
event callback defines start here
@@ -1325,19 +1487,73 @@ void RGFW_window_checkEvents(RGFW_window* win, i32 waitMS) {
#endif
}
-void RGFW_setWindowMoveCallback(RGFW_windowmovefunc func) { RGFW_windowMoveCallback = func; }
-void RGFW_setWindowResizeCallback(RGFW_windowresizefunc func) { RGFW_windowResizeCallback = func; }
-void RGFW_setWindowQuitCallback(RGFW_windowquitfunc func) { RGFW_windowQuitCallback = func; }
-void RGFW_setMousePosCallback(RGFW_mouseposfunc func) { RGFW_mousePosCallback = func; }
-void RGFW_setWindowRefreshCallback(RGFW_windowrefreshfunc func) { RGFW_windowRefreshCallback = func; }
-void RGFW_setFocusCallback(RGFW_focusfunc func) { RGFW_focusCallback = func; }
-void RGFW_setMouseNotifyCallBack(RGFW_mouseNotifyfunc func) { RGFW_mouseNotifyCallBack = func; }
-void RGFW_setDndCallback(RGFW_dndfunc func) { RGFW_dndCallback = func; }
-void RGFW_setDndInitCallback(RGFW_dndInitfunc func) { RGFW_dndInitCallback = func; }
-void RGFW_setKeyCallback(RGFW_keyfunc func) { RGFW_keyCallback = func; }
-void RGFW_setMouseButtonCallback(RGFW_mousebuttonfunc func) { RGFW_mouseButtonCallback = func; }
-void RGFW_setjsButtonCallback(RGFW_jsButtonfunc func) { RGFW_jsButtonCallback = func; }
-void RGFW_setjsAxisCallback(RGFW_jsAxisfunc func) { RGFW_jsAxisCallback = func; }
+RGFW_windowmovefunc RGFW_setWindowMoveCallback(RGFW_windowmovefunc func) {
+ RGFW_windowmovefunc prev = (RGFW_windowMoveCallback == RGFW_windowmovefuncEMPTY) ? NULL : RGFW_windowMoveCallback;
+ RGFW_windowMoveCallback = func;
+ return prev;
+}
+RGFW_windowresizefunc RGFW_setWindowResizeCallback(RGFW_windowresizefunc func) {
+ RGFW_windowresizefunc prev = (RGFW_windowResizeCallback == RGFW_windowresizefuncEMPTY) ? NULL : RGFW_windowResizeCallback;
+ RGFW_windowResizeCallback = func;
+ return prev;
+}
+RGFW_windowquitfunc RGFW_setWindowQuitCallback(RGFW_windowquitfunc func) {
+ RGFW_windowquitfunc prev = (RGFW_windowQuitCallback == RGFW_windowquitfuncEMPTY) ? NULL : RGFW_windowQuitCallback;
+ RGFW_windowQuitCallback = func;
+ return prev;
+}
+
+RGFW_mouseposfunc RGFW_setMousePosCallback(RGFW_mouseposfunc func) {
+ RGFW_mouseposfunc prev = (RGFW_mousePosCallback == RGFW_mouseposfuncEMPTY) ? NULL : RGFW_mousePosCallback;
+ RGFW_mousePosCallback = func;
+ return prev;
+}
+RGFW_windowrefreshfunc RGFW_setWindowRefreshCallback(RGFW_windowrefreshfunc func) {
+ RGFW_windowrefreshfunc prev = (RGFW_windowRefreshCallback == RGFW_windowrefreshfuncEMPTY) ? NULL : RGFW_windowRefreshCallback;
+ RGFW_windowRefreshCallback = func;
+ return prev;
+}
+RGFW_focusfunc RGFW_setFocusCallback(RGFW_focusfunc func) {
+ RGFW_focusfunc prev = (RGFW_focusCallback == RGFW_focusfuncEMPTY) ? NULL : RGFW_focusCallback;
+ RGFW_focusCallback = func;
+ return prev;
+}
+
+RGFW_mouseNotifyfunc RGFW_setMouseNotifyCallBack(RGFW_mouseNotifyfunc func) {
+ RGFW_mouseNotifyfunc prev = (RGFW_mouseNotifyCallBack == RGFW_mouseNotifyfuncEMPTY) ? NULL : RGFW_mouseNotifyCallBack;
+ RGFW_mouseNotifyCallBack = func;
+ return prev;
+}
+RGFW_dndfunc RGFW_setDndCallback(RGFW_dndfunc func) {
+ RGFW_dndfunc prev = (RGFW_dndCallback == RGFW_dndfuncEMPTY) ? NULL : RGFW_dndCallback;
+ RGFW_dndCallback = func;
+ return prev;
+}
+RGFW_dndInitfunc RGFW_setDndInitCallback(RGFW_dndInitfunc func) {
+ RGFW_dndInitfunc prev = (RGFW_dndInitCallback == RGFW_dndInitfuncEMPTY) ? NULL : RGFW_dndInitCallback;
+ RGFW_dndInitCallback = func;
+ return prev;
+}
+RGFW_keyfunc RGFW_setKeyCallback(RGFW_keyfunc func) {
+ RGFW_keyfunc prev = (RGFW_keyCallback == RGFW_keyfuncEMPTY) ? NULL : RGFW_keyCallback;
+ RGFW_keyCallback = func;
+ return prev;
+}
+RGFW_mousebuttonfunc RGFW_setMouseButtonCallback(RGFW_mousebuttonfunc func) {
+ RGFW_mousebuttonfunc prev = (RGFW_mouseButtonCallback == RGFW_mousebuttonfuncEMPTY) ? NULL : RGFW_mouseButtonCallback;
+ RGFW_mouseButtonCallback = func;
+ return prev;
+}
+RGFW_jsButtonfunc RGFW_setjsButtonCallback(RGFW_jsButtonfunc func) {
+ RGFW_jsButtonfunc prev = (RGFW_jsButtonCallback == RGFW_jsButtonfuncEMPTY) ? NULL : RGFW_jsButtonCallback;
+ RGFW_jsButtonCallback = func;
+ return prev;
+}
+RGFW_jsAxisfunc RGFW_setjsAxisCallback(RGFW_jsAxisfunc func) {
+ RGFW_jsAxisfunc prev = (RGFW_jsAxisCallback == RGFW_jsAxisfuncEMPTY) ? NULL : RGFW_jsAxisCallback;
+ RGFW_jsAxisCallback = func;
+ return prev;
+}
/*
no more event call back defines
*/
@@ -1368,7 +1584,7 @@ RGFWDEF RGFW_window* RGFW_window_basic_init(RGFW_rect rect, u16 args);
/* do a basic initialization for RGFW_window, this is to standard it for each OS */
RGFW_window* RGFW_window_basic_init(RGFW_rect rect, u16 args) {
- RGFW_window* win = (RGFW_window*) RGFW_MALLOC(sizeof(RGFW_window)); /* make a new RGFW struct */
+ RGFW_window* win = (RGFW_window*) RGFW_MALLOC(sizeof(RGFW_window)); /*!< make a new RGFW struct */
/* clear out dnd info */
#ifdef RGFW_ALLOC_DROPFILES
@@ -1386,7 +1602,7 @@ RGFW_window* RGFW_window_basic_init(RGFW_rect rect, u16 args) {
assert(win->src.display != NULL);
Screen* scrn = DefaultScreenOfDisplay((Display*)win->src.display);
- RGFW_area screenR = RGFW_AREA(scrn->width, scrn->height);
+ RGFW_area screenR = RGFW_AREA((u32)scrn->width, (u32)scrn->height);
#endif
/* rect based the requested args */
@@ -1398,7 +1614,6 @@ RGFW_window* RGFW_window_basic_init(RGFW_rect rect, u16 args) {
/* set and init the new window's data */
win->r = rect;
- win->fpsCap = 0;
win->event.inFocus = 1;
win->event.droppedFilesCount = 0;
RGFW_joystickCount = 0;
@@ -1424,7 +1639,7 @@ RGFW_window* RGFW_root = NULL;
void RGFW_clipboardFree(char* str) { RGFW_FREE(str); }
-RGFW_keyState RGFW_mouseButtons[5] = { 0 };
+RGFW_keyState RGFW_mouseButtons[5] = { {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0} };
b8 RGFW_isMousePressed(RGFW_window* win, u8 button) {
assert(win != NULL);
@@ -1461,20 +1676,28 @@ b8 RGFW_isReleased(RGFW_window* win, u8 key) {
return (!RGFW_isPressed(win, key) && RGFW_wasPressed(win, key));
}
-void RGFW_window_makeCurrent(RGFW_window* win) {
- assert(win != NULL);
+#if defined(RGFW_WINDOWS) && defined(RGFW_DIRECTX) /* defines for directX context*/
+ RGFW_directXinfo RGFW_dxInfo;
+ RGFW_directXinfo* RGFW_getDirectXInfo(void) { return &RGFW_dxInfo; }
+#endif
+void RGFW_window_makeCurrent(RGFW_window* win) {
#if defined(RGFW_WINDOWS) && defined(RGFW_DIRECTX)
- RGFW_dxInfo.pDeviceContext->lpVtbl->OMSetRenderTargets(RGFW_dxInfo.pDeviceContext, 1, &win->src.renderTargetView, NULL);
+ if (win == NULL)
+ RGFW_dxInfo.pDeviceContext->lpVtbl->OMSetRenderTargets(RGFW_dxInfo.pDeviceContext, 1, NULL, NULL);
+ else
+ RGFW_dxInfo.pDeviceContext->lpVtbl->OMSetRenderTargets(RGFW_dxInfo.pDeviceContext, 1, &win->src.renderTargetView, NULL);
#elif defined(RGFW_OPENGL)
RGFW_window_makeCurrent_OpenGL(win);
+#else
+ RGFW_UNUSED(win)
#endif
}
void RGFW_window_setGPURender(RGFW_window* win, i8 set) {
if (!set && !(win->_winArgs & RGFW_NO_GPU_RENDER))
win->_winArgs |= RGFW_NO_GPU_RENDER;
-
+
else if (set && win->_winArgs & RGFW_NO_GPU_RENDER)
win->_winArgs ^= RGFW_NO_GPU_RENDER;
}
@@ -1510,6 +1733,7 @@ void RGFW_window_setShouldClose(RGFW_window* win) { win->event.type = RGFW_quit;
#endif
RGFWDEF void RGFW_captureCursor(RGFW_window* win, RGFW_rect);
+RGFWDEF void RGFW_releaseCursor(RGFW_window* win);
void RGFW_window_mouseHold(RGFW_window* win, RGFW_area area) {
if ((win->_winArgs & RGFW_HOLD_MOUSE))
@@ -1521,25 +1745,26 @@ void RGFW_window_mouseHold(RGFW_window* win, RGFW_area area) {
win->_winArgs |= RGFW_HOLD_MOUSE;
RGFW_captureCursor(win, win->r);
- RGFW_window_moveMouse(win, RGFW_POINT(win->r.x + (area.w), win->r.y + (area.h)));
+ RGFW_window_moveMouse(win, RGFW_POINT(win->r.x + (win->r.w / 2), win->r.y + (win->r.h / 2)));
}
void RGFW_window_mouseUnhold(RGFW_window* win) {
if ((win->_winArgs & RGFW_HOLD_MOUSE)) {
win->_winArgs ^= RGFW_HOLD_MOUSE;
- RGFW_captureCursor(win, RGFW_RECT(0, 0, 0, 0));
+ RGFW_releaseCursor(win);
}
}
-void RGFW_window_checkFPS(RGFW_window* win) {
+u32 RGFW_window_checkFPS(RGFW_window* win, u32 fpsCap) {
u64 deltaTime = RGFW_getTimeNS() - win->event.frameTime;
+ u32 output_fps = 0;
u64 fps = round(1e+9 / deltaTime);
- win->event.fps = fps;
+ output_fps= fps;
- if (win->fpsCap && fps > win->fpsCap) {
- u64 frameTimeNS = 1e+9 / win->fpsCap;
+ if (fpsCap && fps > fpsCap) {
+ u64 frameTimeNS = 1e+9 / fpsCap;
u64 sleepTimeMS = (frameTimeNS - deltaTime) / 1e6;
if (sleepTimeMS > 0) {
@@ -1550,12 +1775,14 @@ void RGFW_window_checkFPS(RGFW_window* win) {
win->event.frameTime = RGFW_getTimeNS();
- if (win->fpsCap == 0)
- return;
+ if (fpsCap == 0)
+ return (u32) output_fps;
deltaTime = RGFW_getTimeNS() - win->event.frameTime2;
- win->event.fps = round(1e+9 / deltaTime);
+ output_fps = round(1e+9 / deltaTime);
win->event.frameTime2 = RGFW_getTimeNS();
+
+ return output_fps;
}
u32 RGFW_isPressedJS(RGFW_window* win, u16 c, u8 button) {
@@ -1586,7 +1813,7 @@ void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) {
win->event.lockState ^= RGFW_NUMLOCK;
}
-#if defined(RGFW_X11) || defined(RGFW_MACOS)
+#if defined(RGFW_X11) || defined(RGFW_MACOS) || defined(RGFW_WEBASM) || defined(RGFW_WAYLAND)
struct timespec;
int nanosleep(const struct timespec* duration, struct timespec* rem);
@@ -1603,7 +1830,7 @@ void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) {
#endif
/*
- graphics API spcific code (end of generic code)
+ graphics API specific code (end of generic code)
starts here
*/
@@ -1615,12 +1842,13 @@ void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) {
#if defined(RGFW_OPENGL) || defined(RGFW_EGL) || defined(RGFW_OSMESA)
#ifdef RGFW_WINDOWS
#define WIN32_LEAN_AND_MEAN
+ #define OEMRESOURCE
#include
#endif
- #ifndef __APPLE__
+ #if !defined(__APPLE__) && !defined(RGFW_NO_GL_HEADER)
#include
- #else
+ #elif defined(__APPLE__)
#ifndef GL_SILENCE_DEPRECATION
#define GL_SILENCE_DEPRECATION
#endif
@@ -1631,11 +1859,12 @@ void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) {
/* EGL, normal OpenGL only */
#if !defined(RGFW_OSMESA)
i32 RGFW_majorVersion = 0, RGFW_minorVersion = 0;
+ b8 RGFW_profile = RGFW_GL_CORE;
#ifndef RGFW_EGL
- i32 RGFW_STENCIL = 8, RGFW_SAMPLES = 4, RGFW_STEREO = GL_FALSE, RGFW_AUX_BUFFERS = 0;
+ i32 RGFW_STENCIL = 8, RGFW_SAMPLES = 4, RGFW_STEREO = 0, RGFW_AUX_BUFFERS = 0, RGFW_DOUBLE_BUFFER = 1;
#else
- i32 RGFW_STENCIL = 0, RGFW_SAMPLES = 0, RGFW_STEREO = GL_FALSE, RGFW_AUX_BUFFERS = 0;
+ i32 RGFW_STENCIL = 0, RGFW_SAMPLES = 0, RGFW_STEREO = 0, RGFW_AUX_BUFFERS = 0, RGFW_DOUBLE_BUFFER = 1;
#endif
@@ -1643,55 +1872,44 @@ void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) {
void RGFW_setGLSamples(i32 samples) { RGFW_SAMPLES = samples; }
void RGFW_setGLStereo(i32 stereo) { RGFW_STEREO = stereo; }
void RGFW_setGLAuxBuffers(i32 auxBuffers) { RGFW_AUX_BUFFERS = auxBuffers; }
+ void RGFW_setDoubleBuffer(b8 useDoubleBuffer) { RGFW_DOUBLE_BUFFER = useDoubleBuffer; }
- void RGFW_setGLVersion(i32 major, i32 minor) {
+ void RGFW_setGLVersion(b8 profile, i32 major, i32 minor) {
+ RGFW_profile = profile;
RGFW_majorVersion = major;
RGFW_minorVersion = minor;
}
- u8* RGFW_getMaxGLVersion(void) {
- RGFW_window* dummy = RGFW_createWindow("dummy", RGFW_RECT(0, 0, 1, 1), 0);
-
- const char* versionStr = (const char*) glGetString(GL_VERSION);
-
- static u8 version[2];
- version[0] = versionStr[0] - '0',
- version[1] = versionStr[2] - '0';
-
- RGFW_window_close(dummy);
-
- return version;
- }
-
/* OPENGL normal only (no EGL / OSMesa) */
#ifndef RGFW_EGL
-#define RGFW_GL_RENDER_TYPE RGFW_OS_BASED_VALUE(GLX_X_VISUAL_TYPE, 0x2003, 73, 0)
- #define RGFW_GL_ALPHA_SIZE RGFW_OS_BASED_VALUE(GLX_ALPHA_SIZE, 0x201b, 11, 0)
- #define RGFW_GL_DEPTH_SIZE RGFW_OS_BASED_VALUE(GLX_DEPTH_SIZE, 0x2022, 12, 0)
- #define RGFW_GL_DOUBLEBUFFER RGFW_OS_BASED_VALUE(GLX_DOUBLEBUFFER, 0x2011, 5, 0)
- #define RGFW_GL_STENCIL_SIZE RGFW_OS_BASED_VALUE(GLX_STENCIL_SIZE, 0x2023, 13, 0)
- #define RGFW_GL_SAMPLES RGFW_OS_BASED_VALUE(GLX_SAMPLES, 0x2042, 55, 0)
- #define RGFW_GL_STEREO RGFW_OS_BASED_VALUE(GLX_STEREO, 0x2012, 6, 0)
- #define RGFW_GL_AUX_BUFFERS RGFW_OS_BASED_VALUE(GLX_AUX_BUFFERS, 0x2024, 7, 0)
+#define RGFW_GL_RENDER_TYPE RGFW_OS_BASED_VALUE(GLX_X_VISUAL_TYPE, 0x2003, 73, 0, 0)
+ #define RGFW_GL_ALPHA_SIZE RGFW_OS_BASED_VALUE(GLX_ALPHA_SIZE, 0x201b, 11, 0, 0)
+ #define RGFW_GL_DEPTH_SIZE RGFW_OS_BASED_VALUE(GLX_DEPTH_SIZE, 0x2022, 12, 0, 0)
+ #define RGFW_GL_DOUBLEBUFFER RGFW_OS_BASED_VALUE(GLX_DOUBLEBUFFER, 0x2011, 5, 0, 0)
+ #define RGFW_GL_STENCIL_SIZE RGFW_OS_BASED_VALUE(GLX_STENCIL_SIZE, 0x2023, 13, 0, 0)
+ #define RGFW_GL_SAMPLES RGFW_OS_BASED_VALUE(GLX_SAMPLES, 0x2042, 55, 0, 0)
+ #define RGFW_GL_STEREO RGFW_OS_BASED_VALUE(GLX_STEREO, 0x2012, 6, 0, 0)
+ #define RGFW_GL_AUX_BUFFERS RGFW_OS_BASED_VALUE(GLX_AUX_BUFFERS, 0x2024, 7, 0, 0)
#if defined(RGFW_X11) || defined(RGFW_WINDOWS)
- #define RGFW_GL_DRAW RGFW_OS_BASED_VALUE(GLX_X_RENDERABLE, 0x2001, 0, 0)
- #define RGFW_GL_DRAW_TYPE RGFW_OS_BASED_VALUE(GLX_RENDER_TYPE, 0x2013, 0, 0)
- #define RGFW_GL_USE_OPENGL RGFW_OS_BASED_VALUE(GLX_USE_GL, 0x2010, 0, 0)
- #define RGFW_GL_FULL_FORMAT RGFW_OS_BASED_VALUE(GLX_TRUE_COLOR, 0x2027, 0, 0)
- #define RGFW_GL_RED_SIZE RGFW_OS_BASED_VALUE(GLX_RED_SIZE, 0x2015, 0, 0)
- #define RGFW_GL_GREEN_SIZE RGFW_OS_BASED_VALUE(GLX_GREEN_SIZE, 0x2017, 0, 0)
- #define RGFW_GL_BLUE_SIZE RGFW_OS_BASED_VALUE(GLX_BLUE_SIZE, 0x2019, 0, 0)
- #define RGFW_GL_USE_RGBA RGFW_OS_BASED_VALUE(GLX_RGBA_BIT, 0x202B, 0, 0)
+ #define RGFW_GL_DRAW RGFW_OS_BASED_VALUE(GLX_X_RENDERABLE, 0x2001, 0, 0, 0)
+ #define RGFW_GL_DRAW_TYPE RGFW_OS_BASED_VALUE(GLX_RENDER_TYPE, 0x2013, 0, 0, 0)
+ #define RGFW_GL_FULL_FORMAT RGFW_OS_BASED_VALUE(GLX_TRUE_COLOR, 0x2027, 0, 0, 0)
+ #define RGFW_GL_RED_SIZE RGFW_OS_BASED_VALUE(GLX_RED_SIZE, 0x2015, 0, 0, 0)
+ #define RGFW_GL_GREEN_SIZE RGFW_OS_BASED_VALUE(GLX_GREEN_SIZE, 0x2017, 0, 0, 0)
+ #define RGFW_GL_BLUE_SIZE RGFW_OS_BASED_VALUE(GLX_BLUE_SIZE, 0x2019, 0, 0, 0)
+ #define RGFW_GL_USE_RGBA RGFW_OS_BASED_VALUE(GLX_RGBA_BIT, 0x202B, 0, 0, 0)
#endif
#ifdef RGFW_WINDOWS
+ #define WGL_SUPPORT_OPENGL_ARB 0x2010
#define WGL_COLOR_BITS_ARB 0x2014
#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000
#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
+ #define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
#define WGL_SAMPLE_BUFFERS_ARB 0x2041
#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20a9
@@ -1700,8 +1918,12 @@ void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) {
#define WGL_TRANSPARENT_ARB 0x200A
#endif
-
- static u32* RGFW_initAttribs(u32 useSoftware) {
+
+/* The window'ing api needs to know how to render the data we (or opengl) give it
+ MacOS and Windows do this using a structure called a "pixel format"
+ X11 calls it a "Visual"
+ This function returns the attributes for the format we want */
+ static u32* RGFW_initFormatAttribs(u32 useSoftware) {
RGFW_UNUSED(useSoftware);
static u32 attribs[] = {
#if defined(RGFW_X11) || defined(RGFW_WINDOWS)
@@ -1710,13 +1932,7 @@ void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) {
#endif
RGFW_GL_ALPHA_SIZE , 8,
RGFW_GL_DEPTH_SIZE , 24,
- RGFW_GL_DOUBLEBUFFER ,
- #ifndef RGFW_MACOS
- 1,
- #endif
-
#if defined(RGFW_X11) || defined(RGFW_WINDOWS)
- RGFW_GL_USE_OPENGL, 1,
RGFW_GL_DRAW, 1,
RGFW_GL_RED_SIZE , 8,
RGFW_GL_GREEN_SIZE , 8,
@@ -1726,7 +1942,7 @@ void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) {
#ifdef RGFW_X11
GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT,
- #endif
+ #endif
#ifdef RGFW_MACOS
72,
@@ -1734,8 +1950,8 @@ void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) {
#endif
#ifdef RGFW_WINDOWS
+ WGL_SUPPORT_OPENGL_ARB, 1,
WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
- WGL_TRANSPARENT_ARB, TRUE,
WGL_COLOR_BITS_ARB, 32,
#endif
@@ -1750,8 +1966,10 @@ void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) {
attribs[index + 1] = attVal;\
index += 2;\
}
-
- RGFW_GL_ADD_ATTRIB(RGFW_GL_STENCIL_SIZE, RGFW_STENCIL);
+
+ RGFW_GL_ADD_ATTRIB(RGFW_GL_DOUBLEBUFFER, 1);
+
+ RGFW_GL_ADD_ATTRIB(RGFW_GL_STENCIL_SIZE, RGFW_STENCIL);
RGFW_GL_ADD_ATTRIB(RGFW_GL_STEREO, RGFW_STEREO);
RGFW_GL_ADD_ATTRIB(RGFW_GL_AUX_BUFFERS, RGFW_AUX_BUFFERS);
@@ -1769,13 +1987,15 @@ void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) {
#endif
#ifdef RGFW_MACOS
+ /* macOS has the surface attribs and the opengl attribs connected for some reason
+ maybe this is to give macOS more control to limit openGL/the opengl version? */
+
attribs[index] = 99;
attribs[index + 1] = 0x1000;
if (RGFW_majorVersion >= 4 || RGFW_majorVersion >= 3) {
attribs[index + 1] = (u32) ((RGFW_majorVersion >= 4) ? 0x4100 : 0x3200);
}
-
#endif
RGFW_GL_ADD_ATTRIB(0, 0);
@@ -1894,18 +2114,29 @@ void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) {
#else
2,
#endif
- EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE
+ EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE
};
size_t index = 4;
RGFW_GL_ADD_ATTRIB(EGL_STENCIL_SIZE, RGFW_STENCIL);
RGFW_GL_ADD_ATTRIB(EGL_SAMPLES, RGFW_SAMPLES);
+ if (RGFW_DOUBLE_BUFFER)
+ RGFW_GL_ADD_ATTRIB(EGL_RENDER_BUFFER, EGL_BACK_BUFFER);
+
if (RGFW_majorVersion) {
attribs[1] = RGFW_majorVersion;
- RGFW_GL_ADD_ATTRIB(EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT);
+
RGFW_GL_ADD_ATTRIB(EGL_CONTEXT_MAJOR_VERSION, RGFW_majorVersion);
RGFW_GL_ADD_ATTRIB(EGL_CONTEXT_MINOR_VERSION, RGFW_minorVersion);
+
+ if (RGFW_profile == RGFW_GL_CORE) {
+ RGFW_GL_ADD_ATTRIB(EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT);
+ }
+ else {
+ RGFW_GL_ADD_ATTRIB(EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT);
+ }
+
}
#if defined(RGFW_OPENGL_ES1) || defined(RGFW_OPENGL_ES2) || defined(RGFW_OPENGL_ES3)
@@ -1913,13 +2144,20 @@ void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) {
#else
eglBindAPI(EGL_OPENGL_API);
#endif
-
- win->src.EGL_context = eglCreateContext(win->src.EGL_display, config, EGL_NO_CONTEXT, attribs);
+
+ win->src.EGL_context = eglCreateContext(win->src.EGL_display, config, EGL_NO_CONTEXT, attribs);
+
+ if (win->src.EGL_context == NULL)
+ fprintf(stderr, "failed to create an EGL opengl context\n");
eglMakeCurrent(win->src.EGL_display, win->src.EGL_surface, win->src.EGL_surface, win->src.EGL_context);
eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface);
}
+ void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) {
+ eglMakeCurrent(win->src.EGL_display, win->src.EGL_surface, win->src.EGL_surface, win->src.EGL_context);
+ }
+
#ifdef RGFW_APPLE
void* RGFWnsglFramework = NULL;
#elif defined(RGFW_WINDOWS)
@@ -1949,8 +2187,6 @@ void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) {
eglSwapInterval(win->src.EGL_display, swapInterval);
- win->fpsCap = (swapInterval == 1) ? 0 : swapInterval;
-
}
#endif /* RGFW_EGL */
@@ -1990,6 +2226,62 @@ This is where OS specific stuff starts
*/
+#if defined(RGFW_WAYLAND) || defined(RGFW_X11)
+ int RGFW_eventWait_forceStop[] = {0, 0, 0}; /* for wait events */
+
+ #ifdef __linux__
+ #include
+ #include
+ #include
+
+ RGFW_Event* RGFW_linux_updateJoystick(RGFW_window* win) {
+ static int xAxis = 0, yAxis = 0;
+ u8 i;
+ for (i = 0; i < RGFW_joystickCount; i++) {
+ struct js_event e;
+
+
+ if (RGFW_joysticks[i] == 0)
+ continue;
+
+ i32 flags = fcntl(RGFW_joysticks[i], F_GETFL, 0);
+ fcntl(RGFW_joysticks[i], F_SETFL, flags | O_NONBLOCK);
+
+ ssize_t bytes;
+ while ((bytes = read(RGFW_joysticks[i], &e, sizeof(e))) > 0) {
+ switch (e.type) {
+ case JS_EVENT_BUTTON:
+ win->event.type = e.value ? RGFW_jsButtonPressed : RGFW_jsButtonReleased;
+ win->event.button = e.number;
+ RGFW_jsPressed[i][e.number] = e.value;
+ RGFW_jsButtonCallback(win, i, e.number, e.value);
+ return &win->event;
+ case JS_EVENT_AXIS:
+ ioctl(RGFW_joysticks[i], JSIOCGAXES, &win->event.axisesCount);
+
+ if ((e.number == 0 || e.number % 2) && e.number != 1)
+ xAxis = e.value;
+ else
+ yAxis = e.value;
+
+ win->event.axis[e.number / 2].x = xAxis;
+ win->event.axis[e.number / 2].y = yAxis;
+ win->event.type = RGFW_jsAxisMove;
+ win->event.joystick = i;
+ RGFW_jsAxisCallback(win, i, win->event.axis, win->event.axisesCount);
+ return &win->event;
+
+ default: break;
+ }
+ }
+ }
+
+ return NULL;
+ }
+
+ #endif
+#endif
+
/*
@@ -2021,9 +2313,9 @@ Start of Linux / Unix defines
#include
#include /* for data limits (mainly used in drag and drop functions) */
-#include
#include
+
#ifdef __linux__
#include
#endif
@@ -2075,7 +2367,7 @@ Start of Linux / Unix defines
if (RGFW_bufferSize.w == 0 && RGFW_bufferSize.h == 0)
RGFW_bufferSize = RGFW_getScreenSize();
- win->buffer = RGFW_MALLOC(RGFW_bufferSize.w * RGFW_bufferSize.h * 4);
+ win->buffer = (u8*)RGFW_MALLOC(RGFW_bufferSize.w * RGFW_bufferSize.h * 4);
#ifdef RGFW_OSMESA
win->src.ctx = OSMesaCreateContext(OSMESA_RGBA, NULL);
@@ -2092,7 +2384,7 @@ Start of Linux / Unix defines
win->src.gc = XCreateGC(win->src.display, win->src.window, 0, NULL);
#else
- RGFW_UNUSED(win); /* if buffer rendering is not being used */
+ RGFW_UNUSED(win); /*!< if buffer rendering is not being used */
RGFW_UNUSED(vi)
#endif
}
@@ -2117,30 +2409,30 @@ Start of Linux / Unix defines
32, PropModeReplace, (u8*)&hints, 5
);
}
+
+ void RGFW_releaseCursor(RGFW_window* win) {
+ XUngrabPointer(win->src.display, CurrentTime);
- void RGFW_captureCursor(RGFW_window* win, RGFW_rect r) {
+ /* disable raw input */
+ unsigned char mask[] = { 0 };
XIEventMask em;
em.deviceid = XIAllMasterDevices;
-
- /* grab the cursor if the rect struct isn't zeroed out, else ungrab*/
- if (!r.x && !r.y && r.w && !r.h) {
- XUngrabPointer(win->src.display, CurrentTime);
-
- /* disable raw input */
- unsigned char mask[] = { 0 };
- em.mask_len = sizeof(mask);
- em.mask = mask;
- XISelectEvents(win->src.display, XDefaultRootWindow(win->src.display), &em, 1);
- return;
- }
-
- /* enable raw input */
- unsigned char mask[XIMaskLen(XI_RawMotion)] = { 0 };
-
em.mask_len = sizeof(mask);
em.mask = mask;
+
+ XISelectEvents(win->src.display, XDefaultRootWindow(win->src.display), &em, 1);
+ }
+
+ void RGFW_captureCursor(RGFW_window* win, RGFW_rect r) {
+ /* enable raw input */
+ unsigned char mask[XIMaskLen(XI_RawMotion)] = { 0 };
XISetMask(mask, XI_RawMotion);
+ XIEventMask em;
+ em.deviceid = XIAllMasterDevices;
+ em.mask_len = sizeof(mask);
+ em.mask = mask;
+
XISelectEvents(win->src.display, XDefaultRootWindow(win->src.display), &em, 1);
XGrabPointer(win->src.display, win->src.window, True, PointerMotionMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
@@ -2179,24 +2471,24 @@ Start of Linux / Unix defines
}
#endif
- XInitThreads(); /* init X11 threading*/
+ XInitThreads(); /*!< init X11 threading*/
if (args & RGFW_OPENGL_SOFTWARE)
setenv("LIBGL_ALWAYS_SOFTWARE", "1", 1);
RGFW_window* win = RGFW_window_basic_init(rect, args);
- u64 event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask | FocusChangeMask | LeaveWindowMask | EnterWindowMask | ExposureMask; /* X11 events accepted*/
+ u64 event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask | FocusChangeMask | LeaveWindowMask | EnterWindowMask | ExposureMask; /*!< X11 events accepted*/
#ifdef RGFW_OPENGL
- u32* visual_attribs = RGFW_initAttribs(args & RGFW_OPENGL_SOFTWARE);
+ u32* visual_attribs = RGFW_initFormatAttribs(args & RGFW_OPENGL_SOFTWARE);
i32 fbcount;
GLXFBConfig* fbc = glXChooseFBConfig((Display*) win->src.display, DefaultScreen(win->src.display), (i32*) visual_attribs, &fbcount);
i32 best_fbc = -1;
if (fbcount == 0) {
- printf("Failed to find any valid GLX configs\n");
+ printf("Failed to find any valid GLX visual configs\n");
return NULL;
}
@@ -2230,7 +2522,7 @@ Start of Linux / Unix defines
XFree(fbc);
if (args & RGFW_TRANSPARENT_WINDOW) {
- XMatchVisualInfo((Display*) win->src.display, DefaultScreen((Display*) win->src.display), 32, TrueColor, vi); /* for RGBA backgrounds*/
+ XMatchVisualInfo((Display*) win->src.display, DefaultScreen((Display*) win->src.display), 32, TrueColor, vi); /*!< for RGBA backgrounds*/
}
#else
@@ -2241,7 +2533,7 @@ Start of Linux / Unix defines
viNorm.depth = 0;
XVisualInfo* vi = &viNorm;
- XMatchVisualInfo((Display*) win->src.display, DefaultScreen((Display*) win->src.display), 32, TrueColor, vi); /* for RGBA backgrounds*/
+ XMatchVisualInfo((Display*) win->src.display, DefaultScreen((Display*) win->src.display), 32, TrueColor, vi); /*!< for RGBA backgrounds*/
#endif
/* make X window attrubutes*/
XSetWindowAttributes swa;
@@ -2273,16 +2565,19 @@ Start of Linux / Unix defines
// with your application - robrohan
XClassHint *hint = XAllocClassHint();
assert(hint != NULL);
- hint->res_class = "RGFW";
+ hint->res_class = (char*)"RGFW";
hint->res_name = (char*)name; // just use the window name as the app name
XSetClassHint((Display*) win->src.display, win->src.window, hint);
XFree(hint);
if ((args & RGFW_NO_INIT_API) == 0) {
-#ifdef RGFW_OPENGL
+#ifdef RGFW_OPENGL /* This is the second part of setting up opengl. This is where we ask OpenGL for a specific version. */
i32 context_attribs[7] = { 0, 0, 0, 0, 0, 0, 0 };
context_attribs[0] = GLX_CONTEXT_PROFILE_MASK_ARB;
- context_attribs[1] = GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
+ if (RGFW_profile == RGFW_GL_CORE)
+ context_attribs[1] = GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
+ else
+ context_attribs[1] = GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
if (RGFW_majorVersion || RGFW_minorVersion) {
context_attribs[2] = GLX_CONTEXT_MAJOR_VERSION_ARB;
@@ -2328,7 +2623,7 @@ Start of Linux / Unix defines
RGFW_window_setBorder(win, 0);
}
- XSelectInput((Display*) win->src.display, (Drawable) win->src.window, event_mask); /* tell X11 what events we want*/
+ XSelectInput((Display*) win->src.display, (Drawable) win->src.window, event_mask); /*!< tell X11 what events we want*/
/* make it so the user can't close the window until the program does*/
if (wm_delete_window == 0)
@@ -2343,10 +2638,10 @@ Start of Linux / Unix defines
#endif
/* set the background*/
- XStoreName((Display*) win->src.display, (Drawable) win->src.window, name); /* set the name*/
+ XStoreName((Display*) win->src.display, (Drawable) win->src.window, name); /*!< set the name*/
XMapWindow((Display*) win->src.display, (Drawable) win->src.window); /* draw the window*/
- XMoveWindow((Display*) win->src.display, (Drawable) win->src.window, win->r.x, win->r.y); /* move the window to it's proper cords*/
+ XMoveWindow((Display*) win->src.display, (Drawable) win->src.window, win->r.x, win->r.y); /*!< move the window to it's proper cords*/
if (args & RGFW_ALLOW_DND) { /* init drag and drop atoms and turn on drag and drop for this window */
win->_winArgs |= RGFW_ALLOW_DND;
@@ -2373,7 +2668,7 @@ Start of Linux / Unix defines
XChangeProperty((Display*) win->src.display, (Window) win->src.window,
XdndAware, 4, 32,
- PropModeReplace, (u8*) &version, 1); /* turns on drag and drop */
+ PropModeReplace, (u8*) &version, 1); /*!< turns on drag and drop */
}
#ifdef RGFW_EGL
@@ -2421,79 +2716,10 @@ Start of Linux / Unix defines
return RGFWMouse;
}
-
- int RGFW_eventWait_forceStop[] = {0, 0, 0};
-
- void RGFW_stopCheckEvents(void) {
- RGFW_eventWait_forceStop[2] = 1;
- while (1) {
- const char byte = 0;
- const ssize_t result = write(RGFW_eventWait_forceStop[1], &byte, 1);
- if (result == 1 || result == -1)
- break;
- }
- }
-
- void RGFW_window_eventWait(RGFW_window* win, i32 waitMS) {
- if (waitMS == 0)
- return;
-
- u8 i;
-
- if (RGFW_eventWait_forceStop[0] == 0 || RGFW_eventWait_forceStop[1] == 0) {
- if (pipe(RGFW_eventWait_forceStop) != -1) {
- fcntl(RGFW_eventWait_forceStop[0], F_GETFL, 0);
- fcntl(RGFW_eventWait_forceStop[0], F_GETFD, 0);
- fcntl(RGFW_eventWait_forceStop[1], F_GETFL, 0);
- fcntl(RGFW_eventWait_forceStop[1], F_GETFD, 0);
- }
- }
-
- struct pollfd fds[] = {
- { ConnectionNumber(win->src.display), POLLIN, 0 },
- { RGFW_eventWait_forceStop[0], POLLIN, 0 },
- #ifdef __linux__ /* blank space for 4 joystick files*/
- { -1, POLLIN, 0 }, {-1, POLLIN, 0 }, {-1, POLLIN, 0 }, {-1, POLLIN, 0}
- #endif
- };
-
- u8 index = 2;
-
- #if defined(__linux__)
- for (i = 0; i < RGFW_joystickCount; i++) {
- if (RGFW_joysticks[i] == 0)
- continue;
-
- fds[index].fd = RGFW_joysticks[i];
- index++;
- }
- #endif
-
-
- u64 start = RGFW_getTimeNS();
-
- while (XPending(win->src.display) == 0 && waitMS >= -1) {
- if (poll(fds, index, waitMS) <= 0)
- break;
-
- if (waitMS > 0) {
- waitMS -= (RGFW_getTimeNS() - start) / 1e+6;
- }
- }
-
- /* drain any data in the stop request */
- if (RGFW_eventWait_forceStop[2]) {
- char data[64];
- read(RGFW_eventWait_forceStop[0], data, sizeof(data));
-
- RGFW_eventWait_forceStop[2] = 0;
- }
- }
-
typedef struct XDND {
long source, version;
i32 format;
- } XDND; /* data structure for xdnd events */
+ } XDND; /*!< data structure for xdnd events */
XDND xdnd;
int xAxis = 0, yAxis = 0;
@@ -2511,52 +2737,14 @@ Start of Linux / Unix defines
win->event.type = 0;
#ifdef __linux__
- {
- u8 i;
- for (i = 0; i < RGFW_joystickCount; i++) {
- struct js_event e;
-
-
- if (RGFW_joysticks[i] == 0)
- continue;
-
- i32 flags = fcntl(RGFW_joysticks[i], F_GETFL, 0);
- fcntl(RGFW_joysticks[i], F_SETFL, flags | O_NONBLOCK);
-
- ssize_t bytes;
- while ((bytes = read(RGFW_joysticks[i], &e, sizeof(e))) > 0) {
- switch (e.type) {
- case JS_EVENT_BUTTON:
- win->event.type = e.value ? RGFW_jsButtonPressed : RGFW_jsButtonReleased;
- win->event.button = e.number;
- RGFW_jsPressed[i][e.number] = e.value;
- RGFW_jsButtonCallback(win, i, e.number, e.value);
- return &win->event;
- case JS_EVENT_AXIS:
- ioctl(RGFW_joysticks[i], JSIOCGAXES, &win->event.axisesCount);
-
- if ((e.number == 0 || e.number % 2) && e.number != 1)
- xAxis = e.value;
- else
- yAxis = e.value;
-
- win->event.axis[e.number / 2].x = xAxis;
- win->event.axis[e.number / 2].y = yAxis;
- win->event.type = RGFW_jsAxisMove;
- win->event.joystick = i;
- RGFW_jsAxisCallback(win, i, win->event.axis, win->event.axisesCount);
- return &win->event;
-
- default: break;
- }
- }
- }
- }
+ RGFW_Event* event = RGFW_linux_updateJoystick(win);
+ if (event != NULL)
+ return event;
#endif
XPending(win->src.display);
- XEvent E; /* raw X11 event */
+ XEvent E; /*!< raw X11 event */
/* if there is no unread qued events, get a new one */
if ((QLength(win->src.display) || XEventsQueued((Display*) win->src.display, QueuedAlready) + XEventsQueued((Display*) win->src.display, QueuedAfterReading))
@@ -2573,21 +2761,22 @@ Start of Linux / Unix defines
switch (E.type) {
case KeyPress:
- case KeyRelease:
+ case KeyRelease: {
+ win->event.repeat = RGFW_FALSE;
/* check if it's a real key release */
if (E.type == KeyRelease && XEventsQueued((Display*) win->src.display, QueuedAfterReading)) { /* get next event if there is one*/
XEvent NE;
XPeekEvent((Display*) win->src.display, &NE);
if (E.xkey.time == NE.xkey.time && E.xkey.keycode == NE.xkey.keycode) /* check if the current and next are both the same*/
- break;
+ win->event.repeat = RGFW_TRUE;
}
/* set event key data */
- KeySym sym = XkbKeycodeToKeysym((Display*) win->src.display, E.xkey.keycode, 0, E.xkey.state & ShiftMask ? 1 : 0);
+ KeySym sym = (KeySym)XkbKeycodeToKeysym((Display*) win->src.display, E.xkey.keycode, 0, E.xkey.state & ShiftMask ? 1 : 0);
win->event.keyCode = RGFW_apiKeyCodeToRGFW(E.xkey.keycode);
- char* str = XKeysymToString(sym);
+ char* str = (char*)XKeysymToString(sym);
if (str != NULL)
strncpy(win->event.keyName, str, 16);
@@ -2602,14 +2791,13 @@ Start of Linux / Unix defines
XGetKeyboardControl((Display*) win->src.display, &keystate);
RGFW_updateLockState(win, (keystate.led_mask & 1), (keystate.led_mask & 2));
-
RGFW_keyboard[win->event.keyCode].current = (E.type == KeyPress);
RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, (E.type == KeyPress));
break;
-
+ }
case ButtonPress:
case ButtonRelease:
- win->event.type = E.type; // the events match
+ win->event.type = RGFW_mouseButtonPressed + (E.type == ButtonRelease); // the events match
switch(win->event.button) {
case RGFW_mouseScrollUp:
@@ -2623,19 +2811,23 @@ Start of Linux / Unix defines
win->event.button = E.xbutton.button;
RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current;
+
+ if (win->event.repeat == RGFW_FALSE)
+ win->event.repeat = RGFW_isPressed(win, win->event.keyCode);
+
RGFW_mouseButtons[win->event.button].current = (E.type == ButtonPress);
RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, (E.type == ButtonPress));
break;
- case MotionNotify:
+ case MotionNotify:
win->event.point.x = E.xmotion.x;
win->event.point.y = E.xmotion.y;
if ((win->_winArgs & RGFW_HOLD_MOUSE)) {
- win->event.point.x = win->_lastMousePoint.x - win->event.point.x;
- win->event.point.y = win->_lastMousePoint.y - win->event.point.y;
+ win->event.point.y = E.xmotion.y;
- RGFW_window_moveMouse(win, RGFW_POINT(win->r.x + (win->r.w / 2), win->r.y + (win->r.h / 2)));
+ win->event.point.x = win->_lastMousePoint.x - abs(win->event.point.x);
+ win->event.point.y = win->_lastMousePoint.y - abs(win->event.point.y);
}
win->_lastMousePoint = RGFW_POINT(E.xmotion.x, E.xmotion.y);
@@ -2668,7 +2860,9 @@ Start of Linux / Unix defines
if (XIMaskIsSet(raw->valuators.mask, 1) != 0)
deltaY += raw->raw_values[1];
- win->event.point = RGFW_POINT((u32)-deltaX, (u32)-deltaY);
+ win->event.point = RGFW_POINT((i32)deltaX, (i32)deltaY);
+
+ RGFW_window_moveMouse(win, RGFW_POINT(win->r.x + (win->r.w / 2), win->r.y + (win->r.h / 2)));
win->event.type = RGFW_mousePosChanged;
RGFW_mousePosCallback(win, win->event.point);
@@ -2855,7 +3049,7 @@ Start of Linux / Unix defines
RGFW_dndInitCallback(win, win->event.point);
break;
- case SelectionNotify:
+ case SelectionNotify: {
/* this is only for checking for xdnd drops */
if (E.xselection.property != XdndSelection || !(win->_winArgs | RGFW_ALLOW_DND))
break;
@@ -2878,7 +3072,7 @@ Start of Linux / Unix defines
Copyright (c) 2006-2019 Camilla Löwy
*/
- const char* prefix = "file://";
+ const char* prefix = (const char*)"file://";
char* line;
@@ -2945,7 +3139,7 @@ Start of Linux / Unix defines
RGFW_dndCallback(win, win->event.droppedFiles, win->event.droppedFilesCount);
break;
-
+ }
case FocusIn:
win->event.inFocus = 1;
win->event.type = RGFW_focusIn;
@@ -3222,7 +3416,7 @@ Start of Linux / Unix defines
void RGFW_window_setMouseStandard(RGFW_window* win, u8 mouse) {
assert(win != NULL);
-
+
if (mouse > (sizeof(RGFW_mouseIconSrc) / sizeof(u8)))
return;
@@ -3286,7 +3480,7 @@ Start of Linux / Unix defines
*size = sizeN;
return s;
- }
+ }
/*
almost all of this function is sourced from GLFW
@@ -3309,27 +3503,25 @@ Start of Linux / Unix defines
ATOM_PAIR = XInternAtom((Display*) RGFW_root->src.display, "ATOM_PAIR", False);
CLIPBOARD_MANAGER = XInternAtom((Display*) RGFW_root->src.display, "CLIPBOARD_MANAGER", False);
}
-
+
XSetSelectionOwner((Display*) RGFW_root->src.display, CLIPBOARD, (Window) RGFW_root->src.window, CurrentTime);
XConvertSelection((Display*) RGFW_root->src.display, CLIPBOARD_MANAGER, SAVE_TARGETS, None, (Window) RGFW_root->src.window, CurrentTime);
-
for (;;) {
XEvent event;
XNextEvent((Display*) RGFW_root->src.display, &event);
- if (event.type != SelectionRequest)
- return;
+ if (event.type != SelectionRequest) {
+ break;
+ }
const XSelectionRequestEvent* request = &event.xselectionrequest;
XEvent reply = { SelectionNotify };
+ reply.xselection.property = 0;
- char* selectionString = NULL;
const Atom formats[] = { UTF8_STRING, XA_STRING };
const i32 formatCount = sizeof(formats) / sizeof(formats[0]);
-
- selectionString = (char*) text;
if (request->target == TARGETS) {
const Atom targets[] = { TARGETS,
@@ -3350,11 +3542,11 @@ Start of Linux / Unix defines
}
if (request->target == MULTIPLE) {
- Atom* targets;
+ Atom* targets = NULL;
- Atom actualType;
- i32 actualFormat;
- unsigned long count, bytesAfter;
+ Atom actualType = 0;
+ int actualFormat = 0;
+ unsigned long count = 0, bytesAfter = 0;
XGetWindowProperty((Display*) RGFW_root->src.display, request->requestor, request->property, 0, LONG_MAX, False, ATOM_PAIR, &actualType, &actualFormat, &count, &bytesAfter, (u8**) &targets);
@@ -3375,10 +3567,12 @@ Start of Linux / Unix defines
targets[i],
8,
PropModeReplace,
- (u8*) selectionString,
+ (u8*) text,
textLen);
- } else
+ XFlush(RGFW_root->src.display);
+ } else {
targets[i + 1] = None;
+ }
}
XChangeProperty((Display*) RGFW_root->src.display,
@@ -3390,6 +3584,7 @@ Start of Linux / Unix defines
(u8*) targets,
count);
+ XFlush(RGFW_root->src.display);
XFree(targets);
reply.xselection.property = request->property;
@@ -3402,49 +3597,10 @@ Start of Linux / Unix defines
reply.xselection.time = request->time;
XSendEvent((Display*) RGFW_root->src.display, request->requestor, False, 0, &reply);
+ XFlush(RGFW_root->src.display);
}
}
- u16 RGFW_registerJoystick(RGFW_window* win, i32 jsNumber) {
- assert(win != NULL);
-
-#ifdef __linux__
- char file[15];
- sprintf(file, "/dev/input/js%i", jsNumber);
-
- return RGFW_registerJoystickF(win, file);
-#endif
- }
-
- u16 RGFW_registerJoystickF(RGFW_window* win, char* file) {
- assert(win != NULL);
-
-#ifdef __linux__
-
- i32 js = open(file, O_RDONLY);
-
- if (js && RGFW_joystickCount < 4) {
- RGFW_joystickCount++;
-
- RGFW_joysticks[RGFW_joystickCount - 1] = open(file, O_RDONLY);
-
- u8 i;
- for (i = 0; i < 16; i++)
- RGFW_jsPressed[RGFW_joystickCount - 1][i] = 0;
-
- }
-
- else {
-#ifdef RGFW_PRINT_ERRORS
- RGFW_error = 1;
- fprintf(stderr, "Error RGFW_registerJoystickF : Cannot open file %s\n", file);
-#endif
- }
-
- return RGFW_joystickCount - 1;
-#endif
- }
-
u8 RGFW_window_isFullscreen(RGFW_window* win) {
assert(win != NULL);
@@ -3648,9 +3804,10 @@ Start of Linux / Unix defines
#ifdef RGFW_OPENGL
void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) {
- assert(win != NULL);
-
- glXMakeCurrent((Display*) win->src.display, (Drawable) win->src.window, (GLXContext) win->src.ctx);
+ if (win == NULL)
+ glXMakeCurrent((Display*) NULL, (Drawable)NULL, (GLXContext) NULL);
+ else
+ glXMakeCurrent((Display*) win->src.display, (Drawable) win->src.window, (GLXContext) win->src.ctx);
}
#endif
@@ -3658,8 +3815,6 @@ Start of Linux / Unix defines
void RGFW_window_swapBuffers(RGFW_window* win) {
assert(win != NULL);
- RGFW_window_makeCurrent(win);
-
/* clear the window*/
if (!(win->_winArgs & RGFW_NO_CPU_RENDER)) {
#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)
@@ -3693,8 +3848,6 @@ Start of Linux / Unix defines
glXSwapBuffers((Display*) win->src.display, (Window) win->src.window);
#endif
}
-
- RGFW_window_checkFPS(win);
}
#if !defined(RGFW_EGL)
@@ -3703,9 +3856,9 @@ Start of Linux / Unix defines
#if defined(RGFW_OPENGL)
((PFNGLXSWAPINTERVALEXTPROC) glXGetProcAddress((GLubyte*) "glXSwapIntervalEXT"))((Display*) win->src.display, (Window) win->src.window, swapInterval);
+ #else
+ RGFW_UNUSED(swapInterval);
#endif
-
- win->fpsCap = (swapInterval == 1) ? 0 : swapInterval;
}
#endif
@@ -3736,9 +3889,9 @@ Start of Linux / Unix defines
RGFW_root = NULL;
if ((Drawable) win->src.window)
- XDestroyWindow((Display*) win->src.display, (Drawable) win->src.window); /* close the window*/
+ XDestroyWindow((Display*) win->src.display, (Drawable) win->src.window); /*!< close the window*/
- XCloseDisplay((Display*) win->src.display); /* kill the display*/
+ XCloseDisplay((Display*) win->src.display); /*!< kill the display*/
}
#ifdef RGFW_ALLOC_DROPFILES
@@ -3788,7 +3941,134 @@ Start of Linux / Unix defines
win->src.display = (Display*) 0;
win->src.window = (Window) 0;
- RGFW_FREE(win); /* free collected window data */
+ RGFW_FREE(win); /*!< free collected window data */
+ }
+
+
+/*
+ End of X11 linux / unix defines
+*/
+
+#endif /* RGFW_X11 */
+
+
+/* wayland or X11 defines*/
+#if defined(RGFW_WAYLAND) || defined(RGFW_X11)
+#include
+#include
+#include
+ u16 RGFW_registerJoystickF(RGFW_window* win, char* file) {
+ assert(win != NULL);
+
+#ifdef __linux__
+
+ i32 js = open(file, O_RDONLY);
+
+ if (js && RGFW_joystickCount < 4) {
+ RGFW_joystickCount++;
+
+ RGFW_joysticks[RGFW_joystickCount - 1] = open(file, O_RDONLY);
+
+ u8 i;
+ for (i = 0; i < 16; i++)
+ RGFW_jsPressed[RGFW_joystickCount - 1][i] = 0;
+
+ }
+
+ else {
+#ifdef RGFW_PRINT_ERRORS
+ RGFW_error = 1;
+ fprintf(stderr, "Error RGFW_registerJoystickF : Cannot open file %s\n", file);
+#endif
+ }
+
+ return RGFW_joystickCount - 1;
+#endif
+ }
+
+ u16 RGFW_registerJoystick(RGFW_window* win, i32 jsNumber) {
+ assert(win != NULL);
+
+#ifdef __linux__
+ char file[15];
+ sprintf(file, "/dev/input/js%i", jsNumber);
+
+ return RGFW_registerJoystickF(win, file);
+#endif
+ }
+
+ void RGFW_stopCheckEvents(void) {
+ RGFW_eventWait_forceStop[2] = 1;
+ while (1) {
+ const char byte = 0;
+ const ssize_t result = write(RGFW_eventWait_forceStop[1], &byte, 1);
+ if (result == 1 || result == -1)
+ break;
+ }
+ }
+
+ void RGFW_window_eventWait(RGFW_window* win, i32 waitMS) {
+ if (waitMS == 0)
+ return;
+
+ u8 i;
+
+ if (RGFW_eventWait_forceStop[0] == 0 || RGFW_eventWait_forceStop[1] == 0) {
+ if (pipe(RGFW_eventWait_forceStop) != -1) {
+ fcntl(RGFW_eventWait_forceStop[0], F_GETFL, 0);
+ fcntl(RGFW_eventWait_forceStop[0], F_GETFD, 0);
+ fcntl(RGFW_eventWait_forceStop[1], F_GETFL, 0);
+ fcntl(RGFW_eventWait_forceStop[1], F_GETFD, 0);
+ }
+ }
+
+ struct pollfd fds[] = {
+ #ifdef RGFW_WAYLAND
+ { wl_display_get_fd(win->src.display), POLLIN, 0 },
+ #else
+ { ConnectionNumber(win->src.display), POLLIN, 0 },
+ #endif
+ { RGFW_eventWait_forceStop[0], POLLIN, 0 },
+ #ifdef __linux__ /* blank space for 4 joystick files*/
+ { -1, POLLIN, 0 }, {-1, POLLIN, 0 }, {-1, POLLIN, 0 }, {-1, POLLIN, 0}
+ #endif
+ };
+
+ u8 index = 2;
+
+ #if defined(__linux__)
+ for (i = 0; i < RGFW_joystickCount; i++) {
+ if (RGFW_joysticks[i] == 0)
+ continue;
+
+ fds[index].fd = RGFW_joysticks[i];
+ index++;
+ }
+ #endif
+
+
+ u64 start = RGFW_getTimeNS();
+
+ #ifdef RGFW_WAYLAND
+ while (wl_display_dispatch(win->src.display) <= 0 && waitMS >= -1) {
+ #else
+ while (XPending(win->src.display) == 0 && waitMS >= -1) {
+ #endif
+ if (poll(fds, index, waitMS) <= 0)
+ break;
+
+ if (waitMS > 0) {
+ waitMS -= (RGFW_getTimeNS() - start) / 1e+6;
+ }
+ }
+
+ /* drain any data in the stop request */
+ if (RGFW_eventWait_forceStop[2]) {
+ char data[64];
+ (void)!read(RGFW_eventWait_forceStop[0], data, sizeof(data));
+
+ RGFW_eventWait_forceStop[2] = 0;
+ }
}
u64 RGFW_getTimeNS(void) {
@@ -3806,11 +4086,906 @@ Start of Linux / Unix defines
return (double)(nanoSeconds) * 1e-9;
}
-/*
- End of linux / unix defines
+#endif /* end of wayland or X11 time defines*/
+
+
+/*
+
+ Start of Wayland defines
+
+
*/
-#endif /* RGFW_X11 */
+#ifdef RGFW_WAYLAND
+/*
+Wayland TODO:
+- fix RGFW_keyPressed lock state
+
+ RGFW_windowMoved, the window was moved (by the user)
+ RGFW_windowResized the window was resized (by the user), [on webASM this means the browser was resized]
+ RGFW_windowRefresh The window content needs to be refreshed
+
+ RGFW_dnd a file has been dropped into the window
+ RGFW_dnd_init
+
+- window args:
+ #define RGFW_NO_RESIZE the window cannot be resized by the user
+ #define RGFW_ALLOW_DND the window supports drag and drop
+ #define RGFW_SCALE_TO_MONITOR scale the window to the screen
+
+- other missing functions functions ("TODO wayland") (~30 functions)
+- fix buffer rendering weird behavior
+*/
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+
+RGFW_window* RGFW_key_win = NULL;
+
+void RGFW_eventPipe_push(RGFW_window* win, RGFW_Event event) {
+ if (win == NULL) {
+ win = RGFW_key_win;
+
+ if (win == NULL) return;
+ }
+
+ if (win->src.eventLen >= (i32)(sizeof(win->src.events) / sizeof(win->src.events[0])))
+ return;
+
+ win->src.events[win->src.eventLen] = event;
+ win->src.eventLen += 1;
+}
+
+RGFW_Event RGFW_eventPipe_pop(RGFW_window* win) {
+ RGFW_Event ev;
+ ev.type = 0;
+
+ if (win->src.eventLen > -1)
+ win->src.eventLen -= 1;
+
+ if (win->src.eventLen >= 0)
+ ev = win->src.events[win->src.eventLen];
+ else {
+ printf("H2\n");
+ }
+
+ return ev;
+}
+
+/* wayland global garbage (wayland bad, X11 is fine (ish) (not really)) */
+#include "xdg-shell.h"
+#include "xdg-decoration-unstable-v1.h"
+
+struct xdg_wm_base *xdg_wm_base;
+struct wl_compositor* RGFW_compositor = NULL;
+struct wl_shm* shm = NULL;
+struct wl_shell* RGFW_shell = NULL;
+static struct wl_seat *seat = NULL;
+static struct xkb_context *xkb_context;
+static struct xkb_keymap *keymap = NULL;
+static struct xkb_state *xkb_state = NULL;
+enum zxdg_toplevel_decoration_v1_mode client_preferred_mode, RGFW_current_mode;
+static struct zxdg_decoration_manager_v1 *decoration_manager = NULL;
+
+struct wl_cursor_theme* RGFW_wl_cursor_theme = NULL;
+struct wl_surface* RGFW_cursor_surface = NULL;
+struct wl_cursor_image* RGFW_cursor_image = NULL;
+
+static void xdg_wm_base_ping_handler(void *data,
+ struct xdg_wm_base *wm_base, uint32_t serial)
+{
+ RGFW_UNUSED(data);
+ xdg_wm_base_pong(wm_base, serial);
+}
+
+static const struct xdg_wm_base_listener xdg_wm_base_listener = {
+ .ping = xdg_wm_base_ping_handler,
+};
+
+b8 RGFW_wl_configured = 0;
+
+static void xdg_surface_configure_handler(void *data,
+ struct xdg_surface *xdg_surface, uint32_t serial)
+{
+ RGFW_UNUSED(data);
+ xdg_surface_ack_configure(xdg_surface, serial);
+ #ifdef RGFW_DEBUG
+ printf("Surface configured\n");
+ #endif
+ RGFW_wl_configured = 1;
+}
+
+static const struct xdg_surface_listener xdg_surface_listener = {
+ .configure = xdg_surface_configure_handler,
+};
+
+static void xdg_toplevel_configure_handler(void *data,
+ struct xdg_toplevel *toplevel, int32_t width, int32_t height,
+ struct wl_array *states)
+{
+ RGFW_UNUSED(data); RGFW_UNUSED(toplevel); RGFW_UNUSED(states)
+ fprintf(stderr, "XDG toplevel configure: %dx%d\n", width, height);
+}
+
+static void xdg_toplevel_close_handler(void *data,
+ struct xdg_toplevel *toplevel)
+{
+ RGFW_UNUSED(data);
+ RGFW_window* win = (RGFW_window*)xdg_toplevel_get_user_data(toplevel);
+ if (win == NULL)
+ win = RGFW_key_win;
+
+ RGFW_Event ev;
+ ev.type = RGFW_quit;
+
+ RGFW_eventPipe_push(win, ev);
+
+ RGFW_windowQuitCallback(win);
+}
+
+static void shm_format_handler(void *data,
+ struct wl_shm *shm, uint32_t format)
+{
+ RGFW_UNUSED(data); RGFW_UNUSED(shm);
+ fprintf(stderr, "Format %d\n", format);
+}
+
+static const struct wl_shm_listener shm_listener = {
+ .format = shm_format_handler,
+};
+
+static const struct xdg_toplevel_listener xdg_toplevel_listener = {
+ .configure = xdg_toplevel_configure_handler,
+ .close = xdg_toplevel_close_handler,
+};
+
+RGFW_window* RGFW_mouse_win = NULL;
+
+static void pointer_enter(void *data, struct wl_pointer *pointer, uint32_t serial, struct wl_surface *surface, wl_fixed_t surface_x, wl_fixed_t surface_y) {
+ RGFW_UNUSED(data); RGFW_UNUSED(pointer); RGFW_UNUSED(serial); RGFW_UNUSED(surface_x); RGFW_UNUSED(surface_y);
+ RGFW_window* win = (RGFW_window*)wl_surface_get_user_data(surface);
+ RGFW_mouse_win = win;
+
+ RGFW_Event ev;
+ ev.type = RGFW_mouseEnter;
+ ev.point = win->event.point;
+
+ RGFW_eventPipe_push(win, ev);
+
+ RGFW_mouseNotifyCallBack(win, win->event.point, RGFW_TRUE);
+}
+static void pointer_leave(void *data, struct wl_pointer *pointer, uint32_t serial, struct wl_surface *surface) {
+ RGFW_UNUSED(data); RGFW_UNUSED(pointer); RGFW_UNUSED(serial); RGFW_UNUSED(surface);
+ RGFW_window* win = (RGFW_window*)wl_surface_get_user_data(surface);
+ if (RGFW_mouse_win == win)
+ RGFW_mouse_win = NULL;
+
+ RGFW_Event ev;
+ ev.type = RGFW_mouseLeave;
+ ev.point = win->event.point;
+ RGFW_eventPipe_push(win, ev);
+
+ RGFW_mouseNotifyCallBack(win, win->event.point, RGFW_FALSE);
+}
+static void pointer_motion(void *data, struct wl_pointer *pointer, uint32_t time, wl_fixed_t x, wl_fixed_t y) {
+ RGFW_UNUSED(data); RGFW_UNUSED(pointer); RGFW_UNUSED(time); RGFW_UNUSED(x); RGFW_UNUSED(y);
+
+ assert(RGFW_mouse_win != NULL);
+
+ RGFW_Event ev;
+ ev.type = RGFW_mousePosChanged;
+ ev.point = RGFW_POINT(wl_fixed_to_double(x), wl_fixed_to_double(y));
+ RGFW_eventPipe_push(RGFW_mouse_win, ev);
+
+ RGFW_mousePosCallback(RGFW_mouse_win, RGFW_POINT(wl_fixed_to_double(x), wl_fixed_to_double(y)));
+}
+static void pointer_button(void *data, struct wl_pointer *pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state) {
+ RGFW_UNUSED(data); RGFW_UNUSED(pointer); RGFW_UNUSED(time); RGFW_UNUSED(serial);
+ assert(RGFW_mouse_win != NULL);
+
+ u32 b = (button - 0x110) + 1;
+
+ /* flip right and middle button codes */
+ if (b == 2) b = 3;
+ else if (b == 3) b = 2;
+
+ RGFW_mouseButtons[b].prev = RGFW_mouseButtons[b].current;
+ RGFW_mouseButtons[b].current = state;
+
+ RGFW_Event ev;
+ ev.type = RGFW_mouseButtonPressed + state;
+ ev.button = b;
+ RGFW_eventPipe_push(RGFW_mouse_win, ev);
+
+ RGFW_mouseButtonCallback(RGFW_mouse_win, b, 0, state);
+}
+static void pointer_axis(void *data, struct wl_pointer *pointer, uint32_t time, uint32_t axis, wl_fixed_t value) {
+ RGFW_UNUSED(data); RGFW_UNUSED(pointer); RGFW_UNUSED(time); RGFW_UNUSED(axis);
+ assert(RGFW_mouse_win != NULL);
+
+ double scroll = wl_fixed_to_double(value);
+
+ RGFW_Event ev;
+ ev.type = RGFW_mouseButtonPressed;
+ ev.button = RGFW_mouseScrollUp + (scroll < 0);
+ RGFW_eventPipe_push(RGFW_mouse_win, ev);
+
+ RGFW_mouseButtonCallback(RGFW_mouse_win, RGFW_mouseScrollUp + (scroll < 0), scroll, 1);
+}
+
+void RGFW_doNothing(void) { }
+static struct wl_pointer_listener pointer_listener = (struct wl_pointer_listener){&pointer_enter, &pointer_leave, &pointer_motion, &pointer_button, &pointer_axis, (void*)&RGFW_doNothing, (void*)&RGFW_doNothing, (void*)&RGFW_doNothing, (void*)&RGFW_doNothing, (void*)&RGFW_doNothing, (void*)&RGFW_doNothing};
+
+static void keyboard_keymap (void *data, struct wl_keyboard *keyboard, uint32_t format, int32_t fd, uint32_t size) {
+ RGFW_UNUSED(data); RGFW_UNUSED(keyboard); RGFW_UNUSED(format);
+
+ char *keymap_string = mmap (NULL, size, PROT_READ, MAP_SHARED, fd, 0);
+ xkb_keymap_unref (keymap);
+ keymap = xkb_keymap_new_from_string (xkb_context, keymap_string, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
+
+ munmap (keymap_string, size);
+ close (fd);
+ xkb_state_unref (xkb_state);
+ xkb_state = xkb_state_new (keymap);
+}
+static void keyboard_enter (void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface, struct wl_array *keys) {
+ RGFW_UNUSED(data); RGFW_UNUSED(keyboard); RGFW_UNUSED(serial); RGFW_UNUSED(keys);
+
+ RGFW_key_win = (RGFW_window*)wl_surface_get_user_data(surface);
+
+ RGFW_Event ev;
+ ev.type = RGFW_focusIn;
+ ev.inFocus = RGFW_TRUE;
+ RGFW_key_win->event.inFocus = RGFW_TRUE;
+
+ RGFW_eventPipe_push((RGFW_window*)RGFW_mouse_win, ev);
+
+ RGFW_focusCallback(RGFW_key_win, RGFW_TRUE);
+}
+static void keyboard_leave (void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface) {
+ RGFW_UNUSED(data); RGFW_UNUSED(keyboard); RGFW_UNUSED(serial);
+
+ RGFW_window* win = (RGFW_window*)wl_surface_get_user_data(surface);
+ if (RGFW_key_win == win)
+ RGFW_key_win = NULL;
+
+ RGFW_Event ev;
+ ev.type = RGFW_focusOut;
+ ev.inFocus = RGFW_FALSE;
+ win->event.inFocus = RGFW_FALSE;
+ RGFW_eventPipe_push(win, ev);
+
+ RGFW_focusCallback(win, RGFW_FALSE);
+}
+static void keyboard_key (void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state) {
+ RGFW_UNUSED(data); RGFW_UNUSED(keyboard); RGFW_UNUSED(serial); RGFW_UNUSED(time);
+
+ assert(RGFW_key_win != NULL);
+
+ xkb_keysym_t keysym = xkb_state_key_get_one_sym (xkb_state, key+8);
+ char name[16];
+ xkb_keysym_get_name(keysym, name, 16);
+
+ u32 RGFW_key = RGFW_apiKeyCodeToRGFW(key);
+ RGFW_keyboard[RGFW_key].prev = RGFW_keyboard[RGFW_key].current;
+ RGFW_keyboard[RGFW_key].current = state;
+ RGFW_Event ev;
+ ev.type = RGFW_keyPressed + state;
+ ev.keyCode = RGFW_key;
+ strcpy(ev.keyName, name);
+ ev.repeat = RGFW_isHeld(RGFW_key_win, RGFW_key);
+ RGFW_eventPipe_push(RGFW_key_win, ev);
+
+ RGFW_updateLockState(RGFW_key_win, xkb_keymap_mod_get_index(keymap, "Lock"), xkb_keymap_mod_get_index(keymap, "Mod2"));
+
+ RGFW_keyCallback(RGFW_key_win, RGFW_key, name, RGFW_key_win->event.lockState, state);
+}
+static void keyboard_modifiers (void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group) {
+ RGFW_UNUSED(data); RGFW_UNUSED(keyboard); RGFW_UNUSED(serial); RGFW_UNUSED(time);
+ xkb_state_update_mask (xkb_state, mods_depressed, mods_latched, mods_locked, 0, 0, group);
+}
+static struct wl_keyboard_listener keyboard_listener = {&keyboard_keymap, &keyboard_enter, &keyboard_leave, &keyboard_key, &keyboard_modifiers, (void*)&RGFW_doNothing};
+
+static void seat_capabilities (void *data, struct wl_seat *seat, uint32_t capabilities) {
+ RGFW_UNUSED(data);
+
+ if (capabilities & WL_SEAT_CAPABILITY_POINTER) {
+ struct wl_pointer *pointer = wl_seat_get_pointer (seat);
+ wl_pointer_add_listener (pointer, &pointer_listener, NULL);
+ }
+ if (capabilities & WL_SEAT_CAPABILITY_KEYBOARD) {
+ struct wl_keyboard *keyboard = wl_seat_get_keyboard (seat);
+ wl_keyboard_add_listener (keyboard, &keyboard_listener, NULL);
+ }
+}
+static struct wl_seat_listener seat_listener = {&seat_capabilities, (void*)&RGFW_doNothing};
+
+static void wl_global_registry_handler(void *data,
+ struct wl_registry *registry, uint32_t id, const char *interface,
+ uint32_t version)
+{
+ RGFW_UNUSED(data); RGFW_UNUSED(version);
+
+ if (strcmp(interface, "wl_compositor") == 0) {
+ RGFW_compositor = wl_registry_bind(registry,
+ id, &wl_compositor_interface, 4);
+ } else if (strcmp(interface, "xdg_wm_base") == 0) {
+ xdg_wm_base = wl_registry_bind(registry,
+ id, &xdg_wm_base_interface, 1);
+ } else if (strcmp(interface, zxdg_decoration_manager_v1_interface.name) == 0) {
+ decoration_manager = wl_registry_bind(registry, id, &zxdg_decoration_manager_v1_interface, 1);
+ } else if (strcmp(interface, "wl_shm") == 0) {
+ shm = wl_registry_bind(registry,
+ id, &wl_shm_interface, 1);
+ wl_shm_add_listener(shm, &shm_listener, NULL);
+ } else if (strcmp(interface,"wl_seat") == 0) {
+ seat = wl_registry_bind(registry, id, &wl_seat_interface, 1);
+ wl_seat_add_listener(seat, &seat_listener, NULL);
+ }
+
+ else {
+ #ifdef RGFW_DEBUG
+ printf("did not register %s\n", interface);
+ return;
+ #endif
+ }
+
+ #ifdef RGFW_DEBUG
+ printf("registered %s\n", interface);
+ #endif
+}
+
+static void wl_global_registry_remove(void *data, struct wl_registry *registry, uint32_t name) { RGFW_UNUSED(data); RGFW_UNUSED(registry); RGFW_UNUSED(name); }
+static const struct wl_registry_listener registry_listener = {
+ .global = wl_global_registry_handler,
+ .global_remove = wl_global_registry_remove,
+};
+
+static const char *get_mode_name(enum zxdg_toplevel_decoration_v1_mode mode) {
+ switch (mode) {
+ case ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE:
+ return "client-side decorations";
+ case ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE:
+ return "server-side decorations";
+ }
+ abort();
+}
+
+
+static void decoration_handle_configure(void *data,
+ struct zxdg_toplevel_decoration_v1 *decoration,
+ enum zxdg_toplevel_decoration_v1_mode mode) {
+ RGFW_UNUSED(data); RGFW_UNUSED(decoration);
+ printf("Using %s\n", get_mode_name(mode));
+ RGFW_current_mode = mode;
+}
+
+static const struct zxdg_toplevel_decoration_v1_listener decoration_listener = {
+ .configure = decoration_handle_configure,
+};
+
+static void randname(char *buf) {
+ struct timespec ts;
+ clock_gettime(CLOCK_REALTIME, &ts);
+ long r = ts.tv_nsec;
+ for (int i = 0; i < 6; ++i) {
+ buf[i] = 'A'+(r&15)+(r&16)*2;
+ r >>= 5;
+ }
+}
+
+static int anonymous_shm_open(void) {
+ char name[] = "/RGFW-wayland-XXXXXX";
+ int retries = 100;
+
+ do {
+ randname(name + strlen(name) - 6);
+
+ --retries;
+ // shm_open guarantees that O_CLOEXEC is set
+ int fd = shm_open(name, O_RDWR | O_CREAT | O_EXCL, 0600);
+ if (fd >= 0) {
+ shm_unlink(name);
+ return fd;
+ }
+ } while (retries > 0 && errno == EEXIST);
+
+ return -1;
+}
+
+int create_shm_file(off_t size) {
+ int fd = anonymous_shm_open();
+ if (fd < 0) {
+ return fd;
+ }
+
+ if (ftruncate(fd, size) < 0) {
+ close(fd);
+ return -1;
+ }
+
+ return fd;
+}
+
+static void wl_surface_frame_done(void *data, struct wl_callback *cb, uint32_t time) {
+ #ifdef RGFW_BUFFER
+ RGFW_window* win = (RGFW_window*)data;
+ if ((win->_winArgs & RGFW_NO_CPU_RENDER))
+ return;
+
+ #ifndef RGFW_X11_DONT_CONVERT_BGR
+ u32 x, y;
+ for (y = 0; y < (u32)win->r.h; y++) {
+ for (x = 0; x < (u32)win->r.w; x++) {
+ u32 index = (y * 4 * win->r.w) + x * 4;
+
+ u8 red = win->buffer[index];
+ win->buffer[index] = win->buffer[index + 2];
+ win->buffer[index + 2] = red;
+
+ }
+ }
+ #endif
+
+ wl_surface_attach(win->src.surface, win->src.wl_buffer, 0, 0);
+ wl_surface_damage_buffer(win->src.surface, 0, 0, win->r.w, win->r.h);
+ wl_surface_commit(win->src.surface);
+ #endif
+}
+
+static const struct wl_callback_listener wl_surface_frame_listener = {
+ .done = wl_surface_frame_done,
+};
+
+
+ /* normal wayland RGFW stuff */
+
+ RGFW_area RGFW_getScreenSize(void) {
+ RGFW_area area = {};
+
+ if (RGFW_root != NULL)
+ /* this isn't right but it's here for buffers */
+ area = RGFW_AREA(RGFW_root->r.w, RGFW_root->r.h);
+
+ /* TODO wayland */
+ return area;
+ }
+
+ void RGFW_releaseCursor(RGFW_window* win) {
+ RGFW_UNUSED(win);
+ }
+
+ void RGFW_captureCursor(RGFW_window* win, RGFW_rect r) {
+ RGFW_UNUSED(win); RGFW_UNUSED(r);
+
+ /* TODO wayland */
+ }
+
+
+ RGFWDEF void RGFW_init_buffer(RGFW_window* win);
+ void RGFW_init_buffer(RGFW_window* win) {
+ #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)
+ size_t size = win->r.w * win->r.h * 4;
+ int fd = create_shm_file(size);
+ if (fd < 0) {
+ fprintf(stderr, "Failed to create a buffer. size: %ld\n", size);
+ exit(1);
+ }
+
+ win->buffer = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ if (win->buffer == MAP_FAILED) {
+ fprintf(stderr, "mmap failed!\n");
+ close(fd);
+ exit(1);
+ }
+
+ struct wl_shm_pool* pool = wl_shm_create_pool(shm, fd, size);
+ win->src.wl_buffer = wl_shm_pool_create_buffer(pool, 0, win->r.w, win->r.h, win->r.w * 4,
+ WL_SHM_FORMAT_ARGB8888);
+ wl_shm_pool_destroy(pool);
+
+ close(fd);
+
+ wl_surface_attach(win->src.surface, win->src.wl_buffer, 0, 0);
+ wl_surface_commit(win->src.surface);
+
+ u8 color[] = {0x00, 0x00, 0x00, 0xFF};
+
+ size_t i;
+ for (i = 0; i < size; i += 4) {
+ memcpy(&win->buffer[i], color, 4);
+ }
+
+ #if defined(RGFW_OSMESA)
+ win->src.ctx = OSMesaCreateContext(OSMESA_RGBA, NULL);
+ OSMesaMakeCurrent(win->src.ctx, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h);
+ #endif
+ #else
+ RGFW_UNUSED(win);
+ #endif
+ }
+
+
+ RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) {
+ RGFW_window* win = RGFW_window_basic_init(rect, args);
+
+ fprintf(stderr, "Warning: RGFW Wayland support is experimental\n");
+
+ win->src.display = wl_display_connect(NULL);
+ if (win->src.display == NULL) {
+ #ifdef RGFW_DEBUG
+ fprintf(stderr, "Failed to load Wayland display\n");
+ #endif
+ return NULL;
+ }
+
+ struct wl_registry *registry = wl_display_get_registry(win->src.display);
+ wl_registry_add_listener(registry, ®istry_listener, NULL);
+
+ wl_display_dispatch(win->src.display);
+ wl_display_roundtrip(win->src.display);
+
+ if (RGFW_compositor == NULL) {
+ #ifdef RGFW_DEBUG
+ fprintf(stderr, "Can't find compositor.\n");
+ #endif
+
+ return NULL;
+ }
+
+ if (RGFW_wl_cursor_theme == NULL) {
+ RGFW_wl_cursor_theme = wl_cursor_theme_load(NULL, 24, shm);
+ RGFW_cursor_surface = wl_compositor_create_surface(RGFW_compositor);
+
+ struct wl_cursor* cursor = wl_cursor_theme_get_cursor(RGFW_wl_cursor_theme, "left_ptr");
+ RGFW_cursor_image = cursor->images[0];
+ struct wl_buffer* cursor_buffer = wl_cursor_image_get_buffer(RGFW_cursor_image);
+
+ wl_surface_attach(RGFW_cursor_surface, cursor_buffer, 0, 0);
+ wl_surface_commit(RGFW_cursor_surface);
+ }
+
+ if (RGFW_root == NULL)
+ xdg_wm_base_add_listener(xdg_wm_base, &xdg_wm_base_listener, NULL);
+
+ xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
+
+ win->src.surface = wl_compositor_create_surface(RGFW_compositor);
+ wl_surface_set_user_data(win->src.surface, win);
+
+ win->src.xdg_surface = xdg_wm_base_get_xdg_surface(xdg_wm_base, win->src.surface);
+ xdg_surface_add_listener(win->src.xdg_surface, &xdg_surface_listener, NULL);
+
+ xdg_wm_base_set_user_data(xdg_wm_base, win);
+
+ win->src.xdg_toplevel = xdg_surface_get_toplevel(win->src.xdg_surface);
+ xdg_toplevel_set_user_data(win->src.xdg_toplevel, win);
+ xdg_toplevel_set_title(win->src.xdg_toplevel, name);
+ xdg_toplevel_add_listener(win->src.xdg_toplevel, &xdg_toplevel_listener, NULL);
+
+ xdg_surface_set_window_geometry(win->src.xdg_surface, 0, 0, win->r.w, win->r.h);
+
+ if (!(args & RGFW_NO_BORDER)) {
+ win->src.decoration = zxdg_decoration_manager_v1_get_toplevel_decoration(
+ decoration_manager, win->src.xdg_toplevel);
+ }
+
+
+ if (args & RGFW_OPENGL_SOFTWARE)
+ setenv("LIBGL_ALWAYS_SOFTWARE", "1", 1);
+
+ wl_display_roundtrip(win->src.display);
+
+ wl_surface_commit(win->src.surface);
+
+ /* wait for the surface to be configured */
+ while (wl_display_dispatch(win->src.display) != -1 && !RGFW_wl_configured) { }
+
+
+ #ifdef RGFW_OPENGL
+ if ((args & RGFW_NO_INIT_API) == 0) {
+ win->src.window = wl_egl_window_create(win->src.surface, win->r.w, win->r.h);
+ RGFW_createOpenGLContext(win);
+ }
+ #endif
+
+ RGFW_init_buffer(win);
+
+ struct wl_callback* callback = wl_surface_frame(win->src.surface);
+ wl_callback_add_listener(callback, &wl_surface_frame_listener, win);
+ wl_surface_commit(win->src.surface);
+
+ if (args & RGFW_HIDE_MOUSE) {
+ RGFW_window_showMouse(win, 0);
+ }
+
+ if (RGFW_root == NULL) {
+ RGFW_root = win;
+ }
+
+ win->src.eventIndex = 0;
+ win->src.eventLen = 0;
+
+ return win;
+ }
+
+ RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) {
+ if (win->_winArgs & RGFW_WINDOW_HIDE)
+ return NULL;
+
+ if (win->src.eventIndex == 0) {
+ if (wl_display_roundtrip(win->src.display) == -1) {
+ return NULL;
+ }
+ RGFW_resetKey();
+ }
+
+ #ifdef __linux__
+ RGFW_Event* event = RGFW_linux_updateJoystick(win);
+ if (event != NULL)
+ return event;
+ #endif
+
+ if (win->src.eventLen == 0) {
+ return NULL;
+ }
+
+ RGFW_Event ev = RGFW_eventPipe_pop(win);
+
+ if (ev.type == 0 || win->event.type == RGFW_quit) {
+ return NULL;
+ }
+
+ ev.frameTime = win->event.frameTime;
+ ev.frameTime2 = win->event.frameTime2;
+ ev.inFocus = win->event.inFocus;
+ win->event = ev;
+
+ return &win->event;
+ }
+
+
+ void RGFW_window_resize(RGFW_window* win, RGFW_area a) {
+ RGFW_UNUSED(win); RGFW_UNUSED(a);
+
+ /* TODO wayland */
+ }
+
+ void RGFW_window_move(RGFW_window* win, RGFW_point v) {
+ RGFW_UNUSED(win); RGFW_UNUSED(v);
+
+ /* TODO wayland */
+ }
+
+ void RGFW_window_setIcon(RGFW_window* win, u8* src, RGFW_area a, i32 channels) {
+ RGFW_UNUSED(win); RGFW_UNUSED(src); RGFW_UNUSED(a); RGFW_UNUSED(channels)
+ /* TODO wayland */
+ }
+
+ void RGFW_window_moveMouse(RGFW_window* win, RGFW_point v) {
+ RGFW_UNUSED(win); RGFW_UNUSED(v);
+
+ /* TODO wayland */
+ }
+
+ void RGFW_window_showMouse(RGFW_window* win, i8 show) {
+ RGFW_UNUSED(win);
+
+ if (show) {
+
+ }
+ else {
+
+ }
+
+ /* TODO wayland */
+ }
+
+ b8 RGFW_window_isMaximized(RGFW_window* win) {
+ RGFW_UNUSED(win);
+ /* TODO wayland */
+ return 0;
+ }
+
+ b8 RGFW_window_isMinimized(RGFW_window* win) {
+ RGFW_UNUSED(win);
+ /* TODO wayland */
+ return 0;
+ }
+
+ b8 RGFW_window_isHidden(RGFW_window* win) {
+ RGFW_UNUSED(win);
+ /* TODO wayland */
+ return 0;
+ }
+
+ b8 RGFW_window_isFullscreen(RGFW_window* win) {
+ RGFW_UNUSED(win);
+ /* TODO wayland */
+ return 0;
+ }
+
+ RGFW_point RGFW_window_getMousePoint(RGFW_window* win) {
+ RGFW_UNUSED(win);
+ /* TODO wayland */
+ return RGFW_POINT(0, 0);
+ }
+
+ RGFW_point RGFW_getGlobalMousePoint(void) {
+ /* TODO wayland */
+ return RGFW_POINT(0, 0);
+ }
+
+ void RGFW_window_show(RGFW_window* win) {
+ //wl_surface_attach(win->src.surface, win->rc., 0, 0);
+ wl_surface_commit(win->src.surface);
+
+ if (win->_winArgs & RGFW_WINDOW_HIDE)
+ win->_winArgs ^= RGFW_WINDOW_HIDE;
+ }
+
+ void RGFW_window_hide(RGFW_window* win) {
+ wl_surface_attach(win->src.surface, NULL, 0, 0);
+ wl_surface_commit(win->src.surface);
+ win->_winArgs |= RGFW_WINDOW_HIDE;
+ }
+
+ void RGFW_window_setMouseDefault(RGFW_window* win) {
+ RGFW_UNUSED(win);
+
+ RGFW_window_setMouseStandard(win, RGFW_MOUSE_NORMAL);
+ }
+
+ void RGFW_window_setMouseStandard(RGFW_window* win, u8 mouse) {
+ RGFW_UNUSED(win);
+
+ static const char* iconStrings[] = { "left_ptr", "left_ptr", "text", "cross", "pointer", "e-resize", "n-resize", "nw-resize", "ne-resize", "all-resize", "not-allowed" };
+
+ struct wl_cursor* cursor = wl_cursor_theme_get_cursor(RGFW_wl_cursor_theme, iconStrings[mouse]);
+ RGFW_cursor_image = cursor->images[0];
+ struct wl_buffer* cursor_buffer = wl_cursor_image_get_buffer(RGFW_cursor_image);
+
+ wl_surface_attach(RGFW_cursor_surface, cursor_buffer, 0, 0);
+ wl_surface_commit(RGFW_cursor_surface);
+ }
+
+ void RGFW_window_setMouse(RGFW_window* win, u8* image, RGFW_area a, i32 channels) {
+ RGFW_UNUSED(win); RGFW_UNUSED(image); RGFW_UNUSED(a); RGFW_UNUSED(channels)
+ //struct wl_cursor* cursor = wl_cursor_theme_get_cursor(RGFW_wl_cursor_theme, iconStrings[mouse]);
+ //RGFW_cursor_image = image;
+ struct wl_buffer* cursor_buffer = wl_cursor_image_get_buffer(RGFW_cursor_image);
+
+ wl_surface_attach(RGFW_cursor_surface, cursor_buffer, 0, 0);
+ wl_surface_commit(RGFW_cursor_surface);
+ }
+
+ void RGFW_window_setName(RGFW_window* win, char* name) {
+ xdg_toplevel_set_title(win->src.xdg_toplevel, name);
+ }
+
+ void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough) {
+ RGFW_UNUSED(win); RGFW_UNUSED(passthrough);
+
+ /* TODO wayland */
+ }
+
+ void RGFW_window_setBorder(RGFW_window* win, b8 border) {
+ RGFW_UNUSED(win); RGFW_UNUSED(border);
+
+ /* TODO wayland */
+ }
+
+ void RGFW_window_restore(RGFW_window* win) {
+ RGFW_UNUSED(win);
+
+ /* TODO wayland */
+ }
+
+ void RGFW_window_minimize(RGFW_window* win) {
+ RGFW_UNUSED(win);
+
+ /* TODO wayland */
+ }
+
+ void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a) {
+ RGFW_UNUSED(win); RGFW_UNUSED(a);
+
+ /* TODO wayland */
+ }
+
+ void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a) {
+ RGFW_UNUSED(win); RGFW_UNUSED(a);
+
+ /* TODO wayland */
+ }
+
+ RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) {
+ RGFW_monitor m = {};
+ RGFW_UNUSED(win);
+ RGFW_UNUSED(m);
+ /* TODO wayland */
+
+ return m;
+ }
+
+
+ #ifndef RGFW_EGL
+ void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) { RGFW_UNUSED(win); RGFW_UNUSED(swapInterval); }
+ #endif
+
+ void RGFW_window_swapBuffers(RGFW_window* win) {
+ assert(win != NULL);
+
+ /* clear the window*/
+ #ifdef RGFW_BUFFER
+ wl_surface_frame_done(win, NULL, 0);
+ if (!(win->_winArgs & RGFW_NO_GPU_RENDER))
+ #endif
+ {
+ #ifdef RGFW_OPENGL
+ eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface);
+ #endif
+ }
+
+ wl_display_flush(win->src.display);
+ }
+
+ void RGFW_window_close(RGFW_window* win) {
+ #ifdef RGFW_EGL
+ RGFW_closeEGL(win);
+ #endif
+
+ if (RGFW_root == win) {
+ RGFW_root = NULL;
+ }
+
+ xdg_toplevel_destroy(win->src.xdg_toplevel);
+ xdg_surface_destroy(win->src.xdg_surface);
+ wl_surface_destroy(win->src.surface);
+
+ #ifdef RGFW_BUFFER
+ wl_buffer_destroy(win->src.wl_buffer);
+ #endif
+
+ wl_display_disconnect(win->src.display);
+ RGFW_FREE(win);
+ }
+
+ RGFW_monitor RGFW_getPrimaryMonitor(void) {
+ /* TODO wayland */
+
+ return (RGFW_monitor){};
+ }
+
+ RGFW_monitor* RGFW_getMonitors(void) {
+ /* TODO wayland */
+
+ return NULL;
+ }
+
+ void RGFW_writeClipboard(const char* text, u32 textLen) {
+ RGFW_UNUSED(text); RGFW_UNUSED(textLen);
+
+ /* TODO wayland */
+ }
+
+ char* RGFW_readClipboard(size_t* size) {
+ RGFW_UNUSED(size);
+
+ /* TODO wayland */
+
+ return NULL;
+ }
+#endif /* RGFW_WAYLAND */
+
+/*
+ End of Wayland defines
+*/
/*
@@ -3822,6 +4997,8 @@ Start of Linux / Unix defines
#ifdef RGFW_WINDOWS
#define WIN32_LEAN_AND_MEAN
+ #define OEMRESOURCE
+ #include
#include
#include
@@ -3829,8 +5006,6 @@ Start of Linux / Unix defines
#include
#include
#include
- #include
- #include
#ifndef RGFW_NO_XINPUT
typedef DWORD (WINAPI * PFN_XInputGetState)(DWORD,XINPUT_STATE*);
@@ -3873,13 +5048,6 @@ Start of Linux / Unix defines
#define wglGetSwapIntervalEXT wglGetSwapIntervalEXTSrc
-
-#if defined(RGFW_DIRECTX)
- RGFW_directXinfo RGFW_dxInfo;
-
- RGFW_directXinfo* RGFW_getDirectXInfo(void) { return &RGFW_dxInfo; }
-#endif
-
void* RGFWjoystickApi = NULL;
/* these two wgl functions need to be preloaded */
@@ -3893,7 +5061,6 @@ Start of Linux / Unix defines
#define WGL_DRAW_TO_WINDOW_ARB 0x2001
#define WGL_ACCELERATION_ARB 0x2003
#define WGL_NO_ACCELERATION_ARB 0x2025
-#define WGL_SUPPORT_OPENGL_ARB 0x2010
#define WGL_DOUBLE_BUFFER_ARB 0x2011
#define WGL_COLOR_BITS_ARB 0x2014
#define WGL_RED_BITS_ARB 0x2015
@@ -3990,7 +5157,7 @@ static HMODULE wglinstance = NULL;
#endif
__declspec(dllimport) u32 __stdcall timeBeginPeriod(u32 uPeriod);
-
+
#ifndef RGFW_NO_XINPUT
void RGFW_loadXInput(void) {
u32 i;
@@ -4048,7 +5215,7 @@ static HMODULE wglinstance = NULL;
OSMesaMakeCurrent(win->src.ctx, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h);
#endif
#else
-RGFW_UNUSED(win); /* if buffer rendering is not being used */
+RGFW_UNUSED(win); /*!< if buffer rendering is not being used */
#endif
}
@@ -4056,16 +5223,14 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */
DragAcceptFiles(win->src.window, allow);
}
+ void RGFW_releaseCursor(RGFW_window* win) {
+ ClipCursor(NULL);
+ const RAWINPUTDEVICE id = { 0x01, 0x02, RIDEV_REMOVE, NULL };
+ RegisterRawInputDevices(&id, 1, sizeof(id));
+ }
+
void RGFW_captureCursor(RGFW_window* win, RGFW_rect rect) {
RGFW_UNUSED(win)
-
- if (!rect.x && !rect.y && rect.w && !rect.h) {
- ClipCursor(NULL);
- const RAWINPUTDEVICE id = { 0x01, 0x02, RIDEV_REMOVE, NULL };
- RegisterRawInputDevices(&id, 1, sizeof(id));
-
- return;
- }
RECT clipRect;
GetClientRect(win->src.window, &clipRect);
@@ -4101,9 +5266,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */
wglGetCurrentContextSRC = (PFN_wglGetCurrentContext) GetProcAddress(wglinstance, "wglGetCurrentContext");
#endif
}
-
- timeBeginPeriod(1);
-
+
if (name[0] == 0) name = (char*) " ";
RGFW_eventWindow.r = RGFW_RECT(-1, -1, -1, -1);
@@ -4117,7 +5280,12 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */
HINSTANCE inh = GetModuleHandleA(NULL);
- WNDCLASSA Class = { 0 }; /* Setup the Window class. */
+ #ifndef __cplusplus
+ WNDCLASSA Class = { 0 }; /*!< Setup the Window class. */
+ #else
+ WNDCLASSA Class = { };
+ #endif
+
Class.lpszClassName = name;
Class.hInstance = inh;
Class.hCursor = LoadCursor(NULL, IDC_ARROW);
@@ -4130,7 +5298,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */
RECT windowRect, clientRect;
if (!(args & RGFW_NO_BORDER)) {
- window_style |= WS_CAPTION | WS_SYSMENU | WS_BORDER | WS_VISIBLE | WS_MINIMIZEBOX;
+ window_style |= WS_CAPTION | WS_SYSMENU | WS_BORDER | WS_MINIMIZEBOX;
if (!(args & RGFW_NO_RESIZE))
window_style |= WS_SIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME;
@@ -4215,17 +5383,26 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */
#ifdef RGFW_OPENGL
HDC dummy_dc = GetDC(dummyWin);
-
- PIXELFORMATDESCRIPTOR pfd = {
- .nSize = sizeof(pfd),
- .nVersion = 1,
- .iPixelType = PFD_TYPE_RGBA,
- .dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
- .cColorBits = 24,
- .cAlphaBits = 8,
- .iLayerType = PFD_MAIN_PLANE,
- .cDepthBits = 32,
- .cStencilBits = 8,
+
+ u32 pfd_flags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
+
+ //if (RGFW_DOUBLE_BUFFER)
+ pfd_flags |= PFD_DOUBLEBUFFER;
+
+ PIXELFORMATDESCRIPTOR pfd = {
+ sizeof(pfd),
+ 1, /* version */
+ pfd_flags,
+ PFD_TYPE_RGBA, /* ipixel type */
+ 24, /* color bits */
+ 0, 0, 0, 0, 0, 0,
+ 8, /* alpha bits */
+ 0, 0, 0, 0, 0, 0,
+ 32, /* depth bits */
+ 8, /* stencil bits */
+ 0,
+ PFD_MAIN_PLANE, /* Layer type */
+ 0, 0, 0, 0
};
int pixel_format = ChoosePixelFormat(dummy_dc, &pfd);
@@ -4242,41 +5419,41 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */
wglMakeCurrent(dummy_dc, 0);
wglDeleteContext(dummy_context);
ReleaseDC(dummyWin, dummy_dc);
-
+
+ /* try to create the pixel format we want for opengl and then try to create an opengl context for the specified version */
if (wglCreateContextAttribsARB != NULL) {
- PIXELFORMATDESCRIPTOR pfd = (PIXELFORMATDESCRIPTOR){ sizeof(pfd), 1, PFD_TYPE_RGBA, PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, 32, 8, PFD_MAIN_PLANE, 24, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ PIXELFORMATDESCRIPTOR pfd = {sizeof(pfd), 1, pfd_flags, PFD_TYPE_RGBA, 32, 8, PFD_MAIN_PLANE, 24, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
if (args & RGFW_OPENGL_SOFTWARE)
pfd.dwFlags |= PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED;
if (wglChoosePixelFormatARB != NULL) {
- i32* pixel_format_attribs = (i32*)RGFW_initAttribs(args & RGFW_OPENGL_SOFTWARE);
+ i32* pixel_format_attribs = (i32*)RGFW_initFormatAttribs(args & RGFW_OPENGL_SOFTWARE);
int pixel_format;
UINT num_formats;
wglChoosePixelFormatARB(win->src.hdc, pixel_format_attribs, 0, 1, &pixel_format, &num_formats);
if (!num_formats) {
- printf("Failed to set the OpenGL 3.3 pixel format.\n");
+ printf("Failed to create a pixel format for WGL.\n");
}
DescribePixelFormat(win->src.hdc, pixel_format, sizeof(pfd), &pfd);
if (!SetPixelFormat(win->src.hdc, pixel_format, &pfd)) {
- printf("Failed to set the OpenGL 3.3 pixel format.\n");
+ printf("Failed to set the WGL pixel format.\n");
}
}
-
+
+ /* create opengl/WGL context for the specified version */
u32 index = 0;
i32 attribs[40];
- SET_ATTRIB(WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB);
-
- if (RGFW_majorVersion || RGFW_minorVersion) {
- SET_ATTRIB(WGL_CONTEXT_MAJOR_VERSION_ARB, RGFW_majorVersion);
- SET_ATTRIB(WGL_CONTEXT_MINOR_VERSION_ARB, RGFW_minorVersion);
+ if (RGFW_profile == RGFW_GL_CORE) {
+ SET_ATTRIB(WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB);
}
-
- SET_ATTRIB(WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB);
-
+ else {
+ SET_ATTRIB(WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB);
+ }
+
if (RGFW_majorVersion || RGFW_minorVersion) {
SET_ATTRIB(WGL_CONTEXT_MAJOR_VERSION_ARB, RGFW_majorVersion);
SET_ATTRIB(WGL_CONTEXT_MINOR_VERSION_ARB, RGFW_minorVersion);
@@ -4285,7 +5462,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */
SET_ATTRIB(0, 0);
win->src.ctx = (HGLRC)wglCreateContextAttribsARB(win->src.hdc, NULL, attribs);
- } else {
+ } else { /* fall back to a default context (probably opengl 2 or something) */
fprintf(stderr, "Failed to create an accelerated OpenGL Context\n");
int pixel_format = ChoosePixelFormat(win->src.hdc, &pfd);
@@ -4659,7 +5836,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */
CharLowerBuffA(keyName, 16);
}
}
-
+
RGFW_updateLockState(win, (GetKeyState(VK_CAPITAL) & 0x0001), (GetKeyState(VK_NUMLOCK) & 0x0001));
strncpy(win->event.keyName, keyName, 16);
@@ -4670,6 +5847,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */
}
win->event.type = RGFW_keyPressed;
+ win->event.repeat = RGFW_isPressed(win, win->event.keyCode);
RGFW_keyboard[win->event.keyCode].current = 1;
RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, 1);
break;
@@ -4706,8 +5884,8 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */
break;
win->event.type = RGFW_mousePosChanged;
- win->event.point.x = -raw->data.mouse.lLastX;
- win->event.point.y = -raw->data.mouse.lLastY;
+ win->event.point.x = raw->data.mouse.lLastX;
+ win->event.point.y = raw->data.mouse.lLastY;
break;
}
@@ -4830,7 +6008,11 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */
u8 RGFW_window_isFullscreen(RGFW_window* win) {
assert(win != NULL);
+ #ifndef __cplusplus
WINDOWPLACEMENT placement = { 0 };
+ #else
+ WINDOWPLACEMENT placement = { };
+ #endif
GetWindowPlacement(win->src.window, &placement);
return placement.showCmd == SW_SHOWMAXIMIZED;
}
@@ -4844,7 +6026,11 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */
u8 RGFW_window_isMinimized(RGFW_window* win) {
assert(win != NULL);
+ #ifndef __cplusplus
WINDOWPLACEMENT placement = { 0 };
+ #else
+ WINDOWPLACEMENT placement = { };
+ #endif
GetWindowPlacement(win->src.window, &placement);
return placement.showCmd == SW_SHOWMINIMIZED;
}
@@ -4852,7 +6038,11 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */
u8 RGFW_window_isMaximized(RGFW_window* win) {
assert(win != NULL);
+ #ifndef __cplusplus
WINDOWPLACEMENT placement = { 0 };
+ #else
+ WINDOWPLACEMENT placement = { };
+ #endif
GetWindowPlacement(win->src.window, &placement);
return placement.showCmd == SW_SHOWMAXIMIZED;
}
@@ -4892,7 +6082,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */
for (deviceIndex = 0; EnumDisplayDevicesA(0, (DWORD) deviceIndex, &dd, 0); deviceIndex++) {
char* deviceName = dd.DeviceName;
if (EnumDisplayDevicesA(deviceName, info.iIndex, &dd, 0)) {
- strncpy(monitor.name, dd.DeviceString, 128); /* copy the monitor's name */
+ strncpy(monitor.name, dd.DeviceString, 128); /*!< copy the monitor's name */
break;
}
}
@@ -4904,6 +6094,10 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */
monitor.rect.h = monitorInfo.rcWork.bottom - monitorInfo.rcWork.top;
#ifndef RGFW_NO_DPI
+ #ifndef USER_DEFAULT_SCREEN_DPI
+ #define USER_DEFAULT_SCREEN_DPI 96
+ #endif
+
if (GetDpiForMonitor != NULL) {
u32 x, y;
GetDpiForMonitor(src, MDT_ANGULAR_DPI, &x, &y);
@@ -4945,8 +6139,12 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */
}
RGFW_monitor RGFW_getPrimaryMonitor(void) {
+ #ifdef __cplusplus
+ return win32CreateMonitor(MonitorFromPoint({ 0, 0 }, MONITOR_DEFAULTTOPRIMARY));
+ #else
return win32CreateMonitor(MonitorFromPoint((POINT) { 0, 0 }, MONITOR_DEFAULTTOPRIMARY));
- }
+ #endif
+ }
RGFW_monitor* RGFW_getMonitors(void) {
RGFW_mInfo info;
@@ -5102,10 +6300,10 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */
#endif
#ifdef RGFW_OPENGL
- wglDeleteContext((HGLRC) win->src.ctx); /* delete opengl context */
+ wglDeleteContext((HGLRC) win->src.ctx); /*!< delete opengl context */
#endif
- DeleteDC(win->src.hdc); /* delete device context */
- DestroyWindow(win->src.window); /* delete window */
+ DeleteDC(win->src.hdc); /*!< delete device context */
+ DestroyWindow(win->src.window); /*!< delete window */
#if defined(RGFW_OSMESA)
if (win->buffer != NULL)
@@ -5292,8 +6490,10 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */
#ifdef RGFW_OPENGL
void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) {
- assert(win != NULL);
- wglMakeCurrent(win->src.hdc, (HGLRC) win->src.ctx);
+ if (win == NULL)
+ wglMakeCurrent(NULL, NULL);
+ else
+ wglMakeCurrent(win->src.hdc, (HGLRC) win->src.ctx);
}
#endif
@@ -5308,7 +6508,6 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */
if (loadSwapFunc == NULL) {
fprintf(stderr, "wglSwapIntervalEXT not supported\n");
- win->fpsCap = (swapInterval == 1) ? 0 : swapInterval;
return;
}
@@ -5319,18 +6518,15 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */
if (wglSwapIntervalEXT(swapInterval) == FALSE)
fprintf(stderr, "Failed to set swap interval\n");
- #endif
-
- win->fpsCap = (swapInterval == 1) ? 0 : swapInterval;
+ #else
+ RGFW_UNUSED(swapInterval);
+ #endif
}
#endif
void RGFW_window_swapBuffers(RGFW_window* win) {
- assert(win != NULL);
-
- RGFW_window_makeCurrent(win);
-
+ //assert(win != NULL);
/* clear the window*/
if (!(win->_winArgs & RGFW_NO_CPU_RENDER)) {
@@ -5356,8 +6552,6 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */
win->src.swapchain->lpVtbl->Present(win->src.swapchain, 0, 0);
#endif
}
-
- RGFW_window_checkFPS(win);
}
char* createUTF8FromWideStringWin32(const WCHAR* source) {
@@ -5378,20 +6572,28 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */
return target;
}
+
+ static inline LARGE_INTEGER RGFW_win32_initTimer(void) {
+ static LARGE_INTEGER frequency = {{0, 0}};
+ if (frequency.QuadPart == 0) {
+ timeBeginPeriod(1);
+ QueryPerformanceFrequency(&frequency);
+ }
+
+ return frequency;
+ }
u64 RGFW_getTimeNS(void) {
- LARGE_INTEGER frequency;
- QueryPerformanceFrequency(&frequency);
+ LARGE_INTEGER frequency = RGFW_win32_initTimer();
LARGE_INTEGER counter;
QueryPerformanceCounter(&counter);
- return (u64) (counter.QuadPart * 1e9 / frequency.QuadPart);
+ return (u64) ((counter.QuadPart * 1e9) / frequency.QuadPart);
}
u64 RGFW_getTime(void) {
- LARGE_INTEGER frequency;
- QueryPerformanceFrequency(&frequency);
+ LARGE_INTEGER frequency = RGFW_win32_initTimer();
LARGE_INTEGER counter;
QueryPerformanceCounter(&counter);
@@ -5720,11 +6922,9 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */
NSWindowStyleMaskHUDWindow = 1 << 13
};
- typedef const char* NSPasteboardType;
NSPasteboardType const NSPasteboardTypeString = "public.utf8-plain-text"; // Replaces NSStringPboardType
-
typedef NS_ENUM(i32, NSDragOperation) {
NSDragOperationNone = 0,
NSDragOperationCopy = 1,
@@ -6002,7 +7202,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */
OSMesaMakeCurrent(win->src.ctx, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h);
#endif
#else
- RGFW_UNUSED(win); /* if buffer rendering is not being used */
+ RGFW_UNUSED(win); /*!< if buffer rendering is not being used */
#endif
}
@@ -6063,20 +7263,22 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */
#ifdef RGFW_OPENGL
if ((args & RGFW_NO_INIT_API) == 0) {
- void* attrs = RGFW_initAttribs(args & RGFW_OPENGL_SOFTWARE);
+ void* attrs = RGFW_initFormatAttribs(args & RGFW_OPENGL_SOFTWARE);
void* format = NSOpenGLPixelFormat_initWithAttributes(attrs);
if (format == NULL) {
- printf("Failed to load pixel format ");
+ printf("Failed to load pixel format for OpenGL\n");
- void* attrs = RGFW_initAttribs(1);
+ void* attrs = RGFW_initFormatAttribs(1);
format = NSOpenGLPixelFormat_initWithAttributes(attrs);
if (format == NULL)
printf("and loading software rendering OpenGL failed\n");
else
printf("Switching to software rendering\n");
}
-
+
+ /* the pixel format can be passed directly to opengl context creation to create a context
+ this is because the format also includes information about the opengl version (which may be a bad thing) */
win->src.view = NSOpenGLView_initWithFrame((NSRect){{0, 0}, {win->r.w, win->r.h}}, format);
objc_msgSend_void(win->src.view, sel_registerName("prepareOpenGL"));
win->src.ctx = objc_msgSend_id(win->src.view, sel_registerName("openGLContext"));
@@ -6164,6 +7366,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */
}
// Show the window
+ objc_msgSend_void_bool(NSApp, sel_registerName("activateIgnoringOtherApps:"), true);
((id(*)(id, SEL, SEL))objc_msgSend)(win->src.window, sel_registerName("makeKeyAndOrderFront:"), NULL);
objc_msgSend_void_bool(win->src.window, sel_registerName("setIsVisible:"), true);
@@ -6216,7 +7419,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */
CGPoint point = CGEventGetLocation(e);
CFRelease(e);
- return RGFW_POINT((u32) point.x, (u32) point.y); /* the point is loaded during event checks */
+ return RGFW_POINT((u32) point.x, (u32) point.y); /*!< the point is loaded during event checks */
}
RGFW_point RGFW_window_getMousePoint(RGFW_window* win) {
@@ -6340,7 +7543,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */
id eventPool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc"));
eventPool = objc_msgSend_id(eventPool, sel_registerName("init"));
- void* date = (void*) ((id(*)(id, SEL, double))objc_msgSend)
+ void* date = (void*) ((id(*)(Class, SEL, double))objc_msgSend)
(objc_getClass("NSDate"), sel_registerName("dateWithTimeIntervalSinceNow:"), waitMS);
NSEvent* e = (NSEvent*) ((id(*)(id, SEL, NSEventMask, void*, NSString*, bool))objc_msgSend)
@@ -6411,7 +7614,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */
win->event.type = RGFW_mouseEnter;
NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(e, sel_registerName("locationInWindow"));
- win->event.point = RGFW_POINT((u32) p.x, (u32) (win->r.h - p.y));
+ win->event.point = RGFW_POINT((i32) p.x, (i32) (win->r.h - p.y));
RGFW_mouseNotifyCallBack(win, win->event.point, 1);
break;
}
@@ -6429,6 +7632,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */
win->event.type = RGFW_keyPressed;
char* str = (char*)(const char*) NSString_to_char(objc_msgSend_id(e, sel_registerName("characters")));
strncpy(win->event.keyName, str, 16);
+ win->event.repeat = RGFW_isPressed(win, win->event.keyCode);
RGFW_keyboard[win->event.keyCode].current = 1;
RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, 1);
@@ -6501,7 +7705,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */
p.x = ((CGFloat(*)(id, SEL))abi_objc_msgSend_fpret)(e, sel_registerName("deltaX"));
p.y = ((CGFloat(*)(id, SEL))abi_objc_msgSend_fpret)(e, sel_registerName("deltaY"));
- win->event.point = RGFW_POINT((u32) p.x, (u32) (p.y));
+ win->event.point = RGFW_POINT((i32)p.x, (i32)p.y);
}
RGFW_mousePosCallback(win, win->event.point);
@@ -6727,12 +7931,16 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */
CGDisplayShowCursor(kCGDirectMainDisplay);
objc_msgSend_void(mouse, sel_registerName("set"));
}
+
+ void RGFW_releaseCursor(RGFW_window* win) {
+ CGAssociateMouseAndMouseCursorPosition(1);
+ }
void RGFW_captureCursor(RGFW_window* win, RGFW_rect r) {
RGFW_UNUSED(win)
CGWarpMouseCursorPosition(CGPointMake(r.x + (r.w / 2), r.y + (r.h / 2)));
- CGAssociateMouseAndMouseCursorPosition((!r.x && !r.y && r.w && !r.h));
+ CGAssociateMouseAndMouseCursorPosition(0);
}
void RGFW_window_moveMouse(RGFW_window* win, RGFW_point v) {
@@ -6881,8 +8089,6 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */
NSOpenGLContext_setValues(win->src.ctx, &swapInterval, 222);
#endif
-
- win->fpsCap = (swapInterval == 1) ? 0 : swapInterval;
}
#endif
@@ -6910,9 +8116,6 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */
void RGFW_window_swapBuffers(RGFW_window* win) {
assert(win != NULL);
-
- RGFW_window_makeCurrent(win);
-
/* clear the window*/
if (!(win->_winArgs & RGFW_NO_CPU_RENDER)) {
@@ -6953,8 +8156,6 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */
objc_msgSend_void(win->src.ctx, sel_registerName("flushBuffer"));
#endif
}
-
- RGFW_window_checkFPS(win);
}
void RGFW_window_close(RGFW_window* win) {
@@ -7005,23 +8206,14 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */
*/
/*
- Start of Web ASM defines
+ WEBASM defines
*/
#ifdef RGFW_WEBASM
-
-
-#define RGFW_jsButtonPressed 7 /*!< a joystick button was pressed */
-#define RGFW_jsButtonReleased 8 /*!< a joystick button was released */
-#define RGFW_jsAxisMove 9 /*!< an axis of a joystick was moved*/
-
-#define RGFW_mouseEnter 14 /* mouse entered the window */
-#define RGFW_mouseLeave 15 /* mouse left the window */
-
RGFW_Event RGFW_events[20];
size_t RGFW_eventLen = 0;
-EM_BOOL on_keydown(int eventType, const EmscriptenKeyboardEvent* e, void* userData) {
+EM_BOOL Emscripten_on_keydown(int eventType, const EmscriptenKeyboardEvent* e, void* userData) {
RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
RGFW_events[RGFW_eventLen].type = RGFW_keyPressed;
@@ -7032,12 +8224,12 @@ EM_BOOL on_keydown(int eventType, const EmscriptenKeyboardEvent* e, void* userDa
RGFW_keyboard[RGFW_apiKeyCodeToRGFW(e->keyCode)].prev = RGFW_keyboard[RGFW_apiKeyCodeToRGFW(e->keyCode)].current;
RGFW_keyboard[RGFW_apiKeyCodeToRGFW(e->keyCode)].current = 1;
- RGFW_keyCallback(RGFW_root, e->keyCode, RGFW_events[RGFW_eventLen].keyName, 0, 1);
-
+ RGFW_keyCallback(RGFW_root, RGFW_apiKeyCodeToRGFW(e->keyCode), RGFW_events[RGFW_eventLen].keyName, 0, 1);
+
return EM_TRUE;
}
-EM_BOOL on_keyup(int eventType, const EmscriptenKeyboardEvent* e, void* userData) {
+EM_BOOL Emscripten_on_keyup(int eventType, const EmscriptenKeyboardEvent* e, void* userData) {
RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
RGFW_events[RGFW_eventLen].type = RGFW_keyReleased;
@@ -7049,12 +8241,12 @@ EM_BOOL on_keyup(int eventType, const EmscriptenKeyboardEvent* e, void* userData
RGFW_keyboard[RGFW_apiKeyCodeToRGFW(e->keyCode)].prev = RGFW_keyboard[RGFW_apiKeyCodeToRGFW(e->keyCode)].current;
RGFW_keyboard[RGFW_apiKeyCodeToRGFW(e->keyCode)].current = 0;
- RGFW_keyCallback(RGFW_root, e->keyCode, RGFW_events[RGFW_eventLen].keyName, 0, 0);
+ RGFW_keyCallback(RGFW_root, RGFW_apiKeyCodeToRGFW(e->keyCode), RGFW_events[RGFW_eventLen].keyName, 0, 0);
return EM_TRUE;
}
-EM_BOOL on_resize(int eventType, const EmscriptenUiEvent* e, void* userData) {
+EM_BOOL Emscripten_on_resize(int eventType, const EmscriptenUiEvent* e, void* userData) {
RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
RGFW_events[RGFW_eventLen].type = RGFW_windowResized;
@@ -7064,7 +8256,7 @@ EM_BOOL on_resize(int eventType, const EmscriptenUiEvent* e, void* userData) {
return EM_TRUE;
}
-EM_BOOL on_fullscreenchange(int eventType, const EmscriptenFullscreenChangeEvent* e, void* userData) {
+EM_BOOL Emscripten_on_fullscreenchange(int eventType, const EmscriptenFullscreenChangeEvent* e, void* userData) {
RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
RGFW_events[RGFW_eventLen].type = RGFW_windowResized;
@@ -7075,7 +8267,7 @@ EM_BOOL on_fullscreenchange(int eventType, const EmscriptenFullscreenChangeEvent
return EM_TRUE;
}
-EM_BOOL on_focusin(int eventType, const EmscriptenFocusEvent* e, void* userData) {
+EM_BOOL Emscripten_on_focusin(int eventType, const EmscriptenFocusEvent* e, void* userData) {
RGFW_UNUSED(eventType); RGFW_UNUSED(userData); RGFW_UNUSED(e);
RGFW_events[RGFW_eventLen].type = RGFW_focusIn;
@@ -7086,7 +8278,7 @@ EM_BOOL on_focusin(int eventType, const EmscriptenFocusEvent* e, void* userData)
return EM_TRUE;
}
-EM_BOOL on_focusout(int eventType, const EmscriptenFocusEvent* e, void* userData) {
+EM_BOOL Emscripten_on_focusout(int eventType, const EmscriptenFocusEvent* e, void* userData) {
RGFW_UNUSED(eventType); RGFW_UNUSED(userData); RGFW_UNUSED(e);
RGFW_events[RGFW_eventLen].type = RGFW_focusOut;
@@ -7097,13 +8289,13 @@ EM_BOOL on_focusout(int eventType, const EmscriptenFocusEvent* e, void* userData
return EM_TRUE;
}
-EM_BOOL on_mousemove(int eventType, const EmscriptenMouseEvent* e, void* userData) {
+EM_BOOL Emscripten_on_mousemove(int eventType, const EmscriptenMouseEvent* e, void* userData) {
RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
RGFW_events[RGFW_eventLen].type = RGFW_mousePosChanged;
if ((RGFW_root->_winArgs & RGFW_HOLD_MOUSE)) {
- RGFW_point p = RGFW_POINT(-e->movementX, -e->movementY);
+ RGFW_point p = RGFW_POINT(e->movementX, e->movementY);
RGFW_events[RGFW_eventLen].point = p;
}
else
@@ -7114,7 +8306,7 @@ EM_BOOL on_mousemove(int eventType, const EmscriptenMouseEvent* e, void* userDat
return EM_TRUE;
}
-EM_BOOL on_mousedown(int eventType, const EmscriptenMouseEvent* e, void* userData) {
+EM_BOOL Emscripten_on_mousedown(int eventType, const EmscriptenMouseEvent* e, void* userData) {
RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
RGFW_events[RGFW_eventLen].type = RGFW_mouseButtonPressed;
@@ -7131,7 +8323,7 @@ EM_BOOL on_mousedown(int eventType, const EmscriptenMouseEvent* e, void* userDat
return EM_TRUE;
}
-EM_BOOL on_mouseup(int eventType, const EmscriptenMouseEvent* e, void* userData) {
+EM_BOOL Emscripten_on_mouseup(int eventType, const EmscriptenMouseEvent* e, void* userData) {
RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
RGFW_events[RGFW_eventLen].type = RGFW_mouseButtonReleased;
@@ -7147,7 +8339,7 @@ EM_BOOL on_mouseup(int eventType, const EmscriptenMouseEvent* e, void* userData)
return EM_TRUE;
}
-EM_BOOL on_wheel(int eventType, const EmscriptenWheelEvent* e, void* userData) {
+EM_BOOL Emscripten_on_wheel(int eventType, const EmscriptenWheelEvent* e, void* userData) {
RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
RGFW_events[RGFW_eventLen].type = RGFW_mouseButtonPressed;
@@ -7164,54 +8356,82 @@ EM_BOOL on_wheel(int eventType, const EmscriptenWheelEvent* e, void* userData) {
return EM_TRUE;
}
-EM_BOOL on_touchstart(int eventType, const EmscriptenTouchEvent* e, void* userData) {
+EM_BOOL Emscripten_on_touchstart(int eventType, const EmscriptenTouchEvent* e, void* userData) {
RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
- RGFW_events[RGFW_eventLen].type = RGFW_mouseButtonPressed;
- RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->touches[0].targetX, e->touches[0].targetY);
- RGFW_events[RGFW_eventLen].button = 1;
- RGFW_events[RGFW_eventLen].scroll = 0;
+ size_t i;
+ for (i = 0; i < (size_t)e->numTouches; i++) {
+ RGFW_events[RGFW_eventLen].type = RGFW_mouseButtonPressed;
+ RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->touches[i].targetX, e->touches[i].targetY);
+ RGFW_events[RGFW_eventLen].button = 1;
+ RGFW_events[RGFW_eventLen].scroll = 0;
- RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].prev = RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current;
- RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current = 1;
+ RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].prev = RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current;
+ RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current = 1;
- RGFW_mouseButtonCallback(RGFW_root, RGFW_events[RGFW_eventLen].button, RGFW_events[RGFW_eventLen].scroll, 1);
- RGFW_eventLen++;
+ RGFW_mousePosCallback(RGFW_root, RGFW_events[RGFW_eventLen].point);
+
+ RGFW_mouseButtonCallback(RGFW_root, RGFW_events[RGFW_eventLen].button, RGFW_events[RGFW_eventLen].scroll, 1);
+ RGFW_eventLen++;
+ }
return EM_TRUE;
}
-EM_BOOL on_touchmove(int eventType, const EmscriptenTouchEvent* e, void* userData) {
+EM_BOOL Emscripten_on_touchmove(int eventType, const EmscriptenTouchEvent* e, void* userData) {
RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
+
+ size_t i;
+ for (i = 0; i < (size_t)e->numTouches; i++) {
+ RGFW_events[RGFW_eventLen].type = RGFW_mousePosChanged;
+ RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->touches[i].targetX, e->touches[i].targetY);
- RGFW_events[RGFW_eventLen].type = RGFW_mousePosChanged;
- RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->touches[0].targetX, e->touches[0].targetY);
-
- RGFW_mousePosCallback(RGFW_root, RGFW_events[RGFW_eventLen].point);
- RGFW_eventLen++;
-
- return EM_TRUE;
+ RGFW_mousePosCallback(RGFW_root, RGFW_events[RGFW_eventLen].point);
+ RGFW_eventLen++;
+ }
+ return EM_TRUE;
}
-EM_BOOL on_touchend(int eventType, const EmscriptenTouchEvent* e, void* userData) {
+EM_BOOL Emscripten_on_touchend(int eventType, const EmscriptenTouchEvent* e, void* userData) {
RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
- RGFW_events[RGFW_eventLen].type = RGFW_mouseButtonReleased;
- RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->touches[0].targetX, e->touches[0].targetY);
- RGFW_events[RGFW_eventLen].button = 1;
- RGFW_events[RGFW_eventLen].scroll = 0;
-
- RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].prev = RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current;
- RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current = 0;
-
- RGFW_mouseButtonCallback(RGFW_root, RGFW_events[RGFW_eventLen].button, RGFW_events[RGFW_eventLen].scroll, 0);
- RGFW_eventLen++;
+ size_t i;
+ for (i = 0; i < (size_t)e->numTouches; i++) {
+ RGFW_events[RGFW_eventLen].type = RGFW_mouseButtonReleased;
+ RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->touches[i].targetX, e->touches[i].targetY);
+ RGFW_events[RGFW_eventLen].button = 1;
+ RGFW_events[RGFW_eventLen].scroll = 0;
+ RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].prev = RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current;
+ RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current = 0;
+
+ RGFW_mouseButtonCallback(RGFW_root, RGFW_events[RGFW_eventLen].button, RGFW_events[RGFW_eventLen].scroll, 0);
+ RGFW_eventLen++;
+ }
return EM_TRUE;
}
-EM_BOOL on_touchcancel(int eventType, const EmscriptenTouchEvent* e, void* userData) { RGFW_UNUSED(eventType); RGFW_UNUSED(userData); RGFW_UNUSED(e); return EM_TRUE; }
+EM_BOOL Emscripten_on_touchcancel(int eventType, const EmscriptenTouchEvent* e, void* userData) { RGFW_UNUSED(eventType); RGFW_UNUSED(userData); RGFW_UNUSED(e); return EM_TRUE; }
+EM_BOOL Emscripten_on_gamepad(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData) {
+ RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
+
+ if (gamepadEvent->index >= 4)
+ return 0;
+
+ RGFW_joysticks[gamepadEvent->index] = gamepadEvent->connected;
+
+ return 1; // The event was consumed by the callback handler
+}
+
+void EMSCRIPTEN_KEEPALIVE Emscripten_onDrop(size_t count) {
+ if (!(RGFW_root->_winArgs & RGFW_ALLOW_DND))
+ return;
+
+ RGFW_events[RGFW_eventLen].droppedFilesCount = count;
+ RGFW_dndCallback(RGFW_root, RGFW_events[RGFW_eventLen].droppedFiles, count);
+ RGFW_eventLen++;
+}
b8 RGFW_stopCheckEvents_bool = RGFW_FALSE;
void RGFW_stopCheckEvents(void) {
@@ -7221,6 +8441,9 @@ void RGFW_stopCheckEvents(void) {
void RGFW_window_eventWait(RGFW_window* win, i32 waitMS) {
RGFW_UNUSED(win);
+ if (waitMS == 0)
+ return;
+
u32 start = (u32)(((u64)RGFW_getTimeNS()) / 1e+6);
while ((RGFW_eventLen == 0) && RGFW_stopCheckEvents_bool == RGFW_FALSE &&
@@ -7244,25 +8467,57 @@ void RGFW_init_buffer(RGFW_window* win) {
OSMesaMakeCurrent(win->src.ctx, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h);
#endif
#else
- RGFW_UNUSED(win); /* if buffer rendering is not being used */
+ RGFW_UNUSED(win); /*!< if buffer rendering is not being used */
#endif
}
+void EMSCRIPTEN_KEEPALIVE RGFW_makeSetValue(size_t index, char* file) {
+ /* This seems like a terrible idea, don't replicate this unless you hate yourself or the OS */
+ /* TODO: find a better way to do this,
+ strcpy doesn't seem to work, maybe because of asyncio
+ */
+
+ RGFW_events[RGFW_eventLen].type = RGFW_dnd;
+ char** arr = (char**)&RGFW_events[RGFW_eventLen].droppedFiles[index];
+ *arr = file;
+}
+
+#include
+#include
+#include
+
+void EMSCRIPTEN_KEEPALIVE RGFW_mkdir(char* name) { mkdir(name, 0755); }
+
+void EMSCRIPTEN_KEEPALIVE RGFW_writeFile(const char *path, const char *data, size_t len) {
+ FILE* file = fopen(path, "w+");
+ if (file == NULL)
+ return;
+
+ fwrite(data, sizeof(char), len, file);
+ fclose(file);
+}
+
RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) {
RGFW_UNUSED(name)
- RGFW_UNUSED(RGFW_initAttribs);
-
+ RGFW_UNUSED(RGFW_initFormatAttribs);
+
RGFW_window* win = RGFW_window_basic_init(rect, args);
EmscriptenWebGLContextAttributes attrs;
attrs.alpha = EM_TRUE;
attrs.depth = EM_TRUE;
+ attrs.alpha = EM_TRUE;
attrs.stencil = RGFW_STENCIL;
attrs.antialias = RGFW_SAMPLES;
attrs.premultipliedAlpha = EM_TRUE;
attrs.preserveDrawingBuffer = EM_FALSE;
- attrs.renderViaOffscreenBackBuffer = RGFW_AUX_BUFFERS;
+
+ if (RGFW_DOUBLE_BUFFER == 0)
+ attrs.renderViaOffscreenBackBuffer = 0;
+ else
+ attrs.renderViaOffscreenBackBuffer = RGFW_AUX_BUFFERS;
+
attrs.failIfMajorPerformanceCaveat = EM_FALSE;
attrs.majorVersion = (RGFW_majorVersion == 0) ? 1 : RGFW_majorVersion;
attrs.minorVersion = RGFW_minorVersion;
@@ -7279,22 +8534,79 @@ RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) {
#endif
emscripten_set_canvas_element_size("#canvas", rect.w, rect.h);
+ emscripten_set_window_title(name);
/* load callbacks */
- emscripten_set_keydown_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, on_keydown);
- emscripten_set_keyup_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, on_keyup);
- emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, on_resize);
- emscripten_set_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, NULL, EM_FALSE, on_fullscreenchange);
- emscripten_set_mousemove_callback("#canvas", NULL, EM_FALSE, on_mousemove);
- emscripten_set_touchstart_callback("#canvas", NULL, EM_FALSE, on_touchstart);
- emscripten_set_touchend_callback("#canvas", NULL, EM_FALSE, on_touchend);
- emscripten_set_touchmove_callback("#canvas", NULL, EM_FALSE, on_touchmove);
- emscripten_set_touchcancel_callback("#canvas", NULL, EM_FALSE, on_touchcancel);
- emscripten_set_mousedown_callback("#canvas", NULL, EM_FALSE, on_mousedown);
- emscripten_set_mouseup_callback("#canvas", NULL, EM_FALSE, on_mouseup);
- emscripten_set_wheel_callback("#canvas", NULL, EM_FALSE, on_wheel);
- emscripten_set_focusin_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, on_focusin);
- emscripten_set_focusout_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, on_focusout);
+ emscripten_set_keydown_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, Emscripten_on_keydown);
+ emscripten_set_keyup_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, Emscripten_on_keyup);
+ emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, Emscripten_on_resize);
+ emscripten_set_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, NULL, EM_FALSE, Emscripten_on_fullscreenchange);
+ emscripten_set_mousemove_callback("#canvas", NULL, EM_FALSE, Emscripten_on_mousemove);
+ emscripten_set_touchstart_callback("#canvas", NULL, EM_FALSE, Emscripten_on_touchstart);
+ emscripten_set_touchend_callback("#canvas", NULL, EM_FALSE, Emscripten_on_touchend);
+ emscripten_set_touchmove_callback("#canvas", NULL, EM_FALSE, Emscripten_on_touchmove);
+ emscripten_set_touchcancel_callback("#canvas", NULL, EM_FALSE, Emscripten_on_touchcancel);
+ emscripten_set_mousedown_callback("#canvas", NULL, EM_FALSE, Emscripten_on_mousedown);
+ emscripten_set_mouseup_callback("#canvas", NULL, EM_FALSE, Emscripten_on_mouseup);
+ emscripten_set_wheel_callback("#canvas", NULL, EM_FALSE, Emscripten_on_wheel);
+ emscripten_set_focusin_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, Emscripten_on_focusin);
+ emscripten_set_focusout_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, Emscripten_on_focusout);
+ emscripten_set_gamepadconnected_callback(NULL, 1, Emscripten_on_gamepad);
+ emscripten_set_gamepaddisconnected_callback(NULL, 1, Emscripten_on_gamepad);
+
+ if (args & RGFW_ALLOW_DND) {
+ win->_winArgs |= RGFW_ALLOW_DND;
+ }
+
+ EM_ASM({
+ var canvas = document.getElementById('canvas');
+ canvas.addEventListener('drop', function(e) {
+ e.preventDefault();
+ if (e.dataTransfer.file < 0)
+ return;
+
+ var filenamesArray = [];
+ var count = e.dataTransfer.files.length;
+
+ /* Read and save the files to emscripten's files */
+ var drop_dir = '.rgfw_dropped_files';
+ Module._RGFW_mkdir(drop_dir);
+
+ for (var i = 0; i < count; i++) {
+ var file = e.dataTransfer.files[i];
+
+ var path = '/' + drop_dir + '/' + file.name.replace("//", '_');
+ var reader = new FileReader();
+
+ reader.onloadend = (e) => {
+ if (reader.readyState != 2) {
+ out('failed to read dropped file: '+file.name+': '+reader.error);
+ }
+ else {
+ var data = e.target.result;
+
+ _RGFW_writeFile(path, new Uint8Array(data), file.size);
+ }
+ };
+
+ reader.readAsArrayBuffer(file);
+ // This works weird on modern opengl
+ var filename = stringToNewUTF8(path);
+
+ filenamesArray.push(filename);
+
+ Module._RGFW_makeSetValue(i, filename);
+ }
+
+ Module._Emscripten_onDrop(count);
+
+ for (var i = 0; i < count; ++i) {
+ _free(filenamesArray[i]);
+ }
+ }, true);
+
+ canvas.addEventListener('dragover', function(e) { e.preventDefault(); return false; }, true);
+ });
RGFW_init_buffer(win);
glViewport(0, 0, rect.w, rect.h);
@@ -7314,14 +8626,59 @@ RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) {
RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) {
static u8 index = 0;
-
+
if (index == 0)
RGFW_resetKey();
+ /* check gamepads */
+ for (int i = 0; (i < emscripten_get_num_gamepads()) && (i < 4); i++) {
+ if (RGFW_joysticks[i] == 0)
+ continue;;
+
+ EmscriptenGamepadEvent gamepadState;
+
+ if (emscripten_get_gamepad_status(i, &gamepadState) != EMSCRIPTEN_RESULT_SUCCESS)
+ break;
+
+ // Register buttons data for every connected gamepad
+ for (int j = 0; (j < gamepadState.numButtons) && (j < 16); j++) {
+ u32 map[] = {
+ RGFW_JS_A, RGFW_JS_X, RGFW_JS_B, RGFW_JS_Y,
+ RGFW_JS_L1, RGFW_JS_R1, RGFW_JS_L2, RGFW_JS_R2,
+ RGFW_JS_SELECT, RGFW_JS_START,
+ 0, 0,
+ RGFW_JS_UP, RGFW_JS_DOWN, RGFW_JS_LEFT, RGFW_JS_RIGHT
+ };
+
+ u32 button = map[j];
+ if (RGFW_jsPressed[i][button] != gamepadState.digitalButton[j]) {
+ win->event.type = RGFW_jsButtonPressed;
+ win->event.joystick = i;
+ win->event.button = map[j];
+ return &win->event;
+ }
+
+ RGFW_jsPressed[i][button] = gamepadState.digitalButton[j];
+ }
+
+ for (int j = 0; (j < gamepadState.numAxes) && (j < 4); j += 2) {
+ win->event.axisesCount = gamepadState.numAxes;
+ if (win->event.axis[j].x != gamepadState.axis[j] ||
+ win->event.axis[j].y != gamepadState.axis[j + 1]
+ ) {
+ win->event.axis[j].x = gamepadState.axis[j];
+ win->event.axis[j].y = gamepadState.axis[j + 1];
+ win->event.type = RGFW_jsAxisMove;
+ win->event.joystick = i;
+ return &win->event;
+ }
+ }
+ }
+
+ /* check queued events */
if (RGFW_eventLen == 0)
return NULL;
- RGFW_events[index].fps = win->event.fps;
RGFW_events[index].frameTime = win->event.frameTime;
RGFW_events[index].frameTime2 = win->event.frameTime2;
RGFW_events[index].inFocus = win->event.inFocus;
@@ -7389,6 +8746,14 @@ RGFW_point RGFW_getGlobalMousePoint(void) {
return point;
}
+RGFW_point RGFW_window_getMousePoint(RGFW_window* win) {
+ RGFW_UNUSED(win);
+
+ EmscriptenMouseEvent mouseEvent;
+ emscripten_get_mouse_status(&mouseEvent);
+ return RGFW_POINT( mouseEvent.targetX, mouseEvent.targetY);
+}
+
void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough) {
RGFW_UNUSED(win);
@@ -7417,13 +8782,15 @@ char* RGFW_readClipboard(size_t* size) {
if (size != NULL)
*size = 0;
- char* str = malloc(1);
+ char* str = (char*)malloc(1);
str[0] = '\0';
return str;
}
void RGFW_window_swapBuffers(RGFW_window* win) {
+ RGFW_UNUSED(win);
+
#ifdef RGFW_BUFFER
if (!(win->_winArgs & RGFW_NO_CPU_RENDER)) {
glEnable(GL_TEXTURE_2D);
@@ -7431,9 +8798,6 @@ void RGFW_window_swapBuffers(RGFW_window* win) {
GLuint texture;
glGenTextures(1,&texture);
- //glPixelStorei( GL_PACK_ROW_LENGTH, RGFW_bufferSize.w);
- //glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, RGFW_bufferSize.h);
-
glBindTexture(GL_TEXTURE_2D,texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
@@ -7464,23 +8828,19 @@ void RGFW_window_swapBuffers(RGFW_window* win) {
#endif
emscripten_webgl_commit_frame();
-
- if (win->fpsCap == 0 || win->fpsCap < 100) {
- emscripten_sleep(0);
- }
-
- RGFW_window_checkFPS(win);
+ emscripten_sleep(0);
}
void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) {
- emscripten_webgl_make_context_current(win->src.ctx);
+ if (win == NULL)
+ emscripten_webgl_make_context_current(0);
+ else
+ emscripten_webgl_make_context_current(win->src.ctx);
}
#ifndef RGFW_EGL
-void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) {
- win->fpsCap = (swapInterval == 1) ? 0 : swapInterval;
-}
+void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) { RGFW_UNUSED(win); RGFW_UNUSED(swapInterval); }
#endif
void RGFW_window_close(RGFW_window* win) {
@@ -7512,16 +8872,22 @@ u64 RGFW_getTime(void) {
return emscripten_get_now() * 1000;
}
+void RGFW_releaseCursor(RGFW_window* win) {
+ emscripten_exit_pointerlock();
+}
+
void RGFW_captureCursor(RGFW_window* win, RGFW_rect r) {
RGFW_UNUSED(win)
- if (!r.x && !r.y && !r.w && !r.h) {
- emscripten_exit_pointerlock();
- return;
- }
emscripten_request_pointerlock("#canvas", 1);
}
+
+void RGFW_window_setName(RGFW_window* win, char* name) {
+ RGFW_UNUSED(win);
+ emscripten_set_window_title(name);
+}
+
/* unsupported functions */
RGFW_monitor* RGFW_getMonitors(void) { return NULL; }
RGFW_monitor RGFW_getPrimaryMonitor(void) { return (RGFW_monitor){}; }
@@ -7531,8 +8897,6 @@ void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a) { RGFW_UNUSED(win) RG
void RGFW_window_minimize(RGFW_window* win) { RGFW_UNUSED(win)}
void RGFW_window_restore(RGFW_window* win) { RGFW_UNUSED(win) }
void RGFW_window_setBorder(RGFW_window* win, b8 border) { RGFW_UNUSED(win) RGFW_UNUSED(border) }
-void RGFW_window_setDND(RGFW_window* win, b8 allow) { RGFW_UNUSED(win) RGFW_UNUSED(allow) }
-void RGFW_window_setName(RGFW_window* win, char* name) { RGFW_UNUSED(win) RGFW_UNUSED(name) }
void RGFW_window_setIcon(RGFW_window* win, u8* icon, RGFW_area a, i32 channels) { RGFW_UNUSED(win) RGFW_UNUSED(icon) RGFW_UNUSED(a) RGFW_UNUSED(channels) }
void RGFW_window_hide(RGFW_window* win) { RGFW_UNUSED(win) }
void RGFW_window_show(RGFW_window* win) {RGFW_UNUSED(win) }
@@ -7546,7 +8910,7 @@ RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) { RGFW_UNUSED(win) return
/* end of web asm defines */
/* unix (macOS, linux, web asm) only stuff */
-#if defined(RGFW_X11) || defined(RGFW_MACOS) || defined(RGFW_WEBASM)
+#if defined(RGFW_X11) || defined(RGFW_MACOS) || defined(RGFW_WEBASM) || defined(RGFW_WAYLAND)
/* unix threading */
#ifndef RGFW_NO_THREADS
#include
@@ -7561,7 +8925,7 @@ RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) { RGFW_UNUSED(win) return
void RGFW_cancelThread(RGFW_thread thread) { pthread_cancel((pthread_t) thread); }
void RGFW_joinThread(RGFW_thread thread) { pthread_join((pthread_t) thread, NULL); }
#ifdef __linux__
- void RGFW_setThreadPriority(RGFW_thread thread, u8 priority) { pthread_setschedprio(thread, priority); }
+ void RGFW_setThreadPriority(RGFW_thread thread, u8 priority) { pthread_setschedprio((pthread_t)thread, priority); }
#endif
#endif
@@ -7579,6 +8943,6 @@ RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) { RGFW_UNUSED(win) return
#endif /* end of unix / mac stuff*/
#endif /*RGFW_IMPLEMENTATION*/
-#ifdef __cplusplus
+#if defined(__cplusplus) && !defined(__EMSCRIPTEN__)
}
#endif
diff --git a/src/external/miniaudio.h b/src/external/miniaudio.h
index 787c626ad..ad113337e 100644
--- a/src/external/miniaudio.h
+++ b/src/external/miniaudio.h
@@ -36078,9 +36078,15 @@ static ma_result ma_context_get_device_info_from_fd__audio4(ma_context* pContext
ma_uint32 channels;
ma_uint32 sampleRate;
+#ifdef __NetBSD__
+ if (ioctl(fd, AUDIO_GETFORMAT, &fdInfo) < 0) {
+ return MA_ERROR;
+ }
+#else
if (ioctl(fd, AUDIO_GETINFO, &fdInfo) < 0) {
return MA_ERROR;
}
+#endif
if (deviceType == ma_device_type_playback) {
channels = fdInfo.play.channels;
@@ -36358,7 +36364,11 @@ static ma_result ma_device_init_fd__audio4(ma_device* pDevice, const ma_device_c
/* We're using a default device. Get the info from the /dev/audioctl file instead of /dev/audio. */
int fdctl = open(pDefaultDeviceCtlNames[iDefaultDevice], fdFlags, 0);
if (fdctl != -1) {
+#ifdef __NetBSD__
+ fdInfoResult = ioctl(fdctl, AUDIO_GETFORMAT, &fdInfo);
+#else
fdInfoResult = ioctl(fdctl, AUDIO_GETINFO, &fdInfo);
+#endif
close(fdctl);
}
}
diff --git a/src/platforms/rcore_desktop_rgfw.c b/src/platforms/rcore_desktop_rgfw.c
index d98c6391d..afea0c2e6 100644
--- a/src/platforms/rcore_desktop_rgfw.c
+++ b/src/platforms/rcore_desktop_rgfw.c
@@ -1239,15 +1239,15 @@ int InitPlatform(void)
// Check selection OpenGL version
if (rlGetVersion() == RL_OPENGL_21)
{
- RGFW_setGLVersion(2, 1);
+ RGFW_setGLVersion(RGFW_GL_CORE, 2, 1);
}
else if (rlGetVersion() == RL_OPENGL_33)
{
- RGFW_setGLVersion(3, 3);
+ RGFW_setGLVersion(RGFW_GL_CORE, 3, 3);
}
else if (rlGetVersion() == RL_OPENGL_43)
{
- RGFW_setGLVersion(4, 1);
+ RGFW_setGLVersion(RGFW_GL_CORE, 4, 1);
}
if (CORE.Window.flags & FLAG_MSAA_4X_HINT)
diff --git a/src/platforms/rcore_web.c b/src/platforms/rcore_web.c
index 937e15acd..ff7a92dbc 100644
--- a/src/platforms/rcore_web.c
+++ b/src/platforms/rcore_web.c
@@ -129,7 +129,7 @@ static void CursorEnterCallback(GLFWwindow *window, int enter);
// Emscripten window callback events
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);
// Emscripten input callback events
@@ -981,7 +981,7 @@ void PollInputEvents(void)
default: break;
}
- if (button != -1) // Check for valid button
+ if (button + 1 != 0) // Check for valid button
{
if (gamepadState.digitalButton[j] == 1)
{
@@ -1572,12 +1572,12 @@ static EM_BOOL EmscriptenFullscreenChangeCallback(int eventType, const Emscripte
}
// Register window resize event
-static EM_BOOL EmscriptenWindowResizedCallback(int eventType, const EmscriptenUiEvent *event, void *userData)
-{
- // TODO: Implement EmscriptenWindowResizedCallback()?
+// static EM_BOOL EmscriptenWindowResizedCallback(int eventType, const EmscriptenUiEvent *event, void *userData)
+// {
+// // TODO: Implement EmscriptenWindowResizedCallback()?
- return 1; // The event was consumed by the callback handler
-}
+// return 1; // The event was consumed by the callback handler
+// }
EM_JS(int, GetWindowInnerWidth, (), { return window.innerWidth; });
EM_JS(int, GetWindowInnerHeight, (), { return window.innerHeight; });
@@ -1593,11 +1593,11 @@ static EM_BOOL EmscriptenResizeCallback(int eventType, const EmscriptenUiEvent *
int width = GetWindowInnerWidth();
int height = GetWindowInnerHeight();
- if (width < CORE.Window.screenMin.width) width = CORE.Window.screenMin.width;
- else if (width > CORE.Window.screenMax.width && CORE.Window.screenMax.width > 0) width = CORE.Window.screenMax.width;
+ if (width < (int)CORE.Window.screenMin.width) width = CORE.Window.screenMin.width;
+ else if (width > (int)CORE.Window.screenMax.width && CORE.Window.screenMax.width > 0) width = CORE.Window.screenMax.width;
- if (height < CORE.Window.screenMin.height) height = CORE.Window.screenMin.height;
- else if (height > CORE.Window.screenMax.height && CORE.Window.screenMax.height > 0) height = CORE.Window.screenMax.height;
+ if (height < (int)CORE.Window.screenMin.height) height = CORE.Window.screenMin.height;
+ else if (height > (int)CORE.Window.screenMax.height && CORE.Window.screenMax.height > 0) height = CORE.Window.screenMax.height;
emscripten_set_canvas_element_size("#canvas", width, height);
diff --git a/src/raylib.h b/src/raylib.h
index 1cf34f004..0759c259f 100644
--- a/src/raylib.h
+++ b/src/raylib.h
@@ -1238,7 +1238,7 @@ RLAPI void DrawLineBezier(Vector2 startPos, Vector2 endPos, float thick, Color c
RLAPI void DrawCircle(int centerX, int centerY, float radius, Color color); // Draw a color-filled circle
RLAPI void DrawCircleSector(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw a piece of a circle
RLAPI void DrawCircleSectorLines(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw circle sector outline
-RLAPI void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Color color2); // Draw a gradient-filled circle
+RLAPI void DrawCircleGradient(int centerX, int centerY, float radius, Color inner, Color outer); // Draw a gradient-filled circle
RLAPI void DrawCircleV(Vector2 center, float radius, Color color); // Draw a color-filled circle (Vector version)
RLAPI void DrawCircleLines(int centerX, int centerY, float radius, Color color); // Draw circle outline
RLAPI void DrawCircleLinesV(Vector2 center, float radius, Color color); // Draw circle outline (Vector version)
@@ -1250,9 +1250,9 @@ RLAPI void DrawRectangle(int posX, int posY, int width, int height, Color color)
RLAPI void DrawRectangleV(Vector2 position, Vector2 size, Color color); // Draw a color-filled rectangle (Vector version)
RLAPI void DrawRectangleRec(Rectangle rec, Color color); // Draw a color-filled rectangle
RLAPI void DrawRectanglePro(Rectangle rec, Vector2 origin, float rotation, Color color); // Draw a color-filled rectangle with pro parameters
-RLAPI void DrawRectangleGradientV(int posX, int posY, int width, int height, Color color1, Color color2);// Draw a vertical-gradient-filled rectangle
-RLAPI void DrawRectangleGradientH(int posX, int posY, int width, int height, Color color1, Color color2);// Draw a horizontal-gradient-filled rectangle
-RLAPI void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3, Color col4); // Draw a gradient-filled rectangle with custom vertex colors
+RLAPI void DrawRectangleGradientV(int posX, int posY, int width, int height, Color top, Color bottom); // Draw a vertical-gradient-filled rectangle
+RLAPI void DrawRectangleGradientH(int posX, int posY, int width, int height, Color left, Color right); // Draw a horizontal-gradient-filled rectangle
+RLAPI void DrawRectangleGradientEx(Rectangle rec, Color topLeft, Color bottomLeft, Color topRight, Color bottomRight); // Draw a gradient-filled rectangle with custom vertex colors
RLAPI void DrawRectangleLines(int posX, int posY, int width, int height, Color color); // Draw rectangle outline
RLAPI void DrawRectangleLinesEx(Rectangle rec, float lineThick, Color color); // Draw rectangle outline with extended parameters
RLAPI void DrawRectangleRounded(Rectangle rec, float roundness, int segments, Color color); // Draw rectangle with rounded edges
diff --git a/src/rcamera.h b/src/rcamera.h
index d3042d306..c7f6fed3a 100644
--- a/src/rcamera.h
+++ b/src/rcamera.h
@@ -196,12 +196,12 @@ RLAPI Matrix GetCameraProjectionMatrix(Camera* camera, float aspect);
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
-#define CAMERA_MOVE_SPEED 0.09f
+#define CAMERA_MOVE_SPEED 5.4f // Units per second
#define CAMERA_ROTATION_SPEED 0.03f
#define CAMERA_PAN_SPEED 0.2f
// Camera mouse movement sensitivity
-#define CAMERA_MOUSE_MOVE_SENSITIVITY 0.003f // TODO: it should be independant of framerate
+#define CAMERA_MOUSE_MOVE_SENSITIVITY 0.003f
// Camera orbital speed in CAMERA_ORBITAL mode
#define CAMERA_ORBITAL_SPEED 0.5f // Radians per second
@@ -481,10 +481,11 @@ void UpdateCamera(Camera *camera, int mode)
}
// Keyboard support
- if (IsKeyDown(KEY_W)) CameraMoveForward(camera, CAMERA_MOVE_SPEED, moveInWorldPlane);
- if (IsKeyDown(KEY_A)) CameraMoveRight(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane);
- if (IsKeyDown(KEY_S)) CameraMoveForward(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane);
- if (IsKeyDown(KEY_D)) CameraMoveRight(camera, CAMERA_MOVE_SPEED, moveInWorldPlane);
+ float cameraMoveSpeed = CAMERA_MOVE_SPEED*GetFrameTime();
+ if (IsKeyDown(KEY_W)) CameraMoveForward(camera, cameraMoveSpeed, moveInWorldPlane);
+ if (IsKeyDown(KEY_A)) CameraMoveRight(camera, -cameraMoveSpeed, moveInWorldPlane);
+ if (IsKeyDown(KEY_S)) CameraMoveForward(camera, -cameraMoveSpeed, moveInWorldPlane);
+ if (IsKeyDown(KEY_D)) CameraMoveRight(camera, cameraMoveSpeed, moveInWorldPlane);
// Gamepad movement
if (IsGamepadAvailable(0))
@@ -493,16 +494,16 @@ void UpdateCamera(Camera *camera, int mode)
CameraYaw(camera, -(GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_X)*2)*CAMERA_MOUSE_MOVE_SENSITIVITY, rotateAroundTarget);
CameraPitch(camera, -(GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_Y)*2)*CAMERA_MOUSE_MOVE_SENSITIVITY, lockView, rotateAroundTarget, rotateUp);
- if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_Y) <= -0.25f) CameraMoveForward(camera, CAMERA_MOVE_SPEED, moveInWorldPlane);
- if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_X) <= -0.25f) CameraMoveRight(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane);
- if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_Y) >= 0.25f) CameraMoveForward(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane);
- if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_X) >= 0.25f) CameraMoveRight(camera, CAMERA_MOVE_SPEED, moveInWorldPlane);
+ if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_Y) <= -0.25f) CameraMoveForward(camera, cameraMoveSpeed, moveInWorldPlane);
+ if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_X) <= -0.25f) CameraMoveRight(camera, -cameraMoveSpeed, moveInWorldPlane);
+ if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_Y) >= 0.25f) CameraMoveForward(camera, -cameraMoveSpeed, moveInWorldPlane);
+ if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_X) >= 0.25f) CameraMoveRight(camera, cameraMoveSpeed, moveInWorldPlane);
}
if (mode == CAMERA_FREE)
{
- if (IsKeyDown(KEY_SPACE)) CameraMoveUp(camera, CAMERA_MOVE_SPEED);
- if (IsKeyDown(KEY_LEFT_CONTROL)) CameraMoveUp(camera, -CAMERA_MOVE_SPEED);
+ if (IsKeyDown(KEY_SPACE)) CameraMoveUp(camera, cameraMoveSpeed);
+ if (IsKeyDown(KEY_LEFT_CONTROL)) CameraMoveUp(camera, -cameraMoveSpeed);
}
}
diff --git a/src/rcore.c b/src/rcore.c
index b4bc19f34..e8041ea41 100644
--- a/src/rcore.c
+++ b/src/rcore.c
@@ -367,9 +367,9 @@ static int screenshotCounter = 0; // Screenshots counter
#endif
#if defined(SUPPORT_GIF_RECORDING)
-unsigned int gifFrameCounter = 0; // GIF frames counter
-bool gifRecording = false; // GIF recording state
-MsfGifState gifState = { 0 }; // MSGIF context state
+static unsigned int gifFrameCounter = 0; // GIF frames counter
+static bool gifRecording = false; // GIF recording state
+static MsfGifState gifState = { 0 }; // MSGIF context state
#endif
#if defined(SUPPORT_AUTOMATION_EVENTS)
@@ -669,7 +669,6 @@ void InitWindow(int width, int height, const char *title)
#endif
#endif
-
CORE.Time.frameCounter = 0;
CORE.Window.shouldClose = false;
@@ -2707,8 +2706,8 @@ void PlayAutomationEvent(AutomationEvent event)
} break;
case INPUT_MOUSE_WHEEL_MOTION: // param[0]: x delta, param[1]: y delta
{
- CORE.Input.Mouse.currentWheelMove.x = (float)event.params[0]; break;
- CORE.Input.Mouse.currentWheelMove.y = (float)event.params[1]; break;
+ CORE.Input.Mouse.currentWheelMove.x = (float)event.params[0];
+ CORE.Input.Mouse.currentWheelMove.y = (float)event.params[1];
} break;
case INPUT_TOUCH_UP: CORE.Input.Touch.currentTouchState[event.params[0]] = false; break; // param[0]: id
case INPUT_TOUCH_DOWN: CORE.Input.Touch.currentTouchState[event.params[0]] = true; break; // param[0]: id
@@ -2745,6 +2744,8 @@ void PlayAutomationEvent(AutomationEvent event)
case ACTION_SETTARGETFPS: SetTargetFPS(event.params[0]); break;
default: break;
}
+
+ TRACELOG(LOG_INFO, "AUTOMATION PLAY: Frame: %i | Event type: %i | Event parameters: %i, %i, %i", event.frame, event.type, event.params[0], event.params[1], event.params[2]);
}
#endif
}
@@ -2955,7 +2956,7 @@ float GetGamepadAxisMovement(int gamepad, int axis)
float value = (axis == GAMEPAD_AXIS_LEFT_TRIGGER || axis == GAMEPAD_AXIS_RIGHT_TRIGGER)? -1.0f : 0.0f;
if ((gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad] && (axis < MAX_GAMEPAD_AXIS)) {
- float movement = value < 0.0f ? CORE.Input.Gamepad.axisState[gamepad][axis] : fabs(CORE.Input.Gamepad.axisState[gamepad][axis]);
+ float movement = value < 0.0f ? CORE.Input.Gamepad.axisState[gamepad][axis] : fabsf(CORE.Input.Gamepad.axisState[gamepad][axis]);
// 0.1f = GAMEPAD_AXIS_MINIMUM_DRIFT/DELTA
if (movement > value + 0.1f) value = CORE.Input.Gamepad.axisState[gamepad][axis];
diff --git a/src/rlgl.h b/src/rlgl.h
index 8ee602644..5fb9497cd 100644
--- a/src/rlgl.h
+++ b/src/rlgl.h
@@ -3994,18 +3994,18 @@ unsigned int rlLoadShaderCode(const char *vsCode, const char *fsCode)
unsigned int fragmentShaderId = 0;
// Compile vertex shader (if provided)
+ // NOTE: If not vertex shader is provided, use default one
if (vsCode != NULL) vertexShaderId = rlCompileShader(vsCode, GL_VERTEX_SHADER);
- // In case no vertex shader was provided or compilation failed, we use default vertex shader
- if (vertexShaderId == 0) vertexShaderId = RLGL.State.defaultVShaderId;
+ else vertexShaderId = RLGL.State.defaultVShaderId;
// Compile fragment shader (if provided)
+ // NOTE: If not vertex shader is provided, use default one
if (fsCode != NULL) fragmentShaderId = rlCompileShader(fsCode, GL_FRAGMENT_SHADER);
- // In case no fragment shader was provided or compilation failed, we use default fragment shader
- if (fragmentShaderId == 0) fragmentShaderId = RLGL.State.defaultFShaderId;
+ else fragmentShaderId = RLGL.State.defaultFShaderId;
// In case vertex and fragment shader are the default ones, no need to recompile, we can just assign the default shader program id
if ((vertexShaderId == RLGL.State.defaultVShaderId) && (fragmentShaderId == RLGL.State.defaultFShaderId)) id = RLGL.State.defaultShaderId;
- else
+ else if ((vertexShaderId > 0) && (fragmentShaderId > 0))
{
// One of or both shader are new, we need to compile a new shader program
id = rlLoadShaderProgram(vertexShaderId, fragmentShaderId);
@@ -4083,6 +4083,8 @@ unsigned int rlCompileShader(const char *shaderCode, int type)
//case GL_GEOMETRY_SHADER:
#if defined(GRAPHICS_API_OPENGL_43)
case GL_COMPUTE_SHADER: TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to compile compute shader code", shader); break;
+ #elif defined(GRAPHICS_API_OPENGL_33)
+ case GL_COMPUTE_SHADER: TRACELOG(RL_LOG_WARNING, "SHADER: Compute shaders not enabled. Define GRAPHICS_API_OPENGL_43", shader); break;
#endif
default: break;
}
@@ -4098,6 +4100,8 @@ unsigned int rlCompileShader(const char *shaderCode, int type)
TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Compile error: %s", shader, log);
RL_FREE(log);
}
+
+ shader = 0;
}
else
{
@@ -4108,6 +4112,8 @@ unsigned int rlCompileShader(const char *shaderCode, int type)
//case GL_GEOMETRY_SHADER:
#if defined(GRAPHICS_API_OPENGL_43)
case GL_COMPUTE_SHADER: TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Compute shader compiled successfully", shader); break;
+ #elif defined(GRAPHICS_API_OPENGL_33)
+ case GL_COMPUTE_SHADER: TRACELOG(RL_LOG_WARNING, "SHADER: Compute shaders not enabled. Define GRAPHICS_API_OPENGL_43", shader); break;
#endif
default: break;
}
@@ -4348,6 +4354,8 @@ unsigned int rlLoadComputeShaderProgram(unsigned int shaderId)
TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Compute shader program loaded successfully", program);
}
+#else
+ TRACELOG(RL_LOG_WARNING, "SHADER: Compute shaders not enabled. Define GRAPHICS_API_OPENGL_43");
#endif
return program;
@@ -4372,6 +4380,8 @@ unsigned int rlLoadShaderBuffer(unsigned int size, const void *data, int usageHi
glBufferData(GL_SHADER_STORAGE_BUFFER, size, data, usageHint? usageHint : RL_STREAM_COPY);
if (data == NULL) glClearBufferData(GL_SHADER_STORAGE_BUFFER, GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE, NULL); // Clear buffer data to 0
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
+#else
+ TRACELOG(RL_LOG_WARNING, "SSBO: SSBO not enabled. Define GRAPHICS_API_OPENGL_43");
#endif
return ssbo;
@@ -4382,7 +4392,10 @@ void rlUnloadShaderBuffer(unsigned int ssboId)
{
#if defined(GRAPHICS_API_OPENGL_43)
glDeleteBuffers(1, &ssboId);
+#else
+ TRACELOG(RL_LOG_WARNING, "SSBO: SSBO not enabled. Define GRAPHICS_API_OPENGL_43");
#endif
+
}
// Update SSBO buffer data
@@ -4442,6 +4455,8 @@ void rlBindImageTexture(unsigned int id, unsigned int index, int format, bool re
rlGetGlTextureFormats(format, &glInternalFormat, &glFormat, &glType);
glBindImageTexture(index, id, 0, 0, 0, readonly? GL_READ_ONLY : GL_READ_WRITE, glInternalFormat);
+#else
+ TRACELOG(RL_LOG_WARNING, "TEXTURE: Image texture binding not enabled. Define GRAPHICS_API_OPENGL_43");
#endif
}
diff --git a/src/rmodels.c b/src/rmodels.c
index c1d56765e..36a7e254d 100644
--- a/src/rmodels.c
+++ b/src/rmodels.c
@@ -5741,11 +5741,11 @@ static bool GetPoseAtTimeGLTF(cgltf_interpolation_type interpolationType, cgltf_
cgltf_accessor_read_float(output, 3*keyframe+1, tmp, 4);
Vector4 v1 = {tmp[0], tmp[1], tmp[2], tmp[3]};
cgltf_accessor_read_float(output, 3*keyframe+2, tmp, 4);
- Vector4 outTangent1 = {tmp[0], tmp[1], tmp[2]};
+ Vector4 outTangent1 = {tmp[0], tmp[1], tmp[2], 0.0f};
cgltf_accessor_read_float(output, 3*(keyframe+1)+1, tmp, 4);
Vector4 v2 = {tmp[0], tmp[1], tmp[2], tmp[3]};
cgltf_accessor_read_float(output, 3*(keyframe+1), tmp, 4);
- Vector4 inTangent2 = {tmp[0], tmp[1], tmp[2]};
+ Vector4 inTangent2 = {tmp[0], tmp[1], tmp[2], 0.0f};
Vector4 *r = data;
v1 = QuaternionNormalize(v1);
diff --git a/src/rshapes.c b/src/rshapes.c
index 89339708a..66dfbf3b6 100644
--- a/src/rshapes.c
+++ b/src/rshapes.c
@@ -79,8 +79,8 @@
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
-Texture2D texShapes = { 1, 1, 1, 1, 7 }; // Texture used on shapes drawing (white pixel loaded by rlgl)
-Rectangle texShapesRec = { 0.0f, 0.0f, 1.0f, 1.0f }; // Texture source rectangle used on shapes drawing
+static Texture2D texShapes = { 1, 1, 1, 1, 7 }; // Texture used on shapes drawing (white pixel loaded by rlgl)
+static Rectangle texShapesRec = { 0.0f, 0.0f, 1.0f, 1.0f }; // Texture source rectangle used on shapes drawing
//----------------------------------------------------------------------------------
// Module specific Functions Declaration
@@ -430,17 +430,16 @@ void DrawCircleSectorLines(Vector2 center, float radius, float startAngle, float
}
// Draw a gradient-filled circle
-// NOTE: Gradient goes from center (color1) to border (color2)
-void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Color color2)
+void DrawCircleGradient(int centerX, int centerY, float radius, Color inner, Color outer)
{
rlBegin(RL_TRIANGLES);
for (int i = 0; i < 360; i += 10)
{
- rlColor4ub(color1.r, color1.g, color1.b, color1.a);
+ rlColor4ub(inner.r, inner.g, inner.b, inner.a);
rlVertex2f((float)centerX, (float)centerY);
- rlColor4ub(color2.r, color2.g, color2.b, color2.a);
+ rlColor4ub(outer.r, outer.g, outer.b, outer.a);
rlVertex2f((float)centerX + cosf(DEG2RAD*(i + 10))*radius, (float)centerY + sinf(DEG2RAD*(i + 10))*radius);
- rlColor4ub(color2.r, color2.g, color2.b, color2.a);
+ rlColor4ub(outer.r, outer.g, outer.b, outer.a);
rlVertex2f((float)centerX + cosf(DEG2RAD*i)*radius, (float)centerY + sinf(DEG2RAD*i)*radius);
}
rlEnd();
@@ -761,22 +760,19 @@ void DrawRectanglePro(Rectangle rec, Vector2 origin, float rotation, Color color
}
// Draw a vertical-gradient-filled rectangle
-// NOTE: Gradient goes from bottom (color1) to top (color2)
-void DrawRectangleGradientV(int posX, int posY, int width, int height, Color color1, Color color2)
+void DrawRectangleGradientV(int posX, int posY, int width, int height, Color top, Color bottom)
{
- DrawRectangleGradientEx((Rectangle){ (float)posX, (float)posY, (float)width, (float)height }, color1, color2, color2, color1);
+ DrawRectangleGradientEx((Rectangle){ (float)posX, (float)posY, (float)width, (float)height }, top, bottom, bottom, top);
}
// Draw a horizontal-gradient-filled rectangle
-// NOTE: Gradient goes from bottom (color1) to top (color2)
-void DrawRectangleGradientH(int posX, int posY, int width, int height, Color color1, Color color2)
+void DrawRectangleGradientH(int posX, int posY, int width, int height, Color left, Color right)
{
- DrawRectangleGradientEx((Rectangle){ (float)posX, (float)posY, (float)width, (float)height }, color1, color1, color2, color2);
+ DrawRectangleGradientEx((Rectangle){ (float)posX, (float)posY, (float)width, (float)height }, left, left, right, right);
}
// Draw a gradient-filled rectangle
-// NOTE: Colors refer to corners, starting at top-lef corner and counter-clockwise
-void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3, Color col4)
+void DrawRectangleGradientEx(Rectangle rec, Color topLeft, Color bottomLeft, Color topRight, Color bottomRight)
{
rlSetTexture(GetShapesTexture().id);
Rectangle shapeRect = GetShapesTextureRectangle();
@@ -785,19 +781,19 @@ void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3,
rlNormal3f(0.0f, 0.0f, 1.0f);
// NOTE: Default raylib font character 95 is a white square
- rlColor4ub(col1.r, col1.g, col1.b, col1.a);
+ rlColor4ub(topLeft.r, topLeft.g, topLeft.b, topLeft.a);
rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
rlVertex2f(rec.x, rec.y);
- rlColor4ub(col2.r, col2.g, col2.b, col2.a);
+ rlColor4ub(bottomLeft.r, bottomLeft.g, bottomLeft.b, bottomLeft.a);
rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
rlVertex2f(rec.x, rec.y + rec.height);
- rlColor4ub(col3.r, col3.g, col3.b, col3.a);
+ rlColor4ub(topRight.r, topRight.g, topRight.b, topRight.a);
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
rlVertex2f(rec.x + rec.width, rec.y + rec.height);
- rlColor4ub(col4.r, col4.g, col4.b, col4.a);
+ rlColor4ub(bottomRight.r, bottomRight.g, bottomRight.b, bottomRight.a);
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
rlVertex2f(rec.x + rec.width, rec.y);
rlEnd();
diff --git a/src/rtextures.c b/src/rtextures.c
index 5fa01c9df..f2faa1850 100644
--- a/src/rtextures.c
+++ b/src/rtextures.c
@@ -371,7 +371,7 @@ Image LoadImageSvg(const char *fileNameOrString, int width, int height)
if (isSvgStringValid)
{
- struct NSVGimage *svgImage = nsvgParse(fileData, "px", 96.0f);
+ struct NSVGimage *svgImage = nsvgParse((char *)fileData, "px", 96.0f);
unsigned char *img = RL_MALLOC(width*height*4);
@@ -404,7 +404,7 @@ Image LoadImageSvg(const char *fileNameOrString, int width, int height)
nsvgDeleteRasterizer(rast);
}
- if (isSvgStringValid && (fileData != fileNameOrString)) UnloadFileData(fileData);
+ if (isSvgStringValid && (fileData != (unsigned char *)fileNameOrString)) UnloadFileData(fileData);
}
#else
TRACELOG(LOG_WARNING, "SVG image support not enabled, image can not be loaded");
@@ -611,7 +611,7 @@ Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, i
(fileData[2] == 'v') &&
(fileData[3] == 'g'))
{
- struct NSVGimage *svgImage = nsvgParse(fileData, "px", 96.0f);
+ struct NSVGimage *svgImage = nsvgParse((char *)fileData, "px", 96.0f);
unsigned char *img = RL_MALLOC(svgImage->width*svgImage->height*4);
// Rasterize