create-playcanvas 0.5.0 → 0.6.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 +20 -27
- package/dist/index.mjs +44 -42
- package/package.json +1 -1
- package/templates/_features/physics/assets/public/ammo/LICENSE +21 -0
- package/templates/_features/physics/assets/public/ammo/SOURCE.md +16 -0
- package/templates/_features/physics/assets/public/ammo/ammo.js +973 -0
- package/templates/_features/physics/assets/public/ammo/ammo.wasm.js +937 -0
- package/templates/_features/physics/assets/public/ammo/ammo.wasm.wasm +0 -0
- package/templates/_features/physics/react/package.json +5 -0
- package/templates/_features/physics/react/src/sync-ammo.d.ts +4 -0
- package/templates/_shared/ar-placement/README.md +7 -0
- package/templates/_shared/ar-placement/src/ar-placement.ts +123 -0
- package/templates/_shared/first-person-controller/README.md +7 -0
- package/templates/_shared/first-person-controller/src/controller.ts +18 -0
- package/templates/_shared/first-person-controller/src/scripts.d.ts +5 -0
- package/templates/_shared/interactive-sphere/README.md +7 -0
- package/templates/_shared/model-viewer/README.md +7 -0
- package/templates/_shared/physics-playground/README.md +7 -0
- package/templates/_shared/product-configurator/ASSET_LICENSES.md +3 -0
- package/templates/_shared/product-configurator/README.md +7 -0
- package/templates/_shared/product-configurator/src/product.css +14 -0
- package/templates/_shared/scene-editor/README.md +7 -0
- package/templates/_shared/scene-editor/src/scene-editor.ts +57 -0
- package/templates/_shared/spinning-cube/README.md +7 -0
- package/templates/_shared/splat-viewer/README.md +7 -0
- package/templates/_shared/sprite-game/README.md +7 -0
- package/templates/_shared/sprite-game/src/sprite-game.ts +197 -0
- package/templates/_shared/third-person-controller/README.md +7 -0
- package/templates/_shared/third-person-controller/src/controller.ts +53 -0
- package/templates/_shared/third-person-controller/src/scripts.d.ts +5 -0
- package/templates/_shared/vr-starter/README.md +7 -0
- package/templates/_shared/vr-starter/src/vr.ts +40 -0
- package/templates/_shared/vr-starter/src/xr.d.ts +11 -0
- package/templates/engine/ar-placement/src/main.ts +77 -0
- package/templates/engine/base/.prettierignore +1 -0
- package/templates/engine/base/README.md +1 -1
- package/templates/engine/base/_npmrc +1 -0
- package/templates/engine/base/eslint.config.mjs +1 -1
- package/templates/engine/base/index.html +13 -0
- package/templates/engine/base/package.json +2 -2
- package/templates/engine/base/src/starter.css +104 -0
- package/templates/engine/first-person-controller/src/main.ts +139 -0
- package/templates/engine/interactive-sphere/src/App.ts +9 -7
- package/templates/engine/interactive-sphere/src/main.ts +2 -29
- package/templates/engine/interactive-sphere/src/style.css +18 -97
- package/templates/engine/model-viewer/src/main.ts +3 -2
- package/templates/engine/physics-playground/src/main.ts +132 -0
- package/templates/engine/product-configurator/src/main.ts +156 -0
- package/templates/engine/scene-editor/src/main.ts +90 -0
- package/templates/engine/splat-viewer/src/main.ts +4 -3
- package/templates/engine/sprite-game/src/main.ts +72 -0
- package/templates/engine/third-person-controller/src/main.ts +216 -0
- package/templates/engine/vr-starter/src/main.ts +101 -0
- package/templates/index.ts +66 -5
- package/templates/react/ar-placement/src/App.tsx +58 -0
- package/templates/react/base/.prettierignore +1 -0
- package/templates/react/base/README.md +1 -1
- package/templates/react/base/_npmrc +1 -0
- package/templates/react/base/eslint.config.mjs +1 -1
- package/templates/react/base/index.html +13 -0
- package/templates/react/base/package.json +2 -2
- package/templates/react/base/src/main.tsx +10 -0
- package/templates/react/base/src/starter.css +104 -0
- package/templates/react/first-person-controller/src/App.tsx +115 -0
- package/templates/react/interactive-sphere/src/App.css +18 -68
- package/templates/react/interactive-sphere/src/App.tsx +1 -22
- package/templates/react/interactive-sphere/src/Scene.tsx +7 -6
- package/templates/react/interactive-sphere/src/index.css +1 -48
- package/templates/react/model-viewer/src/App.tsx +2 -2
- package/templates/react/physics-playground/src/App.tsx +85 -0
- package/templates/react/product-configurator/src/App.tsx +157 -0
- package/templates/react/scene-editor/src/App.tsx +84 -0
- package/templates/react/splat-viewer/src/App.tsx +3 -3
- package/templates/react/sprite-game/src/App.tsx +38 -0
- package/templates/react/third-person-controller/src/App.tsx +193 -0
- package/templates/react/vr-starter/src/App.tsx +99 -0
- package/templates/web-components/ar-placement/index.html +44 -0
- package/templates/web-components/ar-placement/src/main.ts +13 -0
- package/templates/web-components/base/.prettierignore +1 -0
- package/templates/web-components/base/README.md +1 -1
- package/templates/web-components/base/_npmrc +1 -0
- package/templates/web-components/base/eslint.config.mjs +1 -1
- package/templates/web-components/base/package.json +3 -3
- package/templates/web-components/base/src/starter.css +104 -0
- package/templates/web-components/first-person-controller/index.html +168 -0
- package/templates/web-components/first-person-controller/src/main.ts +15 -0
- package/templates/web-components/interactive-sphere/index.html +5 -22
- package/templates/web-components/interactive-sphere/src/main.ts +5 -4
- package/templates/web-components/interactive-sphere/src/style.css +18 -76
- package/templates/web-components/model-viewer/index.html +1 -1
- package/templates/web-components/model-viewer/src/main.ts +2 -1
- package/templates/web-components/physics-playground/index.html +51 -0
- package/templates/web-components/physics-playground/src/main.ts +32 -0
- package/templates/web-components/product-configurator/index.html +51 -0
- package/templates/web-components/product-configurator/src/main.ts +93 -0
- package/templates/web-components/scene-editor/index.html +51 -0
- package/templates/web-components/scene-editor/src/main.ts +26 -0
- package/templates/web-components/spinning-cube/src/main.ts +1 -0
- package/templates/web-components/splat-viewer/index.html +2 -2
- package/templates/web-components/splat-viewer/src/main.ts +2 -1
- package/templates/web-components/sprite-game/index.html +34 -0
- package/templates/web-components/sprite-game/src/main.ts +9 -0
- package/templates/web-components/third-person-controller/index.html +183 -0
- package/templates/web-components/third-person-controller/src/main.ts +16 -0
- package/templates/web-components/vr-starter/index.html +80 -0
- package/templates/web-components/vr-starter/src/main.ts +12 -0
- package/templates/engine/interactive-sphere/src/assets/typescript.svg +0 -1
- package/templates/react/interactive-sphere/src/assets/react.svg +0 -1
- package/templates/web-components/interactive-sphere/src/assets/typescript.svg +0 -1
|
@@ -1,39 +1,4 @@
|
|
|
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
1
|
body {
|
|
34
|
-
width: 100%;
|
|
35
|
-
height: 100%;
|
|
36
|
-
padding: 0;
|
|
37
2
|
margin: 0;
|
|
38
3
|
overflow: hidden;
|
|
39
4
|
}
|
|
@@ -67,45 +32,22 @@ pc-app {
|
|
|
67
32
|
display: block;
|
|
68
33
|
}
|
|
69
34
|
|
|
70
|
-
.
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
:
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
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;
|
|
35
|
+
.counter {
|
|
36
|
+
position: fixed;
|
|
37
|
+
bottom: 22px;
|
|
38
|
+
left: 50%;
|
|
39
|
+
z-index: 2;
|
|
40
|
+
margin: 0;
|
|
41
|
+
padding: 9px 13px;
|
|
42
|
+
border: 1px solid #ffffff24;
|
|
43
|
+
border-radius: 999px;
|
|
44
|
+
background: #07101bd9;
|
|
45
|
+
color: #f8fafc;
|
|
46
|
+
font:
|
|
47
|
+
650 12px Inter,
|
|
48
|
+
ui-sans-serif,
|
|
49
|
+
system-ui,
|
|
50
|
+
sans-serif;
|
|
51
|
+
translate: -50% 0;
|
|
52
|
+
backdrop-filter: blur(10px);
|
|
111
53
|
}
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
<!-- Camera. Orbit controls are attached in src/main.ts. The sky is HDR, so it needs
|
|
16
16
|
tone mapping to bring it back into displayable range - without it the whole
|
|
17
17
|
image blows out to white -->
|
|
18
|
-
<pc-entity name="camera" position="
|
|
18
|
+
<pc-entity name="camera" position="2.6 1.5 3.2" rotation="-16 39 0">
|
|
19
19
|
<pc-camera tonemap="aces2"></pc-camera>
|
|
20
20
|
</pc-entity>
|
|
21
21
|
|
|
@@ -3,6 +3,7 @@ import { whenReady } from '@playcanvas/web-components';
|
|
|
3
3
|
import { CameraControls } from 'playcanvas/scripts/esm/camera-controls.mjs';
|
|
4
4
|
import { ProceduralSky } from 'playcanvas/scripts/esm/sky/procedural-sky.mjs';
|
|
5
5
|
|
|
6
|
+
import './starter.css';
|
|
6
7
|
import './style.css';
|
|
7
8
|
|
|
8
9
|
// The camera is awaited as <pc-camera> rather than the <pc-entity> holding it - an entity becomes
|
|
@@ -16,7 +17,7 @@ const [cameraComponent, sky] = await Promise.all([
|
|
|
16
17
|
// with <pc-script name="...">, which only resolves scripts fetched at runtime by <pc-asset>
|
|
17
18
|
const camera = cameraComponent.closestEntity;
|
|
18
19
|
camera?.entity?.addComponent('script');
|
|
19
|
-
camera?.entity?.script?.create(CameraControls);
|
|
20
|
+
camera?.entity?.script?.create(CameraControls, { properties: { sceneSize: 2.5 } });
|
|
20
21
|
|
|
21
22
|
sky.entity?.addComponent('script');
|
|
22
23
|
|
|
@@ -0,0 +1,51 @@
|
|
|
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>Physics Playground</title>
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<pc-app>
|
|
11
|
+
<pc-module
|
|
12
|
+
name="Ammo"
|
|
13
|
+
glue="/ammo/ammo.wasm.js"
|
|
14
|
+
wasm="/ammo/ammo.wasm.wasm"
|
|
15
|
+
fallback="/ammo/ammo.js"
|
|
16
|
+
></pc-module>
|
|
17
|
+
<pc-material id="floor-material" diffuse="#2e333d" gloss="0.2"></pc-material>
|
|
18
|
+
<pc-material id="cyan-material" diffuse="#29ade6" gloss="0.45"></pc-material>
|
|
19
|
+
<pc-material id="coral-material" diffuse="#f25738" gloss="0.45"></pc-material>
|
|
20
|
+
<pc-material id="yellow-material" diffuse="#f9ad2e" gloss="0.45"></pc-material>
|
|
21
|
+
<pc-scene>
|
|
22
|
+
<pc-entity name="camera" position="10 8 10" rotation="-23 45 0"
|
|
23
|
+
><pc-camera clear-color="#0d121c"></pc-camera
|
|
24
|
+
></pc-entity>
|
|
25
|
+
<pc-entity name="light" rotation="45 35 0"
|
|
26
|
+
><pc-light
|
|
27
|
+
type="directional"
|
|
28
|
+
intensity="2.5"
|
|
29
|
+
cast-shadows
|
|
30
|
+
shadow-bias="0.2"
|
|
31
|
+
normal-offset-bias="0.05"
|
|
32
|
+
></pc-light
|
|
33
|
+
></pc-entity>
|
|
34
|
+
<pc-entity name="floor" position="0 -0.1 0" scale="10 0.2 10"
|
|
35
|
+
><pc-render type="box" material="floor-material"></pc-render
|
|
36
|
+
><pc-collision type="box" half-extents="5 0.1 5"></pc-collision
|
|
37
|
+
><pc-rigidbody type="static"></pc-rigidbody
|
|
38
|
+
></pc-entity>
|
|
39
|
+
<pc-entity id="bodies"></pc-entity>
|
|
40
|
+
</pc-scene>
|
|
41
|
+
</pc-app>
|
|
42
|
+
<div class="hud">
|
|
43
|
+
<section class="panel">
|
|
44
|
+
<h1>Physics Playground</h1>
|
|
45
|
+
<p>Rigid bodies, collisions and runtime spawning.</p>
|
|
46
|
+
<div class="controls"><button id="spawn">Spawn object</button><button id="reset">Reset</button></div>
|
|
47
|
+
</section>
|
|
48
|
+
</div>
|
|
49
|
+
<script type="module" src="/src/main.ts"></script>
|
|
50
|
+
</body>
|
|
51
|
+
</html>
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { whenReady } from '@playcanvas/web-components';
|
|
2
|
+
import { CameraControls } from 'playcanvas/scripts/esm/camera-controls.mjs';
|
|
3
|
+
|
|
4
|
+
import './starter.css';
|
|
5
|
+
|
|
6
|
+
const MATERIALS = ['cyan-material', 'coral-material', 'yellow-material'];
|
|
7
|
+
const TYPES = ['box', 'sphere', 'capsule', 'cylinder'];
|
|
8
|
+
const SCALES = ['0.9 0.9 0.9', '0.9 0.9 0.9', '0.7 1.1 0.7', '0.8 1.1 0.8'];
|
|
9
|
+
|
|
10
|
+
const camera = (await whenReady('pc-camera')).closestEntity!.entity!;
|
|
11
|
+
camera.addComponent('script');
|
|
12
|
+
camera.script!.create(CameraControls, { properties: { sceneSize: 10 } });
|
|
13
|
+
|
|
14
|
+
const bodies = document.getElementById('bodies')!;
|
|
15
|
+
let count = 0;
|
|
16
|
+
const spawn = () => {
|
|
17
|
+
const i = count++;
|
|
18
|
+
const type = TYPES[i % TYPES.length];
|
|
19
|
+
bodies.insertAdjacentHTML(
|
|
20
|
+
'beforeend',
|
|
21
|
+
`<pc-entity data-body position="${((i % 4) - 1.5) * 1.1} ${0.7 + Math.floor(i / 4) * 1.1} ${(Math.floor(i / 4) - 1) * 1.4}" rotation="${i * 13} ${i * 29} 0" scale="${SCALES[i % SCALES.length]}"><pc-render type="${type}" material="${MATERIALS[i % MATERIALS.length]}"></pc-render><pc-collision type="${type}"></pc-collision><pc-rigidbody type="dynamic" mass="1" restitution="0.35"></pc-rigidbody></pc-entity>`
|
|
22
|
+
);
|
|
23
|
+
};
|
|
24
|
+
const reset = () => {
|
|
25
|
+
bodies.replaceChildren();
|
|
26
|
+
count = 0;
|
|
27
|
+
for (let i = 0; i < 12; i++) spawn();
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
document.getElementById('spawn')!.onclick = spawn;
|
|
31
|
+
document.getElementById('reset')!.onclick = reset;
|
|
32
|
+
reset();
|
|
@@ -0,0 +1,51 @@
|
|
|
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>Product Configurator</title>
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<pc-app>
|
|
11
|
+
<pc-asset id="car" src="https://developer.playcanvas.com/assets/lambo.glb"></pc-asset>
|
|
12
|
+
<pc-scene>
|
|
13
|
+
<pc-entity name="sky"></pc-entity>
|
|
14
|
+
<pc-entity name="camera" position="5.5 3.2 6.5" rotation="-16 40 0">
|
|
15
|
+
<pc-camera fov="40" tonemap="aces2"></pc-camera>
|
|
16
|
+
</pc-entity>
|
|
17
|
+
<pc-entity name="light" rotation="45 -145 0">
|
|
18
|
+
<pc-light
|
|
19
|
+
type="directional"
|
|
20
|
+
intensity="2.5"
|
|
21
|
+
cast-shadows
|
|
22
|
+
shadow-bias="0.2"
|
|
23
|
+
normal-offset-bias="0.05"
|
|
24
|
+
></pc-light>
|
|
25
|
+
</pc-entity>
|
|
26
|
+
<pc-entity name="studio-ground"></pc-entity>
|
|
27
|
+
<pc-entity name="car">
|
|
28
|
+
<pc-model asset="car"></pc-model>
|
|
29
|
+
</pc-entity>
|
|
30
|
+
</pc-scene>
|
|
31
|
+
</pc-app>
|
|
32
|
+
<div class="hud">
|
|
33
|
+
<section class="panel">
|
|
34
|
+
<h1>Product Configurator</h1>
|
|
35
|
+
<p>Choose a paint finish, then drag to orbit.</p>
|
|
36
|
+
<div class="controls variants" id="paints">
|
|
37
|
+
<button aria-pressed="true" data-color="#d6293e" data-shade="#9b1731">
|
|
38
|
+
<span class="finish" style="--color: #d6293e"></span>Crimson
|
|
39
|
+
</button>
|
|
40
|
+
<button data-color="#d8e4e9" data-shade="#8fa8b5">
|
|
41
|
+
<span class="finish" style="--color: #d8e4e9"></span>Arctic
|
|
42
|
+
</button>
|
|
43
|
+
<button data-color="#9acb34" data-shade="#3c742d">
|
|
44
|
+
<span class="finish" style="--color: #9acb34"></span>Volt
|
|
45
|
+
</button>
|
|
46
|
+
</div>
|
|
47
|
+
</section>
|
|
48
|
+
</div>
|
|
49
|
+
<script type="module" src="/src/main.ts"></script>
|
|
50
|
+
</body>
|
|
51
|
+
</html>
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import type { AssetElement, EntityElement, ModelElement } from '@playcanvas/web-components';
|
|
2
|
+
import { whenReady } from '@playcanvas/web-components';
|
|
3
|
+
import type { RenderComponent } from 'playcanvas';
|
|
4
|
+
import { Color, CylinderGeometry, Mesh, MeshInstance, StandardMaterial, Vec2, Vec3 } from 'playcanvas';
|
|
5
|
+
import { CameraControls } from 'playcanvas/scripts/esm/camera-controls.mjs';
|
|
6
|
+
import { ProceduralSky } from 'playcanvas/scripts/esm/sky/procedural-sky.mjs';
|
|
7
|
+
|
|
8
|
+
import './product.css';
|
|
9
|
+
import './starter.css';
|
|
10
|
+
|
|
11
|
+
const CAMERA_FOCUS = new Vec3(0, 0.8, 0);
|
|
12
|
+
const CAMERA_PITCH = new Vec2(-85, -4);
|
|
13
|
+
|
|
14
|
+
const [cameraComponent, , model, sky, groundElement] = await Promise.all([
|
|
15
|
+
whenReady('pc-camera'),
|
|
16
|
+
whenReady<AssetElement>('#car'),
|
|
17
|
+
whenReady<ModelElement>('pc-model'),
|
|
18
|
+
whenReady<EntityElement>('pc-entity[name="sky"]'),
|
|
19
|
+
whenReady<EntityElement>('pc-entity[name="studio-ground"]')
|
|
20
|
+
]);
|
|
21
|
+
|
|
22
|
+
const camera = cameraComponent.closestEntity!.entity!;
|
|
23
|
+
const app = camera.camera!.system.app;
|
|
24
|
+
camera.camera!.requestSceneColorMap(true);
|
|
25
|
+
camera.addComponent('script');
|
|
26
|
+
camera.script!.create(CameraControls, {
|
|
27
|
+
properties: {
|
|
28
|
+
sceneSize: 6.2,
|
|
29
|
+
focusPoint: CAMERA_FOCUS,
|
|
30
|
+
pitchRange: CAMERA_PITCH,
|
|
31
|
+
enableFly: false,
|
|
32
|
+
enablePan: false
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
sky.entity!.addComponent('script');
|
|
37
|
+
sky.entity!.script!.create(ProceduralSky, { properties: { luminance: 0.18 } });
|
|
38
|
+
|
|
39
|
+
const podium = new StandardMaterial();
|
|
40
|
+
podium.diffuse = new Color(0.3, 0.32, 0.34);
|
|
41
|
+
podium.metalness = 0.15;
|
|
42
|
+
podium.gloss = 0.65;
|
|
43
|
+
podium.update();
|
|
44
|
+
|
|
45
|
+
const ground = groundElement.entity!;
|
|
46
|
+
ground.setPosition(0, -0.08, 0);
|
|
47
|
+
ground.addComponent('render', {
|
|
48
|
+
meshInstances: [
|
|
49
|
+
new MeshInstance(
|
|
50
|
+
Mesh.fromGeometry(
|
|
51
|
+
app.graphicsDevice,
|
|
52
|
+
new CylinderGeometry({ radius: 4, height: 0.16, heightSegments: 1, capSegments: 128 })
|
|
53
|
+
),
|
|
54
|
+
podium
|
|
55
|
+
)
|
|
56
|
+
],
|
|
57
|
+
castShadows: false,
|
|
58
|
+
receiveShadows: true
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
const entity = model.entity!;
|
|
62
|
+
entity.setLocalEulerAngles(-90, -25, 0);
|
|
63
|
+
entity.root.syncHierarchy();
|
|
64
|
+
const meshes = (entity.findComponents('render') as RenderComponent[]).flatMap((render) => render.meshInstances);
|
|
65
|
+
const bounds = meshes[0].aabb.clone();
|
|
66
|
+
meshes.slice(1).forEach((mesh) => bounds.add(mesh.aabb));
|
|
67
|
+
const scale = 5 / Math.max(bounds.halfExtents.x * 2, bounds.halfExtents.z * 2);
|
|
68
|
+
entity.setLocalScale(scale, scale, scale);
|
|
69
|
+
entity.root.syncHierarchy();
|
|
70
|
+
bounds.copy(meshes[0].aabb);
|
|
71
|
+
meshes.slice(1).forEach((mesh) => bounds.add(mesh.aabb));
|
|
72
|
+
entity.setPosition(-bounds.center.x, 0.03 - bounds.getMin().y, -bounds.center.z);
|
|
73
|
+
|
|
74
|
+
const body = meshes.filter((mesh) => mesh.material.name === 'material');
|
|
75
|
+
const panels = meshes.filter((mesh) => mesh.material.name === 'material_1');
|
|
76
|
+
const paint = body[0].material.clone() as StandardMaterial;
|
|
77
|
+
const shade = panels[0].material.clone() as StandardMaterial;
|
|
78
|
+
body.forEach((mesh) => (mesh.material = paint));
|
|
79
|
+
panels.forEach((mesh) => (mesh.material = shade));
|
|
80
|
+
paint.diffuse.fromString('#d6293e');
|
|
81
|
+
shade.diffuse.fromString('#9b1731');
|
|
82
|
+
paint.update();
|
|
83
|
+
shade.update();
|
|
84
|
+
|
|
85
|
+
document.querySelectorAll<HTMLButtonElement>('#paints button').forEach((button, i, buttons) => {
|
|
86
|
+
button.onclick = () => {
|
|
87
|
+
paint.diffuse.fromString(button.dataset.color!);
|
|
88
|
+
shade.diffuse.fromString(button.dataset.shade!);
|
|
89
|
+
paint.update();
|
|
90
|
+
shade.update();
|
|
91
|
+
buttons.forEach((item, j) => (item.ariaPressed = String(i === j)));
|
|
92
|
+
};
|
|
93
|
+
});
|
|
@@ -0,0 +1,51 @@
|
|
|
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>Scene Editor</title>
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<pc-app>
|
|
11
|
+
<pc-material id="coral" diffuse="#ff5145"></pc-material>
|
|
12
|
+
<pc-material id="cyan" diffuse="#24addf"></pc-material>
|
|
13
|
+
<pc-scene>
|
|
14
|
+
<pc-entity name="camera" position="4 3.2 5" rotation="-18 39 0"
|
|
15
|
+
><pc-camera clear-color="#0a0f17"></pc-camera
|
|
16
|
+
></pc-entity>
|
|
17
|
+
<pc-entity name="light" rotation="45 30 0"
|
|
18
|
+
><pc-light
|
|
19
|
+
type="directional"
|
|
20
|
+
intensity="2.5"
|
|
21
|
+
cast-shadows
|
|
22
|
+
shadow-bias="0.2"
|
|
23
|
+
normal-offset-bias="0.05"
|
|
24
|
+
></pc-light
|
|
25
|
+
></pc-entity>
|
|
26
|
+
<pc-entity name="grid" scale="12 12 12"></pc-entity>
|
|
27
|
+
<pc-entity name="cube" position="-1.2 0.5 0"
|
|
28
|
+
><pc-render type="box" material="coral"></pc-render
|
|
29
|
+
></pc-entity>
|
|
30
|
+
<pc-entity name="sphere" position="1.2 0.5 0"
|
|
31
|
+
><pc-render type="sphere" material="cyan"></pc-render
|
|
32
|
+
></pc-entity>
|
|
33
|
+
<pc-entity name="editor"></pc-entity>
|
|
34
|
+
</pc-scene>
|
|
35
|
+
</pc-app>
|
|
36
|
+
<div class="hud">
|
|
37
|
+
<section class="panel">
|
|
38
|
+
<h1>Scene Editor</h1>
|
|
39
|
+
<p>Select an object, then translate, rotate or scale it.</p>
|
|
40
|
+
<div class="controls">
|
|
41
|
+
<button data-target="0" aria-pressed="true">Cube</button><button data-target="1">Sphere</button>
|
|
42
|
+
</div>
|
|
43
|
+
<div class="controls">
|
|
44
|
+
<button data-mode="translate" aria-pressed="true">Move</button
|
|
45
|
+
><button data-mode="rotate">Rotate</button><button data-mode="scale">Scale</button>
|
|
46
|
+
</div>
|
|
47
|
+
</section>
|
|
48
|
+
</div>
|
|
49
|
+
<script type="module" src="/src/main.ts"></script>
|
|
50
|
+
</body>
|
|
51
|
+
</html>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { EntityElement } from '@playcanvas/web-components';
|
|
2
|
+
import { whenReady } from '@playcanvas/web-components';
|
|
3
|
+
import { Grid } from 'playcanvas/scripts/esm/grid.mjs';
|
|
4
|
+
|
|
5
|
+
import { SceneEditor } from './scene-editor';
|
|
6
|
+
import './starter.css';
|
|
7
|
+
|
|
8
|
+
const [appElement, camera, grid, cube, sphere, editor] = await Promise.all([
|
|
9
|
+
whenReady('pc-app'),
|
|
10
|
+
whenReady<EntityElement>('pc-entity[name="camera"]'),
|
|
11
|
+
whenReady<EntityElement>('pc-entity[name="grid"]'),
|
|
12
|
+
whenReady<EntityElement>('pc-entity[name="cube"]'),
|
|
13
|
+
whenReady<EntityElement>('pc-entity[name="sphere"]'),
|
|
14
|
+
whenReady<EntityElement>('pc-entity[name="editor"]')
|
|
15
|
+
]);
|
|
16
|
+
|
|
17
|
+
grid.entity!.addComponent('script');
|
|
18
|
+
grid.entity!.script!.create(Grid);
|
|
19
|
+
editor.entity!.addComponent('script');
|
|
20
|
+
editor.entity!.script!.create(SceneEditor, {
|
|
21
|
+
properties: {
|
|
22
|
+
camera: camera.entity,
|
|
23
|
+
targets: [cube.entity, sphere.entity],
|
|
24
|
+
layer: appElement.app!.scene.layers.getLayerByName('World')
|
|
25
|
+
}
|
|
26
|
+
});
|
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
|
|
16
16
|
<pc-scene>
|
|
17
17
|
<!-- Camera. Orbit controls are attached in src/main.ts -->
|
|
18
|
-
<pc-entity name="camera" position="0 0 2.
|
|
19
|
-
<pc-camera></pc-camera>
|
|
18
|
+
<pc-entity name="camera" position="0 0 2.8">
|
|
19
|
+
<pc-camera clear-color="#8f949e"></pc-camera>
|
|
20
20
|
</pc-entity>
|
|
21
21
|
|
|
22
22
|
<!-- Splats are captured in their own space, so this one needs offsetting and flipping upright -->
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { whenReady } from '@playcanvas/web-components';
|
|
2
2
|
import { CameraControls } from 'playcanvas/scripts/esm/camera-controls.mjs';
|
|
3
3
|
|
|
4
|
+
import './starter.css';
|
|
4
5
|
import './style.css';
|
|
5
6
|
|
|
6
7
|
// The camera is awaited as <pc-camera> rather than the <pc-entity> holding it - an entity becomes
|
|
@@ -11,4 +12,4 @@ const cameraComponent = await whenReady('pc-camera');
|
|
|
11
12
|
// with <pc-script name="...">, which only resolves scripts fetched at runtime by <pc-asset>
|
|
12
13
|
const camera = cameraComponent.closestEntity;
|
|
13
14
|
camera?.entity?.addComponent('script');
|
|
14
|
-
camera?.entity?.script?.create(CameraControls);
|
|
15
|
+
camera?.entity?.script?.create(CameraControls, { properties: { sceneSize: 2 } });
|
|
@@ -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>Sprite Game</title>
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<pc-app>
|
|
11
|
+
<pc-material id="dirt-material" emissive="#734729"></pc-material>
|
|
12
|
+
<pc-material id="grass-material" emissive="#479e57"></pc-material>
|
|
13
|
+
<pc-scene>
|
|
14
|
+
<pc-entity name="camera" position="0 0 10"
|
|
15
|
+
><pc-camera projection="orthographic" ortho-height="4.4" clear-color="#5cb9e6"></pc-camera
|
|
16
|
+
></pc-entity>
|
|
17
|
+
<pc-entity name="dirt" position="0 -3.39 0" scale="20 2.6 1"
|
|
18
|
+
><pc-render type="box" material="dirt-material"></pc-render
|
|
19
|
+
></pc-entity>
|
|
20
|
+
<pc-entity name="grass" position="0 -2 0" scale="20 0.18 1"
|
|
21
|
+
><pc-render type="box" material="grass-material"></pc-render
|
|
22
|
+
></pc-entity>
|
|
23
|
+
<pc-entity name="game" position="0 -2.15 0"></pc-entity>
|
|
24
|
+
</pc-scene>
|
|
25
|
+
</pc-app>
|
|
26
|
+
<div class="hud">
|
|
27
|
+
<section class="panel">
|
|
28
|
+
<h1>Sprite Game</h1>
|
|
29
|
+
<p>Use A/D or the arrow keys to move and Space to jump.</p>
|
|
30
|
+
</section>
|
|
31
|
+
</div>
|
|
32
|
+
<script type="module" src="/src/main.ts"></script>
|
|
33
|
+
</body>
|
|
34
|
+
</html>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { EntityElement } from '@playcanvas/web-components';
|
|
2
|
+
import { whenReady } from '@playcanvas/web-components';
|
|
3
|
+
|
|
4
|
+
import { SpriteGame } from './sprite-game';
|
|
5
|
+
import './starter.css';
|
|
6
|
+
|
|
7
|
+
const game = await whenReady<EntityElement>('pc-entity[name="game"]');
|
|
8
|
+
game.entity!.addComponent('script');
|
|
9
|
+
game.entity!.script!.create(SpriteGame);
|