Skip to content

Instantly share code, notes, and snippets.

@dphfox
Created December 8, 2021 01:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dphfox/453b2357ff3499dbcb10282ec21f276c to your computer and use it in GitHub Desktop.
Save dphfox/453b2357ff3499dbcb10282ec21f276c to your computer and use it in GitHub Desktop.
A possible implementation of cascading values for a future version of Fusion.
local function Cascade<T>(): Cascade
local self = {}
local definedValues: {[Instance]: T} = {}
local definedValueChangeListeners: {[Instance]: (forInstance) -> ()} = {}
local function getCascadedValue(target: Instance): T?
return definedValues[target]
or if target.Parent ~= nil then getNearestDefinedAncestor(target.Parent)
else nil
end
do --self:get()
local cachedCascadedStates: {[Instance]: Computed<T?>} = {}
function self:get(target: Instance): Computed<T?>
local cachedCascadedState = cachedCascadedStates[target]
if cachedCascadedState ~= nil then
return cachedCascadedState
end
local currentValue = Value<T?>(getCascadedValue(target))
local function onDefinedValueChanged(forInstance: Instance)
if forInstance:IsAncestorOf(target) then
currentValue:set(getCascadedValue(target))
end
end
definedValueChangeListeners[target] = onDefinedValueChanged
Hydrate(target) {
[Cleanup] = {
target.AncestryChanged:Connect(function()
currentValue:set(getCascadedValue(target))
end),
function()
definedValueChangeListeners[target] = nil
cachedCascadedStates[target] = nil
currentValue:set(nil)
end
}
}
local cascadedState = Computed<T?>(function()
return currentValue:get()
end)
cachedCascadedStates[target] = cascadedState
return cascadedState
end
end
do -- self:set()
local hasCleanupHandler: {[Instance]: boolean} = {}
function self:set(target: Instance, value: T?)
definedValues[target] = value
if value ~= nil and not hasCleanupHandler[target] then
Hydrate(target) {
[Cleanup] = function()
definedValues[target] = nil
hasCleanupHandler[target] = nil
end
}
hasCleanupHandler[target] = true
end
end
end
return self
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment