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