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.
- package/README.md +5 -2
- package/dist/editor.d.ts +12 -0
- package/dist/global.d.ts +4 -8
- package/dist/host.d.ts +2 -3
- package/dist/types/animate/tween/Animation.d.ts +0 -3
- package/dist/types/animate/tween/animateValue.d.ts +4 -2
- package/dist/types/animate/tween/easing.d.ts +8 -0
- package/dist/types/animate/tween/spec.d.ts +15 -7
- package/dist/types/audio/audio.d.ts +2 -1
- package/dist/types/canvas/Canvas.d.ts +40 -108
- package/dist/types/canvas/gen/cssColor.d.ts +17 -0
- package/dist/types/canvas/gen/recorder.d.ts +118 -0
- package/dist/types/canvas/gen/spec.d.ts +144 -0
- package/dist/types/core/color.d.ts +3 -1
- package/dist/types/core/pins.d.ts +18 -0
- package/dist/types/g2/Node2D.d.ts +5 -8
- package/dist/types/g2/Scene2D.d.ts +6 -2
- package/dist/types/gl/Foliage.d.ts +30 -7
- package/dist/types/gl/Light.d.ts +8 -0
- package/dist/types/gl/Lightmap.d.ts +13 -2
- package/dist/types/gl/Material.d.ts +17 -3
- package/dist/types/gl/Model.d.ts +6 -2
- package/dist/types/gl/Node.d.ts +3 -6
- package/dist/types/gl/Scene.d.ts +41 -13
- package/dist/types/gl/Texture.d.ts +1 -1
- package/dist/types/gl/animation/Locomotion.d.ts +8 -1
- package/dist/types/inject.d.ts +11 -11
- package/dist/types/inject.editor.d.ts +1 -0
- package/dist/types/net/core.d.ts +7 -0
- package/dist/types/plugin.d.ts +76 -0
- package/dist/types/plugins/gen/camera/sdk/camera.d.ts +24 -0
- package/dist/types/plugins/gen/camera/sdk/camera.gen.d.ts +25 -0
- package/dist/types/plugins/{geolocation.d.ts → gen/geolocation/sdk/geolocation.d.ts} +2 -20
- package/dist/types/plugins/gen/geolocation/sdk/geolocation.gen.d.ts +31 -0
- package/dist/types/plugins/{map.d.ts → gen/map/sdk/map.d.ts} +9 -50
- package/dist/types/plugins/gen/map/sdk/map.gen.d.ts +53 -0
- package/dist/types/plugins/gen/push/sdk/push.d.ts +23 -0
- package/dist/types/plugins/gen/push/sdk/push.gen.d.ts +35 -0
- package/dist/types/plugins/{qr.d.ts → gen/qr-scanner/sdk/qr-scanner.d.ts} +2 -3
- package/dist/types/plugins/gen/qr-scanner/sdk/qr-scanner.gen.d.ts +15 -0
- package/dist/types/runtime/app.d.ts +9 -2
- package/dist/types/runtime/fetch.d.ts +2 -0
- package/dist/types/runtime/input.d.ts +1 -1
- package/dist/types/runtime/media.d.ts +6 -10
- package/dist/types/runtime/misc.d.ts +4 -1
- package/dist/types/runtime/net.d.ts +3 -2
- package/dist/types/runtime/touch.d.ts +32 -0
- package/dist/types/scene/defineScene.d.ts +43 -2
- package/dist/types/scene/editor.d.ts +52 -0
- package/dist/types/scene/gizmos.d.ts +7 -4
- package/dist/types/ui/NativeView.d.ts +6 -4
- package/dist/types/ui/UI.d.ts +1 -1
- package/dist/types/ui/UIBottomSheet.d.ts +6 -12
- package/dist/types/ui/UIButton.d.ts +12 -14
- package/dist/types/ui/UIContainer.d.ts +0 -6
- package/dist/types/ui/UIImage.d.ts +1 -4
- package/dist/types/ui/UIInput.d.ts +8 -24
- package/dist/types/ui/UIModal.d.ts +0 -2
- package/dist/types/ui/UINode.d.ts +70 -56
- package/dist/types/ui/UIPager.d.ts +28 -27
- package/dist/types/ui/UIPopover.d.ts +0 -2
- package/dist/types/ui/UIScreen.d.ts +12 -17
- package/dist/types/ui/UIScrollable.d.ts +1 -4
- package/dist/types/ui/UIText.d.ts +0 -2
- package/dist/types/ui/UIVideo.d.ts +3 -5
- package/dist/types/ui/UIVirtualizedList.d.ts +14 -16
- package/dist/types/ui/UIWidget.d.ts +10 -9
- package/dist/types/ui/colorKeys.gen.d.ts +9 -0
- package/dist/types/ui/presentable.d.ts +46 -32
- package/dist/types/ui/router.d.ts +18 -7
- package/dist/types/ui/styleColor.d.ts +1 -0
- package/dist/types/ui/transitions.d.ts +18 -0
- package/dist/types/ui/tree.d.ts +75 -0
- package/dist/types/version.d.ts +10 -0
- package/dist/types.json +1 -1
- package/package.json +12 -3
- package/prompts/2d.md +2 -6
- package/prompts/3d.md +1 -5
- package/prompts/README.md +1 -1
- package/prompts/canvas.md +9 -8
- package/prompts/compose.ts +1 -1
- package/prompts/core.md +3 -3
- package/prompts/design.md +1 -1
- package/prompts/dist/2d-game.md +473 -239
- package/prompts/dist/3d-app.md +553 -205
- package/prompts/dist/ar-app.md +435 -202
- package/prompts/dist/design.md +113 -95
- package/prompts/dist/ui-app.md +386 -170
- package/prompts/ui-design.md +2 -3
- package/prompts/ui.md +45 -37
- package/src/animate/tween/Animation.ts +34 -150
- package/src/animate/tween/Timeline.ts +175 -175
- package/src/animate/tween/animateValue.ts +6 -3
- package/src/animate/tween/easing.ts +10 -3
- package/src/animate/tween/spec.ts +41 -15
- package/src/audio/Sound.ts +3 -3
- package/src/audio/audio.ts +2 -1
- package/src/bridges/2d.d.ts +317 -0
- package/src/bridges/app.d.ts +91 -0
- package/src/bridges/audio.d.ts +97 -0
- package/src/bridges/canvas.d.ts +79 -0
- package/src/bridges/device.d.ts +72 -0
- package/src/bridges/fetch.d.ts +80 -0
- package/src/bridges/files.d.ts +70 -0
- package/src/bridges/gl.d.ts +1133 -0
- package/src/bridges/input.d.ts +72 -0
- package/src/bridges/media.d.ts +55 -0
- package/src/bridges/nav.d.ts +71 -0
- package/src/bridges/net.d.ts +52 -0
- package/src/bridges/service.d.ts +52 -0
- package/src/bridges/socket.d.ts +31 -0
- package/src/bridges/storage.d.ts +33 -0
- package/src/bridges/tree.d.ts +301 -0
- package/src/bridges/types.d.ts +49 -0
- package/src/canvas/Canvas.ts +114 -159
- package/src/canvas/gen/cssColor.ts +224 -0
- package/src/canvas/gen/recorder.ts +212 -0
- package/src/canvas/gen/spec.ts +201 -0
- package/src/chisel.ts +193 -0
- package/src/compile/assetMacro.ts +1 -1
- package/src/compile/bundler.ts +11 -2
- package/src/compile/compileProject.ts +43 -4
- package/src/compile/fontMacro.ts +3 -4
- package/src/compile/header.ts +26 -5
- package/src/compile/index.ts +3 -1
- package/src/compile/liteMaterial.ts +1 -1
- package/src/compile/sceneEditor.ts +11 -26
- package/src/core/color.ts +73 -30
- package/src/core/pins.ts +51 -0
- package/src/core/signals.ts +8 -1
- package/src/g2/CharacterController2D.ts +3 -3
- package/src/g2/Node2D.ts +57 -39
- package/src/g2/Physics2D.ts +2 -2
- package/src/g2/Scene2D.ts +35 -23
- package/src/g2/Texture2D.ts +1 -1
- package/src/g2/loop.ts +4 -4
- package/src/gl/CameraPlace.ts +52 -52
- package/src/gl/Foliage.ts +72 -17
- package/src/gl/Geometry.ts +1 -2
- package/src/gl/Light.ts +10 -0
- package/src/gl/Lightmap.ts +45 -29
- package/src/gl/Material.ts +95 -51
- package/src/gl/Mesh.ts +120 -120
- package/src/gl/Model.ts +21 -16
- package/src/gl/Node.ts +91 -24
- package/src/gl/Particles.ts +1 -1
- package/src/gl/Scene.ts +100 -44
- package/src/gl/Texture.ts +8 -7
- package/src/gl/animation/AnimationClip.ts +1 -1
- package/src/gl/animation/DynamicBone.ts +482 -482
- package/src/gl/animation/Locomotion.ts +8 -3
- package/src/gl/nav/NavMesh.ts +3 -4
- package/src/gl/physics/Physics.ts +2 -2
- package/src/gl/physics/physicsEvents.ts +3 -3
- package/src/gl/scenarios.ts +291 -291
- package/src/gl/terrain/Terrain.ts +4 -5
- package/src/gl/touch.ts +14 -15
- package/src/host.d.ts +2 -3
- package/src/inject.editor.ts +7 -0
- package/src/inject.ts +13 -16
- package/src/net/core.ts +6 -5
- package/src/net/index.ts +1 -1
- package/src/net/replication.ts +1 -1
- package/src/plugin.ts +191 -0
- package/src/plugins/gen/camera/contract.d.ts +27 -0
- package/src/plugins/gen/camera/sdk/camera.gen.ts +46 -0
- package/src/plugins/gen/camera/sdk/camera.ts +57 -0
- package/src/plugins/gen/geolocation/contract.d.ts +50 -0
- package/src/plugins/gen/geolocation/sdk/geolocation.gen.ts +54 -0
- package/src/plugins/{geolocation.ts → gen/geolocation/sdk/geolocation.ts} +22 -43
- package/src/plugins/gen/map/contract.d.ts +144 -0
- package/src/plugins/gen/map/sdk/map.gen.ts +88 -0
- package/src/plugins/{map.ts → gen/map/sdk/map.ts} +68 -102
- package/src/plugins/gen/push/contract.d.ts +61 -0
- package/src/plugins/gen/push/sdk/push.gen.ts +60 -0
- package/src/plugins/gen/push/sdk/push.ts +105 -0
- package/src/plugins/gen/qr-scanner/contract.d.ts +16 -0
- package/src/plugins/gen/qr-scanner/sdk/qr-scanner.gen.ts +29 -0
- package/src/plugins/gen/qr-scanner/sdk/qr-scanner.ts +52 -0
- package/src/plugins/permission.ts +5 -4
- package/src/runtime/app.ts +20 -9
- package/src/runtime/appEvents.ts +5 -4
- package/src/runtime/channel.ts +18 -15
- package/src/runtime/clipboard.ts +4 -3
- package/src/runtime/datetime.ts +2 -1
- package/src/runtime/device.ts +17 -15
- package/src/runtime/fetch.ts +30 -20
- package/src/runtime/files.ts +16 -15
- package/src/runtime/input.ts +12 -10
- package/src/runtime/media.ts +50 -46
- package/src/runtime/misc.ts +7 -3
- package/src/runtime/net.ts +8 -7
- package/src/runtime/rpc.ts +1 -3
- package/src/runtime/service.ts +19 -14
- package/src/runtime/share.ts +4 -3
- package/src/runtime/storage.ts +6 -4
- package/src/runtime/touch.ts +32 -0
- package/src/scene/defineScene.ts +61 -365
- package/src/scene/editor.ts +408 -0
- package/src/scene/editorPlugins.ts +3 -3
- package/src/scene/gizmos.ts +15 -9
- package/src/server/db/marci/query.ts +1 -1
- package/src/server/host.ts +1 -1
- package/src/server/runtime.ts +1 -1
- package/src/ui/NativeView.ts +72 -25
- package/src/ui/UI.ts +3 -3
- package/src/ui/UIBottomSheet.ts +16 -17
- package/src/ui/UIButton.ts +54 -16
- package/src/ui/UIContainer.ts +0 -6
- package/src/ui/UIImage.ts +34 -30
- package/src/ui/UIInput.ts +29 -37
- package/src/ui/UIModal.ts +1 -3
- package/src/ui/UINode.ts +347 -297
- package/src/ui/UIPager.ts +93 -78
- package/src/ui/UIPopover.ts +0 -2
- package/src/ui/UIScreen.ts +41 -36
- package/src/ui/UIScrollable.ts +19 -13
- package/src/ui/UISpacer.ts +1 -1
- package/src/ui/UITabs.ts +8 -6
- package/src/ui/UIText.ts +7 -17
- package/src/ui/UIVideo.ts +30 -27
- package/src/ui/UIVirtualizedList.ts +58 -59
- package/src/ui/UIWidget.ts +38 -18
- package/src/ui/colorKeys.gen.ts +37 -0
- package/src/ui/fonts.ts +2 -2
- package/src/ui/presentable.ts +59 -42
- package/src/ui/router.ts +52 -35
- package/src/ui/styleColor.ts +56 -0
- package/src/ui/theme.ts +7 -6
- package/src/ui/transitions.ts +249 -0
- package/src/ui/tree.ts +346 -0
- package/src/version.ts +24 -0
- package/tests/helpers/engineWorld.ts +11 -0
- package/tests/helpers/fakeTree.ts +353 -0
- package/tests/helpers/hostStubs.ts +31 -0
- package/tests/helpers/index.ts +14 -0
- package/tests/helpers/memoryMarci.ts +124 -0
- package/tests/helpers/phases.ts +23 -0
- package/tests/helpers/preload.ts +18 -0
- package/tests/helpers/stubApp.ts +2 -0
- package/tests/helpers/stubDevice.ts +2 -0
- package/tests/helpers/stubFetch.ts +2 -0
- package/tests/helpers/stubInput.ts +2 -0
- package/dist/inject.js +0 -4629
- package/dist/types/core/registry.d.ts +0 -7
- package/dist/types/plugins/camera.d.ts +0 -25
- package/dist/types/plugins/push.d.ts +0 -46
- package/src/bridges.d.ts +0 -1769
- package/src/compile/__tests__/assetIconMacro.test.ts +0 -219
- package/src/compile/__tests__/assetMacro.test.ts +0 -100
- package/src/compile/__tests__/assetName.test.ts +0 -55
- package/src/compile/__tests__/compile.test.ts +0 -310
- package/src/compile/__tests__/detectEntry.test.ts +0 -151
- package/src/compile/__tests__/fontMacro.test.ts +0 -199
- package/src/compile/__tests__/serverSplit.test.ts +0 -27
- package/src/core/__tests__/stateMachine.test.ts +0 -132
- package/src/core/registry.ts +0 -23
- package/src/plugins/camera.ts +0 -81
- package/src/plugins/push.ts +0 -132
- package/src/plugins/qr.ts +0 -73
package/src/ui/NativeView.ts
CHANGED
|
@@ -10,8 +10,10 @@
|
|
|
10
10
|
// wrapper convention.
|
|
11
11
|
|
|
12
12
|
import { _channelCall, _channelEmit, _channelOff, _channelOn, type ChannelListeners } from "../runtime/channel"
|
|
13
|
-
import { _bumpNavEpoch,
|
|
13
|
+
import { _bumpNavEpoch, _setCurrent, Presentable, type DestTuple, type DismissOptions, type PresentOptions } from "./presentable"
|
|
14
|
+
import { _transitionId, TRANSITION_NONE } from "./transitions"
|
|
14
15
|
import { Element, type BaseStyle, type DrawableStyle, type ElementStyle, type UIElementBase } from "./UINode"
|
|
16
|
+
import { TREE_DEST_NATIVE, registerDest, registerNativeView, tree, unregisterNativeView } from "./tree"
|
|
15
17
|
|
|
16
18
|
export type UINativeViewStyle = ElementStyle & DrawableStyle
|
|
17
19
|
|
|
@@ -28,25 +30,30 @@ export interface NativeView extends UIElementBase<UINativeViewStyle, DrawableSty
|
|
|
28
30
|
/** Show fullscreen as the current destination (see Presentable). */
|
|
29
31
|
open(options?: PresentOptions): void,
|
|
30
32
|
/** Dismiss if this is the visible destination. */
|
|
31
|
-
close(): void,
|
|
33
|
+
close(options?: DismissOptions): void,
|
|
32
34
|
|
|
33
35
|
/** Became the visible destination. */
|
|
34
36
|
onOpen(callback: () => void): this
|
|
35
37
|
/** Stopped being the visible destination. */
|
|
36
38
|
onClose(callback: () => void): this
|
|
37
39
|
/** Hardware/system back while current. */
|
|
38
|
-
|
|
40
|
+
onBack(callback: () => void): this
|
|
39
41
|
|
|
40
42
|
/** Invoke a method on the native view (`map.call("setCenter", [lng, lat])`). Args and the
|
|
41
|
-
* result are
|
|
43
|
+
* result are plain data (and Uint8Array). Rejects if the host has no such view/method. */
|
|
42
44
|
call(method: string, ...args: any[]): Promise<any>
|
|
43
45
|
/** Subscribe to an event the native view emits (`map.on("markerTap", cb)`). */
|
|
44
46
|
on(event: string, callback: (data?: any) => void): this
|
|
45
47
|
off(event: string, callback: (data?: any) => void): this
|
|
48
|
+
/** @internal The destination tuple (Presentable). */
|
|
49
|
+
_dest(): DestTuple
|
|
46
50
|
}
|
|
47
51
|
|
|
48
52
|
let nextViewId = 1
|
|
49
53
|
|
|
54
|
+
const PRESENTED = 1
|
|
55
|
+
const MOUNTED = 2
|
|
56
|
+
|
|
50
57
|
/** @internal Base for typed plugin wrappers (QRScanner, CameraView — src/plugins/): subclass it,
|
|
51
58
|
* pin the viewName/params, and layer typed methods over the raw `call`/`on` channel. Not a
|
|
52
59
|
* public global — apps use the `NativeView(name)` factory below. */
|
|
@@ -55,37 +62,41 @@ export class NativeViewElement extends Element<"native"> implements Presentable
|
|
|
55
62
|
readonly params: any
|
|
56
63
|
/** @internal stable per-instance handle for the viewCall channel + promotion identity. */
|
|
57
64
|
readonly _viewId: number
|
|
58
|
-
/** @internal event listeners by event name
|
|
59
|
-
* or calls _emitViewEvent. */
|
|
65
|
+
/** @internal event listeners by event name (host → view events come through the tree emitter). */
|
|
60
66
|
readonly nvl: ChannelListeners = {}
|
|
61
67
|
readonly ol: (() => void)[] = []
|
|
62
68
|
readonly cl: (() => void)[] = []
|
|
63
|
-
_backButtonCallback?: () => void
|
|
64
|
-
private
|
|
69
|
+
private _backButtonCallback?: () => void
|
|
70
|
+
private readonly _paramsJson: string
|
|
71
|
+
/** @internal Where the host has a view of this instance: PRESENTED | MOUNTED. */
|
|
72
|
+
private _shown = 0
|
|
65
73
|
|
|
66
74
|
constructor(viewName: string, params: any) {
|
|
67
75
|
super("native", {})
|
|
68
76
|
this.viewName = viewName
|
|
69
77
|
this.params = params
|
|
70
78
|
this._viewId = nextViewId++
|
|
79
|
+
this._paramsJson = JSON.stringify(params ?? {})
|
|
80
|
+
tree().setString(this._h.id, "viewName", viewName)
|
|
81
|
+
tree().setString(this._h.id, "viewParams", this._paramsJson)
|
|
82
|
+
tree().setInt(this._h.id, "viewId", this._viewId)
|
|
83
|
+
registerDest(TREE_DEST_NATIVE, this._viewId, this)
|
|
71
84
|
}
|
|
72
85
|
|
|
73
|
-
/** @internal
|
|
74
|
-
|
|
75
|
-
return this._vd ??= { type: "native", viewName: this.viewName, params: this.params, viewId: this._viewId, _p: this }
|
|
76
|
-
}
|
|
86
|
+
/** @internal */
|
|
87
|
+
_dest(): DestTuple { return [TREE_DEST_NATIVE, this._viewId, this.viewName, this._paramsJson] }
|
|
77
88
|
|
|
78
89
|
open(options?: PresentOptions): void {
|
|
79
|
-
if (!
|
|
80
|
-
throw new Error(`NativeView("${this.viewName}") is not supported on this host (
|
|
90
|
+
if (!tree().isViewSupported(this.viewName)) {
|
|
91
|
+
throw new Error(`NativeView("${this.viewName}") is not supported on this host (no registered view)`)
|
|
81
92
|
}
|
|
82
93
|
_bumpNavEpoch()
|
|
83
|
-
|
|
94
|
+
tree().open(TREE_DEST_NATIVE, this._viewId, this.viewName, this._paramsJson, _transitionId(options?.transition, TRANSITION_NONE))
|
|
84
95
|
_setCurrent(this)
|
|
85
96
|
}
|
|
86
|
-
close(): void {
|
|
97
|
+
close(options?: DismissOptions): void {
|
|
87
98
|
_bumpNavEpoch()
|
|
88
|
-
|
|
99
|
+
tree().close(TREE_DEST_NATIVE, this._viewId, _transitionId(options?.transition, TRANSITION_NONE))
|
|
89
100
|
if (Presentable.current === this) _setCurrent(null)
|
|
90
101
|
}
|
|
91
102
|
|
|
@@ -97,15 +108,47 @@ export class NativeViewElement extends Element<"native"> implements Presentable
|
|
|
97
108
|
this.cl.push(callback)
|
|
98
109
|
return this
|
|
99
110
|
}
|
|
100
|
-
|
|
111
|
+
onBack(callback: () => void): this {
|
|
101
112
|
this._backButtonCallback = callback
|
|
102
113
|
return this
|
|
103
114
|
}
|
|
115
|
+
/** @internal */
|
|
116
|
+
// The host has a view that can send events while the instance is presented OR mounted among a
|
|
117
|
+
// screen's children: findable by viewId while it is either (owned handles) — a promoted view that
|
|
118
|
+
// closes is still the embedded one.
|
|
119
|
+
private _reach(where: number, on: boolean): void {
|
|
120
|
+
const was = this._shown
|
|
121
|
+
this._shown = on ? was | where : was & ~where
|
|
122
|
+
if (was === 0 && this._shown !== 0) registerNativeView(this._viewId, this)
|
|
123
|
+
else if (was !== 0 && this._shown === 0) unregisterNativeView(this._viewId)
|
|
124
|
+
}
|
|
125
|
+
/** @internal */
|
|
126
|
+
_emitOpen(): void { this._reach(PRESENTED, true); for (const cb of this.ol.slice()) cb() }
|
|
127
|
+
/** @internal */
|
|
128
|
+
_emitClose(): void { this._reach(PRESENTED, false); for (const cb of this.cl.slice()) cb() }
|
|
129
|
+
/** @internal */
|
|
130
|
+
_pinned(): void { this._reach(MOUNTED, true) }
|
|
131
|
+
/** @internal */
|
|
132
|
+
_unpinned(): void { this._reach(MOUNTED, false) }
|
|
133
|
+
/** @internal */
|
|
134
|
+
override _freed(): void {
|
|
135
|
+
this._reach(MOUNTED, false)
|
|
136
|
+
super._freed()
|
|
137
|
+
}
|
|
138
|
+
/** @internal */
|
|
139
|
+
_emitBack(): boolean {
|
|
140
|
+
if (!this._backButtonCallback) return false
|
|
141
|
+
this._backButtonCallback()
|
|
142
|
+
return true
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
call(method: string, ...args: any[]): Promise<any> { return this._channelSend(method, args) }
|
|
104
146
|
|
|
105
|
-
call
|
|
147
|
+
/** @internal One call over the channel (runtime/channel.ts). */
|
|
148
|
+
_channelSend(method: string, args: any[]): Promise<any> {
|
|
106
149
|
return _channelCall(
|
|
107
|
-
typeof
|
|
108
|
-
`NativeView("${this.viewName}") is not supported on this host (requires
|
|
150
|
+
typeof _creatorTree !== "undefined" ? _creatorTree : undefined, "viewCall",
|
|
151
|
+
`NativeView("${this.viewName}") is not supported on this host (requires _creatorTree.viewCall)`,
|
|
109
152
|
this._viewId, method, args)
|
|
110
153
|
}
|
|
111
154
|
|
|
@@ -117,9 +160,9 @@ export class NativeViewElement extends Element<"native"> implements Presentable
|
|
|
117
160
|
_channelOff(this.nvl, event, callback)
|
|
118
161
|
return this
|
|
119
162
|
}
|
|
120
|
-
/** @internal host entry: deliver a native event (payload
|
|
121
|
-
_emitViewEvent(event: string,
|
|
122
|
-
_channelEmit(this.nvl, event,
|
|
163
|
+
/** @internal host entry: deliver a native event (its payload, or none). */
|
|
164
|
+
_emitViewEvent(event: string, data?: unknown): void {
|
|
165
|
+
_channelEmit(this.nvl, event, data)
|
|
123
166
|
}
|
|
124
167
|
}
|
|
125
168
|
|
|
@@ -133,10 +176,14 @@ export const NativeView: {
|
|
|
133
176
|
(name: string, params?: object): NativeView
|
|
134
177
|
/** Whether this host registered a `registerView` factory under `name`. */
|
|
135
178
|
isSupported(name: string): boolean
|
|
179
|
+
/** The contract version of the host's view `name`: 0 when it has none, 1 for one written by hand. */
|
|
180
|
+
version(name: string): number
|
|
136
181
|
} = /*#__PURE__*/ (() => {
|
|
137
182
|
const factory = (name: string, params: object = {}): NativeView =>
|
|
138
183
|
new NativeViewElement(name, params) as unknown as NativeView
|
|
139
184
|
factory.isSupported = (name: string): boolean =>
|
|
140
|
-
typeof
|
|
185
|
+
typeof _creatorTree !== "undefined" && _creatorTree.isViewSupported(name)
|
|
186
|
+
factory.version = (name: string): number =>
|
|
187
|
+
typeof _creatorTree !== "undefined" ? _creatorTree.viewVersion(name) : 0
|
|
141
188
|
return factory
|
|
142
189
|
})()
|
package/src/ui/UI.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
1
|
+
// The UI surface: every element the SDK exports. The host side of each is the runtime's tree
|
|
2
|
+
// (docs/tree.md); the renderers implement HostUI over node ids.
|
|
3
3
|
export { UIButton, type UIButtonStyle } from './UIButton'
|
|
4
4
|
export { UIScreen, type UIScreenStyle } from './UIScreen'
|
|
5
5
|
export { UISpacer, type UISpacerStyle } from './UISpacer'
|
|
@@ -25,7 +25,7 @@ export { Router } from './router'
|
|
|
25
25
|
export { NativeView, type UINativeViewStyle } from './NativeView'
|
|
26
26
|
// Presentable is both the interface and its runtime companion (Presentable.current).
|
|
27
27
|
export { Presentable } from './presentable'
|
|
28
|
-
export type { PresentOptions, Transition, TransitionName,
|
|
28
|
+
export type { DismissOptions, PresentOptions, Transition, TransitionName, TransitionPose, TransitionSpec } from './presentable'
|
|
29
29
|
|
|
30
30
|
// Internal: memoized map for reactive children — the chisel `reactiveUi` pass rewrites
|
|
31
31
|
// `list.map(fn)` inside children bindings to `__uiMap(list, fn, slot)` calls.
|
package/src/ui/UIBottomSheet.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ModalElement, type UIModalStyle } from "./UIModal"
|
|
2
2
|
import type { UIWidget } from "./UIWidget"
|
|
3
3
|
import { buildUI, type ChildrenFn, type UIChildArg, type UINodeChild } from "./UINode"
|
|
4
|
+
import { TREE_FLAG_DETENT } from "./tree"
|
|
4
5
|
|
|
5
6
|
export type UIBottomSheetStyle = UIModalStyle
|
|
6
7
|
|
|
@@ -18,11 +19,11 @@ const SHEET_ANIM_MS = 250
|
|
|
18
19
|
* modal machinery.
|
|
19
20
|
*
|
|
20
21
|
* ```ts
|
|
21
|
-
* const actions = UIBottomSheet({ bgColor: "#1c1c1e", borderRadius: 16 }
|
|
22
|
+
* const actions = UIBottomSheet(rows).style({ bgColor: "#1c1c1e", borderRadius: 16 }) // content-sized
|
|
22
23
|
*
|
|
23
|
-
* const mapSheet = UIBottomSheet({ bgColor: "#1c1c1e", borderRadius: 16 }
|
|
24
|
+
* const mapSheet = UIBottomSheet(results).style({ bgColor: "#1c1c1e", borderRadius: 16 })
|
|
24
25
|
* .detents([0.3, 0.6, 1])
|
|
25
|
-
* .
|
|
26
|
+
* .onDetent(i => map.setPadding(...))
|
|
26
27
|
* ```
|
|
27
28
|
*/
|
|
28
29
|
export interface UIBottomSheet extends UIWidget {
|
|
@@ -30,12 +31,12 @@ export interface UIBottomSheet extends UIWidget {
|
|
|
30
31
|
* the last (highest) detent; set this before `show()`. Without a `detents()` call the sheet
|
|
31
32
|
* is CONTENT-SIZED instead — one position, as tall as its children (up to the screen). */
|
|
32
33
|
detents(list: number[]): this,
|
|
33
|
-
/** Snap to a detent (animated). Clamped to the detents range; fires `
|
|
34
|
+
/** Snap to a detent (animated). Clamped to the detents range; fires `onDetent`. */
|
|
34
35
|
setDetent(index: number): void,
|
|
35
36
|
/** Current detent index. */
|
|
36
37
|
readonly detent: number,
|
|
37
38
|
/** Fires on every settle: a finger snap on native hosts, or a `setDetent()` call. */
|
|
38
|
-
|
|
39
|
+
onDetent(callback: (index: number) => void): this,
|
|
39
40
|
|
|
40
41
|
/** Mount and slide in to the current detent. No-op while already open. */
|
|
41
42
|
show(): void,
|
|
@@ -56,10 +57,6 @@ export interface UIBottomSheet extends UIWidget {
|
|
|
56
57
|
export class BottomSheetElement extends ModalElement {
|
|
57
58
|
_detents: number[] = [1]
|
|
58
59
|
_detent = 0
|
|
59
|
-
/** Host-facing (the `sl`/`otl` contract): hosts read `dtl` at mount and call it with the
|
|
60
|
-
* settled detent index for GESTURE settles only — programmatic `setDetent` fires JS-side.
|
|
61
|
-
* `-1` = dragged below the lowest detent while dismissible. */
|
|
62
|
-
readonly dtl: any[] = []
|
|
63
60
|
readonly _detentListeners: ((index: number) => void)[] = []
|
|
64
61
|
|
|
65
62
|
constructor(style: UIBottomSheetStyle, children: UINodeChild[] | ChildrenFn) {
|
|
@@ -70,11 +67,15 @@ export class BottomSheetElement extends ModalElement {
|
|
|
70
67
|
// The inherited show/hide pose animates ONLY the scrim: sheet geometry rides the
|
|
71
68
|
// sheetDetent style key, never the pose system.
|
|
72
69
|
this._transition = { duration: SHEET_ANIM_MS }
|
|
73
|
-
this.
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
70
|
+
this._addFlags(TREE_FLAG_DETENT)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** @internal The host's GESTURE settles only (programmatic `setDetent` fires JS-side); `-1` =
|
|
74
|
+
* dragged below the lowest detent while dismissible. */
|
|
75
|
+
_emitDetent(index: number): void {
|
|
76
|
+
if (index < 0) { this.hide(); return }
|
|
77
|
+
this._detent = index
|
|
78
|
+
for (const callback of this._detentListeners) callback(index)
|
|
78
79
|
}
|
|
79
80
|
|
|
80
81
|
detents(list: number[]): this {
|
|
@@ -101,7 +102,7 @@ export class BottomSheetElement extends ModalElement {
|
|
|
101
102
|
for (const callback of this._detentListeners) callback(clamped)
|
|
102
103
|
}
|
|
103
104
|
|
|
104
|
-
|
|
105
|
+
onDetent(callback: (index: number) => void): this {
|
|
105
106
|
this._detentListeners.push(callback)
|
|
106
107
|
return this
|
|
107
108
|
}
|
|
@@ -132,8 +133,6 @@ const makeBottomSheet = (style: any, children: any) => new BottomSheetElement(st
|
|
|
132
133
|
* `.detents([...])` for snap positions. Same argument forms as `UIColumn`. */
|
|
133
134
|
export function UIBottomSheet(...children: UIChildArg[]): UIBottomSheet;
|
|
134
135
|
export function UIBottomSheet(children: UINodeChild[] | ChildrenFn): UIBottomSheet;
|
|
135
|
-
/** @deprecated Style as the first argument is legacy — use chained `.style({...})`. */
|
|
136
|
-
export function UIBottomSheet(style: UIBottomSheetStyle, children?: UINodeChild[] | ChildrenFn): UIBottomSheet;
|
|
137
136
|
export function UIBottomSheet(...args: any[]): UIBottomSheet {
|
|
138
137
|
return buildUI(args, null, makeBottomSheet)
|
|
139
138
|
}
|
package/src/ui/UIButton.ts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import { ClickEvent, TouchStartEvent, LongPressEvent } from "../runtime/touch"
|
|
2
|
-
import type { ClickEvent as ClickEventType, TouchStartEvent as TouchStartEventType, LongPressEvent as LongPressEventType } from "../runtime/touch"
|
|
3
|
-
import { type ElementStyle, type ContainerStyle, ContainerElement, buildUI, type DrawableStyle, type UIChildArg, type UIContainerBase, type UINodeChild, type ChildrenFn, type BaseStyle, type Color
|
|
1
|
+
import { ClickEvent, TouchStartEvent, LongPressEvent, MouseEnterEvent } from "../runtime/touch"
|
|
2
|
+
import type { ClickEvent as ClickEventType, TouchStartEvent as TouchStartEventType, LongPressEvent as LongPressEventType, MouseEnterEvent as MouseEnterEventType } from "../runtime/touch"
|
|
3
|
+
import { type ElementStyle, type ContainerStyle, ContainerElement, buildUI, type DrawableStyle, type UIChildArg, type UIContainerBase, type UINodeChild, type ChildrenFn, type BaseStyle, type Color } from "./UINode"
|
|
4
|
+
import { TREE_FLAG_CLICK, TREE_FLAG_HOVER, TREE_FLAG_INTERACTIVE, TREE_FLAG_LONG_PRESS, tree } from "./tree"
|
|
4
5
|
|
|
5
6
|
export type UIButtonStyle = ElementStyle & DrawableStyle & ContainerStyle & { rippleColor?: Color | "default" }
|
|
6
7
|
|
|
7
|
-
/** A tappable container — row + centered children by default. Press feedback via the `
|
|
8
|
-
*
|
|
9
|
-
export interface UIButton extends UIContainerBase<UIButtonStyle
|
|
8
|
+
/** A tappable container — row + centered children by default. Press feedback via the `$pressed`
|
|
9
|
+
* class block or `rippleColor`. */
|
|
10
|
+
export interface UIButton extends UIContainerBase<UIButtonStyle, DrawableStyle & BaseStyle> {
|
|
10
11
|
readonly type: "button",
|
|
11
12
|
|
|
12
13
|
/** Fired on a completed tap/click. */
|
|
@@ -17,8 +18,14 @@ export interface UIButton extends UIContainerBase<UIButtonStyle & { onPressed?:
|
|
|
17
18
|
* `ev.track(...)` the rest of the gesture (like `onTouchStart`), so a hold can flow straight into
|
|
18
19
|
* dragging the element. A handled long-press suppresses the click that would follow the release. */
|
|
19
20
|
onLongPress(callback: (ev: LongPressEventType<UIButton>) => void): this,
|
|
21
|
+
/** Fired when a mouse cursor (no button) enters the button — desktop / web; touch never fires it.
|
|
22
|
+
* There is no leave event: `ev.track({ onMove, onEnd, onCancel })` follows the hover to its
|
|
23
|
+
* end. The visual state is the reserved `$hovered` class (cascades like `$pressed`). */
|
|
24
|
+
onMouseEnter(callback: (ev: MouseEnterEventType<UIButton>) => void): this,
|
|
20
25
|
/** Is a finger currently down on the button? */
|
|
21
|
-
isPressed
|
|
26
|
+
readonly isPressed: boolean,
|
|
27
|
+
/** Is a mouse cursor currently over the button (the topmost interactive node under it)? */
|
|
28
|
+
readonly isHovered: boolean,
|
|
22
29
|
}
|
|
23
30
|
|
|
24
31
|
|
|
@@ -27,11 +34,19 @@ class ButtonElement extends ContainerElement<"button"> {
|
|
|
27
34
|
readonly clickListeners: any[] = []
|
|
28
35
|
readonly touchStartListeners: any[] = []
|
|
29
36
|
readonly longPressListeners: any[] = []
|
|
37
|
+
readonly mouseEnterListeners: any[] = []
|
|
38
|
+
|
|
39
|
+
constructor(type: "button", style: any, children: any) {
|
|
40
|
+
super(type, style, children)
|
|
41
|
+
this._addFlags(TREE_FLAG_INTERACTIVE) // a button is a touch target from the start (press feedback)
|
|
42
|
+
}
|
|
30
43
|
|
|
31
44
|
onClick (callback: any): this {
|
|
32
45
|
this.clickListeners.push(callback)
|
|
46
|
+
this._addFlags(TREE_FLAG_CLICK)
|
|
33
47
|
return this
|
|
34
48
|
}
|
|
49
|
+
/** @internal */
|
|
35
50
|
_emitClick(pointerId: number, clientX: number, clientY: number) {
|
|
36
51
|
const touchEvent = new ClickEvent(clientX, clientY, pointerId)
|
|
37
52
|
touchEvent.target = this
|
|
@@ -45,6 +60,7 @@ class ButtonElement extends ContainerElement<"button"> {
|
|
|
45
60
|
this.touchStartListeners.push(callback)
|
|
46
61
|
return this
|
|
47
62
|
}
|
|
63
|
+
/** @internal */
|
|
48
64
|
_emitTouchStart(pointerId: number, clientX: number, clientY: number): any {
|
|
49
65
|
const touchEvent = new TouchStartEvent(clientX, clientY, pointerId)
|
|
50
66
|
touchEvent.target = this
|
|
@@ -59,12 +75,13 @@ class ButtonElement extends ContainerElement<"button"> {
|
|
|
59
75
|
|
|
60
76
|
onLongPress (callback: any): this {
|
|
61
77
|
this.longPressListeners.push(callback)
|
|
78
|
+
this._addFlags(TREE_FLAG_LONG_PRESS)
|
|
62
79
|
return this
|
|
63
80
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
81
|
+
/** @internal Fired by the host when the finger is held past the long-press threshold. Returns
|
|
82
|
+
* null when nothing is listening — the trailing click then goes through as usual. Otherwise the
|
|
83
|
+
* wrapper whose presence swallows that click, carrying the optional drag handler a listener
|
|
84
|
+
* registered via `ev.track(...)`. */
|
|
68
85
|
_emitLongPress(pointerId: number, clientX: number, clientY: number): any {
|
|
69
86
|
if (this.longPressListeners.length === 0) return null
|
|
70
87
|
const longPressEvent = new LongPressEvent(clientX, clientY, pointerId)
|
|
@@ -75,9 +92,32 @@ class ButtonElement extends ContainerElement<"button"> {
|
|
|
75
92
|
return { track: (longPressEvent as any)._trackHandler ?? null }
|
|
76
93
|
}
|
|
77
94
|
|
|
78
|
-
isPressed(): boolean {
|
|
79
|
-
if (!this.
|
|
80
|
-
return
|
|
95
|
+
get isPressed(): boolean {
|
|
96
|
+
if (!this._h.id) return false
|
|
97
|
+
return tree().isButtonPressed(this._h.id)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
onMouseEnter (callback: any): this {
|
|
101
|
+
this.mouseEnterListeners.push(callback)
|
|
102
|
+
this._addFlags(TREE_FLAG_HOVER) // the runtime crosses into JS for hover only on flagged nodes
|
|
103
|
+
return this
|
|
104
|
+
}
|
|
105
|
+
/** @internal Fired by the runtime when the cursor enters (TREE_EVENT_HOVER_ENTER). Returns the
|
|
106
|
+
* hover track handler a listener registered via `ev.track(...)`, or null — the emitter keeps it
|
|
107
|
+
* in its one hover slot and answers whether moves are wanted. */
|
|
108
|
+
_emitMouseEnter(clientX: number, clientY: number): any {
|
|
109
|
+
const ev = new MouseEnterEvent(clientX, clientY)
|
|
110
|
+
ev.target = this
|
|
111
|
+
for (let callback of this.mouseEnterListeners) {
|
|
112
|
+
callback(ev)
|
|
113
|
+
if ((ev as any)._trackHandler) return (ev as any)._trackHandler
|
|
114
|
+
}
|
|
115
|
+
return null
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
get isHovered(): boolean {
|
|
119
|
+
if (!this._h.id) return false
|
|
120
|
+
return tree().isHovered(this._h.id)
|
|
81
121
|
}
|
|
82
122
|
}
|
|
83
123
|
|
|
@@ -94,8 +134,6 @@ export const __UIButton = (children: UINodeChild[] | ChildrenFn): UIButton => ma
|
|
|
94
134
|
* `UIColumn`; attach behavior with `.onClick(...)`. */
|
|
95
135
|
export function UIButton(...children: UIChildArg[]): UIButton;
|
|
96
136
|
export function UIButton(children: UINodeChild[] | ChildrenFn): UIButton;
|
|
97
|
-
/** @deprecated Style as the first argument is legacy — use chained `.style({...})`. */
|
|
98
|
-
export function UIButton(style: UIButtonStyle, children?: UINodeChild[] | ChildrenFn): UIButton;
|
|
99
137
|
export function UIButton(...args: any[]): UIButton {
|
|
100
138
|
return buildUI(args, BUTTON_DEFAULTS, makeButton)
|
|
101
139
|
}
|
package/src/ui/UIContainer.ts
CHANGED
|
@@ -19,8 +19,6 @@ export const __UIBox = (children: UINodeChild[] | ChildrenFn): UIBox => makeBox(
|
|
|
19
19
|
* entries are skipped; a lone function makes the children reactive. */
|
|
20
20
|
export function UIColumn(...children: UIChildArg[]): UIColumn
|
|
21
21
|
export function UIColumn(children: UINodeChild[] | ChildrenFn): UIColumn
|
|
22
|
-
/** @deprecated Style as the first argument is legacy — use chained `.style({...})`. */
|
|
23
|
-
export function UIColumn(style: UIContainerStyle, children?: UINodeChild[] | ChildrenFn): UIColumn
|
|
24
22
|
export function UIColumn(...args: any[]): UIColumn {
|
|
25
23
|
return buildUI(args, null, makeColumn)
|
|
26
24
|
}
|
|
@@ -35,8 +33,6 @@ const makeRow = (style: any, children: any) => new ContainerElement("row", style
|
|
|
35
33
|
/** Create a horizontal flex container (same argument forms as `UIColumn`). */
|
|
36
34
|
export function UIRow(...children: UIChildArg[]): UIRow
|
|
37
35
|
export function UIRow(children: UINodeChild[] | ChildrenFn): UIRow
|
|
38
|
-
/** @deprecated Style as the first argument is legacy — use chained `.style({...})`. */
|
|
39
|
-
export function UIRow(style: UIContainerStyle, children?: UINodeChild[] | ChildrenFn): UIRow
|
|
40
36
|
export function UIRow(...args: any[]): UIRow {
|
|
41
37
|
return buildUI(args, ROW_DEFAULTS, makeRow)
|
|
42
38
|
}
|
|
@@ -53,8 +49,6 @@ const makeBox = (style: any, children: any) => new ContainerElement("box", style
|
|
|
53
49
|
* avatars, empty states). Same argument forms as `UIColumn`. */
|
|
54
50
|
export function UIBox(...children: UIChildArg[]): UIBox
|
|
55
51
|
export function UIBox(children: UINodeChild[] | ChildrenFn): UIBox
|
|
56
|
-
/** @deprecated Style as the first argument is legacy — use chained `.style({...})`. */
|
|
57
|
-
export function UIBox(style: UIContainerStyle, children?: UINodeChild[] | ChildrenFn): UIBox
|
|
58
52
|
export function UIBox(...args: any[]): UIBox {
|
|
59
53
|
return buildUI(args, BOX_DEFAULTS, makeBox)
|
|
60
54
|
}
|
package/src/ui/UIImage.ts
CHANGED
|
@@ -4,11 +4,12 @@ import type { File } from "../runtime/fetch"
|
|
|
4
4
|
import { Canvas, isCanvas } from "../canvas/Canvas"
|
|
5
5
|
import type { Scene2D } from "../g2/Scene2D"
|
|
6
6
|
import { Element, type Color, type ElementStyle, type UIElementBase } from "./UINode"
|
|
7
|
+
import { wireColor } from "./styleColor"
|
|
8
|
+
import { tree } from "./tree"
|
|
7
9
|
|
|
8
10
|
export type UIImageStyle = ElementStyle & { borderRadius?: number, objectFit?: "cover" | "contain" | "fill", tintColor?: Color }
|
|
9
11
|
|
|
10
|
-
/** A baked Canvas surface as an image source. The UI backend resolves it to a UI texture
|
|
11
|
-
* docs/canvas-contract.md ("Pending"). */
|
|
12
|
+
/** A baked Canvas surface as an image source. The UI backend resolves it to a UI texture. */
|
|
12
13
|
export type CanvasImageSource = { canvasSurface: number }
|
|
13
14
|
|
|
14
15
|
/** A live 2D scene as an image source: the host draws the scene into the node's box every frame
|
|
@@ -50,48 +51,51 @@ export interface UIImage extends UIElementBase<UIImageStyle> {
|
|
|
50
51
|
}
|
|
51
52
|
|
|
52
53
|
class ImageElement extends Element<"image"> {
|
|
53
|
-
private _src
|
|
54
|
-
// Current source sub-rect; undefined until the first setSourceRect. Kept on the node (not
|
|
55
|
-
// just sent as a command) so a crop set while detached (_id == 0) is reapplied at mount —
|
|
56
|
-
// the viewer reads it when it creates the element.
|
|
57
|
-
private _sourceRect?: [number, number, number, number]
|
|
54
|
+
private _src!: ResolvedImageSource
|
|
58
55
|
constructor(style: any, src: ImageSource) {
|
|
59
56
|
super("image", style)
|
|
60
|
-
this.
|
|
57
|
+
this.src = src
|
|
61
58
|
}
|
|
62
59
|
|
|
63
60
|
get src(): ResolvedImageSource {
|
|
64
61
|
return this._src
|
|
65
62
|
}
|
|
66
63
|
set src(value: ImageSource) {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
64
|
+
const next = toSrc(value)
|
|
65
|
+
// A source tint that is not a colour throws BEFORE anything is applied, like a style colour.
|
|
66
|
+
const n: any = next
|
|
67
|
+
const tint = n && typeof n === "object" && "svg" in n && n.tintColor != null ? wireColor("tintColor", n.tintColor) as string : null
|
|
68
|
+
this._src = next
|
|
69
|
+
if (this._h.id === 0) return
|
|
70
|
+
// The wire spellings of a source (the host resolves each prefix): a url as is, "id:<bufferId>"
|
|
71
|
+
// for a fetch / asset buffer, "svg:<source>" (+ "srcTintColor", '#rrggbbaa' or a var(), AFTER
|
|
72
|
+
// the src: a src write resets the source tint), "canvas:<surfaceId>", "scene2d:<sceneId>".
|
|
73
|
+
const s: any = this._src
|
|
74
|
+
if (typeof s === "string") {
|
|
75
|
+
tree().setString(this._h.id, "src", s)
|
|
76
|
+
} else if (s && typeof s === "object") {
|
|
77
|
+
if ("svg" in s) {
|
|
78
|
+
tree().setString(this._h.id, "src", "svg:" + s.svg)
|
|
79
|
+
if (tint != null) tree().setString(this._h.id, "srcTintColor", tint)
|
|
80
|
+
} else if ("canvasSurface" in s) {
|
|
81
|
+
tree().setString(this._h.id, "src", "canvas:" + s.canvasSurface)
|
|
82
|
+
} else if ("scene2d" in s) {
|
|
83
|
+
tree().setString(this._h.id, "src", "scene2d:" + s.scene2d)
|
|
84
|
+
} else if ("_h" in s) {
|
|
85
|
+
tree().setString(this._h.id, "src", "id:" + s._h.id)
|
|
86
|
+
}
|
|
70
87
|
}
|
|
71
88
|
}
|
|
72
89
|
|
|
73
90
|
setSourceRect(x: number, y: number, w: number, h: number): this {
|
|
74
|
-
//
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
// pixels, a different coordinate space). On a detached node there is nothing to mutate yet —
|
|
78
|
-
// the stash above carries it to mount. The viewer decides relayout vs draw-only by comparing
|
|
79
|
-
// w/h against the rect it has stashed on the element.
|
|
80
|
-
if (this._id !== 0) {
|
|
81
|
-
_creatorUI.setSourceRect(this._id, x, y, w, h)
|
|
82
|
-
}
|
|
91
|
+
// Texture pixels (not a style → no density scaling); the host decides relayout vs draw-only by
|
|
92
|
+
// comparing w/h against the rect it has.
|
|
93
|
+
if (this._h.id !== 0) tree().setString(this._h.id, "sourceRect", `${x} ${y} ${w} ${h}`)
|
|
83
94
|
return this
|
|
84
95
|
}
|
|
85
96
|
}
|
|
86
97
|
|
|
87
98
|
/** Create an image element from a source (see {@link ImageSource}). */
|
|
88
|
-
export function UIImage(src: ImageSource): UIImage
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
export function UIImage(...args: [ImageSource] | [UIImageStyle, ImageSource]): UIImage {
|
|
92
|
-
if (args.length === 1) {
|
|
93
|
-
return new ImageElement({}, args[0])
|
|
94
|
-
} else {
|
|
95
|
-
return new ImageElement(args[0], args[1])
|
|
96
|
-
}
|
|
97
|
-
}
|
|
99
|
+
export function UIImage(src: ImageSource): UIImage {
|
|
100
|
+
return new ImageElement({}, src)
|
|
101
|
+
}
|