castle-web-cli 0.4.128 → 0.4.130

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 (157) hide show
  1. package/dist/agent-prompts.js +4 -4
  2. package/dist/filesChanged.d.ts +2 -0
  3. package/dist/filesChanged.js +6 -2
  4. package/dist/ide.js +15 -4
  5. package/dist/importBrowse.js +1 -0
  6. package/dist/index.js +10 -4
  7. package/dist/init.js +63 -15
  8. package/dist/native/loop.js +1 -1
  9. package/dist/native/tools.js +1 -1
  10. package/dist/serve.d.ts +1 -0
  11. package/dist/serve.js +20 -1
  12. package/dist/shell/assets/index-BpOLUyVO.js +441 -0
  13. package/dist/shell/assets/{index-CAq6f9B5.css → index-D6K-0YDB.css} +1 -1
  14. package/dist/shell/index.html +2 -2
  15. package/kits/physics-2d/CLAUDE.md +40 -23
  16. package/kits/physics-2d/behaviors/Joints.jsx +4 -3
  17. package/kits/physics-2d/behaviors/SoundPlayer.jsx +266 -0
  18. package/kits/physics-2d/behaviors/Sprite.jsx +3 -3
  19. package/kits/physics-2d/behaviors/Video.jsx +4 -3
  20. package/kits/physics-2d/castle.json +1 -1
  21. package/kits/physics-2d/editors/PlayOnly.jsx +15 -6
  22. package/kits/physics-2d/editors/PxArtEditor.jsx +95 -31
  23. package/kits/physics-2d/editors/SceneEditor.jsx +5 -5
  24. package/kits/physics-2d/editors/SingleEditor.jsx +37 -8
  25. package/kits/physics-2d/editors/StyleEditor.jsx +7 -4
  26. package/kits/physics-2d/editors/pixelEditorChrome.jsx +7 -7
  27. package/kits/physics-2d/editors/pixelInspector.jsx +13 -7
  28. package/kits/physics-2d/editors/pxArtTimeline.jsx +29 -11
  29. package/kits/physics-2d/editors/pxArtTimeline.module.css +11 -0
  30. package/kits/physics-2d/engine/audioContext.js +41 -0
  31. package/kits/physics-2d/engine/autoInspector.jsx +50 -33
  32. package/kits/physics-2d/engine/blueprint.js +15 -3
  33. package/kits/physics-2d/engine/liveReload.js +33 -21
  34. package/kits/physics-2d/engine/media.js +29 -39
  35. package/kits/physics-2d/engine/sound.js +316 -0
  36. package/kits/physics-2d/engine/systemRegistry.js +1 -1
  37. package/kits/physics-2d/engine/ui.jsx +274 -5
  38. package/kits/physics-2d/engine/ui.module.css +137 -16
  39. package/kits/physics-2d/scripts/testsounds.mjs +84 -0
  40. package/kits/physics-2d/systems/media.js +31 -15
  41. package/kits/physics-3d/CLAUDE.md +109 -0
  42. package/kits/physics-3d/behaviors/Body.jsx +51 -0
  43. package/kits/physics-3d/behaviors/Door.jsx +31 -0
  44. package/kits/physics-3d/behaviors/Lookable.jsx +11 -0
  45. package/kits/physics-3d/behaviors/Model.jsx +14 -0
  46. package/kits/physics-3d/behaviors/Pickup.jsx +39 -0
  47. package/kits/physics-3d/behaviors/Player.jsx +172 -0
  48. package/kits/physics-3d/behaviors/Portal.jsx +19 -0
  49. package/kits/physics-3d/behaviors/Shape.jsx +75 -0
  50. package/kits/physics-3d/behaviors/Solid.jsx +11 -0
  51. package/kits/physics-3d/behaviors/Transform.jsx +24 -0
  52. package/kits/physics-3d/blueprints/barrel.scene +15 -0
  53. package/kits/physics-3d/blueprints/crate.scene +29 -0
  54. package/kits/physics-3d/blueprints/door.scene +35 -0
  55. package/kits/physics-3d/blueprints/gem.scene +26 -0
  56. package/kits/physics-3d/blueprints/pillar.scene +25 -0
  57. package/kits/physics-3d/blueprints/platform.scene +23 -0
  58. package/kits/physics-3d/blueprints/player.scene +29 -0
  59. package/kits/physics-3d/blueprints/portal.scene +21 -0
  60. package/kits/physics-3d/blueprints/rock.scene +14 -0
  61. package/kits/physics-3d/blueprints/statue.scene +26 -0
  62. package/kits/physics-3d/blueprints/tree.scene +14 -0
  63. package/kits/physics-3d/blueprints/wall.scene +26 -0
  64. package/kits/{basic-2d → physics-3d}/castle.json +23 -5
  65. package/kits/physics-3d/docs/pxmodel-format.md +111 -0
  66. package/kits/physics-3d/drawings/crate.pxart +26 -0
  67. package/kits/physics-3d/drawings/door-edge.pxart +26 -0
  68. package/kits/physics-3d/drawings/door.pxart +27 -0
  69. package/kits/physics-3d/drawings/face.pxart +26 -0
  70. package/kits/physics-3d/drawings/floor.pxart +27 -0
  71. package/kits/physics-3d/drawings/platform.pxart +27 -0
  72. package/kits/physics-3d/drawings/statue.pxart +27 -0
  73. package/kits/physics-3d/drawings/wall.pxart +27 -0
  74. package/kits/physics-3d/engine3d/PlayOnly3D.jsx +32 -0
  75. package/kits/physics-3d/engine3d/PxModelEditor.jsx +619 -0
  76. package/kits/physics-3d/engine3d/Scene3DEditor.jsx +618 -0
  77. package/kits/physics-3d/engine3d/Scene3DPlayer.jsx +309 -0
  78. package/kits/physics-3d/engine3d/editor3dData.js +114 -0
  79. package/kits/physics-3d/engine3d/editor3dInspector.jsx +404 -0
  80. package/kits/physics-3d/engine3d/editorChrome.jsx +218 -0
  81. package/kits/physics-3d/engine3d/editorWorld.js +249 -0
  82. package/kits/physics-3d/engine3d/materials.js +174 -0
  83. package/kits/physics-3d/engine3d/meshops.js +123 -0
  84. package/kits/physics-3d/engine3d/modelEditorWorld.js +439 -0
  85. package/kits/physics-3d/engine3d/modelFiles.js +139 -0
  86. package/kits/physics-3d/engine3d/pxmodel.js +265 -0
  87. package/kits/physics-3d/engine3d/thumbnails.js +137 -0
  88. package/kits/physics-3d/engine3d/world3d.js +216 -0
  89. package/kits/{basic-2d → physics-3d}/eslint.config.js +10 -25
  90. package/kits/physics-3d/index.html +20 -0
  91. package/kits/physics-3d/main.jsx +30 -0
  92. package/kits/physics-3d/models/barrel.pxmodel +10 -0
  93. package/kits/physics-3d/models/player.pxmodel +222 -0
  94. package/kits/physics-3d/models/rock.pxmodel +30 -0
  95. package/kits/physics-3d/models/tree.pxmodel +10 -0
  96. package/kits/{basic-2d → physics-3d}/package-lock.json +140 -119
  97. package/kits/{basic-2d → physics-3d}/package.json +11 -9
  98. package/kits/{basic-2d → physics-3d}/pnpm-lock.yaml +162 -137
  99. package/kits/physics-3d/scenes/main.scene +414 -0
  100. package/kits/physics-3d/scenes/model-lab.scene +127 -0
  101. package/kits/physics-3d/systems/physics3d.js +356 -0
  102. package/package.json +5 -2
  103. package/dist/shell/assets/index-DKu9ejyh.js +0 -436
  104. package/kits/basic-2d/CLAUDE.md +0 -221
  105. package/kits/basic-2d/behaviors/Camera.jsx +0 -43
  106. package/kits/basic-2d/behaviors/Collider.jsx +0 -213
  107. package/kits/basic-2d/behaviors/Layout.jsx +0 -53
  108. package/kits/basic-2d/behaviors/Sprite.jsx +0 -357
  109. package/kits/basic-2d/behaviors/tint.js +0 -47
  110. package/kits/basic-2d/blueprints/cauldron.scene +0 -20
  111. package/kits/basic-2d/docs/pxart-format.md +0 -377
  112. package/kits/basic-2d/drawings/cauldron.pxart +0 -113
  113. package/kits/basic-2d/editors/BlueprintLibrary.jsx +0 -270
  114. package/kits/basic-2d/editors/ErrorBoundary.jsx +0 -59
  115. package/kits/basic-2d/editors/PlayOnly.jsx +0 -31
  116. package/kits/basic-2d/editors/PxArtEditor.jsx +0 -1092
  117. package/kits/basic-2d/editors/SceneEditor.jsx +0 -1780
  118. package/kits/basic-2d/editors/SelectionOverlay.jsx +0 -909
  119. package/kits/basic-2d/editors/SingleEditor.jsx +0 -122
  120. package/kits/basic-2d/editors/behaviorRegistry.js +0 -34
  121. package/kits/basic-2d/editors/editorHistory.js +0 -157
  122. package/kits/basic-2d/editors/inspectorSheet.js +0 -13
  123. package/kits/basic-2d/editors/pixelCanvas.js +0 -11
  124. package/kits/basic-2d/editors/pixelEditorChrome.jsx +0 -74
  125. package/kits/basic-2d/editors/pixelGeometry.js +0 -140
  126. package/kits/basic-2d/editors/pixelInspector.jsx +0 -633
  127. package/kits/basic-2d/editors/pxArtEditorModel.js +0 -732
  128. package/kits/basic-2d/editors/pxArtPlayback.js +0 -92
  129. package/kits/basic-2d/editors/pxArtTimeline.jsx +0 -752
  130. package/kits/basic-2d/editors/pxArtTimeline.module.css +0 -506
  131. package/kits/basic-2d/editors/pxArtTools.js +0 -232
  132. package/kits/basic-2d/editors/useArtboardFit.js +0 -105
  133. package/kits/basic-2d/engine/ScenePlayer.jsx +0 -209
  134. package/kits/basic-2d/engine/SceneUI.jsx +0 -59
  135. package/kits/basic-2d/engine/assets.js +0 -15
  136. package/kits/basic-2d/engine/autoInspector.jsx +0 -70
  137. package/kits/basic-2d/engine/behaviorExtensions.js +0 -32
  138. package/kits/basic-2d/engine/blueprint.js +0 -557
  139. package/kits/basic-2d/engine/collider.js +0 -200
  140. package/kits/basic-2d/engine/files.js +0 -141
  141. package/kits/basic-2d/engine/liveReload.js +0 -88
  142. package/kits/basic-2d/engine/pxart.js +0 -1032
  143. package/kits/basic-2d/engine/pxartSmooth.js +0 -222
  144. package/kits/basic-2d/engine/scene.js +0 -696
  145. package/kits/basic-2d/engine/spriteGeometry.js +0 -32
  146. package/kits/basic-2d/engine/systemRegistry.js +0 -16
  147. package/kits/basic-2d/engine/ui.jsx +0 -695
  148. package/kits/basic-2d/engine/ui.module.css +0 -2287
  149. package/kits/basic-2d/index.html +0 -24
  150. package/kits/basic-2d/main.jsx +0 -24
  151. package/kits/basic-2d/scenes/main.scene +0 -16
  152. package/kits/basic-2d/scripts/draw.mjs +0 -121
  153. package/kits/physics-2d/behaviors/Sound.jsx +0 -163
  154. package/kits/physics-2d/behaviors/Tone.jsx +0 -95
  155. package/kits/physics-2d/engine/tone.js +0 -112
  156. /package/kits/{basic-2d → physics-3d}/.prettierrc +0 -0
  157. /package/kits/{basic-2d → physics-3d}/vite.config.js +0 -0
@@ -1,270 +0,0 @@
1
- import React, { useEffect, useRef, useState } from 'react';
2
- import { renderSpriteFrame } from '../engine/pxart';
3
- import { screenToCard } from '../engine/scene';
4
- import { countBlueprintInstances, isImportedPath, listBlueprints } from '../engine/blueprint';
5
- import { ConfirmDialog, ContextMenu, cx, Icon, styles } from '../engine/ui';
6
-
7
- const DRAG_THRESHOLD = 4;
8
-
9
- // Deck-level blueprint library / hotbar: lists `blueprints/*.scene` (replacing
10
- // the old scene-local stamp system). Mirrors castle-client's belt: TAP a slot
11
- // to select the blueprint for editing in the sidebar; DRAG a slot onto the
12
- // canvas to place a new instance; right-click for a delete option.
13
- export function BlueprintLibrary({
14
- files,
15
- sprites,
16
- canvasRef,
17
- editCameraRef,
18
- isPlaying,
19
- selectedBlueprintPath,
20
- instanceBlueprintPath,
21
- onSelectBlueprint,
22
- onAddActor,
23
- dragPlace,
24
- onDeleteBlueprint,
25
- }) {
26
- const blueprints = listBlueprints(files);
27
- const dragRef = useRef(null);
28
- const hotbarRef = useRef(null);
29
- const suppressClickRef = useRef(false);
30
- const [dragPreview, setDragPreview] = useState(null);
31
- const [contextMenu, setContextMenu] = useState(null);
32
- const [confirmDelete, setConfirmDelete] = useState(null);
33
-
34
- // Map a vertical mouse wheel gesture onto horizontal scroll so plain-mouse
35
- // users (no trackpad/touch) can pan the hotbar. Bound natively rather than via
36
- // React's onWheel so the listener is non-passive and can preventDefault.
37
- useEffect(() => {
38
- const bar = hotbarRef.current;
39
- if (!bar) return undefined;
40
- const onWheel = (event) => {
41
- if (event.deltaY !== 0 && Math.abs(event.deltaY) > Math.abs(event.deltaX)) {
42
- bar.scrollLeft += event.deltaY;
43
- event.preventDefault();
44
- }
45
- };
46
- bar.addEventListener('wheel', onWheel, { passive: false });
47
- return () => bar.removeEventListener('wheel', onWheel);
48
- }, []);
49
-
50
- const onSlotContextMenu = (event, blueprint) => {
51
- if (isPlaying) return;
52
- event.preventDefault();
53
- event.stopPropagation();
54
- setContextMenu({ blueprint, x: event.clientX, y: event.clientY });
55
- };
56
-
57
- const onSlotPointerDown = (event, blueprint) => {
58
- if (isPlaying || event.button !== 0) return;
59
- event.preventDefault();
60
- const drag = {
61
- blueprint,
62
- pointerId: event.pointerId,
63
- startX: event.clientX,
64
- startY: event.clientY,
65
- moved: false,
66
- onStage: false,
67
- };
68
- dragRef.current = drag;
69
- try {
70
- event.currentTarget.setPointerCapture(event.pointerId);
71
- } catch {
72
- // Window listeners still finish the drag if capture is unavailable.
73
- }
74
- const onMove = (moveEvent) => {
75
- if (moveEvent.pointerId !== drag.pointerId) return;
76
- if (!drag.moved && Math.hypot(moveEvent.clientX - drag.startX, moveEvent.clientY - drag.startY) > DRAG_THRESHOLD) {
77
- drag.moved = true;
78
- }
79
- if (!drag.moved) return;
80
- const position = eventToStagePoint(moveEvent, canvasRef, editCameraRef);
81
- if (position) {
82
- // Over the stage: the drag becomes a REAL placed instance immediately,
83
- // so it grid-snaps and renders exactly like the actor it is. The
84
- // floating thumbnail only exists off-stage.
85
- if (drag.onStage) {
86
- dragPlace.move(position);
87
- } else {
88
- drag.onStage = true;
89
- setDragPreview(null);
90
- dragPlace.enter(blueprint.path, position);
91
- }
92
- } else {
93
- if (drag.onStage) {
94
- drag.onStage = false;
95
- dragPlace.leave();
96
- }
97
- setDragPreview({ blueprint, x: moveEvent.clientX, y: moveEvent.clientY, overStage: false });
98
- }
99
- };
100
- const onUp = (upEvent) => {
101
- if (upEvent.pointerId !== drag.pointerId) return;
102
- window.removeEventListener('pointermove', onMove);
103
- window.removeEventListener('pointerup', onUp);
104
- window.removeEventListener('pointercancel', onUp);
105
- dragRef.current = null;
106
- setDragPreview(null);
107
- if (!drag.moved) return;
108
- suppressClickRef.current = true;
109
- // Cancelled drags (pointercancel) count as a release off-stage.
110
- if (drag.onStage && upEvent.type !== 'pointercancel') dragPlace.drop();
111
- else if (drag.onStage) dragPlace.leave();
112
- };
113
- window.addEventListener('pointermove', onMove);
114
- window.addEventListener('pointerup', onUp);
115
- window.addEventListener('pointercancel', onUp);
116
- };
117
-
118
- return (
119
- <div ref={hotbarRef} className={styles.bpHotbar} aria-label="Blueprints">
120
- <button
121
- type="button"
122
- className={styles.bpActionSlot}
123
- aria-label="Add actor"
124
- title="New blueprint"
125
- onClick={onAddActor}
126
- disabled={isPlaying}>
127
- <Icon name="plus" />
128
- </button>
129
- {blueprints.map((blueprint) => (
130
- <button
131
- key={blueprint.path}
132
- type="button"
133
- className={cx(
134
- styles.bpSlot,
135
- selectedBlueprintPath === blueprint.path && styles.bpSlotSelected,
136
- selectedBlueprintPath !== blueprint.path &&
137
- instanceBlueprintPath === blueprint.path &&
138
- styles.bpSlotInstance
139
- )}
140
- title={`${blueprint.name} -- click to edit, drag to place`}
141
- disabled={isPlaying}
142
- onPointerDown={(event) => onSlotPointerDown(event, blueprint)}
143
- onContextMenu={(event) => onSlotContextMenu(event, blueprint)}
144
- onClick={() => {
145
- if (suppressClickRef.current) {
146
- suppressClickRef.current = false;
147
- return;
148
- }
149
- onSelectBlueprint(blueprint.path);
150
- }}>
151
- <BlueprintThumbnail blueprint={blueprint} sprites={sprites} />
152
- </button>
153
- ))}
154
- {dragPreview ? <BlueprintDragPreview preview={dragPreview} sprites={sprites} /> : null}
155
- {contextMenu ? (
156
- <ContextMenu
157
- x={contextMenu.x}
158
- y={contextMenu.y}
159
- onClose={() => setContextMenu(null)}
160
- items={
161
- // An imported blueprint belongs to the deck it came from: placeable
162
- // here, but there is nothing this deck can delete.
163
- isImportedPath(contextMenu.blueprint.path)
164
- ? [{ key: 'imported', label: 'From an import (read-only)', disabled: true }]
165
- : [
166
- {
167
- key: 'delete',
168
- label: `Delete ${contextMenu.blueprint.name}...`,
169
- onClick: () => setConfirmDelete(contextMenu.blueprint),
170
- },
171
- ]
172
- }
173
- />
174
- ) : null}
175
- {confirmDelete ? (
176
- <DeleteBlueprintConfirm
177
- files={files}
178
- blueprint={confirmDelete}
179
- onCancel={() => setConfirmDelete(null)}
180
- onConfirm={() => {
181
- onDeleteBlueprint(confirmDelete.path);
182
- setConfirmDelete(null);
183
- }}
184
- />
185
- ) : null}
186
- </div>
187
- );
188
- }
189
-
190
- function DeleteBlueprintConfirm({ files, blueprint, onCancel, onConfirm }) {
191
- const count = countBlueprintInstances(files, blueprint.path);
192
- const instanceText = count === 1 ? '1 placed actor' : `${count} placed actors`;
193
- return (
194
- <ConfirmDialog
195
- title={`Delete ${blueprint.name}?`}
196
- message={
197
- count > 0
198
- ? `This removes ${blueprint.name} and ${instanceText} across every scene in the deck. This can't be undone.`
199
- : `${blueprint.name} has no placed actors. This can't be undone.`
200
- }
201
- confirmLabel="Delete"
202
- onCancel={onCancel}
203
- onConfirm={onConfirm}
204
- />
205
- );
206
- }
207
-
208
- function BlueprintDragPreview({ preview, sprites }) {
209
- const layout = preview.blueprint.components?.Layout;
210
- const width = Math.max(24, Math.min(80, layout?.width ?? 48));
211
- const height = Math.max(24, Math.min(80, layout?.height ?? 48));
212
- return (
213
- <div
214
- className={cx(styles.bpDragPreview, preview.overStage && styles.bpDragPreviewOverStage)}
215
- style={{
216
- left: preview.x,
217
- top: preview.y,
218
- width,
219
- height,
220
- transform: `translate(-50%, -50%) rotate(${layout?.rotation ?? 0}deg)`,
221
- }}>
222
- <BlueprintThumbnail blueprint={preview.blueprint} sprites={sprites} preview />
223
- </div>
224
- );
225
- }
226
-
227
- export function BlueprintThumbnail({ blueprint, sprites, preview = false }) {
228
- const canvasRef = useRef(null);
229
- const spritePath = blueprint.components?.Sprite?.file;
230
- const sprite = spritePath ? sprites?.[spritePath] : null;
231
- useEffect(() => {
232
- const canvas = canvasRef.current;
233
- if (!canvas || !sprite) return;
234
- renderSpriteFrame(sprite, 0, canvas);
235
- }, [sprite]);
236
- if (!sprite) {
237
- return (
238
- <span className={styles.bpSlotFallback}>
239
- <Icon name="clone" />
240
- </span>
241
- );
242
- }
243
- return (
244
- <canvas
245
- ref={canvasRef}
246
- className={cx(styles.bpSlotThumb, preview && styles.bpPreviewThumb)}
247
- aria-hidden="true"
248
- />
249
- );
250
- }
251
-
252
- function eventToStagePoint(event, canvasRef, editCameraRef) {
253
- const canvas = canvasRef.current;
254
- if (!canvas) return null;
255
- const rect = canvas.getBoundingClientRect();
256
- if (
257
- event.clientX < rect.left ||
258
- event.clientX > rect.right ||
259
- event.clientY < rect.top ||
260
- event.clientY > rect.bottom
261
- ) {
262
- return null;
263
- }
264
- const raw = screenToCard(canvas, event.clientX, event.clientY);
265
- const camera = editCameraRef.current ?? { x: 0, y: 0 };
266
- return {
267
- x: raw.x + camera.x,
268
- y: raw.y + camera.y,
269
- };
270
- }
@@ -1,59 +0,0 @@
1
- // Deck-side error boundary for the panel routes. A throwing editor (these are
2
- // agent-edited deck files -- they will throw) shows a small muted message inside
3
- // its panel iframe instead of a blank / loud crash. Inline styles so it doesn't
4
- // depend on whatever module may have failed.
5
-
6
- import React from 'react';
7
-
8
- export class ErrorBoundary extends React.Component {
9
- state = { error: null };
10
- static getDerivedStateFromError(error) {
11
- return { error };
12
- }
13
- componentDidCatch(error) {
14
- console.error('[deck panel error]', error);
15
- }
16
- render() {
17
- if (!this.state.error) return this.props.children;
18
- return (
19
- <div
20
- style={{
21
- height: '100vh',
22
- padding: '14px 16px',
23
- overflow: 'auto',
24
- color: '#6e7781',
25
- font: '13px ui-sans-serif, system-ui, -apple-system, sans-serif',
26
- background: '#ffffff',
27
- }}>
28
- <div style={{ color: '#57606a' }}>this panel hit an error</div>
29
- <pre
30
- style={{
31
- margin: '8px 0 0',
32
- whiteSpace: 'pre-wrap',
33
- wordBreak: 'break-word',
34
- fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace',
35
- fontSize: 12,
36
- color: '#8c959f',
37
- }}>
38
- {String((this.state.error && this.state.error.message) || this.state.error)}
39
- </pre>
40
- <button
41
- type="button"
42
- onClick={() => this.setState({ error: null })}
43
- style={{
44
- marginTop: 8,
45
- font: 'inherit',
46
- fontSize: 12,
47
- padding: '3px 10px',
48
- border: '1px solid #cccccc',
49
- borderRadius: 4,
50
- background: '#ffffff',
51
- color: '#57606a',
52
- cursor: 'pointer',
53
- }}>
54
- retry
55
- </button>
56
- </div>
57
- );
58
- }
59
- }
@@ -1,31 +0,0 @@
1
- import React from 'react';
2
- import { Lifecycle } from 'castle-web-sdk';
3
- import { parseJsonFile } from '../engine/files';
4
- import { useLiveDeckFiles } from '../engine/liveReload';
5
- import { collectAssets } from '../engine/assets';
6
- import { ScenePlayer } from '../engine/ScenePlayer';
7
- import { behaviorClasses } from './behaviorRegistry';
8
- // Play-mode entry point. Plays the scene named by `?scene=<path>` (the shell's
9
- // Play panel sets this), defaulting to `scenes/main.scene`. It renders ONLY the
10
- // game — the scene picker lives in the Play panel chrome (the shell), not here,
11
- // so nothing floats over the game surface and steals input. Files are live:
12
- // scene/drawing edits re-key the player against fresh data.
13
- const DEFAULT_SCENE = 'scenes/main.scene';
14
-
15
- export function PlayOnly({ initialScene } = {}) {
16
- const { files, dataVersion } = useLiveDeckFiles();
17
- const scenePath = initialScene && files[initialScene] !== undefined ? initialScene : DEFAULT_SCENE;
18
- const { value: sceneData } = parseJsonFile(scenePath, files[scenePath] ?? '');
19
- if (!sceneData) return null;
20
- const { sprites } = collectAssets(files);
21
- return (
22
- <ScenePlayer
23
- key={`${scenePath}:${dataVersion}`}
24
- sceneData={sceneData}
25
- sprites={sprites}
26
- files={files}
27
- behaviorClasses={behaviorClasses}
28
- onFirstFrame={Lifecycle.ready}
29
- />
30
- );
31
- }