1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-31 17:53:32 +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.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
@ -156,11 +157,18 @@ namespace Artemis.Core.Models.Profile
public override void Update(double deltaTime) public override void Update(double deltaTime)
{ {
foreach (var property in Properties) foreach (var property in Properties)
{
property.KeyframeEngine?.Update(deltaTime); 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) // For now, reset all keyframe engines after the last keyframe was hit
property.KeyframeEngine.OverrideProgress(TimeSpan.Zero); // 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); LayerBrush?.Update(deltaTime);

View File

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

View File

@ -16,7 +16,7 @@
<DataTrigger.EnterActions> <DataTrigger.EnterActions>
<BeginStoryboard> <BeginStoryboard>
<Storyboard> <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> </Storyboard>
</BeginStoryboard> </BeginStoryboard>
</DataTrigger.EnterActions> </DataTrigger.EnterActions>

View File

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

View File

@ -3,6 +3,7 @@ using System.Windows;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using Artemis.Core.Models.Profile; using Artemis.Core.Models.Profile;
using Artemis.Core.Models.Profile.LayerProperties;
using Artemis.UI.Events; using Artemis.UI.Events;
using Artemis.UI.Services.Interfaces; using Artemis.UI.Services.Interfaces;
using SkiaSharp; using SkiaSharp;
@ -16,7 +17,6 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
private readonly ILayerEditorService _layerEditorService; private readonly ILayerEditorService _layerEditorService;
private SKPoint _dragOffset; private SKPoint _dragOffset;
private SKPoint _dragStart; private SKPoint _dragStart;
private SKSize _dragStartScale;
private SKPoint _topLeft; private SKPoint _topLeft;
public EditToolViewModel(ProfileViewModel profileViewModel, IProfileEditorService profileEditorService, ILayerEditorService layerEditorService) public EditToolViewModel(ProfileViewModel profileViewModel, IProfileEditorService profileEditorService, ILayerEditorService layerEditorService)
@ -112,33 +112,24 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
#region Size #region Size
private bool _isResizing; private bool _isResizing;
private SKSize _dragStartScale;
public void ResizeMouseDown(object sender, ShapeControlEventArgs e) public void ResizeMouseDown(object sender, ShapeControlEventArgs e)
{ {
if (_isResizing || !(ProfileEditorService.SelectedProfileElement is Layer layer)) if (_isResizing || !(ProfileEditorService.SelectedProfileElement is Layer layer))
return; 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 var dragStart = GetRelativePosition(sender, e.MouseEventArgs).ToSKPoint();
_dragStart = GetRelativePosition(sender, e.MouseEventArgs).ToSKPoint(); _dragOffset = _layerEditorService.GetDragOffset(layer, dragStart);
_dragStart = dragStart + _dragOffset;
_dragStartScale = layer.ScaleProperty.CurrentValue; _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; _isResizing = true;
} }
public void ResizeMouseUp(object sender, ShapeControlEventArgs e) public void ResizeMouseUp(object sender, ShapeControlEventArgs e)
{ {
ProfileEditorService.UpdateSelectedProfileElement();
_isResizing = false; _isResizing = false;
} }
@ -248,23 +239,9 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
if (e.ShapeControlPoint == ShapeControlPoint.LayerShape) 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 var dragStart = GetRelativePosition(sender, e.MouseEventArgs).ToSKPoint();
_dragStart = GetRelativePosition(sender, e.MouseEventArgs).ToSKPoint(); _dragOffset = _layerEditorService.GetDragOffset(layer, dragStart);
_dragStartScale = layer.ScaleProperty.CurrentValue; _dragStart = dragStart + _dragOffset;
// 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);
_movingShape = true; _movingShape = true;
} }
else if (e.ShapeControlPoint == ShapeControlPoint.Anchor) 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) public void MoveMouseUp(object sender, ShapeControlEventArgs e)
{ {
ProfileEditorService.UpdateSelectedProfileElement();
_movingShape = false; _movingShape = false;
_movingAnchor = false; _movingAnchor = false;
} }
@ -393,8 +371,6 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
{ {
var layerBounds = _layerEditorService.GetLayerBounds(layer); var layerBounds = _layerEditorService.GetLayerBounds(layer);
var start = _layerEditorService.GetLayerAnchorPosition(layer); var start = _layerEditorService.GetLayerAnchorPosition(layer);
start.X += layerBounds.Left;
start.Y += layerBounds.Top;
var arrival = GetRelativePosition(mouseEventSender, mouseEvent); var arrival = GetRelativePosition(mouseEventSender, mouseEvent);
var radian = (float) Math.Atan2(start.Y - arrival.Y, start.X - arrival.X); 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. /// Returns the layer's anchor, corrected for the current render scale.
/// </summary> /// </summary>
/// <param name="layer"></param> /// <param name="layer"></param>
/// <param name="positionOverride"></param>
/// <returns></returns> /// <returns></returns>
Point GetLayerAnchorPosition(Layer layer); Point GetLayerAnchorPosition(Layer layer, SKPoint? positionOverride = null);
/// <summary> /// <summary>
/// Creates a WPF transform group that contains all the transformations required to render the provided layer. /// 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="includeTranslation"></param>
/// <param name="includeScale"></param> /// <param name="includeScale"></param>
/// <param name="includeRotation"></param> /// <param name="includeRotation"></param>
/// <param name="anchorOverride"></param>
/// <returns></returns> /// <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> /// <summary>
/// Returns a new point scaled to the layer. /// Returns a new point scaled to the layer.
@ -47,5 +49,7 @@ namespace Artemis.UI.Services.Interfaces
/// <param name="absolute"></param> /// <param name="absolute"></param>
/// <returns></returns> /// <returns></returns>
SKPoint GetScaledPoint(Layer layer, SKPoint point, bool absolute); 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 /> /// <inheritdoc />
public Point GetLayerAnchorPosition(Layer layer) public Point GetLayerAnchorPosition(Layer layer, SKPoint? positionOverride = null)
{ {
var layerBounds = GetLayerBounds(layer).ToSKRect(); var layerBounds = GetLayerBounds(layer).ToSKRect();
var positionProperty = layer.PositionProperty.CurrentValue; var positionProperty = layer.PositionProperty.CurrentValue;
if (positionOverride != null)
positionProperty = positionOverride.Value;
// Start at the center of the shape // Start at the center of the shape
var position = new Point(layerBounds.MidX, layerBounds.MidY); var position = new Point(layerBounds.MidX, layerBounds.MidY);
@ -72,12 +74,15 @@ namespace Artemis.UI.Services
} }
/// <inheritdoc /> /// <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(); var layerBounds = GetLayerBounds(layer).ToSKRect();
// Apply transformation like done by the core during layer rendering (same differences apply as in GetLayerTransformGroup) // Apply transformation like done by the core during layer rendering (same differences apply as in GetLayerTransformGroup)
var anchorPosition = GetLayerAnchorPosition(layer).ToSKPoint(); var anchorPosition = GetLayerAnchorPosition(layer).ToSKPoint();
if (anchorOverride != null)
anchorPosition = anchorOverride.Value;
var anchorProperty = layer.AnchorPointProperty.CurrentValue; var anchorProperty = layer.AnchorPointProperty.CurrentValue;
// Translation originates from the unscaled center of the shape and is tied to the anchor // 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 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;
}
} }
} }