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