1 using OpenBveApi;
2 using OpenBveApi.Math;
3 using SoundManager;
4 using TrainManager.Car;
5 
6 namespace TrainManager.Trains
7 {
8 	/// <summary>Represents a horn or whistle</summary>
9 	public class Horn
10 	{
11 		/// <summary>The sound source for this horn</summary>
12 		public SoundSource Source;
13 		/// <summary>The sound buffer to be played once when playback commences</summary>
14 		public SoundBuffer StartSound;
15 		/// <summary>The loop sound</summary>
16 		public SoundBuffer LoopSound;
17 		/// <summary>The sound buffer to be played once when playback ends</summary>
18 		public SoundBuffer EndSound;
19 		/// <summary>The position of the sound within the train car</summary>
20 		public Vector3 SoundPosition;
21 		/// <summary>Whether this horn has start and end sounds, or uses the legacy loop/ stretch method</summary>
22 		public bool StartEndSounds;
23 		/// <summary>Stores whether the sound is looped or stretched when using the legacy method</summary>
24 		public bool Loop;
25 		/// <summary>Stores the loop state</summary>
26 		private bool LoopStarted;
27 		/// <summary>Holds a reference to the base car</summary>
28 		public readonly CarBase baseCar;
29 
30 		/// <summary>The default constructor</summary>
Horn(CarBase car)31 		public Horn(CarBase car)
32 		{
33 			this.StartSound = null;
34 			this.LoopSound = null;
35 			this.EndSound = null;
36 			this.Loop = false;
37 			this.baseCar = car;
38 		}
39 
Horn(SoundBuffer startSound, SoundBuffer loopSound, SoundBuffer endSound, bool loop, CarBase car)40 		public Horn(SoundBuffer startSound, SoundBuffer loopSound, SoundBuffer endSound, bool loop, CarBase car)
41 		{
42 			this.Source = null;
43 			this.StartSound = startSound;
44 			this.LoopSound = loopSound;
45 			this.EndSound = endSound;
46 			this.Loop = loop;
47 			this.StartEndSounds = false;
48 			this.LoopStarted = false;
49 			this.SoundPosition = new Vector3();
50 			this.baseCar = car;
51 		}
52 
53 		/// <summary>Called by the controls loop to start playback of this horn</summary>
Play()54 		public void Play()
55 		{
56 			if (TrainManagerBase.currentHost.SimulationState == SimulationState.MinimalisticSimulation)
57 			{
58 				return;
59 			}
60 
61 			if (StartEndSounds)
62 			{
63 				//New style three-part sounds
64 				if (LoopStarted == false)
65 				{
66 					if (!TrainManagerBase.currentHost.SoundIsPlaying(Source))
67 					{
68 						if (StartSound != null)
69 						{
70 							//The start sound is not currently playing, so start it
71 							Source = (SoundSource)TrainManagerBase.currentHost.PlaySound(StartSound, 1.0, 1.0, SoundPosition, baseCar, false);
72 
73 							//Set the loop control variable to started
74 							LoopStarted = true;
75 						}
76 						else
77 						{
78 							if (LoopSound != null)
79 							{
80 								Source = (SoundSource)TrainManagerBase.currentHost.PlaySound(LoopSound, 1.0, 1.0, SoundPosition, baseCar, true);
81 							}
82 						}
83 					}
84 				}
85 				else
86 				{
87 					if (!TrainManagerBase.currentHost.SoundIsPlaying(Source) && LoopSound != null)
88 					{
89 						//Start our loop sound playing if the start sound is finished
90 						Source = (SoundSource)TrainManagerBase.currentHost.PlaySound(LoopSound, 1.0, 1.0, SoundPosition, baseCar, true);
91 					}
92 				}
93 			}
94 			else
95 			{
96 				//Original single part sounds
97 				if (LoopSound != null)
98 				{
99 					//Loop is ONLY true if this is a Music Horn
100 					if (Loop)
101 					{
102 						if (!TrainManagerBase.currentHost.SoundIsPlaying(Source) && !LoopStarted)
103 						{
104 							//On the first keydown event, start the sound source playing and trigger the loop control variable
105 							Source = (SoundSource)TrainManagerBase.currentHost.PlaySound(LoopSound, 1.0, 1.0, SoundPosition,
106 								baseCar, true);
107 							LoopStarted = true;
108 						}
109 						else
110 						{
111 							if (!LoopStarted)
112 							{
113 								//Our loop control variable is reset by the keyup event so this code will only trigger on the
114 								//second keydown meaning our horn toggles
115 								TrainManagerBase.currentHost.StopSound(Source);
116 								LoopStarted = true;
117 							}
118 						}
119 					}
120 					else
121 					{
122 						if (!LoopStarted)
123 						{
124 							Source = (SoundSource)TrainManagerBase.currentHost.PlaySound(LoopSound, 1.0, 1.0, SoundPosition, baseCar, false);
125 						}
126 
127 						LoopStarted = true;
128 					}
129 				}
130 			}
131 
132 		}
133 
134 		/// <summary>Called by the controls loop to stop playback of this horn</summary>
Stop()135 		public void Stop()
136 		{
137 			//Reset loop control variable
138 			LoopStarted = false;
139 			if (!StartEndSounds & !Loop)
140 			{
141 				//Don't stop horns which are play-once single part sounds
142 				return;
143 			}
144 
145 			if (!StartEndSounds & Loop)
146 			{
147 				//This sound is a toggle music horn sound
148 				return;
149 			}
150 
151 			if (TrainManagerBase.currentHost.SoundIsPlaying(Source))
152 			{
153 				//Stop the loop sound playing
154 				TrainManagerBase.currentHost.StopSound(Source);
155 			}
156 
157 			if (StartEndSounds && !TrainManagerBase.currentHost.SoundIsPlaying(Source) && EndSound != null)
158 			{
159 				//If our end sound is defined and in use, play once
160 				Source =(SoundSource)TrainManagerBase.currentHost.PlaySound(EndSound, 1.0, 1.0, SoundPosition, baseCar, false);
161 			}
162 		}
163 	}
164 }
165