Opal Graph Explorer
Status: Core shipped in the workbench Graph dock (
src/game/graph-explorer/, wired fromsrc/app/phases/graph-explorer.js). Modes: Scene Hierarchy, Event Map, Prefab Anatomy, Asset Dependencies, Component Map, Runtime Trace (+ internal event-bus demo). Live refresh and d3-force layout are in place. Remaining polish: animated trace replay, prefab component inspector focus, richer contextual entry points.
Layer:editor— must not be imported byruntime(see Architecture).
Related: The assets panel graph view (src/game/assets/editor/asset-graph-view.js) andreference-scan.jsare an earlier asset-dependency slice; prefer the shared Graph Explorer adapters over growing a second graph stack.
Note: Sections below retain design-plan detail used while building the feature. Prefer the status callout and the live dock UI when they disagree with older milestone prose.
Overview
The Graph Explorer is a developer-facing visualization system for inspecting Opal project structure, scene data, prefabs, component relationships, events, asset dependencies, and runtime execution traces through interactive node graphs.
The goal is not to replace the existing inspectors, hierarchy panels, or Object Flow editor. The Graph Explorer is an understanding layer: it helps developers see how systems relate, why something is happening, and what will break if a file, object, prefab, component, asset, or event changes.
This feature turns Opal’s internal data into navigable visual maps.
Goals
- Help developers understand complex projects quickly.
- Make prefabs, components, events, and assets inspectable as relationships, not just lists.
- Provide teaching tools for sample games such as Garden Defense.
- Support debugging by showing runtime traces and event flow.
- Reuse a shared graph view model across many data sources.
- Keep graph visualization separate from authored game/runtime data.
- Avoid making D3 the application architecture; use it only for layout, transforms, and interaction primitives where useful.
Non-Goals
- Do not replace Object Flow’s editable node graph.
- Do not make every graph editable in v1.
- Do not serialize graph explorer UI state into scene or prefab data, except optional editor preferences.
- Do not introduce runtime dependencies from game logic into editor-only graph visualization code.
- Do not require all graph modes to ship at once.
Design Principle
The Graph Explorer should answer five questions:
- What is this?
- What owns it?
- What does it depend on?
- What depends on it?
- What happens when it runs?
Every graph mode should be judged against those questions.
Core Concept
The Graph Explorer is built around one shared graph document shape:
{
id: "graph-explorer-view",
title: "Garden Slime Prefab",
mode: "prefab-anatomy",
nodes: [
{
id: "slime-prefab",
type: "prefab",
label: "Garden Slime",
subtitle: "Prefab",
group: "prefab",
icon: "box",
badges: [
{ label: "4 components", tone: "info" },
{ label: "2 events", tone: "event" }
],
status: "ok",
data: {}
}
],
edges: [
{
id: "edge-health-died-flow",
from: "health",
to: "object-flow",
type: "emits",
label: "health/died",
direction: "forward",
status: "ok",
data: {}
}
],
groups: [
{
id: "components",
label: "Components",
type: "section"
}
],
meta: {
sourceKind: "prefab",
sourceId: "prefab_garden_slime"
}
}Each graph mode is an adapter that converts an existing Opal data source into this shared shape.
Graph Modes
1. File Tree / Architecture Graph
Purpose
Visualize source files, folders, architecture layers, and import relationships.
Primary Users
Engine contributors and maintainers.
Data Sources
- Source tree
- Architecture layer classifier (
architecture-boundaries.test.jslayer sets) - Relative imports
- Test coverage metadata, if available later
- Git/churn metadata, optional later
Layouts
- Collapsible tree for folder structure
- Layered dependency graph for imports
- Force graph for highly connected modules
- Treemap or packed circles for file size/churn later
Nodes
- Folder
- File
- Architecture layer
- Test file
- Barrel/export file
Edges
- Contains
- Imports
- Re-exports
- Violates boundary
- Tested by
Useful Badges
- Layer: core, runtime, behavior, project, editor, app
- Import count
- Imported-by count
- Test coverage
- Boundary violation
- Barrel file
Example
src/game/flow/catalog.js
Layer: behavior
Imports: runtime, core, behavior
Imported by: interaction, rules, tests
Risk: high centralityV1 Scope
- Folder tree
- Layer coloring
- Import edges
- Boundary violation highlighting
- Click file to show details
2. Scene Hierarchy Graph
Purpose
Show scene objects spatially as a hierarchy and expose object status at a glance.
Primary Users
Game creators and demo learners.
Data Sources
scene-graph.jscustomObjectshierarchyLayerKindhierarchyLayerBadges- Selected object/component metadata
Layouts
- Top-down tree
- Radial tree
- Compact hierarchy graph
Nodes
- Scene root
- Game object
- Sprite
- Camera
- Trigger
- UI root
- Prefab instance
Edges
- Parent/child
- Optional object reference
- Optional event link
- Optional constraint/link relationship
Useful Badges
- Children
- Components
- Tap action
- Hidden
- Locked
- Prefab instance
- Has Object Flow
- Has diagnostics
V1 Scope
- Read-only hierarchy graph
- Click object to select it in scene
- Highlight current selection
- Show object details side panel
- Filter by object type/status
3. Prefab Anatomy Graph
Purpose
Show what a prefab contains: objects, components, flows, events, asset references, and overrides.
Primary Users
Developers studying demo prefabs and creators building reusable gameplay objects.
Data Sources
- Prefab record
- Prefab instance data
ComponentHostserialized components- Object Flow graphs
- Asset references (
reference-scan.js, prefab/scene serializers) - Override detector
Layout
A structured left-to-right graph:
Prefab Root
→ Objects
→ Components
→ Flow Graphs
→ Events Out
→ Asset ReferencesNodes
- Prefab root
- Object
- Component
- Component field
- Object Flow graph
- Event
- Asset reference
- Override
- Child prefab instance
Edges
- Contains
- Owns component
- Uses asset
- Emits event
- Listens to event
- Overrides field
- Spawns prefab
Example: Garden Slime
Garden Slime Prefab
Components:
SpriteRenderer
Health: hp=3
Tappable
Object Flow
Flow:
On Tap → Health.damage(1)
Health.died → Spawn Coin → Emit slime_defeated → Destroy Self
Asset refs:
slime_sprite_sheet
slime_pop_audio
coin_prefabV1 Scope
- Read-only prefab anatomy view
- Component cards
- Asset reference cards
- Flow summary block
- Event inputs/outputs
- Click node to open inspector / Object Flow / prefab asset
4. Event Bus Map
Purpose
Show who emits and listens to events across the scene, prefabs, components, and Object Flow.
Primary Users
Everyone. This is likely the highest-value graph mode.
Data Sources
- Rules / Object Flow graphs
- Component event descriptors
- Custom event catalog
- Scene Flow
- Prefab graphs
- Runtime trace later
Layout
Emitters on the left, events in the center, listeners on the right.
[Emitter] → [Event Key] → [Listener]Nodes
- Event key
- Component event
- Custom event
- Scene event
- Emitter object/prefab
- Listener object/prefab
- Flow graph
- Payload field
Edges
- Emits
- Listens
- Reads payload field
- Writes payload field
- Forwards event
Useful Badges
- Scope: local, scene, global, targeted
- Payload fields
- Emitter count
- Listener count
- No listeners
- No emitters
- Payload mismatch
- Deprecated key
Example: Garden Defense
slime_defeated
emitted by:
Garden Slime / Health.died
listened by:
Scene Flow / Add Score
Hero / Say Milestone
Nest Spawner / AccelerateV1 Scope
- Scan rules and component events
- Show emitters/listeners
- Show custom event scopes
- Warn for event keys with no listeners
- Warn for listeners with no emitters
- Click event to filter Object Flow list
5. Flow Summary Graph
Purpose
Show high-level logic for a flow graph without exposing every editable node detail.
Primary Users
Learners, debuggers, and creators navigating large graphs.
Data Sources
- Object Flow graph
- Scene Flow graph
- Flow node registry
- Compiler diagnostics
Layout
Layered DAG:
Trigger → Conditions → Actions → Events OutNodes
- Trigger
- Condition
- Action
- Event out
- Data getter/setter
- Broken node
- Comment/group
Edges
- Execution path
- Data path
- True/false branch
- Event output
V1 Scope
- Read-only summary
- Collapse chains
- Show broken nodes
- Show component calls
- Show event emits
- Click to open actual Object Flow editor
6. Component Relationship Graph
Purpose
Visualize how components depend on, call, emit to, or read from other components.
Primary Users
Engine contributors and advanced creators.
Data Sources
- Component registry
- Component definitions
requires- Actions
- Conditions
- Events
- Field metadata
- Optional static hints for component calls
Layout
Force graph or hub-and-spoke per selected component.
Nodes
- Component type
- Action
- Condition
- Event
- Field
- Required component
- Interface/capability, later
Edges
- Requires
- Calls
- Reads
- Writes
- Emits
- Optional dependency
Example: Hazard
Hazard
requires Collider2D
calls Health.damage
optionally calls SpriteRenderer.vanish
reads Team.name
emits hazard/hurtV1 Scope
- Requires graph
- Events/actions/conditions display
- Component detail side panel
- Later: static call graph hints
7. Asset Dependency Graph
Purpose
Show how scenes, prefabs, sprites, audio, UI, and other assets reference each other.
Primary Users
Creators preparing exports and developers debugging missing assets.
Data Sources
- Asset library
- Scene records
- Prefab records
reference-scan.js(forward/reverse index)- SpriteRenderer fields
- Audio action references
- UI document asset references
Layout
Dependency graph or tree grouped by asset type.
Nodes
- Scene
- Prefab
- Image
- Audio
- UI document
- Script
- Folder
- Missing reference
- Unused asset
Edges
- Uses
- Contains
- Spawns
- References
- Missing
Useful Questions
- What will this scene export?
- Which assets are unused?
- Which assets are missing?
- Which prefabs depend on this sprite?
- What uses this audio file?
V1 Scope
- Scene → asset references
- Prefab → asset references
- Missing asset warnings
- Unused asset list
Current partial implementation
The assets panel graph view (src/game/assets/editor/asset-graph-view.js) already renders a filtered asset dependency graph inside the dock. When Graph Explorer lands, reuse reference-scan.js for indexing and replace the bespoke renderer with the shared graph explorer stack.
8. Prefab Variant / Inheritance Graph
Purpose
Show prefab family trees and field overrides.
Primary Users
Advanced prefab creators.
Data Sources
- Prefab records
- Variant/parent metadata
- Override detection
Layout
Tree or layered inheritance graph.
Nodes
- Base prefab
- Variant prefab
- Override group
- Added component
- Removed component
- Overridden field
Edges
- Inherits from
- Overrides
- Adds
- Removes
Example
Base Slime
├─ Berry Slime
│ overrides SpriteRenderer.sprite
│ overrides Loot.points = 2
└─ Thorn Slime
adds Hazard
overrides Health.hp = 5V1 Scope
Defer until prefab variants are mature.
9. Runtime Trace Graph
Purpose
Show what executed during play.
Primary Users
Debuggers and learners.
Data Sources
- Runtime trace store
- Compiled FlowProgram source maps
- Event dispatch logs
- Component event emits
- Action execution results
Layout
Execution path graph with animated pulses or counts.
Nodes
- Trigger
- Flow node
- Component action
- Event
- Object
- Error
Edges
- Executed next
- Emitted event
- Called component
- Spawned prefab
- Destroyed object
Useful Badges
- Fired count
- Last fired time
- Last input value
- Error count
- Duration
- Object id
Example
On Tap
12x → Health.damage
4x → Health.died
4x → Spawn Coin
4x → Add Score
4x → Emit slime_defeated
4x → Destroy SelfV1 Scope
Defer until trace/source-map systems are stable, but design the graph model so this mode can plug in later.
UI Design
Main Entry Point
Add a new editor tab:
Graph ExplorerInside it:
View:
Scene Hierarchy
Prefab Anatomy
Event Map
Flow Summary
Component Relationships
Asset Dependencies
ArchitectureContextual Entry Points
Right-click actions:
Object → View object graph
Prefab asset → View prefab anatomy
Event key → Show event map
Component → Show component relationships
Scene → Show scene hierarchy graph
Asset → Show dependencies
File/dev mode → Show import graphLayout
The Graph Explorer should use a three-region layout:
┌─────────────────────────────────────────────┐
│ Toolbar: mode, search, filters, layout │
├───────────────┬─────────────────────────────┤
│ Filters/Tree │ Graph canvas │
│ │ │
├───────────────┴───────────────┬─────────────┤
│ Details panel / selection info │ Warnings │
└───────────────────────────────┴─────────────┘Interactions
Required:
- Pan
- Zoom
- Fit to view
- Search nodes
- Select node
- Select edge
- Expand/collapse
- Filter by type
- Focus neighbors
- Open source inspector/editor
Later:
- Pin nodes
- Save graph bookmarks
- Compare two graph states
- Animate runtime trace
- Export graph image
Technical Architecture
Folder Proposal
src/game/graph-explorer/
graph-model.js
graph-renderer.js
graph-layouts.js
graph-interactions.js
graph-filters.js
graph-details-panel.js
adapters/
scene-hierarchy-graph.js
prefab-anatomy-graph.js
event-bus-graph.js
flow-summary-graph.js
component-relationship-graph.js
asset-dependency-graph.js
architecture-graph.js
styles/
graph-explorer.css
graph-explorer.test.jsClassify as editor in architecture-boundaries.test.js.
Alternative colocation:
src/game/scene-editor/graph-explorer/A top-level graph-explorer editor feature is clearer because it visualizes many systems.
Shared Graph Model
Pure model module:
export function createGraphExplorerDocument({
id,
title,
mode,
nodes = [],
edges = [],
groups = [],
meta = {},
}) {
return normalizeGraphExplorerDocument({ id, title, mode, nodes, edges, groups, meta });
}Node fields:
{
id,
type,
label,
subtitle,
group,
icon,
badges,
status,
position,
collapsed,
data
}Edge fields:
{
id,
from,
to,
type,
label,
direction,
status,
data
}Status values:
"ok"
"warning"
"error"
"missing"
"disabled"
"runtime"Edge types:
"contains"
"imports"
"uses"
"emits"
"listens"
"calls"
"reads"
"writes"
"requires"
"spawns"
"overrides"
"executes"Adapters
Each adapter is pure:
export function buildPrefabAnatomyGraph(prefab, context) {
return createGraphExplorerDocument({
id: `prefab:${prefab.id}`,
title: prefab.name,
mode: "prefab-anatomy",
nodes,
edges,
groups,
meta,
});
}Adapters must not touch DOM.
Renderer
DOM/SVG view patterned after the Object Flow DOM workspace (interaction/dom-workspace.js, dom-workspace-viewport.js, dom-workspace-interactions.js):
- DOM cards for nodes
- SVG paths for edges
- D3 for layout helpers and zoom/pan (
src/vendor/d3-zoom.jstoday; add narrow modules only as needed) - Opal-owned selection/details state
- No runtime/game dependency on D3
The assets panel asset-graph-view.js is a prototype of this renderer pattern but is not yet adapter-driven.
Layout Engine
Start simple:
layoutTree(document)
layoutLayered(document)
layoutForce(document)V1 can ship with tree/layered layouts only.
D3 may be used for:
d3-hierarchyd3-forced3-zoom
Vendor only narrow D3 modules when they remove meaningful complexity.
Milestones
Milestone 1 — Shared Graph Viewer
Build the generic graph viewer with mock data.
Deliverables:
GraphExplorerDocumentmodel- DOM/SVG graph renderer
- Pan/zoom/fit
- Select node/edge
- Details panel
- Search
- Type filters
- Mock graph fixtures
- Unit tests for normalization
Acceptance Criteria:
- Can render at least 100 nodes and 150 edges smoothly.
- Search focuses a node.
- Details panel updates on selection.
- Graph model is independent of any one data source.
Milestone 2 — Scene Hierarchy Graph
Deliverables:
buildSceneHierarchyGraph(sceneGraph, objects)- Tree layout
- Object badges
- Click node selects object
- Filter hidden/locked/prefab/camera/trigger
- Tests for graph conversion
Acceptance Criteria:
- Scene hierarchy graph matches the existing hierarchy tree.
- Selecting graph node selects the scene object.
- Collapsed nodes hide children.
- Badges match existing hierarchy status.
Milestone 3 — Event Bus Map
Deliverables:
buildEventBusGraph(rules, components, prefabs)- Custom event nodes
- Emitters/listeners
- Payload chips
- Missing emitter/listener warnings
- Click event filters related flows
Acceptance Criteria:
- Shows all custom events.
- Shows component events when used by flow.
- Warns on listener with no emitter.
- Warns on emitter with no listener.
- Works with Garden Defense demo.
Milestone 4 — Prefab Anatomy Graph
Deliverables:
buildPrefabAnatomyGraph(prefab)- Object/component/flow/asset nodes
- Event input/output nodes
- Open inspector/Object Flow from graph selection
- Tests with Garden Slime prefab fixture
Acceptance Criteria:
- Shows prefab root, contained objects, components, flow summary, and assets.
- Clicking component opens component inspector.
- Clicking flow opens Object Flow.
- Missing assets display warnings.
Milestone 5 — Asset Dependency Graph
Deliverables:
buildAssetDependencyGraph(scene, assets, prefabs)- Scene/prefab/image/audio/UI nodes
- Missing/unused asset detection
- Export-readiness summary
- Migrate assets panel graph onto shared renderer
Acceptance Criteria:
- Shows assets used by current scene.
- Shows unused assets.
- Shows missing references.
- Can focus on one asset and show dependents.
Milestone 6 — Component Relationship Graph
Deliverables:
buildComponentRelationshipGraph(registry)- Requires/calls/emits/fields/actions/conditions
- Component details side panel
Acceptance Criteria:
- Shows
requiresrelationships. - Shows actions, conditions, events.
- Hazard/Pickup/Spawner relationships are understandable.
- Registry metadata drives graph without hardcoded component-specific UI.
Milestone 7 — Runtime Trace Graph
Deliverables:
- Trace graph adapter
- Execution counts
- Last fired event path
- Error path highlighting
- Replay last trace
Acceptance Criteria:
- During play, fired nodes pulse or count.
- Trace graph can explain “tap slime → damage → death → coin → score.”
- Selecting a trace node shows last values.
Garden Defense Teaching Use Case
The Garden Defense demo should include a “Study this demo” entry point.
Suggested views:
- Scene Graph — Hero, Flower bed, Slime nest, HUD, Bonus bush
- Prefab Anatomy — Garden Slime, Coin/Sun Seed, Slime Nest, Bonus Bush
- Event Map —
slime_defeated,gold_added,milestone_reached - Runtime Trace — Last slime tap sequence
Example teaching flow:
Open Garden Defense
Click “Study this demo”
Graph Explorer opens Event Map
User clicks slime_defeated
Explorer shows:
emitted by Garden Slime prefab
listened by Score Scene Flow
listened by Hero Speech Flow
listened by Nest Spawner accelerationThis turns the shipped demo into a self-documenting learning project.
Risks
Risk: Graph Explorer becomes another bespoke editor
Mitigation: One shared graph document model; pure adapters; one renderer; no one-off graph widgets outside the shared model.
Risk: D3 bleeds into app architecture
Mitigation: D3 only in graph-explorer layout/interaction modules; authored data remains Opal-owned; runtime does not import graph explorer.
Risk: Too many graph modes delay shipping
Mitigation: Ship Scene Hierarchy + Event Bus + Prefab Anatomy first; defer architecture/component/asset/runtime graphs as follow-ons (asset graph partially exists in the assets panel).
Risk: Graphs become visually noisy
Mitigation: Default filtered views; details on selection; collapse dense subgraphs; semantic grouping; do not show every edge at once.
Risk: Data sources are not normalized enough
Mitigation: Build adapters incrementally; fixture tests per adapter; prefer warnings over silent omissions.
Recommended V1
Ship these first:
- Shared graph viewer
- Scene hierarchy graph
- Event bus map
- Prefab anatomy graph for selected prefab
Do not start with architecture/file graphs unless the feature is initially developer-only. For creators, Event Bus Map and Prefab Anatomy are the most impressive and useful.
V1 Success Criteria
A developer opens the Garden Defense demo and can visually answer:
Where do slimes come from?
What happens when I tap a slime?
What makes the score increase?
Which prefab spawns coins?
Which event connects slime death to the rest of the scene?
Which assets does the slime prefab use?If the Graph Explorer answers those questions cleanly, it is already valuable.
Future Vision
Long-term, the Graph Explorer becomes Opal’s “understanding mode.”
Instead of only editing objects and flows, developers can inspect systems:
Show me this prefab.
Show me who listens to this event.
Show me why this object moved.
Show me what this asset is used by.
Show me what ran during play.
Show me what will break if I delete this.That is the difference between a game editor and a game engine that teaches its own architecture.