Gregory365 / TPF2-Timetables

The Timetable mod for Transport Fever 2
GNU General Public License v3.0
13 stars 5 forks source link

GUI Stuttering when editing timetable #52

Closed Gregory365 closed 8 months ago

Gregory365 commented 1 year ago

The GUI sometimes won't update when interacting with the GUI (adding a timetable slot, deleting a timetable slot, changing the type of timetable, enabling / disabling the timetable, ect.)

Cause

This is caused by the way the timetable is updated from the GUI thread, which is done as follows:

  1. timetableChanged is set to true to notify change has been made (GUI thread)
  2. guiUpdate sends the script event "timetableUpdate" with the updated timetable as a parameter (GUI thread)
  3. handleEvent handles the "timetableUpdate" event and sets the timetable to the updated timetable (Engine thread)
  4. save saves the updated timetable (Engine thread)
  5. load loads the updated timetable (GUI thread)

The issue with this is that if multiple changes are made before the first event can be handled and saved by the engine thread, then, the second changes made will not include the first change made.

Steps to reproduce

  1. Quickly add timetable slots to a station on a line.
  2. Notice how there are less timetable slots showing then times "add" was pressed.
Gregory365 commented 1 year ago

Related to #8

Gregory365 commented 10 months ago

Because GUI events and the timetable management (engine) are on separate threads, it's very difficult to transfer information quickly and without some of it getting missed. This is especially true for when the GUI can reload before the engine thread can see the changes requested from the GUI and save the changed information.

The GUI can't use save.

One solution would be to write just the changes, rather than the entire timetable when sending update events from the GUI to the engine thread. These changes can then be queued up on the engine thread. But problems arise here with how errors are handled and whether the order of GUI operations is maintained (which isn't always guaranteed)

CC-22A commented 8 months ago

Will this issue be resolved? Because this issue is quite annoying for me when setting up time tables!

Gregory365 commented 8 months ago

The timetables mod needs to be completely re-written to solve this issue.

This is not something that is currently planned unfortunately.

It will depend how many people come forward to state this is an important issue to fix for them and how much time I have available.

CC-22A commented 8 months ago

I see. So, I will just need to bear with it then. I will input it slowly :)

Gregory365 commented 8 months ago

The base game

You also get this same behaviour in the base game with no mods when removing stations from a line. If you try to remove two stations quickly (in the same second), then only one will get removed, and the other will stay present. The base game UI doesn't "stutter" but it is (although briefly) unresponsive to the users inputs.

The timetables mod

So while the GUI in this mod doesn't always reflect the true underlaying values (as it assumes the engine thread can handle it), it does always respond to the users inputs instantly. The speed at which the user inputs can be handled is limited by the game and not this mod.


Potential solution

One theorised solution involved raising events in the GUI thread for actions the user makes and then executing the relevant transactions sequentially on the engine thread. However, the events to not guarantee that they will stay in the same order. Therefore, events can not be used if the order matters, which in this case it very much does (Think if you deleted one slot and modified another, but instead watched as the game modifies and then deletes the same slot).

Conclusion

This issue cannot be solved in a favourable way. The best alternative would be to have the mod ignore secondary inputs if they are made shortly after first. But I think this is not worth the effort, and is potentially worse than it is now.

This bug cannot be fixed until the game provides a more comprehensive or reliable way to send data or events between the GUI and engine threads