@playcanvas/web-components 0.13.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app.d.cts +35 -0
- package/dist/app.d.ts +35 -0
- package/dist/asset.d.cts +7 -1
- package/dist/asset.d.ts +7 -1
- package/dist/colors.d.cts +1 -1
- package/dist/colors.d.ts +1 -1
- package/dist/custom-elements.json +114 -1
- package/dist/entity-base.d.cts +1 -7
- package/dist/entity-base.d.ts +1 -7
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/loading-bar.d.cts +1 -35
- package/dist/loading-bar.d.ts +1 -35
- package/dist/material.d.cts +13 -0
- package/dist/material.d.ts +13 -0
- package/dist/model.d.cts +71 -0
- package/dist/model.d.ts +71 -0
- package/dist/node.d.cts +55 -0
- package/dist/node.d.ts +55 -0
- package/dist/parse.d.cts +1 -130
- package/dist/parse.d.ts +1 -130
- package/dist/pwc.cjs +506 -54
- package/dist/pwc.cjs.map +1 -1
- package/dist/pwc.js +506 -54
- 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 +506 -54
- package/dist/pwc.mjs.map +1 -1
- package/dist/vscode.html-custom-data.json +12 -2
- package/dist/web-types.json +22 -3
- package/package.json +3 -3
- package/src/app.ts +92 -19
- package/src/asset.ts +34 -2
- package/src/colors.ts +5 -0
- package/src/components/button-component.ts +7 -7
- package/src/components/element-component.ts +7 -7
- package/src/components/gsplat-component.ts +3 -3
- package/src/components/particlesystem-component.ts +7 -8
- package/src/components/script-component.ts +2 -2
- package/src/components/sound-slot.ts +2 -2
- package/src/entity-base.ts +3 -3
- package/src/index.ts +2 -0
- package/src/loading-bar.ts +2 -3
- package/src/material.ts +31 -2
- package/src/model.ts +158 -5
- package/src/node.ts +277 -2
- package/src/parse.ts +11 -1
- package/src/sky.ts +2 -3
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
},
|
|
51
51
|
{
|
|
52
52
|
"name": "pc-asset",
|
|
53
|
-
"description": "The AssetElement interface provides properties and methods for manipulating\n[`<pc-asset>`](https://developer.playcanvas.com/user-manual/web-components/tags/pc-asset/) elements.\nThe AssetElement interface also inherits the properties and methods of the\nHTMLElement interface.\n\nThe element becomes ready once the containing application has started and the asset is in the\nstate declared by the markup: loaded for preloaded assets (even if loading failed — check the\nasset's `resource`), or registered and awaiting a load for `lazy` assets. Elements inserted\nwhile the application is running are created and registered on insertion, and begin loading\nimmediately unless `lazy`. A `pc-asset` must be a direct child of `pc-app` — elements placed\nelsewhere, or with an unsupported asset type, never become ready.\n\nFor `texture` and `textureatlas` assets, the texture options (`address-u`, `address-v`,\n`min-filter`, `mag-filter`, `anisotropy`, `mipmaps`, `srgb`, `flip-y`) apply when the texture is\ncreated and — like `lazy` — are observed: changing one updates a texture that has already\nloaded, and removing one restores the engine default. Changing `srgb` or `mipmaps` on a loaded\ntexture recreates the underlying GPU resource, so prefer declaring those up front. Each option\noverrides the matching key in the `data` JSON; options left unset write nothing, leaving the\nengine's per-format defaults in force.\n\nApart from `lazy` and the texture options, these attributes are read once when the asset is\ncreated, so changing them later has no effect.\n\n---\n\n\n### **Events:**\n - **error** - Fired when the asset fails to load, with the engine's error in `message`. Does not bubble. The element still becomes ready — readiness means the load settled, not that it succeeded.\n- **load** - Fired each time the asset finishes loading, including a `lazy` asset loaded later and any subsequent reloads. Does not bubble — listen on this element, or use a capture-phase listener on an ancestor to observe every asset.\n- **ready** - Fired when the element is fully initialized — once per readiness cycle, so an element that is torn down and re-initialized (for example by removing and re-inserting it) fires it again. Bubbles and is composed.\n\n### **Methods:**\n - **get(id: _string_): __** - Returns the Asset created by the `<pc-asset>` element with the given `id`, or\n`undefined` if there is no such element or its asset has not been created yet.\n- **ready(): __** - Returns a promise that resolves with this element when it's ready. This is the low-level\nprimitive underlying whenReady, which is the recommended way to wait for elements.\n\nReadiness tracks the element's current lifecycle: once a ready element is torn down (for\nexample by removing it from the document), this returns a fresh promise that resolves when\nthe element is next ready. A promise obtained earlier stays resolved — call this again\nafter re-inserting an element rather than reusing a promise from before its removal.",
|
|
53
|
+
"description": "The AssetElement interface provides properties and methods for manipulating\n[`<pc-asset>`](https://developer.playcanvas.com/user-manual/web-components/tags/pc-asset/) elements.\nThe AssetElement interface also inherits the properties and methods of the\nHTMLElement interface.\n\nThe element becomes ready once the containing application has started and the asset is in the\nstate declared by the markup: loaded for preloaded assets (even if loading failed — check the\nasset's `resource`), or registered and awaiting a load for `lazy` assets. Elements inserted\nwhile the application is running are created and registered on insertion, and begin loading\nimmediately unless `lazy`. A `pc-asset` must be a direct child of `pc-app` — elements placed\nelsewhere, or with an unsupported asset type, never become ready.\n\nA `lazy` asset loads on first use: the first time any element resolves it by `id` — a model,\na material map, a sky, a script `asset:` reference — or when the `lazy` attribute is removed,\nwhichever comes first. Until then it stays registered and unloaded.\n\nFor `texture` and `textureatlas` assets, the texture options (`address-u`, `address-v`,\n`min-filter`, `mag-filter`, `anisotropy`, `mipmaps`, `srgb`, `flip-y`) apply when the texture is\ncreated and — like `lazy` — are observed: changing one updates a texture that has already\nloaded, and removing one restores the engine default. Changing `srgb` or `mipmaps` on a loaded\ntexture recreates the underlying GPU resource, so prefer declaring those up front. Each option\noverrides the matching key in the `data` JSON; options left unset write nothing, leaving the\nengine's per-format defaults in force.\n\nApart from `lazy` and the texture options, these attributes are read once when the asset is\ncreated, so changing them later has no effect.\n\n---\n\n\n### **Events:**\n - **error** - Fired when the asset fails to load, with the engine's error in `message`. Does not bubble. The element still becomes ready — readiness means the load settled, not that it succeeded.\n- **load** - Fired each time the asset finishes loading, including a `lazy` asset loaded later and any subsequent reloads. Does not bubble — listen on this element, or use a capture-phase listener on an ancestor to observe every asset.\n- **ready** - Fired when the element is fully initialized — once per readiness cycle, so an element that is torn down and re-initialized (for example by removing and re-inserting it) fires it again. Bubbles and is composed.\n\n### **Methods:**\n - **get(id: _string_): __** - Returns the Asset created by the `<pc-asset>` element with the given `id`, or\n`undefined` if there is no such element or its asset has not been created yet.\n- **ready(): __** - Returns a promise that resolves with this element when it's ready. This is the low-level\nprimitive underlying whenReady, which is the recommended way to wait for elements.\n\nReadiness tracks the element's current lifecycle: once a ready element is torn down (for\nexample by removing it from the document), this returns a fresh promise that resolves when\nthe element is next ready. A promise obtained earlier stays resolved — call this again\nafter re-inserting an element rather than reusing a promise from before its removal.",
|
|
54
54
|
"attributes": [
|
|
55
55
|
{
|
|
56
56
|
"name": "address-u",
|
|
@@ -544,6 +544,11 @@
|
|
|
544
544
|
"description": "The UV channel the metalness map samples.",
|
|
545
545
|
"values": []
|
|
546
546
|
},
|
|
547
|
+
{
|
|
548
|
+
"name": "name",
|
|
549
|
+
"description": "The name of the material - the label shown wherever materials surface by name, such as profilers, GPU captures and the assignments `pc-model.hierarchy()` reports.",
|
|
550
|
+
"values": []
|
|
551
|
+
},
|
|
547
552
|
{
|
|
548
553
|
"name": "normal-map",
|
|
549
554
|
"description": "The id of the `pc-asset` used as the normal map.",
|
|
@@ -698,7 +703,7 @@
|
|
|
698
703
|
},
|
|
699
704
|
{
|
|
700
705
|
"name": "pc-model",
|
|
701
|
-
"description": "The ModelElement interface provides properties and methods for manipulating\n[`<pc-model>`](https://developer.playcanvas.com/user-manual/web-components/tags/pc-model/) elements.\nThe ModelElement interface also inherits the properties and methods of the\nHTMLElement interface.\n\nThe element becomes ready once its container asset has loaded and the instantiated hierarchy has\nbeen added to the scene — `entity` is non-null by then. A failed load also settles readiness,\nwith `entity` remaining `null`: readiness means the load settled, not that it succeeded — listen\nfor `error`, or check `entity`, to tell the outcomes apart. Changing `asset` re-arms readiness\nand instantiates anew, so a `ready()` obtained after the change resolves against the new\nhierarchy. A `pc-model` outside a `pc-app`, or referencing an unknown asset id, warns and never\nbecomes ready.\n\n---\n\n\n### **Events:**\n - **error** - Fired when the container asset fails to load, with the engine's error in `message`. Does not bubble. The element still becomes ready — readiness means the load settled, not that it succeeded.\n- **load** - Fired each time a container asset finishes instantiating, including re-instantiation after `asset` changes. Does not bubble — listen on this element, or use a capture-phase listener on an ancestor.\n- **ready** - Fired when the element is fully initialized — once per readiness cycle, so an element that is torn down and re-initialized (for example by removing and re-inserting it) fires it again. Bubbles and is composed.\n\n### **Methods:**\n - **ready(): __** - Returns a promise that resolves with this element when it's ready. This is the low-level\nprimitive underlying whenReady, which is the recommended way to wait for elements.\n\nReadiness tracks the element's current lifecycle: once a ready element is torn down (for\nexample by removing it from the document), this returns a fresh promise that resolves when\nthe element is next ready. A promise obtained earlier stays resolved — call this again\nafter re-inserting an element rather than reusing a promise from before its removal.",
|
|
706
|
+
"description": "The ModelElement interface provides properties and methods for manipulating\n[`<pc-model>`](https://developer.playcanvas.com/user-manual/web-components/tags/pc-model/) elements.\nThe ModelElement interface also inherits the properties and methods of the\nHTMLElement interface.\n\nThe element becomes ready once its container asset has loaded and the instantiated hierarchy has\nbeen added to the scene — `entity` is non-null by then. A failed load also settles readiness,\nwith `entity` remaining `null`: readiness means the load settled, not that it succeeded — listen\nfor `error`, or check `entity`, to tell the outcomes apart. Changing `asset` re-arms readiness\nand instantiates anew, so a `ready()` obtained after the change resolves against the new\nhierarchy. A `pc-model` outside a `pc-app`, or referencing an unknown asset id, warns and never\nbecomes ready.\n\n---\n\n\n### **Events:**\n - **error** - Fired when the container asset fails to load, with the engine's error in `message`. Does not bubble. The element still becomes ready — readiness means the load settled, not that it succeeded.\n- **load** - Fired each time a container asset finishes instantiating, including re-instantiation after `asset` changes. Does not bubble — listen on this element, or use a capture-phase listener on an ancestor.\n- **ready** - Fired when the element is fully initialized — once per readiness cycle, so an element that is torn down and re-initialized (for example by removing and re-inserting it) fires it again. Bubbles and is composed.\n\n### **Methods:**\n - **hierarchy(): __** - Returns a snapshot of the instantiated node tree, or `null` while there is none (the\ncontainer asset has not loaded, or the element has left the document). One call grounds a\nsession — a browser console, a test, an agent — in the vocabulary `pc-node` binding\nresolves against: the instantiated names (HierarchyNode.name), paths, match\nindices, attached component types and the material assignments of render components\n(HierarchyNode.materials). `String(...)` of the result, or of any node in it,\nis the printable form.\n\nThe snapshot is plain data, computed afresh each call: it does not follow later changes\nto the hierarchy, and mutating it changes nothing.\n- **ready(): __** - Returns a promise that resolves with this element when it's ready. This is the low-level\nprimitive underlying whenReady, which is the recommended way to wait for elements.\n\nReadiness tracks the element's current lifecycle: once a ready element is torn down (for\nexample by removing it from the document), this returns a fresh promise that resolves when\nthe element is next ready. A promise obtained earlier stays resolved — call this again\nafter re-inserting an element rather than reusing a promise from before its removal.",
|
|
702
707
|
"attributes": [
|
|
703
708
|
{
|
|
704
709
|
"name": "asset",
|
|
@@ -749,6 +754,11 @@
|
|
|
749
754
|
"description": "Which match to bind when `name` matches more than one node, 0-based in depth-first order. Optional for a unique match; required for an ambiguous one.",
|
|
750
755
|
"values": []
|
|
751
756
|
},
|
|
757
|
+
{
|
|
758
|
+
"name": "material-overrides",
|
|
759
|
+
"description": "Overrides material assignments on the bound node's render component, as a JSON object from selector to `pc-material` id — for example `{\"name:CarPaint\": \"candy-red\", \"index:7\": \"smoked-glass\"}`. A `name:X` key selects every mesh instance whose baseline material is named `X`; an `index:N` key selects mesh instance `N` and wins over a name rule for the same instance. Assignments no rule matches keep their baseline materials, and removing the attribute restores all of them. Use `pc-model.hierarchy()` to discover the names and indices a node offers.",
|
|
760
|
+
"values": []
|
|
761
|
+
},
|
|
752
762
|
{
|
|
753
763
|
"name": "name",
|
|
754
764
|
"description": "The name of the node to bind, resolved within the nearest ancestor `pc-model` (or `pc-node`) once it has instantiated.",
|
package/dist/web-types.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://raw.githubusercontent.com/JetBrains/web-types/master/schema/web-types.json",
|
|
3
3
|
"name": "@playcanvas/web-components",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.14.0",
|
|
5
5
|
"description-markup": "markdown",
|
|
6
6
|
"contributions": {
|
|
7
7
|
"html": {
|
|
@@ -139,7 +139,7 @@
|
|
|
139
139
|
},
|
|
140
140
|
{
|
|
141
141
|
"name": "pc-asset",
|
|
142
|
-
"description": "The AssetElement interface provides properties and methods for manipulating\n[`<pc-asset>`](https://developer.playcanvas.com/user-manual/web-components/tags/pc-asset/) elements.\nThe AssetElement interface also inherits the properties and methods of the\nHTMLElement interface.\n\nThe element becomes ready once the containing application has started and the asset is in the\nstate declared by the markup: loaded for preloaded assets (even if loading failed — check the\nasset's `resource`), or registered and awaiting a load for `lazy` assets. Elements inserted\nwhile the application is running are created and registered on insertion, and begin loading\nimmediately unless `lazy`. A `pc-asset` must be a direct child of `pc-app` — elements placed\nelsewhere, or with an unsupported asset type, never become ready.\n\nFor `texture` and `textureatlas` assets, the texture options (`address-u`, `address-v`,\n`min-filter`, `mag-filter`, `anisotropy`, `mipmaps`, `srgb`, `flip-y`) apply when the texture is\ncreated and — like `lazy` — are observed: changing one updates a texture that has already\nloaded, and removing one restores the engine default. Changing `srgb` or `mipmaps` on a loaded\ntexture recreates the underlying GPU resource, so prefer declaring those up front. Each option\noverrides the matching key in the `data` JSON; options left unset write nothing, leaving the\nengine's per-format defaults in force.\n\nApart from `lazy` and the texture options, these attributes are read once when the asset is\ncreated, so changing them later has no effect.\n\n---\n\n\n### **Events:**\n - **error** - Fired when the asset fails to load, with the engine's error in `message`. Does not bubble. The element still becomes ready — readiness means the load settled, not that it succeeded.\n- **load** - Fired each time the asset finishes loading, including a `lazy` asset loaded later and any subsequent reloads. Does not bubble — listen on this element, or use a capture-phase listener on an ancestor to observe every asset.\n- **ready** - Fired when the element is fully initialized — once per readiness cycle, so an element that is torn down and re-initialized (for example by removing and re-inserting it) fires it again. Bubbles and is composed.\n\n### **Methods:**\n - **get(id: _string_): __** - Returns the Asset created by the `<pc-asset>` element with the given `id`, or\n`undefined` if there is no such element or its asset has not been created yet.\n- **ready(): __** - Returns a promise that resolves with this element when it's ready. This is the low-level\nprimitive underlying whenReady, which is the recommended way to wait for elements.\n\nReadiness tracks the element's current lifecycle: once a ready element is torn down (for\nexample by removing it from the document), this returns a fresh promise that resolves when\nthe element is next ready. A promise obtained earlier stays resolved — call this again\nafter re-inserting an element rather than reusing a promise from before its removal.",
|
|
142
|
+
"description": "The AssetElement interface provides properties and methods for manipulating\n[`<pc-asset>`](https://developer.playcanvas.com/user-manual/web-components/tags/pc-asset/) elements.\nThe AssetElement interface also inherits the properties and methods of the\nHTMLElement interface.\n\nThe element becomes ready once the containing application has started and the asset is in the\nstate declared by the markup: loaded for preloaded assets (even if loading failed — check the\nasset's `resource`), or registered and awaiting a load for `lazy` assets. Elements inserted\nwhile the application is running are created and registered on insertion, and begin loading\nimmediately unless `lazy`. A `pc-asset` must be a direct child of `pc-app` — elements placed\nelsewhere, or with an unsupported asset type, never become ready.\n\nA `lazy` asset loads on first use: the first time any element resolves it by `id` — a model,\na material map, a sky, a script `asset:` reference — or when the `lazy` attribute is removed,\nwhichever comes first. Until then it stays registered and unloaded.\n\nFor `texture` and `textureatlas` assets, the texture options (`address-u`, `address-v`,\n`min-filter`, `mag-filter`, `anisotropy`, `mipmaps`, `srgb`, `flip-y`) apply when the texture is\ncreated and — like `lazy` — are observed: changing one updates a texture that has already\nloaded, and removing one restores the engine default. Changing `srgb` or `mipmaps` on a loaded\ntexture recreates the underlying GPU resource, so prefer declaring those up front. Each option\noverrides the matching key in the `data` JSON; options left unset write nothing, leaving the\nengine's per-format defaults in force.\n\nApart from `lazy` and the texture options, these attributes are read once when the asset is\ncreated, so changing them later has no effect.\n\n---\n\n\n### **Events:**\n - **error** - Fired when the asset fails to load, with the engine's error in `message`. Does not bubble. The element still becomes ready — readiness means the load settled, not that it succeeded.\n- **load** - Fired each time the asset finishes loading, including a `lazy` asset loaded later and any subsequent reloads. Does not bubble — listen on this element, or use a capture-phase listener on an ancestor to observe every asset.\n- **ready** - Fired when the element is fully initialized — once per readiness cycle, so an element that is torn down and re-initialized (for example by removing and re-inserting it) fires it again. Bubbles and is composed.\n\n### **Methods:**\n - **get(id: _string_): __** - Returns the Asset created by the `<pc-asset>` element with the given `id`, or\n`undefined` if there is no such element or its asset has not been created yet.\n- **ready(): __** - Returns a promise that resolves with this element when it's ready. This is the low-level\nprimitive underlying whenReady, which is the recommended way to wait for elements.\n\nReadiness tracks the element's current lifecycle: once a ready element is torn down (for\nexample by removing it from the document), this returns a fresh promise that resolves when\nthe element is next ready. A promise obtained earlier stays resolved — call this again\nafter re-inserting an element rather than reusing a promise from before its removal.",
|
|
143
143
|
"doc-url": "",
|
|
144
144
|
"attributes": [
|
|
145
145
|
{
|
|
@@ -785,6 +785,11 @@
|
|
|
785
785
|
"description": "The UV channel the metalness map samples.",
|
|
786
786
|
"value": { "type": "number", "default": "0" }
|
|
787
787
|
},
|
|
788
|
+
{
|
|
789
|
+
"name": "name",
|
|
790
|
+
"description": "The name of the material - the label shown wherever materials surface by name, such as profilers, GPU captures and the assignments `pc-model.hierarchy()` reports.",
|
|
791
|
+
"value": { "type": "string" }
|
|
792
|
+
},
|
|
788
793
|
{
|
|
789
794
|
"name": "normal-map",
|
|
790
795
|
"description": "The id of the `pc-asset` used as the normal map.",
|
|
@@ -1162,6 +1167,10 @@
|
|
|
1162
1167
|
"name": "metalnessMapUv",
|
|
1163
1168
|
"description": "Gets the UV channel the metalness map samples."
|
|
1164
1169
|
},
|
|
1170
|
+
{
|
|
1171
|
+
"name": "name",
|
|
1172
|
+
"description": "Gets the name of the material - the label shown wherever materials surface by name, such\nas profilers, GPU captures and the assignments `pc-model.hierarchy()` reports. Purely a\nlabel: element references resolve through `id`."
|
|
1173
|
+
},
|
|
1165
1174
|
{
|
|
1166
1175
|
"name": "normalMap",
|
|
1167
1176
|
"description": "Gets the id of the `pc-asset` used as the normal map."
|
|
@@ -1284,7 +1293,7 @@
|
|
|
1284
1293
|
},
|
|
1285
1294
|
{
|
|
1286
1295
|
"name": "pc-model",
|
|
1287
|
-
"description": "The ModelElement interface provides properties and methods for manipulating\n[`<pc-model>`](https://developer.playcanvas.com/user-manual/web-components/tags/pc-model/) elements.\nThe ModelElement interface also inherits the properties and methods of the\nHTMLElement interface.\n\nThe element becomes ready once its container asset has loaded and the instantiated hierarchy has\nbeen added to the scene — `entity` is non-null by then. A failed load also settles readiness,\nwith `entity` remaining `null`: readiness means the load settled, not that it succeeded — listen\nfor `error`, or check `entity`, to tell the outcomes apart. Changing `asset` re-arms readiness\nand instantiates anew, so a `ready()` obtained after the change resolves against the new\nhierarchy. A `pc-model` outside a `pc-app`, or referencing an unknown asset id, warns and never\nbecomes ready.\n\n---\n\n\n### **Events:**\n - **error** - Fired when the container asset fails to load, with the engine's error in `message`. Does not bubble. The element still becomes ready — readiness means the load settled, not that it succeeded.\n- **load** - Fired each time a container asset finishes instantiating, including re-instantiation after `asset` changes. Does not bubble — listen on this element, or use a capture-phase listener on an ancestor.\n- **ready** - Fired when the element is fully initialized — once per readiness cycle, so an element that is torn down and re-initialized (for example by removing and re-inserting it) fires it again. Bubbles and is composed.\n\n### **Methods:**\n - **ready(): __** - Returns a promise that resolves with this element when it's ready. This is the low-level\nprimitive underlying whenReady, which is the recommended way to wait for elements.\n\nReadiness tracks the element's current lifecycle: once a ready element is torn down (for\nexample by removing it from the document), this returns a fresh promise that resolves when\nthe element is next ready. A promise obtained earlier stays resolved — call this again\nafter re-inserting an element rather than reusing a promise from before its removal.",
|
|
1296
|
+
"description": "The ModelElement interface provides properties and methods for manipulating\n[`<pc-model>`](https://developer.playcanvas.com/user-manual/web-components/tags/pc-model/) elements.\nThe ModelElement interface also inherits the properties and methods of the\nHTMLElement interface.\n\nThe element becomes ready once its container asset has loaded and the instantiated hierarchy has\nbeen added to the scene — `entity` is non-null by then. A failed load also settles readiness,\nwith `entity` remaining `null`: readiness means the load settled, not that it succeeded — listen\nfor `error`, or check `entity`, to tell the outcomes apart. Changing `asset` re-arms readiness\nand instantiates anew, so a `ready()` obtained after the change resolves against the new\nhierarchy. A `pc-model` outside a `pc-app`, or referencing an unknown asset id, warns and never\nbecomes ready.\n\n---\n\n\n### **Events:**\n - **error** - Fired when the container asset fails to load, with the engine's error in `message`. Does not bubble. The element still becomes ready — readiness means the load settled, not that it succeeded.\n- **load** - Fired each time a container asset finishes instantiating, including re-instantiation after `asset` changes. Does not bubble — listen on this element, or use a capture-phase listener on an ancestor.\n- **ready** - Fired when the element is fully initialized — once per readiness cycle, so an element that is torn down and re-initialized (for example by removing and re-inserting it) fires it again. Bubbles and is composed.\n\n### **Methods:**\n - **hierarchy(): __** - Returns a snapshot of the instantiated node tree, or `null` while there is none (the\ncontainer asset has not loaded, or the element has left the document). One call grounds a\nsession — a browser console, a test, an agent — in the vocabulary `pc-node` binding\nresolves against: the instantiated names (HierarchyNode.name), paths, match\nindices, attached component types and the material assignments of render components\n(HierarchyNode.materials). `String(...)` of the result, or of any node in it,\nis the printable form.\n\nThe snapshot is plain data, computed afresh each call: it does not follow later changes\nto the hierarchy, and mutating it changes nothing.\n- **ready(): __** - Returns a promise that resolves with this element when it's ready. This is the low-level\nprimitive underlying whenReady, which is the recommended way to wait for elements.\n\nReadiness tracks the element's current lifecycle: once a ready element is torn down (for\nexample by removing it from the document), this returns a fresh promise that resolves when\nthe element is next ready. A promise obtained earlier stays resolved — call this again\nafter re-inserting an element rather than reusing a promise from before its removal.",
|
|
1288
1297
|
"doc-url": "",
|
|
1289
1298
|
"attributes": [
|
|
1290
1299
|
{
|
|
@@ -1422,6 +1431,11 @@
|
|
|
1422
1431
|
"description": "Which match to bind when `name` matches more than one node, 0-based in depth-first order. Optional for a unique match; required for an ambiguous one.",
|
|
1423
1432
|
"value": { "type": "string" }
|
|
1424
1433
|
},
|
|
1434
|
+
{
|
|
1435
|
+
"name": "material-overrides",
|
|
1436
|
+
"description": "Overrides material assignments on the bound node's render component, as a JSON object from selector to `pc-material` id — for example `{\"name:CarPaint\": \"candy-red\", \"index:7\": \"smoked-glass\"}`. A `name:X` key selects every mesh instance whose baseline material is named `X`; an `index:N` key selects mesh instance `N` and wins over a name rule for the same instance. Assignments no rule matches keep their baseline materials, and removing the attribute restores all of them. Use `pc-model.hierarchy()` to discover the names and indices a node offers.",
|
|
1437
|
+
"value": { "type": "string" }
|
|
1438
|
+
},
|
|
1425
1439
|
{
|
|
1426
1440
|
"name": "name",
|
|
1427
1441
|
"description": "The name of the node to bind, resolved within the nearest ancestor `pc-model` (or `pc-node`) once it has instantiated.",
|
|
@@ -1532,6 +1546,11 @@
|
|
|
1532
1546
|
"description": "Gets which match to bind.",
|
|
1533
1547
|
"type": "number | null"
|
|
1534
1548
|
},
|
|
1549
|
+
{
|
|
1550
|
+
"name": "materialOverrides",
|
|
1551
|
+
"description": "Gets the material overrides.",
|
|
1552
|
+
"type": "MaterialOverrides | null"
|
|
1553
|
+
},
|
|
1535
1554
|
{
|
|
1536
1555
|
"name": "name",
|
|
1537
1556
|
"description": "Gets the name of the node to bind.",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@playcanvas/web-components",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"author": "PlayCanvas <support@playcanvas.com>",
|
|
5
5
|
"homepage": "https://playcanvas.com",
|
|
6
6
|
"description": "Web Components for the PlayCanvas Engine",
|
|
@@ -96,9 +96,9 @@
|
|
|
96
96
|
"custom-element-vs-code-integration": "1.5.0",
|
|
97
97
|
"earcut": "3.2.3",
|
|
98
98
|
"eslint": "9.39.5",
|
|
99
|
-
"globals": "17.
|
|
99
|
+
"globals": "17.11.0",
|
|
100
100
|
"jsdom": "30.0.1",
|
|
101
|
-
"mediabunny": "1.53.
|
|
101
|
+
"mediabunny": "1.53.1",
|
|
102
102
|
"opentype.js": "2.0.0",
|
|
103
103
|
"playcanvas": "2.22.0-beta.12",
|
|
104
104
|
"prettier": "3.9.6",
|
package/src/app.ts
CHANGED
|
@@ -692,22 +692,68 @@ class AppElement extends AsyncElement {
|
|
|
692
692
|
return null;
|
|
693
693
|
}
|
|
694
694
|
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
695
|
+
/**
|
|
696
|
+
* Converts a pointer event's client coordinates into drawing-buffer coordinates - the space
|
|
697
|
+
* the pick buffer and the camera viewports are laid out in. When the canvas has no CSS box
|
|
698
|
+
* to map through (jsdom; a hidden canvas receives no pointer events in a browser), the
|
|
699
|
+
* client coordinates are passed through unmapped and `mapped` is false, so callers know the
|
|
700
|
+
* coordinates correspond to no real geometry.
|
|
701
|
+
*
|
|
702
|
+
* @param event - The pointer event to convert.
|
|
703
|
+
* @param canvas - The canvas the event was dispatched on.
|
|
704
|
+
* @returns The buffer-space coordinates, and whether they were actually mapped.
|
|
705
|
+
*/
|
|
706
|
+
private _getPickerCoordinates(
|
|
707
|
+
event: PointerEvent,
|
|
708
|
+
canvas: HTMLCanvasElement
|
|
709
|
+
): { x: number; y: number; mapped: boolean } {
|
|
710
|
+
const canvasRect = canvas.getBoundingClientRect();
|
|
711
|
+
if (canvasRect.width === 0 || canvasRect.height === 0) {
|
|
712
|
+
return { x: event.clientX, y: event.clientY, mapped: false };
|
|
713
|
+
}
|
|
714
|
+
const scaleX = canvas.width / canvasRect.width;
|
|
715
|
+
const scaleY = canvas.height / canvasRect.height;
|
|
716
|
+
return {
|
|
717
|
+
x: (event.clientX - canvasRect.left) * scaleX,
|
|
718
|
+
y: (event.clientY - canvasRect.top) * scaleY,
|
|
719
|
+
mapped: true
|
|
720
|
+
};
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
/**
|
|
724
|
+
* Whether a camera's viewport contains the point. A camera renders into its normalized
|
|
725
|
+
* `rect`, whose origin is the bottom-left of the canvas while buffer coordinates run from
|
|
726
|
+
* the top-left - so the vertical test flips, as the engine's ElementInput flips it for UI
|
|
727
|
+
* input. The right and bottom edges are exclusive: a viewport rasterizes the half-open
|
|
728
|
+
* pixel range [left, right) x [top, bottom), so a coordinate on a shared edge belongs to
|
|
729
|
+
* the viewport whose first pixel it is - never to the one it just left, whose pick buffer
|
|
730
|
+
* holds nothing there.
|
|
731
|
+
*
|
|
732
|
+
* @param camera - The camera to test.
|
|
733
|
+
* @param x - The x coordinate, in buffer space.
|
|
734
|
+
* @param y - The y coordinate, in buffer space.
|
|
735
|
+
* @param canvas - The canvas the coordinates are relative to.
|
|
736
|
+
* @returns Whether the camera's viewport contains the point.
|
|
737
|
+
*/
|
|
738
|
+
private _cameraContains(camera: CameraComponent, x: number, y: number, canvas: HTMLCanvasElement): boolean {
|
|
739
|
+
const rect = camera.rect;
|
|
740
|
+
const left = rect.x * canvas.width;
|
|
741
|
+
const bottom = (1 - rect.y) * canvas.height;
|
|
742
|
+
const top = bottom - rect.w * canvas.height;
|
|
743
|
+
return x >= left && x < left + rect.z * canvas.width && y >= top && y < bottom;
|
|
706
744
|
}
|
|
707
745
|
|
|
708
746
|
/**
|
|
709
747
|
* Picks the scene under the pointer and returns the graph node that was hit, or `null`.
|
|
710
748
|
*
|
|
749
|
+
* The camera is resolved the way the engine's ElementInput resolves it for UI input:
|
|
750
|
+
* enabled cameras are tried topmost-first (they render in ascending `priority` order),
|
|
751
|
+
* skipping cameras that render to a texture and cameras whose viewport `rect` does not
|
|
752
|
+
* contain the pointer. A camera that picks nothing ends the search if it clears the color
|
|
753
|
+
* buffer - its background visually owns the pixel - and otherwise cedes to the cameras
|
|
754
|
+
* beneath it, so an overlay camera only intercepts picks where it actually drew something.
|
|
755
|
+
* The pick buffer is prepared per camera, so each camera picks from its own layers.
|
|
756
|
+
*
|
|
711
757
|
* The read back is asynchronous because the synchronous {@link Picker.getSelection} is not
|
|
712
758
|
* supported on WebGPU, where it returns an empty selection rather than failing - which
|
|
713
759
|
* silently disabled every `onpointer*` handler once WebGPU became the resolved backend. The
|
|
@@ -717,17 +763,44 @@ class AppElement extends AsyncElement {
|
|
|
717
763
|
* @returns The graph node under the pointer, or `null` if nothing was hit.
|
|
718
764
|
*/
|
|
719
765
|
private async _pickNode(event: PointerEvent): Promise<GraphNode | null> {
|
|
720
|
-
const
|
|
721
|
-
|
|
766
|
+
const app = this.app;
|
|
767
|
+
const picker = this._picker;
|
|
768
|
+
const canvas = this._canvas;
|
|
769
|
+
if (!app || !picker || !canvas) return null;
|
|
770
|
+
|
|
771
|
+
const { x, y, mapped } = this._getPickerCoordinates(event, canvas);
|
|
772
|
+
|
|
773
|
+
// Walked from the end: the array is sorted by ascending priority, so the last camera
|
|
774
|
+
// renders last and sits on top. Read through .at() because a pick handler may remove
|
|
775
|
+
// cameras while an earlier iteration's read back is in flight.
|
|
776
|
+
const cameras = app.systems.camera?.cameras ?? [];
|
|
777
|
+
for (let i = cameras.length - 1; i >= 0; i--) {
|
|
778
|
+
const camera = cameras.at(i);
|
|
779
|
+
|
|
780
|
+
// A camera rendering to a texture is not on the canvas.
|
|
781
|
+
if (!camera || camera.renderTarget) continue;
|
|
782
|
+
|
|
783
|
+
// Coordinates that could not be mapped cannot be tested for containment.
|
|
784
|
+
if (mapped && !this._cameraContains(camera, x, y, canvas)) continue;
|
|
722
785
|
|
|
723
|
-
|
|
786
|
+
picker.prepare(camera, app.scene);
|
|
787
|
+
const selection = await picker.getSelectionAsync(x, y);
|
|
724
788
|
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
if (selection.length === 0) return null;
|
|
789
|
+
// The element may have disconnected while the read back was in flight.
|
|
790
|
+
if (!this._picker || !this.app) return null;
|
|
728
791
|
|
|
729
|
-
|
|
730
|
-
|
|
792
|
+
if (selection.length > 0) {
|
|
793
|
+
const item = selection[0];
|
|
794
|
+
return item instanceof MeshInstance ? item.node : (item as GSplatComponent).entity;
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
// Nothing hit. A camera that clears the color buffer paints its background over
|
|
798
|
+
// everything beneath it, so the miss is final; one that does not is an overlay
|
|
799
|
+
// that the cameras beneath show through, so they get their turn.
|
|
800
|
+
if (camera.clearColorBuffer) return null;
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
return null;
|
|
731
804
|
}
|
|
732
805
|
|
|
733
806
|
private async _onPointerMove(event: PointerEvent) {
|
package/src/asset.ts
CHANGED
|
@@ -153,6 +153,10 @@ const processBufferView = (
|
|
|
153
153
|
* immediately unless `lazy`. A `pc-asset` must be a direct child of `pc-app` — elements placed
|
|
154
154
|
* elsewhere, or with an unsupported asset type, never become ready.
|
|
155
155
|
*
|
|
156
|
+
* A `lazy` asset loads on first use: the first time any element resolves it by `id` — a model,
|
|
157
|
+
* a material map, a sky, a script `asset:` reference — or when the `lazy` attribute is removed,
|
|
158
|
+
* whichever comes first. Until then it stays registered and unloaded.
|
|
159
|
+
*
|
|
156
160
|
* For `texture` and `textureatlas` assets, the texture options (`address-u`, `address-v`,
|
|
157
161
|
* `min-filter`, `mag-filter`, `anisotropy`, `mipmaps`, `srgb`, `flip-y`) apply when the texture is
|
|
158
162
|
* created and — like `lazy` — are observed: changing one updates a texture that has already
|
|
@@ -385,7 +389,9 @@ class AssetElement extends AsyncElement {
|
|
|
385
389
|
data = data ?? {};
|
|
386
390
|
|
|
387
391
|
// Resolve the referenced texture atlas to its (numeric) asset id. The atlas must be
|
|
388
|
-
// declared before the sprite so its asset already exists in the registry.
|
|
392
|
+
// declared before the sprite so its asset already exists in the registry. Resolved
|
|
393
|
+
// with get, not useAsset: creation-time wiring is not a use, and the engine's
|
|
394
|
+
// sprite handler loads the atlas when the sprite itself loads.
|
|
389
395
|
const atlas = this.getAttribute('atlas') ?? data.textureAtlasAsset;
|
|
390
396
|
if (typeof atlas === 'string') {
|
|
391
397
|
const atlasAsset = AssetElement.get(atlas);
|
|
@@ -564,13 +570,18 @@ class AssetElement extends AsyncElement {
|
|
|
564
570
|
}
|
|
565
571
|
|
|
566
572
|
/**
|
|
567
|
-
* Sets whether the asset should be loaded lazily.
|
|
573
|
+
* Sets whether the asset should be loaded lazily. A lazy asset is registered without being
|
|
574
|
+
* loaded; it loads on first use - the first time any element resolves it by `id` - or when
|
|
575
|
+
* this flag is cleared on a registered asset, whichever comes first.
|
|
568
576
|
* @param value - The lazy loading flag.
|
|
569
577
|
*/
|
|
570
578
|
set lazy(value: boolean) {
|
|
571
579
|
this._lazy = value;
|
|
572
580
|
if (this.asset) {
|
|
573
581
|
this.asset.preload = !value;
|
|
582
|
+
if (!value) {
|
|
583
|
+
this.asset.registry?.load(this.asset);
|
|
584
|
+
}
|
|
574
585
|
}
|
|
575
586
|
}
|
|
576
587
|
|
|
@@ -760,4 +771,25 @@ class AssetElement extends AsyncElement {
|
|
|
760
771
|
|
|
761
772
|
customElements.define('pc-asset', AssetElement);
|
|
762
773
|
|
|
774
|
+
/**
|
|
775
|
+
* Resolves an asset reference for use: {@link AssetElement.get}, plus starting the load of a
|
|
776
|
+
* registered asset that has not begun one - a `lazy` asset. Every element that consumes assets
|
|
777
|
+
* resolves its references here, which is what makes `lazy` mean load on first use without any
|
|
778
|
+
* consumer having to remember the load. The load is asynchronous - callers observe the asset's
|
|
779
|
+
* `load` event for the resource.
|
|
780
|
+
*
|
|
781
|
+
* @param id - The `id` of the `<pc-asset>` element.
|
|
782
|
+
* @returns The asset, or `undefined`.
|
|
783
|
+
* @internal
|
|
784
|
+
*/
|
|
785
|
+
export const useAsset = (id: string) => {
|
|
786
|
+
const asset = AssetElement.get(id);
|
|
787
|
+
// load() ignores an asset that is already loaded or loading, so repeated resolution
|
|
788
|
+
// costs nothing.
|
|
789
|
+
if (asset) {
|
|
790
|
+
asset.registry?.load(asset);
|
|
791
|
+
}
|
|
792
|
+
return asset;
|
|
793
|
+
};
|
|
794
|
+
|
|
763
795
|
export { AssetElement };
|
package/src/colors.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ButtonComponent } from 'playcanvas';
|
|
2
2
|
import { BUTTON_TRANSITION_MODE_SPRITE_CHANGE, BUTTON_TRANSITION_MODE_TINT, Color, Vec4 } from 'playcanvas';
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { useAsset } from '../asset';
|
|
5
5
|
import { getEntity, parseBool, parseColor, parseEnum, parseNumber, parseVec4 } from '../parse';
|
|
6
6
|
|
|
7
7
|
import { ComponentElement } from './component';
|
|
@@ -74,17 +74,17 @@ class ButtonComponentElement extends ComponentElement {
|
|
|
74
74
|
data.imageEntity = imageEntity;
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
const hoverSpriteAsset =
|
|
77
|
+
const hoverSpriteAsset = useAsset(this._hoverSpriteAsset);
|
|
78
78
|
if (hoverSpriteAsset) {
|
|
79
79
|
data.hoverSpriteAsset = hoverSpriteAsset.id;
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
const pressedSpriteAsset =
|
|
82
|
+
const pressedSpriteAsset = useAsset(this._pressedSpriteAsset);
|
|
83
83
|
if (pressedSpriteAsset) {
|
|
84
84
|
data.pressedSpriteAsset = pressedSpriteAsset.id;
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
const inactiveSpriteAsset =
|
|
87
|
+
const inactiveSpriteAsset = useAsset(this._inactiveSpriteAsset);
|
|
88
88
|
if (inactiveSpriteAsset) {
|
|
89
89
|
data.inactiveSpriteAsset = inactiveSpriteAsset.id;
|
|
90
90
|
}
|
|
@@ -265,7 +265,7 @@ class ButtonComponentElement extends ComponentElement {
|
|
|
265
265
|
*/
|
|
266
266
|
set hoverSpriteAsset(value: string) {
|
|
267
267
|
this._hoverSpriteAsset = value;
|
|
268
|
-
const asset =
|
|
268
|
+
const asset = useAsset(value);
|
|
269
269
|
if (this.component && asset) {
|
|
270
270
|
this.component.hoverSpriteAsset = asset.id as any;
|
|
271
271
|
}
|
|
@@ -305,7 +305,7 @@ class ButtonComponentElement extends ComponentElement {
|
|
|
305
305
|
*/
|
|
306
306
|
set pressedSpriteAsset(value: string) {
|
|
307
307
|
this._pressedSpriteAsset = value;
|
|
308
|
-
const asset =
|
|
308
|
+
const asset = useAsset(value);
|
|
309
309
|
if (this.component && asset) {
|
|
310
310
|
this.component.pressedSpriteAsset = asset.id as any;
|
|
311
311
|
}
|
|
@@ -345,7 +345,7 @@ class ButtonComponentElement extends ComponentElement {
|
|
|
345
345
|
*/
|
|
346
346
|
set inactiveSpriteAsset(value: string) {
|
|
347
347
|
this._inactiveSpriteAsset = value;
|
|
348
|
-
const asset =
|
|
348
|
+
const asset = useAsset(value);
|
|
349
349
|
if (this.component && asset) {
|
|
350
350
|
this.component.inactiveSpriteAsset = asset.id as any;
|
|
351
351
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ElementComponent } from 'playcanvas';
|
|
2
2
|
import { Color, Vec2, Vec4 } from 'playcanvas';
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { useAsset } from '../asset';
|
|
5
5
|
import { parseBool, parseColor, parseEnum, parseNumber, parseVec2, parseVec4 } from '../parse';
|
|
6
6
|
|
|
7
7
|
import { ComponentElement } from './component';
|
|
@@ -118,17 +118,17 @@ class ElementComponentElement extends ComponentElement {
|
|
|
118
118
|
|
|
119
119
|
// Asset references are resolved from `<pc-asset>` element ids to engine asset ids. They are
|
|
120
120
|
// only included when they resolve, so image/group elements (with no font) don't error.
|
|
121
|
-
const fontAsset =
|
|
121
|
+
const fontAsset = useAsset(this._fontAsset);
|
|
122
122
|
if (fontAsset) {
|
|
123
123
|
data.fontAsset = fontAsset.id;
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
-
const spriteAsset =
|
|
126
|
+
const spriteAsset = useAsset(this._spriteAsset);
|
|
127
127
|
if (spriteAsset) {
|
|
128
128
|
data.spriteAsset = spriteAsset.id;
|
|
129
129
|
}
|
|
130
130
|
|
|
131
|
-
const textureAsset =
|
|
131
|
+
const textureAsset = useAsset(this._textureAsset);
|
|
132
132
|
if (textureAsset) {
|
|
133
133
|
data.textureAsset = textureAsset.id;
|
|
134
134
|
}
|
|
@@ -257,7 +257,7 @@ class ElementComponentElement extends ComponentElement {
|
|
|
257
257
|
*/
|
|
258
258
|
set fontAsset(value: string) {
|
|
259
259
|
this._fontAsset = value;
|
|
260
|
-
const asset =
|
|
260
|
+
const asset = useAsset(value);
|
|
261
261
|
if (this.component && asset) {
|
|
262
262
|
this.component.fontAsset = asset.id;
|
|
263
263
|
}
|
|
@@ -430,7 +430,7 @@ class ElementComponentElement extends ComponentElement {
|
|
|
430
430
|
*/
|
|
431
431
|
set spriteAsset(value: string) {
|
|
432
432
|
this._spriteAsset = value;
|
|
433
|
-
const asset =
|
|
433
|
+
const asset = useAsset(value);
|
|
434
434
|
if (this.component && asset) {
|
|
435
435
|
this.component.spriteAsset = asset.id;
|
|
436
436
|
}
|
|
@@ -488,7 +488,7 @@ class ElementComponentElement extends ComponentElement {
|
|
|
488
488
|
*/
|
|
489
489
|
set textureAsset(value: string) {
|
|
490
490
|
this._textureAsset = value;
|
|
491
|
-
const asset =
|
|
491
|
+
const asset = useAsset(value);
|
|
492
492
|
if (this.component && asset) {
|
|
493
493
|
this.component.textureAsset = asset.id;
|
|
494
494
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { GSplatComponent } from 'playcanvas';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { useAsset } from '../asset';
|
|
4
4
|
import { parseBool, parseNumber } from '../parse';
|
|
5
5
|
|
|
6
6
|
import { ComponentElement } from './component';
|
|
@@ -33,7 +33,7 @@ class GSplatComponentElement extends ComponentElement {
|
|
|
33
33
|
|
|
34
34
|
protected getInitialComponentData() {
|
|
35
35
|
return {
|
|
36
|
-
asset:
|
|
36
|
+
asset: useAsset(this._asset),
|
|
37
37
|
castShadows: this._castShadows,
|
|
38
38
|
lodBaseDistance: this._lodBaseDistance,
|
|
39
39
|
lodMultiplier: this._lodMultiplier,
|
|
@@ -56,7 +56,7 @@ class GSplatComponentElement extends ComponentElement {
|
|
|
56
56
|
*/
|
|
57
57
|
set asset(value: string) {
|
|
58
58
|
this._asset = value;
|
|
59
|
-
const asset =
|
|
59
|
+
const asset = useAsset(value);
|
|
60
60
|
if (this.component && asset) {
|
|
61
61
|
this.component.asset = asset;
|
|
62
62
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ParticleSystemComponent } from 'playcanvas';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { useAsset } from '../asset';
|
|
4
4
|
|
|
5
5
|
import { ComponentElement } from './component';
|
|
6
6
|
|
|
@@ -21,14 +21,15 @@ class ParticleSystemComponentElement extends ComponentElement {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
protected getInitialComponentData() {
|
|
24
|
-
const asset =
|
|
25
|
-
|
|
24
|
+
const asset = useAsset(this._asset);
|
|
25
|
+
// A lazy config has no resource yet - _loadAsset applies it once the load completes
|
|
26
|
+
if (!asset || !asset.resource) {
|
|
26
27
|
return {};
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
if ((asset.resource as any).colorMapAsset) {
|
|
30
31
|
const id = (asset.resource as any).colorMapAsset;
|
|
31
|
-
const colorMapAsset =
|
|
32
|
+
const colorMapAsset = useAsset(id)?.id;
|
|
32
33
|
if (colorMapAsset) {
|
|
33
34
|
(asset.resource as any).colorMapAsset = colorMapAsset;
|
|
34
35
|
}
|
|
@@ -59,10 +60,9 @@ class ParticleSystemComponentElement extends ComponentElement {
|
|
|
59
60
|
}
|
|
60
61
|
|
|
61
62
|
private async _loadAsset() {
|
|
62
|
-
|
|
63
|
-
const app = appElement?.app;
|
|
63
|
+
await this.closestApp?.ready();
|
|
64
64
|
|
|
65
|
-
const asset =
|
|
65
|
+
const asset = useAsset(this._asset);
|
|
66
66
|
if (!asset) {
|
|
67
67
|
return;
|
|
68
68
|
}
|
|
@@ -73,7 +73,6 @@ class ParticleSystemComponentElement extends ComponentElement {
|
|
|
73
73
|
asset.once('load', () => {
|
|
74
74
|
this.applyConfig(asset.resource);
|
|
75
75
|
});
|
|
76
|
-
app!.assets.load(asset);
|
|
77
76
|
}
|
|
78
77
|
}
|
|
79
78
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ScriptComponent, Script } from 'playcanvas';
|
|
2
2
|
import { Color, Quat, Vec2, Vec3, Vec4 } from 'playcanvas';
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { useAsset } from '../asset';
|
|
5
5
|
import {
|
|
6
6
|
getEntity,
|
|
7
7
|
parseBool,
|
|
@@ -119,7 +119,7 @@ type Conversion = (rest: string, raw: string) => any;
|
|
|
119
119
|
* @returns The asset, or `raw`.
|
|
120
120
|
*/
|
|
121
121
|
const assetConversion: Conversion = (rest, raw) => {
|
|
122
|
-
const asset =
|
|
122
|
+
const asset = useAsset(rest);
|
|
123
123
|
if (asset) {
|
|
124
124
|
return asset;
|
|
125
125
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { SoundSlot } from 'playcanvas';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { useAsset } from '../asset';
|
|
4
4
|
import { AsyncElement } from '../async-element';
|
|
5
5
|
import { parseBool, parseNumber } from '../parse';
|
|
6
6
|
|
|
@@ -120,7 +120,7 @@ class SoundSlotElement extends AsyncElement {
|
|
|
120
120
|
set asset(value: string) {
|
|
121
121
|
this._asset = value;
|
|
122
122
|
if (this.soundSlot) {
|
|
123
|
-
const id =
|
|
123
|
+
const id = useAsset(value)?.id;
|
|
124
124
|
if (id) {
|
|
125
125
|
this.soundSlot.asset = id;
|
|
126
126
|
}
|
package/src/entity-base.ts
CHANGED
|
@@ -6,9 +6,9 @@ import { AsyncElement } from './async-element';
|
|
|
6
6
|
/**
|
|
7
7
|
* The attribute names of the inline `onpointer*` event handlers, shared by every element that
|
|
8
8
|
* fronts an engine entity. Spread into `observedAttributes` by subclasses.
|
|
9
|
-
* @
|
|
9
|
+
* @internal
|
|
10
10
|
*/
|
|
11
|
-
const POINTER_ATTRIBUTES = [
|
|
11
|
+
export const POINTER_ATTRIBUTES = [
|
|
12
12
|
'onpointerenter',
|
|
13
13
|
'onpointerleave',
|
|
14
14
|
'onpointerdown',
|
|
@@ -133,4 +133,4 @@ class EntityBaseElement extends AsyncElement {
|
|
|
133
133
|
}
|
|
134
134
|
}
|
|
135
135
|
|
|
136
|
-
export { EntityBaseElement
|
|
136
|
+
export { EntityBaseElement };
|