diff --git a/README.md b/README.md index 6e72fb7..0cff1ba 100755 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Manually tweaked, auto-generated [raylib](https://github.com/raysan5/raylib) bindings for zig. -Bindings tested on raylib version 5.1-dev and Zig 0.13.0 +Bindings tested on raylib version 5.5-dev and Zig 0.13.0 Thanks to all the [contributors](https://github.com/Not-Nik/raylib-zig/graphs/contributors) for their help with this binding. diff --git a/build.zig b/build.zig index 264c523..969f151 100755 --- a/build.zig +++ b/build.zig @@ -12,7 +12,7 @@ pub const Options = struct { rshapes: bool = true, rtext: bool = true, rtextures: bool = true, - platform_drm: bool = false, + platform: PlatformBackend = .glfw, shared: bool = false, linux_display_backend: LinuxDisplayBackend = .X11, opengl_version: OpenglVersion = .auto, @@ -33,6 +33,13 @@ pub const LinuxDisplayBackend = enum { Wayland, }; +pub const PlatformBackend = enum { + glfw, + rgfw, + sdl, + drm, +}; + const Program = struct { name: []const u8, path: []const u8, @@ -101,7 +108,7 @@ fn getRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.buil .rshapes = options.rshapes, .rtext = options.rtext, .rtextures = options.rtextures, - .platform_drm = options.platform_drm, + .platform = options.platform, .shared = options.shared, .linux_display_backend = options.linux_display_backend, .opengl_version = options.opengl_version, @@ -167,7 +174,7 @@ pub fn build(b: *std.Build) !void { const defaults = Options{}; const options = Options{ - .platform_drm = b.option(bool, "platform_drm", "Compile raylib in native mode (no X11)") orelse defaults.platform_drm, + .platform = b.option(PlatformBackend, "platform", "Compile raylib in native mode (no X11)") orelse defaults.platform, .raudio = b.option(bool, "raudio", "Compile with audio support") orelse defaults.raudio, .rmodels = b.option(bool, "rmodels", "Compile with models support") orelse defaults.rmodels, .rtext = b.option(bool, "rtext", "Compile with text support") orelse defaults.rtext, diff --git a/build.zig.zon b/build.zig.zon index 28978f9..e709b31 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -3,12 +3,12 @@ .version = "5.5.0", .dependencies = .{ .raylib = .{ - .url = "https://github.com/raysan5/raylib/archive/5f49ec3d6448502d798d4d404e08e354ec48012a.tar.gz", - .hash = "1220f655fd57d8e10b5dbe7d99c45a0b9836a13cea085d75cd4c15f6e603a1fcb058", + .url = "https://github.com/raysan5/raylib/archive/c4be01329493d0e772a04de08639b4da32905d2a.tar.gz", + .hash = "1220d1c8697d41a42d4eaaf3f8709865534d1f3d6ad63f8a27500fa881380651a1c5", }, .raygui = .{ - .url = "https://github.com/raysan5/raygui/archive/4b3d94f5df6a5a2aa86286350f7e20c0ca35f516.tar.gz", - .hash = "122002d98ca255ec706ef8e5497b3723d6c6e163511761d116dac3aee87747d46cf1", + .url = "https://github.com/raysan5/raygui/archive/1e03efca48c50c5ea4b4a053d5bf04bad58d3e43.tar.gz", + .hash = "122062b24f031e68f0d11c91dfc32aed5baf06caf26ed3c80ea1802f9e788ef1c358", } }, .minimum_zig_version = "0.13.0", diff --git a/lib/generate_functions.py b/lib/generate_functions.py index 0ff4513..43979a5 100755 --- a/lib/generate_functions.py +++ b/lib/generate_functions.py @@ -59,7 +59,7 @@ def ziggify_type(name: str, t: str, func_name) -> str: "AutomationEventList", "list", "batch", "glInternalFormat", "glFormat", "glType", "mipmaps", "active", "scroll", "view", "checked", "mouseCell", "scrollIndex", "focus", "secretViewActive", "color", "alpha", "colorHsv", - "translation", "rotation", "scale" + "translation", "rotation", "scale", "mat" ] multi = [ "data", "compData", "points", "fileData", "colors", "pixels", diff --git a/lib/preludes/raygui-prelude.zig b/lib/preludes/raygui-prelude.zig index c6202d6..1c8d189 100644 --- a/lib/preludes/raygui-prelude.zig +++ b/lib/preludes/raygui-prelude.zig @@ -127,6 +127,8 @@ pub const GuiComboBoxProperty = enum(c_int) { pub const GuiDropdownBoxProperty = enum(c_int) { arrow_padding = 16, dropdown_items_spacing, + dropdown_arrow_hidden, + dropdown_roll_up, }; pub const GuiTextBoxProperty = enum(c_int) { @@ -143,6 +145,7 @@ pub const GuiListViewProperty = enum(c_int) { list_items_spacing, scrollbar_width, scrollbar_side, + list_items_border_width, }; pub const GuiColorPickerProperty = enum(c_int) { diff --git a/lib/preludes/raylib-prelude.zig b/lib/preludes/raylib-prelude.zig index bbe6b9c..0435530 100755 --- a/lib/preludes/raylib-prelude.zig +++ b/lib/preludes/raylib-prelude.zig @@ -1379,8 +1379,8 @@ pub const Mesh = extern struct { animNormals: [*c]f32, boneIds: [*c]u8, boneWeights: [*c]f32, - vaoId: c_uint, - vboId: [*c]c_uint, + boneMatrices: [*c]Matrix, + boneCount: c_int, /// Draw a 3d mesh with material and transform pub fn draw(self: Mesh, material: Material, transform: Matrix) void { @@ -1827,6 +1827,9 @@ pub const ShaderLocationIndex = enum(c_int) { shader_loc_map_irradiance = 23, shader_loc_map_prefilter = 24, shader_loc_map_brdf = 25, + shader_loc_vertex_boneids = 26, + shader_loc_vertex_boneweights = 27, + shader_loc_bone_matrices = 28 }; pub const ShaderUniformDataType = enum(c_int) { diff --git a/lib/raygui.h b/lib/raygui.h index 5b837d0..85c4778 100644 --- a/lib/raygui.h +++ b/lib/raygui.h @@ -1,6 +1,6 @@ /******************************************************************************************* * -* raygui v4.1-dev - 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 @@ -141,8 +141,23 @@ * Draw text bounds rectangles for debug * * VERSIONS HISTORY: -* 4.1-dev (2024) Current dev version... +* 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() @@ -317,9 +332,9 @@ #define RAYGUI_H #define RAYGUI_VERSION_MAJOR 4 -#define RAYGUI_VERSION_MINOR 1 +#define RAYGUI_VERSION_MINOR 5 #define RAYGUI_VERSION_PATCH 0 -#define RAYGUI_VERSION "4.1-dev" +#define RAYGUI_VERSION "4.5-dev" #if !defined(RAYGUI_STANDALONE) #include "raylib.h" @@ -616,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 @@ -636,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 @@ -722,7 +740,7 @@ RAYGUIAPI int GuiComboBox(Rectangle bounds, const char *text, int *active); 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 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 @@ -975,12 +993,12 @@ typedef enum { ICON_WARNING = 220, ICON_HELP_BOX = 221, ICON_INFO_BOX = 222, - ICON_223 = 223, - ICON_224 = 224, - ICON_225 = 225, - ICON_226 = 226, - ICON_227 = 227, - ICON_228 = 228, + ICON_PRIORITY = 223, + ICON_LAYERS_ISO = 224, + ICON_LAYERS2 = 225, + ICON_MLAYERS = 226, + ICON_MAPS = 227, + ICON_HOT = 228, ICON_229 = 229, ICON_230 = 230, ICON_231 = 231, @@ -1027,6 +1045,7 @@ typedef enum { #if defined(RAYGUI_IMPLEMENTATION) +#include // required for: isspace() [GuiTextBox()] #include // Required for: FILE, fopen(), fclose(), fprintf(), feof(), fscanf(), vsprintf() [GuiLoadStyle(), GuiLoadIcons()] #include // Required for: malloc(), calloc(), free() [GuiLoadStyle(), GuiLoadIcons()] #include // Required for: strlen() [GuiTextBox(), GuiValueBox()], memset(), memcpy() @@ -1293,12 +1312,12 @@ static unsigned int guiIcons[RAYGUI_ICON_MAX_ICONS*RAYGUI_ICON_DATA_ELEMENTS] = 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 - 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 - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_228 + 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 + 0x04200000, 0x1cf00c60, 0x11f019f0, 0x0f3807b8, 0x1e3c0f3c, 0x1c1c1e1c, 0x1e3c1c1c, 0x00000f70, // ICON_HOT 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_229 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_230 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_231 @@ -1621,9 +1640,9 @@ int GuiGroupBox(Rectangle bounds, const char *text) // Draw control //-------------------------------------------------------------------- - GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y, RAYGUI_GROUPBOX_LINE_THICK, bounds.height }, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? BORDER_COLOR_DISABLED : LINE_COLOR))); - GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height - 1, bounds.width, RAYGUI_GROUPBOX_LINE_THICK }, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? BORDER_COLOR_DISABLED : LINE_COLOR))); - GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - 1, bounds.y, RAYGUI_GROUPBOX_LINE_THICK, bounds.height }, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? BORDER_COLOR_DISABLED : LINE_COLOR))); + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y, RAYGUI_GROUPBOX_LINE_THICK, bounds.height }, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED : (int)LINE_COLOR))); + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height - 1, bounds.width, RAYGUI_GROUPBOX_LINE_THICK }, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED : (int)LINE_COLOR))); + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - 1, bounds.y, RAYGUI_GROUPBOX_LINE_THICK, bounds.height }, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED : (int)LINE_COLOR))); GuiLine(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y - GuiGetStyle(DEFAULT, TEXT_SIZE)/2, bounds.width, (float)GuiGetStyle(DEFAULT, TEXT_SIZE) }, text); //-------------------------------------------------------------------- @@ -1644,7 +1663,7 @@ int GuiLine(Rectangle bounds, const char *text) int result = 0; GuiState state = guiState; - Color color = GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? BORDER_COLOR_DISABLED : LINE_COLOR)); + Color color = GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED : (int)LINE_COLOR)); // Draw control //-------------------------------------------------------------------- @@ -1692,7 +1711,7 @@ int GuiPanel(Rectangle bounds, const char *text) //-------------------------------------------------------------------- if (text != NULL) GuiStatusBar(statusBar, text); // Draw panel header as status bar - GuiDrawRectangle(bounds, RAYGUI_PANEL_BORDER_WIDTH, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? BORDER_COLOR_DISABLED: LINE_COLOR)), + GuiDrawRectangle(bounds, RAYGUI_PANEL_BORDER_WIDTH, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED: (int)LINE_COLOR)), GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? BASE_COLOR_DISABLED : BACKGROUND_COLOR))); //-------------------------------------------------------------------- @@ -1869,7 +1888,7 @@ int GuiScrollPanel(Rectangle bounds, const char *text, Rectangle content, Vector 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 }; + 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; @@ -2327,15 +2346,22 @@ 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; @@ -2362,7 +2388,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 +2433,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 +2450,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; @@ -2456,7 +2487,10 @@ int GuiTextBox(Rectangle bounds, char *text, int textSize, 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 @@ -2505,6 +2539,8 @@ int GuiTextBox(Rectangle bounds, char *text, int textSize, 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,12 +2553,9 @@ int GuiTextBox(Rectangle bounds, char *text, int textSize, 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); @@ -2564,30 +2597,66 @@ int GuiTextBox(Rectangle bounds, char *text, int textSize, 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'; } } - // Delete codepoint from text, before current cursor position - if ((textLength > 0) && (IsKeyPressed(KEY_BACKSPACE) || (IsKeyDown(KEY_BACKSPACE) && (autoCursorCooldownCounter >= RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN)))) + // Delete related codepoints from text, before current cursor position + if ((textLength > 0) && IsKeyPressed(KEY_BACKSPACE) && (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_RIGHT_CONTROL))) + { + int i = textBoxCursorIndex - 1; + int accCodepointSize = 0; + + // Move cursor to the end of word if on space already + while ((i > 0) && isspace(text[i])) + { + int prevCodepointSize = 0; + GetCodepointPrevious(text + i, &prevCodepointSize); + i -= prevCodepointSize; + accCodepointSize += prevCodepointSize; + } + + // Move cursor to the start of the word + while ((i > 0) && !isspace(text[i])) + { + int prevCodepointSize = 0; + GetCodepointPrevious(text + i, &prevCodepointSize); + i -= prevCodepointSize; + accCodepointSize += prevCodepointSize; + } + + // Move forward text from cursor position + for (int j = (textBoxCursorIndex - accCodepointSize); j < textLength; j++) text[j] = text[j + accCodepointSize]; + + // Prevent cursor index from decrementing past 0 + if (textBoxCursorIndex > 0) + { + textBoxCursorIndex -= accCodepointSize; + textLength -= accCodepointSize; + } + + // Make sure text last character is EOL + text[textLength] = '\0'; + } + else if ((textLength > 0) && (IsKeyPressed(KEY_BACKSPACE) || (IsKeyDown(KEY_BACKSPACE) && (autoCursorCooldownCounter >= RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN)))) { autoCursorDelayCounter++; if (IsKeyPressed(KEY_BACKSPACE) || (autoCursorDelayCounter%RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY) == 0) // Delay every movement some frames { int prevCodepointSize = 0; - GetCodepointPrevious(text + textBoxCursorIndex, &prevCodepointSize); - // 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) { + GetCodepointPrevious(text + textBoxCursorIndex, &prevCodepointSize); + + // Move backward text from cursor position + for (int i = (textBoxCursorIndex - prevCodepointSize); i < textLength; i++) text[i] = text[i + prevCodepointSize]; + textBoxCursorIndex -= codepointSize; textLength -= codepointSize; } @@ -2605,7 +2674,7 @@ int GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode) if (IsKeyPressed(KEY_LEFT) || (autoCursorDelayCounter%RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY) == 0) // Delay every movement some frames { int prevCodepointSize = 0; - GetCodepointPrevious(text + textBoxCursorIndex, &prevCodepointSize); + if (textBoxCursorIndex > 0) GetCodepointPrevious(text + textBoxCursorIndex, &prevCodepointSize); if (textBoxCursorIndex >= prevCodepointSize) textBoxCursorIndex -= prevCodepointSize; } @@ -2655,7 +2724,7 @@ int GuiTextBox(Rectangle bounds, char *text, int textSize, 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 @@ -2687,7 +2756,7 @@ int GuiTextBox(Rectangle bounds, char *text, int textSize, 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; } } @@ -2892,7 +2961,7 @@ 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))) + 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; @@ -2948,7 +3017,7 @@ int GuiValueBoxFloat(Rectangle bounds, const char *text, char *textValue, float int result = 0; GuiState state = guiState; - + //char textValue[RAYGUI_VALUEBOX_MAX_CHARS + 1] = "\0"; //sprintf(textValue, "%2.2f", *value); @@ -2982,14 +3051,14 @@ int GuiValueBoxFloat(Rectangle bounds, const char *text, char *textValue, float if (GetTextWidth(textValue) < bounds.width) { int key = GetCharPressed(); - if (((key >= 48) && (key <= 57)) || - (key == '.') || + 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; } } @@ -3008,7 +3077,7 @@ int GuiValueBoxFloat(Rectangle bounds, const char *text, char *textValue, float if (valueHasChanged) *value = TextToFloat(textValue); - 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))) result = 1; } else { @@ -3393,11 +3462,13 @@ int GuiListViewEx(Rectangle bounds, const char **text, int count, int *scrollInd // Draw control //-------------------------------------------------------------------- - GuiDrawRectangle(bounds, GuiGetStyle(DEFAULT, BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER + state*3)), GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR))); // Draw background + GuiDrawRectangle(bounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER + state*3)), GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR))); // Draw background // 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))); @@ -3472,7 +3543,7 @@ int GuiColorPanel(Rectangle bounds, const char *text, Color *color) GuiColorPanelHSV(bounds, text, &hsv); // Check if the hsv was changed, only then change the color. - // This is necessary, because the Color->HSV->Color conversion has precision errors. + // 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. @@ -3846,7 +3917,7 @@ int GuiMessageBox(Rectangle bounds, const char *title, const char *message, cons buttonBounds.width = (bounds.width - RAYGUI_MESSAGEBOX_BUTTON_PADDING*(buttonCount + 1))/buttonCount; buttonBounds.height = RAYGUI_MESSAGEBOX_BUTTON_HEIGHT; - int textWidth = GetTextWidth(message) + 2; + //int textWidth = GetTextWidth(message) + 2; Rectangle textBounds = { 0 }; textBounds.x = bounds.x + RAYGUI_MESSAGEBOX_BUTTON_PADDING; @@ -4450,7 +4521,7 @@ static void GuiLoadStyleFromMemory(const unsigned char *fileData, int dataSize) // NOTE: All DEFAULT properties should be defined first in the file GuiSetStyle(0, (int)propertyId, propertyValue); - if (propertyId < RAYGUI_MAX_PROPS_BASE) for (int i = 1; i < RAYGUI_MAX_CONTROLS; i++) GuiSetStyle(i, (int)propertyId, propertyValue); + if (propertyId < RAYGUI_MAX_PROPS_BASE) for (int j = 1; j < RAYGUI_MAX_CONTROLS; j++) GuiSetStyle(j, (int)propertyId, propertyValue); } else GuiSetStyle((int)controlId, (int)propertyId, propertyValue); } @@ -4689,7 +4760,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; @@ -4930,7 +5001,7 @@ static void GuiDrawText(const char *text, Rectangle textBounds, int alignment, C float glyphWidth = 0; int ellipsisWidth = GetTextWidth("..."); - bool overflowReached = false; + bool textOverflow = false; for (int c = 0, codepointSize = 0; c < lineSize; c += codepointSize) { int codepoint = GetCodepointNext(&lines[i][c], &codepointSize); @@ -5001,9 +5072,9 @@ static void GuiDrawText(const char *text, Rectangle textBounds, int alignment, C { DrawTextCodepoint(guiFont, codepoint, RAYGUI_CLITERAL(Vector2){ textBoundsPosition.x + textOffsetX, textBoundsPosition.y + textOffsetY }, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), GuiFade(tint, guiAlpha)); } - else if (!overflowReached) + else if (!textOverflow) { - overflowReached = true; + textOverflow = true; for (int j = 0; j < ellipsisWidth; j += ellipsisWidth/3) { @@ -5597,7 +5668,7 @@ static float TextToFloat(const char *text) divisor = divisor*10.0f; } } - + return value; } diff --git a/lib/raygui.zig b/lib/raygui.zig index f9539a8..3bea717 100644 --- a/lib/raygui.zig +++ b/lib/raygui.zig @@ -127,6 +127,8 @@ pub const GuiComboBoxProperty = enum(c_int) { pub const GuiDropdownBoxProperty = enum(c_int) { arrow_padding = 16, dropdown_items_spacing, + dropdown_arrow_hidden, + dropdown_roll_up, }; pub const GuiTextBoxProperty = enum(c_int) { @@ -143,6 +145,7 @@ pub const GuiListViewProperty = enum(c_int) { list_items_spacing, scrollbar_width, scrollbar_side, + list_items_border_width, }; pub const GuiColorPickerProperty = enum(c_int) { diff --git a/lib/raylib-ext.zig b/lib/raylib-ext.zig index fc23f91..b90a2c3 100644 --- a/lib/raylib-ext.zig +++ b/lib/raylib-ext.zig @@ -134,6 +134,7 @@ pub extern "c" fn GetDirectoryPath(filePath: [*c]const u8) [*c]const u8; pub extern "c" fn GetPrevDirectoryPath(dirPath: [*c]const u8) [*c]const u8; pub extern "c" fn GetWorkingDirectory() [*c]const u8; pub extern "c" fn GetApplicationDirectory() [*c]const u8; +pub extern "c" fn MakeDirectory(dirPath: [*c]const u8) c_int; pub extern "c" fn ChangeDirectory(dir: [*c]const u8) bool; pub extern "c" fn IsPathFile(path: [*c]const u8) bool; pub extern "c" fn IsFileNameValid(fileName: [*c]const u8) bool; @@ -272,7 +273,6 @@ pub extern "c" fn CheckCollisionCircleLine(center: rl.Vector2, radius: f32, p1: pub extern "c" fn GetCollisionRec(rec1: rl.Rectangle, rec2: rl.Rectangle) rl.Rectangle; pub extern "c" fn LoadImage(fileName: [*c]const u8) rl.Image; pub extern "c" fn LoadImageRaw(fileName: [*c]const u8, width: c_int, height: c_int, format: rl.PixelFormat, headerSize: c_int) rl.Image; -pub extern "c" fn LoadImageSvg(fileNameOrString: [*c]const u8, width: c_int, height: c_int) rl.Image; pub extern "c" fn LoadImageAnim(fileName: [*c]const u8, frames: [*c]c_int) rl.Image; pub extern "c" fn LoadImageAnimFromMemory(fileType: [*c]const u8, fileData: [*c]const u8, dataSize: c_int, frames: [*c]c_int) rl.Image; pub extern "c" fn LoadImageFromMemory(fileType: [*c]const u8, fileData: [*c]const u8, dataSize: c_int) rl.Image; @@ -381,6 +381,7 @@ pub extern "c" fn ColorBrightness(color: rl.Color, factor: f32) rl.Color; pub extern "c" fn ColorContrast(color: rl.Color, contrast: f32) rl.Color; pub extern "c" fn ColorAlpha(color: rl.Color, alpha: f32) rl.Color; pub extern "c" fn ColorAlphaBlend(dst: rl.Color, src: rl.Color, tint: rl.Color) rl.Color; +pub extern "c" fn ColorLerp(color1: rl.Color, color2: rl.Color, factor: f32) rl.Color; pub extern "c" fn GetColor(hexValue: c_uint) rl.Color; pub extern "c" fn GetPixelColor(srcPtr: *anyopaque, format: rl.PixelFormat) rl.Color; pub extern "c" fn SetPixelColor(dstPtr: *anyopaque, color: rl.Color, format: rl.PixelFormat) void; @@ -502,6 +503,7 @@ pub extern "c" fn UpdateModelAnimation(model: rl.Model, anim: rl.ModelAnimation, pub extern "c" fn UnloadModelAnimation(anim: rl.ModelAnimation) void; pub extern "c" fn UnloadModelAnimations(animations: [*c]rl.ModelAnimation, animCount: c_int) void; pub extern "c" fn IsModelAnimationValid(model: rl.Model, anim: rl.ModelAnimation) bool; +pub extern "c" fn UpdateModelAnimationBoneMatrices(model: rl.Model, anim: rl.ModelAnimation, frame: c_int) void; pub extern "c" fn CheckCollisionSpheres(center1: rl.Vector3, radius1: f32, center2: rl.Vector3, radius2: f32) bool; pub extern "c" fn CheckCollisionBoxes(box1: rl.BoundingBox, box2: rl.BoundingBox) bool; pub extern "c" fn CheckCollisionBoxSphere(box: rl.BoundingBox, center: rl.Vector3, radius: f32) bool; diff --git a/lib/raylib.h b/lib/raylib.h index 30ba8bd..e0c74af 100644 --- a/lib/raylib.h +++ b/lib/raylib.h @@ -352,8 +352,10 @@ typedef struct Mesh { // Animation vertex data float *animVertices; // Animated vertex positions (after bones transformations) float *animNormals; // Animated normals (after bones transformations) - unsigned char *boneIds; // Vertex bone ids, max 255 bone ids, up to 4 bones influence by vertex (skinning) - float *boneWeights; // Vertex bone weight, up to 4 bones influence by vertex (skinning) + unsigned char *boneIds; // Vertex bone ids, max 255 bone ids, up to 4 bones influence by vertex (skinning) (shader-location = 6) + float *boneWeights; // Vertex bone weight, up to 4 bones influence by vertex (skinning) (shader-location = 7) + Matrix *boneMatrices; // Bones animated transformation matrices + int boneCount; // Number of bones // OpenGL identifiers unsigned int vaoId; // OpenGL Vertex Array Object id @@ -790,7 +792,10 @@ typedef enum { SHADER_LOC_MAP_CUBEMAP, // Shader location: samplerCube texture: cubemap SHADER_LOC_MAP_IRRADIANCE, // Shader location: samplerCube texture: irradiance SHADER_LOC_MAP_PREFILTER, // Shader location: samplerCube texture: prefilter - SHADER_LOC_MAP_BRDF // Shader location: sampler2d texture: brdf + SHADER_LOC_MAP_BRDF, // Shader location: sampler2d texture: brdf + SHADER_LOC_VERTEX_BONEIDS, // Shader location: vertex attribute: boneIds + SHADER_LOC_VERTEX_BONEWEIGHTS, // Shader location: vertex attribute: boneWeights + SHADER_LOC_BONE_MATRICES // Shader location: array of matrices uniform: boneMatrices } ShaderLocationIndex; #define SHADER_LOC_MAP_DIFFUSE SHADER_LOC_MAP_ALBEDO @@ -1122,11 +1127,12 @@ RLAPI const char *GetDirectoryPath(const char *filePath); // Get full pa RLAPI const char *GetPrevDirectoryPath(const char *dirPath); // Get previous directory path for a given path (uses static string) RLAPI const char *GetWorkingDirectory(void); // Get current working directory (uses static string) RLAPI const char *GetApplicationDirectory(void); // Get the directory of the running application (uses static string) +RLAPI int MakeDirectory(const char *dirPath); // Create directories (including full path requested), returns 0 on success RLAPI bool ChangeDirectory(const char *dir); // Change working directory, return true on success RLAPI bool IsPathFile(const char *path); // Check if a given path is a file or a directory RLAPI bool IsFileNameValid(const char *fileName); // Check if fileName is valid for the platform/OS RLAPI FilePathList LoadDirectoryFiles(const char *dirPath); // Load directory filepaths -RLAPI FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool scanSubdirs); // Load directory filepaths with extension filtering and recursive directory scan +RLAPI FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool scanSubdirs); // Load directory filepaths with extension filtering and recursive directory scan. Use 'DIR' in the filter string to include directories in the result RLAPI void UnloadDirectoryFiles(FilePathList files); // Unload filepaths RLAPI bool IsFileDropped(void); // Check if a file has been dropped into window RLAPI FilePathList LoadDroppedFiles(void); // Load dropped filepaths @@ -1228,8 +1234,8 @@ RLAPI Texture2D GetShapesTexture(void); // Get t RLAPI Rectangle GetShapesTextureRectangle(void); // Get texture source rectangle that is used for shapes drawing // Basic shapes drawing functions -RLAPI void DrawPixel(int posX, int posY, Color color); // Draw a pixel -RLAPI void DrawPixelV(Vector2 position, Color color); // Draw a pixel (Vector version) +RLAPI void DrawPixel(int posX, int posY, Color color); // Draw a pixel using geometry [Can be slow, use with care] +RLAPI void DrawPixelV(Vector2 position, Color color); // Draw a pixel using geometry (Vector version) [Can be slow, use with care] RLAPI void DrawLine(int startPosX, int startPosY, int endPosX, int endPosY, Color color); // Draw a line RLAPI void DrawLineV(Vector2 startPos, Vector2 endPos, Color color); // Draw a line (using gl lines) RLAPI void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw a line (using triangles/quads) @@ -1306,7 +1312,6 @@ RLAPI Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2); // NOTE: These functions do not require GPU access RLAPI Image LoadImage(const char *fileName); // Load image from file into CPU memory (RAM) RLAPI Image LoadImageRaw(const char *fileName, int width, int height, int format, int headerSize); // Load image from RAW file data -RLAPI Image LoadImageSvg(const char *fileNameOrString, int width, int height); // Load image from SVG file data or string with specified size RLAPI Image LoadImageAnim(const char *fileName, int *frames); // Load image sequence from file (frames appended to image.data) RLAPI Image LoadImageAnimFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int *frames); // Load image sequence from memory buffer RLAPI Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, int dataSize); // Load image from memory buffer, fileType refers to extension: i.e. '.png' @@ -1431,6 +1436,7 @@ RLAPI Color ColorBrightness(Color color, float factor); // G RLAPI Color ColorContrast(Color color, float contrast); // Get color with contrast correction, contrast values between -1.0f and 1.0f RLAPI Color ColorAlpha(Color color, float alpha); // Get color with alpha applied, alpha goes from 0.0f to 1.0f RLAPI Color ColorAlphaBlend(Color dst, Color src, Color tint); // Get src alpha-blended into dst color with tint +RLAPI Color ColorLerp(Color color1, Color color2, float factor); // Get color lerp interpolation between two colors, factor [0.0f..1.0f] RLAPI Color GetColor(unsigned int hexValue); // Get Color structure from hexadecimal value RLAPI Color GetPixelColor(void *srcPtr, int format); // Get Color from a source pixel pointer of certain format RLAPI void SetPixelColor(void *dstPtr, Color color, int format); // Set color formatted into destination pixel pointer @@ -1590,6 +1596,7 @@ RLAPI void UpdateModelAnimation(Model model, ModelAnimation anim, int frame); RLAPI void UnloadModelAnimation(ModelAnimation anim); // Unload animation data RLAPI void UnloadModelAnimations(ModelAnimation *animations, int animCount); // Unload animation array data RLAPI bool IsModelAnimationValid(Model model, ModelAnimation anim); // Check model animation skeleton match +RLAPI void UpdateModelAnimationBoneMatrices(Model model, ModelAnimation anim, int frame); // Update model animation mesh bone matrices (Note GPU skinning does not work on Mac) // Collision detection functions RLAPI bool CheckCollisionSpheres(Vector3 center1, float radius1, Vector3 center2, float radius2); // Check collision between two spheres diff --git a/lib/raylib.zig b/lib/raylib.zig index e641668..f74c5e2 100644 --- a/lib/raylib.zig +++ b/lib/raylib.zig @@ -1379,8 +1379,8 @@ pub const Mesh = extern struct { animNormals: [*c]f32, boneIds: [*c]u8, boneWeights: [*c]f32, - vaoId: c_uint, - vboId: [*c]c_uint, + boneMatrices: [*c]Matrix, + boneCount: c_int, /// Draw a 3d mesh with material and transform pub fn draw(self: Mesh, material: Material, transform: Matrix) void { @@ -1827,6 +1827,9 @@ pub const ShaderLocationIndex = enum(c_int) { shader_loc_map_irradiance = 23, shader_loc_map_prefilter = 24, shader_loc_map_brdf = 25, + shader_loc_vertex_boneids = 26, + shader_loc_vertex_boneweights = 27, + shader_loc_bone_matrices = 28 }; pub const ShaderUniformDataType = enum(c_int) { @@ -2957,6 +2960,11 @@ pub fn getApplicationDirectory() [*:0]const u8 { return std.mem.span(cdef.GetApplicationDirectory()); } +/// Create directories (including full path requested), returns 0 on success +pub fn makeDirectory(dirPath: [*:0]const u8) i32 { + return @as(i32, cdef.MakeDirectory(@as([*c]const u8, @ptrCast(dirPath)))); +} + /// Change working directory, return true on success pub fn changeDirectory(dir: [*:0]const u8) bool { return cdef.ChangeDirectory(@as([*c]const u8, @ptrCast(dir))); @@ -2977,7 +2985,7 @@ pub fn loadDirectoryFiles(dirPath: [*:0]const u8) FilePathList { return cdef.LoadDirectoryFiles(@as([*c]const u8, @ptrCast(dirPath))); } -/// Load directory filepaths with extension filtering and recursive directory scan +/// Load directory filepaths with extension filtering and recursive directory scan. Use 'DIR' in the filter string to include directories in the result pub fn loadDirectoryFilesEx(basePath: [*:0]const u8, filter: [*:0]const u8, scanSubdirs: bool) FilePathList { return cdef.LoadDirectoryFilesEx(@as([*c]const u8, @ptrCast(basePath)), @as([*c]const u8, @ptrCast(filter)), scanSubdirs); } @@ -3302,12 +3310,12 @@ pub fn getShapesTextureRectangle() Rectangle { return cdef.GetShapesTextureRectangle(); } -/// Draw a pixel +/// Draw a pixel using geometry [Can be slow, use with care] pub fn drawPixel(posX: i32, posY: i32, color: Color) void { cdef.DrawPixel(@as(c_int, posX), @as(c_int, posY), color); } -/// Draw a pixel (Vector version) +/// Draw a pixel using geometry (Vector version) [Can be slow, use with care] pub fn drawPixelV(position: Vector2, color: Color) void { cdef.DrawPixelV(position, color); } @@ -3582,11 +3590,6 @@ pub fn loadImageRaw(fileName: [*:0]const u8, width: i32, height: i32, format: Pi return cdef.LoadImageRaw(@as([*c]const u8, @ptrCast(fileName)), @as(c_int, width), @as(c_int, height), format, @as(c_int, headerSize)); } -/// Load image from SVG file data or string with specified size -pub fn loadImageSvg(fileNameOrString: [*:0]const u8, width: i32, height: i32) Image { - return cdef.LoadImageSvg(@as([*c]const u8, @ptrCast(fileNameOrString)), @as(c_int, width), @as(c_int, height)); -} - /// Load image sequence from file (frames appended to image.data) pub fn loadImageAnim(fileName: [*:0]const u8, frames: *i32) Image { return cdef.LoadImageAnim(@as([*c]const u8, @ptrCast(fileName)), @as([*c]c_int, @ptrCast(frames))); @@ -4102,6 +4105,11 @@ pub fn colorAlphaBlend(dst: Color, src: Color, tint: Color) Color { return cdef.ColorAlphaBlend(dst, src, tint); } +/// Get color lerp interpolation between two colors, factor [0.0f..1.0f] +pub fn colorLerp(color1: Color, color2: Color, factor: f32) Color { + return cdef.ColorLerp(color1, color2, factor); +} + /// Get Color structure from hexadecimal value pub fn getColor(hexValue: u32) Color { return cdef.GetColor(@as(c_uint, hexValue)); @@ -4627,6 +4635,11 @@ pub fn isModelAnimationValid(model: Model, anim: ModelAnimation) bool { return cdef.IsModelAnimationValid(model, anim); } +/// Update model animation mesh bone matrices (Note GPU skinning does not work on Mac) +pub fn updateModelAnimationBoneMatrices(model: Model, anim: ModelAnimation, frame: i32) void { + cdef.UpdateModelAnimationBoneMatrices(model, anim, @as(c_int, frame)); +} + /// Check collision between two spheres pub fn checkCollisionSpheres(center1: Vector3, radius1: f32, center2: Vector3, radius2: f32) bool { return cdef.CheckCollisionSpheres(center1, radius1, center2, radius2); diff --git a/lib/rlgl-ext.zig b/lib/rlgl-ext.zig index 2fdbc11..123c382 100644 --- a/lib/rlgl-ext.zig +++ b/lib/rlgl-ext.zig @@ -135,6 +135,7 @@ pub extern "c" fn rlGetLocationUniform(shaderId: c_uint, uniformName: [*c]const pub extern "c" fn rlGetLocationAttrib(shaderId: c_uint, attribName: [*c]const u8) c_int; pub extern "c" fn rlSetUniform(locIndex: c_int, value: *const anyopaque, uniformType: c_int, count: c_int) void; pub extern "c" fn rlSetUniformMatrix(locIndex: c_int, mat: rl.Matrix) void; +pub extern "c" fn rlSetUniformMatrices(locIndex: c_int, mat: [*c]const rl.Matrix, count: c_int) void; pub extern "c" fn rlSetUniformSampler(locIndex: c_int, textureId: c_uint) void; pub extern "c" fn rlSetShader(id: c_uint, locs: [*c]c_int) void; pub extern "c" fn rlLoadComputeShaderProgram(shaderId: c_uint) c_uint; diff --git a/lib/rlgl.h b/lib/rlgl.h index 9b94d40..1695c2f 100644 --- a/lib/rlgl.h +++ b/lib/rlgl.h @@ -68,12 +68,15 @@ * #define RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR "vertexColor" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR * #define RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT "vertexTangent" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT * #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 "vertexTexCoord2" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2 +* #define RL_DEFAULT_SHADER_ATTRIB_NAME_BONEIDS "vertexBoneIds" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS +* #define RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS "vertexBoneWeights" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS * #define RL_DEFAULT_SHADER_UNIFORM_NAME_MVP "mvp" // model-view-projection matrix * #define RL_DEFAULT_SHADER_UNIFORM_NAME_VIEW "matView" // view matrix * #define RL_DEFAULT_SHADER_UNIFORM_NAME_PROJECTION "matProjection" // projection matrix * #define RL_DEFAULT_SHADER_UNIFORM_NAME_MODEL "matModel" // model matrix * #define RL_DEFAULT_SHADER_UNIFORM_NAME_NORMAL "matNormal" // normal matrix (transpose(inverse(matModelView))) * #define RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR "colDiffuse" // color diffuse (base tint color, multiplied by texture color) +* #define RL_DEFAULT_SHADER_UNIFORM_NAME_BONE_MATRICES "boneMatrices" // bone matrices * #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0 "texture0" // texture0 (texture slot active 0) * #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE1 "texture1" // texture1 (texture slot active 1) * #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE2 "texture2" // texture2 (texture slot active 2) @@ -324,22 +327,34 @@ // Default shader vertex attribute locations #ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION - #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION 0 + #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION 0 #endif #ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD - #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD 1 + #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD 1 #endif #ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL - #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL 2 + #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL 2 #endif #ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR - #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR 3 + #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR 3 #endif #ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT -#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT 4 +#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT 4 #endif #ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2 - #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2 5 + #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2 5 +#endif +#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES + #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES 6 +#endif + +#ifdef RL_SUPPORT_MESH_GPU_SKINNING +#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS + #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS 7 +#endif +#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS + #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS 8 +#endif #endif //---------------------------------------------------------------------------------- @@ -759,6 +774,7 @@ RLAPI int rlGetLocationUniform(unsigned int shaderId, const char *uniformName); RLAPI int rlGetLocationAttrib(unsigned int shaderId, const char *attribName); // Get shader location attribute RLAPI void rlSetUniform(int locIndex, const void *value, int uniformType, int count); // Set shader value uniform RLAPI void rlSetUniformMatrix(int locIndex, Matrix mat); // Set shader value matrix +RLAPI void rlSetUniformMatrices(int locIndex, const Matrix *mat, int count); // Set shader value matrices RLAPI void rlSetUniformSampler(int locIndex, unsigned int textureId); // Set shader value sampler RLAPI void rlSetShader(unsigned int id, int *locs); // Set shader currently active (id and locations) @@ -977,6 +993,12 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad #ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 "vertexTexCoord2" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 #endif +#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_BONEIDS + #define RL_DEFAULT_SHADER_ATTRIB_NAME_BONEIDS "vertexBoneIds" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_NAME_BONEIDS +#endif +#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS + #define RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS "vertexBoneWeights" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS +#endif #ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_MVP #define RL_DEFAULT_SHADER_UNIFORM_NAME_MVP "mvp" // model-view-projection matrix @@ -996,6 +1018,9 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad #ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR #define RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR "colDiffuse" // color diffuse (base tint color, multiplied by texture color) #endif +#ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_BONE_MATRICES + #define RL_DEFAULT_SHADER_UNIFORM_NAME_BONE_MATRICES "boneMatrices" // bone matrices +#endif #ifndef RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0 #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0 "texture0" // texture0 (texture slot active 0) #endif @@ -4149,6 +4174,11 @@ unsigned int rlLoadShaderProgram(unsigned int vShaderId, unsigned int fShaderId) glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT, RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT); glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2, RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2); +#ifdef RL_SUPPORT_MESH_GPU_SKINNING + glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS, RL_DEFAULT_SHADER_ATTRIB_NAME_BONEIDS); + glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS, RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS); +#endif + // NOTE: If some attrib name is no found on the shader, it locations becomes -1 glLinkProgram(program); @@ -4248,7 +4278,7 @@ void rlSetUniform(int locIndex, const void *value, int uniformType, int count) #endif case RL_SHADER_UNIFORM_SAMPLER2D: glUniform1iv(locIndex, count, (int *)value); break; default: TRACELOG(RL_LOG_WARNING, "SHADER: Failed to set uniform value, data type not recognized"); - + // TODO: Support glUniform1uiv(), glUniform2uiv(), glUniform3uiv(), glUniform4uiv() } #endif @@ -4283,6 +4313,14 @@ void rlSetUniformMatrix(int locIndex, Matrix mat) #endif } +// Set shader value uniform matrix +void rlSetUniformMatrices(int locIndex, const Matrix *matrices, int count) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + glUniformMatrix4fv(locIndex, count, true, (const float*)matrices); +#endif +} + // Set shader value uniform sampler void rlSetUniformSampler(int locIndex, unsigned int textureId) { diff --git a/lib/rlgl.zig b/lib/rlgl.zig index 610f7f4..71452e4 100644 --- a/lib/rlgl.zig +++ b/lib/rlgl.zig @@ -908,6 +908,11 @@ pub fn rlSetUniformMatrix(locIndex: i32, mat: Matrix) void { cdef.rlSetUniformMatrix(@as(c_int, locIndex), mat); } +/// Set shader value matrices +pub fn rlSetUniformMatrices(locIndex: i32, mat: *const Matrix, count: i32) void { + cdef.rlSetUniformMatrices(@as(c_int, locIndex), @as([*c]const Matrix, @ptrCast(mat)), @as(c_int, count)); +} + /// Set shader value sampler pub fn rlSetUniformSampler(locIndex: i32, textureId: u32) void { cdef.rlSetUniformSampler(@as(c_int, locIndex), @as(c_uint, textureId));