Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add manual time sync option #25

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

palodequeso
Copy link

Adds flag and method for manual time sync.
To use, you disable "Enable game time"
and enable "Manual Time Management"
and then call manual_time_update() after programmatically setting the time in game.

In my game, the time only changes when the characters move in the overworld for instance.

@JekSun97
Copy link

It's strange that this opportunity didn't exist before.
With this we can change the day cycle in the editor and see the changes?

@TokisanGames
Copy link
Owner

With this we can change the day cycle in the editor and see the changes?

You can already do that. The aim here is for setting static time via the API while timed updates are disabled.

@TokisanGames
Copy link
Owner

TokisanGames commented Jan 12, 2025

I appreciate the effort to keep up with main, but it's unnecessary, and the process is incorrect. You should only rebase. Never merge or cherry pick commits into your branch.

I can automatically rebase on merging the PR, so there's no need unless there's a major change or I ask you too.

As it is, I'd like you to do an interactive rebase, drop the last commit and force push your branch into the PR.

As for the code, I'm working on Terrain3D collision and will review this later. I think there might be a better approach, but I need to look at it and will let you know so you can adjust it.

@palodequeso
Copy link
Author

I'll rebase this soon, thank you!

Copy link
Owner

@TokisanGames TokisanGames left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for working on this. I would like some changes to the design of this implementation.

Some important background:

TODv1 was designed for updating in _process. I changed it to update based on a timer of update_interval. There is some legacy code for the former that doesn't make sense for the latter and should be removed.

Delta originally came from _process, but now I manually calculate when I wrote _on_timeout(). So a key question is what is delta used for?

It looks like delta does 2 things:

  1. It progresses time forward. If a delta of 1000ms occurs, then time moves forward 1s.
  2. A manual timer is tracked for updating celestial positions on a slower schedule than every frame like the rest of the system. This manual timer is now redundant and can be removed.

@@ -103,6 +103,7 @@ func set_show_physical_sky(value: bool) -> void:
@export_range(0.0, 24.0) var current_time: float = 8.0 : set = set_current_time
@export_range(-1440,1440,1) var minutes_per_day: float = 15.0 : set = set_minutes_per_day
@export_range(0.016, 10.0) var update_interval: float = 0.1 : set = set_update_interval
@export var manual_time_management: bool = false : set = set_manual_time_management;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

update_in_game and update_in_editor and both disabled (manual) already define three states. This variable is redundant with both disabled. So rather than tracking it here and the support functions, all we really need is an update() function that can be called at any time, even when both update settings are enabled, to refresh the system without adjusting the time.

__time_process(0)
__repeat_full_cycle()
__check_cycle()
__set_celestial_coords()
Copy link
Owner

@TokisanGames TokisanGames Jan 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good start on the update function, but it also is redundant with _on_timeout(), so we should combine them. Instead, lets make these changes:

  • _on_timeout() is stripped down to only calculate delta and _last_update, then calls update(delta). This means delta will only be calculated from calls to _on_timeout(). Any additional calls to update() won't change the delta calculation from the timer.
  • A new update(delta: float = 0.0) function has the rest of the _on_timeout() function.
  • The whole system_sync section should be skipped if is_approx_zero(delta)
  • __time_process() can be renamed to __progress_time() as that's what it does.
  • There's a problem if system sync is enabled, which calls __get_date_time_os(). That will call set_day, set_month, set_year which is going to fire off day/month/year signals, even if they haven't changed. Those functions should have a check if changed before emitting.
  • All of the __celestials_update_timer stuff can be removed. Just call __set_celestial_coords() every time update() runs.
  • emit(time_changed) is currently in set_total_hours. I think it should be moved to update(), and set_total_hours calls update(). Though time isn't always technically changing, it is an adequate generic "update" signal that is safe to call every micro second.

Now the timer can fire off and update as normal to progress time, and we can do manual zero-delta updates anytime without changing the time.

@@ -130,28 +138,28 @@ var year: int = 2025: set = set_year
func set_total_hours(value: float) -> void:
total_hours = value
emit_signal("time_changed", value)
if Engine.is_editor_hint():
if is_editor_hint_or_manual():
__set_celestial_coords()
Copy link
Owner

@TokisanGames TokisanGames Jan 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here reverting is not right. There's no need for the editor hint at all. This should call update(), and the signal be moved to that function.

func set_total_hours(value: float) -> void:
	total_hours = value
	update()

func set_manual_time_management(value:bool) -> void:
manual_time_management = value
if tod:
tod._manual_time_management = value
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove


func manual_time_update() -> void:
if tod:
tod.manual_time_update()
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change both to just update()


func is_editor_hint_or_manual() -> bool:
return Engine.is_editor_hint() or _manual_time_management
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove all


@export var update_in_game: bool = true :
set(value):
update_in_game = value
if not Engine.is_editor_hint():
if not is_editor_hint_or_manual():
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Revert. Editor hint is appropriate.

@@ -28,7 +31,7 @@ var _last_update: int = 0
@export var update_in_editor: bool = true :
set(value):
update_in_editor = value
if Engine.is_editor_hint():
if is_editor_hint_or_manual():
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Revert. Editor hint is appropriate.

if (Engine.is_editor_hint() and update_in_editor) or \
(not Engine.is_editor_hint() and update_in_game):
if (is_editor_hint_or_manual() and update_in_editor) or \
(not is_editor_hint_or_manual() and update_in_game):
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Revert. Editor hint is appropriate.

__set_celestial_coords()


func set_day(value: int) -> void:
day = value
emit_signal("day_changed", value)
if Engine.is_editor_hint():
if is_editor_hint_or_manual():
__set_celestial_coords()
Copy link
Owner

@TokisanGames TokisanGames Jan 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change to:

func set_day(value: int) -> void:
	if day != value:
		day = value 
		emit_signal("day_changed", value)
	update()

Change all the rest of the set_* functions you changed below. The check if changed is only needed if emitting signals. They can all always update.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants