From 3220ded4eb9fc4ae35b24e6bd03ef811511d981e Mon Sep 17 00:00:00 2001 From: SpoinkyNL Date: Tue, 27 Oct 2020 20:58:41 +0100 Subject: [PATCH] Layers - Fixed a bunch of timeline issues with events --- .../Conditions/DataModelConditionGroup.cs | 20 +++++++-- src/Artemis.Core/Models/Profile/Folder.cs | 5 +-- src/Artemis.Core/Models/Profile/Layer.cs | 43 ++++++++----------- .../Profile/LayerProperties/ILayerProperty.cs | 8 ++-- .../Profile/LayerProperties/LayerProperty.cs | 27 ++++-------- .../Models/Profile/LayerPropertyGroup.cs | 27 +++--------- .../Services/ProfileEditorService.cs | 12 ++---- 7 files changed, 57 insertions(+), 85 deletions(-) diff --git a/src/Artemis.Core/Models/Profile/Conditions/DataModelConditionGroup.cs b/src/Artemis.Core/Models/Profile/Conditions/DataModelConditionGroup.cs index 449a68b74..2b44acb40 100644 --- a/src/Artemis.Core/Models/Profile/Conditions/DataModelConditionGroup.cs +++ b/src/Artemis.Core/Models/Profile/Conditions/DataModelConditionGroup.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Linq; using Artemis.Storage.Entities.Profile.Abstract; using Artemis.Storage.Entities.Profile.Conditions; @@ -82,16 +84,26 @@ namespace Artemis.Core if (Children.Count == 1) return Children[0].Evaluate(); + if (ContainsEvents) + { + bool eventTriggered = Children.Where(c => c is DataModelConditionEvent).Any(c => c.Evaluate()); + return eventTriggered && EvaluateWithOperator(Children.Where(c => !(c is DataModelConditionEvent))); + } + return EvaluateWithOperator(Children); + } + + private bool EvaluateWithOperator(IEnumerable targets) + { switch (BooleanOperator) { case BooleanOperator.And: - return Children.All(c => c.Evaluate()); + return targets.All(c => c.Evaluate()); case BooleanOperator.Or: - return Children.Any(c => c.Evaluate()); + return targets.Any(c => c.Evaluate()); case BooleanOperator.AndNot: - return Children.All(c => !c.Evaluate()); + return targets.All(c => !c.Evaluate()); case BooleanOperator.OrNot: - return Children.Any(c => !c.Evaluate()); + return targets.Any(c => !c.Evaluate()); default: throw new ArgumentOutOfRangeException(); } diff --git a/src/Artemis.Core/Models/Profile/Folder.cs b/src/Artemis.Core/Models/Profile/Folder.cs index 0dfb96dd2..07733c0c4 100644 --- a/src/Artemis.Core/Models/Profile/Folder.cs +++ b/src/Artemis.Core/Models/Profile/Folder.cs @@ -97,9 +97,6 @@ namespace Artemis.Core TimeLine = TimelineLength; ExtraTimeLines.Clear(); - foreach (BaseLayerEffect baseLayerEffect in LayerEffects.Where(e => e.Enabled)) - baseLayerEffect.BaseProperties?.Reset(); - foreach (ProfileElement child in Children) child.Reset(); } @@ -234,7 +231,7 @@ namespace Artemis.Core foreach (BaseLayerEffect baseLayerEffect in LayerEffects.Where(e => e.Enabled)) { - baseLayerEffect.BaseProperties?.Update(renderDelta); + baseLayerEffect.BaseProperties?.Update(timeLine, renderDelta); baseLayerEffect.Update(renderDelta); } diff --git a/src/Artemis.Core/Models/Profile/Layer.cs b/src/Artemis.Core/Models/Profile/Layer.cs index a920689eb..30c3aae39 100644 --- a/src/Artemis.Core/Models/Profile/Layer.cs +++ b/src/Artemis.Core/Models/Profile/Layer.cs @@ -182,13 +182,6 @@ namespace Artemis.Core DisplayConditionMet = false; TimeLine = TimelineLength; ExtraTimeLines.Clear(); - - General.Reset(); - Transform.Reset(); - LayerBrush.BaseProperties?.Reset(); - - foreach (BaseLayerEffect baseLayerEffect in LayerEffects.Where(e => e.Enabled)) - baseLayerEffect.BaseProperties?.Reset(); } #region Storage @@ -265,7 +258,7 @@ namespace Artemis.Core #endregion #region Rendering - + private TimeSpan _lastRenderTime; /// @@ -288,7 +281,7 @@ namespace Artemis.Core { TimelineLength = StartSegmentLength + MainSegmentLength + EndSegmentLength; } - + /// public override void Render(SKCanvas canvas, SKImageInfo canvasInfo) { @@ -306,43 +299,43 @@ namespace Artemis.Core return; RenderLayer(TimeLine, canvas); - foreach (TimeSpan extraTimeLine in ExtraTimeLines) + foreach (TimeSpan extraTimeLine in ExtraTimeLines) RenderLayer(extraTimeLine, canvas); } - private void PrepareForRender(TimeSpan timeLine) + private void PrepareForRender(TimeSpan renderTime) { - double renderDelta = (timeLine - _lastRenderTime).TotalSeconds; + double renderDelta = (renderTime - _lastRenderTime).TotalSeconds; - General.Update(renderDelta); - Transform.Update(renderDelta); - LayerBrush.BaseProperties?.Update(renderDelta); + General.Update(renderTime, renderDelta); + Transform.Update(renderTime, renderDelta); + LayerBrush.BaseProperties?.Update(renderTime, renderDelta); LayerBrush.Update(renderDelta); - + foreach (BaseLayerEffect baseLayerEffect in LayerEffects.Where(e => e.Enabled)) { - baseLayerEffect.BaseProperties?.Update(renderDelta); + baseLayerEffect.BaseProperties?.Update(renderTime, renderDelta); baseLayerEffect.Update(renderDelta); } - _lastRenderTime = timeLine; + _lastRenderTime = renderTime; } private void RenderLayer(TimeSpan timeLine, SKCanvas canvas) { - if (timeLine > TimelineLength || timeLine == TimeSpan.Zero && !DisplayConditionMet) + if (timeLine > TimelineLength) return; - + PrepareForRender(timeLine); if (_layerBitmap == null) { - _layerBitmap = new SKBitmap(new SKImageInfo((int)Path.Bounds.Width, (int)Path.Bounds.Height)); + _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) + else if (_layerBitmap.Info.Width != (int) Path.Bounds.Width || _layerBitmap.Info.Height != (int) Path.Bounds.Height) { _layerBitmap.Dispose(); - _layerBitmap = new SKBitmap(new SKImageInfo((int)Path.Bounds.Width, (int)Path.Bounds.Height)); + _layerBitmap = new SKBitmap(new SKImageInfo((int) Path.Bounds.Width, (int) Path.Bounds.Height)); } using SKPath layerPath = new SKPath(Path); @@ -350,7 +343,7 @@ namespace Artemis.Core using SKPaint layerPaint = new SKPaint { FilterQuality = SKFilterQuality.Low, - Color = new SKColor(0, 0, 0, (byte)(Transform.Opacity.CurrentValue * 2.55f)) + Color = new SKColor(0, 0, 0, (byte) (Transform.Opacity.CurrentValue * 2.55f)) }; layerCanvas.Clear(); @@ -370,7 +363,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); diff --git a/src/Artemis.Core/Models/Profile/LayerProperties/ILayerProperty.cs b/src/Artemis.Core/Models/Profile/LayerProperties/ILayerProperty.cs index 73e0d4a69..9c5f381db 100644 --- a/src/Artemis.Core/Models/Profile/LayerProperties/ILayerProperty.cs +++ b/src/Artemis.Core/Models/Profile/LayerProperties/ILayerProperty.cs @@ -11,7 +11,7 @@ namespace Artemis.Core /// initialize these for you. /// /// - public interface ILayerProperty : IStorageModel, IUpdateModel, IDisposable + public interface ILayerProperty : IStorageModel, IDisposable { /// /// Gets the description attribute applied to this property @@ -38,8 +38,10 @@ namespace Artemis.Core List GetAllDataBindingRegistrations(); /// - /// Resets the internal state of the property + /// Updates the layer properties internal state /// - void Reset(); + /// The current position in the timeline + /// The position difference since last update + void Update(TimeSpan renderTime, double deltaTime); } } \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs b/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs index c86ed4277..ca08aa337 100644 --- a/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs +++ b/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs @@ -19,7 +19,6 @@ namespace Artemis.Core public class LayerProperty : ILayerProperty { private bool _disposed; - private TimeSpan _keyframeProgress; /// /// Creates a new instance of the class @@ -38,16 +37,15 @@ namespace Artemis.Core /// /// Updates the property, applying keyframes and data bindings to the current value /// - public void Update(double deltaTime) + public void Update(TimeSpan time, double deltaTime) { if (_disposed) throw new ObjectDisposedException("LayerProperty"); CurrentValue = BaseValue; - _keyframeProgress = _keyframeProgress.Add(TimeSpan.FromSeconds(deltaTime)); - + if (ProfileElement.ApplyKeyframesEnabled) - UpdateKeyframes(deltaTime); + UpdateKeyframes(time); if (ProfileElement.ApplyDataBindingsEnabled) UpdateDataBindings(deltaTime); @@ -127,7 +125,7 @@ namespace Artemis.Core return; _baseValue = value; - Update(0); + Update(ProfileElement.TimeLine, 0); OnCurrentValueSet(); } } @@ -171,7 +169,7 @@ namespace Artemis.Core // Force an update so that the base value is applied to the current value and // keyframes/data bindings are applied using the new base value - Update(0); + Update(ProfileElement.TimeLine, 0); OnCurrentValueSet(); } @@ -296,13 +294,13 @@ namespace Artemis.Core _keyframes = _keyframes.OrderBy(k => k.Position).ToList(); } - private void UpdateKeyframes(double deltaTime) + private void UpdateKeyframes(TimeSpan time) { if (!KeyframesSupported || !KeyframesEnabled) return; // The current keyframe is the last keyframe before the current time - CurrentKeyframe = _keyframes.LastOrDefault(k => k.Position <= _keyframeProgress); + CurrentKeyframe = _keyframes.LastOrDefault(k => k.Position <= time); // Keyframes are sorted by position so we can safely assume the next keyframe's position is after the current int nextIndex = _keyframes.IndexOf(CurrentKeyframe) + 1; NextKeyframe = _keyframes.Count > nextIndex ? _keyframes[nextIndex] : null; @@ -316,7 +314,7 @@ namespace Artemis.Core else { TimeSpan timeDiff = NextKeyframe.Position - CurrentKeyframe.Position; - float keyframeProgress = (float) ((_keyframeProgress - CurrentKeyframe.Position).TotalMilliseconds / timeDiff.TotalMilliseconds); + float keyframeProgress = (float) ((time - CurrentKeyframe.Position).TotalMilliseconds / timeDiff.TotalMilliseconds); float keyframeProgressEased = (float) Easings.Interpolate(keyframeProgress, CurrentKeyframe.EasingFunction); UpdateCurrentValue(keyframeProgress, keyframeProgressEased); } @@ -363,13 +361,7 @@ namespace Artemis.Core { return _dataBindingRegistrations; } - - /// - public void Reset() - { - _keyframeProgress = TimeSpan.Zero; - } - + public void RegisterDataBindingProperty(Expression> propertyExpression, DataBindingConverter converter) { if (_disposed) @@ -460,7 +452,6 @@ namespace Artemis.Core Entity = entity ?? throw new ArgumentNullException(nameof(entity)); PropertyDescription = description ?? throw new ArgumentNullException(nameof(description)); IsLoadedFromStorage = fromStorage; - LayerPropertyGroup.PropertyGroupUpdating += (sender, args) => Update(args.DeltaTime); } /// diff --git a/src/Artemis.Core/Models/Profile/LayerPropertyGroup.cs b/src/Artemis.Core/Models/Profile/LayerPropertyGroup.cs index 5de2a87f1..a9cb08a99 100644 --- a/src/Artemis.Core/Models/Profile/LayerPropertyGroup.cs +++ b/src/Artemis.Core/Models/Profile/LayerPropertyGroup.cs @@ -198,11 +198,12 @@ namespace Artemis.Core layerPropertyGroup.ApplyToEntity(); } - internal void Update(double deltaTime) + internal void Update(TimeSpan renderTime, double deltaTime) { - // Since at this point we don't know what properties the group has without using reflection, - // let properties subscribe to the update event and update themselves - OnPropertyGroupUpdating(new LayerPropertyGroupUpdatingEventArgs(deltaTime)); + foreach (ILayerProperty layerProperty in LayerProperties) + layerProperty.Update(renderTime, deltaTime); + foreach (LayerPropertyGroup layerPropertyGroup in LayerPropertyGroups) + layerPropertyGroup.Update(renderTime, deltaTime); } private void InitializeProperty(PropertyInfo propertyInfo, PropertyDescriptionAttribute propertyDescription) @@ -266,8 +267,6 @@ namespace Artemis.Core #region Events - internal event EventHandler PropertyGroupUpdating; - /// /// Occurs when the property group has initialized all its children /// @@ -284,11 +283,6 @@ namespace Artemis.Core /// public event EventHandler VisibilityChanged; - internal virtual void OnPropertyGroupUpdating(LayerPropertyGroupUpdatingEventArgs e) - { - PropertyGroupUpdating?.Invoke(this, e); - } - internal virtual void OnVisibilityChanged() { VisibilityChanged?.Invoke(this, EventArgs.Empty); @@ -300,16 +294,5 @@ namespace Artemis.Core } #endregion - - /// - /// Resets the internal state of the property group - /// - public void Reset() - { - foreach (ILayerProperty layerProperty in LayerProperties) - layerProperty.Reset(); - foreach (LayerPropertyGroup layerPropertyGroup in LayerPropertyGroups) - layerPropertyGroup.Reset(); - } } } \ No newline at end of file diff --git a/src/Artemis.UI.Shared/Services/ProfileEditorService.cs b/src/Artemis.UI.Shared/Services/ProfileEditorService.cs index 1cce0362c..6b7b8d719 100644 --- a/src/Artemis.UI.Shared/Services/ProfileEditorService.cs +++ b/src/Artemis.UI.Shared/Services/ProfileEditorService.cs @@ -22,7 +22,6 @@ namespace Artemis.UI.Shared.Services private readonly object _selectedProfileLock = new object(); private TimeSpan _currentTime; private int _pixelsPerSecond; - private bool _previewInvalidated; public ProfileEditorService(IProfileService profileService, IKernel kernel, ILogger logger, ICoreService coreService) { @@ -31,19 +30,14 @@ namespace Artemis.UI.Shared.Services _coreService = coreService; _registeredPropertyEditors = new List(); - _coreService.FrameRendered += CoreServiceOnFrameRendered; - Kernel = kernel; PixelsPerSecond = 100; } private void CoreServiceOnFrameRendered(object? sender, FrameRenderedEventArgs e) { - if (_previewInvalidated) - { - _previewInvalidated = false; - Execute.PostToUIThread(OnProfilePreviewUpdated); - } + _coreService.FrameRendered -= CoreServiceOnFrameRendered; + Execute.PostToUIThread(OnProfilePreviewUpdated); } public IKernel Kernel { get; } @@ -160,7 +154,7 @@ namespace Artemis.UI.Shared.Services foreach (Layer layer in SelectedProfile.GetAllLayers()) layer.OverrideTimeLines(CurrentTime, layer != SelectedProfileElement); - _previewInvalidated = true; + _coreService.FrameRendered += CoreServiceOnFrameRendered; } public bool UndoUpdateProfile()