From ef36950b72fa97785320396cd62ed48318a2b431 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Thu, 27 Aug 2015 18:17:05 +0200 Subject: New raylib module: raygui Immediate Mode GUI (IMGUI) --- src/raygui.c | 1002 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/raygui.h | 271 ++++++++++++++++ 2 files changed, 1273 insertions(+) create mode 100644 src/raygui.c create mode 100644 src/raygui.h (limited to 'src') 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 +#include +#include // Required for malloc(), free() +#include // 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 -- cgit v1.2.3 From 322ca97c24f214d665cad512a70a696b489ecb52 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Fri, 28 Aug 2015 14:14:12 +0200 Subject: Review camera system --- src/camera.c | 59 +++++++++++++++++++++++++++++++++++++++++++++-------------- src/camera.h | 11 ++++++----- 2 files changed, 51 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/camera.c b/src/camera.c index 627451fe..5c4d9ade 100644 --- a/src/camera.c +++ b/src/camera.c @@ -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,7 +155,7 @@ 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); } @@ -162,6 +163,7 @@ void SetCameraMode(int mode) } // Update camera with position +// TODO: I don't like how this function works right now... not clear enough... Camera UpdateCamera(Vector3 *position) { // Calculate camera @@ -170,41 +172,70 @@ Camera UpdateCamera(Vector3 *position) return 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 @@ -298,7 +329,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; } diff --git a/src/camera.h b/src/camera.h index 63d8f786..93929c2a 100644 --- a/src/camera.h +++ b/src/camera.h @@ -76,18 +76,19 @@ 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) +Camera UpdateCamera(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 } -- cgit v1.2.3 From c52ba520cec3c9d3fdf7cb1f70da95e9396c59a9 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Fri, 28 Aug 2015 14:14:29 +0200 Subject: Small tweaks --- src/core.c | 4 ++-- src/raylib.h | 11 ++++++----- src/rlgl.c | 2 +- src/text.c | 8 +++++++- 4 files changed, 16 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/core.c b/src/core.c index e3c4e10b..8d832fd2 100644 --- a/src/core.c +++ b/src/core.c @@ -1007,8 +1007,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/raylib.h b/src/raylib.h index f5220e2e..5ceb3fc1 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -517,18 +517,19 @@ 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) +Camera UpdateCamera(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) diff --git a/src/rlgl.c b/src/rlgl.c index 163fa35a..6dea10c0 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -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) diff --git a/src/text.c b/src/text.c index 65d52f26..3d866c86 100644 --- a/src/text.c +++ b/src/text.c @@ -614,8 +614,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 +637,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 { -- cgit v1.2.3 From 9dd20577cd4dcbadd3bcad5958a7572c5ad45237 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sat, 29 Aug 2015 17:01:25 +0200 Subject: Corrected bugs on DDS and PKM loading --- src/textures.c | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/textures.c b/src/textures.c index 69456701..43d6cb15 100644 --- a/src/textures.c +++ b/src/textures.c @@ -397,9 +397,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 +898,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 +963,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 +1078,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)); -- cgit v1.2.3 From 5cfd59258ae4c308aab1055430f10955e5188736 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sat, 29 Aug 2015 17:01:36 +0200 Subject: Detected issue --- src/rlgl.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/rlgl.c b/src/rlgl.c index 6dea10c0..12eb7a9e 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -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--) { -- cgit v1.2.3 From 8692c495110f650405eb2dd54d5de101880533af Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sat, 29 Aug 2015 20:20:09 +0200 Subject: Corrected bug on first person camera --- src/camera.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/camera.c b/src/camera.c index 5c4d9ade..40885140 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; @@ -234,7 +234,7 @@ void SetCameraMoveControls(int frontKey, int backKey, int leftKey, int rightKey, // Set camera mouse sensitivity (1st person and 3rd person cameras) void SetCameraMouseSensitivity(float sensitivity) { - mouseSensitivity = (sensitivity / 10000.0); + mouseSensitivity = (sensitivity/10000.0); } //---------------------------------------------------------------------------------- @@ -278,7 +278,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) @@ -480,8 +482,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; -- cgit v1.2.3 From 055d8927cccbc2b7b4dd5d6f6928159ba3fff2e6 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sat, 29 Aug 2015 20:20:28 +0200 Subject: Small code tweaks --- src/core.c | 2 ++ src/rlgl.c | 6 ++---- src/rlgl.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/core.c b/src/core.c index 8d832fd2..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) diff --git a/src/rlgl.c b/src/rlgl.c index 12eb7a9e..7fa50af6 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) * @@ -3061,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..cd999bf5 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) -- cgit v1.2.3 From d7e7ef6a7de1e0b4be2fbbd5ff774150e3d1634a Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 30 Aug 2015 17:44:14 +0200 Subject: Added some comments --- src/textures.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/textures.c b/src/textures.c index 43d6cb15..e2eb8b2f 100644 --- a/src/textures.c +++ b/src/textures.c @@ -32,7 +32,10 @@ #include // Declares malloc() and free() for memory management #include // 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 -- cgit v1.2.3 From aa982f80f58ae0f18ed8431be8353c9f997610b5 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 30 Aug 2015 17:44:47 +0200 Subject: Reviewed some comments --- src/rlgl.c | 2 +- src/rlgl.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/rlgl.c b/src/rlgl.c index 7fa50af6..8806b429 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -2077,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; diff --git a/src/rlgl.h b/src/rlgl.h index cd999bf5..172b4868 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -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 -- cgit v1.2.3 From 92bcf09c534c4ef204e973a2e7153e2ea557c1ea Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 30 Aug 2015 17:45:05 +0200 Subject: Redesigned SpriteFont struct --- src/raylib.h | 78 ++++++++++++------------- src/text.c | 181 ++++++++++++++++++++++++++++++++--------------------------- 2 files changed, 134 insertions(+), 125 deletions(-) (limited to 'src') diff --git a/src/raylib.h b/src/raylib.h index 5ceb3fc1..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,7 +487,8 @@ 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 *position); // 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 SetCameraPosition(Vector3 position); // Set internal camera position void SetCameraTarget(Vector3 target); // Set internal camera target @@ -571,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 @@ -599,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 +616,29 @@ bool CheckCollisionBoxes(Vector3 minBBox1, Vector3 maxBBox1, Vector3 minBBox2, V bool CheckCollisionBoxSphere(Vector3 minBBox, Vector3 maxBBox, Vector3 centerSphere, float radiusSphere); // Detect collision between box and sphere 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) //------------------------------------------------------------------------------------ diff --git a/src/text.c b/src/text.c index 3d866c86..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); } @@ -699,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; @@ -708,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; -- cgit v1.2.3 From 535b9e606f6571c5d4163481d077ae3d5a79f1b8 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 30 Aug 2015 17:46:19 +0200 Subject: Redesigned UpdateCamera() function Splitted into: UpdateCamera() // Update only camera UpdateCameraPlayer() // Update camera and player position --- src/camera.c | 20 +++++++++++++++----- src/camera.h | 3 ++- 2 files changed, 17 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/camera.c b/src/camera.c index 40885140..b637b1e4 100644 --- a/src/camera.c +++ b/src/camera.c @@ -162,14 +162,24 @@ void SetCameraMode(int mode) cameraMode = mode; } -// Update camera with position -// TODO: I don't like how this function works right now... not clear enough... -Camera UpdateCamera(Vector3 *position) +// Update camera (player position is ignored) +void UpdateCamera(Camera *camera) { - // Calculate 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) +{ + // Process internal camera and player position (if required) if (cameraMode != CAMERA_CUSTOM) ProcessCamera(&internalCamera, position); - return internalCamera; + *camera = internalCamera; } // Set internal camera position diff --git a/src/camera.h b/src/camera.h index 93929c2a..ed85320a 100644 --- a/src/camera.h +++ b/src/camera.h @@ -76,7 +76,8 @@ extern "C" { // Prevents name mangling of functions // Module Functions Declaration //---------------------------------------------------------------------------------- void SetCameraMode(int mode); // Set camera mode (multiple camera modes available) -Camera UpdateCamera(Vector3 *position); // 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 SetCameraPosition(Vector3 position); // Set internal camera position void SetCameraTarget(Vector3 target); // Set internal camera target -- cgit v1.2.3