From 65b8b377ec356e8e603a01ae376a97f9908ad471 Mon Sep 17 00:00:00 2001 From: Robert Date: Sat, 24 Sep 2022 12:13:12 +0200 Subject: [PATCH] Script editor - Added auto-arrange button --- .../Artemis.Core.csproj.DotSettings | 1 + .../Extensions/NodeScriptExtension.cs | 2 +- .../NodeEditor/Commands/OrganizeScript.cs | 43 ++++++++++++++++++ .../NodeScriptWindowView.axaml | 5 +++ .../NodeScriptWindowViewModel.cs | 45 ++++++++++++++++--- 5 files changed, 89 insertions(+), 7 deletions(-) create mode 100644 src/Artemis.UI.Shared/Services/NodeEditor/Commands/OrganizeScript.cs diff --git a/src/Artemis.Core/Artemis.Core.csproj.DotSettings b/src/Artemis.Core/Artemis.Core.csproj.DotSettings index c23015925..57c6a2f5f 100644 --- a/src/Artemis.Core/Artemis.Core.csproj.DotSettings +++ b/src/Artemis.Core/Artemis.Core.csproj.DotSettings @@ -93,6 +93,7 @@ True True True + True True True True \ No newline at end of file diff --git a/src/Artemis.Core/VisualScripting/Extensions/NodeScriptExtension.cs b/src/Artemis.Core/VisualScripting/Extensions/NodeScriptExtension.cs index f0961dfb6..92d583d99 100644 --- a/src/Artemis.Core/VisualScripting/Extensions/NodeScriptExtension.cs +++ b/src/Artemis.Core/VisualScripting/Extensions/NodeScriptExtension.cs @@ -19,7 +19,7 @@ public static class NodeScriptExtension levels[currentLevelNode] = 0; // DarthAffe 13.09.2022: Init-exit nodes as zero int currentLevel = 1; - while (currentLevelNodes.Count > 0) + while (currentLevelNodes.Count > 0 && currentLevel < 1000) { List nextLevelNodes = currentLevelNodes.SelectMany(node => node.Pins .Where(x => x.Direction == PinDirection.Input) diff --git a/src/Artemis.UI.Shared/Services/NodeEditor/Commands/OrganizeScript.cs b/src/Artemis.UI.Shared/Services/NodeEditor/Commands/OrganizeScript.cs new file mode 100644 index 000000000..cd7f3ec23 --- /dev/null +++ b/src/Artemis.UI.Shared/Services/NodeEditor/Commands/OrganizeScript.cs @@ -0,0 +1,43 @@ +using System.Collections.Generic; +using System.Linq; +using Artemis.Core; + +namespace Artemis.UI.Shared.Services.NodeEditor.Commands; + +/// +/// Represents a node editor command that can be used to organize a script +/// +public class OrganizeScript : INodeEditorCommand +{ + private readonly NodeScript _script; + private readonly List<(INode node, double x, double y)> _originalPositions; + + /// + /// Creates a new instance of the class. + /// + /// The script to organize. + public OrganizeScript(NodeScript script) + { + _script = script; + _originalPositions = script.Nodes.Select(n => (n, n.X, n.Y)).ToList(); + } + + /// + public string DisplayName => "Organize script"; + + /// + public void Execute() + { + _script.Organize(); + } + + /// + public void Undo() + { + foreach ((INode? node, double x, double y) in _originalPositions) + { + node.X = x; + node.Y = y; + } + } +} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/VisualScripting/NodeScriptWindowView.axaml b/src/Artemis.UI/Screens/VisualScripting/NodeScriptWindowView.axaml index e37a84702..3ccf5989b 100644 --- a/src/Artemis.UI/Screens/VisualScripting/NodeScriptWindowView.axaml +++ b/src/Artemis.UI/Screens/VisualScripting/NodeScriptWindowView.axaml @@ -43,6 +43,11 @@ + + + + + diff --git a/src/Artemis.UI/Screens/VisualScripting/NodeScriptWindowViewModel.cs b/src/Artemis.UI/Screens/VisualScripting/NodeScriptWindowViewModel.cs index 911835000..0925e450c 100644 --- a/src/Artemis.UI/Screens/VisualScripting/NodeScriptWindowViewModel.cs +++ b/src/Artemis.UI/Screens/VisualScripting/NodeScriptWindowViewModel.cs @@ -26,6 +26,7 @@ public class NodeScriptWindowViewModel : NodeScriptWindowViewModelBase private readonly IProfileService _profileService; private readonly ISettingsService _settingsService; private readonly IWindowService _windowService; + private bool _pauseUpdate; public NodeScriptWindowViewModel(NodeScript nodeScript, INodeService nodeService, @@ -56,6 +57,7 @@ public class NodeScriptWindowViewModel : NodeScriptWindowViewModelBase Categories = categories; CreateNode = ReactiveCommand.Create(ExecuteCreateNode); + AutoArrange = ReactiveCommand.CreateFromTask(ExecuteAutoArrange); Export = ReactiveCommand.CreateFromTask(ExecuteExport); Import = ReactiveCommand.CreateFromTask(ExecuteImport); @@ -83,6 +85,7 @@ public class NodeScriptWindowViewModel : NodeScriptWindowViewModelBase public ReactiveCommand OpenUri { get; set; } public ReadOnlyObservableCollection> Categories { get; } public ReactiveCommand CreateNode { get; } + public ReactiveCommand AutoArrange { get; } public ReactiveCommand Export { get; } public ReactiveCommand Import { get; } @@ -108,6 +111,27 @@ public class NodeScriptWindowViewModel : NodeScriptWindowViewModelBase _nodeEditorService.ExecuteCommand(NodeScript, new AddNode(NodeScript, node)); } + private async Task ExecuteAutoArrange() + { + try + { + if (!NodeScript.ExitNodeConnected) + { + await _windowService.ShowConfirmContentDialog("Cannot auto-arrange", "The exit node must be connected in order to perform auto-arrange.", "Close", null); + return; + } + + _pauseUpdate = true; + _nodeEditorService.ExecuteCommand(NodeScript, new OrganizeScript(NodeScript)); + await Task.Delay(200); + NodeScriptViewModel.RequestAutoFit(); + } + finally + { + _pauseUpdate = false; + } + } + private async Task ExecuteExport() { // Might not cover everything but then the dialog will complain and that's good enough @@ -131,17 +155,26 @@ public class NodeScriptWindowViewModel : NodeScriptWindowViewModelBase if (result == null) return; - string json = await File.ReadAllTextAsync(result[0]); - _nodeService.ImportScript(json, NodeScript); - History.Clear(); + try + { + _pauseUpdate = true; + string json = await File.ReadAllTextAsync(result[0]); + _nodeService.ImportScript(json, NodeScript); + History.Clear(); - await Task.Delay(200); - NodeScriptViewModel.RequestAutoFit(); + await Task.Delay(200); + NodeScriptViewModel.RequestAutoFit(); + } + finally + { + _pauseUpdate = false; + } } private void Update(object? sender, EventArgs e) { - NodeScript.Run(); + if (!_pauseUpdate) + NodeScript.Run(); } private void Save(object? sender, EventArgs e)