diff --git a/src/Artemis.Core/VisualScripting/CustomNodeViewModel.cs b/src/Artemis.Core/VisualScripting/CustomNodeViewModel.cs index 7efc9956e..5e4aeef46 100644 --- a/src/Artemis.Core/VisualScripting/CustomNodeViewModel.cs +++ b/src/Artemis.Core/VisualScripting/CustomNodeViewModel.cs @@ -1,4 +1,6 @@ -namespace Artemis.Core +using System; + +namespace Artemis.Core { /// /// Represents a custom view model for a @@ -19,5 +21,10 @@ /// Called whenever the custom view model is closed /// void OnDeactivate(); + + /// + /// Occurs whenever the node was modified by the view model + /// + event EventHandler NodeModified; } } \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Editor/Controls/VisualScriptNodeCreationBox.cs b/src/Artemis.VisualScripting/Editor/Controls/VisualScriptNodeCreationBox.cs index 999fcd440..a2dce7bc0 100644 --- a/src/Artemis.VisualScripting/Editor/Controls/VisualScriptNodeCreationBox.cs +++ b/src/Artemis.VisualScripting/Editor/Controls/VisualScriptNodeCreationBox.cs @@ -65,7 +65,7 @@ namespace Artemis.VisualScripting.Editor.Controls public string SearchInput { - get => (string)GetValue(SearchInputProperty); + get => (string) GetValue(SearchInputProperty); set => SetValue(SearchInputProperty, value); } @@ -97,7 +97,7 @@ namespace Artemis.VisualScripting.Editor.Controls _searchBox.SelectionStart = 0; _searchBox.SelectionLength = _searchBox.Text.Length; } - + private void OnContentListSelectionChanged(object sender, SelectionChangedEventArgs args) { if ((args == null) || (_contentList?.SelectedItem == null)) return; @@ -109,10 +109,15 @@ namespace Artemis.VisualScripting.Editor.Controls private bool Filter(object o) { if (o is not NodeData nodeData) return false; - if (string.IsNullOrWhiteSpace(SearchInput)) return true; - bool searchContains = nodeData.Name.Contains(SearchInput, StringComparison.OrdinalIgnoreCase) || - nodeData.Description.Contains(SearchInput, StringComparison.OrdinalIgnoreCase); + bool searchContains; + if (string.IsNullOrWhiteSpace(SearchInput)) + searchContains = true; + else + { + searchContains = nodeData.Name.Contains(SearchInput, StringComparison.OrdinalIgnoreCase) || + nodeData.Description.Contains(SearchInput, StringComparison.OrdinalIgnoreCase); + } if (SourcePin == null || SourcePin.Pin.Type == typeof(object)) return searchContains; diff --git a/src/Artemis.VisualScripting/Editor/Controls/VisualScriptNodePresenter.cs b/src/Artemis.VisualScripting/Editor/Controls/VisualScriptNodePresenter.cs index 17caa6d21..1f24ff5ba 100644 --- a/src/Artemis.VisualScripting/Editor/Controls/VisualScriptNodePresenter.cs +++ b/src/Artemis.VisualScripting/Editor/Controls/VisualScriptNodePresenter.cs @@ -54,6 +54,7 @@ namespace Artemis.VisualScripting.Editor.Controls public VisualScriptNodePresenter() { + Loaded += OnLoaded; Unloaded += OnUnloaded; } @@ -170,12 +171,28 @@ namespace Artemis.VisualScripting.Editor.Controls presenter.GetCustomViewModel(); } + private void OnLoaded(object sender, RoutedEventArgs e) + { + if (CustomViewModel != null) + CustomViewModel.NodeModified += CustomViewModelOnNodeModified; + } + private void OnUnloaded(object sender, RoutedEventArgs e) { - CustomViewModel?.OnDeactivate(); + if (CustomViewModel != null) + { + CustomViewModel.NodeModified -= CustomViewModelOnNodeModified; + CustomViewModel.OnDeactivate(); + } + CustomViewModel = null; } + private void CustomViewModelOnNodeModified(object? sender, EventArgs e) + { + Node.Script.OnScriptUpdated(); + } + #endregion } } \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Editor/Controls/VisualScriptPresenter.cs b/src/Artemis.VisualScripting/Editor/Controls/VisualScriptPresenter.cs index 751794540..d687d4324 100644 --- a/src/Artemis.VisualScripting/Editor/Controls/VisualScriptPresenter.cs +++ b/src/Artemis.VisualScripting/Editor/Controls/VisualScriptPresenter.cs @@ -171,6 +171,12 @@ namespace Artemis.VisualScripting.Editor.Controls #endregion + #region Events + + public event EventHandler ScriptUpdated; + + #endregion + #region Constructors public VisualScriptPresenter() @@ -236,6 +242,7 @@ namespace Artemis.VisualScripting.Editor.Controls { if (VisualScript != null) { + VisualScript.ScriptUpdated -= OnVisualScriptScriptUpdated; VisualScript.PropertyChanged -= OnVisualScriptPropertyChanged; VisualScript.NodeMoved -= OnVisualScriptNodeMoved; VisualScript.NodeCollectionChanged -= OnVisualScriptNodeCollectionChanged; @@ -245,6 +252,7 @@ namespace Artemis.VisualScripting.Editor.Controls if (VisualScript != null) { + VisualScript.ScriptUpdated += OnVisualScriptScriptUpdated; VisualScript.PropertyChanged += OnVisualScriptPropertyChanged; VisualScript.NodeMoved += OnVisualScriptNodeMoved; VisualScript.NodeCollectionChanged += OnVisualScriptNodeCollectionChanged; @@ -264,6 +272,11 @@ namespace Artemis.VisualScripting.Editor.Controls CenterAt(new Vector(0, 0)); } + private void OnVisualScriptScriptUpdated(object sender, EventArgs e) + { + ScriptUpdated?.Invoke(this, EventArgs.Empty); + } + private void OnVisualScriptPropertyChanged(object sender, PropertyChangedEventArgs args) { if (args.PropertyName == nameof(VisualScript.Cables)) @@ -528,7 +541,6 @@ namespace Artemis.VisualScripting.Editor.Controls if (nodeData == null) return; INode node = nodeData.CreateNode(Script, null); - node.Initialize(Script); node.X = _lastRightClickLocation.X - VisualScript.LocationOffset; node.Y = _lastRightClickLocation.Y - VisualScript.LocationOffset; @@ -554,6 +566,7 @@ namespace Artemis.VisualScripting.Editor.Controls _creationBoxParent.ContextMenu.IsOpen = false; Script.AddNode(node); + VisualScript.OnScriptUpdated(); } private void CenterAt(Vector vector) diff --git a/src/Artemis.VisualScripting/Editor/Controls/Wrapper/VisualScript.cs b/src/Artemis.VisualScripting/Editor/Controls/Wrapper/VisualScript.cs index 804e9872b..c3fb645ed 100644 --- a/src/Artemis.VisualScripting/Editor/Controls/Wrapper/VisualScript.cs +++ b/src/Artemis.VisualScripting/Editor/Controls/Wrapper/VisualScript.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; using System.ComponentModel; +using System.Diagnostics; using System.Linq; using System.Windows; using System.Windows.Threading; @@ -66,6 +67,7 @@ namespace Artemis.VisualScripting.Editor.Controls.Wrapper public event EventHandler NodeMoved; public event EventHandler NodeCollectionChanged; + public event EventHandler ScriptUpdated; #endregion @@ -201,6 +203,8 @@ namespace Artemis.VisualScripting.Editor.Controls.Wrapper { foreach (VisualScriptNode node in _selectedNodes) node.SnapNodeToGrid(); + + OnScriptUpdated(); } private void OnNodeDragMoving(object sender, VisualScriptNodeDragMovingEventArgs args) @@ -285,5 +289,10 @@ namespace Artemis.VisualScripting.Editor.Controls.Wrapper } #endregion + + public void OnScriptUpdated() + { + ScriptUpdated?.Invoke(this, EventArgs.Empty); + } } } diff --git a/src/Artemis.VisualScripting/Editor/Controls/Wrapper/VisualScriptNode.cs b/src/Artemis.VisualScripting/Editor/Controls/Wrapper/VisualScriptNode.cs index 081320492..07f70891d 100644 --- a/src/Artemis.VisualScripting/Editor/Controls/Wrapper/VisualScriptNode.cs +++ b/src/Artemis.VisualScripting/Editor/Controls/Wrapper/VisualScriptNode.cs @@ -280,6 +280,7 @@ namespace Artemis.VisualScripting.Editor.Controls.Wrapper { DisconnectAllPins(); Script.RemoveNode(this); + Script.OnScriptUpdated(); } private bool RemoveCanExecute() => !Node.IsExitNode && !Node.IsDefaultNode; diff --git a/src/Artemis.VisualScripting/Editor/Controls/Wrapper/VisualScriptPin.cs b/src/Artemis.VisualScripting/Editor/Controls/Wrapper/VisualScriptPin.cs index a0e8706fc..709cfeace 100644 --- a/src/Artemis.VisualScripting/Editor/Controls/Wrapper/VisualScriptPin.cs +++ b/src/Artemis.VisualScripting/Editor/Controls/Wrapper/VisualScriptPin.cs @@ -21,6 +21,7 @@ namespace Artemis.VisualScripting.Editor.Controls.Wrapper #region Properties & Fields private bool _isConnectionUpdated = false; + private bool _disconnectingAll = false; private VisualScriptPin _isConnectingPin; private VisualScriptCable _isConnectingCable; @@ -32,6 +33,8 @@ namespace Artemis.VisualScripting.Editor.Controls.Wrapper internal ObservableCollection InternalConnections { get; } = new(); private Point _absolutePosition; + + public Point AbsolutePosition { get => _absolutePosition; @@ -106,17 +109,22 @@ namespace Artemis.VisualScripting.Editor.Controls.Wrapper Node?.OnPinConnected(new PinConnectedEventArgs(this, cable)); + if (_isConnectingPin == null) + Node?.Script.OnScriptUpdated(); + _isConnectionUpdated = false; } public void DisconnectAll() { _isConnectionUpdated = true; + _disconnectingAll = true; List cables = InternalConnections.ToList(); foreach (VisualScriptCable cable in cables) cable.Disconnect(); + _disconnectingAll = false; _isConnectionUpdated = false; } @@ -129,6 +137,9 @@ namespace Artemis.VisualScripting.Editor.Controls.Wrapper Node?.OnPinDisconnected(new PinDisconnectedEventArgs(this, cable)); + if (!_disconnectingAll && _isConnectingPin == null) + Node?.Script.OnScriptUpdated(); + _isConnectionUpdated = false; } diff --git a/src/Artemis.VisualScripting/Editor/Controls/Wrapper/VisualScriptPinCollection.cs b/src/Artemis.VisualScripting/Editor/Controls/Wrapper/VisualScriptPinCollection.cs index 9aa6a3681..3de441b2f 100644 --- a/src/Artemis.VisualScripting/Editor/Controls/Wrapper/VisualScriptPinCollection.cs +++ b/src/Artemis.VisualScripting/Editor/Controls/Wrapper/VisualScriptPinCollection.cs @@ -57,6 +57,7 @@ namespace Artemis.VisualScripting.Editor.Controls.Wrapper visualScriptPin.DisconnectAll(); Pins.Remove(visualScriptPin); + Node.Script.OnScriptUpdated(); } private void OnPinCollectionPinAdded(object sender, SingleValueEventArgs args) @@ -66,6 +67,7 @@ namespace Artemis.VisualScripting.Editor.Controls.Wrapper VisualScriptPin visualScriptPin = new(Node, args.Value); _pinMapping.Add(args.Value, visualScriptPin); Pins.Add(visualScriptPin); + Node.Script.OnScriptUpdated(); } public void AddPin() => PinCollection.AddPin(); diff --git a/src/Artemis.VisualScripting/Nodes/Color/BrightenSKColorNode.cs b/src/Artemis.VisualScripting/Nodes/Color/BrightenSKColorNode.cs index fa28baeb3..4640cfde1 100644 --- a/src/Artemis.VisualScripting/Nodes/Color/BrightenSKColorNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Color/BrightenSKColorNode.cs @@ -9,12 +9,12 @@ namespace Artemis.VisualScripting.Nodes.Color public BrightenSKColorNode() : base("Brighten Color", "Brightens a color by a specified amount in percent") { Input = CreateInputPin("Color"); - Percentage = CreateInputPin("%"); + Percentage = CreateInputPin("%"); Output = CreateOutputPin(); } public InputPin Input { get; } - public InputPin Percentage { get; } + public InputPin Percentage { get; } public OutputPin Output { get; set; } public override void Evaluate() diff --git a/src/Artemis.VisualScripting/Nodes/Color/DarkenSKColorNode.cs b/src/Artemis.VisualScripting/Nodes/Color/DarkenSKColorNode.cs index ff8d20380..1eb6d8797 100644 --- a/src/Artemis.VisualScripting/Nodes/Color/DarkenSKColorNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Color/DarkenSKColorNode.cs @@ -9,12 +9,12 @@ namespace Artemis.VisualScripting.Nodes.Color public DarkenSKColorNode() : base("Darken Color", "Darkens a color by a specified amount in percent") { Input = CreateInputPin("Color"); - Percentage = CreateInputPin("%"); + Percentage = CreateInputPin("%"); Output = CreateOutputPin(); } public InputPin Input { get; } - public InputPin Percentage { get; } + public InputPin Percentage { get; } public OutputPin Output { get; set; } public override void Evaluate() diff --git a/src/Artemis.VisualScripting/Nodes/Color/DesaturateSKColorNode.cs b/src/Artemis.VisualScripting/Nodes/Color/DesaturateSKColorNode.cs index 399a6e516..384d0e08d 100644 --- a/src/Artemis.VisualScripting/Nodes/Color/DesaturateSKColorNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Color/DesaturateSKColorNode.cs @@ -10,12 +10,12 @@ namespace Artemis.VisualScripting.Nodes.Color public DesaturateSKColorNode() : base("Desaturate Color", "Desaturates a color by a specified amount in percent") { Input = CreateInputPin("Color"); - Percentage = CreateInputPin("%"); + Percentage = CreateInputPin("%"); Output = CreateOutputPin(); } public InputPin Input { get; } - public InputPin Percentage { get; } + public InputPin Percentage { get; } public OutputPin Output { get; set; } public override void Evaluate() diff --git a/src/Artemis.VisualScripting/Nodes/Color/RotateHueSkColorNode.cs b/src/Artemis.VisualScripting/Nodes/Color/RotateHueSkColorNode.cs index 35f6531b5..0f8abbe4d 100644 --- a/src/Artemis.VisualScripting/Nodes/Color/RotateHueSkColorNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Color/RotateHueSkColorNode.cs @@ -9,12 +9,12 @@ namespace Artemis.VisualScripting.Nodes.Color public RotateHueSKColorNode() : base("Rotate Color Hue", "Rotates the hue of a color by a specified amount in degrees") { Input = CreateInputPin("Color"); - Amount = CreateInputPin("Amount"); + Amount = CreateInputPin("Amount"); Output = CreateOutputPin(); } public InputPin Input { get; } - public InputPin Amount { get; } + public InputPin Amount { get; } public OutputPin Output { get; set; } public override void Evaluate() diff --git a/src/Artemis.VisualScripting/Nodes/Color/SaturateSkColorNode.cs b/src/Artemis.VisualScripting/Nodes/Color/SaturateSkColorNode.cs index 681ce2331..fffd17b69 100644 --- a/src/Artemis.VisualScripting/Nodes/Color/SaturateSkColorNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Color/SaturateSkColorNode.cs @@ -10,12 +10,12 @@ namespace Artemis.VisualScripting.Nodes.Color public SaturateSKColorNode() : base("Saturate Color", "Saturates a color by a specified amount in percent") { Input = CreateInputPin("Color"); - Percentage = CreateInputPin("%"); + Percentage = CreateInputPin("%"); Output = CreateOutputPin(); } public InputPin Input { get; } - public InputPin Percentage { get; } + public InputPin Percentage { get; } public OutputPin Output { get; set; } public override void Evaluate() diff --git a/src/Artemis.VisualScripting/Nodes/CustomViewModels/CustomNodeViewModel.cs b/src/Artemis.VisualScripting/Nodes/CustomViewModels/CustomNodeViewModel.cs index 1c7d23809..6231ba5de 100644 --- a/src/Artemis.VisualScripting/Nodes/CustomViewModels/CustomNodeViewModel.cs +++ b/src/Artemis.VisualScripting/Nodes/CustomViewModels/CustomNodeViewModel.cs @@ -1,4 +1,6 @@ -using Artemis.Core; +using System; +using System.ComponentModel; +using Artemis.Core; using Stylet; namespace Artemis.VisualScripting.Nodes.CustomViewModels @@ -17,11 +19,38 @@ namespace Artemis.VisualScripting.Nodes.CustomViewModels /// public virtual void OnActivate() { + Node.PropertyChanged += NodeOnPropertyChanged; } /// public virtual void OnDeactivate() { + Node.PropertyChanged -= NodeOnPropertyChanged; + } + + #endregion + + #region Events + + /// + public event EventHandler NodeModified; + + /// + /// Invokes the event + /// + protected virtual void OnNodeModified() + { + NodeModified?.Invoke(this, EventArgs.Empty); + } + + #endregion + + #region Event handlers + + private void NodeOnPropertyChanged(object sender, PropertyChangedEventArgs e) + { + if (e.PropertyName == "Storage") + OnNodeModified(); } #endregion diff --git a/src/Artemis.VisualScripting/Nodes/CustomViews/StaticDoubleValueNodeCustomView.xaml b/src/Artemis.VisualScripting/Nodes/CustomViews/StaticDoubleValueNodeCustomView.xaml deleted file mode 100644 index 17731036d..000000000 --- a/src/Artemis.VisualScripting/Nodes/CustomViews/StaticDoubleValueNodeCustomView.xaml +++ /dev/null @@ -1,12 +0,0 @@ - - - diff --git a/src/Artemis.VisualScripting/Nodes/CustomViews/StaticIntegerValueNodeCustomView.xaml b/src/Artemis.VisualScripting/Nodes/CustomViews/StaticIntegerValueNodeCustomView.xaml deleted file mode 100644 index 66f828f08..000000000 --- a/src/Artemis.VisualScripting/Nodes/CustomViews/StaticIntegerValueNodeCustomView.xaml +++ /dev/null @@ -1,12 +0,0 @@ - - - diff --git a/src/Artemis.VisualScripting/Nodes/Easing/IntEasingNode.cs b/src/Artemis.VisualScripting/Nodes/Easing/IntEasingNode.cs deleted file mode 100644 index cfb48808b..000000000 --- a/src/Artemis.VisualScripting/Nodes/Easing/IntEasingNode.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System; -using Artemis.Core; - -namespace Artemis.VisualScripting.Nodes.Easing -{ - [Node("Integer Easing", "Outputs an eased integer value", "Easing", InputType = typeof(int), OutputType = typeof(int))] - public class IntEasingNode : Node - { - private DateTime _lastEvaluate = DateTime.MinValue; - private float _progress; - private int _currentValue; - private int _sourceValue; - private int _targetValue; - - public IntEasingNode() : base("Integer Easing", "Outputs an eased integer value") - { - Input = CreateInputPin(); - EasingTime = CreateInputPin("delay"); - EasingFunction = CreateInputPin("function"); - - Output = CreateOutputPin(); - } - - public InputPin Input { get; set; } - public InputPin EasingTime { get; set; } - public InputPin EasingFunction { get; set; } - - public OutputPin Output { get; set; } - - public override void Evaluate() - { - DateTime now = DateTime.Now; - - // If the value changed reset progress - if (_targetValue != Input.Value) - { - _sourceValue = _currentValue; - _targetValue = Input.Value; - _progress = 0f; - } - - // Update until finished - if (_progress < 1f) - { - Update(); - Output.Value = _currentValue; - } - // Stop updating past 1 and use the target value - else - { - Output.Value = _targetValue; - } - - _lastEvaluate = now; - } - - private void Update() - { - TimeSpan delta = DateTime.Now - _lastEvaluate; - - // In case of odd delta's, keep progress between 0f and 1f - _progress = Math.Clamp(_progress + (float) delta.TotalMilliseconds / EasingTime.Value, 0f, 1f); - - double eased = _sourceValue + (_targetValue - _sourceValue) * Easings.Interpolate(_progress, EasingFunction.Value); - _currentValue = (int) Math.Round(eased, MidpointRounding.AwayFromZero); - } - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Easing/FloatEasingNode.cs b/src/Artemis.VisualScripting/Nodes/Easing/NumericEasingNode.cs similarity index 100% rename from src/Artemis.VisualScripting/Nodes/Easing/FloatEasingNode.cs rename to src/Artemis.VisualScripting/Nodes/Easing/NumericEasingNode.cs diff --git a/src/Artemis.VisualScripting/Nodes/Easing/SKColorEasingNode.cs b/src/Artemis.VisualScripting/Nodes/Easing/SKColorEasingNode.cs index 7bf87b0ab..76d76e690 100644 --- a/src/Artemis.VisualScripting/Nodes/Easing/SKColorEasingNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Easing/SKColorEasingNode.cs @@ -16,14 +16,14 @@ namespace Artemis.VisualScripting.Nodes.Easing public SKColorEasingNode() : base("Color Easing", "Outputs an eased color value") { Input = CreateInputPin(); - EasingTime = CreateInputPin("delay"); + EasingTime = CreateInputPin("delay"); EasingFunction = CreateInputPin("function"); Output = CreateOutputPin(); } public InputPin Input { get; set; } - public InputPin EasingTime { get; set; } + public InputPin EasingTime { get; set; } public InputPin EasingFunction { get; set; } public OutputPin Output { get; set; }