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