diff --git a/src/Artemis.Core/Models/Profile/KeyframeEngines/KeyframeEngine.cs b/src/Artemis.Core/Models/Profile/KeyframeEngines/KeyframeEngine.cs index a48a74457..60396b945 100644 --- a/src/Artemis.Core/Models/Profile/KeyframeEngines/KeyframeEngine.cs +++ b/src/Artemis.Core/Models/Profile/KeyframeEngines/KeyframeEngine.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.Linq; using Artemis.Core.Exceptions; using Artemis.Core.Models.Profile.LayerProperties; diff --git a/src/Artemis.Core/Models/Profile/Layer.cs b/src/Artemis.Core/Models/Profile/Layer.cs index 8654becaa..e8e4a86f4 100644 --- a/src/Artemis.Core/Models/Profile/Layer.cs +++ b/src/Artemis.Core/Models/Profile/Layer.cs @@ -1,9 +1,7 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; -using System.Diagnostics; using System.Linq; -using System.Net.Sockets; using Artemis.Core.Exceptions; using Artemis.Core.Extensions; using Artemis.Core.Models.Profile.LayerProperties; @@ -22,7 +20,6 @@ namespace Artemis.Core.Models.Profile private LayerShape _layerShape; private List _leds; private SKPath _path; - private SKRect _bounds; public Layer(Profile profile, ProfileElement parent, string name) { @@ -95,14 +92,14 @@ namespace Artemis.Core.Models.Profile _path = value; // I can't really be sure about the performance impact of calling Bounds often but // SkiaSharp calls SkiaApi.sk_path_get_bounds (Handle, &rect); which sounds expensive - _bounds = value?.Bounds ?? SKRect.Empty; + Bounds = value?.Bounds ?? SKRect.Empty; } } /// - /// The bounds of this layer + /// The bounds of this layer /// - public SKRect Bounds => _bounds; + public SKRect Bounds { get; private set; } /// /// Defines the shape that is rendered by the . @@ -175,20 +172,22 @@ namespace Artemis.Core.Models.Profile canvas.ClipPath(Path); // Apply transformations - var position = PositionProperty.CurrentValue; - var size = SizeProperty.CurrentValue; - var rotation = RotationProperty.CurrentValue; + var sizeProperty = SizeProperty.CurrentValue; + var rotationProperty = RotationProperty.CurrentValue; - var anchor = GetLayerAnchor(); + var anchorPosition = GetLayerAnchorPosition() + Bounds.Location; + var anchorProperty = AnchorPointProperty.CurrentValue; // Translation originates from the unscaled center of the shape and is tied to the anchor - var x = position.X * Bounds.Width - LayerShape.Bounds.Width / 2 - anchor.X; - var y = position.Y * Bounds.Height - LayerShape.Bounds.Height / 2 - anchor.Y; + var x = anchorPosition.X - LayerShape.Bounds.Width / 2 - anchorProperty.X * Bounds.Width; + var y = anchorPosition.Y - LayerShape.Bounds.Height / 2 - anchorProperty.Y * Bounds.Height; + + // Apply these before translation because anchorPosition takes translation into account + canvas.RotateDegrees(rotationProperty, anchorPosition.X, anchorPosition.Y); + canvas.Scale(sizeProperty.Width, sizeProperty.Height, anchorPosition.X, anchorPosition.Y); + // Once the other transformations are done it is save to translate + canvas.Translate(x, y); - canvas.Translate(Bounds.Left + x, Bounds.Top + y); - canvas.Scale(size.Width, size.Height, anchor.X, anchor.Y); - canvas.RotateDegrees(rotation, anchor.X, anchor.Y); - // Placeholder if (LayerShape?.Path != null) { @@ -209,15 +208,18 @@ namespace Artemis.Core.Models.Profile canvas.Restore(); } - private SKPoint GetLayerAnchor() + private SKPoint GetLayerAnchorPosition() { - if (LayerShape == null) - return SKPoint.Empty; + var positionProperty = PositionProperty.CurrentValue; - var anchor = AnchorPointProperty.CurrentValue; - anchor.X = anchor.X * Bounds.Width; - anchor.Y = anchor.Y * Bounds.Height; - return new SKPoint(anchor.X, anchor.Y); + // Start at the center of the shape + var position = new SKPoint(LayerShape.Bounds.Left, LayerShape.Bounds.Top); + + // Apply translation + position.X += positionProperty.X * Bounds.Width; + position.Y += positionProperty.Y * Bounds.Height; + + return position; } internal override void ApplyToEntity() diff --git a/src/Artemis.Core/Plugins/Abstract/ProfileModule.cs b/src/Artemis.Core/Plugins/Abstract/ProfileModule.cs index ff72cdde9..d7a0ab15f 100644 --- a/src/Artemis.Core/Plugins/Abstract/ProfileModule.cs +++ b/src/Artemis.Core/Plugins/Abstract/ProfileModule.cs @@ -13,13 +13,13 @@ namespace Artemis.Core.Plugins.Abstract { } + public Profile ActiveProfile { get; private set; } + public override void EnablePlugin() { throw new NotImplementedException(); } - public Profile ActiveProfile { get; private set; } - /// public override void Update(double deltaTime) { diff --git a/src/Artemis.Core/Services/CoreService.cs b/src/Artemis.Core/Services/CoreService.cs index 67075912c..dddf834d6 100644 --- a/src/Artemis.Core/Services/CoreService.cs +++ b/src/Artemis.Core/Services/CoreService.cs @@ -21,9 +21,9 @@ namespace Artemis.Core.Services { private readonly ILogger _logger; private readonly IPluginService _pluginService; + private readonly IProfileService _profileService; private readonly IRgbService _rgbService; private readonly ISurfaceService _surfaceService; - private readonly IProfileService _profileService; private List _modules; internal CoreService(ILogger logger, IPluginService pluginService, IRgbService rgbService, ISurfaceService surfaceService, IProfileService profileService) diff --git a/src/Artemis.Core/Services/Interfaces/ICoreService.cs b/src/Artemis.Core/Services/Interfaces/ICoreService.cs index e3a3d712e..453df8244 100644 --- a/src/Artemis.Core/Services/Interfaces/ICoreService.cs +++ b/src/Artemis.Core/Services/Interfaces/ICoreService.cs @@ -11,11 +11,12 @@ namespace Artemis.Core.Services.Interfaces bool IsInitialized { get; } /// - /// Gets or sets whether modules are updated each frame by calling their Update method + /// Gets or sets whether modules are updated each frame by calling their Update method /// bool ModuleUpdatingDisabled { get; set; } + /// - /// Gets or sets whether modules are rendered each frame by calling their Render method + /// Gets or sets whether modules are rendered each frame by calling their Render method /// bool ModuleRenderingDisabled { get; set; } diff --git a/src/Artemis.Plugins.LayerBrushes.Color/ColorBrush.cs b/src/Artemis.Plugins.LayerBrushes.Color/ColorBrush.cs index c1ac4e068..fb8d3283e 100644 --- a/src/Artemis.Plugins.LayerBrushes.Color/ColorBrush.cs +++ b/src/Artemis.Plugins.LayerBrushes.Color/ColorBrush.cs @@ -9,9 +9,9 @@ namespace Artemis.Plugins.LayerBrushes.Color { public class ColorBrush : LayerBrush { + private readonly List _testColors; private SKPaint _paint; private SKShader _shader; - private readonly List _testColors; public ColorBrush(Layer layer, ColorBrushSettings settings, LayerBrushDescriptor descriptor) : base(layer, settings, descriptor) { diff --git a/src/Artemis.Plugins.LayerBrushes.Noise/Utilities/OpenSimplexNoise.cs b/src/Artemis.Plugins.LayerBrushes.Noise/Utilities/OpenSimplexNoise.cs index 97d48c2b2..03e891d9a 100644 --- a/src/Artemis.Plugins.LayerBrushes.Noise/Utilities/OpenSimplexNoise.cs +++ b/src/Artemis.Plugins.LayerBrushes.Noise/Utilities/OpenSimplexNoise.cs @@ -458,9 +458,9 @@ namespace Artemis.Plugins.LayerBrushes.Noise.Utilities { public readonly double dx; public readonly double dy; - public Contribution2 Next; public readonly int xsb; public readonly int ysb; + public Contribution2 Next; public Contribution2(double multiplier, int xsb, int ysb) { @@ -476,10 +476,10 @@ namespace Artemis.Plugins.LayerBrushes.Noise.Utilities public readonly double dx; public readonly double dy; public readonly double dz; - public Contribution3 Next; public readonly int xsb; public readonly int ysb; public readonly int zsb; + public Contribution3 Next; public Contribution3(double multiplier, int xsb, int ysb, int zsb) { @@ -494,15 +494,15 @@ namespace Artemis.Plugins.LayerBrushes.Noise.Utilities private class Contribution4 { + public readonly double dw; public readonly double dx; public readonly double dy; public readonly double dz; - public readonly double dw; - public Contribution4 Next; + public readonly int wsb; public readonly int xsb; public readonly int ysb; public readonly int zsb; - public readonly int wsb; + public Contribution4 Next; public Contribution4(double multiplier, int xsb, int ysb, int zsb, int wsb) { diff --git a/src/Artemis.UI/Artemis.UI.csproj b/src/Artemis.UI/Artemis.UI.csproj index 607dff520..bb8c3118c 100644 --- a/src/Artemis.UI/Artemis.UI.csproj +++ b/src/Artemis.UI/Artemis.UI.csproj @@ -226,6 +226,7 @@ SidebarView.xaml + diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesView.xaml index b12302f3e..de275c1f2 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesView.xaml +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesView.xaml @@ -61,7 +61,7 @@ - diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs index 8eb887d1a..66e6f7c60 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs @@ -103,12 +103,9 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties public void PlayFromStart() { - if (!IsActive) - return; - if (Playing) - Pause(); + if (!Playing) + _profileEditorService.CurrentTime = TimeSpan.Zero; - _profileEditorService.CurrentTime = TimeSpan.Zero; Play(); } diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileEditorViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileEditorViewModel.cs index 0e00b26bf..f1416b518 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileEditorViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileEditorViewModel.cs @@ -196,7 +196,6 @@ namespace Artemis.UI.Screens.Module.ProfileEditor if (!activeProfile.IsActivated) _profileService.ActivateProfile(Module, activeProfile); }); - } } } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileLayerViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileLayerViewModel.cs index 5c3a6465c..112a63c3e 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileLayerViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileLayerViewModel.cs @@ -5,12 +5,9 @@ using System.Windows.Media; using Artemis.Core.Models.Profile; using Artemis.Core.Models.Profile.LayerShapes; using Artemis.Core.Models.Surface; -using Artemis.Core.Services; using Artemis.UI.Extensions; -using Artemis.UI.Services; using Artemis.UI.Services.Interfaces; using RGB.NET.Core; -using SkiaSharp.Views.WPF; using Stylet; using Rectangle = Artemis.Core.Models.Profile.LayerShapes.Rectangle; @@ -18,8 +15,8 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization { public class ProfileLayerViewModel : CanvasViewModel { - private readonly IProfileEditorService _profileEditorService; private readonly ILayerEditorService _layerEditorService; + private readonly IProfileEditorService _profileEditorService; public ProfileLayerViewModel(Layer layer, IProfileEditorService profileEditorService, ILayerEditorService layerEditorService) { @@ -145,13 +142,8 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization return; } - var x = Layer.Leds.Min(l => l.RgbLed.AbsoluteLedRectangle.Location.X); - var y = Layer.Leds.Min(l => l.RgbLed.AbsoluteLedRectangle.Location.Y); - var width = Layer.Leds.Max(l => l.RgbLed.AbsoluteLedRectangle.Location.X + l.RgbLed.AbsoluteLedRectangle.Size.Width) - x; - var height = Layer.Leds.Max(l => l.RgbLed.AbsoluteLedRectangle.Location.Y + l.RgbLed.AbsoluteLedRectangle.Size.Height) - y; - - var rect = new Rect(x, y, width, height); - ViewportRectangle = rect; + var rect = _layerEditorService.GetLayerBounds(Layer); + ViewportRectangle = new Rect(0, 0, rect.Width, rect.Height); } private Geometry CreateRectangleGeometry(ArtemisLed led) diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileViewModel.cs index 64472dc4b..6e4333247 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileViewModel.cs @@ -14,7 +14,6 @@ using Artemis.UI.Events; using Artemis.UI.Ninject.Factories; using Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools; using Artemis.UI.Screens.Shared; -using Artemis.UI.Services; using Artemis.UI.Services.Interfaces; using RGB.NET.Core; using Stylet; @@ -23,8 +22,8 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization { public class ProfileViewModel : ProfileEditorPanelViewModel, IHandle, IHandle { - private readonly IProfileEditorService _profileEditorService; private readonly ILayerEditorService _layerEditorService; + private readonly IProfileEditorService _profileEditorService; private readonly IProfileLayerViewModelFactory _profileLayerViewModelFactory; private readonly ISettingsService _settingsService; private readonly ISurfaceService _surfaceService; diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/EditToolViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/EditToolViewModel.cs index 82634c9c5..adda988d5 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/EditToolViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/EditToolViewModel.cs @@ -4,7 +4,6 @@ using System.Windows.Input; using System.Windows.Media; using Artemis.Core.Models.Profile; using Artemis.UI.Events; -using Artemis.UI.Services; using Artemis.UI.Services.Interfaces; using SkiaSharp; using SkiaSharp.Views.WPF; @@ -45,7 +44,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools LayerBounds = _layerEditorService.GetLayerBounds(layer); ShapePath = _layerEditorService.GetLayerPath(layer, true, true, true); - ShapeAnchor = _layerEditorService.GetLayerAnchor(layer).ToSKPoint(); + ShapeAnchor = _layerEditorService.GetLayerAnchorPosition(layer).ToSKPoint(); Execute.PostToUIThread(() => { var shapeGeometry = new RectangleGeometry(_layerEditorService.GetLayerShapeBounds(layer.LayerShape)) @@ -59,7 +58,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools // Store the last top-left for easy later on _topLeft = _layerEditorService.GetLayerPath(layer, true, true, true).Points[0]; } - + #region Rotation private bool _rotating; @@ -69,7 +68,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools { _rotating = true; if (ProfileEditorService.SelectedProfileElement is Layer layer) - _previousDragAngle = CalculateAngle(_layerEditorService.GetLayerAnchor(layer), GetRelativePosition(sender, e.MouseEventArgs)); + _previousDragAngle = CalculateAngle(_layerEditorService.GetLayerAnchorPosition(layer), GetRelativePosition(sender, e.MouseEventArgs)); else _previousDragAngle = 0; } @@ -86,7 +85,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools return; var previousDragAngle = _previousDragAngle; - var newRotation = CalculateAngle(_layerEditorService.GetLayerAnchor(layer), GetRelativePosition(sender, e.MouseEventArgs)); + var newRotation = CalculateAngle(_layerEditorService.GetLayerAnchorPosition(layer), GetRelativePosition(sender, e.MouseEventArgs)); _previousDragAngle = newRotation; // Allow the user to rotate the shape in increments of 5 @@ -280,7 +279,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools // 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).ToSKPoint() - topLeft; + _dragStartAnchor = _layerEditorService.GetLayerAnchorPosition(layer).ToSKPoint() - 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; diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/EllipseToolViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/EllipseToolViewModel.cs index 6379c8bb5..1f41c0167 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/EllipseToolViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/EllipseToolViewModel.cs @@ -1,13 +1,10 @@ -using System.Diagnostics; -using System.IO; +using System.IO; using System.Windows; using System.Windows.Input; using Artemis.Core.Models.Profile; using Artemis.Core.Models.Profile.LayerShapes; using Artemis.UI.Properties; -using Artemis.UI.Services; using Artemis.UI.Services.Interfaces; -using SkiaSharp.Views.WPF; namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools { diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/FillToolViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/FillToolViewModel.cs index f62a98286..85c4aee81 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/FillToolViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/FillToolViewModel.cs @@ -1,12 +1,9 @@ -using System; -using System.Diagnostics; -using System.IO; +using System.IO; using System.Linq; using System.Windows; using System.Windows.Input; using Artemis.Core.Models.Profile.LayerShapes; using Artemis.UI.Properties; -using Artemis.UI.Services; using Artemis.UI.Services.Interfaces; namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/RectangleToolViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/RectangleToolViewModel.cs index 499278f44..8721fcba9 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/RectangleToolViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/RectangleToolViewModel.cs @@ -4,9 +4,7 @@ using System.Windows.Input; using Artemis.Core.Models.Profile; using Artemis.Core.Models.Profile.LayerShapes; using Artemis.UI.Properties; -using Artemis.UI.Services; using Artemis.UI.Services.Interfaces; -using SkiaSharp.Views.WPF; namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools { @@ -15,7 +13,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools private readonly ILayerEditorService _layerEditorService; private bool _shiftDown; - public RectangleToolViewModel(ProfileViewModel profileViewModel, IProfileEditorService profileEditorService, ILayerEditorService layerEditorService) + public RectangleToolViewModel(ProfileViewModel profileViewModel, IProfileEditorService profileEditorService, ILayerEditorService layerEditorService) : base(profileViewModel, profileEditorService) { _layerEditorService = layerEditorService; diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/SelectionRemoveToolViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/SelectionRemoveToolViewModel.cs index c3ee49bc9..e9578a292 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/SelectionRemoveToolViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/SelectionRemoveToolViewModel.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using System.Diagnostics; using System.IO; using System.Linq; using System.Windows; @@ -8,10 +7,8 @@ using Artemis.Core.Models.Profile; using Artemis.Core.Models.Surface; using Artemis.UI.Extensions; using Artemis.UI.Properties; -using Artemis.UI.Services; using Artemis.UI.Services.Interfaces; using SkiaSharp; -using SkiaSharp.Views.WPF; namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools { @@ -62,11 +59,11 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools var remainingLeds = layer.Leds.Except(selectedLeds).ToList(); layer.ClearLeds(); layer.AddLeds(remainingLeds); - + // Restore the saved size if (layer.LayerShape != null) layer.LayerShape.SetFromUnscaledRectangle(shapeSize); - + ProfileEditorService.UpdateSelectedProfileElement(); } } diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/SelectionToolViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/SelectionToolViewModel.cs index 0652a9c50..bbdc197a0 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/SelectionToolViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/SelectionToolViewModel.cs @@ -7,7 +7,6 @@ using Artemis.Core.Models.Profile; using Artemis.Core.Models.Surface; using Artemis.UI.Extensions; using Artemis.UI.Properties; -using Artemis.UI.Services; using Artemis.UI.Services.Interfaces; using SkiaSharp; @@ -28,7 +27,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools } public Rect DragRectangle { get; set; } - + public override void MouseUp(object sender, MouseButtonEventArgs e) { base.MouseUp(sender, e); diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/UserControls/LayerShapeControl.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/UserControls/LayerShapeControl.xaml index ac020b13a..577741372 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/UserControls/LayerShapeControl.xaml +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/UserControls/LayerShapeControl.xaml @@ -12,25 +12,25 @@ Cursor="/Resources/aero_rotate.cur" MouseDown="RotationOnMouseDown" MouseUp="RotationOnMouseUp" - MouseMove="RotationOnMouseMove"/> + MouseMove="RotationOnMouseMove" /> + MouseMove="RotationOnMouseMove" /> + MouseMove="RotationOnMouseMove" /> + MouseMove="RotationOnMouseMove" /> + MouseMove="ResizeOnMouseMove" /> + MouseMove="MoveOnMouseMove" /> \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/UserControls/LayerShapeControl.xaml.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/UserControls/LayerShapeControl.xaml.cs index 676eaa337..b3bf0d415 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/UserControls/LayerShapeControl.xaml.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/UserControls/LayerShapeControl.xaml.cs @@ -4,7 +4,6 @@ using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; using Artemis.UI.Events; -using Artemis.UI.Utilities; using SkiaSharp; namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.UserControls @@ -38,7 +37,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.UserControls get => (double) GetValue(ZoomProperty); set => SetValue(ZoomProperty, value); } - + public SKPath ShapePath { get => (SKPath) GetValue(ShapePathProperty); @@ -64,7 +63,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.UserControls layerShapeControl.SetCurrentValue(ZoomProperty, e.NewValue); layerShapeControl.UpdateDimensions(); } - + private static void ShapePathChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var layerShapeControl = (LayerShapeControl) d; diff --git a/src/Artemis.UI/Screens/Shared/PanZoomViewModel.cs b/src/Artemis.UI/Screens/Shared/PanZoomViewModel.cs index f21832154..0b2e4d82e 100644 --- a/src/Artemis.UI/Screens/Shared/PanZoomViewModel.cs +++ b/src/Artemis.UI/Screens/Shared/PanZoomViewModel.cs @@ -51,7 +51,7 @@ namespace Artemis.UI.Screens.Shared } else { - PanX = absoluteX - relative.X * Zoom; + PanX = absoluteX - relative.X * Zoom; PanY = absoluteY - relative.Y * Zoom; } } diff --git a/src/Artemis.UI/Services/Interfaces/ILayerEditorService.cs b/src/Artemis.UI/Services/Interfaces/ILayerEditorService.cs new file mode 100644 index 000000000..107f74638 --- /dev/null +++ b/src/Artemis.UI/Services/Interfaces/ILayerEditorService.cs @@ -0,0 +1,67 @@ +using System.Windows; +using System.Windows.Media; +using Artemis.Core.Models.Profile; +using Artemis.Core.Models.Profile.LayerShapes; +using SkiaSharp; + +namespace Artemis.UI.Services.Interfaces +{ + public interface ILayerEditorService : IArtemisUIService + { + /// + /// Returns the layer's bounds, corrected for the current render scale. + /// + /// + /// + Rect GetLayerBounds(Layer layer); + + /// + /// Returns the layer's anchor, corrected for the current render scale. + /// + /// + /// + Point GetLayerAnchorPosition(Layer layer); + + /// + /// Returns the layer shape's bounds, corrected for the current render scale. + /// + /// + /// + Rect GetLayerShapeBounds(LayerShape layerShape); + + /// + /// Creates a WPF transform group that contains all the transformations required to render the provided layer. + /// Note: Run on UI thread. + /// + /// + /// + TransformGroup GetLayerTransformGroup(Layer layer); + + /// + /// Returns an absolute and scaled rectangular path for the given layer that is corrected for the current render scale. + /// + /// + /// + /// + /// + /// + SKPath GetLayerPath(Layer layer, bool includeTranslation, bool includeScale, bool includeRotation); + + /// + /// Sets the base properties of the given shape to match the provided unscaled rectangle. The rectangle is corrected + /// for the current render scale, anchor property and size property. + /// + /// + /// + void SetShapeBaseFromRectangle(LayerShape layerShape, Rect rect); + + /// + /// Returns a new point scaled to the layer. + /// + /// + /// + /// + /// + SKPoint GetScaledPoint(Layer layer, SKPoint point, bool absolute); + } +} \ No newline at end of file diff --git a/src/Artemis.UI/Services/LayerShapeService.cs b/src/Artemis.UI/Services/LayerShapeService.cs index 6f4ce0420..f4694ce89 100644 --- a/src/Artemis.UI/Services/LayerShapeService.cs +++ b/src/Artemis.UI/Services/LayerShapeService.cs @@ -47,16 +47,20 @@ namespace Artemis.UI.Services } /// - public Point GetLayerAnchor(Layer layer) + public Point GetLayerAnchorPosition(Layer layer) { var layerBounds = GetLayerBounds(layer); + var shapeBounds = GetLayerShapeBounds(layer.LayerShape); + var positionProperty = layer.PositionProperty.CurrentValue; - // TODO figure out what else is needed, position should matter here - var anchor = layer.AnchorPointProperty.CurrentValue; - anchor.X = (float) (anchor.X * layerBounds.Width); - anchor.Y = (float) (anchor.Y * layerBounds.Height); + // Start at the center of the shape + var position = new Point(shapeBounds.Left, shapeBounds.Top); - return new Point(anchor.X * layerBounds.Width, anchor.Y * layerBounds.Height); + // Apply translation + position.X += positionProperty.X * layerBounds.Width; + position.Y += positionProperty.Y * layerBounds.Height; + + return position; } /// @@ -65,17 +69,21 @@ namespace Artemis.UI.Services var layerBounds = GetLayerBounds(layer).ToSKRect(); var shapeBounds = GetLayerShapeBounds(layer.LayerShape).ToSKRect(); - // Apply transformation like done by the core during layer rendering - var anchor = GetLayerAnchor(layer); + // Apply transformation like done by the core during layer rendering. + // The order in which translations are applied are different because the UI renders the shape inside + // the layer using the structure of the XAML while the Core has to deal with that by applying the layer + // position to the translation + var anchorPosition = GetLayerAnchorPosition(layer); + var anchorProperty = layer.AnchorPointProperty.CurrentValue; // Translation originates from the unscaled center of the shape and is tied to the anchor - var x = layer.PositionProperty.CurrentValue.X * layerBounds.Width - shapeBounds.Width / 2 - anchor.X; - var y = layer.PositionProperty.CurrentValue.Y * layerBounds.Height - shapeBounds.Height / 2 - anchor.Y; + var x = anchorPosition.X - shapeBounds.Width / 2 - anchorProperty.X * layerBounds.Width; + var y = anchorPosition.Y - shapeBounds.Height / 2 - anchorProperty.Y * layerBounds.Height; var transformGroup = new TransformGroup(); transformGroup.Children.Add(new TranslateTransform(x, y)); - transformGroup.Children.Add(new ScaleTransform(layer.SizeProperty.CurrentValue.Width, layer.SizeProperty.CurrentValue.Height, anchor.X, anchor.Y)); - transformGroup.Children.Add(new RotateTransform(layer.RotationProperty.CurrentValue, anchor.X, anchor.Y)); + transformGroup.Children.Add(new ScaleTransform(layer.SizeProperty.CurrentValue.Width, layer.SizeProperty.CurrentValue.Height, anchorPosition.X, anchorPosition.Y)); + transformGroup.Children.Add(new RotateTransform(layer.RotationProperty.CurrentValue, anchorPosition.X, anchorPosition.Y)); return transformGroup; } @@ -86,21 +94,22 @@ namespace Artemis.UI.Services var layerBounds = GetLayerBounds(layer).ToSKRect(); var shapeBounds = GetLayerShapeBounds(layer.LayerShape).ToSKRect(); - // Apply transformation like done by the core during layer rendering - var anchor = GetLayerAnchor(layer).ToSKPoint(); + // Apply transformation like done by the core during layer rendering (same differences apply as in GetLayerTransformGroup) + var anchorPosition = GetLayerAnchorPosition(layer).ToSKPoint(); + var anchorProperty = layer.AnchorPointProperty.CurrentValue; // Translation originates from the unscaled center of the shape and is tied to the anchor - var x = layer.PositionProperty.CurrentValue.X * layerBounds.Width - shapeBounds.Width / 2 - anchor.X; - var y = layer.PositionProperty.CurrentValue.Y * layerBounds.Height - shapeBounds.Height / 2 - anchor.Y; + var x = anchorPosition.X - shapeBounds.Width / 2 - anchorProperty.X * layerBounds.Width; + var y = anchorPosition.Y - shapeBounds.Height / 2 - anchorProperty.Y * layerBounds.Height; var path = new SKPath(); path.AddRect(shapeBounds); 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)); + path.Transform(SKMatrix.MakeScale(layer.SizeProperty.CurrentValue.Width, layer.SizeProperty.CurrentValue.Height, anchorPosition.X, anchorPosition.Y)); if (includeRotation) - path.Transform(SKMatrix.MakeRotationDegrees(layer.RotationProperty.CurrentValue, anchor.X, anchor.Y)); + path.Transform(SKMatrix.MakeRotationDegrees(layer.RotationProperty.CurrentValue, anchorPosition.X, anchorPosition.Y)); return path; } @@ -159,63 +168,4 @@ namespace Artemis.UI.Services ); } } - - public interface ILayerEditorService : IArtemisUIService - { - /// - /// Returns the layer's bounds, corrected for the current render scale. - /// - /// - /// - Rect GetLayerBounds(Layer layer); - - /// - /// Returns the layer's anchor, corrected for the current render scale. - /// - /// - /// - Point GetLayerAnchor(Layer layer); - - /// - /// Returns the layer shape's bounds, corrected for the current render scale. - /// - /// - /// - Rect GetLayerShapeBounds(LayerShape layerShape); - - /// - /// Creates a WPF transform group that contains all the transformations required to render the provided layer. - /// Note: Run on UI thread. - /// - /// - /// - TransformGroup GetLayerTransformGroup(Layer layer); - - /// - /// Returns an absolute and scaled rectangular path for the given layer that is corrected for the current render scale. - /// - /// - /// - /// - /// - /// - SKPath GetLayerPath(Layer layer, bool includeTranslation, bool includeScale, bool includeRotation); - - /// - /// Sets the base properties of the given shape to match the provided unscaled rectangle. The rectangle is corrected - /// for the current render scale, anchor property and size property. - /// - /// - /// - void SetShapeBaseFromRectangle(LayerShape layerShape, Rect rect); - - /// - /// Returns a new point scaled to the layer. - /// - /// - /// - /// - /// - SKPoint GetScaledPoint(Layer layer, SKPoint point, bool absolute); - } } \ No newline at end of file diff --git a/src/Artemis.UI/Services/ProfileEditorService.cs b/src/Artemis.UI/Services/ProfileEditorService.cs index c3bb8bc0d..e8cbfe5af 100644 --- a/src/Artemis.UI/Services/ProfileEditorService.cs +++ b/src/Artemis.UI/Services/ProfileEditorService.cs @@ -79,7 +79,7 @@ namespace Artemis.UI.Services // Force layer shape to redraw layer.LayerShape?.CalculateRenderProperties(); // Manually update the layer's engine and brush - foreach (var property in layer.Properties) + foreach (var property in layer.Properties) property.KeyframeEngine?.Update(delta.TotalSeconds); layer.LayerBrush?.Update(delta.TotalSeconds); }