From 90896acd439d8f67ce784e925a7bcb6829f4d72d Mon Sep 17 00:00:00 2001 From: volte <100103+volte@users.noreply.github.com> Date: Mon, 3 Jan 2022 09:46:00 -0500 Subject: [PATCH] Additional camera movement actions in visual mode (#682) Added "Orbit" and "Move Camera to Cursor" visual mode actions (not bound by default) --- Source/Core/Resources/Actions.cfg | 21 +++ Source/Core/VisualModes/VisualCamera.cs | 2 +- Source/Core/VisualModes/VisualMode.cs | 155 ++++++++++++++++-- .../VisualModes/BaseVisualMode.cs | 1 - 4 files changed, 160 insertions(+), 19 deletions(-) diff --git a/Source/Core/Resources/Actions.cfg b/Source/Core/Resources/Actions.cfg index d6c8f596d..e739692bb 100755 --- a/Source/Core/Resources/Actions.cfg +++ b/Source/Core/Resources/Actions.cfg @@ -644,6 +644,27 @@ movedown allowscroll = true; disregardshift = true; } + +orbit +{ + title = "Orbit"; + category = "visual"; + description = "When held, the mouse will orbit the camera around the point at the cursor, rather than look around."; + allowkeys = true; + allowmouse = true; + allowscroll = false; + disregardshift = true; +} + +movecameratocursor +{ + title = "Move Camera to Cursor"; + category = "visual"; + description = "Place the camera nearby the point at the cursor."; + allowkeys = true; + allowmouse = true; + allowscroll = false; +} testmap { diff --git a/Source/Core/VisualModes/VisualCamera.cs b/Source/Core/VisualModes/VisualCamera.cs index 7646d9852..6108b5485 100755 --- a/Source/Core/VisualModes/VisualCamera.cs +++ b/Source/Core/VisualModes/VisualCamera.cs @@ -14,7 +14,7 @@ namespace CodeImp.DoomBuilder.VisualModes { #region ================== Constants - private const double ANGLE_FROM_MOUSE = 0.0001; + public const double ANGLE_FROM_MOUSE = 0.0001; public const double MAX_ANGLEZ_LOW = 91.0 / Angle2D.PIDEG; public const double MAX_ANGLEZ_HIGH = (360.0 - 91.0) / Angle2D.PIDEG; public const double THING_Z_OFFSET = 41.0; diff --git a/Source/Core/VisualModes/VisualMode.cs b/Source/Core/VisualModes/VisualMode.cs index d0834ff85..75955385f 100755 --- a/Source/Core/VisualModes/VisualMode.cs +++ b/Source/Core/VisualModes/VisualMode.cs @@ -45,6 +45,8 @@ namespace CodeImp.DoomBuilder.VisualModes #region ================== Constants private const double MOVE_SPEED_MULTIPLIER = 0.001; + protected const float PICK_RANGE = 0.98f; + private const float MOVE_CAMERA_DISTANCE = 64.0f; #endregion @@ -64,6 +66,7 @@ namespace CodeImp.DoomBuilder.VisualModes private bool keyright; private bool keyup; private bool keydown; + private bool orbit; //mxd private List<VisualThing> selectedVisualThings; @@ -75,6 +78,12 @@ namespace CodeImp.DoomBuilder.VisualModes private Vector3D playerStartPosition; private double playerStartAngle; + private Vector3D orbitPoint; + private double orbitXY; + private double orbitZ; + private double orbitRadius; + private bool orbitPointPicked; + // For picking protected PickingMode pickingmode; @@ -90,7 +99,7 @@ namespace CodeImp.DoomBuilder.VisualModes protected List<VisualSector> visiblesectors; protected List<VisualGeometry> visiblegeometry; protected HashSet<VisualSlope> usedslopehandles; - + #endregion #region ================== Properties @@ -395,7 +404,64 @@ namespace CodeImp.DoomBuilder.VisualModes public override void OnMouseInput(Vector2D delta) { base.OnMouseInput(delta); - General.Map.VisualCamera.ProcessMouseInput(delta); + + if (orbit) + { + Vector3D start = General.Map.VisualCamera.Position; + + if (!orbitPointPicked) + { + Vector3D hitPosition = GetHitPosition(); + orbitPoint = hitPosition; + + if (!hitPosition.IsFinite()) + { + return; + } + + orbitPointPicked = true; + + Vector3D pickDelta = start - orbitPoint; + orbitRadius = pickDelta.GetLength(); + orbitXY = pickDelta.GetNormal().GetAngleXY(); + orbitZ = -pickDelta.GetNormal().GetAngleZ(); + } + + // Change camera angles with the mouse changes + orbitXY -= delta.x * VisualCamera.ANGLE_FROM_MOUSE; + if(General.Settings.InvertYAxis) + orbitZ -= delta.y * VisualCamera.ANGLE_FROM_MOUSE; + else + orbitZ += delta.y * VisualCamera.ANGLE_FROM_MOUSE; + + orbitXY = Angle2D.Normalized(orbitXY); + orbitZ = Angle2D.Normalized(orbitZ); + + if (orbitZ < VisualCamera.MAX_ANGLEZ_LOW) orbitZ = VisualCamera.MAX_ANGLEZ_LOW; + if (orbitZ > VisualCamera.MAX_ANGLEZ_HIGH) orbitZ = VisualCamera.MAX_ANGLEZ_HIGH; + + Vector3D orbitDelta = Vector3D.FromAngleXYZ(orbitXY, orbitZ); + + Vector3D newPosition = orbitPoint - orbitDelta * orbitRadius; + Vector3D positionUpdate = newPosition - General.Map.VisualCamera.Position; + + General.Map.VisualCamera.Position += positionUpdate * General.Map.VisualCamera.MoveMultiplier; + start = General.Map.VisualCamera.Position; + + // Recalculate angles to ensure we're always looking at the orbit point + Vector3D updatedDelta = start - orbitPoint; + orbitXY = updatedDelta.GetNormal().GetAngleXY(); + orbitZ = -updatedDelta.GetNormal().GetAngleZ(); + + General.Map.VisualCamera.AngleZ = orbitZ; + General.Map.VisualCamera.AngleXY = orbitXY; + + General.Map.VisualCamera.ProcessMouseInput(new Vector2D()); + } + else + { + General.Map.VisualCamera.ProcessMouseInput(delta); + } } [BeginAction("moveforward", BaseAction = true)] @@ -445,6 +511,19 @@ namespace CodeImp.DoomBuilder.VisualModes { keyright = false; } + + [BeginAction("orbit", BaseAction = true)] + public virtual void BeginOrbit() + { + orbit = true; + } + + [EndAction("orbit", BaseAction = true)] + public virtual void EndOrbit() + { + orbit = false; + orbitPointPicked = false; + } [BeginAction("moveup", BaseAction = true)] public virtual void BeginMoveUp() @@ -469,6 +548,28 @@ namespace CodeImp.DoomBuilder.VisualModes { keydown = false; } + + [BeginAction("movecameratocursor", BaseAction = true)] + protected virtual void MoveCameraToCursor() + { + if (orbit) + { + orbitRadius = MOVE_CAMERA_DISTANCE; + } + else + { + Vector3D hitPosition = GetHitPosition(); + if (!hitPosition.IsFinite()) + { + return; + } + + Vector3D start = General.Map.VisualCamera.Position; + Vector3D delta = start - hitPosition; + General.Map.VisualCamera.Position = hitPosition + delta.GetFixedLength(MOVE_CAMERA_DISTANCE); + } + } + //mxd [BeginAction("movethingleft", BaseAction = true)] @@ -510,14 +611,14 @@ namespace CodeImp.DoomBuilder.VisualModes } //mxd. - public Vector2D GetHitPosition() + public Vector3D GetHitPosition() { Vector3D start = General.Map.VisualCamera.Position; Vector3D delta = General.Map.VisualCamera.Target - General.Map.VisualCamera.Position; delta = delta.GetFixedLength(General.Settings.ViewDistance * 0.98f); VisualPickResult target = PickObject(start, start + delta); - if(target.picked == null) return new Vector2D(double.NaN, double.NaN); + if(target.picked == null) return new Vector3D(double.NaN, double.NaN, double.NaN); // Now find where exactly did we hit VisualGeometry vg = target.picked as VisualGeometry; @@ -525,13 +626,19 @@ namespace CodeImp.DoomBuilder.VisualModes VisualThing vt = target.picked as VisualThing; - if(vt != null) return GetIntersection(start, start + delta, vt.CenterV3D, RenderDevice.V3D(vt.Center - vt.PositionV3)); + if (vt != null) + { + Vector3D normal = start - vt.CenterV3D; + normal.z = 0; + normal = normal.GetNormal(); + return GetIntersection(start, start + delta, vt.CenterV3D, normal); + } - return new Vector2D(double.NaN, double.NaN); + return new Vector3D(double.NaN, double.NaN, double.NaN); } //mxd. This checks intersection between line and plane - private static Vector2D GetIntersection(Vector3D start, Vector3D end, Vector3D planeCenter, Vector3D planeNormal) + private static Vector3D GetIntersection(Vector3D start, Vector3D end, Vector3D planeCenter, Vector3D planeNormal) { Vector3D delta = new Vector3D(planeCenter.x - start.x, planeCenter.y - start.y, planeCenter.z - start.z); return start + Vector3D.DotProduct(planeNormal, delta) / Vector3D.DotProduct(planeNormal, end - start) * (end - start); @@ -1204,19 +1311,33 @@ namespace CodeImp.DoomBuilder.VisualModes Vector3D camdeltapos = new Vector3D(); Vector3D upvec = new Vector3D(0.0, 0.0, 1.0); - // Move the camera double multiplier; if(General.Interface.ShiftState) multiplier = MOVE_SPEED_MULTIPLIER * 2.0f; else multiplier = MOVE_SPEED_MULTIPLIER; - if(keyforward) camdeltapos += camvec * cammovemul * General.Settings.MoveSpeed * multiplier * deltatime; - if(keybackward) camdeltapos -= camvec * cammovemul * General.Settings.MoveSpeed * multiplier * deltatime; - if(keyleft) camdeltapos -= camvecstrafe * cammovemul * General.Settings.MoveSpeed * multiplier * deltatime; - if(keyright) camdeltapos += camvecstrafe * cammovemul * General.Settings.MoveSpeed * multiplier * deltatime; - if(keyup) camdeltapos += upvec * cammovemul * General.Settings.MoveSpeed * multiplier * deltatime; - if(keydown) camdeltapos += -upvec * cammovemul * General.Settings.MoveSpeed * multiplier * deltatime; - - // Move the camera - General.Map.VisualCamera.ProcessMovement(camdeltapos); + if (orbit) + { + if (keyforward) orbitRadius -= General.Settings.MoveSpeed * multiplier * deltatime; + if (keybackward) orbitRadius += General.Settings.MoveSpeed * multiplier * deltatime; + + if (orbitRadius < 1) orbitRadius = 1f; + + General.Map.VisualCamera.ProcessMovement(new Vector3D()); + } + else + { + // Move the camera + + if(keyforward) camdeltapos += camvec * cammovemul * General.Settings.MoveSpeed * multiplier * deltatime; + if(keybackward) camdeltapos -= camvec * cammovemul * General.Settings.MoveSpeed * multiplier * deltatime; + if(keyleft) camdeltapos -= camvecstrafe * cammovemul * General.Settings.MoveSpeed * multiplier * deltatime; + if(keyright) camdeltapos += camvecstrafe * cammovemul * General.Settings.MoveSpeed * multiplier * deltatime; + if(keyup) camdeltapos += upvec * cammovemul * General.Settings.MoveSpeed * multiplier * deltatime; + if(keydown) camdeltapos += -upvec * cammovemul * General.Settings.MoveSpeed * multiplier * deltatime; + + // Move the camera + General.Map.VisualCamera.ProcessMovement(camdeltapos); + } + // Apply new camera matrices renderer.PositionAndLookAt(General.Map.VisualCamera.Position, General.Map.VisualCamera.Target); diff --git a/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs b/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs index cae7904db..e2917e115 100755 --- a/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs +++ b/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs @@ -51,7 +51,6 @@ namespace CodeImp.DoomBuilder.BuilderModes // Object picking private const long PICK_INTERVAL = 80; private const long PICK_INTERVAL_PAINT_SELECT = 10; // biwa - private const float PICK_RANGE = 0.98f; // Gravity private const float GRAVITY = -0.06f; -- GitLab