create-playcanvas 0.5.1 → 0.6.1

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.
Files changed (113) hide show
  1. package/README.md +20 -27
  2. package/dist/index.mjs +44 -42
  3. package/package.json +1 -1
  4. package/skills/calibrate-model/references/direct-engine.md +7 -4
  5. package/skills/calibrate-model/references/react.md +8 -3
  6. package/skills/calibrate-model/references/web-components.md +7 -4
  7. package/skills/configure-animation/references/web-components.md +18 -9
  8. package/skills/inspect-glb/SKILL.md +27 -18
  9. package/skills/inspect-glb/scripts/inspect.mjs +179 -50
  10. package/templates/_features/physics/assets/public/ammo/LICENSE +21 -0
  11. package/templates/_features/physics/assets/public/ammo/SOURCE.md +16 -0
  12. package/templates/_features/physics/assets/public/ammo/ammo.js +973 -0
  13. package/templates/_features/physics/assets/public/ammo/ammo.wasm.js +937 -0
  14. package/templates/_features/physics/assets/public/ammo/ammo.wasm.wasm +0 -0
  15. package/templates/_features/physics/react/package.json +5 -0
  16. package/templates/_features/physics/react/src/sync-ammo.d.ts +4 -0
  17. package/templates/_shared/ar-placement/README.md +7 -0
  18. package/templates/_shared/ar-placement/src/ar-placement.ts +123 -0
  19. package/templates/_shared/first-person-controller/README.md +7 -0
  20. package/templates/_shared/first-person-controller/src/controller.ts +18 -0
  21. package/templates/_shared/first-person-controller/src/scripts.d.ts +5 -0
  22. package/templates/_shared/interactive-sphere/README.md +7 -0
  23. package/templates/_shared/model-viewer/README.md +7 -0
  24. package/templates/_shared/physics-playground/README.md +7 -0
  25. package/templates/_shared/product-configurator/ASSET_LICENSES.md +3 -0
  26. package/templates/_shared/product-configurator/README.md +7 -0
  27. package/templates/_shared/product-configurator/src/product.css +14 -0
  28. package/templates/_shared/scene-editor/README.md +7 -0
  29. package/templates/_shared/scene-editor/src/scene-editor.ts +57 -0
  30. package/templates/_shared/spinning-cube/README.md +7 -0
  31. package/templates/_shared/splat-viewer/README.md +7 -0
  32. package/templates/_shared/sprite-game/README.md +7 -0
  33. package/templates/_shared/sprite-game/src/sprite-game.ts +197 -0
  34. package/templates/_shared/third-person-controller/README.md +7 -0
  35. package/templates/_shared/third-person-controller/src/controller.ts +53 -0
  36. package/templates/_shared/third-person-controller/src/scripts.d.ts +5 -0
  37. package/templates/_shared/vr-starter/README.md +7 -0
  38. package/templates/_shared/vr-starter/src/vr.ts +40 -0
  39. package/templates/_shared/vr-starter/src/xr.d.ts +11 -0
  40. package/templates/engine/ar-placement/src/main.ts +77 -0
  41. package/templates/engine/base/.prettierignore +1 -0
  42. package/templates/engine/base/README.md +1 -1
  43. package/templates/engine/base/_npmrc +1 -0
  44. package/templates/engine/base/eslint.config.mjs +1 -1
  45. package/templates/engine/base/index.html +13 -0
  46. package/templates/engine/base/src/starter.css +104 -0
  47. package/templates/engine/first-person-controller/src/main.ts +139 -0
  48. package/templates/engine/interactive-sphere/src/App.ts +9 -7
  49. package/templates/engine/interactive-sphere/src/main.ts +2 -29
  50. package/templates/engine/interactive-sphere/src/style.css +18 -97
  51. package/templates/engine/model-viewer/src/main.ts +3 -2
  52. package/templates/engine/physics-playground/src/main.ts +132 -0
  53. package/templates/engine/product-configurator/src/main.ts +156 -0
  54. package/templates/engine/scene-editor/src/main.ts +90 -0
  55. package/templates/engine/splat-viewer/src/main.ts +4 -3
  56. package/templates/engine/sprite-game/src/main.ts +72 -0
  57. package/templates/engine/third-person-controller/src/main.ts +216 -0
  58. package/templates/engine/vr-starter/src/main.ts +101 -0
  59. package/templates/index.ts +66 -5
  60. package/templates/react/ar-placement/src/App.tsx +58 -0
  61. package/templates/react/base/.prettierignore +1 -0
  62. package/templates/react/base/README.md +1 -1
  63. package/templates/react/base/_npmrc +1 -0
  64. package/templates/react/base/eslint.config.mjs +1 -1
  65. package/templates/react/base/index.html +13 -0
  66. package/templates/react/base/src/main.tsx +10 -0
  67. package/templates/react/base/src/starter.css +104 -0
  68. package/templates/react/first-person-controller/src/App.tsx +115 -0
  69. package/templates/react/interactive-sphere/src/App.css +18 -68
  70. package/templates/react/interactive-sphere/src/App.tsx +1 -22
  71. package/templates/react/interactive-sphere/src/Scene.tsx +7 -6
  72. package/templates/react/interactive-sphere/src/index.css +1 -48
  73. package/templates/react/model-viewer/src/App.tsx +2 -2
  74. package/templates/react/physics-playground/src/App.tsx +85 -0
  75. package/templates/react/product-configurator/src/App.tsx +157 -0
  76. package/templates/react/scene-editor/src/App.tsx +84 -0
  77. package/templates/react/splat-viewer/src/App.tsx +3 -3
  78. package/templates/react/sprite-game/src/App.tsx +38 -0
  79. package/templates/react/third-person-controller/src/App.tsx +193 -0
  80. package/templates/react/vr-starter/src/App.tsx +99 -0
  81. package/templates/web-components/ar-placement/index.html +44 -0
  82. package/templates/web-components/ar-placement/src/main.ts +13 -0
  83. package/templates/web-components/base/.prettierignore +1 -0
  84. package/templates/web-components/base/README.md +1 -1
  85. package/templates/web-components/base/_npmrc +1 -0
  86. package/templates/web-components/base/eslint.config.mjs +1 -1
  87. package/templates/web-components/base/package.json +1 -1
  88. package/templates/web-components/base/src/starter.css +104 -0
  89. package/templates/web-components/first-person-controller/index.html +168 -0
  90. package/templates/web-components/first-person-controller/src/main.ts +15 -0
  91. package/templates/web-components/interactive-sphere/index.html +5 -22
  92. package/templates/web-components/interactive-sphere/src/main.ts +5 -4
  93. package/templates/web-components/interactive-sphere/src/style.css +18 -76
  94. package/templates/web-components/model-viewer/index.html +1 -1
  95. package/templates/web-components/model-viewer/src/main.ts +2 -1
  96. package/templates/web-components/physics-playground/index.html +51 -0
  97. package/templates/web-components/physics-playground/src/main.ts +32 -0
  98. package/templates/web-components/product-configurator/index.html +51 -0
  99. package/templates/web-components/product-configurator/src/main.ts +93 -0
  100. package/templates/web-components/scene-editor/index.html +51 -0
  101. package/templates/web-components/scene-editor/src/main.ts +26 -0
  102. package/templates/web-components/spinning-cube/src/main.ts +1 -0
  103. package/templates/web-components/splat-viewer/index.html +2 -2
  104. package/templates/web-components/splat-viewer/src/main.ts +2 -1
  105. package/templates/web-components/sprite-game/index.html +34 -0
  106. package/templates/web-components/sprite-game/src/main.ts +9 -0
  107. package/templates/web-components/third-person-controller/index.html +183 -0
  108. package/templates/web-components/third-person-controller/src/main.ts +16 -0
  109. package/templates/web-components/vr-starter/index.html +80 -0
  110. package/templates/web-components/vr-starter/src/main.ts +12 -0
  111. package/templates/engine/interactive-sphere/src/assets/typescript.svg +0 -1
  112. package/templates/react/interactive-sphere/src/assets/react.svg +0 -1
  113. package/templates/web-components/interactive-sphere/src/assets/typescript.svg +0 -1
@@ -0,0 +1,99 @@
1
+ import { Application, Entity } from '@playcanvas/react';
2
+ import { Camera, Light, Render } from '@playcanvas/react/components';
3
+ import { useApp, useMaterial } from '@playcanvas/react/hooks';
4
+ import type { Entity as PcEntity } from 'playcanvas';
5
+ import { useEffect, useRef } from 'react';
6
+
7
+ import './starter.css';
8
+ import { setupVr } from './vr';
9
+
10
+ function Scene() {
11
+ const app = useApp();
12
+ const rig = useRef<PcEntity>(null);
13
+ const camera = useRef<PcEntity>(null);
14
+ const floor = useMaterial({ diffuse: '#61666e' });
15
+ const wall = useMaterial({ diffuse: '#3d424a' });
16
+ const cyan = useMaterial({ diffuse: '#1fb3db' });
17
+ const coral = useMaterial({ diffuse: '#ff594d' });
18
+ const yellow = useMaterial({ diffuse: '#ffbf33' });
19
+
20
+ useEffect(() => {
21
+ if (rig.current && camera.current) return setupVr(app, rig.current, camera.current);
22
+ }, [app]);
23
+
24
+ return (
25
+ <>
26
+ <Entity name="light" rotation={[45, 30, 0]}>
27
+ <Light type="directional" intensity={2} castShadows shadowBias={0.2} normalOffsetBias={0.05} />
28
+ </Entity>
29
+ <Entity name="floor" scale={[10, 1, 10]}>
30
+ <Render type="plane" material={floor} />
31
+ </Entity>
32
+ {[
33
+ ['back-wall', [0, 2, -3.5], [8, 4, 0.2]],
34
+ ['left-wall', [-4, 2, 0], [0.2, 4, 7]],
35
+ ['right-wall', [4, 2, 0], [0.2, 4, 7]]
36
+ ].map(([name, position, scale]) => (
37
+ <Entity
38
+ key={name as string}
39
+ name={name as string}
40
+ position={position as [number, number, number]}
41
+ scale={scale as [number, number, number]}
42
+ >
43
+ <Render type="box" material={wall} />
44
+ </Entity>
45
+ ))}
46
+ {[
47
+ [-2.4, cyan],
48
+ [0, coral],
49
+ [2.4, yellow]
50
+ ].map(([x, material], i) => (
51
+ <Entity key={i} position={[x as number, 2.4, -3.35]} scale={[1.3, 1.3, 0.12]}>
52
+ <Render type="box" material={material as never} />
53
+ </Entity>
54
+ ))}
55
+ {[-2.4, 0, 2.4].map((x) => (
56
+ <Entity key={x} position={[x, 0.45, -1.6]} scale={[1, 0.9, 1]}>
57
+ <Render type="box" material={wall} />
58
+ </Entity>
59
+ ))}
60
+ <Entity position={[-2.4, 1.35, -1.6]} scale={[0.7, 0.7, 0.7]}>
61
+ <Render type="sphere" material={cyan} />
62
+ </Entity>
63
+ <Entity position={[0, 1.35, -1.6]} scale={[0.7, 0.7, 0.7]}>
64
+ <Render type="box" material={coral} />
65
+ </Entity>
66
+ <Entity position={[2.4, 1.35, -1.6]} scale={[0.8, 0.9, 0.8]}>
67
+ <Render type="cone" material={yellow} />
68
+ </Entity>
69
+ <Entity name="xr-rig" ref={rig}>
70
+ <Entity name="camera" ref={camera} position={[0, 1.6, 4]}>
71
+ <Camera clearColor="#292e38" />
72
+ </Entity>
73
+ </Entity>
74
+ </>
75
+ );
76
+ }
77
+
78
+ function App() {
79
+ return (
80
+ <>
81
+ <Application graphicsDeviceOptions={{ xrCompatible: true }}>
82
+ <Scene />
83
+ </Application>
84
+ <div className="hud">
85
+ <section className="panel">
86
+ <h1>VR Starter</h1>
87
+ <p id="xr-status">Checking VR support…</p>
88
+ <div className="controls">
89
+ <button id="xr-button" disabled>
90
+ Enter VR
91
+ </button>
92
+ </div>
93
+ </section>
94
+ </div>
95
+ </>
96
+ );
97
+ }
98
+
99
+ export default App;
@@ -0,0 +1,44 @@
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>AR Placement</title>
8
+ </head>
9
+ <body>
10
+ <pc-app alpha>
11
+ <pc-material id="surface-material" diffuse="#474d57"></pc-material>
12
+ <pc-material id="cyan" diffuse="#1ab3e6"></pc-material>
13
+ <pc-material id="coral" diffuse="#ff5926"></pc-material>
14
+ <pc-scene>
15
+ <pc-entity name="camera" position="3 2.4 4" rotation="-20 37 0"
16
+ ><pc-camera clear-color="#0d141f"></pc-camera
17
+ ></pc-entity>
18
+ <pc-entity name="light" rotation="45 30 0"
19
+ ><pc-light type="directional" intensity="2"></pc-light
20
+ ></pc-entity>
21
+ <pc-entity name="preview">
22
+ <pc-entity name="surface" scale="4 0.15 4"
23
+ ><pc-render type="cylinder" material="surface-material"></pc-render
24
+ ></pc-entity>
25
+ <pc-entity name="box" position="0 0.65 0"
26
+ ><pc-render type="box" material="cyan"></pc-render
27
+ ></pc-entity>
28
+ <pc-entity name="reticle" position="0 0.12 0" scale="1.5 0.03 1.5"
29
+ ><pc-render type="cylinder" material="coral"></pc-render
30
+ ></pc-entity>
31
+ </pc-entity>
32
+ <pc-entity name="placement"></pc-entity>
33
+ </pc-scene>
34
+ </pc-app>
35
+ <div class="hud">
36
+ <section class="panel">
37
+ <h1>AR Placement</h1>
38
+ <p id="xr-status">Checking AR support…</p>
39
+ <div class="controls"><button id="xr-button" disabled>Start AR</button></div>
40
+ </section>
41
+ </div>
42
+ <script type="module" src="/src/main.ts"></script>
43
+ </body>
44
+ </html>
@@ -0,0 +1,13 @@
1
+ import type { EntityElement } from '@playcanvas/web-components';
2
+ import { whenReady } from '@playcanvas/web-components';
3
+
4
+ import { ArPlacement } from './ar-placement';
5
+ import './starter.css';
6
+
7
+ const [camera, preview, placement] = await Promise.all([
8
+ whenReady<EntityElement>('pc-entity[name="camera"]'),
9
+ whenReady<EntityElement>('pc-entity[name="preview"]'),
10
+ whenReady<EntityElement>('pc-entity[name="placement"]')
11
+ ]);
12
+ placement.entity!.addComponent('script');
13
+ placement.entity!.script!.create(ArPlacement, { properties: { camera: camera.entity, preview: preview.entity } });
@@ -1,2 +1,3 @@
1
1
  .claude
2
2
  .agents
3
+ public/ammo
@@ -10,7 +10,7 @@ Node.js 22.23.2 or later.
10
10
  ## Getting started
11
11
 
12
12
  ```bash
13
- npm create playcanvas@latest playcanvas-project -- --template web-components
13
+ npm create playcanvas@latest playcanvas-project -- --format web-components
14
14
  cd playcanvas-project
15
15
  npm install
16
16
  npm run dev
@@ -0,0 +1 @@
1
+ registry=https://registry.npmjs.org/
@@ -1,3 +1,3 @@
1
1
  import typescriptConfig from '@playcanvas/eslint-config/typescript';
2
2
 
3
- export default [{ ignores: ['.claude', '.agents'] }, ...typescriptConfig];
3
+ export default [{ ignores: ['.claude', '.agents', 'public/ammo'] }, ...typescriptConfig];
@@ -15,7 +15,7 @@
15
15
  "typecheck": "tsc --noEmit"
16
16
  },
17
17
  "dependencies": {
18
- "@playcanvas/web-components": "^0.15.0",
18
+ "@playcanvas/web-components": "^0.16.0",
19
19
  "playcanvas": "^2.21.4"
20
20
  },
21
21
  "devDependencies": {
@@ -0,0 +1,104 @@
1
+ * {
2
+ box-sizing: border-box;
3
+ }
4
+
5
+ html,
6
+ body,
7
+ #root,
8
+ #application,
9
+ pc-app,
10
+ canvas {
11
+ width: 100%;
12
+ height: 100%;
13
+ margin: 0;
14
+ overflow: hidden;
15
+ }
16
+
17
+ body {
18
+ background: #11151c;
19
+ color: #f8fafc;
20
+ font-family: Inter, ui-sans-serif, system-ui, sans-serif;
21
+ }
22
+
23
+ canvas,
24
+ pc-app {
25
+ display: block;
26
+ }
27
+
28
+ .hud {
29
+ position: fixed;
30
+ inset: 0;
31
+ z-index: 10;
32
+ padding: 20px;
33
+ pointer-events: none;
34
+ }
35
+
36
+ .panel {
37
+ width: min(360px, calc(100vw - 40px));
38
+ padding: 16px;
39
+ border: 1px solid #ffffff24;
40
+ border-radius: 14px;
41
+ background: #0b1019d9;
42
+ box-shadow: 0 12px 40px #0008;
43
+ backdrop-filter: blur(12px);
44
+ pointer-events: auto;
45
+ }
46
+
47
+ h1 {
48
+ margin: 0 0 6px;
49
+ font-size: 18px;
50
+ }
51
+
52
+ p {
53
+ margin: 6px 0 0;
54
+ color: #aeb8c8;
55
+ font-size: 13px;
56
+ line-height: 1.45;
57
+ }
58
+
59
+ .controls {
60
+ display: flex;
61
+ flex-wrap: wrap;
62
+ gap: 8px;
63
+ margin-top: 14px;
64
+ }
65
+
66
+ button {
67
+ padding: 8px 11px;
68
+ border: 1px solid #ffffff24;
69
+ border-radius: 9px;
70
+ background: #263247;
71
+ color: inherit;
72
+ cursor: pointer;
73
+ }
74
+
75
+ button:hover,
76
+ button[aria-pressed='true'] {
77
+ border-color: #41b6e6;
78
+ background: #334867;
79
+ }
80
+
81
+ button:disabled {
82
+ cursor: not-allowed;
83
+ opacity: 0.5;
84
+ }
85
+
86
+ .swatch {
87
+ width: 32px;
88
+ height: 32px;
89
+ padding: 0;
90
+ border-radius: 50%;
91
+ background: var(--color);
92
+ }
93
+
94
+ .crosshair {
95
+ position: fixed;
96
+ top: 50%;
97
+ left: 50%;
98
+ width: 16px;
99
+ height: 16px;
100
+ border: 2px solid #fff;
101
+ border-radius: 50%;
102
+ translate: -50% -50%;
103
+ box-shadow: 0 0 4px #000;
104
+ }
@@ -0,0 +1,168 @@
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>First-Person Controller</title>
8
+ </head>
9
+ <body>
10
+ <pc-app>
11
+ <pc-material id="floor-material" diffuse="#474d52" emissive="#0e0f10" gloss="0.2"></pc-material>
12
+ <pc-material id="wall-material" diffuse="#6b737a" emissive="#151718" gloss="0.25"></pc-material>
13
+ <pc-material id="blue-material" diffuse="#154a7a" emissive="#040f18" gloss="0.4"></pc-material>
14
+ <pc-material id="green-material" diffuse="#2e6638" emissive="#09140b" gloss="0.2"></pc-material>
15
+ <pc-material id="wood-material" diffuse="#7a451a" emissive="#180e05" gloss="0.2"></pc-material>
16
+ <pc-material id="metal-material" diffuse="#475461" emissive="#0e1113" gloss="0.5"></pc-material>
17
+ <pc-module
18
+ name="Ammo"
19
+ glue="/ammo/ammo.wasm.js"
20
+ wasm="/ammo/ammo.wasm.wasm"
21
+ fallback="/ammo/ammo.js"
22
+ ></pc-module>
23
+ <pc-scene>
24
+ <pc-entity name="light" rotation="50 30 0"
25
+ ><pc-light
26
+ type="directional"
27
+ intensity="2.5"
28
+ cast-shadows
29
+ shadow-bias="0.2"
30
+ normal-offset-bias="0.05"
31
+ ></pc-light
32
+ ></pc-entity>
33
+ <pc-entity name="fill" rotation="-25 -140 0"
34
+ ><pc-light type="directional" intensity="0.8"></pc-light
35
+ ></pc-entity>
36
+ <pc-entity name="floor" position="0 -0.1 0" scale="18 0.2 18"
37
+ ><pc-render type="box" material="floor-material"></pc-render
38
+ ><pc-collision type="box" half-extents="9 0.1 9"></pc-collision
39
+ ><pc-rigidbody type="static"></pc-rigidbody
40
+ ></pc-entity>
41
+ <pc-entity name="back-wall" position="0 1.5 -9" scale="18 3 0.3"
42
+ ><pc-render type="box" material="wall-material"></pc-render
43
+ ><pc-collision type="box" half-extents="9 1.5 0.15"></pc-collision
44
+ ><pc-rigidbody type="static"></pc-rigidbody
45
+ ></pc-entity>
46
+ <pc-entity name="front-wall" position="0 1.5 9" scale="18 3 0.3"
47
+ ><pc-render type="box" material="wall-material"></pc-render
48
+ ><pc-collision type="box" half-extents="9 1.5 0.15"></pc-collision
49
+ ><pc-rigidbody type="static"></pc-rigidbody
50
+ ></pc-entity>
51
+ <pc-entity name="left-wall" position="-9 1.5 0" scale="0.3 3 18"
52
+ ><pc-render type="box" material="wall-material"></pc-render
53
+ ><pc-collision type="box" half-extents="0.15 1.5 9"></pc-collision
54
+ ><pc-rigidbody type="static"></pc-rigidbody
55
+ ></pc-entity>
56
+ <pc-entity name="right-wall" position="9 1.5 0" scale="0.3 3 18"
57
+ ><pc-render type="box" material="wall-material"></pc-render
58
+ ><pc-collision type="box" half-extents="0.15 1.5 9"></pc-collision
59
+ ><pc-rigidbody type="static"></pc-rigidbody
60
+ ></pc-entity>
61
+ <pc-entity name="blue-crate" position="-2 0.75 -3" scale="1.5 1.5 1.5"
62
+ ><pc-render type="box" material="blue-material"></pc-render
63
+ ><pc-collision type="box" half-extents="0.75 0.75 0.75"></pc-collision
64
+ ><pc-rigidbody type="static"></pc-rigidbody
65
+ ></pc-entity>
66
+ <pc-entity name="green-crate" position="3 0.5 1" scale="2.5 1 1"
67
+ ><pc-render type="box" material="green-material"></pc-render
68
+ ><pc-collision type="box" half-extents="1.25 0.5 0.5"></pc-collision
69
+ ><pc-rigidbody type="static"></pc-rigidbody
70
+ ></pc-entity>
71
+ <pc-entity name="cargo-left-0" position="-5.5 0.75 -5.5" scale="2 1.5 2"
72
+ ><pc-render type="box" material="wood-material"></pc-render
73
+ ><pc-collision type="box" half-extents="1 0.75 1"></pc-collision
74
+ ><pc-rigidbody type="static"></pc-rigidbody
75
+ ></pc-entity>
76
+ <pc-entity name="cargo-left-1" position="-5.5 2 -5.5" scale="1.5 1 1.5"
77
+ ><pc-render type="box" material="blue-material"></pc-render
78
+ ><pc-collision type="box" half-extents="0.75 0.5 0.75"></pc-collision
79
+ ><pc-rigidbody type="static"></pc-rigidbody
80
+ ></pc-entity>
81
+ <pc-entity name="cargo-right-0" position="5.3 0.6 -4.8" scale="2.4 1.2 2"
82
+ ><pc-render type="box" material="green-material"></pc-render
83
+ ><pc-collision type="box" half-extents="1.2 0.6 1"></pc-collision
84
+ ><pc-rigidbody type="static"></pc-rigidbody
85
+ ></pc-entity>
86
+ <pc-entity name="cargo-right-1" position="5.3 1.7 -4.8" scale="1.5 1 1.5"
87
+ ><pc-render type="box" material="wood-material"></pc-render
88
+ ><pc-collision type="box" half-extents="0.75 0.5 0.75"></pc-collision
89
+ ><pc-rigidbody type="static"></pc-rigidbody
90
+ ></pc-entity>
91
+ <pc-entity name="cargo-center" position="0 0.6 -6.5" scale="2.2 1.2 1.8"
92
+ ><pc-render type="box" material="blue-material"></pc-render
93
+ ><pc-collision type="box" half-extents="1.1 0.6 0.9"></pc-collision
94
+ ><pc-rigidbody type="static"></pc-rigidbody
95
+ ></pc-entity>
96
+ <pc-entity name="shelf-left-post-0" position="-6.8 1.4 -3.5" scale="0.25 2.8 0.25"
97
+ ><pc-render type="box" material="metal-material"></pc-render
98
+ ><pc-collision type="box" half-extents="0.125 1.4 0.125"></pc-collision
99
+ ><pc-rigidbody type="static"></pc-rigidbody
100
+ ></pc-entity>
101
+ <pc-entity name="shelf-left-post-1" position="-6.8 1.4 0" scale="0.25 2.8 0.25"
102
+ ><pc-render type="box" material="metal-material"></pc-render
103
+ ><pc-collision type="box" half-extents="0.125 1.4 0.125"></pc-collision
104
+ ><pc-rigidbody type="static"></pc-rigidbody
105
+ ></pc-entity>
106
+ <pc-entity name="shelf-left-post-2" position="-6.8 1.4 3.5" scale="0.25 2.8 0.25"
107
+ ><pc-render type="box" material="metal-material"></pc-render
108
+ ><pc-collision type="box" half-extents="0.125 1.4 0.125"></pc-collision
109
+ ><pc-rigidbody type="static"></pc-rigidbody
110
+ ></pc-entity>
111
+ <pc-entity name="shelf-right-post-0" position="6.8 1.4 -3.5" scale="0.25 2.8 0.25"
112
+ ><pc-render type="box" material="metal-material"></pc-render
113
+ ><pc-collision type="box" half-extents="0.125 1.4 0.125"></pc-collision
114
+ ><pc-rigidbody type="static"></pc-rigidbody
115
+ ></pc-entity>
116
+ <pc-entity name="shelf-right-post-1" position="6.8 1.4 0" scale="0.25 2.8 0.25"
117
+ ><pc-render type="box" material="metal-material"></pc-render
118
+ ><pc-collision type="box" half-extents="0.125 1.4 0.125"></pc-collision
119
+ ><pc-rigidbody type="static"></pc-rigidbody
120
+ ></pc-entity>
121
+ <pc-entity name="shelf-right-post-2" position="6.8 1.4 3.5" scale="0.25 2.8 0.25"
122
+ ><pc-render type="box" material="metal-material"></pc-render
123
+ ><pc-collision type="box" half-extents="0.125 1.4 0.125"></pc-collision
124
+ ><pc-rigidbody type="static"></pc-rigidbody
125
+ ></pc-entity>
126
+ <pc-entity name="shelf-left-low" position="-6.8 0.65 0" scale="1.1 0.18 7.5"
127
+ ><pc-render type="box" material="metal-material"></pc-render
128
+ ><pc-collision type="box" half-extents="0.55 0.09 3.75"></pc-collision
129
+ ><pc-rigidbody type="static"></pc-rigidbody
130
+ ></pc-entity>
131
+ <pc-entity name="shelf-left-high" position="-6.8 2.1 0" scale="1.1 0.18 7.5"
132
+ ><pc-render type="box" material="metal-material"></pc-render
133
+ ><pc-collision type="box" half-extents="0.55 0.09 3.75"></pc-collision
134
+ ><pc-rigidbody type="static"></pc-rigidbody
135
+ ></pc-entity>
136
+ <pc-entity name="shelf-right-low" position="6.8 0.65 0" scale="1.1 0.18 7.5"
137
+ ><pc-render type="box" material="metal-material"></pc-render
138
+ ><pc-collision type="box" half-extents="0.55 0.09 3.75"></pc-collision
139
+ ><pc-rigidbody type="static"></pc-rigidbody
140
+ ></pc-entity>
141
+ <pc-entity name="shelf-right-high" position="6.8 2.1 0" scale="1.1 0.18 7.5"
142
+ ><pc-render type="box" material="metal-material"></pc-render
143
+ ><pc-collision type="box" half-extents="0.55 0.09 3.75"></pc-collision
144
+ ><pc-rigidbody type="static"></pc-rigidbody
145
+ ></pc-entity>
146
+ <pc-entity name="pallet" position="-2.5 0.15 2.5" scale="3 0.3 2"
147
+ ><pc-render type="box" material="wood-material"></pc-render
148
+ ><pc-collision type="box" half-extents="1.5 0.15 1"></pc-collision
149
+ ><pc-rigidbody type="static"></pc-rigidbody
150
+ ></pc-entity>
151
+ <pc-entity name="player" position="0 1 5">
152
+ <pc-collision type="capsule" radius="0.45" height="1.8"></pc-collision>
153
+ <pc-rigidbody type="dynamic" mass="80" angular-factor="0 0 0"></pc-rigidbody>
154
+ <pc-entity name="camera" position="0 0.65 0"
155
+ ><pc-camera clear-color="#61a3db" fov="80"></pc-camera
156
+ ></pc-entity>
157
+ </pc-entity>
158
+ </pc-scene>
159
+ </pc-app>
160
+ <div class="hud">
161
+ <section class="panel">
162
+ <h1>First-Person Controller</h1>
163
+ <p>Click the scene, then use WASD, mouse look and Space to jump.</p>
164
+ </section>
165
+ </div>
166
+ <script type="module" src="/src/main.ts"></script>
167
+ </body>
168
+ </html>
@@ -0,0 +1,15 @@
1
+ import type { EntityElement } from '@playcanvas/web-components';
2
+ import { whenReady } from '@playcanvas/web-components';
3
+
4
+ import { addFirstPersonController } from './controller';
5
+ import './starter.css';
6
+
7
+ await Promise.all([
8
+ whenReady('pc-entity[name="player"] > pc-collision'),
9
+ whenReady('pc-entity[name="player"] > pc-rigidbody')
10
+ ]);
11
+ const [player, camera] = await Promise.all([
12
+ whenReady<EntityElement>('pc-entity[name="player"]'),
13
+ whenReady<EntityElement>('pc-entity[name="camera"]')
14
+ ]);
15
+ addFirstPersonController(player.entity!, camera.entity!);
@@ -13,40 +13,23 @@
13
13
 
14
14
  <pc-scene>
15
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>
16
+ <pc-entity name="camera" position="3.2 1.5 3.2" rotation="-10 45 0">
17
+ <pc-camera clear-color="#07101a"></pc-camera>
18
18
  </pc-entity>
19
19
 
20
20
  <!-- Lighting comes from the environment map, which is applied in src/main.ts -->
21
21
 
22
22
  <!-- Background grid. The grid script is attached in src/main.ts -->
23
- <pc-entity name="grid" scale="1000 1000 1000"></pc-entity>
23
+ <pc-entity name="grid" scale="12 12 12"></pc-entity>
24
24
 
25
25
  <!-- The sphere. pc-app dispatches pointer events onto whatever the pointer hits -->
26
- <pc-entity name="sphere" position="0 0.5 0">
26
+ <pc-entity name="sphere" position="0 0.7 0" scale="1.25 1.25 1.25">
27
27
  <pc-render type="sphere" material="sphere-material"></pc-render>
28
28
  </pc-entity>
29
29
  </pc-scene>
30
30
  </pc-app>
31
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>
32
+ <p id="counter" class="counter">Click count: 0</p>
50
33
 
51
34
  <script type="module" src="/src/main.ts"></script>
52
35
  </body>
@@ -5,10 +5,11 @@ import { Asset, TEXTURETYPE_RGBP } from 'playcanvas';
5
5
  import { CameraControls } from 'playcanvas/scripts/esm/camera-controls.mjs';
6
6
  import { Grid } from 'playcanvas/scripts/esm/grid.mjs';
7
7
 
8
+ import './starter.css';
8
9
  import './style.css';
9
10
 
10
- const HOVER_COLOR = 'orange';
11
- const DEFAULT_COLOR = 'lightgrey';
11
+ const HOVER_COLOR = '#40ccff';
12
+ const DEFAULT_COLOR = '#e6edf9';
12
13
 
13
14
  // The camera is awaited as <pc-camera> rather than the <pc-entity> holding it - an entity becomes
14
15
  // ready before its component children do, and CameraControls needs the camera component to exist
@@ -49,7 +50,7 @@ if (skyboxLayer) {
49
50
  // with <pc-script name="...">, which only resolves scripts fetched at runtime by <pc-asset>
50
51
  const camera = cameraComponent.closestEntity;
51
52
  camera?.entity?.addComponent('script');
52
- camera?.entity?.script?.create(CameraControls);
53
+ camera?.entity?.script?.create(CameraControls, { properties: { sceneSize: 3 } });
53
54
  grid.entity?.addComponent('script');
54
55
  grid.entity?.script?.create(Grid);
55
56
 
@@ -72,5 +73,5 @@ sphere.addEventListener('pointerleave', () => {
72
73
 
73
74
  sphere.addEventListener('pointerup', () => {
74
75
  count++;
75
- counterElement.textContent = `Click Count: ${count}`;
76
+ counterElement.textContent = `Click count: ${count}`;
76
77
  });
@@ -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
- .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;
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
  }