Skip to content

Commit 5e5dc85

Browse files
committed
Add 3D cab camera reset and other related features. By dennisat.
1 parent 373b3aa commit 5e5dc85

File tree

2 files changed

+167
-107
lines changed

2 files changed

+167
-107
lines changed

Source/RunActivity/Viewer3D/Cameras.cs

Lines changed: 165 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -1561,7 +1561,16 @@ public InsideThreeDimCamera(Viewer viewer)
15611561
{
15621562
}
15631563

1564-
public PassengerViewPoint viewPoint = null;
1564+
protected Vector3 viewPointLocation;
1565+
protected float viewPointRotationXRadians = 0;
1566+
protected float viewPointRotationYRadians = 0;
1567+
protected Vector3 StartViewPointLocation;
1568+
protected float StartViewPointRotationXRadians = 0;
1569+
protected float StartViewPointRotationYRadians = 0;
1570+
protected string prevcar = "";
1571+
protected int ActViewPoint = 0;
1572+
protected int prevViewPoint = -1;
1573+
protected bool PrevCabWasRear = false;
15651574

15661575
/// <summary>
15671576
/// A camera can use this method to handle any preparation when being activated.
@@ -1659,10 +1668,15 @@ public override void HandleUserInput(ElapsedTime elapsedTime)
16591668
}
16601669
public void MoveCameraXYZ(float x, float y, float z)
16611670
{
1671+
if (PrevCabWasRear)
1672+
{
1673+
x = -x;
1674+
z = -z;
1675+
}
16621676
attachedLocation.X += x;
16631677
attachedLocation.Y += y;
16641678
attachedLocation.Z += z;
1665-
viewPoint.Location.X = attachedLocation.X; viewPoint.Location.Y = attachedLocation.Y; viewPoint.Location.Z = attachedLocation.Z;
1679+
viewPointLocation.X = attachedLocation.X; viewPointLocation.Y = attachedLocation.Y; viewPointLocation.Z = attachedLocation.Z;
16661680
if (attachedCar != null) UpdateLocation(attachedCar.WorldPosition);
16671681
}
16681682

@@ -1673,7 +1687,7 @@ public void MoveCameraXYZ(float x, float y, float z)
16731687
protected override void RotateRight(float speed)
16741688
{
16751689
base.RotateRight(speed);
1676-
viewPoint.RotationYRadians = RotationYRadians;
1690+
viewPointRotationYRadians = RotationYRadians;
16771691
}
16781692

16791693
/// <summary>
@@ -1683,7 +1697,7 @@ protected override void RotateRight(float speed)
16831697
protected override void RotateDown(float speed)
16841698
{
16851699
base.RotateDown(speed);
1686-
viewPoint.RotationXRadians = RotationXRadians;
1700+
viewPointRotationXRadians = RotationXRadians;
16871701
}
16881702

16891703
/// <summary>
@@ -1695,18 +1709,56 @@ protected override void RotateByMouse()
16951709
base.RotateByMouse();
16961710
if (UserInput.IsMouseRightButtonReleased)
16971711
{
1698-
viewPoint.RotationXRadians = RotationXRadians;
1699-
viewPoint.RotationYRadians = RotationYRadians;
1712+
viewPointRotationXRadians = RotationXRadians;
1713+
viewPointRotationYRadians = RotationYRadians;
17001714
}
17011715
}
1716+
1717+
protected internal override void Save(BinaryWriter outf)
1718+
{
1719+
base.Save(outf);
1720+
outf.Write(ActViewPoint);
1721+
outf.Write(prevViewPoint);
1722+
outf.Write(prevcar);
1723+
outf.Write(StartViewPointLocation.X);
1724+
outf.Write(StartViewPointLocation.Y);
1725+
outf.Write(StartViewPointLocation.Z);
1726+
outf.Write(StartViewPointRotationXRadians);
1727+
outf.Write(StartViewPointRotationYRadians);
1728+
}
1729+
1730+
protected internal override void Restore(BinaryReader inf)
1731+
{
1732+
base.Restore(inf);
1733+
ActViewPoint = inf.ReadInt32();
1734+
prevViewPoint = inf.ReadInt32();
1735+
prevcar = inf.ReadString();
1736+
StartViewPointLocation.X = inf.ReadSingle();
1737+
StartViewPointLocation.Y = inf.ReadSingle();
1738+
StartViewPointLocation.Z = inf.ReadSingle();
1739+
StartViewPointRotationXRadians = inf.ReadSingle();
1740+
StartViewPointRotationYRadians = inf.ReadSingle();
1741+
}
1742+
1743+
public override void Reset()
1744+
{
1745+
base.Reset();
1746+
viewPointLocation = StartViewPointLocation;
1747+
attachedLocation = StartViewPointLocation;
1748+
viewPointRotationXRadians = StartViewPointRotationXRadians;
1749+
viewPointRotationYRadians = StartViewPointRotationYRadians;
1750+
RotationXRadians = StartViewPointRotationXRadians;
1751+
RotationYRadians = StartViewPointRotationYRadians;
1752+
XRadians = StartViewPointRotationXRadians;
1753+
YRadians = StartViewPointRotationYRadians;
1754+
}
17021755
}
17031756

17041757
public class PassengerCamera : InsideThreeDimCamera
17051758
{
17061759
public override Styles Style { get { return Styles.Passenger; } }
17071760
public override bool IsAvailable { get { return Viewer.SelectedTrain != null && Viewer.SelectedTrain.Cars.Any(c => c.PassengerViewpoints.Count > 0); } }
17081761
public override string Name { get { return Viewer.Catalog.GetString("Passenger"); } }
1709-
protected int ActViewPoint;
17101762

17111763
public PassengerCamera(Viewer viewer)
17121764
: base(viewer)
@@ -1721,12 +1773,22 @@ protected override List<TrainCar> GetCameraCars()
17211773
protected override void SetCameraCar(TrainCar car)
17221774
{
17231775
base.SetCameraCar(car);
1724-
ActViewPoint = 0;
1725-
viewPoint = attachedCar.PassengerViewpoints[ActViewPoint];
1726-
attachedLocation = viewPoint.Location;
1727-
// Apply previous angle of camera for this type of car.
1728-
RotationXRadians = viewPoint.RotationXRadians;
1729-
RotationYRadians = viewPoint.RotationYRadians;
1776+
// Settings are held so that when switching back from another camera, view is not reset.
1777+
// View is only reset on move to a different car and/or viewpoint or "Ctl + 8".
1778+
if (car.CarID != prevcar || ActViewPoint != prevViewPoint)
1779+
{
1780+
prevcar = car.CarID;
1781+
prevViewPoint = ActViewPoint;
1782+
viewPointLocation = attachedCar.PassengerViewpoints[ActViewPoint].Location;
1783+
viewPointRotationXRadians = attachedCar.PassengerViewpoints[ActViewPoint].RotationXRadians;
1784+
viewPointRotationYRadians = attachedCar.PassengerViewpoints[ActViewPoint].RotationYRadians;
1785+
RotationXRadians = viewPointRotationXRadians;
1786+
RotationYRadians = viewPointRotationYRadians;
1787+
attachedLocation = viewPointLocation;
1788+
StartViewPointLocation = viewPointLocation;
1789+
StartViewPointRotationXRadians = viewPointRotationXRadians;
1790+
StartViewPointRotationYRadians = viewPointRotationYRadians;
1791+
}
17301792
}
17311793

17321794
public override void HandleUserInput(ElapsedTime elapsedTime)
@@ -1736,32 +1798,114 @@ public override void HandleUserInput(ElapsedTime elapsedTime)
17361798
new CameraChangePassengerViewPointCommand(Viewer.Log);
17371799
}
17381800

1739-
public void SwitchSideCameraCar(TrainCar car)
1801+
public void SwitchSideCameraCar(TrainCar car)
17401802
{
17411803
attachedLocation.X = -attachedLocation.X;
1742-
RotationYRadians = -viewPoint.RotationYRadians;
1804+
RotationYRadians = -RotationYRadians;
17431805
}
17441806

17451807
public void ChangePassengerViewPoint(TrainCar car)
17461808
{
17471809
ActViewPoint++;
17481810
if (ActViewPoint >= car.PassengerViewpoints.Count) ActViewPoint = 0;
1749-
viewPoint = attachedCar.PassengerViewpoints[ActViewPoint];
1750-
attachedLocation = viewPoint.Location;
1751-
RotationXRadians = viewPoint.RotationXRadians;
1752-
RotationYRadians = viewPoint.RotationYRadians;
1811+
SetCameraCar(car);
1812+
}
1813+
}
1814+
1815+
public class ThreeDimCabCamera : InsideThreeDimCamera
1816+
{
1817+
public override Styles Style { get { return Styles.ThreeDimCab; } }
1818+
public override bool IsAvailable
1819+
{
1820+
get
1821+
{
1822+
return Viewer.SelectedTrain != null && Viewer.SelectedTrain.IsActualPlayerTrain &&
1823+
Viewer.PlayerLocomotive != null && Viewer.PlayerLocomotive.CabViewpoints != null;
1824+
}
1825+
}
1826+
public override string Name { get { return Viewer.Catalog.GetString("3D Cab"); } }
1827+
1828+
public ThreeDimCabCamera(Viewer viewer)
1829+
: base(viewer)
1830+
{
1831+
}
1832+
1833+
protected override List<TrainCar> GetCameraCars()
1834+
{
1835+
if (Viewer.SelectedTrain != null && Viewer.SelectedTrain.IsActualPlayerTrain &&
1836+
Viewer.PlayerLocomotive != null && Viewer.PlayerLocomotive.CabViewpoints != null)
1837+
{
1838+
List<TrainCar> l = new List<TrainCar>();
1839+
l.Add(Viewer.PlayerLocomotive);
1840+
return l;
1841+
}
1842+
else return base.GetCameraCars();
1843+
}
1844+
1845+
protected override void SetCameraCar(TrainCar car)
1846+
{
1847+
base.SetCameraCar(car);
1848+
// Settings are held so that when switching back from another camera, view is not reset.
1849+
// View is only reset on move to a different cab or "Ctl + 8".
1850+
if (attachedCar.CabViewpoints != null)
1851+
{
1852+
if (ActViewPoint != prevViewPoint)
1853+
{
1854+
prevViewPoint = ActViewPoint;
1855+
viewPointLocation = attachedCar.CabViewpoints[ActViewPoint].Location;
1856+
viewPointRotationXRadians = attachedCar.CabViewpoints[ActViewPoint].RotationXRadians;
1857+
viewPointRotationYRadians = attachedCar.CabViewpoints[ActViewPoint].RotationYRadians;
1858+
RotationXRadians = viewPointRotationXRadians;
1859+
RotationYRadians = viewPointRotationYRadians;
1860+
attachedLocation = viewPointLocation;
1861+
StartViewPointLocation = viewPointLocation;
1862+
StartViewPointRotationXRadians = viewPointRotationXRadians;
1863+
StartViewPointRotationYRadians = viewPointRotationYRadians;
1864+
}
1865+
}
1866+
}
1867+
1868+
public void ChangeCab(TrainCar newCar)
1869+
{
1870+
try
1871+
{
1872+
var mstsLocomotive = newCar as MSTSLocomotive;
1873+
if (PrevCabWasRear != mstsLocomotive.UsingRearCab)
1874+
RotationYRadians += MathHelper.Pi;
1875+
ActViewPoint = mstsLocomotive.UsingRearCab ? 1 : 0;
1876+
PrevCabWasRear = mstsLocomotive.UsingRearCab;
1877+
SetCameraCar(newCar);
1878+
}
1879+
catch
1880+
{
1881+
Trace.TraceInformation("Change Cab failed");
1882+
}
17531883
}
17541884

17551885
protected internal override void Save(BinaryWriter outf)
17561886
{
17571887
base.Save(outf);
1758-
outf.Write(ActViewPoint);
1888+
outf.Write(PrevCabWasRear);
17591889
}
17601890

17611891
protected internal override void Restore(BinaryReader inf)
17621892
{
17631893
base.Restore(inf);
1764-
ActViewPoint = inf.ReadInt32();
1894+
PrevCabWasRear = inf.ReadBoolean();
1895+
}
1896+
1897+
public override bool IsUnderground
1898+
{
1899+
get
1900+
{
1901+
// Camera is underground if target (base) is underground or
1902+
// track location is underground. The latter means we switch
1903+
// to cab view instead of putting the camera above the tunnel.
1904+
if (base.IsUnderground)
1905+
return true;
1906+
var elevationAtCameraTarget = Viewer.Tiles.GetElevation(attachedCar.WorldPosition.WorldLocation);
1907+
return attachedCar.WorldPosition.Location.Y + TerrainAltitudeMargin < elevationAtCameraTarget || attachedCar.CarTunnelData.LengthMOfTunnelAheadFront > 0;
1908+
}
17651909
}
17661910
}
17671911

@@ -2556,88 +2700,4 @@ protected override void ZoomIn(float speed)
25562700
}
25572701
}
25582702
}
2559-
2560-
public class ThreeDimCabCamera : InsideThreeDimCamera
2561-
{
2562-
public override Styles Style { get { return Styles.ThreeDimCab; } }
2563-
public override bool IsAvailable
2564-
{
2565-
get
2566-
{
2567-
return Viewer.SelectedTrain != null && Viewer.SelectedTrain.IsActualPlayerTrain &&
2568-
Viewer.PlayerLocomotive != null && Viewer.PlayerLocomotive.CabViewpoints != null;
2569-
}
2570-
}
2571-
public override string Name { get { return Viewer.Catalog.GetString("3D Cab"); } }
2572-
bool StartDirectionSet = false;
2573-
protected int CurrentViewpointIndex;
2574-
protected bool PrevCabWasRear;
2575-
2576-
public ThreeDimCabCamera(Viewer viewer)
2577-
: base(viewer)
2578-
{
2579-
}
2580-
2581-
protected override List<TrainCar> GetCameraCars()
2582-
{
2583-
if (Viewer.SelectedTrain != null && Viewer.SelectedTrain.IsActualPlayerTrain &&
2584-
Viewer.PlayerLocomotive != null && Viewer.PlayerLocomotive.CabViewpoints != null)
2585-
{
2586-
List<TrainCar> l = new List<TrainCar>();
2587-
l.Add(Viewer.PlayerLocomotive);
2588-
return l;
2589-
}
2590-
else return base.GetCameraCars();
2591-
}
2592-
2593-
protected override void SetCameraCar(TrainCar car)
2594-
{
2595-
base.SetCameraCar(car);
2596-
if (attachedCar.CabViewpoints != null)
2597-
{
2598-
if (CurrentViewpointIndex >= attachedCar.CabViewpoints.Count) { viewPoint = attachedCar.CabViewpoints[0]; CurrentViewpointIndex = 0; }
2599-
else viewPoint = attachedCar.CabViewpoints[CurrentViewpointIndex];
2600-
attachedLocation = viewPoint.Location;
2601-
if (!StartDirectionSet) // Only set the initial direction on first use so, when switching back from another camera, direction is not reset.
2602-
{
2603-
StartDirectionSet = true;
2604-
RotationXRadians = MathHelper.ToRadians(viewPoint.StartDirection.X);
2605-
RotationYRadians = MathHelper.ToRadians(viewPoint.StartDirection.Y);
2606-
}
2607-
else
2608-
{
2609-
RotationXRadians = viewPoint.RotationXRadians;
2610-
RotationYRadians = viewPoint.RotationYRadians;
2611-
}
2612-
}
2613-
}
2614-
2615-
public void ChangeCab(TrainCar newCar)
2616-
{
2617-
try
2618-
{
2619-
var mstsLocomotive = newCar as MSTSLocomotive;
2620-
if (PrevCabWasRear != mstsLocomotive.UsingRearCab)
2621-
RotationYRadians += MathHelper.Pi;
2622-
CurrentViewpointIndex = mstsLocomotive.UsingRearCab ? 1 : 0;
2623-
PrevCabWasRear = mstsLocomotive.UsingRearCab;
2624-
SetCameraCar(newCar);
2625-
}
2626-
catch { }
2627-
}
2628-
2629-
public override bool IsUnderground
2630-
{
2631-
get
2632-
{
2633-
// Camera is underground if target (base) is underground or
2634-
// track location is underground. The latter means we switch
2635-
// to cab view instead of putting the camera above the tunnel.
2636-
if (base.IsUnderground)
2637-
return true;
2638-
var elevationAtCameraTarget = Viewer.Tiles.GetElevation(attachedCar.WorldPosition.WorldLocation);
2639-
return attachedCar.WorldPosition.Location.Y + TerrainAltitudeMargin < elevationAtCameraTarget || attachedCar.CarTunnelData.LengthMOfTunnelAheadFront > 0;
2640-
}
2641-
}
2642-
}
26432703
}

Source/RunActivity/Viewer3D/Viewer.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -793,12 +793,12 @@ public void Update(RenderFrame frame, float elapsedRealTime)
793793
{
794794
// The AbovegroundCamera.Update() has been creating an odd sound issue when the locomotive is in the tunnel.
795795
// Allowing the update to take place when only in cab view solved the issue.
796-
if (Camera == CabCamera)
796+
if (Camera == CabCamera || Camera == ThreeDimCabCamera)
797797
AbovegroundCamera.Update(elapsedTime);
798798
if (!AbovegroundCamera.IsUnderground)
799799
{
800800
// But only if the user hasn't selected another camera!
801-
if (Camera == CabCamera)
801+
if (Camera == CabCamera || Camera == ThreeDimCabCamera)
802802
AbovegroundCamera.Activate();
803803
AbovegroundCamera = null;
804804
}

0 commit comments

Comments
 (0)