]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - radiant/drag.cpp
get the basics of a new scons build system together
[xonotic/netradiant.git] / radiant / drag.cpp
1 /*\r
2 Copyright (C) 1999-2007 id Software, Inc. and contributors.\r
3 For a list of contributors, see the accompanying CONTRIBUTORS file.\r
4 \r
5 This file is part of GtkRadiant.\r
6 \r
7 GtkRadiant is free software; you can redistribute it and/or modify\r
8 it under the terms of the GNU General Public License as published by\r
9 the Free Software Foundation; either version 2 of the License, or\r
10 (at your option) any later version.\r
11 \r
12 GtkRadiant is distributed in the hope that it will be useful,\r
13 but WITHOUT ANY WARRANTY; without even the implied warranty of\r
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
15 GNU General Public License for more details.\r
16 \r
17 You should have received a copy of the GNU General Public License\r
18 along with GtkRadiant; if not, write to the Free Software\r
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\r
20 */\r
21 \r
22 #include "stdafx.h"\r
23 //#include "qe3.h"\r
24 \r
25 /*\r
26 \r
27   drag either multiple brushes, or select plane points from\r
28   a single brush.\r
29 \r
30 */\r
31 \r
32 extern int g_nPatchClickedView;\r
33 \r
34 qboolean        drag_ok;\r
35 vec3_t  drag_xvec;\r
36 vec3_t  drag_yvec;\r
37 \r
38 //static        int     buttonstate;\r
39 int     pressx, pressy;\r
40 static  vec3_t pressdelta;\r
41 static  vec3_t vPressStart;\r
42 //static        int     buttonx, buttony;\r
43 \r
44 \r
45 //int           num_move_points;\r
46 //float *move_points[1024];\r
47 \r
48 int             lastx, lasty;\r
49 \r
50 qboolean        drag_first;\r
51 \r
52 \r
53 void    AxializeVector (vec3_t v)\r
54 {\r
55         vec3_t  a;\r
56         float   o;\r
57         int             i;\r
58 \r
59         if (!v[0] && !v[1])\r
60                 return;\r
61         if (!v[1] && !v[2])\r
62                 return;\r
63         if (!v[0] && !v[2])\r
64                 return;\r
65 \r
66         for (i=0 ; i<3 ; i++)\r
67                 a[i] = fabs(v[i]);\r
68         if (a[0] > a[1] && a[0] > a[2])\r
69                 i = 0;\r
70         else if (a[1] > a[0] && a[1] > a[2])\r
71                 i = 1;\r
72         else\r
73                 i = 2;\r
74 \r
75         o = v[i];\r
76         VectorCopy (vec3_origin, v);\r
77         if (o<0)\r
78                 v[i] = -1;\r
79         else\r
80                 v[i] = 1;\r
81         \r
82 }\r
83 \r
84 /*\r
85 ===========\r
86 Drag_Setup\r
87 ===========\r
88 */\r
89 extern void SelectCurvePointByRay (vec3_t org, vec3_t dir, int buttons);\r
90 \r
91 void Drag_Setup (int x, int y, int buttons,\r
92                  vec3_t xaxis, vec3_t yaxis,\r
93                  vec3_t origin, vec3_t dir)\r
94 {\r
95   trace_t       t;\r
96   face_t        *f;\r
97 \r
98   drag_first = true;\r
99   \r
100   VectorCopy (vec3_origin, pressdelta);\r
101   pressx = x;\r
102   pressy = y;\r
103 \r
104         // snap to nearest axis for camwindow drags\r
105   VectorCopy (xaxis, drag_xvec);\r
106   AxializeVector (drag_xvec);\r
107   VectorCopy (yaxis, drag_yvec);\r
108   AxializeVector (drag_yvec);\r
109 \r
110   if (g_qeglobals.d_select_mode == sel_curvepoint)\r
111   {\r
112     SelectCurvePointByRay (origin, dir, buttons);       \r
113 \r
114     if(g_qeglobals.d_select_mode == sel_area)\r
115     {\r
116       drag_ok = true;\r
117 \r
118                         if(g_nPatchClickedView == W_CAMERA ) {\r
119                                 VectorSet( g_qeglobals.d_vAreaTL, x, y, 0 );\r
120                                 VectorSet( g_qeglobals.d_vAreaBR, x, y, 0 );\r
121                         }\r
122     }\r
123     else if (g_qeglobals.d_num_move_points) // don't add an undo if there are no points selected\r
124     {\r
125       drag_ok = true;\r
126       Sys_UpdateWindows(W_ALL);\r
127       Undo_Start("drag curve point");\r
128       Undo_AddBrushList(&selected_brushes);\r
129     }\r
130     return;\r
131   }\r
132   else\r
133   {\r
134     g_qeglobals.d_num_move_points = 0;\r
135   }\r
136 \r
137   if (g_qeglobals.d_select_mode == sel_areatall)\r
138   {\r
139     VectorCopy(origin, g_qeglobals.d_vAreaTL);\r
140     VectorCopy(origin, g_qeglobals.d_vAreaBR);\r
141 \r
142     Sys_UpdateWindows(W_ALL);\r
143 \r
144     drag_ok = true; \r
145     return;\r
146   }\r
147 \r
148   if (selected_brushes.next == &selected_brushes)\r
149   {\r
150     //in this case a new brush is created when the dragging\r
151     //takes place in the XYWnd, An useless undo is created\r
152     //when the dragging takes place in the CamWnd\r
153     Undo_Start("create brush");\r
154 \r
155     Sys_Status("No selection to drag", 0);\r
156     return;\r
157   }\r
158 \r
159   if (g_qeglobals.d_select_mode == sel_vertex)\r
160   {\r
161     SelectVertexByRay (origin, dir);    \r
162     if (g_qeglobals.d_num_move_points)\r
163     {\r
164       drag_ok = true;\r
165       Undo_Start("drag vertex");\r
166       Undo_AddBrushList(&selected_brushes);\r
167       // Need an update here for highlighting selected vertices\r
168       Sys_UpdateWindows(W_XY | W_CAMERA);\r
169       return;\r
170     }\r
171   }\r
172 \r
173   if (g_qeglobals.d_select_mode == sel_edge)\r
174   {\r
175     SelectEdgeByRay (origin, dir);      \r
176     if (g_qeglobals.d_num_move_points)\r
177     {\r
178       drag_ok = true;\r
179       Undo_Start("drag edge");\r
180       Undo_AddBrushList(&selected_brushes);\r
181       return;\r
182     }\r
183   }\r
184 \r
185   //\r
186   // check for direct hit first\r
187   //\r
188   t = Test_Ray (origin, dir, true);\r
189   if (t.selected)\r
190   {\r
191     drag_ok = true;\r
192 \r
193     Undo_Start("drag selection");\r
194     Undo_AddBrushList(&selected_brushes);\r
195 \r
196     if (buttons == (MK_LBUTTON|MK_CONTROL) )\r
197     {\r
198       Sys_Printf ("Shear dragging face\n");\r
199       Brush_SelectFaceForDragging (t.brush, t.face, true);\r
200     }\r
201     else if (buttons == (MK_LBUTTON|MK_CONTROL|MK_SHIFT) )\r
202     {\r
203       Sys_Printf ("Sticky dragging brush\n");\r
204       for (f=t.brush->brush_faces ; f ; f=f->next)\r
205         Brush_SelectFaceForDragging (t.brush, f, false);\r
206     }\r
207     else\r
208       Sys_Printf ("Dragging entire selection\n");\r
209     \r
210     return;\r
211   }\r
212 \r
213   if (g_qeglobals.d_select_mode == sel_vertex || g_qeglobals.d_select_mode == sel_edge)\r
214     return;\r
215 \r
216   //\r
217   // check for side hit\r
218   //\r
219   // multiple brushes selected?\r
220   if (selected_brushes.next->next != &selected_brushes)\r
221   {\r
222     // yes, special handling\r
223     bool bOK = (g_PrefsDlg.m_bALTEdge) ? Sys_AltDown() : true;\r
224     if (bOK)\r
225     {\r
226       for (brush_t* pBrush = selected_brushes.next ; pBrush != &selected_brushes ; pBrush = pBrush->next)\r
227       {\r
228         if (buttons & MK_CONTROL)\r
229           Brush_SideSelect (pBrush, origin, dir, true);\r
230         else\r
231           Brush_SideSelect (pBrush, origin, dir, false);\r
232       }\r
233     }\r
234     else\r
235     {\r
236       Sys_Printf ("press ALT to drag multiple edges\n");\r
237       return;\r
238     }\r
239   }\r
240   else\r
241   {\r
242     // single select.. trying to drag fixed entities handle themselves and just move\r
243     if (buttons & MK_CONTROL)\r
244       Brush_SideSelect (selected_brushes.next, origin, dir, true);\r
245     else\r
246       Brush_SideSelect (selected_brushes.next, origin, dir, false);\r
247   }\r
248 \r
249   Sys_Printf ("Side stretch\n");\r
250   drag_ok = true;\r
251 \r
252   Undo_Start("side stretch");\r
253   Undo_AddBrushList(&selected_brushes);\r
254 }\r
255 \r
256 entity_t *peLink;\r
257 \r
258 void UpdateTarget(vec3_t origin, vec3_t dir)\r
259 {\r
260         trace_t t;\r
261         entity_t *pe;\r
262         int i;\r
263         char sz[128];\r
264 \r
265         t = Test_Ray (origin, dir, 0);\r
266 \r
267         if (!t.brush)\r
268                 return;\r
269 \r
270         pe = t.brush->owner;\r
271 \r
272         if (pe == NULL)\r
273                 return;\r
274 \r
275         // is this the first?\r
276         if (peLink != NULL)\r
277         {\r
278 \r
279                 // Get the target id from out current target\r
280                 // if there is no id, make one\r
281 \r
282                 i = IntForKey(pe, "target");\r
283                 if (i <= 0)\r
284                 {\r
285                         i = GetUniqueTargetId(1);\r
286                         sprintf(sz, "%d", i);\r
287 \r
288                         SetKeyValue(pe, "target", sz);\r
289                 }\r
290 \r
291                 // set the target # into our src\r
292 \r
293                 sprintf(sz, "%d", i);\r
294                 SetKeyValue(peLink, "targetname", sz);\r
295 \r
296                 Sys_UpdateWindows(W_ENTITY);\r
297 \r
298         }\r
299 \r
300         // promote the target to the src\r
301 \r
302         peLink = pe;\r
303         \r
304 }\r
305 \r
306 /*\r
307 ===========\r
308 Drag_Begin\r
309 //++timo test three button mouse and three button emulation here ?\r
310 ===========\r
311 */\r
312 void Drag_Begin (int x, int y, int buttons,\r
313                    vec3_t xaxis, vec3_t yaxis,\r
314                    vec3_t origin, vec3_t dir, bool sf_camera)\r
315 {\r
316         trace_t t;\r
317   bool altdown;\r
318   int nFlag;\r
319 \r
320         drag_ok = false;\r
321         VectorCopy (vec3_origin, pressdelta);\r
322         VectorCopy (vec3_origin, vPressStart);\r
323 \r
324         drag_first = true;\r
325         peLink = NULL;\r
326 \r
327   altdown = Sys_AltDown();\r
328 \r
329         // shift-LBUTTON = select entire brush\r
330   // shift-alt-LBUTTON = drill select\r
331         if (buttons == (MK_LBUTTON | MK_SHIFT) && g_qeglobals.d_select_mode != sel_curvepoint)\r
332         {\r
333     nFlag = altdown ? SF_CYCLE : 0;\r
334     if (sf_camera)\r
335       nFlag |= SF_CAMERA;\r
336     else\r
337       nFlag |= SF_ENTITIES_FIRST;\r
338     Select_Ray(origin, dir, nFlag);\r
339                 return;\r
340         }\r
341 \r
342   // (shift-)alt-LBUTTON = area select completely tall\r
343   if ( !sf_camera &&\r
344       ( g_PrefsDlg.m_bALTEdge ? buttons == (MK_LBUTTON | MK_CONTROL | MK_SHIFT) : (buttons == MK_LBUTTON || buttons == (MK_LBUTTON | MK_CONTROL | MK_SHIFT)) ) &&\r
345       altdown && g_qeglobals.d_select_mode != sel_curvepoint)\r
346   {\r
347     if (g_pParentWnd->ActiveXY()->AreaSelectOK())\r
348     {\r
349       g_qeglobals.d_select_mode = sel_areatall;\r
350 \r
351       Drag_Setup (x, y, buttons, xaxis, yaxis, origin, dir);\r
352       return;\r
353     }\r
354   }\r
355 \r
356         // ctrl-alt-LBUTTON = multiple brush select without selecting whole entities\r
357         if (buttons == (MK_LBUTTON | MK_CONTROL) && altdown && g_qeglobals.d_select_mode != sel_curvepoint)\r
358         {\r
359     nFlag = 0;\r
360     if (sf_camera)\r
361       nFlag |= SF_CAMERA;\r
362     else\r
363       nFlag |= SF_ENTITIES_FIRST;\r
364     Select_Ray (origin, dir, nFlag);\r
365     UpdateSurfaceDialog();\r
366     \r
367                 return;\r
368         }\r
369 \r
370         // ctrl-shift LBUTTON = select single face\r
371         if (sf_camera && buttons == (MK_LBUTTON | MK_CONTROL | MK_SHIFT) && g_qeglobals.d_select_mode != sel_curvepoint)\r
372         {\r
373     if(Sys_AltDown())\r
374     {\r
375       brush_t *b;\r
376       for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)\r
377       {\r
378         if(b->pPatch)\r
379           continue;\r
380 \r
381         for (face_t* pFace = b->brush_faces; pFace; pFace = pFace->next)\r
382         {\r
383           g_ptrSelectedFaces.Add(pFace);\r
384           g_ptrSelectedFaceBrushes.Add(b);\r
385         }\r
386       }\r
387 \r
388       for (b = selected_brushes.next; b != &selected_brushes; )\r
389       {\r
390         brush_t *pb = b;\r
391                           b = b->next;\r
392         Brush_RemoveFromList (pb);\r
393         Brush_AddToList (pb, &active_brushes);\r
394       }\r
395     }\r
396     else\r
397                   Select_Deselect (true);\r
398 \r
399                 Select_Ray (origin, dir, (SF_SINGLEFACE|SF_CAMERA));\r
400                 return;\r
401         }\r
402 \r
403 \r
404         // LBUTTON + all other modifiers = manipulate selection\r
405         if (buttons & MK_LBUTTON)\r
406         {\r
407                 Drag_Setup (x, y, buttons, xaxis, yaxis, origin, dir);\r
408                 return;\r
409         }\r
410 \r
411         int nMouseButton = g_PrefsDlg.m_nMouseButtons == 2 ? MK_RBUTTON : MK_MBUTTON;\r
412         // middle button = grab texture\r
413         if (buttons == nMouseButton)\r
414         {\r
415                 t = Test_Ray (origin, dir, false);\r
416                 if (t.face)\r
417                 {\r
418       UpdateWorkzone_ForBrush( t.brush );\r
419                         // use a local brushprimit_texdef fitted to a default 2x2 texture\r
420                         brushprimit_texdef_t bp_local;\r
421                         ConvertTexMatWithQTexture( &t.face->brushprimit_texdef, t.face->d_texture, &bp_local, NULL );\r
422                         Texture_SetTexture ( &t.face->texdef, &bp_local, false, NULL);\r
423                         UpdateSurfaceDialog();\r
424                         UpdatePatchInspector();\r
425                 }\r
426                 else\r
427                         Sys_Printf ("Did not select a texture\n");\r
428                 return;\r
429         }\r
430 \r
431         // ctrl-middle button = set entire brush to texture\r
432         if (buttons == (nMouseButton|MK_CONTROL) )\r
433         {\r
434                 t = Test_Ray (origin, dir, false);\r
435                 if (t.brush)\r
436                 {\r
437                         if (t.brush->brush_faces->texdef.GetName()[0] == '(')\r
438                                 Sys_Printf ("Can't change an entity texture\n");\r
439                         else\r
440                         {\r
441                                 Brush_SetTexture (t.brush, &g_qeglobals.d_texturewin.texdef, &g_qeglobals.d_texturewin.brushprimit_texdef, false, static_cast<IPluginTexdef *>( g_qeglobals.d_texturewin.pTexdef ) );\r
442                                 Sys_UpdateWindows (W_ALL);\r
443                         }\r
444                 }\r
445                 else\r
446                         Sys_Printf ("Didn't hit a btrush\n");\r
447                 return;\r
448         }\r
449 \r
450         // ctrl-shift-middle button = set single face to texture\r
451         if (buttons == (nMouseButton|MK_SHIFT|MK_CONTROL) )\r
452         {\r
453                 t = Test_Ray (origin, dir, false);\r
454                 if (t.brush)\r
455                 {\r
456                         if (t.brush->brush_faces->texdef.GetName()[0] == '(')\r
457                                 Sys_Printf ("Can't change an entity texture\n");\r
458                         else\r
459                         {\r
460                                 SetFaceTexdef (t.face, &g_qeglobals.d_texturewin.texdef, &g_qeglobals.d_texturewin.brushprimit_texdef);\r
461                                 Brush_Build( t.brush );\r
462 \r
463                                 Sys_UpdateWindows (W_ALL);\r
464                         }\r
465                 }\r
466                 else\r
467                         Sys_Printf ("Didn't hit a btrush\n");\r
468                 return;\r
469         }\r
470 \r
471         if (buttons == (nMouseButton | MK_SHIFT))\r
472         {\r
473                 Sys_Printf("Set brush face texture info\n");\r
474                 t = Test_Ray (origin, dir, false);\r
475                 if (t.brush)\r
476                 {\r
477                         if (t.brush->brush_faces->texdef.GetName()[0] == '(')\r
478       {\r
479         if (t.brush->owner->eclass->nShowFlags & ECLASS_LIGHT)\r
480         {\r
481           CString strBuff;\r
482           qtexture_t* pTex = g_qeglobals.d_texturewin.pShader->getTexture();\r
483           if (pTex)\r
484           {\r
485             vec3_t vColor;\r
486             VectorCopy(pTex->color, vColor);\r
487 \r
488             float fLargest = 0.0f;\r
489             for (int i = 0; i < 3; i++)\r
490             {\r
491                           if (vColor[i] > fLargest)\r
492                                   fLargest = vColor[i];\r
493             }\r
494                         \r
495                         if (fLargest == 0.0f)\r
496                         {\r
497               vColor[0] = vColor[1] = vColor[2] = 1.0f;\r
498             }\r
499                         else\r
500                         {\r
501                                 float fScale = 1.0f / fLargest;\r
502               for (int i = 0; i < 3; i++)\r
503               {\r
504                 vColor[i] *= fScale;\r
505               }\r
506             }\r
507             strBuff.Format("%f %f %f",pTex->color[0], pTex->color[1], pTex->color[2]);\r
508             SetKeyValue(t.brush->owner, "_color", strBuff.GetBuffer());\r
509                                     Sys_UpdateWindows (W_ALL);\r
510           }\r
511         }\r
512         else\r
513         {\r
514                                   Sys_Printf ("Can't select an entity brush face\n");\r
515         }\r
516       }\r
517                         else\r
518                         {\r
519         // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=425\r
520         Face_SetShader(t.face, g_qeglobals.d_texturewin.texdef.GetName());\r
521                                 Brush_Build(t.brush);\r
522 \r
523                                 Sys_UpdateWindows (W_ALL);\r
524                         }\r
525                 }\r
526                 else\r
527                         Sys_Printf ("Didn't hit a brush\n");\r
528                 return;\r
529         }\r
530 \r
531 }\r
532 \r
533 \r
534 //\r
535 //===========\r
536 //MoveSelection\r
537 //===========\r
538 //\r
539 void MoveSelection (vec3_t move)\r
540 {\r
541         int             i, success;\r
542         brush_t *b;\r
543         CString strStatus;\r
544         vec3_t vTemp, vTemp2, end;\r
545 \r
546         if (!move[0] && !move[1] && !move[2])\r
547   {\r
548                 return;\r
549   }\r
550 \r
551   if (!(g_qeglobals.d_select_mode == sel_area || g_qeglobals.d_select_mode == sel_areatall))\r
552   {\r
553     move[0] = (g_nScaleHow & SCALE_X) ? 0 : move[0];\r
554     move[1] = (g_nScaleHow & SCALE_Y) ? 0 : move[1];\r
555     move[2] = (g_nScaleHow & SCALE_Z) ? 0 : move[2];\r
556   }\r
557 \r
558         if (g_pParentWnd->ActiveXY()->RotateMode() || g_bPatchBendMode)\r
559         {\r
560                 float fDeg = -move[2];\r
561                 float fAdj = move[2];\r
562                 int nAxis = 0;\r
563                 if (g_pParentWnd->ActiveXY()->GetViewType() == XY)\r
564                 {\r
565                         fDeg = -move[1];\r
566                         fAdj = move[1];\r
567                         nAxis = 2;\r
568                 }\r
569                 else \r
570                 if (g_pParentWnd->ActiveXY()->GetViewType() == XZ)\r
571                 {\r
572                         fDeg = move[2];\r
573                         fAdj = move[2];\r
574                         nAxis = 1;\r
575                 }\r
576                 else\r
577                         nAxis = 0;\r
578 \r
579                 g_pParentWnd->ActiveXY()->Rotation()[nAxis] += fAdj;\r
580                 strStatus.Format("%s x:: %.1f  y:: %.1f  z:: %.1f", (g_bPatchBendMode) ? "Bend angle" : "Rotation", g_pParentWnd->ActiveXY()->Rotation()[0], g_pParentWnd->ActiveXY()->Rotation()[1], g_pParentWnd->ActiveXY()->Rotation()[2]);\r
581                 g_pParentWnd->SetStatusText(2, strStatus);\r
582 \r
583                 if (g_bPatchBendMode)\r
584                 {\r
585                         Patch_SelectBendNormal();\r
586                         Select_RotateAxis(nAxis, fDeg*2, false, true);\r
587                         Patch_SelectBendAxis();\r
588                         Select_RotateAxis(nAxis, fDeg, false, true);\r
589                 }\r
590                 else\r
591                 {\r
592                         Select_RotateAxis(nAxis, fDeg, false, true);\r
593                 }\r
594                 return;\r
595         }\r
596 \r
597         if (g_pParentWnd->ActiveXY()->ScaleMode())\r
598         {\r
599                 vec3_t v;\r
600                 v[0] = v[1] = v[2] = 1.0f;\r
601                 if (move[1] > 0)\r
602                 {\r
603                         v[0] = 1.1f;\r
604                         v[1] = 1.1f;\r
605                         v[2] = 1.1f;\r
606                 }\r
607                 else \r
608                         if (move[1] < 0)\r
609                 {\r
610                         v[0] = 0.9f;\r
611                         v[1] = 0.9f;\r
612                         v[2] = 0.9f;\r
613                 }\r
614 \r
615                         Select_Scale((g_nScaleHow & SCALE_X) ? 1.0f : v[0],\r
616                                                                          (g_nScaleHow & SCALE_Y) ? 1.0f : v[1],\r
617                                                                  (g_nScaleHow & SCALE_Z) ? 1.0f : v[2]);\r
618       // is that really necessary???\r
619                 Sys_UpdateWindows (W_ALL);\r
620                 return;\r
621         }\r
622 \r
623 \r
624         vec3_t vDistance;\r
625         VectorSubtract(pressdelta, vPressStart, vDistance);\r
626         strStatus.Format("Distance x: %.1f  y: %.1f  z: %.1f", vDistance[0], vDistance[1], vDistance[2]);\r
627         g_pParentWnd->SetStatusText(3, strStatus);\r
628 \r
629         //\r
630         // dragging only a part of the selection\r
631         //\r
632 \r
633         // this is fairly crappy way to deal with curvepoint and area selection\r
634         // but it touches the smallest amount of code this way\r
635         // \r
636         if (g_qeglobals.d_num_move_points || g_qeglobals.d_select_mode == sel_vertex || g_qeglobals.d_select_mode == sel_area || g_qeglobals.d_select_mode == sel_areatall)\r
637         {\r
638                 //area selection\r
639     if (g_qeglobals.d_select_mode == sel_area || g_qeglobals.d_select_mode == sel_areatall)\r
640                 {\r
641                         VectorAdd(g_qeglobals.d_vAreaBR, move, g_qeglobals.d_vAreaBR);\r
642                         return;\r
643                 }\r
644                 //curve point selection\r
645                 if (g_qeglobals.d_select_mode == sel_curvepoint)\r
646                 {\r
647                         Patch_UpdateSelected(move);\r
648                         return;\r
649                 }\r
650                 //vertex selection\r
651                 if (g_qeglobals.d_select_mode == sel_vertex && g_PrefsDlg.m_bVertexSplit)\r
652                 {\r
653       if(g_qeglobals.d_num_move_points) {\r
654                           success = true;\r
655                           for (b = selected_brushes.next; b != &selected_brushes; b = b->next)\r
656                           {\r
657                                   success &= Brush_MoveVertex(b, g_qeglobals.d_move_points[0], move, end, true);\r
658                           }\r
659                           if (success)\r
660                                   VectorCopy(end, g_qeglobals.d_move_points[0]);\r
661       }\r
662                         return;\r
663                 }\r
664                 //all other selection types\r
665                 for (i=0 ; i<g_qeglobals.d_num_move_points ; i++)\r
666                         VectorAdd (g_qeglobals.d_move_points[i], move, g_qeglobals.d_move_points[i]);\r
667                 for (b = selected_brushes.next; b != &selected_brushes; b = b->next)\r
668                 {\r
669       bool bMoved = false;\r
670       for(face_t *f = b->brush_faces; !bMoved && f!=NULL; f=f->next)\r
671         for(int p=0; !bMoved && p<3; p++)\r
672           for (i=0 ; !bMoved && i<g_qeglobals.d_num_move_points ; i++)\r
673                               if(f->planepts[p] == g_qeglobals.d_move_points[i])\r
674               bMoved = true;\r
675                   if(!bMoved) continue;\r
676 \r
677                         VectorCopy(b->maxs, vTemp);\r
678                         VectorSubtract(vTemp, b->mins, vTemp);\r
679       Brush_Build(b,true,true,false,false); // don't filter\r
680                         for (i=0 ; i<3 ; i++)\r
681                         {\r
682                                 if (b->mins[i] > b->maxs[i]\r
683                                 || b->maxs[i] - b->mins[i] > g_MaxBrushSize)\r
684                                         break;  // dragged backwards or fucked up\r
685                         }\r
686                         if (i != 3)\r
687                                 break;\r
688                         if (b->patchBrush)\r
689                         {\r
690                                 VectorCopy(b->maxs, vTemp2);\r
691                                 VectorSubtract(vTemp2, b->mins, vTemp2);\r
692                                 VectorSubtract(vTemp2, vTemp, vTemp2);\r
693                                 //if (!Patch_DragScale(b->nPatchID, vTemp2, move))\r
694                                 if (!Patch_DragScale(b->pPatch, vTemp2, move))\r
695                                 {\r
696                                         b = NULL;\r
697                                         break;\r
698                                 }\r
699                         }\r
700                 }\r
701                 // if any of the brushes were crushed out of existance\r
702                 // calcel the entire move\r
703                 if (b != &selected_brushes)\r
704                 {\r
705                         Sys_Printf ("Brush dragged backwards, move canceled\n");\r
706                         for (i=0 ; i<g_qeglobals.d_num_move_points ; i++)\r
707                                 VectorSubtract (g_qeglobals.d_move_points[i], move, g_qeglobals.d_move_points[i]);\r
708 \r
709                         for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)\r
710                                 Brush_Build(b,true,true,false,false); // don't filter\r
711                 }\r
712 \r
713         }\r
714         else\r
715         {\r
716                 // reset face originals from vertex edit mode\r
717                 // this is dirty, but unfortunately necessary because Brush_Build\r
718                 // can remove windings\r
719                 for (b = selected_brushes.next; b != &selected_brushes; b = b->next)\r
720                 {\r
721                         Brush_ResetFaceOriginals(b);\r
722                 }\r
723                 //\r
724                 // if there are lots of brushes selected, just translate instead\r
725                 // of rebuilding the brushes\r
726     // NOTE: this is not actually done, but would be a good idea\r
727                 //\r
728           Select_Move (move);\r
729         }\r
730 }\r
731 \r
732 /*\r
733 ===========\r
734 Drag_MouseMoved\r
735 ===========\r
736 */\r
737 void Drag_MouseMoved (int x, int y, int buttons)\r
738 {\r
739   vec3_t        move, delta;\r
740   int           i;\r
741 \r
742   if (!buttons)\r
743   {\r
744     drag_ok = false;\r
745     return;\r
746   }\r
747   if (!drag_ok)\r
748     return;\r
749 \r
750   // clear along one axis\r
751   if (buttons & MK_SHIFT && (g_PrefsDlg.m_bALTEdge && g_qeglobals.d_select_mode != sel_areatall))\r
752   {\r
753     drag_first = false;\r
754     if (abs(x-pressx) > abs(y-pressy))\r
755       y = pressy;\r
756     else\r
757       x = pressx;\r
758   }\r
759 \r
760         if (g_qeglobals.d_select_mode == sel_area && g_nPatchClickedView == W_CAMERA)\r
761         {\r
762                 camera_t *m_pCamera = g_pParentWnd->GetCamWnd()->Camera();\r
763 \r
764                 // snap to window\r
765                 if( y > m_pCamera->height ) y = m_pCamera->height - 1; else if( y < 0 ) y = 0;\r
766                 if( x > m_pCamera->width ) x = m_pCamera->width - 1; else if( x < 0 ) x = 0;\r
767 \r
768                 VectorSet (move, x - pressx, y - pressy, 0);\r
769         } else\r
770         {\r
771                 for (i=0 ; i<3 ; i++)\r
772                 {\r
773                         move[i] = drag_xvec[i]*(x - pressx)     + drag_yvec[i]*(y - pressy);\r
774                         if (!g_PrefsDlg.m_bNoClamp)\r
775                         {\r
776                                 move[i] = floor(move[i]/g_qeglobals.d_gridsize+0.5)*g_qeglobals.d_gridsize;\r
777                         }\r
778                 }\r
779         }\r
780 \r
781   VectorSubtract (move, pressdelta, delta);\r
782   VectorCopy (move, pressdelta);\r
783 \r
784   MoveSelection (delta);\r
785 }\r
786 \r
787 /*\r
788 ===========\r
789 Drag_MouseUp\r
790 ===========\r
791 */\r
792 void Drag_MouseUp (int nButtons)\r
793 {\r
794         Sys_Status ("Drag completed.", 0);\r
795 \r
796   if (g_qeglobals.d_select_mode == sel_area)\r
797   {\r
798     Patch_SelectAreaPoints(nButtons & MK_CONTROL); // adds to selection and/or deselects selected points if ctrl is held\r
799     g_qeglobals.d_select_mode = sel_curvepoint;\r
800                 Sys_UpdateWindows (W_ALL);\r
801   }\r
802 \r
803   if (g_qeglobals.d_select_mode == sel_areatall)\r
804   {\r
805     vec3_t mins, maxs;\r
806 \r
807     int nDim1 = (g_pParentWnd->ActiveXY()->GetViewType() == YZ) ? 1 : 0;\r
808     int nDim2 = (g_pParentWnd->ActiveXY()->GetViewType() == XY) ? 1 : 2;\r
809 \r
810                 // get our rectangle\r
811     mins[nDim1] = MIN( g_qeglobals.d_vAreaTL[nDim1], g_qeglobals.d_vAreaBR[nDim1] );\r
812     mins[nDim2] = MIN( g_qeglobals.d_vAreaTL[nDim2], g_qeglobals.d_vAreaBR[nDim2] );\r
813     maxs[nDim1] = MAX( g_qeglobals.d_vAreaTL[nDim1], g_qeglobals.d_vAreaBR[nDim1] );\r
814     maxs[nDim2] = MAX( g_qeglobals.d_vAreaTL[nDim2], g_qeglobals.d_vAreaBR[nDim2] );\r
815 \r
816     // deselect current selection\r
817     if( !(nButtons & (MK_CONTROL|MK_SHIFT)) )\r
818       Select_Deselect();\r
819 \r
820     // select new selection\r
821     Select_RealCompleteTall( mins, maxs );\r
822 \r
823     Sys_UpdateWindows (W_ALL);\r
824   }\r
825 \r
826   if (g_qeglobals.d_select_translate[0] || g_qeglobals.d_select_translate[1] || g_qeglobals.d_select_translate[2])\r
827         {\r
828                 Select_Move (g_qeglobals.d_select_translate);\r
829                 VectorCopy (vec3_origin, g_qeglobals.d_select_translate);\r
830                 Sys_UpdateWindows (W_CAMERA);\r
831         }\r
832   \r
833   /* note: added cleanup here, since an edge drag will leave selected vertices \r
834            in g_qeglobals.d_num_move_points\r
835   */\r
836   if (  g_qeglobals.d_select_mode != sel_vertex && \r
837         g_qeglobals.d_select_mode != sel_curvepoint &&\r
838         g_qeglobals.d_select_mode != sel_edge)\r
839     g_qeglobals.d_num_move_points = 0;\r
840   \r
841   g_pParentWnd->SetStatusText(3, "");\r
842   Undo_EndBrushList(&selected_brushes);\r
843   Undo_End();\r
844   UpdateSurfaceDialog();\r
845 }\r