UFO: Alien Invasion
Loading...
Searching...
No Matches
ui_node_editor.cpp
Go to the documentation of this file.
1
7
8/*
9Copyright (C) 2002-2025 UFO: Alien Invasion.
10
11This program is free software; you can redistribute it and/or
12modify it under the terms of the GNU General Public License
13as published by the Free Software Foundation; either version 2
14of the License, or (at your option) any later version.
15
16This program is distributed in the hope that it will be useful,
17but WITHOUT ANY WARRANTY; without even the implied warranty of
18MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
20See the GNU General Public License for more details.
21
22You should have received a copy of the GNU General Public License
23along with this program; if not, write to the Free Software
24Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25
26*/
27
28#include "../ui_main.h"
29#include "../ui_parse.h"
30#include "../ui_behaviour.h"
31#include "../ui_draw.h"
32#include "../ui_input.h"
33#include "../ui_nodes.h"
34#include "../ui_windows.h"
35#include "../ui_render.h"
36#include "../ui_actions.h"
37#include "ui_node_editor.h"
39
40#include "../../input/cl_keys.h"
42
44
53
54
55static uiNode_t* anchoredNode = nullptr;
56static const vec4_t red = {1.0, 0.0, 0.0, 1.0};
57static const vec4_t grey = {0.8, 0.8, 0.8, 1.0};
58static const int anchorSize = 10;
60static int startX;
61static int startY;
62
63static void UI_EditorNodeHighlightNode (uiNode_t* node, const vec4_t color, bool displayAnchor)
64{
65 vec2_t pos;
66 UI_GetNodeAbsPos(node, pos);
67
68 UI_DrawRect(pos[0] - 1, pos[1] - 1, node->box.size[0] + 2, node->box.size[1] + 2, color, 1.0, 0x3333);
69
70 if (displayAnchor) {
71 UI_DrawFill(pos[0] - anchorSize, pos[1] - anchorSize, anchorSize, anchorSize, color);
72 UI_DrawFill(pos[0] - anchorSize, pos[1] + node->box.size[1], anchorSize, anchorSize, color);
73 UI_DrawFill(pos[0] + node->box.size[0], pos[1] + node->box.size[1], anchorSize, anchorSize, color);
74 UI_DrawFill(pos[0] + node->box.size[0], pos[1] - anchorSize, anchorSize, anchorSize, color);
75 }
76}
77
79{
81
82 if (x > 0 && x < node->box.size[0] && y > 0 && y < node->box.size[1]) {
83 return ZONE_BODY;
84 }
85
86 if (y > -anchorSize && y < 0) {
87 if (x > -anchorSize && x < 0) {
89 } else if (x > node->box.size[0] && x < node->box.size[0] + anchorSize) {
91 }
92 } else if (y > node->box.size[1] && y < node->box.size[1] + anchorSize) {
93 if (x > -anchorSize && x < 0) {
95 } else if (x > node->box.size[0] && x < node->box.size[0] + anchorSize) {
97 }
98 }
99 return ZONE_NONE;
100}
101
103{
104 UI_CaptureDrawOver(node);
105}
106
108{
109 uiNode_t* hovered = nullptr;
110
111 if (UI_GetMouseCapture() != node) {
112 if (anchoredNode)
114 return;
115 }
116
117 if (dragStatus == ZONE_NONE) {
118#if 0 /* it does nothing, remember why we need that... */
119 if (anchoredNode)
121#endif
123 /* do not edit node from editor window */
124 if (hovered && hovered->root == node->root)
125 hovered = nullptr;
126 }
127
128 if (hovered && hovered != anchoredNode)
129 UI_EditorNodeHighlightNode(hovered, grey, true);
130
131 if (anchoredNode)
133}
134
136{
137 vec2_t size;
138 const int diffX = x - startX;
139 const int diffY = y - startY;
140 startX = x;
141 startY = y;
142
143 if (anchoredNode == nullptr)
144 return;
145
146 switch (dragStatus) {
147 case ZONE_NONE:
148 return;
150 anchoredNode->box.pos[0] += diffX;
151 anchoredNode->box.pos[1] += diffY;
152 size[0] = anchoredNode->box.size[0] - diffX;
153 size[1] = anchoredNode->box.size[1] - diffY;
154 break;
156 anchoredNode->box.pos[1] += diffY;
157 size[0] = anchoredNode->box.size[0] + diffX;
158 size[1] = anchoredNode->box.size[1] - diffY;
159 break;
161 anchoredNode->box.pos[0] += diffX;
162 size[0] = anchoredNode->box.size[0] - diffX;
163 size[1] = anchoredNode->box.size[1] + diffY;
164 break;
166 size[0] = anchoredNode->box.size[0] + diffX;
167 size[1] = anchoredNode->box.size[1] + diffY;
168 break;
169 case ZONE_BODY:
170 anchoredNode->box.pos[0] += diffX;
171 anchoredNode->box.pos[1] += diffY;
172 size[0] = anchoredNode->box.size[0];
173 size[1] = anchoredNode->box.size[1];
174 break;
175 default:
176 Sys_Error("UI_EditorNodeCapturedMouseMove: Invalid status of %i", dragStatus);
177 }
178
179 if (size[0] < 5)
180 size[0] = 5;
181 if (size[1] < 5)
182 size[1] = 5;
183
185}
186
194
195void uiEditorNode::onMouseUp (uiNode_t* node, int x, int y, int button)
196{
197 if (UI_GetMouseCapture() != node)
198 return;
199 if (button != K_MOUSE1)
200 return;
202}
203
204static void UI_EditorNodeSelectNode (uiNode_t* node, uiNode_t* selected)
205{
206 if (selected == nullptr)
207 return;
208 /* do not select a node from the editor window */
209 if (selected->root == node->root)
210 return;
211 anchoredNode = selected;
212 Cvar_Set("ui_sys_editor_node", "%s", anchoredNode->name);
213 Cvar_Set("ui_sys_editor_window", "%s", anchoredNode->root->name);
214}
215
216void uiEditorNode::onMouseDown (uiNode_t* node, int x, int y, int button)
217{
218 uiNode_t* hovered;
219
220 if (UI_GetMouseCapture() != node)
221 return;
222 if (button != K_MOUSE1)
223 return;
224
226
227 /* stop the capture */
228 if (hovered && hovered->root == node->root) {
230 return;
231 }
232
233 if (hovered == anchoredNode)
234 hovered = nullptr;
235
236 if (anchoredNode) {
238 if (dragStatus == ZONE_BODY) {
239 if (hovered == nullptr) {
240 startX = x;
241 startY = y;
242 return;
243 }
244 } else if (dragStatus != ZONE_NONE) {
245 startX = x;
246 startY = y;
247 return;
248 }
249 }
250
251 /* select the node */
252 UI_EditorNodeSelectNode(node, hovered);
253}
254
255static void UI_EditorNodeStart (uiNode_t* node, const uiCallContext_t* context)
256{
257 UI_SetMouseCapture(node);
258}
259
260static void UI_EditorNodeStop (uiNode_t* node, const uiCallContext_t* context)
261{
263}
264
265static void UI_EditorNodeSelectNext (uiNode_t* node, const uiCallContext_t* context)
266{
267 if (dragStatus != ZONE_NONE)
268 return;
269 if (anchoredNode == nullptr)
270 return;
272}
273
274static void UI_EditorNodeSelectParent (uiNode_t* node, const uiCallContext_t* context)
275{
276 if (dragStatus != ZONE_NONE)
277 return;
278 if (anchoredNode == nullptr)
279 return;
281}
282
283static void UI_EditorNodeSelectFirstChild (uiNode_t* node, const uiCallContext_t* context)
284{
285 if (dragStatus != ZONE_NONE)
286 return;
287 if (anchoredNode == nullptr)
288 return;
289 UI_EditorNodeSelectNode(node, anchoredNode->firstChild);
290}
291
292static void UI_EditorNodeExtractNode (qFILE* file, uiNode_t* node, int depth)
293{
294 assert(depth < 16);
295
296 int i;
297 char tab[16];
298 for (i = 0; i < depth; i++) {
299 tab[i] = '\t';
300 }
301 tab[i] = '\0';
302
303 FS_Printf(file, "%s%s %s {\n", tab, node->behaviour->name, node->name);
304 uiNode_t* child = node->firstChild;
305
306 /* properties */
307 if (child) {
308 FS_Printf(file, "%s\t{\n", tab);
309 FS_Printf(file, "%s\t\tpos\t\"%d %d\"\n", tab, (int)node->box.pos[0], (int)node->box.pos[1]);
310 FS_Printf(file, "%s\t\tsize\t\"%d %d\"\n", tab, (int)node->box.size[0], (int)node->box.size[1]);
311 FS_Printf(file, "%s\t}\n", tab);
312 } else {
313 FS_Printf(file, "%s\tpos\t\"%d %d\"\n", tab, (int)node->box.pos[0], (int)node->box.pos[1]);
314 FS_Printf(file, "%s\tsize\t\"%d %d\"\n", tab, (int)node->box.size[0], (int)node->box.size[1]);
315 }
316
317 /* child */
318 while (child) {
319 UI_EditorNodeExtractNode(file, child, depth + 1);
320 child = child->next;
321 }
322
323 FS_Printf(file, "%s}\n", tab);
324}
325
330static void UI_EditorNodeExtract_f (void)
331{
332 if (Cmd_Argc() != 2) {
333 Com_Printf("Usage: %s <windowname>\n", Cmd_Argv(0));
334 return;
335 }
336 uiNode_t* window = UI_GetWindow(Cmd_Argv(1));
337 if (!window) {
338 Com_Printf("Window '%s' not found\n", Cmd_Argv(1));
339 return;
340 }
341
342 ScopedFile file;
343 FS_OpenFile(va("window_%s_extracted.ufo", window->name), &file, FILE_WRITE);
344 UI_EditorNodeExtractNode(&file, window, 0);
345
346 Com_Printf("Window '%s' extracted.\n", Cmd_Argv(1));
347}
348
350{
351 behaviour->name = "editor";
352 behaviour->manager = UINodePtr(new uiEditorNode());
353 behaviour->lua_SWIG_typeinfo = UI_SWIG_TypeQuery("uiEditorNode_t *");
354
355 /* start edition mode */
356 UI_RegisterNodeMethod(behaviour, "start", UI_EditorNodeStart);
357 /* stop edition mode */
358 UI_RegisterNodeMethod(behaviour, "stop", UI_EditorNodeStop);
359 /* select the next node (according to the current one) */
360 UI_RegisterNodeMethod(behaviour, "selectnext", UI_EditorNodeSelectNext);
361 /* select the parent node (according to the current one) */
362 UI_RegisterNodeMethod(behaviour, "selectparent", UI_EditorNodeSelectParent);
363 /* select first child node (according to the current one) */
364 UI_RegisterNodeMethod(behaviour, "selectfirstchild", UI_EditorNodeSelectFirstChild);
365
366 Cmd_AddCommand("ui_extract", UI_EditorNodeExtract_f, "Extract position and size of nodes into a file");
368}
int mousePosY
Definition cl_input.cpp:76
int mousePosX
Definition cl_input.cpp:76
External (non-keyboard) input devices.
Header file for keyboard handler.
@ K_MOUSE1
Definition cl_keys.h:46
void drawOverWindow(uiNode_t *node) override
void onCapturedMouseMove(uiNode_t *node, int x, int y) override
void onMouseDown(uiNode_t *node, int x, int y, int button) override
void onMouseUp(uiNode_t *node, int x, int y, int button) override
void onCapturedMouseLost(uiNode_t *node) override
Called when the node have lost the captured node.
void draw(uiNode_t *node) override
const char * Cmd_Argv(int arg)
Returns a given argument.
Definition cmd.cpp:516
void Cmd_AddParamCompleteFunction(const char *cmdName, int(*function)(const char *partial, const char **match))
Definition cmd.cpp:679
int Cmd_Argc(void)
Return the number of arguments of the current command. "command parameter" will result in a argc of 2...
Definition cmd.cpp:505
void Cmd_AddCommand(const char *cmdName, xcommand_t function, const char *desc)
Add a new command to the script interface.
Definition cmd.cpp:744
void Com_Printf(const char *const fmt,...)
Definition common.cpp:428
static const vec4_t red
@ ZONE_NONE
cvar_t * Cvar_Set(const char *varName, const char *value,...)
Sets a cvar value.
Definition cvar.cpp:615
int FS_Printf(qFILE *f, const char *msg,...)
Can print chunks for 1024 chars into a file.
Definition files.cpp:1497
int FS_OpenFile(const char *filename, qFILE *file, filemode_t mode)
Finds and opens the file in the search path.
Definition files.cpp:162
@ FILE_WRITE
Definition filesys.h:111
void Sys_Error(const char *error,...)
Definition g_main.cpp:421
voidpf void uLong size
Definition ioapi.h:42
QGL_EXTERN GLint i
Definition r_gl.h:113
Header for lua script functions.
const char * va(const char *format,...)
does a varargs printf into a temp buffer, so I don't need to have varargs versions of all text functi...
Definition shared.cpp:410
node behaviour, how a node work
const char * name
void * lua_SWIG_typeinfo
UINodePtr manager
vec2_t size
Definition ui_nodes.h:52
vec2_t pos
Definition ui_nodes.h:51
Contain the context of the calling of a function.
Definition ui_actions.h:208
Atomic structure used to define most of the UI.
Definition ui_nodes.h:80
uiNode_t * firstChild
Definition ui_nodes.h:89
uiNode_t * next
Definition ui_nodes.h:91
uiBehaviour_t * behaviour
Definition ui_nodes.h:83
uiBox_t box
Definition ui_nodes.h:96
char name[MAX_VAR]
Definition ui_nodes.h:82
uiNode_t * root
Definition ui_nodes.h:93
vec_t vec4_t[4]
Definition ufotypes.h:40
vec_t vec2_t[2]
Definition ufotypes.h:38
const struct value_s * UI_RegisterNodeMethod(uiBehaviour_t *behaviour, const char *name, uiNodeMethod_t function)
Register a node method to a behaviour.
void UI_CaptureDrawOver(uiNode_t *node)
Capture a node we will draw over all nodes (per window).
Definition ui_draw.cpp:64
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
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_NodeSetSize(uiNode_t *node, vec2_t size)
Update the node size and fire the size callback.
Definition ui_node.cpp:678
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
zoneNode_t
@ ZONE_TOPRIGHT_CORNER
@ ZONE_TOPLEFT_CORNER
@ ZONE_BOTTOMRIGHT_CORNER
@ ZONE_BODY
@ ZONE_BOTTOMLEFT_CORNER
static zoneNode_t dragStatus
static void UI_EditorNodeStart(uiNode_t *node, const uiCallContext_t *context)
static void UI_EditorNodeExtract_f(void)
static void UI_EditorNodeHighlightNode(uiNode_t *node, const vec4_t color, bool displayAnchor)
static void UI_EditorNodeSelectFirstChild(uiNode_t *node, const uiCallContext_t *context)
void UI_RegisterEditorNode(uiBehaviour_t *behaviour)
static uiNode_t * anchoredNode
static void UI_EditorNodeSelectParent(uiNode_t *node, const uiCallContext_t *context)
static int startY
static int startX
static void UI_EditorNodeSelectNext(uiNode_t *node, const uiCallContext_t *context)
static void UI_EditorNodeExtractNode(qFILE *file, uiNode_t *node, int depth)
static zoneNode_t UI_EditorNodeGetElementAtPosition(uiNode_t *node, int x, int y)
static void UI_EditorNodeSelectNode(uiNode_t *node, uiNode_t *selected)
static const vec4_t grey
static void UI_EditorNodeStop(uiNode_t *node, const uiCallContext_t *context)
static const int anchorSize
uiNode_t * UI_GetNodeAtPosition(int x, int y)
Return the first visible node at a position.
Definition ui_nodes.cpp:527
void UI_DrawRect(int x, int y, int w, int h, const vec4_t color, float lineWidth, int pattern)
Definition ui_render.cpp:42
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
uiNode_t * UI_GetWindow(const char *name)
Searches all windows for the specified one.
int UI_CompleteWithWindow(const char *partial, const char **match)
Complete function for ui_push.