1 using System;
2 using System.ComponentModel;
3 using System.Linq;
4 using OpenBveApi.Interface;
5 using SoundManager;
6 using TrainEditor2.Systems;
7 
8 namespace TrainEditor2.Models.Trains
9 {
10 	internal partial class Motor
11 	{
StartSimulation()12 		internal void StartSimulation()
13 		{
14 			try
15 			{
16 				CreateCar();
17 			}
18 			catch (Exception e)
19 			{
20 				Interface.AddMessage(MessageType.Error, false, $"{e.GetType().FullName}: {e.Message} at {e.StackTrace}");
21 				CurrentSimState = SimulationState.Disable;
22 				return;
23 			}
24 
25 			if (Simulation.TrainManager.TrainManager.PlayerTrain == null)
26 			{
27 				Interface.AddMessage(MessageType.Error, false, "Failed to create train.");
28 				CurrentSimState = SimulationState.Disable;
29 				return;
30 			}
31 
32 			oldElapsedTime = 0;
33 			startTime = DateTime.Now;
34 
35 			if (CurrentSimState != SimulationState.Paused)
36 			{
37 				nowSpeed = StartSpeed;
38 			}
39 
40 			CurrentSimState = SimulationState.Started;
41 		}
42 
PauseSimulation()43 		internal void PauseSimulation()
44 		{
45 			DisposeCar();
46 			CurrentSimState = SimulationState.Paused;
47 		}
48 
StopSimulation()49 		internal void StopSimulation()
50 		{
51 			DisposeCar();
52 			CurrentSimState = SimulationState.Stopped;
53 
54 			IsRefreshGlControl = true;
55 		}
56 
CreateCar()57 		private void CreateCar()
58 		{
59 			DisposeCar();
60 
61 			Simulation.TrainManager.TrainManager.PlayerTrain = new Simulation.TrainManager.TrainManager.Train();
62 			Simulation.TrainManager.TrainManager.PlayerTrain.Car.Sounds.Motor.SpeedConversionFactor = 18.0;
63 			Simulation.TrainManager.TrainManager.PlayerTrain.Car.Sounds.Motor.Tables = Tracks.Select(t => Track.EntriesToMotorSoundTable(Track.TrackToEntries(t))).ToArray();
64 			Simulation.TrainManager.TrainManager.PlayerTrain.Car.ApplySounds();
65 		}
66 
RunSimulation()67 		internal void RunSimulation()
68 		{
69 			if (Simulation.TrainManager.TrainManager.PlayerTrain == null)
70 			{
71 				return;
72 			}
73 
74 			double nowElapsedTime = (DateTime.Now - startTime).TotalSeconds;
75 
76 			if (oldElapsedTime == 0.0)
77 			{
78 				oldElapsedTime = nowElapsedTime;
79 			}
80 
81 			double deltaTime = nowElapsedTime - oldElapsedTime;
82 
83 			double outputAcceleration = Math.Sign(endSpeed - startSpeed) * Acceleration;
84 
85 			nowSpeed += outputAcceleration * deltaTime;
86 			double minSpeed = Math.Min(startSpeed, endSpeed);
87 			double maxSpeed = Math.Max(startSpeed, endSpeed);
88 
89 			if (IsLoop)
90 			{
91 				if (nowSpeed < minSpeed)
92 				{
93 					nowSpeed = maxSpeed;
94 					outputAcceleration = 0.0;
95 				}
96 
97 				if (nowSpeed > maxSpeed)
98 				{
99 					nowSpeed = minSpeed;
100 					outputAcceleration = 0.0;
101 				}
102 
103 				if (IsConstant)
104 				{
105 					nowSpeed = startSpeed;
106 					outputAcceleration = Math.Sign(endSpeed - startSpeed) * acceleration;
107 				}
108 			}
109 			else
110 			{
111 				if (nowSpeed < minSpeed || nowSpeed > maxSpeed)
112 				{
113 					StopSimulation();
114 					return;
115 				}
116 			}
117 
118 			Simulation.TrainManager.TrainManager.PlayerTrain.Car.CurrentSpeed = Simulation.TrainManager.TrainManager.PlayerTrain.Car.Specs.PerceivedSpeed = nowSpeed / 3.6;
119 			Simulation.TrainManager.TrainManager.PlayerTrain.Car.Specs.Acceleration = outputAcceleration / 3.6;
120 
121 			Simulation.TrainManager.TrainManager.PlayerTrain.Car.UpdateRunSounds(deltaTime, RunIndex);
122 
123 			Simulation.TrainManager.TrainManager.PlayerTrain.Car.UpdateMotorSounds(IsPlayTrack1, IsPlayTrack2);
124 
125 			Program.SoundApi.Update(deltaTime, SoundModels.Inverse);
126 
127 			oldElapsedTime = nowElapsedTime;
128 
129 			DrawSimulation();
130 		}
131 
DrawSimulation()132 		internal void DrawSimulation()
133 		{
134 			double rangeVelocity = MaxVelocity - MinVelocity;
135 
136 			if (StartSpeed <= EndSpeed)
137 			{
138 				if (nowSpeed < MinVelocity || nowSpeed > MaxVelocity)
139 				{
140 					minVelocity = 10.0 * Math.Round(0.1 * nowSpeed);
141 
142 					if (MinVelocity < 0.0)
143 					{
144 						minVelocity = 0.0;
145 					}
146 
147 					maxVelocity = MinVelocity + rangeVelocity;
148 
149 					OnPropertyChanged(new PropertyChangedEventArgs(nameof(MinVelocity)));
150 					OnPropertyChanged(new PropertyChangedEventArgs(nameof(MaxVelocity)));
151 
152 					return;
153 				}
154 			}
155 			else
156 			{
157 				if (nowSpeed < MinVelocity || nowSpeed > MaxVelocity)
158 				{
159 					maxVelocity = 10.0 * Math.Round(0.1 * nowSpeed);
160 
161 					if (MaxVelocity < rangeVelocity)
162 					{
163 						maxVelocity = rangeVelocity;
164 					}
165 
166 					minVelocity = MaxVelocity - rangeVelocity;
167 
168 					OnPropertyChanged(new PropertyChangedEventArgs(nameof(MinVelocity)));
169 					OnPropertyChanged(new PropertyChangedEventArgs(nameof(MaxVelocity)));
170 
171 					return;
172 				}
173 			}
174 
175 			IsRefreshGlControl = true;
176 		}
177 
DisposeCar()178 		private void DisposeCar()
179 		{
180 			if (Simulation.TrainManager.TrainManager.PlayerTrain != null)
181 			{
182 				Simulation.TrainManager.TrainManager.PlayerTrain.Dispose();
183 				Simulation.TrainManager.TrainManager.PlayerTrain = null;
184 			}
185 		}
186 	}
187 }
188