Overview
The Editor Store is a Zustand-based state management solution that powers the G3Engine editor. It manages the scene graph, object transformations, editor modes, and history (undo/redo) functionality.
Types
ObjectType
type ObjectType = 'box' | 'sphere' | 'cylinder' | 'plane' | 'cone' | 'torus' | 'pointLight' | 'directionalLight' | 'ambientLight' | 'camera'
Vec3
interface Vec3 {
x: number;
y: number;
z: number;
}
MaterialProps
interface MaterialProps {
color: string;
roughness: number;
metalness: number;
emissive?: string;
emissiveIntensity?: number;
opacity?: number;
transparent?: boolean;
}
SceneObject
interface SceneObject {
id: string;
name: string;
type: ObjectType;
position: Vec3;
rotation: Vec3;
scale: Vec3;
material: MaterialProps;
visible: boolean;
lightIntensity?: number;
lightColor?: string;
}
type TransformMode = 'translate' | 'rotate' | 'scale'
Store Hook
useEditorStore
const useEditorStore = create<EditorState>((set, get) => ({...}))
The main store hook that provides access to the editor state and actions.
State Properties
Array of all scene objects in the current scene
ID of the currently selected object, or null if no selection
Whether the scene is in play mode
Current transform gizmo mode: ‘translate’, ‘rotate’, or ‘scale’
Whether Web3 features are enabled in the editor
Array of history snapshots for undo/redo functionality
Current position in the history array
Object CRUD Actions
addObject
addObject(type: ObjectType): void
Adds a new object to the scene with default properties.
The type of object to create
Example:
import { useEditorStore } from '@/store/editorStore';
const { addObject } = useEditorStore();
addObject('box'); // Adds a new cube to the scene
removeObject
removeObject(id: string): void
Removes an object from the scene by its ID.
The ID of the object to remove
Example:
const { removeObject } = useEditorStore();
removeObject('obj-123');
duplicateObject
duplicateObject(id: string): void
Creates a copy of an existing object, offset by 1 unit on the X axis.
The ID of the object to duplicate
Example:
const { duplicateObject } = useEditorStore();
duplicateObject('obj-123'); // Creates "Object Copy" at position + 1 on X
selectObject
selectObject(id: string | null): void
Selects an object in the scene or clears selection if null.
The ID of the object to select, or null to clear selection
Example:
const { selectObject } = useEditorStore();
selectObject('obj-123');
selectObject(null); // Clear selection
updateTransform(id: string, field: 'position' | 'rotation' | 'scale', value: Vec3): void
Updates the position, rotation, or scale of an object.
The ID of the object to transform
field
'position' | 'rotation' | 'scale'
required
The transform property to update
Example:
const { updateTransform } = useEditorStore();
updateTransform('obj-123', 'position', { x: 0, y: 2, z: 0 });
updateMaterial
updateMaterial(id: string, material: Partial<MaterialProps>): void
Updates material properties of an object.
material
Partial<MaterialProps>
required
Partial material properties to merge
Example:
const { updateMaterial } = useEditorStore();
updateMaterial('obj-123', { color: '#ff0000', metalness: 0.8 });
setTransformMode(mode: TransformMode): void
Sets the active transform gizmo mode.
The transform mode to activate
Example:
const { setTransformMode } = useEditorStore();
setTransformMode('rotate');
renameObject
renameObject(id: string, name: string): void
Renames an object in the scene.
The ID of the object to rename
The new name for the object
Example:
const { renameObject } = useEditorStore();
renameObject('obj-123', 'Hero Character');
Editor Actions
togglePlay
Toggles between edit mode and play mode. Clears selection when entering play mode.
Example:
const { togglePlay, isPlaying } = useEditorStore();
togglePlay(); // Switches to play mode
toggleWeb3
Toggles Web3 integration features on/off.
Example:
const { toggleWeb3, web3Enabled } = useEditorStore();
toggleWeb3();
History Actions
pushHistory
Manually creates a snapshot of the current scene state for undo/redo.
Example:
const { pushHistory } = useEditorStore();
pushHistory(); // Saves current state
undo
Reverts to the previous state in history.
Example:
const { undo } = useEditorStore();
undo();
redo
Reapplies the next state in history after an undo.
Example:
const { redo } = useEditorStore();
redo();
Serialization Actions
exportScene
Exports the current scene to a JSON string.
JSON string containing scene version and objects array
Example:
const { exportScene } = useEditorStore();
const json = exportScene();
console.log(json);
// {"version": 1, "objects": [...]}
importScene
importScene(json: string): void
Imports a scene from JSON, replacing the current scene.
JSON string containing scene data with version and objects array
Example:
const { importScene } = useEditorStore();
const sceneData = '{"version": 1, "objects": [...]}';
importScene(sceneData);
Usage Patterns
Reading State
function SceneHierarchy() {
const objects = useEditorStore((state) => state.objects);
const selectedId = useEditorStore((state) => state.selectedObjectId);
return (
<div>
{objects.map(obj => (
<div key={obj.id} className={obj.id === selectedId ? 'selected' : ''}>
{obj.name}
</div>
))}
</div>
);
}
Calling Actions
function AddObjectButton() {
const addObject = useEditorStore((state) => state.addObject);
return (
<button onClick={() => addObject('sphere')}>
Add Sphere
</button>
);
}
Complete CRUD Example
function ObjectEditor() {
const { objects, selectedObjectId, selectObject, updateTransform, removeObject } = useEditorStore();
const selectedObject = objects.find(obj => obj.id === selectedObjectId);
if (!selectedObject) return null;
return (
<div>
<h3>{selectedObject.name}</h3>
<input
type="number"
value={selectedObject.position.y}
onChange={(e) => updateTransform(
selectedObject.id,
'position',
{ ...selectedObject.position, y: parseFloat(e.target.value) }
)}
/>
<button onClick={() => removeObject(selectedObject.id)}>Delete</button>
</div>
);
}