Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ sourcemap.json
build/
node_modules/
out/
package-lock.json
14 changes: 14 additions & 0 deletions docs/Observers/children.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Children

The `observeChildren` observer can be used to observe added and removed children of a given instance. The removed child is passed to the returned callback.

```lua
observeChildren(parent:Instance, function(child:Instance)
print("Child added to parent", child.Name)

return function(child: Instance)
-- Cleanup
print("Child is being removed",child.Name)
end
end)
```
1 change: 1 addition & 0 deletions lib/init.luau
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ return {
observePlayer = require(script.observePlayer),
observeCharacter = require(script.observeCharacter),
observeLocalCharacter = require(script.observeLocalCharacter),
observeChildren = require(script.observeChildren),
}
83 changes: 83 additions & 0 deletions lib/observeChildren.luau
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
--!strict
type Callback = (child: Instance) -> ((removed: Instance) -> ())?

--[=[
@within Observers

Creates an observer that captures each child of a given instance.

The returned callback is called with removed instances. It's called for every child if the observer is disconnected

```lua
observeChildren(parent:Instance, function(child:Instance)
print("Child added to parent", child.Name)

return function(child:Instance)
-- Cleanup
print("Child is being removed",child.Name)
end
end)
```
]=]
local function observeChildren(parent: Instance, callback: Callback): () -> ()
local childAddedConn: RBXScriptConnection
local childRemovedConn: RBXScriptConnection

local cleanupsPerChild: { [Instance]: (child: Instance) -> () } = {}

local function onChildAdded(child: Instance)
if not childAddedConn.Connected then
return
end

task.spawn(function()
local cleanup = (callback)(child)
if typeof(cleanup) == "function" then
if childAddedConn.Connected then
cleanupsPerChild[child] = cleanup
else
task.spawn(cleanup, child)
end
end
end)
end

local function onChildRemoved(child: Instance)
local cleanup = cleanupsPerChild[child]
cleanupsPerChild[child] = nil
if typeof(cleanup) == "function" then
task.spawn(cleanup, child)
end
end

-- Listen for changes:
childAddedConn = parent.ChildAdded:Connect(onChildAdded)
childRemovedConn = parent.ChildRemoved:Connect(onChildRemoved)

-- Initial:
task.defer(function()
if not childAddedConn.Connected then
return
end

for _, child in parent:GetChildren() do
task.spawn(onChildAdded, child)
end
end)

return function()
childAddedConn:Disconnect()
childRemovedConn:Disconnect()

childAddedConn = nil :: any
childRemovedConn = nil :: any

local child = next(cleanupsPerChild)
while child do
onChildRemoved(child)
child = next(cleanupsPerChild)
end
end
end

return observeChildren