mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Profile editor - Visualization fixes
Profile editor - Timeline fixes
This commit is contained in:
parent
0b42e7f510
commit
c36110e79d
@ -74,47 +74,10 @@
|
||||
"System.Xml.XmlDocument": "4.3.0"
|
||||
}
|
||||
},
|
||||
"EmbedIO": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.4.3",
|
||||
"contentHash": "YM6hpZNAfvbbixfG9T4lWDGfF0D/TqutbTROL4ogVcHKwPF1hp+xS3ABwd3cxxTxvDFkj/zZl57QgWuFA8Igxw==",
|
||||
"dependencies": {
|
||||
"Unosquare.Swan.Lite": "3.0.0"
|
||||
}
|
||||
},
|
||||
"HidSharp": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.1.0",
|
||||
"contentHash": "UTdxWvbgp2xzT1Ajaa2va+Qi3oNHJPasYmVhbKI2VVdu1VYP6yUG+RikhsHvpD7iM0S8e8UYb5Qm/LTWxx9QAA=="
|
||||
},
|
||||
"LiteDB": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.11",
|
||||
"contentHash": "6cL4bOmVCUB0gIK+6qIr68HeqjjHZicPDGQjvJ87mIOvkFsEsJWkIps3yoKNeLpHhJQur++yoQ9Q8gxsdos0xQ=="
|
||||
},
|
||||
"McMaster.NETCore.Plugins": {
|
||||
"type": "Transitive",
|
||||
"resolved": "1.4.0",
|
||||
"contentHash": "UKw5Z2/QHhkR7kiAJmqdCwVDMQV0lwsfj10+FG676r8DsJWIpxtachtEjE0qBs9WoK5GUQIqxgyFeYUSwuPszg==",
|
||||
"dependencies": {
|
||||
"Microsoft.DotNet.PlatformAbstractions": "3.1.6",
|
||||
"Microsoft.Extensions.DependencyModel": "5.0.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.DotNet.PlatformAbstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.1.6",
|
||||
"contentHash": "jek4XYaQ/PGUwDKKhwR8K47Uh1189PFzMeLqO83mXrXQVIpARZCcfuDedH50YDTepBkfijCZN5U/vZi++erxtg=="
|
||||
},
|
||||
"Microsoft.Extensions.DependencyModel": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "umBECCoMC+sOUgm083yFr8SxTobUOcPFH4AXigdO2xJiszCHAnmeDl4qPphJt+oaJ/XIfV1wOjIts2nRnki61Q=="
|
||||
},
|
||||
"Microsoft.NETCore.Platforms": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "VyPlqzH2wavqquTcYpkIIAQ6WdenuKoFN0BdYBbCWsclXacSOHNQn66Gt4z5NBqEYW0FAPm5rlvki9ZiCij5xQ=="
|
||||
"resolved": "1.1.0",
|
||||
"contentHash": "kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A=="
|
||||
},
|
||||
"Microsoft.NETCore.Targets": {
|
||||
"type": "Transitive",
|
||||
@ -182,19 +145,6 @@
|
||||
"System.Xml.XDocument": "4.3.0"
|
||||
}
|
||||
},
|
||||
"Newtonsoft.Json": {
|
||||
"type": "Transitive",
|
||||
"resolved": "13.0.1",
|
||||
"contentHash": "ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A=="
|
||||
},
|
||||
"Ninject.Extensions.ChildKernel": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.3.0",
|
||||
"contentHash": "vl/p3f8sIaCCHiKsjhq9R8n3bH705Hu1WJXNpMEz1UC79EV51Mk5TWYXQbRnsK20hxF48CiAgUBb9pMKfX6sLw==",
|
||||
"dependencies": {
|
||||
"Ninject": "3.3.4"
|
||||
}
|
||||
},
|
||||
"Ninject.Extensions.Factory": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.3.2",
|
||||
@ -204,27 +154,6 @@
|
||||
"Ninject": "3.3.3"
|
||||
}
|
||||
},
|
||||
"RGB.NET.Core": {
|
||||
"type": "Transitive",
|
||||
"resolved": "1.0.0-prerelease7",
|
||||
"contentHash": "IIja5sC4QZ5pbSNckRCG7TlY4U6j/dRbrl4e2FZqsTGgsevaVB3IqonUQLFY1GGst4xNSl2oh0A23coXQxXGbQ=="
|
||||
},
|
||||
"RGB.NET.Layout": {
|
||||
"type": "Transitive",
|
||||
"resolved": "1.0.0-prerelease7",
|
||||
"contentHash": "S0kfWVa8EfMOAl2WPHsq98dwaO+SNz9TWr1AtMkdo8aZuYIVhaJ1c+mSAMMnH1V+mSbxDWPHWkNzi9ITszJucA==",
|
||||
"dependencies": {
|
||||
"RGB.NET.Core": "1.0.0-prerelease7"
|
||||
}
|
||||
},
|
||||
"RGB.NET.Presets": {
|
||||
"type": "Transitive",
|
||||
"resolved": "1.0.0-prerelease7",
|
||||
"contentHash": "NgShvOPQM0miOsdqMKjkNunngJUZMwr8KR8ME2/Ksir7wgIQfgJj1YwZy8aIj+ar7fDo6VZJZenAshs/Ul+04A==",
|
||||
"dependencies": {
|
||||
"RGB.NET.Core": "1.0.0-prerelease7"
|
||||
}
|
||||
},
|
||||
"runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.3.0",
|
||||
@ -332,38 +261,6 @@
|
||||
"resolved": "4.3.0",
|
||||
"contentHash": "VB5cn/7OzUfzdnC8tqAIMQciVLiq2epm2NrAm1E9OjNRyG4lVhfR61SMcLizejzQP8R8Uf/0l5qOIbUEi+RdEg=="
|
||||
},
|
||||
"Serilog.Sinks.Console": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.0.0",
|
||||
"contentHash": "yJQit9sTJ4xGLKgCujqDJsaGqBNJwGB/H898z+xYlMG06twy4//6LLnSrsmpduZxcHIG4im7cv+JmXLzXz2EkQ==",
|
||||
"dependencies": {
|
||||
"Serilog": "2.10.0"
|
||||
}
|
||||
},
|
||||
"Serilog.Sinks.Debug": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.0.0",
|
||||
"contentHash": "Y6g3OBJ4JzTyyw16fDqtFcQ41qQAydnEvEqmXjhwhgjsnG/FaJ8GUqF5ldsC/bVkK8KYmqrPhDO+tm4dF6xx4A==",
|
||||
"dependencies": {
|
||||
"Serilog": "2.10.0"
|
||||
}
|
||||
},
|
||||
"Serilog.Sinks.File": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "uwV5hdhWPwUH1szhO8PJpFiahqXmzPzJT/sOijH/kFgUx+cyoDTMM8MHD0adw9+Iem6itoibbUXHYslzXsLEAg==",
|
||||
"dependencies": {
|
||||
"Serilog": "2.10.0"
|
||||
}
|
||||
},
|
||||
"SkiaSharp": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.80.3",
|
||||
"contentHash": "qX6tGNP3+MXNYe2pKm0PCRiJ/cx+LTeLaggwZifB7sUMXhECfKKKHJq45VqZKt37xQegnCCdf1jHXwmHeJQs5Q==",
|
||||
"dependencies": {
|
||||
"System.Memory": "4.5.3"
|
||||
}
|
||||
},
|
||||
"System.AppContext": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.3.0",
|
||||
@ -656,15 +553,6 @@
|
||||
"System.Threading.Tasks": "4.3.0"
|
||||
}
|
||||
},
|
||||
"System.IO.FileSystem.AccessControl": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "SxHB3nuNrpptVk+vZ/F+7OHEpoHUIKKMl02bUmYHQr1r+glbZQxs7pRtsf4ENO29TVm2TH3AEeep2fJcy92oYw==",
|
||||
"dependencies": {
|
||||
"System.Security.AccessControl": "5.0.0",
|
||||
"System.Security.Principal.Windows": "5.0.0"
|
||||
}
|
||||
},
|
||||
"System.IO.FileSystem.Primitives": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.3.0",
|
||||
@ -709,11 +597,6 @@
|
||||
"System.Threading": "4.3.0"
|
||||
}
|
||||
},
|
||||
"System.Memory": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.3",
|
||||
"contentHash": "3oDzvc/zzetpTKWMShs1AADwZjQ/36HnsufHRPcOjyRAAMLDlu2iD33MBI2opxnezcVUtXyqDXXjoFMOU9c7SA=="
|
||||
},
|
||||
"System.Net.Http": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.3.0",
|
||||
@ -839,11 +722,6 @@
|
||||
"System.Runtime": "4.3.0"
|
||||
}
|
||||
},
|
||||
"System.Reflection.Metadata": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "5NecZgXktdGg34rh1OenY1rFNDCI8xSjFr+Z4OU4cU06AQHUdRnIIEeWENu3Wl4YowbzkymAIMvi3WyK9U53pQ=="
|
||||
},
|
||||
"System.Reflection.Primitives": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.3.0",
|
||||
@ -942,15 +820,6 @@
|
||||
"System.Runtime.Extensions": "4.3.0"
|
||||
}
|
||||
},
|
||||
"System.Security.AccessControl": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "dagJ1mHZO3Ani8GH0PHpPEe/oYO+rVdbQjvjJkBRNQkX4t0r1iaeGn8+/ybkSLEan3/slM0t59SVdHzuHf2jmw==",
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.Platforms": "5.0.0",
|
||||
"System.Security.Principal.Windows": "5.0.0"
|
||||
}
|
||||
},
|
||||
"System.Security.Cryptography.Algorithms": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.3.0",
|
||||
@ -1095,11 +964,6 @@
|
||||
"runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0"
|
||||
}
|
||||
},
|
||||
"System.Security.Principal.Windows": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "t0MGLukB5WAVU9bO3MGzvlGnyJPgUlcwerXn1kzBRjwLKixT96XV0Uza41W49gVd8zEMFu9vQEFlv0IOrytICA=="
|
||||
},
|
||||
"System.Text.Encoding": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.3.0",
|
||||
@ -1226,45 +1090,8 @@
|
||||
"System.Xml.ReaderWriter": "4.3.0"
|
||||
}
|
||||
},
|
||||
"Unosquare.Swan.Lite": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.0.0",
|
||||
"contentHash": "noPwJJl1Q9uparXy1ogtkmyAPGNfSGb0BLT1292nFH1jdMKje6o2kvvrQUvF9Xklj+IoiAI0UzF6Aqxlvo10lw=="
|
||||
},
|
||||
"artemis.core": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Artemis.Storage": "1.0.0",
|
||||
"EmbedIO": "3.4.3",
|
||||
"HidSharp": "2.1.0",
|
||||
"Humanizer.Core": "2.11.10",
|
||||
"LiteDB": "5.0.11",
|
||||
"McMaster.NETCore.Plugins": "1.4.0",
|
||||
"Newtonsoft.Json": "13.0.1",
|
||||
"Ninject": "3.3.4",
|
||||
"Ninject.Extensions.ChildKernel": "3.3.0",
|
||||
"Ninject.Extensions.Conventions": "3.3.0",
|
||||
"RGB.NET.Core": "1.0.0-prerelease7",
|
||||
"RGB.NET.Layout": "1.0.0-prerelease7",
|
||||
"RGB.NET.Presets": "1.0.0-prerelease7",
|
||||
"Serilog": "2.10.0",
|
||||
"Serilog.Sinks.Console": "4.0.0",
|
||||
"Serilog.Sinks.Debug": "2.0.0",
|
||||
"Serilog.Sinks.File": "5.0.0",
|
||||
"SkiaSharp": "2.80.3",
|
||||
"System.Buffers": "4.5.1",
|
||||
"System.IO.FileSystem.AccessControl": "5.0.0",
|
||||
"System.Numerics.Vectors": "4.5.0",
|
||||
"System.Reflection.Metadata": "5.0.0",
|
||||
"System.ValueTuple": "4.5.0"
|
||||
}
|
||||
},
|
||||
"artemis.storage": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"LiteDB": "5.0.11",
|
||||
"Serilog": "2.10.0"
|
||||
}
|
||||
"type": "Project"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -94,6 +94,12 @@ namespace Artemis.Core
|
||||
if (Disposed)
|
||||
throw new ObjectDisposedException("Folder");
|
||||
|
||||
if (Timeline.IsOverridden)
|
||||
{
|
||||
Timeline.ClearOverride();
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateDisplayCondition();
|
||||
UpdateTimeline(deltaTime);
|
||||
|
||||
|
||||
@ -338,6 +338,12 @@ namespace Artemis.Core
|
||||
if (Disposed)
|
||||
throw new ObjectDisposedException("Layer");
|
||||
|
||||
if (Timeline.IsOverridden)
|
||||
{
|
||||
Timeline.ClearOverride();
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateDisplayCondition();
|
||||
UpdateTimeline(deltaTime);
|
||||
|
||||
|
||||
@ -46,6 +46,7 @@ public class Timeline : CorePropertyChanged, IStorageModel
|
||||
private TimeSpan _startSegmentLength;
|
||||
private TimeSpan _mainSegmentLength;
|
||||
private TimeSpan _endSegmentLength;
|
||||
private TimeSpan _lastOverride;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current position of the timeline
|
||||
@ -251,8 +252,6 @@ public class Timeline : CorePropertyChanged, IStorageModel
|
||||
|
||||
#region Updating
|
||||
|
||||
private TimeSpan _lastOverridePosition;
|
||||
|
||||
/// <summary>
|
||||
/// Updates the timeline, applying the provided <paramref name="delta" /> to the <see cref="Position" />
|
||||
/// </summary>
|
||||
@ -262,12 +261,12 @@ public class Timeline : CorePropertyChanged, IStorageModel
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (IsOverridden)
|
||||
throw new ArtemisCoreException("Can't update an overridden timeline, call ClearOverride first.");
|
||||
|
||||
Delta += delta;
|
||||
Position += delta;
|
||||
|
||||
IsOverridden = false;
|
||||
_lastOverridePosition = Position;
|
||||
|
||||
if (!stickToMainSegment || Position <= MainSegmentEndPosition)
|
||||
return;
|
||||
|
||||
@ -334,16 +333,19 @@ public class Timeline : CorePropertyChanged, IStorageModel
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
Delta += position - _lastOverridePosition;
|
||||
Position = position;
|
||||
if (_lastOverride == TimeSpan.Zero)
|
||||
Delta = Position - position;
|
||||
else
|
||||
Delta = position - _lastOverride;
|
||||
|
||||
Position = position;
|
||||
IsOverridden = true;
|
||||
_lastOverridePosition = position;
|
||||
_lastOverride = position;
|
||||
|
||||
if (!stickToMainSegment || Position < MainSegmentStartPosition)
|
||||
return;
|
||||
|
||||
bool atSegmentStart = Position == MainSegmentStartPosition;
|
||||
bool atSegmentStart = Position >= MainSegmentStartPosition;
|
||||
if (MainSegmentLength > TimeSpan.Zero)
|
||||
{
|
||||
Position = MainSegmentStartPosition + TimeSpan.FromMilliseconds(Position.TotalMilliseconds % MainSegmentLength.TotalMilliseconds);
|
||||
@ -359,6 +361,12 @@ public class Timeline : CorePropertyChanged, IStorageModel
|
||||
}
|
||||
}
|
||||
|
||||
internal void ClearOverride()
|
||||
{
|
||||
IsOverridden = false;
|
||||
_lastOverride = TimeSpan.Zero;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the <see cref="Delta" /> to <see cref="TimeSpan.Zero" />
|
||||
/// </summary>
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using Artemis.Storage.Entities.Profile;
|
||||
using SkiaSharp;
|
||||
|
||||
@ -218,6 +218,7 @@ namespace Artemis.Core.Services
|
||||
);
|
||||
_logger.Information("Startup arguments: {args}", StartupArguments);
|
||||
_logger.Information("Elevated permissions: {perms}", IsElevated);
|
||||
_logger.Information("Stopwatch high resolution: {perms}", Stopwatch.IsHighResolution);
|
||||
|
||||
ApplyLoggingLevel();
|
||||
|
||||
|
||||
@ -43,6 +43,13 @@ public class SelectionRectangle : Control
|
||||
public static readonly StyledProperty<IControl?> InputElementProperty =
|
||||
AvaloniaProperty.Register<SelectionRectangle, IControl?>(nameof(InputElement), notifying: OnInputElementChanged);
|
||||
|
||||
/// <summary>
|
||||
/// Defines the <see cref="ZoomRatio" /> property.
|
||||
/// </summary>
|
||||
public static readonly StyledProperty<double> ZoomRatioProperty =
|
||||
AvaloniaProperty.Register<SelectionRectangle, double>(nameof(ZoomRatio), 1);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Defines the read-only <see cref="IsSelecting" /> property.
|
||||
/// </summary>
|
||||
@ -108,6 +115,15 @@ public class SelectionRectangle : Control
|
||||
set => SetValue(InputElementProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the zoom ratio to counteract when drawing
|
||||
/// </summary>
|
||||
public double ZoomRatio
|
||||
{
|
||||
get => GetValue(ZoomRatioProperty);
|
||||
set => SetValue(ZoomRatioProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a boolean indicating whether the selection rectangle is currently performing a selection.
|
||||
/// </summary>
|
||||
@ -150,6 +166,7 @@ public class SelectionRectangle : Control
|
||||
((SelectionRectangle) sender).SubscribeToInputElement();
|
||||
}
|
||||
|
||||
|
||||
private void ParentOnPointerPressed(object? sender, PointerPressedEventArgs e)
|
||||
{
|
||||
if (!e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)
|
||||
@ -227,7 +244,7 @@ public class SelectionRectangle : Control
|
||||
public override void Render(DrawingContext drawingContext)
|
||||
{
|
||||
if (_displayRect != null)
|
||||
drawingContext.DrawRectangle(Background, new Pen(BorderBrush, BorderThickness), _displayRect.Value, BorderRadius, BorderRadius);
|
||||
drawingContext.DrawRectangle(Background, new Pen(BorderBrush, BorderThickness / ZoomRatio), _displayRect.Value, BorderRadius / ZoomRatio, BorderRadius / ZoomRatio);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Artemis.Core;
|
||||
|
||||
namespace Artemis.UI.Shared.Services.ProfileEditor.Commands;
|
||||
@ -32,16 +33,37 @@ public class ToggleLayerPropertyKeyframes<T> : IProfileEditorCommand
|
||||
/// <inheritdoc />
|
||||
public void Execute()
|
||||
{
|
||||
if (_enable)
|
||||
{
|
||||
_layerProperty.KeyframesEnabled = true;
|
||||
|
||||
// If there weren't any keyframes yet, add one with the current value at the current time
|
||||
if (!_layerProperty.Keyframes.Any())
|
||||
{
|
||||
// If executed before, reuse the previous keyframe
|
||||
_keyframe ??= new LayerPropertyKeyframe<T>(_layerProperty.CurrentValue, _time, Easings.Functions.Linear, _layerProperty);
|
||||
_layerProperty.KeyframesEnabled = _enable;
|
||||
_layerProperty.AddKeyframe(_keyframe);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_layerProperty.KeyframesEnabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Undo()
|
||||
{
|
||||
_layerProperty.RemoveKeyframe(_keyframe!);
|
||||
_layerProperty.KeyframesEnabled = !_enable;
|
||||
if (_enable)
|
||||
{
|
||||
if (_keyframe != null)
|
||||
_layerProperty.RemoveKeyframe(_keyframe);
|
||||
_layerProperty.KeyframesEnabled = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
_layerProperty.KeyframesEnabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@ -33,6 +33,12 @@
|
||||
<controls:HyperlinkButton Classes="icon-button icon-button-small">
|
||||
<avalonia:MaterialIcon Kind="Web" />
|
||||
</controls:HyperlinkButton>
|
||||
|
||||
|
||||
<TextBlock Margin="0 5 0 0">Button.window-button</TextBlock>
|
||||
<Button Classes="title-bar-button">
|
||||
<avalonia:MaterialIcon Kind="WindowMinimize" />
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</Design.PreviewWith>
|
||||
@ -69,4 +75,15 @@
|
||||
<Style Selector="controls|HyperlinkButton.icon-button">
|
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonForeground}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="Button.title-bar-button">
|
||||
<Setter Property="Width" Value="46"></Setter>
|
||||
<Setter Property="Height" Value="32"></Setter>
|
||||
<Setter Property="BorderThickness" Value="0"></Setter>
|
||||
<Setter Property="CornerRadius" Value="0"></Setter>
|
||||
<Setter Property="Margin" Value="0"></Setter>
|
||||
</Style>
|
||||
<Style Selector="Button.title-bar-button:pointerover">
|
||||
<Setter Property="Background" Value="Red"></Setter>
|
||||
</Style>
|
||||
</Styles>
|
||||
@ -5,7 +5,7 @@
|
||||
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.UI.Screens.Debugger.Performance.PerformanceDebugView">
|
||||
<Grid RowDefinitions="Auto,*">
|
||||
<Grid RowDefinitions="Auto,Auto,*">
|
||||
<StackPanel Grid.Row="0">
|
||||
<TextBlock Classes="h3">Performance</TextBlock>
|
||||
<TextBlock TextWrapping="Wrap">
|
||||
@ -21,7 +21,19 @@
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
|
||||
<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Right" Margin="10 0">
|
||||
<TextBlock Text="FPS: " />
|
||||
<TextBlock FontWeight="Bold" Text="{Binding CurrentFps}" />
|
||||
<TextBlock Text=" at " />
|
||||
<TextBlock Text="{Binding RenderWidth}" />
|
||||
<TextBlock Text="x" />
|
||||
<TextBlock Text="{Binding RenderHeight}" />
|
||||
<TextBlock Text=" - Renderer: "></TextBlock>
|
||||
<TextBlock Text="{Binding Renderer}"></TextBlock>
|
||||
</StackPanel>
|
||||
|
||||
|
||||
<ScrollViewer Grid.Row="2" VerticalScrollBarVisibility="Auto">
|
||||
<ItemsControl Items="{Binding Items}" Margin="0 0 10 0" />
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
|
||||
@ -8,16 +8,23 @@ using Artemis.Core;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.UI.Shared;
|
||||
using ReactiveUI;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Artemis.UI.Screens.Debugger.Performance
|
||||
{
|
||||
public class PerformanceDebugViewModel : ActivatableViewModelBase, IRoutableViewModel
|
||||
{
|
||||
private readonly ICoreService _coreService;
|
||||
private readonly IPluginManagementService _pluginManagementService;
|
||||
private double _currentFps;
|
||||
private string? _renderer;
|
||||
private int _renderHeight;
|
||||
private int _renderWidth;
|
||||
|
||||
public PerformanceDebugViewModel(IScreen hostScreen, IPluginManagementService pluginManagementService)
|
||||
public PerformanceDebugViewModel(IScreen hostScreen, ICoreService coreService, IPluginManagementService pluginManagementService)
|
||||
{
|
||||
HostScreen = hostScreen;
|
||||
_coreService = coreService;
|
||||
_pluginManagementService = pluginManagementService;
|
||||
|
||||
Timer updateTimer = new(500);
|
||||
@ -38,6 +45,7 @@ namespace Artemis.UI.Screens.Debugger.Performance
|
||||
.Subscribe(_ => Repopulate())
|
||||
.DisposeWith(disposables);
|
||||
|
||||
HandleActivation();
|
||||
PopulateItems();
|
||||
updateTimer.Start();
|
||||
|
||||
@ -45,14 +53,50 @@ namespace Artemis.UI.Screens.Debugger.Performance
|
||||
{
|
||||
updateTimer.Stop();
|
||||
Items.Clear();
|
||||
HandleDeactivation();
|
||||
}).DisposeWith(disposables);
|
||||
});
|
||||
}
|
||||
|
||||
public ObservableCollection<PerformanceDebugPluginViewModel> Items { get; } = new();
|
||||
|
||||
public string UrlPathSegment => "performance";
|
||||
public IScreen HostScreen { get; }
|
||||
public ObservableCollection<PerformanceDebugPluginViewModel> Items { get; } = new();
|
||||
|
||||
public double CurrentFps
|
||||
{
|
||||
get => _currentFps;
|
||||
set => this.RaiseAndSetIfChanged(ref _currentFps, value);
|
||||
}
|
||||
|
||||
public int RenderWidth
|
||||
{
|
||||
get => _renderWidth;
|
||||
set => this.RaiseAndSetIfChanged(ref _renderWidth, value);
|
||||
}
|
||||
|
||||
public int RenderHeight
|
||||
{
|
||||
get => _renderHeight;
|
||||
set => this.RaiseAndSetIfChanged(ref _renderHeight, value);
|
||||
}
|
||||
|
||||
public string? Renderer
|
||||
{
|
||||
get => _renderer;
|
||||
set => this.RaiseAndSetIfChanged(ref _renderer, value);
|
||||
}
|
||||
|
||||
private void HandleActivation()
|
||||
{
|
||||
Renderer = Constants.ManagedGraphicsContext != null ? Constants.ManagedGraphicsContext.GetType().Name : "Software";
|
||||
_coreService.FrameRendered += CoreServiceOnFrameRendered;
|
||||
}
|
||||
|
||||
private void HandleDeactivation()
|
||||
{
|
||||
_coreService.FrameRendered -= CoreServiceOnFrameRendered;
|
||||
}
|
||||
|
||||
private void PopulateItems()
|
||||
{
|
||||
@ -69,10 +113,19 @@ namespace Artemis.UI.Screens.Debugger.Performance
|
||||
PopulateItems();
|
||||
}
|
||||
|
||||
private void UpdateTimerOnElapsed(object sender, ElapsedEventArgs e)
|
||||
private void UpdateTimerOnElapsed(object? sender, ElapsedEventArgs e)
|
||||
{
|
||||
foreach (PerformanceDebugPluginViewModel viewModel in Items)
|
||||
viewModel.Update();
|
||||
}
|
||||
|
||||
private void CoreServiceOnFrameRendered(object? sender, FrameRenderedEventArgs e)
|
||||
{
|
||||
CurrentFps = _coreService.FrameRate;
|
||||
SKImageInfo bitmapInfo = e.Texture.ImageInfo;
|
||||
|
||||
RenderHeight = bitmapInfo.Height;
|
||||
RenderWidth = bitmapInfo.Width;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -24,6 +24,21 @@
|
||||
<TextBlock Text="{Binding Renderer}"></TextBlock>
|
||||
</StackPanel>
|
||||
|
||||
<Image Source="{Binding CurrentFrame}" />
|
||||
<Border Classes="card">
|
||||
<ZoomBorder Name="ZoomBorder"
|
||||
Stretch="None"
|
||||
ClipToBounds="True"
|
||||
Focusable="True"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalAlignment="Stretch">
|
||||
<Image Name="Visualization" Source="{Binding CurrentFrame}">
|
||||
<Image.Transitions>
|
||||
<Transitions>
|
||||
<TransformOperationsTransition Property="RenderTransform" Duration="0:0:0.2" Easing="CubicEaseOut"/>
|
||||
</Transitions>
|
||||
</Image.Transitions>
|
||||
</Image>
|
||||
</ZoomBorder>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
@ -102,7 +102,6 @@ namespace Artemis.UI.Screens.Debugger.Render
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public string UrlPathSegment => "render";
|
||||
public IScreen HostScreen { get; }
|
||||
}
|
||||
|
||||
@ -9,7 +9,9 @@
|
||||
<controls:SelectionRectangle InputElement="{Binding $parent[ZoomBorder]}"
|
||||
BorderBrush="{DynamicResource SystemAccentColor}"
|
||||
BorderRadius="8"
|
||||
SelectionFinished="SelectionRectangle_OnSelectionFinished">
|
||||
BorderThickness="2"
|
||||
SelectionFinished="SelectionRectangle_OnSelectionFinished"
|
||||
ZoomRatio="{Binding $parent[ZoomBorder].ZoomX}">
|
||||
<controls:SelectionRectangle.Background>
|
||||
<SolidColorBrush Color="{DynamicResource SystemAccentColorLight1}" Opacity="0.2"></SolidColorBrush>
|
||||
</controls:SelectionRectangle.Background>
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using Artemis.UI.Shared.Events;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.ReactiveUI;
|
||||
using Avalonia.Skia;
|
||||
@ -19,6 +20,6 @@ public class SelectionAddToolView : ReactiveUserControl<SelectionAddToolViewMode
|
||||
|
||||
private void SelectionRectangle_OnSelectionFinished(object? sender, SelectionRectangleEventArgs e)
|
||||
{
|
||||
ViewModel?.AddLedsInRectangle(e.Rectangle.ToSKRect());
|
||||
ViewModel?.AddLedsInRectangle(e.Rectangle.ToSKRect(), e.KeyModifiers.HasFlag(KeyModifiers.Shift), e.KeyModifiers.HasFlag(KeyModifiers.Control));
|
||||
}
|
||||
}
|
||||
@ -57,12 +57,26 @@ public class SelectionAddToolViewModel : ToolViewModel
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
public void AddLedsInRectangle(SKRect rect)
|
||||
public void AddLedsInRectangle(SKRect rect, bool expand, bool inverse)
|
||||
{
|
||||
if (_layer == null)
|
||||
return;
|
||||
|
||||
List<ArtemisLed> leds = _rgbService.EnabledDevices.SelectMany(d => d.Leds).Where(l => l.AbsoluteRectangle.IntersectsWith(rect)).ToList();
|
||||
if (inverse)
|
||||
{
|
||||
List<ArtemisLed> toRemove = _layer.Leds.Where(l => l.AbsoluteRectangle.IntersectsWith(rect)).ToList();
|
||||
List<ArtemisLed> toAdd = _rgbService.EnabledDevices.SelectMany(d => d.Leds).Where(l => l.AbsoluteRectangle.IntersectsWith(rect)).Except(toRemove).ToList();
|
||||
List<ArtemisLed> leds = _layer.Leds.Except(toRemove).ToList();
|
||||
leds.AddRange(toAdd);
|
||||
|
||||
_profileEditorService.ExecuteCommand(new ChangeLayerLeds(_layer, leds));
|
||||
}
|
||||
else
|
||||
{
|
||||
List<ArtemisLed> leds = _rgbService.EnabledDevices.SelectMany(d => d.Leds).Where(l => l.AbsoluteRectangle.IntersectsWith(rect)).ToList();
|
||||
if (expand)
|
||||
leds.AddRange(_layer.Leds);
|
||||
_profileEditorService.ExecuteCommand(new ChangeLayerLeds(_layer, leds.Distinct().ToList()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -11,7 +11,9 @@
|
||||
<controls:SelectionRectangle InputElement="{Binding $parent[paz:ZoomBorder]}"
|
||||
BorderBrush="{DynamicResource SystemAccentColor}"
|
||||
BorderRadius="8"
|
||||
SelectionFinished="SelectionRectangle_OnSelectionFinished">
|
||||
BorderThickness="2"
|
||||
SelectionFinished="SelectionRectangle_OnSelectionFinished"
|
||||
ZoomRatio="{Binding $parent[ZoomBorder].ZoomX}">
|
||||
<controls:SelectionRectangle.Background>
|
||||
<SolidColorBrush Color="{DynamicResource SystemAccentColorLight1}" Opacity="0.2"></SolidColorBrush>
|
||||
</controls:SelectionRectangle.Background>
|
||||
|
||||
@ -10,6 +10,13 @@
|
||||
<UserControl.Styles>
|
||||
<Style Selector="Path.layer-visualizer">
|
||||
<Setter Property="Stroke" Value="{StaticResource ButtonBorderBrushDisabled}" />
|
||||
<Setter Property="Transitions">
|
||||
<Setter.Value>
|
||||
<Transitions>
|
||||
<DoubleTransition Property="StrokeThickness" Duration="0:0:0.2" Easing="CubicEaseOut"></DoubleTransition>
|
||||
</Transitions>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
<Style Selector="Path.layer-visualizer-selected">
|
||||
<Setter Property="Stroke" Value="{StaticResource SystemAccentColorLight1}" />
|
||||
@ -17,27 +24,35 @@
|
||||
<Style Selector="Path.layer-visualizer-unbound">
|
||||
<Setter Property="Stroke" Value="{StaticResource ButtonBorderBrushDisabled}" />
|
||||
<Setter Property="Opacity" Value="0.50" />
|
||||
<Setter Property="Transitions">
|
||||
<Setter.Value>
|
||||
<Transitions>
|
||||
<DoubleTransition Property="StrokeThickness" Duration="0:0:0.2" Easing="CubicEaseOut"></DoubleTransition>
|
||||
</Transitions>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
<Style Selector="Path.layer-visualizer-unbound-selected">
|
||||
<Setter Property="Opacity" Value="0.75" />
|
||||
</Style>
|
||||
</UserControl.Styles>
|
||||
<Canvas>
|
||||
<Path Classes="layer-visualizer-unbound"
|
||||
<Path Name="LayerVisualizerUnbound"
|
||||
Classes="layer-visualizer-unbound"
|
||||
Classes.layer-visualizer-unbound-selected="{CompiledBinding Selected}"
|
||||
Data="{CompiledBinding ShapeGeometry, Mode=OneWay}"
|
||||
StrokeThickness="2"
|
||||
Margin="0 0 2 2"
|
||||
StrokeThickness="4"
|
||||
StrokeJoin="Round">
|
||||
</Path>
|
||||
<Border ClipToBounds="True"
|
||||
Width="{CompiledBinding LayerBounds.Width}"
|
||||
Height="{CompiledBinding LayerBounds.Height}">
|
||||
<Path Classes="layer-visualizer"
|
||||
<Border Name="LayerVisualizerBounds"
|
||||
ClipToBounds="True"
|
||||
Width="{CompiledBinding LayerBounds.Width, Mode=OneWay}"
|
||||
Height="{CompiledBinding LayerBounds.Height, Mode=OneWay}">
|
||||
<Path Name="LayerVisualizer"
|
||||
Classes="layer-visualizer"
|
||||
Classes.layer-visualizer-selected="{CompiledBinding Selected}"
|
||||
Data="{CompiledBinding ShapeGeometry, Mode=OneWay}"
|
||||
StrokeThickness="2"
|
||||
Margin="0 0 2 2"
|
||||
StrokeThickness="4"
|
||||
StrokeJoin="Round">
|
||||
</Path>
|
||||
</Border>
|
||||
|
||||
@ -1,3 +1,10 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.PanAndZoom;
|
||||
using Avalonia.Controls.Shapes;
|
||||
using Avalonia.LogicalTree;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.ReactiveUI;
|
||||
|
||||
@ -5,14 +12,50 @@ namespace Artemis.UI.Screens.ProfileEditor.VisualEditor.Visualizers
|
||||
{
|
||||
public partial class LayerShapeVisualizerView : ReactiveUserControl<LayerShapeVisualizerViewModel>
|
||||
{
|
||||
private ZoomBorder? _zoomBorder;
|
||||
private readonly Path _layerVisualizerUnbound;
|
||||
private readonly Path _layerVisualizer;
|
||||
|
||||
public LayerShapeVisualizerView()
|
||||
{
|
||||
InitializeComponent();
|
||||
_layerVisualizer = this.Get<Path>("LayerVisualizer");
|
||||
_layerVisualizerUnbound = this.Get<Path>("LayerVisualizerUnbound");
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
|
||||
#region Overrides of TemplatedControl
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
|
||||
{
|
||||
_zoomBorder = (ZoomBorder?) this.GetLogicalAncestors().FirstOrDefault(l => l is ZoomBorder);
|
||||
if (_zoomBorder != null)
|
||||
_zoomBorder.PropertyChanged += ZoomBorderOnPropertyChanged;
|
||||
base.OnAttachedToLogicalTree(e);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e)
|
||||
{
|
||||
if (_zoomBorder != null)
|
||||
_zoomBorder.PropertyChanged -= ZoomBorderOnPropertyChanged;
|
||||
base.OnDetachedFromLogicalTree(e);
|
||||
}
|
||||
|
||||
private void ZoomBorderOnPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.Property != ZoomBorder.ZoomXProperty || _zoomBorder == null)
|
||||
return;
|
||||
|
||||
_layerVisualizer.StrokeThickness = Math.Max(1, 4 / _zoomBorder.ZoomX);
|
||||
_layerVisualizerUnbound.StrokeThickness = _layerVisualizer.StrokeThickness;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -15,10 +15,10 @@
|
||||
<Setter Property="Stroke" Value="{StaticResource SystemAccentColorDark2}" />
|
||||
</Style>
|
||||
</UserControl.Styles>
|
||||
<Path Classes="layer-visualizer"
|
||||
<Path Name="LayerVisualizer"
|
||||
Classes="layer-visualizer"
|
||||
Classes.layer-visualizer-selected="{CompiledBinding Selected}"
|
||||
StrokeThickness="2"
|
||||
Margin="0 0 2 2"
|
||||
StrokeThickness="4"
|
||||
StrokeDashArray="6,2"
|
||||
StrokeJoin="Round">
|
||||
<Path.Data>
|
||||
|
||||
@ -1,15 +1,55 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.PanAndZoom;
|
||||
using Avalonia.Controls.Shapes;
|
||||
using Avalonia.LogicalTree;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.ReactiveUI;
|
||||
using Avalonia.VisualTree;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.VisualEditor.Visualizers
|
||||
{
|
||||
public partial class LayerVisualizerView : ReactiveUserControl<LayerVisualizerViewModel>
|
||||
{
|
||||
private ZoomBorder? _zoomBorder;
|
||||
private readonly Path _layerVisualizer;
|
||||
|
||||
public LayerVisualizerView()
|
||||
{
|
||||
InitializeComponent();
|
||||
_layerVisualizer = this.Get<Path>("LayerVisualizer");
|
||||
}
|
||||
|
||||
#region Overrides of TemplatedControl
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
|
||||
{
|
||||
_zoomBorder = (ZoomBorder?) this.GetLogicalAncestors().FirstOrDefault(l => l is ZoomBorder);
|
||||
if (_zoomBorder != null)
|
||||
_zoomBorder.PropertyChanged += ZoomBorderOnPropertyChanged;
|
||||
base.OnAttachedToLogicalTree(e);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e)
|
||||
{
|
||||
if (_zoomBorder != null)
|
||||
_zoomBorder.PropertyChanged -= ZoomBorderOnPropertyChanged;
|
||||
base.OnDetachedFromLogicalTree(e);
|
||||
}
|
||||
|
||||
private void ZoomBorderOnPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.Property != ZoomBorder.ZoomXProperty || _zoomBorder == null)
|
||||
return;
|
||||
_layerVisualizer.StrokeThickness = Math.Max(1, 4 / _zoomBorder.ZoomX);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.UI.Screens.Root.DefaultTitleBarView">
|
||||
<Button Classes="icon-button icon-button-small" Command="{Binding ShowDebugger}" HorizontalAlignment="Right">
|
||||
<Button Classes="title-bar-button" Command="{Binding ShowDebugger}" HorizontalAlignment="Right">
|
||||
<avalonia:MaterialIcon Kind="Bug"></avalonia:MaterialIcon>
|
||||
</Button>
|
||||
</UserControl>
|
||||
Loading…
x
Reference in New Issue
Block a user