@quenty/blend 12.6.0 → 12.8.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 +25 -0
- package/package.json +15 -15
- package/src/Shared/Blend/Blend.lua +111 -84
- package/src/Shared/Blend/SpringObject.lua +83 -44
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,31 @@
|
|
|
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.8.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/blend@12.7.0...@quenty/blend@12.8.0) (2024-10-04)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
* Avoid additional table construction in Blend.Computed for performance gain ([40ff0c0](https://github.com/Quenty/NevermoreEngine/commit/40ff0c05ed62fec4d6033bdabd477223bbc96a6a))
|
|
12
|
+
* Blend unparents children before destruction saving any instances that need to be reparented ([2728331](https://github.com/Quenty/NevermoreEngine/commit/272833178a1cbe833b35121c707ec8061c3891aa))
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Performance Improvements
|
|
16
|
+
|
|
17
|
+
* Avoid connecting to Rx if not needed in SpringObject ([a5ca4b8](https://github.com/Quenty/NevermoreEngine/commit/a5ca4b8cd4e4855b58a61478c9ecf9ff4a8a2cfe))
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
# [12.7.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/blend@12.6.0...@quenty/blend@12.7.0) (2024-09-25)
|
|
24
|
+
|
|
25
|
+
**Note:** Version bump only for package @quenty/blend
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
6
31
|
# [12.6.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/blend@12.5.2...@quenty/blend@12.6.0) (2024-09-25)
|
|
7
32
|
|
|
8
33
|
**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.8.0",
|
|
4
4
|
"description": "Declarative UI system.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Roblox",
|
|
@@ -28,23 +28,23 @@
|
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@quenty/acceltween": "^2.5.0",
|
|
31
|
-
"@quenty/brio": "^14.
|
|
32
|
-
"@quenty/ducktype": "^5.
|
|
33
|
-
"@quenty/instanceutils": "^13.
|
|
34
|
-
"@quenty/loader": "^10.
|
|
35
|
-
"@quenty/maid": "^3.
|
|
36
|
-
"@quenty/promise": "^10.
|
|
37
|
-
"@quenty/rx": "^13.
|
|
38
|
-
"@quenty/signal": "^7.
|
|
39
|
-
"@quenty/spring": "^10.
|
|
31
|
+
"@quenty/brio": "^14.8.0",
|
|
32
|
+
"@quenty/ducktype": "^5.6.0",
|
|
33
|
+
"@quenty/instanceutils": "^13.8.0",
|
|
34
|
+
"@quenty/loader": "^10.6.0",
|
|
35
|
+
"@quenty/maid": "^3.4.0",
|
|
36
|
+
"@quenty/promise": "^10.6.0",
|
|
37
|
+
"@quenty/rx": "^13.8.0",
|
|
38
|
+
"@quenty/signal": "^7.7.0",
|
|
39
|
+
"@quenty/spring": "^10.6.0",
|
|
40
40
|
"@quenty/steputils": "^3.5.0",
|
|
41
41
|
"@quenty/string": "^3.3.0",
|
|
42
|
-
"@quenty/valuebaseutils": "^13.
|
|
43
|
-
"@quenty/valueobject": "^13.
|
|
42
|
+
"@quenty/valuebaseutils": "^13.8.0",
|
|
43
|
+
"@quenty/valueobject": "^13.8.0"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
|
-
"@quenty/contentproviderutils": "^12.
|
|
47
|
-
"@quenty/playerthumbnailutils": "^10.
|
|
46
|
+
"@quenty/contentproviderutils": "^12.8.0",
|
|
47
|
+
"@quenty/playerthumbnailutils": "^10.6.0"
|
|
48
48
|
},
|
|
49
|
-
"gitHead": "
|
|
49
|
+
"gitHead": "035abfa088c854a73e1c65b350267eaa17669646"
|
|
50
50
|
}
|
|
@@ -20,7 +20,6 @@ local Signal = require("Signal")
|
|
|
20
20
|
local StepUtils = require("StepUtils")
|
|
21
21
|
local ValueBaseUtils = require("ValueBaseUtils")
|
|
22
22
|
local ValueObject = require("ValueObject")
|
|
23
|
-
local ValueObjectUtils = require("ValueObjectUtils")
|
|
24
23
|
local RxBrioUtils = require("RxBrioUtils")
|
|
25
24
|
local SpringObject
|
|
26
25
|
|
|
@@ -49,23 +48,23 @@ local Blend = {}
|
|
|
49
48
|
@param className string
|
|
50
49
|
@return (props: { [string]: any; }) -> Observable<Instance>
|
|
51
50
|
]=]
|
|
52
|
-
function Blend.New(className)
|
|
51
|
+
function Blend.New(className: string)
|
|
53
52
|
assert(type(className) == "string", "Bad className")
|
|
54
53
|
|
|
55
|
-
local defaults = BlendDefaultProps[className]
|
|
56
|
-
|
|
57
54
|
return function(props)
|
|
58
55
|
return Observable.new(function(sub)
|
|
59
56
|
local instance = Instance.new(className)
|
|
60
57
|
|
|
61
|
-
if
|
|
62
|
-
for key, value in pairs(
|
|
58
|
+
if BlendDefaultProps[className] then
|
|
59
|
+
for key, value in pairs(BlendDefaultProps[className]) do
|
|
63
60
|
instance[key] = value
|
|
64
61
|
end
|
|
65
62
|
end
|
|
66
63
|
|
|
67
64
|
local maid = Blend.mount(instance, props)
|
|
68
|
-
maid:GiveTask(
|
|
65
|
+
maid:GiveTask(function()
|
|
66
|
+
Blend._safeCleanupInstance(instance)
|
|
67
|
+
end)
|
|
69
68
|
|
|
70
69
|
sub:Fire(instance)
|
|
71
70
|
|
|
@@ -159,30 +158,32 @@ end
|
|
|
159
158
|
@return Observable<T>
|
|
160
159
|
]=]
|
|
161
160
|
function Blend.Computed(...)
|
|
162
|
-
local values = {...}
|
|
163
161
|
local n = select("#", ...)
|
|
164
|
-
local compute =
|
|
165
|
-
|
|
162
|
+
local compute = select(n, ...)
|
|
166
163
|
assert(type(compute) == "function", "Bad compute")
|
|
167
164
|
|
|
168
|
-
|
|
169
|
-
for i=1, n - 1 do
|
|
170
|
-
local observable = Blend.toPropertyObservable(values[i])
|
|
171
|
-
if observable then
|
|
172
|
-
args[i] = observable
|
|
173
|
-
else
|
|
174
|
-
args[i] = Rx.of(values[i])
|
|
175
|
-
end
|
|
176
|
-
end
|
|
177
|
-
|
|
178
|
-
if #args == 0 then
|
|
165
|
+
if n == 1 then
|
|
179
166
|
-- static value?
|
|
180
167
|
return Observable.new(function(sub)
|
|
181
168
|
sub:Fire(compute())
|
|
182
169
|
end)
|
|
183
|
-
elseif
|
|
184
|
-
|
|
170
|
+
elseif n == 2 then
|
|
171
|
+
local arg = ...
|
|
172
|
+
local observable = Blend.toPropertyObservable(arg) or Rx.of(arg)
|
|
173
|
+
return Rx.map(compute)(observable)
|
|
185
174
|
else
|
|
175
|
+
local args = table.create(n - 1)
|
|
176
|
+
|
|
177
|
+
for i=1, n - 1 do
|
|
178
|
+
local found = select(i, ...)
|
|
179
|
+
local observable = Blend.toPropertyObservable(found)
|
|
180
|
+
if observable then
|
|
181
|
+
args[i] = observable
|
|
182
|
+
else
|
|
183
|
+
args[i] = found
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
186
187
|
return Rx.combineLatest(args)
|
|
187
188
|
:Pipe({
|
|
188
189
|
Rx.map(function(result)
|
|
@@ -269,17 +270,16 @@ end
|
|
|
269
270
|
function Blend.Attached(constructor)
|
|
270
271
|
return function(parent)
|
|
271
272
|
return Observable.new(function(sub)
|
|
272
|
-
local maid = Maid.new()
|
|
273
|
-
|
|
274
273
|
local resource = constructor(parent)
|
|
275
274
|
|
|
275
|
+
local cleanup = nil
|
|
276
276
|
if MaidTaskUtils.isValidTask(resource) then
|
|
277
|
-
|
|
277
|
+
cleanup = resource
|
|
278
278
|
end
|
|
279
279
|
|
|
280
280
|
sub:Fire(resource)
|
|
281
281
|
|
|
282
|
-
return
|
|
282
|
+
return cleanup
|
|
283
283
|
end)
|
|
284
284
|
end;
|
|
285
285
|
end
|
|
@@ -414,14 +414,12 @@ function Blend.Spring(source, speed, damper)
|
|
|
414
414
|
end
|
|
415
415
|
|
|
416
416
|
return Observable.new(function(sub)
|
|
417
|
-
local
|
|
418
|
-
|
|
419
|
-
local spring = maid:Add(SpringObject.new(source, speed, damper))
|
|
417
|
+
local spring = SpringObject.new(source, speed, damper)
|
|
420
418
|
spring.Epsilon = 1e-3
|
|
421
419
|
|
|
422
|
-
|
|
420
|
+
spring._maid:GiveTask(spring:Observe():Subscribe(sub:GetFireFailComplete()))
|
|
423
421
|
|
|
424
|
-
return
|
|
422
|
+
return spring
|
|
425
423
|
end)
|
|
426
424
|
end
|
|
427
425
|
|
|
@@ -432,24 +430,26 @@ end
|
|
|
432
430
|
@return Observable?
|
|
433
431
|
]=]
|
|
434
432
|
function Blend.toPropertyObservable(value)
|
|
435
|
-
if
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
-- IntValue, ObjectValue, et cetera
|
|
439
|
-
if ValueBaseUtils.isValueBase(value) then
|
|
440
|
-
return RxValueBaseUtils.observeValue(value)
|
|
441
|
-
end
|
|
442
|
-
elseif type(value) == "table" then
|
|
443
|
-
if ValueObject.isValueObject(value) then
|
|
444
|
-
return ValueObjectUtils.observeValue(value)
|
|
433
|
+
if type(value) == "table" then
|
|
434
|
+
if Observable.isObservable(value) then
|
|
435
|
+
return value
|
|
445
436
|
elseif Promise.isPromise(value) then
|
|
446
437
|
return Rx.fromPromise(value)
|
|
447
438
|
elseif value.Observe then
|
|
448
439
|
return value:Observe()
|
|
440
|
+
else
|
|
441
|
+
return nil
|
|
449
442
|
end
|
|
443
|
+
elseif typeof(value) == "Instance" then
|
|
444
|
+
-- IntValue, ObjectValue, et cetera
|
|
445
|
+
if ValueBaseUtils.isValueBase(value) then
|
|
446
|
+
return RxValueBaseUtils.observeValue(value)
|
|
447
|
+
else
|
|
448
|
+
return nil
|
|
449
|
+
end
|
|
450
|
+
else
|
|
451
|
+
return nil
|
|
450
452
|
end
|
|
451
|
-
|
|
452
|
-
return nil
|
|
453
453
|
end
|
|
454
454
|
|
|
455
455
|
--[=[
|
|
@@ -578,11 +578,11 @@ function Blend.Children(parent, value)
|
|
|
578
578
|
local observe = Blend._observeChildren(value, parent)
|
|
579
579
|
|
|
580
580
|
if observe then
|
|
581
|
-
return
|
|
582
|
-
|
|
583
|
-
child.Parent = parent
|
|
584
|
-
end)
|
|
585
|
-
|
|
581
|
+
return Observable.new(function(_sub)
|
|
582
|
+
return observe:Subscribe(function(child)
|
|
583
|
+
child.Parent = parent
|
|
584
|
+
end)
|
|
585
|
+
end)
|
|
586
586
|
else
|
|
587
587
|
return Rx.EMPTY
|
|
588
588
|
end
|
|
@@ -682,35 +682,42 @@ function Blend.Find(className)
|
|
|
682
682
|
-- Return observable and assume we're being used in anexternal context
|
|
683
683
|
-- TODO: Maybe not this
|
|
684
684
|
if props.Parent then
|
|
685
|
-
local propertyObservable = Blend.toPropertyObservable(props.Parent)
|
|
685
|
+
local propertyObservable = Blend.toPropertyObservable(props.Parent)
|
|
686
686
|
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
end);
|
|
692
|
-
RxBrioUtils.switchMapBrio(function(parent)
|
|
693
|
-
assert(typeof(parent) == "Instance", "Bad parent retrieved during find spec")
|
|
687
|
+
local function handleChildBrio(brio)
|
|
688
|
+
if brio:IsDead() then
|
|
689
|
+
return
|
|
690
|
+
end
|
|
694
691
|
|
|
695
|
-
|
|
696
|
-
end);
|
|
697
|
-
Rx.flatMap(function(brio)
|
|
698
|
-
if brio:IsDead() then
|
|
699
|
-
return
|
|
700
|
-
end
|
|
692
|
+
local maid, instance = brio:ToMaidAndValue()
|
|
701
693
|
|
|
702
|
-
|
|
703
|
-
local instance = brio:GetValue()
|
|
704
|
-
maid:GiveTask(Blend.mount(instance, props))
|
|
694
|
+
maid:GiveTask(Blend.mount(instance, props))
|
|
705
695
|
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
696
|
+
if brio:IsDead() then
|
|
697
|
+
maid:DoCleaning()
|
|
698
|
+
end
|
|
709
699
|
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
700
|
+
-- Emit back found value (we're used in property scenario)
|
|
701
|
+
return Rx.of(instance)
|
|
702
|
+
end
|
|
703
|
+
|
|
704
|
+
if propertyObservable then
|
|
705
|
+
return propertyObservable:Pipe({
|
|
706
|
+
RxBrioUtils.switchToBrio(function(parent)
|
|
707
|
+
return parent ~= nil
|
|
708
|
+
end);
|
|
709
|
+
RxBrioUtils.switchMapBrio(function(parent)
|
|
710
|
+
assert(typeof(parent) == "Instance", "Bad parent retrieved during find spec")
|
|
711
|
+
|
|
712
|
+
return RxInstanceUtils.observeChildrenOfNameBrio(parent, className, props.Name)
|
|
713
|
+
end);
|
|
714
|
+
Rx.flatMap(handleChildBrio);
|
|
715
|
+
})
|
|
716
|
+
else
|
|
717
|
+
return RxInstanceUtils.observeChildrenOfNameBrio(props.Parent, className, props.Name):Pipe({
|
|
718
|
+
Rx.flatMap(handleChildBrio);
|
|
719
|
+
})
|
|
720
|
+
end
|
|
714
721
|
end
|
|
715
722
|
|
|
716
723
|
-- Return callback
|
|
@@ -730,8 +737,8 @@ function Blend._mountToFinding(props)
|
|
|
730
737
|
return
|
|
731
738
|
end
|
|
732
739
|
|
|
733
|
-
local maid = brio:
|
|
734
|
-
|
|
740
|
+
local maid, instance = brio:ToMaidAndValue()
|
|
741
|
+
|
|
735
742
|
maid:GiveTask(Blend.mount(instance, props))
|
|
736
743
|
|
|
737
744
|
-- Dead after mounting? Clean up...
|
|
@@ -858,6 +865,14 @@ function Blend.Single(observable)
|
|
|
858
865
|
end)
|
|
859
866
|
end
|
|
860
867
|
|
|
868
|
+
function Blend._safeCleanupInstance(result)
|
|
869
|
+
-- Unparent all children incase we want to resurrect them
|
|
870
|
+
for _, child in pairs(result:GetChildren()) do
|
|
871
|
+
child.Parent = nil
|
|
872
|
+
end
|
|
873
|
+
result:Destroy()
|
|
874
|
+
end
|
|
875
|
+
|
|
861
876
|
--[=[
|
|
862
877
|
Observes children and ensures that the value is cleaned up
|
|
863
878
|
afterwards.
|
|
@@ -943,7 +958,9 @@ function Blend._observeChildren(value, parent)
|
|
|
943
958
|
local result = value:GetValue()
|
|
944
959
|
if typeof(result) == "Instance" then
|
|
945
960
|
local maid = value:ToMaid()
|
|
946
|
-
maid:GiveTask(
|
|
961
|
+
maid:GiveTask(function()
|
|
962
|
+
Blend._safeCleanupInstance(result)
|
|
963
|
+
end)
|
|
947
964
|
sub:Fire(result)
|
|
948
965
|
|
|
949
966
|
return maid
|
|
@@ -990,7 +1007,9 @@ function Blend._observeChildren(value, parent)
|
|
|
990
1007
|
maid:GiveTask(value:Subscribe(function(result)
|
|
991
1008
|
if typeof(result) == "Instance" then
|
|
992
1009
|
-- lifetime of subscription
|
|
993
|
-
maid:GiveTask(
|
|
1010
|
+
maid:GiveTask(function()
|
|
1011
|
+
Blend._safeCleanupInstance(result)
|
|
1012
|
+
end)
|
|
994
1013
|
sub:Fire(result)
|
|
995
1014
|
return
|
|
996
1015
|
end
|
|
@@ -1089,6 +1108,7 @@ function Blend.mount(instance, props)
|
|
|
1089
1108
|
|
|
1090
1109
|
local parent = nil
|
|
1091
1110
|
local dependentObservables = {}
|
|
1111
|
+
local children = {}
|
|
1092
1112
|
|
|
1093
1113
|
for key, value in pairs(props) do
|
|
1094
1114
|
if type(key) == "string" then
|
|
@@ -1098,14 +1118,16 @@ function Blend.mount(instance, props)
|
|
|
1098
1118
|
local observable = Blend.toPropertyObservable(value)
|
|
1099
1119
|
if observable then
|
|
1100
1120
|
maid:GiveTask(observable:Subscribe(function(result)
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1121
|
+
instance[key] = result
|
|
1122
|
+
-- task.spawn(function()
|
|
1123
|
+
-- instance[key] = result
|
|
1124
|
+
-- end)
|
|
1104
1125
|
end))
|
|
1105
1126
|
else
|
|
1106
|
-
task.spawn(function()
|
|
1107
|
-
|
|
1108
|
-
end)
|
|
1127
|
+
-- task.spawn(function()
|
|
1128
|
+
-- instance[key] = value
|
|
1129
|
+
-- end)
|
|
1130
|
+
instance[key] = value
|
|
1109
1131
|
end
|
|
1110
1132
|
end
|
|
1111
1133
|
elseif type(key) == "function" then
|
|
@@ -1119,12 +1141,17 @@ function Blend.mount(instance, props)
|
|
|
1119
1141
|
elseif type(key) == "number" then
|
|
1120
1142
|
-- Treat this as an implicit children contract
|
|
1121
1143
|
-- Thus, we don't need an explicit [Blend.Children] call.
|
|
1122
|
-
table.insert(
|
|
1144
|
+
table.insert(children, value)
|
|
1123
1145
|
else
|
|
1124
1146
|
warn(string.format("Unable to apply property %q", tostring(key)))
|
|
1125
1147
|
end
|
|
1126
1148
|
end
|
|
1127
1149
|
|
|
1150
|
+
|
|
1151
|
+
if #children > 0 then
|
|
1152
|
+
maid:GiveTask(Blend.Children(instance, children):Subscribe())
|
|
1153
|
+
end
|
|
1154
|
+
|
|
1128
1155
|
-- Subscribe dependentObservables (which includes adding children)
|
|
1129
1156
|
for _, event in pairs(dependentObservables) do
|
|
1130
1157
|
maid:GiveTask(event[1]:Subscribe(Blend.toEventHandler(event[2])))
|
|
@@ -13,7 +13,6 @@ local DuckTypeUtils = require("DuckTypeUtils")
|
|
|
13
13
|
local Maid = require("Maid")
|
|
14
14
|
local Observable = require("Observable")
|
|
15
15
|
local Promise = require("Promise")
|
|
16
|
-
local Rx = require("Rx")
|
|
17
16
|
local Signal = require("Signal")
|
|
18
17
|
local Spring = require("Spring")
|
|
19
18
|
local SpringUtils = require("SpringUtils")
|
|
@@ -265,30 +264,36 @@ end
|
|
|
265
264
|
function SpringObject:SetTarget(target, doNotAnimate)
|
|
266
265
|
assert(target ~= nil, "Bad target")
|
|
267
266
|
|
|
268
|
-
local observable = Blend.toPropertyObservable(target)
|
|
267
|
+
local observable = Blend.toPropertyObservable(target)
|
|
268
|
+
if not observable then
|
|
269
|
+
self._maid._targetSub = nil
|
|
270
|
+
self:_applyTarget(target, doNotAnimate)
|
|
271
|
+
return
|
|
272
|
+
end
|
|
269
273
|
|
|
270
274
|
if doNotAnimate then
|
|
271
275
|
local isFirst = true
|
|
272
|
-
|
|
273
276
|
self._maid._targetSub = observable:Subscribe(function(unconverted)
|
|
274
277
|
local converted = SpringUtils.toLinearIfNeeded(unconverted)
|
|
275
278
|
assert(converted, "Not a valid converted target")
|
|
276
279
|
|
|
277
|
-
local
|
|
278
|
-
spring:SetTarget(converted, isFirst)
|
|
280
|
+
local wasFirst = isFirst
|
|
279
281
|
isFirst = false
|
|
280
|
-
|
|
281
|
-
self.Changed:Fire()
|
|
282
|
+
self:_applyTarget(unconverted, wasFirst)
|
|
282
283
|
end)
|
|
283
284
|
else
|
|
284
285
|
self._maid._targetSub = observable:Subscribe(function(unconverted)
|
|
285
|
-
|
|
286
|
-
self:_getSpringForType(converted).Target = converted
|
|
287
|
-
self.Changed:Fire()
|
|
286
|
+
self:_applyTarget(unconverted, doNotAnimate)
|
|
288
287
|
end)
|
|
289
288
|
end
|
|
290
289
|
end
|
|
291
290
|
|
|
291
|
+
function SpringObject:_applyTarget(unconverted, doNotAnimate)
|
|
292
|
+
local converted = SpringUtils.toLinearIfNeeded(unconverted)
|
|
293
|
+
self:_getSpringForType(converted):SetTarget(converted, doNotAnimate)
|
|
294
|
+
self.Changed:Fire()
|
|
295
|
+
end
|
|
296
|
+
|
|
292
297
|
--[=[
|
|
293
298
|
Sets the velocity for the spring
|
|
294
299
|
|
|
@@ -297,14 +302,22 @@ end
|
|
|
297
302
|
function SpringObject:SetVelocity(velocity)
|
|
298
303
|
assert(velocity ~= nil, "Bad velocity")
|
|
299
304
|
|
|
300
|
-
local observable = Blend.toPropertyObservable(velocity)
|
|
305
|
+
local observable = Blend.toPropertyObservable(velocity)
|
|
306
|
+
if not observable then
|
|
307
|
+
self._maid._velocitySub = nil
|
|
308
|
+
self:_applyVelocity(velocity)
|
|
309
|
+
else
|
|
310
|
+
self._maid._velocitySub = observable:Subscribe(function(unconverted)
|
|
311
|
+
self:_applyVelocity(unconverted)
|
|
312
|
+
end)
|
|
313
|
+
end
|
|
314
|
+
end
|
|
301
315
|
|
|
302
|
-
|
|
303
|
-
|
|
316
|
+
function SpringObject:_applyVelocity(unconverted)
|
|
317
|
+
local converted = SpringUtils.toLinearIfNeeded(unconverted)
|
|
304
318
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
end)
|
|
319
|
+
self:_getSpringForType(0*converted).Velocity = converted
|
|
320
|
+
self.Changed:Fire()
|
|
308
321
|
end
|
|
309
322
|
|
|
310
323
|
--[=[
|
|
@@ -315,13 +328,21 @@ end
|
|
|
315
328
|
function SpringObject:SetPosition(position)
|
|
316
329
|
assert(position ~= nil, "Bad position")
|
|
317
330
|
|
|
318
|
-
local observable = Blend.toPropertyObservable(position)
|
|
331
|
+
local observable = Blend.toPropertyObservable(position)
|
|
332
|
+
if not observable then
|
|
333
|
+
self._maid._positionSub = nil
|
|
334
|
+
self:_applyPosition(position)
|
|
335
|
+
else
|
|
336
|
+
self._maid._positionSub = observable:Subscribe(function(unconverted)
|
|
337
|
+
self:_applyPosition(unconverted)
|
|
338
|
+
end)
|
|
339
|
+
end
|
|
340
|
+
end
|
|
319
341
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
end)
|
|
342
|
+
function SpringObject:_applyPosition(unconverted)
|
|
343
|
+
local converted = SpringUtils.toLinearIfNeeded(unconverted)
|
|
344
|
+
self:_getSpringForType(converted).Value = converted
|
|
345
|
+
self.Changed:Fire()
|
|
325
346
|
end
|
|
326
347
|
|
|
327
348
|
--[=[
|
|
@@ -332,20 +353,29 @@ end
|
|
|
332
353
|
function SpringObject:SetDamper(damper)
|
|
333
354
|
assert(damper ~= nil, "Bad damper")
|
|
334
355
|
|
|
335
|
-
|
|
356
|
+
if type(damper) == "number" then
|
|
357
|
+
self._maid._damperSub = nil
|
|
358
|
+
self:_applyDamper(damper)
|
|
359
|
+
else
|
|
360
|
+
local observable = assert(Blend.toPropertyObservable(damper), "Invalid damper")
|
|
336
361
|
|
|
337
|
-
|
|
338
|
-
|
|
362
|
+
self._maid._damperSub = observable:Subscribe(function(unconverted)
|
|
363
|
+
self:_applyDamper(unconverted)
|
|
364
|
+
end)
|
|
365
|
+
end
|
|
366
|
+
end
|
|
339
367
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
currentSpring.Damper = unconverted
|
|
343
|
-
else
|
|
344
|
-
self:_getInitInfo().Damper = unconverted
|
|
345
|
-
end
|
|
368
|
+
function SpringObject:_applyDamper(unconverted)
|
|
369
|
+
assert(type(unconverted) == "number", "Bad damper")
|
|
346
370
|
|
|
347
|
-
|
|
348
|
-
|
|
371
|
+
local currentSpring = rawget(self, "_currentSpring")
|
|
372
|
+
if currentSpring then
|
|
373
|
+
currentSpring.Damper = unconverted
|
|
374
|
+
else
|
|
375
|
+
self:_getInitInfo().Damper = unconverted
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
self.Changed:Fire()
|
|
349
379
|
end
|
|
350
380
|
|
|
351
381
|
--[=[
|
|
@@ -356,20 +386,29 @@ end
|
|
|
356
386
|
function SpringObject:SetSpeed(speed)
|
|
357
387
|
assert(speed ~= nil, "Bad speed")
|
|
358
388
|
|
|
359
|
-
|
|
389
|
+
if type(speed) == "number" then
|
|
390
|
+
self._maid._speedSub = nil
|
|
391
|
+
self:_applySpeed(speed)
|
|
392
|
+
else
|
|
393
|
+
local observable = assert(Blend.toPropertyObservable(speed), "Invalid speed")
|
|
360
394
|
|
|
361
|
-
|
|
362
|
-
|
|
395
|
+
self._maid._speedSub = observable:Subscribe(function(unconverted)
|
|
396
|
+
self:_applySpeed(unconverted)
|
|
397
|
+
end)
|
|
398
|
+
end
|
|
399
|
+
end
|
|
363
400
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
currentSpring.Speed = unconverted
|
|
367
|
-
else
|
|
368
|
-
self:_getInitInfo().Speed = unconverted
|
|
369
|
-
end
|
|
401
|
+
function SpringObject:_applySpeed(unconverted)
|
|
402
|
+
assert(type(unconverted) == "number", "Bad damper")
|
|
370
403
|
|
|
371
|
-
|
|
372
|
-
|
|
404
|
+
local currentSpring = rawget(self, "_currentSpring")
|
|
405
|
+
if currentSpring then
|
|
406
|
+
currentSpring.Speed = unconverted
|
|
407
|
+
else
|
|
408
|
+
self:_getInitInfo().Speed = unconverted
|
|
409
|
+
end
|
|
410
|
+
|
|
411
|
+
self.Changed:Fire()
|
|
373
412
|
end
|
|
374
413
|
|
|
375
414
|
--[=[
|