libgui 3.00
libgui is a GUI library for the GameCube, Wii, and Wii U
 
Loading...
Searching...
No Matches
GuiShape.cpp
1/****************************************************************************
2 * libgui
3 * Daryl Borth 2026
4 * GuiShape.cpp
5 ***************************************************************************/
6
7#include "Gui.h"
8
9// A change of state blends through this many looks. Each is a mesh the cache can share between
10// every shape making the same change, so only the first one to fade pays to build them.
11static const int kBlendSteps = 4;
12
13GuiShape::GuiShape(int w, int h) :
14 kind(SHAPE::RECTANGLE), corners(0.0f), transition(0.12f),
15 blend(1.0f), blendStep(kBlendSteps), started(false), dirty(true), meshWidth(-1), meshHeight(-1), meshFeather(-1.0f),
16 mesh(nullptr)
17{
18 width = w;
19 height = h;
20}
21
23{
25 mesh = nullptr;
26}
27
29{
30 kind = s;
31 dirty = true;
32}
33
35{
36 corners = c;
37 dirty = true;
38}
39
41{
42 setCorners(GuiCorners(100000.0f)); // clamped to half the shorter side
43}
44
46{
47 style = s;
48 started = false; // draw the new look at once, without fading from the old one
49}
50
51void GuiShape::setPaint(const GuiPaint& p)
52{
54}
55
57{
58 setShape(dir);
59 setStyle(GuiShapeStyle(GuiPaint().color(rest)).onFocus(GuiPaint().color(lit)));
60 setTransition(0.0f);
61}
62
63void GuiShape::setTransition(float seconds)
64{
65 transition = seconds < 0.0f ? 0.0f : seconds;
66}
67
68static SHAPE_STATE shapeStateFor(STATE s)
69{
70 switch(s)
71 {
72 case STATE::SELECTED:
73 case STATE::HELD: return SHAPE_STATE::FOCUSED;
74 case STATE::CLICKED: return SHAPE_STATE::PRESSED;
75 case STATE::DISABLED: return SHAPE_STATE::DISABLED;
76 default: return SHAPE_STATE::NORMAL;
77 }
78}
79
81{
82 if(!this->isVisible())
83 return;
84
85 const int a = this->getAlpha();
86 if(a > 0 && width > 0 && height > 0)
87 {
88 VideoDriver * video = platform->getVideo();
89
90 // choose the paint for the current state, blending toward it when it changes
91 const GuiPaint& want = style.forState(shapeStateFor(state));
92 if(!started)
93 {
94 from = to = shown = want;
95 blend = 1.0f;
96 blendStep = kBlendSteps;
97 started = true;
98 dirty = true;
99 }
100 else if(want != to)
101 {
102 from = shown;
103 to = want;
104 blend = transition > 0.0f ? 0.0f : 1.0f;
105 blendStep = 0;
106 if(blend >= 1.0f)
107 {
108 shown = to;
109 blendStep = kBlendSteps;
110 dirty = true;
111 }
112 }
113 if(blend < 1.0f)
114 {
115 blend += video->getDeltaTime() / transition;
116 if(blend >= 1.0f)
117 {
118 blend = 1.0f;
119 blendStep = kBlendSteps;
120 shown = to;
121 dirty = true;
122 }
123 else
124 {
125 // Look only changes a few times per blend, so the in-between meshes can be shared
126 const float eased = blend * blend * (3.0f - 2.0f * blend);
127 const int step = (int)(eased * (float)kBlendSteps + 0.5f);
128 if(step != blendStep)
129 {
130 blendStep = step;
131 shown = GuiPaint::mix(from, to, (float)step / (float)kBlendSteps);
132 dirty = true;
133 }
134 }
135 }
136
137 // look the geometry up again when anything it depends on changed
138 const float scale = video->getUIScale();
139 const float feather = scale > 0.0f ? 1.0f / scale : 1.0f;
140 if(dirty || !mesh || meshWidth != width || meshHeight != height || meshFeather != feather)
141 {
142 GuiMeshKey key;
143 key.kind = kind;
144 key.width = width;
145 key.height = height;
146 key.corners = corners;
147 key.paint = shown;
148 key.feather = feather;
149 key.tolerance = 0.3f * feather; // 0.3 of a physical pixel
150 GuiSharedMesh * next = GuiMeshCache::acquire(key); // before releasing, in case it is the same mesh
152 mesh = next;
153 meshWidth = width;
154 meshHeight = height;
155 meshFeather = feather;
156 dirty = false;
157 }
158
159 // place it like an image: scaled about its own center, at the element's position
160 const float sx = this->getScaleX();
161 const float sy = this->getScaleY();
162 const float hw = width * 0.5f;
163 const float hh = height * 0.5f;
164 GuiMeshCache::draw(mesh, this->getLeft() + hw - hw * sx, this->getTop() + hh - hh * sy, sx, sy, (uint8_t)a, scratch);
165 }
166
167 this->updateEffects();
168}
Umbrella header for the platform-agnostic libgui core.
bool isVisible()
Checks whether or not the element is visible.
int getTop()
Gets the current topmost coordinate of the element Considers vertical alignment, y offset,...
float getScaleX()
Gets the element's current x scale Considers scale, scaleDyn, and the parent element's GetScale() val...
int width
Element width.
Definition GuiElement.h:273
int height
Element height.
Definition GuiElement.h:274
float getScaleY()
Gets the element's current y scale Considers scale, scaleDyn, and the parent element's GetScale() val...
void updateEffects()
Updates the element's effects (dynamic values) Called by Draw(), used for animation purposes.
int getLeft()
Gets the current leftmost coordinate of the element Considers horizontal alignment,...
STATE state
Element state (DEFAULT, SELECTED, CLICKED, DISABLED)
Definition GuiElement.h:296
int getAlpha()
Gets the element's alpha value Considers alpha, alphaDyn, and the parent element's GetAlpha() value.
static void draw(GuiSharedMesh *mesh, float x, float y, float scaleX, float scaleY, uint8_t alpha, std::vector< MeshVertex > &scratch)
Draws a mesh with its (0,0) at (x, y), stretched by scaleX/scaleY about that point.
static GuiSharedMesh * acquire(const GuiMeshKey &key)
Finds or builds the mesh for a key and takes a reference to it. Pair with release().
static void release(GuiSharedMesh *mesh)
Gives back a reference from acquire().
void setCorners(const GuiCorners &c)
Sets the corner radii of a rectangle.
Definition GuiShape.cpp:34
void setShape(SHAPE s)
Sets the shape kind (rectangle or ellipse)
Definition GuiShape.cpp:28
void setStyle(const GuiShapeStyle &s)
Sets the look for every state; applies immediately.
Definition GuiShape.cpp:45
void setPaint(const GuiPaint &p)
Sets one look for every state.
Definition GuiShape.cpp:51
void setTransition(float seconds)
Sets how long a change of state takes to blend, in seconds (0 = instant)
Definition GuiShape.cpp:63
GuiShape(int w=0, int h=0)
Constructor.
Definition GuiShape.cpp:13
void draw() override
Constantly called to draw the shape.
Definition GuiShape.cpp:80
void setCapsule()
Rounds a rectangle's ends fully (radius half the shorter side)
Definition GuiShape.cpp:40
void setArrow(SHAPE dir, PixelColor rest, PixelColor lit)
Makes this a small arrow: a filled triangle pointing the way of dir (a SHAPE::TRIANGLE_*),...
Definition GuiShape.cpp:56
~GuiShape()
Destructor.
Definition GuiShape.cpp:22
One cached mesh.
Platform video backend owning the frame lifecycle (init/render/clear, screen size,...
Definition VideoDriver.h:28
virtual float getUIScale() const
Ratio of physical render-target pixels to design-canvas pixels (the width/height passed to init()).
Definition VideoDriver.h:58
virtual float getDeltaTime() const =0
STATE
Interaction state of a GuiElement (default, selected, clicked, held, disabled).
Definition GuiElement.h:37
SHAPE_STATE
The states a styled shape distinguishes.
Definition GuiPaint.h:74
SHAPE
Basic shape kinds a paint can be applied to.
Definition GuiPaint.h:17
@ FOCUSED
Highlighted: under the cursor, or selected with the D-pad.
Definition GuiPaint.h:76
@ RECTANGLE
Rectangle, with optional rounded corners (see GuiCorners)
Definition GuiPaint.h:18
Per-corner radii, in the order top-left, top-right, bottom-right, bottom-left.
Definition GuiGeometry.h:46
Everything that decides what a shape's triangles are.
float tolerance
Curve tolerance, see GuiMesh.
int width
Width in design-canvas pixels.
GuiCorners corners
Corner radii of a rectangle.
GuiPaint paint
Fill, outline and shadow.
SHAPE kind
Rectangle or ellipse.
float feather
Anti-aliasing fringe width, see GuiMesh.
int height
Height in design-canvas pixels.
A set of paints, one per state. States left unset fall back to the normal paint. GuiShapeStyle(rest)....
Definition GuiPaint.h:84
8-bit-per-channel RGBA color used by the video interfaces.
Definition Mesh.h:16