@quenty/blend 12.18.0 → 12.18.1
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
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
|
+
## [12.18.1](https://github.com/Quenty/NevermoreEngine/compare/@quenty/blend@12.18.0...@quenty/blend@12.18.1) (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
|
# [12.18.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/blend@12.17.2...@quenty/blend@12.18.0) (2025-04-02)
|
|
7
18
|
|
|
8
19
|
**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.18.
|
|
3
|
+
"version": "12.18.1",
|
|
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": "^2.5.
|
|
31
|
-
"@quenty/brio": "^14.17.
|
|
32
|
-
"@quenty/ducktype": "^5.8.
|
|
33
|
-
"@quenty/instanceutils": "^13.17.
|
|
34
|
-
"@quenty/loader": "^10.8.
|
|
35
|
-
"@quenty/maid": "^3.4.
|
|
36
|
-
"@quenty/promise": "^10.10.
|
|
37
|
-
"@quenty/rx": "^13.17.
|
|
38
|
-
"@quenty/signal": "^7.10.
|
|
39
|
-
"@quenty/spring": "^10.8.
|
|
40
|
-
"@quenty/steputils": "^3.5.
|
|
41
|
-
"@quenty/string": "^3.3.
|
|
42
|
-
"@quenty/valuebaseutils": "^13.17.
|
|
43
|
-
"@quenty/valueobject": "^13.17.
|
|
30
|
+
"@quenty/acceltween": "^2.5.1",
|
|
31
|
+
"@quenty/brio": "^14.17.1",
|
|
32
|
+
"@quenty/ducktype": "^5.8.2",
|
|
33
|
+
"@quenty/instanceutils": "^13.17.1",
|
|
34
|
+
"@quenty/loader": "^10.8.1",
|
|
35
|
+
"@quenty/maid": "^3.4.1",
|
|
36
|
+
"@quenty/promise": "^10.10.2",
|
|
37
|
+
"@quenty/rx": "^13.17.1",
|
|
38
|
+
"@quenty/signal": "^7.10.1",
|
|
39
|
+
"@quenty/spring": "^10.8.2",
|
|
40
|
+
"@quenty/steputils": "^3.5.4",
|
|
41
|
+
"@quenty/string": "^3.3.2",
|
|
42
|
+
"@quenty/valuebaseutils": "^13.17.1",
|
|
43
|
+
"@quenty/valueobject": "^13.17.1"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
|
-
"@quenty/contentproviderutils": "^12.17.
|
|
47
|
-
"@quenty/playerthumbnailutils": "^10.10.
|
|
46
|
+
"@quenty/contentproviderutils": "^12.17.1",
|
|
47
|
+
"@quenty/playerthumbnailutils": "^10.10.2"
|
|
48
48
|
},
|
|
49
|
-
"gitHead": "
|
|
49
|
+
"gitHead": "78c3ac0ab08dd18085b6e6e6e4f745e76ed99f68"
|
|
50
50
|
}
|
|
@@ -56,7 +56,7 @@ function Blend.New(className: string)
|
|
|
56
56
|
local instance = Instance.new(className)
|
|
57
57
|
|
|
58
58
|
if BlendDefaultProps[className] then
|
|
59
|
-
for key, value in
|
|
59
|
+
for key, value in BlendDefaultProps[className] do
|
|
60
60
|
instance[key] = value
|
|
61
61
|
end
|
|
62
62
|
end
|
|
@@ -77,10 +77,10 @@ end
|
|
|
77
77
|
Creates a new Blend State which is actually just a ValueObject underneath.
|
|
78
78
|
|
|
79
79
|
@param defaultValue T
|
|
80
|
-
@param checkType string
|
|
80
|
+
@param checkType string?
|
|
81
81
|
@return ValueObject<T>
|
|
82
82
|
]=]
|
|
83
|
-
function Blend.State(defaultValue, checkType)
|
|
83
|
+
function Blend.State<T>(defaultValue: T, checkType: ValueObject.ValueObjectTypeArg?): ValueObject.ValueObject<T>
|
|
84
84
|
return ValueObject.new(defaultValue, checkType)
|
|
85
85
|
end
|
|
86
86
|
|
|
@@ -93,10 +93,10 @@ end
|
|
|
93
93
|
@param observable Observable<T>
|
|
94
94
|
@return Observable<T>
|
|
95
95
|
]=]
|
|
96
|
-
function Blend.Throttled(observable)
|
|
96
|
+
function Blend.Throttled<T>(observable: Observable.Observable<T>): Observable.Observable<T>
|
|
97
97
|
return observable:Pipe({
|
|
98
|
-
Rx.throttleDefer()
|
|
99
|
-
})
|
|
98
|
+
Rx.throttleDefer(),
|
|
99
|
+
}) :: any
|
|
100
100
|
end
|
|
101
101
|
|
|
102
102
|
--[=[
|
|
@@ -108,27 +108,27 @@ end
|
|
|
108
108
|
@param observable Observable<T>
|
|
109
109
|
@return Observable<T>
|
|
110
110
|
]=]
|
|
111
|
-
function Blend.Shared(observable)
|
|
111
|
+
function Blend.Shared<T>(observable: Observable.Observable<T>): Observable.Observable<T>
|
|
112
112
|
return observable:Pipe({
|
|
113
|
-
Rx.cache()
|
|
114
|
-
})
|
|
113
|
+
Rx.cache() :: any,
|
|
114
|
+
}) :: any
|
|
115
115
|
end
|
|
116
116
|
|
|
117
117
|
function Blend.Dynamic(...)
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
118
|
+
-- stylua: ignore
|
|
119
|
+
return Blend.Computed(...):Pipe({
|
|
120
|
+
-- This switch map is relatively expensive, so we don't do this for defaul computed
|
|
121
|
+
-- and instead force the user to switch to another promise
|
|
122
|
+
Rx.switchMap(function(promise, ...)
|
|
123
|
+
if Promise.isPromise(promise) then
|
|
124
|
+
return Rx.fromPromise(promise) :: any
|
|
125
|
+
elseif Observable.isObservable(promise) then
|
|
126
|
+
return promise
|
|
127
|
+
else
|
|
128
|
+
return Rx.of(promise, ...)
|
|
129
|
+
end
|
|
130
|
+
end) :: any,
|
|
131
|
+
})
|
|
132
132
|
end
|
|
133
133
|
|
|
134
134
|
--[=[
|
|
@@ -174,7 +174,7 @@ function Blend.Computed(...)
|
|
|
174
174
|
else
|
|
175
175
|
local args = table.create(n - 1)
|
|
176
176
|
|
|
177
|
-
for i=1, n - 1 do
|
|
177
|
+
for i = 1, n - 1 do
|
|
178
178
|
local found = select(i, ...)
|
|
179
179
|
local observable = Blend.toPropertyObservable(found)
|
|
180
180
|
if observable then
|
|
@@ -184,12 +184,11 @@ function Blend.Computed(...)
|
|
|
184
184
|
end
|
|
185
185
|
end
|
|
186
186
|
|
|
187
|
-
return Rx.combineLatest(args)
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
})
|
|
187
|
+
return Rx.combineLatest(args):Pipe({
|
|
188
|
+
Rx.map(function(result)
|
|
189
|
+
return compute(unpack(result, 1, n - 1))
|
|
190
|
+
end),
|
|
191
|
+
})
|
|
193
192
|
end
|
|
194
193
|
end
|
|
195
194
|
|
|
@@ -209,10 +208,10 @@ end
|
|
|
209
208
|
@param propertyName string
|
|
210
209
|
@return (instance: Instance) -> Observable
|
|
211
210
|
]=]
|
|
212
|
-
function Blend.OnChange(propertyName)
|
|
211
|
+
function Blend.OnChange(propertyName: string): (instance: Instance) -> Observable.Observable<any>
|
|
213
212
|
assert(type(propertyName) == "string", "Bad propertyName")
|
|
214
213
|
|
|
215
|
-
return function(instance)
|
|
214
|
+
return function(instance: Instance)
|
|
216
215
|
return RxInstanceUtils.observeProperty(instance, propertyName)
|
|
217
216
|
end
|
|
218
217
|
end
|
|
@@ -235,7 +234,7 @@ end
|
|
|
235
234
|
@param eventName string
|
|
236
235
|
@return (instance: Instance) -> Observable
|
|
237
236
|
]=]
|
|
238
|
-
function Blend.OnEvent(eventName)
|
|
237
|
+
function Blend.OnEvent(eventName: string)
|
|
239
238
|
assert(type(eventName) == "string", "Bad eventName")
|
|
240
239
|
|
|
241
240
|
return function(instance)
|
|
@@ -281,7 +280,7 @@ function Blend.Attached(constructor)
|
|
|
281
280
|
|
|
282
281
|
return cleanup
|
|
283
282
|
end)
|
|
284
|
-
end
|
|
283
|
+
end
|
|
285
284
|
end
|
|
286
285
|
|
|
287
286
|
--[=[
|
|
@@ -300,37 +299,40 @@ function Blend.ComputedPairs(source, compute)
|
|
|
300
299
|
local maidForKeys = Maid.new()
|
|
301
300
|
topMaid:GiveTask(maidForKeys)
|
|
302
301
|
|
|
303
|
-
topMaid:GiveTask(
|
|
304
|
-
|
|
305
|
-
|
|
302
|
+
topMaid:GiveTask(
|
|
303
|
+
sourceObservable:Subscribe(function(newValue)
|
|
304
|
+
-- It's gotta be a table
|
|
305
|
+
assert(type(newValue) == "table", "Bad value emitted from source")
|
|
306
306
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
307
|
+
local excluded = {}
|
|
308
|
+
for key, _ in cache do
|
|
309
|
+
excluded[key] = true
|
|
310
|
+
end
|
|
311
311
|
|
|
312
|
-
|
|
313
|
-
|
|
312
|
+
for key, value in newValue do
|
|
313
|
+
excluded[key] = nil
|
|
314
314
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
315
|
+
if cache[key] ~= value then
|
|
316
|
+
local innerMaid = Maid.new()
|
|
317
|
+
local result = compute(key, value, innerMaid)
|
|
318
318
|
|
|
319
|
-
|
|
320
|
-
|
|
319
|
+
local brio = Brio.new(result)
|
|
320
|
+
innerMaid:GiveTask(brio)
|
|
321
321
|
|
|
322
|
-
|
|
322
|
+
sub:Fire(brio)
|
|
323
323
|
|
|
324
|
-
|
|
325
|
-
|
|
324
|
+
maidForKeys[key] = innerMaid
|
|
325
|
+
cache[key] = value
|
|
326
|
+
end
|
|
326
327
|
end
|
|
327
|
-
end
|
|
328
328
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
329
|
+
for key, _ in excluded do
|
|
330
|
+
maidForKeys[key] = nil
|
|
331
|
+
cache[key] = nil
|
|
332
|
+
end
|
|
333
|
+
end),
|
|
334
|
+
sub:GetFailComplete()
|
|
335
|
+
)
|
|
334
336
|
|
|
335
337
|
return topMaid
|
|
336
338
|
end)
|
|
@@ -410,7 +412,7 @@ end
|
|
|
410
412
|
]=]
|
|
411
413
|
function Blend.Spring(source, speed, damper)
|
|
412
414
|
if not SpringObject then
|
|
413
|
-
SpringObject = require("SpringObject")
|
|
415
|
+
SpringObject = (require :: any)("SpringObject")
|
|
414
416
|
end
|
|
415
417
|
|
|
416
418
|
return Observable.new(function(sub)
|
|
@@ -495,7 +497,7 @@ function Blend.toEventHandler(value)
|
|
|
495
497
|
-- IntValue, ObjectValue, et cetera
|
|
496
498
|
if ValueBaseUtils.isValueBase(value) then
|
|
497
499
|
return function(result)
|
|
498
|
-
value.Value = result
|
|
500
|
+
(value :: any).Value = result
|
|
499
501
|
end
|
|
500
502
|
end
|
|
501
503
|
elseif type(value) == "table" then
|
|
@@ -572,7 +574,7 @@ end
|
|
|
572
574
|
@param value any
|
|
573
575
|
@return Observable
|
|
574
576
|
]=]
|
|
575
|
-
function Blend.Children(parent, value)
|
|
577
|
+
function Blend.Children(parent: Instance, value)
|
|
576
578
|
assert(typeof(parent) == "Instance", "Bad parent")
|
|
577
579
|
|
|
578
580
|
local observe = Blend._observeChildren(value, parent)
|
|
@@ -601,10 +603,10 @@ end
|
|
|
601
603
|
@param value any
|
|
602
604
|
@return Observable
|
|
603
605
|
]=]
|
|
604
|
-
function Blend.Tags(parent, value)
|
|
606
|
+
function Blend.Tags(parent: Instance, value)
|
|
605
607
|
assert(typeof(parent) == "Instance", "Bad parent")
|
|
606
608
|
|
|
607
|
-
local observe = Blend._observeTags(value
|
|
609
|
+
local observe = Blend._observeTags(value)
|
|
608
610
|
|
|
609
611
|
if observe then
|
|
610
612
|
return observe:Pipe({
|
|
@@ -614,14 +616,13 @@ function Blend.Tags(parent, value)
|
|
|
614
616
|
else
|
|
615
617
|
error("Bad tag")
|
|
616
618
|
end
|
|
617
|
-
end)
|
|
619
|
+
end),
|
|
618
620
|
})
|
|
619
621
|
else
|
|
620
622
|
return Rx.EMPTY
|
|
621
623
|
end
|
|
622
624
|
end
|
|
623
625
|
|
|
624
|
-
|
|
625
626
|
function Blend._observeTags(tags)
|
|
626
627
|
if type(tags) == "string" then
|
|
627
628
|
return Rx.of(tags)
|
|
@@ -672,7 +673,7 @@ end
|
|
|
672
673
|
@param className string
|
|
673
674
|
@return function
|
|
674
675
|
]=]
|
|
675
|
-
function Blend.Find(className)
|
|
676
|
+
function Blend.Find(className: string)
|
|
676
677
|
assert(type(className) == "string", "Bad className")
|
|
677
678
|
|
|
678
679
|
return function(props)
|
|
@@ -705,17 +706,17 @@ function Blend.Find(className)
|
|
|
705
706
|
return propertyObservable:Pipe({
|
|
706
707
|
RxBrioUtils.switchToBrio(function(parent)
|
|
707
708
|
return parent ~= nil
|
|
708
|
-
end)
|
|
709
|
+
end),
|
|
709
710
|
RxBrioUtils.switchMapBrio(function(parent)
|
|
710
711
|
assert(typeof(parent) == "Instance", "Bad parent retrieved during find spec")
|
|
711
712
|
|
|
712
713
|
return RxInstanceUtils.observeChildrenOfNameBrio(parent, className, props.Name)
|
|
713
|
-
end)
|
|
714
|
-
Rx.flatMap(handleChildBrio)
|
|
714
|
+
end),
|
|
715
|
+
Rx.flatMap(handleChildBrio),
|
|
715
716
|
})
|
|
716
717
|
else
|
|
717
718
|
return RxInstanceUtils.observeChildrenOfNameBrio(props.Parent, className, props.Name):Pipe({
|
|
718
|
-
Rx.flatMap(handleChildBrio)
|
|
719
|
+
Rx.flatMap(handleChildBrio),
|
|
719
720
|
})
|
|
720
721
|
end
|
|
721
722
|
end
|
|
@@ -725,7 +726,7 @@ function Blend.Find(className)
|
|
|
725
726
|
-- TODO: Swap based upon name
|
|
726
727
|
-- TODO: Avoid assigning name
|
|
727
728
|
return RxInstanceUtils.observeChildrenOfNameBrio(parent, className, props.Name):Pipe({
|
|
728
|
-
Blend._mountToFinding(props)
|
|
729
|
+
Blend._mountToFinding(props),
|
|
729
730
|
})
|
|
730
731
|
end
|
|
731
732
|
end
|
|
@@ -749,7 +750,7 @@ function Blend._mountToFinding(props)
|
|
|
749
750
|
|
|
750
751
|
-- Avoid emitting anything else so we don't get cleaned up
|
|
751
752
|
return Rx.EMPTY
|
|
752
|
-
end)
|
|
753
|
+
end)
|
|
753
754
|
end
|
|
754
755
|
|
|
755
756
|
--[=[
|
|
@@ -802,7 +803,7 @@ end
|
|
|
802
803
|
@param parent Instance
|
|
803
804
|
@return Observable<Instance>
|
|
804
805
|
]=]
|
|
805
|
-
function Blend.Instance(parent)
|
|
806
|
+
function Blend.Instance(parent: Instance): Observable.Observable<Instance>
|
|
806
807
|
return Observable.new(function(sub)
|
|
807
808
|
sub:Fire(parent)
|
|
808
809
|
end)
|
|
@@ -865,9 +866,9 @@ function Blend.Single(observable)
|
|
|
865
866
|
end)
|
|
866
867
|
end
|
|
867
868
|
|
|
868
|
-
function Blend._safeCleanupInstance(result)
|
|
869
|
+
function Blend._safeCleanupInstance(result: Instance)
|
|
869
870
|
-- Unparent all children incase we want to resurrect them
|
|
870
|
-
for _, child in
|
|
871
|
+
for _, child in result:GetChildren() do
|
|
871
872
|
child.Parent = nil
|
|
872
873
|
end
|
|
873
874
|
result:Destroy()
|
|
@@ -1048,7 +1049,7 @@ function Blend._observeChildren(value, parent)
|
|
|
1048
1049
|
|
|
1049
1050
|
if type(value) == "table" and not getmetatable(value) then
|
|
1050
1051
|
local observables = {}
|
|
1051
|
-
for key, item in
|
|
1052
|
+
for key, item in value do
|
|
1052
1053
|
local observe = Blend._observeChildren(item, parent)
|
|
1053
1054
|
if observe then
|
|
1054
1055
|
table.insert(observables, observe)
|
|
@@ -1101,7 +1102,7 @@ end
|
|
|
1101
1102
|
@param props table
|
|
1102
1103
|
@return Maid
|
|
1103
1104
|
]=]
|
|
1104
|
-
function Blend.mount(instance, props)
|
|
1105
|
+
function Blend.mount(instance: Instance, props)
|
|
1105
1106
|
assert(typeof(instance) == "Instance", "Bad instance")
|
|
1106
1107
|
|
|
1107
1108
|
local maid = Maid.new()
|
|
@@ -1110,7 +1111,7 @@ function Blend.mount(instance, props)
|
|
|
1110
1111
|
local dependentObservables = {}
|
|
1111
1112
|
local children = {}
|
|
1112
1113
|
|
|
1113
|
-
for key, value in
|
|
1114
|
+
for key, value in props do
|
|
1114
1115
|
if type(key) == "string" then
|
|
1115
1116
|
if key == "Parent" then
|
|
1116
1117
|
parent = value
|
|
@@ -1153,7 +1154,7 @@ function Blend.mount(instance, props)
|
|
|
1153
1154
|
end
|
|
1154
1155
|
|
|
1155
1156
|
-- Subscribe dependentObservables (which includes adding children)
|
|
1156
|
-
for _, event in
|
|
1157
|
+
for _, event in dependentObservables do
|
|
1157
1158
|
maid:GiveTask(event[1]:Subscribe(Blend.toEventHandler(event[2])))
|
|
1158
1159
|
end
|
|
1159
1160
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
--!strict
|
|
1
2
|
--[=[
|
|
2
3
|
This is like a [Spring], but it can be observed, and emits events. It handles [Observable]s and
|
|
3
4
|
|
|
@@ -6,7 +7,7 @@
|
|
|
6
7
|
|
|
7
8
|
local require = require(script.Parent.loader).load(script)
|
|
8
9
|
|
|
9
|
-
local RunService= game:GetService("RunService")
|
|
10
|
+
local RunService = game:GetService("RunService")
|
|
10
11
|
|
|
11
12
|
local Blend = require("Blend")
|
|
12
13
|
local DuckTypeUtils = require("DuckTypeUtils")
|
|
@@ -22,6 +23,53 @@ local SpringObject = {}
|
|
|
22
23
|
SpringObject.ClassName = "SpringObject"
|
|
23
24
|
SpringObject.__index = SpringObject
|
|
24
25
|
|
|
26
|
+
export type SpringObject<T> = typeof(setmetatable(
|
|
27
|
+
{} :: {
|
|
28
|
+
-- Public
|
|
29
|
+
Changed: Signal.Signal<()>,
|
|
30
|
+
Observe: (self: SpringObject<T>) -> Observable.Observable<T>,
|
|
31
|
+
ObserveRenderStepped: (self: SpringObject<T>) -> Observable.Observable<T>,
|
|
32
|
+
ObserveTarget: (self: SpringObject<T>) -> Observable.Observable<T>,
|
|
33
|
+
ObserveVelocityOnRenderStepped: (self: SpringObject<T>) -> Observable.Observable<T>,
|
|
34
|
+
PromiseFinished: (self: SpringObject<T>, signal: RBXScriptSignal?) -> Promise.Promise<boolean>,
|
|
35
|
+
ObserveVelocityOnSignal: (self: SpringObject<T>, signal: RBXScriptSignal) -> Observable.Observable<T>,
|
|
36
|
+
ObserveOnSignal: (self: SpringObject<T>, signal: RBXScriptSignal) -> Observable.Observable<T>,
|
|
37
|
+
IsAnimating: (self: SpringObject<T>) -> boolean,
|
|
38
|
+
Impulse: (self: SpringObject<T>, velocity: T) -> (),
|
|
39
|
+
SetTarget: (self: SpringObject<T>, target: T, doNotAnimate: boolean?) -> () -> (),
|
|
40
|
+
SetVelocity: (self: SpringObject<T>, velocity: T) -> (),
|
|
41
|
+
SetPosition: (self: SpringObject<T>, position: T) -> (),
|
|
42
|
+
SetDamper: (self: SpringObject<T>, damper: number | Observable.Observable<number>) -> (),
|
|
43
|
+
SetSpeed: (self: SpringObject<T>, speed: number | Observable.Observable<number>) -> (),
|
|
44
|
+
SetClock: (self: SpringObject<T>, clock: Spring.SpringClock) -> (),
|
|
45
|
+
SetEpsilon: (self: SpringObject<T>, epsilon: number) -> (),
|
|
46
|
+
TimeSkip: (self: SpringObject<T>, delta: number) -> (),
|
|
47
|
+
Destroy: (self: SpringObject<T>) -> (),
|
|
48
|
+
|
|
49
|
+
-- Properties
|
|
50
|
+
Value: T,
|
|
51
|
+
Position: T,
|
|
52
|
+
p: T,
|
|
53
|
+
Velocity: T,
|
|
54
|
+
v: T,
|
|
55
|
+
Target: T,
|
|
56
|
+
t: T,
|
|
57
|
+
Damper: number,
|
|
58
|
+
d: number,
|
|
59
|
+
Speed: number,
|
|
60
|
+
s: number,
|
|
61
|
+
Clock: Spring.SpringClock,
|
|
62
|
+
Epsilon: number,
|
|
63
|
+
|
|
64
|
+
-- Members
|
|
65
|
+
_maid: Maid.Maid,
|
|
66
|
+
_epsilon: number,
|
|
67
|
+
_currentSpring: Spring.Spring<T>,
|
|
68
|
+
_initInfo: { Clock: () -> number, Damper: number, Speed: number },
|
|
69
|
+
},
|
|
70
|
+
SpringObject
|
|
71
|
+
))
|
|
72
|
+
|
|
25
73
|
--[=[
|
|
26
74
|
Constructs a new SpringObject.
|
|
27
75
|
|
|
@@ -36,14 +84,14 @@ SpringObject.__index = SpringObject
|
|
|
36
84
|
@param damper number | Observable<number> | NumberValue | any
|
|
37
85
|
@return Spring<T>
|
|
38
86
|
]=]
|
|
39
|
-
function SpringObject.new(target, speed, damper)
|
|
87
|
+
function SpringObject.new<T>(target: T, speed, damper): SpringObject<T>
|
|
40
88
|
local self = setmetatable({
|
|
41
|
-
_maid = Maid.new()
|
|
42
|
-
_epsilon = 1e-6
|
|
43
|
-
Changed = Signal.new()
|
|
89
|
+
_maid = Maid.new(),
|
|
90
|
+
_epsilon = 1e-6,
|
|
91
|
+
Changed = Signal.new(),
|
|
44
92
|
}, SpringObject)
|
|
45
93
|
|
|
46
|
-
--[=[
|
|
94
|
+
--[=[
|
|
47
95
|
Event fires when the spring value changes
|
|
48
96
|
@prop Changed Signal<()> -- Fires whenever the spring initially changes state
|
|
49
97
|
@within SpringObject
|
|
@@ -65,7 +113,7 @@ function SpringObject.new(target, speed, damper)
|
|
|
65
113
|
self.Damper = damper
|
|
66
114
|
end
|
|
67
115
|
|
|
68
|
-
return self
|
|
116
|
+
return self :: any
|
|
69
117
|
end
|
|
70
118
|
|
|
71
119
|
--[=[
|
|
@@ -73,7 +121,7 @@ end
|
|
|
73
121
|
@param value any
|
|
74
122
|
@return boolean
|
|
75
123
|
]=]
|
|
76
|
-
function SpringObject.isSpringObject(value)
|
|
124
|
+
function SpringObject.isSpringObject(value: any): boolean
|
|
77
125
|
return DuckTypeUtils.isImplementation(SpringObject, value)
|
|
78
126
|
end
|
|
79
127
|
|
|
@@ -186,7 +234,7 @@ function SpringObject:ObserveVelocityOnSignal(signal)
|
|
|
186
234
|
if animating then
|
|
187
235
|
sub:Fire(SpringUtils.fromLinearIfNeeded(currentSpring.Velocity))
|
|
188
236
|
else
|
|
189
|
-
sub:Fire(SpringUtils.fromLinearIfNeeded(0*currentSpring.Velocity))
|
|
237
|
+
sub:Fire(SpringUtils.fromLinearIfNeeded(0 * currentSpring.Velocity))
|
|
190
238
|
end
|
|
191
239
|
|
|
192
240
|
return animating
|
|
@@ -232,7 +280,7 @@ end
|
|
|
232
280
|
Returns true when we're animating
|
|
233
281
|
@return boolean -- True if animating
|
|
234
282
|
]=]
|
|
235
|
-
function SpringObject:IsAnimating()
|
|
283
|
+
function SpringObject:IsAnimating(): boolean
|
|
236
284
|
local currentSpring = rawget(self, "_currentSpring")
|
|
237
285
|
if not currentSpring then
|
|
238
286
|
return false
|
|
@@ -261,16 +309,14 @@ end
|
|
|
261
309
|
@param target T -- The target to set
|
|
262
310
|
@param doNotAnimate boolean? -- Whether or not to animate
|
|
263
311
|
]=]
|
|
264
|
-
function SpringObject:SetTarget(target, doNotAnimate)
|
|
312
|
+
function SpringObject:SetTarget<T>(target: T, doNotAnimate: boolean?)
|
|
265
313
|
assert(target ~= nil, "Bad target")
|
|
266
314
|
|
|
267
315
|
local observable = Blend.toPropertyObservable(target)
|
|
268
316
|
if not observable then
|
|
269
317
|
self._maid._targetSub = nil
|
|
270
318
|
self:_applyTarget(target, doNotAnimate)
|
|
271
|
-
return function()
|
|
272
|
-
|
|
273
|
-
end
|
|
319
|
+
return function() end
|
|
274
320
|
end
|
|
275
321
|
|
|
276
322
|
local sub
|
|
@@ -300,7 +346,7 @@ function SpringObject:SetTarget(target, doNotAnimate)
|
|
|
300
346
|
end
|
|
301
347
|
end
|
|
302
348
|
|
|
303
|
-
function SpringObject:_applyTarget(unconverted, doNotAnimate)
|
|
349
|
+
function SpringObject:_applyTarget(unconverted, doNotAnimate: boolean?)
|
|
304
350
|
local converted = SpringUtils.toLinearIfNeeded(unconverted)
|
|
305
351
|
self:_getSpringForType(converted):SetTarget(converted, doNotAnimate)
|
|
306
352
|
self.Changed:Fire()
|
|
@@ -328,7 +374,7 @@ end
|
|
|
328
374
|
function SpringObject:_applyVelocity(unconverted)
|
|
329
375
|
local converted = SpringUtils.toLinearIfNeeded(unconverted)
|
|
330
376
|
|
|
331
|
-
self:_getSpringForType(0*converted).Velocity = converted
|
|
377
|
+
self:_getSpringForType(0 * (converted :: any)).Velocity = converted
|
|
332
378
|
self.Changed:Fire()
|
|
333
379
|
end
|
|
334
380
|
|
|
@@ -377,8 +423,8 @@ function SpringObject:SetDamper(damper)
|
|
|
377
423
|
end
|
|
378
424
|
end
|
|
379
425
|
|
|
380
|
-
function SpringObject:_applyDamper(unconverted)
|
|
381
|
-
assert(type(unconverted) == "number", "Bad
|
|
426
|
+
function SpringObject:_applyDamper(unconverted: number)
|
|
427
|
+
assert(type(unconverted) == "number", "Bad unconverted")
|
|
382
428
|
|
|
383
429
|
local currentSpring = rawget(self, "_currentSpring")
|
|
384
430
|
if currentSpring then
|
|
@@ -410,8 +456,8 @@ function SpringObject:SetSpeed(speed)
|
|
|
410
456
|
end
|
|
411
457
|
end
|
|
412
458
|
|
|
413
|
-
function SpringObject:_applySpeed(unconverted)
|
|
414
|
-
assert(type(unconverted) == "number", "Bad
|
|
459
|
+
function SpringObject:_applySpeed(unconverted: number)
|
|
460
|
+
assert(type(unconverted) == "number", "Bad unconverted")
|
|
415
461
|
|
|
416
462
|
local currentSpring = rawget(self, "_currentSpring")
|
|
417
463
|
if currentSpring then
|
|
@@ -428,7 +474,7 @@ end
|
|
|
428
474
|
|
|
429
475
|
@param clock () -> (number)
|
|
430
476
|
]=]
|
|
431
|
-
function SpringObject:SetClock(clock)
|
|
477
|
+
function SpringObject:SetClock(clock: Spring.SpringClock)
|
|
432
478
|
assert(type(clock) == "function", "Bad clock clock")
|
|
433
479
|
|
|
434
480
|
local currentSpring = rawget(self, "_currentSpring")
|
|
@@ -446,7 +492,7 @@ end
|
|
|
446
492
|
|
|
447
493
|
@param epsilon number
|
|
448
494
|
]=]
|
|
449
|
-
function SpringObject:SetEpsilon(epsilon)
|
|
495
|
+
function SpringObject:SetEpsilon(epsilon: number)
|
|
450
496
|
assert(type(epsilon) == "number", "Bad epsilon")
|
|
451
497
|
|
|
452
498
|
rawset(self, "_epsilon", epsilon)
|
|
@@ -459,7 +505,7 @@ end
|
|
|
459
505
|
@param delta number -- Time to skip forwards
|
|
460
506
|
@return ()
|
|
461
507
|
]=]
|
|
462
|
-
function SpringObject:TimeSkip(delta)
|
|
508
|
+
function SpringObject:TimeSkip(delta: number)
|
|
463
509
|
assert(type(delta) == "number", "Bad delta")
|
|
464
510
|
|
|
465
511
|
local currentSpring = rawget(self, "_currentSpring")
|
|
@@ -471,7 +517,7 @@ function SpringObject:TimeSkip(delta)
|
|
|
471
517
|
self.Changed:Fire()
|
|
472
518
|
end
|
|
473
519
|
|
|
474
|
-
|
|
520
|
+
(SpringObject :: any).__index = function(self, index)
|
|
475
521
|
local currentSpring = rawget(self, "_currentSpring")
|
|
476
522
|
|
|
477
523
|
if SpringObject[index] then
|
|
@@ -498,19 +544,19 @@ function SpringObject:__index(index)
|
|
|
498
544
|
if currentSpring then
|
|
499
545
|
return currentSpring.Damper
|
|
500
546
|
else
|
|
501
|
-
return self:_getInitInfo().Damper
|
|
547
|
+
return (self :: any):_getInitInfo().Damper
|
|
502
548
|
end
|
|
503
549
|
elseif index == "Speed" or index == "s" then
|
|
504
550
|
if currentSpring then
|
|
505
551
|
return currentSpring.Speed
|
|
506
552
|
else
|
|
507
|
-
return self:_getInitInfo().Speed
|
|
553
|
+
return (self :: any):_getInitInfo().Speed
|
|
508
554
|
end
|
|
509
555
|
elseif index == "Clock" then
|
|
510
556
|
if currentSpring then
|
|
511
557
|
return currentSpring.Clock
|
|
512
558
|
else
|
|
513
|
-
return self:_getInitInfo().Clock
|
|
559
|
+
return (self :: any):_getInitInfo().Clock
|
|
514
560
|
end
|
|
515
561
|
elseif index == "Epsilon" then
|
|
516
562
|
return self._epsilon
|
|
@@ -23,7 +23,7 @@ return function(target)
|
|
|
23
23
|
Size = UDim2.new(0, 100, 0, 20);
|
|
24
24
|
[Blend.OnEvent "Activated"] = function()
|
|
25
25
|
local newState = {}
|
|
26
|
-
for _, item in
|
|
26
|
+
for _, item in state.Value do
|
|
27
27
|
table.insert(newState, item)
|
|
28
28
|
end
|
|
29
29
|
table.insert(newState, string.char(string.byte("a") + #newState))
|