5using System.Collections.Generic;
8namespace MPewsey.ManiaMapGodot.Graphs.Editor
11 public partial class LayoutGraphEditor : Control
13 [Export]
public GraphEdit GraphEdit {
get;
set; }
14 [Export]
public Node EdgeLineContainer {
get;
set; }
15 [Export]
public PackedScene NodeElementScene {
get;
set; }
16 [Export]
public PackedScene EdgeElementScene {
get;
set; }
17 [Export]
public PackedScene EdgeLineScene {
get;
set; }
19 [Export]
public Label FileNameLabel {
get;
set; }
20 [Export]
public Button CloseButton {
get;
set; }
21 [Export]
public Button SaveButton {
get;
set; }
22 [Export]
public Button EdgeDisplayButton {
get;
set; }
24 private LayoutGraphResource GraphResource {
get;
set; }
25 public Dictionary<int, LayoutGraphNodeElement> NodeElements {
get; } =
new Dictionary<int, LayoutGraphNodeElement>();
26 public HashSet<LayoutGraphEdgeElement> EdgeElements {
get; } =
new HashSet<LayoutGraphEdgeElement>();
27 private List<LayoutGraphEdgeLine> EdgeLines {
get; } =
new List<LayoutGraphEdgeLine>();
28 private HashSet<Resource> SelectedResources {
get; } =
new HashSet<Resource>();
30 public override void _Ready()
33 GraphEdit.NodeSelected += OnNodeSelected;
34 GraphEdit.NodeDeselected += OnNodeDeselected;
35 GraphEdit.GuiInput += OnGuiInput;
36 GraphEdit.ConnectionRequest += OnConnectionRequest;
37 SaveButton.Pressed += OnSubmitSaveButton;
38 CloseButton.Pressed += OnSubmitCloseButton;
39 EdgeDisplayButton.Toggled += OnToggleEdgeDisplayButton;
40 OnToggleEdgeDisplayButton(
true);
43 public override void _ExitTree()
46 CloseOutGraphResource();
49 public override void _Process(
double delta)
52 MoveEdgesToMidpointsOfNodes();
56 private void DisplayNodes(
bool visible)
58 foreach (var node
in NodeElements.Values)
60 node.Visible = visible;
63 node.Selected =
false;
67 private void DisplayEdges(
bool visible)
69 foreach (var edge
in EdgeElements)
71 edge.Visible = visible;
74 edge.Selected =
false;
78 private void MoveEdgesToMidpointsOfNodes()
80 foreach (var element
in EdgeElements)
82 var edge = element.EdgeResource;
83 var fromFound = NodeElements.TryGetValue(edge.FromNode, out var fromNode);
84 var toFound = NodeElements.TryGetValue(edge.ToNode, out var toNode);
86 if (fromFound && toFound)
88 var zoom = GraphEdit.Zoom;
89 var fromPosition = fromNode.Position + 0.5f * zoom * fromNode.Size;
90 var toPosition = toNode.Position + 0.5f * zoom * toNode.Size;
91 var edgePosition = (fromPosition + toPosition) * 0.5f - 0.5f * zoom * element.Size;
92 element.PositionOffset = GetPositionOffset(edgePosition);
97 private void PopulateEdgeLines()
101 var zoom = GraphEdit.Zoom;
103 foreach (var element
in EdgeElements)
105 var line = EdgeLines[index++];
106 line.Populate(element, NodeElements, zoom);
110 private void SizeEdgeLinesList()
112 while (EdgeLines.Count > EdgeElements.Count)
114 var index = EdgeLines.Count - 1;
115 EdgeLines[index].QueueFree();
116 EdgeLines.RemoveAt(index);
119 while (EdgeLines.Count < EdgeElements.Count)
121 var line = EdgeLineScene.Instantiate<LayoutGraphEdgeLine>();
122 EdgeLineContainer.AddChild(line);
127 private void OnGuiInput(InputEvent input)
129 if (input is InputEventMouseButton mouseInput)
131 if (mouseInput.ButtonIndex == MouseButton.Right && mouseInput.Pressed)
133 AddNode(GetPositionOffset(mouseInput.Position));
134 GetViewport().SetInputAsHandled();
137 else if (input.IsActionPressed(EditorInputs.DeleteAction))
139 DeleteSelectedElements();
140 GetViewport().SetInputAsHandled();
142 else if (input.IsActionPressed(EditorInputs.SelectAllAction))
145 GetViewport().SetInputAsHandled();
147 else if (input.IsActionPressed(EditorInputs.SelectAllNodesAction))
149 SelectAllNodeElements();
150 GetViewport().SetInputAsHandled();
152 else if (input.IsActionPressed(EditorInputs.SelectAllEdgesAction))
154 SelectAllEdgeElements();
155 GetViewport().SetInputAsHandled();
159 private void SelectAllNodeElements()
161 foreach (var node
in NodeElements.Values)
163 node.Selected =
true;
167 private void SelectAllEdgeElements()
169 foreach (var edge
in EdgeElements)
171 edge.Selected = EdgeDisplayButton.ButtonPressed;
175 private void SelectAllElements()
177 SelectAllEdgeElements();
178 SelectAllNodeElements();
181 private void DeleteSelectedElements()
183 SelectedResources.Clear();
185 foreach (var edge
in EdgeElements.Where(x => x.Selected).ToList())
190 foreach (var node
in NodeElements.Values.Where(x => x.Selected).ToList())
196 private void RemoveNode(LayoutGraphNodeElement node)
198 RemoveNodeEdges(node.NodeResource.Id);
199 GraphResource.RemoveNode(node.NodeResource.Id);
200 NodeElements.Remove(node.NodeResource.Id);
204 private void RemoveNodeEdges(
int nodeId)
206 foreach (var edge
in NodeEdges(nodeId))
212 private List<LayoutGraphEdgeElement> NodeEdges(
int nodeId)
214 var result =
new List<LayoutGraphEdgeElement>();
216 foreach (var edge
in EdgeElements)
218 if (edge.EdgeResource.ContainsNode(nodeId))
225 private void RemoveEdge(LayoutGraphEdgeElement element)
227 GraphResource.RemoveEdge(element.EdgeResource.FromNode, element.EdgeResource.ToNode);
228 EdgeElements.Remove(element);
232 private static void ToggleButton(Button button,
bool toggled)
234 button.SetPressedNoSignal(toggled);
235 button.Flat = !toggled;
238 private void OnToggleEdgeDisplayButton(
bool toggled)
240 ToggleButton(EdgeDisplayButton, toggled);
241 DisplayEdges(toggled);
242 DisplayResourceEditor();
245 private void OnSubmitSaveButton()
247 GraphResource?.SaveIfDirty();
248 SaveButton.Disabled =
true;
251 private void OnSubmitCloseButton()
253 CloseOutGraphResource();
256 if (IsInstanceValid(ManiaMapPlugin.Current))
257 ManiaMapPlugin.Current.HideGraphEditorDock();
260 private void OnConnectionRequest(StringName fromNodeName,
long fromSlot, StringName toNodeName,
long toSlot)
262 var node1 = GraphEdit.GetNode<GraphNode>(fromNodeName.ToString());
263 var node2 = GraphEdit.GetNode<GraphNode>(toNodeName.ToString());
265 if (node1 is LayoutGraphNodeElement fromNode && node2 is LayoutGraphNodeElement toNode)
266 AddEdge(fromNode.NodeResource.Id, toNode.NodeResource.Id);
269 private void OnGraphResourceChanged()
271 SaveButton.Disabled =
false;
272 FileNameLabel.Text = GraphResource.ResourcePath.GetFile();
275 public Vector2 GetPositionOffset(Vector2 position)
277 return (position + GraphEdit.ScrollOffset) / GraphEdit.Zoom;
280 public void SetEditorTarget(LayoutGraphResource graphResource)
282 CloseOutGraphResource();
283 GraphResource = graphResource;
284 SaveButton.Disabled =
false;
285 FileNameLabel.Text = graphResource.ResourcePath.GetFile();
286 RegisterChangedSignals();
288 CreateEdgeElements();
289 CreateNodeElements();
292 private void CloseOutGraphResource()
294 if (GraphResource !=
null)
296 GraphResource.SaveIfDirty();
297 GraphResource.QuietDisconnect(Resource.SignalName.Changed, OnGraphResourceChanged);
298 GraphResource.UnregisterOnSubresourceChangedSignals();
299 GraphResource =
null;
303 private void RegisterChangedSignals()
305 GraphResource.Changed += OnGraphResourceChanged;
306 GraphResource.RegisterOnSubresourceChangedSignals();
309 private void OnNodeDeselected(Node node)
313 case LayoutGraphNodeElement nodeElement:
314 SelectedResources.Remove(nodeElement.NodeResource);
316 case LayoutGraphEdgeElement edgeElement:
317 SelectedResources.Remove(edgeElement.EdgeResource);
321 DisplayResourceEditor();
324 private void OnNodeSelected(Node node)
328 case LayoutGraphNodeElement nodeElement:
329 SelectedResources.Add(nodeElement.NodeResource);
331 case LayoutGraphEdgeElement edgeElement:
332 SelectedResources.Add(edgeElement.EdgeResource);
336 DisplayResourceEditor();
339 private void DisplayResourceEditor()
341 if (SelectedResources.Count > 1)
343 var multiEditor =
new LayoutGraphMultiEditor(SelectedResources);
344 EditorInterface.Singleton.EditResource(multiEditor);
348 if (SelectedResources.Count == 1)
350 switch (SelectedResources.First())
352 case LayoutGraphNode nodeResource:
353 EditorInterface.Singleton.EditResource(nodeResource);
355 case LayoutGraphEdge edgeResource:
356 EditorInterface.Singleton.EditResource(edgeResource);
362 private LayoutGraphNodeElement CreateNodeElement(LayoutGraphNode node)
364 var element = NodeElementScene.Instantiate<LayoutGraphNodeElement>();
365 GraphEdit.AddChild(element);
366 NodeElements.Add(node.Id, element);
367 element.Initialize(node);
371 private LayoutGraphEdgeElement CreateEdgeElement(LayoutGraphEdge edge)
373 var element = EdgeElementScene.Instantiate<LayoutGraphEdgeElement>();
374 GraphEdit.AddChild(element);
375 GraphEdit.MoveChild(element, 1);
376 EdgeElements.Add(element);
377 element.Initialize(edge);
378 element.Visible = EdgeDisplayButton.ButtonPressed;
382 private void CreateNodeElements()
384 foreach (var node
in GraphResource.Nodes.Values)
386 CreateNodeElement(node);
390 private void CreateEdgeElements()
392 foreach (var edge
in GraphResource.Edges.Values)
394 CreateEdgeElement(edge);
398 public void AddNode(Vector2 position)
400 var node = GraphResource.AddNode(position);
401 CreateNodeElement(node);
402 GraphResource.SetDirty();
405 public void AddEdge(
int fromNode,
int toNode)
407 var edge = GraphResource.AddEdge(fromNode, toNode);
411 CreateEdgeElement(edge);
412 GraphResource.SetDirty();
416 public void ClearCanvas()
418 foreach (var node
in NodeElements.Values)
423 foreach (var edge
in EdgeElements)
428 foreach (var line
in EdgeLines)
433 SelectedResources.Clear();
434 NodeElements.Clear();
435 EdgeElements.Clear();