1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-31 17:53:32 +00:00

Finished anchor movement

Fixed a few issues when creating new layers
This commit is contained in:
SpoinkyNL 2020-01-22 23:22:50 +01:00
parent 20999919ab
commit 7966d3243c
5 changed files with 84 additions and 75 deletions

View File

@ -153,7 +153,7 @@ namespace Artemis.Core.Models.Profile
public override void Render(double deltaTime, SKCanvas canvas) public override void Render(double deltaTime, SKCanvas canvas)
{ {
if (Path == null) if (Path == null || LayerShape == null)
return; return;
canvas.Save(); canvas.Save();
@ -198,6 +198,9 @@ namespace Artemis.Core.Models.Profile
private SKPoint GetLayerAnchor(bool absolute) private SKPoint GetLayerAnchor(bool absolute)
{ {
if (LayerShape == null)
return SKPoint.Empty;
if (!absolute) if (!absolute)
{ {
var anchor = AnchorPointProperty.CurrentValue; var anchor = AnchorPointProperty.CurrentValue;

View File

@ -11,7 +11,7 @@
public T Value public T Value
{ {
get => (T) BaseValue; get => BaseValue != null ? (T) BaseValue : default;
set => BaseValue = value; set => BaseValue = value;
} }
} }

View File

@ -90,8 +90,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
var layerGeometry = group.GetOutlinedPathGeometry(); var layerGeometry = group.GetOutlinedPathGeometry();
var opacityGeometry = Geometry.Combine(Geometry.Empty, layerGeometry, GeometryCombineMode.Exclude, new TranslateTransform()); var opacityGeometry = Geometry.Combine(Geometry.Empty, layerGeometry, GeometryCombineMode.Exclude, new TranslateTransform());
layerGeometry.Freeze();
opacityGeometry.Freeze();
LayerGeometry = layerGeometry; LayerGeometry = layerGeometry;
OpacityGeometry = opacityGeometry; OpacityGeometry = opacityGeometry;
} }
@ -126,7 +125,6 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
} }
shapeGeometry.Transform = _layerEditorService.GetLayerTransformGroup(Layer); shapeGeometry.Transform = _layerEditorService.GetLayerTransformGroup(Layer);
shapeGeometry.Freeze();
ShapeGeometry = shapeGeometry; ShapeGeometry = shapeGeometry;
}); });
} }

View File

@ -3,7 +3,6 @@ using System.Diagnostics;
using System.Windows; using System.Windows;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Shapes;
using Artemis.Core.Models.Profile; using Artemis.Core.Models.Profile;
using Artemis.UI.Services; using Artemis.UI.Services;
using Artemis.UI.Services.Interfaces; using Artemis.UI.Services.Interfaces;
@ -18,10 +17,10 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
private readonly ILayerEditorService _layerEditorService; private readonly ILayerEditorService _layerEditorService;
private bool _draggingHorizontally; private bool _draggingHorizontally;
private bool _draggingVertically; private bool _draggingVertically;
private bool _isDragging;
private Point _dragStart;
private SKPoint _dragOffset; private SKPoint _dragOffset;
private Point _dragStart;
private SKPoint _dragStartAnchor; private SKPoint _dragStartAnchor;
private bool _isDragging;
public EditToolViewModel(ProfileViewModel profileViewModel, IProfileEditorService profileEditorService, ILayerEditorService layerEditorService) public EditToolViewModel(ProfileViewModel profileViewModel, IProfileEditorService profileEditorService, ILayerEditorService layerEditorService)
: base(profileViewModel, profileEditorService) : base(profileViewModel, profileEditorService)
@ -51,35 +50,34 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
private void Update() private void Update()
{ {
if (ProfileEditorService.SelectedProfileElement is Layer layer) if (!(ProfileEditorService.SelectedProfileElement is Layer layer) || layer.LayerShape == null)
return;
ShapeRectangle = _layerEditorService.GetShapeRenderRect(layer.LayerShape).ToSKRect();
ShapeAnchor = _layerEditorService.GetLayerAnchor(layer, true);
// Get a square path to use for mutation point placement
var path = _layerEditorService.GetLayerPath(layer, true, true, true);
TopLeft = path.Points[0];
TopRight = path.Points[1];
BottomRight = path.Points[2];
BottomLeft = path.Points[3];
TopCenter = new SKPoint((TopLeft.X + TopRight.X) / 2, (TopLeft.Y + TopRight.Y) / 2);
RightCenter = new SKPoint((TopRight.X + BottomRight.X) / 2, (TopRight.Y + BottomRight.Y) / 2);
BottomCenter = new SKPoint((BottomLeft.X + BottomRight.X) / 2, (BottomLeft.Y + BottomRight.Y) / 2);
LeftCenter = new SKPoint((TopLeft.X + BottomLeft.X) / 2, (TopLeft.Y + BottomLeft.Y) / 2);
Execute.PostToUIThread(() =>
{ {
if (layer.LayerShape != null) var shapeGeometry = new RectangleGeometry(_layerEditorService.GetShapeRenderRect(layer.LayerShape))
{ {
ShapeRectangle = _layerEditorService.GetShapeRenderRect(layer.LayerShape).ToSKRect(); Transform = _layerEditorService.GetLayerTransformGroup(layer)
ShapeAnchor = _layerEditorService.GetLayerAnchor(layer, true); };
shapeGeometry.Freeze();
Execute.PostToUIThread(() => ShapeGeometry = shapeGeometry;
{ ShapeTransformCollection = _layerEditorService.GetLayerTransformGroup(layer).Children;
var shapeGeometry = new RectangleGeometry(_layerEditorService.GetShapeRenderRect(layer.LayerShape)); });
shapeGeometry.Transform = _layerEditorService.GetLayerTransformGroup(layer);
shapeGeometry.Freeze();
ShapeGeometry = shapeGeometry;
ShapeTransformCollection = _layerEditorService.GetLayerTransformGroup(layer).Children;
// Get a square path to use for mutation point placement
var path = _layerEditorService.GetLayerPath(layer);
TopLeft = path.Points[0];
TopRight = path.Points[1];
BottomRight = path.Points[2];
BottomLeft = path.Points[3];
TopCenter = new SKPoint((TopLeft.X + TopRight.X) / 2, (TopLeft.Y + TopRight.Y) / 2);
RightCenter = new SKPoint((TopRight.X + BottomRight.X) / 2, (TopRight.Y + BottomRight.Y) / 2);
BottomCenter = new SKPoint((BottomLeft.X + BottomRight.X) / 2, (BottomLeft.Y + BottomRight.Y) / 2);
LeftCenter = new SKPoint((TopLeft.X + BottomLeft.X) / 2, (TopLeft.Y + BottomLeft.Y) / 2);
});
}
}
} }
public void ShapeEditMouseDown(object sender, MouseButtonEventArgs e) public void ShapeEditMouseDown(object sender, MouseButtonEventArgs e)
@ -113,8 +111,17 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
if (ProfileEditorService.SelectedProfileElement is Layer layer) if (ProfileEditorService.SelectedProfileElement is Layer layer)
{ {
var dragStartPosition = GetRelativePosition(sender, e).ToSKPoint(); var dragStartPosition = GetRelativePosition(sender, e).ToSKPoint();
_dragOffset = TopLeft + (dragStartPosition - TopLeft);
_dragStartAnchor = _layerEditorService.GetLayerAnchor(layer, false); // Mouse doesn't care about rotation so get the layer path without rotation
var path = _layerEditorService.GetLayerPath(layer, true, true, false);
var topLeft = path.Points[0];
// Measure from the top-left of the shape (without rotation)
_dragOffset = topLeft + (dragStartPosition - topLeft);
// Get the absolute layer anchor and make it relative to the unrotated shape
_dragStartAnchor = _layerEditorService.GetLayerAnchor(layer, true) - topLeft;
// Ensure the anchor starts in the center of the shape it is now relative to
_dragStartAnchor.X -= path.Bounds.Width / 2f;
_dragStartAnchor.Y -= path.Bounds.Height / 2f;
} }
_isDragging = true; _isDragging = true;
@ -129,6 +136,9 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
{ {
ProfileEditorService.UpdateSelectedProfileElement(); ProfileEditorService.UpdateSelectedProfileElement();
_dragOffset = SKPoint.Empty;
_dragStartAnchor = SKPoint.Empty;
_isDragging = false; _isDragging = false;
_draggingHorizontally = false; _draggingHorizontally = false;
_draggingVertically = false; _draggingVertically = false;
@ -142,44 +152,26 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
if (!_isDragging || !(ProfileEditorService.SelectedProfileElement is Layer layer)) if (!_isDragging || !(ProfileEditorService.SelectedProfileElement is Layer layer))
return; return;
var position = GetRelativePosition(sender, e); // The start anchor is relative to an unrotated version of the shape
var start = _dragStartAnchor; var start = _dragStartAnchor;
var current = start + (position.ToSKPoint() - _dragOffset); // Add the current position to the start anchor to determine the new position
var current = start + (GetRelativePosition(sender, e).ToSKPoint() - _dragOffset);
// In order to keep the mouse movement unrotated, counter-act the active rotation
var countered = UnTransformPoints(new[] {start, current}, layer, start);
var scaled = _layerEditorService.GetScaledPoint(layer, countered[1], false);
var transformedPoints = UnTransformPoints(new[] {start, current}, layer, start); // Update the anchor point, this causes the shape to move
var scaled = _layerEditorService.GetScaledPoint(layer, transformedPoints[1], false);
Debug.WriteLine("Current value before mousedown " + _dragStartAnchor);
Debug.WriteLine("Current value before move " + layer.AnchorPointProperty.CurrentValue);
var before = TopLeft;
layer.AnchorPointProperty.SetCurrentValue(scaled, ProfileEditorService.CurrentTime); layer.AnchorPointProperty.SetCurrentValue(scaled, ProfileEditorService.CurrentTime);
var path = _layerEditorService.GetLayerPath(layer); // TopLeft is not updated yet and acts as a snapshot of the top-left before changing the anchor
var difference = before - path.Points[0]; var path = _layerEditorService.GetLayerPath(layer, true, true, true);
var scaledDifference = _layerEditorService.GetScaledPoint(layer, difference, false); // Calculate the (scaled) difference between the old and now position
var difference = _layerEditorService.GetScaledPoint(layer, TopLeft - path.Points[0], false);
// Apply the difference so that the shape effectively stays in place
layer.PositionProperty.SetCurrentValue(layer.PositionProperty.CurrentValue + difference, ProfileEditorService.CurrentTime);
layer.PositionProperty.SetCurrentValue(layer.PositionProperty.CurrentValue + scaledDifference, ProfileEditorService.CurrentTime);
ProfileEditorService.UpdateProfilePreview(); ProfileEditorService.UpdateProfilePreview();
} }
private SKPoint[] UnTransformPoints(SKPoint[] skPoints, Layer layer, SKPoint pivot)
{
var counterRotatePath = new SKPath();
counterRotatePath.AddPoly(skPoints, false);
counterRotatePath.Transform(SKMatrix.MakeRotationDegrees(layer.RotationProperty.CurrentValue * -1, pivot.X, pivot.Y));
counterRotatePath.Transform(SKMatrix.MakeScale(1f / layer.SizeProperty.CurrentValue.Width, 1f / layer.SizeProperty.CurrentValue.Height));
return counterRotatePath.Points;
}
private SKPoint[] TransformPoints(SKPoint[] skPoints, Layer layer, SKPoint pivot)
{
var counterRotatePath = new SKPath();
counterRotatePath.AddPoly(skPoints, false);
counterRotatePath.Transform(SKMatrix.MakeRotationDegrees(layer.RotationProperty.CurrentValue , pivot.X, pivot.Y));
counterRotatePath.Transform(SKMatrix.MakeScale( layer.SizeProperty.CurrentValue.Width, layer.SizeProperty.CurrentValue.Height));
return counterRotatePath.Points;
}
public void Move(object sender, MouseEventArgs e) public void Move(object sender, MouseEventArgs e)
{ {
if (!_isDragging || !(ProfileEditorService.SelectedProfileElement is Layer layer)) if (!_isDragging || !(ProfileEditorService.SelectedProfileElement is Layer layer))
@ -357,6 +349,16 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
ApplyShapeResize(skRect); ApplyShapeResize(skRect);
} }
private SKPoint[] UnTransformPoints(SKPoint[] skPoints, Layer layer, SKPoint pivot)
{
var counterRotatePath = new SKPath();
counterRotatePath.AddPoly(skPoints, false);
counterRotatePath.Transform(SKMatrix.MakeRotationDegrees(layer.RotationProperty.CurrentValue * -1, pivot.X, pivot.Y));
counterRotatePath.Transform(SKMatrix.MakeScale(1f / layer.SizeProperty.CurrentValue.Width, 1f / layer.SizeProperty.CurrentValue.Height));
return counterRotatePath.Points;
}
private Point GetRelativePosition(object sender, MouseEventArgs mouseEventArgs) private Point GetRelativePosition(object sender, MouseEventArgs mouseEventArgs)
{ {
var parent = VisualTreeHelper.GetParent((DependencyObject) sender); var parent = VisualTreeHelper.GetParent((DependencyObject) sender);

View File

@ -46,7 +46,7 @@ namespace Artemis.UI.Services
} }
/// <inheritdoc /> /// <inheritdoc />
public SKPath GetLayerPath(Layer layer) public SKPath GetLayerPath(Layer layer, bool includeTranslation, bool includeScale, bool includeRotation)
{ {
var layerRect = GetLayerRenderRect(layer).ToSKRect(); var layerRect = GetLayerRenderRect(layer).ToSKRect();
var shapeRect = GetShapeRenderRect(layer.LayerShape).ToSKRect(); var shapeRect = GetShapeRenderRect(layer.LayerShape).ToSKRect();
@ -61,9 +61,12 @@ namespace Artemis.UI.Services
var path = new SKPath(); var path = new SKPath();
path.AddRect(shapeRect); path.AddRect(shapeRect);
path.Transform(SKMatrix.MakeTranslation(x, y)); if (includeTranslation)
path.Transform(SKMatrix.MakeScale(layer.SizeProperty.CurrentValue.Width, layer.SizeProperty.CurrentValue.Height, anchor.X, anchor.Y)); path.Transform(SKMatrix.MakeTranslation(x, y));
path.Transform(SKMatrix.MakeRotationDegrees(layer.RotationProperty.CurrentValue, anchor.X, anchor.Y)); if (includeScale)
path.Transform(SKMatrix.MakeScale(layer.SizeProperty.CurrentValue.Width, layer.SizeProperty.CurrentValue.Height, anchor.X, anchor.Y));
if (includeRotation)
path.Transform(SKMatrix.MakeRotationDegrees(layer.RotationProperty.CurrentValue, anchor.X, anchor.Y));
return path; return path;
} }
@ -207,8 +210,11 @@ namespace Artemis.UI.Services
/// Returns an absolute and scaled rectangular path for the given layer that is corrected for the current render scale. /// Returns an absolute and scaled rectangular path for the given layer that is corrected for the current render scale.
/// </summary> /// </summary>
/// <param name="layer"></param> /// <param name="layer"></param>
/// <param name="includeTranslation"></param>
/// <param name="includeScale"></param>
/// <param name="includeRotation"></param>
/// <returns></returns> /// <returns></returns>
SKPath GetLayerPath(Layer layer); SKPath GetLayerPath(Layer layer, bool includeTranslation, bool includeScale, bool includeRotation);
void ReverseLayerPath(Layer layer, SKPath path); void ReverseLayerPath(Layer layer, SKPath path);