diff --git a/src/raygui.h b/src/raygui.h index 7009dbf..2319187 100644 --- a/src/raygui.h +++ b/src/raygui.h @@ -722,6 +722,7 @@ RAYGUIAPI int GuiComboBox(Rectangle bounds, const char *text, int *active); RAYGUIAPI int GuiDropdownBox(Rectangle bounds, const char *text, int *active, bool editMode); // Dropdown Box control RAYGUIAPI int GuiSpinner(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode); // Spinner control RAYGUIAPI int GuiValueBox(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode); // Value Box control, updates input text with numbers +RAYGUIAPI int GuiValueBoxF(Rectangle bounds,const char* text, char *val_str, float *value, bool editMode); // Floating point Value box control, val_str is buffer where string representation is stored RAYGUIAPI int GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode); // Text Box control, updates input text RAYGUIAPI int GuiSlider(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue); // Slider control @@ -1449,6 +1450,7 @@ static bool CheckCollisionPointRec(Vector2 point, Rectangle rec); // Check if static const char *TextFormat(const char *text, ...); // Formatting of text with variables to 'embed' static const char **TextSplit(const char *text, char delimiter, int *count); // Split text into multiple strings static int TextToInteger(const char *text); // Get integer value from text +static int TextToFloat(const char *text); // Get float value from text static int GetCodepointNext(const char *text, int *codepointSize); // Get next codepoint in a UTF-8 encoded text static const char *CodepointToUTF8(int codepoint, int *byteSize); // Encode codepoint into UTF-8 text (char array size returned as parameter) @@ -2934,6 +2936,121 @@ int GuiValueBox(Rectangle bounds, const char *text, int *value, int minValue, in return result; } +// Floating point Value Box control, updates input val_str with numbers +// NOTE: Requires static variables: frameCounter +int GuiValueBoxF(Rectangle bounds,const char* text, char *val_str, float *value, bool editMode) +{ +#if !defined(RAYGUI_VALUEBOX_MAX_CHARS) +#define RAYGUI_VALUEBOX_MAX_CHARS 32 +#endif + + int result = 0; + GuiState state = guiState; + + Rectangle textBounds = {0}; + if (text != NULL) + { + textBounds.width = (float)GetTextWidth(text) + 2; + textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); + textBounds.x = bounds.x + bounds.width + GuiGetStyle(VALUEBOX, TEXT_PADDING); + textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2; + if (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_LEFT) + textBounds.x = bounds.x - textBounds.width - GuiGetStyle(VALUEBOX, TEXT_PADDING); + } + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) + { + Vector2 mousePoint = GetMousePosition(); + + bool valueHasChanged = false; + + if (editMode) + { + state = STATE_PRESSED; + + int keyCount = (int)strlen(val_str); + + // Only allow keys in range [48..57] + if (keyCount < RAYGUI_VALUEBOX_MAX_CHARS) + { + if (GetTextWidth(val_str) < bounds.width) + { + int key = GetCharPressed(); + if ( + ((key >= 48) && (key <= 57)) + ||key=='.' + ||(!keyCount && key=='+') //sign can only be in first position + ||(!keyCount && key=='-') + ) + { + val_str[keyCount] = (char) key; + keyCount++; + valueHasChanged = true; + } + } + } + + // Pressed backspace + if (IsKeyPressed(KEY_BACKSPACE)) + { + if (keyCount > 0) + { + keyCount--; + val_str[keyCount] = '\0'; + valueHasChanged = true; + } + } + + if (valueHasChanged) + *value = TextToFloat(val_str); + + if (IsKeyPressed(KEY_ENTER) || + (!CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) + result = 1; + } else + { + if (CheckCollisionPointRec(mousePoint, bounds)) + { + state = STATE_FOCUSED; + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + result = 1; + } + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + Color baseColor = BLANK; + if (state == STATE_PRESSED) baseColor = GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_PRESSED)); + else if (state == STATE_DISABLED) baseColor = GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_DISABLED)); + + GuiDrawRectangle(bounds, GuiGetStyle(VALUEBOX, BORDER_WIDTH), GetColor(GuiGetStyle(VALUEBOX, BORDER + (state * 3))), + baseColor); + GuiDrawText(val_str, GetTextBounds(VALUEBOX, bounds), TEXT_ALIGN_CENTER, + GetColor(GuiGetStyle(VALUEBOX, TEXT + (state * 3)))); + + // Draw cursor + if (editMode) + { + // NOTE: ValueBox internal text is always centered + Rectangle cursor = {bounds.x + GetTextWidth(val_str) / 2 + bounds.width / 2 + 1, + bounds.y + 2 * GuiGetStyle(VALUEBOX, BORDER_WIDTH), 4, + bounds.height - 4 * GuiGetStyle(VALUEBOX, BORDER_WIDTH)}; + GuiDrawRectangle(cursor, 0, BLANK, GetColor(GuiGetStyle(VALUEBOX, BORDER_COLOR_PRESSED))); + } + + // Draw text label if provided + GuiDrawText(text, textBounds, + (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT) ? TEXT_ALIGN_LEFT : TEXT_ALIGN_RIGHT, + GetColor(GuiGetStyle(LABEL, TEXT + (state * 3)))); + //-------------------------------------------------------------------- + + return result; +} + // Slider control with pro parameters // NOTE: Other GuiSlider*() controls use this one int GuiSliderPro(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue, int sliderWidth) @@ -5455,6 +5572,28 @@ static int TextToInteger(const char *text) return value*sign; } +static float TextToFloat(const char *text) +{ + float value = 0.0f; + float sign = 1.0f; + + if ((text[0] == '+') || (text[0] == '-')) + { + if (text[0] == '-') sign = -1; + text++; + } + int i = 0; + for (; ((text[i] >= '0') && (text[i] <= '9')); ++i) value = value*10.0f + (float)(text[i] - '0'); + if (text[i++] != '.') return value*sign; + float divisor = 10.0f; + for (; ((text[i] >= '0') && (text[i] <= '9')); ++i) + { + value += ((float)(text[i] - '0'))/divisor; + divisor = divisor*10.0f; + } + return value; +} + // Encode codepoint into UTF-8 text (char array size returned as parameter) static const char *CodepointToUTF8(int codepoint, int *byteSize) {