lecodes-cli 0.19.0 → 0.20.0

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 (270) hide show
  1. package/README.md +1 -0
  2. package/dist/index.js +1069 -396
  3. package/package.json +14 -13
  4. package/runtime/scene-harness.json +1 -1
  5. package/runtime/sdk-types.json +1 -1
  6. package/runtime/web/assets/Roboto-Variable-DHm9jpd-.woff2 +0 -0
  7. package/runtime/web/assets/__vite-browser-external-BIHI7g3E.js +1 -0
  8. package/runtime/web/assets/basis-C64VHDVD.js +1 -0
  9. package/runtime/web/assets/basis_transcoder-VXdx5NbI.wasm +0 -0
  10. package/runtime/web/assets/createViewerLite-BvHobVhp.js +852 -0
  11. package/runtime/web/assets/draco-BiISTFcR.js +118 -0
  12. package/runtime/web/assets/draco_decoder-DsQ12WqX.wasm +0 -0
  13. package/runtime/web/assets/index-CfNCCBjN.js +2 -0
  14. package/runtime/web/assets/mapViewImpl-B2JcES8l.js +810 -0
  15. package/runtime/web/assets/maplibre-gl-worker-CJfwIrte.js +8 -0
  16. package/runtime/web/assets/neutral_ibl128-D-lzdkLN.ktx +0 -0
  17. package/runtime/web/assets/worker-Caf-yYEI.js +2 -0
  18. package/runtime/web/embed.html +32 -0
  19. package/runtime/web/embed.js +171 -0
  20. package/src/api.ts +302 -0
  21. package/src/browserAuth.ts +87 -0
  22. package/src/cmgenTool.ts +104 -0
  23. package/src/commands/app.ts +896 -0
  24. package/src/commands/appAndroid.ts +603 -0
  25. package/src/commands/appDesktop.ts +339 -0
  26. package/src/commands/appDesktopMac.ts +470 -0
  27. package/src/commands/appIcon.ts +187 -0
  28. package/src/commands/appShared.ts +542 -0
  29. package/src/commands/appTemplates.ts +907 -0
  30. package/src/commands/appTemplatesAndroid.ts +599 -0
  31. package/src/commands/appTemplatesGradlew.ts +9 -0
  32. package/src/commands/assets.ts +28 -0
  33. package/src/commands/clone.ts +60 -0
  34. package/src/commands/compile.ts +253 -0
  35. package/src/commands/create.ts +59 -0
  36. package/src/commands/design.ts +863 -0
  37. package/src/commands/designTemplates.ts +11 -0
  38. package/src/commands/desktop.ts +127 -0
  39. package/src/commands/dev.ts +236 -0
  40. package/src/commands/diff.ts +59 -0
  41. package/src/commands/init.ts +191 -0
  42. package/src/commands/install.ts +198 -0
  43. package/src/commands/lightmap.ts +290 -0
  44. package/src/commands/link.ts +147 -0
  45. package/src/commands/login.ts +24 -0
  46. package/src/commands/navmesh.ts +225 -0
  47. package/src/commands/pn.ts +305 -0
  48. package/src/commands/projectTemplates.ts +130 -0
  49. package/src/commands/pull.ts +109 -0
  50. package/src/commands/push.ts +173 -0
  51. package/src/commands/render.ts +416 -0
  52. package/src/commands/scene.ts +148 -0
  53. package/src/commands/shaders.ts +157 -0
  54. package/src/commands/status.ts +29 -0
  55. package/src/commands/test.ts +371 -0
  56. package/src/commands/thumbs.ts +178 -0
  57. package/src/commands/types.ts +87 -0
  58. package/src/commands/update.ts +190 -0
  59. package/src/compile/assetIcons.ts +214 -0
  60. package/src/compile/collect.ts +46 -0
  61. package/src/compile/collectLocal.ts +37 -0
  62. package/src/compile/designCompile.ts +104 -0
  63. package/src/compile/fonts.ts +156 -0
  64. package/src/compile/headlessBundle.ts +129 -0
  65. package/src/compile/nativeStack.ts +21 -0
  66. package/src/compile/projectCompile.ts +109 -0
  67. package/src/compile/sceneCompile.ts +113 -0
  68. package/src/compile/screenEntry.ts +127 -0
  69. package/src/compile/shaders.ts +245 -0
  70. package/src/config.ts +42 -0
  71. package/src/designMeta.ts +35 -0
  72. package/src/desktopRenderer.ts +545 -0
  73. package/src/desktopScript.ts +276 -0
  74. package/src/dev/clientTemplates.ts +160 -0
  75. package/src/dev/devServer.ts +333 -0
  76. package/src/dev/webRunner.ts +22 -0
  77. package/src/dev/wsServer.ts +144 -0
  78. package/src/distRoot.ts +20 -0
  79. package/src/ignore.ts +163 -0
  80. package/src/index.ts +494 -0
  81. package/src/lecodes-3d-editor.d.ts +41 -0
  82. package/src/lecodes-assets.d.ts +7 -0
  83. package/src/lecodes-design.d.ts +191 -0
  84. package/src/lecodes-renderer.d.ts +131 -0
  85. package/src/localFiles.ts +144 -0
  86. package/src/manifest.ts +46 -0
  87. package/src/matcTool.ts +137 -0
  88. package/src/peers.ts +40 -0
  89. package/src/project.ts +61 -0
  90. package/src/projectEnv.ts +94 -0
  91. package/src/qrcode-terminal.d.ts +9 -0
  92. package/src/releases.ts +125 -0
  93. package/src/serverDiff.ts +78 -0
  94. package/src/textDiff.ts +103 -0
  95. package/src/types.ts +0 -0
  96. package/src/util.ts +146 -0
  97. package/runtime/sdk/animate/animate.ts +0 -238
  98. package/runtime/sdk/animate/bezier.ts +0 -138
  99. package/runtime/sdk/animate/easings.ts +0 -126
  100. package/runtime/sdk/canvas/Canvas.ts +0 -305
  101. package/runtime/sdk/compile/aspectMacro.ts +0 -86
  102. package/runtime/sdk/compile/assetIconMacro.ts +0 -384
  103. package/runtime/sdk/compile/assetMacro.ts +0 -146
  104. package/runtime/sdk/compile/assetName.ts +0 -50
  105. package/runtime/sdk/compile/bundler.ts +0 -287
  106. package/runtime/sdk/compile/compileProject.ts +0 -129
  107. package/runtime/sdk/compile/detectEntry.ts +0 -128
  108. package/runtime/sdk/compile/fontMacro.ts +0 -459
  109. package/runtime/sdk/compile/fontRegistry.ts +0 -78
  110. package/runtime/sdk/compile/header.ts +0 -67
  111. package/runtime/sdk/compile/index.ts +0 -100
  112. package/runtime/sdk/compile/libraryImports.ts +0 -52
  113. package/runtime/sdk/compile/liteMaterial.ts +0 -247
  114. package/runtime/sdk/compile/sceneEditor.ts +0 -88
  115. package/runtime/sdk/compile/serverSplit.ts +0 -233
  116. package/runtime/sdk/compile/serverTypes.ts +0 -227
  117. package/runtime/sdk/compile/sfnt.ts +0 -98
  118. package/runtime/sdk/compile/shaderSchema.ts +0 -202
  119. package/runtime/sdk/compile/shaderTargets.ts +0 -81
  120. package/runtime/sdk/compile/sourcemap.ts +0 -25
  121. package/runtime/sdk/core/Aspect.ts +0 -568
  122. package/runtime/sdk/core/InspectorUI.ts +0 -212
  123. package/runtime/sdk/core/StateMachine.ts +0 -308
  124. package/runtime/sdk/core/color.ts +0 -66
  125. package/runtime/sdk/core/compWrite.ts +0 -42
  126. package/runtime/sdk/core/events.ts +0 -38
  127. package/runtime/sdk/core/fields.ts +0 -120
  128. package/runtime/sdk/core/registry.ts +0 -23
  129. package/runtime/sdk/core/signals.ts +0 -277
  130. package/runtime/sdk/core/time.ts +0 -84
  131. package/runtime/sdk/g2/Camera2D.ts +0 -40
  132. package/runtime/sdk/g2/CharacterController2D.ts +0 -276
  133. package/runtime/sdk/g2/Node2D.ts +0 -267
  134. package/runtime/sdk/g2/OneWay2D.ts +0 -66
  135. package/runtime/sdk/g2/Physics2D.ts +0 -346
  136. package/runtime/sdk/g2/Scene2D.ts +0 -209
  137. package/runtime/sdk/g2/Shape2D.ts +0 -259
  138. package/runtime/sdk/g2/Sprite.ts +0 -89
  139. package/runtime/sdk/g2/SpriteAnimation.ts +0 -171
  140. package/runtime/sdk/g2/SpriteSheet.ts +0 -166
  141. package/runtime/sdk/g2/Texture2D.ts +0 -47
  142. package/runtime/sdk/g2/Tilemap.ts +0 -41
  143. package/runtime/sdk/g2/Tileset.ts +0 -71
  144. package/runtime/sdk/g2/Trigger2D.ts +0 -77
  145. package/runtime/sdk/g2/autotile.ts +0 -433
  146. package/runtime/sdk/g2/cells.ts +0 -91
  147. package/runtime/sdk/g2/defineScene2d.ts +0 -381
  148. package/runtime/sdk/g2/groups2d.ts +0 -106
  149. package/runtime/sdk/g2/loop.ts +0 -50
  150. package/runtime/sdk/g2/scenarios2d.ts +0 -69
  151. package/runtime/sdk/g2/touch.ts +0 -83
  152. package/runtime/sdk/gl/Camera.ts +0 -160
  153. package/runtime/sdk/gl/CameraPlace.ts +0 -52
  154. package/runtime/sdk/gl/CharacterController.ts +0 -238
  155. package/runtime/sdk/gl/Gearbox.ts +0 -212
  156. package/runtime/sdk/gl/Geometry.ts +0 -279
  157. package/runtime/sdk/gl/IK.ts +0 -193
  158. package/runtime/sdk/gl/InstancedMesh.ts +0 -132
  159. package/runtime/sdk/gl/Light.ts +0 -107
  160. package/runtime/sdk/gl/Lightmap.ts +0 -256
  161. package/runtime/sdk/gl/Material.ts +0 -260
  162. package/runtime/sdk/gl/Mesh.ts +0 -83
  163. package/runtime/sdk/gl/Model.ts +0 -124
  164. package/runtime/sdk/gl/NavAgent.ts +0 -337
  165. package/runtime/sdk/gl/NavMesh.ts +0 -397
  166. package/runtime/sdk/gl/Node.ts +0 -350
  167. package/runtime/sdk/gl/Noise.ts +0 -30
  168. package/runtime/sdk/gl/Particles.ts +0 -676
  169. package/runtime/sdk/gl/Physics.ts +0 -222
  170. package/runtime/sdk/gl/Plane.ts +0 -53
  171. package/runtime/sdk/gl/Ragdoll.ts +0 -270
  172. package/runtime/sdk/gl/Ray.ts +0 -16
  173. package/runtime/sdk/gl/Scene.ts +0 -486
  174. package/runtime/sdk/gl/Shape.ts +0 -409
  175. package/runtime/sdk/gl/Terrain.ts +0 -1092
  176. package/runtime/sdk/gl/Texture.ts +0 -63
  177. package/runtime/sdk/gl/Trigger.ts +0 -45
  178. package/runtime/sdk/gl/Vehicle.ts +0 -473
  179. package/runtime/sdk/gl/Wheel.ts +0 -240
  180. package/runtime/sdk/gl/animation/AnimationClip.ts +0 -204
  181. package/runtime/sdk/gl/animation/Animator.ts +0 -120
  182. package/runtime/sdk/gl/animation/Layer.ts +0 -31
  183. package/runtime/sdk/gl/animation/Loop.ts +0 -30
  184. package/runtime/sdk/gl/animation/Playback.ts +0 -44
  185. package/runtime/sdk/gl/animation/core.ts +0 -336
  186. package/runtime/sdk/gl/controls.ts +0 -95
  187. package/runtime/sdk/gl/physicsEvents.ts +0 -20
  188. package/runtime/sdk/gl/scenarios.ts +0 -291
  189. package/runtime/sdk/gl/state.ts +0 -6
  190. package/runtime/sdk/gl/terrainMesh.ts +0 -219
  191. package/runtime/sdk/gl/touch.ts +0 -68
  192. package/runtime/sdk/inject.ts +0 -197
  193. package/runtime/sdk/math/Mathf.ts +0 -118
  194. package/runtime/sdk/math/mat4.ts +0 -278
  195. package/runtime/sdk/math/quat.ts +0 -232
  196. package/runtime/sdk/math/vec.ts +0 -255
  197. package/runtime/sdk/net/codec.ts +0 -119
  198. package/runtime/sdk/net/core.ts +0 -384
  199. package/runtime/sdk/net/index.ts +0 -181
  200. package/runtime/sdk/net/replication.ts +0 -622
  201. package/runtime/sdk/plugins/camera.ts +0 -81
  202. package/runtime/sdk/plugins/geolocation.ts +0 -123
  203. package/runtime/sdk/plugins/oauth.ts +0 -61
  204. package/runtime/sdk/plugins/permission.ts +0 -7
  205. package/runtime/sdk/plugins/push.ts +0 -132
  206. package/runtime/sdk/plugins/qr.ts +0 -73
  207. package/runtime/sdk/plugins/service.ts +0 -47
  208. package/runtime/sdk/runtime/app.ts +0 -101
  209. package/runtime/sdk/runtime/appEvents.ts +0 -54
  210. package/runtime/sdk/runtime/channel.ts +0 -61
  211. package/runtime/sdk/runtime/clipboard.ts +0 -20
  212. package/runtime/sdk/runtime/datetime.ts +0 -329
  213. package/runtime/sdk/runtime/device.ts +0 -293
  214. package/runtime/sdk/runtime/fetch.ts +0 -77
  215. package/runtime/sdk/runtime/files.ts +0 -23
  216. package/runtime/sdk/runtime/input.ts +0 -175
  217. package/runtime/sdk/runtime/media.ts +0 -111
  218. package/runtime/sdk/runtime/misc.ts +0 -16
  219. package/runtime/sdk/runtime/net.ts +0 -36
  220. package/runtime/sdk/runtime/rpc.ts +0 -218
  221. package/runtime/sdk/runtime/service.ts +0 -83
  222. package/runtime/sdk/runtime/share.ts +0 -9
  223. package/runtime/sdk/runtime/storage.ts +0 -13
  224. package/runtime/sdk/runtime/touch.ts +0 -76
  225. package/runtime/sdk/scene/defineScene.ts +0 -1353
  226. package/runtime/sdk/scene/editorPlugins.ts +0 -110
  227. package/runtime/sdk/scene/gizmos.ts +0 -148
  228. package/runtime/sdk/scene/grammar.ts +0 -120
  229. package/runtime/sdk/scene/material.ts +0 -188
  230. package/runtime/sdk/server/auth/appConfig.ts +0 -12
  231. package/runtime/sdk/server/auth/global.ts +0 -80
  232. package/runtime/sdk/server/auth/host.ts +0 -318
  233. package/runtime/sdk/server/auth/models.ts +0 -83
  234. package/runtime/sdk/server/auth/types.ts +0 -50
  235. package/runtime/sdk/server/channel.ts +0 -56
  236. package/runtime/sdk/server/context.ts +0 -36
  237. package/runtime/sdk/server/db/defineDb.ts +0 -237
  238. package/runtime/sdk/server/db/fields.ts +0 -132
  239. package/runtime/sdk/server/db/httpTransport.ts +0 -93
  240. package/runtime/sdk/server/db/index.ts +0 -7
  241. package/runtime/sdk/server/db/marci/query.ts +0 -412
  242. package/runtime/sdk/server/db/types.ts +0 -202
  243. package/runtime/sdk/server/errors.ts +0 -12
  244. package/runtime/sdk/server/host.ts +0 -74
  245. package/runtime/sdk/server/inject.ts +0 -13
  246. package/runtime/sdk/server/runtime.ts +0 -133
  247. package/runtime/sdk/server/validate.ts +0 -87
  248. package/runtime/sdk/ui/NativeView.ts +0 -142
  249. package/runtime/sdk/ui/UI.ts +0 -39
  250. package/runtime/sdk/ui/UIBottomSheet.ts +0 -139
  251. package/runtime/sdk/ui/UIButton.ts +0 -101
  252. package/runtime/sdk/ui/UIContainer.ts +0 -60
  253. package/runtime/sdk/ui/UIImage.ts +0 -83
  254. package/runtime/sdk/ui/UIInput.ts +0 -185
  255. package/runtime/sdk/ui/UIModal.ts +0 -139
  256. package/runtime/sdk/ui/UINode.ts +0 -830
  257. package/runtime/sdk/ui/UIPager.ts +0 -362
  258. package/runtime/sdk/ui/UIPopover.ts +0 -100
  259. package/runtime/sdk/ui/UIScreen.ts +0 -123
  260. package/runtime/sdk/ui/UIScrollable.ts +0 -87
  261. package/runtime/sdk/ui/UISpacer.ts +0 -14
  262. package/runtime/sdk/ui/UITabs.ts +0 -236
  263. package/runtime/sdk/ui/UIText.ts +0 -51
  264. package/runtime/sdk/ui/UIVideo.ts +0 -88
  265. package/runtime/sdk/ui/UIVirtualizedList.ts +0 -241
  266. package/runtime/sdk/ui/UIWidget.ts +0 -127
  267. package/runtime/sdk/ui/fonts.ts +0 -13
  268. package/runtime/sdk/ui/presentable.ts +0 -117
  269. package/runtime/sdk/ui/router.ts +0 -132
  270. package/runtime/sdk/ui/theme.ts +0 -84
@@ -1,305 +0,0 @@
1
- // A core 2D drawing surface that bakes to a texture — see docs/canvas-contract.md. It is NOT part of
2
- // creator-2d/creator-gl: the texture it produces is consumed by 2D sprites, 3D materials and UI
3
- // images alike ("a canvas is just a texture"), so world/label text and arbitrary 2D graphics are
4
- // drawn once, per platform, on that platform's native 2D stack (web OffscreenCanvas, iOS CoreGraphics,
5
- // Android Canvas).
6
- //
7
- // The API looks immediate but RECORDS commands into a compact buffer and flushes them to the backend
8
- // ONCE per bake (one bridge crossing, not one per lineTo). Colors and fonts are CSS strings, resolved
9
- // by the platform. Do all drawing AFTER `await registerFont(...)` — an unloaded font mis-measures.
10
- //
11
- // State (fillStyle, font, textAlign, …) is get/set like the browser; drawing calls are methods (they
12
- // return `this`, so drawing still chains). `pixelRatio` is the device-pixel multiplier (browser-style
13
- // `scale(sx, sy)` is a transform).
14
- //
15
- // const c = new Canvas(160, 40, { pixelRatio: 2 })
16
- // c.font = 'bold 24px Inter'
17
- // const w = c.measureText('Alice').width + 24
18
- // c.resize(w, 40)
19
- // c.fillStyle = '#000a'; c.roundRect(0, 0, w, 40, 12).fill()
20
- // c.fillStyle = '#fff'; c.textAlign = 'center'; c.fillText('Alice', w / 2, 27)
21
- // new Sprite({ texture: c }) // Canvas is a valid texture source everywhere
22
-
23
- import { Texture2D } from "../g2/Texture2D"
24
- import { File, type FetchResponse } from "../runtime/fetch"
25
- import type { SvgSourceValue } from "../runtime/misc"
26
-
27
- // Opcodes — MUST stay in sync with docs/canvas-contract.md.
28
- const OP = {
29
- SAVE: 0, RESTORE: 1, TRANSLATE: 2, SCALE: 3, ROTATE: 4, GLOBAL_ALPHA: 5,
30
- FILL_STYLE: 6, STROKE_STYLE: 7, LINE_WIDTH: 8, LINE_JOIN: 9, LINE_CAP: 10,
31
- FONT: 11, TEXT_ALIGN: 12, TEXT_BASELINE: 13,
32
- BEGIN_PATH: 14, CLOSE_PATH: 15, MOVE_TO: 16, LINE_TO: 17, QUADRATIC_TO: 18, BEZIER_TO: 19,
33
- ARC: 20, RECT: 21, ROUND_RECT: 22, FILL: 23, STROKE: 24,
34
- FILL_RECT: 25, STROKE_RECT: 26, CLEAR_RECT: 27, FILL_TEXT: 28, STROKE_TEXT: 29,
35
- DRAW_IMAGE: 30,
36
- } as const
37
-
38
- const ALIGN = { left: 0, center: 1, right: 2, start: 3, end: 4 } as const
39
- const BASELINE = { alphabetic: 0, top: 1, middle: 2, bottom: 3, hanging: 4, ideographic: 5 } as const
40
- const JOIN = { miter: 0, round: 1, bevel: 2 } as const
41
- const CAP = { butt: 0, round: 1, square: 2 } as const
42
-
43
- export type TextAlign = keyof typeof ALIGN
44
- export type TextBaseline = keyof typeof BASELINE
45
- export type LineJoin = keyof typeof JOIN
46
- export type LineCap = keyof typeof CAP
47
- export interface CanvasTextMetrics { width: number, ascent: number, descent: number }
48
-
49
- export class Canvas {
50
- /** Brand so `Sprite`/`UIImage`/`Material` can accept a Canvas anywhere a texture source is expected. */
51
- readonly __canvas = true as const
52
-
53
- width: number
54
- height: number
55
- /** Device-pixel multiplier (draw at 2 for crisp retina text). Applied by the backend. */
56
- pixelRatio: number
57
-
58
- private _cmd: number[] = []
59
- private _refs: string[] = []
60
- // Shadowed drawing state so the get/set accessors read back the current value (like the browser).
61
- private _globalAlpha = 1
62
- private _fillStyle = "#000000"
63
- private _strokeStyle = "#000000"
64
- private _lineWidth = 1
65
- private _lineJoin: LineJoin = "miter"
66
- private _lineCap: LineCap = "butt"
67
- private _font = "10px sans-serif"
68
- private _textAlign: TextAlign = "start"
69
- private _textBaseline: TextBaseline = "alphabetic"
70
- private _surfaceId = 0
71
- private _tex2d?: Texture2D // cached 2D texture, re-uploaded on update()
72
- /** @internal — cached 3D (creator-gl) texture id, set by gl/Texture.fromCanvas; re-uploaded on
73
- * update(). Kept as a bare id (not a Texture import) so a 2D-only canvas never pulls the 3D engine. */
74
- _tex3dId = 0
75
- // Set once this canvas is baked as a UIImage source (see _bakeSurfaceForUI). When true, update()
76
- // also refreshes the on-screen image node(s) via _creatorUI — the UI consumer the 2D/3D texture
77
- // hooks below don't cover. Stays a bare flag so a non-UI canvas never references the UI bridge.
78
- private _uiBound = false
79
-
80
- constructor(width: number, height: number, opts: { pixelRatio?: number } = {}) {
81
- this.width = width
82
- this.height = height
83
- this.pixelRatio = opts.pixelRatio ?? 1
84
- }
85
-
86
- private _ref(s: string): number {
87
- const i = this._refs.indexOf(s)
88
- if (i >= 0) return i
89
- this._refs.push(s)
90
- return this._refs.length - 1
91
- }
92
-
93
- /** Discard the recorded drawing to start a new one (for dynamic canvases). */
94
- reset(): this { this._cmd.length = 0; this._refs.length = 0; return this }
95
- /** Change the surface size; takes effect on the next bake. */
96
- resize(width: number, height: number): this { this.width = width; this.height = height; return this }
97
-
98
- // --- transforms & state stack (actions; chainable) ---
99
- save(): this { this._cmd.push(OP.SAVE); return this }
100
- restore(): this { this._cmd.push(OP.RESTORE); return this }
101
- translate(x: number, y: number): this { this._cmd.push(OP.TRANSLATE, x, y); return this }
102
- scale(sx: number, sy: number): this { this._cmd.push(OP.SCALE, sx, sy); return this }
103
- rotate(rad: number): this { this._cmd.push(OP.ROTATE, rad); return this }
104
-
105
- // --- drawing state (get/set like the browser; colors/fonts are CSS strings resolved by the platform).
106
- // The setter records the state op AND shadows the value so the getter reads it back.
107
- get globalAlpha(): number { return this._globalAlpha }
108
- set globalAlpha(a: number) { this._globalAlpha = a; this._cmd.push(OP.GLOBAL_ALPHA, a) }
109
- get fillStyle(): string { return this._fillStyle }
110
- set fillStyle(color: string) { this._fillStyle = color; this._cmd.push(OP.FILL_STYLE, this._ref(color)) }
111
- get strokeStyle(): string { return this._strokeStyle }
112
- set strokeStyle(color: string) { this._strokeStyle = color; this._cmd.push(OP.STROKE_STYLE, this._ref(color)) }
113
- get lineWidth(): number { return this._lineWidth }
114
- set lineWidth(w: number) { this._lineWidth = w; this._cmd.push(OP.LINE_WIDTH, w) }
115
- get lineJoin(): LineJoin { return this._lineJoin }
116
- set lineJoin(j: LineJoin) { this._lineJoin = j; this._cmd.push(OP.LINE_JOIN, JOIN[j]) }
117
- get lineCap(): LineCap { return this._lineCap }
118
- set lineCap(c: LineCap) { this._lineCap = c; this._cmd.push(OP.LINE_CAP, CAP[c]) }
119
- get font(): string { return this._font }
120
- set font(f: string) { this._font = f; this._cmd.push(OP.FONT, this._ref(f)) }
121
- get textAlign(): TextAlign { return this._textAlign }
122
- set textAlign(a: TextAlign) { this._textAlign = a; this._cmd.push(OP.TEXT_ALIGN, ALIGN[a]) }
123
- get textBaseline(): TextBaseline { return this._textBaseline }
124
- set textBaseline(b: TextBaseline) { this._textBaseline = b; this._cmd.push(OP.TEXT_BASELINE, BASELINE[b]) }
125
-
126
- // --- paths ---
127
- beginPath(): this { this._cmd.push(OP.BEGIN_PATH); return this }
128
- closePath(): this { this._cmd.push(OP.CLOSE_PATH); return this }
129
- moveTo(x: number, y: number): this { this._cmd.push(OP.MOVE_TO, x, y); return this }
130
- lineTo(x: number, y: number): this { this._cmd.push(OP.LINE_TO, x, y); return this }
131
- quadraticCurveTo(cx: number, cy: number, x: number, y: number): this { this._cmd.push(OP.QUADRATIC_TO, cx, cy, x, y); return this }
132
- bezierCurveTo(c1x: number, c1y: number, c2x: number, c2y: number, x: number, y: number): this {
133
- this._cmd.push(OP.BEZIER_TO, c1x, c1y, c2x, c2y, x, y); return this
134
- }
135
- arc(x: number, y: number, r: number, a0: number, a1: number, ccw = false): this {
136
- this._cmd.push(OP.ARC, x, y, r, a0, a1, ccw ? 1 : 0); return this
137
- }
138
- rect(x: number, y: number, w: number, h: number): this { this._cmd.push(OP.RECT, x, y, w, h); return this }
139
- roundRect(x: number, y: number, w: number, h: number, r: number): this { this._cmd.push(OP.ROUND_RECT, x, y, w, h, r); return this }
140
- fill(evenOdd = false): this { this._cmd.push(OP.FILL, evenOdd ? 1 : 0); return this }
141
- stroke(): this { this._cmd.push(OP.STROKE); return this }
142
-
143
- // --- shape/text sugar ---
144
- fillRect(x: number, y: number, w: number, h: number): this { this._cmd.push(OP.FILL_RECT, x, y, w, h); return this }
145
- strokeRect(x: number, y: number, w: number, h: number): this { this._cmd.push(OP.STROKE_RECT, x, y, w, h); return this }
146
- clearRect(x: number, y: number, w: number, h: number): this { this._cmd.push(OP.CLEAR_RECT, x, y, w, h); return this }
147
- fillText(text: string, x: number, y: number, maxWidth = 0): this { this._cmd.push(OP.FILL_TEXT, this._ref(text), x, y, maxWidth); return this }
148
- strokeText(text: string, x: number, y: number, maxWidth = 0): this { this._cmd.push(OP.STROKE_TEXT, this._ref(text), x, y, maxWidth); return this }
149
-
150
- // --- images ---
151
- /** Blit a `Bitmap` (a snapshot from `toBitmap()`) onto this canvas. All coordinates are LOGICAL —
152
- * including the source sub-rect in the 9-arg form (it's scaled by the bitmap's pixelRatio here).
153
- * Records a DRAW_IMAGE op, so the blit runs at bake time: keep the Bitmap alive until the next
154
- * `update()`/`toBitmap()`/`texture()`. Three browser-style forms:
155
- * drawImage(bmp, dx, dy) — whole bitmap at its natural size
156
- * drawImage(bmp, dx, dy, dw, dh) — whole bitmap, scaled into dw×dh
157
- * drawImage(bmp, sx, sy, sw, sh, dx, dy, dw, dh) — a sub-rect of the bitmap, scaled into dw×dh */
158
- drawImage(img: Bitmap, dx: number, dy: number): this
159
- drawImage(img: Bitmap, dx: number, dy: number, dw: number, dh: number): this
160
- drawImage(img: Bitmap, sx: number, sy: number, sw: number, sh: number, dx: number, dy: number, dw: number, dh: number): this
161
- drawImage(img: Bitmap, a: number, b: number, c?: number, d?: number, e?: number, f?: number, g?: number, h?: number): this {
162
- const pr = img.pixelRatio
163
- let sx: number, sy: number, sw: number, sh: number, dx: number, dy: number, dw: number, dh: number
164
- if (e === undefined) { // (dx, dy) or (dx, dy, dw, dh): the whole bitmap
165
- sx = 0; sy = 0; sw = img.pixelWidth; sh = img.pixelHeight
166
- dx = a; dy = b; dw = c ?? img.width; dh = d ?? img.height
167
- } else { // (sx, sy, sw, sh, dx, dy, dw, dh): a sub-rect (logical → device px)
168
- sx = a * pr; sy = b * pr; sw = c! * pr; sh = d! * pr
169
- dx = e; dy = f!; dw = g!; dh = h!
170
- }
171
- this._cmd.push(OP.DRAW_IMAGE, img._surfaceId, sx, sy, sw, sh, dx, dy, dw, dh)
172
- return this
173
- }
174
-
175
- /** Decode an image source into a standalone `Bitmap` you can blit with `drawImage()` — either an
176
- * `SvgSource(...)` (rasterized) or a `FetchResponse` holding already-fetched image bytes (decoded).
177
- * This is async because turning SVG markup / encoded bytes into pixels needs a decode step (on the
178
- * web, `createImageBitmap` / an `<img>` load); `await` it ONCE, then `drawImage(bitmap, …)` is
179
- * synchronous and the Bitmap is reusable. The returned Bitmap owns a native surface at the image's
180
- * natural pixel size (`pixelRatio` 1) — `destroy()` it when done. Typical use:
181
- * const logo = await canvas.loadImage(SvgSource(svg)) // or: await fetch(url) → the response
182
- * canvas.drawImage(logo, 0, 0) // sync, blit as often as you like */
183
- loadImage(source: SvgSourceValue | FetchResponse): Promise<Bitmap> {
184
- // Discriminate without touching FetchResponse internals: only an SvgSource carries `.svg`.
185
- const isSvg = typeof (source as SvgSourceValue).svg === "string"
186
- const svg = isSvg ? (source as SvgSourceValue).svg : ""
187
- const bufferId = isSvg ? -1 : (source as any)._id // <0 = the SVG path; else the host buffer id
188
- return new Promise<Bitmap>((res, rej) => {
189
- _creatorCanvas.loadImage(svg, bufferId, (surfaceId, w, h) => res(new Bitmap(surfaceId, w, h, 1)), rej)
190
- })
191
- }
192
-
193
- /** Measure `text` in the current font on THIS platform. The one synchronous round-trip. */
194
- measureText(text: string): CanvasTextMetrics {
195
- const o = _creatorCanvas.measureText(text, this._font)
196
- return { width: o[0], ascent: o[1], descent: o[2] }
197
- }
198
-
199
- /** @internal — rasterize the recorded commands into the surface; returns the surface id. */
200
- _bakeSurface(): number {
201
- const buf = new Float32Array(this._cmd)
202
- this._surfaceId = _creatorCanvas.rasterize(this._surfaceId, this.width, this.height, this.pixelRatio, buf, buf.length, this._refs)
203
- return this._surfaceId
204
- }
205
-
206
- /** @internal — bake for a `UIImage(canvas)` source: same as `_bakeSurface()` but also flags this
207
- * canvas UI-bound, so a later `update()` re-reads the re-baked pixels into the on-screen image
208
- * node(s) — not just the 2D/3D engine textures. Called by UIImage when a Canvas is assigned as src. */
209
- _bakeSurfaceForUI(): number {
210
- this._uiBound = true
211
- return this._bakeSurface()
212
- }
213
-
214
- /** Bake and return the 2D texture (created once, then cached). */
215
- texture(): Texture2D {
216
- if (!this._tex2d) this._tex2d = Texture2D.fromCanvas(this)
217
- return this._tex2d
218
- }
219
-
220
- /** Re-rasterize and re-upload to every texture this canvas produced (call after redrawing) — the
221
- * cached 2D and/or 3D texture, whichever engines this canvas was baked into. */
222
- update(): this {
223
- const surfaceId = this._bakeSurface()
224
- if (this._tex2d) _creator2d.updateTextureFromCanvas(this._tex2d.id, surfaceId)
225
- if (this._tex3dId) _creator.updateTextureFromCanvas(this._tex3dId, surfaceId)
226
- // UIImage(canvas): repaint any live image node showing this surface with the re-baked pixels —
227
- // draw-only, no relayout (the surface keeps its id and size). Feature-detected so an older host
228
- // without the hook just no-ops (fall back to re-assigning UIImage.src). See docs/canvas-contract.md.
229
- if (this._uiBound) _creatorUI.refreshCanvasSurface?.(surfaceId)
230
- return this
231
- }
232
-
233
- /** Copy the current pixels into a standalone, immutable `Bitmap` — independent of this canvas, so
234
- * later drawing/`reset()` never touches it. Draw it back with `drawImage()`, export it with
235
- * `toDataURL()`, or use it to "flatten" an ever-growing drawing so re-bakes stay O(1):
236
- * const snap = canvas.toBitmap()
237
- * canvas.reset(); canvas.drawImage(snap, 0, 0) // one op replaces the whole history
238
- * // …keep drawing on top; snap.destroy() once it's been drawn in. */
239
- toBitmap(): Bitmap {
240
- return new Bitmap(_creatorCanvas.snapshot(this._bakeSurface()), this.width, this.height, this.pixelRatio)
241
- }
242
-
243
- /** Encode the current pixels to an image `File` — 'image/png' (default) or 'image/jpeg'. The File
244
- * is an opaque host buffer handle (`name`/`size` only): append it to a FormData to upload, load it
245
- * as a texture (`Texture2D.load(file)`), or hand it to a share/save sheet. */
246
- toFile(name = "canvas.png", type = "image/png"): Promise<File> {
247
- const surfaceId = this._bakeSurface()
248
- return new Promise<File>((res, rej) => {
249
- _creatorCanvas.toFile(surfaceId, type, (bufferId, size) => res(new File(bufferId, name, size)), rej)
250
- })
251
- }
252
-
253
- destroy(): void {
254
- if (this._surfaceId) _creatorCanvas.destroySurface(this._surfaceId)
255
- this._tex2d?.destroy()
256
- // The 3D texture (if any) is owned by creator-gl's engine and freed at its teardown — no per-texture
257
- // destroy in the 3D API — so we just drop our cached id here.
258
- this._surfaceId = 0
259
- this._tex2d = undefined
260
- this._tex3dId = 0
261
- }
262
- }
263
-
264
- /** Duck-type guard so consumers can accept a Canvas anywhere a texture source is expected. */
265
- export const isCanvas = (v: unknown): v is Canvas =>
266
- typeof v === "object" && v !== null && (v as { __canvas?: unknown }).__canvas === true
267
-
268
- /** An immutable RGBA8 snapshot of a canvas, produced by `Canvas.toBitmap()`. It owns its own baked
269
- * surface (a copy), so the source canvas can keep drawing or `reset()` without affecting it. Use it
270
- * to stamp/blit back (`canvas.drawImage(bitmap, …)`), to export (`bitmap.toDataURL()`), or as a
271
- * cheap "layer" you composite. Call `destroy()` when done — it holds a native surface. */
272
- export class Bitmap {
273
- readonly __bitmap = true as const
274
- /** @internal — a standalone `_creatorCanvas` surface (RGBA8), independent of any Canvas. */
275
- readonly _surfaceId: number
276
- /** Logical width, matching the Canvas it was captured from (pixelRatio is crispness, not size). */
277
- readonly width: number
278
- readonly height: number
279
- readonly pixelRatio: number
280
-
281
- constructor(surfaceId: number, width: number, height: number, pixelRatio: number) {
282
- this._surfaceId = surfaceId
283
- this.width = width
284
- this.height = height
285
- this.pixelRatio = pixelRatio
286
- }
287
-
288
- /** Device-pixel dimensions of the stored bitmap (`width * pixelRatio`, rounded). */
289
- get pixelWidth(): number { return Math.round(this.width * this.pixelRatio) }
290
- get pixelHeight(): number { return Math.round(this.height * this.pixelRatio) }
291
-
292
- /** Encode to an image `File` — 'image/png' (default) or 'image/jpeg'. See `Canvas.toFile`. */
293
- toFile(name = "canvas.png", type = "image/png"): Promise<File> {
294
- return new Promise<File>((res, rej) => {
295
- _creatorCanvas.toFile(this._surfaceId, type, (bufferId, size) => res(new File(bufferId, name, size)), rej)
296
- })
297
- }
298
-
299
- /** Free the native surface. The bitmap must not be drawn or encoded afterwards. */
300
- destroy(): void { _creatorCanvas.destroySurface(this._surfaceId) }
301
- }
302
-
303
- /** Duck-type guard for a Bitmap (see `isCanvas`). */
304
- export const isBitmap = (v: unknown): v is Bitmap =>
305
- typeof v === "object" && v !== null && (v as { __bitmap?: unknown }).__bitmap === true
@@ -1,86 +0,0 @@
1
- // Compile-time injection of an aspect's runtime name. A user aspect carries its accessor name in the
2
- // (type-erased) generic — `class Health extends Aspect<'health', Sprite> {…}` — so neither the
3
- // bundler nor the runtime can see it after types are stripped. This pass injects the matching
4
- // `static aspect = "health"` so node.aspect()/node.health work at runtime, exactly like the SDK's
5
- // built-in aspects declare it by hand. Systems (`class Hud extends System<'hud'>`) are the same
6
- // thing on a scene and get the same injection.
7
- //
8
- // Runs on PROJECT files only (the SDK's own aspects already declare `static aspect`). Idempotent:
9
- // skips a class that already declares one. String-based, like assetMacro — no parser dependency.
10
- // The generic tail is walked with a bracket counter (not a regex) because the third parameter is
11
- // an event map — an object type with braces and `=>` arrows: `Aspect<'barrel', Node, { explode:
12
- // (b: Barrel) => void }>` — and `> implements Hittable {` may follow the closing bracket.
13
-
14
- // `class X extends Aspect<'name'` / `extends System<'name'` — up to and including the name literal.
15
- const HEAD_RE = /\bclass\s+\w+\s+extends\s+(?:Aspect|System)\s*<\s*(["'])((?:[^"'\\]|\\.)*)\1/g
16
-
17
- /** Cheap pre-check so we don't scan files that define no aspects. */
18
- export const hasAspectExtends = (src: string): boolean => /\bextends\s+(?:Aspect|System)\s*</.test(src)
19
-
20
- /** Inject `static aspect = "<name>"` into each `class … extends Aspect<'<name>', …>` (or System). */
21
- export const injectAspectNames = (src: string): string => {
22
- let out = ""
23
- let last = 0
24
- HEAD_RE.lastIndex = 0
25
- let m: RegExpExecArray | null
26
- while ((m = HEAD_RE.exec(src)) !== null) {
27
- const braceEnd = classBodyStart(src, m.index + m[0].length)
28
- if (braceEnd < 0) continue
29
- HEAD_RE.lastIndex = braceEnd
30
- if (!classBodyDeclaresAspect(src, braceEnd)) {
31
- out += src.slice(last, braceEnd) + ` static aspect = ${JSON.stringify(m[2])};`
32
- last = braceEnd
33
- }
34
- }
35
- return last === 0 ? src : out + src.slice(last)
36
- }
37
-
38
- /** From just past the name literal (inside the `<…>`), walk to the end of the type-argument list,
39
- * then past an optional `implements …` clause, and return the index just past the class body's
40
- * opening `{` — or -1 if the source doesn't look like a class header. */
41
- const classBodyStart = (src: string, from: number): number => {
42
- let angle = 1 // we are inside the `<` that HEAD_RE opened
43
- let i = from
44
- for (; i < src.length && angle > 0; i++) {
45
- const c = src[i]
46
- if (c === '"' || c === "'" || c === "`") { i = skipString(src, i) - 1; continue }
47
- if (c === "=" && src[i + 1] === ">") { i++; continue } // an arrow, not a closing bracket
48
- if (c === "<") angle++
49
- else if (c === ">") angle--
50
- }
51
- if (angle !== 0) return -1
52
- // `>` closed the generic; the class body's `{` follows, possibly after `implements A, B<C>`.
53
- // Scan to the first `{` at angle depth 0.
54
- angle = 0
55
- for (; i < src.length; i++) {
56
- const c = src[i]
57
- if (c === "<") angle++
58
- else if (c === ">") angle--
59
- else if (c === "{" && angle === 0) return i + 1
60
- else if (c === ";" || c === "}") return -1
61
- }
62
- return -1
63
- }
64
-
65
- /** Index just past a string literal starting at `at` (its opening quote). */
66
- const skipString = (src: string, at: number): number => {
67
- const q = src[at]
68
- let i = at + 1
69
- for (; i < src.length; i++) {
70
- if (src[i] === "\\") { i++; continue }
71
- if (src[i] === q) return i + 1
72
- }
73
- return i
74
- }
75
-
76
- /** Does the class body starting just after `from` (its `{`) already declare a `static aspect`? */
77
- const classBodyDeclaresAspect = (src: string, from: number): boolean => {
78
- let depth = 1
79
- let i = from
80
- for (; i < src.length && depth > 0; i++) {
81
- const c = src[i]
82
- if (c === "{") depth++
83
- else if (c === "}") depth--
84
- }
85
- return /\bstatic\b[^;{}()=]*\baspect\b/.test(src.slice(from, i))
86
- }