diff --git a/src/spring.luau b/src/spring.luau index acb50ac..ae77f67 100644 --- a/src/spring.luau +++ b/src/spring.luau @@ -30,15 +30,7 @@ local update_descendants = graph.update_descendants local push_child_to_scope = graph.push_child_to_scope local UPDATE_RATE = 120 -local TOLERANCE = 0.0001 - -type Vec3 = Vector3 - -local function Vec3(x: number?, y: number?, z: number?): Vec3 - return vector.create(x, y, z) -end - -local ZERO = Vec3(0, 0, 0) +local TOLERANCE = vector.create(0.001, 0.001, 0.001) type Animatable = number | CFrame | Color3 | UDim | UDim2 | Vector2 | Vector3 @@ -47,53 +39,53 @@ type SpringData = { c: number, -- damping coeff -- dimensions 1-3 - x0_123: Vec3, - x1_123: Vec3, - v_123: Vec3, + x0_123: Vector3, + x1_123: Vector3, + v_123: Vector3, -- dimensions 4-6 - x0_456: Vec3, - x1_456: Vec3, - v_456: Vec3, + x0_456: Vector3, + x1_456: Vector3, + v_456: Vector3, source_value: T -- current value of spring input source } -type TypeToVec6 = (T) -> (Vec3, Vec3) -type Vec6ToType = (Vec3, Vec3) -> T +type TypeToVec6 = (T) -> (Vector3, Vector3) +type Vec6ToType = (Vector3, Vector3) -> T local type_to_vec6 = { number = function(v) - return Vec3(v, 0, 0), ZERO + return Vector3.new(v, 0, 0), Vector3.zero end :: TypeToVec6, CFrame = function(v) - return v.Position, Vec3(v:ToEulerAnglesXYZ()) + return v.Position, Vector3.new(v:ToEulerAnglesXYZ()) end :: TypeToVec6, Color3 = function(v) -- todo: hsv, oklab? - return Vec3(v.R, v.G, v.B), ZERO + return Vector3.new(v.R, v.G, v.B), Vector3.zero end :: TypeToVec6, UDim = function(v) - return Vec3(v.Scale, v.Offset, 0), ZERO + return Vector3.new(v.Scale, v.Offset, 0), Vector3.zero end :: TypeToVec6, UDim2 = function(v) - return Vec3(v.X.Scale, v.X.Offset, v.Y.Scale), Vec3(v.Y.Offset, 0, 0) + return Vector3.new(v.X.Scale, v.X.Offset, v.Y.Scale), Vector3.new(v.Y.Offset, 0, 0) end :: TypeToVec6, Vector2 = function(v) - return Vec3(v.X, v.Y, 0), ZERO + return Vector3.new(v.X, v.Y, 0), Vector3.zero end :: TypeToVec6, Vector3 = function(v) - return v, ZERO + return v, Vector3.zero end :: TypeToVec6, Rect = function(v) - return Vec3(v.Min.X, v.Min.Y, v.Max.X), Vec3(v.Max.Y, 0, 0) + return Vector3.new(v.Min.X, v.Min.Y, v.Max.X), Vector3.new(v.Max.Y, 0, 0) end :: TypeToVec6 } @@ -167,13 +159,13 @@ local function spring(source: () -> T, period: number?, damping_ratio: number k = k, c = c, - x0_123 = ZERO, - x1_123 = ZERO, - v_123 = ZERO, + x0_123 = Vector3.zero, + x1_123 = Vector3.zero, + v_123 = Vector3.zero, - x0_456 = ZERO, - x1_456 = ZERO, - v_456 = ZERO, + x0_456 = Vector3.zero, + x1_456 = Vector3.zero, + v_456 = Vector3.zero, source_value = false :: any, } @@ -205,12 +197,12 @@ local function spring(source: () -> T, period: number?, damping_ratio: number end -- set current position to value - local v = ... :: T + local v: T = ... :: any data.x0_123, data.x0_456 = type_to_vec6[typeof(v)](v) -- reset velocity - data.v_123 = ZERO - data.v_456 = ZERO + data.v_123 = Vector3.zero + data.v_456 = Vector3.zero -- schedule spring springs[data] = output @@ -268,13 +260,16 @@ local function update_spring_sources() 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 - -- todo: can this false positive? - if vector.magnitude(v_123 + v_456 + dx_123 + dx_456) < TOLERANCE then + local max_difference = vector.max( + vector.abs(x0_123 - x1_123 :: any), + vector.abs(x0_456 - x1_456 :: any), + vector.abs(v_123 :: any), + vector.abs(v_456 :: any), + TOLERANCE + ) + + if max_difference == TOLERANCE then -- close enough to target, unshedule spring and set value to target table.insert(remove_queue, data) output.cache = data.source_value