ZoneBuilder/Source/Core/VisualModes/VisualCamera.cs

182 lines
4.5 KiB
C#

#region ================== Namespaces
using CodeImp.DoomBuilder.Geometry;
using CodeImp.DoomBuilder.Map;
#endregion
namespace CodeImp.DoomBuilder.VisualModes
{
/// <summary>
/// This class provides the camera in Visual Mode
/// </summary>
public class VisualCamera
{
#region ================== Constants
private const float ANGLE_FROM_MOUSE = 0.0001f;
public const float MAX_ANGLEZ_LOW = 91f / Angle2D.PIDEG;
public const float MAX_ANGLEZ_HIGH = (360f - 91f) / Angle2D.PIDEG;
public const float THING_Z_OFFSET = 41.0f;
#endregion
#region ================== Variables
// Properties
private Vector3D position;
private Vector3D target;
private Vector3D movemultiplier;
private float anglexy, anglez;
private Sector sector;
private float gravity = 1.0f; //mxd
#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; UpdateGravity(); } } //mxd
public Vector3D MoveMultiplier { get { return movemultiplier; } set { movemultiplier = value; } }
public float Gravity { get { return gravity; } } //mxd
#endregion
#region ================== Constructor / Destructor
// Constructor
public VisualCamera()
{
// Initialize
movemultiplier = new Vector3D(1.0f, 1.0f, 1.0f);
anglexy = 0.0f;
anglez = Angle2D.PI;
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;
if(General.Settings.InvertYAxis)
anglez -= delta.y * ANGLE_FROM_MOUSE;
else
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 virtual bool PositionAtThing()
{
if(General.Settings.GZSynchCameras) return true; //mxd
Thing modething = null;
// Find a 3D Mode thing
foreach(Thing t in General.Map.Map.Things)
{
if(t.SRB2Type == General.Map.Config.Start3DModeThingType)
{
modething = t;
break; //mxd
}
}
// Found one?
if(modething != null)
{
modething.DetermineSector();
float z = modething.Position.z;
if(modething.Sector != null) z += modething.Sector.FloorHeight;
// Position camera here
Vector3D wantedposition = new Vector3D(modething.Position.x, modething.Position.y, z + THING_Z_OFFSET);
Vector3D delta = position - wantedposition;
if(delta.GetLength() > 1.0f) position = wantedposition;
// Change angle
float wantedanglexy = modething.Angle + Angle2D.PI;
if(anglexy != wantedanglexy)
{
anglexy = wantedanglexy;
anglez = Angle2D.PI;
}
return true;
}
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 virtual bool ApplyToThing()
{
if(General.Settings.GZSynchCameras) return true; //mxd
Thing modething = null;
// Find a 3D Mode thing
foreach(Thing t in General.Map.Map.Things)
{
if(t.SRB2Type == General.Map.Config.Start3DModeThingType)
{
modething = t;
break; //mxd
}
}
// Found one?
if(modething != null)
{
int z = (int)position.z; //mxd
if(sector != null) z -= sector.FloorHeight;
// Position the thing to match camera
modething.Move((int)position.x, (int)position.y, z - THING_Z_OFFSET);
modething.Rotate(anglexy - Angle2D.PI);
return true;
}
return false;
}
//mxd
private void UpdateGravity()
{
if(!General.Map.UDMF || sector == null) return;
gravity = sector.Fields.GetValue("gravity", 1.0f);
}
#endregion
}
}