From e7ce16ba73ee66a322f2a5fffd8561a368f5a7fb Mon Sep 17 00:00:00 2001 From: SpoinkyNL Date: Sun, 25 Oct 2020 22:32:38 +0100 Subject: [PATCH] Data model conditions - Expanded events UI logic --- .../Abstract/DataModelConditionPart.cs | 32 ++++++- .../Conditions/DataModelConditionEvent.cs | 7 +- .../Conditions/DataModelConditionGroup.cs | 4 +- .../Models/Profile/DataModel/DataModelPath.cs | 7 ++ src/Artemis.Core/Models/Profile/Layer.cs | 89 ++++++++++++++----- .../Shared/DataModelPropertiesViewModel.cs | 12 +-- .../Shared/DataModelVisualizationViewModel.cs | 8 +- .../Extensions/DataModelWrapperExtensions.cs | 22 +++-- .../DataModelConditionGroupView.xaml | 17 +++- .../DataModelConditionGroupViewModel.cs | 16 +++- ...taModelConditionEventPredicateViewModel.cs | 5 +- ...ModelConditionGeneralPredicateViewModel.cs | 13 ++- .../DisplayConditionsView.xaml | 12 +++ .../DisplayConditionsViewModel.cs | 30 ++++++- .../PluginDataModelExpansion.cs | 6 ++ 15 files changed, 226 insertions(+), 54 deletions(-) diff --git a/src/Artemis.Core/Models/Profile/Conditions/Abstract/DataModelConditionPart.cs b/src/Artemis.Core/Models/Profile/Conditions/Abstract/DataModelConditionPart.cs index bca0ebc4d..c42ef85ae 100644 --- a/src/Artemis.Core/Models/Profile/Conditions/Abstract/DataModelConditionPart.cs +++ b/src/Artemis.Core/Models/Profile/Conditions/Abstract/DataModelConditionPart.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Linq; using Artemis.Storage.Entities.Profile.Abstract; namespace Artemis.Core @@ -36,6 +37,8 @@ namespace Artemis.Core _children.Insert(index.Value, dataModelConditionPart); else _children.Add(dataModelConditionPart); + + OnChildAdded(); } } @@ -49,9 +52,19 @@ namespace Artemis.Core { dataModelConditionPart.Parent = null; _children.Remove(dataModelConditionPart); + OnChildRemoved(); } } + /// + /// Removes all children. You monster. + /// + public void ClearChildren() + { + while (Children.Any()) + RemoveChild(Children[0]); + } + /// /// Evaluates the condition part on the data model /// @@ -71,7 +84,7 @@ namespace Artemis.Core #region IDisposable /// - /// Disposed the condition part + /// Disposed the condition part /// protected virtual void Dispose(bool disposing) { @@ -88,5 +101,22 @@ namespace Artemis.Core } #endregion + + #region Events + + public event EventHandler ChildAdded; + public event EventHandler ChildRemoved; + + protected virtual void OnChildAdded() + { + ChildAdded?.Invoke(this, EventArgs.Empty); + } + + protected virtual void OnChildRemoved() + { + ChildRemoved?.Invoke(this, EventArgs.Empty); + } + + #endregion } } \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/Conditions/DataModelConditionEvent.cs b/src/Artemis.Core/Models/Profile/Conditions/DataModelConditionEvent.cs index 53f1f27c8..009f1504f 100644 --- a/src/Artemis.Core/Models/Profile/Conditions/DataModelConditionEvent.cs +++ b/src/Artemis.Core/Models/Profile/Conditions/DataModelConditionEvent.cs @@ -43,7 +43,7 @@ namespace Artemis.Core public Type? EventArgumentType { get; set; } internal DataModelConditionEventEntity Entity { get; set; } - + /// public override bool Evaluate() { @@ -93,8 +93,7 @@ namespace Artemis.Core SubscribeToEventPath(); // Remove the old root group that was tied to the old data model - while (Children.Any()) - RemoveChild(Children[0]); + ClearChildren(); if (EventPath != null) { @@ -164,6 +163,8 @@ namespace Artemis.Core internal void Initialize() { + ClearChildren(); + if (Entity.EventPath == null) return; diff --git a/src/Artemis.Core/Models/Profile/Conditions/DataModelConditionGroup.cs b/src/Artemis.Core/Models/Profile/Conditions/DataModelConditionGroup.cs index d96d7065d..b25050d15 100644 --- a/src/Artemis.Core/Models/Profile/Conditions/DataModelConditionGroup.cs +++ b/src/Artemis.Core/Models/Profile/Conditions/DataModelConditionGroup.cs @@ -45,7 +45,9 @@ namespace Artemis.Core else if (childEntity is DataModelConditionGeneralPredicateEntity predicateEntity) AddChild(new DataModelConditionGeneralPredicate(this, predicateEntity)); else if (childEntity is DataModelConditionListPredicateEntity listPredicateEntity) - AddChild(new DataModelConditionListPredicate(this, listPredicateEntity)); + AddChild(new DataModelConditionListPredicate(this, listPredicateEntity)); + else if (childEntity is DataModelConditionEventPredicateEntity eventPredicateEntity) + AddChild(new DataModelConditionEventPredicate(this, eventPredicateEntity)); } } diff --git a/src/Artemis.Core/Models/Profile/DataModel/DataModelPath.cs b/src/Artemis.Core/Models/Profile/DataModel/DataModelPath.cs index bd4f0b540..7d3897870 100644 --- a/src/Artemis.Core/Models/Profile/DataModel/DataModelPath.cs +++ b/src/Artemis.Core/Models/Profile/DataModel/DataModelPath.cs @@ -281,6 +281,13 @@ namespace Artemis.Core Entity.Path = Path; Entity.DataModelGuid = DataModelGuid; + + Entity.WrapperType = Target switch + { + ListPredicateWrapperDataModel _ => PathWrapperType.List, + EventPredicateWrapperDataModel _ => PathWrapperType.Event, + _ => PathWrapperType.None + }; } #endregion diff --git a/src/Artemis.Core/Models/Profile/Layer.cs b/src/Artemis.Core/Models/Profile/Layer.cs index 8e0e66ab2..398011573 100644 --- a/src/Artemis.Core/Models/Profile/Layer.cs +++ b/src/Artemis.Core/Models/Profile/Layer.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; -using System.Diagnostics; using System.Linq; using Artemis.Core.LayerBrushes; using Artemis.Core.LayerEffects; @@ -68,27 +67,6 @@ namespace Artemis.Core Initialize(); } - internal LayerEntity LayerEntity { get; set; } - - /// - public override List GetAllLayerProperties() - { - List result = new List(); - result.AddRange(General.GetAllLayerProperties()); - result.AddRange(Transform.GetAllLayerProperties()); - if (LayerBrush?.BaseProperties != null) - result.AddRange(LayerBrush.BaseProperties.GetAllLayerProperties()); - foreach (BaseLayerEffect layerEffect in LayerEffects) - { - if (layerEffect.BaseProperties != null) - result.AddRange(layerEffect.BaseProperties.GetAllLayerProperties()); - } - - return result; - } - - internal override RenderElementEntity RenderElementEntity => LayerEntity; - /// /// A collection of all the LEDs this layer is assigned to. /// @@ -131,6 +109,25 @@ namespace Artemis.Core internal set => SetAndNotify(ref _layerBrush, value); } + internal LayerEntity LayerEntity { get; set; } + + internal override RenderElementEntity RenderElementEntity => LayerEntity; + + /// + public override List GetAllLayerProperties() + { + List result = new List(); + result.AddRange(General.GetAllLayerProperties()); + result.AddRange(Transform.GetAllLayerProperties()); + if (LayerBrush?.BaseProperties != null) + result.AddRange(LayerBrush.BaseProperties.GetAllLayerProperties()); + foreach (BaseLayerEffect layerEffect in LayerEffects) + if (layerEffect.BaseProperties != null) + result.AddRange(layerEffect.BaseProperties.GetAllLayerProperties()); + + return result; + } + /// public override string ToString() { @@ -309,7 +306,9 @@ namespace Artemis.Core if (stickToMainSegment) { if (!DisplayContinuously) + { TimelinePosition = StartSegmentLength + timeOverride; + } else { double progress = timeOverride.TotalMilliseconds % MainSegmentLength.TotalMilliseconds; @@ -320,7 +319,9 @@ namespace Artemis.Core } } else + { TimelinePosition = timeOverride; + } double delta = (TimelinePosition - beginTime).TotalSeconds; @@ -356,7 +357,9 @@ namespace Artemis.Core return; if (_layerBitmap == null) + { _layerBitmap = new SKBitmap(new SKImageInfo((int) Path.Bounds.Width, (int) Path.Bounds.Height)); + } else if (_layerBitmap.Info.Width != (int) Path.Bounds.Width || _layerBitmap.Info.Height != (int) Path.Bounds.Height) { _layerBitmap.Dispose(); @@ -388,7 +391,7 @@ namespace Artemis.Core else if (General.ResizeMode.CurrentValue == LayerResizeMode.Clip) ClipRender(layerCanvas, _layerBitmap.Info, layerPaint, layerPath); - using SKPaint canvasPaint = new SKPaint { BlendMode = General.BlendMode.CurrentValue }; + using SKPaint canvasPaint = new SKPaint {BlendMode = General.BlendMode.CurrentValue}; foreach (BaseLayerEffect baseLayerEffect in LayerEffects.Where(e => e.Enabled)) baseLayerEffect.PostProcess(layerCanvas, _layerBitmap.Info, layerPath, canvasPaint); @@ -475,7 +478,9 @@ namespace Artemis.Core throw new ObjectDisposedException("Layer"); if (!Leds.Any()) + { Path = new SKPath(); + } else { SKPath path = new SKPath {FillType = SKPathFillType.Winding}; @@ -548,6 +553,44 @@ namespace Artemis.Core } } + /// + /// Creates a transformation matrix that applies the current transformation settings + /// + /// + /// If true, treats the layer as if it is located at 0,0 instead of its actual position on the + /// surface + /// + /// The transformation matrix containing the current transformation settings + public SKMatrix GetTransformMatrix(bool zeroBased) + { + if (_disposed) + throw new ObjectDisposedException("Layer"); + + SKSize sizeProperty = Transform.Scale.CurrentValue; + float rotationProperty = Transform.Rotation.CurrentValue; + + SKPoint anchorPosition = GetLayerAnchorPosition(Path, zeroBased); + SKPoint anchorProperty = Transform.AnchorPoint.CurrentValue; + + // Translation originates from the unscaled center of the shape and is tied to the anchor + float x = anchorPosition.X - (zeroBased ? Bounds.MidX - Bounds.Left : Bounds.MidX) - anchorProperty.X * Bounds.Width; + float y = anchorPosition.Y - (zeroBased ? Bounds.MidY - Bounds.Top : Bounds.MidY) - anchorProperty.Y * Bounds.Height; + + if (General.ResizeMode == LayerResizeMode.Normal) + { + SKMatrix transform = SKMatrix.MakeTranslation(x, y); + transform = transform.PostConcat(SKMatrix.MakeRotationDegrees(rotationProperty, anchorPosition.X, anchorPosition.Y)); + transform = transform.PostConcat(SKMatrix.MakeScale(sizeProperty.Width / 100f, sizeProperty.Height / 100f, anchorPosition.X, anchorPosition.Y)); + return transform; + } + else + { + SKMatrix transform = SKMatrix.MakeTranslation(x, y); + transform = transform.PostConcat(SKMatrix.MakeRotationDegrees(rotationProperty * -1, anchorPosition.X, anchorPosition.Y)); + return transform; + } + } + /// /// Excludes the provided path from the translations applied to the layer by applying translations that cancel the /// layer translations out diff --git a/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelPropertiesViewModel.cs b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelPropertiesViewModel.cs index 2a66363ec..420551577 100644 --- a/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelPropertiesViewModel.cs +++ b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelPropertiesViewModel.cs @@ -29,19 +29,19 @@ namespace Artemis.UI.Shared public override void Update(IDataModelUIService dataModelUIService) { DisplayValueType = DataModelPath?.GetPropertyType(); - + // Only set a display value if ToString returns useful information and not just the type name object currentValue = GetCurrentValue(); if (currentValue != null && currentValue.ToString() != currentValue.GetType().ToString()) DisplayValue = currentValue.ToString(); else DisplayValue = null; - + // Always populate properties PopulateProperties(dataModelUIService); // Only update children if the parent is expanded - if (Parent != null && !Parent.IsVisualizationExpanded && !Parent.IsRootViewModel) + if (Parent != null && !Parent.IsRootViewModel && !Parent.IsVisualizationExpanded) return; foreach (DataModelVisualizationViewModel dataModelVisualizationViewModel in Children) @@ -50,9 +50,9 @@ namespace Artemis.UI.Shared public override object GetCurrentValue() { - if (Parent == null) - return null; - return Parent.IsRootViewModel ? DataModel : base.GetCurrentValue(); + if (Parent == null || Parent.IsRootViewModel || IsRootViewModel) + return DataModel; + return base.GetCurrentValue(); } /// diff --git a/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelVisualizationViewModel.cs b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelVisualizationViewModel.cs index 6892a1c33..facaac227 100644 --- a/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelVisualizationViewModel.cs +++ b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelVisualizationViewModel.cs @@ -28,7 +28,7 @@ namespace Artemis.UI.Shared Children = new BindableCollection(); IsMatchingFilteredTypes = true; - if (dataModel == null && parent == null && dataModelPath == null) + if (parent == null) IsRootViewModel = true; else PropertyDescription = DataModelPath?.GetPropertyDescription() ?? DataModel.DataModelDescription; @@ -184,7 +184,10 @@ namespace Artemis.UI.Shared internal void PopulateProperties(IDataModelUIService dataModelUIService) { - if (IsRootViewModel) + // if (IsRootViewModel) + // return; + + if (Parent == null && DataModel == null) return; Type modelType = Parent == null || Parent.IsRootViewModel ? DataModel.GetType() : DataModelPath.GetPropertyType(); @@ -235,6 +238,7 @@ namespace Artemis.UI.Shared if (toRemoveDynamic.Any()) Children.RemoveRange(toRemoveDynamic); } + private DataModelVisualizationViewModel CreateChild(IDataModelUIService dataModelUIService, string path, int depth) { if (depth > MaxDepth) diff --git a/src/Artemis.UI.Shared/Extensions/DataModelWrapperExtensions.cs b/src/Artemis.UI.Shared/Extensions/DataModelWrapperExtensions.cs index fe4b6b2e8..de5bf9c94 100644 --- a/src/Artemis.UI.Shared/Extensions/DataModelWrapperExtensions.cs +++ b/src/Artemis.UI.Shared/Extensions/DataModelWrapperExtensions.cs @@ -1,17 +1,29 @@ -using Artemis.Core; +using System.Linq; +using Artemis.Core; +using Artemis.UI.Shared.Services; namespace Artemis.UI.Shared { public static class DataModelWrapperExtensions { - public static DataModelPropertiesViewModel CreateViewModel(this EventPredicateWrapperDataModel wrapper) + public static DataModelPropertiesViewModel CreateViewModel(this EventPredicateWrapperDataModel wrapper, IDataModelUIService dataModelUIService) { - return new DataModelPropertiesViewModel(wrapper, null, new DataModelPath(wrapper)); + DataModelPropertiesViewModel viewModel = new DataModelPropertiesViewModel(wrapper, null, new DataModelPath(wrapper)); + viewModel.Update(dataModelUIService); + viewModel.UpdateRequested += (sender, args) => viewModel.Update(dataModelUIService); + viewModel.Children.First().IsVisualizationExpanded = true; + + return viewModel; } - public static DataModelPropertiesViewModel CreateViewModel(this ListPredicateWrapperDataModel wrapper) + public static DataModelPropertiesViewModel CreateViewModel(this ListPredicateWrapperDataModel wrapper, IDataModelUIService dataModelUIService) { - return new DataModelPropertiesViewModel(wrapper, null, new DataModelPath(wrapper)); + DataModelPropertiesViewModel viewModel = new DataModelPropertiesViewModel(wrapper, null, new DataModelPath(wrapper)); + viewModel.Update(dataModelUIService); + viewModel.UpdateRequested += (sender, args) => viewModel.Update(dataModelUIService); + viewModel.Children.First().IsVisualizationExpanded = true; + + return viewModel; } } } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/ProfileEditor/Conditions/DataModelConditionGroupView.xaml b/src/Artemis.UI/Screens/ProfileEditor/Conditions/DataModelConditionGroupView.xaml index 51db5e501..7507ef77a 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/Conditions/DataModelConditionGroupView.xaml +++ b/src/Artemis.UI/Screens/ProfileEditor/Conditions/DataModelConditionGroupView.xaml @@ -17,7 +17,7 @@ - + @@ -45,13 +45,24 @@