@quenty/spring 10.8.1 → 10.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/package.json +4 -4
- package/src/Shared/LinearValue.lua +42 -26
- package/src/Shared/Spring.lua +65 -39
- package/src/Shared/SpringUtils.lua +16 -13
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,17 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [10.8.2](https://github.com/Quenty/NevermoreEngine/compare/@quenty/spring@10.8.1...@quenty/spring@10.8.2) (2025-04-05)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
* Add types to packages ([2374fb2](https://github.com/Quenty/NevermoreEngine/commit/2374fb2b043cfbe0e9b507b3316eec46a4e353a0))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
6
17
|
## [10.8.1](https://github.com/Quenty/NevermoreEngine/compare/@quenty/spring@10.8.0...@quenty/spring@10.8.1) (2025-03-21)
|
|
7
18
|
|
|
8
19
|
**Note:** Version bump only for package @quenty/spring
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quenty/spring",
|
|
3
|
-
"version": "10.8.
|
|
3
|
+
"version": "10.8.2",
|
|
4
4
|
"description": "Spring implementation for Roblox",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Roblox",
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
"access": "public"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@quenty/ducktype": "^5.8.
|
|
33
|
-
"@quenty/loader": "^10.8.
|
|
32
|
+
"@quenty/ducktype": "^5.8.2",
|
|
33
|
+
"@quenty/loader": "^10.8.1"
|
|
34
34
|
},
|
|
35
|
-
"gitHead": "
|
|
35
|
+
"gitHead": "78c3ac0ab08dd18085b6e6e6e4f745e76ed99f68"
|
|
36
36
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
--!nocheck
|
|
1
2
|
--[=[
|
|
2
3
|
Represents a value that can operate in linear space
|
|
3
4
|
|
|
@@ -12,6 +13,14 @@ local LinearValue = {}
|
|
|
12
13
|
LinearValue.ClassName = "LinearValue"
|
|
13
14
|
LinearValue.__index = LinearValue
|
|
14
15
|
|
|
16
|
+
export type LinearValue<T> = typeof(setmetatable(
|
|
17
|
+
{} :: {
|
|
18
|
+
_constructor: (...number) -> T,
|
|
19
|
+
_values: { number },
|
|
20
|
+
},
|
|
21
|
+
LinearValue
|
|
22
|
+
))
|
|
23
|
+
|
|
15
24
|
--[=[
|
|
16
25
|
Constructs a new LinearValue object.
|
|
17
26
|
|
|
@@ -19,10 +28,10 @@ LinearValue.__index = LinearValue
|
|
|
19
28
|
@param values ({ number })
|
|
20
29
|
@return LinearValue<T>
|
|
21
30
|
]=]
|
|
22
|
-
function LinearValue.new(constructor, values)
|
|
31
|
+
function LinearValue.new<T>(constructor: (...number) -> T, values: { number }): LinearValue<T>
|
|
23
32
|
return setmetatable({
|
|
24
|
-
_constructor = constructor
|
|
25
|
-
_values = values
|
|
33
|
+
_constructor = constructor,
|
|
34
|
+
_values = values,
|
|
26
35
|
}, LinearValue)
|
|
27
36
|
end
|
|
28
37
|
|
|
@@ -32,28 +41,32 @@ end
|
|
|
32
41
|
@param value any -- A value to check
|
|
33
42
|
@return boolean -- True if a linear value, false otherwise
|
|
34
43
|
]=]
|
|
35
|
-
function LinearValue.isLinear(value)
|
|
44
|
+
function LinearValue.isLinear(value: any): boolean
|
|
36
45
|
return DuckTypeUtils.isImplementation(LinearValue, value)
|
|
37
46
|
end
|
|
38
47
|
|
|
39
|
-
local function convertUDim2(scaleX, offsetX, scaleY, offsetY)
|
|
48
|
+
local function convertUDim2(scaleX: number, offsetX: number, scaleY: number, offsetY: number): UDim2
|
|
40
49
|
-- Roblox UDim2.new(0, 9.999, 0, 9.999) rounds to UDim2.new(0, 9, 0, 9) which means small floating point
|
|
41
50
|
-- errors can cause shaking UI.
|
|
42
51
|
|
|
43
52
|
return UDim2.new(scaleX, math.round(offsetX), scaleY, math.round(offsetY))
|
|
44
53
|
end
|
|
45
54
|
|
|
46
|
-
local function convertUDim(scale, offset)
|
|
55
|
+
local function convertUDim(scale: number, offset: number): UDim
|
|
47
56
|
-- Roblox UDim.new(0, 9.999) rounds to UDim.new(0, 9) which means small floating point
|
|
48
57
|
-- errors can cause shaking UI.
|
|
49
58
|
|
|
50
59
|
return UDim.new(scale, math.round(offset))
|
|
51
60
|
end
|
|
52
61
|
|
|
53
|
-
local function convertBoolean(value)
|
|
62
|
+
local function convertBoolean(value: number): boolean
|
|
54
63
|
return value ~= 0
|
|
55
64
|
end
|
|
56
65
|
|
|
66
|
+
local function convertColor3(r: number, g: number, b: number): Color3
|
|
67
|
+
return Color3.new(r, g, b)
|
|
68
|
+
end
|
|
69
|
+
|
|
57
70
|
--[=[
|
|
58
71
|
Converts an arbitrary value to a LinearValue if Roblox has not defined this value
|
|
59
72
|
for multiplication and addition.
|
|
@@ -61,13 +74,16 @@ end
|
|
|
61
74
|
@param value T
|
|
62
75
|
@return LinearValue<T> | T
|
|
63
76
|
]=]
|
|
64
|
-
function LinearValue.toLinearIfNeeded(value)
|
|
77
|
+
function LinearValue.toLinearIfNeeded<T>(value: any): LinearValue<any>
|
|
65
78
|
if typeof(value) == "Color3" then
|
|
66
|
-
return LinearValue.new(
|
|
79
|
+
return LinearValue.new(convertColor3, { value.R, value.G, value.B })
|
|
67
80
|
elseif typeof(value) == "UDim2" then
|
|
68
|
-
return LinearValue.new(
|
|
81
|
+
return LinearValue.new(
|
|
82
|
+
convertUDim2,
|
|
83
|
+
{ value.X.Scale, math.round(value.X.Offset), value.Y.Scale, math.round(value.Y.Offset) }
|
|
84
|
+
)
|
|
69
85
|
elseif typeof(value) == "UDim" then
|
|
70
|
-
return LinearValue.new(convertUDim, {value.Scale, math.round(value.Offset)})
|
|
86
|
+
return LinearValue.new(convertUDim, { value.Scale, math.round(value.Offset) })
|
|
71
87
|
elseif type(value) == "boolean" then
|
|
72
88
|
return LinearValue.new(convertBoolean, { value and 1 or 0 })
|
|
73
89
|
else
|
|
@@ -81,7 +97,7 @@ end
|
|
|
81
97
|
@param value LinearValue<T> | any
|
|
82
98
|
@return T | any
|
|
83
99
|
]=]
|
|
84
|
-
function LinearValue.fromLinearIfNeeded(value)
|
|
100
|
+
function LinearValue.fromLinearIfNeeded<T>(value: LinearValue<T> | any): any
|
|
85
101
|
if LinearValue.isLinear(value) then
|
|
86
102
|
return value:ToBaseValue()
|
|
87
103
|
else
|
|
@@ -94,24 +110,24 @@ end
|
|
|
94
110
|
|
|
95
111
|
@return T
|
|
96
112
|
]=]
|
|
97
|
-
function LinearValue:ToBaseValue()
|
|
113
|
+
function LinearValue:ToBaseValue<T>(): T
|
|
98
114
|
return self._constructor(unpack(self._values))
|
|
99
115
|
end
|
|
100
116
|
|
|
101
|
-
local function operation(func)
|
|
102
|
-
return function(a
|
|
117
|
+
local function operation(func: (number, number) -> number)
|
|
118
|
+
return function(a: LinearValue<any>, b: LinearValue<any>)
|
|
103
119
|
if LinearValue.isLinear(a) and LinearValue.isLinear(b) then
|
|
104
120
|
assert(a._constructor == b._constructor, "a is not the same type of linearValue as b")
|
|
105
121
|
|
|
106
122
|
local values = {}
|
|
107
|
-
for i=1, #a._values do
|
|
123
|
+
for i = 1, #a._values do
|
|
108
124
|
values[i] = func(a._values[i], b._values[i])
|
|
109
125
|
end
|
|
110
126
|
return LinearValue.new(a._constructor, values)
|
|
111
127
|
elseif LinearValue.isLinear(a) then
|
|
112
128
|
if type(b) == "number" then
|
|
113
129
|
local values = {}
|
|
114
|
-
for i=1, #a._values do
|
|
130
|
+
for i = 1, #a._values do
|
|
115
131
|
values[i] = func(a._values[i], b)
|
|
116
132
|
end
|
|
117
133
|
return LinearValue.new(a._constructor, values)
|
|
@@ -121,7 +137,7 @@ local function operation(func)
|
|
|
121
137
|
elseif LinearValue.isLinear(b) then
|
|
122
138
|
if type(a) == "number" then
|
|
123
139
|
local values = {}
|
|
124
|
-
for i=1, #b._values do
|
|
140
|
+
for i = 1, #b._values do
|
|
125
141
|
values[i] = func(a, b._values[i])
|
|
126
142
|
end
|
|
127
143
|
return LinearValue.new(b._constructor, values)
|
|
@@ -139,11 +155,11 @@ end
|
|
|
139
155
|
|
|
140
156
|
@return number -- The magnitude of the linear value.
|
|
141
157
|
]=]
|
|
142
|
-
function LinearValue:GetMagnitude()
|
|
143
|
-
local dot = 0
|
|
144
|
-
for i=1, #self._values do
|
|
145
|
-
local value = self._values[i]
|
|
146
|
-
dot = dot + value*value
|
|
158
|
+
function LinearValue:GetMagnitude(): number
|
|
159
|
+
local dot: number = 0
|
|
160
|
+
for i = 1, #self._values do
|
|
161
|
+
local value: number = self._values[i]
|
|
162
|
+
dot = dot + value * value
|
|
147
163
|
end
|
|
148
164
|
return math.sqrt(dot)
|
|
149
165
|
end
|
|
@@ -155,10 +171,10 @@ end
|
|
|
155
171
|
@readonly
|
|
156
172
|
@within LinearValue
|
|
157
173
|
]=]
|
|
158
|
-
function LinearValue
|
|
174
|
+
function LinearValue.__index<T>(self: LinearValue<T>, key: string): any
|
|
159
175
|
if LinearValue[key] then
|
|
160
176
|
return LinearValue[key]
|
|
161
|
-
elseif key == "magnitude" then
|
|
177
|
+
elseif key == "magnitude" or key == "Magnitude" then
|
|
162
178
|
return self:GetMagnitude()
|
|
163
179
|
else
|
|
164
180
|
return nil
|
|
@@ -181,7 +197,7 @@ LinearValue.__div = operation(function(a, b)
|
|
|
181
197
|
return a / b
|
|
182
198
|
end)
|
|
183
199
|
|
|
184
|
-
function LinearValue:__eq(a
|
|
200
|
+
function LinearValue:__eq<T>(a: LinearValue<T>, b: LinearValue<T>): boolean
|
|
185
201
|
if LinearValue.isLinear(a) and LinearValue.isLinear(b) then
|
|
186
202
|
if #a._values ~= #b._values then
|
|
187
203
|
return false
|
package/src/Shared/Spring.lua
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
--!strict
|
|
1
2
|
--[=[
|
|
2
3
|
A physical model of a spring, useful in many applications.
|
|
3
4
|
|
|
@@ -27,6 +28,30 @@
|
|
|
27
28
|
@class Spring
|
|
28
29
|
]=]
|
|
29
30
|
local Spring = {}
|
|
31
|
+
Spring.__index = Spring
|
|
32
|
+
|
|
33
|
+
export type SpringClock = () -> number
|
|
34
|
+
|
|
35
|
+
export type Spring<T> = typeof(setmetatable(
|
|
36
|
+
{} :: {
|
|
37
|
+
Position: T,
|
|
38
|
+
Velocity: T,
|
|
39
|
+
Target: T,
|
|
40
|
+
Damper: number,
|
|
41
|
+
Speed: number,
|
|
42
|
+
Clock: SpringClock,
|
|
43
|
+
|
|
44
|
+
_position0: T,
|
|
45
|
+
_velocity0: T,
|
|
46
|
+
_time0: number,
|
|
47
|
+
_target: T,
|
|
48
|
+
_damper: number,
|
|
49
|
+
_speed: number,
|
|
50
|
+
_clock: SpringClock,
|
|
51
|
+
_positionVelocity: (self: Spring<T>, now: number) -> (T, T),
|
|
52
|
+
},
|
|
53
|
+
Spring
|
|
54
|
+
))
|
|
30
55
|
|
|
31
56
|
--[=[
|
|
32
57
|
Constructs a new Spring at the position and target specified, of type T.
|
|
@@ -46,18 +71,19 @@ local Spring = {}
|
|
|
46
71
|
@param clock? () -> number -- The clock function is optional, and is used to update the spring
|
|
47
72
|
@return Spring<T>
|
|
48
73
|
]=]
|
|
49
|
-
function Spring.new(initial
|
|
50
|
-
local
|
|
51
|
-
|
|
74
|
+
function Spring.new<T>(initial: T?, clock: SpringClock?): Spring<T>
|
|
75
|
+
local p0 = initial or 0
|
|
76
|
+
local springClock = clock or os.clock
|
|
77
|
+
|
|
52
78
|
return setmetatable({
|
|
53
|
-
_clock =
|
|
54
|
-
_time0 =
|
|
55
|
-
_position0 =
|
|
56
|
-
_velocity0 = 0*
|
|
57
|
-
_target =
|
|
58
|
-
_damper = 1
|
|
59
|
-
_speed = 1
|
|
60
|
-
}, Spring)
|
|
79
|
+
_clock = springClock,
|
|
80
|
+
_time0 = springClock(),
|
|
81
|
+
_position0 = p0,
|
|
82
|
+
_velocity0 = 0 * (p0 :: any),
|
|
83
|
+
_target = p0,
|
|
84
|
+
_damper = 1,
|
|
85
|
+
_speed = 1,
|
|
86
|
+
}, Spring) :: any
|
|
61
87
|
end
|
|
62
88
|
|
|
63
89
|
--[=[
|
|
@@ -67,8 +93,8 @@ end
|
|
|
67
93
|
@param velocity T -- The velocity to impulse with
|
|
68
94
|
@return ()
|
|
69
95
|
]=]
|
|
70
|
-
function Spring
|
|
71
|
-
self.Velocity = self.Velocity + velocity
|
|
96
|
+
function Spring.Impulse<T>(self: Spring<T>, velocity: T)
|
|
97
|
+
self.Velocity = (self.Velocity :: any) + velocity
|
|
72
98
|
end
|
|
73
99
|
|
|
74
100
|
--[=[
|
|
@@ -76,9 +102,9 @@ end
|
|
|
76
102
|
@param delta number -- Time to skip forwards
|
|
77
103
|
@return ()
|
|
78
104
|
]=]
|
|
79
|
-
function Spring
|
|
105
|
+
function Spring.TimeSkip<T>(self: Spring<T>, delta: number)
|
|
80
106
|
local now = self._clock()
|
|
81
|
-
local position, velocity = self:_positionVelocity(now+delta)
|
|
107
|
+
local position, velocity = self:_positionVelocity(now + delta)
|
|
82
108
|
self._position0 = position
|
|
83
109
|
self._velocity0 = velocity
|
|
84
110
|
self._time0 = now
|
|
@@ -90,11 +116,11 @@ end
|
|
|
90
116
|
@param value T -- The target to set
|
|
91
117
|
@param doNotAnimate boolean? -- Whether or not to animate
|
|
92
118
|
]=]
|
|
93
|
-
function Spring
|
|
119
|
+
function Spring.SetTarget<T>(self: Spring<T>, value: T, doNotAnimate: boolean?)
|
|
94
120
|
if doNotAnimate then
|
|
95
121
|
local now = self._clock()
|
|
96
122
|
self._position0 = value
|
|
97
|
-
self._velocity0 = 0*value
|
|
123
|
+
self._velocity0 = 0 * (value :: any)
|
|
98
124
|
self._target = value
|
|
99
125
|
self._time0 = now
|
|
100
126
|
else
|
|
@@ -183,7 +209,7 @@ end
|
|
|
183
209
|
@prop Clock () -> number
|
|
184
210
|
@within Spring
|
|
185
211
|
]=]
|
|
186
|
-
function Spring:
|
|
212
|
+
(Spring :: any).__index = function<T>(self: Spring<T>, index: any): any
|
|
187
213
|
if Spring[index] then
|
|
188
214
|
return Spring[index]
|
|
189
215
|
elseif index == "Value" or index == "Position" or index == "p" then
|
|
@@ -205,7 +231,7 @@ function Spring:__index(index)
|
|
|
205
231
|
end
|
|
206
232
|
end
|
|
207
233
|
|
|
208
|
-
function Spring
|
|
234
|
+
function Spring.__newindex<T>(self: Spring<T>, index, value)
|
|
209
235
|
local now = self._clock()
|
|
210
236
|
|
|
211
237
|
if index == "Value" or index == "Position" or index == "p" then
|
|
@@ -247,43 +273,43 @@ function Spring:__newindex(index, value)
|
|
|
247
273
|
end
|
|
248
274
|
end
|
|
249
275
|
|
|
250
|
-
function Spring
|
|
276
|
+
function Spring._positionVelocity<T>(self: Spring<T>, now: number): (T, T)
|
|
251
277
|
local p0 = self._position0
|
|
252
278
|
local v0 = self._velocity0
|
|
253
279
|
local p1 = self._target
|
|
254
|
-
local d = self._damper
|
|
255
|
-
local s = self._speed
|
|
280
|
+
local d: number = self._damper
|
|
281
|
+
local s: number = self._speed
|
|
256
282
|
|
|
257
|
-
local t = s*(now - self._time0)
|
|
258
|
-
local d2 = d*d
|
|
283
|
+
local t: number = s * (now - self._time0)
|
|
284
|
+
local d2 = d * d
|
|
259
285
|
|
|
260
286
|
local h, si, co
|
|
261
287
|
if d2 < 1 then
|
|
262
288
|
h = math.sqrt(1 - d2)
|
|
263
|
-
local ep = math.exp(-d*t)/h
|
|
264
|
-
co, si = ep*math.cos(h*t), ep*math.sin(h*t)
|
|
289
|
+
local ep = math.exp(-d * t) / h
|
|
290
|
+
co, si = ep * math.cos(h * t), ep * math.sin(h * t)
|
|
265
291
|
elseif d2 == 1 then
|
|
266
292
|
h = 1
|
|
267
|
-
local ep = math.exp(-d*t)/h
|
|
268
|
-
co, si = ep, ep*t
|
|
293
|
+
local ep = math.exp(-d * t) / h
|
|
294
|
+
co, si = ep, ep * t
|
|
269
295
|
else
|
|
270
296
|
h = math.sqrt(d2 - 1)
|
|
271
|
-
local u = math.exp((-d + h)*t)/(2*h)
|
|
272
|
-
local v = math.exp((-d - h)*t)/(2*h)
|
|
297
|
+
local u = math.exp((-d + h) * t) / (2 * h)
|
|
298
|
+
local v = math.exp((-d - h) * t) / (2 * h)
|
|
273
299
|
co, si = u + v, u - v
|
|
274
300
|
end
|
|
275
301
|
|
|
276
|
-
local a0 = h*co + d*si
|
|
277
|
-
local a1 = 1 - (h*co + d*si)
|
|
278
|
-
local a2 = si/s
|
|
302
|
+
local a0: any = h * co + d * si
|
|
303
|
+
local a1: any = 1 - (h * co + d * si)
|
|
304
|
+
local a2: any = si / s
|
|
279
305
|
|
|
280
|
-
local b0 = -s*si
|
|
281
|
-
local b1 = s*si
|
|
282
|
-
local b2 = h*co - d*si
|
|
306
|
+
local b0: any = -s * si
|
|
307
|
+
local b1: any = s * si
|
|
308
|
+
local b2: any = h * co - d * si
|
|
283
309
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
b0*p0 + b1*p1 + b2*v0
|
|
310
|
+
-- stylua: ignore
|
|
311
|
+
return a0 * p0 + a1 * p1 + a2 * v0,
|
|
312
|
+
b0 * p0 + b1 * p1 + b2 * v0
|
|
287
313
|
end
|
|
288
314
|
|
|
289
315
|
return Spring
|
|
@@ -1,15 +1,18 @@
|
|
|
1
|
+
--!strict
|
|
1
2
|
--[=[
|
|
2
3
|
Utility functions that are related to the Spring object
|
|
3
4
|
@class SpringUtils
|
|
4
5
|
]=]
|
|
5
6
|
|
|
6
|
-
local EPSILON = 1e-6
|
|
7
|
-
|
|
8
7
|
local require = require(script.Parent.loader).load(script)
|
|
8
|
+
|
|
9
9
|
local LinearValue = require("LinearValue")
|
|
10
|
+
local _Spring = require("Spring")
|
|
10
11
|
|
|
11
12
|
local SpringUtils = {}
|
|
12
13
|
|
|
14
|
+
local EPSILON = 1e-6
|
|
15
|
+
|
|
13
16
|
--[=[
|
|
14
17
|
Utility function that returns whether or not a spring is animating based upon
|
|
15
18
|
velocity and closeness to target, and as the second value, the value that should be
|
|
@@ -19,21 +22,21 @@ local SpringUtils = {}
|
|
|
19
22
|
@param epsilon number? -- Optional epsilon
|
|
20
23
|
@return boolean, T
|
|
21
24
|
]=]
|
|
22
|
-
function SpringUtils.animating(spring
|
|
23
|
-
|
|
25
|
+
function SpringUtils.animating<T>(spring: _Spring.Spring<T>, epsilon: number?): (boolean, T)
|
|
26
|
+
local thisEpsilon = epsilon or EPSILON
|
|
24
27
|
|
|
25
28
|
local position = spring.Position
|
|
26
29
|
local target = spring.Target
|
|
27
30
|
|
|
28
31
|
local animating
|
|
29
32
|
if type(target) == "number" then
|
|
30
|
-
animating = math.abs(spring.Position - spring.Target) >
|
|
31
|
-
or math.abs(spring.Velocity) >
|
|
33
|
+
animating = math.abs((spring :: any).Position - (spring :: any).Target) > thisEpsilon
|
|
34
|
+
or math.abs((spring :: any).Velocity) > thisEpsilon
|
|
32
35
|
else
|
|
33
36
|
local rbxtype = typeof(target)
|
|
34
37
|
if rbxtype == "Vector3" or rbxtype == "Vector2" or LinearValue.isLinear(target) then
|
|
35
|
-
animating = (spring.Position - spring.Target).magnitude >
|
|
36
|
-
or spring.Velocity.magnitude >
|
|
38
|
+
animating = ((spring :: any).Position - (spring :: any).Target).magnitude > thisEpsilon
|
|
39
|
+
or (spring :: any).Velocity.magnitude > thisEpsilon
|
|
37
40
|
else
|
|
38
41
|
error("Unknown type")
|
|
39
42
|
end
|
|
@@ -42,7 +45,7 @@ function SpringUtils.animating(spring, epsilon)
|
|
|
42
45
|
if animating then
|
|
43
46
|
return true, position
|
|
44
47
|
else
|
|
45
|
-
-- We need to return the target so we use the actual target value (i.e. pretend like the spring is asleep)
|
|
48
|
+
-- We need to return the target so we use the actual target value (i.e. pretend like the (spring :: any) is asleep)
|
|
46
49
|
return false, target
|
|
47
50
|
end
|
|
48
51
|
end
|
|
@@ -55,12 +58,12 @@ end
|
|
|
55
58
|
@param speed number
|
|
56
59
|
@return T
|
|
57
60
|
]=]
|
|
58
|
-
function SpringUtils.getVelocityAdjustment(velocity, dampen, speed)
|
|
61
|
+
function SpringUtils.getVelocityAdjustment<T>(velocity: T, dampen: number, speed: number): T
|
|
59
62
|
assert(velocity, "Bad velocity")
|
|
60
63
|
assert(dampen, "Bad dampen")
|
|
61
64
|
assert(speed, "Bad speed")
|
|
62
65
|
|
|
63
|
-
return velocity*(2*dampen/speed)
|
|
66
|
+
return (velocity :: any) * (2 * dampen / speed)
|
|
64
67
|
end
|
|
65
68
|
|
|
66
69
|
--[=[
|
|
@@ -70,7 +73,7 @@ end
|
|
|
70
73
|
@param value T
|
|
71
74
|
@return LinearValue<T> | T
|
|
72
75
|
]=]
|
|
73
|
-
function SpringUtils.toLinearIfNeeded(value)
|
|
76
|
+
function SpringUtils.toLinearIfNeeded<T>(value: T): LinearValue.LinearValue<T> | T
|
|
74
77
|
return LinearValue.toLinearIfNeeded(value)
|
|
75
78
|
end
|
|
76
79
|
|
|
@@ -80,7 +83,7 @@ end
|
|
|
80
83
|
@param value LinearValue<T> | any
|
|
81
84
|
@return T | any
|
|
82
85
|
]=]
|
|
83
|
-
function SpringUtils.fromLinearIfNeeded(value)
|
|
86
|
+
function SpringUtils.fromLinearIfNeeded<T>(value: LinearValue.LinearValue<T> | T): T
|
|
84
87
|
return LinearValue.fromLinearIfNeeded(value)
|
|
85
88
|
end
|
|
86
89
|
|