Skip to content

Commit d0310cf

Browse files
author
DavidQ
committed
Clean up Object Vector Studio V2 manifest shape ownership and remove mixed vector geometry styles - PR_26133_120-object-vector-shapes-ssoT-cleanup
1 parent b62ddc2 commit d0310cf

14 files changed

Lines changed: 239 additions & 342 deletions
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# PR_26133_120-object-vector-shapes-ssoT-cleanup
2+
3+
## Summary
4+
- Renamed the Object Vector Studio V2 manifest map collection from `vectorMaps.vectors` to `vectorMaps.shapes`.
5+
- Removed the active vector-map entry contract that allowed separate `points` and `paths` geometry under `vectorMaps`.
6+
- Kept `objects[].shapes[]` as the single active Asteroids object geometry source for runtime rendering and collision geometry.
7+
8+
## Manifest Cleanup Decisions
9+
- `vectorMaps.vectors` was removed from `games/Asteroids/game.manifest.json`; the document now contains `vectorMaps.shapes`.
10+
- `vectorMaps.shapes` is intentionally empty for Asteroids because the active object geometry lives in `objects[].shapes[]`.
11+
- `vector.asteroids.bullet` was converted into `object.asteroids.bullet` with polygon geometry in `objects[]`.
12+
- The bullet role was added to `vectorMaps.objectVectorRoles` so gameplay render and collision lookup use the same manifest object geometry.
13+
- `vector.asteroids.ui.title` was removed from Object Vector Studio V2 ownership because the Asteroids title is rendered by UI text drawing, not object geometry.
14+
- The `paths[]` vector-map style was removed from the Object Vector Studio V2 schema contract.
15+
- The legacy `vectors.points` vector-map style was removed from the active contract; point geometry now appears only inside Object Vector shape geometry.
16+
- Asteroids manifest map metadata was renamed from `html-js-gaming.asteroids-vector-map` to `html-js-gaming.asteroids-object-vector-shapes`.
17+
18+
## Runtime Cleanup
19+
- Bullet rendering now uses `drawObjectVectorAsset` with the manifest role `bullet`.
20+
- Bullet collision geometry now loads through `requireAsteroidsObjectVectorPoints`.
21+
- Attract screen IDs now resolve through `ASTEROIDS_OBJECT_VECTOR_IDS`.
22+
- Removed runtime hardcoded vector-map lookup helpers and render diagnostics for `vector.asteroids.*`.
23+
- Required Asteroids manifest geometry must resolve through `object-vector-studio-v2.objects`; missing required geometry returns actionable loader errors.
24+
25+
## Validation
26+
- Playwright impacted: Yes, because manifest loading and Object Vector runtime paths changed.
27+
- PASS `node --check` for changed Asteroids runtime files and targeted test files.
28+
- PASS Asteroids manifest JSON parse.
29+
- PASS Object Vector Studio V2 schema JSON parse.
30+
- PASS targeted Asteroids manifest-load and missing-geometry validation.
31+
- PASS targeted Object Vector Studio V2 schema/runtime manifest-load validation.
32+
- PASS `node -e "import('./tests/tools/ObjectVectorStudioV2DeleteCleanup.test.mjs').then(async (m) => { await m.run(); console.log('PASS ObjectVectorStudioV2DeleteCleanup'); })"`
33+
- PASS `node -e "import('./tests/games/AsteroidsValidation.test.mjs').then(async (m) => { await m.run(); console.log('PASS AsteroidsValidation'); })"`
34+
- PASS `node -e "import('./tests/games/AsteroidsVectorTransforms.test.mjs').then(async (m) => { await m.run(); console.log('PASS AsteroidsVectorTransforms'); })"`
35+
- PASS `node -e "import('./tests/games/AsteroidsAssetReferenceAdoption.test.mjs').then(async (m) => { await m.run(); console.log('PASS AsteroidsAssetReferenceAdoption'); })"`
36+
- PASS `node -e "import('./tests/games/AsteroidsPlatformDemo.test.mjs').then(async (m) => { await m.run(); console.log('PASS AsteroidsPlatformDemo'); })"`
37+
- PASS `node -e "import('./tests/games/AsteroidsPresentation.test.mjs').then(async (m) => { await m.run(); console.log('PASS AsteroidsPresentation'); })"`
38+
- PASS `git diff --check`
39+
40+
## Skipped
41+
- Full regression/full samples smoke test skipped per PR instructions.
42+
- `npm run test:workspace-v2` was not run because this PR requested targeted Asteroids/Object Vector validation only.
43+
44+
## Artifacts
45+
- Review diff: `docs/dev/reports/codex_review.diff`
46+
- Changed files report: `docs/dev/reports/codex_changed_files.txt`
47+
- Delta ZIP: `tmp/PR_26133_120-object-vector-shapes-ssoT-cleanup_delta.zip`

games/Asteroids/game.manifest.json

Lines changed: 76 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -213,11 +213,18 @@
213213
"toolId": "object-vector-studio-v2",
214214
"name": "Asteroids Object Vector Assets",
215215
"vectorMaps": {
216-
"schema": "html-js-gaming.asteroids-vector-map",
216+
"schema": "html-js-gaming.asteroids-object-vector-shapes",
217217
"version": 1,
218-
"name": "Asteroids Object Vector Manifest Maps",
218+
"name": "Asteroids Object Vector Shape Roles",
219219
"source": "object-vector-studio-v2",
220220
"objectVectorRoles": {
221+
"bullet": {
222+
"objectId": "object.asteroids.bullet",
223+
"tags": [
224+
"projectile",
225+
"bullet"
226+
]
227+
},
221228
"ship": {
222229
"objectId": "object.asteroids.ship",
223230
"tags": [
@@ -261,54 +268,77 @@
261268
]
262269
}
263270
},
264-
"vectors": [
265-
{
266-
"id": "vector.asteroids.bullet",
267-
"label": "Bullet",
268-
"kind": "polygon",
269-
"usage": [
270-
"gameplay",
271-
"collision",
272-
"projectile"
273-
],
274-
"points": [
275-
{
276-
"x": -2,
277-
"y": -2
278-
},
279-
{
280-
"x": 2,
281-
"y": -2
271+
"shapes": []
272+
},
273+
"objects": [
274+
{
275+
"id": "object.asteroids.bullet",
276+
"name": "Bullet",
277+
"shapes": [
278+
{
279+
"tool": "polygon",
280+
"order": 0,
281+
"visible": true,
282+
"locked": false,
283+
"geometry": {
284+
"points": [
285+
{
286+
"x": -2,
287+
"y": -2
288+
},
289+
{
290+
"x": 2,
291+
"y": -2
292+
},
293+
{
294+
"x": 2,
295+
"y": 2
296+
},
297+
{
298+
"x": -2,
299+
"y": 2
300+
}
301+
]
282302
},
283-
{
284-
"x": 2,
285-
"y": 2
303+
"style": {
304+
"fill": "transparent",
305+
"stroke": "#F8FAFC",
306+
"strokeWidth": 1,
307+
"fillOpacity": 1,
308+
"strokeOpacity": 1
286309
},
287-
{
288-
"x": -2,
289-
"y": 2
310+
"transform": {
311+
"x": 0,
312+
"y": 0,
313+
"rotation": 0,
314+
"scaleX": 1,
315+
"scaleY": 1
290316
}
291-
]
292-
},
293-
{
294-
"id": "vector.asteroids.ui.title",
295-
"label": "Asteroids Title",
296-
"kind": "path",
297-
"usage": [
298-
"splash",
299-
"attract",
300-
"ui"
301-
],
302-
"viewBox": "0 0 220 48",
303-
"paths": [
304-
"M 6 40 L 24 6 L 42 40 Z",
305-
"M 58 40 L 58 8 L 88 8 L 88 18 L 70 18 L 70 22 L 86 22 L 86 32 L 70 32 L 70 40 Z"
306-
],
307-
"points": []
317+
}
318+
],
319+
"states": [
320+
{
321+
"id": "active",
322+
"name": "Active",
323+
"frames": [
324+
{
325+
"id": "frame-1",
326+
"order": 0,
327+
"durationFrames": 1,
328+
"shapeOverrides": []
329+
}
330+
]
331+
}
332+
],
333+
"tags": [
334+
"projectile",
335+
"bullet"
336+
],
337+
"objectOrigin": {
338+
"x": 0,
339+
"y": 0
308340
}
309-
]
310-
},
311-
"objects": [
341+
},
312342
{
313343
"id": "object.asteroids.ship",
314344
"name": "Asteroids Ship",

games/Asteroids/game/AsteroidsAttractAdapter.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ David Quesenberry
55
AsteroidsAttractAdapter.js
66
*/
77
import { clamp } from '../../../src/shared/utils/mathUtils.js';
8-
import { ASTEROIDS_VECTOR_MAP_IDS } from './asteroidsVectorMaps.js';
8+
import { ASTEROIDS_OBJECT_VECTOR_IDS } from './asteroidsVectorMaps.js';
99

1010
function estimateTextWidth(text, fontPx) {
1111
return String(text ?? '').length * (fontPx * 0.62);
@@ -124,7 +124,7 @@ export default class AsteroidsAttractAdapter {
124124
...this.scene.objectVectorRoleOptions('ship'),
125125
elapsedMs: this.scene.objectVectorPlaybackMs,
126126
fps: 12,
127-
objectId: ASTEROIDS_VECTOR_MAP_IDS.attractShip,
127+
objectId: ASTEROIDS_OBJECT_VECTOR_IDS.attractShip,
128128
rotation: -0.28,
129129
scale: 1.1,
130130
stateId: 'idle',
@@ -135,7 +135,7 @@ export default class AsteroidsAttractAdapter {
135135
...this.scene.objectVectorRoleOptions('asteroidLarge'),
136136
elapsedMs: this.scene.objectVectorPlaybackMs,
137137
fps: 12,
138-
objectId: ASTEROIDS_VECTOR_MAP_IDS.attractAsteroid,
138+
objectId: ASTEROIDS_OBJECT_VECTOR_IDS.attractAsteroid,
139139
scale: 0.72,
140140
stateId: 'active',
141141
x: 632,
@@ -213,7 +213,7 @@ export default class AsteroidsAttractAdapter {
213213
...this.scene.objectVectorRoleOptions('ship'),
214214
elapsedMs: this.scene.objectVectorPlaybackMs,
215215
fps: 12,
216-
objectId: ASTEROIDS_VECTOR_MAP_IDS.attractShip,
216+
objectId: ASTEROIDS_OBJECT_VECTOR_IDS.attractShip,
217217
rotation: Math.sin(this.demoTime * 0.9) * 1.2,
218218
stateId: 'idle',
219219
x,
@@ -226,7 +226,7 @@ export default class AsteroidsAttractAdapter {
226226
...this.scene.objectVectorRoleOptions('asteroidLarge'),
227227
elapsedMs: this.scene.objectVectorPlaybackMs,
228228
fps: 12,
229-
objectId: ASTEROIDS_VECTOR_MAP_IDS.attractAsteroid,
229+
objectId: ASTEROIDS_OBJECT_VECTOR_IDS.attractAsteroid,
230230
scale: 0.72,
231231
stateId: 'active',
232232
x: rockX,
@@ -236,7 +236,7 @@ export default class AsteroidsAttractAdapter {
236236
...this.scene.objectVectorRoleOptions('ufoLarge'),
237237
elapsedMs: this.scene.objectVectorPlaybackMs,
238238
fps: 12,
239-
objectId: ASTEROIDS_VECTOR_MAP_IDS.attractUfo,
239+
objectId: ASTEROIDS_OBJECT_VECTOR_IDS.attractUfo,
240240
stateId: 'active',
241241
x: 480 + Math.cos(this.demoTime * 0.43) * 280,
242242
y: 284,

games/Asteroids/game/AsteroidsGameScene.js

Lines changed: 11 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ AsteroidsGameScene.js
66
*/
77
import { AttractModeController, Scene } from '../../../src/engine/scene/index.js';
88
import { ParticleSystem } from '../../../src/engine/fx/index.js';
9-
import { transformPoints } from '../../../src/engine/rendering/index.js';
109
import AsteroidsSession from './AsteroidsSession.js';
1110
import AsteroidsWorld from './AsteroidsWorld.js';
1211
import AsteroidsAudio from '../systems/AsteroidsAudio.js';
@@ -20,10 +19,6 @@ import {
2019
runtimeObjectRoleOptions,
2120
validateAsteroidsRuntimeObjectRoles
2221
} from './asteroidsObjectVectorRoles.js';
23-
import {
24-
ASTEROIDS_VECTOR_MAP_IDS,
25-
getAsteroidsVectorMap
26-
} from './asteroidsVectorMaps.js';
2722
import {
2823
ASTEROIDS_GAME_OVER_AUTO_EXIT_SECONDS, ASTEROIDS_GAME_OVER_RETURN_MODE
2924
} from "../rules/flowRules.js";
@@ -94,10 +89,8 @@ export default class AsteroidsGameScene extends Scene {
9489
this.objectVectorAssets = options.objectVectorAssets || null;
9590
this.objectVectorRuntime = options.objectVectorRuntime || null;
9691
this.vectorMaps = options.vectorMaps || null;
97-
this.vectorMapRenderCounts = {};
98-
this.vectorMapRenderFailures = new Set();
99-
if (!this.vectorMaps?.vectorsById || !this.vectorMaps?.objectVectorRoles) {
100-
const message = 'Asteroids vector map manifest validation failed: vector maps were not loaded from game.manifest.json.';
92+
if (!this.vectorMaps?.objectVectorMapsById || !this.vectorMaps?.objectVectorRoles) {
93+
const message = 'Asteroids Object Vector manifest validation failed: object geometry was not loaded from game.manifest.json.';
10194
console.error(message);
10295
throw new Error(message);
10396
}
@@ -123,6 +116,7 @@ export default class AsteroidsGameScene extends Scene {
123116
this.objectVectorPlaybackMs = 0;
124117
this.objectVectorRenderCounts = {
125118
asteroids: 0,
119+
bullet: 0,
126120
ship: 0,
127121
ufo: 0,
128122
};
@@ -767,18 +761,18 @@ export default class AsteroidsGameScene extends Scene {
767761
}
768762

769763
this.world.bullets.forEach((bullet) => {
770-
this.drawManifestVectorMap(renderer, ASTEROIDS_VECTOR_MAP_IDS.bullet, {
771-
color: '#f8fafc',
772-
lineWidth: 1,
764+
this.drawObjectVectorAsset(renderer, "bullet", {
765+
...this.objectVectorRoleOptions("bullet"),
766+
stateId: "active",
773767
x: bullet.x,
774768
y: bullet.y,
775769
});
776770
});
777771

778772
this.world.ufoBullets.forEach((bullet) => {
779-
this.drawManifestVectorMap(renderer, ASTEROIDS_VECTOR_MAP_IDS.bullet, {
780-
color: '#ffffff',
781-
lineWidth: 1,
773+
this.drawObjectVectorAsset(renderer, "bullet", {
774+
...this.objectVectorRoleOptions("bullet"),
775+
stateId: "active",
782776
x: bullet.x,
783777
y: bullet.y,
784778
});
@@ -889,53 +883,6 @@ export default class AsteroidsGameScene extends Scene {
889883
});
890884
}
891885

892-
drawManifestVectorMap(renderer, vectorMapId, {
893-
color = '#ffffff',
894-
lineWidth = 2,
895-
rotation = 0,
896-
scale = 1,
897-
x = 0,
898-
y = 0,
899-
} = {}) {
900-
const vectorMap = getAsteroidsVectorMap(this.vectorMaps, vectorMapId);
901-
if (!vectorMap || !Array.isArray(vectorMap.points) || vectorMap.points.length < 2) {
902-
this.recordVectorMapRenderFailure(vectorMapId, 'manifest vector map points are unavailable');
903-
return false;
904-
}
905-
const points = transformPoints(vectorMap.points, {
906-
rotation,
907-
scale,
908-
x,
909-
y,
910-
});
911-
if (vectorMap.kind === 'polygon' && typeof renderer.drawPolygon === 'function') {
912-
renderer.drawPolygon(points, {
913-
fillColor: null,
914-
lineWidth,
915-
strokeColor: color,
916-
});
917-
} else {
918-
for (let index = 0; index < points.length - 1; index += 1) {
919-
renderer.drawLine(points[index].x, points[index].y, points[index + 1].x, points[index + 1].y, color, lineWidth);
920-
}
921-
}
922-
this.vectorMapRenderCounts[vectorMapId] = (this.vectorMapRenderCounts[vectorMapId] || 0) + 1;
923-
return true;
924-
}
925-
926-
recordVectorMapRenderFailure(vectorMapId, reason) {
927-
const failureKey = `${vectorMapId || 'unknown'}:${reason}`;
928-
if (this.vectorMapRenderFailures.has(failureKey)) {
929-
return;
930-
}
931-
this.vectorMapRenderFailures.add(failureKey);
932-
this.pushDebugEvent('ASTEROIDS_VECTOR_MAP_RENDER_FAIL', {
933-
reason,
934-
vectorMapId: vectorMapId || 'unknown',
935-
});
936-
console.error(`FAIL Asteroids manifest vector map render blocked for ${vectorMapId || 'unknown'}: ${reason}.`);
937-
}
938-
939886
drawObjectVectorAsset(renderer, renderKey, options) {
940887
if (!this.objectVectorRuntime || !this.objectVectorAssets) {
941888
this.recordObjectVectorRenderFailure(renderKey, options.assetId || options.objectId || options.runtimeRole, "validated Object Vector runtime assets are not loaded");
@@ -971,19 +918,10 @@ export default class AsteroidsGameScene extends Scene {
971918
assetCount: this.objectVectorAssets?.objectsById?.size || 0,
972919
loaded: Boolean(this.objectVectorAssets),
973920
objectCount: this.objectVectorAssets?.objectsById?.size || 0,
974-
objectVectorMapIds: this.vectorMaps?.objectVectorMaps?.map((object) => object.id) || [],
921+
objectVectorObjectIds: this.vectorMaps?.objectVectorMaps?.map((object) => object.id) || [],
975922
runtimeObjectsValid: Boolean(this.objectVectorRuntimeObjectValidation?.ok),
976923
renderCounts: { ...this.objectVectorRenderCounts },
977-
vectorMapIds: this.vectorMaps?.vectors?.map((vector) => vector.id) || [],
978-
vectorMapRenderCounts: { ...this.vectorMapRenderCounts },
979-
vectorMapUsageCounts: { ...(this.vectorMaps?.usageCounts || {}) },
980-
vectorMapsLoaded: Boolean(this.vectorMaps?.vectorsById),
981-
};
982-
globalThis.__asteroidsVectorMaps = {
983-
ids: this.vectorMaps?.vectors?.map((vector) => vector.id) || [],
984-
loaded: Boolean(this.vectorMaps?.vectorsById),
985-
renderCounts: { ...this.vectorMapRenderCounts },
986-
usageCounts: { ...(this.vectorMaps?.usageCounts || {}) },
924+
sharedShapeCount: this.vectorMaps?.shapes?.length || 0,
987925
};
988926
} catch {
989927
// Ignore diagnostics assignment in restricted runtimes.

0 commit comments

Comments
 (0)