Skip to content

Commit ddba1c3

Browse files
author
DavidQ
committed
Clean up Object Vector Studio V2 object panel actions, z-action sizing, and object/game/name identity fields - PR_26132_023-object-vector-studio-v2-object-panel-cleanup
1 parent 48f4b09 commit ddba1c3

13 files changed

Lines changed: 351 additions & 235 deletions

docs/dev/reports/playwright_v8_coverage.txt

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,10 @@ Exercised tool entry points detected:
2020
(0%) Workspace Manager - not exercised by this Playwright run
2121

2222
Changed runtime JS files covered:
23-
(80%) tools/object-vector-studio-v2/js/bootstrap.js - executed lines 99/99; executed functions 4/5
24-
(90%) tools/object-vector-studio-v2/js/ToolStarterApp.js - executed lines 3217/3217; executed functions 335/373
23+
(80%) tools/object-vector-studio-v2/js/bootstrap.js - executed lines 97/97; executed functions 4/5
24+
(90%) tools/object-vector-studio-v2/js/ToolStarterApp.js - executed lines 3187/3187; executed functions 331/369
25+
(95%) tools/object-vector-studio-v2/js/services/ObjectVectorStudioV2SchemaService.js - executed lines 409/409; executed functions 53/56
26+
(98%) src/engine/rendering/ObjectVectorRuntimeAssetService.js - executed lines 914/914; executed functions 106/108
2527

2628
Files with executed line/function counts where available:
2729
(2%) src/engine/input/ActionInputService.js - executed lines 397/397; executed functions 1/51
@@ -167,7 +169,7 @@ Files with executed line/function counts where available:
167169
(80%) src/engine/persistence/StorageService.js - executed lines 49/49; executed functions 4/5
168170
(80%) tools/asset-manager-v2/js/controls/AccordionSection.js - executed lines 27/27; executed functions 4/5
169171
(80%) tools/asset-manager-v2/js/controls/AssetFormControl.js - executed lines 563/563; executed functions 49/61
170-
(80%) tools/object-vector-studio-v2/js/bootstrap.js - executed lines 99/99; executed functions 4/5
172+
(80%) tools/object-vector-studio-v2/js/bootstrap.js - executed lines 97/97; executed functions 4/5
171173
(80%) tools/palette-manager-v2/modules/PaletteHistoryStack.js - executed lines 54/54; executed functions 8/10
172174
(80%) tools/preview-generator-v2/controls/AccordionSection.js - executed lines 31/31; executed functions 4/5
173175
(80%) tools/preview-generator-v2/PreviewGeneratorV2Logger.js - executed lines 19/19; executed functions 4/5
@@ -193,7 +195,7 @@ Files with executed line/function counts where available:
193195
(88%) tools/world-vector-studio-v2/js/controls/SourceInputControl.js - executed lines 33/33; executed functions 7/8
194196
(89%) tools/asset-manager-v2/js/services/AssetSchemaValidator.js - executed lines 295/295; executed functions 25/28
195197
(89%) tools/preview-generator-v2/controls/StatusLogControl.js - executed lines 32/32; executed functions 8/9
196-
(90%) tools/object-vector-studio-v2/js/ToolStarterApp.js - executed lines 3217/3217; executed functions 335/373
198+
(90%) tools/object-vector-studio-v2/js/ToolStarterApp.js - executed lines 3187/3187; executed functions 331/369
197199
(90%) tools/palette-manager-v2/modules/PaletteValidationService.js - executed lines 88/88; executed functions 9/10
198200
(90%) tools/text2speech-V2/js/controls/ActionNavControl.js - executed lines 117/117; executed functions 19/21
199201
(90%) tools/text2speech-V2/js/TextToSpeechToolApp.js - executed lines 807/807; executed functions 62/69
@@ -208,9 +210,9 @@ Files with executed line/function counts where available:
208210
(93%) tools/workspace-manager-v2/js/controls/ToolTilesControl.js - executed lines 137/137; executed functions 14/15
209211
(94%) games/shared/workspaceGameMetadataHydrator.js - executed lines 106/106; executed functions 16/17
210212
(94%) tools/common/PaletteSortService.js - executed lines 103/103; executed functions 17/18
211-
(95%) tools/object-vector-studio-v2/js/services/ObjectVectorStudioV2SchemaService.js - executed lines 401/401; executed functions 52/55
213+
(95%) tools/object-vector-studio-v2/js/services/ObjectVectorStudioV2SchemaService.js - executed lines 409/409; executed functions 53/56
212214
(95%) tools/session-inspector-v2/js/services/SessionInspectorV2StorageService.js - executed lines 142/142; executed functions 18/19
213-
(98%) src/engine/rendering/ObjectVectorRuntimeAssetService.js - executed lines 914/914; executed functions 105/107
215+
(98%) src/engine/rendering/ObjectVectorRuntimeAssetService.js - executed lines 914/914; executed functions 106/108
214216
(100%) games/Asteroids/entities/Asteroid.js - executed lines 72/72; executed functions 11/11
215217
(100%) games/Asteroids/flow/attract.js - executed lines 17/17; executed functions 1/1
216218
(100%) games/Asteroids/flow/highscore.js - executed lines 16/16; executed functions 1/1
@@ -293,5 +295,8 @@ Uncovered or low-coverage changed JS files:
293295

294296
Changed JS files considered:
295297
(0%) tests/playwright/tools/WorkspaceManagerV2.spec.mjs - changed JS file not collected as browser runtime coverage
298+
(0%) tools/object-vector-studio-v2/tests/playwright/FirstClassToolStarter.spec.mjs - changed JS file not collected as browser runtime coverage
296299
(80%) tools/object-vector-studio-v2/js/bootstrap.js - changed JS file with browser V8 coverage
297300
(90%) tools/object-vector-studio-v2/js/ToolStarterApp.js - changed JS file with browser V8 coverage
301+
(95%) tools/object-vector-studio-v2/js/services/ObjectVectorStudioV2SchemaService.js - changed JS file with browser V8 coverage
302+
(98%) src/engine/rendering/ObjectVectorRuntimeAssetService.js - changed JS file with browser V8 coverage
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# PR_26132_023-object-vector-studio-v2-object-panel-cleanup
2+
3+
## Scope
4+
5+
Updates Object Vector Studio V2 object panel layout, z-action button sizing, and durable object identity naming. No unrelated tools and no sample JSON changes.
6+
7+
## Changes
8+
9+
- Moved Add, Rename, Duplicate, and Delete from the Objects accordion to the bottom of the Object accordion.
10+
- Removed the Object Type input, datalist wiring, object type normalization, object type suggestions, and object type payload persistence.
11+
- Kept Object Name and Tag inputs on inline label/input rows.
12+
- Matched z-action button sizing to shape icon buttons in Words and Icons modes for Bring Forward, Send Backward, Bring To Front, Send To Back, Group Shapes, and Ungroup.
13+
- Updated Object Vector Studio V2 durable object identity to `object.<game>.<name>`.
14+
- Updated rename/add flows so object ids remain schema-compliant when object names change.
15+
- Updated Asteroids Object Vector assets to remove object-level `type` fields while preserving shape `type` fields.
16+
- Updated Object Vector Studio V2 schema and runtime validation to reject object-level `type` and non-`object.game.name` ids.
17+
- Updated Object Vector Studio V2 documentation to describe object/game/name identity in object tiles.
18+
19+
## Validation
20+
21+
Playwright impacted: Yes.
22+
23+
Commands run:
24+
25+
- `node --check tools/object-vector-studio-v2/js/ToolStarterApp.js`
26+
- `node --check tools/object-vector-studio-v2/js/bootstrap.js`
27+
- `node --check tools/object-vector-studio-v2/js/services/ObjectVectorStudioV2SchemaService.js`
28+
- `node --check src/engine/rendering/ObjectVectorRuntimeAssetService.js`
29+
- `node --check tests/playwright/tools/WorkspaceManagerV2.spec.mjs`
30+
- `node --check tools/object-vector-studio-v2/tests/playwright/FirstClassToolStarter.spec.mjs`
31+
- `node -e "const fs=require('fs'); for (const file of ['tools/schemas/tools/object-vector-studio-v2.schema.json','games/Asteroids/game.manifest.json']) { JSON.parse(fs.readFileSync(file,'utf8')); console.log(file + ' OK'); }"`
32+
- `npx playwright test tests/playwright/tools/WorkspaceManagerV2.spec.mjs --project=playwright --workers=1 --reporter=list --grep "Object Vector Studio V2"`
33+
- `npx playwright test --config=tools/object-vector-studio-v2/playwright.config.mjs --workers=1 --reporter=list`
34+
- `npm run test:workspace-v2`
35+
- `git diff --check`
36+
37+
Result:
38+
39+
- Focused Object Vector Studio V2 workspace coverage passed: 6 passed.
40+
- Tool-local Object Vector Studio V2 coverage passed: 4 passed.
41+
- Full Workspace Manager V2 suite passed: 45 passed.
42+
- Playwright V8 coverage refreshed at `docs/dev/reports/playwright_v8_coverage.txt`.
43+
- Full samples smoke test skipped per request; this PR does not modify sample JSON.
44+
45+
## Playwright Coverage
46+
47+
Validates:
48+
49+
- z-action button/icon size parity with shape icon buttons.
50+
- Object actions live at the bottom of the Object accordion.
51+
- Object Type UI is absent.
52+
- Object Name and Tag rows are inline.
53+
- `object.game.name` schema validation rejects old object ids.
54+
- Object-level `type` payload drift is rejected.
55+
- Rename updates the schema-compliant identity id consistently.
56+
- Object Vector asset authoring, animation, inheritance, runtime rendering, and workspace launch flows still load with the new identity contract.
57+
58+
Expected pass behavior:
59+
60+
- Object Vector Studio V2 uses durable object ids shaped as `object.<game>.<name>`, keeps object actions in the Object panel, and rejects old object type/id drift before render.
61+
62+
Expected fail behavior:
63+
64+
- Invalid Object Vector payloads log visible FAIL entries and do not partially render.
65+
66+
## Manual Validation
67+
68+
1. Open `tools/object-vector-studio-v2/index.html`.
69+
2. Import a valid Object Vector Studio V2 payload.
70+
3. Confirm the Object accordion shows inline Object Name and Tag rows and has Add/Rename/Duplicate/Delete at the bottom.
71+
4. Confirm the Objects accordion has no Add/Rename/Duplicate/Delete action row.
72+
5. Toggle Words/Icons and confirm z-action buttons match the shape tool button footprint.
73+
6. Rename an object and confirm JSON Details updates its id to `object.<game>.<renamed-name>`.
74+
7. Try importing a payload with object-level `type` or a bare id such as `ship`; confirm it fails visibly before render.
75+
76+
Expected outcome:
77+
78+
- The Object panel is cleaner, object identity follows the schema naming standard, and old object type payloads are rejected.
79+
80+
## Out Of Scope
81+
82+
- No unrelated tools.
83+
- No sample JSON changes.
84+
- No full samples smoke test.

games/Asteroids/game.manifest.json

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,6 @@
256256
{
257257
"id": "object.asteroids.ship",
258258
"name": "Asteroids Ship",
259-
"type": "ship",
260259
"shapes": [
261260
{
262261
"id": "ship-hull",
@@ -405,7 +404,6 @@
405404
{
406405
"id": "object.asteroids.asteroid.large",
407406
"name": "Large Asteroid",
408-
"type": "object",
409407
"shapes": [
410408
{
411409
"id": "large-asteroid-ridge",
@@ -484,7 +482,6 @@
484482
{
485483
"id": "object.asteroids.asteroid.medium",
486484
"name": "Medium Asteroid",
487-
"type": "object",
488485
"shapes": [
489486
{
490487
"id": "medium-asteroid-ridge",
@@ -559,7 +556,6 @@
559556
{
560557
"id": "object.asteroids.asteroid.small",
561558
"name": "Small Asteroid",
562-
"type": "object",
563559
"shapes": [
564560
{
565561
"id": "small-asteroid-ridge",
@@ -630,7 +626,6 @@
630626
{
631627
"id": "object.asteroids.ufo.large",
632628
"name": "Large UFO",
633-
"type": "enemy",
634629
"shapes": [
635630
{
636631
"id": "large-ufo-body",
@@ -707,7 +702,6 @@
707702
{
708703
"id": "object.asteroids.ufo.small",
709704
"name": "Small UFO",
710-
"type": "enemy",
711705
"shapes": [
712706
{
713707
"id": "small-ufo-body",

src/engine/rendering/ObjectVectorRuntimeAssetService.js

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ function clone(value) {
99
return JSON.parse(JSON.stringify(value));
1010
}
1111

12+
function isObjectIdentityId(value) {
13+
return /^object\.[a-z0-9-]+\.[a-z0-9][a-z0-9.-]*$/.test(String(value || ""));
14+
}
15+
1216
function typeMatches(expectedType, value) {
1317
if (expectedType === "array") {
1418
return Array.isArray(value);
@@ -287,13 +291,9 @@ export class ObjectVectorRuntimeAssetService {
287291
const dependencyGraph = new Map();
288292
const objectsById = new Map();
289293
const objectsByName = new Map();
290-
const objectsByType = new Map();
291294
payload.objects.forEach((object) => {
292295
objectsById.set(object.id, object);
293296
objectsByName.set(object.name.toLowerCase(), object);
294-
const typedObjects = objectsByType.get(object.type) || [];
295-
typedObjects.push(object);
296-
objectsByType.set(object.type, typedObjects);
297297
dependencyGraph.set(object.id, object.baseObjectId ? [object.baseObjectId] : []);
298298
});
299299
(payload.assetLibrary?.assets || []).forEach((asset) => {
@@ -308,20 +308,19 @@ export class ObjectVectorRuntimeAssetService {
308308
dependencyGraph,
309309
objectsById,
310310
objectsByName,
311-
objectsByType,
312311
payload,
313312
sourceLabel
314313
};
315314
}
316315

317-
resolveObject(assetSet, { assetId = "", objectId = "", name = "", type = "" } = {}) {
316+
resolveObject(assetSet, { assetId = "", objectId = "", name = "" } = {}) {
318317
if (!assetSet) {
319318
this.log("FAIL", "Object Vector runtime object resolution failed: no validated asset set is loaded.");
320319
return null;
321320
}
322-
const cacheKey = `${assetSet.sourceLabel}:${assetId || objectId || name || type || "unknown"}`;
321+
const cacheKey = `${assetSet.sourceLabel}:${assetId || objectId || name || "unknown"}`;
323322
if (this.assetCache.has(cacheKey)) {
324-
this.logCacheOnce(cacheKey, `Object Vector runtime cache hit for ${assetId || objectId || name || type}.`);
323+
this.logCacheOnce(cacheKey, `Object Vector runtime cache hit for ${assetId || objectId || name}.`);
325324
return this.assetCache.get(cacheKey);
326325
}
327326

@@ -340,11 +339,8 @@ export class ObjectVectorRuntimeAssetService {
340339
if (!object && name) {
341340
object = assetSet.objectsByName.get(name.toLowerCase()) || null;
342341
}
343-
if (!object && type) {
344-
object = assetSet.objectsByType.get(type)?.[0] || null;
345-
}
346342
if (!object) {
347-
this.log("FAIL", `Object Vector runtime object resolution failed: objectId=${objectId || "none"} name=${name || "none"} type=${type || "none"}.`);
343+
this.log("FAIL", `Object Vector runtime object resolution failed: objectId=${objectId || "none"} name=${name || "none"}.`);
348344
return null;
349345
}
350346

@@ -658,6 +654,9 @@ export class ObjectVectorRuntimeAssetService {
658654
if (!isPlainObject(schema.$defs?.shape) || !Array.isArray(schema.$defs.shape.oneOf)) {
659655
errors.push("Object Vector Studio V2 schema must define shape variants.");
660656
}
657+
if (Object.prototype.hasOwnProperty.call(schema.$defs?.object?.properties || {}, "type")) {
658+
errors.push("Object Vector Studio V2 object schema must not define object type.");
659+
}
661660
}
662661

663662
validatePayload(payload) {
@@ -705,6 +704,9 @@ export class ObjectVectorRuntimeAssetService {
705704
validateInheritanceReferences(payload, errors) {
706705
const objectsById = new Map();
707706
payload.objects.forEach((object, objectIndex) => {
707+
if (!isObjectIdentityId(object.id)) {
708+
errors.push(`root.objects[${objectIndex}].id ${object.id} must follow object.game.name.`);
709+
}
708710
if (objectsById.has(object.id)) {
709711
errors.push(`root.objects[${objectIndex}].id ${object.id} duplicates an existing object id.`);
710712
return;
@@ -884,7 +886,6 @@ export class ObjectVectorRuntimeAssetService {
884886
id: object.id.trim(),
885887
name: object.name.trim(),
886888
tags: Array.isArray(object.tags) ? object.tags.map((tag) => tag.trim()).filter(Boolean) : undefined,
887-
type: object.type.trim().toLowerCase(),
888889
shapes: object.shapes.map((shape) => ({
889890
...shape,
890891
id: shape.id.trim(),

0 commit comments

Comments
 (0)