From 041f7e0998c7e039b907df725b727e68477cd61b Mon Sep 17 00:00:00 2001
From: namespace <namespace>
Date: Sat, 9 Sep 2006 15:03:05 +0000
Subject: [PATCH] Added feature: camera strafing while holding ctrl additional
 forward movement when holding shift

Tester: Shaderman

git-svn-id: svn://svn.icculus.org/gtkradiant/GtkRadiant/trunk@101 8a3a26a2-13c4-0310-b231-cf6edde360e5
---
 TODO                  |  1 -
 radiant/camwindow.cpp | 56 +++++++++++++++++++++++++++++++------------
 2 files changed, 41 insertions(+), 16 deletions(-)

diff --git a/TODO b/TODO
index 4f9bf1eb..c32101b6 100644
--- a/TODO
+++ b/TODO
@@ -150,7 +150,6 @@ Selection: Customisable manipulator size - +/- to change the size of the transla
 Selection: Add optional screen-relative control for constrained rotations.
 Clipper: Change selection/manipulation to be consistent with other component editing.
 Filtering: Either deselect filtered nodes, or render filtered nodes that are selected.
-Camera: Strafe while holding ctrl.
 Texdef: Make texdef formats abstract, add conversion between texdef formats (use generic affine-texture-matrix format for conversions).
 Textures Window: Precise display of texture size when selecting.  (tooltip, possibly)
 Status: 'Size of brush' display on status bar.
diff --git a/radiant/camwindow.cpp b/radiant/camwindow.cpp
index 73c416c6..0c2acb5b 100644
--- a/radiant/camwindow.cpp
+++ b/radiant/camwindow.cpp
@@ -137,6 +137,9 @@ struct camera_t
   Matrix4 projection;
   Matrix4 modelview;
 
+  bool m_strafe; // true when in strafemode toggled by the ctrl-key
+  bool m_strafe_forward; // true when in strafemode by ctrl-key and shift is pressed for forward strafing
+
   unsigned int movementflags;  // movement flags
   Timer m_keycontrol_timer;
   guint m_keymove_handler;
@@ -278,23 +281,38 @@ void Camera_setAngles(camera_t& camera, const Vector3& angles)
 
 void Camera_FreeMove(camera_t& camera, int dx, int dy)
 {
-  float dtime = 0.1f;
-  if (g_camwindow_globals_private.m_bCamInverseMouse)
-    camera.angles[CAMERA_PITCH] -= dy * dtime * g_camwindow_globals_private.m_nAngleSpeed;
-  else
-    camera.angles[CAMERA_PITCH] += dy * dtime * g_camwindow_globals_private.m_nAngleSpeed;
+  // free strafe mode, toggled by the ctrl key with optional shift for forward movement
+  if(camera.m_strafe)
+  {
+	  const float strafespeed = 0.65f;
+
+	  camera.origin -= camera.vright * strafespeed * dx;
+	  if(camera.m_strafe_forward)
+	    camera.origin += camera.vpn * strafespeed * dy;
+	  else
+	    camera.origin += camera.vup * strafespeed * dy;
+  }
+  else// free rotation
+  {
+    const float dtime = 0.1f;
 
-  camera.angles[CAMERA_YAW] += dx * dtime * g_camwindow_globals_private.m_nAngleSpeed;
+    if (g_camwindow_globals_private.m_bCamInverseMouse)
+        camera.angles[CAMERA_PITCH] -= dy * dtime * g_camwindow_globals_private.m_nAngleSpeed;
+    else
+        camera.angles[CAMERA_PITCH] += dy * dtime * g_camwindow_globals_private.m_nAngleSpeed;
 
-  if (camera.angles[CAMERA_PITCH] > 90)
-    camera.angles[CAMERA_PITCH] = 90;
-  else if (camera.angles[CAMERA_PITCH] < -90)
-    camera.angles[CAMERA_PITCH] = -90;
+    camera.angles[CAMERA_YAW] += dx * dtime * g_camwindow_globals_private.m_nAngleSpeed;
 
-  if (camera.angles[CAMERA_YAW] >= 360)
-    camera.angles[CAMERA_YAW] -=360;
-  else if (camera.angles[CAMERA_YAW] <= 0)
-    camera.angles[CAMERA_YAW] +=360;
+    if (camera.angles[CAMERA_PITCH] > 90)
+        camera.angles[CAMERA_PITCH] = 90;
+    else if (camera.angles[CAMERA_PITCH] < -90)
+        camera.angles[CAMERA_PITCH] = -90;
+
+    if (camera.angles[CAMERA_YAW] >= 360)
+        camera.angles[CAMERA_YAW] -=360;
+    else if (camera.angles[CAMERA_YAW] <= 0)
+        camera.angles[CAMERA_YAW] +=360;
+  }
 
   Camera_updateModelview(camera);
   Camera_Freemove_updateAxes(camera);
@@ -638,7 +656,15 @@ public:
 
 void Camera_motionDelta(int x, int y, unsigned int state, void* data)
 {
-  reinterpret_cast<camera_t*>(data)->m_mouseMove.motion_delta(x, y, state);
+  camera_t* cam = reinterpret_cast<camera_t*>(data);
+
+  cam->m_mouseMove.motion_delta(x, y, state);
+  cam->m_strafe = (state & GDK_CONTROL_MASK) != 0;
+
+  if(cam->m_strafe)
+    cam->m_strafe_forward = (state & GDK_SHIFT_MASK) != 0;
+  else
+    cam->m_strafe_forward = false;
 }
 
 class CamWnd
-- 
2.39.5