ui_node_editor.c

Go to the documentation of this file.
00001 
00008 /*
00009 Copyright (C) 2002-2010 UFO: Alien Invasion.
00010 
00011 This program is free software; you can redistribute it and/or
00012 modify it under the terms of the GNU General Public License
00013 as published by the Free Software Foundation; either version 2
00014 of the License, or (at your option) any later version.
00015 
00016 This program is distributed in the hope that it will be useful,
00017 but WITHOUT ANY WARRANTY; without even the implied warranty of
00018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00019 
00020 See the GNU General Public License for more details.
00021 
00022 You should have received a copy of the GNU General Public License
00023 along with this program; if not, write to the Free Software
00024 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00025 
00026 */
00027 
00028 #include "../ui_main.h"
00029 #include "../ui_parse.h"
00030 #include "../ui_draw.h"
00031 #include "../ui_input.h"
00032 #include "../ui_nodes.h"
00033 #include "../ui_windows.h"
00034 #include "../ui_render.h"
00035 #include "../ui_actions.h"
00036 #include "ui_node_editor.h"
00037 #include "ui_node_abstractnode.h"
00038 
00039 #include "../../input/cl_keys.h"
00040 #include "../../input/cl_input.h"
00041 #include "../../renderer/r_draw.h"
00042 
00043 typedef enum {
00044     ZONE_NONE = -1,
00045     ZONE_TOPRIGHT_CORNER,
00046     ZONE_TOPLEFT_CORNER,
00047     ZONE_BOTTOMRIGHT_CORNER,
00048     ZONE_BOTTOMLEFT_CORNER,
00049     ZONE_BODY
00050 } zoneNode_t;
00051 
00052 
00053 static uiNode_t* anchoredNode = NULL;
00054 static const vec4_t red = {1.0, 0.0, 0.0, 1.0};
00055 static const vec4_t grey = {0.8, 0.8, 0.8, 1.0};
00056 static const int anchorSize = 10;
00057 static zoneNode_t dragStatus = ZONE_NONE;
00058 static int startX;
00059 static int startY;
00060 
00061 static void UI_EditorNodeHighlightNode (uiNode_t *node, const vec4_t color, qboolean displayAnchor)
00062 {
00063     vec2_t pos;
00064     UI_GetNodeAbsPos(node, pos);
00065 
00066     R_DrawRect(pos[0] - 1, pos[1] - 1, node->size[0] + 2, node->size[1] + 2, color, 1.0, 0x3333);
00067 
00068     if (displayAnchor) {
00069         UI_DrawFill(pos[0] - anchorSize, pos[1] - anchorSize, anchorSize, anchorSize, color);
00070         UI_DrawFill(pos[0] - anchorSize, pos[1] + node->size[1], anchorSize, anchorSize, color);
00071         UI_DrawFill(pos[0] + node->size[0], pos[1] + node->size[1], anchorSize, anchorSize, color);
00072         UI_DrawFill(pos[0] + node->size[0], pos[1] - anchorSize, anchorSize, anchorSize, color);
00073     }
00074 }
00075 
00076 static zoneNode_t UI_EditorNodeGetElementAtPosition (uiNode_t *node, int x, int y)
00077 {
00078     UI_NodeAbsoluteToRelativePos(anchoredNode, &x, &y);
00079 
00080     if (x > 0 && x < node->size[0] && y > 0 && y < node->size[1]) {
00081         return ZONE_BODY;
00082     }
00083 
00084     if (y > -anchorSize && y < 0) {
00085         if (x > -anchorSize && x < 0) {
00086             return ZONE_TOPLEFT_CORNER;
00087         } else if (x > node->size[0] && x < node->size[0] + anchorSize) {
00088             return ZONE_TOPRIGHT_CORNER;
00089         }
00090     } else if (y > node->size[1] && y < node->size[1] + anchorSize) {
00091         if (x > -anchorSize && x < 0) {
00092             return ZONE_BOTTOMLEFT_CORNER;
00093         } else if (x > node->size[0] && x < node->size[0] + anchorSize) {
00094             return ZONE_BOTTOMRIGHT_CORNER;
00095         }
00096     }
00097     return ZONE_NONE;
00098 }
00099 
00100 static void UI_EditorNodeDraw (uiNode_t *node)
00101 {
00102     UI_CaptureDrawOver(node);
00103 }
00104 
00105 static void UI_EditorNodeDrawOverWindow (uiNode_t *node)
00106 {
00107     uiNode_t* hovered = NULL;
00108 
00109     if (UI_GetMouseCapture() != node) {
00110         if (anchoredNode)
00111             UI_EditorNodeHighlightNode(anchoredNode, red, qfalse);
00112         return;
00113     }
00114 
00115     if (dragStatus == ZONE_NONE) {
00116 #if 0   /* it does nothing, remember why we need that... */
00117         if (anchoredNode)
00118             UI_EditorNodeGetElementAtPosition(anchoredNode, mousePosX, mousePosY);
00119 #endif
00120         hovered = UI_GetNodeAtPosition(mousePosX, mousePosY);
00121         /* do not edit node from editor window */
00122         if (hovered && hovered->root == node->root)
00123             hovered = NULL;
00124     }
00125 
00126     if (hovered && hovered != anchoredNode)
00127         UI_EditorNodeHighlightNode(hovered, grey, qtrue);
00128 
00129     if (anchoredNode)
00130         UI_EditorNodeHighlightNode(anchoredNode, red, qtrue);
00131 }
00132 
00133 static void UI_EditorNodeCapturedMouseMove (uiNode_t *node, int x, int y)
00134 {
00135     vec2_t size;
00136     const int diffX = x - startX;
00137     const int diffY = y - startY;
00138     startX = x;
00139     startY = y;
00140 
00141     if (anchoredNode == NULL)
00142         return;
00143 
00144     switch (dragStatus) {
00145     case ZONE_NONE:
00146         return;
00147     case ZONE_TOPLEFT_CORNER:
00148         anchoredNode->pos[0] += diffX;
00149         anchoredNode->pos[1] += diffY;
00150         size[0] = anchoredNode->size[0] - diffX;
00151         size[1] = anchoredNode->size[1] - diffY;
00152         break;
00153     case ZONE_TOPRIGHT_CORNER:
00154         anchoredNode->pos[1] += diffY;
00155         size[0] = anchoredNode->size[0] + diffX;
00156         size[1] = anchoredNode->size[1] - diffY;
00157         break;
00158     case ZONE_BOTTOMLEFT_CORNER:
00159         anchoredNode->pos[0] += diffX;
00160         size[0] = anchoredNode->size[0] - diffX;
00161         size[1] = anchoredNode->size[1] + diffY;
00162         break;
00163     case ZONE_BOTTOMRIGHT_CORNER:
00164         size[0] = anchoredNode->size[0] + diffX;
00165         size[1] = anchoredNode->size[1] + diffY;
00166         break;
00167     case ZONE_BODY:
00168         anchoredNode->pos[0] += diffX;
00169         anchoredNode->pos[1] += diffY;
00170         size[0] = anchoredNode->size[0];
00171         size[1] = anchoredNode->size[1];
00172         break;
00173     default:
00174         Sys_Error("UI_EditorNodeCapturedMouseMove: Invalid status of %i", dragStatus);
00175     }
00176 
00177     if (size[0] < 5)
00178         size[0] = 5;
00179     if (size[1] < 5)
00180         size[1] = 5;
00181 
00182     UI_NodeSetSize(anchoredNode, size);
00183 }
00184 
00188 static void UI_EditorNodeCapturedMouseLost (uiNode_t *node)
00189 {
00190     dragStatus = ZONE_NONE;
00191 }
00192 
00193 static void UI_EditorNodeMouseUp (uiNode_t *node, int x, int y, int button)
00194 {
00195     if (UI_GetMouseCapture() != node)
00196         return;
00197     if (button != K_MOUSE1)
00198         return;
00199     dragStatus = ZONE_NONE;
00200 }
00201 
00202 static void UI_EditorNodeSelectNode (uiNode_t *node, uiNode_t *selected)
00203 {
00204     if (selected == NULL)
00205         return;
00206     /* do not select a node from the editor window */
00207     if (selected->root == node->root)
00208         return;
00209     anchoredNode = selected;
00210     Cvar_Set("mn_sys_editor_node", anchoredNode->name);
00211     Cvar_Set("mn_sys_editor_window", anchoredNode->root->name);
00212 }
00213 
00214 static void UI_EditorNodeMouseDown (uiNode_t *node, int x, int y, int button)
00215 {
00216     uiNode_t* hovered;
00217 
00218     if (UI_GetMouseCapture() != node)
00219         return;
00220     if (button != K_MOUSE1)
00221         return;
00222 
00223     hovered = UI_GetNodeAtPosition(mousePosX, mousePosY);
00224 
00225     /* stop the capture */
00226     if (hovered && hovered->root == node->root) {
00227         UI_MouseRelease();
00228         return;
00229     }
00230 
00231     if (hovered == anchoredNode)
00232         hovered = NULL;
00233 
00234     if (anchoredNode) {
00235         dragStatus = UI_EditorNodeGetElementAtPosition(anchoredNode, x, y);
00236         if (dragStatus == ZONE_BODY) {
00237             if (hovered == NULL) {
00238                 startX = x;
00239                 startY = y;
00240                 return;
00241             }
00242         } else if (dragStatus != ZONE_NONE) {
00243             startX = x;
00244             startY = y;
00245             return;
00246         }
00247     }
00248 
00249     /* select the node */
00250     UI_EditorNodeSelectNode(node, hovered);
00251 }
00252 
00253 static void UI_EditorNodeStart (uiNode_t *node, const uiCallContext_t *context)
00254 {
00255     UI_SetMouseCapture(node);
00256 }
00257 
00258 static void UI_EditorNodeStop (uiNode_t *node, const uiCallContext_t *context)
00259 {
00260     UI_MouseRelease();
00261 }
00262 
00263 static void UI_EditorNodeSelectNext (uiNode_t *node, const uiCallContext_t *context)
00264 {
00265     if (dragStatus != ZONE_NONE)
00266         return;
00267     if (anchoredNode == NULL)
00268         return;
00269     UI_EditorNodeSelectNode(node, anchoredNode->next);
00270 }
00271 
00272 static void UI_EditorNodeSelectParent (uiNode_t *node, const uiCallContext_t *context)
00273 {
00274     if (dragStatus != ZONE_NONE)
00275         return;
00276     if (anchoredNode == NULL)
00277         return;
00278     UI_EditorNodeSelectNode(node, anchoredNode->parent);
00279 }
00280 
00281 static void UI_EditorNodeSelectFirstChild (uiNode_t *node, const uiCallContext_t *context)
00282 {
00283     if (dragStatus != ZONE_NONE)
00284         return;
00285     if (anchoredNode == NULL)
00286         return;
00287     UI_EditorNodeSelectNode(node, anchoredNode->firstChild);
00288 }
00289 
00290 static void UI_EditorNodeExtractNode (qFILE *file, uiNode_t *node, int depth)
00291 {
00292     int i;
00293     char tab[16];
00294     uiNode_t *child;
00295     assert(depth < 16);
00296 
00297     for (i = 0; i < depth; i++) {
00298         tab[i] = '\t';
00299     }
00300     tab[i] = '\0';
00301 
00302     FS_Printf(file, "%s%s %s {\n", tab, node->behaviour->name, node->name);
00303     child = node->firstChild;
00304 
00305     /* properties */
00306     if (child) {
00307         FS_Printf(file, "%s\t{\n", tab);
00308         FS_Printf(file, "%s\t\tpos\t\"%d %d\"\n", tab, (int)node->pos[0], (int)node->pos[1]);
00309         FS_Printf(file, "%s\t\tsize\t\"%d %d\"\n", tab, (int)node->size[0], (int)node->size[1]);
00310         FS_Printf(file, "%s\t}\n", tab);
00311     } else {
00312         FS_Printf(file, "%s\tpos\t\"%d %d\"\n", tab, (int)node->pos[0], (int)node->pos[1]);
00313         FS_Printf(file, "%s\tsize\t\"%d %d\"\n", tab, (int)node->size[0], (int)node->size[1]);
00314     }
00315 
00316     /* child */
00317     while (child) {
00318         UI_EditorNodeExtractNode(file, child, depth + 1);
00319         child = child->next;
00320     }
00321 
00322     FS_Printf(file, "%s}\n", tab);
00323 }
00324 
00329 static void UI_EditorNodeExtract_f (void)
00330 {
00331     uiNode_t* window;
00332     qFILE file;
00333 
00334     if (Cmd_Argc() != 2) {
00335         Com_Printf("Usage: %s <windowname>\n", Cmd_Argv(0));
00336         return;
00337     }
00338     window = UI_GetWindow(Cmd_Argv(1));
00339     if (!window) {
00340         Com_Printf("Window '%s' not found\n", Cmd_Argv(1));
00341         return;
00342     }
00343 
00344     FS_OpenFile(va("window_%s_extracted.ufo", window->name), &file, FILE_WRITE);
00345     UI_EditorNodeExtractNode(&file, window, 0);
00346     FS_CloseFile(&file);
00347 
00348     Com_Printf("Window '%s' extracted.\n", Cmd_Argv(1));
00349 }
00350 
00351 static const value_t properties[] = {
00352     /* start edition mode */
00353     {"start", V_UI_NODEMETHOD, ((size_t) UI_EditorNodeStart), 0},
00354     /* stop edition mode */
00355     {"stop", V_UI_NODEMETHOD, ((size_t) UI_EditorNodeStop), 0},
00356     /* select the next node (according to the current one) */
00357     {"selectnext", V_UI_NODEMETHOD, ((size_t) UI_EditorNodeSelectNext), 0},
00358     /* select the parent node (according to the current one) */
00359     {"selectparent", V_UI_NODEMETHOD, ((size_t) UI_EditorNodeSelectParent), 0},
00360     /* select first child node (according to the current one) */
00361     {"selectfirstchild", V_UI_NODEMETHOD, ((size_t) UI_EditorNodeSelectFirstChild), 0},
00362     {NULL, V_NULL, 0, 0}
00363 };
00364 
00365 void UI_RegisterEditorNode (uiBehaviour_t *behaviour)
00366 {
00367     behaviour->name = "editor";
00368     behaviour->extends = "special";
00369     behaviour->draw = UI_EditorNodeDraw;
00370     behaviour->drawOverWindow = UI_EditorNodeDrawOverWindow;
00371     behaviour->mouseDown = UI_EditorNodeMouseDown;
00372     behaviour->mouseUp = UI_EditorNodeMouseUp;
00373     behaviour->capturedMouseMove = UI_EditorNodeCapturedMouseMove;
00374     behaviour->capturedMouseLost = UI_EditorNodeCapturedMouseLost;
00375     behaviour->properties = properties;
00376 
00377     Cmd_AddCommand("mn_extract", UI_EditorNodeExtract_f, "Extract position and size of nodes into a file");
00378     Cmd_AddParamCompleteFunction("mn_extract", UI_CompleteWithWindow);
00379 }

Generated by  doxygen 1.6.2