create-playcanvas 0.3.0 → 0.4.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 +37 -25
- package/dist/index.mjs +48 -46
- package/package.json +2 -1
- package/templates/_shared/model-viewer/public/playcanvas-cube.glb +0 -0
- package/templates/{vanilla-ts → engine/base}/README.md +3 -19
- package/templates/{vanilla-ts → engine/base}/src/vite-env.d.ts +6 -0
- package/templates/{vanilla-ts → engine/interactive-sphere}/src/main.ts +1 -1
- package/templates/{vanilla-ts → engine/interactive-sphere}/src/style.css +1 -1
- package/templates/{vanilla-ts → engine/interactive-sphere}/src/utils.ts +0 -1
- package/templates/engine/model-viewer/index.html +13 -0
- package/templates/engine/model-viewer/src/main.ts +81 -0
- package/templates/engine/model-viewer/src/style.css +8 -0
- package/templates/engine/spinning-cube/index.html +13 -0
- package/templates/engine/spinning-cube/src/main.ts +65 -0
- package/templates/engine/spinning-cube/src/style.css +8 -0
- package/templates/engine/splat-viewer/index.html +13 -0
- package/templates/engine/splat-viewer/src/main.ts +74 -0
- package/templates/engine/splat-viewer/src/style.css +8 -0
- package/templates/index.ts +37 -5
- package/templates/{react-ts → react/base}/README.md +2 -19
- package/templates/{react-ts → react/base}/src/vite-env.d.ts +6 -0
- package/templates/{react-ts → react/interactive-sphere}/src/Scene.tsx +1 -2
- package/templates/react/model-viewer/index.html +13 -0
- package/templates/react/model-viewer/src/App.tsx +43 -0
- package/templates/react/model-viewer/src/index.css +9 -0
- package/templates/react/model-viewer/src/main.tsx +11 -0
- package/templates/react/spinning-cube/index.html +13 -0
- package/templates/react/spinning-cube/src/App.tsx +36 -0
- package/templates/react/spinning-cube/src/index.css +9 -0
- package/templates/react/spinning-cube/src/main.tsx +11 -0
- package/templates/react/splat-viewer/index.html +13 -0
- package/templates/react/splat-viewer/src/App.tsx +39 -0
- package/templates/react/splat-viewer/src/index.css +9 -0
- package/templates/react/splat-viewer/src/main.tsx +11 -0
- package/templates/web-components/base/README.md +66 -0
- package/templates/web-components/base/_gitignore +24 -0
- package/templates/web-components/base/eslint.config.mjs +3 -0
- package/templates/web-components/base/package.json +31 -0
- package/templates/web-components/base/prettier.config.mjs +1 -0
- package/templates/web-components/base/src/assets/playcanvas.png +0 -0
- package/templates/web-components/base/src/vite-env.d.ts +19 -0
- package/templates/web-components/base/tsconfig.json +25 -0
- package/templates/web-components/interactive-sphere/index.html +53 -0
- package/templates/web-components/interactive-sphere/src/assets/typescript.svg +1 -0
- package/templates/web-components/interactive-sphere/src/main.ts +76 -0
- package/templates/web-components/interactive-sphere/src/style.css +111 -0
- package/templates/web-components/model-viewer/index.html +34 -0
- package/templates/web-components/model-viewer/src/main.ts +26 -0
- package/templates/web-components/model-viewer/src/style.css +8 -0
- package/templates/web-components/spinning-cube/index.html +29 -0
- package/templates/web-components/spinning-cube/src/main.ts +20 -0
- package/templates/web-components/spinning-cube/src/style.css +8 -0
- package/templates/web-components/splat-viewer/index.html +31 -0
- package/templates/web-components/splat-viewer/src/main.ts +14 -0
- package/templates/web-components/splat-viewer/src/style.css +8 -0
- package/templates/vanilla-ts/public/environment-map.png +0 -0
- /package/templates/{react-ts → _shared/interactive-sphere}/public/environment-map.png +0 -0
- /package/templates/{react-ts → engine/base}/_gitignore +0 -0
- /package/templates/{vanilla-ts → engine/base}/eslint.config.mjs +0 -0
- /package/templates/{vanilla-ts → engine/base}/package.json +0 -0
- /package/templates/{react-ts → engine/base}/prettier.config.mjs +0 -0
- /package/templates/{react-ts → engine/base}/src/assets/playcanvas.png +0 -0
- /package/templates/{vanilla-ts → engine/base}/tsconfig.json +0 -0
- /package/templates/{vanilla-ts → engine/interactive-sphere}/index.html +0 -0
- /package/templates/{vanilla-ts → engine/interactive-sphere}/src/App.ts +0 -0
- /package/templates/{vanilla-ts → engine/interactive-sphere}/src/assets/typescript.svg +0 -0
- /package/templates/{vanilla-ts → react/base}/_gitignore +0 -0
- /package/templates/{react-ts → react/base}/eslint.config.mjs +0 -0
- /package/templates/{react-ts → react/base}/package.json +0 -0
- /package/templates/{vanilla-ts → react/base}/prettier.config.mjs +0 -0
- /package/templates/{vanilla-ts → react/base}/src/assets/playcanvas.png +0 -0
- /package/templates/{react-ts → react/base}/tsconfig.json +0 -0
- /package/templates/{react-ts → react/base}/vite.config.ts +0 -0
- /package/templates/{react-ts → react/interactive-sphere}/index.html +0 -0
- /package/templates/{react-ts → react/interactive-sphere}/src/App.css +0 -0
- /package/templates/{react-ts → react/interactive-sphere}/src/App.tsx +0 -0
- /package/templates/{react-ts → react/interactive-sphere}/src/assets/react.svg +0 -0
- /package/templates/{react-ts → react/interactive-sphere}/src/index.css +0 -0
- /package/templates/{react-ts → react/interactive-sphere}/src/main.tsx +0 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "playcanvas-project",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"description": "A PlayCanvas Web Components project",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "vite build",
|
|
9
|
+
"dev": "vite",
|
|
10
|
+
"fmt": "prettier --check .",
|
|
11
|
+
"fmt:fix": "prettier --write .",
|
|
12
|
+
"lint": "eslint .",
|
|
13
|
+
"lint:fix": "eslint . --fix",
|
|
14
|
+
"start": "vite preview",
|
|
15
|
+
"typecheck": "tsc --noEmit"
|
|
16
|
+
},
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"@playcanvas/web-components": "^0.10.1",
|
|
19
|
+
"playcanvas": "^2.21.3"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@playcanvas/eslint-config": "3.0.0-beta.8",
|
|
23
|
+
"eslint": "^9.39.5",
|
|
24
|
+
"prettier": "^3.9.6",
|
|
25
|
+
"typescript": "~6.0.3",
|
|
26
|
+
"vite": "^8.2.0"
|
|
27
|
+
},
|
|
28
|
+
"engines": {
|
|
29
|
+
"node": ">=22.23.2"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@playcanvas/eslint-config/prettier';
|
|
Binary file
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/// <reference types="vite/client" />
|
|
2
|
+
|
|
3
|
+
declare module 'playcanvas/scripts/esm/camera-controls.mjs' {
|
|
4
|
+
import type { Script } from 'playcanvas';
|
|
5
|
+
|
|
6
|
+
export const CameraControls: typeof Script & (new () => Script);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
declare module 'playcanvas/scripts/esm/grid.mjs' {
|
|
10
|
+
import type { Script } from 'playcanvas';
|
|
11
|
+
|
|
12
|
+
export const Grid: typeof Script & (new () => Script);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
declare module 'playcanvas/scripts/esm/sky/procedural-sky.mjs' {
|
|
16
|
+
import type { Script } from 'playcanvas';
|
|
17
|
+
|
|
18
|
+
export const ProceduralSky: typeof Script & (new () => Script);
|
|
19
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"useDefineForClassFields": true,
|
|
5
|
+
"module": "ESNext",
|
|
6
|
+
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
|
7
|
+
"skipLibCheck": true,
|
|
8
|
+
|
|
9
|
+
/* Bundler mode */
|
|
10
|
+
"moduleResolution": "bundler",
|
|
11
|
+
"allowImportingTsExtensions": true,
|
|
12
|
+
"verbatimModuleSyntax": true,
|
|
13
|
+
"moduleDetection": "force",
|
|
14
|
+
"noEmit": true,
|
|
15
|
+
|
|
16
|
+
/* Linting */
|
|
17
|
+
"strict": true,
|
|
18
|
+
"noUnusedLocals": true,
|
|
19
|
+
"noUnusedParameters": true,
|
|
20
|
+
"erasableSyntaxOnly": true,
|
|
21
|
+
"noFallthroughCasesInSwitch": true,
|
|
22
|
+
"noUncheckedSideEffectImports": true
|
|
23
|
+
},
|
|
24
|
+
"include": ["src"]
|
|
25
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<link rel="icon" type="image/png" href="/src/assets/playcanvas.png" />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
+
<title>PlayCanvas + Web Components</title>
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<pc-app>
|
|
11
|
+
<!-- Materials are declared once and referenced by id -->
|
|
12
|
+
<pc-material id="sphere-material" diffuse="lightgrey"></pc-material>
|
|
13
|
+
|
|
14
|
+
<pc-scene>
|
|
15
|
+
<!-- Camera. Orbit controls are attached in src/main.ts -->
|
|
16
|
+
<pc-entity name="camera" position="4 1 4">
|
|
17
|
+
<pc-camera clear-color="#171717"></pc-camera>
|
|
18
|
+
</pc-entity>
|
|
19
|
+
|
|
20
|
+
<!-- Lighting comes from the environment map, which is applied in src/main.ts -->
|
|
21
|
+
|
|
22
|
+
<!-- Background grid. The grid script is attached in src/main.ts -->
|
|
23
|
+
<pc-entity name="grid" scale="1000 1000 1000"></pc-entity>
|
|
24
|
+
|
|
25
|
+
<!-- The sphere. pc-app dispatches pointer events onto whatever the pointer hits -->
|
|
26
|
+
<pc-entity name="sphere" position="0 0.5 0">
|
|
27
|
+
<pc-render type="sphere" material="sphere-material"></pc-render>
|
|
28
|
+
</pc-entity>
|
|
29
|
+
</pc-scene>
|
|
30
|
+
</pc-app>
|
|
31
|
+
|
|
32
|
+
<div class="absolute overlay">
|
|
33
|
+
<div class="grow">
|
|
34
|
+
<header>
|
|
35
|
+
<h1>PlayCanvas + Web Components</h1>
|
|
36
|
+
<a href="https://developer.playcanvas.com/user-manual/web-components/" target="_blank">
|
|
37
|
+
<img src="/src/assets/playcanvas.png" class="playcanvas-logo logo" alt="PlayCanvas logo" />
|
|
38
|
+
</a>
|
|
39
|
+
<a href="https://www.typescriptlang.org/" target="_blank">
|
|
40
|
+
<img src="/src/assets/typescript.svg" class="logo typescript" alt="TypeScript logo" />
|
|
41
|
+
</a>
|
|
42
|
+
</header>
|
|
43
|
+
</div>
|
|
44
|
+
<div>
|
|
45
|
+
<span id="counter" class="pill">Click Count: 0</span>
|
|
46
|
+
<p>Edit <code>index.html</code> and save to reload the scene</p>
|
|
47
|
+
</div>
|
|
48
|
+
<p class="read-the-docs">Click on the PlayCanvas and TypeScript logos to learn more</p>
|
|
49
|
+
</div>
|
|
50
|
+
|
|
51
|
+
<script type="module" src="/src/main.ts"></script>
|
|
52
|
+
</body>
|
|
53
|
+
</html>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="32" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path fill="#007ACC" d="M0 128v128h256V0H0z"></path><path fill="#FFF" d="m56.612 128.85l-.081 10.483h33.32v94.68h23.568v-94.68h33.321v-10.28c0-5.69-.122-10.444-.284-10.566c-.122-.162-20.4-.244-44.983-.203l-44.74.122l-.121 10.443Zm149.955-10.742c6.501 1.625 11.459 4.51 16.01 9.224c2.357 2.52 5.851 7.111 6.136 8.208c.08.325-11.053 7.802-17.798 11.988c-.244.162-1.22-.894-2.317-2.52c-3.291-4.795-6.745-6.867-12.028-7.233c-7.76-.528-12.759 3.535-12.718 10.321c0 1.992.284 3.17 1.097 4.795c1.707 3.536 4.876 5.649 14.832 9.956c18.326 7.883 26.168 13.084 31.045 20.48c5.445 8.249 6.664 21.415 2.966 31.208c-4.063 10.646-14.14 17.879-28.323 20.276c-4.388.772-14.79.65-19.504-.203c-10.28-1.828-20.033-6.908-26.047-13.572c-2.357-2.6-6.949-9.387-6.664-9.874c.122-.163 1.178-.813 2.356-1.504c1.138-.65 5.446-3.129 9.509-5.485l7.355-4.267l1.544 2.276c2.154 3.29 6.867 7.801 9.712 9.305c8.167 4.307 19.383 3.698 24.909-1.26c2.357-2.153 3.332-4.388 3.332-7.68c0-2.966-.366-4.266-1.91-6.501c-1.99-2.845-6.054-5.242-17.595-10.24c-13.206-5.69-18.895-9.224-24.096-14.832c-3.007-3.25-5.852-8.452-7.03-12.8c-.975-3.617-1.22-12.678-.447-16.335c2.723-12.76 12.353-21.659 26.25-24.3c4.51-.853 14.994-.528 19.424.569Z"></path></svg>
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type { EntityElement } from '@playcanvas/web-components';
|
|
2
|
+
import { whenReady } from '@playcanvas/web-components';
|
|
3
|
+
import type { Texture } from 'playcanvas';
|
|
4
|
+
import { Asset, TEXTURETYPE_RGBP } from 'playcanvas';
|
|
5
|
+
import { CameraControls } from 'playcanvas/scripts/esm/camera-controls.mjs';
|
|
6
|
+
import { Grid } from 'playcanvas/scripts/esm/grid.mjs';
|
|
7
|
+
|
|
8
|
+
import './style.css';
|
|
9
|
+
|
|
10
|
+
const HOVER_COLOR = 'orange';
|
|
11
|
+
const DEFAULT_COLOR = 'lightgrey';
|
|
12
|
+
|
|
13
|
+
// The camera is awaited as <pc-camera> rather than the <pc-entity> holding it - an entity becomes
|
|
14
|
+
// ready before its component children do, and CameraControls needs the camera component to exist
|
|
15
|
+
const [appElement, cameraComponent, grid, sphere] = await Promise.all([
|
|
16
|
+
whenReady('pc-app'),
|
|
17
|
+
whenReady('pc-camera'),
|
|
18
|
+
whenReady<EntityElement>('pc-entity[name="grid"]'),
|
|
19
|
+
whenReady<EntityElement>('pc-entity[name="sphere"]')
|
|
20
|
+
]);
|
|
21
|
+
|
|
22
|
+
// This is a pre-generated environment atlas rather than an equirectangular image, so it is applied
|
|
23
|
+
// straight to the scene instead of through <pc-sky>
|
|
24
|
+
const app = appElement.app!;
|
|
25
|
+
const envAtlas = new Asset(
|
|
26
|
+
'env-atlas',
|
|
27
|
+
'texture',
|
|
28
|
+
{ url: '/environment-map.png' },
|
|
29
|
+
{
|
|
30
|
+
type: TEXTURETYPE_RGBP,
|
|
31
|
+
mipmaps: false
|
|
32
|
+
}
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
app.assets.add(envAtlas);
|
|
36
|
+
await new Promise<void>((resolve) => {
|
|
37
|
+
envAtlas.ready(() => resolve());
|
|
38
|
+
app.assets.load(envAtlas);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// Light the scene from the environment, with the skybox itself left hidden
|
|
42
|
+
app.scene.envAtlas = envAtlas.resource as Texture;
|
|
43
|
+
const skyboxLayer = app.scene.layers.getLayerByName('Skybox');
|
|
44
|
+
if (skyboxLayer) {
|
|
45
|
+
skyboxLayer.enabled = false;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Engine scripts are resolved by the bundler, so they are attached through the entity rather than
|
|
49
|
+
// with <pc-script name="...">, which only resolves scripts fetched at runtime by <pc-asset>
|
|
50
|
+
const camera = cameraComponent.closestEntity;
|
|
51
|
+
camera?.entity?.addComponent('script');
|
|
52
|
+
camera?.entity?.script?.create(CameraControls);
|
|
53
|
+
grid.entity?.addComponent('script');
|
|
54
|
+
grid.entity?.script?.create(Grid);
|
|
55
|
+
|
|
56
|
+
const material = document.querySelector('pc-material')!;
|
|
57
|
+
const counterElement = document.getElementById('counter')!;
|
|
58
|
+
|
|
59
|
+
let count = 0;
|
|
60
|
+
|
|
61
|
+
// pc-app picks whatever is under the pointer and dispatches a regular DOM PointerEvent on it, so
|
|
62
|
+
// the sphere is wired up like any other element
|
|
63
|
+
sphere.addEventListener('pointerenter', () => {
|
|
64
|
+
material.setAttribute('diffuse', HOVER_COLOR);
|
|
65
|
+
document.body.style.cursor = 'pointer';
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
sphere.addEventListener('pointerleave', () => {
|
|
69
|
+
material.setAttribute('diffuse', DEFAULT_COLOR);
|
|
70
|
+
document.body.style.cursor = 'default';
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
sphere.addEventListener('pointerup', () => {
|
|
74
|
+
count++;
|
|
75
|
+
counterElement.textContent = `Click Count: ${count}`;
|
|
76
|
+
});
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
|
|
3
|
+
line-height: 1.5;
|
|
4
|
+
font-weight: 400;
|
|
5
|
+
|
|
6
|
+
color-scheme: light dark;
|
|
7
|
+
color: rgba(255, 255, 255, 0.87);
|
|
8
|
+
background-color: #242424;
|
|
9
|
+
|
|
10
|
+
font-synthesis: none;
|
|
11
|
+
text-rendering: optimizeLegibility;
|
|
12
|
+
-webkit-font-smoothing: antialiased;
|
|
13
|
+
-moz-osx-font-smoothing: grayscale;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
header {
|
|
17
|
+
display: flex;
|
|
18
|
+
flex-direction: row;
|
|
19
|
+
align-items: center;
|
|
20
|
+
padding: 2rem;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
a {
|
|
24
|
+
font-weight: 500;
|
|
25
|
+
color: #646cff;
|
|
26
|
+
pointer-events: auto;
|
|
27
|
+
text-decoration: inherit;
|
|
28
|
+
}
|
|
29
|
+
a:hover {
|
|
30
|
+
color: #535bf2;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
body {
|
|
34
|
+
width: 100%;
|
|
35
|
+
height: 100%;
|
|
36
|
+
padding: 0;
|
|
37
|
+
margin: 0;
|
|
38
|
+
overflow: hidden;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
h1 {
|
|
42
|
+
font-size: 2.4em;
|
|
43
|
+
line-height: 1.1;
|
|
44
|
+
opacity: 0.85;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.logo {
|
|
48
|
+
height: 2em;
|
|
49
|
+
padding: 0.5em;
|
|
50
|
+
will-change: filter;
|
|
51
|
+
transition: filter 300ms;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.playcanvas-logo {
|
|
55
|
+
border-radius: 100%;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.logo:hover {
|
|
59
|
+
filter: drop-shadow(0 0 2em #646cffaa);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.logo.typescript:hover {
|
|
63
|
+
filter: drop-shadow(0 0 2em #3178c6aa);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
pc-app {
|
|
67
|
+
display: block;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.read-the-docs {
|
|
71
|
+
color: #888;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
@media (prefers-color-scheme: light) {
|
|
75
|
+
:root {
|
|
76
|
+
color: #213547;
|
|
77
|
+
background-color: #ffffff;
|
|
78
|
+
}
|
|
79
|
+
a:hover {
|
|
80
|
+
color: #747bff;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.overlay {
|
|
85
|
+
margin: 0 auto;
|
|
86
|
+
text-align: center;
|
|
87
|
+
display: flex;
|
|
88
|
+
flex-direction: column;
|
|
89
|
+
align-items: center;
|
|
90
|
+
justify-content: stretch;
|
|
91
|
+
width: 100vw;
|
|
92
|
+
height: 100vh;
|
|
93
|
+
pointer-events: none;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.overlay > .grow {
|
|
97
|
+
flex-grow: 1;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.absolute {
|
|
101
|
+
position: absolute;
|
|
102
|
+
top: 0;
|
|
103
|
+
left: 0;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.pill {
|
|
107
|
+
background-color: #000;
|
|
108
|
+
color: #fff;
|
|
109
|
+
padding: 0.5rem 1rem;
|
|
110
|
+
border-radius: 0.5rem;
|
|
111
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<link rel="icon" type="image/png" href="/src/assets/playcanvas.png" />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
+
<title>PlayCanvas + Web Components</title>
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<pc-app>
|
|
11
|
+
<!-- Swap this for your own model - anything you drop in public/ is served from the site root -->
|
|
12
|
+
<pc-asset id="model" src="/playcanvas-cube.glb"></pc-asset>
|
|
13
|
+
|
|
14
|
+
<pc-scene>
|
|
15
|
+
<!-- Camera. Orbit controls are attached in src/main.ts. The sky is HDR, so it needs
|
|
16
|
+
tone mapping to bring it back into displayable range - without it the whole
|
|
17
|
+
image blows out to white -->
|
|
18
|
+
<pc-entity name="camera" position="0 0 3">
|
|
19
|
+
<pc-camera tonemap="aces2"></pc-camera>
|
|
20
|
+
</pc-entity>
|
|
21
|
+
|
|
22
|
+
<!-- The procedural sky is both the background and the image-based lighting, so no
|
|
23
|
+
light or environment map asset is needed. The script is attached in src/main.ts -->
|
|
24
|
+
<pc-entity name="sky"></pc-entity>
|
|
25
|
+
|
|
26
|
+
<pc-entity name="model">
|
|
27
|
+
<pc-model asset="model"></pc-model>
|
|
28
|
+
</pc-entity>
|
|
29
|
+
</pc-scene>
|
|
30
|
+
</pc-app>
|
|
31
|
+
|
|
32
|
+
<script type="module" src="/src/main.ts"></script>
|
|
33
|
+
</body>
|
|
34
|
+
</html>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { EntityElement } from '@playcanvas/web-components';
|
|
2
|
+
import { whenReady } from '@playcanvas/web-components';
|
|
3
|
+
import { CameraControls } from 'playcanvas/scripts/esm/camera-controls.mjs';
|
|
4
|
+
import { ProceduralSky } from 'playcanvas/scripts/esm/sky/procedural-sky.mjs';
|
|
5
|
+
|
|
6
|
+
import './style.css';
|
|
7
|
+
|
|
8
|
+
// The camera is awaited as <pc-camera> rather than the <pc-entity> holding it - an entity becomes
|
|
9
|
+
// ready before its component children do, and CameraControls needs the camera component to exist
|
|
10
|
+
const [cameraComponent, sky] = await Promise.all([
|
|
11
|
+
whenReady('pc-camera'),
|
|
12
|
+
whenReady<EntityElement>('pc-entity[name="sky"]')
|
|
13
|
+
]);
|
|
14
|
+
|
|
15
|
+
// Engine scripts are resolved by the bundler, so they are attached through the entity rather than
|
|
16
|
+
// with <pc-script name="...">, which only resolves scripts fetched at runtime by <pc-asset>
|
|
17
|
+
const camera = cameraComponent.closestEntity;
|
|
18
|
+
camera?.entity?.addComponent('script');
|
|
19
|
+
camera?.entity?.script?.create(CameraControls);
|
|
20
|
+
|
|
21
|
+
sky.entity?.addComponent('script');
|
|
22
|
+
|
|
23
|
+
// The sky's default luminance is scene-scale bright, so turn it down to keep the model out of clipping
|
|
24
|
+
sky.entity?.script?.create(ProceduralSky, {
|
|
25
|
+
properties: { luminance: 0.2 }
|
|
26
|
+
});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<link rel="icon" type="image/png" href="/src/assets/playcanvas.png" />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
+
<title>PlayCanvas + Web Components</title>
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<pc-app>
|
|
11
|
+
<pc-scene>
|
|
12
|
+
<pc-entity name="camera" position="0 0 3">
|
|
13
|
+
<pc-camera clear-color="#8099e6"></pc-camera>
|
|
14
|
+
</pc-entity>
|
|
15
|
+
|
|
16
|
+
<pc-entity name="light" rotation="45 0 0">
|
|
17
|
+
<pc-light></pc-light>
|
|
18
|
+
</pc-entity>
|
|
19
|
+
|
|
20
|
+
<!-- The rotate script is attached in src/main.ts -->
|
|
21
|
+
<pc-entity name="cube">
|
|
22
|
+
<pc-render type="box"></pc-render>
|
|
23
|
+
</pc-entity>
|
|
24
|
+
</pc-scene>
|
|
25
|
+
</pc-app>
|
|
26
|
+
|
|
27
|
+
<script type="module" src="/src/main.ts"></script>
|
|
28
|
+
</body>
|
|
29
|
+
</html>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { EntityElement } from '@playcanvas/web-components';
|
|
2
|
+
import { whenReady } from '@playcanvas/web-components';
|
|
3
|
+
import { Script } from 'playcanvas';
|
|
4
|
+
|
|
5
|
+
import './style.css';
|
|
6
|
+
|
|
7
|
+
class Rotate extends Script {
|
|
8
|
+
static scriptName = 'rotate';
|
|
9
|
+
|
|
10
|
+
update(dt: number) {
|
|
11
|
+
this.entity.rotate(10 * dt, 20 * dt, 30 * dt);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Engine scripts are resolved by the bundler, so they are attached through the entity rather than
|
|
16
|
+
// with <pc-script name="...">, which only resolves scripts fetched at runtime by <pc-asset>
|
|
17
|
+
const cube = await whenReady<EntityElement>('pc-entity[name="cube"]');
|
|
18
|
+
|
|
19
|
+
cube.entity?.addComponent('script');
|
|
20
|
+
cube.entity?.script?.create(Rotate);
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<link rel="icon" type="image/png" href="/src/assets/playcanvas.png" />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
+
<title>PlayCanvas + Web Components</title>
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<!-- Antialiasing is disabled - splat rendering is fragment bound, so MSAA costs a lot and adds little -->
|
|
11
|
+
<pc-app antialias="false" high-resolution="false">
|
|
12
|
+
<!-- Hosted so the template stays small. Capture or edit your own splat at
|
|
13
|
+
https://superspl.at, then drop the .sog or .ply in public/ and point this at it instead -->
|
|
14
|
+
<pc-asset id="splat" src="https://developer.playcanvas.com/assets/toy-cat.sog"></pc-asset>
|
|
15
|
+
|
|
16
|
+
<pc-scene>
|
|
17
|
+
<!-- Camera. Orbit controls are attached in src/main.ts -->
|
|
18
|
+
<pc-entity name="camera" position="0 0 2.5">
|
|
19
|
+
<pc-camera></pc-camera>
|
|
20
|
+
</pc-entity>
|
|
21
|
+
|
|
22
|
+
<!-- Splats are captured in their own space, so this one needs offsetting and flipping upright -->
|
|
23
|
+
<pc-entity name="toy cat" position="0 -0.7 0" rotation="0 0 180">
|
|
24
|
+
<pc-gsplat asset="splat"></pc-gsplat>
|
|
25
|
+
</pc-entity>
|
|
26
|
+
</pc-scene>
|
|
27
|
+
</pc-app>
|
|
28
|
+
|
|
29
|
+
<script type="module" src="/src/main.ts"></script>
|
|
30
|
+
</body>
|
|
31
|
+
</html>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { whenReady } from '@playcanvas/web-components';
|
|
2
|
+
import { CameraControls } from 'playcanvas/scripts/esm/camera-controls.mjs';
|
|
3
|
+
|
|
4
|
+
import './style.css';
|
|
5
|
+
|
|
6
|
+
// The camera is awaited as <pc-camera> rather than the <pc-entity> holding it - an entity becomes
|
|
7
|
+
// ready before its component children do, and CameraControls needs the camera component to exist
|
|
8
|
+
const cameraComponent = await whenReady('pc-camera');
|
|
9
|
+
|
|
10
|
+
// Engine scripts are resolved by the bundler, so they are attached through the entity rather than
|
|
11
|
+
// with <pc-script name="...">, which only resolves scripts fetched at runtime by <pc-asset>
|
|
12
|
+
const camera = cameraComponent.closestEntity;
|
|
13
|
+
camera?.entity?.addComponent('script');
|
|
14
|
+
camera?.entity?.script?.create(CameraControls);
|
|
Binary file
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|