local Logging = require(script.Parent.Logging)
local CHANGE_PREFIX = "Change."
local EventStatus = {
Disabled = "Disabled",
Suspended = "Suspended",
Enabled = "Enabled",
}
local SingleEventManager = {}
SingleEventManager.__index = SingleEventManager
function SingleEventManager.new(instance)
local self = setmetatable({
_suspendedEventQueue = {},
_connections = {},
_listeners = {},
_status = EventStatus.Disabled,
_isResuming = false,
_instance = instance,
}, SingleEventManager)
return self
end
function SingleEventManager:connectEvent(key, listener)
self:_connect(key, self._instance[key], listener)
end
function SingleEventManager:connectPropertyChange(key, listener)
local success, event = pcall(function()
return self._instance:GetPropertyChangedSignal(key)
end)
if not success then
error(("Cannot get changed signal on property %q: %s"):format(tostring(key), event), 0)
end
self:_connect(CHANGE_PREFIX .. key, event, listener)
end
function SingleEventManager:_connect(eventKey, event, listener)
if listener == nil then
if self._connections[eventKey] ~= nil then
self._connections[eventKey]:Disconnect()
self._connections[eventKey] = nil
end
self._listeners[eventKey] = nil
else
if self._connections[eventKey] == nil then
self._connections[eventKey] = event:Connect(function(...)
if self._status == EventStatus.Enabled then
self._listeners[eventKey](self._instance, ...)
elseif self._status == EventStatus.Suspended then
local argumentCount = select("#", ...)
table.insert(self._suspendedEventQueue, { eventKey, argumentCount, ... })
end
end)
end
self._listeners[eventKey] = listener
end
end
function SingleEventManager:suspend()
self._status = EventStatus.Suspended
end
function SingleEventManager:resume()
if self._isResuming then
return
end
self._isResuming = true
local index = 1
while index <= #self._suspendedEventQueue do
local eventInvocation = self._suspendedEventQueue[index]
local listener = self._listeners[eventInvocation[1]]
local argumentCount = eventInvocation[2]
if listener ~= nil then
local listenerCo = coroutine.create(listener)
local success, result = coroutine.resume(
listenerCo,
self._instance,
unpack(eventInvocation, 3, 2 + argumentCount)
)
if not success then
Logging.warn("%s", result)
end
end
index = index + 1
end
self._isResuming = false
self._status = EventStatus.Enabled
self._suspendedEventQueue = {}
end
return SingleEventManager