This commit is contained in:
Aaron Smith 2023-08-03 12:04:47 +01:00
parent 795ff8725c
commit 5057b7772b
2 changed files with 42 additions and 2 deletions

View file

@ -36,10 +36,12 @@ type SpringData<T> = {
duration: number,
period: number,
damping_ratio: number,
velocity: number,
initial_velocity: number,
initial_position: T,
target_position: T,
target_updated: boolean,
target: () -> T
}
@ -110,9 +112,10 @@ local function spring<T>(target: () -> T, period: number?, damping_ratio: number
target = target
}
local function input_changed()
local function input_changed(node)
data.target_updated = true
data.target_position = target()
springs[data] = node
end
for _, input in next, inputs do
@ -124,11 +127,13 @@ local function spring<T>(target: () -> T, period: number?, damping_ratio: number
return output_get
end
local remove_queue = {}
local function update_springs(dt: number)
for data, output in next, springs do
if data.target_updated then
data.target_updated = false
data.target = data.target()
data.target_position = data.target()
data.initial_position = get(output)
data.alpha = 0
data.duration = 0
@ -168,7 +173,17 @@ local function update_springs(dt: number)
local value = lerp(initial_position, target_position, new_alpha)
set(output, value)
if new_alpha > 0.9 then
table.insert(remove_queue, data)
end
end
for _, data in next, remove_queue do
springs[data] = nil
end
table.clear(remove_queue)
end
return function() return spring, update_springs end

View file

@ -1016,6 +1016,7 @@ TEST("spring()", function()
local create = vide.create
local source = vide.source
local spring = vide.spring
local watch = vide.watch
do CASE "Update state (on next hearbeat resumption cycle)"
local value = source(10)
@ -1067,6 +1068,30 @@ TEST("spring()", function()
gc()
CHECK(wref[1]) -- `output` should not gc
end
do CASE "Spring finished"
local input = source(0)
local output = spring(input)
input(1)
vide.step(1e9) -- spring alpha at ~1
local count = -1
watch(function()
output()
count += 1
end)
vide.step(1) -- spring should be internally removed from spring queue
CHECK(count == 0)
--
gc() -- perform full gc
input(2) -- spring should be re-added to spring queue
vide.step(0) -- process spring queue
CHECK(count == 1) -- check spring was rescheduled correctly
end
end)
TEST("Events", function()