@vgai/editor 0.4.0 → 0.4.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 (137) hide show
  1. package/dist/assets/{axe-BJjvBeOZ.js → axe-N4cNyzfs.js} +1 -1
  2. package/dist/assets/{browserAll-Dn0pgD87.js → browserAll-BIBT0Z2H.js} +1 -1
  3. package/dist/assets/{create-runtime-BF9OD-U8.js → create-runtime-DxLhdk4U.js} +1 -1
  4. package/dist/assets/{game-u6c2Patu.js → game-4NbNRROm.js} +1 -1
  5. package/dist/assets/{game-umrHIqFB.js → game-B3UH5LjS.js} +1 -1
  6. package/dist/assets/{game-BR0GBNgF.js → game-ByxRLJi1.js} +1 -1
  7. package/dist/assets/{game-DeTGdgYt.js → game-CJ5BqOYG.js} +1 -1
  8. package/dist/assets/{game-DQxhCYsZ.js → game-CSJm1kwB.js} +1 -1
  9. package/dist/assets/{game-CLNm2g0y.js → game-D9Mo4L3Q.js} +1 -1
  10. package/dist/assets/{game-B346oj_f.js → game-DJmU9BQF.js} +1 -1
  11. package/dist/assets/{game-BCNN63uV.js → game-ZqGLgxRj.js} +1 -1
  12. package/dist/assets/{game-loop-t5W_oqxz.js → game-loop-9YP76JB1.js} +1 -1
  13. package/dist/assets/{game-source-DzE9taML.js → game-source-DLKG9pmj.js} +1 -1
  14. package/dist/assets/{index-DbQzGLxv.js → index-8A4JLNIp.js} +902 -892
  15. package/dist/assets/{index-CgcH1RpF.js → index-Brzr17q0.js} +1 -1
  16. package/dist/assets/{index-D3tcNB2T.js → index-CnKtvrru.js} +1 -1
  17. package/dist/assets/{index-Fc8Ezr20.js → index-D-WR11Jw.js} +1 -1
  18. package/dist/assets/index-DiUacMXR.css +1 -0
  19. package/dist/assets/{ingest-siblings-CW_xbvrF.js → ingest-siblings-Cmx39OBK.js} +1 -1
  20. package/dist/assets/{mount-manifest-DgUscyaD.js → mount-manifest-kzdZgkkc.js} +1 -1
  21. package/dist/assets/{react-18-C4tVCii_.js → react-18-DvWsdwa_.js} +1 -1
  22. package/dist/assets/webworkerAll-C9GR-KrR.js +1 -0
  23. package/dist/assets/{world-documents-BSaA5YIF.js → world-documents-DM_aIMAW.js} +1 -1
  24. package/dist/index.html +2 -2
  25. package/dist-server/packaged.mjs +27125 -1075
  26. package/package.json +2 -2
  27. package/server/asset-history-snapshots.ts +189 -0
  28. package/server/asset-library-routes.ts +404 -53
  29. package/server/catalog-import-recipe.ts +97 -0
  30. package/server/catalog-reimport.ts +141 -0
  31. package/server/cloud-asset-catalog.ts +71 -5
  32. package/server/dev.ts +1 -1
  33. package/server/editor-server.ts +106 -51
  34. package/server/editor-sse.ts +5 -0
  35. package/server/generative-execution-context.ts +45 -0
  36. package/server/model-import-conversion.ts +345 -0
  37. package/server/packaged.ts +1 -1
  38. package/server/project-hmr-files.ts +3 -5
  39. package/server/project-output-writer.ts +440 -36
  40. package/server/project-tools.ts +529 -0
  41. package/server/server-utils.ts +14 -11
  42. package/src/EditorContext.tsx +4 -4
  43. package/src/action-registry.ts +12 -0
  44. package/src/asset-editor-context.tsx +9 -0
  45. package/src/asset-events.ts +3 -15
  46. package/src/asset-selection.ts +3 -0
  47. package/src/asset-workflow/asset-capabilities.ts +40 -0
  48. package/src/asset-workflow/asset-import-jobs.ts +108 -0
  49. package/src/asset-workflow/asset-library-query.ts +8 -1
  50. package/src/asset-workflow/asset-workflow-quality.ts +2 -0
  51. package/src/asset-workflow/import-contract.ts +2 -0
  52. package/src/asset-workflow/model-inspection.ts +92 -1
  53. package/src/asset-workflow/preview-resource-lifetime.ts +44 -0
  54. package/src/asset-workflow/project-asset-commands.ts +1 -0
  55. package/src/asset-workflow/project-asset-health.ts +3 -6
  56. package/src/asset-workflow/project-asset-operations.ts +119 -4
  57. package/src/command-listener.ts +37 -9
  58. package/src/components/ApplicationMenus.tsx +13 -15
  59. package/src/components/AssetBrowser.tsx +301 -26
  60. package/src/components/AssetImportDetails.tsx +207 -92
  61. package/src/components/AssetImportJobStatus.tsx +55 -0
  62. package/src/components/CenterDocuments.tsx +28 -1
  63. package/src/components/CommandPalette.tsx +2 -2
  64. package/src/components/DefaultEditorLayout.tsx +4 -0
  65. package/src/components/InspectorToolSection.tsx +12 -10
  66. package/src/components/OnlineAssetBrowser.tsx +197 -11
  67. package/src/components/ToolHost.tsx +8 -8
  68. package/src/components/ViewportOverlay.tsx +13 -26
  69. package/src/components/ViewportPanel.tsx +19 -14
  70. package/src/components/ViewportShadingMenu.tsx +103 -0
  71. package/src/components/WorkspaceDock.tsx +103 -17
  72. package/src/components/asset-documents.tsx +38 -11
  73. package/src/components/asset-editor-persistence.ts +300 -5
  74. package/src/components/asset-selection-section.tsx +83 -9
  75. package/src/components/asset-viewers/AudioViewer.tsx +4 -7
  76. package/src/components/asset-viewers/ModelViewer.tsx +168 -5
  77. package/src/components/asset-viewers/OnlineAssetDetail.tsx +52 -12
  78. package/src/components/asset-viewers/SourceAssetViewer.tsx +7 -26
  79. package/src/components/asset-workflow.css +30 -3
  80. package/src/components/primitives/editor-icons.ts +1 -0
  81. package/src/components/project-tool-documents.tsx +298 -0
  82. package/src/components/status-contributions.tsx +38 -0
  83. package/src/components/tool-documents.tsx +20 -17
  84. package/src/components/tool-schema-form.tsx +258 -0
  85. package/src/components/workspace-dock.css +16 -0
  86. package/src/editor-api.ts +159 -22
  87. package/src/editor-store.ts +6 -5
  88. package/src/editor-viewport.ts +12 -7
  89. package/src/game-viewport-state.ts +28 -0
  90. package/src/model-thumbnail.ts +97 -9
  91. package/src/play-mode.ts +30 -3
  92. package/src/project-tool-discovery.ts +5 -5
  93. package/src/{project-operations.ts → project-tools.ts} +39 -26
  94. package/src/scene-sync.ts +0 -67
  95. package/src/storage/handle-storage.ts +5 -1
  96. package/src/storage/http-storage.ts +7 -2
  97. package/src/storage/mem-storage.ts +7 -1
  98. package/src/storage/types.ts +2 -0
  99. package/src/theme-css.ts +17 -7
  100. package/src/tool-loader.ts +152 -241
  101. package/src/viewport-shading-boundary.ts +15 -0
  102. package/src/widgets/index.ts +2 -1
  103. package/src/workspace-dock-controller.ts +8 -0
  104. package/src/workspace-document-registry.ts +4 -4
  105. package/src/workspace-state-persistence.ts +36 -10
  106. package/template/.claude/skills/editor/SKILL.md +13 -3
  107. package/template/AGENTS.md +100 -83
  108. package/template/package.json +16 -0
  109. package/template/public/scenes/default.vscn.json +1 -2
  110. package/template/scripts/playtest.ts +7 -37
  111. package/template/server/rooms/game-room.ts +2 -2
  112. package/template/src/data/README.md +3 -2
  113. package/template/src/data/tuning.data.json +1 -3
  114. package/template/src/data/tuning.schema.json +0 -12
  115. package/template/src/data/tuning.schema.ts +2 -9
  116. package/template/src/data/tuning.ts +1 -1
  117. package/template/src/scripts/registry.ts +0 -3
  118. package/template/src/tools/README.md +151 -16
  119. package/template/src/tools/autoplay.tool.ts +31 -0
  120. package/template/src/tools/autoplay.ts +15 -0
  121. package/template/src/tools/tuning.document.tsx +107 -0
  122. package/template/src/tools/tuning.tool.ts +24 -0
  123. package/template/src/tools/tuning.ts +9 -0
  124. package/template/src/ui/Button.stories.tsx +1 -1
  125. package/template/tests/acceptance/example.spec.ts +4 -59
  126. package/template/vgai.game.json +1 -1
  127. package/dist/assets/index-bAGhEnnO.css +0 -1
  128. package/dist/assets/webworkerAll-BA4aq7xq.js +0 -1
  129. package/dist/project-scripts.bundle.js +0 -3917
  130. package/server/project-operations.ts +0 -343
  131. package/src/components/project-operation-documents.tsx +0 -226
  132. package/template/src/operations/README.md +0 -88
  133. package/template/src/scripts/components/data-spinner.ts +0 -86
  134. package/template/src/scripts/components/spin-lap-math.ts +0 -27
  135. package/template/src/tools/example.tool.tsx +0 -97
  136. package/template/src/tools/spin.tool.tsx +0 -101
  137. package/template/tests/logic/example.test.ts +0 -31
@@ -6,6 +6,7 @@
6
6
  * This module translates them into store method calls.
7
7
  */
8
8
 
9
+ import type { ViewportShadingMode } from '@engine/render/viewport-shading';
9
10
  import { waitForHoldBudget } from '@engine/runtime/debug-bridge';
10
11
  import { parseSceneFile, SceneParseError } from '@engine/scene/parse';
11
12
  import {
@@ -14,13 +15,18 @@ import {
14
15
  captureObjectAssetPreview,
15
16
  } from './asset-preview';
16
17
  import { getActiveSystems } from './authoring/active-systems';
17
- import { isAssetDocumentId, openAssetDocument } from './components/asset-documents';
18
+ import {
19
+ isAssetDocumentId,
20
+ migrateAssetEditorDocumentId,
21
+ openAssetDocument,
22
+ } from './components/asset-documents';
18
23
  import { openBuildProfilesDocument } from './components/build-documents';
19
24
  import { capturePlayComposite } from './composite-screenshot';
20
25
  import { connectEvents, reportCommandResult, reportEditorState } from './editor-api';
21
26
  import { editorConsole } from './editor-console';
22
27
  import { getEditorMode } from './editor-mode';
23
28
  import type { AssetKind, EditorStore, HelperVisibility } from './editor-store';
29
+ import { gameViewportShadingMode, setGameDocumentShadingMode } from './game-viewport-state';
24
30
  import {
25
31
  enterPlayMode,
26
32
  exitPlayMode,
@@ -128,7 +134,7 @@ export function collectState(store: EditorStore): Record<string, unknown> {
128
134
  showGrid: store.showGrid,
129
135
  showHelpers: store.showHelpers,
130
136
  showStats: store.showStats,
131
- shadingMode: store.shadingMode,
137
+ shadingMode: store.activeViewportTab === 'game' ? gameViewportShadingMode() : store.shadingMode,
132
138
  helperVisibility: { ...store.helperVisibility },
133
139
  transformMode: store.transformMode,
134
140
  transformSpace: store.transformSpace,
@@ -783,7 +789,7 @@ export async function handleCommand(
783
789
  // ALWAYS shows the Inspector — nothing displaces it anymore (§10.3).
784
790
  case 'active-tab': {
785
791
  const key = cmd['key'] as string;
786
- if (key !== '__inspector__') activateWorkspaceDocument(key);
792
+ if (key !== '__inspector__') activateWorkspaceDocument(migrateAssetEditorDocumentId(key));
787
793
  break;
788
794
  }
789
795
  case 'open-asset-tab':
@@ -797,13 +803,14 @@ export async function handleCommand(
797
803
  // false` is only a UI-affordance rule, not a registry invariant; see
798
804
  // workspace-document-registry.ts) — so this command must keep the
799
805
  // no-op itself. `isAssetDocumentId` is exactly the legacy asset key
800
- // vocabulary check (project asset path / `asset-lab:entity:<id>` /
806
+ // vocabulary check (project asset path / canonical `asset-editor:entity:<id>`
807
+ // plus compatibility `asset-lab:entity:<id>` /
801
808
  // `online:<source>:<id>` — see asset-documents.tsx), so gating on it
802
809
  // blocks the pinned `workspace:scene`/`workspace:game` ids (and any
803
810
  // story `story:<path>#<name>` id) while preserving the real behavior
804
811
  // for actual asset tabs.
805
812
  const key = cmd['key'] as string;
806
- if (isAssetDocumentId(key)) closeWorkspaceDocument(key);
813
+ if (isAssetDocumentId(key)) closeWorkspaceDocument(migrateAssetEditorDocumentId(key));
807
814
  break;
808
815
  }
809
816
  case 'toggle-command-palette':
@@ -869,7 +876,11 @@ export async function handleCommand(
869
876
  if (store.showStats !== (cmd['enabled'] as boolean)) store.toggleStats();
870
877
  break;
871
878
  case 'set-shading-mode':
872
- store.setShadingMode(cmd['mode'] as 'solid' | 'wireframe' | 'unlit');
879
+ if (store.activeViewportTab === 'game') {
880
+ setGameDocumentShadingMode(cmd['mode'] as ViewportShadingMode);
881
+ } else {
882
+ store.setShadingMode(cmd['mode'] as ViewportShadingMode);
883
+ }
873
884
  break;
874
885
  case 'set-helper-type': {
875
886
  const helperType = cmd['helperType'] as keyof HelperVisibility;
@@ -1147,8 +1158,24 @@ export function connectCommandListener(store: EditorStore): () => void {
1147
1158
  }
1148
1159
  const source = connectEvents();
1149
1160
 
1161
+ const reportLatestState = () => void reportEditorState(collectState(store));
1162
+ let storeReportScheduled = false;
1163
+ const reportStoreChange = () => {
1164
+ // One editor action commonly emits several store notifications. Collapse
1165
+ // that synchronous burst into one current snapshot without delaying it a
1166
+ // frame — UI Play/Stop must be visible to `vgai status` immediately even
1167
+ // though no relayed command caused the transition.
1168
+ if (storeReportScheduled) return;
1169
+ storeReportScheduled = true;
1170
+ queueMicrotask(() => {
1171
+ storeReportScheduled = false;
1172
+ reportLatestState();
1173
+ });
1174
+ };
1175
+ const unsubscribeStoreReport = store.subscribe(reportStoreChange);
1176
+
1150
1177
  // Report initial state
1151
- reportEditorState(collectState(store));
1178
+ reportLatestState();
1152
1179
 
1153
1180
  source.addEventListener('editor-command', (e: MessageEvent) => {
1154
1181
  try {
@@ -1160,7 +1187,7 @@ export function connectCommandListener(store: EditorStore): () => void {
1160
1187
  reportCommandResult(requestId, result.ok, result.error, result.data);
1161
1188
  }
1162
1189
  // Report updated state after command execution
1163
- reportEditorState(collectState(store));
1190
+ reportLatestState();
1164
1191
  });
1165
1192
  } catch {
1166
1193
  /* ignore malformed events */
@@ -1175,7 +1202,7 @@ export function connectCommandListener(store: EditorStore): () => void {
1175
1202
  // #145 — presence freshness: the state snapshot the server holds is only
1176
1203
  // re-POSTed after commands, so visibility/focus changes between commands
1177
1204
  // would go stale. Report on the three events that change presence.
1178
- const reportPresence = () => reportEditorState(collectState(store));
1205
+ const reportPresence = reportLatestState;
1179
1206
  document.addEventListener('visibilitychange', reportPresence);
1180
1207
  window.addEventListener('focus', reportPresence);
1181
1208
  window.addEventListener('blur', reportPresence);
@@ -1190,6 +1217,7 @@ export function connectCommandListener(store: EditorStore): () => void {
1190
1217
  window.addEventListener('unhandledrejection', reportAfterError);
1191
1218
 
1192
1219
  return () => {
1220
+ unsubscribeStoreReport();
1193
1221
  document.removeEventListener('visibilitychange', reportPresence);
1194
1222
  window.removeEventListener('focus', reportPresence);
1195
1223
  window.removeEventListener('blur', reportPresence);
@@ -1,4 +1,3 @@
1
- import { normalizeToolPlacement } from '@engine/tools/define-tool';
2
1
  import { useEffect, useRef, useState, useSyncExternalStore } from 'react';
3
2
  import {
4
3
  EditorIcon,
@@ -10,14 +9,14 @@ import {
10
9
  } from '../design-system';
11
10
  import { useEditorStore, useHistoryCommandSnapshot, useHistoryCommands } from '../EditorContext';
12
11
  import { getEditorMode } from '../editor-mode';
13
- import { getProjectOperations, subscribeProjectOperations } from '../project-operations';
12
+ import { getProjectTools, subscribeProjectTools } from '../project-tools';
14
13
  import { editorThemeLibrarySnapshot, subscribeEditorThemeLibrary } from '../theme-library';
15
14
  import {
16
15
  editorThemeSnapshot,
17
16
  setEditorThemePreference,
18
17
  subscribeEditorTheme,
19
18
  } from '../theme-preference';
20
- import { getGlobalTools, subscribeGlobalTools } from '../tool-loader';
19
+ import { getGlobalToolContributions, subscribeToolContributions } from '../tool-loader';
21
20
  import { openUndoHistory } from '../workspace-aux-commands';
22
21
  import {
23
22
  resetWorkspaceDockLayout,
@@ -29,7 +28,7 @@ import { BUILD_OUTPUT_UTILITY_ID } from '../workspace-utility-commands';
29
28
  import { openBuildProfilesDocument } from './build-documents';
30
29
  import { openDataAssetsDocument } from './data-documents';
31
30
  import { openDebuggerPanel } from './debugger-panel-state';
32
- import { openProjectOperationsDocument } from './project-operation-documents';
31
+ import { openProjectToolsDocument } from './project-tool-documents';
33
32
  import { ThemeManagerDialog } from './ThemeManagerDialog';
34
33
  import { openToolDocument } from './tool-documents';
35
34
 
@@ -39,17 +38,17 @@ export function ApplicationMenus() {
39
38
  const store = useEditorStore();
40
39
  const history = useHistoryCommands();
41
40
  const historySnapshot = useHistoryCommandSnapshot();
42
- const tools = useSyncExternalStore(subscribeGlobalTools, getGlobalTools, getGlobalTools);
41
+ const tools = useSyncExternalStore(
42
+ subscribeToolContributions,
43
+ getGlobalToolContributions,
44
+ getGlobalToolContributions,
45
+ );
43
46
  const themeId = useSyncExternalStore(
44
47
  subscribeEditorTheme,
45
48
  editorThemeSnapshot,
46
49
  editorThemeSnapshot,
47
50
  );
48
- const commands = useSyncExternalStore(
49
- subscribeProjectOperations,
50
- getProjectOperations,
51
- getProjectOperations,
52
- );
51
+ const commands = useSyncExternalStore(subscribeProjectTools, getProjectTools, getProjectTools);
53
52
  const themeChoices = useSyncExternalStore(
54
53
  subscribeEditorThemeLibrary,
55
54
  editorThemeLibrarySnapshot,
@@ -193,20 +192,19 @@ export function ApplicationMenus() {
193
192
  tools: (
194
193
  <>
195
194
  {getEditorMode() === 'server' && (
196
- <MenuItem onSelect={choose(() => openProjectOperationsDocument(store))}>
197
- Project Commands
198
- {commands.operations.length > 0 ? ` (${commands.operations.length})` : ''}
195
+ <MenuItem onSelect={choose(() => openProjectToolsDocument(store))}>
196
+ Project Tools
197
+ {commands.tools.length > 0 ? ` (${commands.tools.length})` : ''}
199
198
  </MenuItem>
200
199
  )}
201
200
  {getEditorMode() === 'server' && <Separator />}
202
201
  {tools.length ? (
203
202
  tools.map((tool) => {
204
- const placement = normalizeToolPlacement(tool.placement);
205
203
  return (
206
204
  <MenuItem
207
205
  key={tool.id}
208
206
  onSelect={choose(() => {
209
- if (placement === 'document') openToolDocument(store, tool.id);
207
+ if (tool.point === 'workspace.document') openToolDocument(store, tool.id);
210
208
  else showWorkspaceUtility(`tool:${tool.id}`);
211
209
  })}
212
210
  >