@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.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { basisInitialize, WasmModule, Vec3, Color, Vec4, Quat, Vec2, createGraphicsDevice, AppOptions, Keyboard, Mouse, ElementInput, AnimComponentSystem, AnimationComponentSystem, AudioListenerComponentSystem, ButtonComponentSystem, CameraComponentSystem, CollisionComponentSystem, ElementComponentSystem, GSplatComponentSystem, JointComponentSystem, LayoutChildComponentSystem, LayoutGroupComponentSystem, LightComponentSystem, ModelComponentSystem, ParticleSystemComponentSystem, RenderComponentSystem, RigidBodyComponentSystem, ScreenComponentSystem, ScriptComponentSystem, ScrollbarComponentSystem, ScrollViewComponentSystem, SoundComponentSystem, SpriteComponentSystem, ZoneComponentSystem, AnimClipHandler, AnimationHandler, AnimStateGraphHandler, AudioHandler, BinaryHandler, CssHandler, ContainerHandler, CubemapHandler, FolderHandler, FontHandler, GSplatHandler, HierarchyHandler, HtmlHandler, JsonHandler, MaterialHandler, ModelHandler, RenderHandler, ScriptHandler, SceneHandler, ShaderHandler, SpriteHandler, TemplateHandler, TextHandler, TextureAtlasHandler, TextureHandler, SoundManager, Lightmapper, BatchManager, XrManager, AppBase, FILLMODE_NONE, RESOLUTION_AUTO, Picker, MeshInstance, Entity, Asset, SPRITE_RENDERMODE_SIMPLE, FILTER_LINEAR_MIPMAP_LINEAR, FILTER_LINEAR, ADDRESS_REPEAT, SPRITE_RENDERMODE_SLICED, SPRITE_RENDERMODE_TILED, ADDRESS_CLAMP_TO_EDGE, ADDRESS_MIRRORED_REPEAT, FILTER_NEAREST, FILTER_NEAREST_MIPMAP_NEAREST, FILTER_LINEAR_MIPMAP_NEAREST, FILTER_NEAREST_MIPMAP_LINEAR, AnimTrack, ANIM_CONTROL_STATES, BUTTON_TRANSITION_MODE_TINT, BUTTON_TRANSITION_MODE_SPRITE_CHANGE, TONEMAP_NONE, PROJECTION_PERSPECTIVE, GAMMA_SRGB, GAMMA_NONE, XRTYPE_VR, TONEMAP_LINEAR, TONEMAP_FILMIC, TONEMAP_HEJL, TONEMAP_ACES, TONEMAP_ACES2, TONEMAP_NEUTRAL, PROJECTION_ORTHOGRAPHIC, ORIENTATION_HORIZONTAL, FITTING_NONE, FITTING_STRETCH, FITTING_SHRINK, FITTING_BOTH, ORIENTATION_VERTICAL, SHADOW_PCF3_32F, SHADOW_PCF1_16F, SHADOW_PCF1_32F, SHADOW_PCF3_16F, SHADOW_PCF5_16F, SHADOW_PCF5_32F, SHADOW_VSM_16F, SHADOW_VSM_32F, SHADOW_PCSS_32F, StandardMaterial, BLEND_NONE, CULLFACE_BACK, FRESNEL_SCHLICK, SPECOCC_AO, BLEND_NORMAL, BLEND_ADDITIVE, BLEND_ADDITIVEALPHA, BLEND_PREMULTIPLIED, BLEND_MULTIPLICATIVE, BLEND_MULTIPLICATIVE2X, BLEND_SCREEN, BLEND_MIN, BLEND_MAX, BLEND_SUBTRACTIVE, CULLFACE_NONE, CULLFACE_FRONT, CULLFACE_FRONTANDBACK, FRESNEL_NONE, SPECOCC_NONE, SPECOCC_GLOSSDEPENDENT, SCALEMODE_NONE, SCALEMODE_BLEND, SCROLL_MODE_BOUNCE, SCROLLBAR_VISIBILITY_SHOW_WHEN_REQUIRED, SCROLLBAR_VISIBILITY_SHOW_ALWAYS, SCROLL_MODE_CLAMP, SCROLL_MODE_INFINITE, EnvLighting, LAYERID_SKYBOX } from 'playcanvas';
|
|
1
|
+
import { basisInitialize, WasmModule, Vec3, Color, Vec4, Quat, Vec2, createGraphicsDevice, AppOptions, Keyboard, Mouse, ElementInput, AnimComponentSystem, AnimationComponentSystem, AudioListenerComponentSystem, ButtonComponentSystem, CameraComponentSystem, CollisionComponentSystem, ElementComponentSystem, GSplatComponentSystem, JointComponentSystem, LayoutChildComponentSystem, LayoutGroupComponentSystem, LightComponentSystem, ModelComponentSystem, ParticleSystemComponentSystem, RenderComponentSystem, RigidBodyComponentSystem, ScreenComponentSystem, ScriptComponentSystem, ScrollbarComponentSystem, ScrollViewComponentSystem, SoundComponentSystem, SpriteComponentSystem, ZoneComponentSystem, AnimClipHandler, AnimationHandler, AnimStateGraphHandler, AudioHandler, BinaryHandler, CssHandler, ContainerHandler, CubemapHandler, FolderHandler, FontHandler, GSplatHandler, HierarchyHandler, HtmlHandler, JsonHandler, MaterialHandler, ModelHandler, RenderHandler, ScriptHandler, SceneHandler, ShaderHandler, SpriteHandler, TemplateHandler, TextHandler, TextureAtlasHandler, TextureHandler, SoundManager, Lightmapper, BatchManager, XrManager, AppBase, FILLMODE_NONE, RESOLUTION_AUTO, Picker, MeshInstance, Entity, Asset, SPRITE_RENDERMODE_SIMPLE, FILTER_LINEAR_MIPMAP_LINEAR, FILTER_LINEAR, ADDRESS_REPEAT, SPRITE_RENDERMODE_SLICED, SPRITE_RENDERMODE_TILED, ADDRESS_CLAMP_TO_EDGE, ADDRESS_MIRRORED_REPEAT, FILTER_NEAREST, FILTER_NEAREST_MIPMAP_NEAREST, FILTER_LINEAR_MIPMAP_NEAREST, FILTER_NEAREST_MIPMAP_LINEAR, AnimTrack, ANIM_CONTROL_STATES, BUTTON_TRANSITION_MODE_TINT, BUTTON_TRANSITION_MODE_SPRITE_CHANGE, TONEMAP_NONE, PROJECTION_PERSPECTIVE, GAMMA_SRGB, GAMMA_NONE, XRTYPE_AR, XRTYPE_VR, TONEMAP_LINEAR, TONEMAP_FILMIC, TONEMAP_HEJL, TONEMAP_ACES, TONEMAP_ACES2, TONEMAP_NEUTRAL, PROJECTION_ORTHOGRAPHIC, ORIENTATION_HORIZONTAL, FITTING_NONE, FITTING_STRETCH, FITTING_SHRINK, FITTING_BOTH, ORIENTATION_VERTICAL, SHADOW_PCF3_32F, SHADOW_PCF1_16F, SHADOW_PCF1_32F, SHADOW_PCF3_16F, SHADOW_PCF5_16F, SHADOW_PCF5_32F, SHADOW_VSM_16F, SHADOW_VSM_32F, SHADOW_PCSS_32F, StandardMaterial, BLEND_NONE, CULLFACE_BACK, FRESNEL_SCHLICK, SPECOCC_AO, BLEND_NORMAL, BLEND_ADDITIVE, BLEND_ADDITIVEALPHA, BLEND_PREMULTIPLIED, BLEND_MULTIPLICATIVE, BLEND_MULTIPLICATIVE2X, BLEND_SCREEN, BLEND_MIN, BLEND_MAX, BLEND_SUBTRACTIVE, CULLFACE_NONE, CULLFACE_FRONT, CULLFACE_FRONTANDBACK, FRESNEL_NONE, SPECOCC_NONE, SPECOCC_GLOSSDEPENDENT, SCALEMODE_NONE, SCALEMODE_BLEND, SCROLL_MODE_BOUNCE, SCROLLBAR_VISIBILITY_SHOW_WHEN_REQUIRED, SCROLLBAR_VISIBILITY_SHOW_ALWAYS, SCROLL_MODE_CLAMP, SCROLL_MODE_INFINITE, EnvLighting, LAYERID_SKYBOX } from 'playcanvas';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Base class for all PlayCanvas Web Components that initialize asynchronously.
|
|
@@ -121,6 +121,10 @@ async function whenReady(target) {
|
|
|
121
121
|
* A `<pc-wasm>` without a `name` warns and never becomes ready; a containing `<pc-app>` still
|
|
122
122
|
* boots.
|
|
123
123
|
*
|
|
124
|
+
* @elementSummary The `<pc-wasm>` element loads a WebAssembly module the engine needs before the
|
|
125
|
+
* application starts — `Ammo` for physics, `Basis` or `DracoDecoderModule` for compressed assets.
|
|
126
|
+
* Must be a direct child of `<pc-app>`.
|
|
127
|
+
*
|
|
124
128
|
* @attribute {string} name - The name of the WebAssembly module to configure, e.g. `Basis` or
|
|
125
129
|
* `Ammo`.
|
|
126
130
|
* @attribute {string} glue - The URL of the module's glue script.
|
|
@@ -173,6 +177,136 @@ class WasmElement extends AsyncElement {
|
|
|
173
177
|
}
|
|
174
178
|
customElements.define('pc-wasm', WasmElement);
|
|
175
179
|
|
|
180
|
+
/**
|
|
181
|
+
* The event types the containing `<pc-app>` synthesizes on entity-fronting elements via picking:
|
|
182
|
+
* the `pointer*` events, plus `click` — which concludes a primary-button press and release, and
|
|
183
|
+
* is delivered as a `PointerEvent` exactly as modern browsers deliver native clicks.
|
|
184
|
+
* @internal
|
|
185
|
+
*/
|
|
186
|
+
const SYNTHESIZED_EVENTS = [
|
|
187
|
+
'pointerenter',
|
|
188
|
+
'pointerleave',
|
|
189
|
+
'pointerdown',
|
|
190
|
+
'pointerup',
|
|
191
|
+
'pointermove',
|
|
192
|
+
'click'
|
|
193
|
+
];
|
|
194
|
+
const SYNTHESIZED_EVENT_SET = new Set(SYNTHESIZED_EVENTS);
|
|
195
|
+
/**
|
|
196
|
+
* The attribute names of the inline event handlers (`onpointerdown`, `onclick`, ...), shared by
|
|
197
|
+
* every element that fronts an engine entity. Spread into `observedAttributes` by subclasses.
|
|
198
|
+
* @internal
|
|
199
|
+
*/
|
|
200
|
+
const EVENT_ATTRIBUTES = SYNTHESIZED_EVENTS.map((type) => `on${type}`);
|
|
201
|
+
/**
|
|
202
|
+
* The base class for elements that front an engine {@link Entity}: `<pc-entity>` and
|
|
203
|
+
* `<pc-model>`, which create one, and `<pc-node>`, which binds to one inside a model's
|
|
204
|
+
* instantiated hierarchy. It carries what all of them need — the `entity` contract, registration
|
|
205
|
+
* with the owning application (which joins picked scene nodes back to elements by identity,
|
|
206
|
+
* never by name), and the pointer listener bookkeeping that lets the application lazily attach
|
|
207
|
+
* its canvas handlers.
|
|
208
|
+
*/
|
|
209
|
+
class EntityBaseElement extends AsyncElement {
|
|
210
|
+
_entity = null;
|
|
211
|
+
/**
|
|
212
|
+
* The application element this entity is registered with, cached at registration time so the
|
|
213
|
+
* entity can be unregistered even once this element has left the DOM.
|
|
214
|
+
*/
|
|
215
|
+
_appElement = null;
|
|
216
|
+
/**
|
|
217
|
+
* The event listeners registered on the element, by type.
|
|
218
|
+
*/
|
|
219
|
+
_listeners = {};
|
|
220
|
+
/**
|
|
221
|
+
* The event types for which an inline handler attribute (`onpointerdown`, `onclick`, ...)
|
|
222
|
+
* is currently present.
|
|
223
|
+
*/
|
|
224
|
+
_inlineHandlerTypes = new Set();
|
|
225
|
+
/**
|
|
226
|
+
* The PlayCanvas entity instance. `null` until the element is ready, and again once the
|
|
227
|
+
* entity is gone — await {@link whenReady} or the element's `ready()` promise before
|
|
228
|
+
* accessing it.
|
|
229
|
+
* @returns The entity instance, or `null`.
|
|
230
|
+
*/
|
|
231
|
+
get entity() {
|
|
232
|
+
return this._entity;
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Registers `entity` as this element's backing entity with the owning application, which
|
|
236
|
+
* joins engine nodes back to elements by identity (never by name).
|
|
237
|
+
*
|
|
238
|
+
* @param entity - The entity to register.
|
|
239
|
+
*/
|
|
240
|
+
_registerEntity(entity) {
|
|
241
|
+
this._appElement = this.closestApp;
|
|
242
|
+
this._appElement?._registerEntityElement(entity, this);
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Removes the registration for `entity`.
|
|
246
|
+
*
|
|
247
|
+
* @param entity - The entity to unregister.
|
|
248
|
+
*/
|
|
249
|
+
_unregisterEntity(entity) {
|
|
250
|
+
this._appElement?._unregisterEntityElement(entity);
|
|
251
|
+
this._appElement = null;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Tracks whether an inline handler attribute is present. The browser itself compiles and
|
|
255
|
+
* runs these attributes — they are standard `GlobalEventHandlers`, so setting one replaces
|
|
256
|
+
* the previous handler and removing it removes the handler, exactly like `onclick` on any
|
|
257
|
+
* HTML element. But because they bypass {@link EventTarget.addEventListener}, the connect/disconnect
|
|
258
|
+
* bookkeeping that lets the application lazily attach its canvas pointer handlers must be
|
|
259
|
+
* kept in sync here.
|
|
260
|
+
*
|
|
261
|
+
* @param name - The attribute name (e.g. 'onpointerdown').
|
|
262
|
+
* @param value - The attribute value, or `null` when the attribute has been removed.
|
|
263
|
+
*/
|
|
264
|
+
_updateInlineHandler(name, value) {
|
|
265
|
+
const type = name.substring(2);
|
|
266
|
+
const had = this._inlineHandlerTypes.has(type);
|
|
267
|
+
const has = value !== null;
|
|
268
|
+
if (has && !had) {
|
|
269
|
+
this._inlineHandlerTypes.add(type);
|
|
270
|
+
this.dispatchEvent(new CustomEvent(`${type}:connect`, { bubbles: true }));
|
|
271
|
+
}
|
|
272
|
+
else if (!has && had) {
|
|
273
|
+
this._inlineHandlerTypes.delete(type);
|
|
274
|
+
this.dispatchEvent(new CustomEvent(`${type}:disconnect`, { bubbles: true }));
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
addEventListener(type, listener, options) {
|
|
278
|
+
if (!this._listeners[type]) {
|
|
279
|
+
this._listeners[type] = [];
|
|
280
|
+
}
|
|
281
|
+
this._listeners[type].push(listener);
|
|
282
|
+
super.addEventListener(type, listener, options);
|
|
283
|
+
if (SYNTHESIZED_EVENT_SET.has(type)) {
|
|
284
|
+
this.dispatchEvent(new CustomEvent(`${type}:connect`, { bubbles: true }));
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
removeEventListener(type, listener, options) {
|
|
288
|
+
if (this._listeners[type]) {
|
|
289
|
+
this._listeners[type] = this._listeners[type].filter((l) => l !== listener);
|
|
290
|
+
}
|
|
291
|
+
super.removeEventListener(type, listener, options);
|
|
292
|
+
if (SYNTHESIZED_EVENT_SET.has(type)) {
|
|
293
|
+
this.dispatchEvent(new CustomEvent(`${type}:disconnect`, { bubbles: true }));
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Whether the element has a listener for an event type, registered either with
|
|
298
|
+
* {@link EventTarget.addEventListener} or with the matching inline handler attribute. Read by the
|
|
299
|
+
* containing `<pc-app>` element to gate event synthesis.
|
|
300
|
+
*
|
|
301
|
+
* @param type - The event type.
|
|
302
|
+
* @returns Whether a listener is registered.
|
|
303
|
+
* @internal
|
|
304
|
+
*/
|
|
305
|
+
_hasListeners(type) {
|
|
306
|
+
return Boolean(this._listeners[type]?.length) || this._inlineHandlerTypes.has(type);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
176
310
|
/** Covers the 0.2s opacity transition; jsdom never fires transitionend, so removal is timed. */
|
|
177
311
|
const REMOVAL_DELAY_MS = 250;
|
|
178
312
|
/**
|
|
@@ -726,14 +860,51 @@ const getEntity = (ref) => {
|
|
|
726
860
|
return element?.entity ?? null;
|
|
727
861
|
};
|
|
728
862
|
|
|
729
|
-
/** The pointer event types the application synthesizes on `<pc-entity>` elements via picking. */
|
|
730
|
-
const pointerEventTypes = ['pointermove', 'pointerdown', 'pointerup', 'pointerenter', 'pointerleave'];
|
|
731
863
|
/**
|
|
732
864
|
* The event types whose listeners make an element a hover target. Hover resolution walks past
|
|
733
865
|
* elements listening for none of them, so a silent element never swallows an ancestor's
|
|
734
866
|
* enter/leave pair.
|
|
735
867
|
*/
|
|
736
868
|
const hoverEventTypes = ['pointerenter', 'pointerleave', 'pointermove'];
|
|
869
|
+
/**
|
|
870
|
+
* The canvas listeners each synthesized event type is driven by. Enter and leave are derived
|
|
871
|
+
* from move picks. A click is concluded from the down/up pair, with pointercancel discarding a
|
|
872
|
+
* press the browser takes back (for example a touch that becomes a scroll).
|
|
873
|
+
*/
|
|
874
|
+
const canvasEventsFor = {
|
|
875
|
+
pointermove: ['pointermove'],
|
|
876
|
+
pointerenter: ['pointermove'],
|
|
877
|
+
pointerleave: ['pointermove'],
|
|
878
|
+
pointerdown: ['pointerdown'],
|
|
879
|
+
pointerup: ['pointerup'],
|
|
880
|
+
click: ['pointerdown', 'pointerup', 'pointercancel']
|
|
881
|
+
};
|
|
882
|
+
/**
|
|
883
|
+
* How long after a click a further click on the same target still raises the click count that
|
|
884
|
+
* `detail` carries, approximating the platform's double-click time.
|
|
885
|
+
*/
|
|
886
|
+
const CLICK_CHAIN_MS = 500;
|
|
887
|
+
/**
|
|
888
|
+
* Finds the nearest common inclusive ancestor of two picked nodes - the node a click belongs to
|
|
889
|
+
* when the press and the release picked different geometry, exactly as the DOM assigns a click
|
|
890
|
+
* whose down and up have different targets.
|
|
891
|
+
*
|
|
892
|
+
* @param a - The node the press picked, or `null`.
|
|
893
|
+
* @param b - The node the release picked, or `null`.
|
|
894
|
+
* @returns The nearest common inclusive ancestor, or `null` when there is none.
|
|
895
|
+
*/
|
|
896
|
+
const commonAncestor = (a, b) => {
|
|
897
|
+
const ancestors = new Set();
|
|
898
|
+
for (let node = a; node !== null; node = node.parent) {
|
|
899
|
+
ancestors.add(node);
|
|
900
|
+
}
|
|
901
|
+
for (let node = b; node !== null; node = node.parent) {
|
|
902
|
+
if (ancestors.has(node)) {
|
|
903
|
+
return node;
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
return null;
|
|
907
|
+
};
|
|
737
908
|
/**
|
|
738
909
|
* Gives `pc-app` the sizing contract of a replaced element (`<video>`, `<img>`): a block-level
|
|
739
910
|
* box that the page's CSS sizes, defaulting to the canvas's own 300x150 intrinsic size, with the
|
|
@@ -762,6 +933,10 @@ const ensureBaseStyles = () => {
|
|
|
762
933
|
* tracked live via a ResizeObserver — so the element can be embedded at any size, resized by
|
|
763
934
|
* its container, or made fullscreen with ordinary CSS such as `width: 100vw; height: 100dvh`.
|
|
764
935
|
*
|
|
936
|
+
* @elementSummary The `<pc-app>` element creates a PlayCanvas application and the canvas it renders
|
|
937
|
+
* into, and is the root of every scene. It holds the `<pc-asset>`, `<pc-material>`, `<pc-wasm>` and
|
|
938
|
+
* `<pc-scene>` elements, and the page's CSS sizes it, as it would a `<video>`.
|
|
939
|
+
*
|
|
765
940
|
* @fires {ProgressEvent} progress - Fired while the application preloads its assets. `loaded` and
|
|
766
941
|
* `total` are asset counts, not bytes, and an asset that fails to load still counts as loaded.
|
|
767
942
|
* Fired at least once per boot, and the final event always has `loaded` equal to `total`. Does
|
|
@@ -814,21 +989,30 @@ class AppElement extends AsyncElement {
|
|
|
814
989
|
*/
|
|
815
990
|
_entityElements = new Map();
|
|
816
991
|
_picker = null;
|
|
817
|
-
_hasPointerListeners = {
|
|
818
|
-
pointerenter: false,
|
|
819
|
-
pointerleave: false,
|
|
820
|
-
pointerdown: false,
|
|
821
|
-
pointerup: false,
|
|
822
|
-
pointermove: false
|
|
823
|
-
};
|
|
824
992
|
_hoveredEntity = null;
|
|
825
993
|
// Identifies the newest in-flight hover pick, so out-of-order results can be discarded
|
|
826
994
|
_pickToken = 0;
|
|
827
995
|
_pointerHandlers = {
|
|
828
996
|
pointermove: null,
|
|
829
997
|
pointerdown: null,
|
|
830
|
-
pointerup: null
|
|
998
|
+
pointerup: null,
|
|
999
|
+
pointercancel: null
|
|
831
1000
|
};
|
|
1001
|
+
/**
|
|
1002
|
+
* The pick of each pointer's primary-button press, keyed by pointerId and kept while a click
|
|
1003
|
+
* may still conclude it. The promise is stored rather than its result, so a release can
|
|
1004
|
+
* await a press pick that has not resolved yet. Entries are removed by the matching
|
|
1005
|
+
* pointerup or pointercancel, and only ever stored while some element listens for click -
|
|
1006
|
+
* which is also what keeps those two canvas listeners attached.
|
|
1007
|
+
*/
|
|
1008
|
+
_downPicks = new Map();
|
|
1009
|
+
/** Whether any element in the tree listens for click. Maintained by _syncCanvasListeners. */
|
|
1010
|
+
_clickListened = false;
|
|
1011
|
+
/**
|
|
1012
|
+
* The previous click's target, time and count, for chaining successive clicks into the
|
|
1013
|
+
* click count that `detail` carries. `null` until a click has fired.
|
|
1014
|
+
*/
|
|
1015
|
+
_lastClick = null;
|
|
832
1016
|
_app = null;
|
|
833
1017
|
_loadProgress = 0;
|
|
834
1018
|
/**
|
|
@@ -863,12 +1047,12 @@ class AppElement extends AsyncElement {
|
|
|
863
1047
|
*/
|
|
864
1048
|
constructor() {
|
|
865
1049
|
super();
|
|
866
|
-
// Track
|
|
867
|
-
// Registered once here rather than on every boot - the
|
|
868
|
-
// canvas, and a re-booted element must not stack a second set.
|
|
869
|
-
|
|
870
|
-
this.addEventListener(`${type}:connect`, () => this.
|
|
871
|
-
this.addEventListener(`${type}:disconnect`, () => this.
|
|
1050
|
+
// Track listeners for the synthesized events being added to and removed from descendant
|
|
1051
|
+
// entities. Registered once here rather than on every boot - the sync no-ops while there
|
|
1052
|
+
// is no canvas, and a re-booted element must not stack a second set.
|
|
1053
|
+
SYNTHESIZED_EVENTS.forEach((type) => {
|
|
1054
|
+
this.addEventListener(`${type}:connect`, () => this._syncCanvasListeners());
|
|
1055
|
+
this.addEventListener(`${type}:disconnect`, () => this._syncCanvasListeners());
|
|
872
1056
|
});
|
|
873
1057
|
}
|
|
874
1058
|
async connectedCallback() {
|
|
@@ -1186,15 +1370,13 @@ class AppElement extends AsyncElement {
|
|
|
1186
1370
|
this._pointerHandlers.pointermove = listener(this._onPointerMove);
|
|
1187
1371
|
this._pointerHandlers.pointerdown = listener(this._onPointerDown);
|
|
1188
1372
|
this._pointerHandlers.pointerup = listener(this._onPointerUp);
|
|
1189
|
-
|
|
1190
|
-
|
|
1373
|
+
this._pointerHandlers.pointercancel = (event) => {
|
|
1374
|
+
this._downPicks.delete(event.pointerId);
|
|
1375
|
+
};
|
|
1376
|
+
// Attach canvas listeners for element listeners registered before this boot (e.g.
|
|
1377
|
+
// handlers created from inline attributes when their elements were first upgraded, or
|
|
1191
1378
|
// listeners carried over from before a re-boot)
|
|
1192
|
-
|
|
1193
|
-
const anyListeners = Array.from(this.querySelectorAll('pc-entity, pc-model, pc-node')).some((entity) => entity._hasListeners(type));
|
|
1194
|
-
if (anyListeners) {
|
|
1195
|
-
this._onPointerListenerAdded(type);
|
|
1196
|
-
}
|
|
1197
|
-
});
|
|
1379
|
+
this._syncCanvasListeners();
|
|
1198
1380
|
}
|
|
1199
1381
|
_pickerDestroy() {
|
|
1200
1382
|
if (this._canvas) {
|
|
@@ -1209,15 +1391,12 @@ class AppElement extends AsyncElement {
|
|
|
1209
1391
|
this._pointerHandlers = {
|
|
1210
1392
|
pointermove: null,
|
|
1211
1393
|
pointerdown: null,
|
|
1212
|
-
pointerup: null
|
|
1213
|
-
|
|
1214
|
-
this._hasPointerListeners = {
|
|
1215
|
-
pointerenter: false,
|
|
1216
|
-
pointerleave: false,
|
|
1217
|
-
pointerdown: false,
|
|
1218
|
-
pointerup: false,
|
|
1219
|
-
pointermove: false
|
|
1394
|
+
pointerup: null,
|
|
1395
|
+
pointercancel: null
|
|
1220
1396
|
};
|
|
1397
|
+
this._downPicks.clear();
|
|
1398
|
+
this._clickListened = false;
|
|
1399
|
+
this._lastClick = null;
|
|
1221
1400
|
}
|
|
1222
1401
|
/**
|
|
1223
1402
|
* Registers the element that fronts an entity. Called by EntityElement when it creates its
|
|
@@ -1423,7 +1602,15 @@ class AppElement extends AsyncElement {
|
|
|
1423
1602
|
async _onPointerDown(event) {
|
|
1424
1603
|
if (!this._picker || !this.app)
|
|
1425
1604
|
return;
|
|
1426
|
-
const
|
|
1605
|
+
const pick = this._pickNode(event);
|
|
1606
|
+
// A click concludes on the matching pointerup, which needs to know what the press
|
|
1607
|
+
// picked. Primary button only - the only button a click can conclude from - and only
|
|
1608
|
+
// while click is listened for, since it is the click mapping that keeps the pointerup
|
|
1609
|
+
// and pointercancel listeners attached to clean the entry up again.
|
|
1610
|
+
if (this._clickListened && event.button === 0) {
|
|
1611
|
+
this._downPicks.set(event.pointerId, pick);
|
|
1612
|
+
}
|
|
1613
|
+
const node = await pick;
|
|
1427
1614
|
if (!this._picker)
|
|
1428
1615
|
return; // the element disconnected while the pick was in flight
|
|
1429
1616
|
const entityElement = this._elementWithListener(node, 'pointerdown');
|
|
@@ -1434,6 +1621,10 @@ class AppElement extends AsyncElement {
|
|
|
1434
1621
|
async _onPointerUp(event) {
|
|
1435
1622
|
if (!this._picker || !this.app)
|
|
1436
1623
|
return;
|
|
1624
|
+
// The press pick this release may conclude as a click. Claimed synchronously, so the
|
|
1625
|
+
// entry is gone before any other event for this pointer can be handled.
|
|
1626
|
+
const downPick = this._downPicks.get(event.pointerId);
|
|
1627
|
+
this._downPicks.delete(event.pointerId);
|
|
1437
1628
|
const node = await this._pickNode(event);
|
|
1438
1629
|
if (!this._picker)
|
|
1439
1630
|
return; // the element disconnected while the pick was in flight
|
|
@@ -1441,30 +1632,60 @@ class AppElement extends AsyncElement {
|
|
|
1441
1632
|
if (entityElement) {
|
|
1442
1633
|
entityElement.dispatchEvent(new PointerEvent('pointerup', event));
|
|
1443
1634
|
}
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1635
|
+
// A click fires where the DOM fires it: at the nearest common inclusive ancestor of
|
|
1636
|
+
// what the press and the release picked, for the primary button only. The press pick
|
|
1637
|
+
// may still be in flight - a quick tap resolves in pick order, not event order.
|
|
1638
|
+
if (!downPick || event.button !== 0)
|
|
1639
|
+
return;
|
|
1640
|
+
const downNode = await downPick;
|
|
1641
|
+
if (!this._picker)
|
|
1642
|
+
return;
|
|
1643
|
+
const clickElement = this._elementWithListener(commonAncestor(downNode, node), 'click');
|
|
1644
|
+
if (clickElement) {
|
|
1645
|
+
const click = new PointerEvent('click', event);
|
|
1646
|
+
// The init above copied pointerup's `detail`, which the Pointer Events spec fixes
|
|
1647
|
+
// at 0 - but click is exempt: its detail is the click count, chained here as the
|
|
1648
|
+
// platform chains it (same target, within the double-click window). Overridden
|
|
1649
|
+
// with defineProperty because an event instance used as an init dict cannot have
|
|
1650
|
+
// single fields replaced.
|
|
1651
|
+
const time = performance.now();
|
|
1652
|
+
const last = this._lastClick;
|
|
1653
|
+
const count = last && last.element === clickElement && time - last.time <= CLICK_CHAIN_MS ? last.count + 1 : 1;
|
|
1654
|
+
this._lastClick = { element: clickElement, time, count };
|
|
1655
|
+
Object.defineProperty(click, 'detail', { value: count });
|
|
1656
|
+
clickElement.dispatchEvent(click);
|
|
1657
|
+
}
|
|
1658
|
+
}
|
|
1659
|
+
/**
|
|
1660
|
+
* Attaches exactly the canvas listeners the tree's current element listeners need, and
|
|
1661
|
+
* detaches the rest. Recomputed whenever a listener connects or disconnects anywhere under
|
|
1662
|
+
* this element: several synthesized types can need the same canvas listener (enter, leave
|
|
1663
|
+
* and move all ride the move pick; click rides the down/up pair), so one type's removal
|
|
1664
|
+
* must not detach a listener another type still uses. Re-attaching an attached listener is
|
|
1665
|
+
* a no-op by EventTarget semantics, so no attach state is kept.
|
|
1666
|
+
*/
|
|
1667
|
+
_syncCanvasListeners() {
|
|
1668
|
+
const canvas = this._canvas;
|
|
1669
|
+
if (!canvas)
|
|
1670
|
+
return; // not booted yet: _pickerCreate syncs once the handlers exist
|
|
1671
|
+
const elements = Array.from(this.querySelectorAll('pc-entity, pc-model, pc-node'));
|
|
1672
|
+
const needed = new Set();
|
|
1673
|
+
for (const type of SYNTHESIZED_EVENTS) {
|
|
1674
|
+
if (elements.some((element) => element._hasListeners(type))) {
|
|
1675
|
+
canvasEventsFor[type].forEach((canvasType) => needed.add(canvasType));
|
|
1454
1676
|
}
|
|
1455
1677
|
}
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
? this._pointerHandlers.pointermove
|
|
1463
|
-
: this._pointerHandlers[type];
|
|
1464
|
-
if (handler) {
|
|
1465
|
-
this._canvas.removeEventListener(type === 'pointerenter' || type === 'pointerleave' ? 'pointermove' : type, handler);
|
|
1678
|
+
this._clickListened = elements.some((element) => element._hasListeners('click'));
|
|
1679
|
+
Object.entries(this._pointerHandlers).forEach(([canvasType, handler]) => {
|
|
1680
|
+
if (!handler)
|
|
1681
|
+
return;
|
|
1682
|
+
if (needed.has(canvasType)) {
|
|
1683
|
+
canvas.addEventListener(canvasType, handler);
|
|
1466
1684
|
}
|
|
1467
|
-
|
|
1685
|
+
else {
|
|
1686
|
+
canvas.removeEventListener(canvasType, handler);
|
|
1687
|
+
}
|
|
1688
|
+
});
|
|
1468
1689
|
}
|
|
1469
1690
|
/**
|
|
1470
1691
|
* Warns that a graphics option was written too late to have any effect. These options are read
|
|
@@ -1633,126 +1854,6 @@ class AppElement extends AsyncElement {
|
|
|
1633
1854
|
}
|
|
1634
1855
|
customElements.define('pc-app', AppElement);
|
|
1635
1856
|
|
|
1636
|
-
/**
|
|
1637
|
-
* The attribute names of the inline `onpointer*` event handlers, shared by every element that
|
|
1638
|
-
* fronts an engine entity. Spread into `observedAttributes` by subclasses.
|
|
1639
|
-
* @internal
|
|
1640
|
-
*/
|
|
1641
|
-
const POINTER_ATTRIBUTES = [
|
|
1642
|
-
'onpointerenter',
|
|
1643
|
-
'onpointerleave',
|
|
1644
|
-
'onpointerdown',
|
|
1645
|
-
'onpointerup',
|
|
1646
|
-
'onpointermove'
|
|
1647
|
-
];
|
|
1648
|
-
/**
|
|
1649
|
-
* The base class for elements that front an engine {@link Entity}: `<pc-entity>` and
|
|
1650
|
-
* `<pc-model>`, which create one, and `<pc-node>`, which binds to one inside a model's
|
|
1651
|
-
* instantiated hierarchy. It carries what all of them need — the `entity` contract, registration
|
|
1652
|
-
* with the owning application (which joins picked scene nodes back to elements by identity,
|
|
1653
|
-
* never by name), and the pointer listener bookkeeping that lets the application lazily attach
|
|
1654
|
-
* its canvas handlers.
|
|
1655
|
-
*/
|
|
1656
|
-
class EntityBaseElement extends AsyncElement {
|
|
1657
|
-
_entity = null;
|
|
1658
|
-
/**
|
|
1659
|
-
* The application element this entity is registered with, cached at registration time so the
|
|
1660
|
-
* entity can be unregistered even once this element has left the DOM.
|
|
1661
|
-
*/
|
|
1662
|
-
_appElement = null;
|
|
1663
|
-
/**
|
|
1664
|
-
* The pointer event listeners for the entity.
|
|
1665
|
-
*/
|
|
1666
|
-
_listeners = {};
|
|
1667
|
-
/**
|
|
1668
|
-
* The event types for which an inline `onpointer*` attribute is currently present.
|
|
1669
|
-
*/
|
|
1670
|
-
_inlineHandlerTypes = new Set();
|
|
1671
|
-
/**
|
|
1672
|
-
* The PlayCanvas entity instance. `null` until the element is ready, and again once the
|
|
1673
|
-
* entity is gone — await {@link whenReady} or the element's `ready()` promise before
|
|
1674
|
-
* accessing it.
|
|
1675
|
-
* @returns The entity instance, or `null`.
|
|
1676
|
-
*/
|
|
1677
|
-
get entity() {
|
|
1678
|
-
return this._entity;
|
|
1679
|
-
}
|
|
1680
|
-
/**
|
|
1681
|
-
* Registers `entity` as this element's backing entity with the owning application, which
|
|
1682
|
-
* joins engine nodes back to elements by identity (never by name).
|
|
1683
|
-
*
|
|
1684
|
-
* @param entity - The entity to register.
|
|
1685
|
-
*/
|
|
1686
|
-
_registerEntity(entity) {
|
|
1687
|
-
this._appElement = this.closestApp;
|
|
1688
|
-
this._appElement?._registerEntityElement(entity, this);
|
|
1689
|
-
}
|
|
1690
|
-
/**
|
|
1691
|
-
* Removes the registration for `entity`.
|
|
1692
|
-
*
|
|
1693
|
-
* @param entity - The entity to unregister.
|
|
1694
|
-
*/
|
|
1695
|
-
_unregisterEntity(entity) {
|
|
1696
|
-
this._appElement?._unregisterEntityElement(entity);
|
|
1697
|
-
this._appElement = null;
|
|
1698
|
-
}
|
|
1699
|
-
/**
|
|
1700
|
-
* Tracks whether an inline `onpointer*` attribute is present. The browser itself compiles and
|
|
1701
|
-
* runs these attributes — they are standard `GlobalEventHandlers`, so setting one replaces
|
|
1702
|
-
* the previous handler and removing it removes the handler, exactly like `onclick` on any
|
|
1703
|
-
* HTML element. But because they bypass {@link addEventListener}, the connect/disconnect
|
|
1704
|
-
* bookkeeping that lets the application lazily attach its canvas pointer handlers must be
|
|
1705
|
-
* kept in sync here.
|
|
1706
|
-
*
|
|
1707
|
-
* @param name - The attribute name (e.g. 'onpointerdown').
|
|
1708
|
-
* @param value - The attribute value, or `null` when the attribute has been removed.
|
|
1709
|
-
*/
|
|
1710
|
-
_updateInlineHandler(name, value) {
|
|
1711
|
-
const type = name.substring(2);
|
|
1712
|
-
const had = this._inlineHandlerTypes.has(type);
|
|
1713
|
-
const has = value !== null;
|
|
1714
|
-
if (has && !had) {
|
|
1715
|
-
this._inlineHandlerTypes.add(type);
|
|
1716
|
-
this.dispatchEvent(new CustomEvent(`${type}:connect`, { bubbles: true }));
|
|
1717
|
-
}
|
|
1718
|
-
else if (!has && had) {
|
|
1719
|
-
this._inlineHandlerTypes.delete(type);
|
|
1720
|
-
this.dispatchEvent(new CustomEvent(`${type}:disconnect`, { bubbles: true }));
|
|
1721
|
-
}
|
|
1722
|
-
}
|
|
1723
|
-
addEventListener(type, listener, options) {
|
|
1724
|
-
if (!this._listeners[type]) {
|
|
1725
|
-
this._listeners[type] = [];
|
|
1726
|
-
}
|
|
1727
|
-
this._listeners[type].push(listener);
|
|
1728
|
-
super.addEventListener(type, listener, options);
|
|
1729
|
-
if (type.startsWith('pointer')) {
|
|
1730
|
-
this.dispatchEvent(new CustomEvent(`${type}:connect`, { bubbles: true }));
|
|
1731
|
-
}
|
|
1732
|
-
}
|
|
1733
|
-
removeEventListener(type, listener, options) {
|
|
1734
|
-
if (this._listeners[type]) {
|
|
1735
|
-
this._listeners[type] = this._listeners[type].filter((l) => l !== listener);
|
|
1736
|
-
}
|
|
1737
|
-
super.removeEventListener(type, listener, options);
|
|
1738
|
-
if (type.startsWith('pointer')) {
|
|
1739
|
-
this.dispatchEvent(new CustomEvent(`${type}:disconnect`, { bubbles: true }));
|
|
1740
|
-
}
|
|
1741
|
-
}
|
|
1742
|
-
/**
|
|
1743
|
-
* Whether the element has a listener for an event type, registered either with
|
|
1744
|
-
* {@link addEventListener} or with the matching inline `onpointer*` attribute. Read by the
|
|
1745
|
-
* containing `<pc-app>` element to gate pointer event synthesis.
|
|
1746
|
-
*
|
|
1747
|
-
* @param type - The event type.
|
|
1748
|
-
* @returns Whether a listener is registered.
|
|
1749
|
-
* @internal
|
|
1750
|
-
*/
|
|
1751
|
-
_hasListeners(type) {
|
|
1752
|
-
return Boolean(this._listeners[type]?.length) || this._inlineHandlerTypes.has(type);
|
|
1753
|
-
}
|
|
1754
|
-
}
|
|
1755
|
-
|
|
1756
1857
|
/**
|
|
1757
1858
|
* Creates and parents the entities of every descendant entity-owning element of `root`, in two
|
|
1758
1859
|
* passes so that no parent's existence depends on document order. Called wherever a subtree could
|
|
@@ -1810,7 +1911,7 @@ class EntityOwnerElement extends EntityBaseElement {
|
|
|
1810
1911
|
*/
|
|
1811
1912
|
_tags = [];
|
|
1812
1913
|
/**
|
|
1813
|
-
* Whether the hierarchy has been built for this entity — set once
|
|
1914
|
+
* Whether the hierarchy has been built for this entity — set once `_buildHierarchy` has
|
|
1814
1915
|
* parented it. Read by subclasses that gate work on the entity being in the scene graph.
|
|
1815
1916
|
*/
|
|
1816
1917
|
_built = false;
|
|
@@ -1899,7 +2000,7 @@ class EntityOwnerElement extends EntityBaseElement {
|
|
|
1899
2000
|
this._onBuilt();
|
|
1900
2001
|
}
|
|
1901
2002
|
/**
|
|
1902
|
-
* Called by
|
|
2003
|
+
* Called by `_buildHierarchy` once the backing entity has been parented — exactly once
|
|
1903
2004
|
* per build cycle. The default announces readiness, which is what a parented `<pc-entity>`
|
|
1904
2005
|
* means; `<pc-model>` overrides it to start loading content instead, because its readiness
|
|
1905
2006
|
* tracks the content settling rather than the host entering the scene graph.
|
|
@@ -2020,8 +2121,13 @@ class EntityOwnerElement extends EntityBaseElement {
|
|
|
2020
2121
|
*
|
|
2021
2122
|
* The pointer events below are dispatched by the containing `<pc-app>` element when the pointer
|
|
2022
2123
|
* intersects this entity's geometry. They are only generated while the entity has a listener for
|
|
2023
|
-
* them, registered either with {@link addEventListener} or with the matching inline
|
|
2024
|
-
* attribute.
|
|
2124
|
+
* them, registered either with {@link EventTarget.addEventListener} or with the matching inline
|
|
2125
|
+
* attribute (`onpointerdown`, `onclick`, ...).
|
|
2126
|
+
*
|
|
2127
|
+
* @elementSummary The `<pc-entity>` element creates an entity: a named, transformable node of the
|
|
2128
|
+
* scene hierarchy, and the host for component elements such as `<pc-camera>`, `<pc-light>` and
|
|
2129
|
+
* `<pc-render>`. Place it in the `<pc-scene>`, or nest it under another `<pc-entity>`, a
|
|
2130
|
+
* `<pc-model>` or a `<pc-node>` to parent it there.
|
|
2025
2131
|
*
|
|
2026
2132
|
* @attribute {boolean} enabled - The enabled state of the entity.
|
|
2027
2133
|
* @attribute {string} name - The name of the entity.
|
|
@@ -2036,11 +2142,17 @@ class EntityOwnerElement extends EntityBaseElement {
|
|
|
2036
2142
|
* entity.
|
|
2037
2143
|
* @attribute {string} onpointerup - Script to run when a pointer button is released over the
|
|
2038
2144
|
* entity.
|
|
2145
|
+
* @attribute {string} onclick - Script to run when the entity is clicked: a primary pointer
|
|
2146
|
+
* button pressed and then released over it.
|
|
2039
2147
|
* @fires {PointerEvent} pointerenter - Fired when the pointer moves onto the entity.
|
|
2040
2148
|
* @fires {PointerEvent} pointerleave - Fired when the pointer moves off the entity.
|
|
2041
2149
|
* @fires {PointerEvent} pointermove - Fired when the pointer moves over the entity.
|
|
2042
2150
|
* @fires {PointerEvent} pointerdown - Fired when a pointer button is pressed over the entity.
|
|
2043
2151
|
* @fires {PointerEvent} pointerup - Fired when a pointer button is released over the entity.
|
|
2152
|
+
* @fires {PointerEvent} click - Fired when a primary pointer button is pressed and then released
|
|
2153
|
+
* over the entity. A press and release that picked different entities fires on their nearest
|
|
2154
|
+
* common ancestor instead, as in the DOM. `detail` carries the click count, so a double click
|
|
2155
|
+
* arrives as a click whose `detail` is 2.
|
|
2044
2156
|
*/
|
|
2045
2157
|
class EntityElement extends EntityOwnerElement {
|
|
2046
2158
|
connectedCallback() {
|
|
@@ -2075,7 +2187,7 @@ class EntityElement extends EntityOwnerElement {
|
|
|
2075
2187
|
this._entity?.destroy();
|
|
2076
2188
|
}
|
|
2077
2189
|
static get observedAttributes() {
|
|
2078
|
-
return ['enabled', 'name', 'position', 'rotation', 'scale', 'tags', ...
|
|
2190
|
+
return ['enabled', 'name', 'position', 'rotation', 'scale', 'tags', ...EVENT_ATTRIBUTES];
|
|
2079
2191
|
}
|
|
2080
2192
|
attributeChangedCallback(name, _oldValue, newValue) {
|
|
2081
2193
|
switch (name) {
|
|
@@ -2102,6 +2214,7 @@ class EntityElement extends EntityOwnerElement {
|
|
|
2102
2214
|
case 'onpointerdown':
|
|
2103
2215
|
case 'onpointerup':
|
|
2104
2216
|
case 'onpointermove':
|
|
2217
|
+
case 'onclick':
|
|
2105
2218
|
this._updateInlineHandler(name, newValue);
|
|
2106
2219
|
break;
|
|
2107
2220
|
}
|
|
@@ -2403,6 +2516,10 @@ const processBufferView = (gltfBuffer, buffers, continuation) => {
|
|
|
2403
2516
|
* Apart from `lazy` and the texture options, these attributes are read once when the asset is
|
|
2404
2517
|
* created, so changing them later has no effect.
|
|
2405
2518
|
*
|
|
2519
|
+
* @elementSummary The `<pc-asset>` element declares an asset for the application to load — a model,
|
|
2520
|
+
* texture, font, sound, script or JSON file — under an `id` that other elements reference. Must be
|
|
2521
|
+
* a direct child of `<pc-app>`.
|
|
2522
|
+
*
|
|
2406
2523
|
* @attribute {string} id - The identifier used to reference the asset from other elements.
|
|
2407
2524
|
* @attribute {string} src - The URL of the asset to load.
|
|
2408
2525
|
* @attribute {string} type - The asset type. Inferred from the `src` file extension when omitted.
|
|
@@ -3029,6 +3146,11 @@ const formatHierarchy = (root, counts) => {
|
|
|
3029
3146
|
* intersects the model's geometry, exactly as for `<pc-entity>` — a hit on a content node that no
|
|
3030
3147
|
* `pc-node` fronts resolves to this element.
|
|
3031
3148
|
*
|
|
3149
|
+
* @elementSummary The `<pc-model>` element instantiates a 3D model from a container asset
|
|
3150
|
+
* (typically a GLB) beneath an entity of its own, so the element's transform and tags place the
|
|
3151
|
+
* instance in the scene. Its `<pc-node>` children override what the asset authored. Place it in the
|
|
3152
|
+
* `<pc-scene>`, or nest it under a `<pc-entity>`, another `<pc-model>` or a `<pc-node>`.
|
|
3153
|
+
*
|
|
3032
3154
|
* @attribute {boolean} enabled - The enabled state of the model.
|
|
3033
3155
|
* @attribute {string} name - The name of the model.
|
|
3034
3156
|
* @attribute {string} position - The position of the model.
|
|
@@ -3042,11 +3164,17 @@ const formatHierarchy = (root, counts) => {
|
|
|
3042
3164
|
* model.
|
|
3043
3165
|
* @attribute {string} onpointerup - Script to run when a pointer button is released over the
|
|
3044
3166
|
* model.
|
|
3167
|
+
* @attribute {string} onclick - Script to run when the model is clicked: a primary pointer
|
|
3168
|
+
* button pressed and then released over it.
|
|
3045
3169
|
* @fires {PointerEvent} pointerenter - Fired when the pointer moves onto the model.
|
|
3046
3170
|
* @fires {PointerEvent} pointerleave - Fired when the pointer moves off the model.
|
|
3047
3171
|
* @fires {PointerEvent} pointermove - Fired when the pointer moves over the model.
|
|
3048
3172
|
* @fires {PointerEvent} pointerdown - Fired when a pointer button is pressed over the model.
|
|
3049
3173
|
* @fires {PointerEvent} pointerup - Fired when a pointer button is released over the model.
|
|
3174
|
+
* @fires {PointerEvent} click - Fired when a primary pointer button is pressed and then released
|
|
3175
|
+
* over the model. A press and release that picked different entities fires on their nearest
|
|
3176
|
+
* common ancestor instead, as in the DOM. `detail` carries the click count, so a double click
|
|
3177
|
+
* arrives as a click whose `detail` is 2.
|
|
3050
3178
|
* @fires {Event} load - Fired each time a container asset finishes instantiating, including
|
|
3051
3179
|
* re-instantiation after `asset` changes. Does not bubble — listen on this element, or use a
|
|
3052
3180
|
* capture-phase listener on an ancestor.
|
|
@@ -3295,7 +3423,7 @@ class ModelElement extends EntityOwnerElement {
|
|
|
3295
3423
|
return this._asset;
|
|
3296
3424
|
}
|
|
3297
3425
|
static get observedAttributes() {
|
|
3298
|
-
return ['asset', 'enabled', 'name', 'position', 'rotation', 'scale', 'tags', ...
|
|
3426
|
+
return ['asset', 'enabled', 'name', 'position', 'rotation', 'scale', 'tags', ...EVENT_ATTRIBUTES];
|
|
3299
3427
|
}
|
|
3300
3428
|
attributeChangedCallback(name, _oldValue, newValue) {
|
|
3301
3429
|
switch (name) {
|
|
@@ -3325,6 +3453,7 @@ class ModelElement extends EntityOwnerElement {
|
|
|
3325
3453
|
case 'onpointerdown':
|
|
3326
3454
|
case 'onpointerup':
|
|
3327
3455
|
case 'onpointermove':
|
|
3456
|
+
case 'onclick':
|
|
3328
3457
|
this._updateInlineHandler(name, newValue);
|
|
3329
3458
|
break;
|
|
3330
3459
|
}
|
|
@@ -3562,6 +3691,11 @@ class ComponentElement extends AsyncElement {
|
|
|
3562
3691
|
*
|
|
3563
3692
|
* Engine component: {@link AnimComponent} (`anim`).
|
|
3564
3693
|
*
|
|
3694
|
+
* @elementSummary The `<pc-anim>` element plays animation clips over its entity's hierarchy, taken
|
|
3695
|
+
* from `<pc-anim-clip>` children or from the enclosing `<pc-model>`'s own animations. The first
|
|
3696
|
+
* clip plays automatically, and the `clip` attribute switches between them. Must be a child of a
|
|
3697
|
+
* `<pc-entity>`, `<pc-model>` or `<pc-node>`.
|
|
3698
|
+
*
|
|
3565
3699
|
* @category Components
|
|
3566
3700
|
*/
|
|
3567
3701
|
class AnimComponentElement extends ComponentElement {
|
|
@@ -4180,7 +4314,9 @@ customElements.define('pc-anim', AnimComponentElement);
|
|
|
4180
4314
|
* named; in a multi-track source the track named `name` is chosen, falling back to the first
|
|
4181
4315
|
* with a warning. The element becomes ready once its resolved track is assigned.
|
|
4182
4316
|
*
|
|
4183
|
-
* @
|
|
4317
|
+
* @elementSummary The `<pc-anim-clip>` element declares one named animation clip on its parent
|
|
4318
|
+
* `<pc-anim>`, taken from the `asset` it names or, without one, from the enclosing `<pc-model>`'s
|
|
4319
|
+
* own animations. Must be a direct child of `<pc-anim>`.
|
|
4184
4320
|
*/
|
|
4185
4321
|
class AnimClipElement extends AsyncElement {
|
|
4186
4322
|
/**
|
|
@@ -4508,6 +4644,10 @@ customElements.define('pc-anim-clip', AnimClipElement);
|
|
|
4508
4644
|
*
|
|
4509
4645
|
* Engine component: {@link AudioListenerComponent} (`audiolistener`).
|
|
4510
4646
|
*
|
|
4647
|
+
* @elementSummary The `<pc-audio-listener>` element makes its entity the point from which
|
|
4648
|
+
* positional sounds are heard, typically the entity holding the `<pc-camera>`. Must be a child of a
|
|
4649
|
+
* `<pc-entity>`, `<pc-model>` or `<pc-node>`.
|
|
4650
|
+
*
|
|
4511
4651
|
* @category Components
|
|
4512
4652
|
*/
|
|
4513
4653
|
class AudioListenerComponentElement extends ComponentElement {
|
|
@@ -4537,6 +4677,11 @@ const transitionModes = new Map([
|
|
|
4537
4677
|
*
|
|
4538
4678
|
* Engine component: {@link ButtonComponent} (`button`).
|
|
4539
4679
|
*
|
|
4680
|
+
* @elementSummary The `<pc-button>` element makes its entity respond to pointer input, tinting or
|
|
4681
|
+
* swapping its image as the pointer hovers, presses and releases it. The entity also needs a
|
|
4682
|
+
* `<pc-element>` with `use-input` set. Must be a child of a `<pc-entity>`, `<pc-model>` or
|
|
4683
|
+
* `<pc-node>`.
|
|
4684
|
+
*
|
|
4540
4685
|
* @category Components
|
|
4541
4686
|
*/
|
|
4542
4687
|
class ButtonComponentElement extends ComponentElement {
|
|
@@ -4940,13 +5085,18 @@ const tonemaps = new Map([
|
|
|
4940
5085
|
*
|
|
4941
5086
|
* Engine component: {@link CameraComponent} (`camera`).
|
|
4942
5087
|
*
|
|
5088
|
+
* @elementSummary The `<pc-camera>` element renders the scene from its entity's transform, with
|
|
5089
|
+
* attributes for the projection, field of view, clip planes, clear color and tonemapping. Must be a
|
|
5090
|
+
* child of a `<pc-entity>`, `<pc-model>` or `<pc-node>`.
|
|
5091
|
+
*
|
|
4943
5092
|
* @category Components
|
|
4944
5093
|
*/
|
|
4945
5094
|
class CameraComponentElement extends ComponentElement {
|
|
4946
5095
|
_clearColor = new Color(0.75, 0.75, 0.75, 1);
|
|
4947
5096
|
_clearColorBuffer = true;
|
|
5097
|
+
_clearDepth = 1;
|
|
4948
5098
|
_clearDepthBuffer = true;
|
|
4949
|
-
_clearStencilBuffer =
|
|
5099
|
+
_clearStencilBuffer = true;
|
|
4950
5100
|
_cullFaces = true;
|
|
4951
5101
|
_farClip = 1000;
|
|
4952
5102
|
_flipFaces = false;
|
|
@@ -4969,6 +5119,7 @@ class CameraComponentElement extends ComponentElement {
|
|
|
4969
5119
|
return {
|
|
4970
5120
|
clearColor: this._clearColor,
|
|
4971
5121
|
clearColorBuffer: this._clearColorBuffer,
|
|
5122
|
+
clearDepth: this._clearDepth,
|
|
4972
5123
|
clearDepthBuffer: this._clearDepthBuffer,
|
|
4973
5124
|
clearStencilBuffer: this._clearStencilBuffer,
|
|
4974
5125
|
cullFaces: this._cullFaces,
|
|
@@ -4987,9 +5138,31 @@ class CameraComponentElement extends ComponentElement {
|
|
|
4987
5138
|
toneMapping: tonemaps.get(this._tonemap) ?? TONEMAP_NONE
|
|
4988
5139
|
};
|
|
4989
5140
|
}
|
|
4990
|
-
|
|
5141
|
+
/**
|
|
5142
|
+
* Whether immersive AR is available. Independent of {@link vrAvailable}: a device can offer
|
|
5143
|
+
* either mode without the other.
|
|
5144
|
+
* @returns Whether immersive AR is available.
|
|
5145
|
+
*/
|
|
5146
|
+
get arAvailable() {
|
|
5147
|
+
return this._available(XRTYPE_AR);
|
|
5148
|
+
}
|
|
5149
|
+
/**
|
|
5150
|
+
* Whether immersive VR is available. Independent of {@link arAvailable}: a device can offer
|
|
5151
|
+
* either mode without the other.
|
|
5152
|
+
* @returns Whether immersive VR is available.
|
|
5153
|
+
*/
|
|
5154
|
+
get vrAvailable() {
|
|
5155
|
+
return this._available(XRTYPE_VR);
|
|
5156
|
+
}
|
|
5157
|
+
/**
|
|
5158
|
+
* Whether one XR session type is available on this device.
|
|
5159
|
+
*
|
|
5160
|
+
* @param type - The XR session type to test.
|
|
5161
|
+
* @returns Whether that type is available.
|
|
5162
|
+
*/
|
|
5163
|
+
_available(type) {
|
|
4991
5164
|
const xrManager = this.component?.system.app.xr;
|
|
4992
|
-
return xrManager
|
|
5165
|
+
return Boolean(xrManager?.supported && xrManager.isAvailable(type));
|
|
4993
5166
|
}
|
|
4994
5167
|
/**
|
|
4995
5168
|
* Starts the camera in XR mode.
|
|
@@ -4997,11 +5170,13 @@ class CameraComponentElement extends ComponentElement {
|
|
|
4997
5170
|
* @param space - The space to start the camera in.
|
|
4998
5171
|
*/
|
|
4999
5172
|
startXr(type, space) {
|
|
5000
|
-
|
|
5173
|
+
// Gated on the mode being started, not on XR in general: a device that offers only
|
|
5174
|
+
// one of the two would otherwise accept a session it cannot serve
|
|
5175
|
+
if (this.component && this._available(type)) {
|
|
5001
5176
|
this.component.startXr(type, space, {
|
|
5002
5177
|
callback: (err) => {
|
|
5003
5178
|
if (err)
|
|
5004
|
-
console.error(`WebXR
|
|
5179
|
+
console.error(`WebXR ${type} failed to start: ${err.message}`);
|
|
5005
5180
|
}
|
|
5006
5181
|
});
|
|
5007
5182
|
}
|
|
@@ -5055,6 +5230,23 @@ class CameraComponentElement extends ComponentElement {
|
|
|
5055
5230
|
get clearColorBuffer() {
|
|
5056
5231
|
return this._clearColorBuffer;
|
|
5057
5232
|
}
|
|
5233
|
+
/**
|
|
5234
|
+
* Sets the depth value the depth buffer is cleared to. Defaults to 1.
|
|
5235
|
+
* @param value - The clear depth value.
|
|
5236
|
+
*/
|
|
5237
|
+
set clearDepth(value) {
|
|
5238
|
+
this._clearDepth = value;
|
|
5239
|
+
if (this.component) {
|
|
5240
|
+
this.component.clearDepth = value;
|
|
5241
|
+
}
|
|
5242
|
+
}
|
|
5243
|
+
/**
|
|
5244
|
+
* Gets the depth value the depth buffer is cleared to.
|
|
5245
|
+
* @returns The clear depth value.
|
|
5246
|
+
*/
|
|
5247
|
+
get clearDepth() {
|
|
5248
|
+
return this._clearDepth;
|
|
5249
|
+
}
|
|
5058
5250
|
/**
|
|
5059
5251
|
* Sets the clear depth buffer of the camera.
|
|
5060
5252
|
* @param value - The clear depth buffer.
|
|
@@ -5333,6 +5525,7 @@ class CameraComponentElement extends ComponentElement {
|
|
|
5333
5525
|
...super.observedAttributes,
|
|
5334
5526
|
'clear-color',
|
|
5335
5527
|
'clear-color-buffer',
|
|
5528
|
+
'clear-depth',
|
|
5336
5529
|
'clear-depth-buffer',
|
|
5337
5530
|
'clear-stencil-buffer',
|
|
5338
5531
|
'cull-faces',
|
|
@@ -5360,11 +5553,14 @@ class CameraComponentElement extends ComponentElement {
|
|
|
5360
5553
|
case 'clear-color-buffer':
|
|
5361
5554
|
this.clearColorBuffer = parseBool(newValue, true);
|
|
5362
5555
|
break;
|
|
5556
|
+
case 'clear-depth':
|
|
5557
|
+
this.clearDepth = parseNumber(newValue, 1, name);
|
|
5558
|
+
break;
|
|
5363
5559
|
case 'clear-depth-buffer':
|
|
5364
5560
|
this.clearDepthBuffer = parseBool(newValue, true);
|
|
5365
5561
|
break;
|
|
5366
5562
|
case 'clear-stencil-buffer':
|
|
5367
|
-
this.clearStencilBuffer = parseBool(newValue,
|
|
5563
|
+
this.clearStencilBuffer = parseBool(newValue, true);
|
|
5368
5564
|
break;
|
|
5369
5565
|
case 'cull-faces':
|
|
5370
5566
|
this.cullFaces = parseBool(newValue, true);
|
|
@@ -5427,6 +5623,10 @@ customElements.define('pc-camera', CameraComponentElement);
|
|
|
5427
5623
|
*
|
|
5428
5624
|
* Engine component: {@link CollisionComponent} (`collision`).
|
|
5429
5625
|
*
|
|
5626
|
+
* @elementSummary The `<pc-collision>` element gives its entity a collision shape — a box, sphere,
|
|
5627
|
+
* capsule, cone, cylinder or mesh — for the physics simulation to collide against. Pair it with a
|
|
5628
|
+
* `<pc-rigid-body>`. Must be a child of a `<pc-entity>`, `<pc-model>` or `<pc-node>`.
|
|
5629
|
+
*
|
|
5430
5630
|
* @category Components
|
|
5431
5631
|
*/
|
|
5432
5632
|
class CollisionComponentElement extends ComponentElement {
|
|
@@ -5617,6 +5817,10 @@ customElements.define('pc-collision', CollisionComponentElement);
|
|
|
5617
5817
|
*
|
|
5618
5818
|
* Engine component: {@link ElementComponent} (`element`).
|
|
5619
5819
|
*
|
|
5820
|
+
* @elementSummary The `<pc-element>` element gives its entity a 2D UI rectangle inside a
|
|
5821
|
+
* `<pc-screen>` hierarchy, drawing an image, a line of text or nothing (`type="image"`, `"text"` or
|
|
5822
|
+
* `"group"`). Must be a child of a `<pc-entity>`, `<pc-model>` or `<pc-node>`.
|
|
5823
|
+
*
|
|
5620
5824
|
* @category Components
|
|
5621
5825
|
*/
|
|
5622
5826
|
class ElementComponentElement extends ComponentElement {
|
|
@@ -6301,6 +6505,11 @@ customElements.define('pc-element', ElementComponentElement);
|
|
|
6301
6505
|
* a rigid body component; leaving `entity-b` empty constrains `entity-a` to a fixed point in world
|
|
6302
6506
|
* space. The underlying engine component is in alpha, so its API may change.
|
|
6303
6507
|
*
|
|
6508
|
+
* @elementSummary The `<pc-joint>` element constrains two rigid bodies to each other — a hinged
|
|
6509
|
+
* door, a swinging chain, a sliding drawer. Its entity's transform is the joint frame, and
|
|
6510
|
+
* `entity-a` and `entity-b` name the bodies. Must be a child of a `<pc-entity>`, `<pc-model>` or
|
|
6511
|
+
* `<pc-node>`.
|
|
6512
|
+
*
|
|
6304
6513
|
* @fires {CustomEvent} break - Fired when the impulse on the joint exceeds `break-impulse` and the
|
|
6305
6514
|
* constraint breaks. A broken joint no longer constrains its bodies; calling `refreshFrames()` on
|
|
6306
6515
|
* the underlying component re-attaches it. Bubbles and is composed.
|
|
@@ -7171,6 +7380,10 @@ customElements.define('pc-joint', JointComponentElement);
|
|
|
7171
7380
|
*
|
|
7172
7381
|
* Engine component: {@link LayoutChildComponent} (`layoutchild`).
|
|
7173
7382
|
*
|
|
7383
|
+
* @elementSummary The `<pc-layout-child>` element controls how its entity is sized by the
|
|
7384
|
+
* `<pc-layout-group>` above it, through minimum and maximum sizes and fit proportions. Must be a
|
|
7385
|
+
* child of a `<pc-entity>`, `<pc-model>` or `<pc-node>`.
|
|
7386
|
+
*
|
|
7174
7387
|
* @category Components
|
|
7175
7388
|
*/
|
|
7176
7389
|
class LayoutChildComponentElement extends ComponentElement {
|
|
@@ -7383,6 +7596,10 @@ const fittings = new Map([
|
|
|
7383
7596
|
*
|
|
7384
7597
|
* Engine component: {@link LayoutGroupComponent} (`layoutgroup`).
|
|
7385
7598
|
*
|
|
7599
|
+
* @elementSummary The `<pc-layout-group>` element arranges its entity's children in a row or
|
|
7600
|
+
* column, with spacing, padding, alignment and fitting. Must be a child of a `<pc-entity>`,
|
|
7601
|
+
* `<pc-model>` or `<pc-node>`.
|
|
7602
|
+
*
|
|
7386
7603
|
* @category Components
|
|
7387
7604
|
*/
|
|
7388
7605
|
class LayoutGroupComponentElement extends ComponentElement {
|
|
@@ -7643,23 +7860,30 @@ const shadowTypes = new Map([
|
|
|
7643
7860
|
*
|
|
7644
7861
|
* Engine component: {@link LightComponent} (`light`).
|
|
7645
7862
|
*
|
|
7863
|
+
* @elementSummary The `<pc-light>` element lights the scene from its entity — as a directional,
|
|
7864
|
+
* omni or spot light — with attributes for color, intensity, range and shadows. Must be a child of
|
|
7865
|
+
* a `<pc-entity>`, `<pc-model>` or `<pc-node>`.
|
|
7866
|
+
*
|
|
7646
7867
|
* @category Components
|
|
7647
7868
|
*/
|
|
7648
7869
|
class LightComponentElement extends ComponentElement {
|
|
7870
|
+
_cascadeBlend = 0;
|
|
7871
|
+
_cascadeDistribution = 0.5;
|
|
7649
7872
|
_castShadows = false;
|
|
7650
7873
|
_color = new Color(1, 1, 1);
|
|
7651
7874
|
_innerConeAngle = 40;
|
|
7652
7875
|
_intensity = 1;
|
|
7653
|
-
_normalOffsetBias = 0
|
|
7876
|
+
_normalOffsetBias = 0;
|
|
7877
|
+
_numCascades = 1;
|
|
7654
7878
|
_outerConeAngle = 45;
|
|
7655
7879
|
_range = 10;
|
|
7656
|
-
_shadowBias = 0.
|
|
7657
|
-
_shadowDistance =
|
|
7880
|
+
_shadowBias = 0.05;
|
|
7881
|
+
_shadowDistance = 40;
|
|
7658
7882
|
_shadowIntensity = 1;
|
|
7659
7883
|
_shadowResolution = 1024;
|
|
7660
7884
|
_shadowType = 'pcf3-32f';
|
|
7661
7885
|
_type = 'directional';
|
|
7662
|
-
_vsmBias = 0.
|
|
7886
|
+
_vsmBias = 0.0025;
|
|
7663
7887
|
_vsmBlurSize = 11;
|
|
7664
7888
|
_penumbraSize = 1;
|
|
7665
7889
|
_penumbraFalloff = 1;
|
|
@@ -7671,11 +7895,14 @@ class LightComponentElement extends ComponentElement {
|
|
|
7671
7895
|
}
|
|
7672
7896
|
getInitialComponentData() {
|
|
7673
7897
|
return {
|
|
7898
|
+
cascadeBlend: this._cascadeBlend,
|
|
7899
|
+
cascadeDistribution: this._cascadeDistribution,
|
|
7674
7900
|
castShadows: this._castShadows,
|
|
7675
7901
|
color: this._color,
|
|
7676
7902
|
innerConeAngle: this._innerConeAngle,
|
|
7677
7903
|
intensity: this._intensity,
|
|
7678
7904
|
normalOffsetBias: this._normalOffsetBias,
|
|
7905
|
+
numCascades: this._numCascades,
|
|
7679
7906
|
outerConeAngle: this._outerConeAngle,
|
|
7680
7907
|
penumbraFalloff: this._penumbraFalloff,
|
|
7681
7908
|
penumbraSize: this._penumbraSize,
|
|
@@ -7686,7 +7913,7 @@ class LightComponentElement extends ComponentElement {
|
|
|
7686
7913
|
shadowIntensity: this._shadowIntensity,
|
|
7687
7914
|
shadowResolution: this._shadowResolution,
|
|
7688
7915
|
shadowSamples: this._shadowSamples,
|
|
7689
|
-
shadowType: shadowTypes.get(this._shadowType),
|
|
7916
|
+
shadowType: shadowTypes.get(this._shadowType) ?? SHADOW_PCF3_32F,
|
|
7690
7917
|
type: this._type,
|
|
7691
7918
|
vsmBias: this._vsmBias,
|
|
7692
7919
|
vsmBlurSize: this._vsmBlurSize
|
|
@@ -7699,6 +7926,47 @@ class LightComponentElement extends ComponentElement {
|
|
|
7699
7926
|
get component() {
|
|
7700
7927
|
return super.component;
|
|
7701
7928
|
}
|
|
7929
|
+
/**
|
|
7930
|
+
* Sets the fraction of each shadow cascade that is blended into the next one, from 0 (no
|
|
7931
|
+
* blending) to 1, which applies only to `directional` lights with `num-cascades` greater than
|
|
7932
|
+
* 1. Defaults to 0.
|
|
7933
|
+
* @param value - The cascade blend factor.
|
|
7934
|
+
*/
|
|
7935
|
+
set cascadeBlend(value) {
|
|
7936
|
+
this._cascadeBlend = value;
|
|
7937
|
+
if (this.component) {
|
|
7938
|
+
this.component.cascadeBlend = value;
|
|
7939
|
+
}
|
|
7940
|
+
}
|
|
7941
|
+
/**
|
|
7942
|
+
* Gets the cascade blend factor of the light, from 0 (no blending) to 1, which applies only to
|
|
7943
|
+
* `directional` lights with `num-cascades` greater than 1.
|
|
7944
|
+
* @returns The cascade blend factor.
|
|
7945
|
+
*/
|
|
7946
|
+
get cascadeBlend() {
|
|
7947
|
+
return this._cascadeBlend;
|
|
7948
|
+
}
|
|
7949
|
+
/**
|
|
7950
|
+
* Sets the distribution of the camera frustum split between shadow cascades, from 0 (linear
|
|
7951
|
+
* split) to 1 (logarithmic split, concentrating shadow resolution near the camera), which
|
|
7952
|
+
* applies only to `directional` lights with `num-cascades` greater than 1. Defaults to 0.5.
|
|
7953
|
+
* @param value - The cascade distribution.
|
|
7954
|
+
*/
|
|
7955
|
+
set cascadeDistribution(value) {
|
|
7956
|
+
this._cascadeDistribution = value;
|
|
7957
|
+
if (this.component) {
|
|
7958
|
+
this.component.cascadeDistribution = value;
|
|
7959
|
+
}
|
|
7960
|
+
}
|
|
7961
|
+
/**
|
|
7962
|
+
* Gets the cascade distribution of the light, from 0 (linear split) to 1 (logarithmic split,
|
|
7963
|
+
* concentrating shadow resolution near the camera), which applies only to `directional` lights
|
|
7964
|
+
* with `num-cascades` greater than 1.
|
|
7965
|
+
* @returns The cascade distribution.
|
|
7966
|
+
*/
|
|
7967
|
+
get cascadeDistribution() {
|
|
7968
|
+
return this._cascadeDistribution;
|
|
7969
|
+
}
|
|
7702
7970
|
/**
|
|
7703
7971
|
* Sets the cast shadows flag of the light.
|
|
7704
7972
|
* @param value - The cast shadows flag.
|
|
@@ -7784,6 +8052,25 @@ class LightComponentElement extends ComponentElement {
|
|
|
7784
8052
|
get normalOffsetBias() {
|
|
7785
8053
|
return this._normalOffsetBias;
|
|
7786
8054
|
}
|
|
8055
|
+
/**
|
|
8056
|
+
* Sets the number of shadow cascades of the light, an integer from 1 (no cascades) to 4, which
|
|
8057
|
+
* applies only to `directional` lights. Defaults to 1.
|
|
8058
|
+
* @param value - The number of shadow cascades.
|
|
8059
|
+
*/
|
|
8060
|
+
set numCascades(value) {
|
|
8061
|
+
this._numCascades = value;
|
|
8062
|
+
if (this.component) {
|
|
8063
|
+
this.component.numCascades = value;
|
|
8064
|
+
}
|
|
8065
|
+
}
|
|
8066
|
+
/**
|
|
8067
|
+
* Gets the number of shadow cascades of the light, an integer from 1 (no cascades) to 4, which
|
|
8068
|
+
* applies only to `directional` lights.
|
|
8069
|
+
* @returns The number of shadow cascades.
|
|
8070
|
+
*/
|
|
8071
|
+
get numCascades() {
|
|
8072
|
+
return this._numCascades;
|
|
8073
|
+
}
|
|
7787
8074
|
/**
|
|
7788
8075
|
* Sets the outer cone angle of the light.
|
|
7789
8076
|
* @param value - The outer cone angle.
|
|
@@ -8036,11 +8323,14 @@ class LightComponentElement extends ComponentElement {
|
|
|
8036
8323
|
static get observedAttributes() {
|
|
8037
8324
|
return [
|
|
8038
8325
|
...super.observedAttributes,
|
|
8039
|
-
'
|
|
8326
|
+
'cascade-blend',
|
|
8327
|
+
'cascade-distribution',
|
|
8040
8328
|
'cast-shadows',
|
|
8041
|
-
'
|
|
8329
|
+
'color',
|
|
8042
8330
|
'inner-cone-angle',
|
|
8331
|
+
'intensity',
|
|
8043
8332
|
'normal-offset-bias',
|
|
8333
|
+
'num-cascades',
|
|
8044
8334
|
'outer-cone-angle',
|
|
8045
8335
|
'penumbra-falloff',
|
|
8046
8336
|
'penumbra-size',
|
|
@@ -8060,12 +8350,18 @@ class LightComponentElement extends ComponentElement {
|
|
|
8060
8350
|
attributeChangedCallback(name, _oldValue, newValue) {
|
|
8061
8351
|
super.attributeChangedCallback(name, _oldValue, newValue);
|
|
8062
8352
|
switch (name) {
|
|
8063
|
-
case '
|
|
8064
|
-
this.
|
|
8353
|
+
case 'cascade-blend':
|
|
8354
|
+
this.cascadeBlend = parseNumber(newValue, 0, name);
|
|
8355
|
+
break;
|
|
8356
|
+
case 'cascade-distribution':
|
|
8357
|
+
this.cascadeDistribution = parseNumber(newValue, 0.5, name);
|
|
8065
8358
|
break;
|
|
8066
8359
|
case 'cast-shadows':
|
|
8067
8360
|
this.castShadows = parseBool(newValue, false);
|
|
8068
8361
|
break;
|
|
8362
|
+
case 'color':
|
|
8363
|
+
this.color = parseColor(newValue, Color.WHITE, name);
|
|
8364
|
+
break;
|
|
8069
8365
|
case 'inner-cone-angle':
|
|
8070
8366
|
this.innerConeAngle = parseNumber(newValue, 40, name);
|
|
8071
8367
|
break;
|
|
@@ -8073,7 +8369,10 @@ class LightComponentElement extends ComponentElement {
|
|
|
8073
8369
|
this.intensity = parseNumber(newValue, 1, name);
|
|
8074
8370
|
break;
|
|
8075
8371
|
case 'normal-offset-bias':
|
|
8076
|
-
this.normalOffsetBias = parseNumber(newValue, 0
|
|
8372
|
+
this.normalOffsetBias = parseNumber(newValue, 0, name);
|
|
8373
|
+
break;
|
|
8374
|
+
case 'num-cascades':
|
|
8375
|
+
this.numCascades = parseNumber(newValue, 1, name);
|
|
8077
8376
|
break;
|
|
8078
8377
|
case 'outer-cone-angle':
|
|
8079
8378
|
this.outerConeAngle = parseNumber(newValue, 45, name);
|
|
@@ -8088,20 +8387,20 @@ class LightComponentElement extends ComponentElement {
|
|
|
8088
8387
|
this.range = parseNumber(newValue, 10, name);
|
|
8089
8388
|
break;
|
|
8090
8389
|
case 'shadow-bias':
|
|
8091
|
-
this.shadowBias = parseNumber(newValue, 0.
|
|
8092
|
-
break;
|
|
8093
|
-
case 'shadow-distance':
|
|
8094
|
-
this.shadowDistance = parseNumber(newValue, 16, name);
|
|
8390
|
+
this.shadowBias = parseNumber(newValue, 0.05, name);
|
|
8095
8391
|
break;
|
|
8096
8392
|
case 'shadow-blocker-samples':
|
|
8097
8393
|
this.shadowBlockerSamples = parseNumber(newValue, 16, name);
|
|
8098
8394
|
break;
|
|
8099
|
-
case 'shadow-
|
|
8100
|
-
this.
|
|
8395
|
+
case 'shadow-distance':
|
|
8396
|
+
this.shadowDistance = parseNumber(newValue, 40, name);
|
|
8101
8397
|
break;
|
|
8102
8398
|
case 'shadow-intensity':
|
|
8103
8399
|
this.shadowIntensity = parseNumber(newValue, 1, name);
|
|
8104
8400
|
break;
|
|
8401
|
+
case 'shadow-resolution':
|
|
8402
|
+
this.shadowResolution = parseNumber(newValue, 1024, name);
|
|
8403
|
+
break;
|
|
8105
8404
|
case 'shadow-samples':
|
|
8106
8405
|
this.shadowSamples = parseNumber(newValue, 16, name);
|
|
8107
8406
|
break;
|
|
@@ -8112,7 +8411,7 @@ class LightComponentElement extends ComponentElement {
|
|
|
8112
8411
|
this.type = parseEnum(newValue, ['directional', 'omni', 'spot'], 'directional', name);
|
|
8113
8412
|
break;
|
|
8114
8413
|
case 'vsm-bias':
|
|
8115
|
-
this.vsmBias = parseNumber(newValue, 0.
|
|
8414
|
+
this.vsmBias = parseNumber(newValue, 0.0025, name);
|
|
8116
8415
|
break;
|
|
8117
8416
|
case 'vsm-blur-size':
|
|
8118
8417
|
this.vsmBlurSize = parseNumber(newValue, 11, name);
|
|
@@ -8130,6 +8429,10 @@ customElements.define('pc-light', LightComponentElement);
|
|
|
8130
8429
|
*
|
|
8131
8430
|
* Engine component: {@link ParticleSystemComponent} (`particlesystem`).
|
|
8132
8431
|
*
|
|
8432
|
+
* @elementSummary The `<pc-particle-system>` element emits particles from its entity, with
|
|
8433
|
+
* attributes for the emitter's shape, rate, lifetime, textures and blending. Must be a child of a
|
|
8434
|
+
* `<pc-entity>`, `<pc-model>` or `<pc-node>`.
|
|
8435
|
+
*
|
|
8133
8436
|
* @category Components
|
|
8134
8437
|
*/
|
|
8135
8438
|
class ParticleSystemComponentElement extends ComponentElement {
|
|
@@ -8278,6 +8581,8 @@ const occludeSpeculars = new Map([
|
|
|
8278
8581
|
['ao', SPECOCC_AO],
|
|
8279
8582
|
['gloss-dependent', SPECOCC_GLOSSDEPENDENT]
|
|
8280
8583
|
]);
|
|
8584
|
+
// The DITHER_* constants are strings whose values are exactly these names, so a parsed value is
|
|
8585
|
+
// assigned to the material unchanged rather than mapped through a table.
|
|
8281
8586
|
const opacityDithers = ['none', 'bayer8', 'bluenoise', 'ignnoise'];
|
|
8282
8587
|
const colorChannels = ['r', 'g', 'b', 'a', 'rgb'];
|
|
8283
8588
|
const scalarChannels = ['r', 'g', 'b', 'a'];
|
|
@@ -8314,6 +8619,10 @@ const roughnessAliases = ['roughness', 'roughness-map'];
|
|
|
8314
8619
|
* The two aliases are documented here rather than on an accessor, because they resolve to the
|
|
8315
8620
|
* `gloss` properties and would otherwise inherit gloss's description - which reads inverted.
|
|
8316
8621
|
*
|
|
8622
|
+
* @elementSummary The `<pc-material>` element defines a physically based material, which
|
|
8623
|
+
* `<pc-render>` elements apply by naming its `id`. It is metal/rough by default, with `metalness`
|
|
8624
|
+
* starting at 0. Must be a direct child of `<pc-app>`.
|
|
8625
|
+
*
|
|
8317
8626
|
* @attribute {number} roughness - The roughness of the material, from 0 (shiny) to 1 (rough). An
|
|
8318
8627
|
* alias for `gloss` that also inverts it, so do not combine it with the `gloss` attributes.
|
|
8319
8628
|
* @attribute {string} roughness-map - The id of the `pc-asset` to use as the roughness map. An
|
|
@@ -10482,6 +10791,11 @@ customElements.define('pc-material', MaterialElement);
|
|
|
10482
10791
|
*
|
|
10483
10792
|
* Engine component: {@link RenderComponent} (`render`).
|
|
10484
10793
|
*
|
|
10794
|
+
* @elementSummary The `<pc-render>` element renders one of the engine's built-in primitives at its
|
|
10795
|
+
* entity — box, sphere, capsule, cone, cylinder or plane — shaded by the `<pc-material>` its
|
|
10796
|
+
* `material` attribute names. For glTF content, use `<pc-model>` instead. Must be a child of a
|
|
10797
|
+
* `<pc-entity>`, `<pc-model>` or `<pc-node>`.
|
|
10798
|
+
*
|
|
10485
10799
|
* @category Components
|
|
10486
10800
|
*/
|
|
10487
10801
|
class RenderComponentElement extends ComponentElement {
|
|
@@ -10612,6 +10926,11 @@ customElements.define('pc-render', RenderComponentElement);
|
|
|
10612
10926
|
*
|
|
10613
10927
|
* Engine component: {@link RigidBodyComponent} (`rigidbody`).
|
|
10614
10928
|
*
|
|
10929
|
+
* @elementSummary The `<pc-rigid-body>` element hands its entity to the physics simulation, with
|
|
10930
|
+
* attributes for its type, mass, friction and restitution. It needs a sibling `<pc-collision>` for
|
|
10931
|
+
* its shape, and `Ammo` loaded through `<pc-wasm>`. Must be a child of a `<pc-entity>`,
|
|
10932
|
+
* `<pc-model>` or `<pc-node>`.
|
|
10933
|
+
*
|
|
10615
10934
|
* @category Components
|
|
10616
10935
|
*/
|
|
10617
10936
|
class RigidBodyComponentElement extends ComponentElement {
|
|
@@ -10821,6 +11140,10 @@ const scaleModes = new Map([
|
|
|
10821
11140
|
*
|
|
10822
11141
|
* Engine component: {@link ScreenComponent} (`screen`).
|
|
10823
11142
|
*
|
|
11143
|
+
* @elementSummary The `<pc-screen>` element gives its entity a 2D space — in screen space or in the
|
|
11144
|
+
* world — that a hierarchy of `<pc-element>` descendants lays out inside. Must be a child of a
|
|
11145
|
+
* `<pc-entity>`, `<pc-model>` or `<pc-node>`.
|
|
11146
|
+
*
|
|
10824
11147
|
* @category Components
|
|
10825
11148
|
*/
|
|
10826
11149
|
class ScreenComponentElement extends ComponentElement {
|
|
@@ -10975,6 +11298,10 @@ const orientations = new Map([
|
|
|
10975
11298
|
*
|
|
10976
11299
|
* Engine component: {@link ScrollbarComponent} (`scrollbar`).
|
|
10977
11300
|
*
|
|
11301
|
+
* @elementSummary The `<pc-scrollbar>` element gives its entity a draggable handle reporting a
|
|
11302
|
+
* position from 0 to 1, which a `<pc-scroll-view>` references to scroll its content. Must be a
|
|
11303
|
+
* child of a `<pc-entity>`, `<pc-model>` or `<pc-node>`.
|
|
11304
|
+
*
|
|
10978
11305
|
* @category Components
|
|
10979
11306
|
*/
|
|
10980
11307
|
class ScrollbarComponentElement extends ComponentElement {
|
|
@@ -11116,6 +11443,10 @@ const visibilities = new Map([
|
|
|
11116
11443
|
*
|
|
11117
11444
|
* Engine component: {@link ScrollViewComponent} (`scrollview`).
|
|
11118
11445
|
*
|
|
11446
|
+
* @elementSummary The `<pc-scroll-view>` element scrolls a larger content entity within a clipped
|
|
11447
|
+
* viewport at its entity, optionally driven by the `<pc-scrollbar>` elements it references. Must be
|
|
11448
|
+
* a child of a `<pc-entity>`, `<pc-model>` or `<pc-node>`.
|
|
11449
|
+
*
|
|
11119
11450
|
* @category Components
|
|
11120
11451
|
*/
|
|
11121
11452
|
class ScrollViewComponentElement extends ComponentElement {
|
|
@@ -11502,6 +11833,10 @@ customElements.define('pc-scroll-view', ScrollViewComponentElement);
|
|
|
11502
11833
|
* The element becomes ready once its script instance has been created by the parent
|
|
11503
11834
|
* `<pc-script>` element.
|
|
11504
11835
|
*
|
|
11836
|
+
* @elementSummary The `<pc-script-instance>` element attaches one script class, named by `name`, to
|
|
11837
|
+
* the entity of its parent `<pc-script>`. Its other attributes set script attributes of the same
|
|
11838
|
+
* name, and `attributes` takes a JSON object instead. Must be a direct child of `<pc-script>`.
|
|
11839
|
+
*
|
|
11505
11840
|
* @fires {CustomEvent} scriptattributeschange - Fired when the script's attributes change. The
|
|
11506
11841
|
* `detail` carries the new `attributes` object. Bubbles.
|
|
11507
11842
|
* @fires {CustomEvent} scriptenablechange - Fired when the script's enabled state changes. The
|
|
@@ -11846,6 +12181,9 @@ const findCaseMatch = (script, key) => {
|
|
|
11846
12181
|
*
|
|
11847
12182
|
* Engine component: {@link ScriptComponent} (`script`).
|
|
11848
12183
|
*
|
|
12184
|
+
* @elementSummary The `<pc-script>` element holds the `<pc-script-instance>` children that attach
|
|
12185
|
+
* scripts to its entity. Must be a child of a `<pc-entity>`, `<pc-model>` or `<pc-node>`.
|
|
12186
|
+
*
|
|
11849
12187
|
* @category Components
|
|
11850
12188
|
*/
|
|
11851
12189
|
class ScriptComponentElement extends ComponentElement {
|
|
@@ -12295,6 +12633,10 @@ customElements.define('pc-script', ScriptComponentElement);
|
|
|
12295
12633
|
*
|
|
12296
12634
|
* Engine component: {@link SoundComponent} (`sound`).
|
|
12297
12635
|
*
|
|
12636
|
+
* @elementSummary The `<pc-sound>` element holds the `<pc-sound-slot>` children that play sounds at
|
|
12637
|
+
* its entity, along with the positional audio settings they share. Must be a child of a
|
|
12638
|
+
* `<pc-entity>`, `<pc-model>` or `<pc-node>`.
|
|
12639
|
+
*
|
|
12298
12640
|
* @category Components
|
|
12299
12641
|
*/
|
|
12300
12642
|
class SoundComponentElement extends ComponentElement {
|
|
@@ -12491,6 +12833,9 @@ customElements.define('pc-sound', SoundComponentElement);
|
|
|
12491
12833
|
* The SoundSlotElement interface provides properties and methods for manipulating
|
|
12492
12834
|
* `<pc-sound-slot>` elements. The SoundSlotElement interface also inherits the properties and
|
|
12493
12835
|
* methods of the {@link AsyncElement} interface.
|
|
12836
|
+
*
|
|
12837
|
+
* @elementSummary The `<pc-sound-slot>` element declares one named sound on its parent `<pc-sound>`
|
|
12838
|
+
* — its asset, volume, pitch, looping and autoplay. Must be a direct child of `<pc-sound>`.
|
|
12494
12839
|
*/
|
|
12495
12840
|
class SoundSlotElement extends AsyncElement {
|
|
12496
12841
|
_asset = '';
|
|
@@ -12772,6 +13117,10 @@ customElements.define('pc-sound-slot', SoundSlotElement);
|
|
|
12772
13117
|
*
|
|
12773
13118
|
* Engine component: {@link GSplatComponent} (`gsplat`).
|
|
12774
13119
|
*
|
|
13120
|
+
* @elementSummary The `<pc-gsplat>` element renders the 3D Gaussian splats of a `gsplat` asset at
|
|
13121
|
+
* its entity, with attributes for shadow casting and level of detail. Must be a child of a
|
|
13122
|
+
* `<pc-entity>`, `<pc-model>` or `<pc-node>`.
|
|
13123
|
+
*
|
|
12775
13124
|
* @category Components
|
|
12776
13125
|
*/
|
|
12777
13126
|
class GSplatComponentElement extends ComponentElement {
|
|
@@ -13067,6 +13416,11 @@ const levenshtein = (a, b) => {
|
|
|
13067
13416
|
* The pointer events below are dispatched by the containing `<pc-app>` element when the pointer
|
|
13068
13417
|
* intersects the bound node's geometry, exactly as for `<pc-entity>`.
|
|
13069
13418
|
*
|
|
13419
|
+
* @elementSummary The `<pc-node>` element binds to a node inside the hierarchy a `<pc-model>`
|
|
13420
|
+
* instantiated and declares overrides against it: a transform, an enabled state, tags, components
|
|
13421
|
+
* to add, or content to attach. Its `name` is a lookup, never a rename. Must be a descendant of
|
|
13422
|
+
* `<pc-model>`.
|
|
13423
|
+
*
|
|
13070
13424
|
* @attribute {string} name - The name of the node to bind, resolved within the nearest ancestor
|
|
13071
13425
|
* `pc-model` (or `pc-node`) once it has instantiated.
|
|
13072
13426
|
* @attribute {number} index - Which match to bind when `name` matches more than one node,
|
|
@@ -13091,11 +13445,17 @@ const levenshtein = (a, b) => {
|
|
|
13091
13445
|
* node.
|
|
13092
13446
|
* @attribute {string} onpointerup - Script to run when a pointer button is released over the
|
|
13093
13447
|
* node.
|
|
13448
|
+
* @attribute {string} onclick - Script to run when the node is clicked: a primary pointer
|
|
13449
|
+
* button pressed and then released over it.
|
|
13094
13450
|
* @fires {PointerEvent} pointerenter - Fired when the pointer moves onto the node.
|
|
13095
13451
|
* @fires {PointerEvent} pointerleave - Fired when the pointer moves off the node.
|
|
13096
13452
|
* @fires {PointerEvent} pointermove - Fired when the pointer moves over the node.
|
|
13097
13453
|
* @fires {PointerEvent} pointerdown - Fired when a pointer button is pressed over the node.
|
|
13098
13454
|
* @fires {PointerEvent} pointerup - Fired when a pointer button is released over the node.
|
|
13455
|
+
* @fires {PointerEvent} click - Fired when a primary pointer button is pressed and then released
|
|
13456
|
+
* over the node. A press and release that picked different entities fires on their nearest
|
|
13457
|
+
* common ancestor instead, as in the DOM. `detail` carries the click count, so a double click
|
|
13458
|
+
* arrives as a click whose `detail` is 2.
|
|
13099
13459
|
*/
|
|
13100
13460
|
class NodeElement extends EntityBaseElement {
|
|
13101
13461
|
_name = '';
|
|
@@ -13745,7 +14105,7 @@ class NodeElement extends EntityBaseElement {
|
|
|
13745
14105
|
'rotation',
|
|
13746
14106
|
'scale',
|
|
13747
14107
|
'tags',
|
|
13748
|
-
...
|
|
14108
|
+
...EVENT_ATTRIBUTES
|
|
13749
14109
|
];
|
|
13750
14110
|
}
|
|
13751
14111
|
attributeChangedCallback(name, _oldValue, newValue) {
|
|
@@ -13795,6 +14155,7 @@ class NodeElement extends EntityBaseElement {
|
|
|
13795
14155
|
case 'onpointerdown':
|
|
13796
14156
|
case 'onpointerup':
|
|
13797
14157
|
case 'onpointermove':
|
|
14158
|
+
case 'onclick':
|
|
13798
14159
|
this._updateInlineHandler(name, newValue);
|
|
13799
14160
|
break;
|
|
13800
14161
|
}
|
|
@@ -13807,8 +14168,16 @@ customElements.define('pc-node', NodeElement);
|
|
|
13807
14168
|
* {@link https://developer.playcanvas.com/user-manual/web-components/tags/pc-scene/ | `<pc-scene>`} elements.
|
|
13808
14169
|
* The SceneElement interface also inherits the properties and methods of the
|
|
13809
14170
|
* {@link HTMLElement} interface.
|
|
14171
|
+
*
|
|
14172
|
+
* @elementSummary The `<pc-scene>` element holds the entity hierarchy the application renders,
|
|
14173
|
+
* along with the scene-wide fog, exposure and gravity settings. Must be a direct child of
|
|
14174
|
+
* `<pc-app>`.
|
|
13810
14175
|
*/
|
|
13811
14176
|
class SceneElement extends AsyncElement {
|
|
14177
|
+
/**
|
|
14178
|
+
* The exposure of the scene.
|
|
14179
|
+
*/
|
|
14180
|
+
_exposure = 1;
|
|
13812
14181
|
/**
|
|
13813
14182
|
* The fog type of the scene.
|
|
13814
14183
|
*/
|
|
@@ -13876,6 +14245,7 @@ class SceneElement extends AsyncElement {
|
|
|
13876
14245
|
}
|
|
13877
14246
|
_updateSceneSettings() {
|
|
13878
14247
|
if (this._scene) {
|
|
14248
|
+
this._scene.exposure = this._exposure;
|
|
13879
14249
|
this._scene.fog.type = this._fog;
|
|
13880
14250
|
this._scene.fog.color = this._fogColor;
|
|
13881
14251
|
this._scene.fog.density = this._fogDensity;
|
|
@@ -13894,6 +14264,24 @@ class SceneElement extends AsyncElement {
|
|
|
13894
14264
|
_applyGravity(value) {
|
|
13895
14265
|
this.closestApp?.app?.systems.rigidbody?.gravity.copy(value);
|
|
13896
14266
|
}
|
|
14267
|
+
/**
|
|
14268
|
+
* Sets the exposure of the scene, which tweaks the overall brightness of the rendered image.
|
|
14269
|
+
* Ignored if the scene is using physical units. Defaults to 1.
|
|
14270
|
+
* @param value - The exposure.
|
|
14271
|
+
*/
|
|
14272
|
+
set exposure(value) {
|
|
14273
|
+
this._exposure = value;
|
|
14274
|
+
if (this.scene) {
|
|
14275
|
+
this.scene.exposure = value;
|
|
14276
|
+
}
|
|
14277
|
+
}
|
|
14278
|
+
/**
|
|
14279
|
+
* Gets the exposure of the scene.
|
|
14280
|
+
* @returns The exposure.
|
|
14281
|
+
*/
|
|
14282
|
+
get exposure() {
|
|
14283
|
+
return this._exposure;
|
|
14284
|
+
}
|
|
13897
14285
|
/**
|
|
13898
14286
|
* Sets the fog type of the scene. Can be `none`, `linear`, `exp` or `exp2`. Defaults to
|
|
13899
14287
|
* `none`.
|
|
@@ -13998,10 +14386,13 @@ class SceneElement extends AsyncElement {
|
|
|
13998
14386
|
return this._gravity;
|
|
13999
14387
|
}
|
|
14000
14388
|
static get observedAttributes() {
|
|
14001
|
-
return ['fog', 'fog-color', 'fog-density', 'fog-start', 'fog-end', 'gravity'];
|
|
14389
|
+
return ['exposure', 'fog', 'fog-color', 'fog-density', 'fog-start', 'fog-end', 'gravity'];
|
|
14002
14390
|
}
|
|
14003
14391
|
attributeChangedCallback(name, _oldValue, newValue) {
|
|
14004
14392
|
switch (name) {
|
|
14393
|
+
case 'exposure':
|
|
14394
|
+
this.exposure = parseNumber(newValue, 1, name);
|
|
14395
|
+
break;
|
|
14005
14396
|
case 'fog':
|
|
14006
14397
|
this.fog = parseEnum(newValue, ['none', 'linear', 'exp', 'exp2'], 'none', name);
|
|
14007
14398
|
break;
|
|
@@ -14030,6 +14421,10 @@ customElements.define('pc-scene', SceneElement);
|
|
|
14030
14421
|
* The SkyElement interface provides properties and methods for manipulating
|
|
14031
14422
|
* `<pc-sky>` elements. The SkyElement interface also inherits the properties and
|
|
14032
14423
|
* methods of the {@link HTMLElement} interface.
|
|
14424
|
+
*
|
|
14425
|
+
* @elementSummary The `<pc-sky>` element renders a skybox from a texture asset, projected as an
|
|
14426
|
+
* infinite background, a box or a dome, and optionally lights the scene from it. Must be a direct
|
|
14427
|
+
* child of `<pc-scene>`.
|
|
14033
14428
|
*/
|
|
14034
14429
|
class SkyElement extends AsyncElement {
|
|
14035
14430
|
_asset = '';
|