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
AxializeVector(vec3_t v)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 */
Drag_Setup(int x,int y,int buttons,vec3_t xaxis,vec3_t yaxis,vec3_t origin,vec3_t dir)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
UpdateTarget(vec3_t origin,vec3_t dir)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 */
Drag_Begin(int x,int y,int buttons,vec3_t xaxis,vec3_t yaxis,vec3_t origin,vec3_t dir)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 */
MoveSelection(vec3_t move)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 */
Drag_MouseMoved(int x,int y,int buttons)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 */
Drag_MouseUp(void)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 }
458