Overview
The Scene Serializer provides utilities for exporting and importing G3Engine scenes to and from JSON format. It includes metadata tracking and downloadable file generation.
Types
SceneExport
interface SceneExport {
version: number;
exportedAt: string;
objects: SceneObject[];
metadata: {
objectCount: number;
hasLights: boolean;
hasWeb3: boolean;
};
}
Represents a complete scene export with version control and metadata.
Functions
exportScene
function exportScene(objects: SceneObject[], web3Enabled: boolean): SceneExport
Exports the current scene state to a serializable JSON format with metadata.
Array of scene objects to export
Whether Web3 features are enabled in the scene
Complete scene export object with version, timestamp, objects, and metadata
Example:
import { exportScene } from '@/lib/sceneSerializer';
import { useEditorStore } from '@/store/editorStore';
function SaveScene() {
const { objects, web3Enabled } = useEditorStore();
const handleExport = () => {
const sceneData = exportScene(objects, web3Enabled);
console.log(sceneData);
// {
// version: 1,
// exportedAt: "2026-03-04T12:00:00.000Z",
// objects: [...],
// metadata: {
// objectCount: 5,
// hasLights: true,
// hasWeb3: false
// }
// }
};
return <button onClick={handleExport}>Export Scene</button>;
}
importScene
function importScene(json: string): SceneObject[] | null
Imports a scene from JSON string and returns the objects array.
JSON string containing the scene export data
Array of scene objects if successful, null if parsing fails or data is invalid
Example:
import { importScene } from '@/lib/sceneSerializer';
function LoadScene() {
const handleImport = (jsonString: string) => {
const objects = importScene(jsonString);
if (objects) {
console.log(`Loaded ${objects.length} objects`);
// Update your store with the objects
} else {
console.error('Failed to import scene');
}
};
return (
<input
type="file"
onChange={(e) => {
const file = e.target.files?.[0];
if (file) {
file.text().then(handleImport);
}
}}
/>
);
}
downloadSceneAsJSON
function downloadSceneAsJSON(objects: SceneObject[], web3Enabled: boolean): void
Exports the scene and triggers a browser download as a JSON file.
Array of scene objects to export
Whether Web3 features are enabled in the scene
Example:
import { downloadSceneAsJSON } from '@/lib/sceneSerializer';
import { useEditorStore } from '@/store/editorStore';
function DownloadButton() {
const { objects, web3Enabled } = useEditorStore();
return (
<button onClick={() => downloadSceneAsJSON(objects, web3Enabled)}>
Download Scene
</button>
);
}
This will download a file named game-scene-{timestamp}.json with the complete scene data.
Usage Patterns
Complete Save/Load Workflow
import { exportScene, importScene, downloadSceneAsJSON } from '@/lib/sceneSerializer';
import { useEditorStore } from '@/store/editorStore';
function SceneManager() {
const { objects, web3Enabled } = useEditorStore();
const { importScene: updateStore } = useEditorStore();
// Save to localStorage
const saveToLocalStorage = () => {
const sceneData = exportScene(objects, web3Enabled);
localStorage.setItem('savedScene', JSON.stringify(sceneData));
};
// Load from localStorage
const loadFromLocalStorage = () => {
const json = localStorage.getItem('savedScene');
if (json) {
const objects = importScene(json);
if (objects) {
updateStore(json); // Use the store's importScene
}
}
};
// Download as file
const handleDownload = () => {
downloadSceneAsJSON(objects, web3Enabled);
};
return (
<div>
<button onClick={saveToLocalStorage}>Save</button>
<button onClick={loadFromLocalStorage}>Load</button>
<button onClick={handleDownload}>Download</button>
</div>
);
}
File Upload Handler
import { importScene } from '@/lib/sceneSerializer';
import { useEditorStore } from '@/store/editorStore';
function SceneUploader() {
const { importScene: updateStore } = useEditorStore();
const handleFileUpload = async (event: React.ChangeEvent<HTMLInputElement>) => {
const file = event.target.files?.[0];
if (!file) return;
try {
const text = await file.text();
const objects = importScene(text);
if (objects) {
updateStore(text);
console.log(`Successfully imported ${objects.length} objects`);
} else {
alert('Invalid scene file');
}
} catch (error) {
console.error('Failed to read file:', error);
alert('Failed to read scene file');
}
};
return (
<input
type="file"
accept=".json"
onChange={handleFileUpload}
/>
);
}
import { exportScene } from '@/lib/sceneSerializer';
import { useEditorStore } from '@/store/editorStore';
function SceneInfo() {
const { objects, web3Enabled } = useEditorStore();
const sceneData = exportScene(objects, web3Enabled);
return (
<div>
<p>Version: {sceneData.version}</p>
<p>Exported: {new Date(sceneData.exportedAt).toLocaleString()}</p>
<p>Objects: {sceneData.metadata.objectCount}</p>
<p>Has Lights: {sceneData.metadata.hasLights ? 'Yes' : 'No'}</p>
<p>Web3 Enabled: {sceneData.metadata.hasWeb3 ? 'Yes' : 'No'}</p>
</div>
);
}
The exported JSON follows this structure:
{
"version": 1,
"exportedAt": "2026-03-04T12:00:00.000Z",
"objects": [
{
"id": "abc-123",
"name": "Cube 1",
"type": "box",
"position": { "x": 0, "y": 0.5, "z": 0 },
"rotation": { "x": 0, "y": 0, "z": 0 },
"scale": { "x": 1, "y": 1, "z": 1 },
"material": {
"color": "#6366f1",
"roughness": 0.4,
"metalness": 0.1
},
"visible": true
}
],
"metadata": {
"objectCount": 1,
"hasLights": false,
"hasWeb3": false
}
}