Skip to content

Commit ec70fbe

Browse files
authored
New: Implement sprung handle types (#755)
* Change: Allow DriverCar to be specified via XML * New: Implement sprung brake handles via XML * New: Implement maximum sprung notch, refactor slightly * New: Implement handle spring types * New: Implement for power handles, move some bits around * Implement handle spring any key reset
1 parent fac2f76 commit ec70fbe

15 files changed

Lines changed: 331 additions & 48 deletions

source/CarXMLConvertor/Convert.ExtensionsCfg.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,8 @@ internal static void GenerateCarXML(ref TabbedList newLines, int i)
449449
newLines.Add("<ReadhesionDevice>NotFitted</ReadhesionDevice>");
450450
break;
451451
}
452+
newLines.Add("<Power>");
453+
newLines.Add("<Notches>" + ConvertTrainDat.PowerNotches + "</Notches>");
452454
newLines.Add("<AccelerationCurves>");
453455
foreach (ConvertTrainDat.AccelerationCurve curve in ConvertTrainDat.AccelerationCurves)
454456
{
@@ -461,6 +463,7 @@ internal static void GenerateCarXML(ref TabbedList newLines, int i)
461463
newLines.Add("</OpenBVE>");
462464
}
463465
newLines.Add("</AccelerationCurves>");
466+
newLines.Add("</Power>");
464467
}
465468
else
466469
{
@@ -518,6 +521,12 @@ internal static void GenerateCarXML(ref TabbedList newLines, int i)
518521
}
519522
}
520523
newLines.Add("<Brake>");
524+
if (i == ConvertTrainDat.DriverCar)
525+
{
526+
newLines.Add("<Handle>");
527+
newLines.Add("<Notches>" + ConvertTrainDat.BrakeNotches + "</Notches>");
528+
newLines.Add("</Handle>");
529+
}
521530
if (ConvertTrainDat.MotorCars[i])
522531
{
523532

@@ -604,6 +613,7 @@ internal static void GenerateDefaultXML()
604613
newLines.Add("<RearAxle>" + -(0.4 * ConvertTrainDat.CarLength) + "</RearAxle>");
605614
newLines.Add("</Car>");
606615
}
616+
newLines.Add("<DriverCar>" + ConvertTrainDat.DriverCar + "</DriverCar>");
607617
string pluginFile = ConvertAts.DllPath(System.IO.Path.GetDirectoryName(FileName));
608618
if (!string.IsNullOrEmpty(pluginFile))
609619
{

source/CarXMLConvertor/Convert.TrainDat.cs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ class ConvertTrainDat
3131
internal static int ReadhesionDeviceType = 0;
3232
internal static double DoorWidth = 1000.0;
3333
internal static double DoorTolerance = 0.0;
34+
internal static int PowerNotches = 0;
35+
internal static int BrakeNotches = 0;
3436
private static MainForm mainForm;
3537
internal static List<AccelerationCurve> AccelerationCurves = new List<AccelerationCurve>();
3638

@@ -281,6 +283,32 @@ internal static void Process(MainForm form)
281283
} i++; n++;
282284
AccelerationCurves.Add(curve);
283285
} i--; break;
286+
case "#handle":
287+
i++;
288+
while (i < Lines.Length && !Lines[i].StartsWith("#", StringComparison.Ordinal))
289+
{
290+
double a; if (NumberFormats.TryParseDoubleVb6(Lines[i], out a))
291+
{
292+
switch (n)
293+
{
294+
case 1:
295+
if (a > 0)
296+
{
297+
PowerNotches = (int)a;
298+
}
299+
break;
300+
case 2:
301+
if (a > 0)
302+
{
303+
BrakeNotches = (int)a;
304+
}
305+
break;
306+
}
307+
}
308+
i++; n++;
309+
}
310+
i--;
311+
break;
284312
default:
285313
{
286314
i++;

source/OpenBVE/System/Input/Keyboard.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using LibRender2.Screens;
33
using OpenTK.Input;
44
using OpenBveApi.Interface;
5+
using TrainManager.Handles;
56

67
namespace OpenBve
78
{
@@ -62,6 +63,10 @@ internal static void keyDownEvent(object sender, KeyboardKeyEventArgs e)
6263
}
6364
}
6465
}
66+
// Attempt to reset handle spring
67+
TrainManager.PlayerTrain.Handles.Power.ResetSpring();
68+
TrainManager.PlayerTrain.Handles.Brake.ResetSpring();
69+
6570
BlockKeyRepeat = false;
6671
//Remember to reset the keyboard modifier after we're done, else it repeats.....
6772
CurrentKeyboardModifier = KeyboardModifier.None;
@@ -102,6 +107,10 @@ internal static void keyUpEvent(object sender, KeyboardKeyEventArgs e)
102107
}
103108
}
104109
}
110+
111+
// Attempt to reset handle spring
112+
TrainManager.PlayerTrain.Handles.Power.ResetSpring();
113+
TrainManager.PlayerTrain.Handles.Brake.ResetSpring();
105114
BlockKeyRepeat = false;
106115
}
107116
}

source/OpenBVE/System/MainLoop.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,9 @@ internal static void ProcessKeyboard()
359359
switch (Interface.CurrentControls[i].Component)
360360
{
361361
case JoystickComponent.Axis:
362+
// Assume that a joystick axis fulfills the criteria for the handle to be 'held' in place
363+
TrainManager.PlayerTrain.Handles.Power.ResetSpring();
364+
TrainManager.PlayerTrain.Handles.Brake.ResetSpring();
362365
var axisState = Program.Joysticks.GetAxis(currentDevice, Interface.CurrentControls[i].Element);
363366
if (axisState.ToString(CultureInfo.InvariantCulture) != Interface.CurrentControls[i].LastState)
364367
{
@@ -444,6 +447,9 @@ internal static void ProcessKeyboard()
444447
//Test whether the state is the same as the last frame
445448
if (buttonState.ToString() != Interface.CurrentControls[i].LastState)
446449
{
450+
// Attempt to reset handle spring
451+
TrainManager.PlayerTrain.Handles.Power.ResetSpring();
452+
TrainManager.PlayerTrain.Handles.Brake.ResetSpring();
447453
if (buttonState == ButtonState.Pressed)
448454
{
449455
Interface.CurrentControls[i].AnalogState = 1.0;
@@ -466,6 +472,9 @@ internal static void ProcessKeyboard()
466472
//Test if the state is the same as last frame
467473
if (hatState.ToString() != Interface.CurrentControls[i].LastState)
468474
{
475+
// Attempt to reset handle spring
476+
TrainManager.PlayerTrain.Handles.Power.ResetSpring();
477+
TrainManager.PlayerTrain.Handles.Brake.ResetSpring();
469478
if ((int)hatState == Interface.CurrentControls[i].Direction)
470479
{
471480
Interface.CurrentControls[i].AnalogState = 1.0;

source/Plugins/Train.OpenBve/Train.OpenBve.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,11 @@
5757
<Compile Include="Train\BVE\ExtensionsCfgParser.cs" />
5858
<Compile Include="Train\BVE\TrainDatParser.cs" />
5959
<Compile Include="Train\BVE\TrainDatparser.Formats.cs" />
60+
<Compile Include="Train\XML\TrainXmlParser.AccelerationNode.cs" />
6061
<Compile Include="Train\XML\TrainXmlParser.BrakeNode.cs" />
6162
<Compile Include="Train\XML\TrainXmlParser.CarNode.cs" />
6263
<Compile Include="Train\XML\TrainXmlParser.cs" />
64+
<Compile Include="Train\XML\TrainXmlParser.HandleNode.cs" />
6365
</ItemGroup>
6466
<ItemGroup>
6567
<ProjectReference Include="..\..\LibRender2\LibRender2.csproj">
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
using System.Xml;
4+
using OpenBveApi.Interface;
5+
using OpenBveApi.Math;
6+
using TrainManager.Power;
7+
8+
namespace Train.OpenBve
9+
{
10+
partial class TrainXmlParser
11+
{
12+
private AccelerationCurve[] ParseAccelerationNode(XmlNode c, string fileName)
13+
{
14+
if (c.ChildNodes.OfType<XmlElement>().Any())
15+
{
16+
List<AccelerationCurve> accelerationCurves = new List<AccelerationCurve>();
17+
foreach (XmlNode cc in c.ChildNodes)
18+
{
19+
switch (cc.Name.ToLowerInvariant())
20+
{
21+
case "openbve": // don't support legacy BVE2 curves in XML, but at the same time specify that this is deliberately BVE4 / OpenBVE format
22+
BveAccelerationCurve curve = new BveAccelerationCurve();
23+
foreach (XmlNode sc in cc.ChildNodes)
24+
{
25+
switch (sc.Name.ToLowerInvariant())
26+
{
27+
case "stagezeroacceleration":
28+
if (!NumberFormats.TryParseDoubleVb6(sc.InnerText, out curve.StageZeroAcceleration))
29+
{
30+
Plugin.currentHost.AddMessage(MessageType.Warning, false, "Stage zero acceleration was invalid for curve " + accelerationCurves.Count + " in XML file " + fileName);
31+
}
32+
33+
curve.StageZeroAcceleration *= 0.277777777777778;
34+
break;
35+
case "stageoneacceleration":
36+
if (!NumberFormats.TryParseDoubleVb6(sc.InnerText, out curve.StageOneAcceleration))
37+
{
38+
Plugin.currentHost.AddMessage(MessageType.Warning, false, "Stage one acceleration was invalid for curve " + accelerationCurves.Count + " in XML file " + fileName);
39+
}
40+
41+
curve.StageOneAcceleration *= 0.277777777777778;
42+
break;
43+
case "stageonespeed":
44+
if (!NumberFormats.TryParseDoubleVb6(sc.InnerText, out curve.StageOneSpeed))
45+
{
46+
Plugin.currentHost.AddMessage(MessageType.Warning, false, "Stage one speed was invalid for curve " + accelerationCurves.Count + " in XML file " + fileName);
47+
}
48+
49+
curve.StageOneSpeed *= 0.277777777777778;
50+
break;
51+
case "stagetwospeed":
52+
if (!NumberFormats.TryParseDoubleVb6(sc.InnerText, out curve.StageTwoSpeed))
53+
{
54+
Plugin.currentHost.AddMessage(MessageType.Warning, false, "Stage two speed was invalid for curve " + accelerationCurves.Count + " in XML file " + fileName);
55+
}
56+
57+
curve.StageTwoSpeed *= 0.277777777777778;
58+
break;
59+
case "stagetwoexponent":
60+
if (!NumberFormats.TryParseDoubleVb6(sc.InnerText, out curve.StageTwoExponent))
61+
{
62+
Plugin.currentHost.AddMessage(MessageType.Warning, false, "Stage two exponent was invalid for curve " + accelerationCurves.Count + " in XML file " + fileName);
63+
}
64+
65+
break;
66+
}
67+
}
68+
accelerationCurves.Add(curve);
69+
break;
70+
}
71+
}
72+
return accelerationCurves.ToArray();
73+
}
74+
Plugin.currentHost.AddMessage(MessageType.Warning, false, "An empty list of acceleration curves was provided in XML file " + fileName);
75+
return new AccelerationCurve[] { };
76+
}
77+
}
78+
}

source/Plugins/Train.OpenBve/Train/XML/TrainXmlParser.BrakeNode.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Linq;
1+
using System;
2+
using System.Linq;
23
using System.Xml;
34
using OpenBveApi.Interface;
45
using OpenBveApi.Math;
@@ -227,8 +228,13 @@ private void ParseBrakeNode(XmlNode Node, string fileName, int Car, ref TrainBas
227228
}
228229
}
229230
break;
231+
case "handle":
232+
ParseHandleNode(c, ref Train.Handles.Brake, Car, Train, fileName);
233+
break;
234+
230235
}
231236
}
237+
232238
Train.Cars[Car].CarBrake.mainReservoir = new MainReservoir(compressorMinimumPressure, compressorMaximumPressure, 0.01, (Train.Handles.Brake is AirBrakeHandle ? 0.25 : 0.075) / Train.Cars.Length);
233239
Train.Cars[Car].CarBrake.airCompressor = new Compressor(compressorRate, Train.Cars[Car].CarBrake.mainReservoir, Train.Cars[Car]);
234240
Train.Cars[Car].CarBrake.equalizingReservoir = new EqualizingReservoir(equalizingReservoirServiceRate, equalizingReservoirEmergencyRate, equalizingReservoirChargeRate);

source/Plugins/Train.OpenBve/Train/XML/TrainXmlParser.CarNode.cs

Lines changed: 17 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
using TrainManager.BrakeSystems;
1313
using TrainManager.Car;
1414
using TrainManager.Cargo;
15+
using TrainManager.Handles;
1516
using TrainManager.Power;
1617
using TrainManager.Trains;
1718

@@ -394,61 +395,32 @@ private void ParseCarNode(XmlNode Node, string fileName, int Car, ref TrainBase
394395
}
395396
break;
396397
case "accelerationcurves":
398+
/*
399+
* NOTE: This was initially implemented here.
400+
* It has moved to being a child-node of the power node
401+
* Retain this for the minute in case someone has actually used the thing (although the format is an ongoing WIP)....
402+
*/
397403
CopyAccelerationCurves = false;
404+
Train.Cars[Car].Specs.AccelerationCurves = ParseAccelerationNode(c, fileName);
405+
break;
406+
case "power":
398407
if (c.ChildNodes.OfType<XmlElement>().Any())
399408
{
400-
List<AccelerationCurve> accelerationCurves = new List<AccelerationCurve>();
401409
foreach (XmlNode cc in c.ChildNodes)
402410
{
403411
switch (cc.Name.ToLowerInvariant())
404412
{
405-
case "openbve": // don't support legacy BVE2 curves in XML, but at the same time specify that this is deliberately BVE4 / OpenBVE format
406-
BveAccelerationCurve curve = new BveAccelerationCurve();
407-
foreach (XmlNode sc in cc.ChildNodes)
408-
{
409-
switch (sc.Name.ToLowerInvariant())
410-
{
411-
case "stagezeroacceleration":
412-
if (!NumberFormats.TryParseDoubleVb6(sc.InnerText, out curve.StageZeroAcceleration))
413-
{
414-
Plugin.currentHost.AddMessage(MessageType.Warning, false, "Stage zero acceleration was invalid for curve " + accelerationCurves.Count + " in XML file " + fileName);
415-
}
416-
curve.StageZeroAcceleration *= 0.277777777777778;
417-
break;
418-
case "stageoneacceleration":
419-
if (!NumberFormats.TryParseDoubleVb6(sc.InnerText, out curve.StageOneAcceleration))
420-
{
421-
Plugin.currentHost.AddMessage(MessageType.Warning, false, "Stage one acceleration was invalid for curve " + accelerationCurves.Count + " in XML file " + fileName);
422-
}
423-
curve.StageOneAcceleration *= 0.277777777777778;
424-
break;
425-
case "stageonespeed":
426-
if (!NumberFormats.TryParseDoubleVb6(sc.InnerText, out curve.StageOneSpeed))
427-
{
428-
Plugin.currentHost.AddMessage(MessageType.Warning, false, "Stage one speed was invalid for curve " + accelerationCurves.Count + " in XML file " + fileName);
429-
}
430-
curve.StageOneSpeed *= 0.277777777777778;
431-
break;
432-
case "stagetwospeed":
433-
if (!NumberFormats.TryParseDoubleVb6(sc.InnerText, out curve.StageTwoSpeed))
434-
{
435-
Plugin.currentHost.AddMessage(MessageType.Warning, false, "Stage two speed was invalid for curve " + accelerationCurves.Count + " in XML file " + fileName);
436-
}
437-
curve.StageTwoSpeed *= 0.277777777777778;
438-
break;
439-
case "stagetwoexponent":
440-
if (!NumberFormats.TryParseDoubleVb6(sc.InnerText, out curve.StageTwoExponent))
441-
{
442-
Plugin.currentHost.AddMessage(MessageType.Warning, false, "Stage two exponent was invalid for curve " + accelerationCurves.Count + " in XML file " + fileName);
443-
}
444-
break;
445-
}
446-
}
447-
accelerationCurves.Add(curve);
413+
case "handle":
414+
AbstractHandle p = Train.Handles.Power; // yuck, but we can't store this as the base type due to constraints elsewhere
415+
ParseHandleNode(cc, ref p, Car, Train, fileName);
416+
break;
417+
case "accelerationcurves":
418+
CopyAccelerationCurves = false;
419+
Train.Cars[Car].Specs.AccelerationCurves = ParseAccelerationNode(c, fileName);
448420
break;
449421
}
450422
}
451-
Train.Cars[Car].Specs.AccelerationCurves = accelerationCurves.ToArray();
423+
452424
}
453425
break;
454426
case "doors":

0 commit comments

Comments
 (0)