NOTICE: The improved version is in 2.2.37+. No need to add it unless you're below that version.
This version is outdated, better version below, which is also integrated into 2.2.37+
I have been importing my larger conversations and the current auto arrange has always left something to be desired. With that in mind, I set out to make a very rough org-chart vibe. Really, it just ends up being a more human-readable grid-layout type thing that tries to make space for branches without thinking too hard about it.
NOTE
This works for vertical arranging only. It's also not perfect, but it is more human readable and organizable. Example screenshot after the instructions.
INSTRUCTIONS
In DialogueEditorWindowConversationNodeEditorAutoArrange.cs in the ArrangeTree function (line 126) we are commenting out the code inside
Code: Select all
if(vertically){}
Code: Select all
currentConversation.dialogueEntries[0].canvasRect = new Rect(2500, 1 * (canvasRectHeight + 24), canvasRectWidth, canvasRectHeight);
HandleChildren(currentConversation.dialogueEntries[0].outgoingLinks, currentConversation.dialogueEntries[0], 2);
nodeGridDict.Clear();
handledNodes.Clear();
Code: Select all
Dictionary<(int x, int y), DialogueEntry> nodeGridDict = new();
List<DialogueEntry> handledNodes = new();
private void HandleChildren(List<Link> links, DialogueEntry parent, int layer, int startX = 8, List<(int x, int y)> parentLocations = null)
{
Rect leftMost = new Rect();
Rect rightMost = new Rect();
int leftIndex = 0;
int rightIndex = 0;
for (int i = 0; i < links.Count; i++)
{
DialogueEntry child = currentConversation.dialogueEntries.Find(x => x.id == links[i].destinationDialogueID);
if(child == null || handledNodes.Contains(child))
{
continue;
}
while (nodeGridDict.ContainsKey((i + startX, layer)))
{
startX++;
}
int xIndex = i + startX;
nodeGridDict[(xIndex,layer)] = child;
handledNodes.Add(child);
child.canvasRect = new Rect((xIndex * (canvasRectWidth+10)), layer * (canvasRectHeight + 24), canvasRectWidth, canvasRectHeight);
if (child.outgoingLinks.Count > 0)
{
if(child.outgoingLinks.Count == 1)
{
if(parentLocations == null)
{
parentLocations = new();
}
parentLocations.Add((xIndex, layer));
HandleChildren(child.outgoingLinks, child, layer + 1, xIndex, parentLocations);
}
else
{
int childIndexStart = xIndex - (child.outgoingLinks.Count / 2);
if (parentLocations != null)
{
//Fill gaps above single stacks with branches below
foreach(var location in parentLocations)
{
// Move parents in line with child, hypothetically
if (nodeGridDict.ContainsKey(location))
{
DialogueEntry value = nodeGridDict[location];
if (value != null)
{
value.canvasRect.x = (xIndex * (canvasRectWidth + 10));
}
nodeGridDict[(xIndex, location.y)] = value;
nodeGridDict.Remove(location);
}
for (int j = 0; j < child.outgoingLinks.Count; j++)
{
nodeGridDict[(childIndexStart + j, location.y)] = null;
}
}
}
HandleChildren(child.outgoingLinks, child, layer + 1, childIndexStart);
}
}
if(i == 0)
{
leftMost = child.canvasRect;
leftIndex = xIndex;
}
rightMost = child.canvasRect;
rightIndex = xIndex;
}
parent.canvasRect.x = ((leftIndex + rightIndex) * 0.5f) * (canvasRectWidth+10);
}