OpenBVE
OpenBVE copied to clipboard
New: Running on other Rails (WIP)
This is a followup to #326 , and introduces the ability for the player's train to run on other rails within the world.
Heavily WIP.
Current Usage:
Track.Switch firstRail; secondRail; initialSetting Creates a standard facing switch.
- FirstRail : The rail the switch is placed on.
- secondRail : The rail that may be switched to.
- initialSetting : The initial setting for the switch.
- switchName: The display name for the switch in the menu etc. (e.g. Yard Entry)
Track.SwitchT firstRail; secondRail; initialSetting Creates a trailing switch.
- FirstRail : The rail the switch is placed on.
- secondRail : The rail that is joined to.
- initialSetting : The initial setting for the switch. Note: To set the trailing switch to start in a position where we can run through it, this must be set to the rail which it is placed upon.
- switchName: The display name for the switch in the menu etc. (e.g. Yard Entry)
Flaws:
N.B. These will change, just need the correct code implementing & thinking about.
- ~~Only works for branching switches.~~
- ~~No direction detection.~~
- ~~Running past a .RailEnd command is likely to crash.~~
- 3 way & greater switches not supported by the current command structure. Need to think about how we could structure this.....
- ~~Needs a way to change switches. (Leverage #317 to highlight the switch?)~~
- ~~Needs sprung return points adding (simples....)~~
- Point sound events are not generated at the minute on other tracks.
To Test:
- Check all combinations.
- Check for conflicts with #326
The current test route (Highly stripped down version of Odaykufan's test route):
With Route
With Train
.Folder(cl104)
.Run(0) 0,
.Run(1) 0,
.Run(2) 0,
With Options
.ObjectVisibility(1)
With Structure
.Ground(0).Load(OdakyufanAtsTestRoute\Grass.csv)
.Rail(0).Load(OdakyufanAtsTestRoute\Rail.csv)
.Rail(1).Load(OdakyufanAtsTestRoute\Rail_L_329.csv)
.Rail(2).Load(OdakyufanAtsTestRoute\Rail_R_329.csv)
.freeobj(45).Load(OdakyufanAtsTestRoute\Grass.csv)
With Texture.Background(1)
.Load(OdakyufanAtsTestRoute\Background.png)
.Aspect(1)
With
With Track
0
.Height(0.5)
.Sta(Station A; 09.5955; 10.01)
25
.Stop(1)
250
.Railstart(1;0;0;0)
275
.Switch(0;1;1)
300
.rail(1;4;0;0;-200)
325
.rail(1;8;0;0;-200)
500
.railend(1)
2100
.Sta(Station B; 10.0300; 10.0330)
2245
.Stop(1)
2275
This will switch the player's train onto Rail 1 at 275m, and correctly derail it at 500m when the track ends. Next step will be to add and test 2 more switches so that Rail 1 can continue into a siding, whilst we turn back to Rail 0. Once this is complete and tested to work with no glitches, I'll think about reversing over switches so we can run backwards over Rail 0 to complete the loop.
This test route implements a switched passing loop, changing first to rail 1, then to rail 2, before finally back to the first rail.
Reversing through the switches also works correctly now. (N.B. Needs the three commits on the master branch from today, but these aren't directly relevant to the switch logic, more to multiple rails)
With Route
With Train
.Folder(cl104)
.Run(0) 0,
.Run(1) 0,
.Run(2) 0,
With Options
.ObjectVisibility(1)
With Structure
.Ground(0).Load(OdakyufanAtsTestRoute\Grass.csv)
.Rail(0).Load(OdakyufanAtsTestRoute\Rail.csv)
.Rail(1).Load(OdakyufanAtsTestRoute\Rail_L_329.csv)
.Rail(2).Load(OdakyufanAtsTestRoute\Rail_R_329.csv)
.freeobj(45).Load(OdakyufanAtsTestRoute\Grass.csv)
With Texture.Background(1)
.Load(OdakyufanAtsTestRoute\Background.png)
.Aspect(1)
With
With Track
0
.Height(0.5)
.Sta(Station A; 09.5955; 10.01)
25
.Stop(1)
250
.Railstart(1;0;0;0)
275
.Switch(0;1;1)
300
.rail(1;4;0;0;-200)
325
.rail(1;8;0;0;-200)
400
.railstart(2;8;0;0)
.switch(1;2;2)
425
.rail(2;4;0)
450
.rail(2;0;0)
.switcht(2;0;2)
475
.railend(2)
500
.railend(1)
2100
.Sta(Station B; 10.0300; 10.0330)
2245
.Stop(1)
2275
Need to finish and merge this, but shouldn't be difficult. Will look again this week.
The new imagebox menu additions should allow us to implement a nice GUI, which was the primary reason this stalled. We also need to add a final parameter to the .Switch command, to allow for a switch name.
Switch icon for overlay (scanned and edited model railway track!)
Couple of nice colored arrows to show switch direction:
Will need to deal with a full rebase before trying to get this done, but nothing has really actually changed other than a few file locations.
WRT to switch menu, should have the following:
- Picture of switch (rotated appropriately)
- Arrow overlay showing currently set direction
- Switch name
- Distance to switch
- Currently set rail (Highlight in different color if this is a trailing switch and is set to derail us) Unsure if we can get two switches (in front and behind) on a single screen, or whether we'll need two. Test when implemented.....
If the Change Switch menu key is set, this branch now functions properly, and our run-round loop above can actually be used. It's still a little clunky, but this has massive potential.
TODO:
- ~~Menu needs to refresh when a switch is changed to reflect the new setting.~~
- Implement visual switch indication into the menu, icons above.
- Add switch names and path descriptions to the routefile command.
- Add switch info to F10 debug screen.
- Add translations for new menu commands.
FLAWS:
- Derailments not yet added.
- Switches are currently calculated from the front car for both locations. This allows splitting of a switch if you're not careful, probably wants the previous switch calculating from the driver car (??)
- Route map doesn't show any other tracks, how difficult would this be to add?
- Menu layout needs thinking about / improvements somehow?
- No point sounds for switches on secondary tracks at the minute. Possibly just trigger a Point Sounds event from the switch? (think about this- could also automagically add one if none exists in the block??)
FUTURE??:
Would be interesting to see what adding an auto-generate option did, as per BRR. Could probably do something along these lines:
- If a track intersects with Rail 0 exactly (e.g. generates a point sound event), assume that this track is drivable.
- Keep a record of these, and any tracks which intersect with these then are also drivable.
- Possibly creates backwards issues, in that we'd need to read back to see what's available in reverse if we switch onto a new track?? This should be a completely separate PR though.
After some fiddling, it seems that a working map will be an absolute PITA, without some serious refactoring in the main parser. This is primarily because it skips large amounts of stuff in preview (map / gradient) generation, including oddly enough secondary track positions. Changing this requires a complete refactor in places, as it generates the track objects here too.....
https://www.youtube.com/watch?v=XuYzDc7g4yI If this is merged, I think that we will do such as this driving. If this is merged, I thought it would be possible to rotate the 3D cab and the outer view of Extensions.cfg by 180 degrees, reverse the lever sir, and reverse acceleration and deceleration, so that reverse direction drives would be possible. However, in the case of push-pull of locomotive + passenger car, I thought it might be difficult because two types of cabs are required.
Still thinking about this, and will get to it eventually :)
Things are just a little slow at the moment as I'm working too much.
Multiple interior views per car isn't actually too difficult (other than a sensible control for switching between them, and automatic switching in the case of reversals etc) The biggest issue is really only figuring out a way to fo the job once, rather than adding a small bit then re-writing it later.
A bit more work on this, on the map side of things. In-game now generates for all rails, but with no colors yet- I used blue for every secondary rail on this, along with a resonably complex route [no other drivable rails] just to make sure this worked. Probably should also generate Rail0 last to ensure that it's always visible with overlapping stuff.
We can also see that the current image resolution isn't necessarily brilliant, and may perhaps need increasing or something. Might get a bit better when all the scenic rails are removed, not sure yet :)
Preview mode isn't working (all points on the secondary rail are at the origin), will have to look into this further.....
Preview mode maps now work. From testing, it's clear that we'll need a map texture with somewhere around a 1km radius (??), probably at 1024 x 1024 as otherwise unfortunately the secondary tracks just aren't visible enough. This may be a performance issue, will have to test that.....
Secondary thought- Can we draw the map using pure GL (as opposed to the current GDI+ implementation?) Not sure without testing as to whether this is going to be faster or slower. Keeping the GDI+ version, would probably allow us to use a background thread to continually re-generate the texture, but perhaps a pure line draing GL shader would be better.
This may end up being a later addition.
1K texture for a preview i think enough, for performance i think if this preview generate a vector/svg path not a raster image maybe it more cheap to compute ??.
Personnally i dont know which is better gdi+ or pure GL.
Anyway a little question about that route preview, is that map generated everytime we click the route file in main game when it still reading the file ? If yes i think we should only regenerate that map when the player want to see it or create only for a first time then put the preview image beside the route csv file with naming like this: MAINLINE-preview.png . if a there already a preview image when we want to see that map with the route file selected it should just load that image not regenerate, also maybe a refresh button to regenerate and update that map preview manually could works ?.
https://github.com/leezer3/OpenBVE/pull/810
This brings all sorts of interesting stuff, which this PR doesn't handle, and will therefore need some design changes,
Basic thoughts:
- Our switch actually needs to link to a specific 'new' track section, not just a rail number.
- Switches may need a 'new' running direction- Consider a 180 degree loop.
????? Track.Switch FirstRail;SecondRail;InitialSetting;SecondRailDistance;SecondRailDirection
If neither SecondRailDistance or SecondRailDirection are set, assume as per current behaviour in this PR, If SecondRailDistance is set, assume that we attach to the track piece from the second rail at this position. ?? What happens if the tracks aren't aligned in this case? Massive glitch? ??
Getting a little closer to usable now- The switch menu now has a local map available, but unfortunately this takes a step back in the process.....
The main issue is going to be getting a 'nice' UI; Now that I've implemented the map, the track image looks awful, and the whole menu concept requires a bit of a redesign. I think what this probably wants is to display visible buttons on the map, which might require complete decoupling from the initial menu concept.
Possible plan of action:
Render overlay map image for entire screen, restricted to an appropriate range, Route map function returns an array of clickable nodes along with the map (should be able to get these at the same time as drawing track elements) Hover over node displays switch position, setting etc. (presume that if we just pass the GUIDs from the function can just draw appropriately) Click changes said switch
The OtherTrack that I had in mind was write the distance from where to where in the route data. 0-1000m:Rail0 1000-1500m:Rail123 1500m-2000m:Rail1 etc... 1000 Track.Switch(123) 1500 Track.Switch(1)
I thought that like this at the first commit.
From what I've heard, it sounds like we can move the distance using POIs while driving and switch directly on the 3D map, just like in Trainsimworld 3, or display many track switch icon on the map display in the upper left, and switch by mouse click. Is this UI idea's is match?
Basically, that's what I'm aiming for (although most likely a map square of ~1km around the player), although your translation is not the clearest.
It shouldn't be too difficult to implement, but might take a while. Bigger problem is really that secondary tracks have no effect on signalling etc. This can be sorted, but it's yet more internal redesign work.
In addition to incorporating instructions into the route data, the plan is to include a function that allows you to switch points at any point while driving, allowing you to run on other tracks!? I was very surprised! I thought it was just a command to the route data, but I think it would be a lot of work, is it? My expectations have increased. Thank you for your answer!
So, I've now got a working map with mouseover showing the switches name, distance and setting with the latest commit. This image shows a 1km radius map on my basic test route above, which possibly needs to be shrunk further. (maybe 500m?) Switches are the grey circles.
Whilst I haven't yet implemented the plumbing to change the switches, a close button, dialog title etc,, the basic concept seems to work quite well, and definitely looks a lot better than the original menu based idea. Not yet decided on what to do with the track coloring either- Probably the secondary rails should be the same color (or at least a lighter variant of), not the testing blue at the minute.
Another thought (how complex, I'm not sure?!)- Perhaps we should highlight the selected path. As we obviously know the selected rail index from each switch, I think this is probably doable in a click event, but again needs some design thinking about.....
I think the UI you showed is really great! In the UI candidate image you provided, I thought the route author needed an option to restrict arbitrary switching. The reason for this is that if the user wants to move the TFO at an arbitrary time and distance, but the user changes the course, things will go wrong. If you are planning to be overtaken and the data is designed to move onto the side track, but the point is switched to the main track, you will collide with the TFO.
This is now usable with the proposed dialog above if built from this branch, but requires a lot of polish to look nice. Please set the command ChangeSwitch to an appropriate key and play around with the examples above to see it in action.
I've settled on blue for the player rail highlight at the minute, as it needs to be nicely distinct from the normal track. Did try black, but that wasn't distinct enough.
TODO:
- We need a way to set the cant of secondary tracks. Proposed command: Track.Cant RailIndex; CantAmount
- TrackEndEvent doesn't seem to be working on a secondary track- Needs investigation.
- ~~Add title and close button to the switch change dialog. (Needs a dedicated button class creating, similar to the picturebox)~~
- ?? Change the switch to a different shape- triangle or square ??
- Fix the behaviour if we split a switch. (Need to think about this, but probably if the difference between the FrontAxle follower & the RearAxle follower is greater than the length of the car, derail?)
Some of these, and behaviour altering the signalling system may well get implemented at a later date after merging, just need to keep on noting them down so I don't forget them.....
https://youtu.be/r9mByy3_qQE
UI is now working relatively nicely. Still need to look into things like adding a title, but the public concept seems to be nearly ready for other people to break it....
I watched the video and understood what it meant. Since it is dangerous on Shinkansen trains, etc., I think it is necessary to decide in advance which track the train will run on, and to provide a lock command to prevent switching while driving.
Not sure, I'd have to think about that. Changing whilst driving shouldn't be an issue if you only setup the appropriate switches in your routefile though? Anything else just remains a dummy.
It sounds more like what you want is a speed parameter for switches, which sets the max allowable speed per route. Starting to wonder about an XML file containing switches, but I quite like the simplicity of the current command.....
If we change the 70km/h limit turning machine suddenly while traveling at 320km/h on a Shinkansen, the train will derail and overturn. To avoid this, we have to use ATC to lower the time to 70km/h before switching, but there is a risk that the driver will intentionally change the timetable at the last minute even though the timetable is supposed to pass. To avoid this, we should use route command in advance such as this. Route.Switchlock 1; I think a command is needed to prevent the driver from switching points without permission while driving.
Now that's an interesting idea, but I think to be implemented a little later- At the minute, this is just trying to get some of the basic mechanics working.
I think in that case, you'd probably want a speed lock and a position lock. We probably also want an event passed to plugins when a switch is changed, but that's possibly the sort of thing that needs to be thought about in conjunction with a v2 of the plugin interface.
The ATC example is an example of the concern that this could happen if the driver were allowed to change the route freely.
Simply, in addition to a function that allows route creators to drive on designated routes, I believe it is necessary to implement a command that prohibits to drivers from changing points by route builder.
The UI is essentially finished now I think, although I'm considering using a multi-line textbox for the labels on the left, along with a 'No switch selected' message.
Other thoughts:
It's clear (unless we introduce textual rail labels with this) that just the rail number isn't the best thing for showing the current setting of the switch. Easiest way to handle this is likely to add two additional optional parameters to our switch command, with textual descriptions in them. Either immediately after the rail index or together at the end- Will add these probably tomorrow.
Station names probably need hiding in favour of track distances, so we have the distance at the top and bottom. (Same style as station names?)