Skip to content

Opal Graph Explorer ​

Status: Core shipped in the workbench Graph dock (src/game/graph-explorer/, wired from src/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 by runtime (see Architecture).
Related: The assets panel graph view (src/game/assets/editor/asset-graph-view.js) and reference-scan.js are 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 View selector chooses among the six shipped modes. Search and Filters narrow the map without consuming a second toolbar row; Reset in Filters clears those filters. Fit frames the content and follows panel resizing until you pan or zoom manually. Use the dock's maximize button for a larger map.

Click a node or focus it and press Enter/Space to inspect it. Ctrl/Cmd+Enter, double-click, or the details action opens its source. Asset selection stays in Graph; Show dependencies from Assets opens the corresponding dependency view. Filters dismiss when leaving the panel.

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 ​

  1. Help developers understand complex projects quickly.
  2. Make prefabs, components, events, and assets inspectable as relationships, not just lists.
  3. Provide teaching tools for sample games such as Garden Defense.
  4. Support debugging by showing runtime traces and event flow.
  5. Reuse a shared graph view model across many data sources.
  6. Keep graph visualization separate from authored game/runtime data.
  7. Avoid making D3 the application architecture; use it only for layout, transforms, and interaction primitives where useful.

Non-Goals ​

  1. Do not replace Object Flow’s editable node graph.
  2. Do not make every graph editable in v1.
  3. Do not serialize graph explorer UI state into scene or prefab data, except optional editor preferences.
  4. Do not introduce runtime dependencies from game logic into editor-only graph visualization code.
  5. Do not require all graph modes to ship at once.

Design Principle ​

The Graph Explorer should answer five questions:

  1. What is this?
  2. What owns it?
  3. What does it depend on?
  4. What depends on it?
  5. 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:

js
{
  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.js layer 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 ​

text
src/game/flow/catalog.js
  Layer: behavior
  Imports: runtime, core, behavior
  Imported by: interaction, rules, tests
  Risk: high centrality

V1 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.js
  • customObjects
  • hierarchyLayerKind
  • hierarchyLayerBadges
  • 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
  • ComponentHost serialized components
  • Object Flow graphs
  • Asset references (reference-scan.js, prefab/scene serializers)
  • Override detector

Layout ​

A structured left-to-right graph:

text
Prefab Root
  → Objects
  → Components
  → Flow Graphs
  → Events Out
  → Asset References

Nodes ​

  • 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 ​

text
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_prefab

V1 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.

text
[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 ​

text
slime_defeated
  emitted by:
    Garden Slime / Health.died
  listened by:
    Scene Flow / Add Score
    Hero / Say Milestone
    Nest Spawner / Accelerate

V1 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:

text
Trigger → Conditions → Actions → Events Out

Nodes ​

  • 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 ​

text
Hazard
  requires Collider2D
  calls Health.damage
  optionally calls SpriteRenderer.vanish
  reads Team.name
  emits hazard/hurt

V1 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 ​

text
Base Slime
  ├─ Berry Slime
  │   overrides SpriteRenderer.sprite
  │   overrides Loot.points = 2
  └─ Thorn Slime
      adds Hazard
      overrides Health.hp = 5

V1 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 ​

text
On Tap
  12x → Health.damage
  4x  → Health.died
  4x  → Spawn Coin
  4x  → Add Score
  4x  → Emit slime_defeated
  4x  → Destroy Self

V1 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:

text
Graph Explorer

Inside it:

text
View:
  Scene Hierarchy
  Prefab Anatomy
  Event Map
  Flow Summary
  Component Relationships
  Asset Dependencies
  Architecture

Contextual Entry Points ​

Right-click actions:

text
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 graph

Layout ​

The Graph Explorer should use a three-region layout:

text
┌─────────────────────────────────────────────┐
│ 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 ​

text
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.js

Classify as editor in architecture-boundaries.test.js.

Alternative colocation:

text
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:

js
export function createGraphExplorerDocument({
  id,
  title,
  mode,
  nodes = [],
  edges = [],
  groups = [],
  meta = {},
}) {
  return normalizeGraphExplorerDocument({ id, title, mode, nodes, edges, groups, meta });
}

Node fields:

js
{
  id,
  type,
  label,
  subtitle,
  group,
  icon,
  badges,
  status,
  position,
  collapsed,
  data
}

Edge fields:

js
{
  id,
  from,
  to,
  type,
  label,
  direction,
  status,
  data
}

Status values:

js
"ok"
"warning"
"error"
"missing"
"disabled"
"runtime"

Edge types:

js
"contains"
"imports"
"uses"
"emits"
"listens"
"calls"
"reads"
"writes"
"requires"
"spawns"
"overrides"
"executes"

Adapters ​

Each adapter is pure:

js
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.js today; 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:

js
layoutTree(document)
layoutLayered(document)
layoutForce(document)

V1 can ship with tree/layered layouts only.

D3 may be used for:

  • d3-hierarchy
  • d3-force
  • d3-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:

  • GraphExplorerDocument model
  • 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 requires relationships.
  • 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:

  1. Scene Graph — Hero, Flower bed, Slime nest, HUD, Bonus bush
  2. Prefab Anatomy — Garden Slime, Coin/Sun Seed, Slime Nest, Bonus Bush
  3. Event Map — slime_defeated, gold_added, milestone_reached
  4. Runtime Trace — Last slime tap sequence

Example teaching flow:

text
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 acceleration

This 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:

  1. Shared graph viewer
  2. Scene hierarchy graph
  3. Event bus map
  4. 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:

text
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:

text
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.