diff --git a/Source/Builder.csproj b/Source/Builder.csproj
index d1b7beb1..2f967c40 100644
--- a/Source/Builder.csproj
+++ b/Source/Builder.csproj
@@ -685,6 +685,7 @@
+
diff --git a/Source/BuilderModes/VisualModes/BaseVisualGeometrySidedef.cs b/Source/BuilderModes/VisualModes/BaseVisualGeometrySidedef.cs
index 6f66f697..82d4f934 100644
--- a/Source/BuilderModes/VisualModes/BaseVisualGeometrySidedef.cs
+++ b/Source/BuilderModes/VisualModes/BaseVisualGeometrySidedef.cs
@@ -268,8 +268,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Select button pressed
public virtual void OnSelectBegin()
{
- dragstartanglexy = mode.CameraAngleXY;
- dragstartanglez = mode.CameraAngleZ;
+ dragstartanglexy = General.Map.VisualCamera.AngleXY;
+ dragstartanglez = General.Map.VisualCamera.AngleZ;
dragorigin = pickintersect;
startoffsetx = Sidedef.OffsetX;
startoffsety = Sidedef.OffsetY;
@@ -321,8 +321,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
if(General.Actions.CheckActionActive(General.ThisAssembly, "visualselect"))
{
// Check if tolerance is exceeded to start UV dragging
- float deltaxy = mode.CameraAngleXY - dragstartanglexy;
- float deltaz = mode.CameraAngleZ - dragstartanglez;
+ float deltaxy = General.Map.VisualCamera.AngleXY - dragstartanglexy;
+ float deltaz = General.Map.VisualCamera.AngleZ - dragstartanglez;
if((Math.Abs(deltaxy) + Math.Abs(deltaz)) > DRAG_ANGLE_TOLERANCE)
{
General.Map.UndoRedo.CreateUndo("Change texture offsets");
@@ -342,9 +342,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
float u_ray;
// Calculate intersection position
- Line2D ray = new Line2D(mode.CameraPosition, mode.CameraTarget);
+ Line2D ray = new Line2D(General.Map.VisualCamera.Position, General.Map.VisualCamera.Target);
Sidedef.Line.Line.GetIntersection(ray, out u_ray);
- Vector3D intersect = mode.CameraPosition + (mode.CameraTarget - mode.CameraPosition) * u_ray;
+ Vector3D intersect = General.Map.VisualCamera.Position + (General.Map.VisualCamera.Target - General.Map.VisualCamera.Position) * u_ray;
// Calculate offsets
Vector3D dragdelta = intersect - dragorigin;
diff --git a/Source/BuilderModes/VisualModes/BaseVisualMode.cs b/Source/BuilderModes/VisualModes/BaseVisualMode.cs
index 50bfabf1..bf37a595 100644
--- a/Source/BuilderModes/VisualModes/BaseVisualMode.cs
+++ b/Source/BuilderModes/VisualModes/BaseVisualMode.cs
@@ -146,8 +146,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
private void PickTarget()
{
// Find the object we are aiming at
- Vector3D start = CameraPosition;
- Vector3D delta = CameraTarget - CameraPosition;
+ Vector3D start = General.Map.VisualCamera.Position;
+ Vector3D delta = General.Map.VisualCamera.Target - General.Map.VisualCamera.Position;
delta = delta.GetFixedLength(General.Settings.ViewDistance * PICK_RANGE);
VisualPickResult newtarget = PickObject(start, start + delta);
@@ -205,32 +205,34 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Setup the move multiplier depending on gravity
Vector3D movemultiplier = new Vector3D(1.0f, 1.0f, 1.0f);
if(BuilderPlug.Me.UseGravity) movemultiplier.z = 0.0f;
- base.MoveMultiplier = movemultiplier;
+ General.Map.VisualCamera.MoveMultiplier = movemultiplier;
// Apply gravity?
- if(BuilderPlug.Me.UseGravity && (CameraSector != null))
+ if(BuilderPlug.Me.UseGravity && (General.Map.VisualCamera.Sector != null))
{
// Camera below floor level?
- if(base.CameraPosition.z <= (CameraSector.FloorHeight + CAMERA_FLOOR_OFFSET + 0.1f))
+ if(General.Map.VisualCamera.Position.z <= (General.Map.VisualCamera.Sector.FloorHeight + CAMERA_FLOOR_OFFSET + 0.1f))
{
// Stay above floor
gravity = new Vector3D(0.0f, 0.0f, 0.0f);
- base.CameraPosition = new Vector3D(base.CameraPosition.x, base.CameraPosition.y,
- CameraSector.FloorHeight + CAMERA_FLOOR_OFFSET);
+ General.Map.VisualCamera.Position = new Vector3D(General.Map.VisualCamera.Position.x,
+ General.Map.VisualCamera.Position.y,
+ General.Map.VisualCamera.Sector.FloorHeight + CAMERA_FLOOR_OFFSET);
}
else
{
// Fall down
gravity += new Vector3D(0.0f, 0.0f, (float)(GRAVITY * deltatime));
- base.CameraPosition = base.CameraPosition + gravity;
+ General.Map.VisualCamera.Position += gravity;
}
// Camera above ceiling level?
- if(base.CameraPosition.z >= (CameraSector.CeilHeight - CAMERA_CEILING_OFFSET - 0.1f))
+ if(General.Map.VisualCamera.Position.z >= (General.Map.VisualCamera.Sector.CeilHeight - CAMERA_CEILING_OFFSET - 0.1f))
{
// Stay below ceiling
- base.CameraPosition = new Vector3D(base.CameraPosition.x, base.CameraPosition.y,
- CameraSector.CeilHeight - CAMERA_CEILING_OFFSET);
+ General.Map.VisualCamera.Position = new Vector3D(General.Map.VisualCamera.Position.x,
+ General.Map.VisualCamera.Position.y,
+ General.Map.VisualCamera.Sector.CeilHeight - CAMERA_CEILING_OFFSET);
}
}
else
diff --git a/Source/General/MapManager.cs b/Source/General/MapManager.cs
index 65960ae2..269bcfab 100644
--- a/Source/General/MapManager.cs
+++ b/Source/General/MapManager.cs
@@ -35,6 +35,7 @@ using CodeImp.DoomBuilder.Actions;
using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.Plugins;
using CodeImp.DoomBuilder.Compilers;
+using CodeImp.DoomBuilder.VisualModes;
#endregion
@@ -86,6 +87,7 @@ namespace CodeImp.DoomBuilder
private ThingsFilter thingsfilter;
private ScriptEditorForm scriptwindow;
private List errors;
+ private VisualCamera visualcamera;
// Disposing
private bool isdisposed = false;
@@ -117,6 +119,7 @@ namespace CodeImp.DoomBuilder
public ThingsFilter ThingsFilter { get { return thingsfilter; } }
internal List Errors { get { return errors; } }
internal ScriptEditorForm ScriptEditor { get { return scriptwindow; } }
+ public VisualCamera VisualCamera { get { return visualcamera; } set { visualcamera = value; } }
public bool IsScriptsWindowOpen { get { return (scriptwindow != null) && !scriptwindow.IsDisposed; } }
#endregion
@@ -172,6 +175,7 @@ namespace CodeImp.DoomBuilder
if(renderer2d != null) renderer2d.Dispose();
if(renderer3d != null) renderer3d.Dispose();
if(graphics != null) graphics.Dispose();
+ visualcamera = null;
grid = null;
launcher = null;
copypaste = null;
@@ -268,7 +272,8 @@ namespace CodeImp.DoomBuilder
// Bind any methods
General.Actions.BindMethods(this);
- // Set default mode
+ // Set defaults
+ this.visualcamera = new VisualCamera();
General.Editing.ChangeMode("VerticesMode");
ClassicMode cmode = (General.Editing.Mode as ClassicMode);
if(cmode != null) cmode.SetZoom(0.5f);
@@ -292,7 +297,7 @@ namespace CodeImp.DoomBuilder
this.filepathname = filepathname;
this.changed = false;
this.options = options;
-
+
General.WriteLogLine("Opening map '" + options.CurrentName + "' with configuration '" + options.ConfigFile + "'");
// Initiate graphics
@@ -357,7 +362,8 @@ namespace CodeImp.DoomBuilder
// Bind any methods
General.Actions.BindMethods(this);
- // Set default mode
+ // Set defaults
+ this.visualcamera = new VisualCamera();
General.Editing.ChangeMode("VerticesMode");
renderer2d.SetViewMode((ViewMode)General.Settings.DefaultViewMode);
@@ -1326,7 +1332,8 @@ namespace CodeImp.DoomBuilder
// Let the plugin and editing mode know
General.Plugins.OnMapSetChangeBegin();
if(General.Editing.Mode != null) General.Editing.Mode.OnMapSetChangeBegin();
-
+ this.visualcamera.Sector = null;
+
// Can't have a selection in an old map set
map.ClearAllSelected();
diff --git a/Source/VisualModes/VisualCamera.cs b/Source/VisualModes/VisualCamera.cs
new file mode 100644
index 00000000..6d9f947e
--- /dev/null
+++ b/Source/VisualModes/VisualCamera.cs
@@ -0,0 +1,155 @@
+#region ================== Namespaces
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Text;
+using CodeImp.DoomBuilder.Geometry;
+using CodeImp.DoomBuilder.Map;
+
+#endregion
+
+namespace CodeImp.DoomBuilder.VisualModes
+{
+ public class VisualCamera
+ {
+ #region ================== Constants
+
+ private const float ANGLE_FROM_MOUSE = 0.0001f;
+ public const float MAX_ANGLEZ_LOW = 100f / Angle2D.PIDEG;
+ public const float MAX_ANGLEZ_HIGH = (360f - 100f) / Angle2D.PIDEG;
+
+ #endregion
+
+ #region ================== Variables
+
+ // Properties
+ private Vector3D position;
+ private Vector3D target;
+ private Vector3D movemultiplier;
+ private float anglexy, anglez;
+ private Sector sector;
+
+ #endregion
+
+ #region ================== Properties
+
+ public Vector3D Position { get { return position; } set { position = value; } }
+ public Vector3D Target { get { return target; } }
+ public float AngleXY { get { return anglexy; } set { anglexy = value; } }
+ public float AngleZ { get { return anglez; } set { anglez = value; } }
+ public Sector Sector { get { return sector; } internal set { sector = value; } }
+ public Vector3D MoveMultiplier { get { return movemultiplier; } set { movemultiplier = value; } }
+
+ #endregion
+
+ #region ================== Constructor / Destructor
+
+ // Constructor
+ public VisualCamera()
+ {
+ // Initialize
+ this.movemultiplier = new Vector3D(1.0f, 1.0f, 1.0f);
+ this.position = position;
+ this.anglexy = 0.0f;
+ this.anglez = Angle2D.PI;
+ this.sector = null;
+
+ PositionAtThing();
+ }
+
+ #endregion
+
+ #region ================== Methods
+
+ // Mouse input
+ internal void ProcessMouseInput(Vector2D delta)
+ {
+ // Change camera angles with the mouse changes
+ anglexy -= delta.x * ANGLE_FROM_MOUSE;
+ anglez += delta.y * ANGLE_FROM_MOUSE;
+
+ // Normalize angles
+ anglexy = Angle2D.Normalized(anglexy);
+ anglez = Angle2D.Normalized(anglez);
+
+ // Limit vertical angle
+ if(anglez < MAX_ANGLEZ_LOW) anglez = MAX_ANGLEZ_LOW;
+ if(anglez > MAX_ANGLEZ_HIGH) anglez = MAX_ANGLEZ_HIGH;
+ }
+
+ // Key input
+ internal void ProcessMovement(Vector3D deltavec)
+ {
+ // Calculate camera direction vectors
+ Vector3D camvec = Vector3D.FromAngleXYZ(anglexy, anglez);
+
+ // Position the camera
+ position += deltavec;
+
+ // Target the camera
+ target = position + camvec;
+ }
+
+ // This applies the position and angle from the 3D Camera Thing
+ // Returns false when it couldn't find a 3D Camera Thing
+ public bool PositionAtThing()
+ {
+ Thing modething = null;
+
+ // Find a 3D Mode thing
+ foreach(Thing t in General.Map.Map.Things)
+ if(t.Type == General.Map.Config.Start3DModeThingType) modething = t;
+
+ // Found one?
+ if(modething != null)
+ {
+ int z = 0;
+ if(sector != null)
+ z = (int)position.z - sector.FloorHeight;
+
+ // Position camera here
+ modething.DetermineSector();
+ position = modething.Position + new Vector3D(0.0f, 0.0f, 96.0f);
+ anglexy = modething.Angle + Angle2D.PI;
+ anglez = Angle2D.PI;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ // This applies the camera position and angle to the 3D Camera Thing
+ // Returns false when it couldn't find a 3D Camera Thing
+ public bool ApplyToThing()
+ {
+ Thing modething = null;
+
+ // Find a 3D Mode thing
+ foreach(Thing t in General.Map.Map.Things)
+ if(t.Type == General.Map.Config.Start3DModeThingType) modething = t;
+
+ // Found one?
+ if(modething != null)
+ {
+ int z = 0;
+ if(sector != null)
+ z = (int)position.z - sector.FloorHeight;
+
+ // Position the thing to match camera
+ modething.Move((int)position.x, (int)position.y, z);
+ modething.Rotate(anglexy - Angle2D.PI);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/Source/VisualModes/VisualMode.cs b/Source/VisualModes/VisualMode.cs
index 4c8b7208..8c9cb558 100644
--- a/Source/VisualModes/VisualMode.cs
+++ b/Source/VisualModes/VisualMode.cs
@@ -45,9 +45,6 @@ namespace CodeImp.DoomBuilder.VisualModes
{
#region ================== Constants
- private const float ANGLE_FROM_MOUSE = 0.0001f;
- public const float MAX_ANGLEZ_LOW = 100f / Angle2D.PIDEG;
- public const float MAX_ANGLEZ_HIGH = (360f - 100f) / Angle2D.PIDEG;
private const double MOVE_SPEED_MULTIPLIER = 0.001d;
#endregion
@@ -61,13 +58,6 @@ namespace CodeImp.DoomBuilder.VisualModes
protected IRenderer3D renderer;
private Renderer3D renderer3d;
- // Camera
- private Vector3D campos;
- private Vector3D camtarget;
- private Vector3D movemultiplier;
- private float camanglexy, camanglez;
- private Sector camsector;
-
// Options
private bool processgeometry;
private bool processthings;
@@ -92,14 +82,8 @@ namespace CodeImp.DoomBuilder.VisualModes
#region ================== Properties
- public Vector3D CameraPosition { get { return campos; } set { campos = value; } }
- public Vector3D CameraTarget { get { return camtarget; } }
- public float CameraAngleXY { get { return camanglexy; } set { camanglexy = value; } }
- public float CameraAngleZ { get { return camanglez; } set { camanglez = value; } }
- public Sector CameraSector { get { return camsector; } }
public bool ProcessGeometry { get { return processgeometry; } set { processgeometry = value; } }
public bool ProcessThings { get { return processthings; } set { processthings = value; } }
- public Vector3D MoveMultiplier { get { return movemultiplier; } set { movemultiplier = value; } }
public VisualBlockMap BlockMap { get { return blockmap; } }
#endregion
@@ -114,9 +98,6 @@ namespace CodeImp.DoomBuilder.VisualModes
// Initialize
this.renderer = General.Map.Renderer3D;
this.renderer3d = (Renderer3D)General.Map.Renderer3D;
- this.campos = new Vector3D(0.0f, 0.0f, 96.0f);
- this.movemultiplier = new Vector3D(1.0f, 1.0f, 1.0f);
- this.camanglez = Angle2D.PI;
this.blockmap = new VisualBlockMap();
this.allsectors = new Dictionary(General.Map.Map.Sectors.Count);
this.allthings = new Dictionary(General.Map.Map.Things.Count);
@@ -161,24 +142,10 @@ namespace CodeImp.DoomBuilder.VisualModes
// Update the used textures
General.Map.Data.UpdateUsedTextures();
-
+
// Fill the blockmap
FillBlockMap();
- // Find a 3D Mode thing
- foreach(Thing t in General.Map.Map.Things)
- if(t.Type == General.Map.Config.Start3DModeThingType) modething = t;
-
- // Found one?
- if(modething != null)
- {
- // Position camera here
- modething.DetermineSector();
- campos = modething.Position + new Vector3D(0.0f, 0.0f, 96.0f);
- camanglexy = modething.Angle + Angle2D.PI;
- camanglez = Angle2D.PI;
- }
-
// Start special input mode
General.Interface.SetProcessorState(true);
General.Interface.StartExclusiveMouseInput();
@@ -197,13 +164,11 @@ namespace CodeImp.DoomBuilder.VisualModes
foreach(KeyValuePair vt in allthings)
vt.Value.Dispose();
- // Do we have a 3D Mode thing?
- if(modething != null)
- {
- // Position the thing to match camera
- modething.Move((int)campos.x, (int)campos.y, 0);
- modething.Rotate(camanglexy - Angle2D.PI);
- }
+ // Apply camera position to thing
+ General.Map.VisualCamera.ApplyToThing();
+
+ // Do not leave the sector on the camera
+ General.Map.VisualCamera.Sector = null;
// Stop special input mode
General.Interface.SetProcessorState(false);
@@ -256,18 +221,7 @@ namespace CodeImp.DoomBuilder.VisualModes
public override void OnMouseInput(Vector2D delta)
{
base.OnMouseInput(delta);
-
- // Change camera angles with the mouse changes
- camanglexy -= delta.x * ANGLE_FROM_MOUSE;
- camanglez += delta.y * ANGLE_FROM_MOUSE;
-
- // Normalize angles
- camanglexy = Angle2D.Normalized(camanglexy);
- camanglez = Angle2D.Normalized(camanglez);
-
- // Limit vertical angle
- if(camanglez < MAX_ANGLEZ_LOW) camanglez = MAX_ANGLEZ_LOW;
- if(camanglez > MAX_ANGLEZ_HIGH) camanglez = MAX_ANGLEZ_HIGH;
+ General.Map.VisualCamera.ProcessMouseInput(delta);
}
[BeginAction("moveforward", BaseAction = true)]
@@ -338,7 +292,7 @@ namespace CodeImp.DoomBuilder.VisualModes
private void DoCulling()
{
Dictionary visiblelines = new Dictionary(200);
- Vector2D campos2d = (Vector2D)campos;
+ Vector2D campos2d = (Vector2D)General.Map.VisualCamera.Position;
float viewdist = General.Settings.ViewDistance;
// Make collections
@@ -410,7 +364,7 @@ namespace CodeImp.DoomBuilder.VisualModes
Linedef nld = MapSet.NearestLinedef(visiblelines.Values, campos2d);
if(nld != null)
{
- camsector = GetCameraSectorFromLinedef(nld);
+ General.Map.VisualCamera.Sector = GetCameraSectorFromLinedef(nld);
}
else
{
@@ -422,10 +376,10 @@ namespace CodeImp.DoomBuilder.VisualModes
nld = General.Map.Map.NearestLinedef(campos2d);
if(nld != null)
{
- camsector = GetCameraSectorFromLinedef(nld);
- if(camsector != null)
+ General.Map.VisualCamera.Sector = GetCameraSectorFromLinedef(nld);
+ if(General.Map.VisualCamera.Sector != null)
{
- foreach(Sidedef sd in camsector.Sidedefs)
+ foreach(Sidedef sd in General.Map.VisualCamera.Sector.Sidedefs)
{
float side = sd.Line.SideOfLine(campos2d);
if(((side < 0) && sd.IsFront) ||
@@ -436,13 +390,13 @@ namespace CodeImp.DoomBuilder.VisualModes
else
{
// Too far away from the map to see anything
- camsector = null;
+ General.Map.VisualCamera.Sector = null;
}
}
else
{
// Map is empty
- camsector = null;
+ General.Map.VisualCamera.Sector = null;
}
}
}
@@ -483,7 +437,7 @@ namespace CodeImp.DoomBuilder.VisualModes
// This returns the camera sector from linedef
private Sector GetCameraSectorFromLinedef(Linedef ld)
{
- if(ld.SideOfLine(campos) < 0)
+ if(ld.SideOfLine(General.Map.VisualCamera.Position) < 0)
{
if(ld.Front != null)
return ld.Front.Sector;
@@ -524,10 +478,10 @@ namespace CodeImp.DoomBuilder.VisualModes
List pickables = new List(blocks.Count * 10);
// Add geometry from the camera sector
- if((camsector != null) && allsectors.ContainsKey(camsector))
+ if((General.Map.VisualCamera.Sector != null) && allsectors.ContainsKey(General.Map.VisualCamera.Sector))
{
- VisualSector vs = allsectors[camsector];
- sectors.Add(camsector, vs);
+ VisualSector vs = allsectors[General.Map.VisualCamera.Sector];
+ sectors.Add(General.Map.VisualCamera.Sector, vs);
foreach(VisualGeometry g in vs.FixedGeometry) pickables.Add(g);
}
@@ -741,22 +695,24 @@ namespace CodeImp.DoomBuilder.VisualModes
base.OnProcess(deltatime);
- // Calculate camera direction vectors
- Vector3D camvec = Vector3D.FromAngleXYZ(camanglexy, camanglez);
- Vector3D camvecstrafe = Vector3D.FromAngleXY(camanglexy + Angle2D.PIHALF);
+ // Camera vectors
+ Vector3D camvec = Vector3D.FromAngleXYZ(General.Map.VisualCamera.AngleXY, General.Map.VisualCamera.AngleZ);
+ Vector3D camvecstrafe = Vector3D.FromAngleXY(General.Map.VisualCamera.AngleXY + Angle2D.PIHALF);
+ Vector3D cammovemul = General.Map.VisualCamera.MoveMultiplier;
+ Vector3D camdeltapos = new Vector3D();
// Move the camera
if(doublespeed) multiplier = MOVE_SPEED_MULTIPLIER * 2.0f; else multiplier = MOVE_SPEED_MULTIPLIER;
- if(keyforward) campos += camvec * movemultiplier * (float)((double)General.Settings.MoveSpeed * multiplier * deltatime);
- if(keybackward) campos -= camvec * movemultiplier * (float)((double)General.Settings.MoveSpeed * multiplier * deltatime);
- if(keyleft) campos -= camvecstrafe * movemultiplier * (float)((double)General.Settings.MoveSpeed * multiplier * deltatime);
- if(keyright) campos += camvecstrafe * movemultiplier * (float)((double)General.Settings.MoveSpeed * multiplier * deltatime);
+ if(keyforward) camdeltapos += camvec * cammovemul * (float)((double)General.Settings.MoveSpeed * multiplier * deltatime);
+ if(keybackward) camdeltapos -= camvec * cammovemul * (float)((double)General.Settings.MoveSpeed * multiplier * deltatime);
+ if(keyleft) camdeltapos -= camvecstrafe * cammovemul * (float)((double)General.Settings.MoveSpeed * multiplier * deltatime);
+ if(keyright) camdeltapos += camvecstrafe * cammovemul * (float)((double)General.Settings.MoveSpeed * multiplier * deltatime);
- // Target the camera
- camtarget = campos + camvec;
+ // Move the camera
+ General.Map.VisualCamera.ProcessMovement(camdeltapos);
// Apply new camera matrices
- renderer.PositionAndLookAt(campos, camtarget);
+ renderer.PositionAndLookAt(General.Map.VisualCamera.Position, General.Map.VisualCamera.Target);
// Visibility culling
DoCulling();