]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake2/extra/qe4/drag.c
Merge branch 'NateEag-master-patch-12920' into 'master'
[xonotic/netradiant.git] / tools / quake2 / extra / qe4 / drag.c
1 /*
2 ===========================================================================
3 Copyright (C) 1997-2006 Id Software, Inc.
4
5 This file is part of Quake 2 Tools source code.
6
7 Quake 2 Tools source code is free software; you can redistribute it
8 and/or modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the License,
10 or (at your option) any later version.
11
12 Quake 2 Tools source code is distributed in the hope that it will be
13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Quake 2 Tools source code; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 ===========================================================================
21 */
22
23 #include "qe3.h"
24
25 /*
26
27   drag either multiple brushes, or select plane points from
28   a single brush.
29
30 */
31
32 qboolean        drag_ok;
33 vec3_t  drag_xvec;
34 vec3_t  drag_yvec;
35
36 static  int     buttonstate;
37 static  int     pressx, pressy;
38 static  vec3_t  pressdelta;
39 static  int     buttonx, buttony;
40
41
42 //int           num_move_points;
43 //float *move_points[1024];
44
45 int             lastx, lasty;
46
47 qboolean        drag_first;
48
49
50 void    AxializeVector (vec3_t v)
51 {
52         vec3_t  a;
53         float   o;
54         int             i;
55
56         if (!v[0] && !v[1])
57                 return;
58         if (!v[1] && !v[2])
59                 return;
60         if (!v[0] && !v[2])
61                 return;
62
63         for (i=0 ; i<3 ; i++)
64                 a[i] = fabs(v[i]);
65         if (a[0] > a[1] && a[0] > a[2])
66                 i = 0;
67         else if (a[1] > a[0] && a[1] > a[2])
68                 i = 1;
69         else
70                 i = 2;
71
72         o = v[i];
73         VectorCopy (vec3_origin, v);
74         if (o<0)
75                 v[i] = -1;
76         else
77                 v[i] = 1;
78
79 }
80
81
82 /*
83 ===========
84 Drag_Setup
85 ===========
86 */
87 void Drag_Setup (int x, int y, int buttons,
88                    vec3_t xaxis, vec3_t yaxis,
89                    vec3_t origin, vec3_t dir)
90 {
91         trace_t t;
92         face_t  *f;
93
94         if (selected_brushes.next == &selected_brushes)
95         {
96                 Sys_Status("No selection to drag\n", 0);
97                 return;
98         }
99
100         drag_first = true;
101         g_qeglobals.d_num_move_points = 0;
102         VectorCopy (vec3_origin, pressdelta);
103         pressx = x;
104         pressy = y;
105
106         VectorCopy (xaxis, drag_xvec);
107         AxializeVector (drag_xvec);
108         VectorCopy (yaxis, drag_yvec);
109         AxializeVector (drag_yvec);
110
111         if (g_qeglobals.d_select_mode == sel_vertex)
112         {
113                 SelectVertexByRay (origin, dir);
114                 if (g_qeglobals.d_num_move_points)
115                 {
116                         drag_ok = true;
117                         return;
118                 }
119         }
120         if (g_qeglobals.d_select_mode == sel_edge)
121         {
122                 SelectEdgeByRay (origin, dir);
123                 if (g_qeglobals.d_num_move_points)
124                 {
125                         drag_ok = true;
126                         return;
127                 }
128         }
129
130
131         //
132         // check for direct hit first
133         //
134         t = Test_Ray (origin, dir, true);
135         if (t.selected)
136         {
137                 drag_ok = true;
138
139                 if (buttons == (MK_LBUTTON|MK_CONTROL) )
140                 {
141                         Sys_Printf ("Shear dragging face\n");
142                         Brush_SelectFaceForDragging (t.brush, t.face, true);
143                 }
144                 else if (buttons == (MK_LBUTTON|MK_CONTROL|MK_SHIFT) )
145                 {
146                         Sys_Printf ("Sticky dragging brush\n");
147                         for (f=t.brush->brush_faces ; f ; f=f->next)
148                                 Brush_SelectFaceForDragging (t.brush, f, false);
149                 }
150                 else
151                         Sys_Printf ("Dragging entire selection\n");
152
153                 return;
154         }
155
156         if (g_qeglobals.d_select_mode == sel_vertex || g_qeglobals.d_select_mode == sel_edge)
157                 return;
158
159         //
160         // check for side hit
161         //
162         if (selected_brushes.next->next != &selected_brushes)
163         {
164                 Sys_Printf ("Click isn't inside multiple selection\n");
165                 return;
166         }
167
168         if (selected_brushes.next->owner->eclass->fixedsize)
169         {
170                 Sys_Printf ("Can't stretch fixed size entities\n");
171                 return;
172         }
173
174
175         if (buttons & MK_CONTROL)
176                 Brush_SideSelect (selected_brushes.next, origin, dir, true);
177         else
178                 Brush_SideSelect (selected_brushes.next, origin, dir, false);
179
180
181         Sys_Printf ("Side stretch\n");
182         drag_ok = true;
183 }
184
185 entity_t *peLink;
186
187 void UpdateTarget(vec3_t origin, vec3_t dir)
188 {
189         trace_t t;
190         entity_t *pe;
191         int i;
192         char sz[128];
193
194         t = Test_Ray (origin, dir, 0);
195
196         if (!t.brush)
197                 return;
198
199         pe = t.brush->owner;
200
201         if (pe == NULL)
202                 return;
203
204         // is this the first?
205         if (peLink != NULL)
206         {
207
208                 // Get the target id from out current target
209                 // if there is no id, make one
210
211                 i = IntForKey(pe, "target");
212                 if (i <= 0)
213                 {
214                         i = GetUniqueTargetId(1);
215                         sprintf(sz, "%d", i);
216
217                         SetKeyValue(pe, "target", sz);
218                 }
219
220                 // set the target # into our src
221
222                 sprintf(sz, "%d", i);
223                 SetKeyValue(peLink, "targetname", sz);
224
225                 Sys_UpdateWindows(W_ENTITY);
226
227         }
228
229         // promote the target to the src
230
231         peLink = pe;
232
233 }
234
235 /*
236 ===========
237 Drag_Begin
238 ===========
239 */
240 void Drag_Begin (int x, int y, int buttons,
241                    vec3_t xaxis, vec3_t yaxis,
242                    vec3_t origin, vec3_t dir)
243 {
244         trace_t t;
245
246         drag_ok = false;
247         VectorCopy (vec3_origin, pressdelta);
248
249         drag_first = true;
250         peLink = NULL;
251
252         // shift LBUTTON = select entire brush
253         if (buttons == (MK_LBUTTON | MK_SHIFT))
254         {
255                 if (!dir[0] && !dir[1])
256                         Select_Ray (origin, dir, SF_ENTITIES_FIRST);    // hack for XY
257                 else
258                         Select_Ray (origin, dir, 0);
259                 return;
260         }
261
262         // ctrl-shift LBUTTON = select single face
263         if (buttons == (MK_LBUTTON | MK_CONTROL | MK_SHIFT))
264         {
265                 Select_Deselect ();
266                 Select_Ray (origin, dir, SF_SINGLEFACE);
267                 return;
268         }
269
270         // LBUTTON + all other modifiers = manipulate selection
271         if (buttons & MK_LBUTTON)
272         {
273                 Drag_Setup (x, y, buttons, xaxis, yaxis, origin, dir);
274                 return;
275         }
276
277         // middle button = grab texture
278         if (buttons == MK_MBUTTON)
279         {
280                 t = Test_Ray (origin, dir, false);
281                 if (t.face)
282                 {
283                         g_qeglobals.d_new_brush_bottom_z = t.brush->mins[2];
284                         g_qeglobals.d_new_brush_top_z = t.brush->maxs[2];
285                         Texture_SetTexture (&t.face->texdef);
286                 }
287                 else
288                         Sys_Printf ("Did not select a texture\n");
289                 return;
290         }
291
292         // ctrl-middle button = set entire brush to texture
293         if (buttons == (MK_MBUTTON|MK_CONTROL) )
294         {
295                 t = Test_Ray (origin, dir, false);
296                 if (t.brush)
297                 {
298                         if (t.brush->brush_faces->texdef.name[0] == '(')
299                                 Sys_Printf ("Can't change an entity texture\n");
300                         else
301                         {
302                                 Brush_SetTexture (t.brush, &g_qeglobals.d_texturewin.texdef);
303                                 Sys_UpdateWindows (W_ALL);
304                         }
305                 }
306                 else
307                         Sys_Printf ("Didn't hit a btrush\n");
308                 return;
309         }
310
311         // ctrl-shift-middle button = set single face to texture
312         if (buttons == (MK_MBUTTON|MK_SHIFT|MK_CONTROL) )
313         {
314                 t = Test_Ray (origin, dir, false);
315                 if (t.brush)
316                 {
317                         if (t.brush->brush_faces->texdef.name[0] == '(')
318                                 Sys_Printf ("Can't change an entity texture\n");
319                         else
320                         {
321                                 t.face->texdef = g_qeglobals.d_texturewin.texdef;
322                                 Brush_Build( t.brush );
323                                 Sys_UpdateWindows (W_ALL);
324                         }
325                 }
326                 else
327                         Sys_Printf ("Didn't hit a btrush\n");
328                 return;
329         }
330
331 }
332
333
334 /*
335 ===========
336 MoveSelection
337 ===========
338 */
339 void MoveSelection (vec3_t move)
340 {
341         int             i;
342         brush_t *b;
343
344         if (!move[0] && !move[1] && !move[2])
345                 return;
346
347         Sys_UpdateWindows (W_XY|W_CAMERA);
348
349         //
350         // dragging only a part of the selection
351         //
352         if (g_qeglobals.d_num_move_points)
353         {
354                 for (i=0 ; i<g_qeglobals.d_num_move_points ; i++)
355                         VectorAdd (g_qeglobals.d_move_points[i], move, g_qeglobals.d_move_points[i]);
356
357                 for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
358                 {
359                         Brush_Build( b );
360                         for (i=0 ; i<3 ; i++)
361                                 if (b->mins[i] > b->maxs[i]
362                                 || b->maxs[i] - b->mins[i] > 4096)
363                                         break;  // dragged backwards or fucked up
364                         if (i != 3)
365                                 break;
366                 }
367
368                 // if any of the brushes were crushed out of existance
369                 // calcel the entire move
370                 if (b != &selected_brushes)
371                 {
372                         Sys_Printf ("Brush dragged backwards, move canceled\n");
373                         for (i=0 ; i<g_qeglobals.d_num_move_points ; i++)
374                                 VectorSubtract (g_qeglobals.d_move_points[i], move, g_qeglobals.d_move_points[i]);
375
376                         for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
377                                 Brush_Build( b );
378                 }
379
380         }
381         else
382         {
383                 //
384                 // if there are lots of brushes selected, just translate instead
385                 // of rebuilding the brushes
386                 //
387                 if (drag_yvec[2] == 0 && selected_brushes.next->next != &selected_brushes)
388                 {
389                         VectorAdd (g_qeglobals.d_select_translate, move, g_qeglobals.d_select_translate);
390                 }
391                 else
392                 {
393                         Select_Move (move);
394                 }
395         }
396 }
397
398 /*
399 ===========
400 Drag_MouseMoved
401 ===========
402 */
403 void Drag_MouseMoved (int x, int y, int buttons)
404 {
405         vec3_t  move, delta;
406         int             i;
407         char    movestring[128];
408
409         if (!buttons)
410         {
411                 drag_ok = false;
412                 return;
413         }
414         if (!drag_ok)
415                 return;
416
417         // clear along one axis
418         if (buttons & MK_SHIFT)
419         {
420                 drag_first = false;
421                 if (abs(x-pressx) > abs(y-pressy))
422                         y = pressy;
423                 else
424                         x = pressx;
425         }
426
427
428         for (i=0 ; i<3 ; i++)
429         {
430                 move[i] = drag_xvec[i]*(x - pressx)
431                                 + drag_yvec[i]*(y - pressy);
432                 move[i] = floor(move[i]/g_qeglobals.d_gridsize+0.5)*g_qeglobals.d_gridsize;
433         }
434
435         sprintf (movestring, "drag (%i %i %i)", (int)move[0], (int)move[1], (int)move[2]);
436         Sys_Status (movestring, 0);
437
438         VectorSubtract (move, pressdelta, delta);
439         MoveSelection (delta);
440         VectorCopy (move, pressdelta);
441 }
442
443 /*
444 ===========
445 Drag_MouseUp
446 ===========
447 */
448 void Drag_MouseUp (void)
449 {
450         Sys_Status ("drag completed.", 0);
451         if (g_qeglobals.d_select_translate[0] || g_qeglobals.d_select_translate[1] || g_qeglobals.d_select_translate[2])
452         {
453                 Select_Move (g_qeglobals.d_select_translate);
454                 VectorCopy (vec3_origin, g_qeglobals.d_select_translate);
455                 Sys_UpdateWindows (W_CAMERA);
456         }
457 }