UFO: Alien Invasion
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
ui_node_editor.cpp
Go to the documentation of this file.
1 
8 /*
9 Copyright (C) 2002-2020 UFO: Alien Invasion.
10 
11 This program is free software; you can redistribute it and/or
12 modify it under the terms of the GNU General Public License
13 as published by the Free Software Foundation; either version 2
14 of the License, or (at your option) any later version.
15 
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 
20 See the GNU General Public License for more details.
21 
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, 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"
38 #include "ui_node_abstractnode.h"
39 
40 #include "../../input/cl_keys.h"
41 #include "../../input/cl_input.h"
42 
43 #include "../../../common/scripts_lua.h"
44 
45 typedef enum {
46  ZONE_NONE = -1,
52 } zoneNode_t;
53 
54 
55 static uiNode_t* anchoredNode = nullptr;
56 static const vec4_t red = {1.0, 0.0, 0.0, 1.0};
57 static const vec4_t grey = {0.8, 0.8, 0.8, 1.0};
58 static const int anchorSize = 10;
60 static int startX;
61 static int startY;
62 
63 static 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 {
80  UI_NodeAbsoluteToRelativePos(anchoredNode, &x, &y);
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) {
88  return ZONE_TOPLEFT_CORNER;
89  } else if (x > node->box.size[0] && x < node->box.size[0] + anchorSize) {
90  return ZONE_TOPRIGHT_CORNER;
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)
113  UI_EditorNodeHighlightNode(anchoredNode, red, false);
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)
132  UI_EditorNodeHighlightNode(anchoredNode, red, true);
133 }
134 
135 void uiEditorNode::onCapturedMouseMove (uiNode_t* node, int x, int y)
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;
149  case ZONE_TOPLEFT_CORNER:
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 
184  UI_NodeSetSize(anchoredNode, size);
185 }
186 
191 {
193 }
194 
195 void 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 
204 static 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 
216 void 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) {
229  UI_MouseRelease();
230  return;
231  }
232 
233  if (hovered == anchoredNode)
234  hovered = nullptr;
235 
236  if (anchoredNode) {
237  dragStatus = UI_EditorNodeGetElementAtPosition(anchoredNode, x, y);
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 
255 static void UI_EditorNodeStart (uiNode_t* node, const uiCallContext_t* context)
256 {
257  UI_SetMouseCapture(node);
258 }
259 
260 static void UI_EditorNodeStop (uiNode_t* node, const uiCallContext_t* context)
261 {
262  UI_MouseRelease();
263 }
264 
265 static void UI_EditorNodeSelectNext (uiNode_t* node, const uiCallContext_t* context)
266 {
267  if (dragStatus != ZONE_NONE)
268  return;
269  if (anchoredNode == nullptr)
270  return;
271  UI_EditorNodeSelectNode(node, anchoredNode->next);
272 }
273 
274 static void UI_EditorNodeSelectParent (uiNode_t* node, const uiCallContext_t* context)
275 {
276  if (dragStatus != ZONE_NONE)
277  return;
278  if (anchoredNode == nullptr)
279  return;
280  UI_EditorNodeSelectNode(node, anchoredNode->parent);
281 }
282 
283 static 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 
292 static 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 
330 static 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 }
const char * Cmd_Argv(int arg)
Returns a given argument.
Definition: cmd.cpp:516
void Cmd_AddCommand(const char *cmdName, xcommand_t function, const char *desc)
Add a new command to the script interface.
Definition: cmd.cpp:744
vec2_t size
Definition: ui_nodes.h:52
static int startX
static uiNode_t * anchoredNode
void Sys_Error(const char *error,...)
Definition: g_main.cpp:421
uiNode_t * parent
Definition: ui_nodes.h:92
uiNode_t * next
Definition: ui_nodes.h:91
int FS_OpenFile(const char *filename, qFILE *file, filemode_t mode)
Finds and opens the file in the search path.
Definition: files.cpp:162
int UI_CompleteWithWindow(const char *partial, const char **match)
Complete function for ui_push.
Definition: ui_windows.cpp:211
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
const char * name
Definition: ui_behaviour.h:41
void UI_CaptureDrawOver(uiNode_t *node)
Capture a node we will draw over all nodes (per window)
Definition: ui_draw.cpp:64
static zoneNode_t dragStatus
void onMouseUp(uiNode_t *node, int x, int y, int button) override
static void UI_EditorNodeHighlightNode(uiNode_t *node, const vec4_t color, bool displayAnchor)
static zoneNode_t UI_EditorNodeGetElementAtPosition(uiNode_t *node, int x, int y)
zoneNode_t
uiNode_t * UI_GetNodeAtPosition(int x, int y)
Return the first visible node at a position.
Definition: ui_nodes.cpp:527
char name[MAX_VAR]
Definition: ui_nodes.h:82
uiBehaviour_t * behaviour
Definition: ui_nodes.h:83
UINodePtr manager
Definition: ui_behaviour.h:43
void drawOverWindow(uiNode_t *node) override
static void UI_EditorNodeStop(uiNode_t *node, const uiCallContext_t *context)
void UI_RegisterEditorNode(uiBehaviour_t *behaviour)
void Com_Printf(const char *const fmt,...)
Definition: common.cpp:386
static void UI_EditorNodeSelectNext(uiNode_t *node, const uiCallContext_t *context)
static const vec4_t grey
void UI_MouseRelease(void)
Release the captured node.
Definition: ui_input.cpp:526
static void UI_EditorNodeSelectNode(uiNode_t *node, uiNode_t *selected)
static void UI_EditorNodeSelectParent(uiNode_t *node, const uiCallContext_t *context)
uiNode_t * root
Definition: ui_nodes.h:93
void onMouseDown(uiNode_t *node, int x, int y, int button) override
static int startY
GLsizei size
Definition: r_gl.h:152
static const vec4_t red
int mousePosY
Definition: cl_input.cpp:80
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
SharedPtr< uiNode > UINodePtr
static void UI_EditorNodeSelectFirstChild(uiNode_t *node, const uiCallContext_t *context)
void * lua_SWIG_typeinfo
Definition: ui_behaviour.h:57
void UI_SetMouseCapture(uiNode_t *node)
Captured the mouse into a node.
Definition: ui_input.cpp:516
int FS_Printf(qFILE *f, const char *msg,...)
Can print chunks for 1024 chars into a file.
Definition: files.cpp:1495
uiNode_t * UI_GetMouseCapture(void)
Return the captured node.
Definition: ui_input.cpp:508
Atomic structure used to define most of the UI.
Definition: ui_nodes.h:80
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_GetNodeAbsPos(const uiNode_t *node, vec2_t pos)
Returns the absolute position of a node.
Definition: ui_node.cpp:514
void draw(uiNode_t *node) override
Contain the context of the calling of a function.
Definition: ui_actions.h:208
uiNode_t * UI_GetWindow(const char *name)
Searches all windows for the specified one.
Definition: ui_windows.cpp:567
void onCapturedMouseMove(uiNode_t *node, int x, int y) override
static void UI_EditorNodeExtractNode(qFILE *file, uiNode_t *node, int depth)
void onCapturedMouseLost(uiNode_t *node) override
Called when the node have lost the captured node.
QGL_EXTERN GLint i
Definition: r_gl.h:113
void UI_NodeAbsoluteToRelativePos(const uiNode_t *node, int *x, int *y)
Update an absolute position to a relative one.
Definition: ui_node.cpp:592
node behaviour, how a node work
Definition: ui_behaviour.h:39
static void UI_EditorNodeExtract_f(void)
vec_t vec2_t[2]
Definition: ufotypes.h:38
void Cmd_AddParamCompleteFunction(const char *cmdName, int(*function)(const char *partial, const char **match))
Definition: cmd.cpp:679
void UI_DrawRect(int x, int y, int w, int h, const vec4_t color, float lineWidth, int pattern)
Definition: ui_render.cpp:42
uiNode_t * firstChild
Definition: ui_nodes.h:89
cvar_t * Cvar_Set(const char *varName, const char *value,...)
Sets a cvar value.
Definition: cvar.cpp:615
uiBox_t box
Definition: ui_nodes.h:96
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
static const int anchorSize
int mousePosX
Definition: cl_input.cpp:80
static void UI_EditorNodeStart(uiNode_t *node, const uiCallContext_t *context)
void UI_NodeSetSize(uiNode_t *node, vec2_t size)
Update the node size and fire the size callback.
Definition: ui_node.cpp:666
const struct value_s * UI_RegisterNodeMethod(uiBehaviour_t *behaviour, const char *name, uiNodeMethod_t function)
Register a node method to a behaviour.
vec_t vec4_t[4]
Definition: ufotypes.h:40
vec2_t pos
Definition: ui_nodes.h:51