@playcanvas/web-components 0.17.0 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -3
- package/dist/app.d.cts +28 -3
- package/dist/app.d.ts +28 -3
- package/dist/asset.d.cts +13 -3
- package/dist/asset.d.ts +13 -3
- package/dist/components/anim-clip.d.cts +3 -1
- package/dist/components/anim-clip.d.ts +3 -1
- package/dist/components/anim-component.d.cts +5 -0
- package/dist/components/anim-component.d.ts +5 -0
- package/dist/components/audio-listener-component.d.cts +4 -0
- package/dist/components/audio-listener-component.d.ts +4 -0
- package/dist/components/button-component.d.cts +5 -0
- package/dist/components/button-component.d.ts +5 -0
- package/dist/components/camera-component.d.cts +35 -1
- package/dist/components/camera-component.d.ts +35 -1
- package/dist/components/collision-component.d.cts +4 -0
- package/dist/components/collision-component.d.ts +4 -0
- package/dist/components/element-component.d.cts +4 -0
- package/dist/components/element-component.d.ts +4 -0
- package/dist/components/gsplat-component.d.cts +4 -0
- package/dist/components/gsplat-component.d.ts +4 -0
- package/dist/components/joint-component.d.cts +12 -2
- package/dist/components/joint-component.d.ts +12 -2
- package/dist/components/layout-child-component.d.cts +4 -0
- package/dist/components/layout-child-component.d.ts +4 -0
- package/dist/components/layout-group-component.d.cts +4 -0
- package/dist/components/layout-group-component.d.ts +4 -0
- package/dist/components/light-component.d.cts +50 -1
- package/dist/components/light-component.d.ts +50 -1
- package/dist/components/particle-system-component.d.cts +4 -0
- package/dist/components/particle-system-component.d.ts +4 -0
- package/dist/components/render-component.d.cts +5 -0
- package/dist/components/render-component.d.ts +5 -0
- package/dist/components/rigid-body-component.d.cts +5 -0
- package/dist/components/rigid-body-component.d.ts +5 -0
- package/dist/components/screen-component.d.cts +4 -0
- package/dist/components/screen-component.d.ts +4 -0
- package/dist/components/script-component.d.cts +3 -0
- package/dist/components/script-component.d.ts +3 -0
- package/dist/components/script-instance.d.cts +4 -0
- package/dist/components/script-instance.d.ts +4 -0
- package/dist/components/scroll-view-component.d.cts +4 -0
- package/dist/components/scroll-view-component.d.ts +4 -0
- package/dist/components/scrollbar-component.d.cts +4 -0
- package/dist/components/scrollbar-component.d.ts +4 -0
- package/dist/components/sound-component.d.cts +4 -0
- package/dist/components/sound-component.d.ts +4 -0
- package/dist/components/sound-slot.d.cts +3 -0
- package/dist/components/sound-slot.d.ts +3 -0
- package/dist/custom-elements.json +338 -7
- package/dist/entity-base.d.cts +5 -4
- package/dist/entity-base.d.ts +5 -4
- package/dist/entity-owner.d.cts +2 -2
- package/dist/entity-owner.d.ts +2 -2
- package/dist/entity.d.cts +13 -2
- package/dist/entity.d.ts +13 -2
- package/dist/index.d.cts +4 -1
- package/dist/index.d.ts +4 -1
- package/dist/material.d.cts +18 -7
- package/dist/material.d.ts +18 -7
- package/dist/model.d.cts +11 -0
- package/dist/model.d.ts +11 -0
- package/dist/node.d.cts +12 -1
- package/dist/node.d.ts +12 -1
- package/dist/pwc.cjs +601 -206
- package/dist/pwc.cjs.map +1 -1
- package/dist/pwc.js +601 -206
- 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 +602 -207
- package/dist/pwc.mjs.map +1 -1
- package/dist/scene.d.cts +19 -0
- package/dist/scene.d.ts +19 -0
- package/dist/sky.d.cts +4 -0
- package/dist/sky.d.ts +4 -0
- package/dist/vscode.html-custom-data.json +257 -62
- package/dist/wasm.d.cts +4 -0
- package/dist/wasm.d.ts +4 -0
- package/dist/web-types.json +169 -69
- package/package.json +3 -3
- package/src/app.ts +150 -71
- package/src/asset.ts +13 -4
- package/src/components/anim-clip.ts +3 -1
- package/src/components/anim-component.ts +5 -0
- package/src/components/audio-listener-component.ts +4 -0
- package/src/components/button-component.ts +5 -0
- package/src/components/camera-component.ts +63 -6
- package/src/components/collision-component.ts +4 -0
- package/src/components/element-component.ts +4 -0
- package/src/components/gsplat-component.ts +4 -0
- package/src/components/joint-component.ts +12 -2
- package/src/components/layout-child-component.ts +4 -0
- package/src/components/layout-group-component.ts +4 -0
- package/src/components/light-component.ts +108 -17
- package/src/components/particle-system-component.ts +4 -0
- package/src/components/render-component.ts +5 -0
- package/src/components/rigid-body-component.ts +5 -0
- package/src/components/screen-component.ts +4 -0
- package/src/components/script-component.ts +3 -0
- package/src/components/script-instance.ts +4 -0
- package/src/components/scroll-view-component.ts +4 -0
- package/src/components/scrollbar-component.ts +4 -0
- package/src/components/sound-component.ts +4 -0
- package/src/components/sound-slot.ts +3 -0
- package/src/entity-base.ts +28 -16
- package/src/entity-owner.ts +2 -2
- package/src/entity.ts +16 -4
- package/src/index.ts +12 -1
- package/src/material.ts +19 -8
- package/src/model.ts +14 -2
- package/src/node.ts +15 -3
- package/src/scene.ts +35 -1
- package/src/sky.ts +4 -0
- package/src/wasm.ts +4 -0
package/dist/pwc.js
CHANGED
|
@@ -125,6 +125,10 @@
|
|
|
125
125
|
* A `<pc-wasm>` without a `name` warns and never becomes ready; a containing `<pc-app>` still
|
|
126
126
|
* boots.
|
|
127
127
|
*
|
|
128
|
+
* @elementSummary The `<pc-wasm>` element loads a WebAssembly module the engine needs before the
|
|
129
|
+
* application starts — `Ammo` for physics, `Basis` or `DracoDecoderModule` for compressed assets.
|
|
130
|
+
* Must be a direct child of `<pc-app>`.
|
|
131
|
+
*
|
|
128
132
|
* @attribute {string} name - The name of the WebAssembly module to configure, e.g. `Basis` or
|
|
129
133
|
* `Ammo`.
|
|
130
134
|
* @attribute {string} glue - The URL of the module's glue script.
|
|
@@ -177,6 +181,136 @@
|
|
|
177
181
|
}
|
|
178
182
|
customElements.define('pc-wasm', WasmElement);
|
|
179
183
|
|
|
184
|
+
/**
|
|
185
|
+
* The event types the containing `<pc-app>` synthesizes on entity-fronting elements via picking:
|
|
186
|
+
* the `pointer*` events, plus `click` — which concludes a primary-button press and release, and
|
|
187
|
+
* is delivered as a `PointerEvent` exactly as modern browsers deliver native clicks.
|
|
188
|
+
* @internal
|
|
189
|
+
*/
|
|
190
|
+
const SYNTHESIZED_EVENTS = [
|
|
191
|
+
'pointerenter',
|
|
192
|
+
'pointerleave',
|
|
193
|
+
'pointerdown',
|
|
194
|
+
'pointerup',
|
|
195
|
+
'pointermove',
|
|
196
|
+
'click'
|
|
197
|
+
];
|
|
198
|
+
const SYNTHESIZED_EVENT_SET = new Set(SYNTHESIZED_EVENTS);
|
|
199
|
+
/**
|
|
200
|
+
* The attribute names of the inline event handlers (`onpointerdown`, `onclick`, ...), shared by
|
|
201
|
+
* every element that fronts an engine entity. Spread into `observedAttributes` by subclasses.
|
|
202
|
+
* @internal
|
|
203
|
+
*/
|
|
204
|
+
const EVENT_ATTRIBUTES = SYNTHESIZED_EVENTS.map((type) => `on${type}`);
|
|
205
|
+
/**
|
|
206
|
+
* The base class for elements that front an engine {@link Entity}: `<pc-entity>` and
|
|
207
|
+
* `<pc-model>`, which create one, and `<pc-node>`, which binds to one inside a model's
|
|
208
|
+
* instantiated hierarchy. It carries what all of them need — the `entity` contract, registration
|
|
209
|
+
* with the owning application (which joins picked scene nodes back to elements by identity,
|
|
210
|
+
* never by name), and the pointer listener bookkeeping that lets the application lazily attach
|
|
211
|
+
* its canvas handlers.
|
|
212
|
+
*/
|
|
213
|
+
class EntityBaseElement extends AsyncElement {
|
|
214
|
+
_entity = null;
|
|
215
|
+
/**
|
|
216
|
+
* The application element this entity is registered with, cached at registration time so the
|
|
217
|
+
* entity can be unregistered even once this element has left the DOM.
|
|
218
|
+
*/
|
|
219
|
+
_appElement = null;
|
|
220
|
+
/**
|
|
221
|
+
* The event listeners registered on the element, by type.
|
|
222
|
+
*/
|
|
223
|
+
_listeners = {};
|
|
224
|
+
/**
|
|
225
|
+
* The event types for which an inline handler attribute (`onpointerdown`, `onclick`, ...)
|
|
226
|
+
* is currently present.
|
|
227
|
+
*/
|
|
228
|
+
_inlineHandlerTypes = new Set();
|
|
229
|
+
/**
|
|
230
|
+
* The PlayCanvas entity instance. `null` until the element is ready, and again once the
|
|
231
|
+
* entity is gone — await {@link whenReady} or the element's `ready()` promise before
|
|
232
|
+
* accessing it.
|
|
233
|
+
* @returns The entity instance, or `null`.
|
|
234
|
+
*/
|
|
235
|
+
get entity() {
|
|
236
|
+
return this._entity;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Registers `entity` as this element's backing entity with the owning application, which
|
|
240
|
+
* joins engine nodes back to elements by identity (never by name).
|
|
241
|
+
*
|
|
242
|
+
* @param entity - The entity to register.
|
|
243
|
+
*/
|
|
244
|
+
_registerEntity(entity) {
|
|
245
|
+
this._appElement = this.closestApp;
|
|
246
|
+
this._appElement?._registerEntityElement(entity, this);
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Removes the registration for `entity`.
|
|
250
|
+
*
|
|
251
|
+
* @param entity - The entity to unregister.
|
|
252
|
+
*/
|
|
253
|
+
_unregisterEntity(entity) {
|
|
254
|
+
this._appElement?._unregisterEntityElement(entity);
|
|
255
|
+
this._appElement = null;
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Tracks whether an inline handler attribute is present. The browser itself compiles and
|
|
259
|
+
* runs these attributes — they are standard `GlobalEventHandlers`, so setting one replaces
|
|
260
|
+
* the previous handler and removing it removes the handler, exactly like `onclick` on any
|
|
261
|
+
* HTML element. But because they bypass {@link EventTarget.addEventListener}, the connect/disconnect
|
|
262
|
+
* bookkeeping that lets the application lazily attach its canvas pointer handlers must be
|
|
263
|
+
* kept in sync here.
|
|
264
|
+
*
|
|
265
|
+
* @param name - The attribute name (e.g. 'onpointerdown').
|
|
266
|
+
* @param value - The attribute value, or `null` when the attribute has been removed.
|
|
267
|
+
*/
|
|
268
|
+
_updateInlineHandler(name, value) {
|
|
269
|
+
const type = name.substring(2);
|
|
270
|
+
const had = this._inlineHandlerTypes.has(type);
|
|
271
|
+
const has = value !== null;
|
|
272
|
+
if (has && !had) {
|
|
273
|
+
this._inlineHandlerTypes.add(type);
|
|
274
|
+
this.dispatchEvent(new CustomEvent(`${type}:connect`, { bubbles: true }));
|
|
275
|
+
}
|
|
276
|
+
else if (!has && had) {
|
|
277
|
+
this._inlineHandlerTypes.delete(type);
|
|
278
|
+
this.dispatchEvent(new CustomEvent(`${type}:disconnect`, { bubbles: true }));
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
addEventListener(type, listener, options) {
|
|
282
|
+
if (!this._listeners[type]) {
|
|
283
|
+
this._listeners[type] = [];
|
|
284
|
+
}
|
|
285
|
+
this._listeners[type].push(listener);
|
|
286
|
+
super.addEventListener(type, listener, options);
|
|
287
|
+
if (SYNTHESIZED_EVENT_SET.has(type)) {
|
|
288
|
+
this.dispatchEvent(new CustomEvent(`${type}:connect`, { bubbles: true }));
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
removeEventListener(type, listener, options) {
|
|
292
|
+
if (this._listeners[type]) {
|
|
293
|
+
this._listeners[type] = this._listeners[type].filter((l) => l !== listener);
|
|
294
|
+
}
|
|
295
|
+
super.removeEventListener(type, listener, options);
|
|
296
|
+
if (SYNTHESIZED_EVENT_SET.has(type)) {
|
|
297
|
+
this.dispatchEvent(new CustomEvent(`${type}:disconnect`, { bubbles: true }));
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Whether the element has a listener for an event type, registered either with
|
|
302
|
+
* {@link EventTarget.addEventListener} or with the matching inline handler attribute. Read by the
|
|
303
|
+
* containing `<pc-app>` element to gate event synthesis.
|
|
304
|
+
*
|
|
305
|
+
* @param type - The event type.
|
|
306
|
+
* @returns Whether a listener is registered.
|
|
307
|
+
* @internal
|
|
308
|
+
*/
|
|
309
|
+
_hasListeners(type) {
|
|
310
|
+
return Boolean(this._listeners[type]?.length) || this._inlineHandlerTypes.has(type);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
180
314
|
/** Covers the 0.2s opacity transition; jsdom never fires transitionend, so removal is timed. */
|
|
181
315
|
const REMOVAL_DELAY_MS = 250;
|
|
182
316
|
/**
|
|
@@ -730,14 +864,51 @@
|
|
|
730
864
|
return element?.entity ?? null;
|
|
731
865
|
};
|
|
732
866
|
|
|
733
|
-
/** The pointer event types the application synthesizes on `<pc-entity>` elements via picking. */
|
|
734
|
-
const pointerEventTypes = ['pointermove', 'pointerdown', 'pointerup', 'pointerenter', 'pointerleave'];
|
|
735
867
|
/**
|
|
736
868
|
* The event types whose listeners make an element a hover target. Hover resolution walks past
|
|
737
869
|
* elements listening for none of them, so a silent element never swallows an ancestor's
|
|
738
870
|
* enter/leave pair.
|
|
739
871
|
*/
|
|
740
872
|
const hoverEventTypes = ['pointerenter', 'pointerleave', 'pointermove'];
|
|
873
|
+
/**
|
|
874
|
+
* The canvas listeners each synthesized event type is driven by. Enter and leave are derived
|
|
875
|
+
* from move picks. A click is concluded from the down/up pair, with pointercancel discarding a
|
|
876
|
+
* press the browser takes back (for example a touch that becomes a scroll).
|
|
877
|
+
*/
|
|
878
|
+
const canvasEventsFor = {
|
|
879
|
+
pointermove: ['pointermove'],
|
|
880
|
+
pointerenter: ['pointermove'],
|
|
881
|
+
pointerleave: ['pointermove'],
|
|
882
|
+
pointerdown: ['pointerdown'],
|
|
883
|
+
pointerup: ['pointerup'],
|
|
884
|
+
click: ['pointerdown', 'pointerup', 'pointercancel']
|
|
885
|
+
};
|
|
886
|
+
/**
|
|
887
|
+
* How long after a click a further click on the same target still raises the click count that
|
|
888
|
+
* `detail` carries, approximating the platform's double-click time.
|
|
889
|
+
*/
|
|
890
|
+
const CLICK_CHAIN_MS = 500;
|
|
891
|
+
/**
|
|
892
|
+
* Finds the nearest common inclusive ancestor of two picked nodes - the node a click belongs to
|
|
893
|
+
* when the press and the release picked different geometry, exactly as the DOM assigns a click
|
|
894
|
+
* whose down and up have different targets.
|
|
895
|
+
*
|
|
896
|
+
* @param a - The node the press picked, or `null`.
|
|
897
|
+
* @param b - The node the release picked, or `null`.
|
|
898
|
+
* @returns The nearest common inclusive ancestor, or `null` when there is none.
|
|
899
|
+
*/
|
|
900
|
+
const commonAncestor = (a, b) => {
|
|
901
|
+
const ancestors = new Set();
|
|
902
|
+
for (let node = a; node !== null; node = node.parent) {
|
|
903
|
+
ancestors.add(node);
|
|
904
|
+
}
|
|
905
|
+
for (let node = b; node !== null; node = node.parent) {
|
|
906
|
+
if (ancestors.has(node)) {
|
|
907
|
+
return node;
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
return null;
|
|
911
|
+
};
|
|
741
912
|
/**
|
|
742
913
|
* Gives `pc-app` the sizing contract of a replaced element (`<video>`, `<img>`): a block-level
|
|
743
914
|
* box that the page's CSS sizes, defaulting to the canvas's own 300x150 intrinsic size, with the
|
|
@@ -766,6 +937,10 @@
|
|
|
766
937
|
* tracked live via a ResizeObserver — so the element can be embedded at any size, resized by
|
|
767
938
|
* its container, or made fullscreen with ordinary CSS such as `width: 100vw; height: 100dvh`.
|
|
768
939
|
*
|
|
940
|
+
* @elementSummary The `<pc-app>` element creates a PlayCanvas application and the canvas it renders
|
|
941
|
+
* into, and is the root of every scene. It holds the `<pc-asset>`, `<pc-material>`, `<pc-wasm>` and
|
|
942
|
+
* `<pc-scene>` elements, and the page's CSS sizes it, as it would a `<video>`.
|
|
943
|
+
*
|
|
769
944
|
* @fires {ProgressEvent} progress - Fired while the application preloads its assets. `loaded` and
|
|
770
945
|
* `total` are asset counts, not bytes, and an asset that fails to load still counts as loaded.
|
|
771
946
|
* Fired at least once per boot, and the final event always has `loaded` equal to `total`. Does
|
|
@@ -818,21 +993,30 @@
|
|
|
818
993
|
*/
|
|
819
994
|
_entityElements = new Map();
|
|
820
995
|
_picker = null;
|
|
821
|
-
_hasPointerListeners = {
|
|
822
|
-
pointerenter: false,
|
|
823
|
-
pointerleave: false,
|
|
824
|
-
pointerdown: false,
|
|
825
|
-
pointerup: false,
|
|
826
|
-
pointermove: false
|
|
827
|
-
};
|
|
828
996
|
_hoveredEntity = null;
|
|
829
997
|
// Identifies the newest in-flight hover pick, so out-of-order results can be discarded
|
|
830
998
|
_pickToken = 0;
|
|
831
999
|
_pointerHandlers = {
|
|
832
1000
|
pointermove: null,
|
|
833
1001
|
pointerdown: null,
|
|
834
|
-
pointerup: null
|
|
1002
|
+
pointerup: null,
|
|
1003
|
+
pointercancel: null
|
|
835
1004
|
};
|
|
1005
|
+
/**
|
|
1006
|
+
* The pick of each pointer's primary-button press, keyed by pointerId and kept while a click
|
|
1007
|
+
* may still conclude it. The promise is stored rather than its result, so a release can
|
|
1008
|
+
* await a press pick that has not resolved yet. Entries are removed by the matching
|
|
1009
|
+
* pointerup or pointercancel, and only ever stored while some element listens for click -
|
|
1010
|
+
* which is also what keeps those two canvas listeners attached.
|
|
1011
|
+
*/
|
|
1012
|
+
_downPicks = new Map();
|
|
1013
|
+
/** Whether any element in the tree listens for click. Maintained by _syncCanvasListeners. */
|
|
1014
|
+
_clickListened = false;
|
|
1015
|
+
/**
|
|
1016
|
+
* The previous click's target, time and count, for chaining successive clicks into the
|
|
1017
|
+
* click count that `detail` carries. `null` until a click has fired.
|
|
1018
|
+
*/
|
|
1019
|
+
_lastClick = null;
|
|
836
1020
|
_app = null;
|
|
837
1021
|
_loadProgress = 0;
|
|
838
1022
|
/**
|
|
@@ -867,12 +1051,12 @@
|
|
|
867
1051
|
*/
|
|
868
1052
|
constructor() {
|
|
869
1053
|
super();
|
|
870
|
-
// Track
|
|
871
|
-
// Registered once here rather than on every boot - the
|
|
872
|
-
// canvas, and a re-booted element must not stack a second set.
|
|
873
|
-
|
|
874
|
-
this.addEventListener(`${type}:connect`, () => this.
|
|
875
|
-
this.addEventListener(`${type}:disconnect`, () => this.
|
|
1054
|
+
// Track listeners for the synthesized events being added to and removed from descendant
|
|
1055
|
+
// entities. Registered once here rather than on every boot - the sync no-ops while there
|
|
1056
|
+
// is no canvas, and a re-booted element must not stack a second set.
|
|
1057
|
+
SYNTHESIZED_EVENTS.forEach((type) => {
|
|
1058
|
+
this.addEventListener(`${type}:connect`, () => this._syncCanvasListeners());
|
|
1059
|
+
this.addEventListener(`${type}:disconnect`, () => this._syncCanvasListeners());
|
|
876
1060
|
});
|
|
877
1061
|
}
|
|
878
1062
|
async connectedCallback() {
|
|
@@ -1190,15 +1374,13 @@
|
|
|
1190
1374
|
this._pointerHandlers.pointermove = listener(this._onPointerMove);
|
|
1191
1375
|
this._pointerHandlers.pointerdown = listener(this._onPointerDown);
|
|
1192
1376
|
this._pointerHandlers.pointerup = listener(this._onPointerUp);
|
|
1193
|
-
|
|
1194
|
-
|
|
1377
|
+
this._pointerHandlers.pointercancel = (event) => {
|
|
1378
|
+
this._downPicks.delete(event.pointerId);
|
|
1379
|
+
};
|
|
1380
|
+
// Attach canvas listeners for element listeners registered before this boot (e.g.
|
|
1381
|
+
// handlers created from inline attributes when their elements were first upgraded, or
|
|
1195
1382
|
// listeners carried over from before a re-boot)
|
|
1196
|
-
|
|
1197
|
-
const anyListeners = Array.from(this.querySelectorAll('pc-entity, pc-model, pc-node')).some((entity) => entity._hasListeners(type));
|
|
1198
|
-
if (anyListeners) {
|
|
1199
|
-
this._onPointerListenerAdded(type);
|
|
1200
|
-
}
|
|
1201
|
-
});
|
|
1383
|
+
this._syncCanvasListeners();
|
|
1202
1384
|
}
|
|
1203
1385
|
_pickerDestroy() {
|
|
1204
1386
|
if (this._canvas) {
|
|
@@ -1213,15 +1395,12 @@
|
|
|
1213
1395
|
this._pointerHandlers = {
|
|
1214
1396
|
pointermove: null,
|
|
1215
1397
|
pointerdown: null,
|
|
1216
|
-
pointerup: null
|
|
1217
|
-
|
|
1218
|
-
this._hasPointerListeners = {
|
|
1219
|
-
pointerenter: false,
|
|
1220
|
-
pointerleave: false,
|
|
1221
|
-
pointerdown: false,
|
|
1222
|
-
pointerup: false,
|
|
1223
|
-
pointermove: false
|
|
1398
|
+
pointerup: null,
|
|
1399
|
+
pointercancel: null
|
|
1224
1400
|
};
|
|
1401
|
+
this._downPicks.clear();
|
|
1402
|
+
this._clickListened = false;
|
|
1403
|
+
this._lastClick = null;
|
|
1225
1404
|
}
|
|
1226
1405
|
/**
|
|
1227
1406
|
* Registers the element that fronts an entity. Called by EntityElement when it creates its
|
|
@@ -1427,7 +1606,15 @@
|
|
|
1427
1606
|
async _onPointerDown(event) {
|
|
1428
1607
|
if (!this._picker || !this.app)
|
|
1429
1608
|
return;
|
|
1430
|
-
const
|
|
1609
|
+
const pick = this._pickNode(event);
|
|
1610
|
+
// A click concludes on the matching pointerup, which needs to know what the press
|
|
1611
|
+
// picked. Primary button only - the only button a click can conclude from - and only
|
|
1612
|
+
// while click is listened for, since it is the click mapping that keeps the pointerup
|
|
1613
|
+
// and pointercancel listeners attached to clean the entry up again.
|
|
1614
|
+
if (this._clickListened && event.button === 0) {
|
|
1615
|
+
this._downPicks.set(event.pointerId, pick);
|
|
1616
|
+
}
|
|
1617
|
+
const node = await pick;
|
|
1431
1618
|
if (!this._picker)
|
|
1432
1619
|
return; // the element disconnected while the pick was in flight
|
|
1433
1620
|
const entityElement = this._elementWithListener(node, 'pointerdown');
|
|
@@ -1438,6 +1625,10 @@
|
|
|
1438
1625
|
async _onPointerUp(event) {
|
|
1439
1626
|
if (!this._picker || !this.app)
|
|
1440
1627
|
return;
|
|
1628
|
+
// The press pick this release may conclude as a click. Claimed synchronously, so the
|
|
1629
|
+
// entry is gone before any other event for this pointer can be handled.
|
|
1630
|
+
const downPick = this._downPicks.get(event.pointerId);
|
|
1631
|
+
this._downPicks.delete(event.pointerId);
|
|
1441
1632
|
const node = await this._pickNode(event);
|
|
1442
1633
|
if (!this._picker)
|
|
1443
1634
|
return; // the element disconnected while the pick was in flight
|
|
@@ -1445,30 +1636,60 @@
|
|
|
1445
1636
|
if (entityElement) {
|
|
1446
1637
|
entityElement.dispatchEvent(new PointerEvent('pointerup', event));
|
|
1447
1638
|
}
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1639
|
+
// A click fires where the DOM fires it: at the nearest common inclusive ancestor of
|
|
1640
|
+
// what the press and the release picked, for the primary button only. The press pick
|
|
1641
|
+
// may still be in flight - a quick tap resolves in pick order, not event order.
|
|
1642
|
+
if (!downPick || event.button !== 0)
|
|
1643
|
+
return;
|
|
1644
|
+
const downNode = await downPick;
|
|
1645
|
+
if (!this._picker)
|
|
1646
|
+
return;
|
|
1647
|
+
const clickElement = this._elementWithListener(commonAncestor(downNode, node), 'click');
|
|
1648
|
+
if (clickElement) {
|
|
1649
|
+
const click = new PointerEvent('click', event);
|
|
1650
|
+
// The init above copied pointerup's `detail`, which the Pointer Events spec fixes
|
|
1651
|
+
// at 0 - but click is exempt: its detail is the click count, chained here as the
|
|
1652
|
+
// platform chains it (same target, within the double-click window). Overridden
|
|
1653
|
+
// with defineProperty because an event instance used as an init dict cannot have
|
|
1654
|
+
// single fields replaced.
|
|
1655
|
+
const time = performance.now();
|
|
1656
|
+
const last = this._lastClick;
|
|
1657
|
+
const count = last && last.element === clickElement && time - last.time <= CLICK_CHAIN_MS ? last.count + 1 : 1;
|
|
1658
|
+
this._lastClick = { element: clickElement, time, count };
|
|
1659
|
+
Object.defineProperty(click, 'detail', { value: count });
|
|
1660
|
+
clickElement.dispatchEvent(click);
|
|
1661
|
+
}
|
|
1662
|
+
}
|
|
1663
|
+
/**
|
|
1664
|
+
* Attaches exactly the canvas listeners the tree's current element listeners need, and
|
|
1665
|
+
* detaches the rest. Recomputed whenever a listener connects or disconnects anywhere under
|
|
1666
|
+
* this element: several synthesized types can need the same canvas listener (enter, leave
|
|
1667
|
+
* and move all ride the move pick; click rides the down/up pair), so one type's removal
|
|
1668
|
+
* must not detach a listener another type still uses. Re-attaching an attached listener is
|
|
1669
|
+
* a no-op by EventTarget semantics, so no attach state is kept.
|
|
1670
|
+
*/
|
|
1671
|
+
_syncCanvasListeners() {
|
|
1672
|
+
const canvas = this._canvas;
|
|
1673
|
+
if (!canvas)
|
|
1674
|
+
return; // not booted yet: _pickerCreate syncs once the handlers exist
|
|
1675
|
+
const elements = Array.from(this.querySelectorAll('pc-entity, pc-model, pc-node'));
|
|
1676
|
+
const needed = new Set();
|
|
1677
|
+
for (const type of SYNTHESIZED_EVENTS) {
|
|
1678
|
+
if (elements.some((element) => element._hasListeners(type))) {
|
|
1679
|
+
canvasEventsFor[type].forEach((canvasType) => needed.add(canvasType));
|
|
1458
1680
|
}
|
|
1459
1681
|
}
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
? this._pointerHandlers.pointermove
|
|
1467
|
-
: this._pointerHandlers[type];
|
|
1468
|
-
if (handler) {
|
|
1469
|
-
this._canvas.removeEventListener(type === 'pointerenter' || type === 'pointerleave' ? 'pointermove' : type, handler);
|
|
1682
|
+
this._clickListened = elements.some((element) => element._hasListeners('click'));
|
|
1683
|
+
Object.entries(this._pointerHandlers).forEach(([canvasType, handler]) => {
|
|
1684
|
+
if (!handler)
|
|
1685
|
+
return;
|
|
1686
|
+
if (needed.has(canvasType)) {
|
|
1687
|
+
canvas.addEventListener(canvasType, handler);
|
|
1470
1688
|
}
|
|
1471
|
-
|
|
1689
|
+
else {
|
|
1690
|
+
canvas.removeEventListener(canvasType, handler);
|
|
1691
|
+
}
|
|
1692
|
+
});
|
|
1472
1693
|
}
|
|
1473
1694
|
/**
|
|
1474
1695
|
* Warns that a graphics option was written too late to have any effect. These options are read
|
|
@@ -1637,126 +1858,6 @@
|
|
|
1637
1858
|
}
|
|
1638
1859
|
customElements.define('pc-app', AppElement);
|
|
1639
1860
|
|
|
1640
|
-
/**
|
|
1641
|
-
* The attribute names of the inline `onpointer*` event handlers, shared by every element that
|
|
1642
|
-
* fronts an engine entity. Spread into `observedAttributes` by subclasses.
|
|
1643
|
-
* @internal
|
|
1644
|
-
*/
|
|
1645
|
-
const POINTER_ATTRIBUTES = [
|
|
1646
|
-
'onpointerenter',
|
|
1647
|
-
'onpointerleave',
|
|
1648
|
-
'onpointerdown',
|
|
1649
|
-
'onpointerup',
|
|
1650
|
-
'onpointermove'
|
|
1651
|
-
];
|
|
1652
|
-
/**
|
|
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.
|
|
1659
|
-
*/
|
|
1660
|
-
class EntityBaseElement extends AsyncElement {
|
|
1661
|
-
_entity = null;
|
|
1662
|
-
/**
|
|
1663
|
-
* The application element this entity is registered with, cached at registration time so the
|
|
1664
|
-
* entity can be unregistered even once this element has left the DOM.
|
|
1665
|
-
*/
|
|
1666
|
-
_appElement = null;
|
|
1667
|
-
/**
|
|
1668
|
-
* The pointer event listeners for the entity.
|
|
1669
|
-
*/
|
|
1670
|
-
_listeners = {};
|
|
1671
|
-
/**
|
|
1672
|
-
* The event types for which an inline `onpointer*` attribute is currently present.
|
|
1673
|
-
*/
|
|
1674
|
-
_inlineHandlerTypes = new Set();
|
|
1675
|
-
/**
|
|
1676
|
-
* The PlayCanvas entity instance. `null` until the element is ready, and again once the
|
|
1677
|
-
* entity is gone — await {@link whenReady} or the element's `ready()` promise before
|
|
1678
|
-
* accessing it.
|
|
1679
|
-
* @returns The entity instance, or `null`.
|
|
1680
|
-
*/
|
|
1681
|
-
get entity() {
|
|
1682
|
-
return this._entity;
|
|
1683
|
-
}
|
|
1684
|
-
/**
|
|
1685
|
-
* Registers `entity` as this element's backing entity with the owning application, which
|
|
1686
|
-
* joins engine nodes back to elements by identity (never by name).
|
|
1687
|
-
*
|
|
1688
|
-
* @param entity - The entity to register.
|
|
1689
|
-
*/
|
|
1690
|
-
_registerEntity(entity) {
|
|
1691
|
-
this._appElement = this.closestApp;
|
|
1692
|
-
this._appElement?._registerEntityElement(entity, this);
|
|
1693
|
-
}
|
|
1694
|
-
/**
|
|
1695
|
-
* Removes the registration for `entity`.
|
|
1696
|
-
*
|
|
1697
|
-
* @param entity - The entity to unregister.
|
|
1698
|
-
*/
|
|
1699
|
-
_unregisterEntity(entity) {
|
|
1700
|
-
this._appElement?._unregisterEntityElement(entity);
|
|
1701
|
-
this._appElement = null;
|
|
1702
|
-
}
|
|
1703
|
-
/**
|
|
1704
|
-
* Tracks whether an inline `onpointer*` attribute is present. The browser itself compiles and
|
|
1705
|
-
* runs these attributes — they are standard `GlobalEventHandlers`, so setting one replaces
|
|
1706
|
-
* the previous handler and removing it removes the handler, exactly like `onclick` on any
|
|
1707
|
-
* HTML element. But because they bypass {@link addEventListener}, the connect/disconnect
|
|
1708
|
-
* bookkeeping that lets the application lazily attach its canvas pointer handlers must be
|
|
1709
|
-
* kept in sync here.
|
|
1710
|
-
*
|
|
1711
|
-
* @param name - The attribute name (e.g. 'onpointerdown').
|
|
1712
|
-
* @param value - The attribute value, or `null` when the attribute has been removed.
|
|
1713
|
-
*/
|
|
1714
|
-
_updateInlineHandler(name, value) {
|
|
1715
|
-
const type = name.substring(2);
|
|
1716
|
-
const had = this._inlineHandlerTypes.has(type);
|
|
1717
|
-
const has = value !== null;
|
|
1718
|
-
if (has && !had) {
|
|
1719
|
-
this._inlineHandlerTypes.add(type);
|
|
1720
|
-
this.dispatchEvent(new CustomEvent(`${type}:connect`, { bubbles: true }));
|
|
1721
|
-
}
|
|
1722
|
-
else if (!has && had) {
|
|
1723
|
-
this._inlineHandlerTypes.delete(type);
|
|
1724
|
-
this.dispatchEvent(new CustomEvent(`${type}:disconnect`, { bubbles: true }));
|
|
1725
|
-
}
|
|
1726
|
-
}
|
|
1727
|
-
addEventListener(type, listener, options) {
|
|
1728
|
-
if (!this._listeners[type]) {
|
|
1729
|
-
this._listeners[type] = [];
|
|
1730
|
-
}
|
|
1731
|
-
this._listeners[type].push(listener);
|
|
1732
|
-
super.addEventListener(type, listener, options);
|
|
1733
|
-
if (type.startsWith('pointer')) {
|
|
1734
|
-
this.dispatchEvent(new CustomEvent(`${type}:connect`, { bubbles: true }));
|
|
1735
|
-
}
|
|
1736
|
-
}
|
|
1737
|
-
removeEventListener(type, listener, options) {
|
|
1738
|
-
if (this._listeners[type]) {
|
|
1739
|
-
this._listeners[type] = this._listeners[type].filter((l) => l !== listener);
|
|
1740
|
-
}
|
|
1741
|
-
super.removeEventListener(type, listener, options);
|
|
1742
|
-
if (type.startsWith('pointer')) {
|
|
1743
|
-
this.dispatchEvent(new CustomEvent(`${type}:disconnect`, { bubbles: true }));
|
|
1744
|
-
}
|
|
1745
|
-
}
|
|
1746
|
-
/**
|
|
1747
|
-
* Whether the element has a listener for an event type, registered either with
|
|
1748
|
-
* {@link addEventListener} or with the matching inline `onpointer*` attribute. Read by the
|
|
1749
|
-
* containing `<pc-app>` element to gate pointer event synthesis.
|
|
1750
|
-
*
|
|
1751
|
-
* @param type - The event type.
|
|
1752
|
-
* @returns Whether a listener is registered.
|
|
1753
|
-
* @internal
|
|
1754
|
-
*/
|
|
1755
|
-
_hasListeners(type) {
|
|
1756
|
-
return Boolean(this._listeners[type]?.length) || this._inlineHandlerTypes.has(type);
|
|
1757
|
-
}
|
|
1758
|
-
}
|
|
1759
|
-
|
|
1760
1861
|
/**
|
|
1761
1862
|
* Creates and parents the entities of every descendant entity-owning element of `root`, in two
|
|
1762
1863
|
* passes so that no parent's existence depends on document order. Called wherever a subtree could
|
|
@@ -1814,7 +1915,7 @@
|
|
|
1814
1915
|
*/
|
|
1815
1916
|
_tags = [];
|
|
1816
1917
|
/**
|
|
1817
|
-
* Whether the hierarchy has been built for this entity — set once
|
|
1918
|
+
* Whether the hierarchy has been built for this entity — set once `_buildHierarchy` has
|
|
1818
1919
|
* parented it. Read by subclasses that gate work on the entity being in the scene graph.
|
|
1819
1920
|
*/
|
|
1820
1921
|
_built = false;
|
|
@@ -1903,7 +2004,7 @@
|
|
|
1903
2004
|
this._onBuilt();
|
|
1904
2005
|
}
|
|
1905
2006
|
/**
|
|
1906
|
-
* Called by
|
|
2007
|
+
* Called by `_buildHierarchy` once the backing entity has been parented — exactly once
|
|
1907
2008
|
* per build cycle. The default announces readiness, which is what a parented `<pc-entity>`
|
|
1908
2009
|
* means; `<pc-model>` overrides it to start loading content instead, because its readiness
|
|
1909
2010
|
* tracks the content settling rather than the host entering the scene graph.
|
|
@@ -2024,8 +2125,13 @@
|
|
|
2024
2125
|
*
|
|
2025
2126
|
* The pointer events below are dispatched by the containing `<pc-app>` element when the pointer
|
|
2026
2127
|
* 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
|
|
2028
|
-
* attribute.
|
|
2128
|
+
* them, registered either with {@link EventTarget.addEventListener} or with the matching inline
|
|
2129
|
+
* attribute (`onpointerdown`, `onclick`, ...).
|
|
2130
|
+
*
|
|
2131
|
+
* @elementSummary The `<pc-entity>` element creates an entity: a named, transformable node of the
|
|
2132
|
+
* scene hierarchy, and the host for component elements such as `<pc-camera>`, `<pc-light>` and
|
|
2133
|
+
* `<pc-render>`. Place it in the `<pc-scene>`, or nest it under another `<pc-entity>`, a
|
|
2134
|
+
* `<pc-model>` or a `<pc-node>` to parent it there.
|
|
2029
2135
|
*
|
|
2030
2136
|
* @attribute {boolean} enabled - The enabled state of the entity.
|
|
2031
2137
|
* @attribute {string} name - The name of the entity.
|
|
@@ -2040,11 +2146,17 @@
|
|
|
2040
2146
|
* entity.
|
|
2041
2147
|
* @attribute {string} onpointerup - Script to run when a pointer button is released over the
|
|
2042
2148
|
* entity.
|
|
2149
|
+
* @attribute {string} onclick - Script to run when the entity is clicked: a primary pointer
|
|
2150
|
+
* button pressed and then released over it.
|
|
2043
2151
|
* @fires {PointerEvent} pointerenter - Fired when the pointer moves onto the entity.
|
|
2044
2152
|
* @fires {PointerEvent} pointerleave - Fired when the pointer moves off the entity.
|
|
2045
2153
|
* @fires {PointerEvent} pointermove - Fired when the pointer moves over the entity.
|
|
2046
2154
|
* @fires {PointerEvent} pointerdown - Fired when a pointer button is pressed over the entity.
|
|
2047
2155
|
* @fires {PointerEvent} pointerup - Fired when a pointer button is released over the entity.
|
|
2156
|
+
* @fires {PointerEvent} click - Fired when a primary pointer button is pressed and then released
|
|
2157
|
+
* over the entity. A press and release that picked different entities fires on their nearest
|
|
2158
|
+
* common ancestor instead, as in the DOM. `detail` carries the click count, so a double click
|
|
2159
|
+
* arrives as a click whose `detail` is 2.
|
|
2048
2160
|
*/
|
|
2049
2161
|
class EntityElement extends EntityOwnerElement {
|
|
2050
2162
|
connectedCallback() {
|
|
@@ -2079,7 +2191,7 @@
|
|
|
2079
2191
|
this._entity?.destroy();
|
|
2080
2192
|
}
|
|
2081
2193
|
static get observedAttributes() {
|
|
2082
|
-
return ['enabled', 'name', 'position', 'rotation', 'scale', 'tags', ...
|
|
2194
|
+
return ['enabled', 'name', 'position', 'rotation', 'scale', 'tags', ...EVENT_ATTRIBUTES];
|
|
2083
2195
|
}
|
|
2084
2196
|
attributeChangedCallback(name, _oldValue, newValue) {
|
|
2085
2197
|
switch (name) {
|
|
@@ -2106,6 +2218,7 @@
|
|
|
2106
2218
|
case 'onpointerdown':
|
|
2107
2219
|
case 'onpointerup':
|
|
2108
2220
|
case 'onpointermove':
|
|
2221
|
+
case 'onclick':
|
|
2109
2222
|
this._updateInlineHandler(name, newValue);
|
|
2110
2223
|
break;
|
|
2111
2224
|
}
|
|
@@ -2407,6 +2520,10 @@
|
|
|
2407
2520
|
* Apart from `lazy` and the texture options, these attributes are read once when the asset is
|
|
2408
2521
|
* created, so changing them later has no effect.
|
|
2409
2522
|
*
|
|
2523
|
+
* @elementSummary The `<pc-asset>` element declares an asset for the application to load — a model,
|
|
2524
|
+
* texture, font, sound, script or JSON file — under an `id` that other elements reference. Must be
|
|
2525
|
+
* a direct child of `<pc-app>`.
|
|
2526
|
+
*
|
|
2410
2527
|
* @attribute {string} id - The identifier used to reference the asset from other elements.
|
|
2411
2528
|
* @attribute {string} src - The URL of the asset to load.
|
|
2412
2529
|
* @attribute {string} type - The asset type. Inferred from the `src` file extension when omitted.
|
|
@@ -3033,6 +3150,11 @@
|
|
|
3033
3150
|
* intersects the model's geometry, exactly as for `<pc-entity>` — a hit on a content node that no
|
|
3034
3151
|
* `pc-node` fronts resolves to this element.
|
|
3035
3152
|
*
|
|
3153
|
+
* @elementSummary The `<pc-model>` element instantiates a 3D model from a container asset
|
|
3154
|
+
* (typically a GLB) beneath an entity of its own, so the element's transform and tags place the
|
|
3155
|
+
* instance in the scene. Its `<pc-node>` children override what the asset authored. Place it in the
|
|
3156
|
+
* `<pc-scene>`, or nest it under a `<pc-entity>`, another `<pc-model>` or a `<pc-node>`.
|
|
3157
|
+
*
|
|
3036
3158
|
* @attribute {boolean} enabled - The enabled state of the model.
|
|
3037
3159
|
* @attribute {string} name - The name of the model.
|
|
3038
3160
|
* @attribute {string} position - The position of the model.
|
|
@@ -3046,11 +3168,17 @@
|
|
|
3046
3168
|
* model.
|
|
3047
3169
|
* @attribute {string} onpointerup - Script to run when a pointer button is released over the
|
|
3048
3170
|
* model.
|
|
3171
|
+
* @attribute {string} onclick - Script to run when the model is clicked: a primary pointer
|
|
3172
|
+
* button pressed and then released over it.
|
|
3049
3173
|
* @fires {PointerEvent} pointerenter - Fired when the pointer moves onto the model.
|
|
3050
3174
|
* @fires {PointerEvent} pointerleave - Fired when the pointer moves off the model.
|
|
3051
3175
|
* @fires {PointerEvent} pointermove - Fired when the pointer moves over the model.
|
|
3052
3176
|
* @fires {PointerEvent} pointerdown - Fired when a pointer button is pressed over the model.
|
|
3053
3177
|
* @fires {PointerEvent} pointerup - Fired when a pointer button is released over the model.
|
|
3178
|
+
* @fires {PointerEvent} click - Fired when a primary pointer button is pressed and then released
|
|
3179
|
+
* over the model. A press and release that picked different entities fires on their nearest
|
|
3180
|
+
* common ancestor instead, as in the DOM. `detail` carries the click count, so a double click
|
|
3181
|
+
* arrives as a click whose `detail` is 2.
|
|
3054
3182
|
* @fires {Event} load - Fired each time a container asset finishes instantiating, including
|
|
3055
3183
|
* re-instantiation after `asset` changes. Does not bubble — listen on this element, or use a
|
|
3056
3184
|
* capture-phase listener on an ancestor.
|
|
@@ -3299,7 +3427,7 @@
|
|
|
3299
3427
|
return this._asset;
|
|
3300
3428
|
}
|
|
3301
3429
|
static get observedAttributes() {
|
|
3302
|
-
return ['asset', 'enabled', 'name', 'position', 'rotation', 'scale', 'tags', ...
|
|
3430
|
+
return ['asset', 'enabled', 'name', 'position', 'rotation', 'scale', 'tags', ...EVENT_ATTRIBUTES];
|
|
3303
3431
|
}
|
|
3304
3432
|
attributeChangedCallback(name, _oldValue, newValue) {
|
|
3305
3433
|
switch (name) {
|
|
@@ -3329,6 +3457,7 @@
|
|
|
3329
3457
|
case 'onpointerdown':
|
|
3330
3458
|
case 'onpointerup':
|
|
3331
3459
|
case 'onpointermove':
|
|
3460
|
+
case 'onclick':
|
|
3332
3461
|
this._updateInlineHandler(name, newValue);
|
|
3333
3462
|
break;
|
|
3334
3463
|
}
|
|
@@ -3566,6 +3695,11 @@
|
|
|
3566
3695
|
*
|
|
3567
3696
|
* Engine component: {@link AnimComponent} (`anim`).
|
|
3568
3697
|
*
|
|
3698
|
+
* @elementSummary The `<pc-anim>` element plays animation clips over its entity's hierarchy, taken
|
|
3699
|
+
* from `<pc-anim-clip>` children or from the enclosing `<pc-model>`'s own animations. The first
|
|
3700
|
+
* clip plays automatically, and the `clip` attribute switches between them. Must be a child of a
|
|
3701
|
+
* `<pc-entity>`, `<pc-model>` or `<pc-node>`.
|
|
3702
|
+
*
|
|
3569
3703
|
* @category Components
|
|
3570
3704
|
*/
|
|
3571
3705
|
class AnimComponentElement extends ComponentElement {
|
|
@@ -4184,7 +4318,9 @@
|
|
|
4184
4318
|
* named; in a multi-track source the track named `name` is chosen, falling back to the first
|
|
4185
4319
|
* with a warning. The element becomes ready once its resolved track is assigned.
|
|
4186
4320
|
*
|
|
4187
|
-
* @
|
|
4321
|
+
* @elementSummary The `<pc-anim-clip>` element declares one named animation clip on its parent
|
|
4322
|
+
* `<pc-anim>`, taken from the `asset` it names or, without one, from the enclosing `<pc-model>`'s
|
|
4323
|
+
* own animations. Must be a direct child of `<pc-anim>`.
|
|
4188
4324
|
*/
|
|
4189
4325
|
class AnimClipElement extends AsyncElement {
|
|
4190
4326
|
/**
|
|
@@ -4512,6 +4648,10 @@
|
|
|
4512
4648
|
*
|
|
4513
4649
|
* Engine component: {@link AudioListenerComponent} (`audiolistener`).
|
|
4514
4650
|
*
|
|
4651
|
+
* @elementSummary The `<pc-audio-listener>` element makes its entity the point from which
|
|
4652
|
+
* positional sounds are heard, typically the entity holding the `<pc-camera>`. Must be a child of a
|
|
4653
|
+
* `<pc-entity>`, `<pc-model>` or `<pc-node>`.
|
|
4654
|
+
*
|
|
4515
4655
|
* @category Components
|
|
4516
4656
|
*/
|
|
4517
4657
|
class AudioListenerComponentElement extends ComponentElement {
|
|
@@ -4541,6 +4681,11 @@
|
|
|
4541
4681
|
*
|
|
4542
4682
|
* Engine component: {@link ButtonComponent} (`button`).
|
|
4543
4683
|
*
|
|
4684
|
+
* @elementSummary The `<pc-button>` element makes its entity respond to pointer input, tinting or
|
|
4685
|
+
* swapping its image as the pointer hovers, presses and releases it. The entity also needs a
|
|
4686
|
+
* `<pc-element>` with `use-input` set. Must be a child of a `<pc-entity>`, `<pc-model>` or
|
|
4687
|
+
* `<pc-node>`.
|
|
4688
|
+
*
|
|
4544
4689
|
* @category Components
|
|
4545
4690
|
*/
|
|
4546
4691
|
class ButtonComponentElement extends ComponentElement {
|
|
@@ -4944,13 +5089,18 @@
|
|
|
4944
5089
|
*
|
|
4945
5090
|
* Engine component: {@link CameraComponent} (`camera`).
|
|
4946
5091
|
*
|
|
5092
|
+
* @elementSummary The `<pc-camera>` element renders the scene from its entity's transform, with
|
|
5093
|
+
* attributes for the projection, field of view, clip planes, clear color and tonemapping. Must be a
|
|
5094
|
+
* child of a `<pc-entity>`, `<pc-model>` or `<pc-node>`.
|
|
5095
|
+
*
|
|
4947
5096
|
* @category Components
|
|
4948
5097
|
*/
|
|
4949
5098
|
class CameraComponentElement extends ComponentElement {
|
|
4950
5099
|
_clearColor = new playcanvas.Color(0.75, 0.75, 0.75, 1);
|
|
4951
5100
|
_clearColorBuffer = true;
|
|
5101
|
+
_clearDepth = 1;
|
|
4952
5102
|
_clearDepthBuffer = true;
|
|
4953
|
-
_clearStencilBuffer =
|
|
5103
|
+
_clearStencilBuffer = true;
|
|
4954
5104
|
_cullFaces = true;
|
|
4955
5105
|
_farClip = 1000;
|
|
4956
5106
|
_flipFaces = false;
|
|
@@ -4973,6 +5123,7 @@
|
|
|
4973
5123
|
return {
|
|
4974
5124
|
clearColor: this._clearColor,
|
|
4975
5125
|
clearColorBuffer: this._clearColorBuffer,
|
|
5126
|
+
clearDepth: this._clearDepth,
|
|
4976
5127
|
clearDepthBuffer: this._clearDepthBuffer,
|
|
4977
5128
|
clearStencilBuffer: this._clearStencilBuffer,
|
|
4978
5129
|
cullFaces: this._cullFaces,
|
|
@@ -4991,9 +5142,31 @@
|
|
|
4991
5142
|
toneMapping: tonemaps.get(this._tonemap) ?? playcanvas.TONEMAP_NONE
|
|
4992
5143
|
};
|
|
4993
5144
|
}
|
|
4994
|
-
|
|
5145
|
+
/**
|
|
5146
|
+
* Whether immersive AR is available. Independent of {@link vrAvailable}: a device can offer
|
|
5147
|
+
* either mode without the other.
|
|
5148
|
+
* @returns Whether immersive AR is available.
|
|
5149
|
+
*/
|
|
5150
|
+
get arAvailable() {
|
|
5151
|
+
return this._available(playcanvas.XRTYPE_AR);
|
|
5152
|
+
}
|
|
5153
|
+
/**
|
|
5154
|
+
* Whether immersive VR is available. Independent of {@link arAvailable}: a device can offer
|
|
5155
|
+
* either mode without the other.
|
|
5156
|
+
* @returns Whether immersive VR is available.
|
|
5157
|
+
*/
|
|
5158
|
+
get vrAvailable() {
|
|
5159
|
+
return this._available(playcanvas.XRTYPE_VR);
|
|
5160
|
+
}
|
|
5161
|
+
/**
|
|
5162
|
+
* Whether one XR session type is available on this device.
|
|
5163
|
+
*
|
|
5164
|
+
* @param type - The XR session type to test.
|
|
5165
|
+
* @returns Whether that type is available.
|
|
5166
|
+
*/
|
|
5167
|
+
_available(type) {
|
|
4995
5168
|
const xrManager = this.component?.system.app.xr;
|
|
4996
|
-
return xrManager
|
|
5169
|
+
return Boolean(xrManager?.supported && xrManager.isAvailable(type));
|
|
4997
5170
|
}
|
|
4998
5171
|
/**
|
|
4999
5172
|
* Starts the camera in XR mode.
|
|
@@ -5001,11 +5174,13 @@
|
|
|
5001
5174
|
* @param space - The space to start the camera in.
|
|
5002
5175
|
*/
|
|
5003
5176
|
startXr(type, space) {
|
|
5004
|
-
|
|
5177
|
+
// Gated on the mode being started, not on XR in general: a device that offers only
|
|
5178
|
+
// one of the two would otherwise accept a session it cannot serve
|
|
5179
|
+
if (this.component && this._available(type)) {
|
|
5005
5180
|
this.component.startXr(type, space, {
|
|
5006
5181
|
callback: (err) => {
|
|
5007
5182
|
if (err)
|
|
5008
|
-
console.error(`WebXR
|
|
5183
|
+
console.error(`WebXR ${type} failed to start: ${err.message}`);
|
|
5009
5184
|
}
|
|
5010
5185
|
});
|
|
5011
5186
|
}
|
|
@@ -5059,6 +5234,23 @@
|
|
|
5059
5234
|
get clearColorBuffer() {
|
|
5060
5235
|
return this._clearColorBuffer;
|
|
5061
5236
|
}
|
|
5237
|
+
/**
|
|
5238
|
+
* Sets the depth value the depth buffer is cleared to. Defaults to 1.
|
|
5239
|
+
* @param value - The clear depth value.
|
|
5240
|
+
*/
|
|
5241
|
+
set clearDepth(value) {
|
|
5242
|
+
this._clearDepth = value;
|
|
5243
|
+
if (this.component) {
|
|
5244
|
+
this.component.clearDepth = value;
|
|
5245
|
+
}
|
|
5246
|
+
}
|
|
5247
|
+
/**
|
|
5248
|
+
* Gets the depth value the depth buffer is cleared to.
|
|
5249
|
+
* @returns The clear depth value.
|
|
5250
|
+
*/
|
|
5251
|
+
get clearDepth() {
|
|
5252
|
+
return this._clearDepth;
|
|
5253
|
+
}
|
|
5062
5254
|
/**
|
|
5063
5255
|
* Sets the clear depth buffer of the camera.
|
|
5064
5256
|
* @param value - The clear depth buffer.
|
|
@@ -5337,6 +5529,7 @@
|
|
|
5337
5529
|
...super.observedAttributes,
|
|
5338
5530
|
'clear-color',
|
|
5339
5531
|
'clear-color-buffer',
|
|
5532
|
+
'clear-depth',
|
|
5340
5533
|
'clear-depth-buffer',
|
|
5341
5534
|
'clear-stencil-buffer',
|
|
5342
5535
|
'cull-faces',
|
|
@@ -5364,11 +5557,14 @@
|
|
|
5364
5557
|
case 'clear-color-buffer':
|
|
5365
5558
|
this.clearColorBuffer = parseBool(newValue, true);
|
|
5366
5559
|
break;
|
|
5560
|
+
case 'clear-depth':
|
|
5561
|
+
this.clearDepth = parseNumber(newValue, 1, name);
|
|
5562
|
+
break;
|
|
5367
5563
|
case 'clear-depth-buffer':
|
|
5368
5564
|
this.clearDepthBuffer = parseBool(newValue, true);
|
|
5369
5565
|
break;
|
|
5370
5566
|
case 'clear-stencil-buffer':
|
|
5371
|
-
this.clearStencilBuffer = parseBool(newValue,
|
|
5567
|
+
this.clearStencilBuffer = parseBool(newValue, true);
|
|
5372
5568
|
break;
|
|
5373
5569
|
case 'cull-faces':
|
|
5374
5570
|
this.cullFaces = parseBool(newValue, true);
|
|
@@ -5431,6 +5627,10 @@
|
|
|
5431
5627
|
*
|
|
5432
5628
|
* Engine component: {@link CollisionComponent} (`collision`).
|
|
5433
5629
|
*
|
|
5630
|
+
* @elementSummary The `<pc-collision>` element gives its entity a collision shape — a box, sphere,
|
|
5631
|
+
* capsule, cone, cylinder or mesh — for the physics simulation to collide against. Pair it with a
|
|
5632
|
+
* `<pc-rigid-body>`. Must be a child of a `<pc-entity>`, `<pc-model>` or `<pc-node>`.
|
|
5633
|
+
*
|
|
5434
5634
|
* @category Components
|
|
5435
5635
|
*/
|
|
5436
5636
|
class CollisionComponentElement extends ComponentElement {
|
|
@@ -5621,6 +5821,10 @@
|
|
|
5621
5821
|
*
|
|
5622
5822
|
* Engine component: {@link ElementComponent} (`element`).
|
|
5623
5823
|
*
|
|
5824
|
+
* @elementSummary The `<pc-element>` element gives its entity a 2D UI rectangle inside a
|
|
5825
|
+
* `<pc-screen>` hierarchy, drawing an image, a line of text or nothing (`type="image"`, `"text"` or
|
|
5826
|
+
* `"group"`). Must be a child of a `<pc-entity>`, `<pc-model>` or `<pc-node>`.
|
|
5827
|
+
*
|
|
5624
5828
|
* @category Components
|
|
5625
5829
|
*/
|
|
5626
5830
|
class ElementComponentElement extends ComponentElement {
|
|
@@ -6305,6 +6509,11 @@
|
|
|
6305
6509
|
* a rigid body component; leaving `entity-b` empty constrains `entity-a` to a fixed point in world
|
|
6306
6510
|
* space. The underlying engine component is in alpha, so its API may change.
|
|
6307
6511
|
*
|
|
6512
|
+
* @elementSummary The `<pc-joint>` element constrains two rigid bodies to each other — a hinged
|
|
6513
|
+
* door, a swinging chain, a sliding drawer. Its entity's transform is the joint frame, and
|
|
6514
|
+
* `entity-a` and `entity-b` name the bodies. Must be a child of a `<pc-entity>`, `<pc-model>` or
|
|
6515
|
+
* `<pc-node>`.
|
|
6516
|
+
*
|
|
6308
6517
|
* @fires {CustomEvent} break - Fired when the impulse on the joint exceeds `break-impulse` and the
|
|
6309
6518
|
* constraint breaks. A broken joint no longer constrains its bodies; calling `refreshFrames()` on
|
|
6310
6519
|
* the underlying component re-attaches it. Bubbles and is composed.
|
|
@@ -7175,6 +7384,10 @@
|
|
|
7175
7384
|
*
|
|
7176
7385
|
* Engine component: {@link LayoutChildComponent} (`layoutchild`).
|
|
7177
7386
|
*
|
|
7387
|
+
* @elementSummary The `<pc-layout-child>` element controls how its entity is sized by the
|
|
7388
|
+
* `<pc-layout-group>` above it, through minimum and maximum sizes and fit proportions. Must be a
|
|
7389
|
+
* child of a `<pc-entity>`, `<pc-model>` or `<pc-node>`.
|
|
7390
|
+
*
|
|
7178
7391
|
* @category Components
|
|
7179
7392
|
*/
|
|
7180
7393
|
class LayoutChildComponentElement extends ComponentElement {
|
|
@@ -7387,6 +7600,10 @@
|
|
|
7387
7600
|
*
|
|
7388
7601
|
* Engine component: {@link LayoutGroupComponent} (`layoutgroup`).
|
|
7389
7602
|
*
|
|
7603
|
+
* @elementSummary The `<pc-layout-group>` element arranges its entity's children in a row or
|
|
7604
|
+
* column, with spacing, padding, alignment and fitting. Must be a child of a `<pc-entity>`,
|
|
7605
|
+
* `<pc-model>` or `<pc-node>`.
|
|
7606
|
+
*
|
|
7390
7607
|
* @category Components
|
|
7391
7608
|
*/
|
|
7392
7609
|
class LayoutGroupComponentElement extends ComponentElement {
|
|
@@ -7647,23 +7864,30 @@
|
|
|
7647
7864
|
*
|
|
7648
7865
|
* Engine component: {@link LightComponent} (`light`).
|
|
7649
7866
|
*
|
|
7867
|
+
* @elementSummary The `<pc-light>` element lights the scene from its entity — as a directional,
|
|
7868
|
+
* omni or spot light — with attributes for color, intensity, range and shadows. Must be a child of
|
|
7869
|
+
* a `<pc-entity>`, `<pc-model>` or `<pc-node>`.
|
|
7870
|
+
*
|
|
7650
7871
|
* @category Components
|
|
7651
7872
|
*/
|
|
7652
7873
|
class LightComponentElement extends ComponentElement {
|
|
7874
|
+
_cascadeBlend = 0;
|
|
7875
|
+
_cascadeDistribution = 0.5;
|
|
7653
7876
|
_castShadows = false;
|
|
7654
7877
|
_color = new playcanvas.Color(1, 1, 1);
|
|
7655
7878
|
_innerConeAngle = 40;
|
|
7656
7879
|
_intensity = 1;
|
|
7657
|
-
_normalOffsetBias = 0
|
|
7880
|
+
_normalOffsetBias = 0;
|
|
7881
|
+
_numCascades = 1;
|
|
7658
7882
|
_outerConeAngle = 45;
|
|
7659
7883
|
_range = 10;
|
|
7660
|
-
_shadowBias = 0.
|
|
7661
|
-
_shadowDistance =
|
|
7884
|
+
_shadowBias = 0.05;
|
|
7885
|
+
_shadowDistance = 40;
|
|
7662
7886
|
_shadowIntensity = 1;
|
|
7663
7887
|
_shadowResolution = 1024;
|
|
7664
7888
|
_shadowType = 'pcf3-32f';
|
|
7665
7889
|
_type = 'directional';
|
|
7666
|
-
_vsmBias = 0.
|
|
7890
|
+
_vsmBias = 0.0025;
|
|
7667
7891
|
_vsmBlurSize = 11;
|
|
7668
7892
|
_penumbraSize = 1;
|
|
7669
7893
|
_penumbraFalloff = 1;
|
|
@@ -7675,11 +7899,14 @@
|
|
|
7675
7899
|
}
|
|
7676
7900
|
getInitialComponentData() {
|
|
7677
7901
|
return {
|
|
7902
|
+
cascadeBlend: this._cascadeBlend,
|
|
7903
|
+
cascadeDistribution: this._cascadeDistribution,
|
|
7678
7904
|
castShadows: this._castShadows,
|
|
7679
7905
|
color: this._color,
|
|
7680
7906
|
innerConeAngle: this._innerConeAngle,
|
|
7681
7907
|
intensity: this._intensity,
|
|
7682
7908
|
normalOffsetBias: this._normalOffsetBias,
|
|
7909
|
+
numCascades: this._numCascades,
|
|
7683
7910
|
outerConeAngle: this._outerConeAngle,
|
|
7684
7911
|
penumbraFalloff: this._penumbraFalloff,
|
|
7685
7912
|
penumbraSize: this._penumbraSize,
|
|
@@ -7690,7 +7917,7 @@
|
|
|
7690
7917
|
shadowIntensity: this._shadowIntensity,
|
|
7691
7918
|
shadowResolution: this._shadowResolution,
|
|
7692
7919
|
shadowSamples: this._shadowSamples,
|
|
7693
|
-
shadowType: shadowTypes.get(this._shadowType),
|
|
7920
|
+
shadowType: shadowTypes.get(this._shadowType) ?? playcanvas.SHADOW_PCF3_32F,
|
|
7694
7921
|
type: this._type,
|
|
7695
7922
|
vsmBias: this._vsmBias,
|
|
7696
7923
|
vsmBlurSize: this._vsmBlurSize
|
|
@@ -7703,6 +7930,47 @@
|
|
|
7703
7930
|
get component() {
|
|
7704
7931
|
return super.component;
|
|
7705
7932
|
}
|
|
7933
|
+
/**
|
|
7934
|
+
* Sets the fraction of each shadow cascade that is blended into the next one, from 0 (no
|
|
7935
|
+
* blending) to 1, which applies only to `directional` lights with `num-cascades` greater than
|
|
7936
|
+
* 1. Defaults to 0.
|
|
7937
|
+
* @param value - The cascade blend factor.
|
|
7938
|
+
*/
|
|
7939
|
+
set cascadeBlend(value) {
|
|
7940
|
+
this._cascadeBlend = value;
|
|
7941
|
+
if (this.component) {
|
|
7942
|
+
this.component.cascadeBlend = value;
|
|
7943
|
+
}
|
|
7944
|
+
}
|
|
7945
|
+
/**
|
|
7946
|
+
* Gets the cascade blend factor of the light, from 0 (no blending) to 1, which applies only to
|
|
7947
|
+
* `directional` lights with `num-cascades` greater than 1.
|
|
7948
|
+
* @returns The cascade blend factor.
|
|
7949
|
+
*/
|
|
7950
|
+
get cascadeBlend() {
|
|
7951
|
+
return this._cascadeBlend;
|
|
7952
|
+
}
|
|
7953
|
+
/**
|
|
7954
|
+
* Sets the distribution of the camera frustum split between shadow cascades, from 0 (linear
|
|
7955
|
+
* split) to 1 (logarithmic split, concentrating shadow resolution near the camera), which
|
|
7956
|
+
* applies only to `directional` lights with `num-cascades` greater than 1. Defaults to 0.5.
|
|
7957
|
+
* @param value - The cascade distribution.
|
|
7958
|
+
*/
|
|
7959
|
+
set cascadeDistribution(value) {
|
|
7960
|
+
this._cascadeDistribution = value;
|
|
7961
|
+
if (this.component) {
|
|
7962
|
+
this.component.cascadeDistribution = value;
|
|
7963
|
+
}
|
|
7964
|
+
}
|
|
7965
|
+
/**
|
|
7966
|
+
* Gets the cascade distribution of the light, from 0 (linear split) to 1 (logarithmic split,
|
|
7967
|
+
* concentrating shadow resolution near the camera), which applies only to `directional` lights
|
|
7968
|
+
* with `num-cascades` greater than 1.
|
|
7969
|
+
* @returns The cascade distribution.
|
|
7970
|
+
*/
|
|
7971
|
+
get cascadeDistribution() {
|
|
7972
|
+
return this._cascadeDistribution;
|
|
7973
|
+
}
|
|
7706
7974
|
/**
|
|
7707
7975
|
* Sets the cast shadows flag of the light.
|
|
7708
7976
|
* @param value - The cast shadows flag.
|
|
@@ -7788,6 +8056,25 @@
|
|
|
7788
8056
|
get normalOffsetBias() {
|
|
7789
8057
|
return this._normalOffsetBias;
|
|
7790
8058
|
}
|
|
8059
|
+
/**
|
|
8060
|
+
* Sets the number of shadow cascades of the light, an integer from 1 (no cascades) to 4, which
|
|
8061
|
+
* applies only to `directional` lights. Defaults to 1.
|
|
8062
|
+
* @param value - The number of shadow cascades.
|
|
8063
|
+
*/
|
|
8064
|
+
set numCascades(value) {
|
|
8065
|
+
this._numCascades = value;
|
|
8066
|
+
if (this.component) {
|
|
8067
|
+
this.component.numCascades = value;
|
|
8068
|
+
}
|
|
8069
|
+
}
|
|
8070
|
+
/**
|
|
8071
|
+
* Gets the number of shadow cascades of the light, an integer from 1 (no cascades) to 4, which
|
|
8072
|
+
* applies only to `directional` lights.
|
|
8073
|
+
* @returns The number of shadow cascades.
|
|
8074
|
+
*/
|
|
8075
|
+
get numCascades() {
|
|
8076
|
+
return this._numCascades;
|
|
8077
|
+
}
|
|
7791
8078
|
/**
|
|
7792
8079
|
* Sets the outer cone angle of the light.
|
|
7793
8080
|
* @param value - The outer cone angle.
|
|
@@ -8040,11 +8327,14 @@
|
|
|
8040
8327
|
static get observedAttributes() {
|
|
8041
8328
|
return [
|
|
8042
8329
|
...super.observedAttributes,
|
|
8043
|
-
'
|
|
8330
|
+
'cascade-blend',
|
|
8331
|
+
'cascade-distribution',
|
|
8044
8332
|
'cast-shadows',
|
|
8045
|
-
'
|
|
8333
|
+
'color',
|
|
8046
8334
|
'inner-cone-angle',
|
|
8335
|
+
'intensity',
|
|
8047
8336
|
'normal-offset-bias',
|
|
8337
|
+
'num-cascades',
|
|
8048
8338
|
'outer-cone-angle',
|
|
8049
8339
|
'penumbra-falloff',
|
|
8050
8340
|
'penumbra-size',
|
|
@@ -8064,12 +8354,18 @@
|
|
|
8064
8354
|
attributeChangedCallback(name, _oldValue, newValue) {
|
|
8065
8355
|
super.attributeChangedCallback(name, _oldValue, newValue);
|
|
8066
8356
|
switch (name) {
|
|
8067
|
-
case '
|
|
8068
|
-
this.
|
|
8357
|
+
case 'cascade-blend':
|
|
8358
|
+
this.cascadeBlend = parseNumber(newValue, 0, name);
|
|
8359
|
+
break;
|
|
8360
|
+
case 'cascade-distribution':
|
|
8361
|
+
this.cascadeDistribution = parseNumber(newValue, 0.5, name);
|
|
8069
8362
|
break;
|
|
8070
8363
|
case 'cast-shadows':
|
|
8071
8364
|
this.castShadows = parseBool(newValue, false);
|
|
8072
8365
|
break;
|
|
8366
|
+
case 'color':
|
|
8367
|
+
this.color = parseColor(newValue, playcanvas.Color.WHITE, name);
|
|
8368
|
+
break;
|
|
8073
8369
|
case 'inner-cone-angle':
|
|
8074
8370
|
this.innerConeAngle = parseNumber(newValue, 40, name);
|
|
8075
8371
|
break;
|
|
@@ -8077,7 +8373,10 @@
|
|
|
8077
8373
|
this.intensity = parseNumber(newValue, 1, name);
|
|
8078
8374
|
break;
|
|
8079
8375
|
case 'normal-offset-bias':
|
|
8080
|
-
this.normalOffsetBias = parseNumber(newValue, 0
|
|
8376
|
+
this.normalOffsetBias = parseNumber(newValue, 0, name);
|
|
8377
|
+
break;
|
|
8378
|
+
case 'num-cascades':
|
|
8379
|
+
this.numCascades = parseNumber(newValue, 1, name);
|
|
8081
8380
|
break;
|
|
8082
8381
|
case 'outer-cone-angle':
|
|
8083
8382
|
this.outerConeAngle = parseNumber(newValue, 45, name);
|
|
@@ -8092,20 +8391,20 @@
|
|
|
8092
8391
|
this.range = parseNumber(newValue, 10, name);
|
|
8093
8392
|
break;
|
|
8094
8393
|
case 'shadow-bias':
|
|
8095
|
-
this.shadowBias = parseNumber(newValue, 0.
|
|
8096
|
-
break;
|
|
8097
|
-
case 'shadow-distance':
|
|
8098
|
-
this.shadowDistance = parseNumber(newValue, 16, name);
|
|
8394
|
+
this.shadowBias = parseNumber(newValue, 0.05, name);
|
|
8099
8395
|
break;
|
|
8100
8396
|
case 'shadow-blocker-samples':
|
|
8101
8397
|
this.shadowBlockerSamples = parseNumber(newValue, 16, name);
|
|
8102
8398
|
break;
|
|
8103
|
-
case 'shadow-
|
|
8104
|
-
this.
|
|
8399
|
+
case 'shadow-distance':
|
|
8400
|
+
this.shadowDistance = parseNumber(newValue, 40, name);
|
|
8105
8401
|
break;
|
|
8106
8402
|
case 'shadow-intensity':
|
|
8107
8403
|
this.shadowIntensity = parseNumber(newValue, 1, name);
|
|
8108
8404
|
break;
|
|
8405
|
+
case 'shadow-resolution':
|
|
8406
|
+
this.shadowResolution = parseNumber(newValue, 1024, name);
|
|
8407
|
+
break;
|
|
8109
8408
|
case 'shadow-samples':
|
|
8110
8409
|
this.shadowSamples = parseNumber(newValue, 16, name);
|
|
8111
8410
|
break;
|
|
@@ -8116,7 +8415,7 @@
|
|
|
8116
8415
|
this.type = parseEnum(newValue, ['directional', 'omni', 'spot'], 'directional', name);
|
|
8117
8416
|
break;
|
|
8118
8417
|
case 'vsm-bias':
|
|
8119
|
-
this.vsmBias = parseNumber(newValue, 0.
|
|
8418
|
+
this.vsmBias = parseNumber(newValue, 0.0025, name);
|
|
8120
8419
|
break;
|
|
8121
8420
|
case 'vsm-blur-size':
|
|
8122
8421
|
this.vsmBlurSize = parseNumber(newValue, 11, name);
|
|
@@ -8134,6 +8433,10 @@
|
|
|
8134
8433
|
*
|
|
8135
8434
|
* Engine component: {@link ParticleSystemComponent} (`particlesystem`).
|
|
8136
8435
|
*
|
|
8436
|
+
* @elementSummary The `<pc-particle-system>` element emits particles from its entity, with
|
|
8437
|
+
* attributes for the emitter's shape, rate, lifetime, textures and blending. Must be a child of a
|
|
8438
|
+
* `<pc-entity>`, `<pc-model>` or `<pc-node>`.
|
|
8439
|
+
*
|
|
8137
8440
|
* @category Components
|
|
8138
8441
|
*/
|
|
8139
8442
|
class ParticleSystemComponentElement extends ComponentElement {
|
|
@@ -8282,6 +8585,8 @@
|
|
|
8282
8585
|
['ao', playcanvas.SPECOCC_AO],
|
|
8283
8586
|
['gloss-dependent', playcanvas.SPECOCC_GLOSSDEPENDENT]
|
|
8284
8587
|
]);
|
|
8588
|
+
// The DITHER_* constants are strings whose values are exactly these names, so a parsed value is
|
|
8589
|
+
// assigned to the material unchanged rather than mapped through a table.
|
|
8285
8590
|
const opacityDithers = ['none', 'bayer8', 'bluenoise', 'ignnoise'];
|
|
8286
8591
|
const colorChannels = ['r', 'g', 'b', 'a', 'rgb'];
|
|
8287
8592
|
const scalarChannels = ['r', 'g', 'b', 'a'];
|
|
@@ -8318,6 +8623,10 @@
|
|
|
8318
8623
|
* The two aliases are documented here rather than on an accessor, because they resolve to the
|
|
8319
8624
|
* `gloss` properties and would otherwise inherit gloss's description - which reads inverted.
|
|
8320
8625
|
*
|
|
8626
|
+
* @elementSummary The `<pc-material>` element defines a physically based material, which
|
|
8627
|
+
* `<pc-render>` elements apply by naming its `id`. It is metal/rough by default, with `metalness`
|
|
8628
|
+
* starting at 0. Must be a direct child of `<pc-app>`.
|
|
8629
|
+
*
|
|
8321
8630
|
* @attribute {number} roughness - The roughness of the material, from 0 (shiny) to 1 (rough). An
|
|
8322
8631
|
* alias for `gloss` that also inverts it, so do not combine it with the `gloss` attributes.
|
|
8323
8632
|
* @attribute {string} roughness-map - The id of the `pc-asset` to use as the roughness map. An
|
|
@@ -10486,6 +10795,11 @@
|
|
|
10486
10795
|
*
|
|
10487
10796
|
* Engine component: {@link RenderComponent} (`render`).
|
|
10488
10797
|
*
|
|
10798
|
+
* @elementSummary The `<pc-render>` element renders one of the engine's built-in primitives at its
|
|
10799
|
+
* entity — box, sphere, capsule, cone, cylinder or plane — shaded by the `<pc-material>` its
|
|
10800
|
+
* `material` attribute names. For glTF content, use `<pc-model>` instead. Must be a child of a
|
|
10801
|
+
* `<pc-entity>`, `<pc-model>` or `<pc-node>`.
|
|
10802
|
+
*
|
|
10489
10803
|
* @category Components
|
|
10490
10804
|
*/
|
|
10491
10805
|
class RenderComponentElement extends ComponentElement {
|
|
@@ -10616,6 +10930,11 @@
|
|
|
10616
10930
|
*
|
|
10617
10931
|
* Engine component: {@link RigidBodyComponent} (`rigidbody`).
|
|
10618
10932
|
*
|
|
10933
|
+
* @elementSummary The `<pc-rigid-body>` element hands its entity to the physics simulation, with
|
|
10934
|
+
* attributes for its type, mass, friction and restitution. It needs a sibling `<pc-collision>` for
|
|
10935
|
+
* its shape, and `Ammo` loaded through `<pc-wasm>`. Must be a child of a `<pc-entity>`,
|
|
10936
|
+
* `<pc-model>` or `<pc-node>`.
|
|
10937
|
+
*
|
|
10619
10938
|
* @category Components
|
|
10620
10939
|
*/
|
|
10621
10940
|
class RigidBodyComponentElement extends ComponentElement {
|
|
@@ -10825,6 +11144,10 @@
|
|
|
10825
11144
|
*
|
|
10826
11145
|
* Engine component: {@link ScreenComponent} (`screen`).
|
|
10827
11146
|
*
|
|
11147
|
+
* @elementSummary The `<pc-screen>` element gives its entity a 2D space — in screen space or in the
|
|
11148
|
+
* world — that a hierarchy of `<pc-element>` descendants lays out inside. Must be a child of a
|
|
11149
|
+
* `<pc-entity>`, `<pc-model>` or `<pc-node>`.
|
|
11150
|
+
*
|
|
10828
11151
|
* @category Components
|
|
10829
11152
|
*/
|
|
10830
11153
|
class ScreenComponentElement extends ComponentElement {
|
|
@@ -10979,6 +11302,10 @@
|
|
|
10979
11302
|
*
|
|
10980
11303
|
* Engine component: {@link ScrollbarComponent} (`scrollbar`).
|
|
10981
11304
|
*
|
|
11305
|
+
* @elementSummary The `<pc-scrollbar>` element gives its entity a draggable handle reporting a
|
|
11306
|
+
* position from 0 to 1, which a `<pc-scroll-view>` references to scroll its content. Must be a
|
|
11307
|
+
* child of a `<pc-entity>`, `<pc-model>` or `<pc-node>`.
|
|
11308
|
+
*
|
|
10982
11309
|
* @category Components
|
|
10983
11310
|
*/
|
|
10984
11311
|
class ScrollbarComponentElement extends ComponentElement {
|
|
@@ -11120,6 +11447,10 @@
|
|
|
11120
11447
|
*
|
|
11121
11448
|
* Engine component: {@link ScrollViewComponent} (`scrollview`).
|
|
11122
11449
|
*
|
|
11450
|
+
* @elementSummary The `<pc-scroll-view>` element scrolls a larger content entity within a clipped
|
|
11451
|
+
* viewport at its entity, optionally driven by the `<pc-scrollbar>` elements it references. Must be
|
|
11452
|
+
* a child of a `<pc-entity>`, `<pc-model>` or `<pc-node>`.
|
|
11453
|
+
*
|
|
11123
11454
|
* @category Components
|
|
11124
11455
|
*/
|
|
11125
11456
|
class ScrollViewComponentElement extends ComponentElement {
|
|
@@ -11506,6 +11837,10 @@
|
|
|
11506
11837
|
* The element becomes ready once its script instance has been created by the parent
|
|
11507
11838
|
* `<pc-script>` element.
|
|
11508
11839
|
*
|
|
11840
|
+
* @elementSummary The `<pc-script-instance>` element attaches one script class, named by `name`, to
|
|
11841
|
+
* the entity of its parent `<pc-script>`. Its other attributes set script attributes of the same
|
|
11842
|
+
* name, and `attributes` takes a JSON object instead. Must be a direct child of `<pc-script>`.
|
|
11843
|
+
*
|
|
11509
11844
|
* @fires {CustomEvent} scriptattributeschange - Fired when the script's attributes change. The
|
|
11510
11845
|
* `detail` carries the new `attributes` object. Bubbles.
|
|
11511
11846
|
* @fires {CustomEvent} scriptenablechange - Fired when the script's enabled state changes. The
|
|
@@ -11850,6 +12185,9 @@
|
|
|
11850
12185
|
*
|
|
11851
12186
|
* Engine component: {@link ScriptComponent} (`script`).
|
|
11852
12187
|
*
|
|
12188
|
+
* @elementSummary The `<pc-script>` element holds the `<pc-script-instance>` children that attach
|
|
12189
|
+
* scripts to its entity. Must be a child of a `<pc-entity>`, `<pc-model>` or `<pc-node>`.
|
|
12190
|
+
*
|
|
11853
12191
|
* @category Components
|
|
11854
12192
|
*/
|
|
11855
12193
|
class ScriptComponentElement extends ComponentElement {
|
|
@@ -12299,6 +12637,10 @@
|
|
|
12299
12637
|
*
|
|
12300
12638
|
* Engine component: {@link SoundComponent} (`sound`).
|
|
12301
12639
|
*
|
|
12640
|
+
* @elementSummary The `<pc-sound>` element holds the `<pc-sound-slot>` children that play sounds at
|
|
12641
|
+
* its entity, along with the positional audio settings they share. Must be a child of a
|
|
12642
|
+
* `<pc-entity>`, `<pc-model>` or `<pc-node>`.
|
|
12643
|
+
*
|
|
12302
12644
|
* @category Components
|
|
12303
12645
|
*/
|
|
12304
12646
|
class SoundComponentElement extends ComponentElement {
|
|
@@ -12495,6 +12837,9 @@
|
|
|
12495
12837
|
* The SoundSlotElement interface provides properties and methods for manipulating
|
|
12496
12838
|
* `<pc-sound-slot>` elements. The SoundSlotElement interface also inherits the properties and
|
|
12497
12839
|
* methods of the {@link AsyncElement} interface.
|
|
12840
|
+
*
|
|
12841
|
+
* @elementSummary The `<pc-sound-slot>` element declares one named sound on its parent `<pc-sound>`
|
|
12842
|
+
* — its asset, volume, pitch, looping and autoplay. Must be a direct child of `<pc-sound>`.
|
|
12498
12843
|
*/
|
|
12499
12844
|
class SoundSlotElement extends AsyncElement {
|
|
12500
12845
|
_asset = '';
|
|
@@ -12776,6 +13121,10 @@
|
|
|
12776
13121
|
*
|
|
12777
13122
|
* Engine component: {@link GSplatComponent} (`gsplat`).
|
|
12778
13123
|
*
|
|
13124
|
+
* @elementSummary The `<pc-gsplat>` element renders the 3D Gaussian splats of a `gsplat` asset at
|
|
13125
|
+
* its entity, with attributes for shadow casting and level of detail. Must be a child of a
|
|
13126
|
+
* `<pc-entity>`, `<pc-model>` or `<pc-node>`.
|
|
13127
|
+
*
|
|
12779
13128
|
* @category Components
|
|
12780
13129
|
*/
|
|
12781
13130
|
class GSplatComponentElement extends ComponentElement {
|
|
@@ -13071,6 +13420,11 @@
|
|
|
13071
13420
|
* The pointer events below are dispatched by the containing `<pc-app>` element when the pointer
|
|
13072
13421
|
* intersects the bound node's geometry, exactly as for `<pc-entity>`.
|
|
13073
13422
|
*
|
|
13423
|
+
* @elementSummary The `<pc-node>` element binds to a node inside the hierarchy a `<pc-model>`
|
|
13424
|
+
* instantiated and declares overrides against it: a transform, an enabled state, tags, components
|
|
13425
|
+
* to add, or content to attach. Its `name` is a lookup, never a rename. Must be a descendant of
|
|
13426
|
+
* `<pc-model>`.
|
|
13427
|
+
*
|
|
13074
13428
|
* @attribute {string} name - The name of the node to bind, resolved within the nearest ancestor
|
|
13075
13429
|
* `pc-model` (or `pc-node`) once it has instantiated.
|
|
13076
13430
|
* @attribute {number} index - Which match to bind when `name` matches more than one node,
|
|
@@ -13095,11 +13449,17 @@
|
|
|
13095
13449
|
* node.
|
|
13096
13450
|
* @attribute {string} onpointerup - Script to run when a pointer button is released over the
|
|
13097
13451
|
* node.
|
|
13452
|
+
* @attribute {string} onclick - Script to run when the node is clicked: a primary pointer
|
|
13453
|
+
* button pressed and then released over it.
|
|
13098
13454
|
* @fires {PointerEvent} pointerenter - Fired when the pointer moves onto the node.
|
|
13099
13455
|
* @fires {PointerEvent} pointerleave - Fired when the pointer moves off the node.
|
|
13100
13456
|
* @fires {PointerEvent} pointermove - Fired when the pointer moves over the node.
|
|
13101
13457
|
* @fires {PointerEvent} pointerdown - Fired when a pointer button is pressed over the node.
|
|
13102
13458
|
* @fires {PointerEvent} pointerup - Fired when a pointer button is released over the node.
|
|
13459
|
+
* @fires {PointerEvent} click - Fired when a primary pointer button is pressed and then released
|
|
13460
|
+
* over the node. A press and release that picked different entities fires on their nearest
|
|
13461
|
+
* common ancestor instead, as in the DOM. `detail` carries the click count, so a double click
|
|
13462
|
+
* arrives as a click whose `detail` is 2.
|
|
13103
13463
|
*/
|
|
13104
13464
|
class NodeElement extends EntityBaseElement {
|
|
13105
13465
|
_name = '';
|
|
@@ -13749,7 +14109,7 @@
|
|
|
13749
14109
|
'rotation',
|
|
13750
14110
|
'scale',
|
|
13751
14111
|
'tags',
|
|
13752
|
-
...
|
|
14112
|
+
...EVENT_ATTRIBUTES
|
|
13753
14113
|
];
|
|
13754
14114
|
}
|
|
13755
14115
|
attributeChangedCallback(name, _oldValue, newValue) {
|
|
@@ -13799,6 +14159,7 @@
|
|
|
13799
14159
|
case 'onpointerdown':
|
|
13800
14160
|
case 'onpointerup':
|
|
13801
14161
|
case 'onpointermove':
|
|
14162
|
+
case 'onclick':
|
|
13802
14163
|
this._updateInlineHandler(name, newValue);
|
|
13803
14164
|
break;
|
|
13804
14165
|
}
|
|
@@ -13811,8 +14172,16 @@
|
|
|
13811
14172
|
* {@link https://developer.playcanvas.com/user-manual/web-components/tags/pc-scene/ | `<pc-scene>`} elements.
|
|
13812
14173
|
* The SceneElement interface also inherits the properties and methods of the
|
|
13813
14174
|
* {@link HTMLElement} interface.
|
|
14175
|
+
*
|
|
14176
|
+
* @elementSummary The `<pc-scene>` element holds the entity hierarchy the application renders,
|
|
14177
|
+
* along with the scene-wide fog, exposure and gravity settings. Must be a direct child of
|
|
14178
|
+
* `<pc-app>`.
|
|
13814
14179
|
*/
|
|
13815
14180
|
class SceneElement extends AsyncElement {
|
|
14181
|
+
/**
|
|
14182
|
+
* The exposure of the scene.
|
|
14183
|
+
*/
|
|
14184
|
+
_exposure = 1;
|
|
13816
14185
|
/**
|
|
13817
14186
|
* The fog type of the scene.
|
|
13818
14187
|
*/
|
|
@@ -13880,6 +14249,7 @@
|
|
|
13880
14249
|
}
|
|
13881
14250
|
_updateSceneSettings() {
|
|
13882
14251
|
if (this._scene) {
|
|
14252
|
+
this._scene.exposure = this._exposure;
|
|
13883
14253
|
this._scene.fog.type = this._fog;
|
|
13884
14254
|
this._scene.fog.color = this._fogColor;
|
|
13885
14255
|
this._scene.fog.density = this._fogDensity;
|
|
@@ -13898,6 +14268,24 @@
|
|
|
13898
14268
|
_applyGravity(value) {
|
|
13899
14269
|
this.closestApp?.app?.systems.rigidbody?.gravity.copy(value);
|
|
13900
14270
|
}
|
|
14271
|
+
/**
|
|
14272
|
+
* Sets the exposure of the scene, which tweaks the overall brightness of the rendered image.
|
|
14273
|
+
* Ignored if the scene is using physical units. Defaults to 1.
|
|
14274
|
+
* @param value - The exposure.
|
|
14275
|
+
*/
|
|
14276
|
+
set exposure(value) {
|
|
14277
|
+
this._exposure = value;
|
|
14278
|
+
if (this.scene) {
|
|
14279
|
+
this.scene.exposure = value;
|
|
14280
|
+
}
|
|
14281
|
+
}
|
|
14282
|
+
/**
|
|
14283
|
+
* Gets the exposure of the scene.
|
|
14284
|
+
* @returns The exposure.
|
|
14285
|
+
*/
|
|
14286
|
+
get exposure() {
|
|
14287
|
+
return this._exposure;
|
|
14288
|
+
}
|
|
13901
14289
|
/**
|
|
13902
14290
|
* Sets the fog type of the scene. Can be `none`, `linear`, `exp` or `exp2`. Defaults to
|
|
13903
14291
|
* `none`.
|
|
@@ -14002,10 +14390,13 @@
|
|
|
14002
14390
|
return this._gravity;
|
|
14003
14391
|
}
|
|
14004
14392
|
static get observedAttributes() {
|
|
14005
|
-
return ['fog', 'fog-color', 'fog-density', 'fog-start', 'fog-end', 'gravity'];
|
|
14393
|
+
return ['exposure', 'fog', 'fog-color', 'fog-density', 'fog-start', 'fog-end', 'gravity'];
|
|
14006
14394
|
}
|
|
14007
14395
|
attributeChangedCallback(name, _oldValue, newValue) {
|
|
14008
14396
|
switch (name) {
|
|
14397
|
+
case 'exposure':
|
|
14398
|
+
this.exposure = parseNumber(newValue, 1, name);
|
|
14399
|
+
break;
|
|
14009
14400
|
case 'fog':
|
|
14010
14401
|
this.fog = parseEnum(newValue, ['none', 'linear', 'exp', 'exp2'], 'none', name);
|
|
14011
14402
|
break;
|
|
@@ -14034,6 +14425,10 @@
|
|
|
14034
14425
|
* The SkyElement interface provides properties and methods for manipulating
|
|
14035
14426
|
* `<pc-sky>` elements. The SkyElement interface also inherits the properties and
|
|
14036
14427
|
* methods of the {@link HTMLElement} interface.
|
|
14428
|
+
*
|
|
14429
|
+
* @elementSummary The `<pc-sky>` element renders a skybox from a texture asset, projected as an
|
|
14430
|
+
* infinite background, a box or a dome, and optionally lights the scene from it. Must be a direct
|
|
14431
|
+
* child of `<pc-scene>`.
|
|
14037
14432
|
*/
|
|
14038
14433
|
class SkyElement extends AsyncElement {
|
|
14039
14434
|
_asset = '';
|