@quenty/blend 12.4.0 → 12.5.1-canary.496.cb49bdf.0
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 +28 -0
- package/package.json +18 -18
- package/src/Shared/Blend/Blend.lua +6 -43
- package/src/Shared/Blend/SpringObject.lua +275 -81
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,34 @@
|
|
|
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
|
+
## [12.5.1-canary.496.cb49bdf.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/blend@12.5.0...@quenty/blend@12.5.1-canary.496.cb49bdf.0) (2024-09-20)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
* SpringObject initializes properly in Blend ([8729989](https://github.com/Quenty/NevermoreEngine/commit/8729989788b482b3a4f0da223e2f2d49c12ff707))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# [12.5.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/blend@12.4.0...@quenty/blend@12.5.0) (2024-09-12)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Bug Fixes
|
|
21
|
+
|
|
22
|
+
* Blend spring uses a default spring object, fixing any errors ([d468636](https://github.com/Quenty/NevermoreEngine/commit/d468636dc58f951fbfc565d4a6b68c79483e379a))
|
|
23
|
+
* Fix some spring object stuff ([34e8ede](https://github.com/Quenty/NevermoreEngine/commit/34e8edee97fa93a0a5bd84442b85826082444f2a))
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
### Features
|
|
27
|
+
|
|
28
|
+
* Update Blend.Spring to use SpringObject underneath ([b5d41f5](https://github.com/Quenty/NevermoreEngine/commit/b5d41f5b6955fc77bd37d9ec97b9704410c7c3f5))
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
6
34
|
# [12.4.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/blend@12.3.0...@quenty/blend@12.4.0) (2024-08-09)
|
|
7
35
|
|
|
8
36
|
**Note:** Version bump only for package @quenty/blend
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quenty/blend",
|
|
3
|
-
"version": "12.
|
|
3
|
+
"version": "12.5.1-canary.496.cb49bdf.0",
|
|
4
4
|
"description": "Declarative UI system.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Roblox",
|
|
@@ -27,24 +27,24 @@
|
|
|
27
27
|
"access": "public"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@quenty/acceltween": "
|
|
31
|
-
"@quenty/brio": "
|
|
32
|
-
"@quenty/ducktype": "
|
|
33
|
-
"@quenty/instanceutils": "
|
|
34
|
-
"@quenty/loader": "
|
|
35
|
-
"@quenty/maid": "
|
|
36
|
-
"@quenty/promise": "
|
|
37
|
-
"@quenty/rx": "
|
|
38
|
-
"@quenty/signal": "
|
|
39
|
-
"@quenty/spring": "
|
|
40
|
-
"@quenty/steputils": "
|
|
41
|
-
"@quenty/string": "
|
|
42
|
-
"@quenty/valuebaseutils": "
|
|
43
|
-
"@quenty/valueobject": "
|
|
30
|
+
"@quenty/acceltween": "2.5.0",
|
|
31
|
+
"@quenty/brio": "14.5.0",
|
|
32
|
+
"@quenty/ducktype": "5.4.0",
|
|
33
|
+
"@quenty/instanceutils": "13.5.0",
|
|
34
|
+
"@quenty/loader": "10.4.0",
|
|
35
|
+
"@quenty/maid": "3.3.0",
|
|
36
|
+
"@quenty/promise": "10.4.0",
|
|
37
|
+
"@quenty/rx": "13.5.0",
|
|
38
|
+
"@quenty/signal": "7.4.0",
|
|
39
|
+
"@quenty/spring": "10.4.0",
|
|
40
|
+
"@quenty/steputils": "3.4.0",
|
|
41
|
+
"@quenty/string": "3.2.0",
|
|
42
|
+
"@quenty/valuebaseutils": "13.5.0",
|
|
43
|
+
"@quenty/valueobject": "13.5.0"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
|
-
"@quenty/contentproviderutils": "
|
|
47
|
-
"@quenty/playerthumbnailutils": "
|
|
46
|
+
"@quenty/contentproviderutils": "12.5.0",
|
|
47
|
+
"@quenty/playerthumbnailutils": "10.4.0"
|
|
48
48
|
},
|
|
49
|
-
"gitHead": "
|
|
49
|
+
"gitHead": "cb49bdf8d79aac6e6901901c914271148df358b2"
|
|
50
50
|
}
|
|
@@ -17,13 +17,12 @@ local BrioUtils = require("BrioUtils")
|
|
|
17
17
|
local RxInstanceUtils = require("RxInstanceUtils")
|
|
18
18
|
local RxValueBaseUtils = require("RxValueBaseUtils")
|
|
19
19
|
local Signal = require("Signal")
|
|
20
|
-
local Spring = require("Spring")
|
|
21
|
-
local SpringUtils = require("SpringUtils")
|
|
22
20
|
local StepUtils = require("StepUtils")
|
|
23
21
|
local ValueBaseUtils = require("ValueBaseUtils")
|
|
24
22
|
local ValueObject = require("ValueObject")
|
|
25
23
|
local ValueObjectUtils = require("ValueObjectUtils")
|
|
26
24
|
local RxBrioUtils = require("RxBrioUtils")
|
|
25
|
+
local SpringObject
|
|
27
26
|
|
|
28
27
|
local Blend = {}
|
|
29
28
|
|
|
@@ -410,53 +409,17 @@ end
|
|
|
410
409
|
@return Observable?
|
|
411
410
|
]=]
|
|
412
411
|
function Blend.Spring(source, speed, damper)
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
local damperObservable = Blend.toNumberObservable(damper)
|
|
416
|
-
|
|
417
|
-
local function createSpring(maid, initialValue)
|
|
418
|
-
local spring = Spring.new(initialValue)
|
|
419
|
-
|
|
420
|
-
if speedObservable then
|
|
421
|
-
maid:GiveTask(speedObservable:Subscribe(function(value)
|
|
422
|
-
assert(type(value) == "number", "Bad value")
|
|
423
|
-
spring.Speed = value
|
|
424
|
-
end))
|
|
425
|
-
end
|
|
426
|
-
|
|
427
|
-
if damperObservable then
|
|
428
|
-
maid:GiveTask(damperObservable:Subscribe(function(value)
|
|
429
|
-
assert(type(value) == "number", "Bad value")
|
|
430
|
-
|
|
431
|
-
spring.Damper = value
|
|
432
|
-
end))
|
|
433
|
-
end
|
|
434
|
-
|
|
435
|
-
return spring
|
|
412
|
+
if not SpringObject then
|
|
413
|
+
SpringObject = require("SpringObject")
|
|
436
414
|
end
|
|
437
415
|
|
|
438
|
-
-- TODO: Centralize and cache
|
|
439
416
|
return Observable.new(function(sub)
|
|
440
|
-
local spring
|
|
441
417
|
local maid = Maid.new()
|
|
442
418
|
|
|
443
|
-
local
|
|
444
|
-
|
|
445
|
-
sub:Fire(SpringUtils.fromLinearIfNeeded(position))
|
|
446
|
-
return animating
|
|
447
|
-
end)
|
|
419
|
+
local spring = maid:Add(SpringObject.new(source, speed, damper))
|
|
420
|
+
spring.Epsilon = 1e-3
|
|
448
421
|
|
|
449
|
-
maid:GiveTask(
|
|
450
|
-
maid:GiveTask(sourceObservable:Subscribe(function(value)
|
|
451
|
-
if value then
|
|
452
|
-
local linearValue = SpringUtils.toLinearIfNeeded(value)
|
|
453
|
-
spring = spring or createSpring(maid, linearValue)
|
|
454
|
-
spring.t = SpringUtils.toLinearIfNeeded(value)
|
|
455
|
-
startAnimate()
|
|
456
|
-
else
|
|
457
|
-
warn("Got nil value from emitted source")
|
|
458
|
-
end
|
|
459
|
-
end))
|
|
422
|
+
maid:GiveTask(spring:Observe():Subscribe(sub:GetFireFailComplete()))
|
|
460
423
|
|
|
461
424
|
return maid
|
|
462
425
|
end)
|
|
@@ -25,6 +25,13 @@ SpringObject.__index = SpringObject
|
|
|
25
25
|
|
|
26
26
|
--[=[
|
|
27
27
|
Constructs a new SpringObject.
|
|
28
|
+
|
|
29
|
+
The spring object is initially initialized as a spring at 0, with a target of 0. Upon setting
|
|
30
|
+
a target or position, it will be initialized and begin emitting events.
|
|
31
|
+
|
|
32
|
+
If two observables emit different types the spring will retain the speed, damper, and switch to
|
|
33
|
+
an initializes.
|
|
34
|
+
|
|
28
35
|
@param target T
|
|
29
36
|
@param speed number | Observable<number> | ValueObject<number> | NumberValue | any
|
|
30
37
|
@param damper number | Observable<number> | NumberValue | any
|
|
@@ -45,9 +52,7 @@ function SpringObject.new(target, speed, damper)
|
|
|
45
52
|
self._maid:GiveTask(self.Changed)
|
|
46
53
|
|
|
47
54
|
if target then
|
|
48
|
-
self
|
|
49
|
-
else
|
|
50
|
-
self:_getSpringForType(0)
|
|
55
|
+
self:SetTarget(target)
|
|
51
56
|
end
|
|
52
57
|
|
|
53
58
|
if speed then
|
|
@@ -131,15 +136,20 @@ function SpringObject:PromiseFinished(signal)
|
|
|
131
136
|
signal = signal or RunService.RenderStepped
|
|
132
137
|
|
|
133
138
|
local maid = Maid.new()
|
|
134
|
-
local promise = Promise.new()
|
|
135
|
-
maid:GiveTask(promise)
|
|
139
|
+
local promise = maid:Add(Promise.new())
|
|
136
140
|
|
|
137
141
|
-- TODO: Mathematical solution?
|
|
138
142
|
local startAnimate, stopAnimate = StepUtils.bindToSignal(signal, function()
|
|
139
|
-
local
|
|
143
|
+
local currentSpring = rawget(self, "_currentSpring")
|
|
144
|
+
if not currentSpring then
|
|
145
|
+
return false
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
local animating = SpringUtils.animating(currentSpring, self._epsilon)
|
|
140
149
|
if not animating then
|
|
141
150
|
promise:Resolve(true)
|
|
142
151
|
end
|
|
152
|
+
|
|
143
153
|
return animating
|
|
144
154
|
end)
|
|
145
155
|
|
|
@@ -165,12 +175,18 @@ function SpringObject:ObserveVelocityOnSignal(signal)
|
|
|
165
175
|
local maid = Maid.new()
|
|
166
176
|
|
|
167
177
|
local startAnimate, stopAnimate = StepUtils.bindToSignal(signal, function()
|
|
168
|
-
local
|
|
178
|
+
local currentSpring = rawget(self, "_currentSpring")
|
|
179
|
+
if not currentSpring then
|
|
180
|
+
return false
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
local animating = SpringUtils.animating(currentSpring, self._epsilon)
|
|
169
184
|
if animating then
|
|
170
|
-
sub:Fire(SpringUtils.fromLinearIfNeeded(
|
|
185
|
+
sub:Fire(SpringUtils.fromLinearIfNeeded(currentSpring.Velocity))
|
|
171
186
|
else
|
|
172
|
-
sub:Fire(SpringUtils.fromLinearIfNeeded(0*
|
|
187
|
+
sub:Fire(SpringUtils.fromLinearIfNeeded(0*currentSpring.Velocity))
|
|
173
188
|
end
|
|
189
|
+
|
|
174
190
|
return animating
|
|
175
191
|
end)
|
|
176
192
|
|
|
@@ -192,7 +208,12 @@ function SpringObject:ObserveOnSignal(signal)
|
|
|
192
208
|
local maid = Maid.new()
|
|
193
209
|
|
|
194
210
|
local startAnimate, stopAnimate = StepUtils.bindToSignal(signal, function()
|
|
195
|
-
local
|
|
211
|
+
local currentSpring = rawget(self, "_currentSpring")
|
|
212
|
+
if not currentSpring then
|
|
213
|
+
return false
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
local animating, position = SpringUtils.animating(currentSpring, self._epsilon)
|
|
196
217
|
sub:Fire(SpringUtils.fromLinearIfNeeded(position))
|
|
197
218
|
return animating
|
|
198
219
|
end)
|
|
@@ -210,7 +231,12 @@ end
|
|
|
210
231
|
@return boolean -- True if animating
|
|
211
232
|
]=]
|
|
212
233
|
function SpringObject:IsAnimating()
|
|
213
|
-
|
|
234
|
+
local currentSpring = rawget(self, "_currentSpring")
|
|
235
|
+
if not currentSpring then
|
|
236
|
+
return false
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
return (SpringUtils.animating(currentSpring, self._epsilon))
|
|
214
240
|
end
|
|
215
241
|
|
|
216
242
|
--[=[
|
|
@@ -221,26 +247,29 @@ end
|
|
|
221
247
|
@return ()
|
|
222
248
|
]=]
|
|
223
249
|
function SpringObject:Impulse(velocity)
|
|
224
|
-
|
|
250
|
+
local converted = SpringUtils.toLinearIfNeeded(velocity)
|
|
251
|
+
local currentSpring = self:_getSpringForType(velocity)
|
|
252
|
+
currentSpring:Impulse(converted)
|
|
225
253
|
self.Changed:Fire()
|
|
226
254
|
end
|
|
227
255
|
|
|
228
256
|
--[=[
|
|
229
257
|
Sets the actual target. If doNotAnimate is set, then animation will be skipped.
|
|
230
258
|
|
|
231
|
-
@param
|
|
259
|
+
@param target T -- The target to set
|
|
232
260
|
@param doNotAnimate boolean? -- Whether or not to animate
|
|
233
|
-
@return ()
|
|
234
261
|
]=]
|
|
235
|
-
function SpringObject:SetTarget(
|
|
236
|
-
|
|
262
|
+
function SpringObject:SetTarget(target, doNotAnimate)
|
|
263
|
+
assert(target ~= nil, "Bad target")
|
|
264
|
+
|
|
265
|
+
local observable = Blend.toPropertyObservable(target) or Rx.of(target)
|
|
237
266
|
|
|
238
267
|
if doNotAnimate then
|
|
239
268
|
local isFirst = true
|
|
240
269
|
|
|
241
270
|
self._maid._targetSub = observable:Subscribe(function(unconverted)
|
|
242
271
|
local converted = SpringUtils.toLinearIfNeeded(unconverted)
|
|
243
|
-
assert(converted, "Not a valid converted
|
|
272
|
+
assert(converted, "Not a valid converted target")
|
|
244
273
|
|
|
245
274
|
local spring = self:_getSpringForType(converted)
|
|
246
275
|
spring:SetTarget(converted, isFirst)
|
|
@@ -252,12 +281,125 @@ function SpringObject:SetTarget(value, doNotAnimate)
|
|
|
252
281
|
self._maid._targetSub = observable:Subscribe(function(unconverted)
|
|
253
282
|
local converted = SpringUtils.toLinearIfNeeded(unconverted)
|
|
254
283
|
self:_getSpringForType(converted).Target = converted
|
|
255
|
-
|
|
256
284
|
self.Changed:Fire()
|
|
257
285
|
end)
|
|
258
286
|
end
|
|
259
287
|
end
|
|
260
288
|
|
|
289
|
+
--[=[
|
|
290
|
+
Sets the velocity for the spring
|
|
291
|
+
|
|
292
|
+
@param velocity T
|
|
293
|
+
]=]
|
|
294
|
+
function SpringObject:SetVelocity(velocity)
|
|
295
|
+
assert(velocity ~= nil, "Bad velocity")
|
|
296
|
+
|
|
297
|
+
local observable = Blend.toPropertyObservable(velocity) or Rx.of(velocity)
|
|
298
|
+
|
|
299
|
+
self._maid._velocitySub = observable:Subscribe(function(unconverted)
|
|
300
|
+
local converted = SpringUtils.toLinearIfNeeded(unconverted)
|
|
301
|
+
|
|
302
|
+
self:_getSpringForType(0*converted).Velocity = converted
|
|
303
|
+
self.Changed:Fire()
|
|
304
|
+
end)
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
--[=[
|
|
308
|
+
Sets the position for the spring
|
|
309
|
+
|
|
310
|
+
@param position T
|
|
311
|
+
]=]
|
|
312
|
+
function SpringObject:SetPosition(position)
|
|
313
|
+
assert(position ~= nil, "Bad position")
|
|
314
|
+
|
|
315
|
+
local observable = Blend.toPropertyObservable(position) or Rx.of(position)
|
|
316
|
+
|
|
317
|
+
self._maid._positionSub = observable:Subscribe(function(unconverted)
|
|
318
|
+
local converted = SpringUtils.toLinearIfNeeded(unconverted)
|
|
319
|
+
self:_getSpringForType(converted).Value = converted
|
|
320
|
+
self.Changed:Fire()
|
|
321
|
+
end)
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
--[=[
|
|
325
|
+
Sets the damper for the spring
|
|
326
|
+
|
|
327
|
+
@param damper number | Observable<number>
|
|
328
|
+
]=]
|
|
329
|
+
function SpringObject:SetDamper(damper)
|
|
330
|
+
assert(damper ~= nil, "Bad damper")
|
|
331
|
+
|
|
332
|
+
local observable = assert(Blend.toNumberObservable(damper), "Invalid damper")
|
|
333
|
+
|
|
334
|
+
self._maid._damperSub = observable:Subscribe(function(unconverted)
|
|
335
|
+
assert(type(unconverted) == "number", "Bad damper")
|
|
336
|
+
|
|
337
|
+
local currentSpring = rawget(self, "_currentSpring")
|
|
338
|
+
if currentSpring then
|
|
339
|
+
currentSpring.Damper = unconverted
|
|
340
|
+
else
|
|
341
|
+
self:_getInitInfo().Damper = unconverted
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
self.Changed:Fire()
|
|
345
|
+
end)
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
--[=[
|
|
349
|
+
Sets the damper for the spring
|
|
350
|
+
|
|
351
|
+
@param speed number | Observable<number>
|
|
352
|
+
]=]
|
|
353
|
+
function SpringObject:SetSpeed(speed)
|
|
354
|
+
assert(speed ~= nil, "Bad speed")
|
|
355
|
+
|
|
356
|
+
local observable = assert(Blend.toNumberObservable(speed), "Invalid speed")
|
|
357
|
+
|
|
358
|
+
self._maid._speedSub = observable:Subscribe(function(unconverted)
|
|
359
|
+
assert(type(unconverted) == "number", "Bad damper")
|
|
360
|
+
|
|
361
|
+
local currentSpring = rawget(self, "_currentSpring")
|
|
362
|
+
if currentSpring then
|
|
363
|
+
currentSpring.Speed = unconverted
|
|
364
|
+
else
|
|
365
|
+
self:_getInitInfo().Speed = unconverted
|
|
366
|
+
end
|
|
367
|
+
|
|
368
|
+
self.Changed:Fire()
|
|
369
|
+
end)
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
--[=[
|
|
373
|
+
Sets the clock function for the spring
|
|
374
|
+
|
|
375
|
+
@param clock () -> (number)
|
|
376
|
+
]=]
|
|
377
|
+
function SpringObject:SetClock(clock)
|
|
378
|
+
assert(type(clock) == "function", "Bad clock clock")
|
|
379
|
+
|
|
380
|
+
local currentSpring = rawget(self, "_currentSpring")
|
|
381
|
+
if currentSpring then
|
|
382
|
+
currentSpring.Clock = clock
|
|
383
|
+
else
|
|
384
|
+
self:_getInitInfo().Clock = clock
|
|
385
|
+
end
|
|
386
|
+
|
|
387
|
+
self.Changed:Fire()
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
--[=[
|
|
391
|
+
Sets the epsilon for the spring to stop animating
|
|
392
|
+
|
|
393
|
+
@param epsilon number
|
|
394
|
+
]=]
|
|
395
|
+
function SpringObject:SetEpsilon(epsilon)
|
|
396
|
+
assert(type(epsilon) == "number", "Bad epsilon")
|
|
397
|
+
|
|
398
|
+
rawset(self, "_epsilon", epsilon)
|
|
399
|
+
|
|
400
|
+
self.Changed:Fire()
|
|
401
|
+
end
|
|
402
|
+
|
|
261
403
|
--[=[
|
|
262
404
|
Instantly skips the spring forwards by that amount time
|
|
263
405
|
@param delta number -- Time to skip forwards
|
|
@@ -266,105 +408,157 @@ end
|
|
|
266
408
|
function SpringObject:TimeSkip(delta)
|
|
267
409
|
assert(type(delta) == "number", "Bad delta")
|
|
268
410
|
|
|
269
|
-
self
|
|
411
|
+
local currentSpring = rawget(self, "_currentSpring")
|
|
412
|
+
if not currentSpring then
|
|
413
|
+
return
|
|
414
|
+
end
|
|
415
|
+
|
|
416
|
+
currentSpring:TimeSkip(delta)
|
|
270
417
|
self.Changed:Fire()
|
|
271
418
|
end
|
|
272
419
|
|
|
273
420
|
function SpringObject:__index(index)
|
|
274
|
-
|
|
275
|
-
|
|
421
|
+
local currentSpring = rawget(self, "_currentSpring")
|
|
422
|
+
|
|
423
|
+
if SpringObject[index] then
|
|
424
|
+
return SpringObject[index]
|
|
425
|
+
elseif index == "Value" or index == "Position" or index == "p" then
|
|
426
|
+
if currentSpring then
|
|
427
|
+
return SpringUtils.fromLinearIfNeeded(currentSpring.Value)
|
|
428
|
+
else
|
|
429
|
+
return 0
|
|
430
|
+
end
|
|
276
431
|
elseif index == "Velocity" or index == "v" then
|
|
277
|
-
|
|
432
|
+
if currentSpring then
|
|
433
|
+
return SpringUtils.fromLinearIfNeeded(currentSpring.Velocity)
|
|
434
|
+
else
|
|
435
|
+
return 0
|
|
436
|
+
end
|
|
278
437
|
elseif index == "Target" or index == "t" then
|
|
279
|
-
|
|
438
|
+
if currentSpring then
|
|
439
|
+
return SpringUtils.fromLinearIfNeeded(currentSpring.Target)
|
|
440
|
+
else
|
|
441
|
+
return 0
|
|
442
|
+
end
|
|
280
443
|
elseif index == "Damper" or index == "d" then
|
|
281
|
-
|
|
444
|
+
if currentSpring then
|
|
445
|
+
return currentSpring.Damper
|
|
446
|
+
else
|
|
447
|
+
return self:_getInitInfo().Damper
|
|
448
|
+
end
|
|
282
449
|
elseif index == "Speed" or index == "s" then
|
|
283
|
-
|
|
450
|
+
if currentSpring then
|
|
451
|
+
return currentSpring.Speed
|
|
452
|
+
else
|
|
453
|
+
return self:_getInitInfo().Speed
|
|
454
|
+
end
|
|
284
455
|
elseif index == "Clock" then
|
|
285
|
-
|
|
456
|
+
if currentSpring then
|
|
457
|
+
return currentSpring.Clock
|
|
458
|
+
else
|
|
459
|
+
return self:_getInitInfo().Clock
|
|
460
|
+
end
|
|
286
461
|
elseif index == "Epsilon" then
|
|
287
462
|
return self._epsilon
|
|
288
|
-
elseif
|
|
289
|
-
|
|
463
|
+
elseif index == "_currentSpring" then
|
|
464
|
+
local found = rawget(self, "_currentSpring")
|
|
465
|
+
if found then
|
|
466
|
+
return found
|
|
467
|
+
end
|
|
468
|
+
|
|
469
|
+
-- Note that sometimes the current spring isn't loaded yet as a type so
|
|
470
|
+
-- we use a number for this.
|
|
471
|
+
error("Internal error: Cannot get _currentSpring, as we aren't initialized yet")
|
|
290
472
|
else
|
|
291
|
-
error(("%q is not a member of SpringObject"
|
|
473
|
+
error(string.format("%q is not a member of SpringObject", tostring(index)))
|
|
292
474
|
end
|
|
293
475
|
end
|
|
294
476
|
|
|
295
477
|
function SpringObject:__newindex(index, value)
|
|
296
478
|
if index == "Value" or index == "Position" or index == "p" then
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
self._maid._valueSub = observable:Subscribe(function(unconverted)
|
|
300
|
-
local converted = SpringUtils.toLinearIfNeeded(unconverted)
|
|
301
|
-
self:_getSpringForType(converted).Value = converted
|
|
302
|
-
self.Changed:Fire()
|
|
303
|
-
end)
|
|
479
|
+
self:SetPosition(value)
|
|
304
480
|
elseif index == "Velocity" or index == "v" then
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
self._maid._velocitySub = observable:Subscribe(function(unconverted)
|
|
308
|
-
local converted = SpringUtils.toLinearIfNeeded(unconverted)
|
|
309
|
-
|
|
310
|
-
self:_getSpringForType(0*converted).Velocity = converted
|
|
311
|
-
self.Changed:Fire()
|
|
312
|
-
end)
|
|
481
|
+
self:SetVelocity(value)
|
|
313
482
|
elseif index == "Target" or index == "t" then
|
|
314
483
|
self:SetTarget(value)
|
|
315
484
|
elseif index == "Damper" or index == "d" then
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
self._maid._damperSub = observable:Subscribe(function(unconverted)
|
|
319
|
-
assert(type(unconverted) == "number", "Bad damper")
|
|
320
|
-
|
|
321
|
-
self._currentSpring.Damper = unconverted
|
|
322
|
-
self.Changed:Fire()
|
|
323
|
-
end)
|
|
485
|
+
self:SetDamper(value)
|
|
324
486
|
elseif index == "Speed" or index == "s" then
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
self._maid._speedSub = observable:Subscribe(function(unconverted)
|
|
328
|
-
assert(type(unconverted) == "number", "Bad damper")
|
|
329
|
-
|
|
330
|
-
self._currentSpring.Speed = unconverted
|
|
331
|
-
self.Changed:Fire()
|
|
332
|
-
end)
|
|
333
|
-
elseif index == "Epsilon" then
|
|
334
|
-
assert(type(value) == "number", "Bad value")
|
|
335
|
-
rawset(self, "_epsilon", value)
|
|
487
|
+
self:SetSpeed(value)
|
|
336
488
|
elseif index == "Clock" then
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
self
|
|
489
|
+
self:SetClock(value)
|
|
490
|
+
elseif index == "Epsilon" then
|
|
491
|
+
self:SetEpsilon(value)
|
|
492
|
+
elseif index == "_currentSpring" then
|
|
493
|
+
error("Cannot set _currentSpring")
|
|
340
494
|
else
|
|
341
|
-
error(("%q is not a member of SpringObject"
|
|
495
|
+
error(string.format("%q is not a member of SpringObject", tostring(index)))
|
|
342
496
|
end
|
|
343
497
|
end
|
|
344
498
|
|
|
499
|
+
--[[
|
|
500
|
+
Callers of this must invoke .Changed after using this method
|
|
501
|
+
]]
|
|
345
502
|
function SpringObject:_getSpringForType(converted)
|
|
346
|
-
|
|
503
|
+
local currentSpring = rawget(self, "_currentSpring")
|
|
504
|
+
|
|
505
|
+
if currentSpring == nil then
|
|
506
|
+
|
|
347
507
|
-- only happens on init
|
|
348
|
-
|
|
349
|
-
|
|
508
|
+
local newSpring = Spring.new(converted)
|
|
509
|
+
|
|
510
|
+
local foundInitInfo = rawget(self, "_initInfo")
|
|
511
|
+
if foundInitInfo then
|
|
512
|
+
rawset(self, "_initInfo", nil)
|
|
513
|
+
newSpring.Clock = foundInitInfo.Clock
|
|
514
|
+
newSpring.Speed = foundInitInfo.Speed
|
|
515
|
+
newSpring.Damper = foundInitInfo.Damper
|
|
516
|
+
end
|
|
517
|
+
|
|
518
|
+
rawset(self, "_currentSpring", newSpring)
|
|
519
|
+
|
|
520
|
+
return newSpring
|
|
350
521
|
else
|
|
351
|
-
local currentType = typeof(SpringUtils.fromLinearIfNeeded(
|
|
522
|
+
local currentType = typeof(SpringUtils.fromLinearIfNeeded(currentSpring.Value))
|
|
352
523
|
if currentType == typeof(SpringUtils.fromLinearIfNeeded(converted)) then
|
|
353
|
-
return
|
|
524
|
+
return currentSpring
|
|
354
525
|
else
|
|
355
|
-
local oldDamper =
|
|
356
|
-
local oldSpeed =
|
|
357
|
-
local clock =
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
526
|
+
local oldDamper = currentSpring.d
|
|
527
|
+
local oldSpeed = currentSpring.s
|
|
528
|
+
local clock = currentSpring.Clock
|
|
529
|
+
|
|
530
|
+
local newSpring = Spring.new(converted)
|
|
531
|
+
newSpring.Clock = clock
|
|
532
|
+
newSpring.Speed = oldSpeed
|
|
533
|
+
newSpring.Damper = oldDamper
|
|
534
|
+
rawset(self, "_currentSpring", newSpring)
|
|
535
|
+
return newSpring
|
|
364
536
|
end
|
|
365
537
|
end
|
|
366
538
|
end
|
|
367
539
|
|
|
540
|
+
function SpringObject:_getInitInfo()
|
|
541
|
+
local currentSpring = rawget(self, "_currentSpring")
|
|
542
|
+
if currentSpring then
|
|
543
|
+
error("Should not have currentSpring")
|
|
544
|
+
end
|
|
545
|
+
|
|
546
|
+
local foundInitInfo = rawget(self, "_initInfo")
|
|
547
|
+
if foundInitInfo then
|
|
548
|
+
return foundInitInfo
|
|
549
|
+
end
|
|
550
|
+
|
|
551
|
+
local value = {
|
|
552
|
+
Clock = os.clock;
|
|
553
|
+
Damper = 1;
|
|
554
|
+
Speed = 1;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
rawset(self, "_initInfo", value)
|
|
558
|
+
|
|
559
|
+
return value
|
|
560
|
+
end
|
|
561
|
+
|
|
368
562
|
--[=[
|
|
369
563
|
Cleans up the BaseObject and sets the metatable to nil
|
|
370
564
|
]=]
|