@rbxts/app-forge 0.7.2-alpha.1 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -26
- package/out/vide/classes/renders.d.ts +0 -4
- package/out/vide/classes/renders.luau +43 -48
- package/out/vide/classes/rules/exclusiveGroup.luau +15 -22
- package/out/vide/classes/rules/init.luau +13 -17
- package/out/vide/classes/rules/parent.luau +4 -8
- package/out/vide/decorator.d.ts +0 -8
- package/out/vide/decorator.luau +3 -39
- package/out/vide/hooks/useAppContext.luau +1 -5
- package/out/vide/hooks/useEventListener.d.ts +6 -1
- package/out/vide/hooks/useEventListener.luau +13 -7
- package/out/vide/hooks/usePx.d.ts +9 -1
- package/out/vide/hooks/usePx.luau +29 -12
- package/out/vide/index.d.ts +2 -5
- package/out/vide/init.luau +24 -85
- package/package.json +1 -1
- package/out/vide/debug/debugger.d.ts +0 -15
- package/out/vide/debug/debugger.luau +0 -83
- package/out/vide/debug/index.d.ts +0 -3
- package/out/vide/debug/init.luau +0 -8
- package/out/vide/debug/logger.d.ts +0 -5
- package/out/vide/debug/logger.luau +0 -37
package/README.md
CHANGED
|
@@ -32,34 +32,14 @@ If you’ve ever ended up with tangled UI state, duplicated visibility logic, or
|
|
|
32
32
|
|
|
33
33
|
## 📦 Installation
|
|
34
34
|
|
|
35
|
-
### Using **bun**
|
|
36
|
-
|
|
37
35
|
```bash
|
|
38
36
|
bun add @rbxts/app-forge
|
|
39
37
|
```
|
|
40
38
|
|
|
41
|
-
Peer dependencies
|
|
39
|
+
Peer dependencies:
|
|
42
40
|
|
|
43
41
|
```bash
|
|
44
|
-
bun add @rbxts/vide
|
|
45
|
-
# or
|
|
46
|
-
bun add @rbxts/react
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
---
|
|
50
|
-
|
|
51
|
-
### Using **npm**
|
|
52
|
-
|
|
53
|
-
```bash
|
|
54
|
-
npm install @rbxts/app-forge
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
Peer dependencies (choose one renderer):
|
|
58
|
-
|
|
59
|
-
```bash
|
|
60
|
-
npm install @rbxts/vide
|
|
61
|
-
# or
|
|
62
|
-
npm install @rbxts/react
|
|
42
|
+
bun add @rbxts/vide @rbxts/loners-pretty-vide-utils
|
|
63
43
|
```
|
|
64
44
|
|
|
65
45
|
---
|
|
@@ -147,7 +127,9 @@ forge.mount(
|
|
|
147
127
|
ResetOnSpawn={false}
|
|
148
128
|
/>
|
|
149
129
|
),
|
|
150
|
-
|
|
130
|
+
{
|
|
131
|
+
props,
|
|
132
|
+
},
|
|
151
133
|
Players.LocalPlayer.WaitForChild("PlayerGui"),
|
|
152
134
|
);
|
|
153
135
|
```
|
|
@@ -175,7 +157,9 @@ forge.mount(
|
|
|
175
157
|
ResetOnSpawn={false}
|
|
176
158
|
/>
|
|
177
159
|
),
|
|
178
|
-
|
|
160
|
+
{
|
|
161
|
+
props,
|
|
162
|
+
},
|
|
179
163
|
Players.LocalPlayer.WaitForChild("PlayerGui"),
|
|
180
164
|
);
|
|
181
165
|
```
|
|
@@ -193,7 +177,9 @@ This:
|
|
|
193
177
|
```ts
|
|
194
178
|
forge.mount(
|
|
195
179
|
() => <screengui ResetOnSpawn={false} />,
|
|
196
|
-
|
|
180
|
+
{
|
|
181
|
+
props: {},
|
|
182
|
+
},
|
|
197
183
|
playerGui,
|
|
198
184
|
);
|
|
199
185
|
```
|
|
@@ -366,6 +352,7 @@ AppForge provides `forge.story` for **isolated rendering**, commonly used with *
|
|
|
366
352
|
const forge = new CreateVideForge();
|
|
367
353
|
|
|
368
354
|
return forge.story({
|
|
355
|
+
forge,
|
|
369
356
|
props,
|
|
370
357
|
config: {
|
|
371
358
|
px: {
|
|
@@ -443,7 +430,7 @@ AppForge
|
|
|
443
430
|
|
|
444
431
|
## ⚛️ React Support (Planned)
|
|
445
432
|
|
|
446
|
-
AppForge is designed as a **renderer-agnostic App Manager**.
|
|
433
|
+
AppForge is designed as a **renderer-agnostic App Manager**.
|
|
447
434
|
|
|
448
435
|
Currently:
|
|
449
436
|
|
|
@@ -8,10 +8,6 @@ export default class Renders extends Rules {
|
|
|
8
8
|
render: Vide.Node;
|
|
9
9
|
}>;
|
|
10
10
|
constructor();
|
|
11
|
-
/**
|
|
12
|
-
* Entry point for mounting renders.
|
|
13
|
-
* Decides render strategy based on props.
|
|
14
|
-
*/
|
|
15
11
|
protected renderMount(this: AppForge, props: Types.Props.Main): Vide.Node;
|
|
16
12
|
private renderNames;
|
|
17
13
|
private collectByGroup;
|
|
@@ -35,28 +35,22 @@ do
|
|
|
35
35
|
local render = _binding.render
|
|
36
36
|
local forge = _binding.forge
|
|
37
37
|
if not forge.__px then
|
|
38
|
-
local _debug = forge.debug
|
|
39
38
|
local _result = config
|
|
40
39
|
if _result ~= nil then
|
|
41
|
-
_result = _result.px
|
|
40
|
+
_result = _result.px.target
|
|
42
41
|
end
|
|
43
|
-
_debug:logTag("px", "global", "Initializing px scaling", _result)
|
|
44
42
|
local _result_1 = config
|
|
45
43
|
if _result_1 ~= nil then
|
|
46
|
-
_result_1 = _result_1.px.
|
|
44
|
+
_result_1 = _result_1.px.resolution
|
|
47
45
|
end
|
|
48
46
|
local _result_2 = config
|
|
49
47
|
if _result_2 ~= nil then
|
|
50
|
-
_result_2 = _result_2.px.
|
|
48
|
+
_result_2 = _result_2.px.minScale
|
|
51
49
|
end
|
|
52
|
-
|
|
53
|
-
if _result_3 ~= nil then
|
|
54
|
-
_result_3 = _result_3.px.minScale
|
|
55
|
-
end
|
|
56
|
-
usePx(_result_1, _result_2, _result_3)
|
|
50
|
+
usePx(_result, _result_1, _result_2)
|
|
57
51
|
forge.__px = true
|
|
58
52
|
else
|
|
59
|
-
|
|
53
|
+
warn("Rendering twice making a second px")
|
|
60
54
|
end
|
|
61
55
|
if render then
|
|
62
56
|
local _condition = render.name
|
|
@@ -64,35 +58,34 @@ do
|
|
|
64
58
|
_condition = render.group
|
|
65
59
|
end
|
|
66
60
|
if _condition ~= "" and _condition then
|
|
67
|
-
forge.debug:logTag("render", "global", "Rendering group by name", render)
|
|
68
61
|
return forge:renderGroupByName(props)
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
62
|
+
else
|
|
63
|
+
local _value = render.names and render.group
|
|
64
|
+
if _value ~= "" and _value then
|
|
65
|
+
return forge:renderGroupByNames(props)
|
|
66
|
+
else
|
|
67
|
+
local _result = render
|
|
68
|
+
if _result ~= nil then
|
|
69
|
+
_result = _result.name
|
|
70
|
+
end
|
|
71
|
+
if _result ~= "" and _result then
|
|
72
|
+
return forge:renderApp(props)
|
|
73
|
+
elseif render.names then
|
|
74
|
+
return forge:renderApps(props)
|
|
75
|
+
else
|
|
76
|
+
local _value_1 = render.group
|
|
77
|
+
if _value_1 ~= "" and _value_1 then
|
|
78
|
+
return forge:renderGroup(props)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
88
82
|
end
|
|
89
83
|
end
|
|
90
|
-
forge.debug:logTag("render", "global", "Rendering all apps")
|
|
91
84
|
return self:renderAll(props)
|
|
92
85
|
end
|
|
93
86
|
function Renders:renderNames(props, names, forge)
|
|
94
87
|
if #names == 0 then
|
|
95
|
-
error("No app names provided to
|
|
88
|
+
error("No app names provided to renderApps")
|
|
96
89
|
end
|
|
97
90
|
-- ▼ ReadonlyArray.map ▼
|
|
98
91
|
local _newValue = table.create(#names)
|
|
@@ -148,21 +141,22 @@ do
|
|
|
148
141
|
return _result
|
|
149
142
|
end
|
|
150
143
|
function Renders:renderApp(props)
|
|
151
|
-
local
|
|
144
|
+
local _binding = props
|
|
145
|
+
local forge = _binding.forge
|
|
146
|
+
local render = _binding.render
|
|
147
|
+
local _name = render
|
|
152
148
|
if _name ~= nil then
|
|
153
149
|
_name = _name.name
|
|
154
150
|
end
|
|
155
151
|
local name = _name
|
|
156
152
|
if not (name ~= "" and name) then
|
|
157
|
-
error("
|
|
153
|
+
error("App name is required to create instance")
|
|
158
154
|
end
|
|
159
155
|
local appClass = AppRegistry[name]
|
|
160
156
|
if not appClass then
|
|
161
|
-
error(`App "{name}" not registered
|
|
157
|
+
error(`App "{name}" not registered`)
|
|
162
158
|
end
|
|
163
|
-
|
|
164
|
-
if not (self.loaded[name] ~= nil) then
|
|
165
|
-
self.debug:logTag("render", name, "Creating render instance")
|
|
159
|
+
if not (forge.loaded[name] ~= nil) then
|
|
166
160
|
local render = appClass.constructor.new(props, name):render()
|
|
167
161
|
apply(render)({
|
|
168
162
|
Name = "Render",
|
|
@@ -175,18 +169,19 @@ do
|
|
|
175
169
|
Size = UDim2.fromScale(1, 1),
|
|
176
170
|
[0] = render,
|
|
177
171
|
})
|
|
178
|
-
local _loaded =
|
|
172
|
+
local _loaded = forge.loaded
|
|
179
173
|
local _arg1 = {
|
|
180
174
|
container = container,
|
|
181
175
|
render = render,
|
|
182
176
|
}
|
|
183
177
|
_loaded[name] = _arg1
|
|
184
|
-
|
|
185
|
-
|
|
178
|
+
end
|
|
179
|
+
local element = forge.loaded[name]
|
|
180
|
+
if not element then
|
|
181
|
+
error(`Failed to create instance for app "{name}"`)
|
|
186
182
|
end
|
|
187
183
|
self:renderRules(name, props)
|
|
188
|
-
|
|
189
|
-
return self.loaded[name].container
|
|
184
|
+
return element.container
|
|
190
185
|
end
|
|
191
186
|
function Renders:renderApps(props)
|
|
192
187
|
local _names = props.render
|
|
@@ -195,7 +190,7 @@ do
|
|
|
195
190
|
end
|
|
196
191
|
local names = _names
|
|
197
192
|
if not names then
|
|
198
|
-
error("
|
|
193
|
+
error("No app names provided")
|
|
199
194
|
end
|
|
200
195
|
return self:renderNames(props, names, self)
|
|
201
196
|
end
|
|
@@ -206,7 +201,7 @@ do
|
|
|
206
201
|
end
|
|
207
202
|
local group = _group
|
|
208
203
|
if not (group ~= "" and group) then
|
|
209
|
-
error("
|
|
204
|
+
error("No group provided")
|
|
210
205
|
end
|
|
211
206
|
local groups = self:normalizeGroups(group)
|
|
212
207
|
return self:renderNames(props, self:collectByGroup(groups), self)
|
|
@@ -216,7 +211,7 @@ do
|
|
|
216
211
|
local group = _binding.group
|
|
217
212
|
local name = _binding.name
|
|
218
213
|
if not (group ~= "" and group) or not (name ~= "" and name) then
|
|
219
|
-
error("Invalid renderGroupByName
|
|
214
|
+
error("Invalid renderGroupByName")
|
|
220
215
|
end
|
|
221
216
|
local groups = self:normalizeGroups(group)
|
|
222
217
|
return self:renderNames(props, self:collectByGroup(groups, function(n)
|
|
@@ -228,7 +223,7 @@ do
|
|
|
228
223
|
local group = _binding.group
|
|
229
224
|
local names = _binding.names
|
|
230
225
|
if not (group ~= "" and group) or not names then
|
|
231
|
-
error("Invalid renderGroupByNames
|
|
226
|
+
error("Invalid renderGroupByNames")
|
|
232
227
|
end
|
|
233
228
|
local groups = self:normalizeGroups(group)
|
|
234
229
|
return self:renderNames(props, self:collectByGroup(groups, function(n)
|
|
@@ -6,43 +6,36 @@ local AppRegistry = TS.import(script, script.Parent.Parent.Parent, "decorator").
|
|
|
6
6
|
local function ExclusiveGroupRule(entry, forge)
|
|
7
7
|
local _entry = entry
|
|
8
8
|
local entryApp = AppRegistry[_entry]
|
|
9
|
-
local
|
|
10
|
-
if
|
|
11
|
-
|
|
12
|
-
if
|
|
13
|
-
|
|
9
|
+
local _result = entryApp
|
|
10
|
+
if _result ~= nil then
|
|
11
|
+
_result = _result.rules
|
|
12
|
+
if _result ~= nil then
|
|
13
|
+
_result = _result.exclusiveGroup
|
|
14
14
|
end
|
|
15
15
|
end
|
|
16
|
-
|
|
17
|
-
if not (group ~= "" and group) then
|
|
16
|
+
if not (_result ~= "" and _result) then
|
|
18
17
|
return nil
|
|
19
18
|
end
|
|
20
|
-
local
|
|
21
|
-
|
|
19
|
+
local group = entryApp.rules.exclusiveGroup
|
|
20
|
+
local entrySource = forge:getSource(entry)()
|
|
21
|
+
if not entrySource then
|
|
22
22
|
return nil
|
|
23
23
|
end
|
|
24
|
-
forge.debug:logTag("rules", entry, "Exclusive group activated", group)
|
|
25
24
|
-- ▼ ReadonlyMap.forEach ▼
|
|
26
25
|
local _callback = function(app, name)
|
|
27
26
|
if name == entry then
|
|
28
27
|
return nil
|
|
29
28
|
end
|
|
30
|
-
local
|
|
31
|
-
if
|
|
32
|
-
|
|
29
|
+
local _result_1 = app.rules
|
|
30
|
+
if _result_1 ~= nil then
|
|
31
|
+
_result_1 = _result_1.exclusiveGroup
|
|
33
32
|
end
|
|
34
|
-
if
|
|
33
|
+
if _result_1 ~= group then
|
|
35
34
|
return nil
|
|
36
35
|
end
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
return nil
|
|
36
|
+
if forge:getSource(name)() then
|
|
37
|
+
forge:close(name, false)
|
|
40
38
|
end
|
|
41
|
-
forge.debug:logTag("rules", entry, "Closing app due to exclusive group", {
|
|
42
|
-
closed = name,
|
|
43
|
-
group = group,
|
|
44
|
-
})
|
|
45
|
-
forge:close(name, false)
|
|
46
39
|
end
|
|
47
40
|
for _k, _v in AppRegistry do
|
|
48
41
|
_callback(_v, _k, AppRegistry)
|
|
@@ -25,40 +25,36 @@ do
|
|
|
25
25
|
local _name = name
|
|
26
26
|
local appClass = AppRegistry[_name]
|
|
27
27
|
if not appClass then
|
|
28
|
-
error(`
|
|
28
|
+
error(`Failed to get class for app: {name} for renderRules`)
|
|
29
29
|
end
|
|
30
|
-
local
|
|
31
|
-
if
|
|
32
|
-
|
|
30
|
+
local _result = appClass.rules
|
|
31
|
+
if _result ~= nil then
|
|
32
|
+
_result = _result.parent
|
|
33
33
|
end
|
|
34
|
-
|
|
35
|
-
local _condition = rules.parent
|
|
34
|
+
local _condition = _result
|
|
36
35
|
if _condition ~= "" and _condition then
|
|
37
|
-
_condition = not rules.detach
|
|
36
|
+
_condition = not appClass.rules.detach
|
|
38
37
|
end
|
|
39
38
|
if _condition ~= "" and _condition then
|
|
40
|
-
self
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
39
|
+
self:anchor(name, appClass.rules.parent, props)
|
|
40
|
+
end
|
|
41
|
+
local _result_1 = appClass.rules
|
|
42
|
+
if _result_1 ~= nil then
|
|
43
|
+
_result_1 = _result_1.index
|
|
44
44
|
end
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
self.debug:logTag("rules", name, "Applying ZIndex", rules.index)
|
|
48
|
-
self:index(name, rules.index)
|
|
45
|
+
if _result_1 ~= 0 and _result_1 == _result_1 and _result_1 then
|
|
46
|
+
self:index(name, appClass.rules.index)
|
|
49
47
|
end
|
|
50
48
|
end
|
|
51
49
|
function Rules:checkRules(name)
|
|
52
50
|
local _processing = self.processing
|
|
53
51
|
local _name = name
|
|
54
52
|
if _processing[_name] ~= nil then
|
|
55
|
-
self.debug:logTag("rules", name, "Skipped rule processing (cycle detected)")
|
|
56
53
|
return nil
|
|
57
54
|
end
|
|
58
55
|
local _processing_1 = self.processing
|
|
59
56
|
local _name_1 = name
|
|
60
57
|
_processing_1[_name_1] = true
|
|
61
|
-
self.debug:logTag("rules", name, "Evaluating rules")
|
|
62
58
|
TS.try(function()
|
|
63
59
|
ParentRule(name, self)
|
|
64
60
|
ExclusiveGroupRule(name, self)
|
|
@@ -4,7 +4,7 @@ local TS = _G[script]
|
|
|
4
4
|
-- Components
|
|
5
5
|
local AppRegistry = TS.import(script, script.Parent.Parent.Parent, "decorator").AppRegistry
|
|
6
6
|
local function ParentRule(entry, forge)
|
|
7
|
-
local
|
|
7
|
+
local entrySource = forge:getSource(entry)()
|
|
8
8
|
-- ▼ ReadonlyMap.forEach ▼
|
|
9
9
|
local _callback = function(app, name)
|
|
10
10
|
local rules = app.rules
|
|
@@ -14,14 +14,10 @@ local function ParentRule(entry, forge)
|
|
|
14
14
|
if name == entry then
|
|
15
15
|
return nil
|
|
16
16
|
end
|
|
17
|
-
local
|
|
18
|
-
if
|
|
19
|
-
|
|
17
|
+
local childSource = forge:getSource(name)()
|
|
18
|
+
if not entrySource and childSource then
|
|
19
|
+
forge:close(name, false)
|
|
20
20
|
end
|
|
21
|
-
forge.debug:logTag("rules", entry, "Closing child app (parent closed)", {
|
|
22
|
-
child = name,
|
|
23
|
-
})
|
|
24
|
-
forge:close(name, false)
|
|
25
21
|
end
|
|
26
22
|
for _k, _v in AppRegistry do
|
|
27
23
|
_callback(_v, _k, AppRegistry)
|
package/out/vide/decorator.d.ts
CHANGED
|
@@ -2,15 +2,7 @@ import Vide from "@rbxts/vide";
|
|
|
2
2
|
import type Types from "./types";
|
|
3
3
|
import type AppForge from ".";
|
|
4
4
|
export declare const AppRegistry: Map<string, Types.AppRegistry.Static>;
|
|
5
|
-
/**
|
|
6
|
-
* Registers a Vide App with AppForge.
|
|
7
|
-
*
|
|
8
|
-
* This runs at definition time and validates static configuration.
|
|
9
|
-
*/
|
|
10
5
|
export declare function App<N extends AppNames>(props: Types.AppRegistry.Props<N>): <T extends new (props: Types.Props.Main, name: AppNames) => Args>(constructor: T) => T;
|
|
11
|
-
/**
|
|
12
|
-
* Base class for all AppForge Apps.
|
|
13
|
-
*/
|
|
14
6
|
export declare abstract class Args {
|
|
15
7
|
readonly forge: AppForge;
|
|
16
8
|
readonly props: Types.Props.Class;
|
package/out/vide/decorator.luau
CHANGED
|
@@ -4,37 +4,13 @@ local TS = _G[script]
|
|
|
4
4
|
-- Types
|
|
5
5
|
-- Hooks
|
|
6
6
|
local px = TS.import(script, script.Parent, "hooks", "usePx").px
|
|
7
|
-
-- Debug
|
|
8
|
-
local Logger = TS.import(script, script.Parent, "debug", "logger").default
|
|
9
|
-
local logger = Logger.new("AppRegistry")
|
|
10
7
|
local AppRegistry = {}
|
|
11
|
-
--[[
|
|
12
|
-
*
|
|
13
|
-
* Registers a Vide App with AppForge.
|
|
14
|
-
*
|
|
15
|
-
* This runs at definition time and validates static configuration.
|
|
16
|
-
|
|
17
|
-
]]
|
|
18
8
|
local function App(props)
|
|
19
9
|
return function(constructor)
|
|
20
10
|
local _name = props.name
|
|
21
11
|
if AppRegistry[_name] ~= nil then
|
|
22
|
-
|
|
23
|
-
name = props.name,
|
|
24
|
-
})
|
|
25
|
-
error(`Duplicate registered App name "{props.name}". ` .. `App names must be globally unique.`, 2)
|
|
12
|
+
error(`Duplicate registered App name "{props.name}"`)
|
|
26
13
|
end
|
|
27
|
-
local _value = props.name
|
|
28
|
-
if not (_value ~= "" and _value) then
|
|
29
|
-
logger:log("ERROR", "Attempted to register App without a name", props)
|
|
30
|
-
error("App registration failed: missing app name", 2)
|
|
31
|
-
end
|
|
32
|
-
logger:log("DEBUG", "Registering App", {
|
|
33
|
-
name = props.name,
|
|
34
|
-
renderGroup = props.renderGroup,
|
|
35
|
-
visible = props.visible,
|
|
36
|
-
rules = props.rules,
|
|
37
|
-
})
|
|
38
14
|
local _name_1 = props.name
|
|
39
15
|
local _arg1 = {
|
|
40
16
|
constructor = constructor,
|
|
@@ -46,11 +22,6 @@ local function App(props)
|
|
|
46
22
|
return constructor
|
|
47
23
|
end
|
|
48
24
|
end
|
|
49
|
-
--[[
|
|
50
|
-
*
|
|
51
|
-
* Base class for all AppForge Apps.
|
|
52
|
-
|
|
53
|
-
]]
|
|
54
25
|
local Args
|
|
55
26
|
do
|
|
56
27
|
Args = {}
|
|
@@ -58,20 +29,13 @@ do
|
|
|
58
29
|
local _binding = props
|
|
59
30
|
local forge = _binding.forge
|
|
60
31
|
self.forge = forge
|
|
61
|
-
self.name = name
|
|
62
32
|
local _object = table.clone(props.props)
|
|
63
33
|
setmetatable(_object, nil)
|
|
64
34
|
_object.px = px
|
|
65
35
|
_object.forge = forge
|
|
66
36
|
self.props = _object
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
logger:log("ERROR", "Missing visibility source for App", {
|
|
70
|
-
name = name,
|
|
71
|
-
})
|
|
72
|
-
error(`Failed to retrieve visibility source for app "{name}"`, 2)
|
|
73
|
-
end
|
|
74
|
-
self.source = src
|
|
37
|
+
self.name = name
|
|
38
|
+
self.source = forge:getSource(name)
|
|
75
39
|
end
|
|
76
40
|
end
|
|
77
41
|
return {
|
|
@@ -2,14 +2,10 @@
|
|
|
2
2
|
local TS = _G[script]
|
|
3
3
|
-- Components
|
|
4
4
|
local Contexts = TS.import(script, script.Parent.Parent, "context").default
|
|
5
|
-
-- Debug
|
|
6
|
-
local Logger = TS.import(script, script.Parent.Parent, "debug", "logger").default
|
|
7
|
-
local logger = Logger.new("useAppContext")
|
|
8
5
|
local default = function()
|
|
9
6
|
local context = Contexts.App()
|
|
10
7
|
if not context then
|
|
11
|
-
|
|
12
|
-
error(`Failed to retrieve App Props for Vide\n{debug.traceback()}`, 2)
|
|
8
|
+
error(`Failed to retrieve App Props for Vide {debug.traceback()}`)
|
|
13
9
|
end
|
|
14
10
|
return context
|
|
15
11
|
end
|
|
@@ -11,7 +11,12 @@ type ConnectionLike = {
|
|
|
11
11
|
disconnect(): void;
|
|
12
12
|
} | (() => void);
|
|
13
13
|
/**
|
|
14
|
-
* Subscribes to an event-like object
|
|
14
|
+
* Subscribes to an event-like object. The subscription is automatically
|
|
15
|
+
* disconnected when the scope cleans up.
|
|
16
|
+
*
|
|
17
|
+
* @param event The event-like object to subscribe to.
|
|
18
|
+
* @param listener The listener to subscribe with.
|
|
19
|
+
* @returns The connection object.
|
|
15
20
|
*/
|
|
16
21
|
export declare function useEventListener<T extends EventLike>(event: T, listener: T extends EventLike<infer U> ? U : never): ReturnType<T>;
|
|
17
22
|
export {};
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
-- Compiled with roblox-ts v3.0.0
|
|
2
2
|
local TS = _G[script]
|
|
3
3
|
local cleanup = TS.import(script, TS.getModule(script, "@rbxts", "vide").src).cleanup
|
|
4
|
-
-- Debug
|
|
5
|
-
local Logger = TS.import(script, script.Parent.Parent, "debug", "logger").default
|
|
6
|
-
local logger = Logger.new("useEventListener")
|
|
7
4
|
local connect = function(event, callback)
|
|
8
5
|
local _event = event
|
|
9
6
|
if typeof(_event) == "RBXScriptSignal" then
|
|
7
|
+
-- With deferred events, a "hard disconnect" is necessary to avoid causing
|
|
8
|
+
-- state updates after a component unmounts. Use 'Connected' to check if
|
|
9
|
+
-- the connection is still valid before invoking the callback.
|
|
10
|
+
-- https://devforum.roblox.com/t/deferred-engine-events/2276564/99
|
|
10
11
|
local connection
|
|
11
12
|
connection = event:Connect(function(...)
|
|
12
13
|
local args = { ... }
|
|
@@ -21,9 +22,9 @@ local connect = function(event, callback)
|
|
|
21
22
|
return event:connect(callback)
|
|
22
23
|
elseif event.subscribe ~= nil then
|
|
23
24
|
return event:subscribe(callback)
|
|
25
|
+
else
|
|
26
|
+
error("Event-like object does not have a supported connect method.")
|
|
24
27
|
end
|
|
25
|
-
logger:log("ERROR", "Unsupported event-like object", event)
|
|
26
|
-
error("Event-like object does not have a supported connect method.", 2)
|
|
27
28
|
end
|
|
28
29
|
local disconnect = function(connection)
|
|
29
30
|
local _connection = connection
|
|
@@ -40,13 +41,18 @@ local disconnect = function(connection)
|
|
|
40
41
|
elseif connection.disconnect ~= nil then
|
|
41
42
|
connection:disconnect()
|
|
42
43
|
else
|
|
43
|
-
|
|
44
|
+
error("Connection-like object does not have a supported disconnect method.")
|
|
44
45
|
end
|
|
45
46
|
end
|
|
46
47
|
end
|
|
47
48
|
--[[
|
|
48
49
|
*
|
|
49
|
-
* Subscribes to an event-like object
|
|
50
|
+
* Subscribes to an event-like object. The subscription is automatically
|
|
51
|
+
* disconnected when the scope cleans up.
|
|
52
|
+
*
|
|
53
|
+
* @param event The event-like object to subscribe to.
|
|
54
|
+
* @param listener The listener to subscribe with.
|
|
55
|
+
* @returns The connection object.
|
|
50
56
|
|
|
51
57
|
]]
|
|
52
58
|
local function useEventListener(event, listener)
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scaled pixel unit helper.
|
|
3
|
+
*
|
|
4
|
+
* - `px(12)` → rounded scaled pixels
|
|
5
|
+
* - `px.scale(12)` → raw scaled value
|
|
6
|
+
* - `px.even(12)` → even pixel values (useful for strokes/borders)
|
|
7
|
+
*/
|
|
1
8
|
export declare const px: ((value: number) => number) & {
|
|
2
9
|
scale: (value: number) => number;
|
|
3
10
|
even: (value: number) => number;
|
|
@@ -6,6 +13,7 @@ export declare const px: ((value: number) => number) & {
|
|
|
6
13
|
};
|
|
7
14
|
/**
|
|
8
15
|
* Initializes global px scaling.
|
|
9
|
-
*
|
|
16
|
+
*
|
|
17
|
+
* Should be called exactly once at app mount.
|
|
10
18
|
*/
|
|
11
19
|
export declare function usePx(target?: GuiObject | Camera, baseResolution?: Vector2, minScale?: number): void;
|
|
@@ -6,18 +6,25 @@ local Workspace = TS.import(script, TS.getModule(script, "@rbxts", "services")).
|
|
|
6
6
|
local source = TS.import(script, TS.getModule(script, "@rbxts", "vide").src).source
|
|
7
7
|
-- Helpers
|
|
8
8
|
local useEventListener = TS.import(script, script.Parent, "useEventListener").useEventListener
|
|
9
|
-
-- Debug
|
|
10
|
-
local Logger = TS.import(script, script.Parent.Parent, "debug", "logger").default
|
|
11
|
-
local logger = Logger.new("usePx")
|
|
12
9
|
--* Default reference resolution for px calculations
|
|
13
10
|
local BASE_RESOLUTION = source(Vector2.new(1920, 1080))
|
|
14
11
|
--* Minimum allowed scale to prevent unreadable UI
|
|
15
12
|
local MIN_SCALE = source(0.5)
|
|
16
|
-
|
|
13
|
+
--[[
|
|
14
|
+
*
|
|
15
|
+
* Interpolates between width- and height-based scaling.
|
|
16
|
+
* 0 = width-driven, 1 = height-driven
|
|
17
|
+
|
|
18
|
+
]]
|
|
17
19
|
local DOMINANT_AXIS = 0.5
|
|
18
20
|
local TARGET = source(Workspace.CurrentCamera)
|
|
19
21
|
local SCALE = source(1)
|
|
20
22
|
local INITIALIZED = false
|
|
23
|
+
--[[
|
|
24
|
+
*
|
|
25
|
+
* Assigns a call signature to an object.
|
|
26
|
+
|
|
27
|
+
]]
|
|
21
28
|
local function callable(callback, object)
|
|
22
29
|
return setmetatable(object, {
|
|
23
30
|
__call = function(_, ...)
|
|
@@ -26,6 +33,15 @@ local function callable(callback, object)
|
|
|
26
33
|
end,
|
|
27
34
|
})
|
|
28
35
|
end
|
|
36
|
+
--[[
|
|
37
|
+
*
|
|
38
|
+
* Scaled pixel unit helper.
|
|
39
|
+
*
|
|
40
|
+
* - `px(12)` → rounded scaled pixels
|
|
41
|
+
* - `px.scale(12)` → raw scaled value
|
|
42
|
+
* - `px.even(12)` → even pixel values (useful for strokes/borders)
|
|
43
|
+
|
|
44
|
+
]]
|
|
29
45
|
local px = callable(function(value)
|
|
30
46
|
return math.round(value * SCALE())
|
|
31
47
|
end, {
|
|
@@ -42,6 +58,11 @@ end, {
|
|
|
42
58
|
return math.ceil(value * SCALE())
|
|
43
59
|
end,
|
|
44
60
|
})
|
|
61
|
+
--[[
|
|
62
|
+
*
|
|
63
|
+
* Recalculates the current scale factor based on the target size.
|
|
64
|
+
|
|
65
|
+
]]
|
|
45
66
|
local function calculateScale()
|
|
46
67
|
local target = TARGET()
|
|
47
68
|
if not target then
|
|
@@ -65,20 +86,16 @@ end
|
|
|
65
86
|
--[[
|
|
66
87
|
*
|
|
67
88
|
* Initializes global px scaling.
|
|
68
|
-
*
|
|
89
|
+
*
|
|
90
|
+
* Should be called exactly once at app mount.
|
|
69
91
|
|
|
70
92
|
]]
|
|
71
93
|
local function usePx(target, baseResolution, minScale)
|
|
72
94
|
if INITIALIZED then
|
|
73
|
-
|
|
95
|
+
warn("usePx() may only be called once")
|
|
74
96
|
return nil
|
|
75
97
|
end
|
|
76
98
|
INITIALIZED = true
|
|
77
|
-
logger:log("DEBUG", "Initializing px scaling", {
|
|
78
|
-
target = target,
|
|
79
|
-
baseResolution = baseResolution,
|
|
80
|
-
minScale = minScale,
|
|
81
|
-
})
|
|
82
99
|
if baseResolution then
|
|
83
100
|
BASE_RESOLUTION(baseResolution)
|
|
84
101
|
end
|
|
@@ -90,7 +107,7 @@ local function usePx(target, baseResolution, minScale)
|
|
|
90
107
|
end
|
|
91
108
|
local resolvedTarget = TARGET()
|
|
92
109
|
if not resolvedTarget then
|
|
93
|
-
|
|
110
|
+
warn("usePx(): no valid target to observe")
|
|
94
111
|
return nil
|
|
95
112
|
end
|
|
96
113
|
local signal = if resolvedTarget:IsA("Camera") then resolvedTarget:GetPropertyChangedSignal("ViewportSize") else resolvedTarget:GetPropertyChangedSignal("AbsoluteSize")
|
package/out/vide/index.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import Vide from "@rbxts/vide";
|
|
2
2
|
import Renders from "./classes/renders";
|
|
3
3
|
import Types from "./types";
|
|
4
|
-
import { Logger, Debugger } from "./debug";
|
|
5
4
|
type Destructor = () => void;
|
|
6
5
|
type Loaded = {
|
|
7
6
|
container: Vide.Node;
|
|
@@ -9,19 +8,17 @@ type Loaded = {
|
|
|
9
8
|
anchor?: Vide.Node;
|
|
10
9
|
};
|
|
11
10
|
export default class AppForge extends Renders {
|
|
12
|
-
readonly logger: Logger;
|
|
13
|
-
readonly debug: Debugger;
|
|
14
11
|
protected sources: Map<string, Vide.Source<boolean>>;
|
|
15
12
|
protected loaded: Map<string, Loaded>;
|
|
16
13
|
protected innerMount?: Destructor;
|
|
17
14
|
protected __px: boolean;
|
|
18
15
|
constructor();
|
|
19
|
-
protected createSource(name: AppNames):
|
|
20
|
-
getSource(name: AppNames): Vide.Source<boolean>;
|
|
16
|
+
protected createSource(name: AppNames): typeof Vide.source | undefined;
|
|
21
17
|
isLoaded(name: AppNames): boolean;
|
|
22
18
|
bind(name: AppNames, value: Vide.Source<boolean>): void;
|
|
23
19
|
anchor(name: AppNames, anchorName: AppNames, props: Types.Props.Main): void;
|
|
24
20
|
index(name: AppNames, index: number): void;
|
|
21
|
+
getSource(name: AppNames): Vide.Source<boolean>;
|
|
25
22
|
set(name: AppNames, value: boolean, rules?: boolean): void;
|
|
26
23
|
open(name: AppNames, rules?: boolean): void;
|
|
27
24
|
close(name: AppNames, rules?: boolean): void;
|
package/out/vide/init.luau
CHANGED
|
@@ -14,10 +14,6 @@ local untrack = _vide.untrack
|
|
|
14
14
|
local Renders = TS.import(script, script, "classes", "renders").default
|
|
15
15
|
-- Helpers
|
|
16
16
|
local AppRegistry = TS.import(script, script, "decorator").AppRegistry
|
|
17
|
-
-- Debug
|
|
18
|
-
local _debug = TS.import(script, script, "debug")
|
|
19
|
-
local Logger = _debug.Logger
|
|
20
|
-
local Debugger = _debug.Debugger
|
|
21
17
|
local AppForge
|
|
22
18
|
do
|
|
23
19
|
local super = Renders
|
|
@@ -34,10 +30,6 @@ do
|
|
|
34
30
|
end
|
|
35
31
|
function AppForge:constructor()
|
|
36
32
|
super.constructor(self)
|
|
37
|
-
self.logger = Logger.new("AppForge")
|
|
38
|
-
self.debug = Debugger.new(function(level, msg, data, trace)
|
|
39
|
-
return self.logger:log(level, msg, data, trace)
|
|
40
|
-
end)
|
|
41
33
|
self.sources = {}
|
|
42
34
|
self.loaded = {}
|
|
43
35
|
self.__px = false
|
|
@@ -54,48 +46,22 @@ do
|
|
|
54
46
|
local _name = name
|
|
55
47
|
local app = AppRegistry[_name]
|
|
56
48
|
if not app then
|
|
57
|
-
|
|
58
|
-
name = name,
|
|
59
|
-
})
|
|
60
|
-
return nil
|
|
49
|
+
error(`App "{name}" not registered`)
|
|
61
50
|
end
|
|
62
51
|
local _sources = self.sources
|
|
63
52
|
local _name_1 = name
|
|
64
53
|
if _sources[_name_1] ~= nil then
|
|
65
54
|
return nil
|
|
66
55
|
end
|
|
67
|
-
local
|
|
56
|
+
local _sources_1 = self.sources
|
|
68
57
|
local _exp = name
|
|
69
|
-
local _object = {}
|
|
70
|
-
local _left = "default"
|
|
71
58
|
local _condition = app.visible
|
|
72
59
|
if _condition == nil then
|
|
73
60
|
_condition = false
|
|
74
61
|
end
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
local _exp_1 = name
|
|
79
|
-
local _condition_1 = app.visible
|
|
80
|
-
if _condition_1 == nil then
|
|
81
|
-
_condition_1 = false
|
|
82
|
-
end
|
|
83
|
-
local _arg1 = source(_condition_1)
|
|
84
|
-
_sources_1[_exp_1] = _arg1
|
|
85
|
-
end
|
|
86
|
-
function AppForge:getSource(name)
|
|
87
|
-
local _sources = self.sources
|
|
88
|
-
local _name = name
|
|
89
|
-
if not (_sources[_name] ~= nil) then
|
|
90
|
-
self:createSource(name)
|
|
91
|
-
end
|
|
92
|
-
local _sources_1 = self.sources
|
|
93
|
-
local _name_1 = name
|
|
94
|
-
local src = _sources_1[_name_1]
|
|
95
|
-
if not src then
|
|
96
|
-
error(`AppForge invariant broken: missing visibility source for {name}`, 2)
|
|
97
|
-
end
|
|
98
|
-
return src
|
|
62
|
+
local _arg1 = source(_condition)
|
|
63
|
+
_sources_1[_exp] = _arg1
|
|
64
|
+
return source
|
|
99
65
|
end
|
|
100
66
|
function AppForge:isLoaded(name)
|
|
101
67
|
local _loaded = self.loaded
|
|
@@ -104,7 +70,6 @@ do
|
|
|
104
70
|
end
|
|
105
71
|
function AppForge:bind(name, value)
|
|
106
72
|
if not RunService:IsRunning() then
|
|
107
|
-
self.debug:logTag("state", name, "Binding external visibility source")
|
|
108
73
|
local _sources = self.sources
|
|
109
74
|
local _name = name
|
|
110
75
|
local _value = value
|
|
@@ -116,26 +81,17 @@ do
|
|
|
116
81
|
end)
|
|
117
82
|
end)
|
|
118
83
|
else
|
|
119
|
-
|
|
120
|
-
name = name,
|
|
121
|
-
})
|
|
84
|
+
warn("forge.bind is used for studio when game isnt running")
|
|
122
85
|
end
|
|
123
86
|
end
|
|
124
87
|
function AppForge:anchor(name, anchorName, props)
|
|
125
88
|
if name == anchorName then
|
|
126
|
-
|
|
127
|
-
name = name,
|
|
128
|
-
})
|
|
129
|
-
return nil
|
|
89
|
+
error(`Tried to anchor an App to itself`)
|
|
130
90
|
end
|
|
131
91
|
local _anchorName = anchorName
|
|
132
92
|
local anchorApp = AppRegistry[_anchorName]
|
|
133
93
|
if not anchorApp then
|
|
134
|
-
|
|
135
|
-
child = name,
|
|
136
|
-
parent = anchorName,
|
|
137
|
-
})
|
|
138
|
-
return nil
|
|
94
|
+
error(`Failed to get class for {anchorName} from AppRegistry for anchor`)
|
|
139
95
|
end
|
|
140
96
|
local _loaded = self.loaded
|
|
141
97
|
local _name = name
|
|
@@ -145,17 +101,11 @@ do
|
|
|
145
101
|
end
|
|
146
102
|
local render = _render
|
|
147
103
|
if not render then
|
|
148
|
-
|
|
149
|
-
parent = anchorName,
|
|
150
|
-
})
|
|
151
|
-
return nil
|
|
104
|
+
error(`Failed to get {name} from this.loaded for anchor to {anchorName}`)
|
|
152
105
|
end
|
|
153
|
-
self.debug:logTag("rules", name, "Anchoring to parent", {
|
|
154
|
-
parent = anchorName,
|
|
155
|
-
})
|
|
156
106
|
local anchor = anchorApp.constructor.new(props, anchorName):render()
|
|
157
|
-
for _,
|
|
158
|
-
|
|
107
|
+
for _, children in anchor:GetDescendants() do
|
|
108
|
+
children:Destroy()
|
|
159
109
|
end
|
|
160
110
|
apply(anchor)({
|
|
161
111
|
Name = "Anchor",
|
|
@@ -166,7 +116,7 @@ do
|
|
|
166
116
|
local _name_1 = name
|
|
167
117
|
local prev = _loaded_1[_name_1]
|
|
168
118
|
if not prev then
|
|
169
|
-
error(`
|
|
119
|
+
error(`Failed to retreive prev loaded data for {name}`)
|
|
170
120
|
end
|
|
171
121
|
apply(prev.container)({
|
|
172
122
|
[0] = anchor,
|
|
@@ -183,19 +133,22 @@ do
|
|
|
183
133
|
local _name = name
|
|
184
134
|
local loaded = _loaded[_name]
|
|
185
135
|
if not loaded then
|
|
186
|
-
|
|
187
|
-
name = name,
|
|
188
|
-
index = index,
|
|
189
|
-
})
|
|
190
|
-
return nil
|
|
136
|
+
error(`Failed to retreive loaded data for app: {name}`)
|
|
191
137
|
end
|
|
192
|
-
self.debug:logTag("rules", name, "Applying ZIndex", {
|
|
193
|
-
index = index,
|
|
194
|
-
})
|
|
195
138
|
apply(loaded.container)({
|
|
196
139
|
ZIndex = index,
|
|
197
140
|
})
|
|
198
141
|
end
|
|
142
|
+
function AppForge:getSource(name)
|
|
143
|
+
local _sources = self.sources
|
|
144
|
+
local _name = name
|
|
145
|
+
if not (_sources[_name] ~= nil) then
|
|
146
|
+
self:createSource(name)
|
|
147
|
+
end
|
|
148
|
+
local _sources_1 = self.sources
|
|
149
|
+
local _name_1 = name
|
|
150
|
+
return _sources_1[_name_1]
|
|
151
|
+
end
|
|
199
152
|
function AppForge:set(name, value, rules)
|
|
200
153
|
if rules == nil then
|
|
201
154
|
rules = true
|
|
@@ -209,21 +162,10 @@ do
|
|
|
209
162
|
local _name_1 = name
|
|
210
163
|
src = _sources_1[_name_1]
|
|
211
164
|
end
|
|
212
|
-
if
|
|
213
|
-
self.logger:log("ERROR", "Failed to set visibility (missing source)", {
|
|
214
|
-
name = name,
|
|
215
|
-
})
|
|
216
|
-
return nil
|
|
217
|
-
end
|
|
218
|
-
local prev = src()
|
|
219
|
-
if prev == value then
|
|
165
|
+
if src() == value then
|
|
220
166
|
return nil
|
|
221
167
|
end
|
|
222
168
|
src(value)
|
|
223
|
-
self.debug:logTag("state", name, "Visibility changed", {
|
|
224
|
-
from = prev,
|
|
225
|
-
to = value,
|
|
226
|
-
})
|
|
227
169
|
if rules then
|
|
228
170
|
self:checkRules(name)
|
|
229
171
|
end
|
|
@@ -247,7 +189,6 @@ do
|
|
|
247
189
|
self:set(name, not self:getSource(name)(), rules)
|
|
248
190
|
end
|
|
249
191
|
function AppForge:story(props)
|
|
250
|
-
self.debug:logTag("lifecycle", "story", "Creating story mount")
|
|
251
192
|
local Container = create("Frame")({
|
|
252
193
|
Name = "Story Container",
|
|
253
194
|
BackgroundTransparency = 1,
|
|
@@ -261,7 +202,6 @@ do
|
|
|
261
202
|
return Container
|
|
262
203
|
end
|
|
263
204
|
function AppForge:mount(callback, props, target)
|
|
264
|
-
self.debug:logTag("lifecycle", "mount", "Mounting AppForge")
|
|
265
205
|
local Container = callback()
|
|
266
206
|
self.innerMount = mount(function()
|
|
267
207
|
apply(Container)({
|
|
@@ -272,7 +212,6 @@ do
|
|
|
272
212
|
return self.innerMount
|
|
273
213
|
end
|
|
274
214
|
function AppForge:unMount()
|
|
275
|
-
self.debug:logTag("lifecycle", "unmount", "Unmounting AppForge")
|
|
276
215
|
local _result = self.innerMount
|
|
277
216
|
if _result ~= nil then
|
|
278
217
|
_result()
|
package/package.json
CHANGED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
export type DebugTag = string;
|
|
2
|
-
type LogFn = (level: "DEBUG" | "PERF", message: string, data?: unknown, traceback?: string) => void;
|
|
3
|
-
export default class Debugger {
|
|
4
|
-
private readonly log;
|
|
5
|
-
private enabled;
|
|
6
|
-
private timers;
|
|
7
|
-
constructor(log: LogFn);
|
|
8
|
-
enable(tag: DebugTag): void;
|
|
9
|
-
disable(tag: DebugTag): void;
|
|
10
|
-
isEnabled(tag: DebugTag): boolean;
|
|
11
|
-
logTag(tag: DebugTag, app: AppNames, message: string, data?: unknown): void;
|
|
12
|
-
time(tag: DebugTag, app: AppNames): void;
|
|
13
|
-
timeEnd(tag: DebugTag, app: AppNames): void;
|
|
14
|
-
}
|
|
15
|
-
export {};
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
-- Compiled with roblox-ts v3.0.0
|
|
2
|
-
local TS = _G[script]
|
|
3
|
-
-- Services
|
|
4
|
-
local RunService = TS.import(script, TS.getModule(script, "@rbxts", "services")).RunService
|
|
5
|
-
local Debugger
|
|
6
|
-
do
|
|
7
|
-
Debugger = setmetatable({}, {
|
|
8
|
-
__tostring = function()
|
|
9
|
-
return "Debugger"
|
|
10
|
-
end,
|
|
11
|
-
})
|
|
12
|
-
Debugger.__index = Debugger
|
|
13
|
-
function Debugger.new(...)
|
|
14
|
-
local self = setmetatable({}, Debugger)
|
|
15
|
-
return self:constructor(...) or self
|
|
16
|
-
end
|
|
17
|
-
function Debugger:constructor(log)
|
|
18
|
-
self.log = log
|
|
19
|
-
self.enabled = {}
|
|
20
|
-
self.timers = {}
|
|
21
|
-
end
|
|
22
|
-
function Debugger:enable(tag)
|
|
23
|
-
local _enabled = self.enabled
|
|
24
|
-
local _tag = tag
|
|
25
|
-
_enabled[_tag] = true
|
|
26
|
-
end
|
|
27
|
-
function Debugger:disable(tag)
|
|
28
|
-
local _enabled = self.enabled
|
|
29
|
-
local _tag = tag
|
|
30
|
-
_enabled[_tag] = nil
|
|
31
|
-
end
|
|
32
|
-
function Debugger:isEnabled(tag)
|
|
33
|
-
local _enabled = self.enabled
|
|
34
|
-
local _tag = tag
|
|
35
|
-
return _enabled[_tag] ~= nil
|
|
36
|
-
end
|
|
37
|
-
function Debugger:logTag(tag, app, message, data)
|
|
38
|
-
if not RunService:IsStudio() then
|
|
39
|
-
return nil
|
|
40
|
-
end
|
|
41
|
-
local _enabled = self.enabled
|
|
42
|
-
local _tag = tag
|
|
43
|
-
if not (_enabled[_tag] ~= nil) then
|
|
44
|
-
return nil
|
|
45
|
-
end
|
|
46
|
-
self.log("DEBUG", `[{tag}][{app}] {message}`, data, debug.traceback(nil, 3))
|
|
47
|
-
end
|
|
48
|
-
function Debugger:time(tag, app)
|
|
49
|
-
if not RunService:IsStudio() then
|
|
50
|
-
return nil
|
|
51
|
-
end
|
|
52
|
-
local _enabled = self.enabled
|
|
53
|
-
local _tag = tag
|
|
54
|
-
if not (_enabled[_tag] ~= nil) then
|
|
55
|
-
return nil
|
|
56
|
-
end
|
|
57
|
-
local _timers = self.timers
|
|
58
|
-
local _arg0 = `{tag}:{app}`
|
|
59
|
-
local _arg1 = os.clock()
|
|
60
|
-
_timers[_arg0] = _arg1
|
|
61
|
-
end
|
|
62
|
-
function Debugger:timeEnd(tag, app)
|
|
63
|
-
if not RunService:IsStudio() then
|
|
64
|
-
return nil
|
|
65
|
-
end
|
|
66
|
-
local _enabled = self.enabled
|
|
67
|
-
local _tag = tag
|
|
68
|
-
if not (_enabled[_tag] ~= nil) then
|
|
69
|
-
return nil
|
|
70
|
-
end
|
|
71
|
-
local key = `{tag}:{app}`
|
|
72
|
-
local start = self.timers[key]
|
|
73
|
-
if start == nil then
|
|
74
|
-
return nil
|
|
75
|
-
end
|
|
76
|
-
self.timers[key] = nil
|
|
77
|
-
local elapsed = os.clock() - start
|
|
78
|
-
self.log("PERF", `[{tag}][{app}] {string.format("%.3fms", elapsed * 1000)}`)
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
|
-
return {
|
|
82
|
-
default = Debugger,
|
|
83
|
-
}
|
package/out/vide/debug/init.luau
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
-- Compiled with roblox-ts v3.0.0
|
|
2
|
-
local TS = _G[script]
|
|
3
|
-
-- debug/logger.ts
|
|
4
|
-
local RunService = TS.import(script, TS.getModule(script, "@rbxts", "services")).RunService
|
|
5
|
-
local Logger
|
|
6
|
-
do
|
|
7
|
-
Logger = setmetatable({}, {
|
|
8
|
-
__tostring = function()
|
|
9
|
-
return "Logger"
|
|
10
|
-
end,
|
|
11
|
-
})
|
|
12
|
-
Logger.__index = Logger
|
|
13
|
-
function Logger.new(...)
|
|
14
|
-
local self = setmetatable({}, Logger)
|
|
15
|
-
return self:constructor(...) or self
|
|
16
|
-
end
|
|
17
|
-
function Logger:constructor(scope)
|
|
18
|
-
self.scope = scope
|
|
19
|
-
end
|
|
20
|
-
function Logger:log(level, message, data, traceback)
|
|
21
|
-
if not RunService:IsStudio() then
|
|
22
|
-
return nil
|
|
23
|
-
end
|
|
24
|
-
local prefix = `[{self.scope}][{level}]`
|
|
25
|
-
if data ~= nil then
|
|
26
|
-
print(prefix, message, data)
|
|
27
|
-
else
|
|
28
|
-
print(prefix, message)
|
|
29
|
-
end
|
|
30
|
-
if traceback ~= "" and traceback then
|
|
31
|
-
print(traceback)
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
return {
|
|
36
|
-
default = Logger,
|
|
37
|
-
}
|