cluaupp 1.4.1 → 1.5.1

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.
Files changed (340) hide show
  1. package/CHANGELOG.md +55 -0
  2. package/README.md +10 -5
  3. package/api/CHANGELOG.md +3 -0
  4. package/api/chat.js +74 -0
  5. package/api/fixtures/roblox/README.md +6 -0
  6. package/api/fixtures/roblox/aux/sample.d.luau +6 -0
  7. package/api/fixtures/roblox/mini/Mini-API-Dump.json +72 -0
  8. package/api/generated/bench-latest.json +39 -0
  9. package/api/generated/capability-profile.json +76 -0
  10. package/api/generated/lsp-index.json +1 -0
  11. package/api/generated/luau/classes.d.luau +11221 -0
  12. package/api/generated/luau/datatypes.d.luau +327 -0
  13. package/api/generated/luau/enums.d.luau +4918 -0
  14. package/api/generated/luau/globals.d.luau +12 -0
  15. package/api/manifests/roblox-target.manifest.json +22 -0
  16. package/api/normalized/roblox-target.profile.json +237461 -0
  17. package/api/overrides/classes.json +8 -0
  18. package/api/overrides/compatibility.json +9 -0
  19. package/api/overrides/datatypes.json +1579 -0
  20. package/api/overrides/enums.json +8 -0
  21. package/api/overrides/globals.json +8 -0
  22. package/api/overrides/type-mappings.json +9 -0
  23. package/api/roblox-api.lock.json +9 -0
  24. package/data/Mini-API-Dump.json +1 -0
  25. package/editors/vscode/README.md +19 -0
  26. package/editors/vscode/extension.js +222 -21
  27. package/editors/vscode/icons/axiom.svg +4 -0
  28. package/editors/vscode/icons/bloom.svg +5 -0
  29. package/editors/vscode/icons/flare.svg +5 -0
  30. package/editors/vscode/icons/helm.svg +4 -0
  31. package/editors/vscode/icons/hive.svg +5 -0
  32. package/editors/vscode/icons/mint.svg +4 -0
  33. package/editors/vscode/icons/shift.svg +6 -0
  34. package/editors/vscode/language-configuration-schema.json +24 -0
  35. package/editors/vscode/language-configuration.json +21 -0
  36. package/editors/vscode/package.json +220 -6
  37. package/editors/vscode/snippets/axiom.json +12 -0
  38. package/editors/vscode/snippets/bloom.json +12 -0
  39. package/editors/vscode/snippets/flare.json +27 -0
  40. package/editors/vscode/snippets/helm.json +12 -0
  41. package/editors/vscode/snippets/hive.json +12 -0
  42. package/editors/vscode/snippets/mint.json +12 -0
  43. package/editors/vscode/snippets/shift.json +17 -0
  44. package/editors/vscode/syntaxes/axiom.tmLanguage.json +5 -0
  45. package/editors/vscode/syntaxes/bloom.tmLanguage.json +5 -0
  46. package/editors/vscode/syntaxes/flare.tmLanguage.json +75 -0
  47. package/editors/vscode/syntaxes/helm.tmLanguage.json +5 -0
  48. package/editors/vscode/syntaxes/hive.tmLanguage.json +5 -0
  49. package/editors/vscode/syntaxes/mint.tmLanguage.json +5 -0
  50. package/editors/vscode/syntaxes/schema.tmLanguage.json +89 -0
  51. package/editors/vscode/syntaxes/shift.tmLanguage.json +5 -0
  52. package/examples/game/.cluaupp/compile-cache/ReplicatedStorage__Shared__Constants__Datas__TemplateData.clh.json +1 -0
  53. package/examples/game/.cluaupp/compile-cache/ServerScriptService__Boot__DataBoot.server.clpp.json +1 -0
  54. package/examples/game/.cluaupp/compile-cache/ServerScriptService__Configuration__ServerConfig.clp.json +1 -0
  55. package/examples/game/.cluaupp/compile-cache/ServerScriptService__Handlers__Guard.server.clpp.json +1 -0
  56. package/examples/game/.cluaupp/compile-cache/ServerScriptService__Handlers__PlayerHandler.server.clpp.json +1 -0
  57. package/examples/game/.cluaupp/compile-cache/StarterPlayer__StarterCharacterScripts__Character__CharacterReady.client.clpp.json +1 -0
  58. package/examples/game/.cluaupp/compile-cache/StarterPlayer__StarterPlayerScripts__Controllers__DataController.client.clpp.json +1 -0
  59. package/examples/game/.cluaupp/compile-cache/index.json +12 -0
  60. package/examples/game/.cluaupp/datamodel-profile.json +94 -0
  61. package/examples/game/.vscode/extensions.json +3 -1
  62. package/examples/game/.vscode/settings.json +13 -1
  63. package/examples/game/include/clpp/datatypes.clh +337 -373
  64. package/examples/game/include/clpp/generated/datamodel.clh +25 -0
  65. package/examples/game/include/clpp/generated/enums.clh +1 -1
  66. package/examples/game/include/clpp/generated/instances.clh +41135 -41064
  67. package/examples/game/include/clpp/libs/axiom.clh +1 -1
  68. package/examples/game/include/clpp/libs/math.clh +14 -0
  69. package/examples/game/include/clpp/libs/roster.clh +6 -0
  70. package/examples/game/include/clpp/libs/spring.clh +17 -0
  71. package/examples/game/include/clpp/libs/ward.clh +1 -0
  72. package/examples/game/include/clpp/roblox.clh +3 -4
  73. package/examples/game/libs/ArrayIndexer/init.luau +209 -0
  74. package/examples/game/libs/Axiom/init.luau +608 -0
  75. package/examples/game/libs/Bloom/init.luau +433 -0
  76. package/examples/game/libs/Coil/init.luau +215 -0
  77. package/examples/game/libs/Crest/init.luau +426 -0
  78. package/examples/game/libs/Echo/init.luau +417 -0
  79. package/examples/game/libs/Ember/init.luau +365 -0
  80. package/examples/game/libs/Flare/init.luau +717 -0
  81. package/examples/game/libs/Gleam/init.luau +729 -0
  82. package/examples/game/libs/Guide/init.luau +215 -0
  83. package/examples/game/libs/Helm/init.luau +377 -0
  84. package/examples/game/libs/Hive/init.luau +241 -0
  85. package/examples/game/libs/Keep/Client.luau +114 -0
  86. package/examples/game/libs/Keep/Data.luau +883 -0
  87. package/examples/game/libs/Keep/Engine.luau +211 -0
  88. package/examples/game/libs/Keep/Enum.luau +6 -0
  89. package/examples/game/libs/Keep/Enums.luau +10 -0
  90. package/examples/game/libs/Keep/Path.luau +236 -0
  91. package/examples/game/libs/Keep/Replicator.luau +298 -0
  92. package/examples/game/libs/Keep/Server.luau +251 -0
  93. package/examples/game/libs/Keep/Store.luau +652 -0
  94. package/examples/game/libs/Keep/Trade.luau +455 -0
  95. package/examples/game/libs/Keep/init.luau +205 -0
  96. package/examples/game/libs/Lens/init.luau +609 -0
  97. package/examples/game/libs/Mint/init.luau +279 -0
  98. package/examples/game/libs/Net/init.luau +156 -0
  99. package/examples/game/libs/Net/src/codec.luau +224 -0
  100. package/examples/game/libs/Occlude/init.luau +117 -0
  101. package/examples/game/libs/Pin/init.luau +309 -0
  102. package/examples/game/libs/Promise/LICENSE +21 -0
  103. package/examples/game/libs/Promise/_impl/LICENSE +21 -0
  104. package/examples/game/libs/Promise/_impl/init.lua +1991 -0
  105. package/examples/game/libs/Promise/init.lua +1990 -0
  106. package/examples/game/libs/Promise/init.luau +13 -0
  107. package/examples/game/libs/Promise/types.luau +46 -0
  108. package/examples/game/libs/Roster/init.luau +686 -0
  109. package/examples/game/libs/SOURCES.md +31 -0
  110. package/examples/game/libs/Shift/init.luau +238 -0
  111. package/examples/game/libs/Spark/init.luau +487 -0
  112. package/examples/game/libs/Stage/init.luau +178 -0
  113. package/examples/game/libs/Sweep/init.luau +259 -0
  114. package/examples/game/libs/Trace/init.luau +213 -0
  115. package/examples/game/libs/Ward/init.luau +211 -0
  116. package/examples/game/out/ReplicatedStorage/Shared/Constants/Datas/TemplateData.luau +29 -0
  117. package/examples/game/out/ReplicatedStorage/Shared/Constants/Datas/TemplateData.luau.map.json +13 -0
  118. package/examples/game/out/ReplicatedStorage/Shared/Net/Net.luau +83 -0
  119. package/examples/game/out/ReplicatedStorage/Shared/Net/Net.luau.map.json +13 -0
  120. package/examples/game/out/ServerScriptService/Boot/DataBoot.server.luau +18 -0
  121. package/examples/game/out/ServerScriptService/Boot/DataBoot.server.luau.map.json +13 -0
  122. package/examples/game/out/ServerScriptService/Configuration/ServerConfig.luau +14 -0
  123. package/examples/game/out/ServerScriptService/Configuration/ServerConfig.luau.map.json +13 -0
  124. package/examples/game/out/ServerScriptService/Handlers/Guard.server.luau +15 -0
  125. package/examples/game/out/ServerScriptService/Handlers/Guard.server.luau.map.json +13 -0
  126. package/examples/game/out/ServerScriptService/Handlers/PlayerHandler.server.luau +50 -0
  127. package/examples/game/out/ServerScriptService/Handlers/PlayerHandler.server.luau.map.json +13 -0
  128. package/examples/game/out/StarterPlayer/StarterCharacterScripts/Character/CharacterReady.client.luau +12 -0
  129. package/examples/game/out/StarterPlayer/StarterCharacterScripts/Character/CharacterReady.client.luau.map.json +13 -0
  130. package/examples/game/out/StarterPlayer/StarterPlayerScripts/Controllers/DataController.client.luau +16 -0
  131. package/examples/game/out/StarterPlayer/StarterPlayerScripts/Controllers/DataController.client.luau.map.json +13 -0
  132. package/examples/game/src/ReplicatedStorage/Shared/Net/Net.clh +26 -0
  133. package/examples/game/src/ReplicatedStorage/Shared/Net/Net.flare +5 -0
  134. package/examples/game/src/ServerScriptService/Boot/DataBoot.server.clpp +2 -2
  135. package/examples/game/src/ServerScriptService/Handlers/PlayerHandler.server.clpp +1 -1
  136. package/examples/game/stylua.toml +9 -0
  137. package/generated/api/build-profile.js +115 -0
  138. package/generated/api/cache.js +44 -0
  139. package/generated/api/coverage.js +32 -0
  140. package/generated/api/diff.js +125 -0
  141. package/generated/api/generators/clpp-headers.js +353 -0
  142. package/generated/api/generators/docs-reference.js +7 -0
  143. package/generated/api/generators/lsp-index.js +81 -0
  144. package/generated/api/generators/luau-defs.js +94 -0
  145. package/generated/api/ide.js +76 -0
  146. package/generated/api/identifier.js +47 -0
  147. package/generated/api/index.js +324 -0
  148. package/generated/api/loader.js +57 -0
  149. package/generated/api/merge.js +88 -0
  150. package/generated/api/model.js +5 -0
  151. package/generated/api/normalize.js +231 -0
  152. package/generated/api/overrides-validate.js +58 -0
  153. package/generated/api/perf.js +12 -0
  154. package/generated/api/registry.js +136 -0
  155. package/generated/api/release.js +44 -0
  156. package/generated/api/resolver.js +250 -0
  157. package/generated/api/sources/aux-types-diff.js +75 -0
  158. package/generated/api/sources/client-tracker.js +11 -0
  159. package/generated/api/sources/creator-docs.js +42 -0
  160. package/generated/api/sources/luau-types.js +34 -0
  161. package/generated/api/sources/mini-dump.js +17 -0
  162. package/generated/api/sources/studio-api.js +8 -0
  163. package/generated/api/sources/studio-apiv2.js +11 -0
  164. package/generated/api/sources/studio-full-api.js +8 -0
  165. package/generated/api/studio-smoke.js +80 -0
  166. package/generated/api/type-parse.js +49 -0
  167. package/generated/api/understander.js +51 -0
  168. package/generated/api/validate.js +135 -0
  169. package/generated/api-cli.js +421 -0
  170. package/generated/cli.js +17 -6
  171. package/generated/clpp/contract.js +3 -3
  172. package/generated/clpp/format-luau.js +236 -0
  173. package/generated/clpp/index.js +13 -1
  174. package/generated/clpp/modules.js +227 -0
  175. package/generated/clpp/postprocess.js +86 -5
  176. package/generated/clpp/rewrite-janitor.js +145 -0
  177. package/generated/clpp/runner.js +14 -2
  178. package/generated/compile.js +82 -0
  179. package/generated/flare/index.js +15 -3
  180. package/generated/flare/language.js +561 -0
  181. package/generated/flare/parse.js +19 -7
  182. package/generated/intellisense.js +76 -2
  183. package/generated/lsp.js +118 -7
  184. package/generated/native/index.js +217 -16
  185. package/generated/target/authority-check.js +136 -0
  186. package/generated/target/authority-graph.js +74 -0
  187. package/generated/target/build-cache.js +112 -0
  188. package/generated/target/capabilities.js +89 -0
  189. package/generated/target/capability-profile.js +30 -0
  190. package/generated/target/component-contracts.js +60 -0
  191. package/generated/target/context-check.js +160 -0
  192. package/generated/target/datamodel-check.js +170 -0
  193. package/generated/target/datamodel-generate.js +74 -0
  194. package/generated/target/datamodel.js +233 -0
  195. package/generated/target/diagnostics.js +63 -0
  196. package/generated/target/doctor.js +152 -0
  197. package/generated/target/flare-version.js +58 -0
  198. package/generated/target/get-service.js +69 -0
  199. package/generated/target/lifetime-check.js +47 -0
  200. package/generated/target/luau-stamp.js +39 -0
  201. package/generated/target/optimizer-advise.js +88 -0
  202. package/generated/target/optimizer-apply.js +44 -0
  203. package/generated/target/optimizer-soa.js +254 -0
  204. package/generated/target/parallel-check.js +136 -0
  205. package/generated/target/pgo.js +148 -0
  206. package/generated/target/project-docs.js +69 -0
  207. package/generated/target/project-graph.js +71 -0
  208. package/generated/target/roblox.js +63 -0
  209. package/generated/target/security-check.js +41 -0
  210. package/generated/target/source-map.js +25 -0
  211. package/generated/target/studio-bridge.js +112 -0
  212. package/generated/utils/project.js +178 -8
  213. package/generated/utils/rojo-mapper.js +11 -3
  214. package/include/clpp/datatypes.clh +337 -373
  215. package/include/clpp/generated/enums.clh +1 -1
  216. package/include/clpp/generated/instances.clh +41135 -41064
  217. package/include/clpp/libs/axiom.clh +1 -1
  218. package/include/clpp/libs/hive.clh +1 -0
  219. package/include/clpp/libs/keep.clh +2 -0
  220. package/include/clpp/libs/math.clh +14 -0
  221. package/include/clpp/libs/roster.clh +6 -0
  222. package/include/clpp/libs/spring.clh +17 -0
  223. package/include/clpp/libs/ward.clh +1 -0
  224. package/include/clpp/roblox.clh +3 -4
  225. package/package.json +10 -3
  226. package/plugins/CluauppNav/Plugin.luau +207 -0
  227. package/plugins/CluauppNav/ProfileLogger.luau +27 -0
  228. package/plugins/CluauppNav/README.md +24 -0
  229. package/runtime/Axiom/init.luau +10 -7
  230. package/runtime/Coil/init.luau +8 -2
  231. package/runtime/Crest/init.luau +1 -0
  232. package/runtime/Flare/init.luau +2 -1
  233. package/runtime/Gleam/init.luau +15 -4
  234. package/runtime/Hive/init.luau +36 -14
  235. package/runtime/Pin/init.luau +5 -2
  236. package/runtime/Roster/init.luau +8 -0
  237. package/runtime/Spark/init.luau +3 -0
  238. package/runtime/Sweep/init.luau +2 -0
  239. package/runtime/Trace/init.luau +3 -0
  240. package/runtime/Ward/init.luau +38 -5
  241. package/scripts/postinstall-editor.js +17 -0
  242. package/skills/README.md +13 -0
  243. package/skills/clpp-hive-flare/SKILL.md +79 -0
  244. package/skills/clpp-language/SKILL.md +123 -0
  245. package/skills/clpp-language/compiler.md +89 -0
  246. package/skills/clpp-style/SKILL.md +95 -0
  247. package/src/api/build-profile.ts +138 -0
  248. package/src/api/cache.ts +45 -0
  249. package/src/api/coverage.ts +46 -0
  250. package/src/api/diff.ts +143 -0
  251. package/src/api/generators/clpp-headers.ts +377 -0
  252. package/src/api/generators/docs-reference.ts +11 -0
  253. package/src/api/generators/lsp-index.ts +106 -0
  254. package/src/api/generators/luau-defs.ts +98 -0
  255. package/src/api/ide.ts +87 -0
  256. package/src/api/identifier.ts +47 -0
  257. package/src/api/index.ts +269 -0
  258. package/src/api/loader.ts +60 -0
  259. package/src/api/merge.ts +126 -0
  260. package/src/api/model.ts +283 -0
  261. package/src/api/normalize.ts +257 -0
  262. package/src/api/overrides-validate.ts +58 -0
  263. package/src/api/perf.ts +15 -0
  264. package/src/api/registry.ts +162 -0
  265. package/src/api/release.ts +47 -0
  266. package/src/api/resolver.ts +255 -0
  267. package/src/api/sources/aux-types-diff.ts +81 -0
  268. package/src/api/sources/client-tracker.ts +10 -0
  269. package/src/api/sources/creator-docs.ts +37 -0
  270. package/src/api/sources/luau-types.ts +30 -0
  271. package/src/api/sources/mini-dump.ts +50 -0
  272. package/src/api/sources/studio-api.ts +7 -0
  273. package/src/api/sources/studio-apiv2.ts +10 -0
  274. package/src/api/sources/studio-full-api.ts +7 -0
  275. package/src/api/studio-smoke.ts +82 -0
  276. package/src/api/type-parse.ts +48 -0
  277. package/src/api/understander.ts +72 -0
  278. package/src/api/validate.ts +160 -0
  279. package/src/api-cli.ts +493 -0
  280. package/src/api.generated.js +37 -22
  281. package/src/cli.ts +22 -7
  282. package/src/clpp/contract.ts +34 -3
  283. package/src/clpp/format-luau.ts +262 -0
  284. package/src/clpp/index.ts +13 -2
  285. package/src/clpp/modules.ts +252 -0
  286. package/src/clpp/postprocess.ts +100 -5
  287. package/src/clpp/rewrite-janitor.ts +156 -0
  288. package/src/clpp/runner.ts +14 -2
  289. package/src/compile.ts +87 -0
  290. package/src/flare/index.ts +20 -1
  291. package/src/flare/language.ts +708 -0
  292. package/src/flare/parse.ts +20 -7
  293. package/src/flare/types.ts +2 -0
  294. package/src/intellisense.ts +76 -2
  295. package/src/lsp.ts +151 -8
  296. package/src/native/index.ts +225 -16
  297. package/src/target/authority-check.ts +162 -0
  298. package/src/target/authority-graph.ts +80 -0
  299. package/src/target/build-cache.ts +129 -0
  300. package/src/target/capabilities.ts +115 -0
  301. package/src/target/capability-profile.ts +25 -0
  302. package/src/target/component-contracts.ts +64 -0
  303. package/src/target/context-check.ts +177 -0
  304. package/src/target/datamodel-check.ts +188 -0
  305. package/src/target/datamodel-generate.ts +78 -0
  306. package/src/target/datamodel.ts +261 -0
  307. package/src/target/diagnostics.ts +67 -0
  308. package/src/target/doctor.ts +171 -0
  309. package/src/target/flare-version.ts +61 -0
  310. package/src/target/get-service.ts +85 -0
  311. package/src/target/lifetime-check.ts +45 -0
  312. package/src/target/luau-stamp.ts +33 -0
  313. package/src/target/optimizer-advise.ts +93 -0
  314. package/src/target/optimizer-apply.ts +63 -0
  315. package/src/target/optimizer-soa.ts +270 -0
  316. package/src/target/parallel-check.ts +135 -0
  317. package/src/target/pgo.ts +157 -0
  318. package/src/target/project-docs.ts +68 -0
  319. package/src/target/project-graph.ts +75 -0
  320. package/src/target/roblox.ts +78 -0
  321. package/src/target/security-check.ts +40 -0
  322. package/src/target/source-map.ts +36 -0
  323. package/src/target/studio-bridge.ts +140 -0
  324. package/src/types.ts +14 -0
  325. package/src/utils/project.ts +183 -9
  326. package/src/utils/rojo-mapper.ts +12 -3
  327. package/stylua.toml +9 -0
  328. package/templates/game/.vscode/extensions.json +3 -1
  329. package/templates/game/.vscode/settings.json +8 -1
  330. package/templates/game/include/clpp/datatypes.clh +337 -373
  331. package/templates/game/include/clpp/generated/enums.clh +1 -1
  332. package/templates/game/include/clpp/generated/instances.clh +41135 -41064
  333. package/templates/game/include/clpp/libs/axiom.clh +1 -1
  334. package/templates/game/include/clpp/libs/roster.clh +6 -0
  335. package/templates/game/include/clpp/libs/ward.clh +1 -0
  336. package/templates/game/include/clpp/roblox.clh +3 -4
  337. package/templates/game/src/ReplicatedStorage/Shared/Net/Net.flare +5 -0
  338. package/templates/game/src/ServerScriptService/Boot/DataBoot.server.clpp +2 -2
  339. package/templates/game/src/ServerScriptService/Handlers/PlayerHandler.server.clpp +1 -1
  340. package/templates/game/stylua.toml +9 -0
@@ -0,0 +1,609 @@
1
+ --!optimize 2
2
+ --!strict
3
+ -- Lens — debug UI. Window is a scope; there is no End().
4
+
5
+ local Players = game:GetService("Players")
6
+ local RunService = game:GetService("RunService")
7
+ local UserInputService = game:GetService("UserInputService")
8
+
9
+ export type Lens = {
10
+ Init: () -> (),
11
+ Window: (title: string, draw: () -> ()) -> (),
12
+ Text: (text: string) -> (),
13
+ Button: (label: string, onClick: (() -> ())?) -> boolean,
14
+ Checkbox: (label: string, value: boolean?) -> boolean,
15
+ Slider: (label: string, value: number, minOrMax: number?, maybeMax: number?) -> number,
16
+ Tree: (label: string, draw: (() -> ())?) -> boolean,
17
+ Table: (title: string, rows: { { any } }?) -> (),
18
+ Plot: (label: string, values: { number }) -> (),
19
+ Search: (query: string) -> (),
20
+ Copy: (value: any) -> (),
21
+ Value: (label: string, value: any) -> (),
22
+ }
23
+
24
+ local Lens = {} :: any
25
+
26
+ if RunService:IsServer() then
27
+ function Lens.Window(_title: string, draw: () -> ())
28
+ draw()
29
+ end
30
+ function Lens.Text(_text: string) end
31
+ function Lens.Button(_label: string, _onClick: (() -> ())?): boolean
32
+ return false
33
+ end
34
+ function Lens.Checkbox(_label: string, value: boolean?): boolean
35
+ return value == true
36
+ end
37
+ function Lens.Slider(_label: string, value: number, _a: number?, _b: number?): number
38
+ return value
39
+ end
40
+ function Lens.Tree(_label: string, draw: (() -> ())?): boolean
41
+ if draw then
42
+ draw()
43
+ end
44
+ return true
45
+ end
46
+ function Lens.Table(_title: string, _rows: { { any } }?) end
47
+ function Lens.Plot(_label: string, _values: { number }) end
48
+ function Lens.Search(_query: string) end
49
+ function Lens.Copy(_value: any) end
50
+ function Lens.Value(_label: string, _value: any) end
51
+ function Lens.Init() end
52
+ return Lens :: Lens
53
+ end
54
+
55
+ local Trace = require(script.Parent.Trace)
56
+
57
+ type WindowState = {
58
+ frame: Frame,
59
+ header: TextButton,
60
+ searchBox: TextBox,
61
+ body: ScrollingFrame,
62
+ title: string,
63
+ }
64
+
65
+ type WidgetState = {
66
+ checked: { [string]: boolean },
67
+ slider: { [string]: number },
68
+ tree: { [string]: boolean },
69
+ clicked: { [string]: boolean },
70
+ }
71
+
72
+ local host: ScreenGui? = nil
73
+ local windows: { [string]: WindowState } = {}
74
+ local widgetState: { [string]: WidgetState } = {}
75
+ local searchQuery = ""
76
+ local copyBuffer = ""
77
+ local parentStack: { GuiObject } = {}
78
+ local activeTitle: string? = nil
79
+ local dragging: {
80
+ frame: Frame,
81
+ origin: Vector2,
82
+ start: Vector2,
83
+ }? = nil
84
+
85
+ local BG = Color3.fromRGB(18, 18, 22)
86
+ local HEADER = Color3.fromRGB(32, 32, 40)
87
+ local ROW = Color3.fromRGB(40, 40, 52)
88
+ local ACCENT = Color3.fromRGB(40, 90, 180)
89
+ local TEXT = Color3.fromRGB(230, 230, 235)
90
+ local MUTED = Color3.fromRGB(160, 160, 170)
91
+
92
+ local function localPlayer(): Player?
93
+ return Players.LocalPlayer
94
+ end
95
+
96
+ local function ensure(): ScreenGui?
97
+ if host and host.Parent then
98
+ return host
99
+ end
100
+ local player = localPlayer()
101
+ if not player then
102
+ return nil
103
+ end
104
+ local gui = player:FindFirstChildOfClass("PlayerGui")
105
+ if not gui then
106
+ gui = player:WaitForChild("PlayerGui", 8) :: PlayerGui?
107
+ end
108
+ if not gui then
109
+ return nil
110
+ end
111
+ local screen = Instance.new("ScreenGui")
112
+ screen.Name = "Lens"
113
+ screen.ResetOnSpawn = false
114
+ screen.DisplayOrder = 1200
115
+ screen.IgnoreGuiInset = true
116
+ screen.ZIndexBehavior = Enum.ZIndexBehavior.Sibling
117
+ screen.Parent = gui
118
+ host = screen
119
+ return screen
120
+ end
121
+
122
+ local function currentParent(): GuiObject?
123
+ return parentStack[#parentStack]
124
+ end
125
+
126
+ local function stateFor(title: string): WidgetState
127
+ local stored = widgetState[title]
128
+ if stored then
129
+ return stored
130
+ end
131
+ stored = {
132
+ checked = {},
133
+ slider = {},
134
+ tree = {},
135
+ clicked = {},
136
+ }
137
+ widgetState[title] = stored
138
+ return stored
139
+ end
140
+
141
+ local function matchesSearch(text: string): boolean
142
+ if searchQuery == "" then
143
+ return true
144
+ end
145
+ return string.find(string.lower(text), string.lower(searchQuery), 1, true) ~= nil
146
+ end
147
+
148
+ local function tag(object: GuiObject, text: string)
149
+ object:SetAttribute("LensText", text)
150
+ object.Visible = matchesSearch(text)
151
+ end
152
+
153
+ local function applyFilter(root: Instance)
154
+ for _, child in root:GetDescendants() do
155
+ if child:IsA("GuiObject") then
156
+ local text = child:GetAttribute("LensText")
157
+ if typeof(text) == "string" then
158
+ child.Visible = matchesSearch(text)
159
+ end
160
+ end
161
+ end
162
+ end
163
+
164
+ local function styleText(label: TextLabel | TextButton | TextBox)
165
+ label.TextColor3 = TEXT
166
+ label.Font = Enum.Font.Code
167
+ label.TextSize = 14
168
+ label.BackgroundTransparency = 1
169
+ label.BorderSizePixel = 0
170
+ label.TextXAlignment = Enum.TextXAlignment.Left
171
+ label.TextTruncate = Enum.TextTruncate.AtEnd
172
+ end
173
+
174
+ local function clearBody(body: ScrollingFrame)
175
+ for _, child in body:GetChildren() do
176
+ if not child:IsA("UIListLayout") and not child:IsA("UIPadding") then
177
+ child:Destroy()
178
+ end
179
+ end
180
+ end
181
+
182
+ local function bindDrag(header: TextButton, frame: Frame)
183
+ header.InputBegan:Connect(function(input)
184
+ if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
185
+ dragging = {
186
+ frame = frame,
187
+ origin = Vector2.new(frame.Position.X.Offset, frame.Position.Y.Offset),
188
+ start = UserInputService:GetMouseLocation(),
189
+ }
190
+ end
191
+ end)
192
+ end
193
+
194
+ UserInputService.InputChanged:Connect(function(input)
195
+ local drag = dragging
196
+ if not drag then
197
+ return
198
+ end
199
+ if input.UserInputType ~= Enum.UserInputType.MouseMovement and input.UserInputType ~= Enum.UserInputType.Touch then
200
+ return
201
+ end
202
+ local mouse = UserInputService:GetMouseLocation()
203
+ local delta = mouse - drag.start
204
+ local x = math.max(0, drag.origin.X + delta.X)
205
+ local y = math.max(0, drag.origin.Y + delta.Y)
206
+ drag.frame.Position = UDim2.fromOffset(x, y)
207
+ end)
208
+
209
+ UserInputService.InputEnded:Connect(function(input)
210
+ if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
211
+ dragging = nil
212
+ end
213
+ end)
214
+
215
+ local function makeWindow(screen: ScreenGui, title: string): WindowState
216
+ local index = 0
217
+ for _ in windows do
218
+ index += 1
219
+ end
220
+ local frame = Instance.new("Frame")
221
+ frame.Name = title
222
+ frame.Size = UDim2.fromOffset(300, 280)
223
+ frame.Position = UDim2.fromOffset(16 + 24 * index, 72 + 18 * index)
224
+ frame.BackgroundColor3 = BG
225
+ frame.BorderSizePixel = 0
226
+ frame.Active = true
227
+ frame.Parent = screen
228
+ local corner = Instance.new("UICorner")
229
+ corner.CornerRadius = UDim.new(0, 8)
230
+ corner.Parent = frame
231
+ local stroke = Instance.new("UIStroke")
232
+ stroke.Color = Color3.fromRGB(60, 60, 72)
233
+ stroke.Thickness = 1
234
+ stroke.Parent = frame
235
+
236
+ local header = Instance.new("TextButton")
237
+ header.Name = "Header"
238
+ header.Size = UDim2.new(1, 0, 0, 28)
239
+ header.BackgroundColor3 = HEADER
240
+ header.BorderSizePixel = 0
241
+ header.AutoButtonColor = false
242
+ header.Text = title
243
+ header.TextColor3 = Color3.new(1, 1, 1)
244
+ header.Font = Enum.Font.GothamBold
245
+ header.TextSize = 14
246
+ header.Parent = frame
247
+ local headerCorner = Instance.new("UICorner")
248
+ headerCorner.CornerRadius = UDim.new(0, 8)
249
+ headerCorner.Parent = header
250
+
251
+ local close = Instance.new("TextButton")
252
+ close.Name = "Close"
253
+ close.Size = UDim2.fromOffset(22, 22)
254
+ close.Position = UDim2.new(1, -26, 0, 3)
255
+ close.BackgroundColor3 = Color3.fromRGB(70, 40, 44)
256
+ close.Text = "x"
257
+ close.TextColor3 = TEXT
258
+ close.Font = Enum.Font.GothamBold
259
+ close.TextSize = 12
260
+ close.AutoButtonColor = true
261
+ close.Parent = header
262
+ local closeCorner = Instance.new("UICorner")
263
+ closeCorner.CornerRadius = UDim.new(0, 4)
264
+ closeCorner.Parent = close
265
+ close.Activated:Connect(function()
266
+ frame.Visible = false
267
+ end)
268
+
269
+ local searchBox = Instance.new("TextBox")
270
+ searchBox.Name = "Search"
271
+ searchBox.Size = UDim2.new(1, -12, 0, 22)
272
+ searchBox.Position = UDim2.fromOffset(6, 30)
273
+ searchBox.BackgroundColor3 = ROW
274
+ searchBox.PlaceholderText = "search"
275
+ searchBox.PlaceholderColor3 = MUTED
276
+ searchBox.Text = searchQuery
277
+ searchBox.ClearTextOnFocus = false
278
+ searchBox.Parent = frame
279
+ styleText(searchBox)
280
+ searchBox.BackgroundTransparency = 0
281
+ local searchCorner = Instance.new("UICorner")
282
+ searchCorner.CornerRadius = UDim.new(0, 4)
283
+ searchCorner.Parent = searchBox
284
+ searchBox:GetPropertyChangedSignal("Text"):Connect(function()
285
+ searchQuery = searchBox.Text
286
+ local body = frame:FindFirstChild("Body")
287
+ if body then
288
+ applyFilter(body)
289
+ end
290
+ end)
291
+
292
+ local body = Instance.new("ScrollingFrame")
293
+ body.Name = "Body"
294
+ body.Size = UDim2.new(1, 0, 1, -56)
295
+ body.Position = UDim2.fromOffset(0, 56)
296
+ body.BackgroundTransparency = 1
297
+ body.BorderSizePixel = 0
298
+ body.ScrollBarThickness = 4
299
+ body.CanvasSize = UDim2.new()
300
+ body.AutomaticCanvasSize = Enum.AutomaticSize.Y
301
+ body.Parent = frame
302
+ local padding = Instance.new("UIPadding")
303
+ padding.PaddingLeft = UDim.new(0, 8)
304
+ padding.PaddingRight = UDim.new(0, 8)
305
+ padding.PaddingTop = UDim.new(0, 4)
306
+ padding.PaddingBottom = UDim.new(0, 8)
307
+ padding.Parent = body
308
+ local layout = Instance.new("UIListLayout")
309
+ layout.Padding = UDim.new(0, 4)
310
+ layout.SortOrder = Enum.SortOrder.LayoutOrder
311
+ layout.Parent = body
312
+
313
+ bindDrag(header, frame)
314
+
315
+ return {
316
+ frame = frame,
317
+ header = header,
318
+ searchBox = searchBox,
319
+ body = body,
320
+ title = title,
321
+ }
322
+ end
323
+
324
+ function Lens.Window(title: string, draw: () -> ())
325
+ local screen = ensure()
326
+ if not screen then
327
+ return
328
+ end
329
+ local existing = windows[title]
330
+ if not existing or existing.frame.Parent == nil then
331
+ existing = makeWindow(screen, title)
332
+ windows[title] = existing
333
+ end
334
+ existing.frame.Visible = true
335
+ existing.searchBox.Text = searchQuery
336
+ clearBody(existing.body)
337
+ activeTitle = title
338
+ table.clear(parentStack)
339
+ table.insert(parentStack, existing.body)
340
+ local ok, err = pcall(draw)
341
+ table.clear(parentStack)
342
+ activeTitle = nil
343
+ applyFilter(existing.body)
344
+ if not ok then
345
+ warn("[Lens]", err)
346
+ end
347
+ end
348
+
349
+ function Lens.Text(text: string)
350
+ local parent = currentParent()
351
+ if not parent then
352
+ return
353
+ end
354
+ local label = Instance.new("TextLabel")
355
+ label.Size = UDim2.new(1, 0, 0, 18)
356
+ label.Text = text
357
+ styleText(label)
358
+ label.Parent = parent
359
+ tag(label, text)
360
+ end
361
+
362
+ function Lens.Button(label: string, onClick: (() -> ())?): boolean
363
+ local parent = currentParent()
364
+ if not parent or not activeTitle then
365
+ return false
366
+ end
367
+ local store = stateFor(activeTitle)
368
+ local clicked = store.clicked[label] == true
369
+ store.clicked[label] = false
370
+ local button = Instance.new("TextButton")
371
+ button.Size = UDim2.new(1, 0, 0, 24)
372
+ button.BackgroundColor3 = ROW
373
+ button.AutoButtonColor = true
374
+ button.Text = label
375
+ styleText(button)
376
+ button.BackgroundTransparency = 0
377
+ button.TextXAlignment = Enum.TextXAlignment.Center
378
+ button.Parent = parent
379
+ local corner = Instance.new("UICorner")
380
+ corner.CornerRadius = UDim.new(0, 4)
381
+ corner.Parent = button
382
+ button.Activated:Connect(function()
383
+ store.clicked[label] = true
384
+ if onClick then
385
+ onClick()
386
+ end
387
+ end)
388
+ tag(button, label)
389
+ return clicked
390
+ end
391
+
392
+ function Lens.Checkbox(label: string, value: boolean?): boolean
393
+ local parent = currentParent()
394
+ if not parent or not activeTitle then
395
+ return value == true
396
+ end
397
+ local store = stateFor(activeTitle)
398
+ if store.checked[label] == nil then
399
+ store.checked[label] = value == true
400
+ end
401
+ local checked = store.checked[label]
402
+ local button = Instance.new("TextButton")
403
+ button.Size = UDim2.new(1, 0, 0, 20)
404
+ button.AutoButtonColor = false
405
+ button.Text = `{if checked then "[x]" else "[ ]"} {label}`
406
+ styleText(button)
407
+ button.Parent = parent
408
+ button.Activated:Connect(function()
409
+ store.checked[label] = not store.checked[label]
410
+ button.Text = `{if store.checked[label] then "[x]" else "[ ]"} {label}`
411
+ end)
412
+ tag(button, label)
413
+ return checked
414
+ end
415
+
416
+ function Lens.Slider(label: string, value: number, minOrMax: number?, maybeMax: number?): number
417
+ local parent = currentParent()
418
+ local minValue = 0
419
+ local maxValue = 1
420
+ if maybeMax ~= nil and minOrMax ~= nil then
421
+ minValue = minOrMax
422
+ maxValue = maybeMax
423
+ elseif minOrMax ~= nil then
424
+ maxValue = minOrMax
425
+ end
426
+ if maxValue == minValue then
427
+ maxValue = minValue + 1
428
+ end
429
+ if not parent or not activeTitle then
430
+ return math.clamp(value, minValue, maxValue)
431
+ end
432
+ local store = stateFor(activeTitle)
433
+ if store.slider[label] == nil then
434
+ store.slider[label] = math.clamp(value, minValue, maxValue)
435
+ end
436
+ local current = store.slider[label]
437
+
438
+ local row = Instance.new("Frame")
439
+ row.Size = UDim2.new(1, 0, 0, 36)
440
+ row.BackgroundTransparency = 1
441
+ row.Parent = parent
442
+ tag(row, label)
443
+
444
+ local caption = Instance.new("TextLabel")
445
+ caption.Size = UDim2.new(1, 0, 0, 16)
446
+ caption.Text = `{label}: {string.format("%.2f", current)}`
447
+ styleText(caption)
448
+ caption.Parent = row
449
+
450
+ local bar = Instance.new("TextButton")
451
+ bar.Name = "Track"
452
+ bar.Size = UDim2.new(1, 0, 0, 10)
453
+ bar.Position = UDim2.fromOffset(0, 20)
454
+ bar.BackgroundColor3 = ROW
455
+ bar.AutoButtonColor = false
456
+ bar.Text = ""
457
+ bar.Parent = row
458
+ local barCorner = Instance.new("UICorner")
459
+ barCorner.CornerRadius = UDim.new(0, 4)
460
+ barCorner.Parent = bar
461
+
462
+ local fill = Instance.new("Frame")
463
+ fill.Name = "Fill"
464
+ fill.BackgroundColor3 = ACCENT
465
+ fill.BorderSizePixel = 0
466
+ fill.Size = UDim2.new(math.clamp((current - minValue) / (maxValue - minValue), 0, 1), 0, 1, 0)
467
+ fill.Parent = bar
468
+ local fillCorner = Instance.new("UICorner")
469
+ fillCorner.CornerRadius = UDim.new(0, 4)
470
+ fillCorner.Parent = fill
471
+
472
+ local function apply(alpha: number)
473
+ local nextValue = minValue + (maxValue - minValue) * math.clamp(alpha, 0, 1)
474
+ store.slider[label] = nextValue
475
+ fill.Size = UDim2.new(math.clamp(alpha, 0, 1), 0, 1, 0)
476
+ caption.Text = `{label}: {string.format("%.2f", nextValue)}`
477
+ end
478
+
479
+ local sliding = false
480
+ local function fromInput(input: InputObject)
481
+ local width = math.max(bar.AbsoluteSize.X, 1)
482
+ apply((input.Position.X - bar.AbsolutePosition.X) / width)
483
+ end
484
+ bar.InputBegan:Connect(function(input)
485
+ if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
486
+ sliding = true
487
+ fromInput(input)
488
+ end
489
+ end)
490
+ bar.InputEnded:Connect(function(input)
491
+ if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
492
+ sliding = false
493
+ end
494
+ end)
495
+ local slideConn = UserInputService.InputChanged:Connect(function(input)
496
+ if not sliding or bar.Parent == nil then
497
+ return
498
+ end
499
+ if input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch then
500
+ fromInput(input)
501
+ end
502
+ end)
503
+ bar.AncestryChanged:Connect(function(_, parent)
504
+ if parent == nil then
505
+ slideConn:Disconnect()
506
+ sliding = false
507
+ end
508
+ end)
509
+
510
+ return current
511
+ end
512
+
513
+ function Lens.Tree(label: string, draw: (() -> ())?): boolean
514
+ local parent = currentParent()
515
+ if not parent or not activeTitle then
516
+ if draw then
517
+ draw()
518
+ end
519
+ return true
520
+ end
521
+ local store = stateFor(activeTitle)
522
+ if store.tree[label] == nil then
523
+ store.tree[label] = true
524
+ end
525
+ local open = store.tree[label]
526
+
527
+ local header = Instance.new("TextButton")
528
+ header.Size = UDim2.new(1, 0, 0, 20)
529
+ header.AutoButtonColor = false
530
+ header.Text = `{if open then "v" else ">"} {label}`
531
+ styleText(header)
532
+ header.Parent = parent
533
+ tag(header, label)
534
+
535
+ local body = Instance.new("Frame")
536
+ body.Name = label
537
+ body.Size = UDim2.new(1, 0, 0, 0)
538
+ body.AutomaticSize = Enum.AutomaticSize.Y
539
+ body.BackgroundTransparency = 1
540
+ body.Visible = open
541
+ body.Parent = parent
542
+ local padding = Instance.new("UIPadding")
543
+ padding.PaddingLeft = UDim.new(0, 12)
544
+ padding.Parent = body
545
+ local layout = Instance.new("UIListLayout")
546
+ layout.Padding = UDim.new(0, 4)
547
+ layout.SortOrder = Enum.SortOrder.LayoutOrder
548
+ layout.Parent = body
549
+
550
+ header.Activated:Connect(function()
551
+ store.tree[label] = not store.tree[label]
552
+ local now = store.tree[label]
553
+ body.Visible = now
554
+ header.Text = `{if now then "v" else ">"} {label}`
555
+ end)
556
+
557
+ if draw then
558
+ table.insert(parentStack, body)
559
+ draw()
560
+ table.remove(parentStack)
561
+ end
562
+
563
+ return open
564
+ end
565
+
566
+ function Lens.Table(title: string, rows: { { any } }?)
567
+ Lens.Text(title)
568
+ if rows then
569
+ for _, item in rows do
570
+ Lens.Text(Trace.display(item))
571
+ end
572
+ end
573
+ end
574
+
575
+ function Lens.Plot(label: string, values: { number })
576
+ local max = 1
577
+ for _, value in values do
578
+ if value > max then
579
+ max = value
580
+ end
581
+ end
582
+ local bars = {}
583
+ for _, value in values do
584
+ table.insert(bars, if value / max > 0.66 then "|" elseif value / max > 0.33 then ":" else ".")
585
+ end
586
+ Lens.Text(`{label} {table.concat(bars)}`)
587
+ end
588
+
589
+ function Lens.Search(query: string)
590
+ searchQuery = query
591
+ for _, window in windows do
592
+ window.searchBox.Text = query
593
+ applyFilter(window.body)
594
+ end
595
+ end
596
+
597
+ function Lens.Copy(value: any)
598
+ copyBuffer = Trace.display(value)
599
+ end
600
+
601
+ function Lens.Value(label: string, value: any)
602
+ Lens.Text(`{label}: {Trace.display(value)}`)
603
+ end
604
+
605
+ function Lens.Init()
606
+ ensure()
607
+ end
608
+
609
+ return Lens :: Lens