@playcanvas/web-components 0.16.0 → 0.17.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/dist/app.d.cts +14 -13
- package/dist/app.d.ts +14 -13
- package/dist/async-element.d.cts +13 -13
- package/dist/async-element.d.ts +13 -13
- package/dist/components/anim-component.d.cts +33 -5
- package/dist/components/anim-component.d.ts +33 -5
- package/dist/components/{listener-component.d.cts → audio-listener-component.d.cts} +7 -5
- package/dist/components/{listener-component.d.ts → audio-listener-component.d.ts} +7 -5
- package/dist/components/button-component.d.cts +5 -1
- package/dist/components/button-component.d.ts +5 -1
- package/dist/components/camera-component.d.cts +2 -0
- package/dist/components/camera-component.d.ts +2 -0
- package/dist/components/collision-component.d.cts +5 -1
- package/dist/components/collision-component.d.ts +5 -1
- package/dist/components/component.d.cts +3 -2
- package/dist/components/component.d.ts +3 -2
- package/dist/components/element-component.d.cts +7 -0
- package/dist/components/element-component.d.ts +7 -0
- package/dist/components/gsplat-component.d.cts +2 -0
- package/dist/components/gsplat-component.d.ts +2 -0
- package/dist/components/joint-component.d.cts +2 -0
- package/dist/components/joint-component.d.ts +2 -0
- package/dist/components/{layoutchild-component.d.cts → layout-child-component.d.cts} +3 -1
- package/dist/components/{layoutchild-component.d.ts → layout-child-component.d.ts} +3 -1
- package/dist/components/{layoutgroup-component.d.cts → layout-group-component.d.cts} +3 -1
- package/dist/components/{layoutgroup-component.d.ts → layout-group-component.d.ts} +3 -1
- package/dist/components/light-component.d.cts +2 -0
- package/dist/components/light-component.d.ts +2 -0
- package/dist/components/{particlesystem-component.d.cts → particle-system-component.d.cts} +3 -1
- package/dist/components/{particlesystem-component.d.ts → particle-system-component.d.ts} +3 -1
- package/dist/components/render-component.d.cts +2 -0
- package/dist/components/render-component.d.ts +2 -0
- package/dist/components/{rigidbody-component.d.cts → rigid-body-component.d.cts} +3 -1
- package/dist/components/{rigidbody-component.d.ts → rigid-body-component.d.ts} +3 -1
- package/dist/components/screen-component.d.cts +2 -0
- package/dist/components/screen-component.d.ts +2 -0
- package/dist/components/script-component.d.cts +23 -12
- package/dist/components/script-component.d.ts +23 -12
- package/dist/components/{script.d.cts → script-instance.d.cts} +7 -7
- package/dist/components/{script.d.ts → script-instance.d.ts} +7 -7
- package/dist/components/{scrollview-component.d.cts → scroll-view-component.d.cts} +3 -1
- package/dist/components/{scrollview-component.d.ts → scroll-view-component.d.ts} +3 -1
- package/dist/components/scrollbar-component.d.cts +2 -0
- package/dist/components/scrollbar-component.d.ts +2 -0
- package/dist/components/sound-component.d.cts +3 -1
- package/dist/components/sound-component.d.ts +3 -1
- package/dist/components/sound-slot.d.cts +2 -2
- package/dist/components/sound-slot.d.ts +2 -2
- package/dist/custom-elements.json +1603 -986
- package/dist/entity-base.d.cts +6 -5
- package/dist/entity-base.d.ts +6 -5
- package/dist/entity-owner.d.cts +118 -0
- package/dist/entity-owner.d.ts +118 -0
- package/dist/entity.d.cts +8 -101
- package/dist/entity.d.ts +8 -101
- package/dist/index.d.cts +22 -21
- package/dist/index.d.ts +22 -21
- package/dist/model.d.cts +67 -24
- package/dist/model.d.ts +67 -24
- package/dist/pwc.cjs +526 -268
- package/dist/pwc.cjs.map +1 -1
- package/dist/pwc.js +526 -268
- package/dist/pwc.js.map +1 -1
- package/dist/pwc.min.js +1 -1
- package/dist/pwc.min.js.map +1 -1
- package/dist/pwc.min.mjs +1 -1
- package/dist/pwc.min.mjs.map +1 -1
- package/dist/pwc.mjs +523 -266
- package/dist/pwc.mjs.map +1 -1
- package/dist/vscode.html-custom-data.json +145 -90
- package/dist/{module.d.cts → wasm.d.cts} +6 -6
- package/dist/{module.d.ts → wasm.d.ts} +6 -6
- package/dist/web-types.json +378 -250
- package/package.json +7 -7
- package/src/app.ts +45 -35
- package/src/async-element.ts +14 -14
- package/src/components/anim-component.ts +84 -14
- package/src/components/{listener-component.ts → audio-listener-component.ts} +8 -6
- package/src/components/button-component.ts +5 -1
- package/src/components/camera-component.ts +2 -0
- package/src/components/collision-component.ts +5 -1
- package/src/components/component.ts +4 -3
- package/src/components/element-component.ts +7 -0
- package/src/components/gsplat-component.ts +2 -0
- package/src/components/joint-component.ts +2 -0
- package/src/components/{layoutchild-component.ts → layout-child-component.ts} +4 -2
- package/src/components/{layoutgroup-component.ts → layout-group-component.ts} +4 -2
- package/src/components/light-component.ts +2 -0
- package/src/components/{particlesystem-component.ts → particle-system-component.ts} +4 -2
- package/src/components/render-component.ts +2 -0
- package/src/components/{rigidbody-component.ts → rigid-body-component.ts} +4 -2
- package/src/components/screen-component.ts +2 -0
- package/src/components/script-component.ts +63 -42
- package/src/components/{script.ts → script-instance.ts} +14 -14
- package/src/components/{scrollview-component.ts → scroll-view-component.ts} +4 -2
- package/src/components/scrollbar-component.ts +2 -0
- package/src/components/sound-component.ts +4 -2
- package/src/components/sound-slot.ts +4 -4
- package/src/entity-base.ts +6 -5
- package/src/entity-owner.ts +298 -0
- package/src/entity.ts +15 -270
- package/src/index.ts +26 -24
- package/src/model.ts +159 -72
- package/src/node.ts +9 -5
- package/src/{module.ts → wasm.ts} +8 -8
package/dist/pwc.mjs
CHANGED
|
@@ -27,13 +27,13 @@ class AsyncElement extends HTMLElement {
|
|
|
27
27
|
return this.parentElement?.closest('pc-app') ?? null;
|
|
28
28
|
}
|
|
29
29
|
/**
|
|
30
|
-
* The nearest ancestor element that fronts an entity — `<pc-entity
|
|
31
|
-
* `null` if this element has no such ancestor. The search starts at the
|
|
32
|
-
* never resolves to itself.
|
|
30
|
+
* The nearest ancestor element that fronts an entity — `<pc-entity>`, `<pc-model>` or
|
|
31
|
+
* `<pc-node>` — or `null` if this element has no such ancestor. The search starts at the
|
|
32
|
+
* parent, so an element never resolves to itself.
|
|
33
33
|
* @returns The closest entity-fronting element, or `null`.
|
|
34
34
|
*/
|
|
35
35
|
get closestEntity() {
|
|
36
|
-
return this.parentElement?.closest('pc-entity, pc-node') ?? null;
|
|
36
|
+
return this.parentElement?.closest('pc-entity, pc-model, pc-node') ?? null;
|
|
37
37
|
}
|
|
38
38
|
/**
|
|
39
39
|
* Called when the element is fully initialized and ready. Subclasses should call this when
|
|
@@ -107,9 +107,9 @@ async function whenReady(target) {
|
|
|
107
107
|
}
|
|
108
108
|
|
|
109
109
|
/**
|
|
110
|
-
* The
|
|
111
|
-
* {@link https://developer.playcanvas.com/user-manual/web-components/tags/pc-
|
|
112
|
-
* elements. The
|
|
110
|
+
* The WasmElement interface provides properties and methods for manipulating
|
|
111
|
+
* {@link https://developer.playcanvas.com/user-manual/web-components/tags/pc-wasm/ | `<pc-wasm>`}
|
|
112
|
+
* elements. The WasmElement interface also inherits the properties and methods of the
|
|
113
113
|
* {@link AsyncElement} interface.
|
|
114
114
|
*
|
|
115
115
|
* The attributes are read once, when the module starts loading - on the element's first
|
|
@@ -118,7 +118,7 @@ async function whenReady(target) {
|
|
|
118
118
|
* modules configure engine-global state that never unloads, so readiness is not re-armed by
|
|
119
119
|
* removing the element, and a re-inserted element does not load again.
|
|
120
120
|
*
|
|
121
|
-
* A `<pc-
|
|
121
|
+
* A `<pc-wasm>` without a `name` warns and never becomes ready; a containing `<pc-app>` still
|
|
122
122
|
* boots.
|
|
123
123
|
*
|
|
124
124
|
* @attribute {string} name - The name of the WebAssembly module to configure, e.g. `Basis` or
|
|
@@ -128,7 +128,7 @@ async function whenReady(target) {
|
|
|
128
128
|
* @attribute {string} fallback - The URL of the module's asm.js fallback script, used when
|
|
129
129
|
* WebAssembly is unavailable.
|
|
130
130
|
*/
|
|
131
|
-
class
|
|
131
|
+
class WasmElement extends AsyncElement {
|
|
132
132
|
_loadPromise = null;
|
|
133
133
|
connectedCallback() {
|
|
134
134
|
this._getLoadPromise();
|
|
@@ -136,7 +136,7 @@ class ModuleElement extends AsyncElement {
|
|
|
136
136
|
async _loadModule() {
|
|
137
137
|
const name = this.getAttribute('name');
|
|
138
138
|
if (!name) {
|
|
139
|
-
console.warn("pc-
|
|
139
|
+
console.warn("pc-wasm requires a 'name' attribute - no module was configured");
|
|
140
140
|
return;
|
|
141
141
|
}
|
|
142
142
|
const config = {
|
|
@@ -171,7 +171,7 @@ class ModuleElement extends AsyncElement {
|
|
|
171
171
|
return this._loadPromise;
|
|
172
172
|
}
|
|
173
173
|
}
|
|
174
|
-
customElements.define('pc-
|
|
174
|
+
customElements.define('pc-wasm', WasmElement);
|
|
175
175
|
|
|
176
176
|
/** Covers the 0.2s opacity transition; jsdom never fires transitionend, so removal is timed. */
|
|
177
177
|
const REMOVAL_DELAY_MS = 250;
|
|
@@ -728,6 +728,12 @@ const getEntity = (ref) => {
|
|
|
728
728
|
|
|
729
729
|
/** The pointer event types the application synthesizes on `<pc-entity>` elements via picking. */
|
|
730
730
|
const pointerEventTypes = ['pointermove', 'pointerdown', 'pointerup', 'pointerenter', 'pointerleave'];
|
|
731
|
+
/**
|
|
732
|
+
* The event types whose listeners make an element a hover target. Hover resolution walks past
|
|
733
|
+
* elements listening for none of them, so a silent element never swallows an ancestor's
|
|
734
|
+
* enter/leave pair.
|
|
735
|
+
*/
|
|
736
|
+
const hoverEventTypes = ['pointerenter', 'pointerleave', 'pointermove'];
|
|
731
737
|
/**
|
|
732
738
|
* Gives `pc-app` the sizing contract of a replaced element (`<video>`, `<img>`): a block-level
|
|
733
739
|
* box that the page's CSS sizes, defaulting to the canvas's own 300x150 intrinsic size, with the
|
|
@@ -802,9 +808,9 @@ class AppElement extends AsyncElement {
|
|
|
802
808
|
_bootGeneration = 0;
|
|
803
809
|
/**
|
|
804
810
|
* The elements backing this application's entities, keyed by the entity itself. Registered
|
|
805
|
-
* by
|
|
806
|
-
*
|
|
807
|
-
* identity - never by name.
|
|
811
|
+
* by entity-owning elements at creation (pc-entity, and pc-model for its host) and by
|
|
812
|
+
* NodeElement at binding, and removed when an entity is destroyed or unbound, this joins
|
|
813
|
+
* engine scene nodes back to their owning elements by identity - never by name.
|
|
808
814
|
*/
|
|
809
815
|
_entityElements = new Map();
|
|
810
816
|
_picker = null;
|
|
@@ -883,7 +889,7 @@ class AppElement extends AsyncElement {
|
|
|
883
889
|
// there, leaving the element permanently unready: no canvas, no entities, no application.
|
|
884
890
|
//
|
|
885
891
|
// Upgrading is the fix here rather than skipping whatever has not upgraded, because a
|
|
886
|
-
// <pc-
|
|
892
|
+
// <pc-wasm> is the one child that nothing else ever builds on its own behalf - skipping
|
|
887
893
|
// it would drop the wasm module the app asked for, silently and only for cloned apps.
|
|
888
894
|
// Upgrading runs each descendant's connectedCallback synchronously, a few lines earlier
|
|
889
895
|
// than the parser's path runs them but into the same state they see there: no application
|
|
@@ -892,10 +898,10 @@ class AppElement extends AsyncElement {
|
|
|
892
898
|
// as any other disconnect is. An already-upgraded subtree - every other insertion path -
|
|
893
899
|
// is left completely untouched.
|
|
894
900
|
customElements.upgrade(this);
|
|
895
|
-
// Get all pc-
|
|
896
|
-
const
|
|
901
|
+
// Get all pc-wasm elements that are direct children of the pc-app element
|
|
902
|
+
const wasmElements = this.querySelectorAll(':scope > pc-wasm');
|
|
897
903
|
// Wait for all modules to load
|
|
898
|
-
await Promise.all(Array.from(
|
|
904
|
+
await Promise.all(Array.from(wasmElements).map((element) => element._getLoadPromise()));
|
|
899
905
|
// The element may have been removed while the modules loaded. Nothing beyond the loading
|
|
900
906
|
// bar exists yet, and disconnectedCallback has already destroyed that.
|
|
901
907
|
if (generation !== this._bootGeneration) {
|
|
@@ -1065,14 +1071,15 @@ class AppElement extends AsyncElement {
|
|
|
1065
1071
|
Array.from(materialElements).forEach((materialElement) => {
|
|
1066
1072
|
materialElement._createMaterial();
|
|
1067
1073
|
});
|
|
1068
|
-
// Create all entities
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1074
|
+
// Create all entities. pc-model joins the sweep because it owns a host entity of its
|
|
1075
|
+
// own; its instantiated content arrives later, beneath that host.
|
|
1076
|
+
const ownerElements = this.querySelectorAll('pc-entity, pc-model');
|
|
1077
|
+
Array.from(ownerElements).forEach((ownerElement) => {
|
|
1078
|
+
ownerElement._createEntity(app);
|
|
1072
1079
|
});
|
|
1073
1080
|
// Build hierarchy
|
|
1074
|
-
|
|
1075
|
-
|
|
1081
|
+
ownerElements.forEach((ownerElement) => {
|
|
1082
|
+
ownerElement._buildHierarchy(app);
|
|
1076
1083
|
});
|
|
1077
1084
|
// Building the hierarchy dispatched each entity's ready event synchronously, and a
|
|
1078
1085
|
// listener may have removed the element. The sweep itself degrades safely - destroying
|
|
@@ -1183,7 +1190,7 @@ class AppElement extends AsyncElement {
|
|
|
1183
1190
|
// created from onpointer* attributes when their elements were first upgraded, or
|
|
1184
1191
|
// listeners carried over from before a re-boot)
|
|
1185
1192
|
pointerEventTypes.forEach((type) => {
|
|
1186
|
-
const anyListeners = Array.from(this.querySelectorAll('pc-entity, pc-node')).some((entity) => entity._hasListeners(type));
|
|
1193
|
+
const anyListeners = Array.from(this.querySelectorAll('pc-entity, pc-model, pc-node')).some((entity) => entity._hasListeners(type));
|
|
1187
1194
|
if (anyListeners) {
|
|
1188
1195
|
this._onPointerListenerAdded(type);
|
|
1189
1196
|
}
|
|
@@ -1233,10 +1240,10 @@ class AppElement extends AsyncElement {
|
|
|
1233
1240
|
this._entityElements.delete(entity);
|
|
1234
1241
|
}
|
|
1235
1242
|
/**
|
|
1236
|
-
* Returns the `<pc-entity>` or `<pc-node>` element whose backing entity is
|
|
1237
|
-
* `null` if the entity is not fronted by an element of this application - for
|
|
1238
|
-
* unbound node inside a model's instantiated hierarchy, or an entity created
|
|
1239
|
-
* engine API.
|
|
1243
|
+
* Returns the `<pc-entity>`, `<pc-model>` or `<pc-node>` element whose backing entity is
|
|
1244
|
+
* `entity`, or `null` if the entity is not fronted by an element of this application - for
|
|
1245
|
+
* example, an unbound node inside a model's instantiated hierarchy, or an entity created
|
|
1246
|
+
* through the engine API.
|
|
1240
1247
|
*
|
|
1241
1248
|
* @param entity - The entity to look up.
|
|
1242
1249
|
* @returns The element fronting the entity, or `null`.
|
|
@@ -1245,18 +1252,19 @@ class AppElement extends AsyncElement {
|
|
|
1245
1252
|
return this._entityElements.get(entity) ?? null;
|
|
1246
1253
|
}
|
|
1247
1254
|
/**
|
|
1248
|
-
* Resolves the element that owns a picked node: the nearest node up the parent
|
|
1249
|
-
* starting with the node itself -
|
|
1250
|
-
*
|
|
1251
|
-
*
|
|
1255
|
+
* Resolves the element that owns hover for a picked node: the nearest node up the parent
|
|
1256
|
+
* chain - starting with the node itself - whose element listens for any of the hover event
|
|
1257
|
+
* types. Skipping silent elements matches {@link _elementWithListener}, so a registered
|
|
1258
|
+
* element with no hover listeners (a `<pc-model>` host, a plain child entity) is transparent
|
|
1259
|
+
* to hover rather than swallowing a listening ancestor's enter/leave pair.
|
|
1252
1260
|
*
|
|
1253
1261
|
* @param node - The picked node, or `null`.
|
|
1254
|
-
* @returns The owning element, or `null`.
|
|
1262
|
+
* @returns The hover-owning element, or `null`.
|
|
1255
1263
|
*/
|
|
1256
|
-
|
|
1264
|
+
_hoverTarget(node) {
|
|
1257
1265
|
while (node !== null) {
|
|
1258
1266
|
const element = this._entityElements.get(node);
|
|
1259
|
-
if (element) {
|
|
1267
|
+
if (element && hoverEventTypes.some((type) => element._hasListeners(type))) {
|
|
1260
1268
|
return element;
|
|
1261
1269
|
}
|
|
1262
1270
|
node = node.parent;
|
|
@@ -1392,9 +1400,10 @@ class AppElement extends AsyncElement {
|
|
|
1392
1400
|
const node = await this._pickNode(event);
|
|
1393
1401
|
if (token !== this._pickToken || !this._picker)
|
|
1394
1402
|
return;
|
|
1395
|
-
// The hovered element is the nearest one up the node's parent chain
|
|
1396
|
-
//
|
|
1397
|
-
|
|
1403
|
+
// The hovered element is the nearest one up the node's parent chain with a hover
|
|
1404
|
+
// listener - the nearest-listener rule down/up use. Dispatch is still gated per event
|
|
1405
|
+
// type below: having any hover listener selects the target, each event needs its own.
|
|
1406
|
+
const newHoverEntity = this._hoverTarget(node);
|
|
1398
1407
|
// Handle enter/leave events
|
|
1399
1408
|
if (this._hoveredEntity !== newHoverEntity) {
|
|
1400
1409
|
if (this._hoveredEntity && this._hoveredEntity._hasListeners('pointerleave')) {
|
|
@@ -1446,7 +1455,7 @@ class AppElement extends AsyncElement {
|
|
|
1446
1455
|
}
|
|
1447
1456
|
}
|
|
1448
1457
|
_onPointerListenerRemoved(type) {
|
|
1449
|
-
const hasListeners = Array.from(this.querySelectorAll('pc-entity, pc-node')).some((entity) => entity._hasListeners(type));
|
|
1458
|
+
const hasListeners = Array.from(this.querySelectorAll('pc-entity, pc-model, pc-node')).some((entity) => entity._hasListeners(type));
|
|
1450
1459
|
if (!hasListeners && this._canvas) {
|
|
1451
1460
|
this._hasPointerListeners[type] = false;
|
|
1452
1461
|
const handler = type === 'pointerenter' || type === 'pointerleave'
|
|
@@ -1637,11 +1646,12 @@ const POINTER_ATTRIBUTES = [
|
|
|
1637
1646
|
'onpointermove'
|
|
1638
1647
|
];
|
|
1639
1648
|
/**
|
|
1640
|
-
* The base class for elements that front an engine {@link Entity}: `<pc-entity
|
|
1641
|
-
* one, and `<pc-node>`, which binds to one inside a model's
|
|
1642
|
-
* what
|
|
1643
|
-
* picked scene nodes back to elements by identity,
|
|
1644
|
-
* bookkeeping that lets the application lazily attach
|
|
1649
|
+
* The base class for elements that front an engine {@link Entity}: `<pc-entity>` and
|
|
1650
|
+
* `<pc-model>`, which create one, and `<pc-node>`, which binds to one inside a model's
|
|
1651
|
+
* instantiated hierarchy. It carries what all of them need — the `entity` contract, registration
|
|
1652
|
+
* with the owning application (which joins picked scene nodes back to elements by identity,
|
|
1653
|
+
* never by name), and the pointer listener bookkeeping that lets the application lazily attach
|
|
1654
|
+
* its canvas handlers.
|
|
1645
1655
|
*/
|
|
1646
1656
|
class EntityBaseElement extends AsyncElement {
|
|
1647
1657
|
_entity = null;
|
|
@@ -1744,17 +1754,17 @@ class EntityBaseElement extends AsyncElement {
|
|
|
1744
1754
|
}
|
|
1745
1755
|
|
|
1746
1756
|
/**
|
|
1747
|
-
* Creates and parents the entities of every descendant
|
|
1748
|
-
* that no parent's existence depends on document order. Called wherever a subtree could
|
|
1749
|
-
* itself: an element inserted into an application that is already running, and a
|
|
1750
|
-
* children waited for it to bind.
|
|
1757
|
+
* Creates and parents the entities of every descendant entity-owning element of `root`, in two
|
|
1758
|
+
* passes so that no parent's existence depends on document order. Called wherever a subtree could
|
|
1759
|
+
* not build itself: an element inserted into an application that is already running, and a
|
|
1760
|
+
* `<pc-node>` whose children waited for it to bind.
|
|
1751
1761
|
*
|
|
1752
1762
|
* Descendants that are not yet custom elements are skipped, because there is nothing useful to do
|
|
1753
1763
|
* for them and reaching for `_createEntity` would throw. A subtree cloned from a `<template>`
|
|
1754
1764
|
* arrives entirely unupgraded — template content lives in an inert document, where custom element
|
|
1755
1765
|
* definitions are never looked up — and appending the clone upgrades its elements in tree order,
|
|
1756
1766
|
* an element before its descendants. So a sweep from an element's own `connectedCallback` sees
|
|
1757
|
-
* plain `HTMLElement`s below it. Each becomes an
|
|
1767
|
+
* plain `HTMLElement`s below it. Each becomes an entity-owning element moments later and its own
|
|
1758
1768
|
* `connectedCallback` creates and parents it, by which time the ancestor it parents under has its
|
|
1759
1769
|
* entity — the same guarantee tree order gives this sweep.
|
|
1760
1770
|
*
|
|
@@ -1763,35 +1773,18 @@ class EntityBaseElement extends AsyncElement {
|
|
|
1763
1773
|
* @internal
|
|
1764
1774
|
*/
|
|
1765
1775
|
const buildDescendantEntities = (root, app) => {
|
|
1766
|
-
const children = Array.from(root.querySelectorAll('pc-entity')).filter((child) => child instanceof
|
|
1776
|
+
const children = Array.from(root.querySelectorAll('pc-entity, pc-model')).filter((child) => child instanceof EntityOwnerElement);
|
|
1767
1777
|
children.forEach((child) => child._createEntity(app));
|
|
1768
1778
|
children.forEach((child) => child._buildHierarchy(app));
|
|
1769
1779
|
};
|
|
1770
1780
|
/**
|
|
1771
|
-
* The
|
|
1772
|
-
*
|
|
1773
|
-
*
|
|
1774
|
-
*
|
|
1775
|
-
*
|
|
1776
|
-
* The pointer events below are dispatched by the containing `<pc-app>` element when the pointer
|
|
1777
|
-
* intersects this entity's geometry. They are only generated while the entity has a listener for
|
|
1778
|
-
* them, registered either with {@link addEventListener} or with the matching inline `onpointer*`
|
|
1779
|
-
* attribute.
|
|
1780
|
-
*
|
|
1781
|
-
* @attribute {string} onpointerenter - Script to run when the pointer moves onto the entity.
|
|
1782
|
-
* @attribute {string} onpointerleave - Script to run when the pointer moves off the entity.
|
|
1783
|
-
* @attribute {string} onpointermove - Script to run when the pointer moves over the entity.
|
|
1784
|
-
* @attribute {string} onpointerdown - Script to run when a pointer button is pressed over the
|
|
1785
|
-
* entity.
|
|
1786
|
-
* @attribute {string} onpointerup - Script to run when a pointer button is released over the
|
|
1787
|
-
* entity.
|
|
1788
|
-
* @fires {PointerEvent} pointerenter - Fired when the pointer moves onto the entity.
|
|
1789
|
-
* @fires {PointerEvent} pointerleave - Fired when the pointer moves off the entity.
|
|
1790
|
-
* @fires {PointerEvent} pointermove - Fired when the pointer moves over the entity.
|
|
1791
|
-
* @fires {PointerEvent} pointerdown - Fired when a pointer button is pressed over the entity.
|
|
1792
|
-
* @fires {PointerEvent} pointerup - Fired when a pointer button is released over the entity.
|
|
1781
|
+
* The base class for elements that create and own their backing entity: `<pc-entity>` and
|
|
1782
|
+
* `<pc-model>`, whose host entity carries the same authored properties. It carries the cached
|
|
1783
|
+
* property state, entity creation and parenting, and the reset that follows the entity's
|
|
1784
|
+
* destruction. `<pc-node>` sits outside this class: it borrows an entity a model instantiated,
|
|
1785
|
+
* and its properties are nullable overrides rather than owned values.
|
|
1793
1786
|
*/
|
|
1794
|
-
class
|
|
1787
|
+
class EntityOwnerElement extends EntityBaseElement {
|
|
1795
1788
|
/**
|
|
1796
1789
|
* Whether the entity is enabled.
|
|
1797
1790
|
*/
|
|
@@ -1817,7 +1810,8 @@ class EntityElement extends EntityBaseElement {
|
|
|
1817
1810
|
*/
|
|
1818
1811
|
_tags = [];
|
|
1819
1812
|
/**
|
|
1820
|
-
* Whether the hierarchy has been built for this entity
|
|
1813
|
+
* Whether the hierarchy has been built for this entity — set once {@link _buildHierarchy} has
|
|
1814
|
+
* parented it. Read by subclasses that gate work on the entity being in the scene graph.
|
|
1821
1815
|
*/
|
|
1822
1816
|
_built = false;
|
|
1823
1817
|
/**
|
|
@@ -1870,10 +1864,10 @@ class EntityElement extends EntityBaseElement {
|
|
|
1870
1864
|
this._resetReady();
|
|
1871
1865
|
}
|
|
1872
1866
|
/**
|
|
1873
|
-
* Parents the backing entity: under the entity of the nearest ancestor `<pc-entity
|
|
1874
|
-
* `<pc-node>` when there is one, and under the application root otherwise.
|
|
1875
|
-
* containing `<pc-app>` element once a sweep has created every entity, so a
|
|
1876
|
-
* existence never depends on document order.
|
|
1867
|
+
* Parents the backing entity: under the entity of the nearest ancestor `<pc-entity>`,
|
|
1868
|
+
* `<pc-model>` or `<pc-node>` when there is one, and under the application root otherwise.
|
|
1869
|
+
* Called by the containing `<pc-app>` element once a sweep has created every entity, so a
|
|
1870
|
+
* parent's existence never depends on document order.
|
|
1877
1871
|
*
|
|
1878
1872
|
* @param app - The application whose root adopts parentless entities.
|
|
1879
1873
|
* @internal
|
|
@@ -1888,6 +1882,13 @@ class EntityElement extends EntityBaseElement {
|
|
|
1888
1882
|
if (closestEntity && !closestEntity.entity) {
|
|
1889
1883
|
return;
|
|
1890
1884
|
}
|
|
1885
|
+
// An owner that exists but is not yet parented is itself deferred behind an unresolved
|
|
1886
|
+
// node further up. Building beneath it would announce readiness for an entity that is
|
|
1887
|
+
// not in the scene graph; stay unbuilt with it - the node's bind sweeps the whole
|
|
1888
|
+
// subtree, ancestors before descendants.
|
|
1889
|
+
if (closestEntity instanceof EntityOwnerElement && !closestEntity._built) {
|
|
1890
|
+
return;
|
|
1891
|
+
}
|
|
1891
1892
|
this._built = true;
|
|
1892
1893
|
if (closestEntity?.entity) {
|
|
1893
1894
|
closestEntity.entity.addChild(this.entity);
|
|
@@ -1895,35 +1896,16 @@ class EntityElement extends EntityBaseElement {
|
|
|
1895
1896
|
else {
|
|
1896
1897
|
app.root.addChild(this.entity);
|
|
1897
1898
|
}
|
|
1898
|
-
this.
|
|
1899
|
+
this._onBuilt();
|
|
1899
1900
|
}
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
const label = name ? ` '${name}'` : '';
|
|
1909
|
-
console.warn(`pc-entity${label} must be a descendant of pc-app - entity not created`);
|
|
1910
|
-
return;
|
|
1911
|
-
}
|
|
1912
|
-
// If app is already running, create entity immediately
|
|
1913
|
-
if (closestApp._hierarchyReady) {
|
|
1914
|
-
const app = closestApp.app;
|
|
1915
|
-
this._createEntity(app);
|
|
1916
|
-
this._buildHierarchy(app);
|
|
1917
|
-
// Handle any child entities that might exist
|
|
1918
|
-
buildDescendantEntities(this, app);
|
|
1919
|
-
}
|
|
1920
|
-
}
|
|
1921
|
-
disconnectedCallback() {
|
|
1922
|
-
// Destroying the entity destroys its whole subtree, and the engine fires 'destroy' for
|
|
1923
|
-
// every entity in it - so _onEntityDestroy resets this element AND every descendant
|
|
1924
|
-
// element before the descendants' own disconnectedCallbacks run. Their entities are null
|
|
1925
|
-
// by then, making this call a no-op for them.
|
|
1926
|
-
this._entity?.destroy();
|
|
1901
|
+
/**
|
|
1902
|
+
* Called by {@link _buildHierarchy} once the backing entity has been parented — exactly once
|
|
1903
|
+
* per build cycle. The default announces readiness, which is what a parented `<pc-entity>`
|
|
1904
|
+
* means; `<pc-model>` overrides it to start loading content instead, because its readiness
|
|
1905
|
+
* tracks the content settling rather than the host entering the scene graph.
|
|
1906
|
+
*/
|
|
1907
|
+
_onBuilt() {
|
|
1908
|
+
this._onReady();
|
|
1927
1909
|
}
|
|
1928
1910
|
/**
|
|
1929
1911
|
* Sets the enabled state of the entity.
|
|
@@ -2028,6 +2010,70 @@ class EntityElement extends EntityBaseElement {
|
|
|
2028
2010
|
get tags() {
|
|
2029
2011
|
return this._tags;
|
|
2030
2012
|
}
|
|
2013
|
+
}
|
|
2014
|
+
|
|
2015
|
+
/**
|
|
2016
|
+
* The EntityElement interface provides properties and methods for manipulating
|
|
2017
|
+
* {@link https://developer.playcanvas.com/user-manual/web-components/tags/pc-entity/ | `<pc-entity>`} elements.
|
|
2018
|
+
* The EntityElement interface also inherits the properties and methods of the
|
|
2019
|
+
* {@link HTMLElement} interface.
|
|
2020
|
+
*
|
|
2021
|
+
* The pointer events below are dispatched by the containing `<pc-app>` element when the pointer
|
|
2022
|
+
* intersects this entity's geometry. They are only generated while the entity has a listener for
|
|
2023
|
+
* them, registered either with {@link addEventListener} or with the matching inline `onpointer*`
|
|
2024
|
+
* attribute.
|
|
2025
|
+
*
|
|
2026
|
+
* @attribute {boolean} enabled - The enabled state of the entity.
|
|
2027
|
+
* @attribute {string} name - The name of the entity.
|
|
2028
|
+
* @attribute {string} position - The position of the entity.
|
|
2029
|
+
* @attribute {string} rotation - The rotation of the entity.
|
|
2030
|
+
* @attribute {string} scale - The scale of the entity.
|
|
2031
|
+
* @attribute {string} tags - The tags of the entity.
|
|
2032
|
+
* @attribute {string} onpointerenter - Script to run when the pointer moves onto the entity.
|
|
2033
|
+
* @attribute {string} onpointerleave - Script to run when the pointer moves off the entity.
|
|
2034
|
+
* @attribute {string} onpointermove - Script to run when the pointer moves over the entity.
|
|
2035
|
+
* @attribute {string} onpointerdown - Script to run when a pointer button is pressed over the
|
|
2036
|
+
* entity.
|
|
2037
|
+
* @attribute {string} onpointerup - Script to run when a pointer button is released over the
|
|
2038
|
+
* entity.
|
|
2039
|
+
* @fires {PointerEvent} pointerenter - Fired when the pointer moves onto the entity.
|
|
2040
|
+
* @fires {PointerEvent} pointerleave - Fired when the pointer moves off the entity.
|
|
2041
|
+
* @fires {PointerEvent} pointermove - Fired when the pointer moves over the entity.
|
|
2042
|
+
* @fires {PointerEvent} pointerdown - Fired when a pointer button is pressed over the entity.
|
|
2043
|
+
* @fires {PointerEvent} pointerup - Fired when a pointer button is released over the entity.
|
|
2044
|
+
*/
|
|
2045
|
+
class EntityElement extends EntityOwnerElement {
|
|
2046
|
+
connectedCallback() {
|
|
2047
|
+
// Wait for app to be ready
|
|
2048
|
+
const closestApp = this.closestApp;
|
|
2049
|
+
if (!closestApp) {
|
|
2050
|
+
// An entity outside an application is inert and never becomes ready, so awaiting it
|
|
2051
|
+
// hangs. Warn rather than fail silently, naming the parent it requires, as every other
|
|
2052
|
+
// misplaced element does.
|
|
2053
|
+
const name = this.getAttribute('name');
|
|
2054
|
+
const label = name ? ` '${name}'` : '';
|
|
2055
|
+
console.warn(`pc-entity${label} must be a descendant of pc-app - entity not created`);
|
|
2056
|
+
return;
|
|
2057
|
+
}
|
|
2058
|
+
// If app is already running, create entity immediately
|
|
2059
|
+
if (closestApp._hierarchyReady) {
|
|
2060
|
+
const app = closestApp.app;
|
|
2061
|
+
this._createEntity(app);
|
|
2062
|
+
this._buildHierarchy(app);
|
|
2063
|
+
// Handle any child entities that might exist. A build that deferred (an unresolved
|
|
2064
|
+
// pc-node above) defers the whole subtree with it - the node's bind sweeps it.
|
|
2065
|
+
if (this._built) {
|
|
2066
|
+
buildDescendantEntities(this, app);
|
|
2067
|
+
}
|
|
2068
|
+
}
|
|
2069
|
+
}
|
|
2070
|
+
disconnectedCallback() {
|
|
2071
|
+
// Destroying the entity destroys its whole subtree, and the engine fires 'destroy' for
|
|
2072
|
+
// every entity in it - so _onEntityDestroy resets this element AND every descendant
|
|
2073
|
+
// element before the descendants' own disconnectedCallbacks run. Their entities are null
|
|
2074
|
+
// by then, making this call a no-op for them.
|
|
2075
|
+
this._entity?.destroy();
|
|
2076
|
+
}
|
|
2031
2077
|
static get observedAttributes() {
|
|
2032
2078
|
return ['enabled', 'name', 'position', 'rotation', 'scale', 'tags', ...POINTER_ATTRIBUTES];
|
|
2033
2079
|
}
|
|
@@ -2965,14 +3011,42 @@ const formatHierarchy = (root, counts) => {
|
|
|
2965
3011
|
* The ModelElement interface also inherits the properties and methods of the
|
|
2966
3012
|
* {@link HTMLElement} interface.
|
|
2967
3013
|
*
|
|
2968
|
-
* The element
|
|
2969
|
-
*
|
|
2970
|
-
*
|
|
2971
|
-
*
|
|
2972
|
-
*
|
|
2973
|
-
*
|
|
2974
|
-
* becomes ready
|
|
3014
|
+
* The element creates and fronts a stable host entity: `entity` is that host, created when the
|
|
3015
|
+
* application builds its hierarchy and kept across `asset` changes, so the element's transform
|
|
3016
|
+
* and tags are instance placement that composes with whatever transform the asset authored on
|
|
3017
|
+
* its root. The instantiated content is parented beneath the host and exposed as
|
|
3018
|
+
* {@link contentEntity}.
|
|
3019
|
+
*
|
|
3020
|
+
* The element becomes ready once its current asset selection has settled: the container asset
|
|
3021
|
+
* has loaded and its content root has been parented beneath the host, the load has failed
|
|
3022
|
+
* (`contentEntity` stays `null` — listen for `error`, or check `contentEntity`, to tell the
|
|
3023
|
+
* outcomes apart), or no asset is assigned at all. Changing `asset` re-arms readiness and
|
|
3024
|
+
* instantiates anew, so a `ready()` obtained after the change resolves against the new content.
|
|
3025
|
+
* A `pc-model` outside a `pc-app`, or referencing an unknown asset id, warns and never becomes
|
|
3026
|
+
* ready.
|
|
3027
|
+
*
|
|
3028
|
+
* The pointer events below are dispatched by the containing `<pc-app>` element when the pointer
|
|
3029
|
+
* intersects the model's geometry, exactly as for `<pc-entity>` — a hit on a content node that no
|
|
3030
|
+
* `pc-node` fronts resolves to this element.
|
|
2975
3031
|
*
|
|
3032
|
+
* @attribute {boolean} enabled - The enabled state of the model.
|
|
3033
|
+
* @attribute {string} name - The name of the model.
|
|
3034
|
+
* @attribute {string} position - The position of the model.
|
|
3035
|
+
* @attribute {string} rotation - The rotation of the model.
|
|
3036
|
+
* @attribute {string} scale - The scale of the model.
|
|
3037
|
+
* @attribute {string} tags - The tags of the model.
|
|
3038
|
+
* @attribute {string} onpointerenter - Script to run when the pointer moves onto the model.
|
|
3039
|
+
* @attribute {string} onpointerleave - Script to run when the pointer moves off the model.
|
|
3040
|
+
* @attribute {string} onpointermove - Script to run when the pointer moves over the model.
|
|
3041
|
+
* @attribute {string} onpointerdown - Script to run when a pointer button is pressed over the
|
|
3042
|
+
* model.
|
|
3043
|
+
* @attribute {string} onpointerup - Script to run when a pointer button is released over the
|
|
3044
|
+
* model.
|
|
3045
|
+
* @fires {PointerEvent} pointerenter - Fired when the pointer moves onto the model.
|
|
3046
|
+
* @fires {PointerEvent} pointerleave - Fired when the pointer moves off the model.
|
|
3047
|
+
* @fires {PointerEvent} pointermove - Fired when the pointer moves over the model.
|
|
3048
|
+
* @fires {PointerEvent} pointerdown - Fired when a pointer button is pressed over the model.
|
|
3049
|
+
* @fires {PointerEvent} pointerup - Fired when a pointer button is released over the model.
|
|
2976
3050
|
* @fires {Event} load - Fired each time a container asset finishes instantiating, including
|
|
2977
3051
|
* re-instantiation after `asset` changes. Does not bubble — listen on this element, or use a
|
|
2978
3052
|
* capture-phase listener on an ancestor.
|
|
@@ -2980,14 +3054,14 @@ const formatHierarchy = (root, counts) => {
|
|
|
2980
3054
|
* error in `message`. Does not bubble. The element still becomes ready — readiness means the load
|
|
2981
3055
|
* settled, not that it succeeded.
|
|
2982
3056
|
*/
|
|
2983
|
-
class ModelElement extends
|
|
3057
|
+
class ModelElement extends EntityOwnerElement {
|
|
2984
3058
|
_asset = '';
|
|
2985
|
-
|
|
3059
|
+
_contentEntity = null;
|
|
2986
3060
|
/**
|
|
2987
|
-
* Incremented on every new load
|
|
2988
|
-
* load that resumes from an await or a load callback abandons
|
|
2989
|
-
* on, so a superseded load can neither instantiate a second
|
|
2990
|
-
*
|
|
3061
|
+
* Incremented on every new load, on disconnect, and when the host entity dies, and captured
|
|
3062
|
+
* by a load when it starts. A load that resumes from an await or a load callback abandons
|
|
3063
|
+
* itself if the value has moved on, so a superseded load can neither instantiate a second
|
|
3064
|
+
* content root nor parent one under a host a newer cycle has already replaced.
|
|
2991
3065
|
*/
|
|
2992
3066
|
_loadGeneration = 0;
|
|
2993
3067
|
/**
|
|
@@ -2998,12 +3072,13 @@ class ModelElement extends AsyncElement {
|
|
|
2998
3072
|
_loadHandle = null;
|
|
2999
3073
|
_errorHandle = null;
|
|
3000
3074
|
/**
|
|
3001
|
-
* The root entity of the instantiated model
|
|
3002
|
-
*
|
|
3003
|
-
*
|
|
3075
|
+
* The root entity of the instantiated model content, parented beneath the host entity.
|
|
3076
|
+
* `null` until the container asset has loaded and been instantiated, after a failed load,
|
|
3077
|
+
* and again once the element has been removed from the document.
|
|
3078
|
+
* @returns The content root entity, or `null`.
|
|
3004
3079
|
*/
|
|
3005
|
-
get
|
|
3006
|
-
return this.
|
|
3080
|
+
get contentEntity() {
|
|
3081
|
+
return this._contentEntity;
|
|
3007
3082
|
}
|
|
3008
3083
|
/**
|
|
3009
3084
|
* Returns a snapshot of the instantiated node tree, or `null` while there is none (the
|
|
@@ -3015,12 +3090,13 @@ class ModelElement extends AsyncElement {
|
|
|
3015
3090
|
* is the printable form.
|
|
3016
3091
|
*
|
|
3017
3092
|
* The snapshot is plain data, computed afresh each call: it does not follow later changes
|
|
3018
|
-
* to the hierarchy, and mutating it changes nothing.
|
|
3093
|
+
* to the hierarchy, and mutating it changes nothing. It covers the instantiated content
|
|
3094
|
+
* only — the host entity the element fronts is not part of the asset's node tree.
|
|
3019
3095
|
*
|
|
3020
3096
|
* @returns The root of the instantiated node tree, or `null`.
|
|
3021
3097
|
*/
|
|
3022
3098
|
hierarchy() {
|
|
3023
|
-
const root = this.
|
|
3099
|
+
const root = this._contentEntity;
|
|
3024
3100
|
if (!root) {
|
|
3025
3101
|
return null;
|
|
3026
3102
|
}
|
|
@@ -3060,18 +3136,53 @@ class ModelElement extends AsyncElement {
|
|
|
3060
3136
|
// A model outside an application is inert and never becomes ready, so awaiting it hangs.
|
|
3061
3137
|
// Warn rather than fail silently, naming the parent it requires, as every other misplaced
|
|
3062
3138
|
// element does.
|
|
3063
|
-
|
|
3139
|
+
const closestApp = this.closestApp;
|
|
3140
|
+
if (!closestApp) {
|
|
3064
3141
|
const label = this._asset ? ` '${this._asset}'` : '';
|
|
3065
3142
|
console.warn(`pc-model${label} must be a descendant of pc-app - model not created`);
|
|
3066
3143
|
return;
|
|
3067
3144
|
}
|
|
3068
|
-
|
|
3145
|
+
// If the app is already running, create the host immediately; during a boot, the app's
|
|
3146
|
+
// own sweep does it. Either way, _onBuilt starts the content load once the host is
|
|
3147
|
+
// parented.
|
|
3148
|
+
if (closestApp._hierarchyReady) {
|
|
3149
|
+
const app = closestApp.app;
|
|
3150
|
+
this._createEntity(app);
|
|
3151
|
+
this._buildHierarchy(app);
|
|
3152
|
+
// A build that deferred (an unresolved pc-node above) defers the whole subtree with
|
|
3153
|
+
// it - the node's bind sweeps it.
|
|
3154
|
+
if (this._built) {
|
|
3155
|
+
buildDescendantEntities(this, app);
|
|
3156
|
+
}
|
|
3157
|
+
}
|
|
3069
3158
|
}
|
|
3070
3159
|
disconnectedCallback() {
|
|
3160
|
+
// Destroying the host destroys the instantiated content with it, and the destroy hook
|
|
3161
|
+
// resets the element. The generation guard comes first so a load suspended on an await
|
|
3162
|
+
// cannot resume against the torn-down element.
|
|
3071
3163
|
this._loadGeneration++;
|
|
3072
3164
|
this._detachLoadHandlers();
|
|
3073
|
-
this.
|
|
3074
|
-
|
|
3165
|
+
this._entity?.destroy();
|
|
3166
|
+
}
|
|
3167
|
+
/**
|
|
3168
|
+
* Starts (or restarts) the content load once the host has been parented. Readiness is not
|
|
3169
|
+
* announced here — it tracks the content settling, not the host entering the scene graph.
|
|
3170
|
+
*/
|
|
3171
|
+
_onBuilt() {
|
|
3172
|
+
this._loadContent();
|
|
3173
|
+
}
|
|
3174
|
+
/**
|
|
3175
|
+
* Extends the owner reset for the content: the engine's destroy cascade has already taken
|
|
3176
|
+
* the content root down with the host subtree, so only the reference and the in-flight load
|
|
3177
|
+
* are dropped here. The next build re-creates the host and re-instantiates the content.
|
|
3178
|
+
*
|
|
3179
|
+
* @param entity - The host entity that was destroyed.
|
|
3180
|
+
*/
|
|
3181
|
+
_onEntityDestroy(entity) {
|
|
3182
|
+
this._loadGeneration++;
|
|
3183
|
+
this._detachLoadHandlers();
|
|
3184
|
+
this._contentEntity = null;
|
|
3185
|
+
super._onEntityDestroy(entity);
|
|
3075
3186
|
}
|
|
3076
3187
|
_detachLoadHandlers() {
|
|
3077
3188
|
this._loadHandle?.off();
|
|
@@ -3080,51 +3191,34 @@ class ModelElement extends AsyncElement {
|
|
|
3080
3191
|
this._errorHandle = null;
|
|
3081
3192
|
}
|
|
3082
3193
|
/**
|
|
3083
|
-
* Resolves readiness and dispatches the `load` event. Called once the instantiated
|
|
3084
|
-
* has been parented —
|
|
3085
|
-
* model's
|
|
3194
|
+
* Resolves readiness and dispatches the `load` event. Called once the instantiated content
|
|
3195
|
+
* has been parented beneath the host — the host itself is already in the scene graph by
|
|
3196
|
+
* then, so a ready model's content always has world transforms.
|
|
3086
3197
|
*/
|
|
3087
3198
|
_announceLoad() {
|
|
3088
3199
|
this._onReady();
|
|
3089
3200
|
this.dispatchEvent(new Event('load'));
|
|
3090
3201
|
}
|
|
3091
3202
|
_instantiate(container) {
|
|
3092
|
-
const
|
|
3093
|
-
|
|
3094
|
-
this._entity
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
});
|
|
3107
|
-
}
|
|
3108
|
-
else {
|
|
3109
|
-
const appElement = this.closestApp;
|
|
3110
|
-
if (appElement) {
|
|
3111
|
-
appElement.ready().then(() => {
|
|
3112
|
-
if (generation !== this._loadGeneration) {
|
|
3113
|
-
return;
|
|
3114
|
-
}
|
|
3115
|
-
appElement.app.root.addChild(entity);
|
|
3116
|
-
this._announceLoad();
|
|
3117
|
-
});
|
|
3118
|
-
}
|
|
3119
|
-
}
|
|
3120
|
-
}
|
|
3121
|
-
async _loadModel() {
|
|
3122
|
-
this._unloadModel();
|
|
3203
|
+
const content = container.instantiateRenderEntity();
|
|
3204
|
+
this._contentEntity = content;
|
|
3205
|
+
this._entity.addChild(content);
|
|
3206
|
+
this._announceLoad();
|
|
3207
|
+
}
|
|
3208
|
+
_destroyContent() {
|
|
3209
|
+
this._contentEntity?.destroy();
|
|
3210
|
+
this._contentEntity = null;
|
|
3211
|
+
}
|
|
3212
|
+
async _loadContent() {
|
|
3213
|
+
// The old content goes down synchronously, so a reader that checks after an asset change
|
|
3214
|
+
// never sees the outgoing hierarchy. The host survives - components and child entities
|
|
3215
|
+
// attached to it carry over to the new content.
|
|
3216
|
+
this._destroyContent();
|
|
3123
3217
|
// Supersede any load already in flight - only the newest load may instantiate
|
|
3124
3218
|
const generation = ++this._loadGeneration;
|
|
3125
3219
|
this._detachLoadHandlers();
|
|
3126
3220
|
// Re-arm readiness so a waiter obtained after an asset change resolves against the new
|
|
3127
|
-
//
|
|
3221
|
+
// content. A no-op on first connection, where readiness is still pending.
|
|
3128
3222
|
this._resetReady();
|
|
3129
3223
|
const appElement = this.closestApp;
|
|
3130
3224
|
if (!appElement) {
|
|
@@ -3136,14 +3230,23 @@ class ModelElement extends AsyncElement {
|
|
|
3136
3230
|
if (generation !== this._loadGeneration) {
|
|
3137
3231
|
return;
|
|
3138
3232
|
}
|
|
3233
|
+
// The host may not be parented yet - a model under a pc-node that has not bound, reached
|
|
3234
|
+
// through the asset setter. Nothing settles here: _onBuilt re-runs this load once the
|
|
3235
|
+
// host builds.
|
|
3236
|
+
if (!this._entity || !this._built) {
|
|
3237
|
+
return;
|
|
3238
|
+
}
|
|
3239
|
+
if (this._asset === '') {
|
|
3240
|
+
// No asset assigned is a settled selection: the element is a usable host (components
|
|
3241
|
+
// attach, waiters resolve) with no content. Assigning an asset later re-arms.
|
|
3242
|
+
this._onReady();
|
|
3243
|
+
return;
|
|
3244
|
+
}
|
|
3139
3245
|
const asset = useAsset(this._asset);
|
|
3140
3246
|
if (!asset) {
|
|
3141
|
-
//
|
|
3142
|
-
// non-empty one that resolves to nothing is a dead end - say so rather than staying
|
|
3247
|
+
// A non-empty id that resolves to nothing is a dead end - say so rather than staying
|
|
3143
3248
|
// silently pending.
|
|
3144
|
-
|
|
3145
|
-
console.warn(`pc-model could not find asset '${this._asset}' - model not created`);
|
|
3146
|
-
}
|
|
3249
|
+
console.warn(`pc-model could not find asset '${this._asset}' - model not created`);
|
|
3147
3250
|
return;
|
|
3148
3251
|
}
|
|
3149
3252
|
if (asset.loaded) {
|
|
@@ -3165,7 +3268,7 @@ class ModelElement extends AsyncElement {
|
|
|
3165
3268
|
if (generation !== this._loadGeneration) {
|
|
3166
3269
|
return;
|
|
3167
3270
|
}
|
|
3168
|
-
// A failed load settles readiness with a null
|
|
3271
|
+
// A failed load settles readiness with a null contentEntity, mirroring pc-asset:
|
|
3169
3272
|
// readiness means the load settled, not that it succeeded.
|
|
3170
3273
|
this.dispatchEvent(new ErrorEvent('error', {
|
|
3171
3274
|
message: err instanceof Error ? err.message : String(err)
|
|
@@ -3174,10 +3277,6 @@ class ModelElement extends AsyncElement {
|
|
|
3174
3277
|
});
|
|
3175
3278
|
}
|
|
3176
3279
|
}
|
|
3177
|
-
_unloadModel() {
|
|
3178
|
-
this._entity?.destroy();
|
|
3179
|
-
this._entity = null;
|
|
3180
|
-
}
|
|
3181
3280
|
/**
|
|
3182
3281
|
* Sets the id of the `pc-asset` to use for the model.
|
|
3183
3282
|
* @param value - The asset ID.
|
|
@@ -3185,7 +3284,7 @@ class ModelElement extends AsyncElement {
|
|
|
3185
3284
|
set asset(value) {
|
|
3186
3285
|
this._asset = value;
|
|
3187
3286
|
if (this.isConnected) {
|
|
3188
|
-
this.
|
|
3287
|
+
this._loadContent();
|
|
3189
3288
|
}
|
|
3190
3289
|
}
|
|
3191
3290
|
/**
|
|
@@ -3196,13 +3295,38 @@ class ModelElement extends AsyncElement {
|
|
|
3196
3295
|
return this._asset;
|
|
3197
3296
|
}
|
|
3198
3297
|
static get observedAttributes() {
|
|
3199
|
-
return ['asset'];
|
|
3298
|
+
return ['asset', 'enabled', 'name', 'position', 'rotation', 'scale', 'tags', ...POINTER_ATTRIBUTES];
|
|
3200
3299
|
}
|
|
3201
3300
|
attributeChangedCallback(name, _oldValue, newValue) {
|
|
3202
3301
|
switch (name) {
|
|
3203
3302
|
case 'asset':
|
|
3204
3303
|
this.asset = newValue ?? '';
|
|
3205
3304
|
break;
|
|
3305
|
+
case 'enabled':
|
|
3306
|
+
this.enabled = parseBool(newValue, true);
|
|
3307
|
+
break;
|
|
3308
|
+
case 'name':
|
|
3309
|
+
this.name = newValue ?? 'Untitled';
|
|
3310
|
+
break;
|
|
3311
|
+
case 'position':
|
|
3312
|
+
this.position = parseVec3(newValue, Vec3.ZERO, name);
|
|
3313
|
+
break;
|
|
3314
|
+
case 'rotation':
|
|
3315
|
+
this.rotation = parseVec3(newValue, Vec3.ZERO, name);
|
|
3316
|
+
break;
|
|
3317
|
+
case 'scale':
|
|
3318
|
+
this.scale = parseVec3(newValue, Vec3.ONE, name);
|
|
3319
|
+
break;
|
|
3320
|
+
case 'tags':
|
|
3321
|
+
this.tags = parseTags(newValue);
|
|
3322
|
+
break;
|
|
3323
|
+
case 'onpointerenter':
|
|
3324
|
+
case 'onpointerleave':
|
|
3325
|
+
case 'onpointerdown':
|
|
3326
|
+
case 'onpointerup':
|
|
3327
|
+
case 'onpointermove':
|
|
3328
|
+
this._updateInlineHandler(name, newValue);
|
|
3329
|
+
break;
|
|
3206
3330
|
}
|
|
3207
3331
|
}
|
|
3208
3332
|
}
|
|
@@ -3293,7 +3417,7 @@ class ComponentElement extends AsyncElement {
|
|
|
3293
3417
|
// A component can only exist on an entity, so an element placed outside one is inert.
|
|
3294
3418
|
// It still becomes ready (with a null `component`), so warn rather than fail silently
|
|
3295
3419
|
const label = this.id ? ` '${this.id}'` : '';
|
|
3296
|
-
console.warn(`${this.tagName.toLowerCase()}${label} must be a descendant of pc-entity - component not added`);
|
|
3420
|
+
console.warn(`${this.tagName.toLowerCase()}${label} must be a descendant of pc-entity, pc-model or pc-node - component not added`);
|
|
3297
3421
|
return;
|
|
3298
3422
|
}
|
|
3299
3423
|
await entityElement.ready();
|
|
@@ -3381,8 +3505,9 @@ class ComponentElement extends AsyncElement {
|
|
|
3381
3505
|
}
|
|
3382
3506
|
/**
|
|
3383
3507
|
* The PlayCanvas component instance. `null` until the element is ready, and also for an
|
|
3384
|
-
* element that is not a descendant of
|
|
3385
|
-
* element's `ready()` promise
|
|
3508
|
+
* element that is not a descendant of an entity-fronting element (`<pc-entity>`,
|
|
3509
|
+
* `<pc-model>` or `<pc-node>`) — await {@link whenReady} or the element's `ready()` promise
|
|
3510
|
+
* before accessing it.
|
|
3386
3511
|
* @returns The component instance, or `null`.
|
|
3387
3512
|
*/
|
|
3388
3513
|
get component() {
|
|
@@ -3435,6 +3560,8 @@ class ComponentElement extends AsyncElement {
|
|
|
3435
3560
|
* the underlying {@link AnimComponent} (via {@link component}) for playback state beyond what
|
|
3436
3561
|
* this element exposes.
|
|
3437
3562
|
*
|
|
3563
|
+
* Engine component: {@link AnimComponent} (`anim`).
|
|
3564
|
+
*
|
|
3438
3565
|
* @category Components
|
|
3439
3566
|
*/
|
|
3440
3567
|
class AnimComponentElement extends ComponentElement {
|
|
@@ -3456,6 +3583,11 @@ class AnimComponentElement extends ComponentElement {
|
|
|
3456
3583
|
* The name of the active clip.
|
|
3457
3584
|
*/
|
|
3458
3585
|
_clip = '';
|
|
3586
|
+
/**
|
|
3587
|
+
* The binding root this element last assigned through {@link _applyRootBone}, distinguishing
|
|
3588
|
+
* its own writes from a `rootBone` assigned through the engine API — which is left alone.
|
|
3589
|
+
*/
|
|
3590
|
+
_managedRootBone = null;
|
|
3459
3591
|
/**
|
|
3460
3592
|
* The element the model-readiness listener is attached to, held so disconnection can detach
|
|
3461
3593
|
* it after `closestEntity` no longer resolves.
|
|
@@ -3481,27 +3613,71 @@ class AnimComponentElement extends ComponentElement {
|
|
|
3481
3613
|
*/
|
|
3482
3614
|
_warnedClip = null;
|
|
3483
3615
|
/**
|
|
3484
|
-
* Rebinds when a model
|
|
3485
|
-
*
|
|
3616
|
+
* Rebinds when a model that is not this component's host announces readiness — a sibling or
|
|
3617
|
+
* deeper model whose content changed under the assigned clips. The engine resolves each
|
|
3618
|
+
* curve once, at the first tick after assignment, and never retries — and its mesh-instance
|
|
3486
3619
|
* broadcast fires before an instantiated hierarchy is parented, so a model that loads after
|
|
3487
|
-
* the clips were assigned would otherwise stay silently unbound.
|
|
3488
|
-
*
|
|
3489
|
-
*
|
|
3620
|
+
* the clips were assigned would otherwise stay silently unbound. The host model's own cycles
|
|
3621
|
+
* are excluded: those re-enter through {@link initComponent}, which refreshes the whole clip
|
|
3622
|
+
* set against the new container.
|
|
3490
3623
|
*/
|
|
3491
3624
|
_onModelReady = (event) => {
|
|
3492
3625
|
if (!(event.target instanceof ModelElement) || !this.component) {
|
|
3493
3626
|
return;
|
|
3494
3627
|
}
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
|
|
3501
|
-
}
|
|
3628
|
+
// The host model's own readiness cycle already re-initialized this component through
|
|
3629
|
+
// ComponentElement's host-ready listener, which is attached first and so has run by now.
|
|
3630
|
+
// Acting here too would resolve every track twice and capture the playhead-restore
|
|
3631
|
+
// snapshot mid-rebuild.
|
|
3632
|
+
if (event.target === this._modelListenerTarget) {
|
|
3633
|
+
return;
|
|
3502
3634
|
}
|
|
3635
|
+
// A model cycle can replace the skeleton source's host entity (a rebuild under a
|
|
3636
|
+
// retargeting pc-node), so the binding root is re-asserted before the rebind.
|
|
3637
|
+
this._applyRootBone();
|
|
3503
3638
|
this.component.rebind();
|
|
3504
3639
|
};
|
|
3640
|
+
/**
|
|
3641
|
+
* The model whose host entity scopes this component's curve binding: the parent `pc-model`,
|
|
3642
|
+
* or the sole `pc-model` among the parent's direct children (the arrangement where clips
|
|
3643
|
+
* live in a library asset beside the skeleton). `null` when there is no such model, or more
|
|
3644
|
+
* than one — an ambiguous skeleton is left to the engine's name-based resolution.
|
|
3645
|
+
*/
|
|
3646
|
+
_skeletonSource() {
|
|
3647
|
+
const parent = this.parentElement;
|
|
3648
|
+
if (parent instanceof ModelElement) {
|
|
3649
|
+
return parent;
|
|
3650
|
+
}
|
|
3651
|
+
const models = parent ? parent.querySelectorAll(':scope > pc-model') : null;
|
|
3652
|
+
return models?.length === 1 && models[0] instanceof ModelElement ? models[0] : null;
|
|
3653
|
+
}
|
|
3654
|
+
/**
|
|
3655
|
+
* Keeps the component's binding root pointing at the skeleton source's host entity. The host
|
|
3656
|
+
* wraps the instantiated content, so left at its default — the component's own entity — the
|
|
3657
|
+
* engine binder mis-resolves curves that target the asset's root node: its fallback treats
|
|
3658
|
+
* the graph as the asset root once the root is no longer a direct child.
|
|
3659
|
+
*
|
|
3660
|
+
* Authoritative in both directions for values this element assigned: a source appearing pins
|
|
3661
|
+
* its host, and a source dissolving (the model gone, or a second model making the skeleton
|
|
3662
|
+
* ambiguous) clears the pin rather than leaving it on a stale host. A root assigned through
|
|
3663
|
+
* the engine API is never overwritten — the user's choice outranks the managed default.
|
|
3664
|
+
* Writes are skipped while unchanged, because the engine setter itself triggers a rebind.
|
|
3665
|
+
*/
|
|
3666
|
+
_applyRootBone() {
|
|
3667
|
+
const component = this.component;
|
|
3668
|
+
// A non-null root this element did not assign came through the engine API. A fresh
|
|
3669
|
+
// component starts at null, which is always reclaimable.
|
|
3670
|
+
if (component.rootBone !== null && component.rootBone !== this._managedRootBone) {
|
|
3671
|
+
return;
|
|
3672
|
+
}
|
|
3673
|
+
const host = this._skeletonSource()?.entity ?? null;
|
|
3674
|
+
if (component.rootBone !== host) {
|
|
3675
|
+
// The engine setter accepts null - restoring the component's own entity as the
|
|
3676
|
+
// binding graph - but its declared type does not
|
|
3677
|
+
component.rootBone = host;
|
|
3678
|
+
}
|
|
3679
|
+
this._managedRootBone = host;
|
|
3680
|
+
}
|
|
3505
3681
|
/** @ignore */
|
|
3506
3682
|
constructor() {
|
|
3507
3683
|
super('anim');
|
|
@@ -3526,7 +3702,16 @@ class AnimComponentElement extends ComponentElement {
|
|
|
3526
3702
|
host.addEventListener('ready', this._onModelReady);
|
|
3527
3703
|
this._modelListenerTarget = host;
|
|
3528
3704
|
}
|
|
3529
|
-
this.
|
|
3705
|
+
this._applyRootBone();
|
|
3706
|
+
if (this.component.baseLayer) {
|
|
3707
|
+
// The component survived the host's readiness cycle (a pc-model reloading content on
|
|
3708
|
+
// its stable host entity). A loaded graph cannot be reassigned in place, so drop it
|
|
3709
|
+
// and reassign from the current source, restoring the active clip and playhead.
|
|
3710
|
+
this._refreshClips();
|
|
3711
|
+
}
|
|
3712
|
+
else {
|
|
3713
|
+
this._applyClips();
|
|
3714
|
+
}
|
|
3530
3715
|
}
|
|
3531
3716
|
disconnectedCallback() {
|
|
3532
3717
|
this._modelListenerTarget?.removeEventListener('ready', this._onModelReady);
|
|
@@ -3536,6 +3721,7 @@ class AnimComponentElement extends ComponentElement {
|
|
|
3536
3721
|
this._sourceGeneration++;
|
|
3537
3722
|
this._assignedClips.clear();
|
|
3538
3723
|
this._autoAssigned = false;
|
|
3724
|
+
this._managedRootBone = null;
|
|
3539
3725
|
super.disconnectedCallback();
|
|
3540
3726
|
}
|
|
3541
3727
|
/**
|
|
@@ -3704,6 +3890,10 @@ class AnimComponentElement extends ComponentElement {
|
|
|
3704
3890
|
if (!component) {
|
|
3705
3891
|
return;
|
|
3706
3892
|
}
|
|
3893
|
+
// A clip-set change is also a chance for the skeleton source to have changed shape (a
|
|
3894
|
+
// clip child appearing or leaving can accompany a model coming or going) - re-derive the
|
|
3895
|
+
// binding root before the reassignment binds against it.
|
|
3896
|
+
this._applyRootBone();
|
|
3707
3897
|
const layer = component.baseLayer;
|
|
3708
3898
|
const restore = layer ? {
|
|
3709
3899
|
state: layer.activeState,
|
|
@@ -4311,14 +4501,16 @@ class AnimClipElement extends AsyncElement {
|
|
|
4311
4501
|
customElements.define('pc-anim-clip', AnimClipElement);
|
|
4312
4502
|
|
|
4313
4503
|
/**
|
|
4314
|
-
* The
|
|
4315
|
-
* {@link https://developer.playcanvas.com/user-manual/web-components/tags/pc-listener/ | `<pc-listener>`} elements.
|
|
4316
|
-
* The
|
|
4504
|
+
* The AudioListenerComponentElement interface provides properties and methods for manipulating
|
|
4505
|
+
* {@link https://developer.playcanvas.com/user-manual/web-components/tags/pc-audio-listener/ | `<pc-audio-listener>`} elements.
|
|
4506
|
+
* The AudioListenerComponentElement interface also inherits the properties and methods of the
|
|
4317
4507
|
* {@link HTMLElement} interface.
|
|
4318
4508
|
*
|
|
4509
|
+
* Engine component: {@link AudioListenerComponent} (`audiolistener`).
|
|
4510
|
+
*
|
|
4319
4511
|
* @category Components
|
|
4320
4512
|
*/
|
|
4321
|
-
class
|
|
4513
|
+
class AudioListenerComponentElement extends ComponentElement {
|
|
4322
4514
|
/** @ignore */
|
|
4323
4515
|
constructor() {
|
|
4324
4516
|
super('audiolistener');
|
|
@@ -4331,7 +4523,7 @@ class ListenerComponentElement extends ComponentElement {
|
|
|
4331
4523
|
return super.component;
|
|
4332
4524
|
}
|
|
4333
4525
|
}
|
|
4334
|
-
customElements.define('pc-listener',
|
|
4526
|
+
customElements.define('pc-audio-listener', AudioListenerComponentElement);
|
|
4335
4527
|
|
|
4336
4528
|
const transitionModes = new Map([
|
|
4337
4529
|
['tint', BUTTON_TRANSITION_MODE_TINT],
|
|
@@ -4343,6 +4535,8 @@ const transitionModes = new Map([
|
|
|
4343
4535
|
* The ButtonComponentElement interface also inherits the properties and methods of the
|
|
4344
4536
|
* {@link HTMLElement} interface.
|
|
4345
4537
|
*
|
|
4538
|
+
* Engine component: {@link ButtonComponent} (`button`).
|
|
4539
|
+
*
|
|
4346
4540
|
* @category Components
|
|
4347
4541
|
*/
|
|
4348
4542
|
class ButtonComponentElement extends ComponentElement {
|
|
@@ -4423,7 +4617,9 @@ class ButtonComponentElement extends ComponentElement {
|
|
|
4423
4617
|
}
|
|
4424
4618
|
/**
|
|
4425
4619
|
* Sets the reference (CSS selector, element id or entity name) to the `<pc-entity>` whose image
|
|
4426
|
-
* element is used for visual transitions. Defaults to the button's own entity
|
|
4620
|
+
* element is used for visual transitions. Defaults to the button's own entity — inside a
|
|
4621
|
+
* `<pc-model>`, that is the model's host entity, so supply an explicit reference to target a
|
|
4622
|
+
* UI entity instead.
|
|
4427
4623
|
* @param value - The image entity reference.
|
|
4428
4624
|
*/
|
|
4429
4625
|
set image(value) {
|
|
@@ -4742,6 +4938,8 @@ const tonemaps = new Map([
|
|
|
4742
4938
|
* The CameraComponentElement interface also inherits the properties and methods of the
|
|
4743
4939
|
* {@link HTMLElement} interface.
|
|
4744
4940
|
*
|
|
4941
|
+
* Engine component: {@link CameraComponent} (`camera`).
|
|
4942
|
+
*
|
|
4745
4943
|
* @category Components
|
|
4746
4944
|
*/
|
|
4747
4945
|
class CameraComponentElement extends ComponentElement {
|
|
@@ -5227,6 +5425,8 @@ customElements.define('pc-camera', CameraComponentElement);
|
|
|
5227
5425
|
* retargets or rebinds picks up the new node's geometry. An entity with no asset-backed render
|
|
5228
5426
|
* component warns, and the collider has no shape.
|
|
5229
5427
|
*
|
|
5428
|
+
* Engine component: {@link CollisionComponent} (`collision`).
|
|
5429
|
+
*
|
|
5230
5430
|
* @category Components
|
|
5231
5431
|
*/
|
|
5232
5432
|
class CollisionComponentElement extends ComponentElement {
|
|
@@ -5263,7 +5463,9 @@ class CollisionComponentElement extends ComponentElement {
|
|
|
5263
5463
|
* no attribute to supply it - so the host's visible geometry, the meaning a mesh collider
|
|
5264
5464
|
* on a glTF node carries, fills the gap. Runs on every application (so a rebound `pc-node`
|
|
5265
5465
|
* recomputes it) and on a runtime switch to `type="mesh"`; an explicitly assigned
|
|
5266
|
-
* `renderAsset` is never overwritten.
|
|
5466
|
+
* `renderAsset` is never overwritten. A `pc-model` host entity never carries a render
|
|
5467
|
+
* component (the instantiated content beneath it does), so a mesh collider that should take
|
|
5468
|
+
* an asset's geometry belongs on a bound `pc-node`.
|
|
5267
5469
|
*/
|
|
5268
5470
|
_applyMeshGeometryDefault() {
|
|
5269
5471
|
const component = this.component;
|
|
@@ -5408,6 +5610,13 @@ customElements.define('pc-collision', CollisionComponentElement);
|
|
|
5408
5610
|
* The ElementComponentElement interface also inherits the properties and methods of the
|
|
5409
5611
|
* {@link HTMLElement} interface.
|
|
5410
5612
|
*
|
|
5613
|
+
* Despite the name, this is not a base class or a generic wrapper: it is the engine's 2D UI
|
|
5614
|
+
* component, which gives its host entity a rectangle in a `<pc-screen>` hierarchy that draws
|
|
5615
|
+
* either an image, a line of text or nothing (`type="image"`, `"text"` or `"group"`). The tag
|
|
5616
|
+
* spells the engine component it adds, as every component element does.
|
|
5617
|
+
*
|
|
5618
|
+
* Engine component: {@link ElementComponent} (`element`).
|
|
5619
|
+
*
|
|
5411
5620
|
* @category Components
|
|
5412
5621
|
*/
|
|
5413
5622
|
class ElementComponentElement extends ComponentElement {
|
|
@@ -6096,6 +6305,8 @@ customElements.define('pc-element', ElementComponentElement);
|
|
|
6096
6305
|
* constraint breaks. A broken joint no longer constrains its bodies; calling `refreshFrames()` on
|
|
6097
6306
|
* the underlying component re-attaches it. Bubbles and is composed.
|
|
6098
6307
|
*
|
|
6308
|
+
* Engine component: {@link JointComponent} (`joint`).
|
|
6309
|
+
*
|
|
6099
6310
|
* @category Components
|
|
6100
6311
|
*/
|
|
6101
6312
|
class JointComponentElement extends ComponentElement {
|
|
@@ -6954,10 +7165,12 @@ customElements.define('pc-joint', JointComponentElement);
|
|
|
6954
7165
|
|
|
6955
7166
|
/**
|
|
6956
7167
|
* The LayoutChildComponentElement interface provides properties and methods for manipulating
|
|
6957
|
-
* {@link https://developer.playcanvas.com/user-manual/web-components/tags/pc-
|
|
7168
|
+
* {@link https://developer.playcanvas.com/user-manual/web-components/tags/pc-layout-child/ | `<pc-layout-child>`} elements.
|
|
6958
7169
|
* The LayoutChildComponentElement interface also inherits the properties and methods of the
|
|
6959
7170
|
* {@link HTMLElement} interface.
|
|
6960
7171
|
*
|
|
7172
|
+
* Engine component: {@link LayoutChildComponent} (`layoutchild`).
|
|
7173
|
+
*
|
|
6961
7174
|
* @category Components
|
|
6962
7175
|
*/
|
|
6963
7176
|
class LayoutChildComponentElement extends ComponentElement {
|
|
@@ -7150,7 +7363,7 @@ class LayoutChildComponentElement extends ComponentElement {
|
|
|
7150
7363
|
}
|
|
7151
7364
|
}
|
|
7152
7365
|
}
|
|
7153
|
-
customElements.define('pc-
|
|
7366
|
+
customElements.define('pc-layout-child', LayoutChildComponentElement);
|
|
7154
7367
|
|
|
7155
7368
|
const orientations$1 = new Map([
|
|
7156
7369
|
['horizontal', ORIENTATION_HORIZONTAL],
|
|
@@ -7164,10 +7377,12 @@ const fittings = new Map([
|
|
|
7164
7377
|
]);
|
|
7165
7378
|
/**
|
|
7166
7379
|
* The LayoutGroupComponentElement interface provides properties and methods for manipulating
|
|
7167
|
-
* {@link https://developer.playcanvas.com/user-manual/web-components/tags/pc-
|
|
7380
|
+
* {@link https://developer.playcanvas.com/user-manual/web-components/tags/pc-layout-group/ | `<pc-layout-group>`} elements.
|
|
7168
7381
|
* The LayoutGroupComponentElement interface also inherits the properties and methods of the
|
|
7169
7382
|
* {@link HTMLElement} interface.
|
|
7170
7383
|
*
|
|
7384
|
+
* Engine component: {@link LayoutGroupComponent} (`layoutgroup`).
|
|
7385
|
+
*
|
|
7171
7386
|
* @category Components
|
|
7172
7387
|
*/
|
|
7173
7388
|
class LayoutGroupComponentElement extends ComponentElement {
|
|
@@ -7407,7 +7622,7 @@ class LayoutGroupComponentElement extends ComponentElement {
|
|
|
7407
7622
|
}
|
|
7408
7623
|
}
|
|
7409
7624
|
}
|
|
7410
|
-
customElements.define('pc-
|
|
7625
|
+
customElements.define('pc-layout-group', LayoutGroupComponentElement);
|
|
7411
7626
|
|
|
7412
7627
|
const shadowTypes = new Map([
|
|
7413
7628
|
['pcf1-16f', SHADOW_PCF1_16F],
|
|
@@ -7426,6 +7641,8 @@ const shadowTypes = new Map([
|
|
|
7426
7641
|
* The LightComponentElement interface also inherits the properties and methods of the
|
|
7427
7642
|
* {@link HTMLElement} interface.
|
|
7428
7643
|
*
|
|
7644
|
+
* Engine component: {@link LightComponent} (`light`).
|
|
7645
|
+
*
|
|
7429
7646
|
* @category Components
|
|
7430
7647
|
*/
|
|
7431
7648
|
class LightComponentElement extends ComponentElement {
|
|
@@ -7907,10 +8124,12 @@ customElements.define('pc-light', LightComponentElement);
|
|
|
7907
8124
|
|
|
7908
8125
|
/**
|
|
7909
8126
|
* The ParticleSystemComponentElement interface provides properties and methods for manipulating
|
|
7910
|
-
* {@link https://developer.playcanvas.com/user-manual/web-components/tags/pc-
|
|
8127
|
+
* {@link https://developer.playcanvas.com/user-manual/web-components/tags/pc-particle-system/ | `<pc-particle-system>`} elements.
|
|
7911
8128
|
* The ParticleSystemComponentElement interface also inherits the properties and methods of the
|
|
7912
8129
|
* {@link HTMLElement} interface.
|
|
7913
8130
|
*
|
|
8131
|
+
* Engine component: {@link ParticleSystemComponent} (`particlesystem`).
|
|
8132
|
+
*
|
|
7914
8133
|
* @category Components
|
|
7915
8134
|
*/
|
|
7916
8135
|
class ParticleSystemComponentElement extends ComponentElement {
|
|
@@ -8029,7 +8248,7 @@ class ParticleSystemComponentElement extends ComponentElement {
|
|
|
8029
8248
|
}
|
|
8030
8249
|
}
|
|
8031
8250
|
}
|
|
8032
|
-
customElements.define('pc-
|
|
8251
|
+
customElements.define('pc-particle-system', ParticleSystemComponentElement);
|
|
8033
8252
|
|
|
8034
8253
|
const blendTypes = new Map([
|
|
8035
8254
|
['none', BLEND_NONE],
|
|
@@ -10261,6 +10480,8 @@ customElements.define('pc-material', MaterialElement);
|
|
|
10261
10480
|
* to `box`). It does not cover the engine's `asset` render type, since there is no way to supply
|
|
10262
10481
|
* a render asset here — use `pc-model` for glTF content instead.
|
|
10263
10482
|
*
|
|
10483
|
+
* Engine component: {@link RenderComponent} (`render`).
|
|
10484
|
+
*
|
|
10264
10485
|
* @category Components
|
|
10265
10486
|
*/
|
|
10266
10487
|
class RenderComponentElement extends ComponentElement {
|
|
@@ -10385,10 +10606,12 @@ customElements.define('pc-render', RenderComponentElement);
|
|
|
10385
10606
|
|
|
10386
10607
|
/**
|
|
10387
10608
|
* The RigidBodyComponentElement interface provides properties and methods for manipulating
|
|
10388
|
-
* {@link https://developer.playcanvas.com/user-manual/web-components/tags/pc-
|
|
10609
|
+
* {@link https://developer.playcanvas.com/user-manual/web-components/tags/pc-rigid-body/ | `<pc-rigid-body>`} elements.
|
|
10389
10610
|
* The RigidBodyComponentElement interface also inherits the properties and methods of the
|
|
10390
10611
|
* {@link HTMLElement} interface.
|
|
10391
10612
|
*
|
|
10613
|
+
* Engine component: {@link RigidBodyComponent} (`rigidbody`).
|
|
10614
|
+
*
|
|
10392
10615
|
* @category Components
|
|
10393
10616
|
*/
|
|
10394
10617
|
class RigidBodyComponentElement extends ComponentElement {
|
|
@@ -10580,7 +10803,7 @@ class RigidBodyComponentElement extends ComponentElement {
|
|
|
10580
10803
|
}
|
|
10581
10804
|
}
|
|
10582
10805
|
}
|
|
10583
|
-
customElements.define('pc-
|
|
10806
|
+
customElements.define('pc-rigid-body', RigidBodyComponentElement);
|
|
10584
10807
|
|
|
10585
10808
|
// The engine's SCALEMODE_* constants are the strings 'none' and 'blend', so this map happens to be
|
|
10586
10809
|
// an identity. It is still the right shape: it supplies parseEnum's valid-name list, it is what the
|
|
@@ -10596,6 +10819,8 @@ const scaleModes = new Map([
|
|
|
10596
10819
|
* The ScreenComponentElement interface also inherits the properties and methods of the
|
|
10597
10820
|
* {@link HTMLElement} interface.
|
|
10598
10821
|
*
|
|
10822
|
+
* Engine component: {@link ScreenComponent} (`screen`).
|
|
10823
|
+
*
|
|
10599
10824
|
* @category Components
|
|
10600
10825
|
*/
|
|
10601
10826
|
class ScreenComponentElement extends ComponentElement {
|
|
@@ -10748,6 +10973,8 @@ const orientations = new Map([
|
|
|
10748
10973
|
* The ScrollbarComponentElement interface also inherits the properties and methods of the
|
|
10749
10974
|
* {@link HTMLElement} interface.
|
|
10750
10975
|
*
|
|
10976
|
+
* Engine component: {@link ScrollbarComponent} (`scrollbar`).
|
|
10977
|
+
*
|
|
10751
10978
|
* @category Components
|
|
10752
10979
|
*/
|
|
10753
10980
|
class ScrollbarComponentElement extends ComponentElement {
|
|
@@ -10883,10 +11110,12 @@ const visibilities = new Map([
|
|
|
10883
11110
|
]);
|
|
10884
11111
|
/**
|
|
10885
11112
|
* The ScrollViewComponentElement interface provides properties and methods for manipulating
|
|
10886
|
-
* {@link https://developer.playcanvas.com/user-manual/web-components/tags/pc-
|
|
11113
|
+
* {@link https://developer.playcanvas.com/user-manual/web-components/tags/pc-scroll-view/ | `<pc-scroll-view>`} elements.
|
|
10887
11114
|
* The ScrollViewComponentElement interface also inherits the properties and methods of the
|
|
10888
11115
|
* {@link HTMLElement} interface.
|
|
10889
11116
|
*
|
|
11117
|
+
* Engine component: {@link ScrollViewComponent} (`scrollview`).
|
|
11118
|
+
*
|
|
10890
11119
|
* @category Components
|
|
10891
11120
|
*/
|
|
10892
11121
|
class ScrollViewComponentElement extends ComponentElement {
|
|
@@ -11245,11 +11474,11 @@ class ScrollViewComponentElement extends ComponentElement {
|
|
|
11245
11474
|
}
|
|
11246
11475
|
}
|
|
11247
11476
|
}
|
|
11248
|
-
customElements.define('pc-
|
|
11477
|
+
customElements.define('pc-scroll-view', ScrollViewComponentElement);
|
|
11249
11478
|
|
|
11250
11479
|
/**
|
|
11251
|
-
* The
|
|
11252
|
-
* `<pc-script>` elements. The
|
|
11480
|
+
* The ScriptInstanceElement interface provides properties and methods for manipulating
|
|
11481
|
+
* `<pc-script-instance>` elements. The ScriptInstanceElement interface also inherits the properties and
|
|
11253
11482
|
* methods of the {@link AsyncElement} interface.
|
|
11254
11483
|
*
|
|
11255
11484
|
* Script attributes can be supplied through two channels:
|
|
@@ -11271,7 +11500,7 @@ customElements.define('pc-scrollview', ScrollViewComponentElement);
|
|
|
11271
11500
|
* new-name one, re-applying both attribute channels to it.
|
|
11272
11501
|
*
|
|
11273
11502
|
* The element becomes ready once its script instance has been created by the parent
|
|
11274
|
-
* `<pc-
|
|
11503
|
+
* `<pc-script>` element.
|
|
11275
11504
|
*
|
|
11276
11505
|
* @fires {CustomEvent} scriptattributeschange - Fired when the script's attributes change. The
|
|
11277
11506
|
* `detail` carries the new `attributes` object. Bubbles.
|
|
@@ -11280,11 +11509,11 @@ customElements.define('pc-scrollview', ScrollViewComponentElement);
|
|
|
11280
11509
|
* @fires {CustomEvent} scriptnamechange - Fired when the script is renamed on a live element. The
|
|
11281
11510
|
* `detail` carries `oldName` and `newName`. Bubbles.
|
|
11282
11511
|
*/
|
|
11283
|
-
class
|
|
11512
|
+
class ScriptInstanceElement extends AsyncElement {
|
|
11284
11513
|
_attributes = {};
|
|
11285
11514
|
_enabled = true;
|
|
11286
11515
|
/**
|
|
11287
|
-
* The Script instance created for this element by its parent `<pc-
|
|
11516
|
+
* The Script instance created for this element by its parent `<pc-script>` element.
|
|
11288
11517
|
* @internal
|
|
11289
11518
|
*/
|
|
11290
11519
|
_script = null;
|
|
@@ -11330,11 +11559,11 @@ class ScriptElement extends AsyncElement {
|
|
|
11330
11559
|
}
|
|
11331
11560
|
/**
|
|
11332
11561
|
* Sets the name of the script to create. The `name` attribute is the single source of truth
|
|
11333
|
-
* (it is what the parent `<pc-
|
|
11562
|
+
* (it is what the parent `<pc-script>` element reads when creating the instance), so the
|
|
11334
11563
|
* property writes through to it — assigning before insertion works as expected:
|
|
11335
11564
|
*
|
|
11336
11565
|
* ```js
|
|
11337
|
-
* const script = document.createElement('pc-script');
|
|
11566
|
+
* const script = document.createElement('pc-script-instance');
|
|
11338
11567
|
* script.name = 'rotate';
|
|
11339
11568
|
* scriptsElement.appendChild(script);
|
|
11340
11569
|
* await script.ready();
|
|
@@ -11361,10 +11590,10 @@ class ScriptElement extends AsyncElement {
|
|
|
11361
11590
|
return this._script;
|
|
11362
11591
|
}
|
|
11363
11592
|
connectedCallback() {
|
|
11364
|
-
// Script instances are created by the parent pc-
|
|
11593
|
+
// Script instances are created by the parent pc-script element, so an element placed
|
|
11365
11594
|
// anywhere else is inert and never becomes ready - warn rather than hang silently
|
|
11366
|
-
if (this.parentElement?.tagName !== 'PC-
|
|
11367
|
-
console.warn(`pc-script '${this.getAttribute('name')}' must be a direct child of pc-
|
|
11595
|
+
if (this.parentElement?.tagName !== 'PC-SCRIPT') {
|
|
11596
|
+
console.warn(`pc-script-instance '${this.getAttribute('name')}' must be a direct child of pc-script - script not created`);
|
|
11368
11597
|
}
|
|
11369
11598
|
}
|
|
11370
11599
|
disconnectedCallback() {
|
|
@@ -11375,7 +11604,7 @@ class ScriptElement extends AsyncElement {
|
|
|
11375
11604
|
this._resetReady();
|
|
11376
11605
|
}
|
|
11377
11606
|
/**
|
|
11378
|
-
* Called by the parent `<pc-
|
|
11607
|
+
* Called by the parent `<pc-script>` element when the script instance has been created.
|
|
11379
11608
|
* Creation can happen more than once per connection (a runtime `name` change recreates the
|
|
11380
11609
|
* instance), but `_onReady` signals readiness at most once per cycle.
|
|
11381
11610
|
* @internal
|
|
@@ -11397,7 +11626,7 @@ class ScriptElement extends AsyncElement {
|
|
|
11397
11626
|
this.scriptAttributes = JSON.parse(newValue);
|
|
11398
11627
|
}
|
|
11399
11628
|
catch (error) {
|
|
11400
|
-
console.warn(`Invalid 'attributes' JSON on pc-script '${this.getAttribute('name')}': ${error.message}`);
|
|
11629
|
+
console.warn(`Invalid 'attributes' JSON on pc-script-instance '${this.getAttribute('name')}': ${error.message}`);
|
|
11401
11630
|
}
|
|
11402
11631
|
break;
|
|
11403
11632
|
case 'enabled':
|
|
@@ -11417,14 +11646,14 @@ class ScriptElement extends AsyncElement {
|
|
|
11417
11646
|
}
|
|
11418
11647
|
}
|
|
11419
11648
|
}
|
|
11420
|
-
customElements.define('pc-script',
|
|
11649
|
+
customElements.define('pc-script-instance', ScriptInstanceElement);
|
|
11421
11650
|
|
|
11422
11651
|
/**
|
|
11423
|
-
* Attributes on `pc-script` that never map to script attributes: the element's own API (derived
|
|
11652
|
+
* Attributes on `pc-script-instance` that never map to script attributes: the element's own API (derived
|
|
11424
11653
|
* from its observed attributes) plus reserved and global HTML attribute names.
|
|
11425
11654
|
*/
|
|
11426
11655
|
const RESERVED_ATTRIBUTES = new Set([
|
|
11427
|
-
...
|
|
11656
|
+
...ScriptInstanceElement.observedAttributes,
|
|
11428
11657
|
'accesskey',
|
|
11429
11658
|
'autocapitalize',
|
|
11430
11659
|
'autofocus',
|
|
@@ -11455,7 +11684,7 @@ const RESERVED_ATTRIBUTES = new Set([
|
|
|
11455
11684
|
'translate'
|
|
11456
11685
|
]);
|
|
11457
11686
|
/**
|
|
11458
|
-
* Checks whether a `pc-script` attribute name is reserved (and so never maps to a script
|
|
11687
|
+
* Checks whether a `pc-script-instance` attribute name is reserved (and so never maps to a script
|
|
11459
11688
|
* attribute). Reserved names are the element's own API, global HTML attribute names, `data-*`
|
|
11460
11689
|
* and `aria-*` attributes, names starting with `_` (framework-stamped attributes), and real
|
|
11461
11690
|
* inline event handler names (`onclick` etc. — detected via the platform, so script attributes
|
|
@@ -11611,10 +11840,12 @@ const findCaseMatch = (script, key) => {
|
|
|
11611
11840
|
};
|
|
11612
11841
|
/**
|
|
11613
11842
|
* The ScriptComponentElement interface provides properties and methods for manipulating
|
|
11614
|
-
* {@link https://developer.playcanvas.com/user-manual/web-components/tags/pc-
|
|
11843
|
+
* {@link https://developer.playcanvas.com/user-manual/web-components/tags/pc-script/ | `<pc-script>`} elements.
|
|
11615
11844
|
* The ScriptComponentElement interface also inherits the properties and methods of the
|
|
11616
11845
|
* {@link HTMLElement} interface.
|
|
11617
11846
|
*
|
|
11847
|
+
* Engine component: {@link ScriptComponent} (`script`).
|
|
11848
|
+
*
|
|
11618
11849
|
* @category Components
|
|
11619
11850
|
*/
|
|
11620
11851
|
class ScriptComponentElement extends ComponentElement {
|
|
@@ -11631,14 +11862,23 @@ class ScriptComponentElement extends ComponentElement {
|
|
|
11631
11862
|
}
|
|
11632
11863
|
connectedCallback() {
|
|
11633
11864
|
// (Re-)observe on every connection - disconnectedCallback disconnects the observer.
|
|
11634
|
-
// Attribute changes on child pc-script elements are watched here too: per-property
|
|
11865
|
+
// Attribute changes on child pc-script-instance elements are watched here too: per-property
|
|
11635
11866
|
// script attributes are not statically known, so they cannot use observedAttributes.
|
|
11636
11867
|
this.observer.observe(this, { childList: true, subtree: true, attributes: true });
|
|
11637
11868
|
return super.connectedCallback();
|
|
11638
11869
|
}
|
|
11639
11870
|
initComponent() {
|
|
11640
|
-
|
|
11641
|
-
|
|
11871
|
+
this.querySelectorAll(':scope > pc-script-instance').forEach((scriptElement) => {
|
|
11872
|
+
// A host readiness cycle re-runs this against a component that can have survived it
|
|
11873
|
+
// (a pc-model reloading content on its stable host entity). The engine rejects a
|
|
11874
|
+
// duplicate create - returning null, silently in production builds - which would
|
|
11875
|
+
// skip attribute application entirely. A surviving instance is re-asserted instead,
|
|
11876
|
+
// so both cycle outcomes leave the component reflecting the element's declared state.
|
|
11877
|
+
const script = this.scriptFor(scriptElement);
|
|
11878
|
+
if (script) {
|
|
11879
|
+
this.applyDeclaredState(script, scriptElement);
|
|
11880
|
+
return;
|
|
11881
|
+
}
|
|
11642
11882
|
this.createScript(scriptElement);
|
|
11643
11883
|
});
|
|
11644
11884
|
}
|
|
@@ -11772,9 +12012,9 @@ class ScriptComponentElement extends ComponentElement {
|
|
|
11772
12012
|
this.mergeDeep(script, converted);
|
|
11773
12013
|
}
|
|
11774
12014
|
/**
|
|
11775
|
-
* Returns the camelCase keys of the per-property attributes present on a `pc-script`
|
|
12015
|
+
* Returns the camelCase keys of the per-property attributes present on a `pc-script-instance`
|
|
11776
12016
|
* element.
|
|
11777
|
-
* @param scriptElement - The `pc-script` element.
|
|
12017
|
+
* @param scriptElement - The `pc-script-instance` element.
|
|
11778
12018
|
* @returns The camelCase keys.
|
|
11779
12019
|
*/
|
|
11780
12020
|
inlineKeys(scriptElement) {
|
|
@@ -11787,10 +12027,10 @@ class ScriptComponentElement extends ComponentElement {
|
|
|
11787
12027
|
return keys;
|
|
11788
12028
|
}
|
|
11789
12029
|
/**
|
|
11790
|
-
* Resolves the script instance owned by a `pc-script` element. Returns `null` when the
|
|
12030
|
+
* Resolves the script instance owned by a `pc-script-instance` element. Returns `null` when the
|
|
11791
12031
|
* element has no created script, or when its name resolves to a script created by a
|
|
11792
12032
|
* different element (e.g. a duplicate-named sibling).
|
|
11793
|
-
* @param scriptElement - The `pc-script` element.
|
|
12033
|
+
* @param scriptElement - The `pc-script-instance` element.
|
|
11794
12034
|
* @returns The owned script, or `null`.
|
|
11795
12035
|
*/
|
|
11796
12036
|
scriptFor(scriptElement) {
|
|
@@ -11819,7 +12059,7 @@ class ScriptComponentElement extends ComponentElement {
|
|
|
11819
12059
|
}
|
|
11820
12060
|
}
|
|
11821
12061
|
/**
|
|
11822
|
-
* Handles a runtime `name` change on a child `pc-script`, swapping the engine script instance
|
|
12062
|
+
* Handles a runtime `name` change on a child `pc-script-instance`, swapping the engine script instance
|
|
11823
12063
|
* to match. Without this the element would keep pointing at the old-name instance: the old
|
|
11824
12064
|
* script would go on running while every subsequent update (attribute changes, enable
|
|
11825
12065
|
* changes, destruction on removal) resolved the new name and silently no-opped.
|
|
@@ -11830,8 +12070,8 @@ class ScriptComponentElement extends ComponentElement {
|
|
|
11830
12070
|
*/
|
|
11831
12071
|
handleScriptNameChange(event) {
|
|
11832
12072
|
const scriptElement = event.target;
|
|
11833
|
-
// Only direct children are managed, matching initComponent's ':scope > pc-script'
|
|
11834
|
-
// contract - the event bubbles, so a deeper pc-script must not be created here
|
|
12073
|
+
// Only direct children are managed, matching initComponent's ':scope > pc-script-instance'
|
|
12074
|
+
// contract - the event bubbles, so a deeper pc-script-instance must not be created here
|
|
11835
12075
|
if (scriptElement.parentElement !== this)
|
|
11836
12076
|
return;
|
|
11837
12077
|
// Before the component exists there is nothing to swap: initComponent creates from
|
|
@@ -11848,11 +12088,11 @@ class ScriptComponentElement extends ComponentElement {
|
|
|
11848
12088
|
this.createScript(scriptElement);
|
|
11849
12089
|
}
|
|
11850
12090
|
/**
|
|
11851
|
-
* Creates the script instance for a `pc-script` element. The instance is created disabled,
|
|
12091
|
+
* Creates the script instance for a `pc-script-instance` element. The instance is created disabled,
|
|
11852
12092
|
* the element's converted attributes are merged over the instance's defaults (which is what
|
|
11853
12093
|
* allows plain numeric arrays to be typed against those defaults), and only then is the
|
|
11854
12094
|
* declared enabled state applied — so `initialize()` runs with every attribute in place.
|
|
11855
|
-
* @param scriptElement - The `pc-script` element to create the script instance for.
|
|
12095
|
+
* @param scriptElement - The `pc-script-instance` element to create the script instance for.
|
|
11856
12096
|
* @returns The created script, or `null`.
|
|
11857
12097
|
*/
|
|
11858
12098
|
createScript(scriptElement) {
|
|
@@ -11863,21 +12103,30 @@ class ScriptComponentElement extends ComponentElement {
|
|
|
11863
12103
|
if (!script)
|
|
11864
12104
|
return null;
|
|
11865
12105
|
scriptElement._script = script;
|
|
11866
|
-
|
|
11867
|
-
|
|
12106
|
+
this.applyDeclaredState(script, scriptElement);
|
|
12107
|
+
scriptElement._onScriptCreated();
|
|
12108
|
+
return script;
|
|
12109
|
+
}
|
|
12110
|
+
/**
|
|
12111
|
+
* Applies a `pc-script-instance` element's declared state to a script instance: the `attributes` JSON
|
|
12112
|
+
* first with per-property-shadowed keys stripped, then the per-property attributes — each
|
|
12113
|
+
* property is written exactly once and individual attributes win — and finally the declared
|
|
12114
|
+
* enabled state, so `initialize()` runs with every attribute in place.
|
|
12115
|
+
* @param script - The script instance.
|
|
12116
|
+
* @param scriptElement - The `pc-script-instance` element holding the declared state.
|
|
12117
|
+
*/
|
|
12118
|
+
applyDeclaredState(script, scriptElement) {
|
|
11868
12119
|
this.applyAttributes(script, scriptElement.scriptAttributes, this.inlineKeys(scriptElement));
|
|
11869
12120
|
this.applyInlineAttributes(script, scriptElement);
|
|
11870
12121
|
script.enabled = scriptElement.enabled;
|
|
11871
|
-
scriptElement._onScriptCreated();
|
|
11872
|
-
return script;
|
|
11873
12122
|
}
|
|
11874
12123
|
/**
|
|
11875
|
-
* Applies the per-property attributes present on a `pc-script` element — any attribute that
|
|
12124
|
+
* Applies the per-property attributes present on a `pc-script-instance` element — any attribute that
|
|
11876
12125
|
* is not part of the element's own API or a reserved HTML attribute name. These are applied
|
|
11877
12126
|
* after the `attributes` JSON, so an individual attribute always takes precedence over the
|
|
11878
12127
|
* blob.
|
|
11879
12128
|
* @param script - The script to apply the attributes to.
|
|
11880
|
-
* @param scriptElement - The `pc-script` element holding the attributes.
|
|
12129
|
+
* @param scriptElement - The `pc-script-instance` element holding the attributes.
|
|
11881
12130
|
*/
|
|
11882
12131
|
applyInlineAttributes(script, scriptElement) {
|
|
11883
12132
|
const scriptName = scriptElement.getAttribute('name') ?? '';
|
|
@@ -11888,10 +12137,10 @@ class ScriptComponentElement extends ComponentElement {
|
|
|
11888
12137
|
}
|
|
11889
12138
|
}
|
|
11890
12139
|
/**
|
|
11891
|
-
* Applies a single per-property attribute change to the script of a `pc-script` element.
|
|
12140
|
+
* Applies a single per-property attribute change to the script of a `pc-script-instance` element.
|
|
11892
12141
|
* When the attribute has been removed, the value from the `attributes` JSON (if any) takes
|
|
11893
12142
|
* effect again.
|
|
11894
|
-
* @param scriptElement - The `pc-script` element whose attribute changed.
|
|
12143
|
+
* @param scriptElement - The `pc-script-instance` element whose attribute changed.
|
|
11895
12144
|
* @param attributeName - The name of the changed attribute.
|
|
11896
12145
|
*/
|
|
11897
12146
|
applyScriptProperty(scriptElement, attributeName) {
|
|
@@ -11927,7 +12176,7 @@ class ScriptComponentElement extends ComponentElement {
|
|
|
11927
12176
|
try {
|
|
11928
12177
|
const current = script[key];
|
|
11929
12178
|
if (typeof current === 'function' || SCRIPT_API_MEMBERS.has(key)) {
|
|
11930
|
-
console.warn(`Ignoring attribute '${attributeName}' on pc-script '${scriptName}' - '${key}' is part of the Script API.`);
|
|
12179
|
+
console.warn(`Ignoring attribute '${attributeName}' on pc-script-instance '${scriptName}' - '${key}' is part of the Script API.`);
|
|
11931
12180
|
return;
|
|
11932
12181
|
}
|
|
11933
12182
|
if (typeof current === 'string') {
|
|
@@ -11983,10 +12232,10 @@ class ScriptComponentElement extends ComponentElement {
|
|
|
11983
12232
|
}
|
|
11984
12233
|
handleMutations(mutations) {
|
|
11985
12234
|
for (const mutation of mutations) {
|
|
11986
|
-
// Handle per-property attribute changes on child pc-script elements
|
|
12235
|
+
// Handle per-property attribute changes on child pc-script-instance elements
|
|
11987
12236
|
if (mutation.type === 'attributes') {
|
|
11988
12237
|
const target = mutation.target;
|
|
11989
|
-
if (target instanceof
|
|
12238
|
+
if (target instanceof ScriptInstanceElement &&
|
|
11990
12239
|
target.parentElement === this &&
|
|
11991
12240
|
mutation.attributeName &&
|
|
11992
12241
|
!isReservedAttribute(mutation.attributeName)) {
|
|
@@ -11996,16 +12245,16 @@ class ScriptComponentElement extends ComponentElement {
|
|
|
11996
12245
|
}
|
|
11997
12246
|
// Only direct children are managed - the observer watches the subtree for attribute
|
|
11998
12247
|
// changes, but deeper childList records must not create or destroy scripts
|
|
11999
|
-
// (matching initComponent's ':scope > pc-script' contract)
|
|
12248
|
+
// (matching initComponent's ':scope > pc-script-instance' contract)
|
|
12000
12249
|
if (mutation.target !== this) {
|
|
12001
12250
|
continue;
|
|
12002
12251
|
}
|
|
12003
|
-
// Handle removed nodes first, so that replacing a pc-script with a same-named one
|
|
12252
|
+
// Handle removed nodes first, so that replacing a pc-script-instance with a same-named one
|
|
12004
12253
|
// destroys the old script before the replacement is created. Only destroy a script
|
|
12005
12254
|
// this element actually owns - a duplicate-named element whose own create() failed
|
|
12006
12255
|
// must not take down the live script on removal.
|
|
12007
12256
|
mutation.removedNodes.forEach((node) => {
|
|
12008
|
-
if (node instanceof
|
|
12257
|
+
if (node instanceof ScriptInstanceElement) {
|
|
12009
12258
|
const scriptName = node.getAttribute('name');
|
|
12010
12259
|
if (scriptName &&
|
|
12011
12260
|
node._script &&
|
|
@@ -12018,7 +12267,7 @@ class ScriptComponentElement extends ComponentElement {
|
|
|
12018
12267
|
});
|
|
12019
12268
|
// Handle added nodes
|
|
12020
12269
|
mutation.addedNodes.forEach((node) => {
|
|
12021
|
-
if (node instanceof
|
|
12270
|
+
if (node instanceof ScriptInstanceElement) {
|
|
12022
12271
|
this.createScript(node);
|
|
12023
12272
|
}
|
|
12024
12273
|
});
|
|
@@ -12036,14 +12285,16 @@ class ScriptComponentElement extends ComponentElement {
|
|
|
12036
12285
|
return super.component;
|
|
12037
12286
|
}
|
|
12038
12287
|
}
|
|
12039
|
-
customElements.define('pc-
|
|
12288
|
+
customElements.define('pc-script', ScriptComponentElement);
|
|
12040
12289
|
|
|
12041
12290
|
/**
|
|
12042
12291
|
* The SoundComponentElement interface provides properties and methods for manipulating
|
|
12043
|
-
* {@link https://developer.playcanvas.com/user-manual/web-components/tags/pc-
|
|
12292
|
+
* {@link https://developer.playcanvas.com/user-manual/web-components/tags/pc-sound/ | `<pc-sound>`} elements.
|
|
12044
12293
|
* The SoundComponentElement interface also inherits the properties and methods of the
|
|
12045
12294
|
* {@link HTMLElement} interface.
|
|
12046
12295
|
*
|
|
12296
|
+
* Engine component: {@link SoundComponent} (`sound`).
|
|
12297
|
+
*
|
|
12047
12298
|
* @category Components
|
|
12048
12299
|
*/
|
|
12049
12300
|
class SoundComponentElement extends ComponentElement {
|
|
@@ -12234,11 +12485,11 @@ class SoundComponentElement extends ComponentElement {
|
|
|
12234
12485
|
}
|
|
12235
12486
|
}
|
|
12236
12487
|
}
|
|
12237
|
-
customElements.define('pc-
|
|
12488
|
+
customElements.define('pc-sound', SoundComponentElement);
|
|
12238
12489
|
|
|
12239
12490
|
/**
|
|
12240
12491
|
* The SoundSlotElement interface provides properties and methods for manipulating
|
|
12241
|
-
* `<pc-sound>` elements. The SoundSlotElement interface also inherits the properties and
|
|
12492
|
+
* `<pc-sound-slot>` elements. The SoundSlotElement interface also inherits the properties and
|
|
12242
12493
|
* methods of the {@link AsyncElement} interface.
|
|
12243
12494
|
*/
|
|
12244
12495
|
class SoundSlotElement extends AsyncElement {
|
|
@@ -12252,7 +12503,7 @@ class SoundSlotElement extends AsyncElement {
|
|
|
12252
12503
|
_startTime = 0;
|
|
12253
12504
|
_volume = 1;
|
|
12254
12505
|
/**
|
|
12255
|
-
* The `<pc-
|
|
12506
|
+
* The `<pc-sound>` this slot was added to, captured at connect time.
|
|
12256
12507
|
*
|
|
12257
12508
|
* `disconnectedCallback` cannot rediscover it: by the time the element is disconnected its
|
|
12258
12509
|
* `parentElement` is already `null`, so a lookup would both fail to find the component and
|
|
@@ -12315,7 +12566,7 @@ class SoundSlotElement extends AsyncElement {
|
|
|
12315
12566
|
get soundElement() {
|
|
12316
12567
|
const soundElement = this.parentElement;
|
|
12317
12568
|
if (!(soundElement instanceof SoundComponentElement)) {
|
|
12318
|
-
console.warn('pc-sound must be a direct child of a pc-
|
|
12569
|
+
console.warn('pc-sound-slot must be a direct child of a pc-sound element');
|
|
12319
12570
|
return null;
|
|
12320
12571
|
}
|
|
12321
12572
|
return soundElement;
|
|
@@ -12511,7 +12762,7 @@ class SoundSlotElement extends AsyncElement {
|
|
|
12511
12762
|
}
|
|
12512
12763
|
}
|
|
12513
12764
|
}
|
|
12514
|
-
customElements.define('pc-sound', SoundSlotElement);
|
|
12765
|
+
customElements.define('pc-sound-slot', SoundSlotElement);
|
|
12515
12766
|
|
|
12516
12767
|
/**
|
|
12517
12768
|
* The GSplatComponentElement interface provides properties and methods for manipulating
|
|
@@ -12519,6 +12770,8 @@ customElements.define('pc-sound', SoundSlotElement);
|
|
|
12519
12770
|
* The GSplatComponentElement interface also inherits the properties and methods of the
|
|
12520
12771
|
* {@link HTMLElement} interface.
|
|
12521
12772
|
*
|
|
12773
|
+
* Engine component: {@link GSplatComponent} (`gsplat`).
|
|
12774
|
+
*
|
|
12522
12775
|
* @category Components
|
|
12523
12776
|
*/
|
|
12524
12777
|
class GSplatComponentElement extends ComponentElement {
|
|
@@ -12940,7 +13193,10 @@ class NodeElement extends EntityBaseElement {
|
|
|
12940
13193
|
* is retained untouched — a redundant edit must not flicker overrides through a revert.
|
|
12941
13194
|
*/
|
|
12942
13195
|
_rebind() {
|
|
12943
|
-
|
|
13196
|
+
// A model fronts a host entity of its own; the names this element resolves are the
|
|
13197
|
+
// asset's, so the search starts at the instantiated content root, not the wrapper.
|
|
13198
|
+
const host = this._host;
|
|
13199
|
+
const hostEntity = (host instanceof ModelElement ? host.contentEntity : host?.entity) ?? null;
|
|
12944
13200
|
if (!hostEntity || !this._name) {
|
|
12945
13201
|
// Host not instantiated (or nothing to look up yet): return to pending. An assigned
|
|
12946
13202
|
// name arriving later, or the host's next cycle, resolves it.
|
|
@@ -13037,8 +13293,9 @@ class NodeElement extends EntityBaseElement {
|
|
|
13037
13293
|
}
|
|
13038
13294
|
this._revertOverrides();
|
|
13039
13295
|
// Attachment points anchor to the bound node, so they cannot outlive the binding. Each
|
|
13040
|
-
// destroyed entity resets its element, which the next _buildChildren re-creates
|
|
13041
|
-
|
|
13296
|
+
// destroyed entity resets its element, which the next _buildChildren re-creates - a
|
|
13297
|
+
// model host among them re-instantiates its content when it rebuilds.
|
|
13298
|
+
this.querySelectorAll('pc-entity, pc-model').forEach((child) => {
|
|
13042
13299
|
if (child.closestEntity === this) {
|
|
13043
13300
|
child.entity?.destroy();
|
|
13044
13301
|
}
|
|
@@ -14064,5 +14321,5 @@ class SkyElement extends AsyncElement {
|
|
|
14064
14321
|
}
|
|
14065
14322
|
customElements.define('pc-sky', SkyElement);
|
|
14066
14323
|
|
|
14067
|
-
export { AnimClipElement, AnimComponentElement, AppElement, AssetElement, AsyncElement, ButtonComponentElement, CameraComponentElement, CollisionComponentElement, ComponentElement, ElementComponentElement, EntityBaseElement, EntityElement, GSplatComponentElement, JointComponentElement, LayoutChildComponentElement, LayoutGroupComponentElement, LightComponentElement,
|
|
14324
|
+
export { AnimClipElement, AnimComponentElement, AppElement, AssetElement, AsyncElement, AudioListenerComponentElement, ButtonComponentElement, CameraComponentElement, CollisionComponentElement, ComponentElement, ElementComponentElement, EntityBaseElement, EntityElement, EntityOwnerElement, GSplatComponentElement, JointComponentElement, LayoutChildComponentElement, LayoutGroupComponentElement, LightComponentElement, MaterialElement, ModelElement, NodeElement, ParticleSystemComponentElement, RenderComponentElement, RigidBodyComponentElement, SceneElement, ScreenComponentElement, ScriptComponentElement, ScriptInstanceElement, ScrollViewComponentElement, ScrollbarComponentElement, SkyElement, SoundComponentElement, SoundSlotElement, WasmElement, whenReady };
|
|
14068
14325
|
//# sourceMappingURL=pwc.mjs.map
|