UFO: Alien Invasion
Loading...
Searching...
No Matches
ui_node_abstractvalue.cpp
Go to the documentation of this file.
1
6
7/*
8Copyright (C) 2002-2025 UFO: Alien Invasion.
9
10This program is free software; you can redistribute it and/or
11modify it under the terms of the GNU General Public License
12as published by the Free Software Foundation; either version 2
13of the License, or (at your option) any later version.
14
15This program is distributed in the hope that it will be useful,
16but WITHOUT ANY WARRANTY; without even the implied warranty of
17MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18
19See the GNU General Public License for more details.
20
21You should have received a copy of the GNU General Public License
22along with this program; if not, write to the Free Software
23Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24
25*/
26
27#include "../ui_nodes.h"
28#include "../ui_parse.h"
29#include "../ui_internal.h"
30#include "../ui_lua.h"
31
33
35#include "../../input/cl_keys.h"
36
38
39#define EXTRADATA_TYPE abstractValueExtraData_t
40#define EXTRADATA(node) UI_EXTRADATA(node, EXTRADATA_TYPE)
41#define EXTRADATACONST(node) UI_EXTRADATACONST(node, EXTRADATA_TYPE)
42
46static inline void UI_InitCvarOrFloat (float** adress, float defaultValue)
47{
48 if (*adress == nullptr) {
49 *adress = UI_AllocStaticFloat(1);
50 **adress = defaultValue;
51 }
52}
53
54static void UI_CloneCvarOrFloat (const uiNode_t* source, uiNode_t* clone, const float*const* sourceData, float** cloneData)
55{
56 /* dont update cvar */
57 if (Q_strstart(*(const char*const*)sourceData, "*cvar:")) {
58 /* thats anyway a const string */
59 if (clone->dynamic)
60 Mem_Free(*(char**)cloneData);
61 *(const char**)cloneData = *(const char*const*)sourceData;
62 } else {
63 /* clone float */
64 if (!clone->dynamic)
65 *cloneData = UI_AllocStaticFloat(1);
66 **cloneData = **sourceData;
67 }
68}
69
70static void UI_FreeCvarOrFloat (const uiNode_t* node, void** data) {
71 /* if this is a string starting with "*cvar", then it points to a cvar variable and the
72 allocated string should be released */
73 if ((*data != nullptr) && Q_strstart((char*)(*data), "*cvar:")) {
74 Mem_Free(*data);
75 }
76 /* else this is a reference float */
77 else {
78 /* static floats do not have to be released */
79 }
80 *data = nullptr;
81}
82
83
85{
87 EXTRADATA(node).shiftIncreaseFactor = 2.0F;
88}
89
91{
93 UI_InitCvarOrFloat((float**)&EXTRADATA(node).value, 0);
94 UI_InitCvarOrFloat((float**)&EXTRADATA(node).delta, 1);
95 UI_InitCvarOrFloat((float**)&EXTRADATA(node).max, 0);
96 UI_InitCvarOrFloat((float**)&EXTRADATA(node).min, 0);
97}
98
102
107
109{
110 uiNode::deleteNode(node);
111 UI_FreeCvarOrFloat(node, &EXTRADATA(node).min);
112 UI_FreeCvarOrFloat(node, &EXTRADATA(node).max);
113 UI_FreeCvarOrFloat(node, &EXTRADATA(node).value);
114 UI_FreeCvarOrFloat(node, &EXTRADATA(node).delta);
115}
116
121{
123 /* upon cloning a memcpy is done of the internal data so we need to replace the allocated floats with
124 new allocs or else a mismatch will occur between the number of allocated floats and the number of
125 deleted floats if nodes go out of scope */
130 /* now clone the values */
131 UI_CloneCvarOrFloat(source, clone, (const float*const*)&EXTRADATACONST(source).value, (float**)&EXTRADATA(clone).value);
132 UI_CloneCvarOrFloat(source, clone, (const float*const*)&EXTRADATACONST(source).delta, (float**)&EXTRADATA(clone).delta);
133 UI_CloneCvarOrFloat(source, clone, (const float*const*)&EXTRADATACONST(source).max, (float**)&EXTRADATA(clone).max);
134 UI_CloneCvarOrFloat(source, clone, (const float*const*)&EXTRADATACONST(source).min, (float**)&EXTRADATA(clone).min);
135}
136
138{
139 if (!Key_IsDown(K_SHIFT))
140 return 1.0F;
141
142 return EXTRADATACONST(node).shiftIncreaseFactor;
143}
144
146 return EXTRADATACONST(node).lastdiff;
147}
148
150 return EXTRADATA(node).shiftIncreaseFactor;
151}
152
153void uiAbstractValueNode::setRange(uiNode_t* node, float min, float max)
154{
155 if (EXTRADATA(node).min == nullptr) {
156 UI_InitCvarOrFloat((float**)&EXTRADATA(node).min, min);
157 }
158 else {
159 setMin(node, min);
160 }
161 if (EXTRADATA(node).max == nullptr) {
162 UI_InitCvarOrFloat((float**)&EXTRADATA(node).max, max);
163 }
164 else {
165 setMax(node, max);
166 }
167}
168
170{
171 const float last = UI_GetReferenceFloat(node, EXTRADATA(node).value);
172 const float max = UI_GetReferenceFloat(node, EXTRADATA(node).max);
173 const float min = UI_GetReferenceFloat(node, EXTRADATA(node).min);
174
175 /* ensure sane values */
176 if (value < min)
177 value = min;
178 else if (value > max)
179 value = max;
180
181 /* nothing change? */
182 if (last == value) {
183 return false;
184 }
185
186 /* save result */
187 EXTRADATA(node).lastdiff = value - last;
188 const char* cvar = Q_strstart((char*)EXTRADATA(node).value, "*cvar:");
189 if (cvar)
190 Cvar_SetValue(cvar, value);
191 else
192 *(float*) EXTRADATA(node).value = value;
193
194 /* fire change event */
195 if (node->onChange) {
196 UI_ExecuteEventActions(node, node->onChange);
197 }
198 if (node->lua_onChange != LUA_NOREF) {
200 }
201
202 return true;
203}
204
205bool uiAbstractValueNode::setDelta(uiNode_t* node, float delta) {
206 const float last = UI_GetReferenceFloat(node, EXTRADATA(node).delta);
207
208 /* nothing change? */
209 if (last == delta) {
210 return false;
211 }
212
213 /* save result */
214 const char* cvar = Q_strstart((char*)EXTRADATA(node).delta, "*cvar:");
215 if (cvar)
216 Cvar_SetValue(cvar, delta);
217 else
218 *(float*) EXTRADATA(node).delta = delta;
219
220 return true;
221}
222bool uiAbstractValueNode::setMax(uiNode_t* node, float max) {
223 const float last = UI_GetReferenceFloat(node, EXTRADATA(node).max);
224
225 /* nothing change? */
226 if (last == max) {
227 return false;
228 }
229
230 /* save result */
231 const char* cvar = Q_strstart((char*)EXTRADATA(node).max, "*cvar:");
232 if (cvar)
233 Cvar_SetValue(cvar, max);
234 else
235 *(float*) EXTRADATA(node).max = max;
236
237 return true;
238}
239
240bool uiAbstractValueNode::setMin(uiNode_t* node, float min) {
241 const float last = UI_GetReferenceFloat(node, EXTRADATA(node).min);
242
243 /* nothing change? */
244 if (last == min) {
245 return false;
246 }
247
248 /* save result */
249 const char* cvar = Q_strstart((char*)EXTRADATA(node).min, "*cvar:");
250 if (cvar)
251 Cvar_SetValue(cvar, min);
252 else
253 *(float*) EXTRADATA(node).min = min;
254
255 return true;
256}
257
259{
260 float value = UI_GetReferenceFloat(node, EXTRADATA(node).value);
261 const float delta = getFactorFloat(node) * UI_GetReferenceFloat(node, EXTRADATA(node).delta);
262 return setValue(node, value + delta);
263}
264
266{
267 float value = UI_GetReferenceFloat(node, EXTRADATA(node).value);
268 const float delta = getFactorFloat(node) * UI_GetReferenceFloat(node, EXTRADATA(node).delta);
269 return setValue(node, value - delta);
270}
271
273{
274 return UI_GetReferenceFloat(node, EXTRADATACONST(node).min);
275}
276
278{
279 return UI_GetReferenceFloat(node, EXTRADATACONST(node).max);
280}
281
283{
284 return UI_GetReferenceFloat(node, EXTRADATACONST(node).delta);
285}
286
288{
289 return UI_GetReferenceFloat(node, EXTRADATACONST(node).value);
290}
291
294 return b->getMin(node);
295}
296
299 return b->getMax(node);
300}
301
304 return b->getValue(node);
305}
306
309 return b->getDelta(node);
310}
311
314 return b->getLastDiff(node);
315}
316
321
324 b->incValue(node);
325}
326
329 b->decValue(node);
330}
331
332void UI_AbstractValue_SetRange (uiNode_t* node, float min, float max) {
334 b->setRange(node, min, max);
335}
336
337void UI_AbstractValue_SetMin (uiNode_t* node, float min) {
339 b->setRange(node, min, b->getMax(node));
340}
341
342void UI_AbstractValue_SetMax (uiNode_t* node, float max) {
344 b->setRange(node, b->getMin(node), max);
345}
346
347void UI_AbstractValue_SetValue (uiNode_t* node, float value) {
349 b->setValue(node, value);
350}
351
352void UI_AbstractValue_SetDelta (uiNode_t* node, float delta) {
354 b->setDelta(node, delta);
355}
356
357void UI_AbstractValue_SetRangeCvar (uiNode_t* node, const char* min, const char* max) {
358 /* This is a special case: we have a situation where the node already has a (min,max) value
359 (either being floats or cvars). We now want to replace this value by a new cvar. So we first
360 need to free the existing references, then create new cvar references and store them. */
361 UI_FreeCvarOrFloat(node, &EXTRADATA(node).min);
362 EXTRADATA(node).min = Mem_StrDup(min);
363 UI_FreeCvarOrFloat(node, &EXTRADATA(node).max);
364 EXTRADATA(node).max = Mem_StrDup(max);
365}
366
367void UI_AbstractValue_SetMinCvar (uiNode_t* node, const char* min) {
368 /* This is a special case: we have a situation where the node already has a (min,max) value
369 (either being floats or cvars). We now want to replace this value by a new cvar. So we first
370 need to free the existing references, then create new cvar references and store them. */
371 UI_FreeCvarOrFloat(node, &EXTRADATA(node).min);
372 EXTRADATA(node).min = Mem_StrDup(min);
373}
374
375void UI_AbstractValue_SetMaxCvar (uiNode_t* node, const char* max) {
376 /* This is a special case: we have a situation where the node already has a (min,max) value
377 (either being floats or cvars). We now want to replace this value by a new cvar. So we first
378 need to free the existing references, then create new cvar references and store them. */
379 UI_FreeCvarOrFloat(node, &EXTRADATA(node).max);
380 EXTRADATA(node).max = Mem_StrDup(max);
381}
382
383void UI_AbstractValue_SetValueCvar (uiNode_t* node, const char* value) {
384 /* This is a special case: we have a situation where the node already has a value reference
385 (either being float or cvar). We now want to replace this value reference by a new cvar. So we first
386 need to free the existing reference, then create new cvar reference (just a string starting with
387 '*cvar' and store it. */
388 UI_FreeCvarOrFloat(node, &EXTRADATA(node).value);
389 EXTRADATA(node).value= Mem_StrDup(value);
390
391 /* fire change event */
392 if (node->onChange) {
393 UI_ExecuteEventActions(node, node->onChange);
394 }
395 if (node->lua_onChange != LUA_NOREF) {
397 }
398}
399
401 EXTRADATA(node).shiftIncreaseFactor = factor;
402}
403
405{
406 behaviour->name = "abstractvalue";
407 behaviour->manager = UINodePtr(new uiAbstractValueNode());
408 behaviour->isAbstract = true;
409 behaviour->extraDataSize = sizeof(EXTRADATA_TYPE);
410 behaviour->lua_SWIG_typeinfo = UI_SWIG_TypeQuery("uiAbstractValueNode_t *");
411
412 /* Current value of the node. It should be a cvar */
414 /* Value of a positive step. Must be bigger than 1. */
416 /* Maximum value we can set to the node. It can be a cvar. Default value is 0. */
418 /* Minimum value we can set to the node. It can be a cvar. Default value is 1. */
420 /* Defines a factor that is applied to the delta value when the shift key is held down. */
421 UI_RegisterExtradataNodeProperty(behaviour, "shiftincreasefactor", V_FLOAT, abstractValueExtraData_t, shiftIncreaseFactor);
422
423 /* Callback value set when before calling onChange. It is used to know the change apply by the user
424 * @Deprecated
425 */
426 UI_RegisterExtradataNodeProperty(behaviour, "lastdiff", V_FLOAT, abstractValueExtraData_t, lastdiff);
427
428}
External (non-keyboard) input devices.
bool Key_IsDown(unsigned int key)
Checks whether a given key is currently pressed.
Definition cl_keys.cpp:214
Header file for keyboard handler.
@ K_SHIFT
Definition cl_keys.h:97
PointerType get() const
Definition sharedptr.h:197
bool setDelta(uiNode_t *node, float delta)
void onLoaded(uiNode_t *node) override
bool setMin(uiNode_t *node, float min)
bool setMax(uiNode_t *node, float max)
void initNode(uiNode_t *node) override
float getValue(uiNode_t const *node)
void onLoading(uiNode_t *node) override
float getShiftIncreaseFactor(uiNode_t *const node)
bool setValue(uiNode_t *node, float value)
float getLastDiff(uiNode_t const *node)
bool decValue(uiNode_t *node)
bool incValue(uiNode_t *node)
void deleteNode(uiNode_t *node) override
float getDelta(uiNode_t const *node)
void initNodeDynamic(uiNode_t *node) override
float getFactorFloat(uiNode_t const *node)
float getMax(uiNode_t const *node)
float getMin(uiNode_t const *node)
void clone(uiNode_t const *source, uiNode_t *clone) override
Call to update a cloned node.
void setRange(uiNode_t *node, float min, float max)
virtual void initNodeDynamic(uiNode_t *node)
virtual void onLoading(uiNode_t *node)
virtual void onLoaded(uiNode_t *node)
virtual void deleteNode(uiNode_t *node)
virtual void clone(uiNode_t const *source, uiNode_t *clone)
virtual void initNode(uiNode_t *node)
void Cvar_SetValue(const char *varName, float value)
Expands value to a string and calls Cvar_Set.
Definition cvar.cpp:671
#define Mem_Free(ptr)
Definition mem.h:35
#define Mem_PoolAllocType(type, pool)
Definition mem.h:43
#define Mem_StrDup(in)
Definition mem.h:48
QGL_EXTERN GLsizei const GLvoid * data
Definition r_gl.h:89
@ V_FLOAT
Definition scripts.h:54
Header for lua script functions.
char const * Q_strstart(char const *str, char const *start)
Matches the start of a string.
Definition shared.cpp:587
extradata for common GUI widget which allow to edit a value (scrollbar, spinner, and more)
node behaviour, how a node work
const char * name
void * lua_SWIG_typeinfo
UINodePtr manager
intptr_t extraDataSize
Atomic structure used to define most of the UI.
Definition ui_nodes.h:80
uiBehaviour_t * behaviour
Definition ui_nodes.h:83
LUA_EVENT lua_onChange
Definition ui_nodes.h:162
struct uiAction_s * onChange
Definition ui_nodes.h:143
bool dynamic
Definition ui_nodes.h:85
void UI_ExecuteEventActions(uiNode_t *source, const uiAction_t *firstAction)
#define UI_RegisterExtradataNodeProperty(BEHAVIOUR, NAME, TYPE, EXTRADATATYPE, ATTRIBUTE)
Initialize a property from extradata of node.
Internal data use by the UI package.
memPool_t * ui_dynPool
Definition ui_main.cpp:41
bool UI_ExecuteLuaEventScript(uiNode_t *node, LUA_EVENT event)
Executes a lua event handler.
Definition ui_lua.cpp:71
Basic lua initialization for the ui.
void * UI_SWIG_TypeQuery(const char *name)
This function queries the SWIG type table for a type information structure. It is used in combination...
SharedPtr< uiNode > UINodePtr
#define EXTRADATA_TYPE
#define EXTRADATA(node)
void UI_AbstractValue_SetMin(uiNode_t *node, float min)
void UI_AbstractValue_SetValueCvar(uiNode_t *node, const char *value)
float UI_AbstractValue_GetLastDiff(uiNode_t *node)
void UI_AbstractValue_SetRange(uiNode_t *node, float min, float max)
float UI_AbstractValue_GetDelta(uiNode_t *node)
void UI_AbstractValue_SetRangeCvar(uiNode_t *node, const char *min, const char *max)
#define EXTRADATA(node)
void UI_AbstractValue_SetMaxCvar(uiNode_t *node, const char *max)
void UI_AbstractValue_DecValue(uiNode_t *node)
float UI_AbstractValue_GetMin(uiNode_t *node)
float UI_AbstractValue_GetValue(uiNode_t *node)
void UI_AbstractValue_SetShiftIncreaseFactor(uiNode_t *node, float factor)
void UI_AbstractValue_SetMax(uiNode_t *node, float max)
void UI_AbstractValue_IncValue(uiNode_t *node)
void UI_AbstractValue_SetValue(uiNode_t *node, float value)
float UI_AbstractValue_GetMax(uiNode_t *node)
void UI_AbstractValue_SetMinCvar(uiNode_t *node, const char *min)
static void UI_InitCvarOrFloat(float **adress, float defaultValue)
Allocates a float and initializes it if the pointer value is not set, else does nothing.
#define EXTRADATACONST(node)
float UI_AbstractValue_GetShiftIncreaseFactor(uiNode_t *node)
static void UI_CloneCvarOrFloat(const uiNode_t *source, uiNode_t *clone, const float *const *sourceData, float **cloneData)
void UI_RegisterAbstractValueNode(uiBehaviour_t *behaviour)
void UI_AbstractValue_SetDelta(uiNode_t *node, float delta)
static void UI_FreeCvarOrFloat(const uiNode_t *node, void **data)
Define common thing for GUI controls which allow to edit a value (scroolbar, spinner,...
float UI_GetReferenceFloat(const uiNode_t *const node, const void *ref)
Returns the value of the reference variable.
float * UI_AllocStaticFloat(int count)
Allocate a float into the UI static memory.
Definition ui_parse.cpp:171
#define V_CVAR_OR_FLOAT
Definition ui_parse.h:68