2015-12-31 12:21:44 +00:00
|
|
|
#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)
|
|
|
|
{
|
2016-02-29 10:41:17 +00:00
|
|
|
if(t.SRB2Type == General.Map.Config.Start3DModeThingType)
|
2015-12-31 12:21:44 +00:00
|
|
|
{
|
|
|
|
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)
|
|
|
|
{
|
2016-02-29 10:41:17 +00:00
|
|
|
if(t.SRB2Type == General.Map.Config.Start3DModeThingType)
|
2015-12-31 12:21:44 +00:00
|
|
|
{
|
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|