-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathTree.lua
137 lines (107 loc) · 3.68 KB
/
Tree.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
local DELIM = "/"
local function FullNameToPath(instance: Instance): string
return instance:GetFullName():gsub("%.", DELIM)
end
--[=[
@class Tree
]=]
local Tree = {}
--[=[
Similar to FindFirstChild, with a few key differences:
- An error is thrown if the instance is not found
- A path to the instance can be provided, delimited by forward slashes (e.g. `Path/To/Child`)
- Optionally, the instance's type can be asserted using `IsA`
```lua
-- Find "Child" directly under parent:
local instance = Tree.Find(parent, "Child")
-- Find "Child" descendant:
local instance = Tree.Find(parent, "Path/To/Child")
-- Find "Child" descendant and assert that it's a BasePart:
local instance = Tree.Find(parent, "Path/To/Child", "BasePart") :: BasePart
```
]=]
function Tree.Find(parent: Instance, path: string, assertIsA: string?): Instance
local instance = parent
local paths = path:split(DELIM)
for _, p in paths do
-- Error for empty path parts:
if p == "" then
error(`Invalid path: {path}`, 2)
end
instance = instance:FindFirstChild(p)
-- Error if instance is not found:
if instance == nil then
error(`Failed to find {path} in {FullNameToPath(parent)}`, 2)
end
end
-- Assert class type if argument is supplied:
if assertIsA and not instance:IsA(assertIsA) then
error(`Got class {instance.ClassName}; expected to be of type {assertIsA}`, 2)
end
return instance
end
--[=[
Returns `true` if the instance is found. Similar to `Tree.Find`, except this returns `true|false`. No error is thrown unless the path is invalid.
```lua
-- Check if "Child" exists directly in `parent`:
if Tree.Exists(parent, "Child") then ... end
-- Check if "Child" descendant exists at `parent.Path.To.Child`:
if Tree.Exists(parent, "Path/To/Child") then ... end
-- Check if "Child" descendant exists at `parent.Path.To.Child` and is a BasePart:
if Tree.Exists(parent, "Path/To/Child", "BasePart") then ... end
```
]=]
function Tree.Exists(parent: Instance, path: string, assertIsA: string?): boolean
local instance = parent
local paths = path:split(DELIM)
for _, p in paths do
-- Error for empty path parts:
if p == "" then
error(`Invalid path: {path}`, 2)
end
instance = instance:FindFirstChild(p)
if instance == nil then
return false
end
end
if assertIsA and not instance:IsA(assertIsA) then
return false
end
return true
end
--[=[
@yields
Waits for the path to exist within the parent instance. Similar to `Tree.Find`, except `WaitForChild`
is used internally. An optional `timeout` can be supplied, which is passed along to each call to
`WaitForChild`.
An error is thrown if the path fails to resolve. This will only happen if the path is invalid _or_ if
the supplied timeout is reached.
:::caution Indefinite Yield Possible
If the `timeout` parameter is not supplied, then the internal call to `WaitForChild` will yield
indefinitely until the child is found. It is good practice to supply a timeout parameter.
:::
```lua
local child = Tree.Await(parent, "Path/To/Child", 30)
```
]=]
function Tree.Await(parent: Instance, path: string, timeout: number?, assertIsA: string?): Instance
local instance = parent
local paths = path:split(DELIM)
for _, p in paths do
-- Error for empty path parts:
if p == "" then
error(`Invalid path: {path}`, 2)
end
instance = instance:WaitForChild(p, timeout)
-- Error if instance is not found:
if instance == nil then
error(`Failed to await {path} in {FullNameToPath(parent)} (timeout reached)`, 2)
end
end
-- Assert class type if argument is supplied:
if assertIsA and not instance:IsA(assertIsA) then
error(`Got class {instance.ClassName}; expected to be of type {assertIsA}`, 2)
end
return instance
end
return Tree