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.
Files changed (109) hide show
  1. package/README.md +20 -27
  2. package/dist/index.mjs +44 -42
  3. package/package.json +1 -1
  4. package/templates/_features/physics/assets/public/ammo/LICENSE +21 -0
  5. package/templates/_features/physics/assets/public/ammo/SOURCE.md +16 -0
  6. package/templates/_features/physics/assets/public/ammo/ammo.js +973 -0
  7. package/templates/_features/physics/assets/public/ammo/ammo.wasm.js +937 -0
  8. package/templates/_features/physics/assets/public/ammo/ammo.wasm.wasm +0 -0
  9. package/templates/_features/physics/react/package.json +5 -0
  10. package/templates/_features/physics/react/src/sync-ammo.d.ts +4 -0
  11. package/templates/_shared/ar-placement/README.md +7 -0
  12. package/templates/_shared/ar-placement/src/ar-placement.ts +123 -0
  13. package/templates/_shared/first-person-controller/README.md +7 -0
  14. package/templates/_shared/first-person-controller/src/controller.ts +18 -0
  15. package/templates/_shared/first-person-controller/src/scripts.d.ts +5 -0
  16. package/templates/_shared/interactive-sphere/README.md +7 -0
  17. package/templates/_shared/model-viewer/README.md +7 -0
  18. package/templates/_shared/physics-playground/README.md +7 -0
  19. package/templates/_shared/product-configurator/ASSET_LICENSES.md +3 -0
  20. package/templates/_shared/product-configurator/README.md +7 -0
  21. package/templates/_shared/product-configurator/src/product.css +14 -0
  22. package/templates/_shared/scene-editor/README.md +7 -0
  23. package/templates/_shared/scene-editor/src/scene-editor.ts +57 -0
  24. package/templates/_shared/spinning-cube/README.md +7 -0
  25. package/templates/_shared/splat-viewer/README.md +7 -0
  26. package/templates/_shared/sprite-game/README.md +7 -0
  27. package/templates/_shared/sprite-game/src/sprite-game.ts +197 -0
  28. package/templates/_shared/third-person-controller/README.md +7 -0
  29. package/templates/_shared/third-person-controller/src/controller.ts +53 -0
  30. package/templates/_shared/third-person-controller/src/scripts.d.ts +5 -0
  31. package/templates/_shared/vr-starter/README.md +7 -0
  32. package/templates/_shared/vr-starter/src/vr.ts +40 -0
  33. package/templates/_shared/vr-starter/src/xr.d.ts +11 -0
  34. package/templates/engine/ar-placement/src/main.ts +77 -0
  35. package/templates/engine/base/.prettierignore +1 -0
  36. package/templates/engine/base/README.md +1 -1
  37. package/templates/engine/base/_npmrc +1 -0
  38. package/templates/engine/base/eslint.config.mjs +1 -1
  39. package/templates/engine/base/index.html +13 -0
  40. package/templates/engine/base/package.json +2 -2
  41. package/templates/engine/base/src/starter.css +104 -0
  42. package/templates/engine/first-person-controller/src/main.ts +139 -0
  43. package/templates/engine/interactive-sphere/src/App.ts +9 -7
  44. package/templates/engine/interactive-sphere/src/main.ts +2 -29
  45. package/templates/engine/interactive-sphere/src/style.css +18 -97
  46. package/templates/engine/model-viewer/src/main.ts +3 -2
  47. package/templates/engine/physics-playground/src/main.ts +132 -0
  48. package/templates/engine/product-configurator/src/main.ts +156 -0
  49. package/templates/engine/scene-editor/src/main.ts +90 -0
  50. package/templates/engine/splat-viewer/src/main.ts +4 -3
  51. package/templates/engine/sprite-game/src/main.ts +72 -0
  52. package/templates/engine/third-person-controller/src/main.ts +216 -0
  53. package/templates/engine/vr-starter/src/main.ts +101 -0
  54. package/templates/index.ts +66 -5
  55. package/templates/react/ar-placement/src/App.tsx +58 -0
  56. package/templates/react/base/.prettierignore +1 -0
  57. package/templates/react/base/README.md +1 -1
  58. package/templates/react/base/_npmrc +1 -0
  59. package/templates/react/base/eslint.config.mjs +1 -1
  60. package/templates/react/base/index.html +13 -0
  61. package/templates/react/base/package.json +2 -2
  62. package/templates/react/base/src/main.tsx +10 -0
  63. package/templates/react/base/src/starter.css +104 -0
  64. package/templates/react/first-person-controller/src/App.tsx +115 -0
  65. package/templates/react/interactive-sphere/src/App.css +18 -68
  66. package/templates/react/interactive-sphere/src/App.tsx +1 -22
  67. package/templates/react/interactive-sphere/src/Scene.tsx +7 -6
  68. package/templates/react/interactive-sphere/src/index.css +1 -48
  69. package/templates/react/model-viewer/src/App.tsx +2 -2
  70. package/templates/react/physics-playground/src/App.tsx +85 -0
  71. package/templates/react/product-configurator/src/App.tsx +157 -0
  72. package/templates/react/scene-editor/src/App.tsx +84 -0
  73. package/templates/react/splat-viewer/src/App.tsx +3 -3
  74. package/templates/react/sprite-game/src/App.tsx +38 -0
  75. package/templates/react/third-person-controller/src/App.tsx +193 -0
  76. package/templates/react/vr-starter/src/App.tsx +99 -0
  77. package/templates/web-components/ar-placement/index.html +44 -0
  78. package/templates/web-components/ar-placement/src/main.ts +13 -0
  79. package/templates/web-components/base/.prettierignore +1 -0
  80. package/templates/web-components/base/README.md +1 -1
  81. package/templates/web-components/base/_npmrc +1 -0
  82. package/templates/web-components/base/eslint.config.mjs +1 -1
  83. package/templates/web-components/base/package.json +3 -3
  84. package/templates/web-components/base/src/starter.css +104 -0
  85. package/templates/web-components/first-person-controller/index.html +168 -0
  86. package/templates/web-components/first-person-controller/src/main.ts +15 -0
  87. package/templates/web-components/interactive-sphere/index.html +5 -22
  88. package/templates/web-components/interactive-sphere/src/main.ts +5 -4
  89. package/templates/web-components/interactive-sphere/src/style.css +18 -76
  90. package/templates/web-components/model-viewer/index.html +1 -1
  91. package/templates/web-components/model-viewer/src/main.ts +2 -1
  92. package/templates/web-components/physics-playground/index.html +51 -0
  93. package/templates/web-components/physics-playground/src/main.ts +32 -0
  94. package/templates/web-components/product-configurator/index.html +51 -0
  95. package/templates/web-components/product-configurator/src/main.ts +93 -0
  96. package/templates/web-components/scene-editor/index.html +51 -0
  97. package/templates/web-components/scene-editor/src/main.ts +26 -0
  98. package/templates/web-components/spinning-cube/src/main.ts +1 -0
  99. package/templates/web-components/splat-viewer/index.html +2 -2
  100. package/templates/web-components/splat-viewer/src/main.ts +2 -1
  101. package/templates/web-components/sprite-game/index.html +34 -0
  102. package/templates/web-components/sprite-game/src/main.ts +9 -0
  103. package/templates/web-components/third-person-controller/index.html +183 -0
  104. package/templates/web-components/third-person-controller/src/main.ts +16 -0
  105. package/templates/web-components/vr-starter/index.html +80 -0
  106. package/templates/web-components/vr-starter/src/main.ts +12 -0
  107. package/templates/engine/interactive-sphere/src/assets/typescript.svg +0 -1
  108. package/templates/react/interactive-sphere/src/assets/react.svg +0 -1
  109. 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
- .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
  }
@@ -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="0 0 3">
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
+ });
@@ -2,6 +2,7 @@ import type { EntityElement } from '@playcanvas/web-components';
2
2
  import { whenReady } from '@playcanvas/web-components';
3
3
  import { Script } from 'playcanvas';
4
4
 
5
+ import './starter.css';
5
6
  import './style.css';
6
7
 
7
8
  class Rotate extends Script {
@@ -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.5">
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);