libgui 2.01
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
56void GuiShape::setTransition(float seconds)
57{
58 transition = seconds < 0.0f ? 0.0f : seconds;
59}
60
61static SHAPE_STATE shapeStateFor(STATE s)
62{
63 switch(s)
64 {
65 case STATE::SELECTED:
66 case STATE::HELD: return SHAPE_STATE::FOCUSED;
67 case STATE::CLICKED: return SHAPE_STATE::PRESSED;
68 case STATE::DISABLED: return SHAPE_STATE::DISABLED;
69 default: return SHAPE_STATE::NORMAL;
70 }
71}
72
74{
75 if(!this->isVisible())
76 return;
77
78 const int a = this->getAlpha();
79 if(a > 0 && width > 0 && height > 0)
80 {
81 VideoDriver * video = platform->getVideo();
82
83 // choose the paint for the current state, blending toward it when it changes
84 const GuiPaint& want = style.forState(shapeStateFor(state));
85 if(!started)
86 {
87 from = to = shown = want;
88 blend = 1.0f;
89 blendStep = kBlendSteps;
90 started = true;
91 dirty = true;
92 }
93 else if(want != to)
94 {
95 from = shown;
96 to = want;
97 blend = transition > 0.0f ? 0.0f : 1.0f;
98 blendStep = 0;
99 if(blend >= 1.0f)
100 {
101 shown = to;
102 blendStep = kBlendSteps;
103 dirty = true;
104 }
105 }
106 if(blend < 1.0f)
107 {
108 blend += video->getDeltaTime() / transition;
109 if(blend >= 1.0f)
110 {
111 blend = 1.0f;
112 blendStep = kBlendSteps;
113 shown = to;
114 dirty = true;
115 }
116 else
117 {
118 // Look only changes a few times per blend, so the in-between meshes can be shared
119 const float eased = blend * blend * (3.0f - 2.0f * blend);
120 const int step = (int)(eased * (float)kBlendSteps + 0.5f);
121 if(step != blendStep)
122 {
123 blendStep = step;
124 shown = GuiPaint::mix(from, to, (float)step / (float)kBlendSteps);
125 dirty = true;
126 }
127 }
128 }
129
130 // look the geometry up again when anything it depends on changed
131 const float scale = video->getUIScale();
132 const float feather = scale > 0.0f ? 1.0f / scale : 1.0f;
133 if(dirty || !mesh || meshWidth != width || meshHeight != height || meshFeather != feather)
134 {
135 GuiMeshKey key;
136 key.kind = kind;
137 key.width = width;
138 key.height = height;
139 key.corners = corners;
140 key.paint = shown;
141 key.feather = feather;
142 key.tolerance = 0.3f * feather; // 0.3 of a physical pixel
143 GuiSharedMesh * next = GuiMeshCache::acquire(key); // before releasing, in case it is the same mesh
145 mesh = next;
146 meshWidth = width;
147 meshHeight = height;
148 meshFeather = feather;
149 dirty = false;
150 }
151
152 // place it like an image: scaled about its own center, at the element's position
153 const float sx = this->getScaleX();
154 const float sy = this->getScaleY();
155 const float hw = width * 0.5f;
156 const float hh = height * 0.5f;
157 GuiMeshCache::draw(mesh, this->getLeft() + hw - hw * sx, this->getTop() + hh - hh * sy, sx, sy, (uint8_t)a, scratch);
158 }
159
160 this->updateEffects();
161}
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:268
int height
Element height.
Definition GuiElement.h:269
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:291
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:56
GuiShape(int w=0, int h=0)
Constructor.
Definition GuiShape.cpp:13
void draw() override
Constantly called to draw the shape.
Definition GuiShape.cpp:73
void setCapsule()
Rounds a rectangle's ends fully (radius half the shorter side)
Definition GuiShape.cpp:40
~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:36
SHAPE_STATE
The states a styled shape distinguishes.
Definition GuiPaint.h:70
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:72
@ 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:40
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:80