roblox-opencode 1.0.0 → 1.0.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/README.md +112 -122
- package/commands/setup-game.md +108 -108
- package/commands/sync-check.md +53 -53
- package/core/roblox-core.md +93 -93
- package/dist/server.js +189 -167
- package/package.json +35 -35
- package/skills/roblox-analytics/SKILL.md +277 -277
- package/skills/roblox-analytics/references/event-batcher.luau +75 -75
- package/skills/roblox-animation-vfx/SKILL.md +1325 -1325
- package/skills/roblox-architecture/SKILL.md +863 -863
- package/skills/roblox-architecture/references/combat-systems.md +1381 -1381
- package/skills/roblox-code-review/SKILL.md +686 -686
- package/skills/roblox-data/SKILL.md +889 -889
- package/skills/roblox-data/references/inventory-systems.md +1729 -1729
- package/skills/roblox-debug/SKILL.md +98 -98
- package/skills/roblox-gui/SKILL.md +1103 -1103
- package/skills/roblox-gui-fusion/SKILL.md +150 -150
- package/skills/roblox-gui-fusion/references/inventory.luau +427 -427
- package/skills/roblox-gui-fusion/references/settings-menu.luau +579 -579
- package/skills/roblox-gui-fusion/references/shop.luau +411 -411
- package/skills/roblox-luau-mastery/SKILL.md +1519 -1519
- package/skills/roblox-monetization/SKILL.md +1084 -1084
- package/skills/roblox-monetization/references/process-receipt.luau +131 -131
- package/skills/roblox-networking/SKILL.md +669 -669
- package/skills/roblox-networking/references/remote-validator.luau +193 -193
- package/skills/roblox-publish-checklist/SKILL.md +127 -127
- package/skills/roblox-runtime/SKILL.md +753 -753
- package/skills/roblox-sharp-edges/SKILL.md +294 -294
- package/skills/roblox-sync/SKILL.md +126 -126
- package/skills/roblox-testing/SKILL.md +943 -943
- package/skills/roblox-tooling/SKILL.md +149 -149
- package/vendor/LICENSES/ProfileStore-LICENSE +201 -201
- package/vendor/LICENSES/RbxUtil-LICENSE +7 -7
- package/vendor/LICENSES/promise-LICENSE +20 -20
- package/vendor/LICENSES/t-LICENSE +21 -21
- package/vendor/LICENSES/testez-LICENSE +200 -200
- package/vendor/README.md +83 -83
- package/vendor/fusion/Animation/ExternalTime.luau +83 -83
- package/vendor/fusion/Animation/Spring.luau +321 -321
- package/vendor/fusion/Animation/Stopwatch.luau +127 -127
- package/vendor/fusion/Animation/Tween.luau +187 -187
- package/vendor/fusion/Animation/getTweenDuration.luau +27 -27
- package/vendor/fusion/Animation/getTweenRatio.luau +47 -47
- package/vendor/fusion/Animation/lerpType.luau +163 -163
- package/vendor/fusion/Animation/packType.luau +99 -99
- package/vendor/fusion/Animation/springCoefficients.luau +80 -80
- package/vendor/fusion/Animation/unpackType.luau +102 -102
- package/vendor/fusion/Colour/Oklab.luau +70 -70
- package/vendor/fusion/Colour/sRGB.luau +54 -54
- package/vendor/fusion/External.luau +167 -167
- package/vendor/fusion/ExternalDebug.luau +69 -69
- package/vendor/fusion/Graph/Observer.luau +113 -113
- package/vendor/fusion/Graph/castToGraph.luau +28 -28
- package/vendor/fusion/Graph/change.luau +80 -80
- package/vendor/fusion/Graph/depend.luau +32 -32
- package/vendor/fusion/Graph/evaluate.luau +55 -55
- package/vendor/fusion/Instances/Attribute.luau +57 -57
- package/vendor/fusion/Instances/AttributeChange.luau +46 -46
- package/vendor/fusion/Instances/AttributeOut.luau +63 -63
- package/vendor/fusion/Instances/Child.luau +21 -21
- package/vendor/fusion/Instances/Children.luau +147 -147
- package/vendor/fusion/Instances/Hydrate.luau +32 -32
- package/vendor/fusion/Instances/New.luau +52 -52
- package/vendor/fusion/Instances/OnChange.luau +49 -49
- package/vendor/fusion/Instances/OnEvent.luau +53 -53
- package/vendor/fusion/Instances/Out.luau +69 -69
- package/vendor/fusion/Instances/applyInstanceProps.luau +148 -148
- package/vendor/fusion/Instances/defaultProps.luau +194 -194
- package/vendor/fusion/LICENSE +21 -21
- package/vendor/fusion/Logging/formatError.luau +48 -48
- package/vendor/fusion/Logging/messages.luau +51 -51
- package/vendor/fusion/Logging/parseError.luau +24 -24
- package/vendor/fusion/Memory/checkLifetime.luau +133 -133
- package/vendor/fusion/Memory/deriveScope.luau +23 -23
- package/vendor/fusion/Memory/deriveScopeImpl.luau +44 -44
- package/vendor/fusion/Memory/doCleanup.luau +78 -78
- package/vendor/fusion/Memory/innerScope.luau +33 -33
- package/vendor/fusion/Memory/legacyCleanup.luau +17 -17
- package/vendor/fusion/Memory/needsDestruction.luau +16 -16
- package/vendor/fusion/Memory/poisonScope.luau +33 -33
- package/vendor/fusion/Memory/scopePool.luau +54 -54
- package/vendor/fusion/Memory/scoped.luau +26 -26
- package/vendor/fusion/Memory/whichLivesLonger.luau +74 -74
- package/vendor/fusion/RobloxExternal.luau +97 -97
- package/vendor/fusion/State/Computed.luau +138 -138
- package/vendor/fusion/State/For/Disassembly.luau +210 -210
- package/vendor/fusion/State/For/ForTypes.luau +30 -30
- package/vendor/fusion/State/For/init.luau +109 -109
- package/vendor/fusion/State/ForKeys.luau +93 -93
- package/vendor/fusion/State/ForPairs.luau +96 -96
- package/vendor/fusion/State/ForValues.luau +93 -93
- package/vendor/fusion/State/Value.luau +87 -87
- package/vendor/fusion/State/castToState.luau +25 -25
- package/vendor/fusion/State/peek.luau +30 -30
- package/vendor/fusion/Types.luau +314 -314
- package/vendor/fusion/Utility/Contextual.luau +90 -90
- package/vendor/fusion/Utility/Safe.luau +22 -22
- package/vendor/fusion/Utility/isSimilar.luau +29 -29
- package/vendor/fusion/Utility/merge.luau +35 -35
- package/vendor/fusion/Utility/nameOf.luau +34 -34
- package/vendor/fusion/Utility/never.luau +13 -13
- package/vendor/fusion/Utility/nicknames.luau +10 -10
- package/vendor/fusion/Utility/xtypeof.luau +26 -26
- package/vendor/fusion/init.luau +82 -82
- package/vendor/profilestore/init.luau +2242 -2242
- package/vendor/promise/init.luau +1982 -1982
- package/vendor/rbxutil/buffer-util/Buffer.test.luau +25 -25
- package/vendor/rbxutil/buffer-util/BufferReader.luau +228 -228
- package/vendor/rbxutil/buffer-util/BufferWriter.luau +269 -269
- package/vendor/rbxutil/buffer-util/DataTypeBuffer.luau +223 -223
- package/vendor/rbxutil/buffer-util/Types.luau +60 -60
- package/vendor/rbxutil/buffer-util/index.d.ts +153 -153
- package/vendor/rbxutil/buffer-util/init.luau +41 -41
- package/vendor/rbxutil/buffer-util/package.json +16 -16
- package/vendor/rbxutil/buffer-util/wally.toml +9 -9
- package/vendor/rbxutil/comm/Client/ClientComm.luau +232 -232
- package/vendor/rbxutil/comm/Client/ClientRemoteProperty.luau +156 -156
- package/vendor/rbxutil/comm/Client/ClientRemoteSignal.luau +109 -109
- package/vendor/rbxutil/comm/Client/init.luau +135 -135
- package/vendor/rbxutil/comm/Server/RemoteProperty.luau +295 -295
- package/vendor/rbxutil/comm/Server/RemoteSignal.luau +211 -211
- package/vendor/rbxutil/comm/Server/ServerComm.luau +211 -211
- package/vendor/rbxutil/comm/Server/init.luau +140 -140
- package/vendor/rbxutil/comm/Types.luau +18 -18
- package/vendor/rbxutil/comm/Util.luau +27 -27
- package/vendor/rbxutil/comm/init.luau +35 -35
- package/vendor/rbxutil/comm/wally.toml +13 -13
- package/vendor/rbxutil/component/init.luau +759 -759
- package/vendor/rbxutil/component/init.test.luau +311 -311
- package/vendor/rbxutil/component/wally.toml +14 -14
- package/vendor/rbxutil/concur/init.luau +542 -542
- package/vendor/rbxutil/concur/init.test.luau +364 -364
- package/vendor/rbxutil/concur/wally.toml +8 -8
- package/vendor/rbxutil/enum-list/init.luau +101 -101
- package/vendor/rbxutil/enum-list/init.test.luau +91 -91
- package/vendor/rbxutil/enum-list/wally.toml +8 -8
- package/vendor/rbxutil/find/index.d.ts +20 -20
- package/vendor/rbxutil/find/init.luau +44 -44
- package/vendor/rbxutil/find/package.json +17 -17
- package/vendor/rbxutil/find/wally.toml +8 -8
- package/vendor/rbxutil/input/Gamepad.luau +559 -559
- package/vendor/rbxutil/input/Keyboard.luau +124 -124
- package/vendor/rbxutil/input/Mouse.luau +278 -278
- package/vendor/rbxutil/input/PreferredInput.luau +91 -91
- package/vendor/rbxutil/input/Touch.luau +120 -120
- package/vendor/rbxutil/input/init.luau +33 -33
- package/vendor/rbxutil/input/wally.toml +12 -12
- package/vendor/rbxutil/loader/index.d.ts +15 -15
- package/vendor/rbxutil/loader/init.luau +137 -137
- package/vendor/rbxutil/loader/wally.toml +8 -8
- package/vendor/rbxutil/log/index.d.ts +38 -38
- package/vendor/rbxutil/log/init.luau +746 -746
- package/vendor/rbxutil/log/wally.toml +8 -8
- package/vendor/rbxutil/net/init.luau +190 -190
- package/vendor/rbxutil/net/wally.toml +8 -8
- package/vendor/rbxutil/option/index.d.ts +44 -44
- package/vendor/rbxutil/option/init.luau +489 -489
- package/vendor/rbxutil/option/init.test.luau +342 -342
- package/vendor/rbxutil/option/wally.toml +8 -8
- package/vendor/rbxutil/pid/index.d.ts +53 -53
- package/vendor/rbxutil/pid/init.luau +195 -195
- package/vendor/rbxutil/pid/package.json +16 -16
- package/vendor/rbxutil/pid/wally.toml +9 -9
- package/vendor/rbxutil/quaternion/index.d.ts +117 -117
- package/vendor/rbxutil/quaternion/init.luau +570 -570
- package/vendor/rbxutil/quaternion/package.json +16 -16
- package/vendor/rbxutil/quaternion/wally.toml +9 -9
- package/vendor/rbxutil/query/index.d.ts +43 -43
- package/vendor/rbxutil/query/init.luau +117 -117
- package/vendor/rbxutil/query/package.json +18 -18
- package/vendor/rbxutil/query/wally.toml +9 -9
- package/vendor/rbxutil/sequent/index.d.ts +28 -28
- package/vendor/rbxutil/sequent/init.luau +340 -340
- package/vendor/rbxutil/sequent/package.json +16 -16
- package/vendor/rbxutil/sequent/wally.toml +9 -9
- package/vendor/rbxutil/ser/init.luau +175 -175
- package/vendor/rbxutil/ser/init.test.luau +50 -50
- package/vendor/rbxutil/ser/wally.toml +11 -11
- package/vendor/rbxutil/shake/index.d.ts +36 -36
- package/vendor/rbxutil/shake/init.luau +532 -532
- package/vendor/rbxutil/shake/init.test.luau +267 -267
- package/vendor/rbxutil/shake/package.json +16 -16
- package/vendor/rbxutil/shake/wally.toml +9 -9
- package/vendor/rbxutil/signal/index.d.ts +100 -100
- package/vendor/rbxutil/signal/init.luau +432 -432
- package/vendor/rbxutil/signal/init.test.luau +190 -190
- package/vendor/rbxutil/signal/package.json +17 -17
- package/vendor/rbxutil/signal/wally.toml +9 -9
- package/vendor/rbxutil/silo/TableWatcher.luau +65 -65
- package/vendor/rbxutil/silo/Util.luau +55 -55
- package/vendor/rbxutil/silo/init.luau +338 -338
- package/vendor/rbxutil/silo/init.test.luau +215 -215
- package/vendor/rbxutil/silo/wally.toml +8 -8
- package/vendor/rbxutil/spring/index.d.ts +40 -40
- package/vendor/rbxutil/spring/init.luau +97 -97
- package/vendor/rbxutil/spring/package.json +17 -17
- package/vendor/rbxutil/spring/wally.toml +8 -8
- package/vendor/rbxutil/stream/index.d.ts +88 -88
- package/vendor/rbxutil/stream/init.luau +597 -597
- package/vendor/rbxutil/stream/package.json +18 -18
- package/vendor/rbxutil/stream/wally.toml +9 -9
- package/vendor/rbxutil/streamable/Streamable.luau +202 -202
- package/vendor/rbxutil/streamable/StreamableUtil.luau +80 -80
- package/vendor/rbxutil/streamable/init.luau +8 -8
- package/vendor/rbxutil/streamable/wally.toml +12 -12
- package/vendor/rbxutil/symbol/init.luau +56 -56
- package/vendor/rbxutil/symbol/init.test.luau +37 -37
- package/vendor/rbxutil/symbol/wally.toml +8 -8
- package/vendor/rbxutil/table-util/init.luau +938 -938
- package/vendor/rbxutil/table-util/init.test.luau +439 -439
- package/vendor/rbxutil/task-queue/index.d.ts +27 -27
- package/vendor/rbxutil/task-queue/init.luau +97 -97
- package/vendor/rbxutil/task-queue/wally.toml +8 -8
- package/vendor/rbxutil/timer/index.d.ts +81 -81
- package/vendor/rbxutil/timer/init.luau +249 -249
- package/vendor/rbxutil/timer/init.test.luau +73 -73
- package/vendor/rbxutil/timer/wally.toml +11 -11
- package/vendor/rbxutil/tree/index.d.ts +15 -15
- package/vendor/rbxutil/tree/init.luau +137 -137
- package/vendor/rbxutil/tree/wally.toml +8 -8
- package/vendor/rbxutil/trove/index.d.ts +46 -46
- package/vendor/rbxutil/trove/init.luau +787 -787
- package/vendor/rbxutil/trove/init.test.luau +203 -203
- package/vendor/rbxutil/trove/wally.toml +8 -8
- package/vendor/rbxutil/typed-remote/init.luau +196 -196
- package/vendor/rbxutil/typed-remote/wally.toml +8 -8
- package/vendor/rbxutil/wait-for/index.d.ts +17 -17
- package/vendor/rbxutil/wait-for/init.luau +257 -257
- package/vendor/rbxutil/wait-for/init.test.luau +182 -182
- package/vendor/rbxutil/wait-for/wally.toml +11 -11
- package/vendor/t/t.lua +1350 -1350
- package/vendor/testez/Context.lua +26 -26
- package/vendor/testez/Expectation.lua +311 -311
- package/vendor/testez/ExpectationContext.lua +38 -38
- package/vendor/testez/LifecycleHooks.lua +89 -89
- package/vendor/testez/Reporters/TeamCityReporter.lua +101 -101
- package/vendor/testez/Reporters/TextReporter.lua +105 -105
- package/vendor/testez/Reporters/TextReporterQuiet.lua +96 -96
- package/vendor/testez/TestBootstrap.lua +146 -146
- package/vendor/testez/TestEnum.lua +27 -27
- package/vendor/testez/TestPlan.lua +304 -304
- package/vendor/testez/TestPlanner.lua +39 -39
- package/vendor/testez/TestResults.lua +111 -111
- package/vendor/testez/TestRunner.lua +188 -188
- package/vendor/testez/TestSession.lua +243 -243
- package/vendor/testez/init.lua +39 -39
|
@@ -1,128 +1,128 @@
|
|
|
1
|
-
--!strict
|
|
2
|
-
--!nolint LocalUnused
|
|
3
|
-
--!nolint LocalShadow
|
|
4
|
-
local task = nil -- Disable usage of Roblox's task scheduler
|
|
5
|
-
|
|
6
|
-
--[[
|
|
7
|
-
State object for measuring time since an event using a reference timer.
|
|
8
|
-
|
|
9
|
-
TODO: this should not be exposed to users until it has a proper reactive API
|
|
10
|
-
surface
|
|
11
|
-
]]
|
|
12
|
-
|
|
13
|
-
local Package = script.Parent.Parent
|
|
14
|
-
local Types = require(Package.Types)
|
|
15
|
-
-- Memory
|
|
16
|
-
local checkLifetime = require(Package.Memory.checkLifetime)
|
|
17
|
-
-- Graph
|
|
18
|
-
local depend = require(Package.Graph.depend)
|
|
19
|
-
local change = require(Package.Graph.change)
|
|
20
|
-
-- State
|
|
21
|
-
local peek = require(Package.State.peek)
|
|
22
|
-
-- Utility
|
|
23
|
-
local nicknames = require(Package.Utility.nicknames)
|
|
24
|
-
|
|
25
|
-
export type Stopwatch = Types.StateObject<number> & {
|
|
26
|
-
zero: (Stopwatch) -> (),
|
|
27
|
-
pause: (Stopwatch) -> (),
|
|
28
|
-
unpause: (Stopwatch) -> ()
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
type Self = Stopwatch & {
|
|
32
|
-
_measureTimeSince: number,
|
|
33
|
-
_playing: boolean,
|
|
34
|
-
_timer: Types.StateObject<number>
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
local class = {}
|
|
38
|
-
class.type = "State"
|
|
39
|
-
class.kind = "Stopwatch"
|
|
40
|
-
class.timeliness = "lazy"
|
|
41
|
-
|
|
42
|
-
local METATABLE = table.freeze {__index = class}
|
|
43
|
-
|
|
44
|
-
local function Stopwatch(
|
|
45
|
-
scope: Types.Scope<unknown>,
|
|
46
|
-
timer: Types.StateObject<number>
|
|
47
|
-
): Stopwatch
|
|
48
|
-
local createdAt = os.clock()
|
|
49
|
-
local self: Self = setmetatable(
|
|
50
|
-
{
|
|
51
|
-
awake = true,
|
|
52
|
-
createdAt = createdAt,
|
|
53
|
-
dependencySet = {},
|
|
54
|
-
dependentSet = {},
|
|
55
|
-
lastChange = nil,
|
|
56
|
-
scope = scope,
|
|
57
|
-
validity = "invalid",
|
|
58
|
-
_EXTREMELY_DANGEROUS_usedAsValue = 0,
|
|
59
|
-
_measureTimeSince = 0, -- this should be set on unpause
|
|
60
|
-
_playing = false,
|
|
61
|
-
_timer = timer
|
|
62
|
-
},
|
|
63
|
-
METATABLE
|
|
64
|
-
) :: any
|
|
65
|
-
local destroy = function()
|
|
66
|
-
self.scope = nil
|
|
67
|
-
end
|
|
68
|
-
self.oldestTask = destroy
|
|
69
|
-
nicknames[self.oldestTask] = "Stopwatch"
|
|
70
|
-
table.insert(scope, destroy)
|
|
71
|
-
|
|
72
|
-
checkLifetime.bOutlivesA(
|
|
73
|
-
scope, self.oldestTask,
|
|
74
|
-
timer.scope, timer.oldestTask,
|
|
75
|
-
checkLifetime.formatters.parameter, "timer"
|
|
76
|
-
)
|
|
77
|
-
depend(self, timer)
|
|
78
|
-
return self
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
function class.zero(
|
|
82
|
-
self: Self
|
|
83
|
-
): ()
|
|
84
|
-
local newTimepoint = peek(self._timer)
|
|
85
|
-
if newTimepoint ~= self._measureTimeSince then
|
|
86
|
-
self._measureTimeSince = newTimepoint
|
|
87
|
-
self._EXTREMELY_DANGEROUS_usedAsValue = 0
|
|
88
|
-
change(self)
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
function class.pause(
|
|
93
|
-
self: Self
|
|
94
|
-
): ()
|
|
95
|
-
if self._playing == true then
|
|
96
|
-
self._playing = false
|
|
97
|
-
change(self)
|
|
98
|
-
end
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
function class.unpause(
|
|
102
|
-
self: Self
|
|
103
|
-
): ()
|
|
104
|
-
if self._playing == false then
|
|
105
|
-
self._playing = true
|
|
106
|
-
self._measureTimeSince = peek(self._timer) - self._EXTREMELY_DANGEROUS_usedAsValue
|
|
107
|
-
change(self)
|
|
108
|
-
end
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
function class._evaluate(
|
|
112
|
-
self: Self
|
|
113
|
-
): boolean
|
|
114
|
-
if self._playing then
|
|
115
|
-
depend(self, self._timer)
|
|
116
|
-
local currentTime = peek(self._timer)
|
|
117
|
-
local oldValue = self._EXTREMELY_DANGEROUS_usedAsValue
|
|
118
|
-
local newValue = currentTime - self._measureTimeSince
|
|
119
|
-
self._EXTREMELY_DANGEROUS_usedAsValue = newValue
|
|
120
|
-
return oldValue ~= newValue
|
|
121
|
-
else
|
|
122
|
-
return false
|
|
123
|
-
end
|
|
124
|
-
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
table.freeze(class)
|
|
1
|
+
--!strict
|
|
2
|
+
--!nolint LocalUnused
|
|
3
|
+
--!nolint LocalShadow
|
|
4
|
+
local task = nil -- Disable usage of Roblox's task scheduler
|
|
5
|
+
|
|
6
|
+
--[[
|
|
7
|
+
State object for measuring time since an event using a reference timer.
|
|
8
|
+
|
|
9
|
+
TODO: this should not be exposed to users until it has a proper reactive API
|
|
10
|
+
surface
|
|
11
|
+
]]
|
|
12
|
+
|
|
13
|
+
local Package = script.Parent.Parent
|
|
14
|
+
local Types = require(Package.Types)
|
|
15
|
+
-- Memory
|
|
16
|
+
local checkLifetime = require(Package.Memory.checkLifetime)
|
|
17
|
+
-- Graph
|
|
18
|
+
local depend = require(Package.Graph.depend)
|
|
19
|
+
local change = require(Package.Graph.change)
|
|
20
|
+
-- State
|
|
21
|
+
local peek = require(Package.State.peek)
|
|
22
|
+
-- Utility
|
|
23
|
+
local nicknames = require(Package.Utility.nicknames)
|
|
24
|
+
|
|
25
|
+
export type Stopwatch = Types.StateObject<number> & {
|
|
26
|
+
zero: (Stopwatch) -> (),
|
|
27
|
+
pause: (Stopwatch) -> (),
|
|
28
|
+
unpause: (Stopwatch) -> ()
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
type Self = Stopwatch & {
|
|
32
|
+
_measureTimeSince: number,
|
|
33
|
+
_playing: boolean,
|
|
34
|
+
_timer: Types.StateObject<number>
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
local class = {}
|
|
38
|
+
class.type = "State"
|
|
39
|
+
class.kind = "Stopwatch"
|
|
40
|
+
class.timeliness = "lazy"
|
|
41
|
+
|
|
42
|
+
local METATABLE = table.freeze {__index = class}
|
|
43
|
+
|
|
44
|
+
local function Stopwatch(
|
|
45
|
+
scope: Types.Scope<unknown>,
|
|
46
|
+
timer: Types.StateObject<number>
|
|
47
|
+
): Stopwatch
|
|
48
|
+
local createdAt = os.clock()
|
|
49
|
+
local self: Self = setmetatable(
|
|
50
|
+
{
|
|
51
|
+
awake = true,
|
|
52
|
+
createdAt = createdAt,
|
|
53
|
+
dependencySet = {},
|
|
54
|
+
dependentSet = {},
|
|
55
|
+
lastChange = nil,
|
|
56
|
+
scope = scope,
|
|
57
|
+
validity = "invalid",
|
|
58
|
+
_EXTREMELY_DANGEROUS_usedAsValue = 0,
|
|
59
|
+
_measureTimeSince = 0, -- this should be set on unpause
|
|
60
|
+
_playing = false,
|
|
61
|
+
_timer = timer
|
|
62
|
+
},
|
|
63
|
+
METATABLE
|
|
64
|
+
) :: any
|
|
65
|
+
local destroy = function()
|
|
66
|
+
self.scope = nil
|
|
67
|
+
end
|
|
68
|
+
self.oldestTask = destroy
|
|
69
|
+
nicknames[self.oldestTask] = "Stopwatch"
|
|
70
|
+
table.insert(scope, destroy)
|
|
71
|
+
|
|
72
|
+
checkLifetime.bOutlivesA(
|
|
73
|
+
scope, self.oldestTask,
|
|
74
|
+
timer.scope, timer.oldestTask,
|
|
75
|
+
checkLifetime.formatters.parameter, "timer"
|
|
76
|
+
)
|
|
77
|
+
depend(self, timer)
|
|
78
|
+
return self
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
function class.zero(
|
|
82
|
+
self: Self
|
|
83
|
+
): ()
|
|
84
|
+
local newTimepoint = peek(self._timer)
|
|
85
|
+
if newTimepoint ~= self._measureTimeSince then
|
|
86
|
+
self._measureTimeSince = newTimepoint
|
|
87
|
+
self._EXTREMELY_DANGEROUS_usedAsValue = 0
|
|
88
|
+
change(self)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
function class.pause(
|
|
93
|
+
self: Self
|
|
94
|
+
): ()
|
|
95
|
+
if self._playing == true then
|
|
96
|
+
self._playing = false
|
|
97
|
+
change(self)
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
function class.unpause(
|
|
102
|
+
self: Self
|
|
103
|
+
): ()
|
|
104
|
+
if self._playing == false then
|
|
105
|
+
self._playing = true
|
|
106
|
+
self._measureTimeSince = peek(self._timer) - self._EXTREMELY_DANGEROUS_usedAsValue
|
|
107
|
+
change(self)
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
function class._evaluate(
|
|
112
|
+
self: Self
|
|
113
|
+
): boolean
|
|
114
|
+
if self._playing then
|
|
115
|
+
depend(self, self._timer)
|
|
116
|
+
local currentTime = peek(self._timer)
|
|
117
|
+
local oldValue = self._EXTREMELY_DANGEROUS_usedAsValue
|
|
118
|
+
local newValue = currentTime - self._measureTimeSince
|
|
119
|
+
self._EXTREMELY_DANGEROUS_usedAsValue = newValue
|
|
120
|
+
return oldValue ~= newValue
|
|
121
|
+
else
|
|
122
|
+
return false
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
table.freeze(class)
|
|
128
128
|
return Stopwatch
|
|
@@ -1,187 +1,187 @@
|
|
|
1
|
-
--!strict
|
|
2
|
-
--!nolint LocalUnused
|
|
3
|
-
--!nolint LocalShadow
|
|
4
|
-
local task = nil -- Disable usage of Roblox's task scheduler
|
|
5
|
-
|
|
6
|
-
--[[
|
|
7
|
-
A specialised state object for following a goal state smoothly over time,
|
|
8
|
-
using a TweenInfo to shape the motion.
|
|
9
|
-
|
|
10
|
-
https://elttob.uk/Fusion/0.3/api-reference/animation/types/tween/
|
|
11
|
-
]]
|
|
12
|
-
|
|
13
|
-
local Package = script.Parent.Parent
|
|
14
|
-
local Types = require(Package.Types)
|
|
15
|
-
local External = require(Package.External)
|
|
16
|
-
-- Memory
|
|
17
|
-
local checkLifetime = require(Package.Memory.checkLifetime)
|
|
18
|
-
-- Graph
|
|
19
|
-
local depend = require(Package.Graph.depend)
|
|
20
|
-
local evaluate = require(Package.Graph.evaluate)
|
|
21
|
-
-- State
|
|
22
|
-
local castToState = require(Package.State.castToState)
|
|
23
|
-
local peek = require(Package.State.peek)
|
|
24
|
-
-- Animation
|
|
25
|
-
local ExternalTime = require(Package.Animation.ExternalTime)
|
|
26
|
-
local Stopwatch = require(Package.Animation.Stopwatch)
|
|
27
|
-
local lerpType = require(Package.Animation.lerpType)
|
|
28
|
-
local getTweenRatio = require(Package.Animation.getTweenRatio)
|
|
29
|
-
local getTweenDuration = require(Package.Animation.getTweenDuration)
|
|
30
|
-
-- Utility
|
|
31
|
-
local nicknames = require(Package.Utility.nicknames)
|
|
32
|
-
|
|
33
|
-
export type Self<T> = Types.Tween<T> & {
|
|
34
|
-
_activeDuration: number,
|
|
35
|
-
_activeElapsed: number,
|
|
36
|
-
_activeFrom: T,
|
|
37
|
-
_activeTo: T,
|
|
38
|
-
_activeTweenInfo: TweenInfo,
|
|
39
|
-
_goal: Types.UsedAs<T>,
|
|
40
|
-
_stopwatch: Stopwatch.Stopwatch?,
|
|
41
|
-
_tweenInfo: Types.UsedAs<TweenInfo>,
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
local class = {}
|
|
45
|
-
class.type = "State"
|
|
46
|
-
class.kind = "Tween"
|
|
47
|
-
class.timeliness = "eager"
|
|
48
|
-
|
|
49
|
-
local METATABLE = table.freeze {__index = class}
|
|
50
|
-
|
|
51
|
-
local function Tween<T>(
|
|
52
|
-
scope: Types.Scope<unknown>,
|
|
53
|
-
goal: Types.UsedAs<T>,
|
|
54
|
-
tweenInfo: Types.UsedAs<TweenInfo>?
|
|
55
|
-
): Types.Tween<T>
|
|
56
|
-
local createdAt = os.clock()
|
|
57
|
-
if castToState(scope) then
|
|
58
|
-
External.logError("scopeMissing", nil, "Tweens", "myScope:Tween(goalState, tweenInfo)")
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
local goalState = castToState(goal)
|
|
62
|
-
local stopwatch = nil
|
|
63
|
-
if goalState ~= nil then
|
|
64
|
-
stopwatch = Stopwatch(scope, ExternalTime(scope))
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
local self: Self<T> = setmetatable(
|
|
68
|
-
{
|
|
69
|
-
createdAt = createdAt,
|
|
70
|
-
dependencySet = {},
|
|
71
|
-
dependentSet = {},
|
|
72
|
-
lastChange = nil,
|
|
73
|
-
scope = scope,
|
|
74
|
-
validity = "invalid",
|
|
75
|
-
_activeDuration = nil,
|
|
76
|
-
_activeElapsed = nil,
|
|
77
|
-
_activeFrom = nil,
|
|
78
|
-
_activeTo = nil,
|
|
79
|
-
_activeTweenInfo = nil,
|
|
80
|
-
_EXTREMELY_DANGEROUS_usedAsValue = peek(goal),
|
|
81
|
-
_goal = goal,
|
|
82
|
-
_stopwatch = stopwatch,
|
|
83
|
-
_tweenInfo = tweenInfo or TweenInfo.new()
|
|
84
|
-
},
|
|
85
|
-
METATABLE
|
|
86
|
-
) :: any
|
|
87
|
-
local destroy = function()
|
|
88
|
-
self.scope = nil
|
|
89
|
-
for dependency in pairs(self.dependencySet) do
|
|
90
|
-
dependency.dependentSet[self] = nil
|
|
91
|
-
end
|
|
92
|
-
end
|
|
93
|
-
self.oldestTask = destroy
|
|
94
|
-
nicknames[self.oldestTask] = "Tween"
|
|
95
|
-
table.insert(scope, destroy)
|
|
96
|
-
|
|
97
|
-
if goalState ~= nil then
|
|
98
|
-
checkLifetime.bOutlivesA(
|
|
99
|
-
scope, self.oldestTask,
|
|
100
|
-
goalState.scope, goalState.oldestTask,
|
|
101
|
-
checkLifetime.formatters.animationGoal
|
|
102
|
-
)
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
local tweenInfoState = castToState(tweenInfo)
|
|
106
|
-
if tweenInfoState ~= nil then
|
|
107
|
-
checkLifetime.bOutlivesA(
|
|
108
|
-
scope, self.oldestTask,
|
|
109
|
-
tweenInfoState.scope, tweenInfoState.oldestTask,
|
|
110
|
-
checkLifetime.formatters.parameter, "tween info"
|
|
111
|
-
)
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
-- Eagerly evaluated objects need to evaluate themselves so that they're
|
|
115
|
-
-- valid at all times.
|
|
116
|
-
evaluate(self, true)
|
|
117
|
-
|
|
118
|
-
return self
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
function class.get<T>(
|
|
122
|
-
self: Self<T>
|
|
123
|
-
): never
|
|
124
|
-
return External.logError("stateGetWasRemoved")
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
function class._evaluate<T>(
|
|
128
|
-
self: Self<T>
|
|
129
|
-
): boolean
|
|
130
|
-
local goal = castToState(self._goal)
|
|
131
|
-
-- Allow non-state goals to pass through transparently.
|
|
132
|
-
if goal == nil then
|
|
133
|
-
self._EXTREMELY_DANGEROUS_usedAsValue = self._goal :: T
|
|
134
|
-
return false
|
|
135
|
-
end
|
|
136
|
-
depend(self, goal)
|
|
137
|
-
local newTweenTo = peek(goal)
|
|
138
|
-
-- Protect against NaN goals.
|
|
139
|
-
if newTweenTo ~= newTweenTo then
|
|
140
|
-
External.logWarn("tweenNanGoal")
|
|
141
|
-
return false
|
|
142
|
-
end
|
|
143
|
-
local stopwatch = self._stopwatch :: Stopwatch.Stopwatch
|
|
144
|
-
local tweenInfo = peek(self._tweenInfo) :: TweenInfo
|
|
145
|
-
-- Restart animation when the goal changes, or if the tween info changes
|
|
146
|
-
-- partway through another animation.
|
|
147
|
-
if
|
|
148
|
-
self._activeTo ~= newTweenTo or
|
|
149
|
-
(self._activeElapsed < self._activeDuration and self._activeTweenInfo ~= tweenInfo)
|
|
150
|
-
then
|
|
151
|
-
self._activeDuration = getTweenDuration(tweenInfo)
|
|
152
|
-
self._activeFrom = self._EXTREMELY_DANGEROUS_usedAsValue
|
|
153
|
-
self._activeTo = newTweenTo
|
|
154
|
-
self._activeTweenInfo = tweenInfo
|
|
155
|
-
stopwatch:zero()
|
|
156
|
-
stopwatch:unpause()
|
|
157
|
-
end
|
|
158
|
-
depend(self, stopwatch)
|
|
159
|
-
self._activeElapsed = peek(stopwatch)
|
|
160
|
-
if
|
|
161
|
-
self._activeFrom == self._activeTo or -- endpoints match
|
|
162
|
-
self._activeElapsed >= self._activeDuration or -- animation is done
|
|
163
|
-
typeof(self._activeTo) ~= typeof(self._activeFrom) -- type difference
|
|
164
|
-
then
|
|
165
|
-
self._activeFrom = self._activeTo
|
|
166
|
-
self._activeElapsed = self._activeDuration
|
|
167
|
-
stopwatch:pause()
|
|
168
|
-
end
|
|
169
|
-
-- Compute actual tweened value.
|
|
170
|
-
local ratio = getTweenRatio(tweenInfo, self._activeElapsed)
|
|
171
|
-
local oldValue = self._EXTREMELY_DANGEROUS_usedAsValue
|
|
172
|
-
local newValue = lerpType(self._activeFrom, self._activeTo, ratio) :: T
|
|
173
|
-
-- Protect against NaN after motion.
|
|
174
|
-
if newValue ~= newValue then
|
|
175
|
-
External.logWarn("tweenNanMotion")
|
|
176
|
-
newValue = self._activeTo
|
|
177
|
-
end
|
|
178
|
-
-- Push update and check for similarity.
|
|
179
|
-
-- Don't need to use the similarity test here because this code doesn't
|
|
180
|
-
-- deal with tables, and NaN is already guarded against, so the similarity
|
|
181
|
-
-- test doesn't actually add any new safety here.
|
|
182
|
-
self._EXTREMELY_DANGEROUS_usedAsValue = newValue
|
|
183
|
-
return oldValue ~= newValue
|
|
184
|
-
end
|
|
185
|
-
|
|
186
|
-
table.freeze(class)
|
|
187
|
-
return Tween :: Types.TweenConstructor
|
|
1
|
+
--!strict
|
|
2
|
+
--!nolint LocalUnused
|
|
3
|
+
--!nolint LocalShadow
|
|
4
|
+
local task = nil -- Disable usage of Roblox's task scheduler
|
|
5
|
+
|
|
6
|
+
--[[
|
|
7
|
+
A specialised state object for following a goal state smoothly over time,
|
|
8
|
+
using a TweenInfo to shape the motion.
|
|
9
|
+
|
|
10
|
+
https://elttob.uk/Fusion/0.3/api-reference/animation/types/tween/
|
|
11
|
+
]]
|
|
12
|
+
|
|
13
|
+
local Package = script.Parent.Parent
|
|
14
|
+
local Types = require(Package.Types)
|
|
15
|
+
local External = require(Package.External)
|
|
16
|
+
-- Memory
|
|
17
|
+
local checkLifetime = require(Package.Memory.checkLifetime)
|
|
18
|
+
-- Graph
|
|
19
|
+
local depend = require(Package.Graph.depend)
|
|
20
|
+
local evaluate = require(Package.Graph.evaluate)
|
|
21
|
+
-- State
|
|
22
|
+
local castToState = require(Package.State.castToState)
|
|
23
|
+
local peek = require(Package.State.peek)
|
|
24
|
+
-- Animation
|
|
25
|
+
local ExternalTime = require(Package.Animation.ExternalTime)
|
|
26
|
+
local Stopwatch = require(Package.Animation.Stopwatch)
|
|
27
|
+
local lerpType = require(Package.Animation.lerpType)
|
|
28
|
+
local getTweenRatio = require(Package.Animation.getTweenRatio)
|
|
29
|
+
local getTweenDuration = require(Package.Animation.getTweenDuration)
|
|
30
|
+
-- Utility
|
|
31
|
+
local nicknames = require(Package.Utility.nicknames)
|
|
32
|
+
|
|
33
|
+
export type Self<T> = Types.Tween<T> & {
|
|
34
|
+
_activeDuration: number,
|
|
35
|
+
_activeElapsed: number,
|
|
36
|
+
_activeFrom: T,
|
|
37
|
+
_activeTo: T,
|
|
38
|
+
_activeTweenInfo: TweenInfo,
|
|
39
|
+
_goal: Types.UsedAs<T>,
|
|
40
|
+
_stopwatch: Stopwatch.Stopwatch?,
|
|
41
|
+
_tweenInfo: Types.UsedAs<TweenInfo>,
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
local class = {}
|
|
45
|
+
class.type = "State"
|
|
46
|
+
class.kind = "Tween"
|
|
47
|
+
class.timeliness = "eager"
|
|
48
|
+
|
|
49
|
+
local METATABLE = table.freeze {__index = class}
|
|
50
|
+
|
|
51
|
+
local function Tween<T>(
|
|
52
|
+
scope: Types.Scope<unknown>,
|
|
53
|
+
goal: Types.UsedAs<T>,
|
|
54
|
+
tweenInfo: Types.UsedAs<TweenInfo>?
|
|
55
|
+
): Types.Tween<T>
|
|
56
|
+
local createdAt = os.clock()
|
|
57
|
+
if castToState(scope) then
|
|
58
|
+
External.logError("scopeMissing", nil, "Tweens", "myScope:Tween(goalState, tweenInfo)")
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
local goalState = castToState(goal)
|
|
62
|
+
local stopwatch = nil
|
|
63
|
+
if goalState ~= nil then
|
|
64
|
+
stopwatch = Stopwatch(scope, ExternalTime(scope))
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
local self: Self<T> = setmetatable(
|
|
68
|
+
{
|
|
69
|
+
createdAt = createdAt,
|
|
70
|
+
dependencySet = {},
|
|
71
|
+
dependentSet = {},
|
|
72
|
+
lastChange = nil,
|
|
73
|
+
scope = scope,
|
|
74
|
+
validity = "invalid",
|
|
75
|
+
_activeDuration = nil,
|
|
76
|
+
_activeElapsed = nil,
|
|
77
|
+
_activeFrom = nil,
|
|
78
|
+
_activeTo = nil,
|
|
79
|
+
_activeTweenInfo = nil,
|
|
80
|
+
_EXTREMELY_DANGEROUS_usedAsValue = peek(goal),
|
|
81
|
+
_goal = goal,
|
|
82
|
+
_stopwatch = stopwatch,
|
|
83
|
+
_tweenInfo = tweenInfo or TweenInfo.new()
|
|
84
|
+
},
|
|
85
|
+
METATABLE
|
|
86
|
+
) :: any
|
|
87
|
+
local destroy = function()
|
|
88
|
+
self.scope = nil
|
|
89
|
+
for dependency in pairs(self.dependencySet) do
|
|
90
|
+
dependency.dependentSet[self] = nil
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
self.oldestTask = destroy
|
|
94
|
+
nicknames[self.oldestTask] = "Tween"
|
|
95
|
+
table.insert(scope, destroy)
|
|
96
|
+
|
|
97
|
+
if goalState ~= nil then
|
|
98
|
+
checkLifetime.bOutlivesA(
|
|
99
|
+
scope, self.oldestTask,
|
|
100
|
+
goalState.scope, goalState.oldestTask,
|
|
101
|
+
checkLifetime.formatters.animationGoal
|
|
102
|
+
)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
local tweenInfoState = castToState(tweenInfo)
|
|
106
|
+
if tweenInfoState ~= nil then
|
|
107
|
+
checkLifetime.bOutlivesA(
|
|
108
|
+
scope, self.oldestTask,
|
|
109
|
+
tweenInfoState.scope, tweenInfoState.oldestTask,
|
|
110
|
+
checkLifetime.formatters.parameter, "tween info"
|
|
111
|
+
)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
-- Eagerly evaluated objects need to evaluate themselves so that they're
|
|
115
|
+
-- valid at all times.
|
|
116
|
+
evaluate(self, true)
|
|
117
|
+
|
|
118
|
+
return self
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
function class.get<T>(
|
|
122
|
+
self: Self<T>
|
|
123
|
+
): never
|
|
124
|
+
return External.logError("stateGetWasRemoved")
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
function class._evaluate<T>(
|
|
128
|
+
self: Self<T>
|
|
129
|
+
): boolean
|
|
130
|
+
local goal = castToState(self._goal)
|
|
131
|
+
-- Allow non-state goals to pass through transparently.
|
|
132
|
+
if goal == nil then
|
|
133
|
+
self._EXTREMELY_DANGEROUS_usedAsValue = self._goal :: T
|
|
134
|
+
return false
|
|
135
|
+
end
|
|
136
|
+
depend(self, goal)
|
|
137
|
+
local newTweenTo = peek(goal)
|
|
138
|
+
-- Protect against NaN goals.
|
|
139
|
+
if newTweenTo ~= newTweenTo then
|
|
140
|
+
External.logWarn("tweenNanGoal")
|
|
141
|
+
return false
|
|
142
|
+
end
|
|
143
|
+
local stopwatch = self._stopwatch :: Stopwatch.Stopwatch
|
|
144
|
+
local tweenInfo = peek(self._tweenInfo) :: TweenInfo
|
|
145
|
+
-- Restart animation when the goal changes, or if the tween info changes
|
|
146
|
+
-- partway through another animation.
|
|
147
|
+
if
|
|
148
|
+
self._activeTo ~= newTweenTo or
|
|
149
|
+
(self._activeElapsed < self._activeDuration and self._activeTweenInfo ~= tweenInfo)
|
|
150
|
+
then
|
|
151
|
+
self._activeDuration = getTweenDuration(tweenInfo)
|
|
152
|
+
self._activeFrom = self._EXTREMELY_DANGEROUS_usedAsValue
|
|
153
|
+
self._activeTo = newTweenTo
|
|
154
|
+
self._activeTweenInfo = tweenInfo
|
|
155
|
+
stopwatch:zero()
|
|
156
|
+
stopwatch:unpause()
|
|
157
|
+
end
|
|
158
|
+
depend(self, stopwatch)
|
|
159
|
+
self._activeElapsed = peek(stopwatch)
|
|
160
|
+
if
|
|
161
|
+
self._activeFrom == self._activeTo or -- endpoints match
|
|
162
|
+
self._activeElapsed >= self._activeDuration or -- animation is done
|
|
163
|
+
typeof(self._activeTo) ~= typeof(self._activeFrom) -- type difference
|
|
164
|
+
then
|
|
165
|
+
self._activeFrom = self._activeTo
|
|
166
|
+
self._activeElapsed = self._activeDuration
|
|
167
|
+
stopwatch:pause()
|
|
168
|
+
end
|
|
169
|
+
-- Compute actual tweened value.
|
|
170
|
+
local ratio = getTweenRatio(tweenInfo, self._activeElapsed)
|
|
171
|
+
local oldValue = self._EXTREMELY_DANGEROUS_usedAsValue
|
|
172
|
+
local newValue = lerpType(self._activeFrom, self._activeTo, ratio) :: T
|
|
173
|
+
-- Protect against NaN after motion.
|
|
174
|
+
if newValue ~= newValue then
|
|
175
|
+
External.logWarn("tweenNanMotion")
|
|
176
|
+
newValue = self._activeTo
|
|
177
|
+
end
|
|
178
|
+
-- Push update and check for similarity.
|
|
179
|
+
-- Don't need to use the similarity test here because this code doesn't
|
|
180
|
+
-- deal with tables, and NaN is already guarded against, so the similarity
|
|
181
|
+
-- test doesn't actually add any new safety here.
|
|
182
|
+
self._EXTREMELY_DANGEROUS_usedAsValue = newValue
|
|
183
|
+
return oldValue ~= newValue
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
table.freeze(class)
|
|
187
|
+
return Tween :: Types.TweenConstructor
|
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
--!strict
|
|
2
|
-
--!nolint LocalUnused
|
|
3
|
-
--!nolint LocalShadow
|
|
4
|
-
local task = nil -- Disable usage of Roblox's task scheduler
|
|
5
|
-
|
|
6
|
-
--[[
|
|
7
|
-
Given a `tweenInfo`, returns how many seconds it will take before the tween
|
|
8
|
-
finishes moving. The result may be infinite if the tween repeats forever.
|
|
9
|
-
]]
|
|
10
|
-
|
|
11
|
-
local TweenService = game:GetService("TweenService")
|
|
12
|
-
|
|
13
|
-
local function getTweenDuration(
|
|
14
|
-
tweenInfo: TweenInfo
|
|
15
|
-
): number
|
|
16
|
-
if tweenInfo.RepeatCount <= -1 then
|
|
17
|
-
return math.huge
|
|
18
|
-
end
|
|
19
|
-
local tweenDuration = tweenInfo.DelayTime + tweenInfo.Time
|
|
20
|
-
if tweenInfo.Reverses then
|
|
21
|
-
tweenDuration += tweenInfo.Time
|
|
22
|
-
end
|
|
23
|
-
tweenDuration *= tweenInfo.RepeatCount + 1
|
|
24
|
-
return tweenDuration
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
return getTweenDuration
|
|
1
|
+
--!strict
|
|
2
|
+
--!nolint LocalUnused
|
|
3
|
+
--!nolint LocalShadow
|
|
4
|
+
local task = nil -- Disable usage of Roblox's task scheduler
|
|
5
|
+
|
|
6
|
+
--[[
|
|
7
|
+
Given a `tweenInfo`, returns how many seconds it will take before the tween
|
|
8
|
+
finishes moving. The result may be infinite if the tween repeats forever.
|
|
9
|
+
]]
|
|
10
|
+
|
|
11
|
+
local TweenService = game:GetService("TweenService")
|
|
12
|
+
|
|
13
|
+
local function getTweenDuration(
|
|
14
|
+
tweenInfo: TweenInfo
|
|
15
|
+
): number
|
|
16
|
+
if tweenInfo.RepeatCount <= -1 then
|
|
17
|
+
return math.huge
|
|
18
|
+
end
|
|
19
|
+
local tweenDuration = tweenInfo.DelayTime + tweenInfo.Time
|
|
20
|
+
if tweenInfo.Reverses then
|
|
21
|
+
tweenDuration += tweenInfo.Time
|
|
22
|
+
end
|
|
23
|
+
tweenDuration *= tweenInfo.RepeatCount + 1
|
|
24
|
+
return tweenDuration
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
return getTweenDuration
|