Skip to content

Commit f6d3e76

Browse files
committed
Initial support for external controllers using the Web Server
1 parent 44fa8ad commit f6d3e76

File tree

7 files changed

+296
-150
lines changed

7 files changed

+296
-150
lines changed

Source/RunActivity/Viewer3D/RollingStock/MSTSLocomotiveViewer.cs

Lines changed: 42 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -234,48 +234,61 @@ public override void HandleUserInput(ElapsedTime elapsedTime)
234234
if (UserInput.IsPressed(UserCommand.DebugResetWheelSlip)) { Locomotive.Train.SignalEvent(Event._ResetWheelSlip); }
235235
if (UserInput.IsPressed(UserCommand.DebugToggleAdvancedAdhesion)) { Locomotive.Train.SignalEvent(Event._ResetWheelSlip); Locomotive.Simulator.UseAdvancedAdhesion = !Locomotive.Simulator.UseAdvancedAdhesion; }
236236

237-
if (UserInput.RDState != null)
238-
{
239-
if (UserInput.RDState.BailOff)
240-
{
241-
Locomotive.SetBailOff(true);
242-
}
243-
if (UserInput.RDState.Changed)
244-
{
245-
Locomotive.AlerterReset();
246-
247-
Locomotive.SetThrottlePercentWithSound(UserInput.RDState.ThrottlePercent);
248-
Locomotive.SetTrainBrakePercent(UserInput.RDState.TrainBrakePercent);
249-
Locomotive.SetEngineBrakePercent(UserInput.RDState.EngineBrakePercent);
250-
// Locomotive.SetBrakemanBrakePercent(UserInput.RDState.BrakemanBrakePercent); // For Raildriver control not complete for this value?
251-
if (Locomotive.CombinedControlType != MSTSLocomotive.CombinedControl.ThrottleAir)
252-
Locomotive.SetDynamicBrakePercentWithSound(UserInput.RDState.DynamicBrakePercent);
253-
if (UserInput.RDState.DirectionPercent > 50)
237+
ExternalDeviceState[] externalDevices = {UserInput.RDState, UserInput.WebDeviceState};
238+
foreach (var external in externalDevices)
239+
{
240+
if (external == null) continue;
241+
if (external.Throttle.Changed)
242+
Locomotive.SetThrottlePercentWithSound(external.Throttle.Value * 100);
243+
if (external.TrainBrake.Changed)
244+
Locomotive.SetTrainBrakePercent(external.TrainBrake.Value * 100);
245+
if (external.EngineBrake.Changed)
246+
Locomotive.SetEngineBrakePercent(external.EngineBrake.Value * 100);
247+
// Locomotive.SetBrakemanBrakePercent(external.BrakemanBrakePercent); // For Raildriver control not complete for this value?
248+
if (external.DynamicBrake.Changed && Locomotive.CombinedControlType != MSTSLocomotive.CombinedControl.ThrottleAir)
249+
Locomotive.SetDynamicBrakePercentWithSound(external.DynamicBrake.Value * 100);
250+
251+
if (external.Direction.Changed)
252+
{
253+
if (Locomotive is MSTSSteamLocomotive steam)
254+
{
255+
steam.SetCutoffPercent(UserInput.RDState.Direction.Value * 100);
256+
}
257+
else if (external.Direction.Value > 0.5f)
254258
Locomotive.SetDirection(Direction.Forward);
255-
else if (UserInput.RDState.DirectionPercent < -50)
259+
else if (external.Direction.Value < -0.5f)
256260
Locomotive.SetDirection(Direction.Reverse);
257261
else
258262
Locomotive.SetDirection(Direction.N);
259-
if (UserInput.RDState.Emergency)
260-
new EmergencyPushButtonCommand(Viewer.Log, true);
261-
else
262-
new EmergencyPushButtonCommand(Viewer.Log, false);
263-
if (UserInput.RDState.Wipers == 1 && Locomotive.Wiper)
264-
Locomotive.SignalEvent(Event.WiperOff);
265-
if (UserInput.RDState.Wipers != 1 && !Locomotive.Wiper)
266-
Locomotive.SignalEvent(Event.WiperOn);
263+
}
264+
265+
if (external.Lights.Changed)
266+
{
267267
// changing Headlight more than one step at a time doesn't work for some reason
268-
if (Locomotive.Headlight < UserInput.RDState.Lights - 1)
268+
if (Locomotive.Headlight < external.Lights.Value - 1)
269269
{
270270
Locomotive.Headlight++;
271271
Locomotive.SignalEvent(Event.LightSwitchToggle);
272272
}
273-
if (Locomotive.Headlight > UserInput.RDState.Lights - 1)
273+
if (Locomotive.Headlight > external.Lights.Value - 1)
274274
{
275275
Locomotive.Headlight--;
276276
Locomotive.SignalEvent(Event.LightSwitchToggle);
277277
}
278278
}
279+
// Handle other cabcontrols
280+
foreach (var kvp in external.CabControls)
281+
{
282+
if (_CabRenderer == null) break;
283+
if (!kvp.Value.Changed) continue;
284+
if (_CabRenderer.ControlMap.TryGetValue(kvp.Key, out var renderer) && renderer is CabViewDiscreteRenderer discrete)
285+
{
286+
var oldChanged = discrete.ChangedValue;
287+
discrete.ChangedValue = (val) => kvp.Value.Value;
288+
discrete.HandleUserInput();
289+
discrete.ChangedValue = oldChanged;
290+
}
291+
}
279292
}
280293

281294
foreach (var command in UserInputCommands.Keys)
@@ -1973,7 +1986,7 @@ public class CabViewDiscreteRenderer : CabViewControlRenderer, ICabViewMouseCont
19731986
/// <summary>
19741987
/// Function calculating response value for mouse events (movement, left-click), determined by configured style.
19751988
/// </summary>
1976-
readonly Func<float, float> ChangedValue;
1989+
public Func<float, float> ChangedValue;
19771990

19781991
public CabViewDiscreteRenderer(Viewer viewer, MSTSLocomotive locomotive, CVCWithFrames control, CabShader shader)
19791992
: base(viewer, locomotive, control, shader)

Source/RunActivity/Viewer3D/RollingStock/MSTSSteamLocomotiveViewer.cs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -184,9 +184,6 @@ public override void HandleUserInput(ElapsedTime elapsedTime)
184184
// Keeping separated, since it is not a real engine control. (Probably wrong classification?)
185185
if (UserInput.IsPressed(UserCommand.ControlAIFireReset)) new AIFireResetCommand(Viewer.Log);
186186

187-
if (UserInput.RDState != null && UserInput.RDState.Changed)
188-
SteamLocomotive.SetCutoffPercent(UserInput.RDState.DirectionPercent);
189-
190187
base.HandleUserInput(elapsedTime);
191188

192189
#if DEBUG_DUMP_STEAM_POWER_CURVE

Source/RunActivity/Viewer3D/UserInput.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ public static class UserInput
4949
static bool MouseButtonsSwapped;
5050
public static int MouseSpeedX;
5151
public static int MouseSpeedY;
52-
5352
public static RailDriverState RDState;
53+
public static ExternalDeviceState WebDeviceState = new ExternalDeviceState();
5454

5555
static InputSettings InputSettings;
5656

@@ -136,8 +136,8 @@ static Keys[] GetKeysWithPrintScreenFix(KeyboardState keyboardState)
136136

137137
public static void Handled()
138138
{
139-
if (RDState != null)
140-
RDState.Handled();
139+
RDState?.Handled();
140+
WebDeviceState?.Handled();
141141
}
142142

143143
public static bool IsPressed(UserCommand command)
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
// COPYRIGHT 2022 by the Open Rails project.
2+
//
3+
// This file is part of Open Rails.
4+
//
5+
// Open Rails is free software: you can redistribute it and/or modify
6+
// it under the terms of the GNU General Public License as published by
7+
// the Free Software Foundation, either version 3 of the License, or
8+
// (at your option) any later version.
9+
//
10+
// Open Rails is distributed in the hope that it will be useful,
11+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
// GNU General Public License for more details.
14+
//
15+
// You should have received a copy of the GNU General Public License
16+
// along with Open Rails. If not, see <http://www.gnu.org/licenses/>.
17+
18+
using System;
19+
using System.Collections.Generic;
20+
using Orts.Formats.Msts;
21+
using Orts.Simulation.RollingStocks;
22+
using ORTS.Common;
23+
using ORTS.Common.Input;
24+
25+
namespace Orts.Viewer3D
26+
{
27+
/// <summary>
28+
/// Processed external device data sent to UserInput class
29+
/// </summary>
30+
public class ExternalDeviceState
31+
{
32+
public ExternalDeviceCabControl Direction = new ExternalDeviceCabControl(); // -100 (reverse) to 100 (forward)
33+
public ExternalDeviceCabControl Throttle = new ExternalDeviceCabControl(); // 0 to 100
34+
public ExternalDeviceCabControl DynamicBrake = new ExternalDeviceCabControl(); // 0 to 100 if active otherwise less than 0
35+
public ExternalDeviceCabControl TrainBrake = new ExternalDeviceCabControl(); // 0 (release) to 100 (CS), does not include emergency
36+
public ExternalDeviceCabControl EngineBrake = new ExternalDeviceCabControl(); // 0 to 100
37+
public ExternalDeviceCabControl Lights = new ExternalDeviceCabControl(); // lights rotary, 1 off, 2 dim, 3 full
38+
public Dictionary<(CabViewControlType,int), ExternalDeviceCabControl> CabControls;
39+
public Dictionary<UserCommand, ExternalDeviceButton> Buttons;
40+
public ExternalDeviceState()
41+
{
42+
Buttons = new Dictionary<UserCommand, ExternalDeviceButton>();
43+
CabControls = new Dictionary<(CabViewControlType,int), ExternalDeviceCabControl>();
44+
}
45+
46+
public virtual void Handled()
47+
{
48+
Direction.Changed = false;
49+
Throttle.Changed = false;
50+
DynamicBrake.Changed = false;
51+
TrainBrake.Changed = false;
52+
EngineBrake.Changed = false;
53+
Lights.Changed = false;
54+
foreach (var button in Buttons.Values)
55+
{
56+
button.Changed = false;
57+
}
58+
foreach (var control in CabControls.Values)
59+
{
60+
control.Changed = false;
61+
}
62+
}
63+
64+
public bool IsPressed(UserCommand command)
65+
{
66+
return Buttons.TryGetValue(command, out var button) && button.IsPressed;
67+
}
68+
69+
public bool IsReleased(UserCommand command)
70+
{
71+
return Buttons.TryGetValue(command, out var button) && button.IsReleased;
72+
}
73+
74+
public bool IsDown(UserCommand command)
75+
{
76+
return Buttons.TryGetValue(command, out var button) && button.IsDown;
77+
}
78+
}
79+
public class ExternalDeviceButton
80+
{
81+
bool isDown;
82+
public bool IsDown
83+
{
84+
get
85+
{
86+
return isDown;
87+
}
88+
set
89+
{
90+
if (isDown != value)
91+
{
92+
isDown = value;
93+
Changed = true;
94+
}
95+
}
96+
}
97+
public bool IsPressed { get { return IsDown && Changed; } }
98+
public bool IsReleased { get { return !IsDown && Changed; } }
99+
public bool Changed;
100+
}
101+
public class ExternalDeviceCabControl
102+
{
103+
float value;
104+
public bool Changed;
105+
public float Value
106+
{
107+
get
108+
{
109+
return value;
110+
}
111+
set
112+
{
113+
if (this.value != value)
114+
{
115+
this.value = value;
116+
Changed = true;
117+
}
118+
}
119+
}
120+
}
121+
}

0 commit comments

Comments
 (0)