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:
parent
20999919ab
commit
7966d3243c
@ -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;
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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);
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user