# DialogueTreeEditorWindow.cs: Explanation and Integration
This document explains the `DialogueTreeEditorWindow.cs` script, a Unity Editor window for visually editing dialogue trees. It covers the script's functionality, its integration with the previously discussed dialogue system scripts (`DialogueManager.cs`, `DialogueNodeAuthoring.cs`, etc.), the purpose of each method, the GameObjects required, and how to use it in the Unity Editor.
---
## Overview of [[DialogueTreeEditorWindow.cs]]
The `DialogueTreeEditorWindow.cs` script provides a **visual graph editor** in the Unity Editor for creating and editing dialogue trees. It allows developers to:
- Create new dialogue nodes
- Connect nodes via linear progression or branching choices
- Edit node properties (e.g., character name, dialogue text, sprites, audio)
- Save and load node layouts to/from JSON files
- Automatically arrange nodes for better visualization
This script builds on the dialogue system by providing a user-friendly interface to manage `DialogueNodeAuthoring` components, which define the dialogue structure.
---
## How [[DialogueTreeEditorWindow.cs]] Works
### General Functionality
- **Graph View**: Uses Unity's `GraphView` API to create a node-based editor window where each node represents a `DialogueNodeAuthoring` component.
- **Node Creation and Editing**: Allows adding new nodes, editing their properties (e.g., character name, dialogue text), and connecting them via ports (for linear progression or choices).
- **Connections**: Supports linear connections (`linearNextNode`) and choice-based branching (`Choices` in `DialogueNodeAuthoring`).
- **Layout Management**: Automatically arranges nodes (`AutoLayoutNodes`) and allows saving/loading custom layouts to JSON files.
- **Integration**: Works directly with `DialogueNodeAuthoring` components attached to GameObjects, updating their properties in real-time.
### Integration with Other Scripts
- **DialogueNodeAuthoring.cs**: The editor window directly manipulates `DialogueNodeAuthoring` components, which define dialogue nodes (e.g., character name, dialogue text, choices). Each node in the graph represents a `DialogueNodeAuthoring` component.
- **DialogueManager.cs**: While not directly used at runtime, the editor creates dialogue structures that `DialogueManager` will later use to display dialogue in-game.
- **NPCConversationManager.cs**: The dialogue trees edited in this window are part of the `dialogueRoot` GameObjects managed by `NPCConversationManager`, which can export/import them to/from JSON.
- **NPCMemory.cs**: The editor allows setting memory keys/values for choices (`memoryKey`, `memoryValue`), which `NPCMemory` uses to track player choices.
- **Environment.cs**: The editor ensures the selected `dialogueRoot` GameObject has an `Environment` component, as required by the dialogue system.
---
## Key Methods and Their Purpose
### Main Class: DialogueTreeEditorWindow
- `OpenWindow()`:
- **Purpose**: Static method to open the editor window.
- **Details**: Accessible via the Unity Editor menu (`Window > Dialogue Tree Editor`). Creates or focuses the window and sets its title.
- `OnEnable()`:
- **Purpose**: Initializes the window when it’s opened.
- **Details**: Calls `ConstructGraphView()` to set up the graph view and `AddToolbar()` to create the toolbar with controls.
- `OnDisable()`:
- **Purpose**: Cleans up when the window is closed.
- **Details**: Clears the `rootVisualElement` to prevent memory leaks.
- `ConstructGraphView()`:
- **Purpose**: Sets up the `DialogueGraphView` (a custom `GraphView`).
- **Details**:
- Initializes the graph with zooming, dragging, and selection capabilities.
- Adds a node creation request handler (right-click to add nodes if a `dialogueRoot` is selected).
- Registers callbacks to save node positions (`GeometryChangedEvent`) and handle edge deletions (`graphViewChanged`).
- `AddToolbar()`:
- **Purpose**: Creates a toolbar with controls for selecting a dialogue root, adding nodes, and managing layouts.
- **Details**:
- **ObjectField**: Selects a `dialogueRoot` GameObject (must have an `Environment` component).
- **Add Node Button**: Calls `AddNewNode()` to create a new dialogue node.
- **Reset Layout Button**: Calls `ResetLayout()` to auto-arrange nodes.
- **Save Layout Button**: Calls `SaveLayout()` to save node positions to a JSON file.
- **Load Layout Button**: Calls `LoadSavedLayout()` to load saved node positions.
- `AddNewNode()`:
- **Purpose**: Creates a new dialogue node in the hierarchy and graph.
- **Details**:
- Prompts for a node name (defaults to "NewNode").
- Creates a new GameObject under the `dialogueRoot`, adds a `DialogueNodeAuthoring` component, and registers it for undo.
- Adds a visual node to the graph via `CreateVisualNode()` and positions it.
- `RefreshGraph()`:
- **Purpose**: Updates the graph to reflect the current state of the `dialogueRoot`.
- **Details**:
- Clears existing nodes and edges.
- Loads all `DialogueNodeAuthoring` components from the `dialogueRoot`.
- Creates visual nodes and reconnects edges for linear and choice connections.
- Applies saved layouts or auto-layout if none exists.
- `ResetLayout()`:
- **Purpose**: Resets the node layout to a default auto-arranged structure.
- **Details**: Clears saved positions and calls `AutoLayoutNodes()` to rearrange nodes.
- `AutoLayoutNodes(Dictionary<string, Node> nodeMap, Dictionary<string, DialogueNodeAuthoring> authoringMap, DialogueNodeAuthoring[] nodes)`:
- **Purpose**: Automatically arranges nodes in the graph to avoid overlap.
- **Details**:
- Identifies the root node (a node with no incoming connections).
- Uses `AssignPositions()` to recursively position nodes based on their connections (linear or choice-based).
- Ensures nodes are spaced appropriately (`NODE_WIDTH`, `NODE_HEIGHT`, `HORIZONTAL_SPACING`, `VERTICAL_SPACING`).
- `FindNextAvailableY(float x, float desiredY, Dictionary<float, List<float>> occupiedYPositions)`:
- **Purpose**: Helper method to find a non-overlapping Y position for a node at a given X coordinate.
- **Details**: Adjusts the Y position to avoid overlap with other nodes, ensuring proper spacing.
- `AssignPositions(DialogueNodeAuthoring node, Dictionary<string, DialogueNodeAuthoring> nodeMap, Dictionary<string, Vector2> positionMap, Dictionary<float, List<float>> occupiedYPositions, HashSet<string> visited, float x, float y)`:
- **Purpose**: Recursively positions nodes in the graph.
- **Details**:
- Positions the current node at `(x, y)` after adjusting `y` to avoid overlap.
- Recursively positions the `linearNextNode` and choice nodes at the next X level.
- Adjusts Y positions for choice nodes to fan out vertically (`CHOICE_VERTICAL_OFFSET`, `VERTICAL_SPACING`).
- `SaveLayout()`:
- **Purpose**: Saves the current node positions to a JSON file.
- **Details**:
- Saves positions to `Assets/DialogueLayouts/[dialogueRootName]_Layout.json`.
- Serializes positions using `SerializableNodePositions`.
- `LoadSavedLayout()`:
- **Purpose**: Loads saved node positions from a JSON file.
- **Details**:
- Loads from `Assets/DialogueLayouts/[dialogueRootName]_Layout.json`.
- Applies saved positions to nodes in the graph.
- `CreateVisualNode(DialogueNodeAuthoring authoringNode, Dictionary<string, Node> nodeMap)`:
- **Purpose**: Creates a visual node in the graph for a `DialogueNodeAuthoring` component.
- **Details**:
- Sets up the node’s UI with fields for editing properties (e.g., `characterName`, `dialogueText`, `characterSprite`).
- Adds input/output ports for connections (linear and choices).
- Supports adding new choices (`AddChoiceUI`), renaming nodes, and selecting the GameObject in the hierarchy.
- Updates the `DialogueNodeAuthoring` component in real-time with `Undo` support.
- `AddChoiceUI(Node node, DialogueNodeAuthoring authoringNode, int choiceIndex)`:
- **Purpose**: Adds UI for a choice to a visual node.
- **Details**:
- Creates fields for `choiceText`, `memoryKey`, and `memoryValue`.
- Adds an output port for connecting the choice to another node.
- Updates the `DialogueNodeAuthoring.Choices` list with `Undo` support.
### Nested Classes
#### DialogueGraphView
- **Purpose**: A custom `GraphView` subclass for the dialogue editor.
- **Details**: Initializes with basic manipulators (dragging, zooming, selection).
#### EdgeConnectorListener
- **Purpose**: Handles choice connections between nodes.
- **Methods**:
- `OnDropOutsidePort(Edge edge, Vector2 position)`: Connects a choice to a node if dropped near its input port.
- `OnDrop(GraphView graphView, Edge edge)`: Connects a choice to a node when dropped on its input port, updating `choice.nextNode`.
#### LinearEdgeConnectorListener
- **Purpose**: Handles linear connections between nodes.
- **Methods**:
- `OnDropOutsidePort(Edge edge, Vector2 position)`: Connects a linear next node if dropped near an input port.
- `OnDrop(GraphView graphView, Edge edge)`: Connects a linear next node, updating `linearNextNode`.
---
## How It Works with Other Scripts
- **DialogueNodeAuthoring.cs**:
- The editor window directly modifies `DialogueNodeAuthoring` components attached to GameObjects.
- Each visual node represents a `DialogueNodeAuthoring` instance, allowing editing of its properties (e.g., `characterName`, `dialogueText`, `Choices`).
- Connections (linear or choice-based) update the `linearNextNode` and `Choices` fields.
- **DialogueManager.cs**:
- The dialogue trees created/edited in this window are used by `DialogueManager` at runtime to load and display dialogue.
- The editor ensures the dialogue structure is valid for `DialogueManager` to process.
- **NPCConversationManager.cs**:
- The `dialogueRoot` GameObject selected in the editor is the same one managed by `NPCConversationManager`.
- `NPCConversationManager` can export the edited dialogue trees to JSON, preserving the structure created in the editor.
- **NPCMemory.cs**:
- The editor allows setting `memoryKey` and `memoryValue` for choices, which `NPCMemory` uses to track player decisions and influence future conversations.
- **Environment.cs**:
- The editor enforces that the `dialogueRoot` GameObject has an `Environment` component, aligning with the dialogue system’s requirements.
---
## GameObjects Needed
- **Dialogue Root GameObject**:
- Must have an `Environment` component (enforced by the editor).
- Children: GameObjects with `DialogueNodeAuthoring` components (representing dialogue nodes).
- Typically part of an NPC’s hierarchy, as used by `NPCConversationManager`.
- **No Additional Runtime GameObjects**:
- This script is an **Editor-only tool** and does not require GameObjects at runtime beyond what the dialogue system already needs (e.g., `dialogueRoot` for `NPCConversationManager`).
---
## How to Use [[DialogueTreeEditorWindow.cs]] in the Unity Editor
### Setup
1. **Ensure Prerequisites**:
- The dialogue system scripts (`DialogueManager.cs`, `DialogueNodeAuthoring.cs`, `Environment.cs`, `NPCConversationManager.cs`, `NPCMemory.cs`) must be in your project.
- Create an NPC GameObject with `NPCConversationManager` and a `dialogueRoot` child GameObject.
- Add an `Environment` component to the `dialogueRoot` GameObject.
2. **Open the Editor Window**:
- In the Unity Editor, go to `Window > Dialogue Tree Editor`.
- This opens the `Dialogue Tree Editor` window.
### Using the Editor
1. **Select a Dialogue Root**:
- In the toolbar at the top of the window, use the `ObjectField` labeled "Dialogue Root" to select your `dialogueRoot` GameObject.
- The GameObject must have an `Environment` component, or the selection will be rejected.
- Once selected, the graph will populate with existing nodes (if any).
2. **Add Nodes**:
- Click the `Add Node` button in the toolbar (or right-click in the graph view).
- Enter a name for the new node (defaults to "NewNode").
- A new GameObject with a `DialogueNodeAuthoring` component will be created under the `dialogueRoot`, and a visual node will appear in the graph.
3. **Edit Node Properties**:
- Each node in the graph displays fields for editing:
- `Character`, `Sprite`, `Emotion`, `Text`, `Audio`, `Animation`, `Char Panel Color`, `Dialogue Panel Color`, `Text Color`
- `Player Name`, `Player Sprite`, `Player Emotion`, `Is Player Speaking`
- Changes are saved to the `DialogueNodeAuthoring` component with `Undo` support.
4. **Add Choices**:
- Click the `Add Choice` button on a node to add a choice.
- Edit the `Choice` text, `Memory Key`, and `Memory Value`.
- Connect the choice to another node by dragging from the yellow output port to another node’s cyan input port.
5. **Connect Nodes**:
- **Linear Connections**: Drag from the green `Linear Next` port to another node’s input port to set `linearNextNode`.
- **Choice Connections**: Drag from a choice’s yellow output port to another node’s input port to set `choice.nextNode`.
- Deleting an edge (select and press Delete) clears the connection in the `DialogueNodeAuthoring` component.
6. **Manage Layout**:
- **Reset Layout**: Click `Reset Layout` to auto-arrange nodes.
- **Save Layout**: Click `Save Layout` to save node positions to a JSON file (`Assets/DialogueLayouts/[dialogueRootName]_Layout.json`).
- **Load Layout**: Click `Load Layout` to load saved positions.
7. **Additional Features**:
- **Rename Node**: Click the `Rename` button on a node to rename it.
- **Select Object**: Click the `Select Object` button to select the node’s GameObject in the hierarchy.
### Post-Editing
- The dialogue tree created/edited in the window is ready to be used by `NPCConversationManager` and `DialogueManager` in-game.
- You can export the dialogue to JSON using `NPCConversationManager`’s export functionality for runtime loading.
![[Dialogue Tree Editor Network.png]]
![[Dialogue Tree Editor Node.png]]
---
## Summary
- **Purpose**: `DialogueTreeEditorWindow.cs` provides a visual editor for creating and managing dialogue trees in the Unity Editor.
- **Integration**: Works with `DialogueNodeAuthoring` to define dialogue nodes, integrates with `NPCConversationManager` for runtime use, and supports `NPCMemory` for choice-based memory.
- **Key Features**: Node creation, property editing, connections (linear/choices), auto-layout, save/load layouts.
- **Usage**: Open via `Window > Dialogue Tree Editor`, select a `dialogueRoot`, and edit the dialogue tree visually.
This script enhances the dialogue system by providing a user-friendly interface for developers to design complex dialogue structures, which are then used by the runtime scripts to deliver an interactive experience in a 2D game.