From 5069be4af46997a1f3802e554781739d4ac0f9e8 Mon Sep 17 00:00:00 2001 From: Robert Date: Wed, 15 Jan 2020 20:06:07 +0100 Subject: [PATCH] Hooked up rotation and opacity --- .../KeyframeEngines/IntKeyframeEngine.cs | 2 +- src/Artemis.Core/Models/Profile/Layer.cs | 16 +- .../Models/Profile/LayerShapes/Ellipse.cs | 11 +- .../Models/Profile/LayerShapes/Rectangle.cs | 10 +- .../Visualization/ProfileLayerViewModel.cs | 5 +- .../Visualization/ProfileViewModel.cs | 2 +- .../Visualization/Tools/EditToolView.xaml | 205 +++++++++--------- .../Visualization/Tools/EditToolViewModel.cs | 75 +++++-- .../Screens/Shared/PanZoomViewModel.cs | 13 +- 9 files changed, 202 insertions(+), 137 deletions(-) diff --git a/src/Artemis.Core/Models/Profile/KeyframeEngines/IntKeyframeEngine.cs b/src/Artemis.Core/Models/Profile/KeyframeEngines/IntKeyframeEngine.cs index b31e87b8d..9d25f8148 100644 --- a/src/Artemis.Core/Models/Profile/KeyframeEngines/IntKeyframeEngine.cs +++ b/src/Artemis.Core/Models/Profile/KeyframeEngines/IntKeyframeEngine.cs @@ -15,7 +15,7 @@ namespace Artemis.Core.Models.Profile.KeyframeEngines var nextKeyframe = (Keyframe) NextKeyframe; var diff = nextKeyframe.Value - currentKeyframe.Value; - return currentKeyframe.Value + diff * KeyframeProgressEased; + return (int) Math.Round(currentKeyframe.Value + diff * KeyframeProgressEased, MidpointRounding.AwayFromZero); } } } \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/Layer.cs b/src/Artemis.Core/Models/Profile/Layer.cs index 3132d7210..b0216b37b 100644 --- a/src/Artemis.Core/Models/Profile/Layer.cs +++ b/src/Artemis.Core/Models/Profile/Layer.cs @@ -132,12 +132,12 @@ namespace Artemis.Core.Models.Profile public LayerProperty SizeProperty { get; private set; } /// - /// The rotation property of this layer, also found in + /// The rotation property of this layer range 0 - 360, also found in /// public LayerProperty RotationProperty { get; private set; } /// - /// The opacity property of this layer, also found in + /// The opacity property of this layer range 0 - 100, also found in /// public LayerProperty OpacityProperty { get; private set; } @@ -158,9 +158,19 @@ namespace Artemis.Core.Models.Profile canvas.Save(); canvas.ClipPath(Path); + + // Apply transformations + var rotation = RotationProperty.CurrentValue; + var anchor = AnchorPointProperty.CurrentValue; + if (rotation != 0) + canvas.RotateDegrees(rotation, anchor.X * AbsoluteRectangle.Width + LayerShape.RenderRectangle.Left, anchor.Y * AbsoluteRectangle.Height + LayerShape.RenderRectangle.Top); + // Placeholder if (LayerShape?.RenderPath != null) - canvas.DrawPath(LayerShape.RenderPath, new SKPaint {Color = new SKColor(255, 0, 0)}); + { + canvas.DrawPath(LayerShape.RenderPath, new SKPaint {Color = new SKColor(255, 0, 0, (byte) (2.55 * OpacityProperty.CurrentValue))}); + } + LayerBrush?.Render(canvas); canvas.Restore(); } diff --git a/src/Artemis.Core/Models/Profile/LayerShapes/Ellipse.cs b/src/Artemis.Core/Models/Profile/LayerShapes/Ellipse.cs index fa25cf18d..bd182685f 100644 --- a/src/Artemis.Core/Models/Profile/LayerShapes/Ellipse.cs +++ b/src/Artemis.Core/Models/Profile/LayerShapes/Ellipse.cs @@ -17,14 +17,17 @@ namespace Artemis.Core.Models.Profile.LayerShapes { var width = Layer.AbsoluteRectangle.Width; var height = Layer.AbsoluteRectangle.Height; - var rect = SKRect.Create(shapePosition.X * width, shapePosition.Y * height, shapeSize.Width * width, shapeSize.Height * height); - + var rect = SKRect.Create( + Layer.Rectangle.Left + shapePosition.X * width, + Layer.Rectangle.Top + shapePosition.Y * height, + shapeSize.Width * width, + shapeSize.Height * height + ); var path = new SKPath(); path.AddOval(rect); - path.Transform(SKMatrix.MakeTranslation(Layer.Rectangle.Left, Layer.Rectangle.Top)); RenderPath = path; - RenderRectangle = path.GetRect(); + RenderRectangle = rect; } public override void ApplyToEntity() diff --git a/src/Artemis.Core/Models/Profile/LayerShapes/Rectangle.cs b/src/Artemis.Core/Models/Profile/LayerShapes/Rectangle.cs index adffbccbb..a17fe4fbe 100644 --- a/src/Artemis.Core/Models/Profile/LayerShapes/Rectangle.cs +++ b/src/Artemis.Core/Models/Profile/LayerShapes/Rectangle.cs @@ -17,13 +17,17 @@ namespace Artemis.Core.Models.Profile.LayerShapes { var width = Layer.AbsoluteRectangle.Width; var height = Layer.AbsoluteRectangle.Height; - var rect = SKRect.Create(shapePosition.X * width, shapePosition.Y * height, shapeSize.Width * width, shapeSize.Height * height); + var rect = SKRect.Create( + Layer.Rectangle.Left + shapePosition.X * width, + Layer.Rectangle.Top + shapePosition.Y * height, + shapeSize.Width * width, + shapeSize.Height * height + ); var path = new SKPath(); path.AddRect(rect); - path.Transform(SKMatrix.MakeTranslation(Layer.Rectangle.Left, Layer.Rectangle.Top)); RenderPath = path; - RenderRectangle = path.GetRect(); + RenderRectangle = rect; } public override void ApplyToEntity() diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileLayerViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileLayerViewModel.cs index 4e0d2c958..2f7d668dd 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileLayerViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileLayerViewModel.cs @@ -83,7 +83,6 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization } var layerGeometry = group.GetOutlinedPathGeometry(); - var opacityGeometry = Geometry.Combine(Geometry.Empty, layerGeometry, GeometryCombineMode.Exclude, new TranslateTransform()); layerGeometry.Freeze(); opacityGeometry.Freeze(); @@ -120,6 +119,10 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization break; } + // Apply transformation like done by the core during layer rendering + var anchor = Layer.LayerShape.GetUnscaledAnchor(); + shapeGeometry.Transform = new RotateTransform(Layer.RotationProperty.CurrentValue, anchor.X, anchor.Y); + shapeGeometry.Freeze(); ShapeGeometry = shapeGeometry; } diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileViewModel.cs index 16c62b899..3a13f4677 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileViewModel.cs @@ -46,7 +46,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization { CanvasViewModels = new ObservableCollection(); DeviceViewModels = new ObservableCollection(); - PanZoomViewModel = new PanZoomViewModel(); + PanZoomViewModel = new PanZoomViewModel {LimitToZero = false}; }); ApplySurfaceConfiguration(surfaceService.ActiveSurface); diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/EditToolView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/EditToolView.xaml index 053932f15..ea044d963 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/EditToolView.xaml +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/EditToolView.xaml @@ -10,112 +10,119 @@ d:DesignWidth="800" d:DataContext="{d:DesignInstance {x:Type local:EditToolViewModel}}"> - - + + + + + + - - + + + + + + - - - - - - + + + + - - - - + + + + + + - - - - - - + + + + - - - - + + + + + + - - - - - - + + + + - - - - + + + + + + - - - - - - - - - - - + + + + + + + + + \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/EditToolViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/EditToolViewModel.cs index df87b7aa9..2b6d7a291 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/EditToolViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/EditToolViewModel.cs @@ -29,6 +29,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools public SKRect ShapeSkRect { get; set; } public SKPoint AnchorSkPoint { get; set; } + public int RotationAngle { get; set; } private void Update() { @@ -38,6 +39,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools { ShapeSkRect = layer.LayerShape.GetUnscaledRectangle(); AnchorSkPoint = layer.LayerShape.GetUnscaledAnchor(); + RotationAngle = layer.RotationProperty.CurrentValue; } } } @@ -64,15 +66,29 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools e.Handled = true; } + public void AnchorEditMouseDown(object sender, MouseButtonEventArgs e) + { + if (_isDragging) + return; + + // Use the regular mousedown + ShapeEditMouseDown(sender, e); + // Override the drag offset + var dragStartPosition = GetRelativePosition(sender, e); + _dragOffsetX = AnchorSkPoint.X - dragStartPosition.X; + _dragOffsetY = AnchorSkPoint.Y - dragStartPosition.Y; + _dragStart = dragStartPosition; + } + public void ShapeEditMouseUp(object sender, MouseButtonEventArgs e) { - ((IInputElement) sender).ReleaseMouseCapture(); ProfileEditorService.UpdateSelectedProfileElement(); _isDragging = false; _draggingHorizontally = false; _draggingVertically = false; + ((IInputElement) sender).ReleaseMouseCapture(); e.Handled = true; } @@ -82,7 +98,9 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools return; var position = GetRelativePosition(sender, e); - layer.LayerShape.SetFromUnscaledAnchor(new SKPoint((float) position.X, (float) position.Y), ProfileEditorService.CurrentTime); + var x = (float) (position.X + _dragOffsetX); + var y = (float) (position.Y + _dragOffsetY); + layer.LayerShape.SetFromUnscaledAnchor(new SKPoint(x, y), ProfileEditorService.CurrentTime); ProfileEditorService.UpdateProfilePreview(); } @@ -136,8 +154,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools skRect.Left = (float) Math.Min(position.X, skRect.Bottom); } - layer.LayerShape.SetFromUnscaledRectangle(skRect, ProfileEditorService.CurrentTime); - ProfileEditorService.UpdateProfilePreview(); + ApplyShapeResize(skRect); } public void TopCenterResize(object sender, MouseEventArgs e) @@ -149,8 +166,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools var skRect = layer.LayerShape.GetUnscaledRectangle(); skRect.Top = (float) Math.Min(position.Y, skRect.Bottom); - layer.LayerShape.SetFromUnscaledRectangle(skRect, ProfileEditorService.CurrentTime); - ProfileEditorService.UpdateProfilePreview(); + ApplyShapeResize(skRect); } public void TopRightRotate(object sender, MouseEventArgs e) @@ -175,8 +191,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools skRect.Right = (float) Math.Max(position.X, skRect.Left); } - layer.LayerShape.SetFromUnscaledRectangle(skRect, ProfileEditorService.CurrentTime); - ProfileEditorService.UpdateProfilePreview(); + ApplyShapeResize(skRect); } public void CenterRightResize(object sender, MouseEventArgs e) @@ -188,14 +203,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools var skRect = layer.LayerShape.GetUnscaledRectangle(); skRect.Right = (float) Math.Max(position.X, skRect.Left); - layer.LayerShape.SetFromUnscaledRectangle(skRect, ProfileEditorService.CurrentTime); - ProfileEditorService.UpdateProfilePreview(); - } - - private Point GetRelativePosition(object sender, MouseEventArgs mouseEventArgs) - { - var parent = VisualTreeHelper.GetParent((DependencyObject) sender); - return mouseEventArgs.GetPosition((IInputElement) parent); + ApplyShapeResize(skRect); } public void BottomRightRotate(object sender, MouseEventArgs e) @@ -220,8 +228,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools skRect.Right = (float) Math.Max(position.X, skRect.Left); } - layer.LayerShape.SetFromUnscaledRectangle(skRect, ProfileEditorService.CurrentTime); - ProfileEditorService.UpdateProfilePreview(); + ApplyShapeResize(skRect); } public void BottomCenterResize(object sender, MouseEventArgs e) @@ -233,8 +240,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools var skRect = layer.LayerShape.GetUnscaledRectangle(); skRect.Bottom = (float) Math.Max(position.Y, skRect.Top); - layer.LayerShape.SetFromUnscaledRectangle(skRect, ProfileEditorService.CurrentTime); - ProfileEditorService.UpdateProfilePreview(); + ApplyShapeResize(skRect); } public void BottomLeftRotate(object sender, MouseEventArgs e) @@ -259,8 +265,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools skRect.Left = (float) Math.Min(position.X, skRect.Right); } - layer.LayerShape.SetFromUnscaledRectangle(skRect, ProfileEditorService.CurrentTime); - ProfileEditorService.UpdateProfilePreview(); + ApplyShapeResize(skRect); } public void CenterLeftResize(object sender, MouseEventArgs e) @@ -272,7 +277,31 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools var skRect = layer.LayerShape.GetUnscaledRectangle(); skRect.Left = (float) Math.Min(position.X, skRect.Right); - layer.LayerShape.SetFromUnscaledRectangle(skRect, ProfileEditorService.CurrentTime); + ApplyShapeResize(skRect); + } + + private Point GetRelativePosition(object sender, MouseEventArgs mouseEventArgs) + { + var parent = VisualTreeHelper.GetParent((DependencyObject) sender); + return mouseEventArgs.GetPosition((IInputElement) parent); + } + + private void ApplyShapeResize(SKRect newRect) + { + if (!(ProfileEditorService.SelectedProfileElement is Layer layer)) + return; + + // Store the original position to create an offset for the anchor + var original = layer.PositionProperty.CurrentValue; + layer.LayerShape.SetFromUnscaledRectangle(newRect, ProfileEditorService.CurrentTime); + var updated = layer.PositionProperty.CurrentValue; + // Apply the offset to the anchor so it stays in at same spot + layer.AnchorPointProperty.SetCurrentValue(new SKPoint( + layer.AnchorPointProperty.CurrentValue.X + (original.X - updated.X), + layer.AnchorPointProperty.CurrentValue.Y + (original.Y - updated.Y) + ), ProfileEditorService.CurrentTime); + + // Update the preview ProfileEditorService.UpdateProfilePreview(); } } diff --git a/src/Artemis.UI/Screens/Shared/PanZoomViewModel.cs b/src/Artemis.UI/Screens/Shared/PanZoomViewModel.cs index 727b815ff..45cc0ee60 100644 --- a/src/Artemis.UI/Screens/Shared/PanZoomViewModel.cs +++ b/src/Artemis.UI/Screens/Shared/PanZoomViewModel.cs @@ -25,6 +25,7 @@ namespace Artemis.UI.Screens.Shared public double PanY { get; set; } public double CanvasWidth { get; set; } public double CanvasHeight { get; set; } + public bool LimitToZero { get; set; } public Rect BackgroundViewport => new Rect(PanX, PanY, 20, 20); @@ -61,8 +62,16 @@ namespace Artemis.UI.Screens.Shared var position = e.GetPosition((IInputElement) sender); var delta = LastPanPosition - position; - PanX = Math.Min(0, PanX - delta.Value.X); - PanY = Math.Min(0, PanY - delta.Value.Y); + if (LimitToZero) + { + PanX = Math.Min(0, PanX - delta.Value.X); + PanY = Math.Min(0, PanY - delta.Value.Y); + } + else + { + PanX -= delta.Value.X; + PanY -= delta.Value.Y; + } LastPanPosition = position; }