lecodes-sdk 1.2.0 → 2.0.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 (260) hide show
  1. package/README.md +5 -2
  2. package/dist/editor.d.ts +12 -0
  3. package/dist/global.d.ts +4 -8
  4. package/dist/host.d.ts +2 -3
  5. package/dist/types/animate/tween/Animation.d.ts +0 -3
  6. package/dist/types/animate/tween/animateValue.d.ts +4 -2
  7. package/dist/types/animate/tween/easing.d.ts +8 -0
  8. package/dist/types/animate/tween/spec.d.ts +15 -7
  9. package/dist/types/audio/audio.d.ts +2 -1
  10. package/dist/types/canvas/Canvas.d.ts +40 -108
  11. package/dist/types/canvas/gen/cssColor.d.ts +17 -0
  12. package/dist/types/canvas/gen/recorder.d.ts +118 -0
  13. package/dist/types/canvas/gen/spec.d.ts +144 -0
  14. package/dist/types/core/color.d.ts +3 -1
  15. package/dist/types/core/pins.d.ts +18 -0
  16. package/dist/types/g2/Node2D.d.ts +5 -8
  17. package/dist/types/g2/Scene2D.d.ts +6 -2
  18. package/dist/types/gl/Foliage.d.ts +30 -7
  19. package/dist/types/gl/Light.d.ts +8 -0
  20. package/dist/types/gl/Lightmap.d.ts +13 -2
  21. package/dist/types/gl/Material.d.ts +17 -3
  22. package/dist/types/gl/Model.d.ts +6 -2
  23. package/dist/types/gl/Node.d.ts +3 -6
  24. package/dist/types/gl/Scene.d.ts +41 -13
  25. package/dist/types/gl/Texture.d.ts +1 -1
  26. package/dist/types/gl/animation/Locomotion.d.ts +8 -1
  27. package/dist/types/inject.d.ts +11 -11
  28. package/dist/types/inject.editor.d.ts +1 -0
  29. package/dist/types/net/core.d.ts +7 -0
  30. package/dist/types/plugin.d.ts +76 -0
  31. package/dist/types/plugins/gen/camera/sdk/camera.d.ts +24 -0
  32. package/dist/types/plugins/gen/camera/sdk/camera.gen.d.ts +25 -0
  33. package/dist/types/plugins/{geolocation.d.ts → gen/geolocation/sdk/geolocation.d.ts} +2 -20
  34. package/dist/types/plugins/gen/geolocation/sdk/geolocation.gen.d.ts +31 -0
  35. package/dist/types/plugins/{map.d.ts → gen/map/sdk/map.d.ts} +9 -50
  36. package/dist/types/plugins/gen/map/sdk/map.gen.d.ts +53 -0
  37. package/dist/types/plugins/gen/push/sdk/push.d.ts +23 -0
  38. package/dist/types/plugins/gen/push/sdk/push.gen.d.ts +35 -0
  39. package/dist/types/plugins/{qr.d.ts → gen/qr-scanner/sdk/qr-scanner.d.ts} +2 -3
  40. package/dist/types/plugins/gen/qr-scanner/sdk/qr-scanner.gen.d.ts +15 -0
  41. package/dist/types/runtime/app.d.ts +9 -2
  42. package/dist/types/runtime/fetch.d.ts +2 -0
  43. package/dist/types/runtime/input.d.ts +1 -1
  44. package/dist/types/runtime/media.d.ts +6 -10
  45. package/dist/types/runtime/misc.d.ts +4 -1
  46. package/dist/types/runtime/net.d.ts +3 -2
  47. package/dist/types/runtime/touch.d.ts +32 -0
  48. package/dist/types/scene/defineScene.d.ts +43 -2
  49. package/dist/types/scene/editor.d.ts +52 -0
  50. package/dist/types/scene/gizmos.d.ts +7 -4
  51. package/dist/types/ui/NativeView.d.ts +6 -4
  52. package/dist/types/ui/UI.d.ts +1 -1
  53. package/dist/types/ui/UIBottomSheet.d.ts +6 -12
  54. package/dist/types/ui/UIButton.d.ts +12 -14
  55. package/dist/types/ui/UIContainer.d.ts +0 -6
  56. package/dist/types/ui/UIImage.d.ts +1 -4
  57. package/dist/types/ui/UIInput.d.ts +8 -24
  58. package/dist/types/ui/UIModal.d.ts +0 -2
  59. package/dist/types/ui/UINode.d.ts +70 -56
  60. package/dist/types/ui/UIPager.d.ts +28 -27
  61. package/dist/types/ui/UIPopover.d.ts +0 -2
  62. package/dist/types/ui/UIScreen.d.ts +12 -17
  63. package/dist/types/ui/UIScrollable.d.ts +1 -4
  64. package/dist/types/ui/UIText.d.ts +0 -2
  65. package/dist/types/ui/UIVideo.d.ts +3 -5
  66. package/dist/types/ui/UIVirtualizedList.d.ts +14 -16
  67. package/dist/types/ui/UIWidget.d.ts +10 -9
  68. package/dist/types/ui/colorKeys.gen.d.ts +9 -0
  69. package/dist/types/ui/presentable.d.ts +46 -32
  70. package/dist/types/ui/router.d.ts +18 -7
  71. package/dist/types/ui/styleColor.d.ts +1 -0
  72. package/dist/types/ui/transitions.d.ts +18 -0
  73. package/dist/types/ui/tree.d.ts +75 -0
  74. package/dist/types/version.d.ts +10 -0
  75. package/dist/types.json +1 -1
  76. package/package.json +12 -3
  77. package/prompts/2d.md +2 -6
  78. package/prompts/3d.md +1 -5
  79. package/prompts/README.md +1 -1
  80. package/prompts/canvas.md +9 -8
  81. package/prompts/compose.ts +1 -1
  82. package/prompts/core.md +3 -3
  83. package/prompts/design.md +1 -1
  84. package/prompts/dist/2d-game.md +473 -239
  85. package/prompts/dist/3d-app.md +553 -205
  86. package/prompts/dist/ar-app.md +435 -202
  87. package/prompts/dist/design.md +113 -95
  88. package/prompts/dist/ui-app.md +386 -170
  89. package/prompts/ui-design.md +2 -3
  90. package/prompts/ui.md +45 -37
  91. package/src/animate/tween/Animation.ts +34 -150
  92. package/src/animate/tween/Timeline.ts +175 -175
  93. package/src/animate/tween/animateValue.ts +6 -3
  94. package/src/animate/tween/easing.ts +10 -3
  95. package/src/animate/tween/spec.ts +41 -15
  96. package/src/audio/Sound.ts +3 -3
  97. package/src/audio/audio.ts +2 -1
  98. package/src/bridges/2d.d.ts +317 -0
  99. package/src/bridges/app.d.ts +91 -0
  100. package/src/bridges/audio.d.ts +97 -0
  101. package/src/bridges/canvas.d.ts +79 -0
  102. package/src/bridges/device.d.ts +72 -0
  103. package/src/bridges/fetch.d.ts +80 -0
  104. package/src/bridges/files.d.ts +70 -0
  105. package/src/bridges/gl.d.ts +1133 -0
  106. package/src/bridges/input.d.ts +72 -0
  107. package/src/bridges/media.d.ts +55 -0
  108. package/src/bridges/nav.d.ts +71 -0
  109. package/src/bridges/net.d.ts +52 -0
  110. package/src/bridges/service.d.ts +52 -0
  111. package/src/bridges/socket.d.ts +31 -0
  112. package/src/bridges/storage.d.ts +33 -0
  113. package/src/bridges/tree.d.ts +301 -0
  114. package/src/bridges/types.d.ts +49 -0
  115. package/src/canvas/Canvas.ts +114 -159
  116. package/src/canvas/gen/cssColor.ts +224 -0
  117. package/src/canvas/gen/recorder.ts +212 -0
  118. package/src/canvas/gen/spec.ts +201 -0
  119. package/src/chisel.ts +193 -0
  120. package/src/compile/assetMacro.ts +1 -1
  121. package/src/compile/bundler.ts +11 -2
  122. package/src/compile/compileProject.ts +43 -4
  123. package/src/compile/fontMacro.ts +3 -4
  124. package/src/compile/header.ts +26 -5
  125. package/src/compile/index.ts +3 -1
  126. package/src/compile/liteMaterial.ts +1 -1
  127. package/src/compile/sceneEditor.ts +11 -26
  128. package/src/core/color.ts +73 -30
  129. package/src/core/pins.ts +51 -0
  130. package/src/core/signals.ts +8 -1
  131. package/src/g2/CharacterController2D.ts +3 -3
  132. package/src/g2/Node2D.ts +57 -39
  133. package/src/g2/Physics2D.ts +2 -2
  134. package/src/g2/Scene2D.ts +35 -23
  135. package/src/g2/Texture2D.ts +1 -1
  136. package/src/g2/loop.ts +4 -4
  137. package/src/gl/CameraPlace.ts +52 -52
  138. package/src/gl/Foliage.ts +72 -17
  139. package/src/gl/Geometry.ts +1 -2
  140. package/src/gl/Light.ts +10 -0
  141. package/src/gl/Lightmap.ts +45 -29
  142. package/src/gl/Material.ts +95 -51
  143. package/src/gl/Mesh.ts +120 -120
  144. package/src/gl/Model.ts +21 -16
  145. package/src/gl/Node.ts +91 -24
  146. package/src/gl/Particles.ts +1 -1
  147. package/src/gl/Scene.ts +100 -44
  148. package/src/gl/Texture.ts +8 -7
  149. package/src/gl/animation/AnimationClip.ts +1 -1
  150. package/src/gl/animation/DynamicBone.ts +482 -482
  151. package/src/gl/animation/Locomotion.ts +8 -3
  152. package/src/gl/nav/NavMesh.ts +3 -4
  153. package/src/gl/physics/Physics.ts +2 -2
  154. package/src/gl/physics/physicsEvents.ts +3 -3
  155. package/src/gl/scenarios.ts +291 -291
  156. package/src/gl/terrain/Terrain.ts +4 -5
  157. package/src/gl/touch.ts +14 -15
  158. package/src/host.d.ts +2 -3
  159. package/src/inject.editor.ts +7 -0
  160. package/src/inject.ts +13 -16
  161. package/src/net/core.ts +6 -5
  162. package/src/net/index.ts +1 -1
  163. package/src/net/replication.ts +1 -1
  164. package/src/plugin.ts +191 -0
  165. package/src/plugins/gen/camera/contract.d.ts +27 -0
  166. package/src/plugins/gen/camera/sdk/camera.gen.ts +46 -0
  167. package/src/plugins/gen/camera/sdk/camera.ts +57 -0
  168. package/src/plugins/gen/geolocation/contract.d.ts +50 -0
  169. package/src/plugins/gen/geolocation/sdk/geolocation.gen.ts +54 -0
  170. package/src/plugins/{geolocation.ts → gen/geolocation/sdk/geolocation.ts} +22 -43
  171. package/src/plugins/gen/map/contract.d.ts +144 -0
  172. package/src/plugins/gen/map/sdk/map.gen.ts +88 -0
  173. package/src/plugins/{map.ts → gen/map/sdk/map.ts} +68 -102
  174. package/src/plugins/gen/push/contract.d.ts +61 -0
  175. package/src/plugins/gen/push/sdk/push.gen.ts +60 -0
  176. package/src/plugins/gen/push/sdk/push.ts +105 -0
  177. package/src/plugins/gen/qr-scanner/contract.d.ts +16 -0
  178. package/src/plugins/gen/qr-scanner/sdk/qr-scanner.gen.ts +29 -0
  179. package/src/plugins/gen/qr-scanner/sdk/qr-scanner.ts +52 -0
  180. package/src/plugins/permission.ts +5 -4
  181. package/src/runtime/app.ts +20 -9
  182. package/src/runtime/appEvents.ts +5 -4
  183. package/src/runtime/channel.ts +18 -15
  184. package/src/runtime/clipboard.ts +4 -3
  185. package/src/runtime/datetime.ts +2 -1
  186. package/src/runtime/device.ts +17 -15
  187. package/src/runtime/fetch.ts +30 -20
  188. package/src/runtime/files.ts +16 -15
  189. package/src/runtime/input.ts +12 -10
  190. package/src/runtime/media.ts +50 -46
  191. package/src/runtime/misc.ts +7 -3
  192. package/src/runtime/net.ts +8 -7
  193. package/src/runtime/rpc.ts +1 -3
  194. package/src/runtime/service.ts +19 -14
  195. package/src/runtime/share.ts +4 -3
  196. package/src/runtime/storage.ts +6 -4
  197. package/src/runtime/touch.ts +32 -0
  198. package/src/scene/defineScene.ts +61 -365
  199. package/src/scene/editor.ts +408 -0
  200. package/src/scene/editorPlugins.ts +3 -3
  201. package/src/scene/gizmos.ts +15 -9
  202. package/src/server/db/marci/query.ts +1 -1
  203. package/src/server/host.ts +1 -1
  204. package/src/server/runtime.ts +1 -1
  205. package/src/ui/NativeView.ts +72 -25
  206. package/src/ui/UI.ts +3 -3
  207. package/src/ui/UIBottomSheet.ts +16 -17
  208. package/src/ui/UIButton.ts +54 -16
  209. package/src/ui/UIContainer.ts +0 -6
  210. package/src/ui/UIImage.ts +34 -30
  211. package/src/ui/UIInput.ts +29 -37
  212. package/src/ui/UIModal.ts +1 -3
  213. package/src/ui/UINode.ts +347 -297
  214. package/src/ui/UIPager.ts +93 -78
  215. package/src/ui/UIPopover.ts +0 -2
  216. package/src/ui/UIScreen.ts +41 -36
  217. package/src/ui/UIScrollable.ts +19 -13
  218. package/src/ui/UISpacer.ts +1 -1
  219. package/src/ui/UITabs.ts +8 -6
  220. package/src/ui/UIText.ts +7 -17
  221. package/src/ui/UIVideo.ts +30 -27
  222. package/src/ui/UIVirtualizedList.ts +58 -59
  223. package/src/ui/UIWidget.ts +38 -18
  224. package/src/ui/colorKeys.gen.ts +37 -0
  225. package/src/ui/fonts.ts +2 -2
  226. package/src/ui/presentable.ts +59 -42
  227. package/src/ui/router.ts +52 -35
  228. package/src/ui/styleColor.ts +56 -0
  229. package/src/ui/theme.ts +7 -6
  230. package/src/ui/transitions.ts +249 -0
  231. package/src/ui/tree.ts +346 -0
  232. package/src/version.ts +24 -0
  233. package/tests/helpers/engineWorld.ts +11 -0
  234. package/tests/helpers/fakeTree.ts +353 -0
  235. package/tests/helpers/hostStubs.ts +31 -0
  236. package/tests/helpers/index.ts +14 -0
  237. package/tests/helpers/memoryMarci.ts +124 -0
  238. package/tests/helpers/phases.ts +23 -0
  239. package/tests/helpers/preload.ts +18 -0
  240. package/tests/helpers/stubApp.ts +2 -0
  241. package/tests/helpers/stubDevice.ts +2 -0
  242. package/tests/helpers/stubFetch.ts +2 -0
  243. package/tests/helpers/stubInput.ts +2 -0
  244. package/dist/inject.js +0 -4629
  245. package/dist/types/core/registry.d.ts +0 -7
  246. package/dist/types/plugins/camera.d.ts +0 -25
  247. package/dist/types/plugins/push.d.ts +0 -46
  248. package/src/bridges.d.ts +0 -1769
  249. package/src/compile/__tests__/assetIconMacro.test.ts +0 -219
  250. package/src/compile/__tests__/assetMacro.test.ts +0 -100
  251. package/src/compile/__tests__/assetName.test.ts +0 -55
  252. package/src/compile/__tests__/compile.test.ts +0 -310
  253. package/src/compile/__tests__/detectEntry.test.ts +0 -151
  254. package/src/compile/__tests__/fontMacro.test.ts +0 -199
  255. package/src/compile/__tests__/serverSplit.test.ts +0 -27
  256. package/src/core/__tests__/stateMachine.test.ts +0 -132
  257. package/src/core/registry.ts +0 -23
  258. package/src/plugins/camera.ts +0 -81
  259. package/src/plugins/push.ts +0 -132
  260. package/src/plugins/qr.ts +0 -73
package/src/ui/tree.ts ADDED
@@ -0,0 +1,346 @@
1
+ // The SDK's side of the tree of truth (docs/plans/hosts-unification-plan.md, phase 9): the numbers shared
2
+ // with runtime/native (creator-pkg/tree-events.h — mirrored VERBATIM, `bun run check:tree-consts`),
3
+ // the pin table that keeps the element of every attached node alive and findable by id, the
4
+ // destination registry, and the ONE emitter every event of `_creatorTree` comes through.
5
+ //
6
+ // Ownership (tree.h): an attached node belongs to the runtime's tree and its element is PINNED here
7
+ // (so `children` returns the same objects and listeners survive the app dropping its reference); a
8
+ // detached root belongs to its element — when that is collected, the handle's finalizer frees the
9
+ // node. The runtime tells us when it detaches a root (TREE_EVENT_DETACHED) or frees nodes underneath
10
+ // their handles (TREE_EVENT_FREED); everything else we pin / unpin ourselves.
11
+
12
+ // ---- emit kinds (id = the node, 0 for world-level events) ----------------------------------------
13
+ export const TREE_EVENT_LAYOUT = 1
14
+ export const TREE_EVENT_TOUCH_START = 2
15
+ export const TREE_EVENT_CLICK = 3
16
+ export const TREE_EVENT_LONG_PRESS = 4
17
+ export const TREE_EVENT_TOUCH_MOVE = 5
18
+ export const TREE_EVENT_TOUCH_END = 6
19
+ export const TREE_EVENT_TOUCH_CANCEL = 7
20
+ export const TREE_EVENT_SCROLL = 8
21
+ export const TREE_EVENT_OVERSCROLL = 9
22
+ export const TREE_EVENT_SCROLL_RELEASE = 10
23
+ export const TREE_EVENT_REFRESH = 11
24
+ export const TREE_EVENT_CHANGE = 12
25
+ export const TREE_EVENT_FOCUS = 13
26
+ export const TREE_EVENT_BLUR = 14
27
+ export const TREE_EVENT_SUBMIT = 15
28
+ export const TREE_EVENT_OVERLAY_TAP = 16
29
+ export const TREE_EVENT_DETENT = 17
30
+ export const TREE_EVENT_OPEN = 18
31
+ export const TREE_EVENT_CLOSE = 19
32
+ export const TREE_EVENT_BACK = 20
33
+ export const TREE_EVENT_PAGER_SELECT = 21
34
+ export const TREE_EVENT_PAGER_POP = 22
35
+ export const TREE_EVENT_VLIST_SYNC = 23
36
+ export const TREE_EVENT_VLIST_EDGE = 24
37
+ export const TREE_EVENT_VIEW_EVENT = 25
38
+ export const TREE_EVENT_RESIZE = 26
39
+ export const TREE_EVENT_ROUTER_CHANGE = 27
40
+ export const TREE_EVENT_SCENE_TOUCH_START = 28
41
+ export const TREE_EVENT_SCENE_CLICK = 29
42
+ export const TREE_EVENT_DETACHED = 30
43
+ export const TREE_EVENT_FREED = 31
44
+ export const TREE_EVENT_HOVER_ENTER = 32
45
+ export const TREE_EVENT_HOVER_MOVE = 33
46
+ export const TREE_EVENT_HOVER_END = 34
47
+ export const TREE_EVENT_HOVER_CANCEL = 35
48
+
49
+ // ---- setFlags(id, mask) ---------------------------------------------------------------------------
50
+ export const TREE_FLAG_INTERACTIVE = 1 << 0
51
+ export const TREE_FLAG_CLICK = 1 << 1
52
+ export const TREE_FLAG_LONG_PRESS = 1 << 2
53
+ export const TREE_FLAG_LAYOUT = 1 << 3
54
+ export const TREE_FLAG_SCROLL = 1 << 4
55
+ export const TREE_FLAG_OVERSCROLL = 1 << 5
56
+ export const TREE_FLAG_SCROLL_RELEASE = 1 << 6
57
+ export const TREE_FLAG_REFRESH = 1 << 7
58
+ export const TREE_FLAG_CHANGE = 1 << 8
59
+ export const TREE_FLAG_FOCUS = 1 << 9
60
+ export const TREE_FLAG_BLUR = 1 << 10
61
+ export const TREE_FLAG_SUBMIT = 1 << 11
62
+ export const TREE_FLAG_OVERLAY_TAP = 1 << 12
63
+ export const TREE_FLAG_DETENT = 1 << 13
64
+ export const TREE_FLAG_KEEP_ALIVE = 1 << 14
65
+ export const TREE_FLAG_BACK = 1 << 15
66
+ export const TREE_FLAG_VLIST_END = 1 << 16
67
+ export const TREE_FLAG_VLIST_START = 1 << 17
68
+ export const TREE_FLAG_HOVER = 1 << 18
69
+
70
+ // ---- the touchStart / longPress answer -------------------------------------------------------------
71
+ export const TREE_TRACK_CLAIM_MASK = 0xFF
72
+ export const TREE_TRACK_TRACKED = 1 << 8
73
+ export const TREE_TRACK_MOVE = 1 << 9
74
+ export const TREE_TRACK_HANDLED = 1 << 10
75
+
76
+ // ---- destination kinds -------------------------------------------------------------------------------
77
+ export const TREE_DEST_SCREEN = 0
78
+ export const TREE_DEST_SCENE3D = 1
79
+ export const TREE_DEST_SCENE2D = 2
80
+ export const TREE_DEST_NATIVE = 3
81
+ export const TREE_DEST_VIDEO = 4
82
+ export const TREE_DEST_NONE = 0xFF
83
+
84
+ // Owned-handle kinds (owned.h OwnedKind) — the `_creatorApp.setFreedEmitter` channel names the kind
85
+ // whose resources the runtime freed underneath their wrappers (core/pins.ts).
86
+ export const OWNED_KIND_TREE = 0
87
+ export const OWNED_KIND_FETCH = 1
88
+ export const OWNED_KIND_GL_MATERIAL = 2
89
+ export const OWNED_KIND_GL_TEXTURE = 3
90
+ export const OWNED_KIND_GL_ENTITY = 4
91
+ export const OWNED_KIND_ENTITY_2D = 5
92
+ export const OWNED_KIND_MEDIA = 6
93
+ export const OWNED_KIND_TWEEN = 7
94
+ export const OWNED_KIND_CANVAS = 8
95
+
96
+ // PanDirection (creator-pkg.h) — the low byte of a track answer.
97
+ import { DEAD_HANDLE } from "../core/pins"
98
+
99
+ const PAN: Record<string, number> = { "pan-up": 1, "pan-right": 2, "pan-down": 4, "pan-left": 8, "pan-x": 10, "pan-y": 5 }
100
+
101
+ // ---- the bridge ---------------------------------------------------------------------------------------
102
+ /** @internal The tree bridge. Every host that runs bundles installs it before the bundle evaluates. */
103
+ export const tree = (): typeof _creatorTree => _creatorTree
104
+
105
+ // ---- what an element / presentable must offer the emitter (duck-typed, all `_`-prefixed so chisel keeps them)
106
+ /** @internal */
107
+ export interface TreeElement {
108
+ /** The owned handle (`_h.id` = the node id; DEAD_HANDLE once the node is gone). */
109
+ _h: Handle
110
+ _emitLayout?(box: { left: number, top: number, width: number, height: number }): void
111
+ _emitTouchStart?(pointerId: number, x: number, y: number): TrackLike | null
112
+ _emitClick?(pointerId: number, x: number, y: number): void
113
+ _emitLongPress?(pointerId: number, x: number, y: number): { track: TrackLike | null } | null
114
+ _emitMouseEnter?(x: number, y: number): HoverTrackLike | null
115
+ _emitScroll?(position: number): void
116
+ _emitOverscroll?(delta: number): void
117
+ _emitScrollRelease?(): void
118
+ _emitRefresh?(): unknown
119
+ _emitChange?(value: string): void
120
+ _emitFocus?(): void
121
+ _emitBlur?(): void
122
+ _emitSubmit?(value: string): void
123
+ _emitOverlayTap?(): void
124
+ _emitDetent?(index: number): void
125
+ _hostDidSelect?(index: number): void
126
+ _hostDidPop?(depth: number): void
127
+ _syncWindow?(unmountKeys: string[], mountKeys: string[]): void
128
+ _emitEdge?(end: boolean): void
129
+ _detached?(): void
130
+ _freed?(): void
131
+ /** The element's node got a native owner (it was inserted under a parent) / lost it. */
132
+ _pinned?(): void
133
+ _unpinned?(): void
134
+ _emitBack?(): boolean
135
+ }
136
+
137
+ /** @internal A track handler (runtime/touch.ts TrackHandler), as the emitter reads it. */
138
+ export interface TrackLike {
139
+ onMove?(pos: { clientX: number, clientY: number, deltaX: number, deltaY: number }): void
140
+ onEnd?(pos: { clientX: number, clientY: number, deltaX: number, deltaY: number }): void
141
+ onCancel?(): void
142
+ claim?: boolean | string
143
+ }
144
+ /** @internal A hover track handler (runtime/touch.ts HoverTrackHandler): TrackLike without a claim. */
145
+ export type HoverTrackLike = Omit<TrackLike, "claim">
146
+
147
+ /** @internal What a destination offers: the presentation lifecycle + the back handler. */
148
+ export interface TreeDest {
149
+ _emitOpen?(): void
150
+ _emitClose?(): void
151
+ _emitBack?(): boolean
152
+ }
153
+
154
+ export { DEAD_HANDLE }
155
+
156
+ // ---- pins -------------------------------------------------------------------------------------------------
157
+ const pins = new Map<number, TreeElement>()
158
+
159
+ /** @internal Keep `el` alive and findable while its node is attached / presented / shown. */
160
+ export const pin = (el: TreeElement | null | undefined): void => {
161
+ if (!el || el._h.id === 0) return
162
+ pins.set(el._h.id, el)
163
+ el._pinned?.()
164
+ }
165
+ /** @internal */
166
+ export const unpin = (id: number): void => {
167
+ const el = pins.get(id)
168
+ if (!el) return
169
+ pins.delete(id)
170
+ el._unpinned?.()
171
+ }
172
+ /** @internal The pinned element of a node id (an attached node's element), or undefined. */
173
+ export const byId = (id: number): TreeElement | undefined => pins.get(id)
174
+ /** @internal The elements of a list of ids (attached nodes only). */
175
+ export const elementsOf = (ids: number[]): any[] => {
176
+ const out: any[] = []
177
+ for (const id of ids) { const el = pins.get(id); if (el) out.push(el) }
178
+ return out
179
+ }
180
+
181
+ // ---- destinations ------------------------------------------------------------------------------------------
182
+ // Non-screen presentables (scenes, native views) register here under their engine id; screens and
183
+ // video nodes resolve through the pins (their destination id IS the node id).
184
+ const dests = new Map<string, TreeDest>()
185
+ const destKey = (kind: number, id: number): string => `${kind}:${id}`
186
+
187
+ /** @internal */
188
+ export const registerDest = (kind: number, id: number, p: TreeDest): void => { dests.set(destKey(kind, id), p) }
189
+ /** @internal */
190
+ export const unregisterDest = (kind: number, id: number): void => { dests.delete(destKey(kind, id)) }
191
+ /** @internal The presentable a (kind, id) pair names. */
192
+ export const resolveDest = (kind: number, id: number): (TreeDest & Partial<TreeElement>) | undefined => {
193
+ if (kind === TREE_DEST_SCREEN || kind === TREE_DEST_VIDEO) return pins.get(id) as any
194
+ return dests.get(destKey(kind, id)) as any
195
+ }
196
+
197
+ // ---- world-level hooks (set by the modules that own them) --------------------------------------------------
198
+ type SceneTouchStart = (pointerId: number, x: number, y: number, entityId: number) => TrackLike | null
199
+ type SceneClick = (pointerId: number, x: number, y: number, entityId: number) => void
200
+ let sceneTouchStart: SceneTouchStart | null = null
201
+ let sceneClick: SceneClick | null = null
202
+ /** @internal gl/touch.ts: the scene-level pointer dispatch. */
203
+ export const setSceneTouchHandlers = (start: SceneTouchStart | null, click: SceneClick | null): void => {
204
+ sceneTouchStart = start
205
+ sceneClick = click
206
+ }
207
+
208
+ const resizeListeners: ((width: number, height: number) => void)[] = []
209
+ /** @internal runtime/device.ts */
210
+ export const onTreeResize = (cb: (width: number, height: number) => void): (() => void) => {
211
+ resizeListeners.push(cb)
212
+ return () => { const i = resizeListeners.indexOf(cb); if (i >= 0) resizeListeners.splice(i, 1) }
213
+ }
214
+
215
+ let routerChange: ((kind: number, id: number) => void) | null = null
216
+ /** @internal ui/router.ts */
217
+ export const setRouterChangeHandler = (cb: ((kind: number, id: number) => void) | null): void => { routerChange = cb }
218
+
219
+ let appBack: (() => void) | null = null
220
+ /** @internal runtime/app.ts — the app-level back handler (the end of the runtime's back chain). */
221
+ export const setAppBackHandler = (cb: (() => void) | null): void => { appBack = cb }
222
+
223
+ const nativeViews = new Map<number, { _emitViewEvent(event: string, data?: unknown): void }>()
224
+ /** @internal ui/NativeView.ts: the instance a viewId names (host → view events). */
225
+ export const registerNativeView = (viewId: number, v: { _emitViewEvent(event: string, data?: unknown): void }): void => { nativeViews.set(viewId, v) }
226
+ /** @internal */
227
+ export const unregisterNativeView = (viewId: number): void => { nativeViews.delete(viewId) }
228
+
229
+ // ---- gestures -----------------------------------------------------------------------------------------------
230
+ // The track handler of every pointer a listener claimed (`ev.track(...)`): the runtime feeds the
231
+ // pointer's moves / end / cancel here by pointer id — nothing of it is retained natively.
232
+ const trackers = new Map<number, TrackLike>()
233
+
234
+ // The hover's own slot — the cursor is one, and it is NOT a gesture: a mouse drag keeps its touch
235
+ // tracker under pointer 0 while the hover under the same cursor runs here, independently.
236
+ let hoverTracker: HoverTrackLike | null = null
237
+
238
+ const hoverAnswer = (handler: HoverTrackLike | null | undefined): number => {
239
+ hoverTracker = handler ?? null
240
+ if (!handler) return 0
241
+ return TREE_TRACK_TRACKED | (handler.onMove ? TREE_TRACK_MOVE : 0)
242
+ }
243
+
244
+ const trackAnswer = (pointerId: number, handler: TrackLike | null | undefined): number => {
245
+ if (!handler) return 0
246
+ trackers.set(pointerId, handler)
247
+ let r = TREE_TRACK_TRACKED
248
+ if (handler.onMove) r |= TREE_TRACK_MOVE
249
+ const claim = handler.claim
250
+ if (claim === true || claim === "all") r |= 15
251
+ else if (typeof claim === "string") r |= PAN[claim] ?? 0
252
+ return r
253
+ }
254
+
255
+ // ---- the emitter --------------------------------------------------------------------------------------------
256
+ let installed = false
257
+ const emit = (id: number, kind: number, a?: any, b?: any, c?: any, d?: any, e?: any): any => {
258
+ switch (kind) {
259
+ case TREE_EVENT_LAYOUT: pins.get(id)?._emitLayout?.({ left: a, top: b, width: c, height: d }); return
260
+ case TREE_EVENT_TOUCH_START: return trackAnswer(a, pins.get(id)?._emitTouchStart?.(a, b, c))
261
+ case TREE_EVENT_CLICK: pins.get(id)?._emitClick?.(a, b, c); return
262
+ case TREE_EVENT_LONG_PRESS: {
263
+ const r = pins.get(id)?._emitLongPress?.(a, b, c)
264
+ if (!r) return 0
265
+ return TREE_TRACK_HANDLED | trackAnswer(a, r.track)
266
+ }
267
+ case TREE_EVENT_TOUCH_MOVE: trackers.get(a)?.onMove?.({ clientX: b, clientY: c, deltaX: d, deltaY: e }); return
268
+ case TREE_EVENT_TOUCH_END: {
269
+ const t = trackers.get(a)
270
+ trackers.delete(a)
271
+ t?.onEnd?.({ clientX: b, clientY: c, deltaX: d, deltaY: e })
272
+ return
273
+ }
274
+ case TREE_EVENT_TOUCH_CANCEL: {
275
+ const t = trackers.get(a)
276
+ trackers.delete(a)
277
+ t?.onCancel?.()
278
+ return
279
+ }
280
+ case TREE_EVENT_HOVER_ENTER: return hoverAnswer(pins.get(id)?._emitMouseEnter?.(a, b))
281
+ case TREE_EVENT_HOVER_MOVE: hoverTracker?.onMove?.({ clientX: a, clientY: b, deltaX: c, deltaY: d }); return
282
+ case TREE_EVENT_HOVER_END: {
283
+ const t = hoverTracker
284
+ hoverTracker = null
285
+ t?.onEnd?.({ clientX: a, clientY: b, deltaX: c, deltaY: d })
286
+ return
287
+ }
288
+ case TREE_EVENT_HOVER_CANCEL: {
289
+ const t = hoverTracker
290
+ hoverTracker = null
291
+ t?.onCancel?.()
292
+ return
293
+ }
294
+ case TREE_EVENT_SCROLL: pins.get(id)?._emitScroll?.(a); return
295
+ case TREE_EVENT_OVERSCROLL: pins.get(id)?._emitOverscroll?.(a); return
296
+ case TREE_EVENT_SCROLL_RELEASE: pins.get(id)?._emitScrollRelease?.(); return
297
+ case TREE_EVENT_REFRESH: return pins.get(id)?._emitRefresh?.()
298
+ case TREE_EVENT_CHANGE: pins.get(id)?._emitChange?.(a); return
299
+ case TREE_EVENT_FOCUS: pins.get(id)?._emitFocus?.(); return
300
+ case TREE_EVENT_BLUR: pins.get(id)?._emitBlur?.(); return
301
+ case TREE_EVENT_SUBMIT: pins.get(id)?._emitSubmit?.(a); return
302
+ case TREE_EVENT_OVERLAY_TAP: pins.get(id)?._emitOverlayTap?.(); return
303
+ case TREE_EVENT_DETENT: pins.get(id)?._emitDetent?.(a); return
304
+ case TREE_EVENT_OPEN: resolveDest(a, b)?._emitOpen?.(); return
305
+ case TREE_EVENT_CLOSE: resolveDest(a, b)?._emitClose?.(); return
306
+ case TREE_EVENT_BACK: {
307
+ if (a === TREE_DEST_NONE) {
308
+ if (id !== 0) return pins.get(id)?._emitBack?.() === true // a widget
309
+ if (!appBack) return false
310
+ appBack()
311
+ return true
312
+ }
313
+ return resolveDest(a, b)?._emitBack?.() === true
314
+ }
315
+ case TREE_EVENT_PAGER_SELECT: pins.get(id)?._hostDidSelect?.(a); return
316
+ case TREE_EVENT_PAGER_POP: pins.get(id)?._hostDidPop?.(a); return
317
+ case TREE_EVENT_VLIST_SYNC: pins.get(id)?._syncWindow?.(a, b); return
318
+ case TREE_EVENT_VLIST_EDGE: pins.get(id)?._emitEdge?.(!!a); return
319
+ case TREE_EVENT_VIEW_EVENT: nativeViews.get(a)?._emitViewEvent(b, c); return
320
+ case TREE_EVENT_RESIZE: for (const cb of resizeListeners.slice()) cb(a, b); return
321
+ case TREE_EVENT_ROUTER_CHANGE: routerChange?.(a, b); return
322
+ case TREE_EVENT_SCENE_TOUCH_START: return trackAnswer(a, sceneTouchStart?.(a, b, c, d))
323
+ case TREE_EVENT_SCENE_CLICK: sceneClick?.(a, b, c, d); return
324
+ case TREE_EVENT_DETACHED: {
325
+ const el = pins.get(id)
326
+ pins.delete(id)
327
+ el?._detached?.()
328
+ return
329
+ }
330
+ case TREE_EVENT_FREED: {
331
+ for (const fid of a as number[]) {
332
+ const el = pins.get(fid)
333
+ pins.delete(fid)
334
+ el?._freed?.()
335
+ }
336
+ return
337
+ }
338
+ }
339
+ }
340
+
341
+ /** @internal Install the emitter once per world (the first element / presentable calls it). */
342
+ export const ensureEmitter = (): void => {
343
+ if (installed) return
344
+ installed = true
345
+ _creatorTree.setEmitter(emit)
346
+ }
package/src/version.ts ADDED
@@ -0,0 +1,24 @@
1
+ // GENERATED by scripts/release/set-version.ts from sdk/package.json — do not edit by hand.
2
+ // The ONE version of the SDK + the runtime (the npm runtime set ships as one version; the C++
3
+ // twin is CREATOR_PKG_SDK_VERSION in creator-pkg/host.gen.h, emitted by gen:bridges from the
4
+ // same manifest). Its MAJOR is the bundle ↔ runtime contract: a bundle's `// sdk:` header line
5
+ // and a host's embedded version must agree on the major for the host to run the bundle; minor
6
+ // and patch never gate anything (features are detected, never versioned).
7
+ export const SDK_VERSION = "2.0.0"
8
+
9
+ /** The major of a semver string, or null when it is not one. */
10
+ export const sdkMajor = (version: string | null | undefined): number | null => {
11
+ const m = version?.match(/^(\d+)\.\d+\.\d+/)
12
+ return m ? Number(m[1]) : null
13
+ }
14
+
15
+ /** The `// sdk: <version>` line of a compiled bundle's header (sdk/src/compile/header.ts), read from
16
+ * its first bytes; null for a bundle compiled before the line existed (SDK 0.x / 1.x — the
17
+ * pre-tree contract, which no 2.x host runs). */
18
+ export const bundleSdkVersion = (head: string): string | null =>
19
+ head.slice(0, 2000).match(/^\/\/ sdk: (\d+\.\d+\.\d+\S*)/m)?.[1] ?? null
20
+
21
+ /** Whether a host embedding `hostVersion` can run a bundle whose header carries `bundleVersion`
22
+ * (null = no line = pre-2.0 contract): the majors must match. */
23
+ export const bundleRunsOn = (bundleVersion: string | null, hostVersion: string): boolean =>
24
+ sdkMajor(bundleVersion) !== null && sdkMajor(bundleVersion) === sdkMajor(hostVersion)
@@ -0,0 +1,11 @@
1
+ // A test file's 3D engine world is its `_creator` stub, and it ends with the file. The runtime frees
2
+ // a torn-down world's nodes and reports them (core/pins.ts); a stub does not, and every stub restarts
3
+ // its entity ids — so a node the SDK still pins (parented / in a scene: gl/Node.ts `nodes`) would
4
+ // answer for a later file's entity with the same id (`parent`, `children`, the rig an IK chain lands
5
+ // on). A file whose nodes get pinned reports its entity ids freed in its afterAll.
6
+ import { nodes } from "../../src/gl/Node"
7
+
8
+ /** Report the entity ids `first`..`last`, plus `extra`, freed — the runtime's world teardown. */
9
+ export const freeEntities = (first: number, last: number, ...extra: number[]): void => {
10
+ nodes.freed([ ...Array.from({ length: Math.max(0, last - first + 1) }, (_, i) => first + i), ...extra ])
11
+ }