diff --git a/raygui/button.go b/raygui/button.go new file mode 100644 index 0000000..153d2c8 --- /dev/null +++ b/raygui/button.go @@ -0,0 +1,63 @@ +package raygui + +import "github.com/gen2brain/raylib-go/raylib" + +// Button - Button element, returns true when clicked +func Button(bounds rl.Rectangle, text string) bool { + b := bounds.ToInt32() + state := Normal + mousePoint := rl.GetMousePosition() + clicked := false + + textHeight := int32(style[GlobalTextFontsize]) + textWidth := rl.MeasureText(text, textHeight) + + // Update control + if b.Width < textWidth { + b.Width = textWidth + int32(style[ButtonTextPadding]) + } + + if b.Height < textHeight { + b.Height = textHeight + int32(style[ButtonTextPadding])/2 + } + + if rl.CheckCollisionPointRec(mousePoint, bounds) { + if rl.IsMouseButtonDown(rl.MouseLeftButton) { + state = Pressed + } else if rl.IsMouseButtonReleased(rl.MouseLeftButton) || rl.IsMouseButtonPressed(rl.MouseLeftButton) { + clicked = true + } else { + state = Focused + } + } + + // Draw control + switch state { + case Normal: + rl.DrawRectangle(b.X, b.Y, b.Width, b.Height, rl.GetColor(int32(style[ButtonDefaultBorderColor]))) + rl.DrawRectangle(b.X+int32(style[ButtonBorderWidth]), b.Y+int32(style[ButtonBorderWidth]), b.Width-(2*int32(style[ButtonBorderWidth])), b.Height-(2*int32(style[ButtonBorderWidth])), rl.GetColor(int32(style[ButtonDefaultInsideColor]))) + rl.DrawText(text, b.X+((b.Width/2)-(rl.MeasureText(text, textHeight)/2)), b.Y+((b.Height/2)-(textHeight/2)), textHeight, rl.GetColor(int32(style[ButtonDefaultTextColor]))) + break + + case Focused: + rl.DrawRectangle(b.X, b.Y, b.Width, b.Height, rl.GetColor(int32(style[ButtonHoverBorderColor]))) + rl.DrawRectangle(b.X+int32(style[ButtonBorderWidth]), b.Y+int32(style[ButtonBorderWidth]), b.Width-(2*int32(style[ButtonBorderWidth])), b.Height-(2*int32(style[ButtonBorderWidth])), rl.GetColor(int32(style[ButtonHoverInsideColor]))) + rl.DrawText(text, b.X+((b.Width/2)-(rl.MeasureText(text, textHeight)/2)), b.Y+((b.Height/2)-(textHeight/2)), textHeight, rl.GetColor(int32(style[ButtonHoverTextColor]))) + break + + case Pressed: + rl.DrawRectangle(b.X, b.Y, b.Width, b.Height, rl.GetColor(int32(style[ButtonPressedBorderColor]))) + rl.DrawRectangle(b.X+int32(style[ButtonBorderWidth]), b.Y+int32(style[ButtonBorderWidth]), b.Width-(2*int32(style[ButtonBorderWidth])), b.Height-(2*int32(style[ButtonBorderWidth])), rl.GetColor(int32(style[ButtonPressedInsideColor]))) + rl.DrawText(text, b.X+((b.Width/2)-(rl.MeasureText(text, textHeight)/2)), b.Y+((b.Height/2)-(textHeight/2)), textHeight, rl.GetColor(int32(style[ButtonPressedTextColor]))) + break + + default: + break + } + + if clicked { + return true + } + + return false +} diff --git a/raygui/checkbox.go b/raygui/checkbox.go new file mode 100644 index 0000000..705d8d5 --- /dev/null +++ b/raygui/checkbox.go @@ -0,0 +1,46 @@ +package raygui + +import "github.com/gen2brain/raylib-go/raylib" + +// CheckBox - Check Box element, returns true when active +func CheckBox(bounds rl.Rectangle, checked bool) bool { + b := bounds.ToInt32() + state := Normal + mousePoint := rl.GetMousePosition() + + // Update control + if rl.CheckCollisionPointRec(mousePoint, bounds) { + if rl.IsMouseButtonDown(rl.MouseLeftButton) { + state = Pressed + } else if rl.IsMouseButtonReleased(rl.MouseLeftButton) || rl.IsMouseButtonPressed(rl.MouseLeftButton) { + state = Normal + checked = !checked + } else { + state = Focused + } + } + + // Draw control + switch state { + case Normal: + rl.DrawRectangle(b.X, b.Y, b.Width, b.Height, rl.GetColor(int32(style[CheckboxDefaultBorderColor]))) + rl.DrawRectangle(b.X+int32(style[ToggleBorderWidth]), b.Y+int32(style[ToggleBorderWidth]), b.Width-(2*int32(style[ToggleBorderWidth])), b.Height-(2*int32(style[ToggleBorderWidth])), rl.GetColor(int32(style[CheckboxDefaultInsideColor]))) + break + case Focused: + rl.DrawRectangle(b.X, b.Y, b.Width, b.Height, rl.GetColor(int32(style[CheckboxHoverBorderColor]))) + rl.DrawRectangle(b.X+int32(style[ToggleBorderWidth]), b.Y+int32(style[ToggleBorderWidth]), b.Width-(2*int32(style[ToggleBorderWidth])), b.Height-(2*int32(style[ToggleBorderWidth])), rl.GetColor(int32(style[CheckboxHoverInsideColor]))) + break + case Pressed: + rl.DrawRectangle(b.X, b.Y, b.Width, b.Height, rl.GetColor(int32(style[CheckboxClickBorderColor]))) + rl.DrawRectangle(b.X+int32(style[ToggleBorderWidth]), b.Y+int32(style[ToggleBorderWidth]), b.Width-(2*int32(style[ToggleBorderWidth])), b.Height-(2*int32(style[ToggleBorderWidth])), rl.GetColor(int32(style[CheckboxClickInsideColor]))) + break + default: + break + } + + if checked { + rl.DrawRectangle(b.X+int32(style[CheckboxInsideWidth]), b.Y+int32(style[CheckboxInsideWidth]), b.Width-(2*int32(style[CheckboxInsideWidth])), b.Height-(2*int32(style[CheckboxInsideWidth])), rl.GetColor(int32(style[CheckboxDefaultActiveColor]))) + } + + return checked +} diff --git a/raygui/combobox.go b/raygui/combobox.go new file mode 100644 index 0000000..aa3a07e --- /dev/null +++ b/raygui/combobox.go @@ -0,0 +1,102 @@ +package raygui + +import ( + "fmt" + "github.com/gen2brain/raylib-go/raylib" +) + +// ComboBox draws a simplified version of a ComboBox allowing the user to select a string +// from a list accompanied by an N/M counter. The widget does not provide a drop-down/completion +// or any input support. +func ComboBox(bounds rl.Rectangle, comboText []string, active int) int { + // Reject invalid selections and disable rendering. + comboCount := len(comboText) + if active < 0 || active >= comboCount { + rl.TraceLog(rl.LogWarning, "ComboBox active expects 0 <= active <= %d", comboCount) + return -1 + } + + activeText := comboText[active] + + // style sizing. + textHeight := int32(style[GlobalTextFontsize]) + textWidth := rl.MeasureText(activeText, textHeight) + borderWidth := int32(style[ComboboxBorderWidth]) + textPadding := int32(style[ToggleTextPadding]) + + b := bounds.ToInt32() + if b.Width < textWidth { + b.Width = textWidth + textPadding + bounds.Width = float32(b.Width) + } + if b.Height < textHeight { + b.Height = textHeight + textPadding + bounds.Height = float32(b.Height) + } + + // Identify what the counter is going to look like with max digits so we don't resize it. + clickWidth := rl.MeasureText(fmt.Sprintf("%d/%d", comboCount, comboCount), b.Height) + + click := rl.NewRectangle(bounds.X+bounds.Width+float32(style[ComboboxPadding]), bounds.Y, float32(clickWidth), float32(b.Height)) + c := click.ToInt32() + mousePoint := rl.GetMousePosition() + state := Normal + if rl.CheckCollisionPointRec(mousePoint, bounds) || rl.CheckCollisionPointRec(mousePoint, click) { + if rl.IsMouseButtonDown(rl.MouseLeftButton) { + state = Pressed + } else if rl.IsMouseButtonReleased(rl.MouseLeftButton) || rl.IsMouseButtonPressed(rl.MouseLeftButton) { + state = Pressed + } else { + state = Focused + } + } + + // Draw control + var borderColor, insideColor, listColor, textColor rl.Color + + switch state { + case Normal: + borderColor = rl.GetColor(int32(style[ComboboxDefaultBorderColor])) + insideColor = rl.GetColor(int32(style[ComboboxDefaultInsideColor])) + listColor = rl.GetColor(int32(style[ComboboxDefaultListTextColor])) + textColor = rl.GetColor(int32(style[ComboboxDefaultTextColor])) + + case Focused: + borderColor = rl.GetColor(int32(style[ComboboxHoverBorderColor])) + insideColor = rl.GetColor(int32(style[ComboboxHoverInsideColor])) + listColor = rl.GetColor(int32(style[ComboboxHoverListTextColor])) + textColor = rl.GetColor(int32(style[ComboboxHoverTextColor])) + + case Pressed: + borderColor = rl.GetColor(int32(style[ComboboxPressedBorderColor])) + insideColor = rl.GetColor(int32(style[ComboboxPressedInsideColor])) + listColor = rl.GetColor(int32(style[ComboboxPressedListTextColor])) + textColor = rl.GetColor(int32(style[ComboboxPressedTextColor])) + + default: + rl.TraceLog(rl.LogWarning, "ComboBox in unrecognized state %d", state) + return -1 + } + + // Render the box itself + rl.DrawRectangle(b.X, b.Y, b.Width, b.Height, borderColor) + rl.DrawRectangle(b.X+borderWidth, b.Y+borderWidth, b.Width-(2*borderWidth), b.Height-(2*borderWidth), insideColor) + rl.DrawText(activeText, b.X+((b.Width/2)-(rl.MeasureText(activeText, textHeight)/2)), b.Y+((b.Height/2)-(textHeight/2)), textHeight, textColor) + + // Render the accompanying "clicks" box showing the element counter. + rl.DrawRectangle(c.X, c.Y, c.Width, c.Height, borderColor) + rl.DrawRectangle(c.X+borderWidth, c.Y+borderWidth, c.Width-(2*borderWidth), c.Height-(2*borderWidth), insideColor) + companionText := fmt.Sprintf("%d/%d", active+1, comboCount) + rl.DrawText(companionText, c.X+((c.Width/2)-(rl.MeasureText(companionText, textHeight)/2)), c.Y+((c.Height/2)-(textHeight/2)), textHeight, listColor) + + if rl.CheckCollisionPointRec(mousePoint, bounds) || rl.CheckCollisionPointRec(mousePoint, click) { + if rl.IsMouseButtonPressed(rl.MouseLeftButton) { + active++ + if active >= comboCount { + active = 0 + } + } + } + + return active +} diff --git a/raygui/label.go b/raygui/label.go new file mode 100644 index 0000000..c59c299 --- /dev/null +++ b/raygui/label.go @@ -0,0 +1,28 @@ +package raygui + +import rl "github.com/gen2brain/raylib-go/raylib" + +// Label - Label element, show text +func Label(bounds rl.Rectangle, text string) { + LabelEx(bounds, text, rl.GetColor(int32(style[LabelTextColor])), rl.NewColor(0, 0, 0, 0), rl.NewColor(0, 0, 0, 0)) +} + +// LabelEx - Label element extended, configurable colors +func LabelEx(bounds rl.Rectangle, text string, textColor, border, inner rl.Color) { + b := bounds.ToInt32() + // Update control + textHeight := int32(style[GlobalTextFontsize]) + textWidth := rl.MeasureText(text, textHeight) + + if b.Width < textWidth { + b.Width = textWidth + int32(style[LabelTextPadding]) + } + if b.Height < textHeight { + b.Height = textHeight + int32(style[LabelTextPadding])/2 + } + + // Draw control + rl.DrawRectangle(b.X, b.Y, b.Width, b.Height, border) + rl.DrawRectangle(b.X+int32(style[LabelBorderWidth]), b.Y+int32(style[LabelBorderWidth]), b.Width-(2*int32(style[LabelBorderWidth])), b.Height-(2*int32(style[LabelBorderWidth])), inner) + rl.DrawText(text, b.X+((b.Width/2)-(textWidth/2)), b.Y+((b.Height/2)-(textHeight/2)), textHeight, textColor) +} diff --git a/raygui/progressbar.go b/raygui/progressbar.go new file mode 100644 index 0000000..4d6164c --- /dev/null +++ b/raygui/progressbar.go @@ -0,0 +1,21 @@ +package raygui + +import "github.com/gen2brain/raylib-go/raylib" + +// ProgressBar - Progress Bar element, shows current progress value +func ProgressBar(bounds rl.Rectangle, value float32) { + b := bounds.ToInt32() + if value > 1.0 { + value = 1.0 + } else if value < 0.0 { + value = 0.0 + } + + progressBar := rl.RectangleInt32{b.X + int32(style[ProgressbarBorderWidth]), b.Y + int32(style[ProgressbarBorderWidth]), b.Width - (int32(style[ProgressbarBorderWidth]) * 2), b.Height - (int32(style[ProgressbarBorderWidth]) * 2)} + progressValue := rl.RectangleInt32{b.X + int32(style[ProgressbarBorderWidth]), b.Y + int32(style[ProgressbarBorderWidth]), int32(value * float32(b.Width-int32(style[ProgressbarBorderWidth])*2)), b.Height - (int32(style[ProgressbarBorderWidth]) * 2)} + + // Draw control + rl.DrawRectangle(b.X, b.Y, b.Width, b.Height, rl.GetColor(int32(style[ProgressbarBorderColor]))) + rl.DrawRectangle(progressBar.X, progressBar.Y, progressBar.Width, progressBar.Height, rl.GetColor(int32(style[ProgressbarInsideColor]))) + rl.DrawRectangle(progressValue.X, progressValue.Y, progressValue.Width, progressValue.Height, rl.GetColor(int32(style[ProgressbarProgressColor]))) +} diff --git a/raygui/raygui.go b/raygui/raygui.go index 2610e6f..4e6c2c8 100644 --- a/raygui/raygui.go +++ b/raygui/raygui.go @@ -1,1088 +1,16 @@ // Package raygui - Simple and easy-to-use IMGUI (immediate mode GUI API) library + package raygui -import ( - "bufio" - "fmt" - "io/ioutil" - "strconv" - "strings" - - "github.com/gen2brain/raylib-go/raylib" -) - -// Property - GUI property -type Property int32 - -// GUI properties enumeration -const ( - GlobalBaseColor Property = iota - GlobalBorderColor - GlobalTextColor - GlobalTextFontsize - GlobalBorderWidth - GlobalBackgroundColor - GlobalLinesColor - LabelBorderWidth - LabelTextColor - LabelTextPadding - ButtonBorderWidth - ButtonTextPadding - ButtonDefaultBorderColor - ButtonDefaultInsideColor - ButtonDefaultTextColor - ButtonHoverBorderColor - ButtonHoverInsideColor - ButtonHoverTextColor - ButtonPressedBorderColor - ButtonPressedInsideColor - ButtonPressedTextColor - ToggleTextPadding - ToggleBorderWidth - ToggleDefaultBorderColor - ToggleDefaultInsideColor - ToggleDefaultTextColor - ToggleHoverBorderColor - ToggleHoverInsideColor - ToggleHoverTextColor - TogglePressedBorderColor - TogglePressedInsideColor - TogglePressedTextColor - ToggleActiveBorderColor - ToggleActiveInsideColor - ToggleActiveTextColor - TogglegroupPadding - SliderBorderWidth - SliderButtonBorderWidth - SliderBorderColor - SliderInsideColor - SliderDefaultColor - SliderHoverColor - SliderActiveColor - SliderbarBorderColor - SliderbarInsideColor - SliderbarDefaultColor - SliderbarHoverColor - SliderbarActiveColor - SliderbarZeroLineColor - ProgressbarBorderColor - ProgressbarInsideColor - ProgressbarProgressColor - ProgressbarBorderWidth - SpinnerLabelBorderColor - SpinnerLabelInsideColor - SpinnerDefaultButtonBorderColor - SpinnerDefaultButtonInsideColor - SpinnerDefaultSymbolColor - SpinnerDefaultTextColor - SpinnerHoverButtonBorderColor - SpinnerHoverButtonInsideColor - SpinnerHoverSymbolColor - SpinnerHoverTextColor - SpinnerPressedButtonBorderColor - SpinnerPressedButtonInsideColor - SpinnerPressedSymbolColor - SpinnerPressedTextColor - ComboboxPadding - boundsWidth - boundsHeight - ComboboxBorderWidth - ComboboxDefaultBorderColor - ComboboxDefaultInsideColor - ComboboxDefaultTextColor - ComboboxDefaultListTextColor - ComboboxHoverBorderColor - ComboboxHoverInsideColor - ComboboxHoverTextColor - ComboboxHoverListTextColor - ComboboxPressedBorderColor - ComboboxPressedInsideColor - ComboboxPressedTextColor - ComboboxPressedListBorderColor - ComboboxPressedListInsideColor - ComboboxPressedListTextColor - CheckboxDefaultBorderColor - CheckboxDefaultInsideColor - CheckboxHoverBorderColor - CheckboxHoverInsideColor - CheckboxClickBorderColor - CheckboxClickInsideColor - CheckboxDefaultActiveColor - CheckboxInsideWidth - TextboxBorderWidth - TextboxBorderColor - TextboxInsideColor - TextboxTextColor - TextboxLineColor - TextboxTextFontsize -) - // GUI controls states +type ControlState int + const ( - Disabled = iota + Disabled ControlState = iota + // Normal is the default state for rendering GUI elements. Normal + // Focused indicates the mouse is hovering over the GUI element. Focused + // Pressed indicates the mouse is hovering over the GUI element and LMB is pressed down. Pressed ) - -// Current GUI style (default light) -var style = []int64{ - 0xf5f5f5ff, // GLOBAL_BASE_COLOR - 0xf5f5f5ff, // GLOBAL_BORDER_COLOR - 0xf5f5f5ff, // GLOBAL_TEXT_COLOR - 10, // GLOBAL_TEXT_FONTSIZE - 1, // GLOBAL_BORDER_WIDTH - 0xf5f5f5ff, // BACKGROUND_COLOR - 0x90abb5ff, // LINES_COLOR - 1, // LABEL_BORDER_WIDTH - 0x4d4d4dff, // 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 - 0x4d4d4dff, // BUTTON_DEFAULT_TEXT_COLOR - 0xc8c8c8ff, // BUTTON_HOVER_BORDER_COLOR - 0xffffffff, // BUTTON_HOVER_INSIDE_COLOR - 0x868686ff, // 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 - 20, // 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 - 0xbcecffff, // CHECKBOX_STATUS_ACTIVE_COLOR - 1, // 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 -} - -// GUI property names (to read/write style text files) -var propertyName = []string{ - "GLOBAL_BASE_COLOR", - "GLOBAL_BORDER_COLOR", - "GLOBAL_TEXT_COLOR", - "GLOBAL_TEXT_FONTSIZE", - "GLOBAL_BORDER_WIDTH", - "BACKGROUND_COLOR", - "LINES_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", -} - -// For spinner -var ( - framesCounter int - framesCounter2 int - valueSpeed bool -) - -// BackgroundColor - Get background color -func BackgroundColor() rl.Color { - return rl.GetColor(int32(style[GlobalBackgroundColor])) -} - -// LinesColor - Get lines color -func LinesColor() rl.Color { - return rl.GetColor(int32(style[GlobalLinesColor])) -} - -// TextColor - Get text color for normal state -func TextColor() rl.Color { - return rl.GetColor(int32(style[GlobalTextColor])) -} - -// Label - Label element, show text -func Label(bounds rl.Rectangle, text string) { - LabelEx(bounds, text, rl.GetColor(int32(style[LabelTextColor])), rl.NewColor(0, 0, 0, 0), rl.NewColor(0, 0, 0, 0)) -} - -// LabelEx - Label element extended, configurable colors -func LabelEx(bounds rl.Rectangle, text string, textColor, border, inner rl.Color) { - b := bounds.ToInt32() - // Update control - textHeight := int32(style[GlobalTextFontsize]) - textWidth := rl.MeasureText(text, textHeight) - - if b.Width < textWidth { - b.Width = textWidth + int32(style[LabelTextPadding]) - } - if b.Height < textHeight { - b.Height = textHeight + int32(style[LabelTextPadding])/2 - } - - // Draw control - rl.DrawRectangle(b.X, b.Y, b.Width, b.Height, border) - rl.DrawRectangle(b.X+int32(style[LabelBorderWidth]), b.Y+int32(style[LabelBorderWidth]), b.Width-(2*int32(style[LabelBorderWidth])), b.Height-(2*int32(style[LabelBorderWidth])), inner) - rl.DrawText(text, b.X+((b.Width/2)-(textWidth/2)), b.Y+((b.Height/2)-(textHeight/2)), textHeight, textColor) -} - -// Button - Button element, returns true when clicked -func Button(bounds rl.Rectangle, text string) bool { - b := bounds.ToInt32() - state := Normal - mousePoint := rl.GetMousePosition() - clicked := false - - textHeight := int32(style[GlobalTextFontsize]) - textWidth := rl.MeasureText(text, textHeight) - - // Update control - if b.Width < textWidth { - b.Width = textWidth + int32(style[ButtonTextPadding]) - } - - if b.Height < textHeight { - b.Height = textHeight + int32(style[ButtonTextPadding])/2 - } - - if rl.CheckCollisionPointRec(mousePoint, bounds) { - if rl.IsMouseButtonDown(rl.MouseLeftButton) { - state = Pressed - } else if rl.IsMouseButtonReleased(rl.MouseLeftButton) || rl.IsMouseButtonPressed(rl.MouseLeftButton) { - clicked = true - } else { - state = Focused - } - } - - // Draw control - switch state { - case Normal: - rl.DrawRectangle(b.X, b.Y, b.Width, b.Height, rl.GetColor(int32(style[ButtonDefaultBorderColor]))) - rl.DrawRectangle(b.X+int32(style[ButtonBorderWidth]), b.Y+int32(style[ButtonBorderWidth]), b.Width-(2*int32(style[ButtonBorderWidth])), b.Height-(2*int32(style[ButtonBorderWidth])), rl.GetColor(int32(style[ButtonDefaultInsideColor]))) - rl.DrawText(text, b.X+((b.Width/2)-(rl.MeasureText(text, textHeight)/2)), b.Y+((b.Height/2)-(textHeight/2)), textHeight, rl.GetColor(int32(style[ButtonDefaultTextColor]))) - break - - case Focused: - rl.DrawRectangle(b.X, b.Y, b.Width, b.Height, rl.GetColor(int32(style[ButtonHoverBorderColor]))) - rl.DrawRectangle(b.X+int32(style[ButtonBorderWidth]), b.Y+int32(style[ButtonBorderWidth]), b.Width-(2*int32(style[ButtonBorderWidth])), b.Height-(2*int32(style[ButtonBorderWidth])), rl.GetColor(int32(style[ButtonHoverInsideColor]))) - rl.DrawText(text, b.X+((b.Width/2)-(rl.MeasureText(text, textHeight)/2)), b.Y+((b.Height/2)-(textHeight/2)), textHeight, rl.GetColor(int32(style[ButtonHoverTextColor]))) - break - - case Pressed: - rl.DrawRectangle(b.X, b.Y, b.Width, b.Height, rl.GetColor(int32(style[ButtonPressedBorderColor]))) - rl.DrawRectangle(b.X+int32(style[ButtonBorderWidth]), b.Y+int32(style[ButtonBorderWidth]), b.Width-(2*int32(style[ButtonBorderWidth])), b.Height-(2*int32(style[ButtonBorderWidth])), rl.GetColor(int32(style[ButtonPressedInsideColor]))) - rl.DrawText(text, b.X+((b.Width/2)-(rl.MeasureText(text, textHeight)/2)), b.Y+((b.Height/2)-(textHeight/2)), textHeight, rl.GetColor(int32(style[ButtonPressedTextColor]))) - break - - default: - break - } - - if clicked { - return true - } - - return false -} - -// ToggleButton - Toggle Button element, returns true when active -func ToggleButton(bounds rl.Rectangle, text string, active bool) bool { - b := bounds.ToInt32() - state := Normal - mousePoint := rl.GetMousePosition() - - textHeight := int32(style[GlobalTextFontsize]) - textWidth := rl.MeasureText(text, textHeight) - - // Update control - if b.Width < textWidth { - b.Width = textWidth + int32(style[ToggleTextPadding]) - } - if b.Height < textHeight { - b.Height = textHeight + int32(style[ToggleTextPadding])/2 - } - - if rl.CheckCollisionPointRec(mousePoint, bounds) { - if rl.IsMouseButtonDown(rl.MouseLeftButton) { - state = Pressed - } else if rl.IsMouseButtonReleased(rl.MouseLeftButton) || rl.IsMouseButtonPressed(rl.MouseLeftButton) { - state = Normal - active = !active - } else { - state = Focused - } - } - - // Draw control - switch state { - case Normal: - if active { - rl.DrawRectangle(b.X, b.Y, b.Width, b.Height, rl.GetColor(int32(style[ToggleActiveBorderColor]))) - rl.DrawRectangle(b.X+int32(style[ToggleBorderWidth]), b.Y+int32(style[ToggleBorderWidth]), b.Width-(2*int32(style[ToggleBorderWidth])), b.Height-(2*int32(style[ToggleBorderWidth])), rl.GetColor(int32(style[ToggleActiveInsideColor]))) - rl.DrawText(text, b.X+((b.Width/2)-(rl.MeasureText(text, textHeight)/2)), b.Y+((b.Height/2)-(textHeight/2)), textHeight, rl.GetColor(int32(style[ToggleDefaultTextColor]))) - } else { - rl.DrawRectangle(b.X, b.Y, b.Width, b.Height, rl.GetColor(int32(style[ToggleDefaultBorderColor]))) - rl.DrawRectangle(b.X+int32(style[ToggleBorderWidth]), b.Y+int32(style[ToggleBorderWidth]), b.Width-(2*int32(style[ToggleBorderWidth])), b.Height-(2*int32(style[ToggleBorderWidth])), rl.GetColor(int32(style[ToggleDefaultInsideColor]))) - rl.DrawText(text, b.X+((b.Width/2)-(rl.MeasureText(text, textHeight)/2)), b.Y+((b.Height/2)-(textHeight/2)), textHeight, rl.GetColor(int32(style[ToggleDefaultTextColor]))) - } - break - case Focused: - rl.DrawRectangle(b.X, b.Y, b.Width, b.Height, rl.GetColor(int32(style[ToggleHoverBorderColor]))) - rl.DrawRectangle(b.X+int32(style[ToggleBorderWidth]), b.Y+int32(style[ToggleBorderWidth]), b.Width-(2*int32(style[ToggleBorderWidth])), b.Height-(2*int32(style[ToggleBorderWidth])), rl.GetColor(int32(style[ToggleHoverInsideColor]))) - rl.DrawText(text, b.X+((b.Width/2)-(rl.MeasureText(text, textHeight)/2)), b.Y+((b.Height/2)-(textHeight/2)), textHeight, rl.GetColor(int32(style[ToggleHoverTextColor]))) - break - case Pressed: - rl.DrawRectangle(b.X, b.Y, b.Width, b.Height, rl.GetColor(int32(style[TogglePressedBorderColor]))) - rl.DrawRectangle(b.X+int32(style[ToggleBorderWidth]), b.Y+int32(style[ToggleBorderWidth]), b.Width-(2*int32(style[ToggleBorderWidth])), b.Height-(2*int32(style[ToggleBorderWidth])), rl.GetColor(int32(style[TogglePressedInsideColor]))) - rl.DrawText(text, b.X+((b.Width/2)-(rl.MeasureText(text, textHeight)/2)), b.Y+((b.Height/2)-(textHeight/2)), textHeight, rl.GetColor(int32(style[TogglePressedTextColor]))) - break - default: - break - } - - return active -} - -// ToggleGroup - Toggle Group element, returns toggled button index -func ToggleGroup(bounds rl.Rectangle, toggleText []string, active int) int { - for i := 0; i < len(toggleText); i++ { - if i == active { - ToggleButton(rl.NewRectangle(bounds.X+float32(i)*(bounds.Width+float32(style[TogglegroupPadding])), bounds.Y, bounds.Width, bounds.Height), toggleText[i], true) - } else if ToggleButton(rl.NewRectangle(bounds.X+float32(i)*(bounds.Width+float32(style[TogglegroupPadding])), bounds.Y, bounds.Width, bounds.Height), toggleText[i], false) { - active = i - } - } - - return active -} - -// ComboBox draws a simplified version of a ComboBox allowing the user to select a string -// from a list accompanied by an N/M counter. The widget does not provide a drop-down/completion -// or any input support. -func ComboBox(bounds rl.Rectangle, comboText []string, active int) int { - // Reject invalid selections and disable rendering. - comboCount := len(comboText) - if active < 0 || active >= comboCount { - rl.TraceLog(rl.LogWarning, "ComboBox active expects 0 <= active <= %d", comboCount) - return -1 - } - - activeText := comboText[active] - - // style sizing. - textHeight := int32(style[GlobalTextFontsize]) - textWidth := rl.MeasureText(activeText, textHeight) - borderWidth := int32(style[ComboboxBorderWidth]) - textPadding := int32(style[ToggleTextPadding]) - - b := bounds.ToInt32() - if b.Width < textWidth { - b.Width = textWidth + textPadding - bounds.Width = float32(b.Width) - } - if b.Height < textHeight { - b.Height = textHeight + textPadding - bounds.Height = float32(b.Height) - } - - // Identify what the counter is going to look like with max digits so we don't resize it. - clickWidth := rl.MeasureText(fmt.Sprintf("%d/%d", comboCount, comboCount), b.Height) - - click := rl.NewRectangle(bounds.X+bounds.Width+float32(style[ComboboxPadding]), bounds.Y, float32(clickWidth), float32(b.Height)) - c := click.ToInt32() - mousePoint := rl.GetMousePosition() - state := Normal - if rl.CheckCollisionPointRec(mousePoint, bounds) || rl.CheckCollisionPointRec(mousePoint, click) { - if rl.IsMouseButtonDown(rl.MouseLeftButton) { - state = Pressed - } else if rl.IsMouseButtonReleased(rl.MouseLeftButton) || rl.IsMouseButtonPressed(rl.MouseLeftButton) { - state = Pressed - } else { - state = Focused - } - } - - // Draw control - var borderColor, insideColor, listColor, textColor rl.Color - - switch state { - case Normal: - borderColor = rl.GetColor(int32(style[ComboboxDefaultBorderColor])) - insideColor = rl.GetColor(int32(style[ComboboxDefaultInsideColor])) - listColor = rl.GetColor(int32(style[ComboboxDefaultListTextColor])) - textColor = rl.GetColor(int32(style[ComboboxDefaultTextColor])) - - case Focused: - borderColor = rl.GetColor(int32(style[ComboboxHoverBorderColor])) - insideColor = rl.GetColor(int32(style[ComboboxHoverInsideColor])) - listColor = rl.GetColor(int32(style[ComboboxHoverListTextColor])) - textColor = rl.GetColor(int32(style[ComboboxHoverTextColor])) - - case Pressed: - borderColor = rl.GetColor(int32(style[ComboboxPressedBorderColor])) - insideColor = rl.GetColor(int32(style[ComboboxPressedInsideColor])) - listColor = rl.GetColor(int32(style[ComboboxPressedListTextColor])) - textColor = rl.GetColor(int32(style[ComboboxPressedTextColor])) - - default: - rl.TraceLog(rl.LogWarning, "ComboBox in unrecognized state %d", state) - return -1 - } - - // Render the box itself - rl.DrawRectangle(b.X, b.Y, b.Width, b.Height, borderColor) - rl.DrawRectangle(b.X+borderWidth, b.Y+borderWidth, b.Width-(2*borderWidth), b.Height-(2*borderWidth), insideColor) - rl.DrawText(activeText, b.X+((b.Width/2)-(rl.MeasureText(activeText, textHeight)/2)), b.Y+((b.Height/2)-(textHeight/2)), textHeight, textColor) - - // Render the accompanying "clicks" box showing the element counter. - rl.DrawRectangle(c.X, c.Y, c.Width, c.Height, borderColor) - rl.DrawRectangle(c.X+borderWidth, c.Y+borderWidth, c.Width-(2*borderWidth), c.Height-(2*borderWidth), insideColor) - companionText := fmt.Sprintf("%d/%d", active+1, comboCount) - rl.DrawText(companionText, c.X+((c.Width/2)-(rl.MeasureText(companionText, textHeight)/2)), c.Y+((c.Height/2)-(textHeight/2)), textHeight, listColor) - - if rl.CheckCollisionPointRec(mousePoint, bounds) || rl.CheckCollisionPointRec(mousePoint, click) { - if rl.IsMouseButtonPressed(rl.MouseLeftButton) { - active++ - if active >= comboCount { - active = 0 - } - } - } - - return active -} - -// CheckBox - Check Box element, returns true when active -func CheckBox(bounds rl.Rectangle, checked bool) bool { - b := bounds.ToInt32() - state := Normal - mousePoint := rl.GetMousePosition() - - // Update control - if rl.CheckCollisionPointRec(mousePoint, bounds) { - if rl.IsMouseButtonDown(rl.MouseLeftButton) { - state = Pressed - } else if rl.IsMouseButtonReleased(rl.MouseLeftButton) || rl.IsMouseButtonPressed(rl.MouseLeftButton) { - state = Normal - checked = !checked - } else { - state = Focused - } - } - - // Draw control - switch state { - case Normal: - rl.DrawRectangle(b.X, b.Y, b.Width, b.Height, rl.GetColor(int32(style[CheckboxDefaultBorderColor]))) - rl.DrawRectangle(b.X+int32(style[ToggleBorderWidth]), b.Y+int32(style[ToggleBorderWidth]), b.Width-(2*int32(style[ToggleBorderWidth])), b.Height-(2*int32(style[ToggleBorderWidth])), rl.GetColor(int32(style[CheckboxDefaultInsideColor]))) - break - case Focused: - rl.DrawRectangle(b.X, b.Y, b.Width, b.Height, rl.GetColor(int32(style[CheckboxHoverBorderColor]))) - rl.DrawRectangle(b.X+int32(style[ToggleBorderWidth]), b.Y+int32(style[ToggleBorderWidth]), b.Width-(2*int32(style[ToggleBorderWidth])), b.Height-(2*int32(style[ToggleBorderWidth])), rl.GetColor(int32(style[CheckboxHoverInsideColor]))) - break - case Pressed: - rl.DrawRectangle(b.X, b.Y, b.Width, b.Height, rl.GetColor(int32(style[CheckboxClickBorderColor]))) - rl.DrawRectangle(b.X+int32(style[ToggleBorderWidth]), b.Y+int32(style[ToggleBorderWidth]), b.Width-(2*int32(style[ToggleBorderWidth])), b.Height-(2*int32(style[ToggleBorderWidth])), rl.GetColor(int32(style[CheckboxClickInsideColor]))) - break - default: - break - } - - if checked { - rl.DrawRectangle(b.X+int32(style[CheckboxInsideWidth]), b.Y+int32(style[CheckboxInsideWidth]), b.Width-(2*int32(style[CheckboxInsideWidth])), b.Height-(2*int32(style[CheckboxInsideWidth])), rl.GetColor(int32(style[CheckboxDefaultActiveColor]))) - } - - return checked -} - -// Slider - Slider element, returns selected value -func Slider(bounds rl.Rectangle, value, minValue, maxValue float32) float32 { - b := bounds.ToInt32() - sliderPos := float32(0) - state := Normal - - buttonTravelDistance := float32(0) - mousePoint := rl.GetMousePosition() - - // Update control - if value < minValue { - value = minValue - } else if value >= maxValue { - value = maxValue - } - - sliderPos = (value - minValue) / (maxValue - minValue) - - sliderButton := rl.RectangleInt32{} - sliderButton.Width = (b.Width-(2*int32(style[SliderButtonBorderWidth])))/10 - 8 - sliderButton.Height = b.Height - (2 * int32(style[SliderBorderWidth]+2*style[SliderButtonBorderWidth])) - - sliderButtonMinPos := b.X + int32(style[SliderBorderWidth]) + int32(style[SliderButtonBorderWidth]) - sliderButtonMaxPos := b.X + b.Width - (int32(style[SliderBorderWidth]) + int32(style[SliderButtonBorderWidth]) + sliderButton.Width) - - buttonTravelDistance = float32(sliderButtonMaxPos - sliderButtonMinPos) - - sliderButton.X = b.X + int32(style[SliderBorderWidth]) + int32(style[SliderButtonBorderWidth]) + int32(sliderPos*buttonTravelDistance) - sliderButton.Y = b.Y + int32(style[SliderBorderWidth]) + int32(style[SliderButtonBorderWidth]) - - if rl.CheckCollisionPointRec(mousePoint, bounds) { - state = Focused - - if rl.IsMouseButtonDown(rl.MouseLeftButton) { - state = Pressed - } - - if state == Pressed && rl.IsMouseButtonDown(rl.MouseLeftButton) { - sliderButton.X = int32(mousePoint.X) - sliderButton.Width/2 - - if sliderButton.X <= sliderButtonMinPos { - sliderButton.X = sliderButtonMinPos - } else if sliderButton.X >= sliderButtonMaxPos { - sliderButton.X = sliderButtonMaxPos - } - - sliderPos = float32(sliderButton.X-sliderButtonMinPos) / buttonTravelDistance - } - } else { - state = Normal - } - - // Draw control - rl.DrawRectangle(b.X, b.Y, b.Width, b.Height, rl.GetColor(int32(style[SliderBorderColor]))) - rl.DrawRectangle(b.X+int32(style[SliderBorderWidth]), b.Y+int32(style[SliderBorderWidth]), b.Width-(2*int32(style[SliderBorderWidth])), b.Height-(2*int32(style[SliderBorderWidth])), rl.GetColor(int32(style[SliderInsideColor]))) - - switch state { - case Normal: - rl.DrawRectangle(sliderButton.X, sliderButton.Y, sliderButton.Width, sliderButton.Height, rl.GetColor(int32(style[SliderDefaultColor]))) - break - case Focused: - rl.DrawRectangle(sliderButton.X, sliderButton.Y, sliderButton.Width, sliderButton.Height, rl.GetColor(int32(style[SliderHoverColor]))) - break - case Pressed: - rl.DrawRectangle(sliderButton.X, sliderButton.Y, sliderButton.Width, sliderButton.Height, rl.GetColor(int32(style[SliderActiveColor]))) - break - default: - break - } - - return minValue + (maxValue-minValue)*sliderPos -} - -// SliderBar - Slider Bar element, returns selected value -func SliderBar(bounds rl.Rectangle, value, minValue, maxValue float32) float32 { - b := bounds.ToInt32() - state := Normal - - mousePoint := rl.GetMousePosition() - - fixedValue := float32(0) - fixedMinValue := float32(0) - - fixedValue = value - minValue - maxValue = maxValue - minValue - fixedMinValue = 0 - - // Update control - if fixedValue <= fixedMinValue { - fixedValue = fixedMinValue - } else if fixedValue >= maxValue { - fixedValue = maxValue - } - - sliderBar := rl.RectangleInt32{} - - sliderBar.X = b.X + int32(style[SliderBorderWidth]) - sliderBar.Y = b.Y + int32(style[SliderBorderWidth]) - sliderBar.Width = int32((fixedValue * (float32(b.Width) - 2*float32(style[SliderBorderWidth]))) / (maxValue - fixedMinValue)) - sliderBar.Height = b.Height - 2*int32(style[SliderBorderWidth]) - - if rl.CheckCollisionPointRec(mousePoint, bounds) { - state = Focused - - if rl.IsMouseButtonDown(rl.MouseLeftButton) { - state = Pressed - - sliderBar.Width = (int32(mousePoint.X) - b.X - int32(style[SliderBorderWidth])) - - if int32(mousePoint.X) <= (b.X + int32(style[SliderBorderWidth])) { - sliderBar.Width = 0 - } else if int32(mousePoint.X) >= (b.X + b.Width - int32(style[SliderBorderWidth])) { - sliderBar.Width = b.Width - 2*int32(style[SliderBorderWidth]) - } - } - } else { - state = Normal - } - - fixedValue = (float32(sliderBar.Width) * (maxValue - fixedMinValue)) / (float32(b.Width) - 2*float32(style[SliderBorderWidth])) - - // Draw control - rl.DrawRectangle(b.X, b.Y, b.Width, b.Height, rl.GetColor(int32(style[SliderbarBorderColor]))) - rl.DrawRectangle(b.X+int32(style[SliderBorderWidth]), b.Y+int32(style[SliderBorderWidth]), b.Width-(2*int32(style[SliderBorderWidth])), b.Height-(2*int32(style[SliderBorderWidth])), rl.GetColor(int32(style[SliderbarInsideColor]))) - - switch state { - case Normal: - rl.DrawRectangle(sliderBar.X, sliderBar.Y, sliderBar.Width, sliderBar.Height, rl.GetColor(int32(style[SliderbarDefaultColor]))) - break - case Focused: - rl.DrawRectangle(sliderBar.X, sliderBar.Y, sliderBar.Width, sliderBar.Height, rl.GetColor(int32(style[SliderbarHoverColor]))) - break - case Pressed: - rl.DrawRectangle(sliderBar.X, sliderBar.Y, sliderBar.Width, sliderBar.Height, rl.GetColor(int32(style[SliderbarActiveColor]))) - break - default: - break - } - - if minValue < 0 && maxValue > 0 { - rl.DrawRectangle((b.X+int32(style[SliderBorderWidth]))-int32(minValue*(float32(b.Width-(int32(style[SliderBorderWidth])*2))/maxValue)), sliderBar.Y, 1, sliderBar.Height, rl.GetColor(int32(style[SliderbarZeroLineColor]))) - } - - return fixedValue + minValue -} - -// ProgressBar - Progress Bar element, shows current progress value -func ProgressBar(bounds rl.Rectangle, value float32) { - b := bounds.ToInt32() - if value > 1.0 { - value = 1.0 - } else if value < 0.0 { - value = 0.0 - } - - progressBar := rl.RectangleInt32{b.X + int32(style[ProgressbarBorderWidth]), b.Y + int32(style[ProgressbarBorderWidth]), b.Width - (int32(style[ProgressbarBorderWidth]) * 2), b.Height - (int32(style[ProgressbarBorderWidth]) * 2)} - progressValue := rl.RectangleInt32{b.X + int32(style[ProgressbarBorderWidth]), b.Y + int32(style[ProgressbarBorderWidth]), int32(value * float32(b.Width-int32(style[ProgressbarBorderWidth])*2)), b.Height - (int32(style[ProgressbarBorderWidth]) * 2)} - - // Draw control - rl.DrawRectangle(b.X, b.Y, b.Width, b.Height, rl.GetColor(int32(style[ProgressbarBorderColor]))) - rl.DrawRectangle(progressBar.X, progressBar.Y, progressBar.Width, progressBar.Height, rl.GetColor(int32(style[ProgressbarInsideColor]))) - rl.DrawRectangle(progressValue.X, progressValue.Y, progressValue.Width, progressValue.Height, rl.GetColor(int32(style[ProgressbarProgressColor]))) -} - -// Spinner - Spinner element, returns selected value -func Spinner(bounds rl.Rectangle, value, minValue, maxValue int) int { - b := bounds.ToInt32() - state := Normal - - mousePoint := rl.GetMousePosition() - labelBoxBound := rl.RectangleInt32{b.X + b.Width/4 + 1, b.Y, b.Width / 2, b.Height} - leftButtonBound := rl.RectangleInt32{b.X, b.Y, b.Width / 4, b.Height} - rightButtonBound := rl.RectangleInt32{b.X + b.Width - b.Width/4 + 1, b.Y, b.Width / 4, b.Height} - - textHeight := int32(style[GlobalTextFontsize]) - textWidth := rl.MeasureText(fmt.Sprintf("%d", value), textHeight) - - buttonSide := 0 - - // Update control - if rl.CheckCollisionPointRec(mousePoint, leftButtonBound.ToFloat32()) || rl.CheckCollisionPointRec(mousePoint, rightButtonBound.ToFloat32()) || rl.CheckCollisionPointRec(mousePoint, labelBoxBound.ToFloat32()) { - if rl.IsKeyDown(rl.KeyLeft) { - state = Pressed - buttonSide = 1 - - if value > minValue { - value-- - } - } else if rl.IsKeyDown(rl.KeyRight) { - state = Pressed - buttonSide = 2 - - if value < maxValue { - value++ - } - } - } - - if rl.CheckCollisionPointRec(mousePoint, leftButtonBound.ToFloat32()) { - buttonSide = 1 - state = Focused - - if rl.IsMouseButtonDown(rl.MouseLeftButton) { - if !valueSpeed { - if value > minValue { - value-- - } - valueSpeed = true - } else { - framesCounter++ - } - - state = Pressed - - if value > minValue { - if framesCounter >= 30 { - value-- - } - } - } - } else if rl.CheckCollisionPointRec(mousePoint, rightButtonBound.ToFloat32()) { - buttonSide = 2 - state = Focused - - if rl.IsMouseButtonDown(rl.MouseLeftButton) { - if !valueSpeed { - if value < maxValue { - value++ - } - valueSpeed = true - } else { - framesCounter++ - } - - state = Pressed - - if value < maxValue { - if framesCounter >= 30 { - value++ - } - } - } - } else if !rl.CheckCollisionPointRec(mousePoint, labelBoxBound.ToFloat32()) { - buttonSide = 0 - } - - if rl.IsMouseButtonUp(rl.MouseLeftButton) { - valueSpeed = false - framesCounter = 0 - } - - // Draw control - switch state { - case Normal: - rl.DrawRectangle(leftButtonBound.X, leftButtonBound.Y, leftButtonBound.Width, leftButtonBound.Height, rl.GetColor(int32(style[SpinnerDefaultButtonBorderColor]))) - rl.DrawRectangle(leftButtonBound.X+2, leftButtonBound.Y+2, leftButtonBound.Width-4, leftButtonBound.Height-4, rl.GetColor(int32(style[SpinnerDefaultButtonInsideColor]))) - - rl.DrawRectangle(rightButtonBound.X, rightButtonBound.Y, rightButtonBound.Width, rightButtonBound.Height, rl.GetColor(int32(style[SpinnerDefaultButtonBorderColor]))) - rl.DrawRectangle(rightButtonBound.X+2, rightButtonBound.Y+2, rightButtonBound.Width-4, rightButtonBound.Height-4, rl.GetColor(int32(style[SpinnerDefaultButtonInsideColor]))) - - rl.DrawText("-", leftButtonBound.X+(leftButtonBound.Width/2-(rl.MeasureText("+", textHeight))/2), leftButtonBound.Y+(leftButtonBound.Height/2-(textHeight/2)), textHeight, rl.GetColor(int32(style[SpinnerDefaultSymbolColor]))) - rl.DrawText("+", rightButtonBound.X+(rightButtonBound.Width/2-(rl.MeasureText("-", textHeight))/2), rightButtonBound.Y+(rightButtonBound.Height/2-(textHeight/2)), textHeight, rl.GetColor(int32(style[SpinnerDefaultSymbolColor]))) - - rl.DrawRectangle(labelBoxBound.X, labelBoxBound.Y, labelBoxBound.Width, labelBoxBound.Height, rl.GetColor(int32(style[SpinnerLabelBorderColor]))) - rl.DrawRectangle(labelBoxBound.X+1, labelBoxBound.Y+1, labelBoxBound.Width-2, labelBoxBound.Height-2, rl.GetColor(int32(style[SpinnerLabelInsideColor]))) - - rl.DrawText(fmt.Sprintf("%d", value), labelBoxBound.X+(labelBoxBound.Width/2-textWidth/2), labelBoxBound.Y+(labelBoxBound.Height/2-(textHeight/2)), textHeight, rl.GetColor(int32(style[SpinnerDefaultTextColor]))) - break - case Focused: - if buttonSide == 1 { - rl.DrawRectangle(leftButtonBound.X, leftButtonBound.Y, leftButtonBound.Width, leftButtonBound.Height, rl.GetColor(int32(style[SpinnerHoverButtonBorderColor]))) - rl.DrawRectangle(leftButtonBound.X+2, leftButtonBound.Y+2, leftButtonBound.Width-4, leftButtonBound.Height-4, rl.GetColor(int32(style[SpinnerHoverButtonInsideColor]))) - - rl.DrawRectangle(rightButtonBound.X, rightButtonBound.Y, rightButtonBound.Width, rightButtonBound.Height, rl.GetColor(int32(style[SpinnerDefaultButtonBorderColor]))) - rl.DrawRectangle(rightButtonBound.X+2, rightButtonBound.Y+2, rightButtonBound.Width-4, rightButtonBound.Height-4, rl.GetColor(int32(style[SpinnerDefaultButtonInsideColor]))) - - rl.DrawText("-", leftButtonBound.X+(leftButtonBound.Width/2-(rl.MeasureText("+", textHeight))/2), leftButtonBound.Y+(leftButtonBound.Height/2-(textHeight/2)), textHeight, rl.GetColor(int32(style[SpinnerHoverSymbolColor]))) - rl.DrawText("+", rightButtonBound.X+(rightButtonBound.Width/2-(rl.MeasureText("-", textHeight))/2), rightButtonBound.Y+(rightButtonBound.Height/2-(textHeight/2)), textHeight, rl.GetColor(int32(style[SpinnerDefaultSymbolColor]))) - } else if buttonSide == 2 { - rl.DrawRectangle(leftButtonBound.X, leftButtonBound.Y, leftButtonBound.Width, leftButtonBound.Height, rl.GetColor(int32(style[SpinnerDefaultButtonBorderColor]))) - rl.DrawRectangle(leftButtonBound.X+2, leftButtonBound.Y+2, leftButtonBound.Width-4, leftButtonBound.Height-4, rl.GetColor(int32(style[SpinnerDefaultButtonInsideColor]))) - - rl.DrawRectangle(rightButtonBound.X, rightButtonBound.Y, rightButtonBound.Width, rightButtonBound.Height, rl.GetColor(int32(style[SpinnerHoverButtonBorderColor]))) - rl.DrawRectangle(rightButtonBound.X+2, rightButtonBound.Y+2, rightButtonBound.Width-4, rightButtonBound.Height-4, rl.GetColor(int32(style[SpinnerHoverButtonInsideColor]))) - - rl.DrawText("-", leftButtonBound.X+(leftButtonBound.Width/2-(rl.MeasureText("+", textHeight))/2), leftButtonBound.Y+(leftButtonBound.Height/2-(textHeight/2)), textHeight, rl.GetColor(int32(style[SpinnerDefaultSymbolColor]))) - rl.DrawText("+", rightButtonBound.X+(rightButtonBound.Width/2-(rl.MeasureText("-", textHeight))/2), rightButtonBound.Y+(rightButtonBound.Height/2-(textHeight/2)), textHeight, rl.GetColor(int32(style[SpinnerHoverSymbolColor]))) - } - - rl.DrawRectangle(labelBoxBound.X, labelBoxBound.Y, labelBoxBound.Width, labelBoxBound.Height, rl.GetColor(int32(style[SpinnerLabelBorderColor]))) - rl.DrawRectangle(labelBoxBound.X+1, labelBoxBound.Y+1, labelBoxBound.Width-2, labelBoxBound.Height-2, rl.GetColor(int32(style[SpinnerLabelInsideColor]))) - - rl.DrawText(fmt.Sprintf("%d", value), labelBoxBound.X+(labelBoxBound.Width/2-textWidth/2), labelBoxBound.Y+(labelBoxBound.Height/2-(textHeight/2)), textHeight, rl.GetColor(int32(style[SpinnerHoverTextColor]))) - break - case Pressed: - if buttonSide == 1 { - rl.DrawRectangle(leftButtonBound.X, leftButtonBound.Y, leftButtonBound.Width, leftButtonBound.Height, rl.GetColor(int32(style[SpinnerPressedButtonBorderColor]))) - rl.DrawRectangle(leftButtonBound.X+2, leftButtonBound.Y+2, leftButtonBound.Width-4, leftButtonBound.Height-4, rl.GetColor(int32(style[SpinnerPressedButtonInsideColor]))) - - rl.DrawRectangle(rightButtonBound.X, rightButtonBound.Y, rightButtonBound.Width, rightButtonBound.Height, rl.GetColor(int32(style[SpinnerDefaultButtonBorderColor]))) - rl.DrawRectangle(rightButtonBound.X+2, rightButtonBound.Y+2, rightButtonBound.Width-4, rightButtonBound.Height-4, rl.GetColor(int32(style[SpinnerDefaultButtonInsideColor]))) - - rl.DrawText("-", leftButtonBound.X+(leftButtonBound.Width/2-(rl.MeasureText("+", textHeight))/2), leftButtonBound.Y+(leftButtonBound.Height/2-(textHeight/2)), textHeight, rl.GetColor(int32(style[SpinnerPressedSymbolColor]))) - rl.DrawText("+", rightButtonBound.X+(rightButtonBound.Width/2-(rl.MeasureText("-", textHeight))/2), rightButtonBound.Y+(rightButtonBound.Height/2-(textHeight/2)), textHeight, rl.GetColor(int32(style[SpinnerDefaultSymbolColor]))) - } else if buttonSide == 2 { - rl.DrawRectangle(leftButtonBound.X, leftButtonBound.Y, leftButtonBound.Width, leftButtonBound.Height, rl.GetColor(int32(style[SpinnerDefaultButtonBorderColor]))) - rl.DrawRectangle(leftButtonBound.X+2, leftButtonBound.Y+2, leftButtonBound.Width-4, leftButtonBound.Height-4, rl.GetColor(int32(style[SpinnerDefaultButtonInsideColor]))) - - rl.DrawRectangle(rightButtonBound.X, rightButtonBound.Y, rightButtonBound.Width, rightButtonBound.Height, rl.GetColor(int32(style[SpinnerPressedButtonBorderColor]))) - rl.DrawRectangle(rightButtonBound.X+2, rightButtonBound.Y+2, rightButtonBound.Width-4, rightButtonBound.Height-4, rl.GetColor(int32(style[SpinnerPressedButtonInsideColor]))) - - rl.DrawText("-", leftButtonBound.X+(leftButtonBound.Width/2-(rl.MeasureText("+", textHeight))/2), leftButtonBound.Y+(leftButtonBound.Height/2-(textHeight/2)), textHeight, rl.GetColor(int32(style[SpinnerDefaultSymbolColor]))) - rl.DrawText("+", rightButtonBound.X+(rightButtonBound.Width/2-(rl.MeasureText("-", textHeight))/2), rightButtonBound.Y+(rightButtonBound.Height/2-(textHeight/2)), textHeight, rl.GetColor(int32(style[SpinnerPressedSymbolColor]))) - } - - rl.DrawRectangle(labelBoxBound.X, labelBoxBound.Y, labelBoxBound.Width, labelBoxBound.Height, rl.GetColor(int32(style[SpinnerLabelBorderColor]))) - rl.DrawRectangle(labelBoxBound.X+1, labelBoxBound.Y+1, labelBoxBound.Width-2, labelBoxBound.Height-2, rl.GetColor(int32(style[SpinnerLabelInsideColor]))) - - rl.DrawText(fmt.Sprintf("%d", value), labelBoxBound.X+(labelBoxBound.Width/2-textWidth/2), labelBoxBound.Y+(labelBoxBound.Height/2-(textHeight/2)), textHeight, rl.GetColor(int32(style[SpinnerPressedTextColor]))) - break - default: - break - } - - return value -} - -// TextBox - Text Box element, updates input text -func TextBox(bounds rl.Rectangle, text string) string { - b := bounds.ToInt32() - state := Normal - - mousePoint := rl.GetMousePosition() - letter := int32(-1) - - // Update control - if rl.CheckCollisionPointRec(mousePoint, bounds) { - state = Focused // NOTE: PRESSED state is not used on this control - - framesCounter2++ - - letter = rl.GetKeyPressed() - if letter != -1 { - if letter >= 32 && letter < 127 { - text = fmt.Sprintf("%s%c", text, letter) - } - } - - if rl.IsKeyPressed(rl.KeyBackspace) { - if len(text) > 0 { - text = text[:len(text)-1] - } - } - } - - // Draw control - switch state { - case Normal: - rl.DrawRectangle(b.X, b.Y, b.Width, b.Height, rl.GetColor(int32(style[TextboxBorderColor]))) - rl.DrawRectangle(b.X+int32(style[TextboxBorderWidth]), b.Y+int32(style[TextboxBorderWidth]), b.Width-(int32(style[TextboxBorderWidth])*2), b.Height-(int32(style[TextboxBorderWidth])*2), rl.GetColor(int32(style[TextboxInsideColor]))) - rl.DrawText(text, b.X+2, b.Y+int32(style[TextboxBorderWidth])+b.Height/2-int32(style[TextboxTextFontsize])/2, int32(style[TextboxTextFontsize]), rl.GetColor(int32(style[TextboxTextColor]))) - break - case Focused: - rl.DrawRectangle(b.X, b.Y, b.Width, b.Height, rl.GetColor(int32(style[ToggleActiveBorderColor]))) - rl.DrawRectangle(b.X+int32(style[TextboxBorderWidth]), b.Y+int32(style[TextboxBorderWidth]), b.Width-(int32(style[TextboxBorderWidth])*2), b.Height-(int32(style[TextboxBorderWidth])*2), rl.GetColor(int32(style[TextboxInsideColor]))) - rl.DrawText(text, b.X+2, b.Y+int32(style[TextboxBorderWidth])+b.Height/2-int32(style[TextboxTextFontsize])/2, int32(style[TextboxTextFontsize]), rl.GetColor(int32(style[TextboxTextColor]))) - - if (framesCounter2/20)%2 == 0 && rl.CheckCollisionPointRec(mousePoint, bounds) { - rl.DrawRectangle(b.X+4+rl.MeasureText(text, int32(style[GlobalTextFontsize])), b.Y+2, 1, b.Height-4, rl.GetColor(int32(style[TextboxLineColor]))) - } - break - case Pressed: - break - default: - break - } - - return text -} - -// SaveGuiStyle - Save GUI style file -func SaveGuiStyle(fileName string) { - var styleFile string - for i := 0; i < len(propertyName); i++ { - styleFile += fmt.Sprintf("%-40s0x%x\n", propertyName[i], GetStyleProperty(Property(i))) - } - - ioutil.WriteFile(fileName, []byte(styleFile), 0644) -} - -// LoadGuiStyle - Load GUI style file -func LoadGuiStyle(fileName string) { - file, err := rl.OpenAsset(fileName) - if err != nil { - rl.TraceLog(rl.LogWarning, "[%s] GUI style file could not be opened", fileName) - return - } - defer file.Close() - - var lines []string - scanner := bufio.NewScanner(file) - for scanner.Scan() { - lines = append(lines, scanner.Text()) - } - - for _, line := range lines { - fields := strings.Fields(line) - if len(fields) != 2 { - continue - } - - id := fields[0] - value := fields[1] - - for i := 0; i < len(propertyName); i++ { - if id == propertyName[i] { - if strings.HasPrefix(value, "0x") { - value = value[2:] - } - - v, err := strconv.ParseInt(value, 16, 64) - if err == nil { - style[i] = int64(v) - } - } - } - } -} - -// SetStyleProperty - Set one style property -func SetStyleProperty(guiProperty Property, value int64) { - style[guiProperty] = value -} - -// GetStyleProperty - Get one style property -func GetStyleProperty(guiProperty Property) int64 { - return style[int(guiProperty)] -} diff --git a/raygui/slider.go b/raygui/slider.go new file mode 100644 index 0000000..153b867 --- /dev/null +++ b/raygui/slider.go @@ -0,0 +1,76 @@ +package raygui + +import "github.com/gen2brain/raylib-go/raylib" + +// Slider - Slider element, returns selected value +func Slider(bounds rl.Rectangle, value, minValue, maxValue float32) float32 { + b := bounds.ToInt32() + sliderPos := float32(0) + state := Normal + + buttonTravelDistance := float32(0) + mousePoint := rl.GetMousePosition() + + // Update control + if value < minValue { + value = minValue + } else if value >= maxValue { + value = maxValue + } + + sliderPos = (value - minValue) / (maxValue - minValue) + + sliderButton := rl.RectangleInt32{} + sliderButton.Width = (b.Width-(2*int32(style[SliderButtonBorderWidth])))/10 - 8 + sliderButton.Height = b.Height - (2 * int32(style[SliderBorderWidth]+2*style[SliderButtonBorderWidth])) + + sliderButtonMinPos := b.X + int32(style[SliderBorderWidth]) + int32(style[SliderButtonBorderWidth]) + sliderButtonMaxPos := b.X + b.Width - (int32(style[SliderBorderWidth]) + int32(style[SliderButtonBorderWidth]) + sliderButton.Width) + + buttonTravelDistance = float32(sliderButtonMaxPos - sliderButtonMinPos) + + sliderButton.X = b.X + int32(style[SliderBorderWidth]) + int32(style[SliderButtonBorderWidth]) + int32(sliderPos*buttonTravelDistance) + sliderButton.Y = b.Y + int32(style[SliderBorderWidth]) + int32(style[SliderButtonBorderWidth]) + + if rl.CheckCollisionPointRec(mousePoint, bounds) { + state = Focused + + if rl.IsMouseButtonDown(rl.MouseLeftButton) { + state = Pressed + } + + if state == Pressed && rl.IsMouseButtonDown(rl.MouseLeftButton) { + sliderButton.X = int32(mousePoint.X) - sliderButton.Width/2 + + if sliderButton.X <= sliderButtonMinPos { + sliderButton.X = sliderButtonMinPos + } else if sliderButton.X >= sliderButtonMaxPos { + sliderButton.X = sliderButtonMaxPos + } + + sliderPos = float32(sliderButton.X-sliderButtonMinPos) / buttonTravelDistance + } + } else { + state = Normal + } + + // Draw control + rl.DrawRectangle(b.X, b.Y, b.Width, b.Height, rl.GetColor(int32(style[SliderBorderColor]))) + rl.DrawRectangle(b.X+int32(style[SliderBorderWidth]), b.Y+int32(style[SliderBorderWidth]), b.Width-(2*int32(style[SliderBorderWidth])), b.Height-(2*int32(style[SliderBorderWidth])), rl.GetColor(int32(style[SliderInsideColor]))) + + switch state { + case Normal: + rl.DrawRectangle(sliderButton.X, sliderButton.Y, sliderButton.Width, sliderButton.Height, rl.GetColor(int32(style[SliderDefaultColor]))) + break + case Focused: + rl.DrawRectangle(sliderButton.X, sliderButton.Y, sliderButton.Width, sliderButton.Height, rl.GetColor(int32(style[SliderHoverColor]))) + break + case Pressed: + rl.DrawRectangle(sliderButton.X, sliderButton.Y, sliderButton.Width, sliderButton.Height, rl.GetColor(int32(style[SliderActiveColor]))) + break + default: + break + } + + return minValue + (maxValue-minValue)*sliderPos +} diff --git a/raygui/sliderbar.go b/raygui/sliderbar.go new file mode 100644 index 0000000..dbce8fc --- /dev/null +++ b/raygui/sliderbar.go @@ -0,0 +1,76 @@ +package raygui + +import "github.com/gen2brain/raylib-go/raylib" + +// SliderBar - Slider Bar element, returns selected value +func SliderBar(bounds rl.Rectangle, value, minValue, maxValue float32) float32 { + b := bounds.ToInt32() + state := Normal + + mousePoint := rl.GetMousePosition() + + fixedValue := float32(0) + fixedMinValue := float32(0) + + fixedValue = value - minValue + maxValue = maxValue - minValue + fixedMinValue = 0 + + // Update control + if fixedValue <= fixedMinValue { + fixedValue = fixedMinValue + } else if fixedValue >= maxValue { + fixedValue = maxValue + } + + sliderBar := rl.RectangleInt32{} + + sliderBar.X = b.X + int32(style[SliderBorderWidth]) + sliderBar.Y = b.Y + int32(style[SliderBorderWidth]) + sliderBar.Width = int32((fixedValue * (float32(b.Width) - 2*float32(style[SliderBorderWidth]))) / (maxValue - fixedMinValue)) + sliderBar.Height = b.Height - 2*int32(style[SliderBorderWidth]) + + if rl.CheckCollisionPointRec(mousePoint, bounds) { + state = Focused + + if rl.IsMouseButtonDown(rl.MouseLeftButton) { + state = Pressed + + sliderBar.Width = (int32(mousePoint.X) - b.X - int32(style[SliderBorderWidth])) + + if int32(mousePoint.X) <= (b.X + int32(style[SliderBorderWidth])) { + sliderBar.Width = 0 + } else if int32(mousePoint.X) >= (b.X + b.Width - int32(style[SliderBorderWidth])) { + sliderBar.Width = b.Width - 2*int32(style[SliderBorderWidth]) + } + } + } else { + state = Normal + } + + fixedValue = (float32(sliderBar.Width) * (maxValue - fixedMinValue)) / (float32(b.Width) - 2*float32(style[SliderBorderWidth])) + + // Draw control + rl.DrawRectangle(b.X, b.Y, b.Width, b.Height, rl.GetColor(int32(style[SliderbarBorderColor]))) + rl.DrawRectangle(b.X+int32(style[SliderBorderWidth]), b.Y+int32(style[SliderBorderWidth]), b.Width-(2*int32(style[SliderBorderWidth])), b.Height-(2*int32(style[SliderBorderWidth])), rl.GetColor(int32(style[SliderbarInsideColor]))) + + switch state { + case Normal: + rl.DrawRectangle(sliderBar.X, sliderBar.Y, sliderBar.Width, sliderBar.Height, rl.GetColor(int32(style[SliderbarDefaultColor]))) + break + case Focused: + rl.DrawRectangle(sliderBar.X, sliderBar.Y, sliderBar.Width, sliderBar.Height, rl.GetColor(int32(style[SliderbarHoverColor]))) + break + case Pressed: + rl.DrawRectangle(sliderBar.X, sliderBar.Y, sliderBar.Width, sliderBar.Height, rl.GetColor(int32(style[SliderbarActiveColor]))) + break + default: + break + } + + if minValue < 0 && maxValue > 0 { + rl.DrawRectangle((b.X+int32(style[SliderBorderWidth]))-int32(minValue*(float32(b.Width-(int32(style[SliderBorderWidth])*2))/maxValue)), sliderBar.Y, 1, sliderBar.Height, rl.GetColor(int32(style[SliderbarZeroLineColor]))) + } + + return fixedValue + minValue +} diff --git a/raygui/spinner.go b/raygui/spinner.go new file mode 100644 index 0000000..eb9a8f3 --- /dev/null +++ b/raygui/spinner.go @@ -0,0 +1,176 @@ +package raygui + +import ( + "fmt" + "github.com/gen2brain/raylib-go/raylib" +) + +// For spinner +var ( + framesCounter int + framesCounter2 int + valueSpeed bool +) + +// Spinner - Spinner element, returns selected value +func Spinner(bounds rl.Rectangle, value, minValue, maxValue int) int { + b := bounds.ToInt32() + state := Normal + + mousePoint := rl.GetMousePosition() + labelBoxBound := rl.RectangleInt32{b.X + b.Width/4 + 1, b.Y, b.Width / 2, b.Height} + leftButtonBound := rl.RectangleInt32{b.X, b.Y, b.Width / 4, b.Height} + rightButtonBound := rl.RectangleInt32{b.X + b.Width - b.Width/4 + 1, b.Y, b.Width / 4, b.Height} + + textHeight := int32(style[GlobalTextFontsize]) + textWidth := rl.MeasureText(fmt.Sprintf("%d", value), textHeight) + + buttonSide := 0 + + // Update control + if rl.CheckCollisionPointRec(mousePoint, leftButtonBound.ToFloat32()) || rl.CheckCollisionPointRec(mousePoint, rightButtonBound.ToFloat32()) || rl.CheckCollisionPointRec(mousePoint, labelBoxBound.ToFloat32()) { + if rl.IsKeyDown(rl.KeyLeft) { + state = Pressed + buttonSide = 1 + + if value > minValue { + value-- + } + } else if rl.IsKeyDown(rl.KeyRight) { + state = Pressed + buttonSide = 2 + + if value < maxValue { + value++ + } + } + } + + if rl.CheckCollisionPointRec(mousePoint, leftButtonBound.ToFloat32()) { + buttonSide = 1 + state = Focused + + if rl.IsMouseButtonDown(rl.MouseLeftButton) { + if !valueSpeed { + if value > minValue { + value-- + } + valueSpeed = true + } else { + framesCounter++ + } + + state = Pressed + + if value > minValue { + if framesCounter >= 30 { + value-- + } + } + } + } else if rl.CheckCollisionPointRec(mousePoint, rightButtonBound.ToFloat32()) { + buttonSide = 2 + state = Focused + + if rl.IsMouseButtonDown(rl.MouseLeftButton) { + if !valueSpeed { + if value < maxValue { + value++ + } + valueSpeed = true + } else { + framesCounter++ + } + + state = Pressed + + if value < maxValue { + if framesCounter >= 30 { + value++ + } + } + } + } else if !rl.CheckCollisionPointRec(mousePoint, labelBoxBound.ToFloat32()) { + buttonSide = 0 + } + + if rl.IsMouseButtonUp(rl.MouseLeftButton) { + valueSpeed = false + framesCounter = 0 + } + + // Draw control + switch state { + case Normal: + rl.DrawRectangle(leftButtonBound.X, leftButtonBound.Y, leftButtonBound.Width, leftButtonBound.Height, rl.GetColor(int32(style[SpinnerDefaultButtonBorderColor]))) + rl.DrawRectangle(leftButtonBound.X+2, leftButtonBound.Y+2, leftButtonBound.Width-4, leftButtonBound.Height-4, rl.GetColor(int32(style[SpinnerDefaultButtonInsideColor]))) + + rl.DrawRectangle(rightButtonBound.X, rightButtonBound.Y, rightButtonBound.Width, rightButtonBound.Height, rl.GetColor(int32(style[SpinnerDefaultButtonBorderColor]))) + rl.DrawRectangle(rightButtonBound.X+2, rightButtonBound.Y+2, rightButtonBound.Width-4, rightButtonBound.Height-4, rl.GetColor(int32(style[SpinnerDefaultButtonInsideColor]))) + + rl.DrawText("-", leftButtonBound.X+(leftButtonBound.Width/2-(rl.MeasureText("+", textHeight))/2), leftButtonBound.Y+(leftButtonBound.Height/2-(textHeight/2)), textHeight, rl.GetColor(int32(style[SpinnerDefaultSymbolColor]))) + rl.DrawText("+", rightButtonBound.X+(rightButtonBound.Width/2-(rl.MeasureText("-", textHeight))/2), rightButtonBound.Y+(rightButtonBound.Height/2-(textHeight/2)), textHeight, rl.GetColor(int32(style[SpinnerDefaultSymbolColor]))) + + rl.DrawRectangle(labelBoxBound.X, labelBoxBound.Y, labelBoxBound.Width, labelBoxBound.Height, rl.GetColor(int32(style[SpinnerLabelBorderColor]))) + rl.DrawRectangle(labelBoxBound.X+1, labelBoxBound.Y+1, labelBoxBound.Width-2, labelBoxBound.Height-2, rl.GetColor(int32(style[SpinnerLabelInsideColor]))) + + rl.DrawText(fmt.Sprintf("%d", value), labelBoxBound.X+(labelBoxBound.Width/2-textWidth/2), labelBoxBound.Y+(labelBoxBound.Height/2-(textHeight/2)), textHeight, rl.GetColor(int32(style[SpinnerDefaultTextColor]))) + break + case Focused: + if buttonSide == 1 { + rl.DrawRectangle(leftButtonBound.X, leftButtonBound.Y, leftButtonBound.Width, leftButtonBound.Height, rl.GetColor(int32(style[SpinnerHoverButtonBorderColor]))) + rl.DrawRectangle(leftButtonBound.X+2, leftButtonBound.Y+2, leftButtonBound.Width-4, leftButtonBound.Height-4, rl.GetColor(int32(style[SpinnerHoverButtonInsideColor]))) + + rl.DrawRectangle(rightButtonBound.X, rightButtonBound.Y, rightButtonBound.Width, rightButtonBound.Height, rl.GetColor(int32(style[SpinnerDefaultButtonBorderColor]))) + rl.DrawRectangle(rightButtonBound.X+2, rightButtonBound.Y+2, rightButtonBound.Width-4, rightButtonBound.Height-4, rl.GetColor(int32(style[SpinnerDefaultButtonInsideColor]))) + + rl.DrawText("-", leftButtonBound.X+(leftButtonBound.Width/2-(rl.MeasureText("+", textHeight))/2), leftButtonBound.Y+(leftButtonBound.Height/2-(textHeight/2)), textHeight, rl.GetColor(int32(style[SpinnerHoverSymbolColor]))) + rl.DrawText("+", rightButtonBound.X+(rightButtonBound.Width/2-(rl.MeasureText("-", textHeight))/2), rightButtonBound.Y+(rightButtonBound.Height/2-(textHeight/2)), textHeight, rl.GetColor(int32(style[SpinnerDefaultSymbolColor]))) + } else if buttonSide == 2 { + rl.DrawRectangle(leftButtonBound.X, leftButtonBound.Y, leftButtonBound.Width, leftButtonBound.Height, rl.GetColor(int32(style[SpinnerDefaultButtonBorderColor]))) + rl.DrawRectangle(leftButtonBound.X+2, leftButtonBound.Y+2, leftButtonBound.Width-4, leftButtonBound.Height-4, rl.GetColor(int32(style[SpinnerDefaultButtonInsideColor]))) + + rl.DrawRectangle(rightButtonBound.X, rightButtonBound.Y, rightButtonBound.Width, rightButtonBound.Height, rl.GetColor(int32(style[SpinnerHoverButtonBorderColor]))) + rl.DrawRectangle(rightButtonBound.X+2, rightButtonBound.Y+2, rightButtonBound.Width-4, rightButtonBound.Height-4, rl.GetColor(int32(style[SpinnerHoverButtonInsideColor]))) + + rl.DrawText("-", leftButtonBound.X+(leftButtonBound.Width/2-(rl.MeasureText("+", textHeight))/2), leftButtonBound.Y+(leftButtonBound.Height/2-(textHeight/2)), textHeight, rl.GetColor(int32(style[SpinnerDefaultSymbolColor]))) + rl.DrawText("+", rightButtonBound.X+(rightButtonBound.Width/2-(rl.MeasureText("-", textHeight))/2), rightButtonBound.Y+(rightButtonBound.Height/2-(textHeight/2)), textHeight, rl.GetColor(int32(style[SpinnerHoverSymbolColor]))) + } + + rl.DrawRectangle(labelBoxBound.X, labelBoxBound.Y, labelBoxBound.Width, labelBoxBound.Height, rl.GetColor(int32(style[SpinnerLabelBorderColor]))) + rl.DrawRectangle(labelBoxBound.X+1, labelBoxBound.Y+1, labelBoxBound.Width-2, labelBoxBound.Height-2, rl.GetColor(int32(style[SpinnerLabelInsideColor]))) + + rl.DrawText(fmt.Sprintf("%d", value), labelBoxBound.X+(labelBoxBound.Width/2-textWidth/2), labelBoxBound.Y+(labelBoxBound.Height/2-(textHeight/2)), textHeight, rl.GetColor(int32(style[SpinnerHoverTextColor]))) + break + case Pressed: + if buttonSide == 1 { + rl.DrawRectangle(leftButtonBound.X, leftButtonBound.Y, leftButtonBound.Width, leftButtonBound.Height, rl.GetColor(int32(style[SpinnerPressedButtonBorderColor]))) + rl.DrawRectangle(leftButtonBound.X+2, leftButtonBound.Y+2, leftButtonBound.Width-4, leftButtonBound.Height-4, rl.GetColor(int32(style[SpinnerPressedButtonInsideColor]))) + + rl.DrawRectangle(rightButtonBound.X, rightButtonBound.Y, rightButtonBound.Width, rightButtonBound.Height, rl.GetColor(int32(style[SpinnerDefaultButtonBorderColor]))) + rl.DrawRectangle(rightButtonBound.X+2, rightButtonBound.Y+2, rightButtonBound.Width-4, rightButtonBound.Height-4, rl.GetColor(int32(style[SpinnerDefaultButtonInsideColor]))) + + rl.DrawText("-", leftButtonBound.X+(leftButtonBound.Width/2-(rl.MeasureText("+", textHeight))/2), leftButtonBound.Y+(leftButtonBound.Height/2-(textHeight/2)), textHeight, rl.GetColor(int32(style[SpinnerPressedSymbolColor]))) + rl.DrawText("+", rightButtonBound.X+(rightButtonBound.Width/2-(rl.MeasureText("-", textHeight))/2), rightButtonBound.Y+(rightButtonBound.Height/2-(textHeight/2)), textHeight, rl.GetColor(int32(style[SpinnerDefaultSymbolColor]))) + } else if buttonSide == 2 { + rl.DrawRectangle(leftButtonBound.X, leftButtonBound.Y, leftButtonBound.Width, leftButtonBound.Height, rl.GetColor(int32(style[SpinnerDefaultButtonBorderColor]))) + rl.DrawRectangle(leftButtonBound.X+2, leftButtonBound.Y+2, leftButtonBound.Width-4, leftButtonBound.Height-4, rl.GetColor(int32(style[SpinnerDefaultButtonInsideColor]))) + + rl.DrawRectangle(rightButtonBound.X, rightButtonBound.Y, rightButtonBound.Width, rightButtonBound.Height, rl.GetColor(int32(style[SpinnerPressedButtonBorderColor]))) + rl.DrawRectangle(rightButtonBound.X+2, rightButtonBound.Y+2, rightButtonBound.Width-4, rightButtonBound.Height-4, rl.GetColor(int32(style[SpinnerPressedButtonInsideColor]))) + + rl.DrawText("-", leftButtonBound.X+(leftButtonBound.Width/2-(rl.MeasureText("+", textHeight))/2), leftButtonBound.Y+(leftButtonBound.Height/2-(textHeight/2)), textHeight, rl.GetColor(int32(style[SpinnerDefaultSymbolColor]))) + rl.DrawText("+", rightButtonBound.X+(rightButtonBound.Width/2-(rl.MeasureText("-", textHeight))/2), rightButtonBound.Y+(rightButtonBound.Height/2-(textHeight/2)), textHeight, rl.GetColor(int32(style[SpinnerPressedSymbolColor]))) + } + + rl.DrawRectangle(labelBoxBound.X, labelBoxBound.Y, labelBoxBound.Width, labelBoxBound.Height, rl.GetColor(int32(style[SpinnerLabelBorderColor]))) + rl.DrawRectangle(labelBoxBound.X+1, labelBoxBound.Y+1, labelBoxBound.Width-2, labelBoxBound.Height-2, rl.GetColor(int32(style[SpinnerLabelInsideColor]))) + + rl.DrawText(fmt.Sprintf("%d", value), labelBoxBound.X+(labelBoxBound.Width/2-textWidth/2), labelBoxBound.Y+(labelBoxBound.Height/2-(textHeight/2)), textHeight, rl.GetColor(int32(style[SpinnerPressedTextColor]))) + break + default: + break + } + + return value +} diff --git a/raygui/style.go b/raygui/style.go new file mode 100644 index 0000000..f97efe1 --- /dev/null +++ b/raygui/style.go @@ -0,0 +1,414 @@ +// GUI element appearance can be dynamically configured through Property values, the set of which +// forms a theme called the Style. +package raygui + +import ( + "bufio" + "fmt" + rl "github.com/gen2brain/raylib-go/raylib" + "io/ioutil" + "strconv" + "strings" +) + +// Property - GUI property +type Property int32 + +// GUI properties enumeration +const ( + GlobalBaseColor Property = iota + GlobalBorderColor + GlobalTextColor + GlobalTextFontsize + GlobalBorderWidth + GlobalBackgroundColor + GlobalLinesColor + LabelBorderWidth + LabelTextColor + LabelTextPadding + ButtonBorderWidth + ButtonTextPadding + ButtonDefaultBorderColor + ButtonDefaultInsideColor + ButtonDefaultTextColor + ButtonHoverBorderColor + ButtonHoverInsideColor + ButtonHoverTextColor + ButtonPressedBorderColor + ButtonPressedInsideColor + ButtonPressedTextColor + ToggleTextPadding + ToggleBorderWidth + ToggleDefaultBorderColor + ToggleDefaultInsideColor + ToggleDefaultTextColor + ToggleHoverBorderColor + ToggleHoverInsideColor + ToggleHoverTextColor + TogglePressedBorderColor + TogglePressedInsideColor + TogglePressedTextColor + ToggleActiveBorderColor + ToggleActiveInsideColor + ToggleActiveTextColor + TogglegroupPadding + SliderBorderWidth + SliderButtonBorderWidth + SliderBorderColor + SliderInsideColor + SliderDefaultColor + SliderHoverColor + SliderActiveColor + SliderbarBorderColor + SliderbarInsideColor + SliderbarDefaultColor + SliderbarHoverColor + SliderbarActiveColor + SliderbarZeroLineColor + ProgressbarBorderColor + ProgressbarInsideColor + ProgressbarProgressColor + ProgressbarBorderWidth + SpinnerLabelBorderColor + SpinnerLabelInsideColor + SpinnerDefaultButtonBorderColor + SpinnerDefaultButtonInsideColor + SpinnerDefaultSymbolColor + SpinnerDefaultTextColor + SpinnerHoverButtonBorderColor + SpinnerHoverButtonInsideColor + SpinnerHoverSymbolColor + SpinnerHoverTextColor + SpinnerPressedButtonBorderColor + SpinnerPressedButtonInsideColor + SpinnerPressedSymbolColor + SpinnerPressedTextColor + ComboboxPadding + boundsWidth + boundsHeight + ComboboxBorderWidth + ComboboxDefaultBorderColor + ComboboxDefaultInsideColor + ComboboxDefaultTextColor + ComboboxDefaultListTextColor + ComboboxHoverBorderColor + ComboboxHoverInsideColor + ComboboxHoverTextColor + ComboboxHoverListTextColor + ComboboxPressedBorderColor + ComboboxPressedInsideColor + ComboboxPressedTextColor + ComboboxPressedListBorderColor + ComboboxPressedListInsideColor + ComboboxPressedListTextColor + CheckboxDefaultBorderColor + CheckboxDefaultInsideColor + CheckboxHoverBorderColor + CheckboxHoverInsideColor + CheckboxClickBorderColor + CheckboxClickInsideColor + CheckboxDefaultActiveColor + CheckboxInsideWidth + TextboxBorderWidth + TextboxBorderColor + TextboxInsideColor + TextboxTextColor + TextboxLineColor + TextboxTextFontsize + + // Add new properties above. + NumProperties +) + +// GUI property names (to read/write style text files) +var propertyName = [NumProperties]string{ + "GLOBAL_BASE_COLOR", + "GLOBAL_BORDER_COLOR", + "GLOBAL_TEXT_COLOR", + "GLOBAL_TEXT_FONTSIZE", + "GLOBAL_BORDER_WIDTH", + "BACKGROUND_COLOR", + "LINES_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", +} + +// Current GUI style (default light). +var style = [NumProperties]int64{ + 0xf5f5f5ff, // GLOBAL_BASE_COLOR + 0xf5f5f5ff, // GLOBAL_BORDER_COLOR + 0xf5f5f5ff, // GLOBAL_TEXT_COLOR + 10, // GLOBAL_TEXT_FONTSIZE + 1, // GLOBAL_BORDER_WIDTH + 0xf5f5f5ff, // BACKGROUND_COLOR + 0x90abb5ff, // LINES_COLOR + 1, // LABEL_BORDER_WIDTH + 0x4d4d4dff, // 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 + 0x4d4d4dff, // BUTTON_DEFAULT_TEXT_COLOR + 0xc8c8c8ff, // BUTTON_HOVER_BORDER_COLOR + 0xffffffff, // BUTTON_HOVER_INSIDE_COLOR + 0x868686ff, // 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 + 20, // 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 + 0xbcecffff, // CHECKBOX_STATUS_ACTIVE_COLOR + 1, // 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 +} + +// LoadGuiStyle will load a GUI style from a file. See SaveGuiStyle. +func LoadGuiStyle(fileName string) { + file, err := rl.OpenAsset(fileName) + if err != nil { + rl.TraceLog(rl.LogWarning, "[%s] GUI style file could not be opened: %w", fileName, err) + return + } + defer file.Close() + + var lines []string + scanner := bufio.NewScanner(file) + for scanner.Scan() { + lines = append(lines, scanner.Text()) + } + + for _, line := range lines { + fields := strings.Fields(line) + if len(fields) != 2 { + continue + } + + id := fields[0] + value := fields[1] + + for i := 0; i < len(propertyName); i++ { + if id == propertyName[i] { + if strings.HasPrefix(value, "0x") { + value = value[2:] + } + + v, err := strconv.ParseInt(value, 16, 64) + if err == nil { + style[i] = int64(v) + } + } + } + } +} + +// SaveGuiStyle will write the current GUI style to a file in a format suitable for loading via LoadGuiStyle. +func SaveGuiStyle(fileName string) { + var styleFile string + for i := 0; i < len(propertyName); i++ { + styleFile += fmt.Sprintf("%-40s0x%x\n", propertyName[i], GetStyleProperty(Property(i))) + } + + if err := ioutil.WriteFile(fileName, []byte(styleFile), 0644); err != nil { + rl.TraceLog(rl.LogWarning, "[%s] GUI style file could not be written: %w", fileName, err) + } +} + +// SetStyleProperty - Set one style property +func SetStyleProperty(guiProperty Property, value int64) { + style[guiProperty] = value +} + +// GetStyleProperty - Get one style property +func GetStyleProperty(guiProperty Property) int64 { + return style[int(guiProperty)] +} + +// BackgroundColor will return the current background color +func BackgroundColor() rl.Color { + return rl.GetColor(int32(style[GlobalBackgroundColor])) +} + +// LinesColor will return the current color for lines +func LinesColor() rl.Color { + return rl.GetColor(int32(style[GlobalLinesColor])) +} + +// TextColor will return the current color for normal state +func TextColor() rl.Color { + return rl.GetColor(int32(style[GlobalTextColor])) +} + +// GetStyle32 will return the int32 for a given property of the current style +func GetStyle32(property Property) int32 { + return int32(style[property]) +} + +// GetPropColor will return the Color value for a given property of the current style +func GetStyleColor(property Property) rl.Color { + return rl.GetColor(int32(style[property])) +} + diff --git a/raygui/textbox.go b/raygui/textbox.go new file mode 100644 index 0000000..e0e356e --- /dev/null +++ b/raygui/textbox.go @@ -0,0 +1,59 @@ +package raygui + +import ( + "fmt" + "github.com/gen2brain/raylib-go/raylib" +) + +// TextBox - Text Box element, updates input text +func TextBox(bounds rl.Rectangle, text string) string { + b := bounds.ToInt32() + state := Normal + + mousePoint := rl.GetMousePosition() + letter := int32(-1) + + // Update control + if rl.CheckCollisionPointRec(mousePoint, bounds) { + state = Focused // NOTE: PRESSED state is not used on this control + + framesCounter2++ + + letter = rl.GetKeyPressed() + if letter != -1 { + if letter >= 32 && letter < 127 { + text = fmt.Sprintf("%s%c", text, letter) + } + } + + if rl.IsKeyPressed(rl.KeyBackspace) { + if len(text) > 0 { + text = text[:len(text)-1] + } + } + } + + // Draw control + switch state { + case Normal: + rl.DrawRectangle(b.X, b.Y, b.Width, b.Height, rl.GetColor(int32(style[TextboxBorderColor]))) + rl.DrawRectangle(b.X+int32(style[TextboxBorderWidth]), b.Y+int32(style[TextboxBorderWidth]), b.Width-(int32(style[TextboxBorderWidth])*2), b.Height-(int32(style[TextboxBorderWidth])*2), rl.GetColor(int32(style[TextboxInsideColor]))) + rl.DrawText(text, b.X+2, b.Y+int32(style[TextboxBorderWidth])+b.Height/2-int32(style[TextboxTextFontsize])/2, int32(style[TextboxTextFontsize]), rl.GetColor(int32(style[TextboxTextColor]))) + break + case Focused: + rl.DrawRectangle(b.X, b.Y, b.Width, b.Height, rl.GetColor(int32(style[ToggleActiveBorderColor]))) + rl.DrawRectangle(b.X+int32(style[TextboxBorderWidth]), b.Y+int32(style[TextboxBorderWidth]), b.Width-(int32(style[TextboxBorderWidth])*2), b.Height-(int32(style[TextboxBorderWidth])*2), rl.GetColor(int32(style[TextboxInsideColor]))) + rl.DrawText(text, b.X+2, b.Y+int32(style[TextboxBorderWidth])+b.Height/2-int32(style[TextboxTextFontsize])/2, int32(style[TextboxTextFontsize]), rl.GetColor(int32(style[TextboxTextColor]))) + + if (framesCounter2/20)%2 == 0 && rl.CheckCollisionPointRec(mousePoint, bounds) { + rl.DrawRectangle(b.X+4+rl.MeasureText(text, int32(style[GlobalTextFontsize])), b.Y+2, 1, b.Height-4, rl.GetColor(int32(style[TextboxLineColor]))) + } + break + case Pressed: + break + default: + break + } + + return text +} diff --git a/raygui/togglebutton.go b/raygui/togglebutton.go new file mode 100644 index 0000000..a9278c1 --- /dev/null +++ b/raygui/togglebutton.go @@ -0,0 +1,61 @@ +package raygui + +import "github.com/gen2brain/raylib-go/raylib" + +// ToggleButton - Toggle Button element, returns true when active +func ToggleButton(bounds rl.Rectangle, text string, active bool) bool { + b := bounds.ToInt32() + state := Normal + mousePoint := rl.GetMousePosition() + + textHeight := int32(style[GlobalTextFontsize]) + textWidth := rl.MeasureText(text, textHeight) + + // Update control + if b.Width < textWidth { + b.Width = textWidth + int32(style[ToggleTextPadding]) + } + if b.Height < textHeight { + b.Height = textHeight + int32(style[ToggleTextPadding])/2 + } + + if rl.CheckCollisionPointRec(mousePoint, bounds) { + if rl.IsMouseButtonDown(rl.MouseLeftButton) { + state = Pressed + } else if rl.IsMouseButtonReleased(rl.MouseLeftButton) || rl.IsMouseButtonPressed(rl.MouseLeftButton) { + state = Normal + active = !active + } else { + state = Focused + } + } + + // Draw control + switch state { + case Normal: + if active { + rl.DrawRectangle(b.X, b.Y, b.Width, b.Height, rl.GetColor(int32(style[ToggleActiveBorderColor]))) + rl.DrawRectangle(b.X+int32(style[ToggleBorderWidth]), b.Y+int32(style[ToggleBorderWidth]), b.Width-(2*int32(style[ToggleBorderWidth])), b.Height-(2*int32(style[ToggleBorderWidth])), rl.GetColor(int32(style[ToggleActiveInsideColor]))) + rl.DrawText(text, b.X+((b.Width/2)-(rl.MeasureText(text, textHeight)/2)), b.Y+((b.Height/2)-(textHeight/2)), textHeight, rl.GetColor(int32(style[ToggleDefaultTextColor]))) + } else { + rl.DrawRectangle(b.X, b.Y, b.Width, b.Height, rl.GetColor(int32(style[ToggleDefaultBorderColor]))) + rl.DrawRectangle(b.X+int32(style[ToggleBorderWidth]), b.Y+int32(style[ToggleBorderWidth]), b.Width-(2*int32(style[ToggleBorderWidth])), b.Height-(2*int32(style[ToggleBorderWidth])), rl.GetColor(int32(style[ToggleDefaultInsideColor]))) + rl.DrawText(text, b.X+((b.Width/2)-(rl.MeasureText(text, textHeight)/2)), b.Y+((b.Height/2)-(textHeight/2)), textHeight, rl.GetColor(int32(style[ToggleDefaultTextColor]))) + } + break + case Focused: + rl.DrawRectangle(b.X, b.Y, b.Width, b.Height, rl.GetColor(int32(style[ToggleHoverBorderColor]))) + rl.DrawRectangle(b.X+int32(style[ToggleBorderWidth]), b.Y+int32(style[ToggleBorderWidth]), b.Width-(2*int32(style[ToggleBorderWidth])), b.Height-(2*int32(style[ToggleBorderWidth])), rl.GetColor(int32(style[ToggleHoverInsideColor]))) + rl.DrawText(text, b.X+((b.Width/2)-(rl.MeasureText(text, textHeight)/2)), b.Y+((b.Height/2)-(textHeight/2)), textHeight, rl.GetColor(int32(style[ToggleHoverTextColor]))) + break + case Pressed: + rl.DrawRectangle(b.X, b.Y, b.Width, b.Height, rl.GetColor(int32(style[TogglePressedBorderColor]))) + rl.DrawRectangle(b.X+int32(style[ToggleBorderWidth]), b.Y+int32(style[ToggleBorderWidth]), b.Width-(2*int32(style[ToggleBorderWidth])), b.Height-(2*int32(style[ToggleBorderWidth])), rl.GetColor(int32(style[TogglePressedInsideColor]))) + rl.DrawText(text, b.X+((b.Width/2)-(rl.MeasureText(text, textHeight)/2)), b.Y+((b.Height/2)-(textHeight/2)), textHeight, rl.GetColor(int32(style[TogglePressedTextColor]))) + break + default: + break + } + + return active +} diff --git a/raygui/togglegroup.go b/raygui/togglegroup.go new file mode 100644 index 0000000..376e0c1 --- /dev/null +++ b/raygui/togglegroup.go @@ -0,0 +1,16 @@ +package raygui + +import "github.com/gen2brain/raylib-go/raylib" + +// ToggleGroup - Toggle Group element, returns toggled button index +func ToggleGroup(bounds rl.Rectangle, toggleText []string, active int) int { + for i := 0; i < len(toggleText); i++ { + if i == active { + ToggleButton(rl.NewRectangle(bounds.X+float32(i)*(bounds.Width+float32(style[TogglegroupPadding])), bounds.Y, bounds.Width, bounds.Height), toggleText[i], true) + } else if ToggleButton(rl.NewRectangle(bounds.X+float32(i)*(bounds.Width+float32(style[TogglegroupPadding])), bounds.Y, bounds.Width, bounds.Height), toggleText[i], false) { + active = i + } + } + + return active +}