1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-13 05:48:35 +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)
{
if (Path == null)
if (Path == null || LayerShape == null)
return;
canvas.Save();
@ -198,6 +198,9 @@ namespace Artemis.Core.Models.Profile
private SKPoint GetLayerAnchor(bool absolute)
{
if (LayerShape == null)
return SKPoint.Empty;
if (!absolute)
{
var anchor = AnchorPointProperty.CurrentValue;

View File

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

View File

@ -90,8 +90,7 @@ 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();
LayerGeometry = layerGeometry;
OpacityGeometry = opacityGeometry;
}
@ -126,7 +125,6 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
}
shapeGeometry.Transform = _layerEditorService.GetLayerTransformGroup(Layer);
shapeGeometry.Freeze();
ShapeGeometry = shapeGeometry;
});
}

View File

@ -3,7 +3,6 @@ using System.Diagnostics;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
using Artemis.Core.Models.Profile;
using Artemis.UI.Services;
using Artemis.UI.Services.Interfaces;
@ -18,10 +17,10 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
private readonly ILayerEditorService _layerEditorService;
private bool _draggingHorizontally;
private bool _draggingVertically;
private bool _isDragging;
private Point _dragStart;
private SKPoint _dragOffset;
private Point _dragStart;
private SKPoint _dragStartAnchor;
private bool _isDragging;
public EditToolViewModel(ProfileViewModel profileViewModel, IProfileEditorService profileEditorService, ILayerEditorService layerEditorService)
: base(profileViewModel, profileEditorService)
@ -51,35 +50,34 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
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();
ShapeAnchor = _layerEditorService.GetLayerAnchor(layer, true);
Execute.PostToUIThread(() =>
{
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);
});
}
}
Transform = _layerEditorService.GetLayerTransformGroup(layer)
};
shapeGeometry.Freeze();
ShapeGeometry = shapeGeometry;
ShapeTransformCollection = _layerEditorService.GetLayerTransformGroup(layer).Children;
});
}
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)
{
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;
@ -129,6 +136,9 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
{
ProfileEditorService.UpdateSelectedProfileElement();
_dragOffset = SKPoint.Empty;
_dragStartAnchor = SKPoint.Empty;
_isDragging = false;
_draggingHorizontally = false;
_draggingVertically = false;
@ -141,45 +151,27 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
{
if (!_isDragging || !(ProfileEditorService.SelectedProfileElement is Layer layer))
return;
var position = GetRelativePosition(sender, e);
var start = _dragStartAnchor;
var current = start + (position.ToSKPoint() - _dragOffset);
var transformedPoints = UnTransformPoints(new[] {start, current}, layer, start);
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;
// The start anchor is relative to an unrotated version of the shape
var start = _dragStartAnchor;
// 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);
// Update the anchor point, this causes the shape to move
layer.AnchorPointProperty.SetCurrentValue(scaled, ProfileEditorService.CurrentTime);
var path = _layerEditorService.GetLayerPath(layer);
var difference = before - path.Points[0];
var scaledDifference = _layerEditorService.GetScaledPoint(layer, difference, false);
// TopLeft is not updated yet and acts as a snapshot of the top-left before changing the anchor
var path = _layerEditorService.GetLayerPath(layer, true, true, true);
// 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();
}
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)
{
if (!_isDragging || !(ProfileEditorService.SelectedProfileElement is Layer layer))
@ -357,6 +349,16 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
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)
{
var parent = VisualTreeHelper.GetParent((DependencyObject) sender);

View File

@ -46,7 +46,7 @@ namespace Artemis.UI.Services
}
/// <inheritdoc />
public SKPath GetLayerPath(Layer layer)
public SKPath GetLayerPath(Layer layer, bool includeTranslation, bool includeScale, bool includeRotation)
{
var layerRect = GetLayerRenderRect(layer).ToSKRect();
var shapeRect = GetShapeRenderRect(layer.LayerShape).ToSKRect();
@ -61,9 +61,12 @@ namespace Artemis.UI.Services
var path = new SKPath();
path.AddRect(shapeRect);
path.Transform(SKMatrix.MakeTranslation(x, y));
path.Transform(SKMatrix.MakeScale(layer.SizeProperty.CurrentValue.Width, layer.SizeProperty.CurrentValue.Height, anchor.X, anchor.Y));
path.Transform(SKMatrix.MakeRotationDegrees(layer.RotationProperty.CurrentValue, anchor.X, anchor.Y));
if (includeTranslation)
path.Transform(SKMatrix.MakeTranslation(x, 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;
}
@ -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.
/// </summary>
/// <param name="layer"></param>
/// <param name="includeTranslation"></param>
/// <param name="includeScale"></param>
/// <param name="includeRotation"></param>
/// <returns></returns>
SKPath GetLayerPath(Layer layer);
SKPath GetLayerPath(Layer layer, bool includeTranslation, bool includeScale, bool includeRotation);
void ReverseLayerPath(Layer layer, SKPath path);