1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-13 05:48:35 +00:00

Show outlines for all layers

Rotation fixes
Movement fixes
This commit is contained in:
Robert 2020-02-06 20:35:51 +01:00
parent 12d5fd39a0
commit dd9c701738
7 changed files with 53 additions and 49 deletions

View File

@ -1,4 +1,5 @@
using System;

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
@ -156,11 +157,18 @@ namespace Artemis.Core.Models.Profile
public override void Update(double deltaTime)
{
foreach (var property in Properties)
{
property.KeyframeEngine?.Update(deltaTime);
// This is a placeholder method of repeating the animation until repeat modes are implemented
if (property.KeyframeEngine != null && property.IsUsingKeyframes && property.KeyframeEngine.NextKeyframe == null)
property.KeyframeEngine.OverrideProgress(TimeSpan.Zero);
// For now, reset all keyframe engines after the last keyframe was hit
// This is a placeholder method of repeating the animation until repeat modes are implemented
var lastKeyframe = Properties.SelectMany(p => p.UntypedKeyframes).OrderByDescending(t => t.Position).FirstOrDefault();
if (lastKeyframe != null)
{
if (Properties.Any(p => p.KeyframeEngine?.Progress > lastKeyframe.Position))
{
foreach (var baseLayerProperty in Properties)
baseLayerProperty.KeyframeEngine?.OverrideProgress(TimeSpan.Zero);
}
}
LayerBrush?.Update(deltaTime);

View File

@ -216,7 +216,7 @@
<Compile Include="Screens\Sidebar\SidebarViewModel.cs" />
<Compile Include="Services\Interfaces\ILayerEditorService.cs" />
<Compile Include="Services\Interfaces\IProfileEditorService.cs" />
<Compile Include="Services\LayerShapeService.cs" />
<Compile Include="Services\LayerEditorService.cs" />
<Compile Include="Services\ProfileEditorService.cs" />
<Compile Include="Utilities\ThemeWatcher.cs" />
<Compile Include="Behaviors\TreeViewSelectionBehavior.cs" />

View File

@ -16,7 +16,7 @@
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(Canvas.Opacity)" To="0" Duration="0:0:0.25" />
<DoubleAnimation Storyboard.TargetProperty="(Canvas.Opacity)" To="0.8" Duration="0:0:0.25" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>

View File

@ -190,14 +190,11 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
private void OnSelectedProfileElementUpdated(object sender, EventArgs e)
{
if (IsSelected)
Update();
Update();
}
private void ProfileEditorServiceOnProfilePreviewUpdated(object sender, EventArgs e)
{
if (!IsSelected)
return;
CreateShapeGeometry();
CreateViewportRectangle();
}

View File

@ -3,6 +3,7 @@ using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using Artemis.Core.Models.Profile;
using Artemis.Core.Models.Profile.LayerProperties;
using Artemis.UI.Events;
using Artemis.UI.Services.Interfaces;
using SkiaSharp;
@ -16,7 +17,6 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
private readonly ILayerEditorService _layerEditorService;
private SKPoint _dragOffset;
private SKPoint _dragStart;
private SKSize _dragStartScale;
private SKPoint _topLeft;
public EditToolViewModel(ProfileViewModel profileViewModel, IProfileEditorService profileEditorService, ILayerEditorService layerEditorService)
@ -112,33 +112,24 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
#region Size
private bool _isResizing;
private SKSize _dragStartScale;
public void ResizeMouseDown(object sender, ShapeControlEventArgs e)
{
if (_isResizing || !(ProfileEditorService.SelectedProfileElement is Layer layer))
return;
// The path starts at 0,0 so there's no simple way to get the position relative to the top-left of the path
_dragStart = GetRelativePosition(sender, e.MouseEventArgs).ToSKPoint();
var dragStart = GetRelativePosition(sender, e.MouseEventArgs).ToSKPoint();
_dragOffset = _layerEditorService.GetDragOffset(layer, dragStart);
_dragStart = dragStart + _dragOffset;
_dragStartScale = layer.ScaleProperty.CurrentValue;
// Store the original position and do a test to figure out the mouse offset
var originalPosition = layer.PositionProperty.CurrentValue;
var scaledDragStart = _layerEditorService.GetScaledPoint(layer, _dragStart, true);
layer.PositionProperty.SetCurrentValue(scaledDragStart, ProfileEditorService.CurrentTime);
// TopLeft is not updated yet and acts as a snapshot of the top-left before changing the position
// GetLayerPath will return the updated position with all transformations applied, the difference is the offset
_dragOffset = _topLeft - _layerEditorService.GetLayerPath(layer, true, true, true).Points[0];
_dragStart += _dragOffset;
// Restore the position back to before the test was done
layer.PositionProperty.SetCurrentValue(originalPosition, ProfileEditorService.CurrentTime);
_isResizing = true;
}
public void ResizeMouseUp(object sender, ShapeControlEventArgs e)
{
ProfileEditorService.UpdateSelectedProfileElement();
_isResizing = false;
}
@ -248,23 +239,9 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
if (e.ShapeControlPoint == ShapeControlPoint.LayerShape)
{
// The path starts at 0,0 so there's no simple way to get the position relative to the top-left of the path
_dragStart = GetRelativePosition(sender, e.MouseEventArgs).ToSKPoint();
_dragStartScale = layer.ScaleProperty.CurrentValue;
// Store the original position and do a test to figure out the mouse offset
var originalPosition = layer.PositionProperty.CurrentValue;
var scaledDragStart = _layerEditorService.GetScaledPoint(layer, _dragStart, true);
layer.PositionProperty.SetCurrentValue(scaledDragStart, ProfileEditorService.CurrentTime);
// TopLeft is not updated yet and acts as a snapshot of the top-left before changing the position
// GetLayerPath will return the updated position with all transformations applied, the difference is the offset
_dragOffset = _topLeft - _layerEditorService.GetLayerPath(layer, true, true, true).Points[0];
_dragStart += _dragOffset;
// Restore the position back to before the test was done
layer.PositionProperty.SetCurrentValue(originalPosition, ProfileEditorService.CurrentTime);
var dragStart = GetRelativePosition(sender, e.MouseEventArgs).ToSKPoint();
_dragOffset = _layerEditorService.GetDragOffset(layer, dragStart);
_dragStart = dragStart + _dragOffset;
_movingShape = true;
}
else if (e.ShapeControlPoint == ShapeControlPoint.Anchor)
@ -287,6 +264,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
public void MoveMouseUp(object sender, ShapeControlEventArgs e)
{
ProfileEditorService.UpdateSelectedProfileElement();
_movingShape = false;
_movingAnchor = false;
}
@ -393,8 +371,6 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
{
var layerBounds = _layerEditorService.GetLayerBounds(layer);
var start = _layerEditorService.GetLayerAnchorPosition(layer);
start.X += layerBounds.Left;
start.Y += layerBounds.Top;
var arrival = GetRelativePosition(mouseEventSender, mouseEvent);
var radian = (float) Math.Atan2(start.Y - arrival.Y, start.X - arrival.X);

View File

@ -18,8 +18,9 @@ namespace Artemis.UI.Services.Interfaces
/// Returns the layer's anchor, corrected for the current render scale.
/// </summary>
/// <param name="layer"></param>
/// <param name="positionOverride"></param>
/// <returns></returns>
Point GetLayerAnchorPosition(Layer layer);
Point GetLayerAnchorPosition(Layer layer, SKPoint? positionOverride = null);
/// <summary>
/// Creates a WPF transform group that contains all the transformations required to render the provided layer.
@ -36,8 +37,9 @@ namespace Artemis.UI.Services.Interfaces
/// <param name="includeTranslation"></param>
/// <param name="includeScale"></param>
/// <param name="includeRotation"></param>
/// <param name="anchorOverride"></param>
/// <returns></returns>
SKPath GetLayerPath(Layer layer, bool includeTranslation, bool includeScale, bool includeRotation);
SKPath GetLayerPath(Layer layer, bool includeTranslation, bool includeScale, bool includeRotation, SKPoint? anchorOverride = null);
/// <summary>
/// Returns a new point scaled to the layer.
@ -47,5 +49,7 @@ namespace Artemis.UI.Services.Interfaces
/// <param name="absolute"></param>
/// <returns></returns>
SKPoint GetScaledPoint(Layer layer, SKPoint point, bool absolute);
SKPoint GetDragOffset(Layer layer, SKPoint dragStart);
}
}

View File

@ -32,10 +32,12 @@ namespace Artemis.UI.Services
}
/// <inheritdoc />
public Point GetLayerAnchorPosition(Layer layer)
public Point GetLayerAnchorPosition(Layer layer, SKPoint? positionOverride = null)
{
var layerBounds = GetLayerBounds(layer).ToSKRect();
var positionProperty = layer.PositionProperty.CurrentValue;
if (positionOverride != null)
positionProperty = positionOverride.Value;
// Start at the center of the shape
var position = new Point(layerBounds.MidX, layerBounds.MidY);
@ -72,12 +74,15 @@ namespace Artemis.UI.Services
}
/// <inheritdoc />
public SKPath GetLayerPath(Layer layer, bool includeTranslation, bool includeScale, bool includeRotation)
public SKPath GetLayerPath(Layer layer, bool includeTranslation, bool includeScale, bool includeRotation, SKPoint? anchorOverride = null)
{
var layerBounds = GetLayerBounds(layer).ToSKRect();
// Apply transformation like done by the core during layer rendering (same differences apply as in GetLayerTransformGroup)
var anchorPosition = GetLayerAnchorPosition(layer).ToSKPoint();
if (anchorOverride != null)
anchorPosition = anchorOverride.Value;
var anchorProperty = layer.AnchorPointProperty.CurrentValue;
// Translation originates from the unscaled center of the shape and is tied to the anchor
@ -113,5 +118,19 @@ namespace Artemis.UI.Services
100f / layer.Bounds.Height * (float) (point.Y * renderScale) / 100f
);
}
public SKPoint GetDragOffset(Layer layer, SKPoint dragStart)
{
// Figure out what the top left will be if the shape moves to the current cursor position
var scaledDragStart = GetScaledPoint(layer, dragStart, true);
var tempAnchor = GetLayerAnchorPosition(layer, scaledDragStart).ToSKPoint();
var tempTopLeft = GetLayerPath(layer, true, true, true, tempAnchor)[0];
// Get the shape's position
var topLeft = GetLayerPath(layer, true, true, true)[0];
// The difference between the two is the offset
return topLeft - tempTopLeft;
}
}
}