Skip to content

Conversation

wvpm
Copy link
Contributor

@wvpm wvpm commented Aug 4, 2025

When it comes to reactivity in the UI I'd love to use a reactive pull based model.
Where the reactive part is event-driven marking data as dirty.
The pull part would be the UI updating all elements marked dirty.
This would be kinda like Svelte, but Svelte does it compile-time.

Sadly according to Gemini and my own research neither godot nor C++ have something like this.
We're stuck with signals and manually invalidating or directly updating UI elements.
Also we have to ensure that signals can't flood the UI with updates.

This is a error-prone approach.

I thought about it some more and came up with the following high-level idea:
Split state up into:

constant state
mutable state (properties with events)
derived state (tracks dependencies is marked dirty when they update. recalculates if dirty when requested)
manually tracked derived state

We can use signal for the events.
signal_property would have to be replaced with mutable state that exposes a get() method and changed signal.
Manually tracked derived state would be pop distributions and other aggregates that we know when to update in the sim.
You don't want to track every pop his size in the province + the list of all pops. You could just manually update that like we do now.
Mutable, derived & manually tracked derived state all implement the same interface of a get() method and changed signal.
The derived state (mainly for UI purposes) should automatically handle tracking.

@wvpm wvpm added enhancement New feature or request topic:core labels Aug 4, 2025
@wvpm wvpm added this to the 0.9.0 milestone Aug 4, 2025
@wvpm wvpm force-pushed the automatic_dependency_tracking_reboot branch 6 times, most recently from 25fefc4 to e9feff3 Compare August 4, 2025 21:07
@wvpm wvpm force-pushed the automatic_dependency_tracking_reboot branch from e9feff3 to 1ef929d Compare August 7, 2025 12:23
@wvpm wvpm force-pushed the automatic_dependency_tracking_reboot branch 3 times, most recently from 80e2576 to ff029bb Compare August 7, 2025 14:00
Spartan322
Spartan322 previously approved these changes Aug 7, 2025
@wvpm wvpm force-pushed the automatic_dependency_tracking_reboot branch from ff029bb to 752d671 Compare August 7, 2025 15:06
@wvpm wvpm force-pushed the automatic_dependency_tracking_reboot branch from 752d671 to 855d37f Compare August 7, 2025 15:10
@wvpm wvpm enabled auto-merge August 7, 2025 15:25
@schombert
Copy link

schombert commented Aug 8, 2025

Are you worried that this will be infeasible? For example: a nation has STATE_PROPERTY(fixed_point_t, prestige). So, when the list of nations with their prestige is visible (plus the numerous other windows that may show a prestige value, such as the topbar and province view), the ui will have registered various components with one or more of the signals for many nations, which means that as the day's update progresses you will lock a mutex at least once for each of those nations to update their value and then call some ui function, and often those signals will be sent multiple times for a given nation, as prestige is updated from many sources, including events. That feels like a lot of overhead to add to what should be a simple operation to update a nation's prestige. We haven't had any issues updating the entire ui whenever the gamestate is flagged as updated, as a whole; it doesn't lead to dropped frames because there really isn't that much information visible in the ui at any given time that needs to be updated.

I ask because you seemed concerned about the performance impact of adding an additional pointer indirection to a handful of arrays, and adding that sort of overhead to changing prestige values is going to cost far more than those pointer indirections could have.

@wvpm
Copy link
Contributor Author

wvpm commented Aug 8, 2025

Are you worried that this will be infeasible? For example: a nation has STATE_PROPERTY(fixed_point_t, prestige). So, when the list of nations with their prestige is visible (plus the numerous other windows that may show a prestige value, such as the topbar and province view), the ui will have registered various components with one or more of the signals for many nations, which means that as the day's update progresses you will lock a mutex at least once for each of those nations to update their value and then call some ui function, and often those signals will be sent multiple times for a given nation, as prestige is updated from many sources, including events. That feels like a lot of overhead to add to what should be a simple operation to update a nation's prestige. We haven't had any issues updating the entire ui whenever the gamestate is flagged as updated, as a whole; it doesn't lead to dropped frames because there really isn't that much information visible in the ui at any given time that needs to be updated.

I ask because you seemed concerned about the performance impact of adding an additional pointer indirection to a handful of arrays, and adding that sort of overhead to changing prestige values is going to cost far more than those pointer indirections could have.

The concern is mainly that we don't know when to update a part of the UI.
Sure after each tick, the UI must be updated. But we realised when implementing the budget menu that we also need fine grained UI updates.

We still have to find the right balance between reacting directly and updating after a tick. Events, decisions, reforms and peace treaties are difficult to deal with as they could have all sorts of effects.

Perhaps we'll end up marking a pop, province, state, building or country dirty or perhaps we have to force a full UI refresh.
This PR is mainly about supporting reactive programming and demonstrating it works. Follow up PRs will implement the finer details.

@wvpm wvpm merged commit eb37484 into master Aug 8, 2025
16 checks passed
@Spartan322 Spartan322 deleted the automatic_dependency_tracking_reboot branch August 8, 2025 15:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request topic:core
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants