UFO: Alien Invasion
Loading...
Searching...
No Matches
ui_node_selectbox.cpp
Go to the documentation of this file.
1
25
26/*
27Copyright (C) 2002-2025 UFO: Alien Invasion.
28
29This program is free software; you can redistribute it and/or
30modify it under the terms of the GNU General Public License
31as published by the Free Software Foundation; either version 2
32of the License, or (at your option) any later version.
33
34This program is distributed in the hope that it will be useful,
35but WITHOUT ANY WARRANTY; without even the implied warranty of
36MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
37
38See the GNU General Public License for more details.
39
40You should have received a copy of the GNU General Public License
41along with this program; if not, write to the Free Software
42Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
43
44*/
45
46#include "../ui_main.h"
47#include "../ui_internal.h"
48#include "../ui_parse.h"
49#include "../ui_font.h"
50#include "../ui_input.h"
51#include "../ui_draw.h"
52#include "../ui_render.h"
53#include "ui_node_selectbox.h"
56#include "ui_node_option.h"
57
58#include "../../cl_language.h"
59
61
62#define EXTRADATA(node) UI_EXTRADATA(node, abstractOptionExtraData_t)
63
64#define SELECTBOX_DEFAULT_HEIGHT 20.0f
65
66#define SELECTBOX_SIDE_WIDTH 7.0f
67#define SELECTBOX_RIGHT_WIDTH 20.0f
68
69#define SELECTBOX_SPACER 2.0f
70#define SELECTBOX_BOTTOM_HEIGHT 4.0f
71
77{
78 UI_NodeAbsoluteToRelativePos(node, &x, &y);
79
80 /* test bounded box */
81 if (x < 0 || y < 0 || x > node->box.size[0] || y > node->box.size[1] * (EXTRADATA(node).count + 1)) {
82 return;
83 }
84
85 int posy = node->box.size[1];
86 for (uiNode_t* option = UI_AbstractOption_GetFirstOption(node); option; option = option->next) {
87 if (option->invis)
88 continue;
89 OPTIONEXTRADATA(option).hovered = (posy <= y && y < posy + node->box.size[1]);
90 posy += node->box.size[1];
91 }
92}
93
95{
96 vec2_t nodepos;
97 static vec4_t invisColor = {1.0, 1.0, 1.0, 0.7};
98
99 const char* ref = UI_AbstractOption_GetCurrentValue(node);
100 if (ref == nullptr)
101 return;
102
103 UI_GetNodeAbsPos(node, nodepos);
104 const char* imageName = UI_GetReferenceString(node, node->image);
105 if (!imageName)
106 imageName = "ui/selectbox";
107
108 const image_t* image = UI_LoadImage(imageName);
109
110 const char* font = UI_GetFontFromNode(node);
111 int selBoxX = nodepos[0] + SELECTBOX_SIDE_WIDTH;
112 int selBoxY = nodepos[1] + SELECTBOX_SPACER;
113
114 /* left border */
115 UI_DrawNormImage(false, nodepos[0], nodepos[1], SELECTBOX_SIDE_WIDTH, node->box.size[1],
117 /* stretched middle bar */
118 UI_DrawNormImage(false, nodepos[0] + SELECTBOX_SIDE_WIDTH, nodepos[1], node->box.size[0]-SELECTBOX_SIDE_WIDTH-SELECTBOX_RIGHT_WIDTH, node->box.size[1],
119 12.0f, SELECTBOX_DEFAULT_HEIGHT, 7.0f, 0.0f, image);
120 /* right border (arrow) */
121 UI_DrawNormImage(false, nodepos[0] + node->box.size[0] - SELECTBOX_RIGHT_WIDTH, nodepos[1], SELECTBOX_DEFAULT_HEIGHT, node->box.size[1],
122 12.0f + SELECTBOX_RIGHT_WIDTH, SELECTBOX_DEFAULT_HEIGHT, 12.0f, 0.0f, image);
123
124 /* draw the label for the current selected option */
125 for (uiNode_t* option = UI_AbstractOption_GetFirstOption(node); option; option = option->next) {
126 if (!Q_streq(OPTIONEXTRADATA(option).value, ref))
127 continue;
128
129 if (option->invis)
130 R_Color(invisColor);
131
132 const char* label = CL_Translate(OPTIONEXTRADATA(option).label);
133
134 UI_DrawString(font, ALIGN_UL, selBoxX, selBoxY,
135 selBoxX, node->box.size[0] - 4,
136 0, label, 0, 0, nullptr, false, LONGLINES_PRETTYCHOP);
137
138 R_Color(nullptr);
139 break;
140 }
141
142 /* must we draw the drop-down list */
143 if (UI_GetMouseCapture() == node) {
144 UI_CaptureDrawOver(node);
145 }
146}
147
149{
150 const char* ref = UI_AbstractOption_GetCurrentValue(node);
151 if (ref == nullptr)
152 return;
153
154 vec2_t nodepos;
155 UI_GetNodeAbsPos(node, nodepos);
156
157 const char* imageName = UI_GetReferenceString(node, node->image);
158 if (!imageName)
159 imageName = "ui/selectbox";
160
161 const image_t* image = UI_LoadImage(imageName);
162
163 const char* font = UI_GetFontFromNode(node);
164 int selBoxX = nodepos[0] + SELECTBOX_SIDE_WIDTH;
165 int selBoxY = nodepos[1] + SELECTBOX_SPACER;
166
167 selBoxY += node->box.size[1];
168
169 /* drop down list */
170 /* left side */
171 UI_DrawNormImage(false, nodepos[0], nodepos[1] + node->box.size[1], SELECTBOX_SIDE_WIDTH, node->box.size[1] * EXTRADATA(node).count,
172 7.0f, 28.0f, 0.0f, 21.0f, image);
173
174 /* stretched middle bar */
175 UI_DrawNormImage(false, nodepos[0] + SELECTBOX_SIDE_WIDTH, nodepos[1] + node->box.size[1], node->box.size[0] -SELECTBOX_SIDE_WIDTH-SELECTBOX_RIGHT_WIDTH, node->box.size[1] * EXTRADATA(node).count,
176 16.0f, 28.0f, 7.0f, 21.0f, image);
177
178 /* right side */
179 UI_DrawNormImage(false, nodepos[0] + node->box.size[0] -SELECTBOX_SIDE_WIDTH-SELECTBOX_RIGHT_WIDTH, nodepos[1] + node->box.size[1], SELECTBOX_SIDE_WIDTH, node->box.size[1] * EXTRADATA(node).count,
180 23.0f, 28.0f, 16.0f, 21.0f, image);
181
182 /* now draw all available options for this selectbox */
183 int check = 0;
184 for (uiNode_t* option = UI_AbstractOption_GetFirstOption(node); option; option = option->next) {
185 if (option->invis)
186 continue;
187 /* draw the hover effect */
188 if (OPTIONEXTRADATA(option).hovered)
191 /* print the option label */
192 const char* label = CL_Translate(OPTIONEXTRADATA(option).label);
193 UI_DrawString(font, ALIGN_UL, selBoxX, selBoxY,
194 selBoxX, node->box.size[0] - 4,
195 0, label, 0, 0, nullptr, false, LONGLINES_PRETTYCHOP);
196 /* next entries' position */
197 selBoxY += node->box.size[1];
198 check++;
199 }
200
202 if (check != EXTRADATA(node).count) {
204 Com_Printf("uiSelectBoxNode::drawOverWindow: Node '%s' contains unsynchronized option list. Fixed.\n", UI_GetPath(node));
205 EXTRADATA(node).versionId = 0;
206 }
207
208 /* left side */
210 7.0f, 32.0f, 0.0f, 28.0f, image);
211
212 /* stretched middle bar */
215 16.0f, 32.0f, 7.0f, 28.0f, image);
216
217 /* right bottom side */
218 UI_DrawNormImage(false, nodepos[0] + node->box.size[0] - SELECTBOX_SIDE_WIDTH - SELECTBOX_RIGHT_WIDTH, selBoxY - SELECTBOX_SPACER,
220 23.0f, 32.0f, 16.0f, 28.0f, image);
221}
222
226void uiSelectBoxNode::onLeftClick (uiNode_t* node, int x, int y)
227{
228 /* dropdown the node */
229 if (UI_GetMouseCapture() == nullptr) {
230 UI_SetMouseCapture(node);
231 return;
232 }
233
234 vec2_t pos;
235 UI_GetNodeAbsPos(node, pos);
236 int clickedAtOption = (y - pos[1]);
237
238 /* we click outside */
239 if (x < pos[0] || y < pos[1] || x >= pos[0] + node->box.size[0] || y >= pos[1] + node->box.size[1] * (EXTRADATA(node).count + 1)) {
241 return;
242 }
243
244 /* we click on the head */
245 if (clickedAtOption < node->box.size[1]) {
247 return;
248 }
249
250 clickedAtOption = (clickedAtOption - node->box.size[1]) / node->box.size[1];
251 if (clickedAtOption < 0 || clickedAtOption >= EXTRADATA(node).count)
252 return;
253
254 if (UI_AbstractOption_GetCurrentValue(node) == nullptr)
255 return;
256
257 /* select the right option */
259 for (; option; option = option->next) {
260 if (option->invis)
261 continue;
262 if (clickedAtOption == 0)
263 break;
264 clickedAtOption--;
265 }
266
267 /* update the status */
268 if (option)
270
271 /* close the dropdown */
273}
274
279{
280 Vector4Set(node->color, 0.6, 0.6, 0.6, 0.3);
281}
282
284{
285 /* force a size (according to the texture) */
287}
288
290{
291 behaviour->name = "selectbox";
292 behaviour->extends = "abstractoption";
293 behaviour->manager = UINodePtr(new uiSelectBoxNode());
294 behaviour->drawItselfChild = true;
295 behaviour->lua_SWIG_typeinfo = UI_SWIG_TypeQuery("uiSelectBoxNode_t *");
296}
const char * CL_Translate(const char *t)
@ LONGLINES_PRETTYCHOP
void R_Color(const vec4_t rgba)
Change the color to given value.
Definition r_state.cpp:1011
void onCapturedMouseMove(uiNode_t *node, int x, int y) override
call when the mouse move is the node is captured
void onLeftClick(uiNode_t *node, int x, int y) override
Handles selectboxes clicks.
void drawOverWindow(uiNode_t *node) override
void onLoading(uiNode_t *node) override
Called before loading. Used to set default attribute values.
void draw(uiNode_t *node) override
void onLoaded(uiNode_t *node) override
void Com_Printf(const char *const fmt,...)
Definition common.cpp:428
QGL_EXTERN GLuint count
Definition r_gl.h:99
@ ALIGN_UL
Definition scripts.h:90
Header for lua script functions.
#define Q_streq(a, b)
Definition shared.h:136
node behaviour, how a node work
const char * name
void * lua_SWIG_typeinfo
UINodePtr manager
const char * extends
vec2_t size
Definition ui_nodes.h:52
Atomic structure used to define most of the UI.
Definition ui_nodes.h:80
bool invis
Definition ui_nodes.h:101
uiNode_t * next
Definition ui_nodes.h:91
vec4_t color
Definition ui_nodes.h:127
uiBox_t box
Definition ui_nodes.h:96
char * image
Definition ui_nodes.h:123
vec_t vec4_t[4]
Definition ufotypes.h:40
vec_t vec2_t[2]
Definition ufotypes.h:38
void UI_CaptureDrawOver(uiNode_t *node)
Capture a node we will draw over all nodes (per window).
Definition ui_draw.cpp:64
const char * UI_GetFontFromNode(const uiNode_t *const node)
Return the font for a specific node or default font.
Definition ui_font.cpp:145
void UI_SetMouseCapture(uiNode_t *node)
Captured the mouse into a node.
Definition ui_input.cpp:516
uiNode_t * UI_GetMouseCapture(void)
Return the captured node.
Definition ui_input.cpp:508
void UI_MouseRelease(void)
Release the captured node.
Definition ui_input.cpp:526
Internal data use by the UI package.
void * UI_SWIG_TypeQuery(const char *name)
This function queries the SWIG type table for a type information structure. It is used in combination...
void UI_NodeAbsoluteToRelativePos(const uiNode_t *node, int *x, int *y)
Update an absolute position to a relative one.
Definition ui_node.cpp:604
void UI_GetNodeAbsPos(const uiNode_t *node, vec2_t pos)
Returns the absolute position of a node.
Definition ui_node.cpp:526
SharedPtr< uiNode > UINodePtr
uiNode_t * UI_AbstractOption_GetFirstOption(uiNode_t *node)
Return the first option of the node.
const char * UI_AbstractOption_GetCurrentValue(uiNode_t *node)
#define EXTRADATA(node)
void UI_AbstractOption_SetCurrentValue(uiNode_t *node, const char *value)
#define OPTIONEXTRADATA(node)
#define SELECTBOX_BOTTOM_HEIGHT
#define SELECTBOX_RIGHT_WIDTH
#define SELECTBOX_SIDE_WIDTH
void UI_RegisterSelectBoxNode(uiBehaviour_t *behaviour)
#define SELECTBOX_DEFAULT_HEIGHT
#define SELECTBOX_SPACER
const char * UI_GetPath(const uiNode_t *node)
Return a path from a window to a node.
Definition ui_nodes.cpp:174
const char * UI_GetReferenceString(const uiNode_t *const node, const char *ref)
int UI_DrawString(const char *fontID, align_t align, int x, int y, int absX, int maxWidth, int lineHeight, const char *c, int boxHeight, int scrollPos, int *curLine, bool increaseLine, longlines_t method)
const struct image_s * UI_LoadImage(const char *name)
Searches for an image in the image array.
Definition ui_render.cpp:91
void UI_DrawFill(int x, int y, int w, int h, const vec4_t color)
Fills a box of pixels with a single color.
Definition ui_render.cpp:37
void UI_DrawNormImage(bool flip, float x, float y, float w, float h, float sh, float th, float sl, float tl, const image_t *image)
Draw a normalized (to the screen) image.
#define Vector4Set(v, r, g, b, a)
Definition vector.h:62