mirror of
https://github.com/Artemis-RGB/Artemis
synced 2026-11-09 18:36:27 +00:00
* Profile editor - Fix undoing profile editor commands - Undoing a change to an existing keyframe's value restores the value instead of deleting the keyframe - Undoing "remove effect" puts the effect back in its place instead of below the next one - Undoing "toggle keyframes" restores what it was before - Undoing a brush change on a layer that had no brush removes the brush again, using the new Layer.RemoveLayerBrush - Undoing "add element" disables the element again - Undoing an event path change back to no path goes back to an event start node, like a new condition - MoveProfileElement says "Move folder" for folders - UpdateLayerProperty without a time no longer calls itself "Add ... keyframe" * Profile editor - Fix auto-saving, failing commands, suspended editing and smaller editor issues - A failed auto-save no longer stops auto-saving for the rest of the session - A failing command is no longer also reported to ReactiveUI as unhandled, on top of the error dialog - Resuming editing applies the editor's time again right away - Nothing is focused while editing is suspended - A layer created on another layer gets a name that isn't in use next to it - CanUndo and CanRedo start out false, so new subscribers know the state right away - An empty command scope doesn't add an undo step - New subscribers to History get the current history once - Expanding the keyframe selection with an already selected keyframe doesn't add it twice - Snapping can snap to a snap time of zero
173 lines
5.8 KiB
C#
173 lines
5.8 KiB
C#
using Artemis.UI.Shared.Services.ProfileEditor.Commands;
|
|
using Artemis.UI.Shared.Tests.Infrastructure;
|
|
using RGB.NET.Core;
|
|
|
|
namespace Artemis.UI.Shared.Tests.ProfileEditor;
|
|
|
|
/// <summary>
|
|
/// Moving through time in the editor, which overrides the timelines of the profile being edited, and suspending editing
|
|
/// </summary>
|
|
public class ProfileEditorTimeTests : ProfileEditorTestBase
|
|
{
|
|
[Fact]
|
|
public async Task ChangeTime_MovesTheTimelineOfEveryElement()
|
|
{
|
|
Folder folder = Harness.AddFolder(Root, "Folder");
|
|
Layer layer = AddLayer("Layer", folder, LedId.Keyboard_A);
|
|
await StartEditing();
|
|
|
|
Service.ChangeTime(TimeSpan.FromSeconds(1.5));
|
|
|
|
Current(Service.Time).ShouldBe(TimeSpan.FromSeconds(1.5));
|
|
foreach (RenderProfileElement element in new RenderProfileElement[] {Root, folder, layer})
|
|
{
|
|
element.Timeline.Position.ShouldBe(TimeSpan.FromSeconds(1.5));
|
|
element.Timeline.IsOverridden.ShouldBeTrue();
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ChangeTime_EnablesElements()
|
|
{
|
|
Folder folder = Harness.AddFolder(Root, "Folder");
|
|
Layer layer = AddLayer("Layer", folder, LedId.Keyboard_A);
|
|
folder.Disable();
|
|
layer.Disable();
|
|
await StartEditing();
|
|
|
|
Service.ChangeTime(TimeSpan.FromSeconds(1));
|
|
|
|
folder.Enabled.ShouldBeTrue();
|
|
layer.Enabled.ShouldBeTrue();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ChangeTime_AppliesKeyframesAtTheNewTime()
|
|
{
|
|
Layer layer = AddLayer("Layer", null, LedId.Keyboard_A);
|
|
FloatLayerProperty opacity = layer.Transform.Opacity;
|
|
opacity.KeyframesEnabled = true;
|
|
opacity.AddKeyframe(new LayerPropertyKeyframe<float>(0, TimeSpan.Zero, Easings.Functions.Linear, opacity));
|
|
opacity.AddKeyframe(new LayerPropertyKeyframe<float>(100, TimeSpan.FromSeconds(2), Easings.Functions.Linear, opacity));
|
|
await StartEditing();
|
|
|
|
Service.ChangeTime(TimeSpan.FromSeconds(1));
|
|
opacity.CurrentValue.ShouldBe(50, 0.01f);
|
|
|
|
Service.ChangeTime(TimeSpan.FromSeconds(2));
|
|
opacity.CurrentValue.ShouldBe(100, 0.01f);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ChangeTime_DisablesSuspendedElementsAndSkipsTheirChildren()
|
|
{
|
|
Folder folder = Harness.AddFolder(Root, "Folder");
|
|
Layer layer = AddLayer("Layer", folder, LedId.Keyboard_A);
|
|
await StartEditing();
|
|
Service.ChangeTime(TimeSpan.FromSeconds(1));
|
|
|
|
folder.Suspended = true;
|
|
Service.ChangeTime(TimeSpan.FromSeconds(2));
|
|
|
|
// Disabling a folder disables its children, their timelines are left where they were
|
|
folder.Enabled.ShouldBeFalse();
|
|
layer.Enabled.ShouldBeFalse();
|
|
layer.Timeline.Position.ShouldBe(TimeSpan.FromSeconds(1));
|
|
}
|
|
|
|
[Fact]
|
|
public void ChangeTime_WithoutProfile_OnlyChangesTheTime()
|
|
{
|
|
Layer layer = AddLayer("Layer", null, LedId.Keyboard_A);
|
|
|
|
Service.ChangeTime(TimeSpan.FromSeconds(1));
|
|
|
|
Current(Service.Time).ShouldBe(TimeSpan.FromSeconds(1));
|
|
layer.Timeline.IsOverridden.ShouldBeFalse();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ChangeTime_WhileEditingIsSuspended_LeavesTheProfileAlone()
|
|
{
|
|
Layer layer = AddLayer("Layer", null, LedId.Keyboard_A);
|
|
await StartEditing();
|
|
Service.ChangeSuspendedEditing(true);
|
|
|
|
Service.ChangeTime(TimeSpan.FromSeconds(1));
|
|
|
|
Current(Service.Time).ShouldBe(TimeSpan.FromSeconds(1));
|
|
layer.Timeline.Position.ShouldNotBe(TimeSpan.FromSeconds(1));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ExecuteCommand_AppliesTheCurrentTimeToTheChangedProfile()
|
|
{
|
|
await StartEditing();
|
|
Service.ChangeTime(TimeSpan.FromSeconds(1));
|
|
Layer layer = new(Root, "New layer");
|
|
|
|
Service.ExecuteCommand(new AddProfileElement(layer, Root, 0));
|
|
|
|
layer.Timeline.Position.ShouldBe(TimeSpan.FromSeconds(1));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task SuspendingEditing_StopsPlayingAndHandsTheProfileBackToNormalPlayback()
|
|
{
|
|
Layer layer = AddLayer("Layer", null, LedId.Keyboard_A);
|
|
await StartEditing();
|
|
Service.ChangeTime(TimeSpan.FromSeconds(2));
|
|
Service.Play();
|
|
|
|
Service.ChangeSuspendedEditing(true);
|
|
|
|
Current(Service.SuspendedEditing).ShouldBeTrue();
|
|
Current(Service.Playing).ShouldBeFalse();
|
|
ProfileService.UpdateFocusProfile.ShouldBeTrue();
|
|
// The profile is reset so it plays from the start
|
|
layer.Timeline.Position.ShouldBe(TimeSpan.Zero);
|
|
// The editor keeps its own time
|
|
Current(Service.Time).ShouldBe(TimeSpan.FromSeconds(2));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ResumingEditing_TakesBackControlAndAppliesTheTime()
|
|
{
|
|
Layer layer = AddLayer("Layer", null, LedId.Keyboard_A);
|
|
await StartEditing();
|
|
Service.ChangeTime(TimeSpan.FromSeconds(2));
|
|
Service.ChangeSuspendedEditing(true);
|
|
|
|
Service.ChangeSuspendedEditing(false);
|
|
|
|
Current(Service.SuspendedEditing).ShouldBeFalse();
|
|
ProfileService.UpdateFocusProfile.ShouldBeFalse();
|
|
Current(Service.Time).ShouldBe(TimeSpan.FromSeconds(2));
|
|
layer.Timeline.Position.ShouldBe(TimeSpan.FromSeconds(2));
|
|
}
|
|
|
|
[Fact]
|
|
public void ResumingEditing_WithoutProfile_LeavesTheProfileServiceAlone()
|
|
{
|
|
Service.ChangeSuspendedEditing(true);
|
|
ProfileService.UpdateFocusProfile.ShouldBeTrue();
|
|
|
|
Service.ChangeSuspendedEditing(false);
|
|
|
|
ProfileService.UpdateFocusProfile.ShouldBeTrue();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ChangeSuspendedEditing_ToTheCurrentValue_DoesNothing()
|
|
{
|
|
await StartEditing();
|
|
List<bool> received = [];
|
|
using IDisposable _ = Service.SuspendedEditing.Subscribe(received.Add);
|
|
|
|
Service.ChangeSuspendedEditing(false);
|
|
|
|
received.ShouldBe([false]);
|
|
ProfileService.UpdateFocusProfile.ShouldBeFalse();
|
|
}
|
|
}
|