From 5ab76a434edb4b238440af8c6be5df4d81b0ebc8 Mon Sep 17 00:00:00 2001 From: aaron <83140718+centau@users.noreply.github.com> Date: Sat, 26 Aug 2023 14:49:46 +0100 Subject: [PATCH] Update spring tests --- src/spring.luau | 35 +++++++++++++++++++++----------- test/spring-test.luau | 8 ++++---- test/tests.luau | 47 ++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 71 insertions(+), 19 deletions(-) diff --git a/src/spring.luau b/src/spring.luau index fbccc93..1f8fdb3 100644 --- a/src/spring.luau +++ b/src/spring.luau @@ -42,7 +42,7 @@ type Animatable = number | CFrame | Color3 | UDim | UDim2 | Vector2 | Vector3 type SpringData = { k: number, -- spring constant - c: number, -- damping coeff (from k) + c: number, -- damping coeff -- dimensions 1-3 x0_123: Vec3, @@ -54,7 +54,7 @@ type SpringData = { x1_456: Vec3, v_456: Vec3, - source_value: T + source_value: T -- current value of spring input source } type TypeToVec6 = (T) -> (Vec3, Vec3) @@ -140,7 +140,7 @@ setmetatable(type_to_vec6, invalid_type) setmetatable(vec6_to_type, invalid_type) -- maps spring data to its corresponding output node --- lifetime of spring data is tied to output node's +-- lifetime of spring data is tied to output node local springs: { [SpringData]: Node } = {} setmetatable(springs, { __mode = "v" }) @@ -162,7 +162,7 @@ local function spring(source: () -> T, period: number?, damping_ratio: number local c_c = 2*w_n local c = z * c_c - local data: SpringData = { -- todo: confirm gc of data + local data: SpringData = { k = k, c = c, @@ -178,26 +178,32 @@ local function spring(source: () -> T, period: number?, damping_ratio: number } -- reschedule spring for simulation on input update - local function input_updated() + local function input_updated(node) local v = source() data.x1_123, data.x1_456 = type_to_vec6[typeof(v)](v) data.source_value = v - springs[data] = output -- todo: investigate why insertion is not O(1) at ~20k springs + springs[data] = node -- todo: investigate why insertion is not O(1) at ~20k springs end - output.derive = input_updated :: any -- have output reference inputs + -- unused field, use so output prevents gc of inputs + output.derive = source :: any -- register above function as side-effect for all inputs for _, input in next, inputs do set_effect(input, input_updated, output) end - return output_get + return output_get, data end local function step_springs(dt: number) - for data, output in next, springs do - local k, c, x0_123, x1_123, u_123, x0_456, x1_456, u_456 = data.k, data.c, data.x0_123, data.x1_123, data.v_123, data.x0_456, data.x1_456, data.v_456 + for data in next, springs do + local k, c, + x0_123, x1_123, u_123, + x0_456, x1_456, u_456 = + data.k, data.c, + data.x0_123, data.x1_123, data.v_123, + data.x0_456, data.x1_456, data.v_456 -- calculate displacement from target local dx_123 = x0_123 - x1_123 @@ -232,9 +238,14 @@ local remove_queue = {} local function update_spring_sources() for data, output in next, springs do - local x0_123, x1_123, v_123, x0_456, x1_456, v_456 = data.x0_123, data.x1_123, data.v_123, data.x0_456, data.x1_456, data.v_456 + local x0_123, x1_123, v_123, + x0_456, x1_456, v_456 = + data.x0_123, data.x1_123, data.v_123, + data.x0_456, data.x1_456, data.v_456 - local dx_123, dx_456 = x0_123 - x1_123, x0_456 - x1_456 + local dx_123, dx_456 = + x0_123 - x1_123, + x0_456 - x1_456 -- todo: can this false positive? if (v_123 + v_456 + dx_123 + dx_456).Magnitude < TOLERANCE then diff --git a/test/spring-test.luau b/test/spring-test.luau index 691e256..f2f19f3 100644 --- a/test/spring-test.luau +++ b/test/spring-test.luau @@ -13,10 +13,6 @@ local function step(): number end local function main() - local source = vide.source - local spring = vide.spring - local watch = vide.watch - local TERMINAL_HEIGHT = 73 --* REDUCE IF BAR DOES NOT FIT IN TERMINAL local MIN_ALPHA = 0.3 local MAX_ALPHA = 0.7 @@ -39,6 +35,10 @@ local function main() else "▁" end + local source = vide.source + local spring = vide.spring + local watch = vide.watch + local value = source(MAX) local sprung = spring(value, 1, 0.3) diff --git a/test/tests.luau b/test/tests.luau index 6cb5bab..2c1ff34 100644 --- a/test/tests.luau +++ b/test/tests.luau @@ -214,6 +214,19 @@ TEST("source()", function() state(b) CHECK(updates == 1) end + + do CASE "garbage collection of node" + local capture = require "src/graph".capture + local src = source(0) + + local wref do + local node = unpack(capture(src)) + wref = weak { node } + end + + gc() + CHECK(not wref[1]) + end end) TEST("derive()", function() @@ -332,6 +345,20 @@ TEST("derive()", function() CHECK(c() == 2) end end + + do CASE "garbage collection of node" + local capture = require "src/graph".capture + local input = source(1) + + local wref do + local output = derive(input) + local output_node = unpack(capture(output)) + wref = weak { output_node } + end + + gc() + CHECK(not wref[1]) + end end) TEST("watch()", function() @@ -632,8 +659,6 @@ TEST("create()", function() Position = UDim2.new() } - print("template", template.AnchorPoint) - local text = create(template) { AnchorPoint = { 1, 2 }, Position = { 3, 4 } @@ -1215,8 +1240,24 @@ TEST("spring()", function() gc() CHECK(not wref[1]) end - end + do -- spring data gc + local capture = require "src/graph".capture + + local input = source(10) + + local wref do + local output, data = (spring :: any)(input) + input(input() + 1) -- schedule spring calculation + local output_node = unpack(capture(output)) + wref = weak { output_node, data } + end + + gc() + CHECK(not wref[1]) + CHECK(not wref[2]) + end + end do CASE "garbage collection (binded)" local input = source(10)