2013/luau/10000001.luau

3418 lines
79 KiB
Plaintext

local __DARKLUA_BUNDLE_MODULES = {}
do
__DARKLUA_BUNDLE_MODULES.c = {
cannotAssignProperty = "The class type '%s' has no assignable property '%s'.",
cannotConnectChange = "The %s class doesn't have a property called '%s'.",
cannotConnectEvent = "The %s class doesn't have an event called '%s'.",
cannotCreateClass = "Can't create a new instance of class '%s'.",
computedCallbackError = "Computed callback error: ERROR_MESSAGE",
destructorNeededValue = [[To save instances into Values, provide a destructor function. This will be an error soon - see discussion #183 on GitHub.]],
destructorNeededComputed = [[To return instances from Computeds, provide a destructor function. This will be an error soon - see discussion #183 on GitHub.]],
multiReturnComputed = [[Returning multiple values from Computeds is discouraged, as behaviour will change soon - see discussion #189 on GitHub.]],
destructorNeededForKeys = [[To return instances from ForKeys, provide a destructor function. This will be an error soon - see discussion #183 on GitHub.]],
destructorNeededForValues = [[To return instances from ForValues, provide a destructor function. This will be an error soon - see discussion #183 on GitHub.]],
destructorNeededForPairs = [[To return instances from ForPairs, provide a destructor function. This will be an error soon - see discussion #183 on GitHub.]],
forKeysProcessorError = "ForKeys callback error: ERROR_MESSAGE",
forKeysKeyCollision = [[ForKeys should only write to output key '%s' once when processing key changes, but it wrote to it twice. Previously input key: '%s'; New input key: '%s']],
forKeysDestructorError = "ForKeys destructor error: ERROR_MESSAGE",
forPairsDestructorError = "ForPairs destructor error: ERROR_MESSAGE",
forPairsKeyCollision = [[ForPairs should only write to output key '%s' once when processing key changes, but it wrote to it twice. Previous input pair: '[%s] = %s'; New input pair: '[%s] = %s']],
forPairsProcessorError = "ForPairs callback error: ERROR_MESSAGE",
forValuesProcessorError = "ForValues callback error: ERROR_MESSAGE",
forValuesDestructorError = "ForValues destructor error: ERROR_MESSAGE",
invalidChangeHandler = [[The change handler for the '%s' property must be a function.]],
invalidEventHandler = "The handler for the '%s' event must be a function.",
invalidPropertyType = "'%s.%s' expected a '%s' type, but got a '%s' type.",
invalidRefType = "Instance refs must be Value objects.",
invalidOutType = "[Out] properties must be given Value objects.",
invalidOutProperty = "The %s class doesn't have a property called '%s'.",
invalidSpringDamping = [[The damping ratio for a spring must be >= 0. (damping was %.2f)]],
invalidSpringSpeed = "The speed of a spring must be >= 0. (speed was %.2f)",
mistypedSpringDamping = "The damping ratio for a spring must be a number. (got a %s)",
mistypedSpringSpeed = "The speed of a spring must be a number. (got a %s)",
mistypedTweenInfo = "The tween info of a tween must be a TweenInfo. (got a %s)",
noTaskScheduler = "Fusion is not connected to an external task scheduler.",
springTypeMismatch = "The type '%s' doesn't match the spring's type '%s'.",
stateGetWasRemoved = [[`StateObject:get()` has been replaced by `use()` and `peek()` - see discussion #217 on GitHub.]],
strictReadError = "'%s' is not a valid member of '%s'.",
unknownMessage = "Unknown error: ERROR_MESSAGE",
unrecognisedChildType = "'%s' type children aren't accepted by `[Children]`.",
unrecognisedPropertyKey = "'%s' keys aren't accepted in property tables.",
unrecognisedPropertyStage = [['%s' isn't a valid stage for a special key to be applied at.]],
invalidEasingStyle = [[The easing style must be a valid Enum.EasingStyle or a string of 'Linear', 'Quad', 'Cubic', 'Quart', 'Quint', 'Sine', 'Exponential', 'Circular', 'Elastic', 'Back', 'Bounce'. (got %s)]],
invalidEasingDirection = [[The easing direction must be a valid Enum.EasingDirection or a string of 'In', 'Out', 'InOut', 'OutIn'. (got %s)]],
}
end
do
local messages = __DARKLUA_BUNDLE_MODULES.c
local function logError(messageID, errObj, ...)
local formatString
if messages[messageID] ~= nil then
formatString = messages[messageID]
else
messageID = "unknownMessage"
formatString = messages[messageID]
end
local errorString
if errObj == nil then
errorString = string.format(
"[Fusion] " .. formatString .. "\n(ID: " .. messageID .. ")",
...
)
else
formatString =
formatString:gsub("ERROR_MESSAGE", tostring(errObj.message))
errorString = string.format(
"[Fusion] "
.. formatString
.. "\n(ID: "
.. messageID
.. ")\n---- Stack trace ----\n"
.. tostring(errObj.trace),
...
)
end
error(errorString:gsub("\n", "\n "), 0)
end
__DARKLUA_BUNDLE_MODULES.d = logError
end
do
local logError = __DARKLUA_BUNDLE_MODULES.d
local External = {}
local updateStepCallbacks = {}
local currentScheduler = nil
local lastUpdateStep = 0
function External.setExternalScheduler(newScheduler)
local oldScheduler = currentScheduler
if oldScheduler ~= nil then
oldScheduler.stopScheduler()
end
currentScheduler = newScheduler
if newScheduler ~= nil then
newScheduler.startScheduler()
end
return oldScheduler
end
function External.doTaskImmediate(resume)
if currentScheduler == nil then
logError "noTaskScheduler"
else
currentScheduler.doTaskImmediate(resume)
end
end
function External.doTaskDeferred(resume)
if currentScheduler == nil then
logError "noTaskScheduler"
else
currentScheduler.doTaskDeferred(resume)
end
end
function External.bindToUpdateStep(callback)
local uniqueIdentifier = {}
updateStepCallbacks[uniqueIdentifier] = callback
return function()
updateStepCallbacks[uniqueIdentifier] = nil
end
end
function External.performUpdateStep(now)
lastUpdateStep = now
for _, callback in pairs(updateStepCallbacks) do
callback(now)
end
end
function External.lastUpdateStep()
return lastUpdateStep
end
__DARKLUA_BUNDLE_MODULES.e = External
end
do
local logError = __DARKLUA_BUNDLE_MODULES.d
local function restrictRead(tableName, strictTable)
local metatable = getmetatable(strictTable)
if metatable == nil then
metatable = {}
setmetatable(strictTable, metatable)
end
function metatable:__index(memberName)
logError("strictReadError", nil, tostring(memberName), tableName)
end
return strictTable
end
__DARKLUA_BUNDLE_MODULES.f = restrictRead
end
do
local RunService = game:GetService "RunService"
local External = __DARKLUA_BUNDLE_MODULES.e
local MercuryExternal = {}
function MercuryExternal.doTaskImmediate(resume)
Spawn(resume)
end
function MercuryExternal.doTaskDeferred(resume)
coroutine.resume(coroutine.create(resume))
end
local function performUpdateStep()
External.performUpdateStep(tick())
end
local stopSchedulerFunc = nil
function MercuryExternal.startScheduler()
if stopSchedulerFunc ~= nil then
return
end
local conn = RunService.RenderStepped:connect(performUpdateStep)
stopSchedulerFunc = function()
conn:disconnect()
end
end
function MercuryExternal.stopScheduler()
if stopSchedulerFunc ~= nil then
stopSchedulerFunc()
stopSchedulerFunc = nil
end
end
__DARKLUA_BUNDLE_MODULES.g = MercuryExternal
end
do
__DARKLUA_BUNDLE_MODULES.h = {
BillboardGui = { Active = true },
Frame = {
BackgroundColor3 = Color3.new(1, 1, 1),
BorderColor3 = Color3.new(0, 0, 0),
BorderSizePixel = 0,
},
TextLabel = {
BackgroundColor3 = Color3.new(1, 1, 1),
BorderColor3 = Color3.new(0, 0, 0),
BorderSizePixel = 0,
Font = Enum.Font.SourceSans,
Text = "",
TextColor3 = Color3.new(0, 0, 0),
FontSize = Enum.FontSize.Size14,
},
TextButton = {
BackgroundColor3 = Color3.new(1, 1, 1),
BorderColor3 = Color3.new(0, 0, 0),
BorderSizePixel = 0,
AutoButtonColor = false,
Font = Enum.Font.SourceSans,
Text = "",
TextColor3 = Color3.new(0, 0, 0),
FontSize = Enum.FontSize.Size14,
},
TextBox = {
BackgroundColor3 = Color3.new(1, 1, 1),
BorderColor3 = Color3.new(0, 0, 0),
BorderSizePixel = 0,
ClearTextOnFocus = false,
Font = Enum.Font.SourceSans,
Text = "",
TextColor3 = Color3.new(0, 0, 0),
FontSize = Enum.FontSize.Size14,
},
ImageLabel = {
BackgroundColor3 = Color3.new(1, 1, 1),
BorderColor3 = Color3.new(0, 0, 0),
BorderSizePixel = 0,
},
ImageButton = {
BackgroundColor3 = Color3.new(1, 1, 1),
BorderColor3 = Color3.new(0, 0, 0),
BorderSizePixel = 0,
AutoButtonColor = false,
},
SpawnLocation = { Duration = 0 },
Part = {
Anchored = true,
Size = Vector3.new(1, 1, 1),
FrontSurface = Enum.SurfaceType.Smooth,
BackSurface = Enum.SurfaceType.Smooth,
LeftSurface = Enum.SurfaceType.Smooth,
RightSurface = Enum.SurfaceType.Smooth,
TopSurface = Enum.SurfaceType.Smooth,
BottomSurface = Enum.SurfaceType.Smooth,
},
TrussPart = {
Anchored = true,
Size = Vector3.new(2, 2, 2),
FrontSurface = Enum.SurfaceType.Smooth,
BackSurface = Enum.SurfaceType.Smooth,
LeftSurface = Enum.SurfaceType.Smooth,
RightSurface = Enum.SurfaceType.Smooth,
TopSurface = Enum.SurfaceType.Smooth,
BottomSurface = Enum.SurfaceType.Smooth,
},
CornerWedgePart = {
Anchored = true,
Size = Vector3.new(1, 1, 1),
FrontSurface = Enum.SurfaceType.Smooth,
BackSurface = Enum.SurfaceType.Smooth,
LeftSurface = Enum.SurfaceType.Smooth,
RightSurface = Enum.SurfaceType.Smooth,
TopSurface = Enum.SurfaceType.Smooth,
BottomSurface = Enum.SurfaceType.Smooth,
},
VehicleSeat = {
Anchored = true,
Size = Vector3.new(1, 1, 1),
FrontSurface = Enum.SurfaceType.Smooth,
BackSurface = Enum.SurfaceType.Smooth,
LeftSurface = Enum.SurfaceType.Smooth,
RightSurface = Enum.SurfaceType.Smooth,
TopSurface = Enum.SurfaceType.Smooth,
BottomSurface = Enum.SurfaceType.Smooth,
},
}
end
do
__DARKLUA_BUNDLE_MODULES.i = function(value)
local basicType = type(value)
if
basicType == "nil"
or basicType == "boolean"
or basicType == "number"
or basicType == "string"
or basicType == "function"
or basicType == "thread"
or basicType == "table"
then
return basicType
end
local tests = {
{
"Instance",
{
"ClassName",
},
},
{
"EnumItem",
{
"EnumType",
"Name",
"Value",
},
},
{
"Enum",
{
"GetEnumItems",
},
},
{
"Enums",
{
"MembershipType",
},
},
{
"RBXScriptSignal",
{
"connect",
"wait",
},
},
{
"RBXScriptConnection",
{
"connected",
"disconnect",
},
},
{
"TweenInfo",
{
"EasingDirection",
"RepeatCount",
"EasingStyle",
},
},
{
"CFrame",
{
"p",
"x",
"y",
"z",
"lookVector",
},
},
{
"Vector3",
{
"Lerp",
"unit",
"magnitude",
"x",
"y",
"z",
},
},
{
"Vector3int16",
{
"z",
"x",
"y",
},
},
{
"Vector2",
{
"unit",
"magnitude",
"x",
"y",
},
},
{
"Vector2int16",
{
"x",
"y",
},
},
{
"Region3",
{
"CFrame",
"Size",
},
},
{
"Region3int16",
{
"Min",
"Max",
},
},
{
"Ray",
{
"Origin",
"Direction",
"Unit",
"ClosestPoint",
"Distance",
},
},
{
"UDim",
{
"Scale",
"Offset",
},
},
{
"Axes",
{
"Z",
"X",
"Y",
},
},
{
"UDim2",
{
"X",
"Y",
},
},
{
"BrickColor",
{
"Number",
"Name",
"Color",
"r",
"g",
"b",
},
},
{
"Color3",
{
"r",
"g",
"b",
},
},
{
"Faces",
{
"Right",
"Top",
"Back",
},
},
}
for _, v in ipairs(tests) do
local t, test = v[1], v[2]
local ok, result = pcall(function()
for _, prop in ipairs(test) do
if value[prop] == nil then
return false
end
end
return true
end)
if ok and result then
return t
end
end
end
end
do
local typeof = __DARKLUA_BUNDLE_MODULES.i
local function cleanupOne(task)
local taskType = typeof(task)
if taskType == "Instance" then
task:Destroy()
elseif taskType == "RBXScriptConnection" then
task:disconnect()
elseif taskType == "function" then
task()
elseif taskType == "table" then
if type(task.destroy) == "function" then
task:destroy()
elseif type(task.Destroy) == "function" then
task:Destroy()
elseif task[1] ~= nil then
for _, subtask in ipairs(task) do
cleanupOne(subtask)
end
end
end
end
local function cleanup(...)
for index = 1, select("#", ...) do
cleanupOne(select(index, ...))
end
end
__DARKLUA_BUNDLE_MODULES.j = cleanup
end
do
local typeof = __DARKLUA_BUNDLE_MODULES.i
local function xtypeof(x)
local typeString = typeof(x)
if typeString == "table" and type(x.type) == "string" then
return x.type
else
return typeString
end
end
__DARKLUA_BUNDLE_MODULES.k = xtypeof
end
do
local External = __DARKLUA_BUNDLE_MODULES.e
local class = {}
local CLASS_METATABLE = { __index = class }
local strongRefs = {}
function class:update()
for _, callback in pairs(self._changeListeners) do
External.doTaskImmediate(callback)
end
return false
end
function class:onChange(callback)
local uniqueIdentifier = {}
self._numChangeListeners = self._numChangeListeners + 1
self._changeListeners[uniqueIdentifier] = callback
strongRefs[self] = true
local disconnected = false
return function()
if disconnected then
return
end
disconnected = true
self._changeListeners[uniqueIdentifier] = nil
self._numChangeListeners = self._numChangeListeners - 1
if self._numChangeListeners == 0 then
strongRefs[self] = nil
end
end
end
function class:onBind(callback)
External.doTaskImmediate(callback)
return self:onChange(callback)
end
local function Observer(watchedState)
local self = setmetatable({
type = "State",
kind = "Observer",
dependencySet = { [watchedState] = true },
dependentSet = {},
_changeListeners = {},
_numChangeListeners = 0,
}, CLASS_METATABLE)
watchedState.dependentSet[self] = true
return self
end
__DARKLUA_BUNDLE_MODULES.l = Observer
end
do
local function isState(target)
return type(target) == "table" and type(target._peek) == "function"
end
__DARKLUA_BUNDLE_MODULES.m = isState
end
do
local isState = __DARKLUA_BUNDLE_MODULES.m
local function peek(target)
if isState(target) then
return (target):_peek()
end
return target
end
__DARKLUA_BUNDLE_MODULES.n = peek
end
do
local External = __DARKLUA_BUNDLE_MODULES.e
local cleanup = __DARKLUA_BUNDLE_MODULES.j
local xtypeof = __DARKLUA_BUNDLE_MODULES.k
local logError = __DARKLUA_BUNDLE_MODULES.d
local Observer = __DARKLUA_BUNDLE_MODULES.l
local peek = __DARKLUA_BUNDLE_MODULES.n
local typeof = __DARKLUA_BUNDLE_MODULES.i
local function setProperty_unsafe(instance, property, value)
(instance)[property] = value
end
local function testPropertyAssignable(instance, property)
(instance)[property] = (instance)[property]
end
local function setProperty(instance, property, value)
if not pcall(setProperty_unsafe, instance, property, value) then
if not pcall(testPropertyAssignable, instance, property) then
if instance == nil then
logError(
"setPropertyNilRef",
nil,
property,
tostring(value)
)
else
logError(
"cannotAssignProperty",
nil,
instance.ClassName,
property
)
end
else
local givenType = typeof(value)
local expectedType = typeof((instance)[property])
logError(
"invalidPropertyType",
nil,
instance.ClassName,
property,
expectedType,
givenType
)
end
end
end
local function bindProperty(instance, property, value, cleanupTasks)
if xtypeof(value) == "State" then
local willUpdate = false
local function updateLater()
if not willUpdate then
willUpdate = true
External.doTaskDeferred(function()
willUpdate = false
setProperty(instance, property, peek(value))
end)
end
end
setProperty(instance, property, peek(value))
table.insert(cleanupTasks, Observer(value):onChange(updateLater))
else
setProperty(instance, property, value)
end
end
local function applyInstanceProps(props, applyTo)
local specialKeys = {
self = {},
descendants = {},
ancestor = {},
observer = {},
}
local cleanupTasks = {}
for key, value in pairs(props) do
local keyType = xtypeof(key)
if keyType == "string" then
if key ~= "Parent" then
bindProperty(applyTo, key, value, cleanupTasks)
end
elseif keyType == "SpecialKey" then
local stage = (key).stage
local keys = specialKeys[stage]
if keys == nil then
logError("unrecognisedPropertyStage", nil, stage)
else
keys[key] = value
end
else
logError("unrecognisedPropertyKey", nil, xtypeof(key))
end
end
for key, value in pairs(specialKeys.self) do
key:apply(value, applyTo, cleanupTasks)
end
for key, value in pairs(specialKeys.descendants) do
key:apply(value, applyTo, cleanupTasks)
end
if props.Parent ~= nil then
bindProperty(applyTo, "Parent", props.Parent, cleanupTasks)
end
for key, value in pairs(specialKeys.ancestor) do
key:apply(value, applyTo, cleanupTasks)
end
for key, value in pairs(specialKeys.observer) do
key:apply(value, applyTo, cleanupTasks)
end
if applyTo.Parent then
game.DescendantRemoving:connect(function(descendant)
if descendant == applyTo then
cleanup(cleanupTasks)
end
end)
end
end
__DARKLUA_BUNDLE_MODULES.o = applyInstanceProps
end
do
local defaultProps = __DARKLUA_BUNDLE_MODULES.h
local applyInstanceProps = __DARKLUA_BUNDLE_MODULES.o
local logError = __DARKLUA_BUNDLE_MODULES.d
local function New(className)
return function(props)
local ok, instance = pcall(Instance.new, className)
if not ok then
logError("cannotCreateClass", nil, className)
end
local classDefaults = defaultProps[className]
if classDefaults ~= nil then
for defaultProp, defaultValue in pairs(classDefaults) do
instance[defaultProp] = defaultValue
end
end
applyInstanceProps(props, instance)
return instance
end
end
__DARKLUA_BUNDLE_MODULES.p = New
end
do
local applyInstanceProps = __DARKLUA_BUNDLE_MODULES.o
local function Hydrate(target)
return function(props)
applyInstanceProps(props, target)
return target
end
end
__DARKLUA_BUNDLE_MODULES.q = Hydrate
end
do
local logError = __DARKLUA_BUNDLE_MODULES.d
local xtypeof = __DARKLUA_BUNDLE_MODULES.k
local Ref = {}
Ref.type = "SpecialKey"
Ref.kind = "Ref"
Ref.stage = "observer"
function Ref:apply(refState, applyTo, cleanupTasks)
if xtypeof(refState) ~= "State" or refState.kind ~= "Value" then
logError "invalidRefType"
else
refState:set(applyTo)
table.insert(cleanupTasks, function()
refState:set(nil)
end)
end
end
__DARKLUA_BUNDLE_MODULES.r = Ref
end
do
local logError = __DARKLUA_BUNDLE_MODULES.d
local xtypeof = __DARKLUA_BUNDLE_MODULES.k
local function Out(propertyName)
local outKey = {}
outKey.type = "SpecialKey"
outKey.kind = "Out"
outKey.stage = "observer"
function outKey:apply(outState, applyTo, cleanupTasks)
local ok, event = pcall(function()
return applyTo.Changed
end)
if not ok then
logError(
"invalidOutProperty",
nil,
applyTo.ClassName,
propertyName
)
elseif xtypeof(outState) ~= "State" or outState.kind ~= "Value" then
logError "invalidOutType"
else
outState:set((applyTo)[propertyName])
table.insert(
cleanupTasks,
event:connect(function(prop)
if prop == propertyName then
outState:set((applyTo)[propertyName])
end
end)
)
table.insert(cleanupTasks, function()
outState:set(nil)
end)
end
end
return outKey
end
__DARKLUA_BUNDLE_MODULES.s = Out
end
do
local Cleanup = {}
Cleanup.type = "SpecialKey"
Cleanup.kind = "Cleanup"
Cleanup.stage = "observer"
function Cleanup:apply(userTask, _, cleanupTasks)
table.insert(cleanupTasks, userTask)
end
__DARKLUA_BUNDLE_MODULES.t = Cleanup
end
do
local messages = __DARKLUA_BUNDLE_MODULES.c
local function logWarn(messageID, ...)
local formatString
if messages[messageID] ~= nil then
formatString = messages[messageID]
else
messageID = "unknownMessage"
formatString = messages[messageID]
end
warn(
string.format(
"[Fusion] " .. formatString .. "\n(ID: " .. messageID .. ")",
...
)
)
end
__DARKLUA_BUNDLE_MODULES.u = logWarn
end
do
local External = __DARKLUA_BUNDLE_MODULES.e
local logWarn = __DARKLUA_BUNDLE_MODULES.u
local Observer = __DARKLUA_BUNDLE_MODULES.l
local peek = __DARKLUA_BUNDLE_MODULES.n
local isState = __DARKLUA_BUNDLE_MODULES.m
local typeof = __DARKLUA_BUNDLE_MODULES.i
local EXPERIMENTAL_AUTO_NAMING = false
local Children = {}
Children.type = "SpecialKey"
Children.kind = "Children"
Children.stage = "descendants"
function Children:apply(propValue, applyTo, cleanupTasks)
local newParented = {}
local oldParented = {}
local newDisconnects = {}
local oldDisconnects = {}
local updateQueued = false
local queueUpdate
local function updateChildren()
if not updateQueued then
return
end
updateQueued = false
oldParented, newParented = newParented, oldParented
oldDisconnects, newDisconnects = newDisconnects, oldDisconnects
for i, _ in pairs(newParented) do
newParented[i] = nil
end
for i, _ in pairs(newDisconnects) do
newDisconnects[i] = nil
end
local function processChild(child, autoName)
local childType = typeof(child)
if childType == "Instance" then
newParented[child] = true
if oldParented[child] == nil then
child.Parent = applyTo
else
oldParented[child] = nil
end
if EXPERIMENTAL_AUTO_NAMING and autoName ~= nil then
child.Name = autoName
end
elseif isState(child) then
local value = peek(child)
if value ~= nil then
processChild(value, autoName)
end
local disconnect = oldDisconnects[child]
if disconnect == nil then
disconnect = Observer(child):onChange(queueUpdate)
else
oldDisconnects[child] = nil
end
newDisconnects[child] = disconnect
elseif childType == "table" then
for key, subChild in pairs(child) do
local keyType = typeof(key)
local subAutoName = nil
if keyType == "string" then
subAutoName = key
elseif keyType == "number" and autoName ~= nil then
subAutoName = autoName .. "_" .. key
end
processChild(subChild, subAutoName)
end
else
logWarn("unrecognisedChildType", childType)
end
end
if propValue ~= nil then
processChild(propValue)
end
for oldInstance in pairs(oldParented) do
oldInstance.Parent = nil
end
for _, disconnect in pairs(oldDisconnects) do
disconnect()
end
end
queueUpdate = function()
if not updateQueued then
updateQueued = true
External.doTaskDeferred(updateChildren)
end
end
table.insert(cleanupTasks, function()
propValue = nil
updateQueued = true
updateChildren()
end)
updateQueued = true
updateChildren()
end
__DARKLUA_BUNDLE_MODULES.v = Children
end
do
local logError = __DARKLUA_BUNDLE_MODULES.d
local typeof = __DARKLUA_BUNDLE_MODULES.i
local function getProperty_unsafe(instance, property)
return (instance)[property]
end
local function OnEvent(eventName)
local eventKey = {}
eventKey.type = "SpecialKey"
eventKey.kind = "OnEvent"
eventKey.stage = "observer"
function eventKey:apply(callback, applyTo, cleanupTasks)
local ok, event = pcall(getProperty_unsafe, applyTo, eventName)
if not ok or typeof(event) ~= "RBXScriptSignal" then
logError(
"cannotConnectEvent",
nil,
applyTo.ClassName,
eventName
)
elseif typeof(callback) ~= "function" then
logError("invalidEventHandler", nil, eventName)
else
table.insert(cleanupTasks, event:connect(callback))
end
end
return eventKey
end
__DARKLUA_BUNDLE_MODULES.w = OnEvent
end
do
local logError = __DARKLUA_BUNDLE_MODULES.d
local typeof = __DARKLUA_BUNDLE_MODULES.i
local function OnChange(propertyName)
local changeKey = {}
changeKey.type = "SpecialKey"
changeKey.kind = "OnChange"
changeKey.stage = "observer"
function changeKey:apply(callback, applyTo, cleanupTasks)
local ok, event = pcall(function()
return applyTo.Changed
end)
if not ok then
logError(
"cannotConnectChange",
nil,
applyTo.ClassName,
propertyName
)
elseif typeof(callback) ~= "function" then
logError("invalidChangeHandler", nil, propertyName)
else
table.insert(
cleanupTasks,
event:connect(function(prop)
if prop == propertyName then
callback((applyTo)[propertyName])
end
end)
)
end
end
return changeKey
end
__DARKLUA_BUNDLE_MODULES.x = OnChange
end
do
local function updateAll(root)
local counters = {}
local flags = {}
local queue = {}
local queueSize = 0
local queuePos = 1
for object in pairs(root.dependentSet) do
queueSize = queueSize + 1
queue[queueSize] = object
flags[object] = true
end
while queuePos <= queueSize do
local next = queue[queuePos]
local counter = counters[next]
counters[next] = (function()
if counter == nil then
return 1
else
return counter + 1
end
end)()
if next.dependentSet ~= nil then
for object in pairs(next.dependentSet) do
queueSize = queueSize + 1
queue[queueSize] = object
end
end
queuePos = queuePos + 1
end
queuePos = 1
while queuePos <= queueSize do
local next = queue[queuePos]
local counter = counters[next] - 1
counters[next] = counter
if
counter == 0
and flags[next]
and next:update()
and next.dependentSet ~= nil
then
for object in pairs(next.dependentSet) do
flags[object] = true
end
end
queuePos = queuePos + 1
end
end
__DARKLUA_BUNDLE_MODULES.y = updateAll
end
do
local function isSimilar(a, b)
if type(a) == "table" then
return false
end
return a == b
end
__DARKLUA_BUNDLE_MODULES.z = isSimilar
end
do
local logError = __DARKLUA_BUNDLE_MODULES.d
local updateAll = __DARKLUA_BUNDLE_MODULES.y
local isSimilar = __DARKLUA_BUNDLE_MODULES.z
local class = {}
local CLASS_METATABLE = { __index = class }
local WEAK_KEYS_METATABLE = {
__mode = "k",
}
function class:set(newValue, force)
local oldValue = self._value
if force or not isSimilar(oldValue, newValue) then
self._value = newValue
updateAll(self)
end
end
function class:_peek()
return self._value
end
function class:get()
logError "stateGetWasRemoved"
end
local function Value(initialValue)
local self = setmetatable({
type = "State",
kind = "Value",
dependentSet = setmetatable({}, WEAK_KEYS_METATABLE),
_value = initialValue,
}, CLASS_METATABLE)
return self
end
__DARKLUA_BUNDLE_MODULES.A = Value
end
do
local messages = __DARKLUA_BUNDLE_MODULES.c
local function logErrorNonFatal(messageID, errObj, ...)
local formatString
if messages[messageID] ~= nil then
formatString = messages[messageID]
else
messageID = "unknownMessage"
formatString = messages[messageID]
end
local errorString
if errObj == nil then
errorString = string.format(
"[Fusion] " .. formatString .. "\n(ID: " .. messageID .. ")",
...
)
else
formatString =
formatString:gsub("ERROR_MESSAGE", tostring(errObj.message))
errorString = string.format(
"[Fusion] "
.. formatString
.. "\n(ID: "
.. messageID
.. ")\n---- Stack trace ----\n"
.. tostring(errObj.trace),
...
)
end
coroutine.wrap(function()
error(errorString:gsub("\n", "\n "), 0)
end)()
end
__DARKLUA_BUNDLE_MODULES.B = logErrorNonFatal
end
do
local function parseError(err)
local trace = "Traceback not available"
if debug and debug.traceback then
trace = debug.traceback(nil, 2)
end
return {
type = "Error",
raw = err,
message = err:gsub("^.+:%d+:%s*", ""),
trace = trace,
}
end
__DARKLUA_BUNDLE_MODULES.C = parseError
end
do
local typeof = __DARKLUA_BUNDLE_MODULES.i
local function needsDestruction(x)
return typeof(x) == "Instance"
end
__DARKLUA_BUNDLE_MODULES.D = needsDestruction
end
do
local isState = __DARKLUA_BUNDLE_MODULES.m
local function makeUseCallback(dependencySet)
local function use(target)
if isState(target) then
dependencySet[target] = true
return (target):_peek()
end
return target
end
return use
end
__DARKLUA_BUNDLE_MODULES.E = makeUseCallback
end
do
local logError = __DARKLUA_BUNDLE_MODULES.d
local logErrorNonFatal = __DARKLUA_BUNDLE_MODULES.B
local logWarn = __DARKLUA_BUNDLE_MODULES.u
local parseError = __DARKLUA_BUNDLE_MODULES.C
local isSimilar = __DARKLUA_BUNDLE_MODULES.z
local needsDestruction = __DARKLUA_BUNDLE_MODULES.D
local makeUseCallback = __DARKLUA_BUNDLE_MODULES.E
local class = {}
local CLASS_METATABLE = { __index = class }
local WEAK_KEYS_METATABLE = {
__mode = "k",
}
function class:update()
for dependency in pairs(self.dependencySet) do
dependency.dependentSet[self] = nil
end
self._oldDependencySet, self.dependencySet =
self.dependencySet, self._oldDependencySet
for i, _ in pairs(self.dependencySet) do
self.dependencySet[i] = nil
end
local use = makeUseCallback(self.dependencySet)
local ok, newValue, newMetaValue = pcall(self._processor, use)
if ok then
if self._destructor == nil and needsDestruction(newValue) then
logWarn "destructorNeededComputed"
end
if newMetaValue ~= nil then
logWarn "multiReturnComputed"
end
local oldValue = self._value
local similar = isSimilar(oldValue, newValue)
if self._destructor ~= nil then
self._destructor(oldValue)
end
self._value = newValue
for dependency in pairs(self.dependencySet) do
dependency.dependentSet[self] = true
end
return not similar
else
logErrorNonFatal("computedCallbackError", parseError(newValue))
self._oldDependencySet, self.dependencySet =
self.dependencySet, self._oldDependencySet
for dependency in pairs(self.dependencySet) do
dependency.dependentSet[self] = true
end
return false
end
end
function class:_peek()
return self._value
end
function class:get()
logError "stateGetWasRemoved"
end
local function Computed(processor, destructor)
local dependencySet = {}
local self = setmetatable({
type = "State",
kind = "Computed",
dependencySet = dependencySet,
dependentSet = setmetatable({}, WEAK_KEYS_METATABLE),
_oldDependencySet = {},
_processor = processor,
_destructor = destructor,
_value = nil,
}, CLASS_METATABLE)
self:update()
return self
end
__DARKLUA_BUNDLE_MODULES.F = Computed
end
do
local parseError = __DARKLUA_BUNDLE_MODULES.C
local logErrorNonFatal = __DARKLUA_BUNDLE_MODULES.B
local logError = __DARKLUA_BUNDLE_MODULES.d
local logWarn = __DARKLUA_BUNDLE_MODULES.u
local cleanup = __DARKLUA_BUNDLE_MODULES.j
local needsDestruction = __DARKLUA_BUNDLE_MODULES.D
local peek = __DARKLUA_BUNDLE_MODULES.n
local makeUseCallback = __DARKLUA_BUNDLE_MODULES.E
local isState = __DARKLUA_BUNDLE_MODULES.m
local class = {}
local CLASS_METATABLE = { __index = class }
local WEAK_KEYS_METATABLE = {
__mode = "k",
}
function class:update()
local inputIsState = self._inputIsState
local newInputTable = peek(self._inputTable)
local oldInputTable = self._oldInputTable
local keyIOMap = self._keyIOMap
local meta = self._meta
local didChange = false
for dependency in pairs(self.dependencySet) do
dependency.dependentSet[self] = nil
end
self._oldDependencySet, self.dependencySet =
self.dependencySet, self._oldDependencySet
for i, _ in pairs(self.dependencySet) do
self.dependencySet[i] = nil
end
if inputIsState then
self._inputTable.dependentSet[self] = true
self.dependencySet[self._inputTable] = true
end
self._oldOutputTable, self._outputTable =
self._outputTable, self._oldOutputTable
local oldOutputTable = self._oldOutputTable
local newOutputTable = self._outputTable
for i, _ in pairs(newOutputTable) do
newOutputTable[i] = nil
end
for newInKey, newInValue in pairs(newInputTable) do
local keyData = self._keyData[newInKey]
if keyData == nil then
keyData = {
dependencySet = setmetatable({}, WEAK_KEYS_METATABLE),
oldDependencySet = setmetatable({}, WEAK_KEYS_METATABLE),
dependencyValues = setmetatable({}, WEAK_KEYS_METATABLE),
}
self._keyData[newInKey] = keyData
end
local shouldRecalculate = oldInputTable[newInKey] ~= newInValue
if shouldRecalculate == false then
for dependency, oldValue in pairs(keyData.dependencyValues) do
if oldValue ~= peek(dependency) then
shouldRecalculate = true
break
end
end
end
if shouldRecalculate then
keyData.oldDependencySet, keyData.dependencySet =
keyData.dependencySet, keyData.oldDependencySet
for i, _ in pairs(keyData.dependencySet) do
keyData.dependencySet[i] = nil
end
local use = makeUseCallback(keyData.dependencySet)
local processOK, newOutKey, newOutValue, newMetaValue =
pcall(self._processor, use, newInKey, newInValue)
if processOK then
if
self._destructor == nil
and (
needsDestruction(newOutKey)
or needsDestruction(newOutValue)
or needsDestruction(newMetaValue)
)
then
logWarn "destructorNeededForPairs"
end
if newOutputTable[newOutKey] ~= nil then
local previousNewKey, previousNewValue
for inKey, outKey in pairs(keyIOMap) do
if outKey == newOutKey then
previousNewValue = newInputTable[inKey]
if previousNewValue ~= nil then
previousNewKey = inKey
break
end
end
end
if previousNewKey ~= nil then
logError(
"forPairsKeyCollision",
nil,
tostring(newOutKey),
tostring(previousNewKey),
tostring(previousNewValue),
tostring(newInKey),
tostring(newInValue)
)
end
end
local oldOutValue = oldOutputTable[newOutKey]
if oldOutValue ~= newOutValue then
local oldMetaValue = meta[newOutKey]
if oldOutValue ~= nil then
local destructOK, err = pcall(
self._destructor or cleanup,
newOutKey,
oldOutValue,
oldMetaValue
)
if not destructOK then
logErrorNonFatal(
"forPairsDestructorError",
parseError(err)
)
end
end
oldOutputTable[newOutKey] = nil
end
oldInputTable[newInKey] = newInValue
keyIOMap[newInKey] = newOutKey
meta[newOutKey] = newMetaValue
newOutputTable[newOutKey] = newOutValue
didChange = true
else
keyData.oldDependencySet, keyData.dependencySet =
keyData.dependencySet, keyData.oldDependencySet
logErrorNonFatal(
"forPairsProcessorError",
parseError(newOutKey)
)
end
else
local storedOutKey = keyIOMap[newInKey]
if newOutputTable[storedOutKey] ~= nil then
local previousNewKey, previousNewValue
for inKey, outKey in pairs(keyIOMap) do
if storedOutKey == outKey then
previousNewValue = newInputTable[inKey]
if previousNewValue ~= nil then
previousNewKey = inKey
break
end
end
end
if previousNewKey ~= nil then
logError(
"forPairsKeyCollision",
nil,
tostring(storedOutKey),
tostring(previousNewKey),
tostring(previousNewValue),
tostring(newInKey),
tostring(newInValue)
)
end
end
newOutputTable[storedOutKey] = oldOutputTable[storedOutKey]
end
for dependency in pairs(keyData.dependencySet) do
keyData.dependencyValues[dependency] = peek(dependency)
self.dependencySet[dependency] = true
dependency.dependentSet[self] = true
end
end
for oldOutKey, oldOutValue in pairs(oldOutputTable) do
if newOutputTable[oldOutKey] ~= oldOutValue then
local oldMetaValue = meta[oldOutKey]
if oldOutValue ~= nil then
local destructOK, err = pcall(
self._destructor or cleanup,
oldOutKey,
oldOutValue,
oldMetaValue
)
if not destructOK then
logErrorNonFatal(
"forPairsDestructorError",
parseError(err)
)
end
end
if newOutputTable[oldOutKey] == nil then
meta[oldOutKey] = nil
self._keyData[oldOutKey] = nil
end
didChange = true
end
end
for key in pairs(oldInputTable) do
if newInputTable[key] == nil then
oldInputTable[key] = nil
keyIOMap[key] = nil
end
end
return didChange
end
function class:_peek()
return self._outputTable
end
function class:get()
logError "stateGetWasRemoved"
end
local function ForPairs(inputTable, processor, destructor)
local inputIsState = isState(inputTable)
local self = setmetatable({
type = "State",
kind = "ForPairs",
dependencySet = {},
dependentSet = setmetatable({}, WEAK_KEYS_METATABLE),
_oldDependencySet = {},
_processor = processor,
_destructor = destructor,
_inputIsState = inputIsState,
_inputTable = inputTable,
_oldInputTable = {},
_outputTable = {},
_oldOutputTable = {},
_keyIOMap = {},
_keyData = {},
_meta = {},
}, CLASS_METATABLE)
self:update()
return self
end
__DARKLUA_BUNDLE_MODULES.G = ForPairs
end
do
local parseError = __DARKLUA_BUNDLE_MODULES.C
local logErrorNonFatal = __DARKLUA_BUNDLE_MODULES.B
local logError = __DARKLUA_BUNDLE_MODULES.d
local logWarn = __DARKLUA_BUNDLE_MODULES.u
local cleanup = __DARKLUA_BUNDLE_MODULES.j
local needsDestruction = __DARKLUA_BUNDLE_MODULES.D
local peek = __DARKLUA_BUNDLE_MODULES.n
local makeUseCallback = __DARKLUA_BUNDLE_MODULES.E
local isState = __DARKLUA_BUNDLE_MODULES.m
local class = {}
local CLASS_METATABLE = { __index = class }
local WEAK_KEYS_METATABLE = {
__mode = "k",
}
function class:update()
local inputIsState = self._inputIsState
local newInputTable = peek(self._inputTable)
local oldInputTable = self._oldInputTable
local outputTable = self._outputTable
local keyOIMap = self._keyOIMap
local keyIOMap = self._keyIOMap
local meta = self._meta
local didChange = false
for dependency in pairs(self.dependencySet) do
dependency.dependentSet[self] = nil
end
self._oldDependencySet, self.dependencySet =
self.dependencySet, self._oldDependencySet
for i, _ in pairs(self.dependencySet) do
self.dependencySet[i] = nil
end
if inputIsState then
self._inputTable.dependentSet[self] = true
self.dependencySet[self._inputTable] = true
end
for newInKey, value in pairs(newInputTable) do
local keyData = self._keyData[newInKey]
if keyData == nil then
keyData = {
dependencySet = setmetatable({}, WEAK_KEYS_METATABLE),
oldDependencySet = setmetatable({}, WEAK_KEYS_METATABLE),
dependencyValues = setmetatable({}, WEAK_KEYS_METATABLE),
}
self._keyData[newInKey] = keyData
end
local shouldRecalculate = oldInputTable[newInKey] == nil
if shouldRecalculate == false then
for dependency, oldValue in pairs(keyData.dependencyValues) do
if oldValue ~= peek(dependency) then
shouldRecalculate = true
break
end
end
end
if shouldRecalculate then
keyData.oldDependencySet, keyData.dependencySet =
keyData.dependencySet, keyData.oldDependencySet
for i, _ in pairs(keyData.dependencySet) do
keyData.dependencySet[i] = nil
end
local use = makeUseCallback(keyData.dependencySet)
local processOK, newOutKey, newMetaValue =
pcall(self._processor, use, newInKey)
if processOK then
if
self._destructor == nil
and (
needsDestruction(newOutKey)
or needsDestruction(newMetaValue)
)
then
logWarn "destructorNeededForKeys"
end
local oldInKey = keyOIMap[newOutKey]
local oldOutKey = keyIOMap[newInKey]
if
oldInKey ~= newInKey
and newInputTable[oldInKey] ~= nil
then
logError(
"forKeysKeyCollision",
nil,
tostring(newOutKey),
tostring(oldInKey),
tostring(newOutKey)
)
end
if
oldOutKey ~= newOutKey
and keyOIMap[oldOutKey] == newInKey
then
local oldMetaValue = meta[oldOutKey]
local destructOK, err = pcall(
self._destructor or cleanup,
oldOutKey,
oldMetaValue
)
if not destructOK then
logErrorNonFatal(
"forKeysDestructorError",
parseError(err)
)
end
keyOIMap[oldOutKey] = nil
outputTable[oldOutKey] = nil
meta[oldOutKey] = nil
end
oldInputTable[newInKey] = value
meta[newOutKey] = newMetaValue
keyOIMap[newOutKey] = newInKey
keyIOMap[newInKey] = newOutKey
outputTable[newOutKey] = value
didChange = true
else
keyData.oldDependencySet, keyData.dependencySet =
keyData.dependencySet, keyData.oldDependencySet
logErrorNonFatal(
"forKeysProcessorError",
parseError(newOutKey)
)
end
end
for dependency in pairs(keyData.dependencySet) do
keyData.dependencyValues[dependency] = peek(dependency)
self.dependencySet[dependency] = true
dependency.dependentSet[self] = true
end
end
for outputKey, inputKey in pairs(keyOIMap) do
if newInputTable[inputKey] == nil then
local oldMetaValue = meta[outputKey]
local destructOK, err =
pcall(self._destructor or cleanup, outputKey, oldMetaValue)
if not destructOK then
logErrorNonFatal("forKeysDestructorError", parseError(err))
end
oldInputTable[inputKey] = nil
meta[outputKey] = nil
keyOIMap[outputKey] = nil
keyIOMap[inputKey] = nil
outputTable[outputKey] = nil
self._keyData[inputKey] = nil
didChange = true
end
end
return didChange
end
function class:_peek()
return self._outputTable
end
function class:get()
logError "stateGetWasRemoved"
end
local function ForKeys(inputTable, processor, destructor)
local inputIsState = isState(inputTable)
local self = setmetatable({
type = "State",
kind = "ForKeys",
dependencySet = {},
dependentSet = setmetatable({}, WEAK_KEYS_METATABLE),
_oldDependencySet = {},
_processor = processor,
_destructor = destructor,
_inputIsState = inputIsState,
_inputTable = inputTable,
_oldInputTable = {},
_outputTable = {},
_keyOIMap = {},
_keyIOMap = {},
_keyData = {},
_meta = {},
}, CLASS_METATABLE)
self:update()
return self
end
__DARKLUA_BUNDLE_MODULES.H = ForKeys
end
do
local parseError = __DARKLUA_BUNDLE_MODULES.C
local logError = __DARKLUA_BUNDLE_MODULES.d
local logErrorNonFatal = __DARKLUA_BUNDLE_MODULES.B
local logWarn = __DARKLUA_BUNDLE_MODULES.u
local cleanup = __DARKLUA_BUNDLE_MODULES.j
local needsDestruction = __DARKLUA_BUNDLE_MODULES.D
local peek = __DARKLUA_BUNDLE_MODULES.n
local makeUseCallback = __DARKLUA_BUNDLE_MODULES.E
local isState = __DARKLUA_BUNDLE_MODULES.m
local class = {}
local CLASS_METATABLE = { __index = class }
local WEAK_KEYS_METATABLE = {
__mode = "k",
}
function class:update()
local inputIsState = self._inputIsState
local inputTable = peek(self._inputTable)
local outputValues = {}
local didChange = false
self._oldValueCache, self._valueCache =
self._valueCache, self._oldValueCache
local newValueCache = self._valueCache
local oldValueCache = self._oldValueCache
for i, _ in pairs(newValueCache) do
newValueCache[i] = nil
end
for dependency in pairs(self.dependencySet) do
dependency.dependentSet[self] = nil
end
self._oldDependencySet, self.dependencySet =
self.dependencySet, self._oldDependencySet
for i, _ in pairs(self.dependencySet) do
self.dependencySet[i] = nil
end
if inputIsState then
self._inputTable.dependentSet[self] = true
self.dependencySet[self._inputTable] = true
end
for inKey, inValue in pairs(inputTable) do
local oldCachedValues = oldValueCache[inValue]
local shouldRecalculate = oldCachedValues == nil
local value, valueData, meta
if type(oldCachedValues) == "table" and #oldCachedValues > 0 then
local valueInfo =
table.remove(oldCachedValues, #oldCachedValues)
value = valueInfo.value
valueData = valueInfo.valueData
meta = valueInfo.meta
if #oldCachedValues <= 0 then
oldValueCache[inValue] = nil
end
elseif oldCachedValues ~= nil then
oldValueCache[inValue] = nil
shouldRecalculate = true
end
if valueData == nil then
valueData = {
dependencySet = setmetatable({}, WEAK_KEYS_METATABLE),
oldDependencySet = setmetatable({}, WEAK_KEYS_METATABLE),
dependencyValues = setmetatable({}, WEAK_KEYS_METATABLE),
}
end
if shouldRecalculate == false then
for dependency, oldValue in pairs(valueData.dependencyValues) do
if oldValue ~= peek(dependency) then
shouldRecalculate = true
break
end
end
end
if shouldRecalculate then
valueData.oldDependencySet, valueData.dependencySet =
valueData.dependencySet, valueData.oldDependencySet
for i, _ in pairs(valueData.dependencySet) do
valueData.dependencySet[i] = nil
end
local use = makeUseCallback(valueData.dependencySet)
local processOK, newOutValue, newMetaValue =
pcall(self._processor, use, inValue)
if processOK then
if
self._destructor == nil
and (
needsDestruction(newOutValue)
or needsDestruction(newMetaValue)
)
then
logWarn "destructorNeededForValues"
end
if value ~= nil then
local destructOK, err =
pcall(self._destructor or cleanup, value, meta)
if not destructOK then
logErrorNonFatal(
"forValuesDestructorError",
parseError(err)
)
end
end
value = newOutValue
meta = newMetaValue
didChange = true
else
valueData.oldDependencySet, valueData.dependencySet =
valueData.dependencySet, valueData.oldDependencySet
logErrorNonFatal(
"forValuesProcessorError",
parseError(newOutValue)
)
end
end
local newCachedValues = newValueCache[inValue]
if newCachedValues == nil then
newCachedValues = {}
newValueCache[inValue] = newCachedValues
end
table.insert(newCachedValues, {
value = value,
valueData = valueData,
meta = meta,
})
outputValues[inKey] = value
for dependency in pairs(valueData.dependencySet) do
valueData.dependencyValues[dependency] = peek(dependency)
self.dependencySet[dependency] = true
dependency.dependentSet[self] = true
end
end
for _oldInValue, oldCachedValueInfo in pairs(oldValueCache) do
for _, valueInfo in ipairs(oldCachedValueInfo) do
local oldValue = valueInfo.value
local oldMetaValue = valueInfo.meta
local destructOK, err =
pcall(self._destructor or cleanup, oldValue, oldMetaValue)
if not destructOK then
logErrorNonFatal(
"forValuesDestructorError",
parseError(err)
)
end
didChange = true
end
for i, _ in pairs(oldCachedValueInfo) do
oldCachedValueInfo[i] = nil
end
end
self._outputTable = outputValues
return didChange
end
function class:_peek()
return self._outputTable
end
function class:get()
logError "stateGetWasRemoved"
end
local function ForValues(inputTable, processor, destructor)
local inputIsState = isState(inputTable)
local self = setmetatable({
type = "State",
kind = "ForValues",
dependencySet = {},
dependentSet = setmetatable({}, WEAK_KEYS_METATABLE),
_oldDependencySet = {},
_processor = processor,
_destructor = destructor,
_inputIsState = inputIsState,
_inputTable = inputTable,
_outputTable = {},
_valueCache = {},
_oldValueCache = {},
}, CLASS_METATABLE)
self:update()
return self
end
__DARKLUA_BUNDLE_MODULES.I = ForValues
end
do
local Oklab = {}
function Oklab.to(rgb)
local l = rgb.r * 0.4122214708
+ rgb.g * 0.5363325363
+ rgb.b * 0.0514459929
local m = rgb.r * 0.2119034982
+ rgb.g * 0.6806995451
+ rgb.b * 0.1073969566
local s = rgb.r * 0.0883024619
+ rgb.g * 0.2817188376
+ rgb.b * 0.6299787005
local lRoot = l ^ 0.3333333333333333
local mRoot = m ^ 0.3333333333333333
local sRoot = s ^ 0.3333333333333333
return Vector3.new(
lRoot * 0.2104542553 + mRoot * 0.793617785 - sRoot * 0.0040720468,
lRoot * 1.9779984951 - mRoot * 2.428592205 + sRoot * 0.4505937099,
lRoot * 0.0259040371 + mRoot * 0.7827717662 - sRoot * 0.808675766
)
end
function Oklab.from(lab, unclamped)
local lRoot = lab.X + lab.Y * 0.3963377774 + lab.Z * 0.2158037573
local mRoot = lab.X - lab.Y * 0.1055613458 - lab.Z * 0.0638541728
local sRoot = lab.X - lab.Y * 0.0894841775 - lab.Z * 1.291485548
local l = lRoot ^ 3
local m = mRoot ^ 3
local s = sRoot ^ 3
local red = l * 4.0767416621 - m * 3.3077115913 + s * 0.2309699292
local green = l * -1.2684380046 + m * 2.6097574011 - s * 0.3413193965
local blue = l * -4.196086299999999E-3
- m * 0.7034186147
+ s * 1.707614701
if not unclamped then
red = math.max(0, math.min(red, 1))
green = math.max(0, math.min(green, 1))
blue = math.max(0, math.min(blue, 1))
end
return Color3.new(red, green, blue)
end
__DARKLUA_BUNDLE_MODULES.J = Oklab
end
do
local Oklab = __DARKLUA_BUNDLE_MODULES.J
local typeof = __DARKLUA_BUNDLE_MODULES.i
local function lerpType(from, to, ratio)
local typeString = typeof(from)
if typeof(to) == typeString then
if typeString == "number" then
return (to - from) * ratio + from
elseif typeString == "CFrame" then
return from:Lerp(to, ratio)
elseif typeString == "Color3" then
local fromLab = Oklab.to(from)
local toLab = Oklab.to(to)
return Oklab.from(fromLab:Lerp(toLab, ratio), false)
elseif typeString == "Ray" then
return Ray.new(
from.Origin:Lerp(to.Origin, ratio),
from.Direction:Lerp(to.Direction, ratio)
)
elseif typeString == "Region3" then
local position =
from.CFrame.Position:Lerp(to.CFrame.Position, ratio)
local halfSize = from.Size:Lerp(to.Size, ratio) / 2
return Region3.new(position - halfSize, position + halfSize)
elseif typeString == "Region3int16" then
return Region3int16.new(
Vector3int16.new(
(to.Min.X - from.Min.X) * ratio + from.Min.X,
(to.Min.Y - from.Min.Y) * ratio + from.Min.Y,
(to.Min.Z - from.Min.Z) * ratio + from.Min.Z
),
Vector3int16.new(
(to.Max.X - from.Max.X) * ratio + from.Max.X,
(to.Max.Y - from.Max.Y) * ratio + from.Max.Y,
(to.Max.Z - from.Max.Z) * ratio + from.Max.Z
)
)
elseif typeString == "UDim" then
return UDim.new(
(to.Scale - from.Scale) * ratio + from.Scale,
(to.Offset - from.Offset) * ratio + from.Offset
)
elseif typeString == "UDim2" then
return UDim2.new(
(to.X.Scale - from.X.Scale) * ratio + from.X.Scale,
(to.X.Offset - from.X.Offset) * ratio + from.X.Offset,
(to.Y.Scale - from.Y.Scale) * ratio + from.Y.Scale,
(to.Y.Offset - from.Y.Offset) * ratio + from.Y.Offset
)
elseif typeString == "Vector2" or typeString == "Vector3" then
return from:Lerp(to, ratio)
elseif typeString == "Vector2int16" then
return Vector2int16.new(
(to.X - from.X) * ratio + from.X,
(to.Y - from.Y) * ratio + from.Y
)
elseif typeString == "Vector3int16" then
return Vector3int16.new(
(to.X - from.X) * ratio + from.X,
(to.Y - from.Y) * ratio + from.Y,
(to.Z - from.Z) * ratio + from.Z
)
end
end
if ratio < 0.5 then
return from
end
return to
end
__DARKLUA_BUNDLE_MODULES.K = lerpType
end
do
local pow = math.pow
local sin = math.sin
local cos = math.cos
local pi = math.pi
local sqrt = math.sqrt
local abs = math.abs
local asin = math.asin
local easing = {
Linear = {},
Quad = {},
Cubic = {},
Quart = {},
Quint = {},
Sine = {},
Exponential = {},
Circular = {},
Elastic = {},
Back = {},
Bounce = {},
}
local linear = function(t, b, c)
return c * t + b
end
easing.Linear.In = linear
easing.Linear.Out = linear
easing.Linear.InOut = linear
easing.Linear.OutIn = linear
easing.Quad.In = function(t, b, c)
return c * pow(t, 2) + b
end
easing.Quad.Out = function(t, b, c)
return -c * t * (t - 2) + b
end
easing.Quad.InOut = function(t, b, c)
t = t * 2
if t < 1 then
return c / 2 * pow(t, 2) + b
end
return -c / 2 * ((t - 1) * (t - 3) - 1) + b
end
easing.Quad.OutIn = function(t, b, c)
if t < 0.5 then
return easing.Quad.Out(t * 2, b, c / 2)
end
return easing.Quad.In((t * 2) - 1, b + c / 2, c / 2)
end
easing.Cubic.In = function(t, b, c)
return c * pow(t, 3) + b
end
easing.Cubic.Out = function(t, b, c)
t = t - 1
return c * (pow(t, 3) + 1) + b
end
easing.Cubic.InOut = function(t, b, c)
t = t * 2
if t < 1 then
return c / 2 * t * t * t + b
end
t = t - 2
return c / 2 * (t * t * t + 2) + b
end
easing.Cubic.OutIn = function(t, b, c)
if t < 0.5 then
return easing.Cubic.Out(t * 2, b, c / 2)
end
return easing.Cubic.In((t * 2) - 1, b + c / 2, c / 2)
end
easing.Quart.In = function(t, b, c)
return c * pow(t, 4) + b
end
easing.Quart.Out = function(t, b, c)
t = t - 1
return -c * (pow(t, 4) - 1) + b
end
easing.Quart.InOut = function(t, b, c)
t = t * 2
if t < 1 then
return c / 2 * pow(t, 4) + b
end
t = t - 2
return -c / 2 * (pow(t, 4) - 2) + b
end
easing.Quart.OutIn = function(t, b, c)
if t < 0.5 then
return easing.Quart.Out(t * 2, b, c / 2)
end
return easing.Quart.In((t * 2) - 1, b + c / 2, c / 2)
end
easing.Quint.In = function(t, b, c)
return c * pow(t, 5) + b
end
easing.Quint.Out = function(t, b, c)
t = t - 1
return c * (pow(t, 5) + 1) + b
end
easing.Quint.InOut = function(t, b, c)
t = t * 2
if t < 1 then
return c / 2 * pow(t, 5) + b
end
t = t - 2
return c / 2 * (pow(t, 5) + 2) + b
end
easing.Quint.OutIn = function(t, b, c)
if t < 0.5 then
return easing.Quint.Out(t * 2, b, c / 2)
end
return easing.Quint.In((t * 2) - 1, b + c / 2, c / 2)
end
easing.Sine.In = function(t, b, c)
return -c * cos(t * (pi / 2)) + c + b
end
easing.Sine.Out = function(t, b, c)
return c * sin(t * (pi / 2)) + b
end
easing.Sine.InOut = function(t, b, c)
return -c / 2 * (cos(pi * t) - 1) + b
end
easing.Sine.OutIn = function(t, b, c)
if t < 0.5 then
return easing.Sine.Out(t * 2, b, c / 2)
end
return easing.Sine.In((t * 2) - 1, b + c / 2, c / 2)
end
easing.Exponential.In = function(t, b, c)
if t == 0 then
return b
end
return c * pow(2, 10 * (t - 1)) + b - c * 0.001
end
easing.Exponential.Out = function(t, b, c)
if t == 1 then
return b + c
end
return c * 1.001 * (-pow(2, -10 * t) + 1) + b
end
easing.Exponential.InOut = function(t, b, c)
if t == 0 then
return b
elseif t == 1 then
return b + c
end
t = t * 2
if t < 1 then
return c / 2 * pow(2, 10 * (t - 1)) + b - c * 0.0005
end
t = t - 1
return c / 2 * 1.0005 * (-pow(2, -10 * t) + 2) + b
end
easing.Exponential.OutIn = function(t, b, c)
if t < 0.5 then
return t.Exponential.Out(t * 2, b, c / 2)
end
return t.Exponential.In((t * 2) - 1, b + c / 2, c / 2)
end
easing.Circular.In = function(t, b, c)
return (-c * (sqrt(1 - pow(t, 2)) - 1) + b)
end
easing.Circular.Out = function(t, b, c)
t = t - 1
return (c * sqrt(1 - pow(t, 2)) + b)
end
easing.Circular.InOut = function(t, b, c)
t = t * 2
if t < 1 then
return -c / 2 * (sqrt(1 - t * t) - 1) + b
end
t = t - 2
return c / 2 * (sqrt(1 - t * t) + 1) + b
end
easing.Circular.OutIn = function(t, b, c)
if t < 0.5 then
return easing.Circular.Out(t * 2, b, c / 2)
end
return easing.Circular.In((t * 2) - 1, b + c / 2, c / 2)
end
easing.Elastic.In = function(t, b, c)
if t == 0 then
return b
elseif t == 1 then
return b + c
end
local p = 0.3
local s
s = p / 4
t = t - 1
return -(c * pow(2, 10 * t) * sin((t * 1 - s) * (2 * pi) / p)) + b
end
easing.Elastic.Out = function(t, b, c)
if t == 0 then
return b
elseif t == 1 then
return b + c
end
local p = 0.3
local s
s = p / 4
return c * pow(2, -10 * t) * sin((t - s) * (2 * pi) / p) + c + b
end
easing.Elastic.InOut = function(t, b, c)
if t == 0 then
return b
end
t = t * 2
if t == 2 then
return b + c
end
local p = 0.45
local a = 0
local s
if not a or a < abs(c) then
a = c
s = p / 4
else
s = p / (2 * pi) * asin(c / a)
end
t = t - 1
if t < 1 then
return -0.5 * (a * pow(2, 10 * t) * sin((t - s) * (2 * pi) / p)) + b
end
return a * pow(2, -10 * t) * sin((t - s) * (2 * pi) / p) * 0.5 + c + b
end
easing.Elastic.OutIn = function(t, b, c)
if t < 0.5 then
return easing.Elastic.Out(t * 2, b, c / 2)
end
return easing.Elastic.In((t * 2) - 1, b + c / 2, c / 2)
end
easing.Back.In = function(t, b, c)
local s = 1.70158
return c * t * t * ((s + 1) * t - s) + b
end
easing.Back.Out = function(t, b, c)
local s = 1.70158
t = t - 1
return c * (t * t * ((s + 1) * t + s) + 1) + b
end
easing.Back.InOut = function(t, b, c)
local s = 2.5949095
t = t * 2
if t < 1 then
return c / 2 * (t * t * ((s + 1) * t - s)) + b
end
t = t - 2
return c / 2 * (t * t * ((s + 1) * t + s) + 2) + b
end
easing.Back.OutIn = function(t, b, c)
if t < 0.5 then
return easing.Back.Out(t * 2, b, c / 2)
end
return easing.Back.In((t * 2) - 1, b + c / 2, c / 2)
end
easing.Bounce.Out = function(t, b, c)
if t < 0.36363636363636365 then
return c * (7.5625 * t * t) + b
elseif t < 0.7272727272727273 then
t = t - 0.5454545454545454
return c * (7.5625 * t * t + 0.75) + b
elseif t < 0.9090909090909091 then
t = t - 0.8181818181818182
return c * (7.5625 * t * t + 0.9375) + b
end
t = t - 0.9545454545454546
return c * (7.5625 * t * t + 0.984375) + b
end
easing.Bounce.In = function(t, b, c)
return c - easing.Bounce.Out(1 - t, 0, c) + b
end
easing.Bounce.InOut = function(t, b, c)
if t < 0.5 then
return easing.Bounce.In(t * 2, 0, c) * 0.5 + b
end
return easing.Bounce.Out(t * 2 - 1, 0, c) * 0.5 + c * 0.5 + b
end
easing.Bounce.OutIn = function(t, b, c)
if t < 0.5 then
return easing.Bounce.Out(t * 2, b, c / 2)
end
return easing.Bounce.In((t * 2) - 1, b + c / 2, c / 2)
end
__DARKLUA_BUNDLE_MODULES.L = easing
end
do
local easing = __DARKLUA_BUNDLE_MODULES.L
local function getTweenRatio(tweenInfo, currentTime)
local delay = tweenInfo.DelayTime
local duration = tweenInfo.Time
local reverses = tweenInfo.Reverses
local numCycles = 1 + tweenInfo.RepeatCount
local easeStyle = tweenInfo.EasingStyle
local easeDirection = tweenInfo.EasingDirection
local cycleDuration = delay + duration
if reverses then
cycleDuration = cycleDuration + duration
end
if
currentTime >= cycleDuration * numCycles
and tweenInfo.RepeatCount > -1
then
return 1
end
local cycleTime = currentTime % cycleDuration
if cycleTime <= delay then
return 0
end
local tweenProgress = (cycleTime - delay) / duration
if tweenProgress > 1 then
tweenProgress = 2 - tweenProgress
end
return easing[easeStyle][easeDirection](tweenProgress, 0, 1)
end
__DARKLUA_BUNDLE_MODULES.M = getTweenRatio
end
do
local External = __DARKLUA_BUNDLE_MODULES.e
local lerpType = __DARKLUA_BUNDLE_MODULES.K
local getTweenRatio = __DARKLUA_BUNDLE_MODULES.M
local updateAll = __DARKLUA_BUNDLE_MODULES.y
local TweenScheduler = {}
local WEAK_KEYS_METATABLE = {
__mode = "k",
}
local allTweens = {}
setmetatable(allTweens, WEAK_KEYS_METATABLE)
function TweenScheduler.add(tween)
allTweens[tween] = true
end
function TweenScheduler.remove(tween)
allTweens[tween] = nil
end
local function updateAllTweens(now)
for tween in pairs(allTweens) do
local currentTime = now - tween._currentTweenStartTime
if
currentTime > tween._currentTweenDuration
and tween._currentTweenInfo.RepeatCount > -1
then
if tween._currentTweenInfo.Reverses then
tween._currentValue = tween._prevValue
else
tween._currentValue = tween._nextValue
end
tween._currentlyAnimating = false
updateAll(tween)
TweenScheduler.remove(tween)
else
local ratio =
getTweenRatio(tween._currentTweenInfo, currentTime)
local currentValue =
lerpType(tween._prevValue, tween._nextValue, ratio)
tween._currentValue = currentValue
tween._currentlyAnimating = true
updateAll(tween)
end
end
end
External.bindToUpdateStep(updateAllTweens)
__DARKLUA_BUNDLE_MODULES.N = TweenScheduler
end
do
local External = __DARKLUA_BUNDLE_MODULES.e
local TweenScheduler = __DARKLUA_BUNDLE_MODULES.N
local logError = __DARKLUA_BUNDLE_MODULES.d
local logErrorNonFatal = __DARKLUA_BUNDLE_MODULES.B
local xtypeof = __DARKLUA_BUNDLE_MODULES.k
local peek = __DARKLUA_BUNDLE_MODULES.n
local typeof = __DARKLUA_BUNDLE_MODULES.i
local class = {}
local CLASS_METATABLE = { __index = class }
local WEAK_KEYS_METATABLE = {
__mode = "k",
}
function class:update()
local goalValue = peek(self._goalState)
if goalValue == self._nextValue and not self._currentlyAnimating then
return false
end
local tweenInfo = peek(self._tweenInfo)
if typeof(tweenInfo) ~= "TweenInfo" then
logErrorNonFatal("mistypedTweenInfo", nil, typeof(tweenInfo))
return false
end
self._prevValue = self._currentValue
self._nextValue = goalValue
self._currentTweenStartTime = External.lastUpdateStep()
self._currentTweenInfo = tweenInfo
local tweenDuration = tweenInfo.DelayTime + tweenInfo.Time
if tweenInfo.Reverses then
tweenDuration = tweenDuration + tweenInfo.Time
end
tweenDuration = tweenDuration * (tweenInfo.RepeatCount + 1)
self._currentTweenDuration = tweenDuration
TweenScheduler.add(self)
return false
end
function class:_peek()
return self._currentValue
end
function class:get()
logError "stateGetWasRemoved"
end
local function Tween(goalState, tweenInfo)
local currentValue = peek(goalState)
if tweenInfo == nil then
tweenInfo = TweenInfo.new()
end
local dependencySet = { [goalState] = true }
local tweenInfoIsState = xtypeof(tweenInfo) == "State"
if tweenInfoIsState then
dependencySet[tweenInfo] = true
end
local startingTweenInfo = peek(tweenInfo)
if typeof(startingTweenInfo) ~= "TweenInfo" then
logError("mistypedTweenInfo", nil, typeof(startingTweenInfo))
end
local self = setmetatable({
type = "State",
kind = "Tween",
dependencySet = dependencySet,
dependentSet = setmetatable({}, WEAK_KEYS_METATABLE),
_goalState = goalState,
_tweenInfo = tweenInfo,
_tweenInfoIsState = tweenInfoIsState,
_prevValue = currentValue,
_nextValue = currentValue,
_currentValue = currentValue,
_currentTweenInfo = tweenInfo,
_currentTweenDuration = 0,
_currentTweenStartTime = 0,
_currentlyAnimating = false,
}, CLASS_METATABLE)
goalState.dependentSet[self] = true
return self
end
__DARKLUA_BUNDLE_MODULES.O = Tween
end
do
local Oklab = __DARKLUA_BUNDLE_MODULES.J
local function unpackType(value, typeString)
if typeString == "number" then
return { value }
elseif typeString == "CFrame" then
local axis, angle = value:ToAxisAngle()
return {
value.X,
value.Y,
value.Z,
axis.X,
axis.Y,
axis.Z,
angle,
}
elseif typeString == "Color3" then
local lab = Oklab.to(value)
return {
lab.X,
lab.Y,
lab.Z,
}
elseif typeString == "ColorSequenceKeypoint" then
local lab = Oklab.to(value.Value)
return {
lab.X,
lab.Y,
lab.Z,
value.Time,
}
elseif typeString == "DateTime" then
return {
value.UnixTimestampMillis,
}
elseif typeString == "NumberRange" then
return {
value.Min,
value.Max,
}
elseif typeString == "NumberSequenceKeypoint" then
return {
value.Value,
value.Time,
value.Envelope,
}
elseif typeString == "PhysicalProperties" then
return {
value.Density,
value.Friction,
value.Elasticity,
value.FrictionWeight,
value.ElasticityWeight,
}
elseif typeString == "Ray" then
return {
value.Origin.X,
value.Origin.Y,
value.Origin.Z,
value.Direction.X,
value.Direction.Y,
value.Direction.Z,
}
elseif typeString == "Rect" then
return {
value.Min.X,
value.Min.Y,
value.Max.X,
value.Max.Y,
}
elseif typeString == "Region3" then
return {
value.CFrame.X,
value.CFrame.Y,
value.CFrame.Z,
value.Size.X,
value.Size.Y,
value.Size.Z,
}
elseif typeString == "Region3int16" then
return {
value.Min.X,
value.Min.Y,
value.Min.Z,
value.Max.X,
value.Max.Y,
value.Max.Z,
}
elseif typeString == "UDim" then
return {
value.Scale,
value.Offset,
}
elseif typeString == "UDim2" then
return {
value.X.Scale,
value.X.Offset,
value.Y.Scale,
value.Y.Offset,
}
elseif typeString == "Vector2" then
return {
value.X,
value.Y,
}
elseif typeString == "Vector2int16" then
return {
value.X,
value.Y,
}
elseif typeString == "Vector3" then
return {
value.X,
value.Y,
value.Z,
}
elseif typeString == "Vector3int16" then
return {
value.X,
value.Y,
value.Z,
}
else
return {}
end
end
__DARKLUA_BUNDLE_MODULES.P = unpackType
end
do
local Oklab = __DARKLUA_BUNDLE_MODULES.J
local function packType(numbers, typeString)
if typeString == "number" then
return numbers[1]
elseif typeString == "CFrame" then
return CFrame.new(numbers[1], numbers[2], numbers[3])
* CFrame.fromAxisAngle(
Vector3.new(numbers[4], numbers[5], numbers[6]).Unit,
numbers[7]
)
elseif typeString == "Color3" then
return Oklab.from(
Vector3.new(numbers[1], numbers[2], numbers[3]),
false
)
elseif typeString == "ColorSequenceKeypoint" then
return ColorSequenceKeypoint.new(
numbers[4],
Oklab.from(
Vector3.new(numbers[1], numbers[2], numbers[3]),
false
)
)
elseif typeString == "DateTime" then
return DateTime.fromUnixTimestampMillis(numbers[1])
elseif typeString == "NumberRange" then
return NumberRange.new(numbers[1], numbers[2])
elseif typeString == "NumberSequenceKeypoint" then
return NumberSequenceKeypoint.new(
numbers[2],
numbers[1],
numbers[3]
)
elseif typeString == "PhysicalProperties" then
return PhysicalProperties.new(
numbers[1],
numbers[2],
numbers[3],
numbers[4],
numbers[5]
)
elseif typeString == "Ray" then
return Ray.new(
Vector3.new(numbers[1], numbers[2], numbers[3]),
Vector3.new(numbers[4], numbers[5], numbers[6])
)
elseif typeString == "Rect" then
return Rect.new(numbers[1], numbers[2], numbers[3], numbers[4])
elseif typeString == "Region3" then
local position = Vector3.new(numbers[1], numbers[2], numbers[3])
local halfSize =
Vector3.new(numbers[4] / 2, numbers[5] / 2, numbers[6] / 2)
return Region3.new(position - halfSize, position + halfSize)
elseif typeString == "Region3int16" then
return Region3int16.new(
Vector3int16.new(numbers[1], numbers[2], numbers[3]),
Vector3int16.new(numbers[4], numbers[5], numbers[6])
)
elseif typeString == "UDim" then
return UDim.new(numbers[1], numbers[2])
elseif typeString == "UDim2" then
return UDim2.new(numbers[1], numbers[2], numbers[3], numbers[4])
elseif typeString == "Vector2" then
return Vector2.new(numbers[1], numbers[2])
elseif typeString == "Vector2int16" then
return Vector2int16.new(numbers[1], numbers[2])
elseif typeString == "Vector3" then
return Vector3.new(numbers[1], numbers[2], numbers[3])
elseif typeString == "Vector3int16" then
return Vector3int16.new(numbers[1], numbers[2], numbers[3])
else
return nil
end
end
__DARKLUA_BUNDLE_MODULES.Q = packType
end
do
local function springCoefficients(time, damping, speed)
if time == 0 or speed == 0 then
return 1, 0, 0, 1
end
local posPos, posVel, velPos, velVel
if damping > 1 then
local scaledTime = time * speed
local alpha = math.sqrt(damping ^ 2 - 1)
local scaledInvAlpha = -0.5 / alpha
local z1 = -alpha - damping
local z2 = 1 / z1
local expZ1 = math.exp(scaledTime * z1)
local expZ2 = math.exp(scaledTime * z2)
posPos = (expZ2 * z1 - expZ1 * z2) * scaledInvAlpha
posVel = (expZ1 - expZ2) * scaledInvAlpha / speed
velPos = (expZ2 - expZ1) * scaledInvAlpha * speed
velVel = (expZ1 * z1 - expZ2 * z2) * scaledInvAlpha
elseif damping == 1 then
local scaledTime = time * speed
local expTerm = math.exp(-scaledTime)
posPos = expTerm * (1 + scaledTime)
posVel = expTerm * time
velPos = expTerm * (-scaledTime * speed)
velVel = expTerm * (1 - scaledTime)
else
local scaledTime = time * speed
local alpha = math.sqrt(1 - damping ^ 2)
local invAlpha = 1 / alpha
local alphaTime = alpha * scaledTime
local expTerm = math.exp(-scaledTime * damping)
local sinTerm = expTerm * math.sin(alphaTime)
local cosTerm = expTerm * math.cos(alphaTime)
local sinInvAlpha = sinTerm * invAlpha
local sinInvAlphaDamp = sinInvAlpha * damping
posPos = sinInvAlphaDamp + cosTerm
posVel = sinInvAlpha
velPos = -(sinInvAlphaDamp * damping + sinTerm * alpha)
velVel = cosTerm - sinInvAlphaDamp
end
return posPos, posVel, velPos, velVel
end
__DARKLUA_BUNDLE_MODULES.R = springCoefficients
end
do
local External = __DARKLUA_BUNDLE_MODULES.e
local packType = __DARKLUA_BUNDLE_MODULES.Q
local springCoefficients = __DARKLUA_BUNDLE_MODULES.R
local updateAll = __DARKLUA_BUNDLE_MODULES.y
local SpringScheduler = {}
local EPSILON = 0.0001
local activeSprings = {}
local lastUpdateTime = External.lastUpdateStep()
function SpringScheduler.add(spring)
spring._lastSchedule = lastUpdateTime
spring._startDisplacements = {}
spring._startVelocities = {}
for index, goal in ipairs(spring._springGoals) do
spring._startDisplacements[index] = spring._springPositions[index]
- goal
spring._startVelocities[index] = spring._springVelocities[index]
end
activeSprings[spring] = true
end
function SpringScheduler.remove(spring)
activeSprings[spring] = nil
end
local function updateAllSprings(now)
local springsToSleep = {}
lastUpdateTime = now
for spring in pairs(activeSprings) do
local posPos, posVel, velPos, velVel = springCoefficients(
lastUpdateTime - spring._lastSchedule,
spring._currentDamping,
spring._currentSpeed
)
local positions = spring._springPositions
local velocities = spring._springVelocities
local startDisplacements = spring._startDisplacements
local startVelocities = spring._startVelocities
local isMoving = false
for index, goal in ipairs(spring._springGoals) do
local oldDisplacement = startDisplacements[index]
local oldVelocity = startVelocities[index]
local newDisplacement = oldDisplacement * posPos
+ oldVelocity * posVel
local newVelocity = oldDisplacement * velPos
+ oldVelocity * velVel
if
math.abs(newDisplacement) > EPSILON
or math.abs(newVelocity) > EPSILON
then
isMoving = true
end
positions[index] = newDisplacement + goal
velocities[index] = newVelocity
end
if not isMoving then
springsToSleep[spring] = true
end
end
for spring in pairs(activeSprings) do
spring._currentValue =
packType(spring._springPositions, spring._currentType)
updateAll(spring)
end
for spring in pairs(springsToSleep) do
activeSprings[spring] = nil
spring._currentValue =
packType(spring._springGoals, spring._currentType)
end
end
External.bindToUpdateStep(updateAllSprings)
__DARKLUA_BUNDLE_MODULES.S = SpringScheduler
end
do
local logError = __DARKLUA_BUNDLE_MODULES.d
local logErrorNonFatal = __DARKLUA_BUNDLE_MODULES.B
local unpackType = __DARKLUA_BUNDLE_MODULES.P
local SpringScheduler = __DARKLUA_BUNDLE_MODULES.S
local updateAll = __DARKLUA_BUNDLE_MODULES.y
local xtypeof = __DARKLUA_BUNDLE_MODULES.k
local peek = __DARKLUA_BUNDLE_MODULES.n
local typeof = __DARKLUA_BUNDLE_MODULES.i
local class = {}
local CLASS_METATABLE = { __index = class }
local WEAK_KEYS_METATABLE = {
__mode = "k",
}
function class:setPosition(newValue)
local newType = typeof(newValue)
if newType ~= self._currentType then
logError("springTypeMismatch", nil, newType, self._currentType)
end
self._springPositions = unpackType(newValue, newType)
self._currentValue = newValue
SpringScheduler.add(self)
updateAll(self)
end
function class:setVelocity(newValue)
local newType = typeof(newValue)
if newType ~= self._currentType then
logError("springTypeMismatch", nil, newType, self._currentType)
end
self._springVelocities = unpackType(newValue, newType)
SpringScheduler.add(self)
end
function class:addVelocity(deltaValue)
local deltaType = typeof(deltaValue)
if deltaType ~= self._currentType then
logError("springTypeMismatch", nil, deltaType, self._currentType)
end
local springDeltas = unpackType(deltaValue, deltaType)
for index, delta in ipairs(springDeltas) do
do
local __DARKLUA_VAR = self._springVelocities
__DARKLUA_VAR[index] = __DARKLUA_VAR[index] + delta
end
end
SpringScheduler.add(self)
end
function class:update()
local goalValue = peek(self._goalState)
if goalValue == self._goalValue then
local damping = peek(self._damping)
if typeof(damping) ~= "number" then
logErrorNonFatal("mistypedSpringDamping", nil, typeof(damping))
elseif damping < 0 then
logErrorNonFatal("invalidSpringDamping", nil, damping)
else
self._currentDamping = damping
end
local speed = peek(self._speed)
if typeof(speed) ~= "number" then
logErrorNonFatal("mistypedSpringSpeed", nil, typeof(speed))
elseif speed < 0 then
logErrorNonFatal("invalidSpringSpeed", nil, speed)
else
self._currentSpeed = speed
end
return false
else
self._goalValue = goalValue
local oldType = self._currentType
local newType = typeof(goalValue)
self._currentType = newType
local springGoals = unpackType(goalValue, newType)
local numSprings = #springGoals
self._springGoals = springGoals
if newType ~= oldType then
self._currentValue = self._goalValue
local springPositions = {}
for i = 1, numSprings do
springPositions[i] = 0
end
local springVelocities = {}
for i = 1, numSprings do
springVelocities[i] = 0
end
for index, springGoal in ipairs(springGoals) do
springPositions[index] = springGoal
end
self._springPositions = springPositions
self._springVelocities = springVelocities
SpringScheduler.remove(self)
return true
elseif numSprings == 0 then
self._currentValue = self._goalValue
return true
else
SpringScheduler.add(self)
return false
end
end
end
function class:_peek()
return self._currentValue
end
function class:get()
logError "stateGetWasRemoved"
end
local function Spring(goalState, speed, damping)
if speed == nil then
speed = 10
end
if damping == nil then
damping = 1
end
local dependencySet = { [goalState] = true }
if xtypeof(speed) == "State" then
dependencySet[speed] = true
end
if xtypeof(damping) == "State" then
dependencySet[damping] = true
end
local self = setmetatable({
type = "State",
kind = "Spring",
dependencySet = dependencySet,
dependentSet = setmetatable({}, WEAK_KEYS_METATABLE),
_speed = speed,
_damping = damping,
_goalState = goalState,
_goalValue = nil,
_currentType = nil,
_currentValue = nil,
_currentSpeed = peek(speed),
_currentDamping = peek(damping),
_springPositions = nil,
_springGoals = nil,
_springVelocities = nil,
}, CLASS_METATABLE)
goalState.dependentSet[self] = true
self:update()
return self
end
__DARKLUA_BUNDLE_MODULES.T = Spring
end
do
local function doNothing() end
__DARKLUA_BUNDLE_MODULES.U = doNothing
end
do
local logError = __DARKLUA_BUNDLE_MODULES.d
local TweenInfo = {}
function TweenInfo.new(
time,
easingStyle,
easingDirection,
repeatCount,
reverses,
delayTime
)
local proxy = newproxy(true)
local mt = getmetatable(proxy)
if type(easingStyle) ~= "string" then
if easingStyle then
easingStyle = tostring(easingStyle):gsub("Enum.%w+.", "")
end
else
local ok
for _, s in ipairs {
"Linear",
"Quad",
"Cubic",
"Quart",
"Quint",
"Sine",
"Exponential",
"Circular",
"Elastic",
"Back",
"Bounce",
} do
if easingStyle == s then
ok = true
break
end
end
if not ok then
logError("invalidEasingStyle", nil, easingStyle)
end
end
if type(easingDirection) ~= "string" then
if easingDirection then
easingDirection =
tostring(easingDirection):gsub("Enum.%w+.", "")
end
else
local ok
for _, d in ipairs {
"In",
"Out",
"InOut",
"OutIn",
} do
if easingDirection == d then
ok = true
break
end
end
if not ok then
logError("invalidEasingDirection", nil, easingDirection)
end
end
time = time or 1
easingStyle = easingStyle or "Quad"
easingDirection = easingDirection or "Out"
repeatCount = repeatCount or 0
reverses = reverses or false
delayTime = delayTime or 0
mt.__index = {
Time = time,
EasingStyle = easingStyle,
EasingDirection = easingDirection,
RepeatCount = repeatCount,
Reverses = reverses,
DelayTime = delayTime,
}
mt.__newindex = function(_, prop)
error(prop .. " cannot be assigned to", math.huge)
end
mt.__tostring = function()
return "Time:"
.. tostring(time)
.. " DelayTime:"
.. tostring(delayTime)
.. " RepeatCount:"
.. tostring(repeatCount)
.. " Reverses:"
.. (reverses and "True" or "False")
.. " EasingDirection:"
.. easingDirection
.. " EasingStyle:"
.. easingStyle
end
mt.__metatable = "The metatable is locked"
return proxy
end
__DARKLUA_BUNDLE_MODULES.V = TweenInfo
end
local External = __DARKLUA_BUNDLE_MODULES.e
local restrictRead = __DARKLUA_BUNDLE_MODULES.f
do
local MercuryExternal = __DARKLUA_BUNDLE_MODULES.g
External.setExternalScheduler(MercuryExternal)
end
local Fusion = restrictRead("Fusion", {
version = {
major = 0,
minor = 3,
isRelease = false,
},
New = __DARKLUA_BUNDLE_MODULES.p,
Hydrate = __DARKLUA_BUNDLE_MODULES.q,
Ref = __DARKLUA_BUNDLE_MODULES.r,
Out = __DARKLUA_BUNDLE_MODULES.s,
Cleanup = __DARKLUA_BUNDLE_MODULES.t,
Children = __DARKLUA_BUNDLE_MODULES.v,
OnEvent = __DARKLUA_BUNDLE_MODULES.w,
OnChange = __DARKLUA_BUNDLE_MODULES.x,
Value = __DARKLUA_BUNDLE_MODULES.A,
Computed = __DARKLUA_BUNDLE_MODULES.F,
ForPairs = __DARKLUA_BUNDLE_MODULES.G,
ForKeys = __DARKLUA_BUNDLE_MODULES.H,
ForValues = __DARKLUA_BUNDLE_MODULES.I,
Observer = __DARKLUA_BUNDLE_MODULES.l,
Tween = __DARKLUA_BUNDLE_MODULES.O,
Spring = __DARKLUA_BUNDLE_MODULES.T,
cleanup = __DARKLUA_BUNDLE_MODULES.j,
doNothing = __DARKLUA_BUNDLE_MODULES.U,
peek = __DARKLUA_BUNDLE_MODULES.n,
typeof = __DARKLUA_BUNDLE_MODULES.i,
TweenInfo = __DARKLUA_BUNDLE_MODULES.V,
Help = function()
return "See https://elttob.uk/Fusion/0.3/ for more information."
end,
})
return Fusion