Transform tool - Finished initial implementation

This commit is contained in:
Robert committed 2022-02-13 21:19:32 +01:00
1 parent 1716eba8ec
commit 32ebf5f000
36 files changed
+1094 -499

No files matched your search

+5 -7
View File
@@ -579,10 +579,8 @@ namespace Artemis.Core
SKRect bounds = customBounds ?? Bounds;
SKPoint positionProperty = Transform.Position.CurrentValue;
// Start at the center of the shape
SKPoint position = zeroBased
? new SKPoint(bounds.MidX - bounds.Left, bounds.MidY - Bounds.Top)
: new SKPoint(bounds.MidX, bounds.MidY);
// Start at the top left of the shape
SKPoint position = zeroBased ? new SKPoint(0, 0) : new SKPoint(bounds.Left, bounds.Top);
// Apply translation
if (applyTranslation)
@@ -649,9 +647,9 @@ namespace Artemis.Core
SKPoint anchorPosition = GetLayerAnchorPosition(true, zeroBased, bounds);
SKPoint anchorProperty = Transform.AnchorPoint.CurrentValue;
// Translation originates from the unscaled center of the shape and is tied to the anchor
float x = anchorPosition.X - (zeroBased ? bounds.MidX - bounds.Left : bounds.MidX) - anchorProperty.X * bounds.Width;
float y = anchorPosition.Y - (zeroBased ? bounds.MidY - bounds.Top : bounds.MidY) - anchorProperty.Y * bounds.Height;
// Translation originates from the top left of the shape and is tied to the anchor
float x = anchorPosition.X - (zeroBased ? 0 : bounds.Left) - anchorProperty.X * bounds.Width;
float y = anchorPosition.Y - (zeroBased ? 0 : bounds.Top) - anchorProperty.Y * bounds.Height;
SKMatrix transform = SKMatrix.Empty;
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using Artemis.Storage.Entities.Profile;
@@ -201,33 +202,33 @@ namespace Artemis.Core
/// An optional time to set the value add, if provided and property is using keyframes the value will be set to an new
/// or existing keyframe.
/// </param>
/// <returns>The new keyframe if one was created.</returns>
/// <returns>The keyframe if one was created or updated.</returns>
public LayerPropertyKeyframe<T>? SetCurrentValue(T value, TimeSpan? time)
{
if (_disposed)
throw new ObjectDisposedException("LayerProperty");
LayerPropertyKeyframe<T>? newKeyframe = null;
LayerPropertyKeyframe<T>? keyframe = null;
if (time == null || !KeyframesEnabled || !KeyframesSupported)
BaseValue = value;
else
{
// If on a keyframe, update the keyframe
LayerPropertyKeyframe<T>? currentKeyframe = Keyframes.FirstOrDefault(k => k.Position == time.Value);
keyframe = Keyframes.FirstOrDefault(k => k.Position == time.Value);
// Create a new keyframe if none found
if (currentKeyframe == null)
if (keyframe == null)
{
newKeyframe = new LayerPropertyKeyframe<T>(value, time.Value, Easings.Functions.Linear, this);
AddKeyframe(newKeyframe);
keyframe = new LayerPropertyKeyframe<T>(value, time.Value, Easings.Functions.Linear, this);
AddKeyframe(keyframe);
}
else
currentKeyframe.Value = value;
keyframe.Value = value;
}
// Force an update so that the base value is applied to the current value and
// keyframes/data bindings are applied using the new base value
ReapplyUpdate();
return newKeyframe;
return keyframe;
}
/// <inheritdoc />
@@ -0,0 +1,93 @@
using System;
using System.Linq;
namespace Artemis.Core;
/// <summary>
/// Represents a container for a preview value of a <see cref="LayerProperty{T}" /> that can be used to update and
/// discard a temporary value.
/// </summary>
/// <typeparam name="T">The value type of the layer property.</typeparam>
public sealed class LayerPropertyPreview<T> : IDisposable
{
/// <summary>
/// Creates a new instance of the <see cref="LayerPropertyPreview{T}" /> class.
/// </summary>
/// <param name="layerProperty">The layer property to apply the preview value to.</param>
/// <param name="time">The time in the timeline at which the preview is applied.</param>
public LayerPropertyPreview(LayerProperty<T> layerProperty, TimeSpan time)
{
Property = layerProperty;
Time = time;
OriginalKeyframe = layerProperty.Keyframes.FirstOrDefault(k => k.Position == time);
OriginalValue = OriginalKeyframe != null ? OriginalKeyframe.Value : layerProperty.CurrentValue;
PreviewValue = OriginalValue;
}
/// <summary>
/// Gets the property this preview applies to.
/// </summary>
public LayerProperty<T> Property { get; }
/// <summary>
/// Gets the original keyframe of the property at the time the preview was created.
/// </summary>
public LayerPropertyKeyframe<T>? OriginalKeyframe { get; }
/// <summary>
/// Gets the original value of the property at the time the preview was created.
/// </summary>
public T OriginalValue { get; }
/// <summary>
/// Gets the time in the timeline at which the preview is applied.
/// </summary>
public TimeSpan Time { get; }
/// <summary>
/// Gets the keyframe that was created to preview the value.
/// </summary>
public LayerPropertyKeyframe<T>? PreviewKeyframe { get; private set; }
/// <summary>
/// Gets the preview value.
/// </summary>
public T? PreviewValue { get; private set; }
/// <summary>
/// Updates the layer property to the given <paramref name="value" />, keeping track of the original state of the
/// property.
/// </summary>
/// <param name="value">The value to preview.</param>
public void Preview(T value)
{
PreviewValue = value;
PreviewKeyframe = Property.SetCurrentValue(value, Time);
}
/// <summary>
/// Discard the preview value and restores the original state of the property. The returned boolean can be used to
/// determine whether the preview value was different from the original value.
/// </summary>
/// <returns><see langword="true" /> if any changes where discarded; otherwise <see langword="false" />.</returns>
public bool DiscardPreview()
{
if (PreviewKeyframe != null && OriginalKeyframe == null)
{
Property.RemoveKeyframe(PreviewKeyframe);
return true;
}
Property.SetCurrentValue(OriginalValue, Time);
return !Equals(OriginalValue, PreviewValue); ;
}
/// <summary>
/// Discard the preview value and restores the original state of the property. The returned boolean can be used to
/// determine whether the preview value was different from the original value.
/// </summary>
public void Dispose()
{
DiscardPreview();
}
}
@@ -12,13 +12,13 @@ namespace Artemis.Core
/// <summary>
/// The point at which the shape is attached to its position
/// </summary>
[PropertyDescription(Description = "The point at which the shape is attached to its position", InputStepSize = 0.001f)]
[PropertyDescription(Description = "The point at which the shape is attached to its position", InputAffix = "%")]
public SKPointLayerProperty AnchorPoint { get; set; }
/// <summary>
/// The position of the shape
/// </summary>
[PropertyDescription(Description = "The position of the shape", InputStepSize = 0.001f)]
[PropertyDescription(Description = "The position of the shape", InputAffix = "%")]
public SKPointLayerProperty Position { get; set; }
/// <summary>
@@ -43,6 +43,8 @@ namespace Artemis.Core
protected override void PopulateDefaults()
{
Scale.DefaultValue = new SKSize(100, 100);
AnchorPoint.DefaultValue = new SKPoint(0.5f, 0.5f);
Position.DefaultValue = new SKPoint(0.5f, 0.5f);
Opacity.DefaultValue = 100;
}