Gama C Library
Gama C API Documentation
scale.h
Go to the documentation of this file.
1/**
2 * @file widgets/scale.h
3 * @brief Defines the theme and functionality for a scale (slider) widget.
4 *
5 * This file provides structures for customizing the appearance of a slider
6 * control and a function to render an interactive slider that allows users
7 * to select a value within a range.
8 */
9#pragma once
10
11#include "../animate.h"
12#include "../collision.h"
13#include "../draw.h"
14
15/**
16 * @brief Structure defining the visual theme for a scale (slider) widget.
17 */
18typedef struct {
19 int enabled; /**< Whether the scale is enabled for interaction (1) or disabled (0). */
20
21 double scale; /**< Overall widget scale when normal. */
22
23 gmColor background; /**< Track background color when normal. */
24 gmColor border; /**< Track border color when normal. */
25
26 struct {
27 double scale; /**< Scale factor when focused/hovered. */
28 gmColor border; /**< Border color when focused/hovered. */
29 } focussed; /**< Theme properties when the scale is focused or hovered. */
30
31 struct {
32 double scale; /**< Scale factor when active (being dragged). */
33 gmColor border; /**< Border color when active. */
34 } active; /**< Theme properties when the scale is active (mouse button down on it). */
35
36 gmColor knob; /**< Knob color. */
37 gmColor knob_border; /**< Knob border color. */
38
39 double border_width; /**< Track border thickness. */
40 double step; /**< Step size for discrete values (0.0 means allow any value between 0 and 1). */
42
43/**
44 * @brief Global scale theme instance with default values.
45 */
46gmwScaleTheme gmwScale = {.enabled = 1,
47 .scale = 1.0,
48
49 .background = 0x3A2A3AE0,
50 .border = 0x7F4F7FFF,
51
52 .focussed = {.scale = 1.03, .border = 0xAA77AAFF},
53 .active = {.scale = 0.97, .border = 0x7F4F7FFF},
54
55 .knob = 0xAA77AAFF,
56 .knob_border = 0x6F3F6FFF,
57
58 .border_width = 0.01,
59 .step = 0.0};
60
61/**
62 * @brief Creates and renders an animated scale (slider) widget that can be
63 * manipulated with the mouse.
64 *
65 * This function draws a slider, tracks mouse interaction to update its value,
66 * and animates the knob's position.
67 *
68 * @param x The x-coordinate of the scale's center.
69 * @param y The y-coordinate of the scale's center.
70 * @param width The width of the scale track.
71 * @param height The height of the scale track.
72 * @param value Pointer to a double to store the current scale value (0.0
73 * to 1.0). This value is updated by user interaction.
74 * @param anim Pointer to a double for the animated visual position of the knob.
75 * If NULL, `value` is used for the knob's position (non-animated).
76 * @return 1 if the scale is currently being actively manipulated (mouse button down and hovering),
77 * 0 otherwise.
78 */
79int gmw_scale_anim(double x, double y, double width, double height,
80 double *value, double *anim) {
81
82 if (value == NULL)
83 return 0;
84 if (*value < 0)
85 *value = 0;
86 if (*value > 1)
87 *value = 1;
88 if (anim != NULL && (*anim > 1 || *anim < 0))
89 *anim = *value;
90
91 int enabled = gmwScale.enabled;
92
93 // Hover test uses full widget size (logical width/height)
94 int hovered = enabled && gm_mouse_in_rect(x, y, width, height);
95 int active = enabled && gm_mouse.down && hovered;
96
97 if (anim == NULL)
98 anim = value;
99 else
100 gm_anim_ease_out_quad(anim, (double)(*value), 0.05);
101
102 // Visual scale / border
103 double scale = 1.0;
104 gmColor border = gmwScale.border;
105 if (active) {
106 scale = gmwScale.active.scale;
107 border = gmwScale.active.border;
108 } else if (hovered) {
109 scale = gmwScale.focussed.scale;
110 border = gmwScale.focussed.border;
111 } else {
112 scale = gmwScale.scale;
113 }
114
115 // Draw sizes (scaled visually)
116 double sw = width * scale;
117 double sh = height * scale;
118
119 // Draw track border
120 gm_draw_rectangle(x, y, sw, sh, border);
121
122 // Track inner size (for knob movement)
123 double track_w = sw - gmwScale.border_width * 2;
124 double track_h = sh - gmwScale.border_width * 2;
125
126 // Draw track
127 gm_draw_rectangle(x, y, track_w, track_h, gmwScale.background);
128
129 // Orientation
130 int horizontal = (width >= height);
131
132 // Handle dragging along logical track (not scaled)
133 if (active) {
134 if (horizontal) {
135 double left = x - width * 0.5 + gmwScale.border_width;
136 double rel =
137 (gm_mouse.position.x - left) / (width - gmwScale.border_width * 2);
138 if (rel < 0.0)
139 rel = 0.0;
140 if (rel > 1.0)
141 rel = 1.0;
142 if (gmwScale.step > 0.0)
143 rel = ((int)(rel / gmwScale.step + 0.5)) * gmwScale.step;
144 *value = rel;
145 } else {
146 double bottom = y - height * 0.5 + gmwScale.border_width;
147 double rel =
148 (gm_mouse.position.y - bottom) / (height - gmwScale.border_width * 2);
149 if (rel < 0.0)
150 rel = 0.0;
151 if (rel > 1.0)
152 rel = 1.0;
153 if (gmwScale.step > 0.0)
154 rel = ((int)(rel / gmwScale.step + 0.5)) * gmwScale.step;
155 *value = rel;
156 }
157 }
158
159 // Draw knob
160 double knob_size = (horizontal ? sh : sw) * 1.5;
161 double knob_x, knob_y;
162
163 if (horizontal) {
164 double left = x - sw * 0.5 + knob_size * 0.5;
165 double right = x + sw * 0.5 - knob_size * 0.5;
166 knob_x = left + (*anim) * (right - left);
167 knob_y = y;
168 } else {
169 double bottom = y - sh * 0.5 + knob_size * 0.5;
170 double top = y + sh * 0.5 - knob_size * 0.5;
171 knob_y = bottom + (*anim) * (top - bottom);
172 knob_x = x;
173 }
174
175 // Draw knob border
176 gm_draw_rectangle(knob_x, knob_y, knob_size + gmwScale.border_width * 2,
177 knob_size + gmwScale.border_width * 2,
178 gmwScale.knob_border);
179
180 // Draw knob
181 gm_draw_rectangle(knob_x, knob_y, knob_size, knob_size, gmwScale.knob);
182
183 return active;
184}
185
186/**
187 * @brief Creates and renders a scale (slider) widget that can be manipulated
188 * with the mouse (non-animated version).
189 *
190 * This is a simplified wrapper around `gmw_scale_anim` that does not use
191 * a separate animated visual position, causing the knob to snap to the
192 * current value.
193 *
194 * @param x The x-coordinate of the scale's center.
195 * @param y The y-coordinate of the scale's center.
196 * @param width The width of the scale track.
197 * @param height The height of the scale track.
198 * @param value Pointer to a double to store the current scale value (0.0
199 * to 1.0).
200 * @return 1 if the scale is currently being actively manipulated (mouse button down and hovering),
201 * 0 otherwise.
202 */
203static inline int gmw_scale(double x, double y, double width, double height,
204 double *value) {
205 return gmw_scale_anim(x, y, width, height, value, NULL);
206}
Provides utility functions for animating numerical values using various easing effects.
void gm_anim_ease_out_quad(double *value, const double target, double t)
Animates a value towards a target with a quadratic ease-out effect.
Definition animate.h:56
Defines collision structures and provides functions for 2D collision detection.
int gm_mouse_in_rect(const double x, const double y, const double w, const double h)
Checks if the mouse cursor is currently within a given rectangular area.
Definition collision.h:172
uint32_t gmColor
Type definition for color values, stored as a 32-bit unsigned integer. The color components are packe...
Definition color.h:13
Functions for drawing shapes, text, and images.
int32_t gm_draw_rectangle(double x, double y, double w, double h, gmColor c)
Draws a rectangle centered at a point.
Definition draw.h:57
struct _gmMouse gm_mouse
Definition mouse.h:32
int gmw_scale_anim(double x, double y, double width, double height, double *value, double *anim)
Creates and renders an animated scale (slider) widget that can be manipulated with the mouse.
Definition scale.h:79
gmwScaleTheme gmwScale
Global scale theme instance with default values.
Definition scale.h:46
Structure defining the visual theme for a scale (slider) widget.
Definition scale.h:18
gmColor knob_border
Definition scale.h:37
gmColor border
Definition scale.h:24
gmColor background
Definition scale.h:23
double step
Definition scale.h:40
int enabled
Definition scale.h:19
double border_width
Definition scale.h:39
gmColor knob
Definition scale.h:36
double scale
Definition scale.h:21