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