@playcanvas/web-components 0.10.1 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app.d.ts +103 -32
- package/dist/components/camera-component.d.ts +13 -13
- package/dist/components/screen-component.d.ts +25 -4
- package/dist/components/scrollview-component.d.ts +6 -4
- package/dist/custom-elements.json +239 -96
- package/dist/entity.d.ts +13 -0
- package/dist/parse.d.ts +4 -2
- package/dist/pwc.cjs +308 -156
- package/dist/pwc.cjs.map +1 -1
- package/dist/pwc.js +308 -156
- 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 +309 -157
- package/dist/pwc.mjs.map +1 -1
- package/dist/sky.d.ts +12 -11
- package/dist/vscode.html-custom-data.json +40 -20
- package/dist/web-types.json +67 -48
- package/package.json +1 -1
- package/src/app.ts +189 -79
- package/src/components/camera-component.ts +31 -26
- package/src/components/screen-component.ts +42 -12
- package/src/components/scrollview-component.ts +6 -4
- package/src/entity.ts +35 -17
- package/src/parse.ts +5 -3
- package/src/sky.ts +26 -25
package/dist/pwc.js
CHANGED
|
@@ -491,7 +491,9 @@
|
|
|
491
491
|
* the value is invalid — the latter also logs a warning listing the valid names.
|
|
492
492
|
*
|
|
493
493
|
* @param value - The attribute value to parse (`null` when the attribute is absent).
|
|
494
|
-
* @param valid - The valid names: an array, or a map whose keys are the valid names.
|
|
494
|
+
* @param valid - The valid names: an array, or a map whose keys are the valid names. Only the keys
|
|
495
|
+
* are read, so the map's value type is unconstrained - engine enums are mostly numeric constants,
|
|
496
|
+
* but some (e.g. `SCALEMODE_BLEND`) are strings.
|
|
495
497
|
* @param defaultValue - The value to use when the attribute is absent or invalid.
|
|
496
498
|
* @param attribute - The attribute name, used in the warning message.
|
|
497
499
|
* @returns The resolved enum name.
|
|
@@ -679,12 +681,24 @@
|
|
|
679
681
|
_alpha = true;
|
|
680
682
|
_backend = 'webgpu';
|
|
681
683
|
_antialias = true;
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
684
|
+
_depthBuffer = true;
|
|
685
|
+
_stencilBuffer = true;
|
|
686
|
+
_maxPixelRatio = Infinity;
|
|
685
687
|
_loadingBar = true;
|
|
688
|
+
/**
|
|
689
|
+
* Set once the graphics options above have been handed to `createGraphicsDevice`, after which
|
|
690
|
+
* writing any of them changes nothing. Guards the warning in {@link _warnIfBooted}, and is
|
|
691
|
+
* cleared on disconnect so a re-connected element boots from its current attributes.
|
|
692
|
+
*/
|
|
693
|
+
_optionsLocked = false;
|
|
686
694
|
_bar = null;
|
|
687
695
|
_hierarchyReady = false;
|
|
696
|
+
/**
|
|
697
|
+
* The elements backing this application's entities, keyed by the entity itself. Registered
|
|
698
|
+
* by EntityElement at creation and removed when an entity is destroyed, this joins engine
|
|
699
|
+
* scene nodes back to their owning elements by identity - never by name.
|
|
700
|
+
*/
|
|
701
|
+
_entityElements = new Map();
|
|
688
702
|
_picker = null;
|
|
689
703
|
_hasPointerListeners = {
|
|
690
704
|
pointerenter: false,
|
|
@@ -752,15 +766,19 @@
|
|
|
752
766
|
null: ['null']
|
|
753
767
|
};
|
|
754
768
|
const deviceTypes = backendToDeviceTypes[this._backend] || [];
|
|
769
|
+
this._optionsLocked = true;
|
|
755
770
|
const device = await playcanvas.createGraphicsDevice(this._canvas, {
|
|
756
771
|
// @ts-ignore - alpha needs to be documented
|
|
757
772
|
alpha: this._alpha,
|
|
758
773
|
antialias: this._antialias,
|
|
759
|
-
depth: this.
|
|
774
|
+
depth: this._depthBuffer,
|
|
760
775
|
deviceTypes: deviceTypes,
|
|
761
|
-
stencil: this.
|
|
776
|
+
stencil: this._stencilBuffer
|
|
762
777
|
});
|
|
763
|
-
|
|
778
|
+
// Assigned rather than resolved to a number here: the engine caps against the live
|
|
779
|
+
// window.devicePixelRatio on every resize, so an uncapped Infinity keeps following the
|
|
780
|
+
// display when a window moves between monitors of differing density.
|
|
781
|
+
device.maxPixelRatio = this._maxPixelRatio;
|
|
764
782
|
const createOptions = new playcanvas.AppOptions();
|
|
765
783
|
createOptions.graphicsDevice = device;
|
|
766
784
|
createOptions.keyboard = new playcanvas.Keyboard(window);
|
|
@@ -887,12 +905,15 @@
|
|
|
887
905
|
});
|
|
888
906
|
}
|
|
889
907
|
disconnectedCallback() {
|
|
908
|
+
this._optionsLocked = false;
|
|
890
909
|
this._pickerDestroy();
|
|
891
|
-
// Clean up the application
|
|
910
|
+
// Clean up the application. Destroying it destroys every entity, whose destroy hooks
|
|
911
|
+
// unregister them - clear() covers any entity the engine no longer reached.
|
|
892
912
|
if (this._app) {
|
|
893
913
|
this._app.destroy();
|
|
894
914
|
this._app = null;
|
|
895
915
|
}
|
|
916
|
+
this._entityElements.clear();
|
|
896
917
|
this._loadProgress = 0;
|
|
897
918
|
this._bar?.destroy();
|
|
898
919
|
this._bar = null;
|
|
@@ -958,6 +979,74 @@
|
|
|
958
979
|
pointermove: false
|
|
959
980
|
};
|
|
960
981
|
}
|
|
982
|
+
/**
|
|
983
|
+
* Registers the element that created an entity. Called by EntityElement when it creates its
|
|
984
|
+
* entity.
|
|
985
|
+
*
|
|
986
|
+
* @param entity - The entity.
|
|
987
|
+
* @param element - The element that created it.
|
|
988
|
+
* @ignore
|
|
989
|
+
*/
|
|
990
|
+
_registerEntityElement(entity, element) {
|
|
991
|
+
this._entityElements.set(entity, element);
|
|
992
|
+
}
|
|
993
|
+
/**
|
|
994
|
+
* Removes the registration for a destroyed entity. Called by EntityElement.
|
|
995
|
+
*
|
|
996
|
+
* @param entity - The entity.
|
|
997
|
+
* @ignore
|
|
998
|
+
*/
|
|
999
|
+
_unregisterEntityElement(entity) {
|
|
1000
|
+
this._entityElements.delete(entity);
|
|
1001
|
+
}
|
|
1002
|
+
/**
|
|
1003
|
+
* Returns the `<pc-entity>` element whose backing entity is `entity`, or `null` if the
|
|
1004
|
+
* entity was not created by an element of this application - for example, a node inside a
|
|
1005
|
+
* model's instantiated hierarchy, or an entity created through the engine API.
|
|
1006
|
+
*
|
|
1007
|
+
* @param entity - The entity to look up.
|
|
1008
|
+
* @returns The element backing the entity, or `null`.
|
|
1009
|
+
*/
|
|
1010
|
+
elementFromEntity(entity) {
|
|
1011
|
+
return this._entityElements.get(entity) ?? null;
|
|
1012
|
+
}
|
|
1013
|
+
/**
|
|
1014
|
+
* Resolves the element that owns a picked node: the nearest node up the parent chain -
|
|
1015
|
+
* starting with the node itself - that was created by a `<pc-entity>` of this application.
|
|
1016
|
+
* A hit inside a model's instantiated hierarchy therefore resolves to the element hosting
|
|
1017
|
+
* the model.
|
|
1018
|
+
*
|
|
1019
|
+
* @param node - The picked node, or `null`.
|
|
1020
|
+
* @returns The owning element, or `null`.
|
|
1021
|
+
*/
|
|
1022
|
+
_elementFromNode(node) {
|
|
1023
|
+
while (node !== null) {
|
|
1024
|
+
const element = this._entityElements.get(node);
|
|
1025
|
+
if (element) {
|
|
1026
|
+
return element;
|
|
1027
|
+
}
|
|
1028
|
+
node = node.parent;
|
|
1029
|
+
}
|
|
1030
|
+
return null;
|
|
1031
|
+
}
|
|
1032
|
+
/**
|
|
1033
|
+
* Like {@link _elementFromNode}, but skips elements without a listener for `type`, so a hit
|
|
1034
|
+
* on an unlistened child still reaches a listening ancestor.
|
|
1035
|
+
*
|
|
1036
|
+
* @param node - The picked node, or `null`.
|
|
1037
|
+
* @param type - The pointer event type a listener is required for.
|
|
1038
|
+
* @returns The nearest listening element, or `null`.
|
|
1039
|
+
*/
|
|
1040
|
+
_elementWithListener(node, type) {
|
|
1041
|
+
while (node !== null) {
|
|
1042
|
+
const element = this._entityElements.get(node);
|
|
1043
|
+
if (element?.hasListeners(type)) {
|
|
1044
|
+
return element;
|
|
1045
|
+
}
|
|
1046
|
+
node = node.parent;
|
|
1047
|
+
}
|
|
1048
|
+
return null;
|
|
1049
|
+
}
|
|
961
1050
|
// New helper to convert CSS coordinates to canvas (picker) coordinates
|
|
962
1051
|
_getPickerCoordinates(event) {
|
|
963
1052
|
// Get the canvas' bounding rectangle in CSS pixels.
|
|
@@ -1003,17 +1092,9 @@
|
|
|
1003
1092
|
const node = await this._pickNode(event);
|
|
1004
1093
|
if (token !== this._pickToken || !this._picker)
|
|
1005
1094
|
return;
|
|
1006
|
-
//
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
while (currentNode !== null) {
|
|
1010
|
-
const entityElement = this.querySelector(`pc-entity[name="${currentNode.name}"]`);
|
|
1011
|
-
if (entityElement) {
|
|
1012
|
-
newHoverEntity = entityElement;
|
|
1013
|
-
break;
|
|
1014
|
-
}
|
|
1015
|
-
currentNode = currentNode.parent;
|
|
1016
|
-
}
|
|
1095
|
+
// The hovered element is the nearest one up the node's parent chain, listening or not -
|
|
1096
|
+
// dispatch is gated per event type below
|
|
1097
|
+
const newHoverEntity = this._elementFromNode(node);
|
|
1017
1098
|
// Handle enter/leave events
|
|
1018
1099
|
if (this._hoveredEntity !== newHoverEntity) {
|
|
1019
1100
|
if (this._hoveredEntity && this._hoveredEntity.hasListeners('pointerleave')) {
|
|
@@ -1033,26 +1114,22 @@
|
|
|
1033
1114
|
async _onPointerDown(event) {
|
|
1034
1115
|
if (!this._picker || !this.app)
|
|
1035
1116
|
return;
|
|
1036
|
-
|
|
1117
|
+
const node = await this._pickNode(event);
|
|
1037
1118
|
if (!this._picker)
|
|
1038
1119
|
return; // the element disconnected while the pick was in flight
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
entityElement.dispatchEvent(new PointerEvent('pointerdown', event));
|
|
1043
|
-
break;
|
|
1044
|
-
}
|
|
1045
|
-
currentNode = currentNode.parent;
|
|
1120
|
+
const entityElement = this._elementWithListener(node, 'pointerdown');
|
|
1121
|
+
if (entityElement) {
|
|
1122
|
+
entityElement.dispatchEvent(new PointerEvent('pointerdown', event));
|
|
1046
1123
|
}
|
|
1047
1124
|
}
|
|
1048
1125
|
async _onPointerUp(event) {
|
|
1049
1126
|
if (!this._picker || !this.app)
|
|
1050
1127
|
return;
|
|
1051
1128
|
const node = await this._pickNode(event);
|
|
1052
|
-
if (!
|
|
1053
|
-
return;
|
|
1054
|
-
const entityElement = this.
|
|
1055
|
-
if (entityElement
|
|
1129
|
+
if (!this._picker)
|
|
1130
|
+
return; // the element disconnected while the pick was in flight
|
|
1131
|
+
const entityElement = this._elementWithListener(node, 'pointerup');
|
|
1132
|
+
if (entityElement) {
|
|
1056
1133
|
entityElement.dispatchEvent(new PointerEvent('pointerup', event));
|
|
1057
1134
|
}
|
|
1058
1135
|
}
|
|
@@ -1082,28 +1159,43 @@
|
|
|
1082
1159
|
}
|
|
1083
1160
|
}
|
|
1084
1161
|
/**
|
|
1085
|
-
*
|
|
1162
|
+
* Warns that a graphics option was written too late to have any effect. These options are read
|
|
1163
|
+
* once, when the element connects and creates its graphics device, so a later write updates
|
|
1164
|
+
* only the element's own property - silently, without this.
|
|
1165
|
+
*
|
|
1166
|
+
* @param name - The name of the option, as its attribute.
|
|
1167
|
+
*/
|
|
1168
|
+
_warnIfBooted(name) {
|
|
1169
|
+
if (this._optionsLocked) {
|
|
1170
|
+
console.warn(`Attribute '${name}' on <pc-app> is only read when the application boots, so this change has no effect. Set it before the element is connected, or remove and re-insert the element to reboot with the new value.`);
|
|
1171
|
+
}
|
|
1172
|
+
}
|
|
1173
|
+
/**
|
|
1174
|
+
* Sets whether the frame buffer has an alpha channel, which is what lets the page show through
|
|
1175
|
+
* wherever the scene has not drawn. Read only when the application boots.
|
|
1086
1176
|
* @param value - The alpha flag.
|
|
1087
1177
|
*/
|
|
1088
1178
|
set alpha(value) {
|
|
1179
|
+
this._warnIfBooted('alpha');
|
|
1089
1180
|
this._alpha = value;
|
|
1090
1181
|
}
|
|
1091
1182
|
/**
|
|
1092
|
-
* Gets the alpha
|
|
1183
|
+
* Gets whether the frame buffer has an alpha channel.
|
|
1093
1184
|
* @returns The alpha flag.
|
|
1094
1185
|
*/
|
|
1095
1186
|
get alpha() {
|
|
1096
1187
|
return this._alpha;
|
|
1097
1188
|
}
|
|
1098
1189
|
/**
|
|
1099
|
-
* Sets the
|
|
1190
|
+
* Sets whether the frame buffer is anti-aliased. Read only when the application boots.
|
|
1100
1191
|
* @param value - The antialias flag.
|
|
1101
1192
|
*/
|
|
1102
1193
|
set antialias(value) {
|
|
1194
|
+
this._warnIfBooted('antialias');
|
|
1103
1195
|
this._antialias = value;
|
|
1104
1196
|
}
|
|
1105
1197
|
/**
|
|
1106
|
-
* Gets the
|
|
1198
|
+
* Gets whether the frame buffer is anti-aliased.
|
|
1107
1199
|
* @returns The antialias flag.
|
|
1108
1200
|
*/
|
|
1109
1201
|
get antialias() {
|
|
@@ -1111,10 +1203,11 @@
|
|
|
1111
1203
|
}
|
|
1112
1204
|
/**
|
|
1113
1205
|
* Sets the graphics backend. Defaults to 'webgpu', which falls back to 'webgl2' if WebGPU
|
|
1114
|
-
* is not supported by the browser.
|
|
1206
|
+
* is not supported by the browser. Read only when the application boots.
|
|
1115
1207
|
* @param value - The graphics backend ('webgpu', 'webgl2', or 'null').
|
|
1116
1208
|
*/
|
|
1117
1209
|
set backend(value) {
|
|
1210
|
+
this._warnIfBooted('backend');
|
|
1118
1211
|
this._backend = value;
|
|
1119
1212
|
}
|
|
1120
1213
|
/**
|
|
@@ -1125,18 +1218,20 @@
|
|
|
1125
1218
|
return this._backend;
|
|
1126
1219
|
}
|
|
1127
1220
|
/**
|
|
1128
|
-
* Sets the depth
|
|
1129
|
-
*
|
|
1221
|
+
* Sets whether the frame buffer has a depth buffer, which the renderer needs to resolve which
|
|
1222
|
+
* surface is nearest the camera. Read only when the application boots.
|
|
1223
|
+
* @param value - The depth buffer flag.
|
|
1130
1224
|
*/
|
|
1131
|
-
set
|
|
1132
|
-
this.
|
|
1225
|
+
set depthBuffer(value) {
|
|
1226
|
+
this._warnIfBooted('depth-buffer');
|
|
1227
|
+
this._depthBuffer = value;
|
|
1133
1228
|
}
|
|
1134
1229
|
/**
|
|
1135
|
-
* Gets the depth
|
|
1136
|
-
* @returns The depth flag.
|
|
1230
|
+
* Gets whether the frame buffer has a depth buffer.
|
|
1231
|
+
* @returns The depth buffer flag.
|
|
1137
1232
|
*/
|
|
1138
|
-
get
|
|
1139
|
-
return this.
|
|
1233
|
+
get depthBuffer() {
|
|
1234
|
+
return this._depthBuffer;
|
|
1140
1235
|
}
|
|
1141
1236
|
/**
|
|
1142
1237
|
* Gets the hierarchy ready flag.
|
|
@@ -1146,24 +1241,6 @@
|
|
|
1146
1241
|
get hierarchyReady() {
|
|
1147
1242
|
return this._hierarchyReady;
|
|
1148
1243
|
}
|
|
1149
|
-
/**
|
|
1150
|
-
* Sets the high resolution flag. When true, the application will render at the device's
|
|
1151
|
-
* physical resolution. When false, the application will render at CSS resolution.
|
|
1152
|
-
* @param value - The high resolution flag.
|
|
1153
|
-
*/
|
|
1154
|
-
set highResolution(value) {
|
|
1155
|
-
this._highResolution = value;
|
|
1156
|
-
if (this.app) {
|
|
1157
|
-
this.app.graphicsDevice.maxPixelRatio = value ? window.devicePixelRatio : 1;
|
|
1158
|
-
}
|
|
1159
|
-
}
|
|
1160
|
-
/**
|
|
1161
|
-
* Gets the high resolution flag.
|
|
1162
|
-
* @returns The high resolution flag.
|
|
1163
|
-
*/
|
|
1164
|
-
get highResolution() {
|
|
1165
|
-
return this._highResolution;
|
|
1166
|
-
}
|
|
1167
1244
|
/**
|
|
1168
1245
|
* Sets whether the application shows its built-in loading bar while it boots and preloads its
|
|
1169
1246
|
* assets. Enabled by default; setting `false` removes the bar immediately, while setting
|
|
@@ -1188,21 +1265,45 @@
|
|
|
1188
1265
|
return this._loadingBar;
|
|
1189
1266
|
}
|
|
1190
1267
|
/**
|
|
1191
|
-
* Sets the
|
|
1192
|
-
*
|
|
1268
|
+
* Sets the cap on the pixel ratio the application renders at. The canvas is sized by the
|
|
1269
|
+
* smaller of this value and the display's own device pixel ratio, so the default of `Infinity`
|
|
1270
|
+
* renders at full physical resolution, `1` renders at CSS resolution, and an intermediate
|
|
1271
|
+
* value such as `2` keeps a dense display sharp without paying for every one of its pixels.
|
|
1272
|
+
* Must be greater than 0. Unlike the other graphics options, this applies immediately.
|
|
1273
|
+
* @param value - The maximum pixel ratio.
|
|
1274
|
+
*/
|
|
1275
|
+
set maxPixelRatio(value) {
|
|
1276
|
+
this._maxPixelRatio = value;
|
|
1277
|
+
if (this.app) {
|
|
1278
|
+
this.app.graphicsDevice.maxPixelRatio = value;
|
|
1279
|
+
this.app.resizeCanvas();
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1282
|
+
/**
|
|
1283
|
+
* Gets the cap on the pixel ratio the application renders at.
|
|
1284
|
+
* @returns The maximum pixel ratio.
|
|
1285
|
+
*/
|
|
1286
|
+
get maxPixelRatio() {
|
|
1287
|
+
return this._maxPixelRatio;
|
|
1288
|
+
}
|
|
1289
|
+
/**
|
|
1290
|
+
* Sets whether the frame buffer has a stencil buffer, which stencil-based effects and UI
|
|
1291
|
+
* masking need. Read only when the application boots.
|
|
1292
|
+
* @param value - The stencil buffer flag.
|
|
1193
1293
|
*/
|
|
1194
|
-
set
|
|
1195
|
-
this.
|
|
1294
|
+
set stencilBuffer(value) {
|
|
1295
|
+
this._warnIfBooted('stencil-buffer');
|
|
1296
|
+
this._stencilBuffer = value;
|
|
1196
1297
|
}
|
|
1197
1298
|
/**
|
|
1198
|
-
* Gets the stencil
|
|
1199
|
-
* @returns The stencil flag.
|
|
1299
|
+
* Gets whether the frame buffer has a stencil buffer.
|
|
1300
|
+
* @returns The stencil buffer flag.
|
|
1200
1301
|
*/
|
|
1201
|
-
get
|
|
1202
|
-
return this.
|
|
1302
|
+
get stencilBuffer() {
|
|
1303
|
+
return this._stencilBuffer;
|
|
1203
1304
|
}
|
|
1204
1305
|
static get observedAttributes() {
|
|
1205
|
-
return ['alpha', 'antialias', 'backend', 'depth', '
|
|
1306
|
+
return ['alpha', 'antialias', 'backend', 'depth-buffer', 'loading-bar', 'max-pixel-ratio', 'stencil-buffer'];
|
|
1206
1307
|
}
|
|
1207
1308
|
attributeChangedCallback(name, _oldValue, newValue) {
|
|
1208
1309
|
switch (name) {
|
|
@@ -1215,17 +1316,17 @@
|
|
|
1215
1316
|
case 'backend':
|
|
1216
1317
|
this.backend = parseEnum(newValue, ['webgpu', 'webgl2', 'null'], 'webgpu', name);
|
|
1217
1318
|
break;
|
|
1218
|
-
case 'depth':
|
|
1219
|
-
this.
|
|
1220
|
-
break;
|
|
1221
|
-
case 'high-resolution':
|
|
1222
|
-
this.highResolution = parseBool(newValue, true);
|
|
1319
|
+
case 'depth-buffer':
|
|
1320
|
+
this.depthBuffer = parseBool(newValue, true);
|
|
1223
1321
|
break;
|
|
1224
1322
|
case 'loading-bar':
|
|
1225
1323
|
this.loadingBar = parseBool(newValue, true);
|
|
1226
1324
|
break;
|
|
1227
|
-
case '
|
|
1228
|
-
this.
|
|
1325
|
+
case 'max-pixel-ratio':
|
|
1326
|
+
this.maxPixelRatio = parseNumber(newValue, Infinity, name);
|
|
1327
|
+
break;
|
|
1328
|
+
case 'stencil-buffer':
|
|
1329
|
+
this.stencilBuffer = parseBool(newValue, true);
|
|
1229
1330
|
break;
|
|
1230
1331
|
}
|
|
1231
1332
|
}
|
|
@@ -1294,6 +1395,11 @@
|
|
|
1294
1395
|
*/
|
|
1295
1396
|
_built = false;
|
|
1296
1397
|
_entity = null;
|
|
1398
|
+
/**
|
|
1399
|
+
* The application element this entity is registered with, cached at creation time so the
|
|
1400
|
+
* entity can be unregistered even once this element has left the DOM.
|
|
1401
|
+
*/
|
|
1402
|
+
_appElement = null;
|
|
1297
1403
|
/**
|
|
1298
1404
|
* The PlayCanvas entity instance. `null` until the element is ready, and again once it has
|
|
1299
1405
|
* been removed from the document — await {@link whenReady} or the element's `ready()`
|
|
@@ -1323,6 +1429,27 @@
|
|
|
1323
1429
|
if (this._tags.length > 0) {
|
|
1324
1430
|
entity.tags.add(this._tags);
|
|
1325
1431
|
}
|
|
1432
|
+
// Register with the owning application, which joins engine nodes back to elements by
|
|
1433
|
+
// identity (never by name), and hook the entity's destruction. The engine fires 'destroy'
|
|
1434
|
+
// for every entity in a destroyed subtree, so the element learns of its entity's death no
|
|
1435
|
+
// matter who causes it: this element, an ancestor, the whole application, or a user
|
|
1436
|
+
// script calling entity.destroy().
|
|
1437
|
+
this._appElement = this.closestApp;
|
|
1438
|
+
this._appElement?._registerEntityElement(entity, this);
|
|
1439
|
+
entity.once('destroy', this._onEntityDestroy, this);
|
|
1440
|
+
}
|
|
1441
|
+
/**
|
|
1442
|
+
* Handles the destruction of the backing entity. Resets the element so a later re-insertion
|
|
1443
|
+
* starts clean: `_built` must be cleared alongside `_entity`, or buildHierarchy would bail
|
|
1444
|
+
* and a re-created entity would never be parented.
|
|
1445
|
+
*
|
|
1446
|
+
* @param entity - The entity that was destroyed.
|
|
1447
|
+
*/
|
|
1448
|
+
_onEntityDestroy(entity) {
|
|
1449
|
+
this._appElement?._unregisterEntityElement(entity);
|
|
1450
|
+
this._appElement = null;
|
|
1451
|
+
this._entity = null;
|
|
1452
|
+
this._built = false;
|
|
1326
1453
|
}
|
|
1327
1454
|
buildHierarchy(app) {
|
|
1328
1455
|
if (!this.entity || this._built)
|
|
@@ -1365,22 +1492,11 @@
|
|
|
1365
1492
|
}
|
|
1366
1493
|
}
|
|
1367
1494
|
disconnectedCallback() {
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
// on re-insertion, so the descendant would get a fresh entity that is never parented.
|
|
1374
|
-
const children = this.querySelectorAll('pc-entity');
|
|
1375
|
-
children.forEach((child) => {
|
|
1376
|
-
child._entity = null;
|
|
1377
|
-
child._built = false;
|
|
1378
|
-
});
|
|
1379
|
-
// Destroy the entity
|
|
1380
|
-
this.entity.destroy();
|
|
1381
|
-
this._entity = null;
|
|
1382
|
-
this._built = false;
|
|
1383
|
-
}
|
|
1495
|
+
// Destroying the entity destroys its whole subtree, and the engine fires 'destroy' for
|
|
1496
|
+
// every entity in it - so _onEntityDestroy resets this element AND every descendant
|
|
1497
|
+
// element before the descendants' own disconnectedCallbacks run. Their entities are null
|
|
1498
|
+
// by then, making this call a no-op for them.
|
|
1499
|
+
this._entity?.destroy();
|
|
1384
1500
|
}
|
|
1385
1501
|
/**
|
|
1386
1502
|
* Sets the enabled state of the entity.
|
|
@@ -2527,6 +2643,10 @@
|
|
|
2527
2643
|
}
|
|
2528
2644
|
customElements.define('pc-button', ButtonComponentElement);
|
|
2529
2645
|
|
|
2646
|
+
const projections = new Map([
|
|
2647
|
+
['perspective', playcanvas.PROJECTION_PERSPECTIVE],
|
|
2648
|
+
['orthographic', playcanvas.PROJECTION_ORTHOGRAPHIC]
|
|
2649
|
+
]);
|
|
2530
2650
|
const tonemaps = new Map([
|
|
2531
2651
|
['none', playcanvas.TONEMAP_NONE],
|
|
2532
2652
|
['linear', playcanvas.TONEMAP_LINEAR],
|
|
@@ -2557,7 +2677,7 @@
|
|
|
2557
2677
|
_gamma = 'srgb';
|
|
2558
2678
|
_horizontalFov = false;
|
|
2559
2679
|
_nearClip = 0.1;
|
|
2560
|
-
|
|
2680
|
+
_projection = 'perspective';
|
|
2561
2681
|
_orthoHeight = 10;
|
|
2562
2682
|
_priority = 0;
|
|
2563
2683
|
_rect = new playcanvas.Vec4(0, 0, 1, 1);
|
|
@@ -2581,12 +2701,12 @@
|
|
|
2581
2701
|
gammaCorrection: this._gamma === 'srgb' ? playcanvas.GAMMA_SRGB : playcanvas.GAMMA_NONE,
|
|
2582
2702
|
horizontalFov: this._horizontalFov,
|
|
2583
2703
|
nearClip: this._nearClip,
|
|
2584
|
-
projection: this.
|
|
2704
|
+
projection: projections.get(this._projection) ?? playcanvas.PROJECTION_PERSPECTIVE,
|
|
2585
2705
|
orthoHeight: this._orthoHeight,
|
|
2586
2706
|
priority: this._priority,
|
|
2587
2707
|
rect: this._rect,
|
|
2588
2708
|
scissorRect: this._scissorRect,
|
|
2589
|
-
toneMapping: tonemaps.get(this._tonemap)
|
|
2709
|
+
toneMapping: tonemaps.get(this._tonemap) ?? playcanvas.TONEMAP_NONE
|
|
2590
2710
|
};
|
|
2591
2711
|
}
|
|
2592
2712
|
get xrAvailable() {
|
|
@@ -2828,23 +2948,6 @@
|
|
|
2828
2948
|
get nearClip() {
|
|
2829
2949
|
return this._nearClip;
|
|
2830
2950
|
}
|
|
2831
|
-
/**
|
|
2832
|
-
* Sets the orthographic projection of the camera.
|
|
2833
|
-
* @param value - The orthographic projection.
|
|
2834
|
-
*/
|
|
2835
|
-
set orthographic(value) {
|
|
2836
|
-
this._orthographic = value;
|
|
2837
|
-
if (this.component) {
|
|
2838
|
-
this.component.projection = value ? playcanvas.PROJECTION_ORTHOGRAPHIC : playcanvas.PROJECTION_PERSPECTIVE;
|
|
2839
|
-
}
|
|
2840
|
-
}
|
|
2841
|
-
/**
|
|
2842
|
-
* Gets the orthographic projection of the camera.
|
|
2843
|
-
* @returns The orthographic projection.
|
|
2844
|
-
*/
|
|
2845
|
-
get orthographic() {
|
|
2846
|
-
return this._orthographic;
|
|
2847
|
-
}
|
|
2848
2951
|
/**
|
|
2849
2952
|
* Sets the orthographic height of the camera.
|
|
2850
2953
|
* @param value - The orthographic height.
|
|
@@ -2879,6 +2982,23 @@
|
|
|
2879
2982
|
get priority() {
|
|
2880
2983
|
return this._priority;
|
|
2881
2984
|
}
|
|
2985
|
+
/**
|
|
2986
|
+
* Sets the projection of the camera. Use `orthoHeight` to size an orthographic projection.
|
|
2987
|
+
* @param value - The projection ('perspective' or 'orthographic').
|
|
2988
|
+
*/
|
|
2989
|
+
set projection(value) {
|
|
2990
|
+
this._projection = value;
|
|
2991
|
+
if (this.component) {
|
|
2992
|
+
this.component.projection = projections.get(value) ?? playcanvas.PROJECTION_PERSPECTIVE;
|
|
2993
|
+
}
|
|
2994
|
+
}
|
|
2995
|
+
/**
|
|
2996
|
+
* Gets the projection of the camera.
|
|
2997
|
+
* @returns The projection.
|
|
2998
|
+
*/
|
|
2999
|
+
get projection() {
|
|
3000
|
+
return this._projection;
|
|
3001
|
+
}
|
|
2882
3002
|
/**
|
|
2883
3003
|
* Sets the rect of the camera.
|
|
2884
3004
|
* @param value - The rect.
|
|
@@ -2945,9 +3065,9 @@
|
|
|
2945
3065
|
'gamma',
|
|
2946
3066
|
'horizontal-fov',
|
|
2947
3067
|
'near-clip',
|
|
2948
|
-
'orthographic',
|
|
2949
3068
|
'ortho-height',
|
|
2950
3069
|
'priority',
|
|
3070
|
+
'projection',
|
|
2951
3071
|
'rect',
|
|
2952
3072
|
'scissor-rect',
|
|
2953
3073
|
'tonemap'
|
|
@@ -2992,15 +3112,15 @@
|
|
|
2992
3112
|
case 'near-clip':
|
|
2993
3113
|
this.nearClip = parseNumber(newValue, 0.1, name);
|
|
2994
3114
|
break;
|
|
2995
|
-
case 'orthographic':
|
|
2996
|
-
this.orthographic = parseBool(newValue, false);
|
|
2997
|
-
break;
|
|
2998
3115
|
case 'ortho-height':
|
|
2999
3116
|
this.orthoHeight = parseNumber(newValue, 10, name);
|
|
3000
3117
|
break;
|
|
3001
3118
|
case 'priority':
|
|
3002
3119
|
this.priority = parseNumber(newValue, 0, name);
|
|
3003
3120
|
break;
|
|
3121
|
+
case 'projection':
|
|
3122
|
+
this.projection = parseEnum(newValue, projections, 'perspective', name);
|
|
3123
|
+
break;
|
|
3004
3124
|
case 'rect':
|
|
3005
3125
|
this.rect = parseVec4(newValue, new playcanvas.Vec4(0, 0, 1, 1), name);
|
|
3006
3126
|
break;
|
|
@@ -7418,6 +7538,14 @@
|
|
|
7418
7538
|
}
|
|
7419
7539
|
customElements.define('pc-rigidbody', RigidBodyComponentElement);
|
|
7420
7540
|
|
|
7541
|
+
// The engine's SCALEMODE_* constants are the strings 'none' and 'blend', so this map happens to be
|
|
7542
|
+
// an identity. It is still the right shape: it supplies parseEnum's valid-name list, it is what the
|
|
7543
|
+
// manifest generator reads the enum values from, and it keeps the attribute vocabulary independent
|
|
7544
|
+
// of constants the engine is free to change.
|
|
7545
|
+
const scaleModes = new Map([
|
|
7546
|
+
['none', playcanvas.SCALEMODE_NONE],
|
|
7547
|
+
['blend', playcanvas.SCALEMODE_BLEND]
|
|
7548
|
+
]);
|
|
7421
7549
|
/**
|
|
7422
7550
|
* The ScreenComponentElement interface provides properties and methods for manipulating
|
|
7423
7551
|
* {@link https://developer.playcanvas.com/user-manual/web-components/tags/pc-screen/ | `<pc-screen>`} elements.
|
|
@@ -7431,7 +7559,7 @@
|
|
|
7431
7559
|
_resolution = new playcanvas.Vec2(640, 320);
|
|
7432
7560
|
_referenceResolution = new playcanvas.Vec2(640, 320);
|
|
7433
7561
|
_priority = 0;
|
|
7434
|
-
|
|
7562
|
+
_scaleMode = 'none';
|
|
7435
7563
|
_scaleBlend = 0.5;
|
|
7436
7564
|
/** @ignore */
|
|
7437
7565
|
constructor() {
|
|
@@ -7443,7 +7571,7 @@
|
|
|
7443
7571
|
referenceResolution: this._referenceResolution,
|
|
7444
7572
|
resolution: this._resolution,
|
|
7445
7573
|
scaleBlend: this._scaleBlend,
|
|
7446
|
-
scaleMode: this.
|
|
7574
|
+
scaleMode: scaleModes.get(this._scaleMode) ?? playcanvas.SCALEMODE_NONE,
|
|
7447
7575
|
screenSpace: this._screenSpace
|
|
7448
7576
|
};
|
|
7449
7577
|
}
|
|
@@ -7481,23 +7609,44 @@
|
|
|
7481
7609
|
get resolution() {
|
|
7482
7610
|
return this._resolution;
|
|
7483
7611
|
}
|
|
7612
|
+
/**
|
|
7613
|
+
* Sets how the screen's `resolution` and `referenceResolution` are weighted against each other
|
|
7614
|
+
* when `scaleMode` is `blend`, from 0 (follow the resolution) to 1 (follow the reference
|
|
7615
|
+
* resolution). Ignored while `scaleMode` is `none`.
|
|
7616
|
+
* @param value - The scale blend factor.
|
|
7617
|
+
*/
|
|
7484
7618
|
set scaleBlend(value) {
|
|
7485
7619
|
this._scaleBlend = value;
|
|
7486
7620
|
if (this.component) {
|
|
7487
7621
|
this.component.scaleBlend = this._scaleBlend;
|
|
7488
7622
|
}
|
|
7489
7623
|
}
|
|
7624
|
+
/**
|
|
7625
|
+
* Gets how the screen's resolutions are weighted against each other.
|
|
7626
|
+
* @returns The scale blend factor.
|
|
7627
|
+
*/
|
|
7490
7628
|
get scaleBlend() {
|
|
7491
7629
|
return this._scaleBlend;
|
|
7492
7630
|
}
|
|
7493
|
-
|
|
7494
|
-
|
|
7631
|
+
/**
|
|
7632
|
+
* Sets how the screen scales its contents. `none` renders at `resolution` and ignores
|
|
7633
|
+
* `referenceResolution`; `blend` scales between the two, weighted by `scaleBlend`, which is what
|
|
7634
|
+
* keeps a UI laid out at one resolution usable at another. Requires `screenSpace` - the engine
|
|
7635
|
+
* forces `none` on a world-space screen, which does not support scaling.
|
|
7636
|
+
* @param value - The scale mode ('none' or 'blend').
|
|
7637
|
+
*/
|
|
7638
|
+
set scaleMode(value) {
|
|
7639
|
+
this._scaleMode = value;
|
|
7495
7640
|
if (this.component) {
|
|
7496
|
-
this.component.scaleMode =
|
|
7641
|
+
this.component.scaleMode = scaleModes.get(value) ?? playcanvas.SCALEMODE_NONE;
|
|
7497
7642
|
}
|
|
7498
7643
|
}
|
|
7499
|
-
|
|
7500
|
-
|
|
7644
|
+
/**
|
|
7645
|
+
* Gets how the screen scales its contents.
|
|
7646
|
+
* @returns The scale mode.
|
|
7647
|
+
*/
|
|
7648
|
+
get scaleMode() {
|
|
7649
|
+
return this._scaleMode;
|
|
7501
7650
|
}
|
|
7502
7651
|
set screenSpace(value) {
|
|
7503
7652
|
this._screenSpace = value;
|
|
@@ -7511,12 +7660,12 @@
|
|
|
7511
7660
|
static get observedAttributes() {
|
|
7512
7661
|
return [
|
|
7513
7662
|
...super.observedAttributes,
|
|
7514
|
-
'blend',
|
|
7515
7663
|
'screen-space',
|
|
7516
7664
|
'resolution',
|
|
7517
7665
|
'reference-resolution',
|
|
7518
7666
|
'priority',
|
|
7519
|
-
'scale-blend'
|
|
7667
|
+
'scale-blend',
|
|
7668
|
+
'scale-mode'
|
|
7520
7669
|
];
|
|
7521
7670
|
}
|
|
7522
7671
|
attributeChangedCallback(name, _oldValue, newValue) {
|
|
@@ -7534,8 +7683,8 @@
|
|
|
7534
7683
|
case 'scale-blend':
|
|
7535
7684
|
this.scaleBlend = parseNumber(newValue, 0.5, name);
|
|
7536
7685
|
break;
|
|
7537
|
-
case '
|
|
7538
|
-
this.
|
|
7686
|
+
case 'scale-mode':
|
|
7687
|
+
this.scaleMode = parseEnum(newValue, scaleModes, 'none', name);
|
|
7539
7688
|
break;
|
|
7540
7689
|
case 'screen-space':
|
|
7541
7690
|
this.screenSpace = parseBool(newValue, false);
|
|
@@ -7758,7 +7907,8 @@
|
|
|
7758
7907
|
return super.component;
|
|
7759
7908
|
}
|
|
7760
7909
|
/**
|
|
7761
|
-
* Sets whether horizontal
|
|
7910
|
+
* Sets whether scrolling along the horizontal axis is enabled. This is a toggle, unlike the
|
|
7911
|
+
* `orientation` of a `<pc-scrollbar>`, for which `horizontal` is one of the accepted values.
|
|
7762
7912
|
* @param value - Whether horizontal scrolling is enabled.
|
|
7763
7913
|
*/
|
|
7764
7914
|
set horizontal(value) {
|
|
@@ -7768,14 +7918,15 @@
|
|
|
7768
7918
|
}
|
|
7769
7919
|
}
|
|
7770
7920
|
/**
|
|
7771
|
-
* Gets whether horizontal
|
|
7921
|
+
* Gets whether scrolling along the horizontal axis is enabled.
|
|
7772
7922
|
* @returns Whether horizontal scrolling is enabled.
|
|
7773
7923
|
*/
|
|
7774
7924
|
get horizontal() {
|
|
7775
7925
|
return this._horizontal;
|
|
7776
7926
|
}
|
|
7777
7927
|
/**
|
|
7778
|
-
* Sets whether vertical
|
|
7928
|
+
* Sets whether scrolling along the vertical axis is enabled. This is a toggle, unlike the
|
|
7929
|
+
* `orientation` of a `<pc-scrollbar>`, for which `vertical` is one of the accepted values.
|
|
7779
7930
|
* @param value - Whether vertical scrolling is enabled.
|
|
7780
7931
|
*/
|
|
7781
7932
|
set vertical(value) {
|
|
@@ -7785,7 +7936,7 @@
|
|
|
7785
7936
|
}
|
|
7786
7937
|
}
|
|
7787
7938
|
/**
|
|
7788
|
-
* Gets whether vertical
|
|
7939
|
+
* Gets whether scrolling along the vertical axis is enabled.
|
|
7789
7940
|
* @returns Whether vertical scrolling is enabled.
|
|
7790
7941
|
*/
|
|
7791
7942
|
get vertical() {
|
|
@@ -9775,7 +9926,7 @@
|
|
|
9775
9926
|
_center = new playcanvas.Vec3(0, 0.01, 0);
|
|
9776
9927
|
_intensity = 1;
|
|
9777
9928
|
_rotation = new playcanvas.Vec3();
|
|
9778
|
-
|
|
9929
|
+
_mipLevel = 0;
|
|
9779
9930
|
_lighting = false;
|
|
9780
9931
|
_scale = new playcanvas.Vec3(100, 100, 100);
|
|
9781
9932
|
_type = 'infinite';
|
|
@@ -9809,7 +9960,7 @@
|
|
|
9809
9960
|
this._scene.sky.node.setLocalScale(this._scale);
|
|
9810
9961
|
this._scene.sky.center = this._center;
|
|
9811
9962
|
this._scene.skyboxIntensity = this._intensity;
|
|
9812
|
-
this._scene.skyboxMip = this.
|
|
9963
|
+
this._scene.skyboxMip = this._mipLevel;
|
|
9813
9964
|
}
|
|
9814
9965
|
async _loadSkybox() {
|
|
9815
9966
|
const appElement = await this.closestApp?.ready();
|
|
@@ -9901,23 +10052,6 @@
|
|
|
9901
10052
|
get intensity() {
|
|
9902
10053
|
return this._intensity;
|
|
9903
10054
|
}
|
|
9904
|
-
/**
|
|
9905
|
-
* Sets the mip level of the skybox.
|
|
9906
|
-
* @param value - The mip level.
|
|
9907
|
-
*/
|
|
9908
|
-
set level(value) {
|
|
9909
|
-
this._level = value;
|
|
9910
|
-
if (this._scene) {
|
|
9911
|
-
this._scene.skyboxMip = this._level;
|
|
9912
|
-
}
|
|
9913
|
-
}
|
|
9914
|
-
/**
|
|
9915
|
-
* Gets the mip level of the skybox.
|
|
9916
|
-
* @returns The mip level.
|
|
9917
|
-
*/
|
|
9918
|
-
get level() {
|
|
9919
|
-
return this._level;
|
|
9920
|
-
}
|
|
9921
10055
|
/**
|
|
9922
10056
|
* Sets whether the skybox is used as a light source.
|
|
9923
10057
|
* @param value - Whether to use lighting.
|
|
@@ -9932,6 +10066,24 @@
|
|
|
9932
10066
|
get lighting() {
|
|
9933
10067
|
return this._lighting;
|
|
9934
10068
|
}
|
|
10069
|
+
/**
|
|
10070
|
+
* Sets the mip level of the skybox, where 0 is the sharpest. Raising it selects a blurrier mip,
|
|
10071
|
+
* which is how a skybox is softened without blurring the texture itself.
|
|
10072
|
+
* @param value - The mip level.
|
|
10073
|
+
*/
|
|
10074
|
+
set mipLevel(value) {
|
|
10075
|
+
this._mipLevel = value;
|
|
10076
|
+
if (this._scene) {
|
|
10077
|
+
this._scene.skyboxMip = this._mipLevel;
|
|
10078
|
+
}
|
|
10079
|
+
}
|
|
10080
|
+
/**
|
|
10081
|
+
* Gets the mip level of the skybox.
|
|
10082
|
+
* @returns The mip level.
|
|
10083
|
+
*/
|
|
10084
|
+
get mipLevel() {
|
|
10085
|
+
return this._mipLevel;
|
|
10086
|
+
}
|
|
9935
10087
|
/**
|
|
9936
10088
|
* Sets the Euler rotation of the skybox.
|
|
9937
10089
|
* @param value - The rotation.
|
|
@@ -9988,7 +10140,7 @@
|
|
|
9988
10140
|
return this._type;
|
|
9989
10141
|
}
|
|
9990
10142
|
static get observedAttributes() {
|
|
9991
|
-
return ['asset', 'center', 'intensity', '
|
|
10143
|
+
return ['asset', 'center', 'intensity', 'lighting', 'mip-level', 'rotation', 'scale', 'type'];
|
|
9992
10144
|
}
|
|
9993
10145
|
attributeChangedCallback(name, _oldValue, newValue) {
|
|
9994
10146
|
switch (name) {
|
|
@@ -10001,12 +10153,12 @@
|
|
|
10001
10153
|
case 'intensity':
|
|
10002
10154
|
this.intensity = parseNumber(newValue, 1, name);
|
|
10003
10155
|
break;
|
|
10004
|
-
case 'level':
|
|
10005
|
-
this.level = parseNumber(newValue, 0, name);
|
|
10006
|
-
break;
|
|
10007
10156
|
case 'lighting':
|
|
10008
10157
|
this.lighting = parseBool(newValue, false);
|
|
10009
10158
|
break;
|
|
10159
|
+
case 'mip-level':
|
|
10160
|
+
this.mipLevel = parseNumber(newValue, 0, name);
|
|
10161
|
+
break;
|
|
10010
10162
|
case 'rotation':
|
|
10011
10163
|
this.rotation = parseVec3(newValue, playcanvas.Vec3.ZERO, name);
|
|
10012
10164
|
break;
|