1 /**
2 * @file
3 */
4
5 /*
6 Copyright (C) 2002-2013 UFO: Alien Invasion.
7
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
17 See the GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22
23 */
24
25 #include "ui_internal.h"
26 #include "ui_dragndrop.h"
27 #include "ui_input.h"
28 #include "ui_node.h"
29 #include "ui_sound.h"
30
31 #include "node/ui_node_abstractnode.h"
32 #include "node/ui_node_container.h"
33
34 #include "../input/cl_input.h"
35
36 static int oldMousePosX = -1; /**< Save position X of the mouse to know when it move */
37 static int oldMousePosY = -1; /**< Save position Y of the mouse to know when it move */
38
39 static bool nodeAcceptDND = false; /**< Save if the current target node can accept the DND object */
40 static bool positionAcceptDND = false; /**< Save if the current position accept the DND object */
41
42 static uiDNDType_t objectType; /**< Save the type of the object we are dragging */
43 static Item draggingItem; /**< Save the dragging object */
44
45 static uiNode_t* sourceNode; /**< Node where come from the DND object */
46 static uiNode_t* targetNode; /**< Current node under the mouse */
47
48
49 /**
50 * @brief Return true if we are dragging something
51 */
UI_DNDIsDragging(void)52 bool UI_DNDIsDragging (void)
53 {
54 return objectType != DND_NOTHING;
55 }
56
57 /**
58 * @brief Return true if the requested node is the current target of the DND
59 */
UI_DNDIsTargetNode(uiNode_t * node)60 bool UI_DNDIsTargetNode (uiNode_t* node)
61 {
62 if (!UI_DNDIsDragging())
63 return false;
64 return targetNode == node;
65 }
66
67 /**
68 * @brief Return true if the requested node is the source of the DND
69 */
UI_DNDIsSourceNode(uiNode_t * node)70 bool UI_DNDIsSourceNode (uiNode_t* node)
71 {
72 if (!UI_DNDIsDragging())
73 return false;
74 return sourceNode == node;
75 }
76
77 /**
78 * @brief Return the current type of the dragging object, else DND_NOTHING
79 */
UI_DNDGetType(void)80 int UI_DNDGetType (void)
81 {
82 return objectType;
83 }
84
85 /**
86 * @brief Return target of the DND
87 */
UI_DNDGetTargetNode(void)88 uiNode_t* UI_DNDGetTargetNode (void)
89 {
90 assert(UI_DNDIsDragging());
91 return targetNode;
92 }
93
94 /**
95 * @brief Return source of the DND
96 */
UI_DNDGetSourceNode(void)97 uiNode_t* UI_DNDGetSourceNode (void)
98 {
99 assert(UI_DNDIsDragging());
100 return sourceNode;
101 }
102
103 /**
104 * @brief Private function to initialize a the start of a DND
105 * @sa UI_DNDDragItem
106 * @sa UI_DNDDrop
107 * @sa UI_DNDAbort
108 */
UI_DNDDrag(uiNode_t * node)109 static void UI_DNDDrag (uiNode_t* node)
110 {
111 assert(!UI_DNDIsDragging());
112 objectType = DND_SOMETHING;
113 sourceNode = node;
114
115 UI_PlaySound("item-drag");
116 }
117
118 /**
119 * @brief Start to drag an item
120 * @sa UI_DNDDrag
121 * @sa UI_DNDDrop
122 * @sa UI_DNDAbort
123 */
UI_DNDDragItem(uiNode_t * node,const Item * item)124 void UI_DNDDragItem (uiNode_t* node, const Item* item)
125 {
126 UI_DNDDrag(node);
127 assert(UI_DNDIsDragging());
128 objectType = DND_ITEM;
129 draggingItem = *item;
130 }
131
132 /**
133 * @brief Cleanup data about DND
134 */
UI_DNDCleanup(void)135 static inline void UI_DNDCleanup (void)
136 {
137 objectType = DND_NOTHING;
138 targetNode = nullptr;
139 sourceNode = nullptr;
140 }
141
142 /**
143 * @brief Drop the object at the current position
144 * @sa UI_DNDStartDrag
145 * @sa UI_DNDDrop
146 */
UI_DNDAbort(void)147 void UI_DNDAbort (void)
148 {
149 assert(UI_DNDIsDragging());
150 assert(objectType != DND_NOTHING);
151 assert(sourceNode != nullptr);
152
153 if (nodeAcceptDND && targetNode) {
154 UI_Node_DndLeave(targetNode);
155 }
156 UI_Node_DndFinished(sourceNode, false);
157
158 UI_DNDCleanup();
159 UI_InvalidateMouse();
160 }
161
162 /**
163 * @brief Drop the object at the current position
164 * @sa UI_DNDStartDrag
165 * @sa UI_DNDAbort
166 */
UI_DNDDrop(void)167 void UI_DNDDrop (void)
168 {
169 bool result = false;
170 assert(UI_DNDIsDragging());
171 assert(objectType != DND_NOTHING);
172 assert(sourceNode != nullptr);
173
174 if (!positionAcceptDND) {
175 UI_DNDAbort();
176 return;
177 }
178
179 if (targetNode) {
180 result = UI_Node_DndDrop(targetNode, mousePosX, mousePosY);
181 }
182 UI_Node_DndFinished(sourceNode, result);
183
184 UI_PlaySound("item-drop");
185
186 UI_DNDCleanup();
187 UI_InvalidateMouse();
188 }
189
UI_DNDGetItem(void)190 Item* UI_DNDGetItem (void)
191 {
192 assert(objectType == DND_ITEM);
193 return &draggingItem;
194 }
195
196 /**
197 * @brief Manage the DND when we move the mouse
198 */
UI_DNDMouseMove(int mousePosX,int mousePosY)199 static void UI_DNDMouseMove (int mousePosX, int mousePosY)
200 {
201 uiNode_t* node = UI_GetNodeAtPosition(mousePosX, mousePosY);
202
203 if (node != targetNode) {
204 if (nodeAcceptDND && targetNode) {
205 UI_Node_DndLeave(targetNode);
206 }
207 targetNode = node;
208 if (targetNode) {
209 nodeAcceptDND = UI_Node_DndEnter(targetNode);
210 }
211 }
212
213 if (targetNode == nullptr) {
214 nodeAcceptDND = false;
215 positionAcceptDND = false;
216 return;
217 }
218
219 if (!nodeAcceptDND) {
220 positionAcceptDND = false;
221 return;
222 }
223
224 positionAcceptDND = UI_Node_DndMove(targetNode, mousePosX, mousePosY);
225 }
226
227 /**
228 * @brief Draw to dragging object and catch mouse move event
229 */
UI_DrawDragAndDrop(int mousePosX,int mousePosY)230 void UI_DrawDragAndDrop (int mousePosX, int mousePosY)
231 {
232 const vec3_t scale = { 3.5, 3.5, 3.5 };
233 vec3_t orgine;
234 vec4_t color = { 1, 1, 1, 1 };
235
236 /* check mouse move */
237 if (mousePosX != oldMousePosX || mousePosY != oldMousePosY) {
238 oldMousePosX = mousePosX;
239 oldMousePosY = mousePosY;
240 UI_DNDMouseMove(mousePosX, mousePosY);
241 }
242
243 /* draw the dragging item */
244
245 VectorSet(orgine, mousePosX, mousePosY, -50);
246
247 /* Tune down the opacity of the cursor-item if the preview item is drawn. */
248 if (positionAcceptDND)
249 color[3] = 0.2;
250
251 switch (objectType) {
252 case DND_ITEM:
253 UI_DrawItem(nullptr, orgine, &draggingItem, -1, -1, scale, color);
254 break;
255
256 default:
257 assert(false);
258 }
259 }
260