Skip to content

Commit d2e4691

Browse files
author
DavidQ
committed
Reviewed and fixed why it wasn’t loading:
Demo runtime was reading toolFormattedParallax.export.js, not the JSON file. imageSource paths were relative in a way that can fail in the Parallax Editor context.
1 parent a1d70d3 commit d2e4691

4 files changed

Lines changed: 278 additions & 47 deletions

File tree

samples/Phase 12 - Demo Games/Demo 1208 - Tool Formatted Tiles Parallax/ToolFormattedTilesParallaxScene.js

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { clamp } from '../../../engine/utils/index.js';
1010
import { Camera2D, worldRectToScreen } from '../../../engine/camera/index.js';
1111
import { Tilemap, resolveRectVsTilemap } from '../../../engine/tilemap/index.js';
1212
import tileMapToolExport from './data/toolFormattedTileMap.export.js';
13-
import parallaxToolExport from './data/toolFormattedParallax.export.js';
13+
import fallbackParallaxToolExport from './data/toolFormattedParallax.export.js';
1414

1515
const theme = new Theme(ThemeTokens);
1616

@@ -54,7 +54,8 @@ export default class ToolFormattedTilesParallaxScene extends Scene {
5454
try {
5555
this.applyTileExportData(tileMapToolExport);
5656
const tileAssetCount = await this.loadTileAssets(extractTileEntries(tileMapToolExport));
57-
this.parallaxLayers = await this.loadParallaxAssets(extractParallaxLayers(parallaxToolExport));
57+
const parallaxDocument = await loadParallaxDocument(fallbackParallaxToolExport);
58+
this.parallaxLayers = await this.loadParallaxAssets(extractParallaxLayers(parallaxDocument));
5859

5960
this.contentLoaded = tileAssetCount > 0 && this.parallaxLayers.length === 3;
6061
this.contentStatus = `Loaded ${tileAssetCount} PNG atlas image and ${this.parallaxLayers.length} SVG parallax layers.`;
@@ -183,7 +184,14 @@ export default class ToolFormattedTilesParallaxScene extends Scene {
183184
}
184185

185186
const loadOperations = layerDefinitions.map(async (layerDefinition, index) => {
186-
const image = await loadImageFromRelativePath(layerDefinition.asset, import.meta.url);
187+
const assetPath = layerDefinition.asset
188+
|| layerDefinition.imageDataUrl
189+
|| layerDefinition.imageSource;
190+
if (!assetPath) {
191+
throw new Error(`Parallax layer ${layerDefinition.id || index} missing image source.`);
192+
}
193+
194+
const image = await loadImageFromRelativePath(assetPath, import.meta.url);
187195
const sourceWidth = Number(layerDefinition.sourceWidth)
188196
|| image.naturalWidth
189197
|| image.width
@@ -199,8 +207,8 @@ export default class ToolFormattedTilesParallaxScene extends Scene {
199207
image,
200208
sourceWidth,
201209
sourceHeight,
202-
scrollFactor: Number(layerDefinition.scrollFactor) || [0.2, 0.45, 0.7][index],
203-
y: Number(layerDefinition.y) || 0,
210+
scrollFactor: Number(layerDefinition.scrollFactor ?? layerDefinition.scrollFactorX) || [0.2, 0.45, 0.7][index],
211+
y: Number(layerDefinition.y ?? layerDefinition.offsetY) || 0,
204212
height: Number(layerDefinition.height) || 90,
205213
segmentWidth: Number(layerDefinition.segmentWidth) || sourceWidth || 1024,
206214
};
@@ -511,7 +519,27 @@ function extractTileEntries(tileExport) {
511519
}
512520

513521
function extractParallaxLayers(parallaxExport) {
514-
return Array.isArray(parallaxExport?.layers) ? parallaxExport.layers : [];
522+
if (!Array.isArray(parallaxExport?.layers)) {
523+
return [];
524+
}
525+
526+
if (parallaxExport?.schema === 'toolbox.parallax/1') {
527+
const normalized = parallaxExport.layers
528+
.filter((layer) => layer?.visible !== false)
529+
.sort((a, b) => (Number(a?.drawOrder) || 0) - (Number(b?.drawOrder) || 0))
530+
.map((layer) => ({
531+
id: layer.id,
532+
imageSource: layer.imageSource,
533+
imageDataUrl: layer.imageDataUrl,
534+
scrollFactorX: Number(layer.scrollFactorX),
535+
offsetY: Number(layer.offsetY) || 0,
536+
opacity: Number(layer.opacity),
537+
segmentWidth: Number(layer.segmentWidth) || undefined,
538+
}));
539+
return normalized;
540+
}
541+
542+
return parallaxExport.layers;
515543
}
516544

517545
function placePlatform(cells, row, startCol, endCol, tileId) {
@@ -520,6 +548,20 @@ function placePlatform(cells, row, startCol, endCol, tileId) {
520548
}
521549
}
522550

551+
async function loadParallaxDocument(fallbackDocument) {
552+
try {
553+
const response = await fetch(new URL('./data/toolFormattedParallax.json', import.meta.url), {
554+
cache: 'no-store',
555+
});
556+
if (!response.ok) {
557+
throw new Error(`HTTP ${response.status}`);
558+
}
559+
return await response.json();
560+
} catch (_error) {
561+
return fallbackDocument;
562+
}
563+
}
564+
523565
function getPrimaryTileLayer(tileExport) {
524566
if (!Array.isArray(tileExport?.layers)) {
525567
return null;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
{
2+
"schema": "toolbox.parallax/1",
3+
"version": 1,
4+
"companionEditor": "ParallaxEditor",
5+
"map": {
6+
"name": "mario-style-learning-level",
7+
"width": 64,
8+
"height": 16,
9+
"tileSize": 24,
10+
"pixelWidth": 1536,
11+
"pixelHeight": 384
12+
},
13+
"layers": [
14+
{
15+
"id": "mario-sky",
16+
"name": "Mario Sky",
17+
"drawOrder": 0,
18+
"imageSource": "./samples/mario_style_sky.svg",
19+
"imageDataUrl": "",
20+
"scrollFactorX": 0.08,
21+
"scrollFactorY": 0.03,
22+
"offsetX": 0,
23+
"offsetY": 0,
24+
"repeatX": true,
25+
"repeatY": false,
26+
"wrapMode": "wrap",
27+
"opacity": 1,
28+
"visible": true
29+
},
30+
{
31+
"id": "mario-clouds",
32+
"name": "Mario Clouds",
33+
"drawOrder": 1,
34+
"imageSource": "./samples/mario_style_clouds.svg",
35+
"imageDataUrl": "",
36+
"scrollFactorX": 0.18,
37+
"scrollFactorY": 0.06,
38+
"offsetX": 0,
39+
"offsetY": 36,
40+
"repeatX": true,
41+
"repeatY": false,
42+
"wrapMode": "wrap",
43+
"opacity": 0.95,
44+
"visible": true
45+
},
46+
{
47+
"id": "mario-mountains-tall",
48+
"name": "Mario Mountains Tall",
49+
"drawOrder": 2,
50+
"imageSource": "./samples/mario_style_mountains.svg",
51+
"imageDataUrl": "",
52+
"scrollFactorX": 0.34,
53+
"scrollFactorY": 0.18,
54+
"offsetX": 0,
55+
"offsetY": 178,
56+
"repeatX": true,
57+
"repeatY": false,
58+
"wrapMode": "wrap",
59+
"opacity": 0.96,
60+
"visible": true
61+
},
62+
{
63+
"id": "mario-mountains-short",
64+
"name": "Mario Mountains Short",
65+
"drawOrder": 3,
66+
"imageSource": "./samples/mario_style_hills.svg",
67+
"imageDataUrl": "",
68+
"scrollFactorX": 0.58,
69+
"scrollFactorY": 0.22,
70+
"offsetX": 0,
71+
"offsetY": 214,
72+
"repeatX": true,
73+
"repeatY": false,
74+
"wrapMode": "wrap",
75+
"opacity": 0.96,
76+
"visible": true
77+
},
78+
{
79+
"id": "mario-hero-proxy",
80+
"name": "Mario Hero Proxy",
81+
"drawOrder": 4,
82+
"imageSource": "./samples/images/hero-proxy.svg",
83+
"imageDataUrl": "",
84+
"scrollFactorX": 1,
85+
"scrollFactorY": 1,
86+
"offsetX": 720,
87+
"offsetY": 258,
88+
"repeatX": false,
89+
"repeatY": false,
90+
"wrapMode": "clamp",
91+
"opacity": 1,
92+
"visible": true
93+
},
94+
{
95+
"id": "mario-foreground-trees",
96+
"name": "Mario Foreground Trees",
97+
"drawOrder": 5,
98+
"imageSource": "./samples/mario_style_bushes_foreground.svg",
99+
"imageDataUrl": "",
100+
"scrollFactorX": 1.08,
101+
"scrollFactorY": 0.36,
102+
"offsetX": 84,
103+
"offsetY": 182,
104+
"repeatX": true,
105+
"repeatY": false,
106+
"wrapMode": "wrap",
107+
"opacity": 0.96,
108+
"visible": true
109+
}
110+
],
111+
"metadata": {
112+
"createdAt": "2026-03-30T00:00:00.000Z",
113+
"updatedAt": "2026-03-31T23:14:30.335Z",
114+
"source": "parallax-editor-companion"
115+
}
116+
}

samples/Phase 12 - Demo Games/Demo 1208 - Tool Formatted Tiles Parallax/data/toolFormattedParallax.export.js

Lines changed: 57 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,68 @@
1-
export default {
2-
"tool": "Parallax Editor",
3-
"formatVersion": 2,
4-
"exportProfile": "demo1208-parallax-correction",
1+
export default {
2+
"schema": "toolbox.parallax/1",
3+
"version": 1,
4+
"companionEditor": "ParallaxEditor",
5+
"map": {
6+
"name": "demo1208-tool-formatted-parallax-world",
7+
"width": 72,
8+
"height": 18,
9+
"tileSize": 48,
10+
"pixelWidth": 3456,
11+
"pixelHeight": 864
12+
},
513
"layers": [
614
{
715
"id": "far-mountains",
8-
"asset": "./assets/parallax/layer-far-mountains.svg",
9-
"scrollFactor": 0.2,
10-
"y": 6,
11-
"height": 172,
12-
"segmentWidth": 1024
16+
"name": "Far Mountains",
17+
"drawOrder": 0,
18+
"imageSource": "/samples/Phase%2012%20-%20Demo%20Games/Demo%201208%20-%20Tool%20Formatted%20Tiles%20Parallax/assets/parallax/layer-far-mountains.svg",
19+
"imageDataUrl": "",
20+
"scrollFactorX": 0.2,
21+
"scrollFactorY": 0.05,
22+
"offsetX": 0,
23+
"offsetY": 6,
24+
"repeatX": true,
25+
"repeatY": false,
26+
"wrapMode": "wrap",
27+
"opacity": 1,
28+
"visible": true
1329
},
1430
{
1531
"id": "mid-cliffs",
16-
"asset": "./assets/parallax/layer-mid-cliffs.svg",
17-
"scrollFactor": 0.45,
18-
"y": 36,
19-
"height": 198,
20-
"segmentWidth": 1024
32+
"name": "Mid Cliffs",
33+
"drawOrder": 1,
34+
"imageSource": "/samples/Phase%2012%20-%20Demo%20Games/Demo%201208%20-%20Tool%20Formatted%20Tiles%20Parallax/assets/parallax/layer-mid-cliffs.svg",
35+
"imageDataUrl": "",
36+
"scrollFactorX": 0.45,
37+
"scrollFactorY": 0.16,
38+
"offsetX": 0,
39+
"offsetY": 36,
40+
"repeatX": true,
41+
"repeatY": false,
42+
"wrapMode": "wrap",
43+
"opacity": 0.96,
44+
"visible": true
2145
},
2246
{
2347
"id": "near-forest",
24-
"asset": "./assets/parallax/layer-near-forest.svg",
25-
"scrollFactor": 0.7,
26-
"y": 72,
27-
"height": 214,
28-
"segmentWidth": 1024
48+
"name": "Near Forest",
49+
"drawOrder": 2,
50+
"imageSource": "/samples/Phase%2012%20-%20Demo%20Games/Demo%201208%20-%20Tool%20Formatted%20Tiles%20Parallax/assets/parallax/layer-near-forest.svg",
51+
"imageDataUrl": "",
52+
"scrollFactorX": 0.7,
53+
"scrollFactorY": 0.28,
54+
"offsetX": 0,
55+
"offsetY": 72,
56+
"repeatX": true,
57+
"repeatY": false,
58+
"wrapMode": "wrap",
59+
"opacity": 0.95,
60+
"visible": true
2961
}
30-
]
62+
],
63+
"metadata": {
64+
"createdAt": "2026-03-31T23:16:18.660Z",
65+
"updatedAt": "2026-03-31T23:16:18.660Z",
66+
"source": "parallax-editor-companion"
67+
}
3168
};
32-
Lines changed: 57 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,68 @@
1-
{
2-
"tool": "Parallax Editor",
3-
"formatVersion": 2,
4-
"exportProfile": "demo1208-parallax-correction",
1+
{
2+
"schema": "toolbox.parallax/1",
3+
"version": 1,
4+
"companionEditor": "ParallaxEditor",
5+
"map": {
6+
"name": "demo1208-tool-formatted-parallax-world",
7+
"width": 72,
8+
"height": 18,
9+
"tileSize": 48,
10+
"pixelWidth": 3456,
11+
"pixelHeight": 864
12+
},
513
"layers": [
614
{
715
"id": "far-mountains",
8-
"asset": "./assets/parallax/layer-far-mountains.svg",
9-
"scrollFactor": 0.2,
10-
"y": 6,
11-
"height": 172,
12-
"segmentWidth": 1024
16+
"name": "Far Mountains",
17+
"drawOrder": 0,
18+
"imageSource": "/samples/Phase%2012%20-%20Demo%20Games/Demo%201208%20-%20Tool%20Formatted%20Tiles%20Parallax/assets/parallax/layer-far-mountains.svg",
19+
"imageDataUrl": "",
20+
"scrollFactorX": 0.2,
21+
"scrollFactorY": 0.05,
22+
"offsetX": 0,
23+
"offsetY": 6,
24+
"repeatX": true,
25+
"repeatY": false,
26+
"wrapMode": "wrap",
27+
"opacity": 1,
28+
"visible": true
1329
},
1430
{
1531
"id": "mid-cliffs",
16-
"asset": "./assets/parallax/layer-mid-cliffs.svg",
17-
"scrollFactor": 0.45,
18-
"y": 36,
19-
"height": 198,
20-
"segmentWidth": 1024
32+
"name": "Mid Cliffs",
33+
"drawOrder": 1,
34+
"imageSource": "/samples/Phase%2012%20-%20Demo%20Games/Demo%201208%20-%20Tool%20Formatted%20Tiles%20Parallax/assets/parallax/layer-mid-cliffs.svg",
35+
"imageDataUrl": "",
36+
"scrollFactorX": 0.45,
37+
"scrollFactorY": 0.16,
38+
"offsetX": 0,
39+
"offsetY": 36,
40+
"repeatX": true,
41+
"repeatY": false,
42+
"wrapMode": "wrap",
43+
"opacity": 0.96,
44+
"visible": true
2145
},
2246
{
2347
"id": "near-forest",
24-
"asset": "./assets/parallax/layer-near-forest.svg",
25-
"scrollFactor": 0.7,
26-
"y": 72,
27-
"height": 214,
28-
"segmentWidth": 1024
48+
"name": "Near Forest",
49+
"drawOrder": 2,
50+
"imageSource": "/samples/Phase%2012%20-%20Demo%20Games/Demo%201208%20-%20Tool%20Formatted%20Tiles%20Parallax/assets/parallax/layer-near-forest.svg",
51+
"imageDataUrl": "",
52+
"scrollFactorX": 0.7,
53+
"scrollFactorY": 0.28,
54+
"offsetX": 0,
55+
"offsetY": 72,
56+
"repeatX": true,
57+
"repeatY": false,
58+
"wrapMode": "wrap",
59+
"opacity": 0.95,
60+
"visible": true
2961
}
30-
]
62+
],
63+
"metadata": {
64+
"createdAt": "2026-03-31T23:16:18.660Z",
65+
"updatedAt": "2026-03-31T23:16:18.660Z",
66+
"source": "parallax-editor-companion"
67+
}
3168
}

0 commit comments

Comments
 (0)