KontrolSystem2
KontrolSystem2 copied to clipboard
sync fn and warp_to
I have an error message with my script below used in the VAB.
I use it inside the
.on_click method of my warp button.
It's the first time I see this error. Is it caused by the last released version (0.5.4.1)?
This is my script. I have a comment line just before the problem
use { floor } from core::math
use { CONSOLE } from ksp::console
use { screen_size, open_window, Align } from ksp::ui
use { yield, current_time } from ksp::game
use { warp_to } from ksp::game::warp
pub fn main_editor () -> Unit = {
CONSOLE.clear()
create_window()
}
fn create_window() -> Unit = {
const myScreen = screen_size()
const window_width = myScreen.x/5
const window_height = 50
const text_font_size = 15
const main_window = open_window("<b>CURRENT TIME</b>",
(myScreen.x-window_width-10),
myScreen.y - 40,
window_width,
window_height)
const hours_per_day = 6
const now_time: Cell<float> = Cell(current_time())
const now_time_days: Cell<float> = Cell(0)
now_time_days.value = floor(now_time.value / (hours_per_day*3600))
const days_in_game: Cell<float> = Cell(0)
days_in_game.value = now_time_days.value + 1
const now_time_hours: Cell<float> = Cell(0)
now_time_hours.value = floor((now_time.value - now_time_days.value*(hours_per_day*3600)) / 3600)
const now_time_minutes: Cell<float> = Cell(0)
now_time_minutes.value = floor((now_time.value - now_time_hours.value*3600) / 60)
const now_time_seconds: Cell<float> = Cell(0)
now_time_seconds.value = floor(now_time.value - now_time_hours.value*3600 - now_time_minutes.value*60)
const main_box = main_window.add_vertical(10.0, Align.Stretch)
const detail_box = main_window.add_horizontal(10.0, Align.Center)
const toggle_box = main_window.add_vertical(10.0, Align.Stretch)
const warp_box = main_window.add_vertical(10.0, Align.Stretch)
const now_time_label = main_box.add_label("Current time (s):", Align.Stretch)
now_time_label.bind(now_time, "Current time: {0:N2} s")
now_time_label.font_size = text_font_size
const days_label = detail_box.add_label("day:", Align.Center)
days_label.bind(days_in_game, "{0:N0} d")
days_label.font_size = text_font_size
const hours_label = detail_box.add_label("hour:", Align.Center)
hours_label.bind(now_time_hours, "{0:N0} h")
hours_label.font_size = text_font_size
const minutes_label = detail_box.add_label("min:", Align.Center)
minutes_label.bind(now_time_minutes, "{0:N0} min")
minutes_label.font_size = text_font_size
const seconds_label = detail_box.add_label("sec:", Align.Center)
seconds_label.bind(now_time_seconds, "{0:N0} s")
seconds_label.font_size = text_font_size
const toggle_sec = toggle_box.add_toggle("WARP to Current time + DeltaT", Align.Start)
toggle_sec.value = true
toggle_sec.font_size = text_font_size
const toggle_UT = toggle_box.add_toggle("WARP to new UT", Align.Start)
toggle_UT.value = false
toggle_UT.font_size = text_font_size
const warp_input_box = warp_box.add_horizontal(10.0, Align.Stretch, 10.0)
const warp_label = warp_input_box.add_label("Warp (deltaT in sec):", Align.Start)
warp_label.font_size = text_font_size
const warp_value = warp_input_box.add_float_input(Align.Start, 10.0)
warp_value.value = 0
// -----------------------------------> PROBLEM HERE
const warp_button = warp_box.add_button("WARP", Align.Center)
warp_button.on_click(fn() -> {
const now = current_time()
const deltaT = warp_value.value
if (toggle_sec.value) {
warp_to(now + deltaT)
}
else {
warp_to(deltaT)
}
})
toggle_sec.on_change(fn(b) -> {
if (toggle_sec.value) {
toggle_UT.value = false
warp_label.text = "Warp (deltaT in sec)"
}
CONSOLE.clear()
})
toggle_UT.on_change(fn(b) -> {
if (toggle_UT.value) {
toggle_sec.value = false
warp_label.text = "Warp (UT in sec)"
}
CONSOLE.clear()
})
while(!main_window.is_closed) {
now_time.value = current_time()
now_time_days.value = floor(now_time.value / (hours_per_day*3600))
days_in_game.value = now_time_days.value + 1
now_time_hours.value = floor((now_time.value - now_time_days.value*(hours_per_day*3600)) / 3600)
now_time_minutes.value = floor((now_time.value - now_time_days.value*(hours_per_day*3600) - now_time_hours.value*3600) / 60)
now_time_seconds.value = floor(now_time.value - now_time_days.value*(hours_per_day*3600) - now_time_hours.value*3600 - now_time_minutes.value*60)
toggle_sec.enabled = !toggle_sec.value
toggle_UT.enabled = !toggle_UT.value
yield()
}
}
Yes, warp_to has recently changed to async because I had noticed some very strange behavior when using it without properly surrounding it with a yield in certain situations (i.e. wait for a FixedUpdate to happen).
But I can see your use-case and triggering a warp in a UI callback most like will not cause any problem.
As a quick-fix I added a sync_warp_to function to ksp::game::warp with the previous functionality in this pre-release:
https://github.com/untoldwind/KontrolSystem2/releases/tag/v0.5.5.1
... I guess the proper way to fix this would be to allow for async lambda functions, which I tried to avoid so far.
I tried this and it worked fine.
Could I write my scrip differently so I can continue to use warp_to instead of sync_warp_to? I have no problem to use sync_warp_to, it's just to understand.
(btw, the last vsix extension (0.0.27) for visual studio is great too)
Just a thing about the vsix extension. I have this "error" message with the use of format.
The vsix extension (or rather the underlying lsp-server) still has some issues with generics, I made a small tweak so that at least no error is shown if the concrete type is still in question.
Concerning the warp_to: As a rule of thumb, use warp_to whenever possible unless there is this sync context error (e.g. inside at button callback).
Unluckily the underlying problem is quite complicated.
In the unity engine every component might have an Update or FixedUpdate method which is called either on every frame refresh or as often as possible. In KSP2 these are used to do a lot of calculations and internal updates.
For the scripting part the problem boils down to: How many changes can you make to the internal game state inbetween those update cycles without the entire state getting wonky. E.g. changing a maneuver node and triggering a warp_to in the same cycle has created some pretty unpredictable results, therefore the change.
So the new warp_to will do:
- Wait for the next
FixedUpdate - Do the change to the internal
TimeWarpclass - Wait for another
FixedUpdatejust to be save
Unluckily this currently only works, when the script is in an async context (like in the fn main_flight function). Inside a button callback this is not so easy, because it is an UI event listener and "Waiting for the next FixedUpdate" would most likely freeze the UI.
I am still not sure about the best solution for this, eventually though there should be only one warp_to function that works in both cases.
In 0.5.5.3 https://github.com/untoldwind/KontrolSystem2/releases/tag/v0.5.5.3
the two version of war_to should be merge again, i.e. there is just one warp_to that can be use in sync and async (under the hood there are still two functions that are picked based on the context ... in short it is the task of the compiler to worry about what version to use).
Nice 👍
This issue is stale because it has been open for 60 days with no activity.
This issue was closed because it has been inactive for 14 days since being marked as stale.