]> de.git.xonotic.org Git - xonotic/netradiant.git/blobdiff - radiant/drag.cpp
more eol-style
[xonotic/netradiant.git] / radiant / drag.cpp
index f9e67aefe04002bbb352ae53e81ae33d41535ac1..d8df7b82c379f05e3072cc93dfa074de401832ed 100644 (file)
-/*\r
-Copyright (C) 1999-2007 id Software, Inc. and contributors.\r
-For a list of contributors, see the accompanying CONTRIBUTORS file.\r
-\r
-This file is part of GtkRadiant.\r
-\r
-GtkRadiant is free software; you can redistribute it and/or modify\r
-it under the terms of the GNU General Public License as published by\r
-the Free Software Foundation; either version 2 of the License, or\r
-(at your option) any later version.\r
-\r
-GtkRadiant is distributed in the hope that it will be useful,\r
-but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-GNU General Public License for more details.\r
-\r
-You should have received a copy of the GNU General Public License\r
-along with GtkRadiant; if not, write to the Free Software\r
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\r
-*/\r
-\r
-#include "stdafx.h"\r
-//#include "qe3.h"\r
-\r
-/*\r
-\r
-  drag either multiple brushes, or select plane points from\r
-  a single brush.\r
-\r
-*/\r
-\r
-extern int g_nPatchClickedView;\r
-\r
-qboolean       drag_ok;\r
-vec3_t drag_xvec;\r
-vec3_t drag_yvec;\r
-\r
-//static       int     buttonstate;\r
-int    pressx, pressy;\r
-static vec3_t pressdelta;\r
-static vec3_t vPressStart;\r
-//static       int     buttonx, buttony;\r
-\r
-\r
-//int          num_move_points;\r
-//float        *move_points[1024];\r
-\r
-int            lastx, lasty;\r
-\r
-qboolean       drag_first;\r
-\r
-\r
-void   AxializeVector (vec3_t v)\r
-{\r
-       vec3_t  a;\r
-       float   o;\r
-       int             i;\r
-\r
-       if (!v[0] && !v[1])\r
-               return;\r
-       if (!v[1] && !v[2])\r
-               return;\r
-       if (!v[0] && !v[2])\r
-               return;\r
-\r
-       for (i=0 ; i<3 ; i++)\r
-               a[i] = fabs(v[i]);\r
-       if (a[0] > a[1] && a[0] > a[2])\r
-               i = 0;\r
-       else if (a[1] > a[0] && a[1] > a[2])\r
-               i = 1;\r
-       else\r
-               i = 2;\r
-\r
-       o = v[i];\r
-       VectorCopy (vec3_origin, v);\r
-       if (o<0)\r
-               v[i] = -1;\r
-       else\r
-               v[i] = 1;\r
-       \r
-}\r
-\r
-/*\r
-===========\r
-Drag_Setup\r
-===========\r
-*/\r
-extern void SelectCurvePointByRay (vec3_t org, vec3_t dir, int buttons);\r
-\r
-void Drag_Setup (int x, int y, int buttons,\r
-                vec3_t xaxis, vec3_t yaxis,\r
-                vec3_t origin, vec3_t dir)\r
-{\r
-  trace_t      t;\r
-  face_t       *f;\r
-\r
-  drag_first = true;\r
-  \r
-  VectorCopy (vec3_origin, pressdelta);\r
-  pressx = x;\r
-  pressy = y;\r
-\r
-       // snap to nearest axis for camwindow drags\r
-  VectorCopy (xaxis, drag_xvec);\r
-  AxializeVector (drag_xvec);\r
-  VectorCopy (yaxis, drag_yvec);\r
-  AxializeVector (drag_yvec);\r
-\r
-  if (g_qeglobals.d_select_mode == sel_curvepoint)\r
-  {\r
-    SelectCurvePointByRay (origin, dir, buttons);      \r
-\r
-    if(g_qeglobals.d_select_mode == sel_area)\r
-    {\r
-      drag_ok = true;\r
-\r
-                       if(g_nPatchClickedView == W_CAMERA ) {\r
-                               VectorSet( g_qeglobals.d_vAreaTL, x, y, 0 );\r
-                               VectorSet( g_qeglobals.d_vAreaBR, x, y, 0 );\r
-                       }\r
-    }\r
-    else if (g_qeglobals.d_num_move_points) // don't add an undo if there are no points selected\r
-    {\r
-      drag_ok = true;\r
-      Sys_UpdateWindows(W_ALL);\r
-      Undo_Start("drag curve point");\r
-      Undo_AddBrushList(&selected_brushes);\r
-    }\r
-    return;\r
-  }\r
-  else\r
-  {\r
-    g_qeglobals.d_num_move_points = 0;\r
-  }\r
-\r
-  if (g_qeglobals.d_select_mode == sel_areatall)\r
-  {\r
-    VectorCopy(origin, g_qeglobals.d_vAreaTL);\r
-    VectorCopy(origin, g_qeglobals.d_vAreaBR);\r
-\r
-    Sys_UpdateWindows(W_ALL);\r
-\r
-    drag_ok = true; \r
-    return;\r
-  }\r
-\r
-  if (selected_brushes.next == &selected_brushes)\r
-  {\r
-    //in this case a new brush is created when the dragging\r
-    //takes place in the XYWnd, An useless undo is created\r
-    //when the dragging takes place in the CamWnd\r
-    Undo_Start("create brush");\r
-\r
-    Sys_Status("No selection to drag", 0);\r
-    return;\r
-  }\r
-\r
-  if (g_qeglobals.d_select_mode == sel_vertex)\r
-  {\r
-    SelectVertexByRay (origin, dir);   \r
-    if (g_qeglobals.d_num_move_points)\r
-    {\r
-      drag_ok = true;\r
-      Undo_Start("drag vertex");\r
-      Undo_AddBrushList(&selected_brushes);\r
-      // Need an update here for highlighting selected vertices\r
-      Sys_UpdateWindows(W_XY | W_CAMERA);\r
-      return;\r
-    }\r
-  }\r
-\r
-  if (g_qeglobals.d_select_mode == sel_edge)\r
-  {\r
-    SelectEdgeByRay (origin, dir);     \r
-    if (g_qeglobals.d_num_move_points)\r
-    {\r
-      drag_ok = true;\r
-      Undo_Start("drag edge");\r
-      Undo_AddBrushList(&selected_brushes);\r
-      return;\r
-    }\r
-  }\r
-\r
-  //\r
-  // check for direct hit first\r
-  //\r
-  t = Test_Ray (origin, dir, true);\r
-  if (t.selected)\r
-  {\r
-    drag_ok = true;\r
-\r
-    Undo_Start("drag selection");\r
-    Undo_AddBrushList(&selected_brushes);\r
-\r
-    if (buttons == (MK_LBUTTON|MK_CONTROL) )\r
-    {\r
-      Sys_Printf ("Shear dragging face\n");\r
-      Brush_SelectFaceForDragging (t.brush, t.face, true);\r
-    }\r
-    else if (buttons == (MK_LBUTTON|MK_CONTROL|MK_SHIFT) )\r
-    {\r
-      Sys_Printf ("Sticky dragging brush\n");\r
-      for (f=t.brush->brush_faces ; f ; f=f->next)\r
-       Brush_SelectFaceForDragging (t.brush, f, false);\r
-    }\r
-    else\r
-      Sys_Printf ("Dragging entire selection\n");\r
-    \r
-    return;\r
-  }\r
-\r
-  if (g_qeglobals.d_select_mode == sel_vertex || g_qeglobals.d_select_mode == sel_edge)\r
-    return;\r
-\r
-  //\r
-  // check for side hit\r
-  //\r
-  // multiple brushes selected?\r
-  if (selected_brushes.next->next != &selected_brushes)\r
-  {\r
-    // yes, special handling\r
-    bool bOK = (g_PrefsDlg.m_bALTEdge) ? Sys_AltDown() : true;\r
-    if (bOK)\r
-    {\r
-      for (brush_t* pBrush = selected_brushes.next ; pBrush != &selected_brushes ; pBrush = pBrush->next)\r
-      {\r
-       if (buttons & MK_CONTROL)\r
-         Brush_SideSelect (pBrush, origin, dir, true);\r
-       else\r
-         Brush_SideSelect (pBrush, origin, dir, false);\r
-      }\r
-    }\r
-    else\r
-    {\r
-      Sys_Printf ("press ALT to drag multiple edges\n");\r
-      return;\r
-    }\r
-  }\r
-  else\r
-  {\r
-    // single select.. trying to drag fixed entities handle themselves and just move\r
-    if (buttons & MK_CONTROL)\r
-      Brush_SideSelect (selected_brushes.next, origin, dir, true);\r
-    else\r
-      Brush_SideSelect (selected_brushes.next, origin, dir, false);\r
-  }\r
-\r
-  Sys_Printf ("Side stretch\n");\r
-  drag_ok = true;\r
-\r
-  Undo_Start("side stretch");\r
-  Undo_AddBrushList(&selected_brushes);\r
-}\r
-\r
-entity_t *peLink;\r
-\r
-void UpdateTarget(vec3_t origin, vec3_t dir)\r
-{\r
-       trace_t t;\r
-       entity_t *pe;\r
-       int i;\r
-       char sz[128];\r
-\r
-       t = Test_Ray (origin, dir, 0);\r
-\r
-       if (!t.brush)\r
-               return;\r
-\r
-       pe = t.brush->owner;\r
-\r
-       if (pe == NULL)\r
-               return;\r
-\r
-       // is this the first?\r
-       if (peLink != NULL)\r
-       {\r
-\r
-               // Get the target id from out current target\r
-               // if there is no id, make one\r
-\r
-               i = IntForKey(pe, "target");\r
-               if (i <= 0)\r
-               {\r
-                       i = GetUniqueTargetId(1);\r
-                       sprintf(sz, "%d", i);\r
-\r
-                       SetKeyValue(pe, "target", sz);\r
-               }\r
-\r
-               // set the target # into our src\r
-\r
-               sprintf(sz, "%d", i);\r
-               SetKeyValue(peLink, "targetname", sz);\r
-\r
-               Sys_UpdateWindows(W_ENTITY);\r
-\r
-       }\r
-\r
-       // promote the target to the src\r
-\r
-       peLink = pe;\r
-       \r
-}\r
-\r
-/*\r
-===========\r
-Drag_Begin\r
-//++timo test three button mouse and three button emulation here ?\r
-===========\r
-*/\r
-void Drag_Begin (int x, int y, int buttons,\r
-                  vec3_t xaxis, vec3_t yaxis,\r
-                  vec3_t origin, vec3_t dir, bool sf_camera)\r
-{\r
-       trace_t t;\r
-  bool altdown;\r
-  int nFlag;\r
-\r
-       drag_ok = false;\r
-       VectorCopy (vec3_origin, pressdelta);\r
-       VectorCopy (vec3_origin, vPressStart);\r
-\r
-       drag_first = true;\r
-       peLink = NULL;\r
-\r
-  altdown = Sys_AltDown();\r
-\r
-       // shift-LBUTTON = select entire brush\r
-  // shift-alt-LBUTTON = drill select\r
-       if (buttons == (MK_LBUTTON | MK_SHIFT) && g_qeglobals.d_select_mode != sel_curvepoint)\r
-       {\r
-    nFlag = altdown ? SF_CYCLE : 0;\r
-    if (sf_camera)\r
-      nFlag |= SF_CAMERA;\r
-    else\r
-      nFlag |= SF_ENTITIES_FIRST;\r
-    Select_Ray(origin, dir, nFlag);\r
-               return;\r
-       }\r
-\r
-  // (shift-)alt-LBUTTON = area select completely tall\r
-  if ( !sf_camera &&\r
-      ( g_PrefsDlg.m_bALTEdge ? buttons == (MK_LBUTTON | MK_CONTROL | MK_SHIFT) : (buttons == MK_LBUTTON || buttons == (MK_LBUTTON | MK_CONTROL | MK_SHIFT)) ) &&\r
-      altdown && g_qeglobals.d_select_mode != sel_curvepoint)\r
-  {\r
-    if (g_pParentWnd->ActiveXY()->AreaSelectOK())\r
-    {\r
-      g_qeglobals.d_select_mode = sel_areatall;\r
-\r
-      Drag_Setup (x, y, buttons, xaxis, yaxis, origin, dir);\r
-      return;\r
-    }\r
-  }\r
-\r
-       // ctrl-alt-LBUTTON = multiple brush select without selecting whole entities\r
-       if (buttons == (MK_LBUTTON | MK_CONTROL) && altdown && g_qeglobals.d_select_mode != sel_curvepoint)\r
-       {\r
-    nFlag = 0;\r
-    if (sf_camera)\r
-      nFlag |= SF_CAMERA;\r
-    else\r
-      nFlag |= SF_ENTITIES_FIRST;\r
-    Select_Ray (origin, dir, nFlag);\r
-    UpdateSurfaceDialog();\r
-    \r
-               return;\r
-       }\r
-\r
-       // ctrl-shift LBUTTON = select single face\r
-       if (sf_camera && buttons == (MK_LBUTTON | MK_CONTROL | MK_SHIFT) && g_qeglobals.d_select_mode != sel_curvepoint)\r
-       {\r
-    if(Sys_AltDown())\r
-    {\r
-      brush_t *b;\r
-      for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)\r
-      {\r
-        if(b->pPatch)\r
-          continue;\r
-\r
-        for (face_t* pFace = b->brush_faces; pFace; pFace = pFace->next)\r
-        {\r
-          g_ptrSelectedFaces.Add(pFace);\r
-          g_ptrSelectedFaceBrushes.Add(b);\r
-        }\r
-      }\r
-\r
-      for (b = selected_brushes.next; b != &selected_brushes; )\r
-      {\r
-        brush_t *pb = b;\r
-                         b = b->next;\r
-        Brush_RemoveFromList (pb);\r
-        Brush_AddToList (pb, &active_brushes);\r
-      }\r
-    }\r
-    else\r
-                 Select_Deselect (true);\r
-\r
-               Select_Ray (origin, dir, (SF_SINGLEFACE|SF_CAMERA));\r
-               return;\r
-       }\r
-\r
-\r
-       // LBUTTON + all other modifiers = manipulate selection\r
-       if (buttons & MK_LBUTTON)\r
-       {\r
-               Drag_Setup (x, y, buttons, xaxis, yaxis, origin, dir);\r
-               return;\r
-       }\r
-\r
-       int nMouseButton = g_PrefsDlg.m_nMouseButtons == 2 ? MK_RBUTTON : MK_MBUTTON;\r
-       // middle button = grab texture\r
-       if (buttons == nMouseButton)\r
-       {\r
-               t = Test_Ray (origin, dir, false);\r
-               if (t.face)\r
-               {\r
-      UpdateWorkzone_ForBrush( t.brush );\r
-                       // use a local brushprimit_texdef fitted to a default 2x2 texture\r
-                       brushprimit_texdef_t bp_local;\r
-                       ConvertTexMatWithQTexture( &t.face->brushprimit_texdef, t.face->d_texture, &bp_local, NULL );\r
-                       Texture_SetTexture ( &t.face->texdef, &bp_local, false, NULL);\r
-                       UpdateSurfaceDialog();\r
-                       UpdatePatchInspector();\r
-               }\r
-               else\r
-                       Sys_Printf ("Did not select a texture\n");\r
-               return;\r
-       }\r
-\r
-       // ctrl-middle button = set entire brush to texture\r
-       if (buttons == (nMouseButton|MK_CONTROL) )\r
-       {\r
-               t = Test_Ray (origin, dir, false);\r
-               if (t.brush)\r
-               {\r
-                       if (t.brush->brush_faces->texdef.GetName()[0] == '(')\r
-                               Sys_Printf ("Can't change an entity texture\n");\r
-                       else\r
-                       {\r
-                               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
-                               Sys_UpdateWindows (W_ALL);\r
-                       }\r
-               }\r
-               else\r
-                       Sys_Printf ("Didn't hit a btrush\n");\r
-               return;\r
-       }\r
-\r
-       // ctrl-shift-middle button = set single face to texture\r
-       if (buttons == (nMouseButton|MK_SHIFT|MK_CONTROL) )\r
-       {\r
-               t = Test_Ray (origin, dir, false);\r
-               if (t.brush)\r
-               {\r
-                       if (t.brush->brush_faces->texdef.GetName()[0] == '(')\r
-                               Sys_Printf ("Can't change an entity texture\n");\r
-                       else\r
-                       {\r
-                               SetFaceTexdef (t.face, &g_qeglobals.d_texturewin.texdef, &g_qeglobals.d_texturewin.brushprimit_texdef);\r
-                               Brush_Build( t.brush );\r
-\r
-                               Sys_UpdateWindows (W_ALL);\r
-                       }\r
-               }\r
-               else\r
-                       Sys_Printf ("Didn't hit a btrush\n");\r
-               return;\r
-       }\r
-\r
-       if (buttons == (nMouseButton | MK_SHIFT))\r
-       {\r
-               Sys_Printf("Set brush face texture info\n");\r
-               t = Test_Ray (origin, dir, false);\r
-               if (t.brush)\r
-               {\r
-                       if (t.brush->brush_faces->texdef.GetName()[0] == '(')\r
-      {\r
-        if (t.brush->owner->eclass->nShowFlags & ECLASS_LIGHT)\r
-        {\r
-          CString strBuff;\r
-          qtexture_t* pTex = g_qeglobals.d_texturewin.pShader->getTexture();\r
-          if (pTex)\r
-          {\r
-            vec3_t vColor;\r
-            VectorCopy(pTex->color, vColor);\r
-\r
-            float fLargest = 0.0f;\r
-            for (int i = 0; i < 3; i++)\r
-            {\r
-                         if (vColor[i] > fLargest)\r
-                                 fLargest = vColor[i];\r
-            }\r
-                       \r
-                       if (fLargest == 0.0f)\r
-                       {\r
-              vColor[0] = vColor[1] = vColor[2] = 1.0f;\r
-            }\r
-                       else\r
-                       {\r
-                               float fScale = 1.0f / fLargest;\r
-              for (int i = 0; i < 3; i++)\r
-              {\r
-                vColor[i] *= fScale;\r
-              }\r
-            }\r
-            strBuff.Format("%f %f %f",pTex->color[0], pTex->color[1], pTex->color[2]);\r
-            SetKeyValue(t.brush->owner, "_color", strBuff.GetBuffer());\r
-                                   Sys_UpdateWindows (W_ALL);\r
-          }\r
-        }\r
-        else\r
-        {\r
-                                 Sys_Printf ("Can't select an entity brush face\n");\r
-        }\r
-      }\r
-                       else\r
-                       {\r
-        // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=425\r
-        Face_SetShader(t.face, g_qeglobals.d_texturewin.texdef.GetName());\r
-                               Brush_Build(t.brush);\r
-\r
-                               Sys_UpdateWindows (W_ALL);\r
-                       }\r
-               }\r
-               else\r
-                       Sys_Printf ("Didn't hit a brush\n");\r
-               return;\r
-       }\r
-\r
-}\r
-\r
-\r
-//\r
-//===========\r
-//MoveSelection\r
-//===========\r
-//\r
-void MoveSelection (vec3_t move)\r
-{\r
-       int             i, success;\r
-       brush_t *b;\r
-       CString strStatus;\r
-       vec3_t vTemp, vTemp2, end;\r
-\r
-       if (!move[0] && !move[1] && !move[2])\r
-  {\r
-               return;\r
-  }\r
-\r
-  if (!(g_qeglobals.d_select_mode == sel_area || g_qeglobals.d_select_mode == sel_areatall))\r
-  {\r
-    move[0] = (g_nScaleHow & SCALE_X) ? 0 : move[0];\r
-    move[1] = (g_nScaleHow & SCALE_Y) ? 0 : move[1];\r
-    move[2] = (g_nScaleHow & SCALE_Z) ? 0 : move[2];\r
-  }\r
-\r
-       if (g_pParentWnd->ActiveXY()->RotateMode() || g_bPatchBendMode)\r
-       {\r
-               float fDeg = -move[2];\r
-               float fAdj = move[2];\r
-               int nAxis = 0;\r
-               if (g_pParentWnd->ActiveXY()->GetViewType() == XY)\r
-               {\r
-                       fDeg = -move[1];\r
-                       fAdj = move[1];\r
-                       nAxis = 2;\r
-               }\r
-               else \r
-               if (g_pParentWnd->ActiveXY()->GetViewType() == XZ)\r
-               {\r
-                       fDeg = move[2];\r
-                       fAdj = move[2];\r
-                       nAxis = 1;\r
-               }\r
-               else\r
-                       nAxis = 0;\r
-\r
-               g_pParentWnd->ActiveXY()->Rotation()[nAxis] += fAdj;\r
-               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
-               g_pParentWnd->SetStatusText(2, strStatus);\r
-\r
-               if (g_bPatchBendMode)\r
-               {\r
-                       Patch_SelectBendNormal();\r
-                       Select_RotateAxis(nAxis, fDeg*2, false, true);\r
-                       Patch_SelectBendAxis();\r
-                       Select_RotateAxis(nAxis, fDeg, false, true);\r
-               }\r
-               else\r
-               {\r
-                       Select_RotateAxis(nAxis, fDeg, false, true);\r
-               }\r
-               return;\r
-       }\r
-\r
-       if (g_pParentWnd->ActiveXY()->ScaleMode())\r
-       {\r
-               vec3_t v;\r
-               v[0] = v[1] = v[2] = 1.0f;\r
-               if (move[1] > 0)\r
-               {\r
-                       v[0] = 1.1f;\r
-                       v[1] = 1.1f;\r
-                       v[2] = 1.1f;\r
-               }\r
-               else \r
-                       if (move[1] < 0)\r
-               {\r
-                       v[0] = 0.9f;\r
-                       v[1] = 0.9f;\r
-                       v[2] = 0.9f;\r
-               }\r
-\r
-                       Select_Scale((g_nScaleHow & SCALE_X) ? 1.0f : v[0],\r
-                                                                        (g_nScaleHow & SCALE_Y) ? 1.0f : v[1],\r
-                                                                (g_nScaleHow & SCALE_Z) ? 1.0f : v[2]);\r
-      // is that really necessary???\r
-               Sys_UpdateWindows (W_ALL);\r
-               return;\r
-       }\r
-\r
-\r
-       vec3_t vDistance;\r
-       VectorSubtract(pressdelta, vPressStart, vDistance);\r
-       strStatus.Format("Distance x: %.1f  y: %.1f  z: %.1f", vDistance[0], vDistance[1], vDistance[2]);\r
-       g_pParentWnd->SetStatusText(3, strStatus);\r
-\r
-       //\r
-       // dragging only a part of the selection\r
-       //\r
-\r
-       // this is fairly crappy way to deal with curvepoint and area selection\r
-       // but it touches the smallest amount of code this way\r
-       // \r
-       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
-       {\r
-               //area selection\r
-    if (g_qeglobals.d_select_mode == sel_area || g_qeglobals.d_select_mode == sel_areatall)\r
-               {\r
-                       VectorAdd(g_qeglobals.d_vAreaBR, move, g_qeglobals.d_vAreaBR);\r
-                       return;\r
-               }\r
-               //curve point selection\r
-               if (g_qeglobals.d_select_mode == sel_curvepoint)\r
-               {\r
-                       Patch_UpdateSelected(move);\r
-                       return;\r
-               }\r
-               //vertex selection\r
-               if (g_qeglobals.d_select_mode == sel_vertex && g_PrefsDlg.m_bVertexSplit)\r
-               {\r
-      if(g_qeglobals.d_num_move_points) {\r
-                         success = true;\r
-                         for (b = selected_brushes.next; b != &selected_brushes; b = b->next)\r
-                         {\r
-                                 success &= Brush_MoveVertex(b, g_qeglobals.d_move_points[0], move, end, true);\r
-                         }\r
-                         if (success)\r
-                                 VectorCopy(end, g_qeglobals.d_move_points[0]);\r
-      }\r
-                       return;\r
-               }\r
-               //all other selection types\r
-               for (i=0 ; i<g_qeglobals.d_num_move_points ; i++)\r
-                       VectorAdd (g_qeglobals.d_move_points[i], move, g_qeglobals.d_move_points[i]);\r
-               for (b = selected_brushes.next; b != &selected_brushes; b = b->next)\r
-               {\r
-      bool bMoved = false;\r
-      for(face_t *f = b->brush_faces; !bMoved && f!=NULL; f=f->next)\r
-        for(int p=0; !bMoved && p<3; p++)\r
-          for (i=0 ; !bMoved && i<g_qeglobals.d_num_move_points ; i++)\r
-                             if(f->planepts[p] == g_qeglobals.d_move_points[i])\r
-              bMoved = true;\r
-                 if(!bMoved) continue;\r
-\r
-                       VectorCopy(b->maxs, vTemp);\r
-                       VectorSubtract(vTemp, b->mins, vTemp);\r
-      Brush_Build(b,true,true,false,false); // don't filter\r
-                       for (i=0 ; i<3 ; i++)\r
-                       {\r
-                               if (b->mins[i] > b->maxs[i]\r
-                               || b->maxs[i] - b->mins[i] > g_MaxBrushSize)\r
-                                       break;  // dragged backwards or fucked up\r
-                       }\r
-                       if (i != 3)\r
-                               break;\r
-                       if (b->patchBrush)\r
-                       {\r
-                               VectorCopy(b->maxs, vTemp2);\r
-                               VectorSubtract(vTemp2, b->mins, vTemp2);\r
-                               VectorSubtract(vTemp2, vTemp, vTemp2);\r
-                               //if (!Patch_DragScale(b->nPatchID, vTemp2, move))\r
-                               if (!Patch_DragScale(b->pPatch, vTemp2, move))\r
-                               {\r
-                                       b = NULL;\r
-                                       break;\r
-                               }\r
-                       }\r
-               }\r
-               // if any of the brushes were crushed out of existance\r
-               // calcel the entire move\r
-               if (b != &selected_brushes)\r
-               {\r
-                       Sys_Printf ("Brush dragged backwards, move canceled\n");\r
-                       for (i=0 ; i<g_qeglobals.d_num_move_points ; i++)\r
-                               VectorSubtract (g_qeglobals.d_move_points[i], move, g_qeglobals.d_move_points[i]);\r
-\r
-                       for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)\r
-                               Brush_Build(b,true,true,false,false); // don't filter\r
-               }\r
-\r
-       }\r
-       else\r
-       {\r
-               // reset face originals from vertex edit mode\r
-               // this is dirty, but unfortunately necessary because Brush_Build\r
-               // can remove windings\r
-               for (b = selected_brushes.next; b != &selected_brushes; b = b->next)\r
-               {\r
-                       Brush_ResetFaceOriginals(b);\r
-               }\r
-               //\r
-               // if there are lots of brushes selected, just translate instead\r
-               // of rebuilding the brushes\r
-    // NOTE: this is not actually done, but would be a good idea\r
-               //\r
-         Select_Move (move);\r
-       }\r
-}\r
-\r
-/*\r
-===========\r
-Drag_MouseMoved\r
-===========\r
-*/\r
-void Drag_MouseMoved (int x, int y, int buttons)\r
-{\r
-  vec3_t       move, delta;\r
-  int          i;\r
-\r
-  if (!buttons)\r
-  {\r
-    drag_ok = false;\r
-    return;\r
-  }\r
-  if (!drag_ok)\r
-    return;\r
-\r
-  // clear along one axis\r
-  if (buttons & MK_SHIFT && (g_PrefsDlg.m_bALTEdge && g_qeglobals.d_select_mode != sel_areatall))\r
-  {\r
-    drag_first = false;\r
-    if (abs(x-pressx) > abs(y-pressy))\r
-      y = pressy;\r
-    else\r
-      x = pressx;\r
-  }\r
-\r
-       if (g_qeglobals.d_select_mode == sel_area && g_nPatchClickedView == W_CAMERA)\r
-       {\r
-               camera_t *m_pCamera = g_pParentWnd->GetCamWnd()->Camera();\r
-\r
-               // snap to window\r
-               if( y > m_pCamera->height ) y = m_pCamera->height - 1; else if( y < 0 ) y = 0;\r
-               if( x > m_pCamera->width ) x = m_pCamera->width - 1; else if( x < 0 ) x = 0;\r
-\r
-               VectorSet (move, x - pressx, y - pressy, 0);\r
-       } else\r
-       {\r
-               for (i=0 ; i<3 ; i++)\r
-               {\r
-                       move[i] = drag_xvec[i]*(x - pressx)     + drag_yvec[i]*(y - pressy);\r
-                       if (!g_PrefsDlg.m_bNoClamp)\r
-                       {\r
-                               move[i] = floor(move[i]/g_qeglobals.d_gridsize+0.5)*g_qeglobals.d_gridsize;\r
-                       }\r
-               }\r
-       }\r
-\r
-  VectorSubtract (move, pressdelta, delta);\r
-  VectorCopy (move, pressdelta);\r
-\r
-  MoveSelection (delta);\r
-}\r
-\r
-/*\r
-===========\r
-Drag_MouseUp\r
-===========\r
-*/\r
-void Drag_MouseUp (int nButtons)\r
-{\r
-       Sys_Status ("Drag completed.", 0);\r
-\r
-  if (g_qeglobals.d_select_mode == sel_area)\r
-  {\r
-    Patch_SelectAreaPoints(nButtons & MK_CONTROL); // adds to selection and/or deselects selected points if ctrl is held\r
-    g_qeglobals.d_select_mode = sel_curvepoint;\r
-               Sys_UpdateWindows (W_ALL);\r
-  }\r
-\r
-  if (g_qeglobals.d_select_mode == sel_areatall)\r
-  {\r
-    vec3_t mins, maxs;\r
-\r
-    int nDim1 = (g_pParentWnd->ActiveXY()->GetViewType() == YZ) ? 1 : 0;\r
-    int nDim2 = (g_pParentWnd->ActiveXY()->GetViewType() == XY) ? 1 : 2;\r
-\r
-               // get our rectangle\r
-    mins[nDim1] = MIN( g_qeglobals.d_vAreaTL[nDim1], g_qeglobals.d_vAreaBR[nDim1] );\r
-    mins[nDim2] = MIN( g_qeglobals.d_vAreaTL[nDim2], g_qeglobals.d_vAreaBR[nDim2] );\r
-    maxs[nDim1] = MAX( g_qeglobals.d_vAreaTL[nDim1], g_qeglobals.d_vAreaBR[nDim1] );\r
-    maxs[nDim2] = MAX( g_qeglobals.d_vAreaTL[nDim2], g_qeglobals.d_vAreaBR[nDim2] );\r
-\r
-    // deselect current selection\r
-    if( !(nButtons & (MK_CONTROL|MK_SHIFT)) )\r
-      Select_Deselect();\r
-\r
-    // select new selection\r
-    Select_RealCompleteTall( mins, maxs );\r
-\r
-    Sys_UpdateWindows (W_ALL);\r
-  }\r
-\r
-  if (g_qeglobals.d_select_translate[0] || g_qeglobals.d_select_translate[1] || g_qeglobals.d_select_translate[2])\r
-       {\r
-               Select_Move (g_qeglobals.d_select_translate);\r
-               VectorCopy (vec3_origin, g_qeglobals.d_select_translate);\r
-               Sys_UpdateWindows (W_CAMERA);\r
-       }\r
-  \r
-  /* note: added cleanup here, since an edge drag will leave selected vertices \r
-           in g_qeglobals.d_num_move_points\r
-  */\r
-  if (  g_qeglobals.d_select_mode != sel_vertex && \r
-        g_qeglobals.d_select_mode != sel_curvepoint &&\r
-        g_qeglobals.d_select_mode != sel_edge)\r
-    g_qeglobals.d_num_move_points = 0;\r
-  \r
-  g_pParentWnd->SetStatusText(3, "");\r
-  Undo_EndBrushList(&selected_brushes);\r
-  Undo_End();\r
-  UpdateSurfaceDialog();\r
-}\r
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+GtkRadiant is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "stdafx.h"
+//#include "qe3.h"
+
+/*
+
+  drag either multiple brushes, or select plane points from
+  a single brush.
+
+*/
+
+extern int g_nPatchClickedView;
+
+qboolean       drag_ok;
+vec3_t drag_xvec;
+vec3_t drag_yvec;
+
+//static       int     buttonstate;
+int    pressx, pressy;
+static vec3_t pressdelta;
+static vec3_t vPressStart;
+//static       int     buttonx, buttony;
+
+
+//int          num_move_points;
+//float        *move_points[1024];
+
+int            lastx, lasty;
+
+qboolean       drag_first;
+
+
+void   AxializeVector (vec3_t v)
+{
+       vec3_t  a;
+       float   o;
+       int             i;
+
+       if (!v[0] && !v[1])
+               return;
+       if (!v[1] && !v[2])
+               return;
+       if (!v[0] && !v[2])
+               return;
+
+       for (i=0 ; i<3 ; i++)
+               a[i] = fabs(v[i]);
+       if (a[0] > a[1] && a[0] > a[2])
+               i = 0;
+       else if (a[1] > a[0] && a[1] > a[2])
+               i = 1;
+       else
+               i = 2;
+
+       o = v[i];
+       VectorCopy (vec3_origin, v);
+       if (o<0)
+               v[i] = -1;
+       else
+               v[i] = 1;
+       
+}
+
+/*
+===========
+Drag_Setup
+===========
+*/
+extern void SelectCurvePointByRay (vec3_t org, vec3_t dir, int buttons);
+
+void Drag_Setup (int x, int y, int buttons,
+                vec3_t xaxis, vec3_t yaxis,
+                vec3_t origin, vec3_t dir)
+{
+  trace_t      t;
+  face_t       *f;
+
+  drag_first = true;
+  
+  VectorCopy (vec3_origin, pressdelta);
+  pressx = x;
+  pressy = y;
+
+       // snap to nearest axis for camwindow drags
+  VectorCopy (xaxis, drag_xvec);
+  AxializeVector (drag_xvec);
+  VectorCopy (yaxis, drag_yvec);
+  AxializeVector (drag_yvec);
+
+  if (g_qeglobals.d_select_mode == sel_curvepoint)
+  {
+    SelectCurvePointByRay (origin, dir, buttons);      
+
+    if(g_qeglobals.d_select_mode == sel_area)
+    {
+      drag_ok = true;
+
+                       if(g_nPatchClickedView == W_CAMERA ) {
+                               VectorSet( g_qeglobals.d_vAreaTL, x, y, 0 );
+                               VectorSet( g_qeglobals.d_vAreaBR, x, y, 0 );
+                       }
+    }
+    else if (g_qeglobals.d_num_move_points) // don't add an undo if there are no points selected
+    {
+      drag_ok = true;
+      Sys_UpdateWindows(W_ALL);
+      Undo_Start("drag curve point");
+      Undo_AddBrushList(&selected_brushes);
+    }
+    return;
+  }
+  else
+  {
+    g_qeglobals.d_num_move_points = 0;
+  }
+
+  if (g_qeglobals.d_select_mode == sel_areatall)
+  {
+    VectorCopy(origin, g_qeglobals.d_vAreaTL);
+    VectorCopy(origin, g_qeglobals.d_vAreaBR);
+
+    Sys_UpdateWindows(W_ALL);
+
+    drag_ok = true; 
+    return;
+  }
+
+  if (selected_brushes.next == &selected_brushes)
+  {
+    //in this case a new brush is created when the dragging
+    //takes place in the XYWnd, An useless undo is created
+    //when the dragging takes place in the CamWnd
+    Undo_Start("create brush");
+
+    Sys_Status("No selection to drag", 0);
+    return;
+  }
+
+  if (g_qeglobals.d_select_mode == sel_vertex)
+  {
+    SelectVertexByRay (origin, dir);   
+    if (g_qeglobals.d_num_move_points)
+    {
+      drag_ok = true;
+      Undo_Start("drag vertex");
+      Undo_AddBrushList(&selected_brushes);
+      // Need an update here for highlighting selected vertices
+      Sys_UpdateWindows(W_XY | W_CAMERA);
+      return;
+    }
+  }
+
+  if (g_qeglobals.d_select_mode == sel_edge)
+  {
+    SelectEdgeByRay (origin, dir);     
+    if (g_qeglobals.d_num_move_points)
+    {
+      drag_ok = true;
+      Undo_Start("drag edge");
+      Undo_AddBrushList(&selected_brushes);
+      return;
+    }
+  }
+
+  //
+  // check for direct hit first
+  //
+  t = Test_Ray (origin, dir, true);
+  if (t.selected)
+  {
+    drag_ok = true;
+
+    Undo_Start("drag selection");
+    Undo_AddBrushList(&selected_brushes);
+
+    if (buttons == (MK_LBUTTON|MK_CONTROL) )
+    {
+      Sys_Printf ("Shear dragging face\n");
+      Brush_SelectFaceForDragging (t.brush, t.face, true);
+    }
+    else if (buttons == (MK_LBUTTON|MK_CONTROL|MK_SHIFT) )
+    {
+      Sys_Printf ("Sticky dragging brush\n");
+      for (f=t.brush->brush_faces ; f ; f=f->next)
+       Brush_SelectFaceForDragging (t.brush, f, false);
+    }
+    else
+      Sys_Printf ("Dragging entire selection\n");
+    
+    return;
+  }
+
+  if (g_qeglobals.d_select_mode == sel_vertex || g_qeglobals.d_select_mode == sel_edge)
+    return;
+
+  //
+  // check for side hit
+  //
+  // multiple brushes selected?
+  if (selected_brushes.next->next != &selected_brushes)
+  {
+    // yes, special handling
+    bool bOK = (g_PrefsDlg.m_bALTEdge) ? Sys_AltDown() : true;
+    if (bOK)
+    {
+      for (brush_t* pBrush = selected_brushes.next ; pBrush != &selected_brushes ; pBrush = pBrush->next)
+      {
+       if (buttons & MK_CONTROL)
+         Brush_SideSelect (pBrush, origin, dir, true);
+       else
+         Brush_SideSelect (pBrush, origin, dir, false);
+      }
+    }
+    else
+    {
+      Sys_Printf ("press ALT to drag multiple edges\n");
+      return;
+    }
+  }
+  else
+  {
+    // single select.. trying to drag fixed entities handle themselves and just move
+    if (buttons & MK_CONTROL)
+      Brush_SideSelect (selected_brushes.next, origin, dir, true);
+    else
+      Brush_SideSelect (selected_brushes.next, origin, dir, false);
+  }
+
+  Sys_Printf ("Side stretch\n");
+  drag_ok = true;
+
+  Undo_Start("side stretch");
+  Undo_AddBrushList(&selected_brushes);
+}
+
+entity_t *peLink;
+
+void UpdateTarget(vec3_t origin, vec3_t dir)
+{
+       trace_t t;
+       entity_t *pe;
+       int i;
+       char sz[128];
+
+       t = Test_Ray (origin, dir, 0);
+
+       if (!t.brush)
+               return;
+
+       pe = t.brush->owner;
+
+       if (pe == NULL)
+               return;
+
+       // is this the first?
+       if (peLink != NULL)
+       {
+
+               // Get the target id from out current target
+               // if there is no id, make one
+
+               i = IntForKey(pe, "target");
+               if (i <= 0)
+               {
+                       i = GetUniqueTargetId(1);
+                       sprintf(sz, "%d", i);
+
+                       SetKeyValue(pe, "target", sz);
+               }
+
+               // set the target # into our src
+
+               sprintf(sz, "%d", i);
+               SetKeyValue(peLink, "targetname", sz);
+
+               Sys_UpdateWindows(W_ENTITY);
+
+       }
+
+       // promote the target to the src
+
+       peLink = pe;
+       
+}
+
+/*
+===========
+Drag_Begin
+//++timo test three button mouse and three button emulation here ?
+===========
+*/
+void Drag_Begin (int x, int y, int buttons,
+                  vec3_t xaxis, vec3_t yaxis,
+                  vec3_t origin, vec3_t dir, bool sf_camera)
+{
+       trace_t t;
+  bool altdown;
+  int nFlag;
+
+       drag_ok = false;
+       VectorCopy (vec3_origin, pressdelta);
+       VectorCopy (vec3_origin, vPressStart);
+
+       drag_first = true;
+       peLink = NULL;
+
+  altdown = Sys_AltDown();
+
+       // shift-LBUTTON = select entire brush
+  // shift-alt-LBUTTON = drill select
+       if (buttons == (MK_LBUTTON | MK_SHIFT) && g_qeglobals.d_select_mode != sel_curvepoint)
+       {
+    nFlag = altdown ? SF_CYCLE : 0;
+    if (sf_camera)
+      nFlag |= SF_CAMERA;
+    else
+      nFlag |= SF_ENTITIES_FIRST;
+    Select_Ray(origin, dir, nFlag);
+               return;
+       }
+
+  // (shift-)alt-LBUTTON = area select completely tall
+  if ( !sf_camera &&
+      ( g_PrefsDlg.m_bALTEdge ? buttons == (MK_LBUTTON | MK_CONTROL | MK_SHIFT) : (buttons == MK_LBUTTON || buttons == (MK_LBUTTON | MK_CONTROL | MK_SHIFT)) ) &&
+      altdown && g_qeglobals.d_select_mode != sel_curvepoint)
+  {
+    if (g_pParentWnd->ActiveXY()->AreaSelectOK())
+    {
+      g_qeglobals.d_select_mode = sel_areatall;
+
+      Drag_Setup (x, y, buttons, xaxis, yaxis, origin, dir);
+      return;
+    }
+  }
+
+       // ctrl-alt-LBUTTON = multiple brush select without selecting whole entities
+       if (buttons == (MK_LBUTTON | MK_CONTROL) && altdown && g_qeglobals.d_select_mode != sel_curvepoint)
+       {
+    nFlag = 0;
+    if (sf_camera)
+      nFlag |= SF_CAMERA;
+    else
+      nFlag |= SF_ENTITIES_FIRST;
+    Select_Ray (origin, dir, nFlag);
+    UpdateSurfaceDialog();
+    
+               return;
+       }
+
+       // ctrl-shift LBUTTON = select single face
+       if (sf_camera && buttons == (MK_LBUTTON | MK_CONTROL | MK_SHIFT) && g_qeglobals.d_select_mode != sel_curvepoint)
+       {
+    if(Sys_AltDown())
+    {
+      brush_t *b;
+      for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
+      {
+        if(b->pPatch)
+          continue;
+
+        for (face_t* pFace = b->brush_faces; pFace; pFace = pFace->next)
+        {
+          g_ptrSelectedFaces.Add(pFace);
+          g_ptrSelectedFaceBrushes.Add(b);
+        }
+      }
+
+      for (b = selected_brushes.next; b != &selected_brushes; )
+      {
+        brush_t *pb = b;
+                         b = b->next;
+        Brush_RemoveFromList (pb);
+        Brush_AddToList (pb, &active_brushes);
+      }
+    }
+    else
+                 Select_Deselect (true);
+
+               Select_Ray (origin, dir, (SF_SINGLEFACE|SF_CAMERA));
+               return;
+       }
+
+
+       // LBUTTON + all other modifiers = manipulate selection
+       if (buttons & MK_LBUTTON)
+       {
+               Drag_Setup (x, y, buttons, xaxis, yaxis, origin, dir);
+               return;
+       }
+
+       int nMouseButton = g_PrefsDlg.m_nMouseButtons == 2 ? MK_RBUTTON : MK_MBUTTON;
+       // middle button = grab texture
+       if (buttons == nMouseButton)
+       {
+               t = Test_Ray (origin, dir, false);
+               if (t.face)
+               {
+      UpdateWorkzone_ForBrush( t.brush );
+                       // use a local brushprimit_texdef fitted to a default 2x2 texture
+                       brushprimit_texdef_t bp_local;
+                       ConvertTexMatWithQTexture( &t.face->brushprimit_texdef, t.face->d_texture, &bp_local, NULL );
+                       Texture_SetTexture ( &t.face->texdef, &bp_local, false, NULL);
+                       UpdateSurfaceDialog();
+                       UpdatePatchInspector();
+               }
+               else
+                       Sys_Printf ("Did not select a texture\n");
+               return;
+       }
+
+       // ctrl-middle button = set entire brush to texture
+       if (buttons == (nMouseButton|MK_CONTROL) )
+       {
+               t = Test_Ray (origin, dir, false);
+               if (t.brush)
+               {
+                       if (t.brush->brush_faces->texdef.GetName()[0] == '(')
+                               Sys_Printf ("Can't change an entity texture\n");
+                       else
+                       {
+                               Brush_SetTexture (t.brush, &g_qeglobals.d_texturewin.texdef, &g_qeglobals.d_texturewin.brushprimit_texdef, false, static_cast<IPluginTexdef *>( g_qeglobals.d_texturewin.pTexdef ) );
+                               Sys_UpdateWindows (W_ALL);
+                       }
+               }
+               else
+                       Sys_Printf ("Didn't hit a btrush\n");
+               return;
+       }
+
+       // ctrl-shift-middle button = set single face to texture
+       if (buttons == (nMouseButton|MK_SHIFT|MK_CONTROL) )
+       {
+               t = Test_Ray (origin, dir, false);
+               if (t.brush)
+               {
+                       if (t.brush->brush_faces->texdef.GetName()[0] == '(')
+                               Sys_Printf ("Can't change an entity texture\n");
+                       else
+                       {
+                               SetFaceTexdef (t.face, &g_qeglobals.d_texturewin.texdef, &g_qeglobals.d_texturewin.brushprimit_texdef);
+                               Brush_Build( t.brush );
+
+                               Sys_UpdateWindows (W_ALL);
+                       }
+               }
+               else
+                       Sys_Printf ("Didn't hit a btrush\n");
+               return;
+       }
+
+       if (buttons == (nMouseButton | MK_SHIFT))
+       {
+               Sys_Printf("Set brush face texture info\n");
+               t = Test_Ray (origin, dir, false);
+               if (t.brush)
+               {
+                       if (t.brush->brush_faces->texdef.GetName()[0] == '(')
+      {
+        if (t.brush->owner->eclass->nShowFlags & ECLASS_LIGHT)
+        {
+          CString strBuff;
+          qtexture_t* pTex = g_qeglobals.d_texturewin.pShader->getTexture();
+          if (pTex)
+          {
+            vec3_t vColor;
+            VectorCopy(pTex->color, vColor);
+
+            float fLargest = 0.0f;
+            for (int i = 0; i < 3; i++)
+            {
+                         if (vColor[i] > fLargest)
+                                 fLargest = vColor[i];
+            }
+                       
+                       if (fLargest == 0.0f)
+                       {
+              vColor[0] = vColor[1] = vColor[2] = 1.0f;
+            }
+                       else
+                       {
+                               float fScale = 1.0f / fLargest;
+              for (int i = 0; i < 3; i++)
+              {
+                vColor[i] *= fScale;
+              }
+            }
+            strBuff.Format("%f %f %f",pTex->color[0], pTex->color[1], pTex->color[2]);
+            SetKeyValue(t.brush->owner, "_color", strBuff.GetBuffer());
+                                   Sys_UpdateWindows (W_ALL);
+          }
+        }
+        else
+        {
+                                 Sys_Printf ("Can't select an entity brush face\n");
+        }
+      }
+                       else
+                       {
+        // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=425
+        Face_SetShader(t.face, g_qeglobals.d_texturewin.texdef.GetName());
+                               Brush_Build(t.brush);
+
+                               Sys_UpdateWindows (W_ALL);
+                       }
+               }
+               else
+                       Sys_Printf ("Didn't hit a brush\n");
+               return;
+       }
+
+}
+
+
+//
+//===========
+//MoveSelection
+//===========
+//
+void MoveSelection (vec3_t move)
+{
+       int             i, success;
+       brush_t *b;
+       CString strStatus;
+       vec3_t vTemp, vTemp2, end;
+
+       if (!move[0] && !move[1] && !move[2])
+  {
+               return;
+  }
+
+  if (!(g_qeglobals.d_select_mode == sel_area || g_qeglobals.d_select_mode == sel_areatall))
+  {
+    move[0] = (g_nScaleHow & SCALE_X) ? 0 : move[0];
+    move[1] = (g_nScaleHow & SCALE_Y) ? 0 : move[1];
+    move[2] = (g_nScaleHow & SCALE_Z) ? 0 : move[2];
+  }
+
+       if (g_pParentWnd->ActiveXY()->RotateMode() || g_bPatchBendMode)
+       {
+               float fDeg = -move[2];
+               float fAdj = move[2];
+               int nAxis = 0;
+               if (g_pParentWnd->ActiveXY()->GetViewType() == XY)
+               {
+                       fDeg = -move[1];
+                       fAdj = move[1];
+                       nAxis = 2;
+               }
+               else 
+               if (g_pParentWnd->ActiveXY()->GetViewType() == XZ)
+               {
+                       fDeg = move[2];
+                       fAdj = move[2];
+                       nAxis = 1;
+               }
+               else
+                       nAxis = 0;
+
+               g_pParentWnd->ActiveXY()->Rotation()[nAxis] += fAdj;
+               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]);
+               g_pParentWnd->SetStatusText(2, strStatus);
+
+               if (g_bPatchBendMode)
+               {
+                       Patch_SelectBendNormal();
+                       Select_RotateAxis(nAxis, fDeg*2, false, true);
+                       Patch_SelectBendAxis();
+                       Select_RotateAxis(nAxis, fDeg, false, true);
+               }
+               else
+               {
+                       Select_RotateAxis(nAxis, fDeg, false, true);
+               }
+               return;
+       }
+
+       if (g_pParentWnd->ActiveXY()->ScaleMode())
+       {
+               vec3_t v;
+               v[0] = v[1] = v[2] = 1.0f;
+               if (move[1] > 0)
+               {
+                       v[0] = 1.1f;
+                       v[1] = 1.1f;
+                       v[2] = 1.1f;
+               }
+               else 
+                       if (move[1] < 0)
+               {
+                       v[0] = 0.9f;
+                       v[1] = 0.9f;
+                       v[2] = 0.9f;
+               }
+
+                       Select_Scale((g_nScaleHow & SCALE_X) ? 1.0f : v[0],
+                                                                        (g_nScaleHow & SCALE_Y) ? 1.0f : v[1],
+                                                                (g_nScaleHow & SCALE_Z) ? 1.0f : v[2]);
+      // is that really necessary???
+               Sys_UpdateWindows (W_ALL);
+               return;
+       }
+
+
+       vec3_t vDistance;
+       VectorSubtract(pressdelta, vPressStart, vDistance);
+       strStatus.Format("Distance x: %.1f  y: %.1f  z: %.1f", vDistance[0], vDistance[1], vDistance[2]);
+       g_pParentWnd->SetStatusText(3, strStatus);
+
+       //
+       // dragging only a part of the selection
+       //
+
+       // this is fairly crappy way to deal with curvepoint and area selection
+       // but it touches the smallest amount of code this way
+       // 
+       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)
+       {
+               //area selection
+    if (g_qeglobals.d_select_mode == sel_area || g_qeglobals.d_select_mode == sel_areatall)
+               {
+                       VectorAdd(g_qeglobals.d_vAreaBR, move, g_qeglobals.d_vAreaBR);
+                       return;
+               }
+               //curve point selection
+               if (g_qeglobals.d_select_mode == sel_curvepoint)
+               {
+                       Patch_UpdateSelected(move);
+                       return;
+               }
+               //vertex selection
+               if (g_qeglobals.d_select_mode == sel_vertex && g_PrefsDlg.m_bVertexSplit)
+               {
+      if(g_qeglobals.d_num_move_points) {
+                         success = true;
+                         for (b = selected_brushes.next; b != &selected_brushes; b = b->next)
+                         {
+                                 success &= Brush_MoveVertex(b, g_qeglobals.d_move_points[0], move, end, true);
+                         }
+                         if (success)
+                                 VectorCopy(end, g_qeglobals.d_move_points[0]);
+      }
+                       return;
+               }
+               //all other selection types
+               for (i=0 ; i<g_qeglobals.d_num_move_points ; i++)
+                       VectorAdd (g_qeglobals.d_move_points[i], move, g_qeglobals.d_move_points[i]);
+               for (b = selected_brushes.next; b != &selected_brushes; b = b->next)
+               {
+      bool bMoved = false;
+      for(face_t *f = b->brush_faces; !bMoved && f!=NULL; f=f->next)
+        for(int p=0; !bMoved && p<3; p++)
+          for (i=0 ; !bMoved && i<g_qeglobals.d_num_move_points ; i++)
+                             if(f->planepts[p] == g_qeglobals.d_move_points[i])
+              bMoved = true;
+                 if(!bMoved) continue;
+
+                       VectorCopy(b->maxs, vTemp);
+                       VectorSubtract(vTemp, b->mins, vTemp);
+      Brush_Build(b,true,true,false,false); // don't filter
+                       for (i=0 ; i<3 ; i++)
+                       {
+                               if (b->mins[i] > b->maxs[i]
+                               || b->maxs[i] - b->mins[i] > g_MaxBrushSize)
+                                       break;  // dragged backwards or fucked up
+                       }
+                       if (i != 3)
+                               break;
+                       if (b->patchBrush)
+                       {
+                               VectorCopy(b->maxs, vTemp2);
+                               VectorSubtract(vTemp2, b->mins, vTemp2);
+                               VectorSubtract(vTemp2, vTemp, vTemp2);
+                               //if (!Patch_DragScale(b->nPatchID, vTemp2, move))
+                               if (!Patch_DragScale(b->pPatch, vTemp2, move))
+                               {
+                                       b = NULL;
+                                       break;
+                               }
+                       }
+               }
+               // if any of the brushes were crushed out of existance
+               // calcel the entire move
+               if (b != &selected_brushes)
+               {
+                       Sys_Printf ("Brush dragged backwards, move canceled\n");
+                       for (i=0 ; i<g_qeglobals.d_num_move_points ; i++)
+                               VectorSubtract (g_qeglobals.d_move_points[i], move, g_qeglobals.d_move_points[i]);
+
+                       for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
+                               Brush_Build(b,true,true,false,false); // don't filter
+               }
+
+       }
+       else
+       {
+               // reset face originals from vertex edit mode
+               // this is dirty, but unfortunately necessary because Brush_Build
+               // can remove windings
+               for (b = selected_brushes.next; b != &selected_brushes; b = b->next)
+               {
+                       Brush_ResetFaceOriginals(b);
+               }
+               //
+               // if there are lots of brushes selected, just translate instead
+               // of rebuilding the brushes
+    // NOTE: this is not actually done, but would be a good idea
+               //
+         Select_Move (move);
+       }
+}
+
+/*
+===========
+Drag_MouseMoved
+===========
+*/
+void Drag_MouseMoved (int x, int y, int buttons)
+{
+  vec3_t       move, delta;
+  int          i;
+
+  if (!buttons)
+  {
+    drag_ok = false;
+    return;
+  }
+  if (!drag_ok)
+    return;
+
+  // clear along one axis
+  if (buttons & MK_SHIFT && (g_PrefsDlg.m_bALTEdge && g_qeglobals.d_select_mode != sel_areatall))
+  {
+    drag_first = false;
+    if (abs(x-pressx) > abs(y-pressy))
+      y = pressy;
+    else
+      x = pressx;
+  }
+
+       if (g_qeglobals.d_select_mode == sel_area && g_nPatchClickedView == W_CAMERA)
+       {
+               camera_t *m_pCamera = g_pParentWnd->GetCamWnd()->Camera();
+
+               // snap to window
+               if( y > m_pCamera->height ) y = m_pCamera->height - 1; else if( y < 0 ) y = 0;
+               if( x > m_pCamera->width ) x = m_pCamera->width - 1; else if( x < 0 ) x = 0;
+
+               VectorSet (move, x - pressx, y - pressy, 0);
+       } else
+       {
+               for (i=0 ; i<3 ; i++)
+               {
+                       move[i] = drag_xvec[i]*(x - pressx)     + drag_yvec[i]*(y - pressy);
+                       if (!g_PrefsDlg.m_bNoClamp)
+                       {
+                               move[i] = floor(move[i]/g_qeglobals.d_gridsize+0.5)*g_qeglobals.d_gridsize;
+                       }
+               }
+       }
+
+  VectorSubtract (move, pressdelta, delta);
+  VectorCopy (move, pressdelta);
+
+  MoveSelection (delta);
+}
+
+/*
+===========
+Drag_MouseUp
+===========
+*/
+void Drag_MouseUp (int nButtons)
+{
+       Sys_Status ("Drag completed.", 0);
+
+  if (g_qeglobals.d_select_mode == sel_area)
+  {
+    Patch_SelectAreaPoints(nButtons & MK_CONTROL); // adds to selection and/or deselects selected points if ctrl is held
+    g_qeglobals.d_select_mode = sel_curvepoint;
+               Sys_UpdateWindows (W_ALL);
+  }
+
+  if (g_qeglobals.d_select_mode == sel_areatall)
+  {
+    vec3_t mins, maxs;
+
+    int nDim1 = (g_pParentWnd->ActiveXY()->GetViewType() == YZ) ? 1 : 0;
+    int nDim2 = (g_pParentWnd->ActiveXY()->GetViewType() == XY) ? 1 : 2;
+
+               // get our rectangle
+    mins[nDim1] = MIN( g_qeglobals.d_vAreaTL[nDim1], g_qeglobals.d_vAreaBR[nDim1] );
+    mins[nDim2] = MIN( g_qeglobals.d_vAreaTL[nDim2], g_qeglobals.d_vAreaBR[nDim2] );
+    maxs[nDim1] = MAX( g_qeglobals.d_vAreaTL[nDim1], g_qeglobals.d_vAreaBR[nDim1] );
+    maxs[nDim2] = MAX( g_qeglobals.d_vAreaTL[nDim2], g_qeglobals.d_vAreaBR[nDim2] );
+
+    // deselect current selection
+    if( !(nButtons & (MK_CONTROL|MK_SHIFT)) )
+      Select_Deselect();
+
+    // select new selection
+    Select_RealCompleteTall( mins, maxs );
+
+    Sys_UpdateWindows (W_ALL);
+  }
+
+  if (g_qeglobals.d_select_translate[0] || g_qeglobals.d_select_translate[1] || g_qeglobals.d_select_translate[2])
+       {
+               Select_Move (g_qeglobals.d_select_translate);
+               VectorCopy (vec3_origin, g_qeglobals.d_select_translate);
+               Sys_UpdateWindows (W_CAMERA);
+       }
+  
+  /* note: added cleanup here, since an edge drag will leave selected vertices 
+           in g_qeglobals.d_num_move_points
+  */
+  if (  g_qeglobals.d_select_mode != sel_vertex && 
+        g_qeglobals.d_select_mode != sel_curvepoint &&
+        g_qeglobals.d_select_mode != sel_edge)
+    g_qeglobals.d_num_move_points = 0;
+  
+  g_pParentWnd->SetStatusText(3, "");
+  Undo_EndBrushList(&selected_brushes);
+  Undo_End();
+  UpdateSurfaceDialog();
+}