aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRay <raysan5@gmail.com>2015-08-31 01:16:34 +0200
committerRay <raysan5@gmail.com>2015-08-31 01:16:34 +0200
commit60194753d7b8abcdec3df2a502ccd29a1076bb7c (patch)
tree47df863966fee50bd3a10d195c3f8274b4ed5ee6 /src
parent3a9ed0e8462570e30d92e2aa8c0ff3cf655ef863 (diff)
parent808aeabf4c2ab0828e4f7806b75d95dc1b5ab212 (diff)
downloadraylib-60194753d7b8abcdec3df2a502ccd29a1076bb7c.tar.gz
raylib-60194753d7b8abcdec3df2a502ccd29a1076bb7c.zip
Merge pull request #26 from raysan5/develop
Develop branch integration
Diffstat (limited to 'src')
-rw-r--r--src/camera.c91
-rw-r--r--src/camera.h12
-rw-r--r--src/core.c6
-rw-r--r--src/raygui.c1002
-rw-r--r--src/raygui.h271
-rw-r--r--src/raylib.h87
-rw-r--r--src/rlgl.c16
-rw-r--r--src/rlgl.h4
-rw-r--r--src/text.c189
-rw-r--r--src/textures.c40
10 files changed, 1538 insertions, 180 deletions
diff --git a/src/camera.c b/src/camera.c
index 627451fe..b637b1e4 100644
--- a/src/camera.c
+++ b/src/camera.c
@@ -84,12 +84,12 @@ typedef enum { MOVE_FRONT = 0, MOVE_LEFT, MOVE_BACK, MOVE_RIGHT, MOVE_UP, MOVE_D
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
-static Camera internalCamera = {{2,0,2},{0,0,0},{0,1,0}};
+static Camera internalCamera = {{2, 0, 2}, {0, 0, 0}, {0, 1, 0}};
static Vector2 cameraAngle = { 0, 0 };
-static float cameraTargetDistance = 5;
+static float cameraTargetDistance = 5.0f;
static Vector2 cameraMousePosition = { 0, 0 };
static Vector2 cameraMouseVariation = { 0, 0 };
-static float mouseSensitivity = 0.003;
+static float mouseSensitivity = 0.003f;
static int cameraMoveControl[6] = { 'W', 'A', 'S', 'D', 'E', 'Q' };
static int cameraMoveCounter = 0;
static int cameraUseGravity = 1;
@@ -123,6 +123,7 @@ static int IsKeyDown(int key) { return 0; }
//----------------------------------------------------------------------------------
// Select camera mode (multiple camera modes available)
+// TODO: Review hardcoded values when changing modes...
void SetCameraMode(int mode)
{
if ((cameraMode == CAMERA_FIRST_PERSON) && (mode == CAMERA_FREE))
@@ -144,7 +145,7 @@ void SetCameraMode(int mode)
cameraTargetDistance = 10;
cameraAngle.x = 45 * DEG2RAD;
cameraAngle.y = -40 * DEG2RAD;
- internalCamera.target = (Vector3){ 0, 0, 0};
+ internalCamera.target = (Vector3){ 0, 0, 0 };
ProcessCamera(&internalCamera, &internalCamera.position);
ShowCursor();
@@ -154,57 +155,97 @@ void SetCameraMode(int mode)
cameraTargetDistance = 10;
cameraAngle.x = 225 * DEG2RAD;
cameraAngle.y = -40 * DEG2RAD;
- internalCamera.target = (Vector3){ 3, 0, 3};
+ internalCamera.target = (Vector3){ 0, 0, 0};
ProcessCamera(&internalCamera, &internalCamera.position);
}
cameraMode = mode;
}
-// Update camera with position
-Camera UpdateCamera(Vector3 *position)
+// Update camera (player position is ignored)
+void UpdateCamera(Camera *camera)
+{
+ Vector3 position = { 0, 0, 0 };
+
+ // Process internal camera and player position (if required)
+ if (cameraMode != CAMERA_CUSTOM) ProcessCamera(&internalCamera, &position);
+
+ *camera = internalCamera;
+}
+
+// Update camera and player position (1st person and 3rd person cameras)
+void UpdateCameraPlayer(Camera *camera, Vector3 *position)
{
- // Calculate camera
+ // Process internal camera and player position (if required)
if (cameraMode != CAMERA_CUSTOM) ProcessCamera(&internalCamera, position);
- return internalCamera;
+ *camera = internalCamera;
}
-void SetCameraMoveControls(int frontKey, int backKey, int leftKey, int rightKey, int upKey, int downKey)
+// Set internal camera position
+void SetCameraPosition(Vector3 position)
{
- cameraMoveControl[MOVE_FRONT] = frontKey;
- cameraMoveControl[MOVE_LEFT] = leftKey;
- cameraMoveControl[MOVE_BACK] = backKey;
- cameraMoveControl[MOVE_RIGHT] = rightKey;
- cameraMoveControl[MOVE_UP] = upKey;
- cameraMoveControl[MOVE_DOWN] = downKey;
+ internalCamera.position = position;
+
+ Vector3 v1 = internalCamera.position;
+ Vector3 v2 = internalCamera.target;
+
+ float dx = v2.x - v1.x;
+ float dy = v2.y - v1.y;
+ float dz = v2.z - v1.z;
+
+ cameraTargetDistance = sqrt(dx*dx + dy*dy + dz*dz);
}
-void SetCameraMouseSensitivity(float sensitivity)
+// Set internal camera target
+void SetCameraTarget(Vector3 target)
{
- mouseSensitivity = (sensitivity / 10000.0);
+ internalCamera.target = target;
+
+ Vector3 v1 = internalCamera.position;
+ Vector3 v2 = internalCamera.target;
+
+ float dx = v2.x - v1.x;
+ float dy = v2.y - v1.y;
+ float dz = v2.z - v1.z;
+
+ cameraTargetDistance = sqrt(dx*dx + dy*dy + dz*dz);
}
+// Set camera pan key to combine with mouse movement (free camera)
void SetCameraPanControl(int panKey)
{
panControlKey = panKey;
}
+// Set camera alt key to combine with mouse movement (free camera)
void SetCameraAltControl(int altKey)
{
altControlKey = altKey;
}
+// Set camera smooth zoom key to combine with mouse (free camera)
void SetCameraSmoothZoomControl(int szKey)
{
smoothZoomControlKey = szKey;
}
-void SetCameraTarget(Vector3 target)
+// Set camera move controls (1st person and 3rd person cameras)
+void SetCameraMoveControls(int frontKey, int backKey, int leftKey, int rightKey, int upKey, int downKey)
{
- internalCamera.target = target;
+ cameraMoveControl[MOVE_FRONT] = frontKey;
+ cameraMoveControl[MOVE_LEFT] = leftKey;
+ cameraMoveControl[MOVE_BACK] = backKey;
+ cameraMoveControl[MOVE_RIGHT] = rightKey;
+ cameraMoveControl[MOVE_UP] = upKey;
+ cameraMoveControl[MOVE_DOWN] = downKey;
}
+// Set camera mouse sensitivity (1st person and 3rd person cameras)
+void SetCameraMouseSensitivity(float sensitivity)
+{
+ mouseSensitivity = (sensitivity/10000.0);
+}
//----------------------------------------------------------------------------------
// Module specific Functions Definition
@@ -247,7 +288,9 @@ static void ProcessCamera(Camera *camera, Vector3 *playerPosition)
cameraMouseVariation.y = mousePosition.y - cameraMousePosition.y;
}
- cameraMousePosition = mousePosition;
+ // NOTE: We GetMousePosition() again because it can be modified by a previous SetMousePosition() call
+ // If using directly mousePosition variable we have problems on CAMERA_FIRST_PERSON and CAMERA_THIRD_PERSON
+ cameraMousePosition = GetMousePosition();
// Support for multiple automatic camera modes
switch (cameraMode)
@@ -298,7 +341,7 @@ static void ProcessCamera(Camera *camera, Vector3 *playerPosition)
}
else if ((camera->position.y < camera->target.y) && (camera->target.y > 0) && (mouseWheelMove > 0))
{
- cameraTargetDistance -= (mouseWheelMove * CAMERA_SCROLL_SENSITIVITY);
+ cameraTargetDistance -= (mouseWheelMove*CAMERA_SCROLL_SENSITIVITY);
if (cameraTargetDistance < FREE_CAMERA_DISTANCE_MIN_CLAMP) cameraTargetDistance = FREE_CAMERA_DISTANCE_MIN_CLAMP;
}
@@ -449,8 +492,8 @@ static void ProcessCamera(Camera *camera, Vector3 *playerPosition)
if (isMoving) cameraMoveCounter++;
// Camera orientation calculation
- cameraAngle.x += cameraMouseVariation.x*-mouseSensitivity;
- cameraAngle.y += cameraMouseVariation.y*-mouseSensitivity;
+ cameraAngle.x += (cameraMouseVariation.x * -mouseSensitivity);
+ cameraAngle.y += (cameraMouseVariation.y * -mouseSensitivity);
// Angle clamp
if (cameraAngle.y > FIRST_PERSON_MIN_CLAMP*DEG2RAD) cameraAngle.y = FIRST_PERSON_MIN_CLAMP*DEG2RAD;
diff --git a/src/camera.h b/src/camera.h
index 63d8f786..ed85320a 100644
--- a/src/camera.h
+++ b/src/camera.h
@@ -76,18 +76,20 @@ extern "C" { // Prevents name mangling of functions
// Module Functions Declaration
//----------------------------------------------------------------------------------
void SetCameraMode(int mode); // Set camera mode (multiple camera modes available)
-Camera UpdateCamera(Vector3 *playerPosition); // Update camera and player position (1st person and 3rd person cameras)
+void UpdateCamera(Camera *camera); // Update camera (player position is ignored)
+void UpdateCameraPlayer(Camera *camera, Vector3 *position); // Update camera and player position (1st person and 3rd person cameras)
-void SetCameraMoveControls(int frontKey, int backKey,
- int leftKey, int rightKey,
- int upKey, int downKey); // Set camera move controls (1st person and 3rd person cameras)
+void SetCameraPosition(Vector3 position); // Set internal camera position
+void SetCameraTarget(Vector3 target); // Set internal camera target
void SetCameraPanControl(int panKey); // Set camera pan key to combine with mouse movement (free camera)
void SetCameraAltControl(int altKey); // Set camera alt key to combine with mouse movement (free camera)
void SetCameraSmoothZoomControl(int szKey); // Set camera smooth zoom key to combine with mouse (free camera)
+void SetCameraMoveControls(int frontKey, int backKey,
+ int leftKey, int rightKey,
+ int upKey, int downKey); // Set camera move controls (1st person and 3rd person cameras)
void SetCameraMouseSensitivity(float sensitivity); // Set camera mouse sensitivity (1st person and 3rd person cameras)
-void SetCameraTarget(Vector3 target); // Set internal camera target
#ifdef __cplusplus
}
diff --git a/src/core.c b/src/core.c
index e3c4e10b..1ebc8a8f 100644
--- a/src/core.c
+++ b/src/core.c
@@ -638,6 +638,7 @@ void ShowLogo(void)
showLogo = true;
}
+#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
// Check if a file have been dropped into window
bool IsFileDropped(void)
{
@@ -664,6 +665,7 @@ void ClearDroppedFiles(void)
dropFilesCount = 0;
}
}
+#endif
// TODO: Gives the ray trace from mouse position
Ray GetMouseRay(Vector2 mousePosition, Camera camera)
@@ -1007,8 +1009,8 @@ static void InitDisplay(int width, int height)
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); // Avoid window being resizable
//glfwWindowHint(GLFW_DECORATED, GL_TRUE); // Border and buttons on Window
- //glfwWindowHint(GLFW_RED_BITS, 8); // Color framebuffer red component bits
- //glfwWindowHint(GLFW_DEPTH_BITS, 16); // Depth buffer bits (24 by default)
+ //glfwWindowHint(GLFW_RED_BITS, 8); // Framebuffer red color component bits
+ //glfwWindowHint(GLFW_DEPTH_BITS, 16); // Depthbuffer bits (24 by default)
//glfwWindowHint(GLFW_REFRESH_RATE, 0); // Refresh rate for fullscreen window
//glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API); // Default OpenGL API to use. Alternative: GLFW_OPENGL_ES_API
//glfwWindowHint(GLFW_AUX_BUFFERS, 0); // Number of auxiliar buffers
diff --git a/src/raygui.c b/src/raygui.c
new file mode 100644
index 00000000..fd45e1f2
--- /dev/null
+++ b/src/raygui.c
@@ -0,0 +1,1002 @@
+/**********************************************************************************************
+*
+* raygui - raylib IMGUI system (Immedite Mode GUI)
+*
+* Copyright (c) 2015 Kevin Gato, Daniel Nicolás, Sergio Martinez and Ramon Santamaria
+*
+* This software is provided "as-is", without any express or implied warranty. In no event
+* will the authors be held liable for any damages arising from the use of this software.
+*
+* Permission is granted to anyone to use this software for any purpose, including commercial
+* applications, and to alter it and redistribute it freely, subject to the following restrictions:
+*
+* 1. The origin of this software must not be misrepresented; you must not claim that you
+* wrote the original software. If you use this software in a product, an acknowledgment
+* in the product documentation would be appreciated but is not required.
+*
+* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
+* as being the original software.
+*
+* 3. This notice may not be removed or altered from any source distribution.
+*
+**********************************************************************************************/
+
+#include "raygui.h"
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h> // Required for malloc(), free()
+#include <string.h> // Required for strcmp()
+
+//----------------------------------------------------------------------------------
+// Defines and Macros
+//----------------------------------------------------------------------------------
+//...
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+//----------------------------------------------------------------------------------
+
+// GUI elements states
+typedef enum { BUTTON_DEFAULT, BUTTON_HOVER, BUTTON_PRESSED, BUTTON_CLICKED } ButtonState;
+typedef enum { TOGGLE_UNACTIVE, TOGGLE_HOVER, TOGGLE_PRESSED, TOGGLE_ACTIVE } ToggleState;
+typedef enum { COMBOBOX_UNACTIVE, COMBOBOX_HOVER, COMBOBOX_PRESSED, COMBOBOX_ACTIVE } ComboBoxState;
+typedef enum { SPINNER_DEFAULT, SPINNER_HOVER, SPINNER_PRESSED } SpinnerState;
+typedef enum { CHECKBOX_STATUS, CHECKBOX_HOVER, CHECKBOX_PRESSED } CheckBoxState;
+typedef enum { SLIDER_DEFAULT, SLIDER_HOVER, SLIDER_ACTIVE } SliderState;
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition
+//----------------------------------------------------------------------------------
+
+//Current GUI style (default light)
+static int style[NUM_PROPERTIES] = {
+ 0xf5f5f5ff, // GLOBAL_BASE_COLOR,
+ 0xf5f5f5ff, // GLOBAL_BORDER_COLOR,
+ 0xf5f5f5ff, // GLOBAL_TEXT_COLOR,
+ 10, // GLOBAL_TEXT_FONTSIZE
+ 1, // GLOBAL_BORDER_WIDTH
+ 0xf5f5f5ff, // BACKGROUND_COLOR
+ 1, // LABEL_BORDER_WIDTH
+ 0x000000ff, // LABEL_TEXT_COLOR
+ 20, // LABEL_TEXT_PADDING
+ 2, // BUTTON_BORDER_WIDTH
+ 20, // BUTTON_TEXT_PADDING
+ 0x828282ff, // BUTTON_DEFAULT_BORDER_COLOR
+ 0xc8c8c8ff, // BUTTON_DEFAULT_INSIDE_COLOR
+ 0x000000ff, // BUTTON_DEFAULT_TEXT_COLOR
+ 0xc8c8c8ff, // BUTTON_HOVER_BORDER_COLOR
+ 0xffffffff, // BUTTON_HOVER_INSIDE_COLOR
+ 0x000000ff, // BUTTON_HOVER_TEXT_COLOR
+ 0x7bb0d6ff, // BUTTON_PRESSED_BORDER_COLOR
+ 0xbcecffff, // BUTTON_PRESSED_INSIDE_COLOR
+ 0x5f9aa7ff, // BUTTON_PRESSED_TEXT_COLOR
+ 20, // TOGGLE_TEXT_PADDING
+ 1, // TOGGLE_BORDER_WIDTH
+ 0x828282ff, // TOGGLE_DEFAULT_BORDER_COLOR
+ 0xc8c8c8ff, // TOGGLE_DEFAULT_INSIDE_COLOR
+ 0x828282ff, // TOGGLE_DEFAULT_TEXT_COLOR
+ 0xc8c8c8ff, // TOGGLE_HOVER_BORDER_COLOR
+ 0xffffffff, // TOGGLE_HOVER_INSIDE_COLOR
+ 0x828282ff, // TOGGLE_HOVER_TEXT_COLOR
+ 0xbdd7eaff, // TOGGLE_PRESSED_BORDER_COLOR
+ 0xddf5ffff, // TOGGLE_PRESSED_INSIDE_COLOR
+ 0xafccd3ff, // TOGGLE_PRESSED_TEXT_COLOR
+ 0x7bb0d6ff, // TOGGLE_ACTIVE_BORDER_COLOR
+ 0xbcecffff, // TOGGLE_ACTIVE_INSIDE_COLOR
+ 0x5f9aa7ff, // TOGGLE_ACTIVE_TEXT_COLOR
+ 3, // TOGGLEGROUP_PADDING
+ 1, // SLIDER_BORDER_WIDTH
+ 1, // SLIDER_BUTTON_BORDER_WIDTH
+ 0x828282ff, // SLIDER_BORDER_COLOR
+ 0xc8c8c8ff, // SLIDER_INSIDE_COLOR
+ 0xbcecffff, // SLIDER_DEFAULT_COLOR
+ 0xffffffff, // SLIDER_HOVER_COLOR
+ 0xddf5ffff, // SLIDER_ACTIVE_COLOR
+ 0x828282ff, // SLIDERBAR_BORDER_COLOR
+ 0xc8c8c8ff, // SLIDERBAR_INSIDE_COLOR
+ 0xbcecffff, // SLIDERBAR_DEFAULT_COLOR
+ 0xffffffff, // SLIDERBAR_HOVER_COLOR
+ 0xddf5ffff, // SLIDERBAR_ACTIVE_COLOR
+ 0x828282ff, // SLIDERBAR_ZERO_LINE_COLOR
+ 0x828282ff, // PROGRESSBAR_BORDER_COLOR
+ 0xc8c8c8ff, // PROGRESSBAR_INSIDE_COLOR
+ 0xbcecffff, // PROGRESSBAR_PROGRESS_COLOR
+ 2, // PROGRESSBAR_BORDER_WIDTH
+ 0x828282ff, // SPINNER_LABEL_BORDER_COLOR
+ 0xc8c8c8ff, // SPINNER_LABEL_INSIDE_COLOR
+ 0x828282ff, // SPINNER_DEFAULT_BUTTON_BORDER_COLOR
+ 0xc8c8c8ff, // SPINNER_DEFAULT_BUTTON_INSIDE_COLOR
+ 0x000000ff, // SPINNER_DEFAULT_SYMBOL_COLOR
+ 0x000000ff, // SPINNER_DEFAULT_TEXT_COLOR
+ 0xc8c8c8ff, // SPINNER_HOVER_BUTTON_BORDER_COLOR
+ 0xffffffff, // SPINNER_HOVER_BUTTON_INSIDE_COLOR
+ 0x000000ff, // SPINNER_HOVER_SYMBOL_COLOR
+ 0x000000ff, // SPINNER_HOVER_TEXT_COLOR
+ 0x7bb0d6ff, // SPINNER_PRESSED_BUTTON_BORDER_COLOR
+ 0xbcecffff, // SPINNER_PRESSED_BUTTON_INSIDE_COLOR
+ 0x5f9aa7ff, // SPINNER_PRESSED_SYMBOL_COLOR
+ 0x000000ff, // SPINNER_PRESSED_TEXT_COLOR
+ 1, // COMBOBOX_PADDING
+ 30, // COMBOBOX_BUTTON_WIDTH
+ 30, // COMBOBOX_BUTTON_HEIGHT
+ 1, // COMBOBOX_BORDER_WIDTH
+ 0x828282ff, // COMBOBOX_DEFAULT_BORDER_COLOR
+ 0xc8c8c8ff, // COMBOBOX_DEFAULT_INSIDE_COLOR
+ 0x828282ff, // COMBOBOX_DEFAULT_TEXT_COLOR
+ 0x828282ff, // COMBOBOX_DEFAULT_LIST_TEXT_COLOR
+ 0xc8c8c8ff, // COMBOBOX_HOVER_BORDER_COLOR
+ 0xffffffff, // COMBOBOX_HOVER_INSIDE_COLOR
+ 0x828282ff, // COMBOBOX_HOVER_TEXT_COLOR
+ 0x828282ff, // COMBOBOX_HOVER_LIST_TEXT_COLOR
+ 0x7bb0d6ff, // COMBOBOX_PRESSED_BORDER_COLOR
+ 0xbcecffff, // COMBOBOX_PRESSED_INSIDE_COLOR
+ 0x5f9aa7ff, // COMBOBOX_PRESSED_TEXT_COLOR
+ 0x0078acff, // COMBOBOX_PRESSED_LIST_BORDER_COLOR
+ 0x66e7ffff, // COMBOBOX_PRESSED_LIST_INSIDE_COLOR
+ 0x0078acff, // COMBOBOX_PRESSED_LIST_TEXT_COLOR
+ 0x828282ff, // CHECKBOX_DEFAULT_BORDER_COLOR
+ 0xffffffff, // CHECKBOX_DEFAULT_INSIDE_COLOR
+ 0xc8c8c8ff, // CHECKBOX_HOVER_BORDER_COLOR
+ 0xffffffff, // CHECKBOX_HOVER_INSIDE_COLOR
+ 0x66e7ffff, // CHECKBOX_CLICK_BORDER_COLOR
+ 0xddf5ffff, // CHECKBOX_CLICK_INSIDE_COLOR
+ 0x7bb0d6ff, // CHECKBOX_STATUS_ACTIVE_COLOR
+ 4, // CHECKBOX_INSIDE_WIDTH
+ 1, // TEXTBOX_BORDER_WIDTH
+ 0x828282ff, // TEXTBOX_BORDER_COLOR
+ 0xf5f5f5ff, // TEXTBOX_INSIDE_COLOR
+ 0x000000ff, // TEXTBOX_TEXT_COLOR
+ 0x000000ff, // TEXTBOX_LINE_COLOR
+ 10 // TEXTBOX_TEXT_FONTSIZE
+};
+
+//----------------------------------------------------------------------------------
+// Module specific Functions Declaration
+//----------------------------------------------------------------------------------
+static Color ColorMultiply(Color baseColor, float value);
+
+//----------------------------------------------------------------------------------
+// Module Functions Definition
+//----------------------------------------------------------------------------------
+
+// Label element, show text
+void GuiLabel(Rectangle bounds, const char *text)
+{
+ GuiLabelEx(bounds,text, GetColor(style[LABEL_TEXT_COLOR]), BLANK, BLANK);
+}
+
+// Label element extended, configurable colors
+void GuiLabelEx(Rectangle bounds, const char *text, Color textColor, Color border, Color inner)
+{
+ int textWidth = MeasureText(text, style[GLOBAL_TEXT_FONTSIZE]);
+ int textHeight = GetFontBaseSize(GetDefaultFont());
+
+ if (bounds.width < textWidth) bounds.width = textWidth + style[LABEL_TEXT_PADDING];
+ if (bounds.height < textHeight) bounds.height = textHeight + style[LABEL_TEXT_PADDING]/2;
+
+ // Draw control
+ //--------------------------------------------------------------------
+ DrawRectangleRec(bounds, border);
+ DrawRectangle(bounds.x + style[LABEL_BORDER_WIDTH], bounds.y + style[LABEL_BORDER_WIDTH], bounds.width - (2 * style[LABEL_BORDER_WIDTH]), bounds.height - (2 * style[LABEL_BORDER_WIDTH]), inner);
+ DrawText(text, bounds.x + ((bounds.width/2) - (textWidth/2)), bounds.y + ((bounds.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], textColor);
+ //--------------------------------------------------------------------
+}
+
+// Button element, returns true when clicked
+bool GuiButton(Rectangle bounds, const char *text)
+{
+ ButtonState buttonState = BUTTON_DEFAULT;
+
+ Rectangle button = bounds;
+ Vector2 mousePoint = GetMousePosition();
+
+ int textWidth = MeasureText(text, style[GLOBAL_TEXT_FONTSIZE]);
+ int textHeight = GetFontBaseSize(GetDefaultFont());
+
+ if (button.width < textWidth) button.width = textWidth + style[BUTTON_TEXT_PADDING];
+ if (button.height < textHeight) button.height = textHeight + style[BUTTON_TEXT_PADDING]/2;
+
+ if (CheckCollisionPointRec(mousePoint, button))
+ {
+ if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) buttonState = BUTTON_PRESSED;
+ else if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) buttonState = BUTTON_CLICKED;
+ else buttonState = BUTTON_HOVER;
+ }
+
+ // Draw control
+ //--------------------------------------------------------------------
+ switch (buttonState)
+ {
+ case BUTTON_DEFAULT:
+ {
+ DrawRectangleRec(button, GetColor(style[BUTTON_DEFAULT_BORDER_COLOR]));
+ DrawRectangle((int)(button.x + style[BUTTON_BORDER_WIDTH]), (int)(button.y + style[BUTTON_BORDER_WIDTH]) , (int)(button.width - (2 * style[BUTTON_BORDER_WIDTH])), (int)(button.height - (2 * style[BUTTON_BORDER_WIDTH])), GetColor(style[BUTTON_DEFAULT_INSIDE_COLOR]));
+ DrawText(text, button.x + ((button.width/2) - (MeasureText(text, style[GLOBAL_TEXT_FONTSIZE])/2)), button.y + ((button.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[BUTTON_DEFAULT_TEXT_COLOR]));
+ } break;
+ case BUTTON_HOVER:
+ {
+ DrawRectangleRec(button, GetColor(style[BUTTON_HOVER_BORDER_COLOR]));
+ DrawRectangle((int)(button.x + style[BUTTON_BORDER_WIDTH]), (int)(button.y + style[BUTTON_BORDER_WIDTH]) , (int)(button.width - (2 * style[BUTTON_BORDER_WIDTH])), (int)(button.height - (2 * style[BUTTON_BORDER_WIDTH])), GetColor(style[BUTTON_HOVER_INSIDE_COLOR]));
+ DrawText(text, button.x + ((button.width/2) - (MeasureText(text, style[GLOBAL_TEXT_FONTSIZE])/2)), button.y + ((button.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[BUTTON_HOVER_TEXT_COLOR]));
+ } break;
+ case BUTTON_PRESSED:
+ {
+ DrawRectangleRec(button, GetColor(style[BUTTON_PRESSED_BORDER_COLOR]));
+ DrawRectangle((int)(button.x + style[BUTTON_BORDER_WIDTH]), (int)(button.y + style[BUTTON_BORDER_WIDTH]) , (int)(button.width - (2 * style[BUTTON_BORDER_WIDTH])), (int)(button.height - (2 * style[BUTTON_BORDER_WIDTH])), GetColor(style[BUTTON_PRESSED_INSIDE_COLOR]));
+ DrawText(text, button.x + ((button.width/2) - (MeasureText(text, style[GLOBAL_TEXT_FONTSIZE])/2)), button.y + ((button.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[BUTTON_PRESSED_TEXT_COLOR]));
+ } break;
+ case BUTTON_CLICKED:
+ {
+ DrawRectangleRec(button, GetColor(style[BUTTON_PRESSED_BORDER_COLOR]));
+ DrawRectangle((int)(button.x + style[BUTTON_BORDER_WIDTH]), (int)(button.y + style[BUTTON_BORDER_WIDTH]) , (int)(button.width - (2 * style[BUTTON_BORDER_WIDTH])), (int)(button.height - (2 * style[BUTTON_BORDER_WIDTH])), GetColor(style[BUTTON_PRESSED_INSIDE_COLOR]));
+ } break;
+ default: break;
+ }
+ //------------------------------------------------------------------
+
+ if (buttonState == BUTTON_CLICKED) return true;
+ else return false;
+}
+
+// Toggle Button element, returns true when active
+bool GuiToggleButton(Rectangle bounds, const char *text, bool toggle)
+{
+ ToggleState toggleState = TOGGLE_UNACTIVE;
+ Rectangle toggleButton = bounds;
+ Vector2 mousePoint = GetMousePosition();
+
+ int textWidth = MeasureText(text, style[GLOBAL_TEXT_FONTSIZE]);
+ int textHeight = GetFontBaseSize(GetDefaultFont());
+
+ if (toggleButton.width < textWidth) toggleButton.width = textWidth + style[TOGGLE_TEXT_PADDING];
+ if (toggleButton.height < textHeight) toggleButton.height = textHeight + style[TOGGLE_TEXT_PADDING]/2;
+ if (CheckCollisionPointRec(mousePoint, toggleButton))
+ {
+ if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) toggleState = TOGGLE_PRESSED;
+ else if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) toggleState = TOGGLE_ACTIVE;
+ else toggleState = TOGGLE_HOVER;
+ }
+
+ if (toggleState == TOGGLE_ACTIVE && !toggle) toggle = true;
+ if (toggle) toggleState = TOGGLE_ACTIVE;
+
+ // Draw control
+ //--------------------------------------------------------------------
+ switch (toggleState)
+ {
+ case TOGGLE_UNACTIVE:
+ {
+ DrawRectangleRec(toggleButton, GetColor(style[TOGGLE_DEFAULT_BORDER_COLOR]));
+ DrawRectangle((int)(toggleButton.x + style[TOGGLE_BORDER_WIDTH]), (int)(toggleButton.y + style[TOGGLE_BORDER_WIDTH]) , (int)(toggleButton.width - (2 * style[TOGGLE_BORDER_WIDTH])), (int)(toggleButton.height - (2 * style[TOGGLE_BORDER_WIDTH])), GetColor(style[TOGGLE_DEFAULT_INSIDE_COLOR]));
+ DrawText(text, toggleButton.x + ((toggleButton.width/2) - (MeasureText(text, style[GLOBAL_TEXT_FONTSIZE])/2)), toggleButton.y + ((toggleButton.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[TOGGLE_DEFAULT_TEXT_COLOR]));
+ } break;
+ case TOGGLE_HOVER:
+ {
+ DrawRectangleRec(toggleButton, GetColor(style[TOGGLE_HOVER_BORDER_COLOR]));
+ DrawRectangle((int)(toggleButton.x + style[TOGGLE_BORDER_WIDTH]), (int)(toggleButton.y + style[TOGGLE_BORDER_WIDTH]) , (int)(toggleButton.width - (2 * style[TOGGLE_BORDER_WIDTH])), (int)(toggleButton.height - (2 * style[TOGGLE_BORDER_WIDTH])), GetColor(style[TOGGLE_HOVER_INSIDE_COLOR]));
+ DrawText(text, toggleButton.x + ((toggleButton.width/2) - (MeasureText(text, style[GLOBAL_TEXT_FONTSIZE])/2)), toggleButton.y + ((toggleButton.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[TOGGLE_HOVER_TEXT_COLOR]));
+ } break;
+ case TOGGLE_PRESSED:
+ {
+ DrawRectangleRec(toggleButton, GetColor(style[TOGGLE_PRESSED_BORDER_COLOR]));
+ DrawRectangle((int)(toggleButton.x + style[TOGGLE_BORDER_WIDTH]), (int)(toggleButton.y + style[TOGGLE_BORDER_WIDTH]) , (int)(toggleButton.width - (2 * style[TOGGLE_BORDER_WIDTH])), (int)(toggleButton.height - (2 * style[TOGGLE_BORDER_WIDTH])), GetColor(style[TOGGLE_PRESSED_INSIDE_COLOR]));
+ DrawText(text, toggleButton.x + ((toggleButton.width/2) - (MeasureText(text, style[GLOBAL_TEXT_FONTSIZE])/2)), toggleButton.y + ((toggleButton.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[TOGGLE_PRESSED_TEXT_COLOR]));
+ } break;
+ case TOGGLE_ACTIVE:
+ {
+ DrawRectangleRec(toggleButton, GetColor(style[TOGGLE_ACTIVE_BORDER_COLOR]));
+ DrawRectangle((int)(toggleButton.x + style[TOGGLE_BORDER_WIDTH]), (int)(toggleButton.y + style[TOGGLE_BORDER_WIDTH]) , (int)(toggleButton.width - (2 * style[TOGGLE_BORDER_WIDTH])), (int)(toggleButton.height - (2 * style[TOGGLE_BORDER_WIDTH])), GetColor(style[TOGGLE_ACTIVE_INSIDE_COLOR]));
+ DrawText(text, toggleButton.x + ((toggleButton.width/2) - (MeasureText(text, style[GLOBAL_TEXT_FONTSIZE])/2)), toggleButton.y + ((toggleButton.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[TOGGLE_ACTIVE_TEXT_COLOR]));
+ } break;
+ default: break;
+ }
+ //--------------------------------------------------------------------
+
+ return toggle;
+}
+
+// Toggle Group element, returns toggled button index
+int GuiToggleGroup(Rectangle bounds, int toggleNum, char **toggleText, int toggleActive)
+{
+ for (int i = 0; i < toggleNum; i++)
+ {
+ if (i == toggleActive) GuiToggleButton((Rectangle){bounds.x + i*(bounds.width + style[TOGGLEGROUP_PADDING]),bounds.y,bounds.width,bounds.height}, toggleText[i], true);
+ else if (GuiToggleButton((Rectangle){bounds.x + i*(bounds.width + style[TOGGLEGROUP_PADDING]),bounds.y,bounds.width,bounds.height}, toggleText[i], false) == true) toggleActive = i;
+ }
+
+ return toggleActive;
+}
+
+// Combo Box element, returns selected item index
+int GuiComboBox(Rectangle bounds, int comboNum, char **comboText, int comboActive)
+{
+ ComboBoxState comboBoxState = COMBOBOX_UNACTIVE;
+ Rectangle comboBoxButton = bounds;
+ Rectangle click = { bounds.x + bounds.width + style[COMBOBOX_PADDING], bounds.y, style[COMBOBOX_BUTTON_WIDTH], bounds.height };
+ Vector2 mousePoint = GetMousePosition();
+
+ int textHeight = GetFontBaseSize(GetDefaultFont());
+
+ for (int i = 0; i < comboNum; i++)
+ {
+ if (i == comboActive)
+ {
+ int textWidth = MeasureText(comboText[i], style[GLOBAL_TEXT_FONTSIZE]);
+
+ if (comboBoxButton.width < textWidth) comboBoxButton.width = textWidth + style[TOGGLE_TEXT_PADDING];
+ if (comboBoxButton.height < textHeight) comboBoxButton.height = textHeight + style[TOGGLE_TEXT_PADDING]/2;
+
+ if (CheckCollisionPointRec(mousePoint, comboBoxButton) || CheckCollisionPointRec(mousePoint, click))
+ {
+ if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) comboBoxState = COMBOBOX_PRESSED;
+ else if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) comboBoxState = COMBOBOX_ACTIVE;
+ else comboBoxState = COMBOBOX_HOVER;
+ }
+
+ // Draw control
+ //--------------------------------------------------------------------
+ switch (comboBoxState)
+ {
+ case COMBOBOX_UNACTIVE:
+ {
+ DrawRectangleRec(comboBoxButton, GetColor(style[COMBOBOX_DEFAULT_BORDER_COLOR]));
+ DrawRectangle((int)(comboBoxButton.x + style[COMBOBOX_BORDER_WIDTH]), (int)(comboBoxButton.y + style[COMBOBOX_BORDER_WIDTH]), (int)(comboBoxButton.width - (2 * style[COMBOBOX_BORDER_WIDTH])), (int)(comboBoxButton.height - (2*style[COMBOBOX_BORDER_WIDTH])), GetColor(style[COMBOBOX_DEFAULT_INSIDE_COLOR]));
+
+ DrawRectangleRec(click, GetColor(style[COMBOBOX_DEFAULT_BORDER_COLOR]));
+ DrawRectangle((int)(click.x + style[COMBOBOX_BORDER_WIDTH]), (int)(click.y + style[COMBOBOX_BORDER_WIDTH]) , (int)(click.width - (2*style[COMBOBOX_BORDER_WIDTH])), (int)(click.height - (2*style[COMBOBOX_BORDER_WIDTH])), GetColor(style[COMBOBOX_DEFAULT_INSIDE_COLOR]));
+ DrawText(FormatText("%i/%i", comboActive + 1, comboNum), click.x + ((click.width/2) - (MeasureText(FormatText("%i/%i", comboActive + 1, comboNum), style[GLOBAL_TEXT_FONTSIZE])/2)), click.y + ((click.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[COMBOBOX_DEFAULT_LIST_TEXT_COLOR]));
+ DrawText(comboText[i], comboBoxButton.x + ((comboBoxButton.width/2) - (MeasureText(comboText[i], style[GLOBAL_TEXT_FONTSIZE])/2)), comboBoxButton.y + ((comboBoxButton.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[COMBOBOX_DEFAULT_TEXT_COLOR]));
+ } break;
+ case COMBOBOX_HOVER:
+ {
+ DrawRectangleRec(comboBoxButton, GetColor(style[COMBOBOX_HOVER_BORDER_COLOR]));
+ DrawRectangle((int)(comboBoxButton.x + style[COMBOBOX_BORDER_WIDTH]), (int)(comboBoxButton.y + style[COMBOBOX_BORDER_WIDTH]), (int)(comboBoxButton.width - (2 * style[COMBOBOX_BORDER_WIDTH])), (int)(comboBoxButton.height - (2*style[COMBOBOX_BORDER_WIDTH])), GetColor(style[COMBOBOX_HOVER_INSIDE_COLOR]));
+
+ DrawRectangleRec(click, GetColor(style[COMBOBOX_HOVER_BORDER_COLOR]));
+ DrawRectangle((int)(click.x + style[COMBOBOX_BORDER_WIDTH]), (int)(click.y + style[COMBOBOX_BORDER_WIDTH]) , (int)(click.width - (2*style[COMBOBOX_BORDER_WIDTH])), (int)(click.height - (2*style[COMBOBOX_BORDER_WIDTH])), GetColor(style[COMBOBOX_HOVER_INSIDE_COLOR]));
+ DrawText(FormatText("%i/%i", comboActive + 1, comboNum), click.x + ((click.width/2) - (MeasureText(FormatText("%i/%i", comboActive + 1, comboNum), style[GLOBAL_TEXT_FONTSIZE])/2)), click.y + ((click.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[COMBOBOX_HOVER_LIST_TEXT_COLOR]));
+ DrawText(comboText[i], comboBoxButton.x + ((comboBoxButton.width/2) - (MeasureText(comboText[i], style[GLOBAL_TEXT_FONTSIZE])/2)), comboBoxButton.y + ((comboBoxButton.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[COMBOBOX_HOVER_TEXT_COLOR]));
+ } break;
+ case COMBOBOX_PRESSED:
+ {
+ DrawRectangleRec(comboBoxButton, GetColor(style[COMBOBOX_PRESSED_BORDER_COLOR]));
+ DrawRectangle((int)(comboBoxButton.x + style[COMBOBOX_BORDER_WIDTH]), (int)(comboBoxButton.y + style[COMBOBOX_BORDER_WIDTH]), (int)(comboBoxButton.width - (2 * style[COMBOBOX_BORDER_WIDTH])), (int)(comboBoxButton.height - (2*style[COMBOBOX_BORDER_WIDTH])), GetColor(style[COMBOBOX_PRESSED_INSIDE_COLOR]));
+
+ DrawRectangleRec(click, GetColor(style[COMBOBOX_PRESSED_LIST_BORDER_COLOR]));
+ DrawRectangle((int)(click.x + style[COMBOBOX_BORDER_WIDTH]), (int)(click.y + style[COMBOBOX_BORDER_WIDTH]) , (int)(click.width - (2*style[COMBOBOX_BORDER_WIDTH])), (int)(click.height - (2*style[COMBOBOX_BORDER_WIDTH])), GetColor(style[COMBOBOX_PRESSED_LIST_INSIDE_COLOR]));
+ DrawText(FormatText("%i/%i", comboActive + 1, comboNum), click.x + ((click.width/2) - (MeasureText(FormatText("%i/%i", comboActive + 1, comboNum), style[GLOBAL_TEXT_FONTSIZE])/2)), click.y + ((click.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[COMBOBOX_PRESSED_LIST_TEXT_COLOR]));
+ DrawText(comboText[i], comboBoxButton.x + ((comboBoxButton.width/2) - (MeasureText(comboText[i], style[GLOBAL_TEXT_FONTSIZE])/2)), comboBoxButton.y + ((comboBoxButton.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[COMBOBOX_PRESSED_TEXT_COLOR]));
+ } break;
+ case COMBOBOX_ACTIVE:
+ {
+ DrawRectangleRec(comboBoxButton, GetColor(style[COMBOBOX_PRESSED_BORDER_COLOR]));
+ DrawRectangle((int)(comboBoxButton.x + style[COMBOBOX_BORDER_WIDTH]), (int)(comboBoxButton.y + style[COMBOBOX_BORDER_WIDTH]), (int)(comboBoxButton.width - (2 * style[COMBOBOX_BORDER_WIDTH])), (int)(comboBoxButton.height - (2*style[COMBOBOX_BORDER_WIDTH])), GetColor(style[COMBOBOX_PRESSED_INSIDE_COLOR]));
+
+ DrawRectangleRec(click, GetColor(style[COMBOBOX_PRESSED_LIST_BORDER_COLOR]));
+ DrawRectangle((int)(click.x + style[COMBOBOX_BORDER_WIDTH]), (int)(click.y + style[COMBOBOX_BORDER_WIDTH]) , (int)(click.width - (2*style[COMBOBOX_BORDER_WIDTH])), (int)(click.height - (2*style[COMBOBOX_BORDER_WIDTH])), GetColor(style[COMBOBOX_PRESSED_LIST_INSIDE_COLOR]));
+ DrawText(FormatText("%i/%i", comboActive + 1, comboNum), click.x + ((click.width/2) - (MeasureText(FormatText("%i/%i", comboActive + 1, comboNum), style[GLOBAL_TEXT_FONTSIZE])/2)), click.y + ((click.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[COMBOBOX_PRESSED_LIST_TEXT_COLOR]));
+ DrawText(comboText[i], comboBoxButton.x + ((comboBoxButton.width/2) - (MeasureText(comboText[i], style[GLOBAL_TEXT_FONTSIZE])/2)), comboBoxButton.y + ((comboBoxButton.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[COMBOBOX_PRESSED_TEXT_COLOR]));
+ } break;
+ default: break;
+ }
+
+ //DrawText(comboText[i], comboBoxButton.x + ((comboBoxButton.width/2) - (MeasureText(comboText[i], style[]globalTextFontSize)/2)), comboBoxButton.y + ((comboBoxButton.height/2) - (style[]globalTextFontSize/2)), style[]globalTextFontSize, COMBOBOX_PRESSED_TEXT_COLOR);
+ //--------------------------------------------------------------------
+ }
+ }
+
+ if (CheckCollisionPointRec(GetMousePosition(), bounds) || CheckCollisionPointRec(GetMousePosition(), click))
+ {
+ if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
+ {
+ comboActive += 1;
+ if(comboActive >= comboNum) comboActive = 0;
+ }
+ }
+
+ return comboActive;
+}
+
+// Check Box element, returns true when active
+bool GuiCheckBox(Rectangle checkBoxBounds, const char *text, bool checked)
+{
+ CheckBoxState checkBoxState = CHECKBOX_STATUS;
+ Rectangle checkBoxRec = checkBoxBounds;
+ Vector2 mousePoint = GetMousePosition();
+
+ if (CheckCollisionPointRec(mousePoint, checkBoxRec))
+ {
+ if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) checkBoxState = CHECKBOX_PRESSED;
+ else if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON))
+ {
+ checkBoxState = CHECKBOX_STATUS;
+ checked = !checked;
+ }
+ else checkBoxState = CHECKBOX_HOVER;
+ }
+
+ // Draw control
+ //--------------------------------------------------------------------
+ switch (checkBoxState)
+ {
+ case CHECKBOX_HOVER:
+ {
+ DrawRectangleRec(checkBoxRec, GetColor(style[CHECKBOX_HOVER_BORDER_COLOR]));
+ DrawRectangle((int)(checkBoxRec.x + style[TOGGLE_BORDER_WIDTH]), (int)(checkBoxRec.y + style[TOGGLE_BORDER_WIDTH]), (int)(checkBoxRec.width - (2*style[TOGGLE_BORDER_WIDTH])), (int)(checkBoxRec.height - (2*style[TOGGLE_BORDER_WIDTH])), GetColor(style[CHECKBOX_HOVER_INSIDE_COLOR]));
+ } break;
+ case CHECKBOX_STATUS:
+ {
+ DrawRectangleRec(checkBoxRec, GetColor(style[CHECKBOX_DEFAULT_BORDER_COLOR]));
+ DrawRectangle((int)(checkBoxRec.x + style[TOGGLE_BORDER_WIDTH]), (int)(checkBoxRec.y + style[TOGGLE_BORDER_WIDTH]), (int)(checkBoxRec.width - (2*style[TOGGLE_BORDER_WIDTH])), (int)(checkBoxRec.height - (2*style[TOGGLE_BORDER_WIDTH])), GetColor(style[CHECKBOX_DEFAULT_INSIDE_COLOR]));
+ } break;
+ case CHECKBOX_PRESSED:
+ {
+ DrawRectangleRec(checkBoxRec, GetColor(style[CHECKBOX_CLICK_BORDER_COLOR]));
+ DrawRectangle((int)(checkBoxRec.x + style[TOGGLE_BORDER_WIDTH]), (int)(checkBoxRec.y + style[TOGGLE_BORDER_WIDTH]), (int)(checkBoxRec.width - (2*style[TOGGLE_BORDER_WIDTH])), (int)(checkBoxRec.height - (2*style[TOGGLE_BORDER_WIDTH])), GetColor(style[CHECKBOX_CLICK_INSIDE_COLOR]));
+ } break;
+ default: break;
+ }
+
+ if (checked)
+ {
+ DrawRectangle((int)(checkBoxRec.x + style[CHECKBOX_INSIDE_WIDTH]), (int)(checkBoxRec.y + style[CHECKBOX_INSIDE_WIDTH]), (int)(checkBoxRec.width - (2*style[CHECKBOX_INSIDE_WIDTH])), (int)(checkBoxRec.height - (2*style[CHECKBOX_INSIDE_WIDTH])), GetColor(style[CHECKBOX_STATUS_ACTIVE_COLOR]));
+ }
+ //--------------------------------------------------------------------
+
+ return checked;
+}
+
+// Slider element, returns selected value
+float GuiSlider(Rectangle bounds, float value, float minValue, float maxValue)
+{
+ SliderState sliderState = SLIDER_DEFAULT;
+ float buttonTravelDistance = 0;
+ float sliderPos = 0;
+ Vector2 mousePoint = GetMousePosition();
+
+ if (value < minValue) value = minValue;
+ else if (value >= maxValue) value = maxValue;
+
+ sliderPos = (value - minValue)/(maxValue - minValue);
+
+ Rectangle sliderButton;
+ sliderButton.width = ((int)(bounds.width - (2 * style[SLIDER_BUTTON_BORDER_WIDTH]))/10 - 8);
+ sliderButton.height =((int)(bounds.height - ( 2 * style[SLIDER_BORDER_WIDTH] + 2 * style[SLIDER_BUTTON_BORDER_WIDTH])));
+
+ float sliderButtonMinPos = bounds.x + style[SLIDER_BORDER_WIDTH] + style[SLIDER_BUTTON_BORDER_WIDTH];
+ float sliderButtonMaxPos = bounds.x + bounds.width - (style[SLIDER_BORDER_WIDTH] + style[SLIDER_BUTTON_BORDER_WIDTH] + sliderButton.width);
+
+ buttonTravelDistance = sliderButtonMaxPos - sliderButtonMinPos;
+
+ sliderButton.x = ((int)(bounds.x + style[SLIDER_BORDER_WIDTH] + style[SLIDER_BUTTON_BORDER_WIDTH]) + (sliderPos * buttonTravelDistance));
+ sliderButton.y = ((int)(bounds.y + style[SLIDER_BORDER_WIDTH] + style[SLIDER_BUTTON_BORDER_WIDTH]));
+
+ if (CheckCollisionPointRec(mousePoint, bounds))
+ {
+ sliderState = SLIDER_HOVER;
+
+ if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) sliderState = SLIDER_ACTIVE;
+
+ if ((sliderState == SLIDER_ACTIVE) && (IsMouseButtonDown(MOUSE_LEFT_BUTTON)))
+ {
+ sliderButton.x = mousePoint.x - sliderButton.width / 2;
+
+ if (sliderButton.x <= sliderButtonMinPos) sliderButton.x = sliderButtonMinPos;
+ else if (sliderButton.x >= sliderButtonMaxPos) sliderButton.x = sliderButtonMaxPos;
+
+ sliderPos = (sliderButton.x - sliderButtonMinPos) / buttonTravelDistance;
+ }
+ }
+ else sliderState = SLIDER_DEFAULT;
+
+ // Draw control
+ //--------------------------------------------------------------------
+ DrawRectangleRec(bounds, GetColor(style[SLIDER_BORDER_COLOR]));
+ DrawRectangle((int)(bounds.x + style[SLIDER_BORDER_WIDTH]), (int)(bounds.y + style[SLIDER_BORDER_WIDTH]), (int)(bounds.width - (2*style[SLIDER_BORDER_WIDTH])), (int)(bounds.height - (2*style[SLIDER_BORDER_WIDTH])), GetColor(style[SLIDER_INSIDE_COLOR]));
+
+ switch (sliderState)
+ {
+ case SLIDER_DEFAULT: DrawRectangleRec(sliderButton, GetColor(style[SLIDER_DEFAULT_COLOR])); break;
+ case SLIDER_HOVER: DrawRectangleRec(sliderButton, GetColor(style[SLIDER_HOVER_COLOR])); break;
+ case SLIDER_ACTIVE: DrawRectangleRec(sliderButton, GetColor(style[SLIDER_ACTIVE_COLOR])); break;
+ default: break;
+ }
+ //--------------------------------------------------------------------
+
+ return minValue + (maxValue - minValue)*sliderPos;
+}
+
+// Slider Bar element, returns selected value
+float GuiSliderBar(Rectangle bounds, float value, float minValue, float maxValue)
+{
+ SliderState sliderState = SLIDER_DEFAULT;
+ Vector2 mousePoint = GetMousePosition();
+ float fixedValue;
+ float fixedMinValue;
+
+ fixedValue = value - minValue;
+ maxValue = maxValue - minValue;
+ fixedMinValue = 0;
+
+ if (fixedValue <= fixedMinValue) fixedValue = fixedMinValue;
+ else if (fixedValue >= maxValue) fixedValue = maxValue;
+
+ Rectangle sliderBar;
+
+ sliderBar.x = bounds.x + style[SLIDER_BORDER_WIDTH];
+ sliderBar.y = bounds.y + style[SLIDER_BORDER_WIDTH];
+ sliderBar.width = ((fixedValue*((float)bounds.width - 2*style[SLIDER_BORDER_WIDTH]))/(maxValue - fixedMinValue));
+ sliderBar.height = bounds.height - 2*style[SLIDER_BORDER_WIDTH];
+
+ if (CheckCollisionPointRec(mousePoint, bounds))
+ {
+ sliderState = SLIDER_HOVER;
+
+ if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
+ {
+ sliderState = SLIDER_ACTIVE;
+
+ sliderBar.width = (mousePoint.x - bounds.x - style[SLIDER_BORDER_WIDTH]);
+
+ if (mousePoint.x <= (bounds.x + style[SLIDER_BORDER_WIDTH])) sliderBar.width = 0;
+ else if (mousePoint.x >= (bounds.x + bounds.width - style[SLIDER_BORDER_WIDTH])) sliderBar.width = bounds.width - 2*style[SLIDER_BORDER_WIDTH];
+ }
+ }
+ else sliderState = SLIDER_DEFAULT;
+
+ fixedValue = ((float)sliderBar.width*(maxValue - fixedMinValue))/((float)bounds.width - 2*style[SLIDER_BORDER_WIDTH]);
+
+ // Draw control
+ //--------------------------------------------------------------------
+ DrawRectangleRec(bounds, GetColor(style[SLIDERBAR_BORDER_COLOR]));
+ DrawRectangle((int)(bounds.x + style[SLIDER_BORDER_WIDTH]), (int)(bounds.y + style[SLIDER_BORDER_WIDTH]) , (int)(bounds.width - (2*style[SLIDER_BORDER_WIDTH])), (int)(bounds.height - (2*style[SLIDER_BORDER_WIDTH])), GetColor(style[SLIDERBAR_INSIDE_COLOR]));
+
+ switch (sliderState)
+ {
+ case SLIDER_DEFAULT: DrawRectangleRec(sliderBar, GetColor(style[SLIDERBAR_DEFAULT_COLOR])); break;
+ case SLIDER_HOVER: DrawRectangleRec(sliderBar, GetColor(style[SLIDERBAR_HOVER_COLOR])); break;
+ case SLIDER_ACTIVE: DrawRectangleRec(sliderBar, GetColor(style[SLIDERBAR_ACTIVE_COLOR])); break;
+ default: break;
+ }
+
+ if (minValue < 0 && maxValue > 0) DrawRectangle((bounds.x + style[SLIDER_BORDER_WIDTH]) - (minValue * ((bounds.width - (style[SLIDER_BORDER_WIDTH]*2))/maxValue)), sliderBar.y, 1, sliderBar.height, GetColor(style[SLIDERBAR_ZERO_LINE_COLOR]));
+ //--------------------------------------------------------------------
+
+ return fixedValue + minValue;
+}
+
+// Progress Bar element, shows current progress value
+void GuiProgressBar(Rectangle bounds, float value)
+{
+ if (value > 1.0f) value = 1.0f;
+ else if (value < 0.0f) value = 0.0f;
+
+ Rectangle progressBar = { bounds.x + style[PROGRESSBAR_BORDER_WIDTH], bounds.y + style[PROGRESSBAR_BORDER_WIDTH], bounds.width - (style[PROGRESSBAR_BORDER_WIDTH] * 2), bounds.height - (style[PROGRESSBAR_BORDER_WIDTH] * 2)};
+ Rectangle progressValue = { bounds.x + style[PROGRESSBAR_BORDER_WIDTH], bounds.y + style[PROGRESSBAR_BORDER_WIDTH], value * (bounds.width - (style[PROGRESSBAR_BORDER_WIDTH] * 2)), bounds.height - (style[PROGRESSBAR_BORDER_WIDTH] * 2)};
+
+ // Draw control
+ //--------------------------------------------------------------------
+ DrawRectangleRec(bounds, GetColor(style[PROGRESSBAR_BORDER_COLOR]));
+ DrawRectangleRec(progressBar, GetColor(style[PROGRESSBAR_INSIDE_COLOR]));
+ DrawRectangleRec(progressValue, GetColor(style[PROGRESSBAR_PROGRESS_COLOR]));
+ //--------------------------------------------------------------------
+}
+
+// Spinner element, returns selected value
+// NOTE: Requires static variables: framesCounter, valueSpeed - ERROR!
+int GuiSpinner(Rectangle bounds, int value, int minValue, int maxValue)
+{
+ SpinnerState spinnerState = SPINNER_DEFAULT;
+ Rectangle labelBoxBound = { bounds.x + bounds.width/4 + 1, bounds.y, bounds.width/2, bounds.height };
+ Rectangle leftButtonBound = { bounds.x, bounds.y, bounds.width/4, bounds.height };
+ Rectangle rightButtonBound = { bounds.x + bounds.width - bounds.width/4 + 1, bounds.y, bounds.width/4, bounds.height };
+ Vector2 mousePoint = GetMousePosition();
+
+ int textHeight = GetFontBaseSize(GetDefaultFont());
+
+ int textWidth = MeasureText(FormatText("%i", value), style[GLOBAL_TEXT_FONTSIZE]);
+
+ int buttonSide = 0;
+
+ static int framesCounter = 0;
+ static bool valueSpeed = false;;
+
+ //if (comboBoxButton.width < textWidth) comboBoxButton.width = textWidth + style[TOGGLE_TEXT_PADDING];
+ //if (comboBoxButton.height < textHeight) comboBoxButton.height = textHeight + style[TOGGLE_TEXT_PADDING]/2;
+
+ if (CheckCollisionPointRec(mousePoint, leftButtonBound) || CheckCollisionPointRec(mousePoint, rightButtonBound) || CheckCollisionPointRec(mousePoint, labelBoxBound))
+ {
+ if (IsKeyDown(KEY_LEFT))
+ {
+ spinnerState = SPINNER_PRESSED;
+ buttonSide = 1;
+
+ if (value > minValue) value -= 1;
+ }
+ else if (IsKeyDown(KEY_RIGHT))
+ {
+ spinnerState = SPINNER_PRESSED;
+ buttonSide = 2;
+
+ if (value < maxValue) value += 1;
+ }
+ }
+
+ if (CheckCollisionPointRec(mousePoint, leftButtonBound))
+ {
+ buttonSide = 1;
+ spinnerState = SPINNER_HOVER;
+
+ if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
+ {
+ if (!valueSpeed)
+ {
+ if (value > minValue) value--;
+ valueSpeed = true;
+ }
+ else framesCounter++;
+
+ spinnerState = SPINNER_PRESSED;
+
+ if (value > minValue)
+ {
+ if (framesCounter >= 30) value -= 1;
+ }
+ }
+ }
+ else if (CheckCollisionPointRec(mousePoint, rightButtonBound))
+ {
+ buttonSide = 2;
+ spinnerState = SPINNER_HOVER;
+
+ if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
+ {
+ if (!valueSpeed)
+ {
+ if (value < maxValue) value++;
+ valueSpeed = true;
+ }
+ else framesCounter++;
+
+ spinnerState = SPINNER_PRESSED;
+
+ if (value < maxValue)
+ {
+ if (framesCounter >= 30) value += 1;
+ }
+ }
+ }
+ else if (!CheckCollisionPointRec(mousePoint, labelBoxBound)) buttonSide = 0;
+
+ if(IsMouseButtonUp(MOUSE_LEFT_BUTTON))
+ {
+ valueSpeed = false;
+ framesCounter = 0;
+ }
+
+ // Draw control
+ //--------------------------------------------------------------------
+ switch (spinnerState)
+ {
+ case SPINNER_DEFAULT:
+ {
+ DrawRectangleRec(leftButtonBound, GetColor(style[SPINNER_DEFAULT_BUTTON_BORDER_COLOR]));
+ DrawRectangle(leftButtonBound.x + 2, leftButtonBound.y + 2, leftButtonBound.width - 4, leftButtonBound.height - 4, GetColor(style[SPINNER_DEFAULT_BUTTON_INSIDE_COLOR]));
+
+ DrawRectangleRec(rightButtonBound, GetColor(style[SPINNER_DEFAULT_BUTTON_BORDER_COLOR]));
+ DrawRectangle(rightButtonBound.x + 2, rightButtonBound.y + 2, rightButtonBound.width - 4, rightButtonBound.height - 4, GetColor(style[SPINNER_DEFAULT_BUTTON_INSIDE_COLOR]));
+
+ DrawText(FormatText("-"), leftButtonBound.x + (leftButtonBound.width/2 - (MeasureText(FormatText("+"), style[GLOBAL_TEXT_FONTSIZE]))/2), leftButtonBound.y + (leftButtonBound.height/2 - textHeight/2), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_DEFAULT_SYMBOL_COLOR]));
+ DrawText(FormatText("+"), rightButtonBound.x + (rightButtonBound.width/2 - (MeasureText(FormatText("-"), style[GLOBAL_TEXT_FONTSIZE]))/2), rightButtonBound.y + (rightButtonBound.height/2 - textHeight/2), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_DEFAULT_SYMBOL_COLOR]));
+
+ DrawRectangleRec(labelBoxBound, GetColor(style[SPINNER_LABEL_BORDER_COLOR]));
+ DrawRectangle(labelBoxBound.x + 1, labelBoxBound.y + 1, labelBoxBound.width - 2, labelBoxBound.height - 2, GetColor(style[SPINNER_LABEL_INSIDE_COLOR]));
+
+ DrawText(FormatText("%i", value), labelBoxBound.x + (labelBoxBound.width/2 - textWidth/2), labelBoxBound.y + (labelBoxBound.height/2 - textHeight/2), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_DEFAULT_TEXT_COLOR]));
+ } break;
+ case SPINNER_HOVER:
+ {
+ if (buttonSide == 1)
+ {
+ DrawRectangleRec(leftButtonBound, GetColor(style[SPINNER_HOVER_BUTTON_BORDER_COLOR]));
+ DrawRectangle(leftButtonBound.x + 2, leftButtonBound.y + 2, leftButtonBound.width - 4, leftButtonBound.height - 4, GetColor(style[SPINNER_HOVER_BUTTON_INSIDE_COLOR]));
+
+ DrawRectangleRec(rightButtonBound, GetColor(style[SPINNER_DEFAULT_BUTTON_BORDER_COLOR]));
+ DrawRectangle(rightButtonBound.x + 2, rightButtonBound.y + 2, rightButtonBound.width - 4, rightButtonBound.height - 4, GetColor(style[SPINNER_DEFAULT_BUTTON_INSIDE_COLOR]));
+
+ DrawText(FormatText("-"), leftButtonBound.x + (leftButtonBound.width/2 - (MeasureText(FormatText("+"), style[GLOBAL_TEXT_FONTSIZE]))/2), leftButtonBound.y + (leftButtonBound.height/2 - textHeight/2), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_HOVER_SYMBOL_COLOR]));
+ DrawText(FormatText("+"), rightButtonBound.x + (rightButtonBound.width/2 - (MeasureText(FormatText("-"), style[GLOBAL_TEXT_FONTSIZE]))/2), rightButtonBound.y + (rightButtonBound.height/2 - textHeight/2), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_DEFAULT_SYMBOL_COLOR]));
+ }
+ else if (buttonSide == 2)
+ {
+ DrawRectangleRec(leftButtonBound, GetColor(style[SPINNER_DEFAULT_BUTTON_BORDER_COLOR]));
+ DrawRectangle(leftButtonBound.x + 2, leftButtonBound.y + 2, leftButtonBound.width - 4, leftButtonBound.height - 4, GetColor(style[SPINNER_DEFAULT_BUTTON_INSIDE_COLOR]));
+
+ DrawRectangleRec(rightButtonBound, GetColor(style[SPINNER_HOVER_BUTTON_BORDER_COLOR]));
+ DrawRectangle(rightButtonBound.x + 2, rightButtonBound.y + 2, rightButtonBound.width - 4, rightButtonBound.height - 4, GetColor(style[SPINNER_HOVER_BUTTON_INSIDE_COLOR]));
+
+ DrawText(FormatText("-"), leftButtonBound.x + (leftButtonBound.width/2 - (MeasureText(FormatText("+"), style[GLOBAL_TEXT_FONTSIZE]))/2), leftButtonBound.y + (leftButtonBound.height/2 - textHeight/2), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_DEFAULT_SYMBOL_COLOR]));
+ DrawText(FormatText("+"), rightButtonBound.x + (rightButtonBound.width/2 - (MeasureText(FormatText("-"), style[GLOBAL_TEXT_FONTSIZE]))/2), rightButtonBound.y + (rightButtonBound.height/2 - textHeight/2), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_HOVER_SYMBOL_COLOR]));
+ }
+
+ DrawRectangleRec(labelBoxBound, GetColor(style[SPINNER_LABEL_BORDER_COLOR]));
+ DrawRectangle(labelBoxBound.x + 1, labelBoxBound.y + 1, labelBoxBound.width - 2, labelBoxBound.height - 2, GetColor(style[SPINNER_LABEL_INSIDE_COLOR]));
+
+ DrawText(FormatText("%i", value), labelBoxBound.x + (labelBoxBound.width/2 - textWidth/2), labelBoxBound.y + (labelBoxBound.height/2 - textHeight/2), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_HOVER_TEXT_COLOR]));
+ } break;
+ case SPINNER_PRESSED:
+ {
+ if (buttonSide == 1)
+ {
+ DrawRectangleRec(leftButtonBound, GetColor(style[SPINNER_PRESSED_BUTTON_BORDER_COLOR]));
+ DrawRectangle(leftButtonBound.x + 2, leftButtonBound.y + 2, leftButtonBound.width - 4, leftButtonBound.height - 4, GetColor(style[SPINNER_PRESSED_BUTTON_INSIDE_COLOR]));
+
+ DrawRectangleRec(rightButtonBound, GetColor(style[SPINNER_DEFAULT_BUTTON_BORDER_COLOR]));
+ DrawRectangle(rightButtonBound.x + 2, rightButtonBound.y + 2, rightButtonBound.width - 4, rightButtonBound.height - 4, GetColor(style[SPINNER_DEFAULT_BUTTON_INSIDE_COLOR]));
+
+ DrawText(FormatText("-"), leftButtonBound.x + (leftButtonBound.width/2 - (MeasureText(FormatText("+"), style[GLOBAL_TEXT_FONTSIZE]))/2), leftButtonBound.y + (leftButtonBound.height/2 - textHeight/2), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_PRESSED_SYMBOL_COLOR]));
+ DrawText(FormatText("+"), rightButtonBound.x + (rightButtonBound.width/2 - (MeasureText(FormatText("-"), style[GLOBAL_TEXT_FONTSIZE]))/2), rightButtonBound.y + (rightButtonBound.height/2 - textHeight/2), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_DEFAULT_SYMBOL_COLOR]));
+ }
+ else if (buttonSide == 2)
+ {
+ DrawRectangleRec(leftButtonBound, GetColor(style[SPINNER_DEFAULT_BUTTON_BORDER_COLOR]));
+ DrawRectangle(leftButtonBound.x + 2, leftButtonBound.y + 2, leftButtonBound.width - 4, leftButtonBound.height - 4, GetColor(style[SPINNER_DEFAULT_BUTTON_INSIDE_COLOR]));
+
+ DrawRectangleRec(rightButtonBound, GetColor(style[SPINNER_PRESSED_BUTTON_BORDER_COLOR]));
+ DrawRectangle(rightButtonBound.x + 2, rightButtonBound.y + 2, rightButtonBound.width - 4, rightButtonBound.height - 4, GetColor(style[SPINNER_PRESSED_BUTTON_INSIDE_COLOR]));
+
+ DrawText(FormatText("-"), leftButtonBound.x + (leftButtonBound.width/2 - (MeasureText(FormatText("+"), style[GLOBAL_TEXT_FONTSIZE]))/2), leftButtonBound.y + (leftButtonBound.height/2 - textHeight/2), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_DEFAULT_SYMBOL_COLOR]));
+ DrawText(FormatText("+"), rightButtonBound.x + (rightButtonBound.width/2 - (MeasureText(FormatText("-"), style[GLOBAL_TEXT_FONTSIZE]))/2), rightButtonBound.y + (rightButtonBound.height/2 - textHeight/2), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_PRESSED_SYMBOL_COLOR]));
+ }
+ DrawRectangleRec(labelBoxBound, GetColor(style[SPINNER_LABEL_BORDER_COLOR]));
+ DrawRectangle(labelBoxBound.x + 1, labelBoxBound.y + 1, labelBoxBound.width - 2, labelBoxBound.height - 2, GetColor(style[SPINNER_LABEL_INSIDE_COLOR]));
+
+ DrawText(FormatText("%i", value), labelBoxBound.x + (labelBoxBound.width/2 - textWidth/2), labelBoxBound.y + (labelBoxBound.height/2 - textHeight/2), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_PRESSED_TEXT_COLOR]));
+ } break;
+ default: break;
+ }
+ return value;
+}
+
+// Text Box element, returns input text
+// NOTE: Requires static variables: framesCounter, maxChars - ERROR!
+char *GuiTextBox(Rectangle bounds, char *text)
+{
+ static int maxChars = 20;
+ int initPos = bounds.x + 4;
+ char letter = -1;
+ static int framesCounter = 0;
+
+ framesCounter++;
+
+ letter = GetKeyPressed();
+
+ if (letter != -1)
+ {
+ if (letter == 3)
+ {
+ for (int i = 0; i < maxChars; i++)
+ {
+ if ((text[i] == '\0') && (i > 0))
+ {
+ text[i - 1] = '\0';
+ break;
+ }
+ }
+
+ text[19] = '\0';
+ }
+ else
+ {
+ for (int i = 0; i < maxChars; i++)
+ {
+ if (text[i] == '\0')
+ {
+ text[i] = letter;
+ break;
+ }
+ }
+ }
+ }
+
+ // Draw control
+ //--------------------------------------------------------------------
+ DrawRectangleRec(bounds, GetColor(style[TEXTBOX_BORDER_COLOR]));
+ DrawRectangle(bounds.x + style[TEXTBOX_BORDER_WIDTH], bounds.y + style[TEXTBOX_BORDER_WIDTH], bounds.width - (style[TEXTBOX_BORDER_WIDTH] * 2), bounds.height - (style[TEXTBOX_BORDER_WIDTH] * 2), GetColor(style[TEXTBOX_INSIDE_COLOR]));
+
+ for (int i = 0; i < maxChars; i++)
+ {
+ if (text[i] == '\0') break;
+
+ DrawText(FormatText("%c", text[i]), initPos, bounds.y + 10, style[TEXTBOX_TEXT_FONTSIZE], GetColor(style[TEXTBOX_TEXT_COLOR]));
+ initPos += ((GetDefaultFont().charSet[(int)text[i] - 32].w + 2));
+ }
+
+ if ((framesCounter/20)%2) DrawLine(initPos + 2, bounds.y + 10, initPos + 2, bounds.y + 10 + 10, GetColor(style[TEXTBOX_LINE_COLOR]));
+ //--------------------------------------------------------------------
+
+ return text;
+}
+
+// TODO: GuiBox?
+// TODO: GuiWindow?
+// TODO: GuiPanel?
+
+// Save current GUI style into a text file
+void SaveGuiStyle(const char *fileName)
+{
+ FILE *styleFile = fopen(fileName, "wt");
+
+ for (int i = 0; i < NUM_PROPERTIES; i++) fprintf(styleFile, "%-40s0x%x\n", guiPropertyName[i], GetStyleProperty(i));
+
+ fclose(styleFile);
+}
+
+// Load GUI style from a text file
+void LoadGuiStyle(const char *fileName)
+{
+ typedef struct {
+ char id[64];
+ int value;
+ } StyleProperty;
+
+ StyleProperty *styleProp = (StyleProperty *)malloc(128*sizeof(StyleProperty));;
+ int counter = 0;
+
+ FILE *styleFile = fopen(fileName, "rt");
+
+ while (!feof(styleFile))
+ {
+ fscanf(styleFile, "%s %i\n", styleProp[counter].id, &styleProp[counter].value);
+ counter++;
+ }
+
+ fclose(styleFile);
+
+ for (int i = 0; i < counter; i++)
+ {
+ for (int j = 0; j < NUM_PROPERTIES; j++)
+ {
+ if (strcmp(styleProp[i].id, guiPropertyName[j]) == 0)
+ {
+ // Assign correct property to style
+ style[j] = styleProp[i].value;
+ }
+ }
+ }
+
+ free(styleProp);
+}
+
+// Set one style property value
+void SetStyleProperty(int guiProperty, int value)
+{
+ #define NUM_COLOR_SAMPLES 10
+
+ if (guiProperty == GLOBAL_BASE_COLOR)
+ {
+ Color baseColor = GetColor(value);
+ Color fadeColor[NUM_COLOR_SAMPLES];
+
+ for (int i = 0; i < NUM_COLOR_SAMPLES; i++) fadeColor[i] = ColorMultiply(baseColor, 1.0f - (float)i/(NUM_COLOR_SAMPLES - 1));
+
+ style[GLOBAL_BASE_COLOR] = value;
+ style[BACKGROUND_COLOR] = GetHexValue(fadeColor[3]);
+ style[BUTTON_DEFAULT_INSIDE_COLOR] = GetHexValue(fadeColor[4]);
+ style[BUTTON_HOVER_INSIDE_COLOR] = GetHexValue(fadeColor[4]);
+ style[BUTTON_PRESSED_INSIDE_COLOR] = GetHexValue(fadeColor[5]);
+ style[TOGGLE_DEFAULT_INSIDE_COLOR] = GetHexValue(fadeColor[4]);
+ style[TOGGLE_HOVER_INSIDE_COLOR] = GetHexValue(fadeColor[4]);
+ style[TOGGLE_PRESSED_INSIDE_COLOR] = GetHexValue(fadeColor[5]);
+ style[TOGGLE_ACTIVE_INSIDE_COLOR] = GetHexValue(fadeColor[8]);
+ style[SLIDER_INSIDE_COLOR] = GetHexValue(fadeColor[4]);
+ style[SLIDER_DEFAULT_COLOR] = GetHexValue(fadeColor[6]);
+ style[SLIDER_HOVER_COLOR] = GetHexValue(fadeColor[7]);
+ style[SLIDER_ACTIVE_COLOR] = GetHexValue(fadeColor[9]);
+ style[SLIDERBAR_INSIDE_COLOR] = GetHexValue(fadeColor[4]);
+ style[SLIDERBAR_DEFAULT_COLOR] = GetHexValue(fadeColor[6]);
+ style[SLIDERBAR_HOVER_COLOR] = GetHexValue(fadeColor[7]);
+ style[SLIDERBAR_ACTIVE_COLOR] = GetHexValue(fadeColor[9]);
+ style[SLIDERBAR_ZERO_LINE_COLOR] = GetHexValue(fadeColor[8]);
+ style[PROGRESSBAR_INSIDE_COLOR] = GetHexValue(fadeColor[4]);
+ style[PROGRESSBAR_PROGRESS_COLOR] = GetHexValue(fadeColor[6]);
+ style[SPINNER_LABEL_INSIDE_COLOR] = GetHexValue(fadeColor[4]);
+ style[SPINNER_DEFAULT_BUTTON_INSIDE_COLOR] = GetHexValue(fadeColor[4]);
+ style[SPINNER_HOVER_BUTTON_INSIDE_COLOR] = GetHexValue(fadeColor[4]);
+ style[SPINNER_PRESSED_BUTTON_INSIDE_COLOR] = GetHexValue(fadeColor[5]);
+ style[COMBOBOX_DEFAULT_INSIDE_COLOR] = GetHexValue(fadeColor[4]);
+ style[COMBOBOX_HOVER_INSIDE_COLOR] = GetHexValue(fadeColor[4]);
+ style[COMBOBOX_PRESSED_INSIDE_COLOR] = GetHexValue(fadeColor[8]);
+ style[COMBOBOX_PRESSED_LIST_INSIDE_COLOR] = GetHexValue(fadeColor[8]);
+ style[CHECKBOX_DEFAULT_INSIDE_COLOR] = GetHexValue(fadeColor[4]);
+ style[CHECKBOX_CLICK_INSIDE_COLOR] = GetHexValue(fadeColor[6]);
+ style[CHECKBOX_STATUS_ACTIVE_COLOR] = GetHexValue(fadeColor[8]);
+ style[TEXTBOX_INSIDE_COLOR] = GetHexValue(fadeColor[4]);
+ }
+ else if (guiProperty == GLOBAL_BORDER_COLOR)
+ {
+ Color baseColor = GetColor(value);
+ Color fadeColor[NUM_COLOR_SAMPLES];
+
+ for (int i = 0; i < NUM_COLOR_SAMPLES; i++) fadeColor[i] = ColorMultiply(baseColor, 1.0f - (float)i/(NUM_COLOR_SAMPLES - 1));
+
+ style[GLOBAL_BORDER_COLOR] = value;
+ style[BUTTON_DEFAULT_BORDER_COLOR] = GetHexValue(fadeColor[7]);
+ style[BUTTON_HOVER_BORDER_COLOR] = GetHexValue(fadeColor[8]);
+ style[BUTTON_PRESSED_BORDER_COLOR] = GetHexValue(fadeColor[9]);
+ style[TOGGLE_DEFAULT_BORDER_COLOR] = GetHexValue(fadeColor[7]);
+ style[TOGGLE_HOVER_BORDER_COLOR] = GetHexValue(fadeColor[8]);
+ style[TOGGLE_PRESSED_BORDER_COLOR] = GetHexValue(fadeColor[9]);
+ style[TOGGLE_ACTIVE_BORDER_COLOR] = GetHexValue(fadeColor[9]);
+ style[SLIDER_BORDER_COLOR] = GetHexValue(fadeColor[7]);
+ style[SLIDERBAR_BORDER_COLOR] = GetHexValue(fadeColor[7]);
+ style[PROGRESSBAR_BORDER_COLOR] = GetHexValue(fadeColor[7]);
+ style[SPINNER_LABEL_BORDER_COLOR] = GetHexValue(fadeColor[7]);
+ style[SPINNER_DEFAULT_BUTTON_BORDER_COLOR] = GetHexValue(fadeColor[7]);
+ style[SPINNER_HOVER_BUTTON_BORDER_COLOR] = GetHexValue(fadeColor[8]);
+ style[SPINNER_PRESSED_BUTTON_BORDER_COLOR] = GetHexValue(fadeColor[9]);
+ style[COMBOBOX_DEFAULT_BORDER_COLOR] = GetHexValue(fadeColor[7]);
+ style[COMBOBOX_HOVER_BORDER_COLOR] = GetHexValue(fadeColor[8]);
+ style[COMBOBOX_PRESSED_BORDER_COLOR] = GetHexValue(fadeColor[9]);
+ style[COMBOBOX_PRESSED_LIST_BORDER_COLOR] = GetHexValue(fadeColor[9]);
+ style[CHECKBOX_DEFAULT_BORDER_COLOR] = GetHexValue(fadeColor[7]);
+ style[CHECKBOX_HOVER_BORDER_COLOR] = GetHexValue(fadeColor[8]);
+ style[CHECKBOX_CLICK_BORDER_COLOR] = GetHexValue(fadeColor[9]);
+ style[TEXTBOX_BORDER_COLOR] = GetHexValue(fadeColor[7]);
+ }
+ else if (guiProperty == GLOBAL_TEXT_COLOR)
+ {
+ Color baseColor = GetColor(value);
+ Color fadeColor[NUM_COLOR_SAMPLES];
+
+ for (int i = 0; i < NUM_COLOR_SAMPLES; i++) fadeColor[i] = ColorMultiply(baseColor, 1.0f - (float)i/(NUM_COLOR_SAMPLES - 1));
+
+ style[GLOBAL_TEXT_COLOR] = value;
+ style[LABEL_TEXT_COLOR] = GetHexValue(fadeColor[9]);
+ style[BUTTON_DEFAULT_TEXT_COLOR] = GetHexValue(fadeColor[9]);
+ style[BUTTON_HOVER_TEXT_COLOR] = GetHexValue(fadeColor[8]);
+ style[BUTTON_PRESSED_TEXT_COLOR] = GetHexValue(fadeColor[5]);
+ style[TOGGLE_DEFAULT_TEXT_COLOR] = GetHexValue(fadeColor[9]);
+ style[TOGGLE_HOVER_TEXT_COLOR] = GetHexValue(fadeColor[8]);
+ style[TOGGLE_PRESSED_TEXT_COLOR] = GetHexValue(fadeColor[5]);
+ style[TOGGLE_ACTIVE_TEXT_COLOR] = GetHexValue(fadeColor[5]);
+ style[SPINNER_DEFAULT_SYMBOL_COLOR] = GetHexValue(fadeColor[9]);
+ style[SPINNER_DEFAULT_TEXT_COLOR] = GetHexValue(fadeColor[9]);
+ style[SPINNER_HOVER_SYMBOL_COLOR] = GetHexValue(fadeColor[8]);
+ style[SPINNER_HOVER_TEXT_COLOR] = GetHexValue(fadeColor[8]);
+ style[SPINNER_PRESSED_SYMBOL_COLOR] = GetHexValue(fadeColor[5]);
+ style[SPINNER_PRESSED_TEXT_COLOR] = GetHexValue(fadeColor[5]);
+ style[COMBOBOX_DEFAULT_TEXT_COLOR] = GetHexValue(fadeColor[9]);
+ style[COMBOBOX_DEFAULT_LIST_TEXT_COLOR] = GetHexValue(fadeColor[9]);
+ style[COMBOBOX_HOVER_TEXT_COLOR] = GetHexValue(fadeColor[8]);
+ style[COMBOBOX_HOVER_LIST_TEXT_COLOR] = GetHexValue(fadeColor[8]);
+ style[COMBOBOX_PRESSED_TEXT_COLOR] = GetHexValue(fadeColor[4]);
+ style[COMBOBOX_PRESSED_LIST_TEXT_COLOR] = GetHexValue(fadeColor[4]);
+ style[TEXTBOX_TEXT_COLOR] = GetHexValue(fadeColor[9]);
+ style[TEXTBOX_LINE_COLOR] = GetHexValue(fadeColor[6]);
+ }
+ else style[guiProperty] = value;
+
+}
+
+// Get one style property value
+int GetStyleProperty(int guiProperty) { return style[guiProperty]; }
+
+//----------------------------------------------------------------------------------
+// Module specific Functions Definition
+//----------------------------------------------------------------------------------
+
+static Color ColorMultiply(Color baseColor, float value)
+{
+ Color multColor = baseColor;
+
+ if (value > 1.0f) value = 1.0f;
+ else if (value < 0.0f) value = 0.0f;
+
+ multColor.r += (255 - multColor.r)*value;
+ multColor.g += (255 - multColor.g)*value;
+ multColor.b += (255 - multColor.b)*value;
+
+ return multColor;
+} \ No newline at end of file
diff --git a/src/raygui.h b/src/raygui.h
new file mode 100644
index 00000000..6906eca7
--- /dev/null
+++ b/src/raygui.h
@@ -0,0 +1,271 @@
+/*******************************************************************************************
+*
+* raygui - raylib IMGUI system (Immedite Mode GUI)
+*
+* Copyright (c) 2015 Kevin Gato, Daniel Nicolás, Sergio Martinez and Ramon Santamaria
+*
+* This software is provided "as-is", without any express or implied warranty. In no event
+* will the authors be held liable for any damages arising from the use of this software.
+*
+* Permission is granted to anyone to use this software for any purpose, including commercial
+* applications, and to alter it and redistribute it freely, subject to the following restrictions:
+*
+* 1. The origin of this software must not be misrepresented; you must not claim that you
+* wrote the original software. If you use this software in a product, an acknowledgment
+* in the product documentation would be appreciated but is not required.
+*
+* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
+* as being the original software.
+*
+* 3. This notice may not be removed or altered from any source distribution.
+*
+**********************************************************************************************/
+#ifndef RAYGUI_H
+#define RAYGUI_H
+
+#include "raylib.h"
+
+//----------------------------------------------------------------------------------
+// Defines and Macros
+//----------------------------------------------------------------------------------
+#define NUM_PROPERTIES 98
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+//----------------------------------------------------------------------------------
+typedef enum GuiProperty {
+ GLOBAL_BASE_COLOR = 0,
+ GLOBAL_BORDER_COLOR,
+ GLOBAL_TEXT_COLOR,
+ GLOBAL_TEXT_FONTSIZE,
+ GLOBAL_BORDER_WIDTH,
+ BACKGROUND_COLOR,
+ LABEL_BORDER_WIDTH,
+ LABEL_TEXT_COLOR,
+ LABEL_TEXT_PADDING,
+ BUTTON_BORDER_WIDTH,
+ BUTTON_TEXT_PADDING,
+ BUTTON_DEFAULT_BORDER_COLOR,
+ BUTTON_DEFAULT_INSIDE_COLOR,
+ BUTTON_DEFAULT_TEXT_COLOR,
+ BUTTON_HOVER_BORDER_COLOR,
+ BUTTON_HOVER_INSIDE_COLOR,
+ BUTTON_HOVER_TEXT_COLOR,
+ BUTTON_PRESSED_BORDER_COLOR,
+ BUTTON_PRESSED_INSIDE_COLOR,
+ BUTTON_PRESSED_TEXT_COLOR,
+ TOGGLE_TEXT_PADDING,
+ TOGGLE_BORDER_WIDTH,
+ TOGGLE_DEFAULT_BORDER_COLOR,
+ TOGGLE_DEFAULT_INSIDE_COLOR,
+ TOGGLE_DEFAULT_TEXT_COLOR,
+ TOGGLE_HOVER_BORDER_COLOR,
+ TOGGLE_HOVER_INSIDE_COLOR,
+ TOGGLE_HOVER_TEXT_COLOR,
+ TOGGLE_PRESSED_BORDER_COLOR,
+ TOGGLE_PRESSED_INSIDE_COLOR,
+ TOGGLE_PRESSED_TEXT_COLOR,
+ TOGGLE_ACTIVE_BORDER_COLOR,
+ TOGGLE_ACTIVE_INSIDE_COLOR,
+ TOGGLE_ACTIVE_TEXT_COLOR,
+ TOGGLEGROUP_PADDING,
+ SLIDER_BORDER_WIDTH,
+ SLIDER_BUTTON_BORDER_WIDTH,
+ SLIDER_BORDER_COLOR,
+ SLIDER_INSIDE_COLOR,
+ SLIDER_DEFAULT_COLOR,
+ SLIDER_HOVER_COLOR,
+ SLIDER_ACTIVE_COLOR,
+ SLIDERBAR_BORDER_COLOR,
+ SLIDERBAR_INSIDE_COLOR,
+ SLIDERBAR_DEFAULT_COLOR,
+ SLIDERBAR_HOVER_COLOR,
+ SLIDERBAR_ACTIVE_COLOR,
+ SLIDERBAR_ZERO_LINE_COLOR,
+ PROGRESSBAR_BORDER_COLOR,
+ PROGRESSBAR_INSIDE_COLOR,
+ PROGRESSBAR_PROGRESS_COLOR,
+ PROGRESSBAR_BORDER_WIDTH,
+ SPINNER_LABEL_BORDER_COLOR,
+ SPINNER_LABEL_INSIDE_COLOR,
+ SPINNER_DEFAULT_BUTTON_BORDER_COLOR,
+ SPINNER_DEFAULT_BUTTON_INSIDE_COLOR,
+ SPINNER_DEFAULT_SYMBOL_COLOR,
+ SPINNER_DEFAULT_TEXT_COLOR,
+ SPINNER_HOVER_BUTTON_BORDER_COLOR,
+ SPINNER_HOVER_BUTTON_INSIDE_COLOR,
+ SPINNER_HOVER_SYMBOL_COLOR,
+ SPINNER_HOVER_TEXT_COLOR,
+ SPINNER_PRESSED_BUTTON_BORDER_COLOR,
+ SPINNER_PRESSED_BUTTON_INSIDE_COLOR,
+ SPINNER_PRESSED_SYMBOL_COLOR,
+ SPINNER_PRESSED_TEXT_COLOR,
+ COMBOBOX_PADDING,
+ COMBOBOX_BUTTON_WIDTH,
+ COMBOBOX_BUTTON_HEIGHT,
+ COMBOBOX_BORDER_WIDTH,
+ COMBOBOX_DEFAULT_BORDER_COLOR,
+ COMBOBOX_DEFAULT_INSIDE_COLOR,
+ COMBOBOX_DEFAULT_TEXT_COLOR,
+ COMBOBOX_DEFAULT_LIST_TEXT_COLOR,
+ COMBOBOX_HOVER_BORDER_COLOR,
+ COMBOBOX_HOVER_INSIDE_COLOR,
+ COMBOBOX_HOVER_TEXT_COLOR,
+ COMBOBOX_HOVER_LIST_TEXT_COLOR,
+ COMBOBOX_PRESSED_BORDER_COLOR,
+ COMBOBOX_PRESSED_INSIDE_COLOR,
+ COMBOBOX_PRESSED_TEXT_COLOR,
+ COMBOBOX_PRESSED_LIST_BORDER_COLOR,
+ COMBOBOX_PRESSED_LIST_INSIDE_COLOR,
+ COMBOBOX_PRESSED_LIST_TEXT_COLOR,
+ CHECKBOX_DEFAULT_BORDER_COLOR,
+ CHECKBOX_DEFAULT_INSIDE_COLOR,
+ CHECKBOX_HOVER_BORDER_COLOR,
+ CHECKBOX_HOVER_INSIDE_COLOR,
+ CHECKBOX_CLICK_BORDER_COLOR,
+ CHECKBOX_CLICK_INSIDE_COLOR,
+ CHECKBOX_STATUS_ACTIVE_COLOR,
+ CHECKBOX_INSIDE_WIDTH,
+ TEXTBOX_BORDER_WIDTH,
+ TEXTBOX_BORDER_COLOR,
+ TEXTBOX_INSIDE_COLOR,
+ TEXTBOX_TEXT_COLOR,
+ TEXTBOX_LINE_COLOR,
+ TEXTBOX_TEXT_FONTSIZE
+} GuiProperty;
+
+#ifdef __cplusplus
+extern "C" { // Prevents name mangling of functions
+#endif
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition
+//----------------------------------------------------------------------------------
+static const char *guiPropertyName[] = {
+ "GLOBAL_BASE_COLOR",
+ "GLOBAL_BORDER_COLOR",
+ "GLOBAL_TEXT_COLOR",
+ "GLOBAL_TEXT_FONTSIZE",
+ "GLOBAL_BORDER_WIDTH",
+ "BACKGROUND_COLOR",
+ "LABEL_BORDER_WIDTH",
+ "LABEL_TEXT_COLOR",
+ "LABEL_TEXT_PADDING",
+ "BUTTON_BORDER_WIDTH",
+ "BUTTON_TEXT_PADDING",
+ "BUTTON_DEFAULT_BORDER_COLOR",
+ "BUTTON_DEFAULT_INSIDE_COLOR",
+ "BUTTON_DEFAULT_TEXT_COLOR",
+ "BUTTON_HOVER_BORDER_COLOR",
+ "BUTTON_HOVER_INSIDE_COLOR",
+ "BUTTON_HOVER_TEXT_COLOR",
+ "BUTTON_PRESSED_BORDER_COLOR",
+ "BUTTON_PRESSED_INSIDE_COLOR",
+ "BUTTON_PRESSED_TEXT_COLOR",
+ "TOGGLE_TEXT_PADDING",
+ "TOGGLE_BORDER_WIDTH",
+ "TOGGLE_DEFAULT_BORDER_COLOR",
+ "TOGGLE_DEFAULT_INSIDE_COLOR",
+ "TOGGLE_DEFAULT_TEXT_COLOR",
+ "TOGGLE_HOVER_BORDER_COLOR",
+ "TOGGLE_HOVER_INSIDE_COLOR",
+ "TOGGLE_HOVER_TEXT_COLOR",
+ "TOGGLE_PRESSED_BORDER_COLOR",
+ "TOGGLE_PRESSED_INSIDE_COLOR",
+ "TOGGLE_PRESSED_TEXT_COLOR",
+ "TOGGLE_ACTIVE_BORDER_COLOR",
+ "TOGGLE_ACTIVE_INSIDE_COLOR",
+ "TOGGLE_ACTIVE_TEXT_COLOR",
+ "TOGGLEGROUP_PADDING",
+ "SLIDER_BORDER_WIDTH",
+ "SLIDER_BUTTON_BORDER_WIDTH",
+ "SLIDER_BORDER_COLOR",
+ "SLIDER_INSIDE_COLOR",
+ "SLIDER_DEFAULT_COLOR",
+ "SLIDER_HOVER_COLOR",
+ "SLIDER_ACTIVE_COLOR",
+ "SLIDERBAR_BORDER_COLOR",
+ "SLIDERBAR_INSIDE_COLOR",
+ "SLIDERBAR_DEFAULT_COLOR",
+ "SLIDERBAR_HOVER_COLOR",
+ "SLIDERBAR_ACTIVE_COLOR",
+ "SLIDERBAR_ZERO_LINE_COLOR",
+ "PROGRESSBAR_BORDER_COLOR",
+ "PROGRESSBAR_INSIDE_COLOR",
+ "PROGRESSBAR_PROGRESS_COLOR",
+ "PROGRESSBAR_BORDER_WIDTH",
+ "SPINNER_LABEL_BORDER_COLOR",
+ "SPINNER_LABEL_INSIDE_COLOR",
+ "SPINNER_DEFAULT_BUTTON_BORDER_COLOR",
+ "SPINNER_DEFAULT_BUTTON_INSIDE_COLOR",
+ "SPINNER_DEFAULT_SYMBOL_COLOR",
+ "SPINNER_DEFAULT_TEXT_COLOR",
+ "SPINNER_HOVER_BUTTON_BORDER_COLOR",
+ "SPINNER_HOVER_BUTTON_INSIDE_COLOR",
+ "SPINNER_HOVER_SYMBOL_COLOR",
+ "SPINNER_HOVER_TEXT_COLOR",
+ "SPINNER_PRESSED_BUTTON_BORDER_COLOR",
+ "SPINNER_PRESSED_BUTTON_INSIDE_COLOR",
+ "SPINNER_PRESSED_SYMBOL_COLOR",
+ "SPINNER_PRESSED_TEXT_COLOR",
+ "COMBOBOX_PADDING",
+ "COMBOBOX_BUTTON_WIDTH",
+ "COMBOBOX_BUTTON_HEIGHT",
+ "COMBOBOX_BORDER_WIDTH",
+ "COMBOBOX_DEFAULT_BORDER_COLOR",
+ "COMBOBOX_DEFAULT_INSIDE_COLOR",
+ "COMBOBOX_DEFAULT_TEXT_COLOR",
+ "COMBOBOX_DEFAULT_LIST_TEXT_COLOR",
+ "COMBOBOX_HOVER_BORDER_COLOR",
+ "COMBOBOX_HOVER_INSIDE_COLOR",
+ "COMBOBOX_HOVER_TEXT_COLOR",
+ "COMBOBOX_HOVER_LIST_TEXT_COLOR",
+ "COMBOBOX_PRESSED_BORDER_COLOR",
+ "COMBOBOX_PRESSED_INSIDE_COLOR",
+ "COMBOBOX_PRESSED_TEXT_COLOR",
+ "COMBOBOX_PRESSED_LIST_BORDER_COLOR",
+ "COMBOBOX_PRESSED_LIST_INSIDE_COLOR",
+ "COMBOBOX_PRESSED_LIST_TEXT_COLOR",
+ "CHECKBOX_DEFAULT_BORDER_COLOR",
+ "CHECKBOX_DEFAULT_INSIDE_COLOR",
+ "CHECKBOX_HOVER_BORDER_COLOR",
+ "CHECKBOX_HOVER_INSIDE_COLOR",
+ "CHECKBOX_CLICK_BORDER_COLOR",
+ "CHECKBOX_CLICK_INSIDE_COLOR",
+ "CHECKBOX_STATUS_ACTIVE_COLOR",
+ "CHECKBOX_INSIDE_WIDTH",
+ "TEXTBOX_BORDER_WIDTH",
+ "TEXTBOX_BORDER_COLOR",
+ "TEXTBOX_INSIDE_COLOR",
+ "TEXTBOX_TEXT_COLOR",
+ "TEXTBOX_LINE_COLOR",
+ "TEXTBOX_TEXT_FONTSIZE"
+};
+
+//----------------------------------------------------------------------------------
+// Module Functions Declaration
+//----------------------------------------------------------------------------------
+void GuiLabel(Rectangle bounds, const char *text); // Label element, show text
+void GuiLabelEx(Rectangle bounds, const char *text, Color textColor, Color border, Color inner); // Label element extended, configurable colors
+bool GuiButton(Rectangle bounds, const char *text); // Button element, returns true when clicked
+bool GuiToggleButton(Rectangle bounds, const char *text, bool toggle); // Toggle Button element, returns true when active
+int GuiToggleGroup(Rectangle bounds, int toggleNum, char **toggleText, int toggleActive); // Toggle Group element, returns toggled button index
+int GuiComboBox(Rectangle bounds, int comboNum, char **comboText, int comboActive); // Combo Box element, returns selected item index
+bool GuiCheckBox(Rectangle bounds, const char *text, bool checked); // Check Box element, returns true when active
+float GuiSlider(Rectangle bounds, float value, float minValue, float maxValue); // Slider element, returns selected value
+float GuiSliderBar(Rectangle bounds, float value, float minValue, float maxValue); // Slider Bar element, returns selected value
+void GuiProgressBar(Rectangle bounds, float value); // Progress Bar element, shows current progress value
+int GuiSpinner(Rectangle bounds, int value, int minValue, int maxValue); // Spinner element, returns selected value
+char *GuiTextBox(Rectangle bounds, char *text); // Text Box element, returns input text
+
+void SaveGuiStyle(const char *fileName); // Save GUI style file
+void LoadGuiStyle(const char *fileName); // Load GUI style file
+
+void SetStyleProperty(int guiProperty, int value); // Set one style property
+int GetStyleProperty(int guiProperty); // Get one style property
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // RAYGUI_H
diff --git a/src/raylib.h b/src/raylib.h
index f5220e2e..bf5fe99f 100644
--- a/src/raylib.h
+++ b/src/raylib.h
@@ -241,20 +241,13 @@ typedef struct Texture2D {
int format; // Data format (TextureFormat)
} Texture2D;
-// Character type (one font glyph)
-typedef struct Character {
- int value; //char value = ' '; (int)value = 32;
- int x;
- int y;
- int w;
- int h;
-} Character;
-
// SpriteFont type, includes texture and charSet array data
typedef struct SpriteFont {
- Texture2D texture;
- int numChars;
- Character *charSet;
+ Texture2D texture; // Font texture
+ int size; // Base size (default chars height)
+ int numChars; // Number of characters
+ int *charValues; // Characters values array
+ Rectangle *charRecs; // Characters rectangles within the texture
} SpriteFont;
// Camera type, defines a camera position/orientation in 3d space
@@ -276,7 +269,7 @@ typedef struct VertexData {
unsigned int vboId[4];
} VertexData;
-// Shader type
+// Shader type (generic shader)
typedef struct Shader {
unsigned int id; // Shader program id
@@ -411,6 +404,8 @@ void EndDrawing(void); // End canvas drawin
void Begin3dMode(Camera cam); // Initializes 3D mode for drawing (Camera setup)
void End3dMode(void); // Ends 3D mode and returns to default 2D orthographic mode
+Ray GetMouseRay(Vector2 mousePosition, Camera camera); // TODO: Returns a ray trace from mouse position
+
void SetTargetFPS(int fps); // Set target FPS (maximum)
float GetFPS(void); // Returns current FPS
float GetFrameTime(void); // Returns time in seconds for one frame
@@ -421,38 +416,13 @@ int GetHexValue(Color color); // Returns hexadecim
int GetRandomValue(int min, int max); // Returns a random value between min and max (both included)
Color Fade(Color color, float alpha); // Color fade-in or fade-out, alpha goes from 0.0f to 1.0f
-void SetConfigFlags(char flags); // Enable some window configurations
+void SetConfigFlags(char flags); // Setup some window configuration flags
void ShowLogo(void); // Activates raylib logo at startup (can be done with flags)
bool IsFileDropped(void); // Check if a file have been dropped into window
char **GetDroppedFiles(int *count); // Retrieve dropped files into window
void ClearDroppedFiles(void); // Clear dropped files paths buffer
-Ray GetMouseRay(Vector2 mousePosition, Camera camera); // TODO: Gives the ray trace from mouse position
-
-//------------------------------------------------------------------------------------
-// Shaders System Functions (Module: rlgl)
-// NOTE: This functions are useless when using OpenGL 1.1
-//------------------------------------------------------------------------------------
-Shader LoadShader(char *vsFileName, char *fsFileName); // Load a custom shader and bind default locations
-unsigned int LoadShaderProgram(char *vShaderStr, char *fShaderStr); // Load a custom shader and return program id
-void UnloadShader(Shader shader); // Unload a custom shader from memory
-void SetPostproShader(Shader shader); // Set fullscreen postproduction shader
-void SetCustomShader(Shader shader); // Set custom shader to be used in batch draw
-void SetDefaultShader(void); // Set default shader to be used in batch draw
-void SetModelShader(Model *model, Shader shader); // Link a shader to a model
-bool IsPosproShaderEnabled(void); // Check if postprocessing shader is enabled
-
-int GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location
-void SetShaderValue(Shader shader, int uniformLoc, float *value, int size); // Set shader uniform value (float)
-void SetShaderValuei(Shader shader, int uniformLoc, int *value, int size); // Set shader uniform value (int)
-void SetShaderMapDiffuse(Shader *shader, Texture2D texture); // Default diffuse shader map texture assignment
-void SetShaderMapNormal(Shader *shader, const char *uniformName, Texture2D texture); // Normal map texture shader assignment
-void SetShaderMapSpecular(Shader *shader, const char *uniformName, Texture2D texture); // Specular map texture shader assignment
-void SetShaderMap(Shader *shader, int mapLocation, Texture2D texture, int textureUnit); // TODO: Generic shader map assignment
-
-void SetBlendMode(int mode); // Set blending mode (alpha, additive, multiplied)
-
//------------------------------------------------------------------------------------
// Input Handling Functions (Module: core)
//------------------------------------------------------------------------------------
@@ -517,18 +487,20 @@ float GetGesturePinchAngle(void); // Get gesture pinch ang
// Camera System Functions (Module: camera)
//------------------------------------------------------------------------------------
void SetCameraMode(int mode); // Set camera mode (multiple camera modes available)
-Camera UpdateCamera(Vector3 *playerPosition); // Update camera and player position (1st person and 3rd person cameras)
+void UpdateCamera(Camera *camera); // Update camera (player position is ignored)
+void UpdateCameraPlayer(Camera *camera, Vector3 *position); // Update camera and player position (1st person and 3rd person cameras)
-void SetCameraMoveControls(int frontKey, int backKey,
- int leftKey, int rightKey,
- int upKey, int downKey); // Set camera move controls (1st person and 3rd person cameras)
+void SetCameraPosition(Vector3 position); // Set internal camera position
+void SetCameraTarget(Vector3 target); // Set internal camera target
void SetCameraPanControl(int panKey); // Set camera pan key to combine with mouse movement (free camera)
void SetCameraAltControl(int altKey); // Set camera alt key to combine with mouse movement (free camera)
void SetCameraSmoothZoomControl(int szKey); // Set camera smooth zoom key to combine with mouse (free camera)
+void SetCameraMoveControls(int frontKey, int backKey,
+ int leftKey, int rightKey,
+ int upKey, int downKey); // Set camera move controls (1st person and 3rd person cameras)
void SetCameraMouseSensitivity(float sensitivity); // Set camera mouse sensitivity (1st person and 3rd person cameras)
-void SetCameraTarget(Vector3 target); // Set internal camera target
//------------------------------------------------------------------------------------
// Basic Shapes Drawing Functions (Module: shapes)
@@ -570,7 +542,7 @@ Image LoadImageFromRES(const char *rresName, int resId);
Texture2D LoadTexture(const char *fileName); // Load an image as texture into GPU memory
Texture2D LoadTextureEx(void *data, int width, int height, int textureFormat, int mipmapCount); // Load a texture from raw data into GPU memory
Texture2D LoadTextureFromRES(const char *rresName, int resId); // Load an image as texture from rRES file (raylib Resource)
-Texture2D LoadTextureFromImage(Image image); // Load a texture from image data (and generate mipmaps)
+Texture2D LoadTextureFromImage(Image image); // Load a texture from image data
void UnloadImage(Image image); // Unload image from CPU memory (RAM)
void UnloadTexture(Texture2D texture); // Unload texture from GPU memory
Color *GetImageData(Image image); // Get pixel data from image as a Color struct array
@@ -598,7 +570,7 @@ void DrawTextEx(SpriteFont spriteFont, const char* text, Vector2 position,
int fontSize, int spacing, Color tint);
int MeasureText(const char *text, int fontSize); // Measure string width for default font
Vector2 MeasureTextEx(SpriteFont spriteFont, const char *text, int fontSize, int spacing); // Measure string size for SpriteFont
-int GetFontBaseSize(SpriteFont spriteFont); // Returns the base size for a SpriteFont (chars height)
+
void DrawFPS(int posX, int posY); // Shows current FPS on top-left corner
const char *FormatText(const char *text, ...); // Formatting of text with variables to 'embed'
@@ -645,6 +617,29 @@ bool CheckCollisionBoxSphere(Vector3 minBBox, Vector3 maxBBox, Vector3 centerSph
Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *playerPosition, float radius); // Return the normal vector of the impacted surface
//------------------------------------------------------------------------------------
+// Shaders System Functions (Module: rlgl)
+// NOTE: This functions are useless when using OpenGL 1.1
+//------------------------------------------------------------------------------------
+Shader LoadShader(char *vsFileName, char *fsFileName); // Load a custom shader and bind default locations
+unsigned int LoadShaderProgram(char *vShaderStr, char *fShaderStr); // Load custom shaders strings and return program id
+void UnloadShader(Shader shader); // Unload a custom shader from memory
+void SetPostproShader(Shader shader); // Set fullscreen postproduction shader
+void SetCustomShader(Shader shader); // Set custom shader to be used in batch draw
+void SetDefaultShader(void); // Set default shader to be used in batch draw
+void SetModelShader(Model *model, Shader shader); // Link a shader to a model
+bool IsPosproShaderEnabled(void); // Check if postprocessing shader is enabled
+
+int GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location
+void SetShaderValue(Shader shader, int uniformLoc, float *value, int size); // Set shader uniform value (float)
+void SetShaderValuei(Shader shader, int uniformLoc, int *value, int size); // Set shader uniform value (int)
+void SetShaderMapDiffuse(Shader *shader, Texture2D texture); // Default diffuse shader map texture assignment
+void SetShaderMapNormal(Shader *shader, const char *uniformName, Texture2D texture); // Normal map texture shader assignment
+void SetShaderMapSpecular(Shader *shader, const char *uniformName, Texture2D texture); // Specular map texture shader assignment
+void SetShaderMap(Shader *shader, int mapLocation, Texture2D texture, int textureUnit); // TODO: Generic shader map assignment
+
+void SetBlendMode(int mode); // Set blending mode (alpha, additive, multiplied)
+
+//------------------------------------------------------------------------------------
// Audio Loading and Playing Functions (Module: audio)
//------------------------------------------------------------------------------------
void InitAudioDevice(void); // Initialize audio device and context
diff --git a/src/rlgl.c b/src/rlgl.c
index 163fa35a..8806b429 100644
--- a/src/rlgl.c
+++ b/src/rlgl.c
@@ -4,8 +4,8 @@
*
* raylib now uses OpenGL 1.1 style functions (rlVertex) that are mapped to selected OpenGL version:
* OpenGL 1.1 - Direct map rl* -> gl*
-* OpenGL 3.3+ - Vertex data is stored in VAOs, call rlglDraw() to render
-* OpenGL ES 2 - Same behaviour as OpenGL 3.3+
+* OpenGL 3.3 - Vertex data is stored in VAOs, call rlglDraw() to render
+* OpenGL ES 2 - Vertex data is stored in VBOs or VAOs (when available), call rlglDraw() to render
*
* Copyright (c) 2014 Ramon Santamaria (@raysan5)
*
@@ -858,7 +858,7 @@ void rlglInit(void)
// NOTE: We don't need that much data on screen... right now...
#if defined(GRAPHICS_API_OPENGL_11)
- TraceLog(INFO, "OpenGL 1.1 profile initialized");
+ //TraceLog(INFO, "OpenGL 1.1 (or driver default) profile initialized");
#endif
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
@@ -1938,15 +1938,17 @@ Model rlglLoadModel(VertexData mesh)
}
// Read screen pixel data (color buffer)
+// ISSUE: Non pre-multiplied alpha when reading from backbuffer!
+// TODO: Multiply alpha
unsigned char *rlglReadScreenPixels(int width, int height)
{
- unsigned char *screenData = (unsigned char *)malloc(width * height * sizeof(unsigned char) * 4);
+ unsigned char *screenData = (unsigned char *)malloc(width*height*sizeof(unsigned char)*4);
// NOTE: glReadPixels returns image flipped vertically -> (0,0) is the bottom left corner of the framebuffer
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, screenData);
// Flip image vertically!
- unsigned char *imgData = (unsigned char *)malloc(width * height * sizeof(unsigned char) * 4);
+ unsigned char *imgData = (unsigned char *)malloc(width*height*sizeof(unsigned char)*4);
for (int y = height-1; y >= 0; y--)
{
@@ -2075,7 +2077,7 @@ Shader LoadShader(char *vsFileName, char *fsFileName)
return shader;
}
-// Load a custom shader and return program id
+// Load custom shader strings and return program id
unsigned int LoadShaderProgram(char *vShaderStr, char *fShaderStr)
{
unsigned int program = 0;
@@ -3059,8 +3061,6 @@ static pixel *GenNextMipmap(pixel *srcData, int srcWidth, int srcHeight)
#if defined(RLGL_STANDALONE)
-typedef enum { INFO = 0, ERROR, WARNING, DEBUG, OTHER } TraceLogType;
-
// Output a trace log message
// NOTE: Expected msgType: (0)Info, (1)Error, (2)Warning
static void TraceLog(int msgType, const char *text, ...)
diff --git a/src/rlgl.h b/src/rlgl.h
index af312596..172b4868 100644
--- a/src/rlgl.h
+++ b/src/rlgl.h
@@ -4,7 +4,7 @@
*
* raylib now uses OpenGL 1.1 style functions (rlVertex) that are mapped to selected OpenGL version:
* OpenGL 1.1 - Direct map rl* -> gl*
-* OpenGL 3.3+ - Vertex data is stored in VAOs, call rlglDraw() to render
+* OpenGL 3.3 - Vertex data is stored in VAOs, call rlglDraw() to render
* OpenGL ES 2 - Vertex data is stored in VBOs or VAOs (when available), call rlglDraw() to render
*
* Copyright (c) 2014 Ramon Santamaria (@raysan5)
@@ -270,7 +270,7 @@ void PrintModelviewMatrix(void); // DEBUG: Print modelview matrix
// NOTE: This functions are useless when using OpenGL 1.1
//------------------------------------------------------------------------------------
Shader LoadShader(char *vsFileName, char *fsFileName); // Load a custom shader and bind default locations
-unsigned int LoadShaderProgram(char *vShaderStr, char *fShaderStr); // Load a custom shader and return program id
+unsigned int LoadShaderProgram(char *vShaderStr, char *fShaderStr); // Load custom shader strings and return program id
void UnloadShader(Shader shader); // Unload a custom shader from memory
void SetPostproShader(Shader shader); // Set fullscreen postproduction shader
void SetCustomShader(Shader shader); // Set custom shader to be used in batch draw
diff --git a/src/text.c b/src/text.c
index 65d52f26..3364a9bf 100644
--- a/src/text.c
+++ b/src/text.c
@@ -67,7 +67,7 @@ static SpriteFont defaultFont; // Default font provided by raylib
// Module specific Functions Declaration
//----------------------------------------------------------------------------------
static bool PixelIsMagenta(Color p); // Check if a pixel is magenta
-static int ParseImageData(Color *imgDataPixel, int imgWidth, int imgHeight, Character **charSet); // Parse image pixel data to obtain character set measures
+static int ParseImageData(Image image, int **charValues, Rectangle **charSet); // Parse image pixel data to obtain characters data
static SpriteFont LoadRBMF(const char *fileName); // Load a rBMF font file (raylib BitMap Font)
static SpriteFont LoadTTF(const char *fileName, int fontSize); // Generate a sprite font image from TTF data (font size required)
@@ -181,21 +181,23 @@ extern void LoadDefaultFont(void)
// Reconstruct charSet using charsWidth[], charsHeight, charsDivisor, numChars
//------------------------------------------------------------------------------
- defaultFont.charSet = (Character *)malloc(defaultFont.numChars * sizeof(Character)); // Allocate space for our character data
- // This memory should be freed at end! --> Done on CloseWindow()
+ defaultFont.charValues = (int *)malloc(defaultFont.numChars*sizeof(int));
+ defaultFont.charRecs = (Rectangle *)malloc(defaultFont.numChars*sizeof(Rectangle)); // Allocate space for our character rectangle data
+ // This memory should be freed at end! --> Done on CloseWindow()
int currentLine = 0;
int currentPosX = charsDivisor;
int testPosX = charsDivisor;
for (int i = 0; i < defaultFont.numChars; i++)
{
- defaultFont.charSet[i].value = FONT_FIRST_CHAR + i; // First char is 32
- defaultFont.charSet[i].x = currentPosX;
- defaultFont.charSet[i].y = charsDivisor + currentLine * (charsHeight + charsDivisor);
- defaultFont.charSet[i].w = charsWidth[i];
- defaultFont.charSet[i].h = charsHeight;
+ defaultFont.charValues[i] = FONT_FIRST_CHAR + i; // First char is 32
+
+ defaultFont.charRecs[i].x = currentPosX;
+ defaultFont.charRecs[i].y = charsDivisor + currentLine * (charsHeight + charsDivisor);
+ defaultFont.charRecs[i].width = charsWidth[i];
+ defaultFont.charRecs[i].height = charsHeight;
- testPosX += (defaultFont.charSet[i].w + charsDivisor);
+ testPosX += (defaultFont.charRecs[i].width + charsDivisor);
if (testPosX >= defaultFont.texture.width)
{
@@ -203,11 +205,13 @@ extern void LoadDefaultFont(void)
currentPosX = 2 * charsDivisor + charsWidth[i];
testPosX = currentPosX;
- defaultFont.charSet[i].x = charsDivisor;
- defaultFont.charSet[i].y = charsDivisor + currentLine * (charsHeight + charsDivisor);
+ defaultFont.charRecs[i].x = charsDivisor;
+ defaultFont.charRecs[i].y = charsDivisor + currentLine*(charsHeight + charsDivisor);
}
else currentPosX = testPosX;
}
+
+ defaultFont.size = defaultFont.charRecs[0].y;
TraceLog(INFO, "[TEX ID %i] Default font loaded successfully", defaultFont.texture.id);
}
@@ -215,7 +219,8 @@ extern void LoadDefaultFont(void)
extern void UnloadDefaultFont(void)
{
UnloadTexture(defaultFont.texture);
- free(defaultFont.charSet);
+ free(defaultFont.charValues);
+ free(defaultFont.charRecs);
TraceLog(INFO, "Unloaded default font data");
}
@@ -238,25 +243,20 @@ SpriteFont LoadSpriteFont(const char *fileName)
{
Image image = LoadImage(fileName);
- // At this point we have a data array...
-
- Color *imagePixels = GetImageData(image);
-
#if defined(PLATFORM_RPI) || defined(PLATFORM_WEB)
ImageConvertToPOT(&image, MAGENTA);
#endif
- // Process bitmap Font pixel data to get measures (Character array)
+ // Process bitmap font pixel data to get characters measures
// spriteFont.charSet data is filled inside the function and memory is allocated!
- int numChars = ParseImageData(imagePixels, image.width, image.height, &spriteFont.charSet);
+ int numChars = ParseImageData(image, &spriteFont.charValues, &spriteFont.charRecs);
- TraceLog(INFO, "[%s] SpriteFont data parsed correctly", fileName);
- TraceLog(INFO, "[%s] SpriteFont num chars detected: %i", fileName, numChars);
+ TraceLog(DEBUG, "[%s] SpriteFont data parsed correctly", fileName);
+ TraceLog(DEBUG, "[%s] SpriteFont num chars detected: %i", fileName, numChars);
spriteFont.numChars = numChars;
-
spriteFont.texture = LoadTextureFromImage(image); // Convert loaded image to OpenGL texture
+ spriteFont.size = spriteFont.charRecs[0].height;
- free(imagePixels);
UnloadImage(image);
}
@@ -267,7 +267,8 @@ SpriteFont LoadSpriteFont(const char *fileName)
void UnloadSpriteFont(SpriteFont spriteFont)
{
UnloadTexture(spriteFont.texture);
- free(spriteFont.charSet);
+ free(spriteFont.charValues);
+ free(spriteFont.charRecs);
TraceLog(INFO, "Unloaded sprite font data");
}
@@ -298,32 +299,32 @@ void DrawTextEx(SpriteFont spriteFont, const char *text, Vector2 position, int f
float scaleFactor;
unsigned char letter;
- Character c;
+ Rectangle rec;
- //if (fontSize <= spriteFont.charSet[0].h) scaleFactor = 1.0f;
- //else scaleFactor = (float)fontSize / spriteFont.charSet[0].h;
+ //if (fontSize <= spriteFont.charRecs[0].height) scaleFactor = 1.0f;
+ //else scaleFactor = (float)fontSize / spriteFont.charRecs[0].height;
- scaleFactor = (float)fontSize/spriteFont.charSet[0].h;
+ scaleFactor = (float)fontSize/spriteFont.charRecs[0].height;
for(int i = 0; i < length; i++)
{
if ((unsigned char)text[i] == 0xc2)
{
letter = (unsigned char)text[i + 1];
- c = spriteFont.charSet[letter - FONT_FIRST_CHAR];
+ rec = spriteFont.charRecs[letter - FONT_FIRST_CHAR];
i++;
}
else if ((unsigned char)text[i] == 0xc3)
{
letter = (unsigned char)text[i + 1];
- c = spriteFont.charSet[letter - FONT_FIRST_CHAR + 64];
+ rec = spriteFont.charRecs[letter - FONT_FIRST_CHAR + 64];
i++;
}
- else c = spriteFont.charSet[(int)text[i] - FONT_FIRST_CHAR];
+ else rec = spriteFont.charRecs[(int)text[i] - FONT_FIRST_CHAR];
- DrawTexturePro(spriteFont.texture, (Rectangle){ c.x, c.y, c.w, c.h }, (Rectangle){ position.x + offsetX, position.y, c.w*scaleFactor, c.h*scaleFactor} , (Vector2){ 0, 0 }, 0.0f, tint);
+ DrawTexturePro(spriteFont.texture, rec, (Rectangle){ position.x + offsetX, position.y, rec.width*scaleFactor, rec.height*scaleFactor} , (Vector2){ 0, 0 }, 0.0f, tint);
- offsetX += (c.w*scaleFactor + spacing);
+ offsetX += (rec.width*scaleFactor + spacing);
}
}
@@ -363,25 +364,19 @@ Vector2 MeasureTextEx(SpriteFont spriteFont, const char *text, int fontSize, int
for (int i = 0; i < len; i++)
{
- textWidth += spriteFont.charSet[(int)text[i] - FONT_FIRST_CHAR].w;
+ textWidth += spriteFont.charRecs[(int)text[i] - FONT_FIRST_CHAR].width;
}
- if (fontSize <= spriteFont.charSet[0].h) scaleFactor = 1.0f;
- else scaleFactor = (float)fontSize / spriteFont.charSet[0].h;
+ if (fontSize <= spriteFont.charRecs[0].height) scaleFactor = 1.0f;
+ else scaleFactor = (float)fontSize / spriteFont.charRecs[0].height;
Vector2 vec;
vec.x = (float)textWidth * scaleFactor + (len - 1) * spacing; // Adds chars spacing to measure
- vec.y = (float)spriteFont.charSet[0].h * scaleFactor;
+ vec.y = (float)spriteFont.charRecs[0].height * scaleFactor;
return vec;
}
-// Returns the base size for a SpriteFont (chars height)
-int GetFontBaseSize(SpriteFont spriteFont)
-{
- return spriteFont.charSet[0].h;
-}
-
// Shows current FPS on top-left corner
// NOTE: Uses default font
void DrawFPS(int posX, int posY)
@@ -420,8 +415,8 @@ static bool PixelIsMagenta(Color p)
return ((p.r == 255) && (p.g == 0) && (p.b == 255) && (p.a == 255));
}
-// Parse image pixel data to obtain character set measures
-static int ParseImageData(Color *imgDataPixel, int imgWidth, int imgHeight, Character **charSet)
+// Parse image pixel data to obtain characters data (measures)
+static int ParseImageData(Image image, int **charValues, Rectangle **charRecs)
{
int charSpacing = 0;
int lineSpacing = 0;
@@ -429,15 +424,20 @@ static int ParseImageData(Color *imgDataPixel, int imgWidth, int imgHeight, Char
int x = 0;
int y = 0;
- Character tempCharSet[MAX_FONTCHARS]; // We allocate a temporal array for charData, once we get the actual charNumber we copy data to a sized array.
+ // We allocate a temporal arrays for chars data measures,
+ // once we get the actual number of chars, we copy data to a sized arrays
+ int tempCharValues[MAX_FONTCHARS];
+ Rectangle tempCharRecs[MAX_FONTCHARS];
+
+ Color *pixels = GetImageData(image);
- for(y = 0; y < imgHeight; y++)
+ for(y = 0; y < image.height; y++)
{
- for(x = 0; x < imgWidth; x++)
+ for(x = 0; x < image.width; x++)
{
- if (!PixelIsMagenta(imgDataPixel[y*imgWidth + x])) break;
+ if (!PixelIsMagenta(pixels[y*image.width + x])) break;
}
- if (!PixelIsMagenta(imgDataPixel[y*imgWidth + x])) break;
+ if (!PixelIsMagenta(pixels[y*image.width + x])) break;
}
charSpacing = x;
@@ -446,7 +446,7 @@ static int ParseImageData(Color *imgDataPixel, int imgWidth, int imgHeight, Char
int charHeight = 0;
int j = 0;
- while(!PixelIsMagenta(imgDataPixel[(lineSpacing + j)*imgWidth + charSpacing])) j++;
+ while(!PixelIsMagenta(pixels[(lineSpacing + j)*image.width + charSpacing])) j++;
charHeight = j;
@@ -455,21 +455,22 @@ static int ParseImageData(Color *imgDataPixel, int imgWidth, int imgHeight, Char
int lineToRead = 0;
int xPosToRead = charSpacing;
- while((lineSpacing + lineToRead * (charHeight + lineSpacing)) < imgHeight)
+ while((lineSpacing + lineToRead * (charHeight + lineSpacing)) < image.height)
{
- while((xPosToRead < imgWidth) &&
- !PixelIsMagenta((imgDataPixel[(lineSpacing + (charHeight+lineSpacing)*lineToRead)*imgWidth + xPosToRead])))
+ while((xPosToRead < image.width) &&
+ !PixelIsMagenta((pixels[(lineSpacing + (charHeight+lineSpacing)*lineToRead)*image.width + xPosToRead])))
{
- tempCharSet[index].value = FONT_FIRST_CHAR + index;
- tempCharSet[index].x = xPosToRead;
- tempCharSet[index].y = lineSpacing + lineToRead * (charHeight + lineSpacing);
- tempCharSet[index].h = charHeight;
+ tempCharValues[index] = FONT_FIRST_CHAR + index;
+
+ tempCharRecs[index].x = xPosToRead;
+ tempCharRecs[index].y = lineSpacing + lineToRead * (charHeight + lineSpacing);
+ tempCharRecs[index].height = charHeight;
int charWidth = 0;
- while(!PixelIsMagenta(imgDataPixel[(lineSpacing + (charHeight+lineSpacing)*lineToRead)*imgWidth + xPosToRead + charWidth])) charWidth++;
+ while(!PixelIsMagenta(pixels[(lineSpacing + (charHeight+lineSpacing)*lineToRead)*image.width + xPosToRead + charWidth])) charWidth++;
- tempCharSet[index].w = charWidth;
+ tempCharRecs[index].width = charWidth;
index++;
@@ -479,12 +480,20 @@ static int ParseImageData(Color *imgDataPixel, int imgWidth, int imgHeight, Char
lineToRead++;
xPosToRead = charSpacing;
}
+
+ free(pixels);
- // We got tempCharSet populated with char data and the number of chars (index)
- // Now we move temp data to real charSet (passed as parameter to the function)
- (*charSet) = (Character *)malloc(index * sizeof(Character)); // BE CAREFUL! This memory should be freed!
+ // We got tempCharValues and tempCharsRecs populated with chars data
+ // Now we move temp data to sized charValues and charRecs arrays (passed as parameter to the function)
+ // NOTE: This memory should be freed!
+ (*charRecs) = (Rectangle *)malloc(index*sizeof(Rectangle));
+ (*charValues) = (int *)malloc(index*sizeof(int));
- for (int i = 0; i < index; i++) (*charSet)[i] = tempCharSet[i];
+ for (int i = 0; i < index; i++)
+ {
+ (*charValues)[i] = tempCharValues[i];
+ (*charRecs)[i] = tempCharRecs[i];
+ }
return index;
}
@@ -528,7 +537,7 @@ static SpriteFont LoadRBMF(const char *fileName)
{
fread(&rbmfHeader, sizeof(rbmfInfoHeader), 1, rbmfFile);
- TraceLog(INFO, "[%s] Loading rBMF file, size: %ix%i, numChars: %i, charHeight: %i", fileName, rbmfHeader.imgWidth, rbmfHeader.imgHeight, rbmfHeader.numChars, rbmfHeader.charHeight);
+ TraceLog(DEBUG, "[%s] Loading rBMF file, size: %ix%i, numChars: %i, charHeight: %i", fileName, rbmfHeader.imgWidth, rbmfHeader.imgHeight, rbmfHeader.numChars, rbmfHeader.charHeight);
spriteFont.numChars = (int)rbmfHeader.numChars;
@@ -566,15 +575,16 @@ static SpriteFont LoadRBMF(const char *fileName)
free(imagePixels);
- TraceLog(INFO, "[%s] Image reconstructed correctly, now converting it to texture", fileName);
+ TraceLog(DEBUG, "[%s] Image reconstructed correctly, now converting it to texture", fileName);
spriteFont.texture = LoadTextureFromImage(image);
UnloadImage(image); // Unload image data
- //TraceLog(INFO, "[%s] Starting charSet reconstruction", fileName);
+ //TraceLog(INFO, "[%s] Starting chars set reconstruction", fileName);
- // Reconstruct charSet using rbmfCharWidthData, rbmfHeader.charHeight, charsDivisor, rbmfHeader.numChars
- spriteFont.charSet = (Character *)malloc(spriteFont.numChars * sizeof(Character)); // Allocate space for our character data
+ // Get characters data using rbmfCharWidthData, rbmfHeader.charHeight, charsDivisor, rbmfHeader.numChars
+ spriteFont.charValues = (int *)malloc(spriteFont.numChars*sizeof(int));
+ spriteFont.charRecs = (Rectangle *)malloc(spriteFont.numChars*sizeof(Rectangle));
int currentLine = 0;
int currentPosX = charsDivisor;
@@ -582,13 +592,14 @@ static SpriteFont LoadRBMF(const char *fileName)
for (int i = 0; i < spriteFont.numChars; i++)
{
- spriteFont.charSet[i].value = (int)rbmfHeader.firstChar + i;
- spriteFont.charSet[i].x = currentPosX;
- spriteFont.charSet[i].y = charsDivisor + currentLine * ((int)rbmfHeader.charHeight + charsDivisor);
- spriteFont.charSet[i].w = (int)rbmfCharWidthData[i];
- spriteFont.charSet[i].h = (int)rbmfHeader.charHeight;
+ spriteFont.charValues[i] = (int)rbmfHeader.firstChar + i;
+
+ spriteFont.charRecs[i].x = currentPosX;
+ spriteFont.charRecs[i].y = charsDivisor + currentLine * ((int)rbmfHeader.charHeight + charsDivisor);
+ spriteFont.charRecs[i].width = (int)rbmfCharWidthData[i];
+ spriteFont.charRecs[i].height = (int)rbmfHeader.charHeight;
- testPosX += (spriteFont.charSet[i].w + charsDivisor);
+ testPosX += (spriteFont.charRecs[i].width + charsDivisor);
if (testPosX > spriteFont.texture.width)
{
@@ -596,11 +607,13 @@ static SpriteFont LoadRBMF(const char *fileName)
currentPosX = 2 * charsDivisor + (int)rbmfCharWidthData[i];
testPosX = currentPosX;
- spriteFont.charSet[i].x = charsDivisor;
- spriteFont.charSet[i].y = charsDivisor + currentLine * (rbmfHeader.charHeight + charsDivisor);
+ spriteFont.charRecs[i].x = charsDivisor;
+ spriteFont.charRecs[i].y = charsDivisor + currentLine * (rbmfHeader.charHeight + charsDivisor);
}
else currentPosX = testPosX;
}
+
+ spriteFont.size = spriteFont.charRecs[0].height;
TraceLog(INFO, "[%s] rBMF file loaded correctly as SpriteFont", fileName);
}
@@ -614,8 +627,14 @@ static SpriteFont LoadRBMF(const char *fileName)
}
// Generate a sprite font from TTF data (font size required)
+// NOTE: This function is a mess, it should be completely redone!
static SpriteFont LoadTTF(const char *fileName, int fontSize)
{
+ // Steps:
+
+ // 1) Generate sprite sheet image with characters from TTF
+ // 2) Load image as SpriteFont
+
SpriteFont font;
Image image;
@@ -631,7 +650,7 @@ static SpriteFont LoadTTF(const char *fileName, int fontSize)
unsigned char *tempBitmap = (unsigned char *)malloc(image.width*image.height*sizeof(unsigned char)); // One channel bitmap returned!
- // REFERENCE
+ // Reference struct
/*
typedef struct
{
@@ -693,8 +712,10 @@ static SpriteFont LoadTTF(const char *fileName, int fontSize)
print(100,160, 0, "This is a test");
*/
+/*
font.numChars = 95;
- font.charSet = (Character *)malloc(font.numChars*sizeof(Character));
+ font.charValues (int *)malloc(font.numChars*sizeof(int));
+ font.charRecs = (Character *)malloc(font.numChars*sizeof(Character));
font.texture = LoadTextureFromImage(image);
//stbtt_aligned_quad letter;
@@ -702,16 +723,16 @@ static SpriteFont LoadTTF(const char *fileName, int fontSize)
for (int i = 0; i < font.numChars; i++)
{
- font.charSet[i].value = i + 32;
+ font.charValues[i] = i + 32;
//stbtt_GetPackedQuad(chardata[0], 512, 512, i, &x, &y, &letter, 0);
- font.charSet[i].x = chardata[i + 32].x0;
- font.charSet[i].y = chardata[i + 32].y0;
- font.charSet[i].w = chardata[i + 32].x1 - chardata[i + 32].x0;
- font.charSet[i].h = chardata[i + 32].y1 - chardata[i + 32].y0;
+ font.charRecs[i].x = chardata[i + 32].x0;
+ font.charRecs[i].y = chardata[i + 32].y0;
+ font.charRecs[i].width = chardata[i + 32].x1 - chardata[i + 32].x0;
+ font.charRecs[i].height = chardata[i + 32].y1 - chardata[i + 32].y0;
}
-
+*/
UnloadImage(image);
return font;
diff --git a/src/textures.c b/src/textures.c
index 69456701..e2eb8b2f 100644
--- a/src/textures.c
+++ b/src/textures.c
@@ -32,7 +32,10 @@
#include <stdlib.h> // Declares malloc() and free() for memory management
#include <string.h> // Required for strcmp(), strrchr(), strncmp()
-#include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3+ or ES2
+#include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3 or ES2
+ // Required: rlglLoadTexture() rlDeleteTextures(),
+ // rlglGenerateMipmaps(), some funcs for DrawTexturePro()
+
#include "utils.h" // rRES data decompression utility function
// NOTE: Includes Android fopen function map
@@ -397,9 +400,12 @@ void UnloadImage(Image image)
// Unload texture from GPU memory
void UnloadTexture(Texture2D texture)
{
- rlDeleteTextures(texture.id);
-
- TraceLog(INFO, "[TEX ID %i] Unloaded texture data", texture.id);
+ if (texture.id != 0)
+ {
+ rlDeleteTextures(texture.id);
+
+ TraceLog(INFO, "[TEX ID %i] Unloaded texture data", texture.id);
+ }
}
// Get pixel data from image in the form of Color struct array
@@ -895,6 +901,7 @@ static Image LoadDDS(const char *fileName)
TraceLog(DEBUG, "[%s] DDS file pixel format size: %i", fileName, header.ddspf.size);
TraceLog(DEBUG, "[%s] DDS file pixel format flags: 0x%x", fileName, header.ddspf.flags);
TraceLog(DEBUG, "[%s] DDS file format: 0x%x", fileName, header.ddspf.fourCC);
+ TraceLog(DEBUG, "[%s] DDS file bit count: 0x%x", fileName, header.ddspf.rgbBitCount);
image.width = header.width;
image.height = header.height;
@@ -959,10 +966,22 @@ static Image LoadDDS(const char *fileName)
{
image.data = (unsigned char *)malloc(image.width*image.height*4*sizeof(unsigned char));
fread(image.data, image.width*image.height*4, 1, ddsFile);
+
+ unsigned char blue = 0;
+ // NOTE: Data comes as A8R8G8B8, it must be reordered R8G8B8A8 (view next comment)
+ // DirecX understand ARGB as a 32bit DWORD but the actual memory byte alignment is BGRA
+ // So, we must realign B8G8R8A8 to R8G8B8A8
+ for (int i = 0; i < image.width*image.height*4; i += 4)
+ {
+ blue = ((unsigned char *)image.data)[i];
+ ((unsigned char *)image.data)[i] = ((unsigned char *)image.data)[i + 2];
+ ((unsigned char *)image.data)[i + 2] = blue;
+ }
+
image.format = UNCOMPRESSED_R8G8B8A8;
}
- else if (((header.ddspf.flags == 0x04) || (header.ddspf.flags == 0x05)) && (header.ddspf.fourCC > 0))
+ else if (((header.ddspf.flags == 0x04) || (header.ddspf.flags == 0x05)) && (header.ddspf.fourCC > 0)) // Compressed
{
int bufsize;
@@ -1062,15 +1081,18 @@ static Image LoadPKM(const char *fileName)
header.width = ((header.width & 0x00FF) << 8) | ((header.width & 0xFF00) >> 8);
header.height = ((header.height & 0x00FF) << 8) | ((header.height & 0xFF00) >> 8);
- TraceLog(INFO, "PKM (ETC) image width: %i", header.width);
- TraceLog(INFO, "PKM (ETC) image height: %i", header.height);
- TraceLog(INFO, "PKM (ETC) image format: %i", header.format);
+ TraceLog(DEBUG, "PKM (ETC) image width: %i", header.width);
+ TraceLog(DEBUG, "PKM (ETC) image height: %i", header.height);
+ TraceLog(DEBUG, "PKM (ETC) image format: %i", header.format);
image.width = header.width;
image.height = header.height;
image.mipmaps = 1;
- int size = image.width*image.height*4/8; // Total data size in bytes
+ int bpp = 4;
+ if (header.format == 3) bpp = 8;
+
+ int size = image.width*image.height*bpp/8; // Total data size in bytes
image.data = (unsigned char*)malloc(size * sizeof(unsigned char));