1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-13 05:48:35 +00:00

UI - Updated Stylet

Keyframes - Finished copy/paste implementation
This commit is contained in:
Robert 2020-12-03 19:35:38 +01:00
parent 0fd30aef2d
commit dd73c1e4c9
14 changed files with 177 additions and 64 deletions

View File

@ -16,10 +16,15 @@ namespace Artemis.Core
/// <summary> /// <summary>
/// Gets the description attribute applied to this property /// Gets the description attribute applied to this property
/// </summary> /// </summary>
public PropertyDescriptionAttribute PropertyDescription { get; } PropertyDescriptionAttribute PropertyDescription { get; }
/// <summary> /// <summary>
/// Gets the unique path of the property on the layer /// The parent group of this layer property, set after construction
/// </summary>
LayerPropertyGroup LayerPropertyGroup { get; }
/// <summary>
/// Gets the unique path of the property on the layer
/// </summary> /// </summary>
public string Path { get; } public string Path { get; }
@ -30,7 +35,7 @@ namespace Artemis.Core
/// <see cref="LayerProperty{T}" /> /// <see cref="LayerProperty{T}" />
/// </para> /// </para>
/// </summary> /// </summary>
void Initialize(RenderProfileElement profileElement, LayerPropertyGroup @group, PropertyEntity entity, bool fromStorage, PropertyDescriptionAttribute description, string path); void Initialize(RenderProfileElement profileElement, LayerPropertyGroup group, PropertyEntity entity, bool fromStorage, PropertyDescriptionAttribute description, string path);
/// <summary> /// <summary>
/// Returns a list off all data binding registrations /// Returns a list off all data binding registrations
@ -38,7 +43,14 @@ namespace Artemis.Core
List<IDataBindingRegistration> GetAllDataBindingRegistrations(); List<IDataBindingRegistration> GetAllDataBindingRegistrations();
/// <summary> /// <summary>
/// Updates the layer properties internal state /// Attempts to load and add the provided keyframe entity to the layer property
/// </summary>
/// <param name="keyframeEntity">The entity representing the keyframe to add</param>
/// <returns>If succeeded the resulting keyframe, otherwise <see langword="null" /></returns>
ILayerPropertyKeyframe? AddKeyframeEntity(KeyframeEntity keyframeEntity);
/// <summary>
/// Updates the layer properties internal state
/// </summary> /// </summary>
/// <param name="timeline">The timeline to apply to the property</param> /// <param name="timeline">The timeline to apply to the property</param>
void Update(Timeline timeline); void Update(Timeline timeline);

View File

@ -118,9 +118,7 @@ namespace Artemis.Core
/// </summary> /// </summary>
public RenderProfileElement ProfileElement { get; internal set; } public RenderProfileElement ProfileElement { get; internal set; }
/// <summary> /// <inheritdoc />
/// The parent group of this layer property, set after construction
/// </summary>
public LayerPropertyGroup LayerPropertyGroup { get; internal set; } public LayerPropertyGroup LayerPropertyGroup { get; internal set; }
#endregion #endregion
@ -282,6 +280,22 @@ namespace Artemis.Core
OnKeyframeAdded(); OnKeyframeAdded();
} }
/// <inheritdoc />
public ILayerPropertyKeyframe? AddKeyframeEntity(KeyframeEntity keyframeEntity)
{
if (keyframeEntity.Position > ProfileElement.Timeline.Length)
return null;
T value = CoreJson.DeserializeObject<T>(keyframeEntity.Value);
if (value == null)
return null;
LayerPropertyKeyframe<T> keyframe = new LayerPropertyKeyframe<T>(
CoreJson.DeserializeObject<T>(keyframeEntity.Value)!, keyframeEntity.Position, (Easings.Functions) keyframeEntity.EasingFunction, this
);
AddKeyframe(keyframe);
return keyframe;
}
/// <summary> /// <summary>
/// Removes a keyframe from the layer property /// Removes a keyframe from the layer property
/// </summary> /// </summary>
@ -508,6 +522,7 @@ namespace Artemis.Core
if (!IsLoadedFromStorage) if (!IsLoadedFromStorage)
ApplyDefaultValue(null); ApplyDefaultValue(null);
else else
{
try try
{ {
if (Entity.Value != null) if (Entity.Value != null)
@ -517,6 +532,7 @@ namespace Artemis.Core
{ {
// ignored for now // ignored for now
} }
}
CurrentValue = BaseValue; CurrentValue = BaseValue;
KeyframesEnabled = Entity.KeyframesEnabled; KeyframesEnabled = Entity.KeyframesEnabled;
@ -524,12 +540,8 @@ namespace Artemis.Core
_keyframes.Clear(); _keyframes.Clear();
try try
{ {
_keyframes.AddRange(Entity.KeyframeEntities foreach (KeyframeEntity keyframeEntity in Entity.KeyframeEntities.Where(k => k.Position <= ProfileElement.Timeline.Length))
.Where(k => k.Position <= ProfileElement.Timeline.Length) AddKeyframeEntity(keyframeEntity);
.Select(k => new LayerPropertyKeyframe<T>(
CoreJson.DeserializeObject<T>(k.Value)!, k.Position, (Easings.Functions) k.EasingFunction, this
))
);
} }
catch (JsonException) catch (JsonException)
{ {

View File

@ -43,7 +43,7 @@
<PackageReference Include="SharpVectors.Reloaded" Version="1.6.0" /> <PackageReference Include="SharpVectors.Reloaded" Version="1.6.0" />
<PackageReference Include="SkiaSharp" Version="2.80.2" /> <PackageReference Include="SkiaSharp" Version="2.80.2" />
<PackageReference Include="SkiaSharp.Views.WPF" Version="2.80.2" /> <PackageReference Include="SkiaSharp.Views.WPF" Version="2.80.2" />
<PackageReference Include="Stylet" Version="1.3.4" /> <PackageReference Include="Stylet" Version="1.3.5" />
<PackageReference Include="System.Buffers" Version="4.5.0" /> <PackageReference Include="System.Buffers" Version="4.5.0" />
<PackageReference Include="System.Numerics.Vectors" Version="4.5.0" /> <PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />
<PackageReference Include="Unclassified.NetRevisionTask" Version="0.3.0"> <PackageReference Include="Unclassified.NetRevisionTask" Version="0.3.0">

View File

@ -85,9 +85,9 @@
}, },
"Stylet": { "Stylet": {
"type": "Direct", "type": "Direct",
"requested": "[1.3.4, )", "requested": "[1.3.5, )",
"resolved": "1.3.4", "resolved": "1.3.5",
"contentHash": "bCEdA+AIi+TM9SQQGLYMsFRIfzZcDUDg2Mznyr72kOkcC/cdBj01/jel4/v2aoKwbFcxVjiqmpgnbsFgMEZ4zQ==", "contentHash": "9vjjaTgf5sZAGHnxQWIslD32MG5gXj7ANgS+w965L5Eh//UC3qwZDrEf226Pf+v1P/ldAJDpUySnOyGlb3TSSw==",
"dependencies": { "dependencies": {
"System.Drawing.Common": "4.6.0" "System.Drawing.Common": "4.6.0"
} }

View File

@ -145,7 +145,7 @@
<PackageReference Include="RawInput.Sharp" Version="0.0.3" /> <PackageReference Include="RawInput.Sharp" Version="0.0.3" />
<PackageReference Include="Serilog" Version="2.9.0" /> <PackageReference Include="Serilog" Version="2.9.0" />
<PackageReference Include="SkiaSharp.Views.WPF" Version="2.80.2" /> <PackageReference Include="SkiaSharp.Views.WPF" Version="2.80.2" />
<PackageReference Include="Stylet" Version="1.3.4" /> <PackageReference Include="Stylet" Version="1.3.5" />
<PackageReference Include="System.Buffers" Version="4.5.0" /> <PackageReference Include="System.Buffers" Version="4.5.0" />
<PackageReference Include="System.ComponentModel.Annotations" Version="4.7.0" /> <PackageReference Include="System.ComponentModel.Annotations" Version="4.7.0" />
<PackageReference Include="System.Drawing.Common" Version="4.7.0" /> <PackageReference Include="System.Drawing.Common" Version="4.7.0" />

View File

@ -1,6 +1,7 @@
using System.Collections.Specialized; using System.Collections.Specialized;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Input;
using Microsoft.Xaml.Behaviors; using Microsoft.Xaml.Behaviors;
namespace Artemis.UI.Behaviors namespace Artemis.UI.Behaviors
@ -105,7 +106,8 @@ namespace Artemis.UI.Behaviors
{ {
item.IsSelected = true; item.IsSelected = true;
// Focus the newly selected item as if was clicked // Focus the newly selected item as if was clicked
item.Focus(); if (FocusManager.GetIsFocusScope(item))
item.Focus();
if (ExpandSelected) if (ExpandSelected)
item.IsExpanded = true; item.IsExpanded = true;
} }

View File

@ -199,6 +199,12 @@
<materialDesign:CircleWipe /> <materialDesign:CircleWipe />
</materialDesign:TransitionerSlide.BackwardWipe> </materialDesign:TransitionerSlide.BackwardWipe>
<Grid> <Grid>
<Grid.InputBindings>
<KeyBinding Key="Delete" Command="{s:Action DeleteKeyframes}" s:View.ActionTarget="{Binding TimelineViewModel}"/>
<KeyBinding Key="D" Modifiers="Control" Command="{s:Action DuplicateKeyframes}" s:View.ActionTarget="{Binding TimelineViewModel}" />
<KeyBinding Key="C" Modifiers="Control" Command="{s:Action CopyKeyframes}" s:View.ActionTarget="{Binding TimelineViewModel}"/>
<KeyBinding Key="V" Modifiers="Control" Command="{s:Action PasteKeyframes}" s:View.ActionTarget="{Binding TimelineViewModel}"/>
</Grid.InputBindings>
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="48" /> <RowDefinition Height="48" />
<RowDefinition Height="*" /> <RowDefinition Height="*" />
@ -206,7 +212,11 @@
</Grid.RowDefinitions> </Grid.RowDefinitions>
<!-- Timeline headers --> <!-- Timeline headers -->
<ScrollViewer Grid.Row="0" x:Name="TimelineHeaderScrollViewer" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden" ScrollChanged="TimelineScrollChanged"> <ScrollViewer Grid.Row="0"
x:Name="TimelineHeaderScrollViewer"
HorizontalScrollBarVisibility="Hidden"
VerticalScrollBarVisibility="Hidden"
ScrollChanged="TimelineScrollChanged">
<Canvas Background="{DynamicResource MaterialDesignCardBackground}" Width="{Binding ActualWidth, ElementName=PropertyTimeLine}"> <Canvas Background="{DynamicResource MaterialDesignCardBackground}" Width="{Binding ActualWidth, ElementName=PropertyTimeLine}">
<!-- Timeline segments --> <!-- Timeline segments -->
<ContentControl Canvas.Left="{Binding EndTimelineSegmentViewModel.SegmentStartPosition}" s:View.Model="{Binding EndTimelineSegmentViewModel}" /> <ContentControl Canvas.Left="{Binding EndTimelineSegmentViewModel.SegmentStartPosition}" s:View.Model="{Binding EndTimelineSegmentViewModel}" />

View File

@ -1,32 +1,86 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using Artemis.Core; using Artemis.Core;
using Artemis.Storage.Entities.Profile; using Artemis.Storage.Entities.Profile;
using Artemis.UI.Exceptions; using Artemis.UI.Exceptions;
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline.Models namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline.Models
{ {
public class KeyframeClipboardModel public class KeyframesClipboardModel
{ {
public Dictionary<string, KeyframeEntity> KeyframeEntities { get; set; } // ReSharper disable once UnusedMember.Global - For JSON.NET
public KeyframeClipboardModel(List<ILayerPropertyKeyframe> keyframes) public KeyframesClipboardModel()
{ {
KeyframeEntities = new Dictionary<string, KeyframeEntity>(); ClipboardModels = new List<KeyframeClipboardModel>();
foreach (ILayerPropertyKeyframe keyframe in keyframes)
{
KeyframeEntities.Add(keyframe.UntypedLayerProperty.Path, );
}
} }
public void Paste(RenderProfileElement target, TimeSpan pastePosition) public KeyframesClipboardModel(IEnumerable<ILayerPropertyKeyframe> keyframes)
{
ClipboardModels = new List<KeyframeClipboardModel>();
foreach (ILayerPropertyKeyframe keyframe in keyframes.OrderBy(k => k.Position))
ClipboardModels.Add(new KeyframeClipboardModel(keyframe));
}
public List<KeyframeClipboardModel> ClipboardModels { get; set; }
public bool HasBeenPasted { get; set; }
public List<ILayerPropertyKeyframe> Paste(RenderProfileElement target, TimeSpan pastePosition)
{ {
if (target == null) throw new ArgumentNullException(nameof(target)); if (target == null) throw new ArgumentNullException(nameof(target));
if (HasBeenPasted) if (HasBeenPasted)
throw new ArtemisUIException("Clipboard model can only be pasted once"); throw new ArtemisUIException("Clipboard model can only be pasted once");
List<ILayerPropertyKeyframe> results = new List<ILayerPropertyKeyframe>();
if (!ClipboardModels.Any())
return results;
// Determine the offset by looking at the position of the first keyframe, start pasting from there
TimeSpan offset = pastePosition - ClipboardModels.First().KeyframeEntity.Position;
List<ILayerProperty> properties = target.GetAllLayerProperties();
foreach (KeyframeClipboardModel clipboardModel in ClipboardModels)
{
ILayerPropertyKeyframe layerPropertyKeyframe = clipboardModel.Paste(properties, offset);
if (layerPropertyKeyframe != null)
results.Add(layerPropertyKeyframe);
}
HasBeenPasted = true; HasBeenPasted = true;
return results;
}
}
public class KeyframeClipboardModel
{
// ReSharper disable once UnusedMember.Global - For JSON.NET
public KeyframeClipboardModel()
{
} }
public bool HasBeenPasted { get; set; } public KeyframeClipboardModel(ILayerPropertyKeyframe layerPropertyKeyframe)
{
FeatureId = layerPropertyKeyframe.UntypedLayerProperty.LayerPropertyGroup.Feature.Id;
Path = layerPropertyKeyframe.UntypedLayerProperty.Path;
KeyframeEntity = layerPropertyKeyframe.GetKeyframeEntity();
}
public string FeatureId { get; set; }
public string Path { get; set; }
public KeyframeEntity KeyframeEntity { get; set; }
public ILayerPropertyKeyframe Paste(List<ILayerProperty> properties, TimeSpan offset)
{
ILayerProperty property = properties.FirstOrDefault(p => p.LayerPropertyGroup.Feature.Id == FeatureId && p.Path == Path);
if (property != null)
{
KeyframeEntity.Position += offset;
ILayerPropertyKeyframe keyframe = property.AddKeyframeEntity(KeyframeEntity);
KeyframeEntity.Position -= offset;
return keyframe;
}
return null;
}
} }
} }

View File

@ -19,12 +19,6 @@
Height="{Binding LayerPropertiesViewModel.TreeViewModelHeight}" Height="{Binding LayerPropertiesViewModel.TreeViewModelHeight}"
VerticalAlignment="Top" VerticalAlignment="Top"
Focusable="True"> Focusable="True">
<Grid.InputBindings>
<KeyBinding Key="Delete" Command="{s:Action DeleteKeyframes}" />
<KeyBinding Key="D" Modifiers="Control" Command="{s:Action DuplicateKeyframes}" />
<KeyBinding Key="C" Modifiers="Control" Command="{s:Action CopyKeyframes}" />
<KeyBinding Key="V" Modifiers="Control" Command="{s:Action PasteKeyframes}" />
</Grid.InputBindings>
<Grid.Triggers> <Grid.Triggers>
<EventTrigger RoutedEvent="UIElement.MouseLeftButtonDown"> <EventTrigger RoutedEvent="UIElement.MouseLeftButtonDown">
<BeginStoryboard> <BeginStoryboard>
@ -43,12 +37,12 @@
</Grid.Triggers> </Grid.Triggers>
<Grid.ContextMenu> <Grid.ContextMenu>
<ContextMenu> <ContextMenu>
<MenuItem Header="Duplicate" Command="{s:Action DuplicateKeyframes}" CommandParameter="{Binding}" InputGestureText="Ctrl+D" IsEnabled="False"> <MenuItem Header="Duplicate" Command="{s:Action DuplicateKeyframes}" CommandParameter="{Binding}" InputGestureText="Ctrl+D">
<MenuItem.Icon> <MenuItem.Icon>
<materialDesign:PackIcon Kind="ContentDuplicate" /> <materialDesign:PackIcon Kind="ContentDuplicate" />
</MenuItem.Icon> </MenuItem.Icon>
</MenuItem> </MenuItem>
<MenuItem Header="Copy" Command="{s:Action CopyKeyframes}" CommandParameter="{Binding}" InputGestureText="Ctrl+C" IsEnabled="False"> <MenuItem Header="Copy" Command="{s:Action CopyKeyframes}" CommandParameter="{Binding}" InputGestureText="Ctrl+C">
<MenuItem.Icon> <MenuItem.Icon>
<materialDesign:PackIcon Kind="ContentCopy" /> <materialDesign:PackIcon Kind="ContentCopy" />
</MenuItem.Icon> </MenuItem.Icon>
@ -59,7 +53,7 @@
</MenuItem.Icon> </MenuItem.Icon>
</MenuItem> </MenuItem>
<Separator /> <Separator />
<MenuItem Header="Delete" Command="{s:Action DeleteKeyframes}" InputGestureText="Del" IsEnabled="False"> <MenuItem Header="Delete" Command="{s:Action DeleteKeyframes}" InputGestureText="Del">
<MenuItem.Icon> <MenuItem.Icon>
<materialDesign:PackIcon Kind="Delete" /> <materialDesign:PackIcon Kind="Delete" />
</MenuItem.Icon> </MenuItem.Icon>

View File

@ -158,13 +158,17 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
public bool CanDuplicateKeyframes => GetAllKeyframeViewModels().Any(k => k.IsSelected); public bool CanDuplicateKeyframes => GetAllKeyframeViewModels().Any(k => k.IsSelected);
public bool CanCopyKeyframes => GetAllKeyframeViewModels().Any(k => k.IsSelected); public bool CanCopyKeyframes => GetAllKeyframeViewModels().Any(k => k.IsSelected);
public bool CanDeleteKeyframes => GetAllKeyframeViewModels().Any(k => k.IsSelected); public bool CanDeleteKeyframes => GetAllKeyframeViewModels().Any(k => k.IsSelected);
public bool CanPasteKeyframes => JsonClipboard.GetData() is KeyframeClipboardModel; public bool CanPasteKeyframes => JsonClipboard.GetData() is KeyframesClipboardModel;
private TimeSpan? _contextMenuOpenPosition; private TimeSpan? _contextMenuOpenPosition;
public void ContextMenuOpening(object sender, ContextMenuEventArgs e) public void ContextMenuOpening(object sender, ContextMenuEventArgs e)
{ {
_contextMenuOpenPosition = GetCursorTime(new Point(e.CursorLeft, e.CursorTop)); _contextMenuOpenPosition = GetCursorTime(new Point(e.CursorLeft, e.CursorTop));
NotifyOfPropertyChange(nameof(CanDuplicateKeyframes));
NotifyOfPropertyChange(nameof(CanCopyKeyframes));
NotifyOfPropertyChange(nameof(CanDeleteKeyframes));
NotifyOfPropertyChange(nameof(CanPasteKeyframes));
} }
public void ContextMenuClosing(object sender, ContextMenuEventArgs e) public void ContextMenuClosing(object sender, ContextMenuEventArgs e)
@ -193,12 +197,17 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
_profileEditorService.UpdateSelectedProfileElement(); _profileEditorService.UpdateSelectedProfileElement();
} }
public void DuplicateKeyframes(ITimelineKeyframeViewModel viewModel = null) public void DuplicateKeyframes(object sender)
{ {
TimeSpan pastePosition = GetPastePosition(viewModel); TimeSpan pastePosition = GetPastePosition(sender as ITimelineKeyframeViewModel);
List<ILayerPropertyKeyframe> keyframes = GetAllKeyframeViewModels().Where(k => k.IsSelected).Select(k => k.Keyframe).ToList(); List<ILayerPropertyKeyframe> keyframes = GetAllKeyframeViewModels().Where(k => k.IsSelected).Select(k => k.Keyframe).ToList();
DuplicateKeyframes(keyframes, pastePosition); List<ILayerPropertyKeyframe> newKeyframes = DuplicateKeyframes(keyframes, pastePosition);
// Select only the newly duplicated keyframes
foreach (ITimelineKeyframeViewModel timelineKeyframeViewModel in GetAllKeyframeViewModels())
timelineKeyframeViewModel.IsSelected = newKeyframes.Contains(timelineKeyframeViewModel.Keyframe);
_profileEditorService.UpdateSelectedProfileElement();
} }
public void CopyKeyframes() public void CopyKeyframes()
@ -207,10 +216,15 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
CopyKeyframes(keyframes); CopyKeyframes(keyframes);
} }
public void PasteKeyframes(ITimelineKeyframeViewModel viewModel = null) public void PasteKeyframes(object sender)
{ {
TimeSpan pastePosition = GetPastePosition(viewModel); TimeSpan pastePosition = GetPastePosition(sender as ITimelineKeyframeViewModel);
PasteKeyframes(pastePosition); List<ILayerPropertyKeyframe> newKeyframes = PasteKeyframes(pastePosition);
// Select only the newly pasted keyframes
foreach (ITimelineKeyframeViewModel timelineKeyframeViewModel in GetAllKeyframeViewModels())
timelineKeyframeViewModel.IsSelected = newKeyframes.Contains(timelineKeyframeViewModel.Keyframe);
_profileEditorService.UpdateSelectedProfileElement();
} }
private TimeSpan GetPastePosition(ITimelineKeyframeViewModel viewModel) private TimeSpan GetPastePosition(ITimelineKeyframeViewModel viewModel)
@ -226,26 +240,26 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
return pastePosition; return pastePosition;
} }
public List<ILayerPropertyKeyframe> DuplicateKeyframes(List<ILayerPropertyKeyframe> keyframes, TimeSpan pastePosition) private List<ILayerPropertyKeyframe> DuplicateKeyframes(List<ILayerPropertyKeyframe> keyframes, TimeSpan pastePosition)
{ {
KeyframeClipboardModel clipboardModel = CoreJson.DeserializeObject<KeyframeClipboardModel>(CoreJson.SerializeObject(new KeyframeClipboardModel(keyframes), true), true); KeyframesClipboardModel clipboardModel = CoreJson.DeserializeObject<KeyframesClipboardModel>(CoreJson.SerializeObject(new KeyframesClipboardModel(keyframes), true), true);
return PasteClipboardData(clipboardModel, pastePosition); return PasteClipboardData(clipboardModel, pastePosition);
} }
public void CopyKeyframes(List<ILayerPropertyKeyframe> keyframes) private void CopyKeyframes(List<ILayerPropertyKeyframe> keyframes)
{ {
KeyframeClipboardModel clipboardModel = new KeyframeClipboardModel(keyframes); KeyframesClipboardModel clipboardModel = new KeyframesClipboardModel(keyframes);
JsonClipboard.SetObject(clipboardModel); JsonClipboard.SetObject(clipboardModel);
} }
public List<ILayerPropertyKeyframe> PasteKeyframes(TimeSpan pastePosition) private List<ILayerPropertyKeyframe> PasteKeyframes(TimeSpan pastePosition)
{ {
KeyframeClipboardModel clipboardObject = JsonClipboard.GetData<KeyframeClipboardModel>(); KeyframesClipboardModel clipboardObject = JsonClipboard.GetData<KeyframesClipboardModel>();
return PasteClipboardData(clipboardObject, pastePosition); return PasteClipboardData(clipboardObject, pastePosition);
} }
private List<ILayerPropertyKeyframe> PasteClipboardData(KeyframeClipboardModel clipboardModel, TimeSpan pastePosition) private List<ILayerPropertyKeyframe> PasteClipboardData(KeyframesClipboardModel clipboardModel, TimeSpan pastePosition)
{ {
List<ILayerPropertyKeyframe> pasted = new List<ILayerPropertyKeyframe>(); List<ILayerPropertyKeyframe> pasted = new List<ILayerPropertyKeyframe>();
if (clipboardModel == null) if (clipboardModel == null)
@ -254,9 +268,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
if (target == null) if (target == null)
return pasted; return pasted;
clipboardModel.Paste(target, pastePosition); return clipboardModel.Paste(target, pastePosition);
return pasted;
} }
#endregion #endregion

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows; using System.Windows;
using System.Windows.Input;
using Artemis.Core; using Artemis.Core;
using Artemis.Core.Modules; using Artemis.Core.Modules;
using Artemis.Core.Services; using Artemis.Core.Services;
@ -209,6 +210,8 @@ namespace Artemis.UI.Screens.ProfileEditor
// Expanded status is also undone because undoing works a bit crude, that's annoying // Expanded status is also undone because undoing works a bit crude, that's annoying
List<LayerPropertyGroupViewModel> beforeGroups = LayerPropertiesViewModel.GetAllLayerPropertyGroupViewModels(); List<LayerPropertyGroupViewModel> beforeGroups = LayerPropertiesViewModel.GetAllLayerPropertyGroupViewModels();
List<string> expandedPaths = beforeGroups.Where(g => g.IsExpanded).Select(g => g.LayerPropertyGroup.Path).ToList(); List<string> expandedPaths = beforeGroups.Where(g => g.IsExpanded).Select(g => g.LayerPropertyGroup.Path).ToList();
// Store the focused element so we can restore it later
IInputElement focusedElement = FocusManager.GetFocusedElement(Window.GetWindow(View));
if (!_profileEditorService.UndoUpdateProfile()) if (!_profileEditorService.UndoUpdateProfile())
{ {
@ -219,7 +222,13 @@ namespace Artemis.UI.Screens.ProfileEditor
// Restore the expanded status // Restore the expanded status
foreach (LayerPropertyGroupViewModel allLayerPropertyGroupViewModel in LayerPropertiesViewModel.GetAllLayerPropertyGroupViewModels()) foreach (LayerPropertyGroupViewModel allLayerPropertyGroupViewModel in LayerPropertiesViewModel.GetAllLayerPropertyGroupViewModels())
allLayerPropertyGroupViewModel.IsExpanded = expandedPaths.Contains(allLayerPropertyGroupViewModel.LayerPropertyGroup.Path); allLayerPropertyGroupViewModel.IsExpanded = expandedPaths.Contains(allLayerPropertyGroupViewModel.LayerPropertyGroup.Path);
// Restore the focused element
Execute.PostToUIThread(async () =>
{
await Task.Delay(50);
focusedElement?.Focus();
});
_snackbarMessageQueue.Enqueue("Undid profile update", "REDO", Redo); _snackbarMessageQueue.Enqueue("Undid profile update", "REDO", Redo);
} }
@ -228,6 +237,8 @@ namespace Artemis.UI.Screens.ProfileEditor
// Expanded status is also undone because undoing works a bit crude, that's annoying // Expanded status is also undone because undoing works a bit crude, that's annoying
List<LayerPropertyGroupViewModel> beforeGroups = LayerPropertiesViewModel.GetAllLayerPropertyGroupViewModels(); List<LayerPropertyGroupViewModel> beforeGroups = LayerPropertiesViewModel.GetAllLayerPropertyGroupViewModels();
List<string> expandedPaths = beforeGroups.Where(g => g.IsExpanded).Select(g => g.LayerPropertyGroup.Path).ToList(); List<string> expandedPaths = beforeGroups.Where(g => g.IsExpanded).Select(g => g.LayerPropertyGroup.Path).ToList();
// Store the focused element so we can restore it later
IInputElement focusedElement = FocusManager.GetFocusedElement(Window.GetWindow(View));
if (!_profileEditorService.RedoUpdateProfile()) if (!_profileEditorService.RedoUpdateProfile())
{ {
@ -238,6 +249,12 @@ namespace Artemis.UI.Screens.ProfileEditor
// Restore the expanded status // Restore the expanded status
foreach (LayerPropertyGroupViewModel allLayerPropertyGroupViewModel in LayerPropertiesViewModel.GetAllLayerPropertyGroupViewModels()) foreach (LayerPropertyGroupViewModel allLayerPropertyGroupViewModel in LayerPropertiesViewModel.GetAllLayerPropertyGroupViewModels())
allLayerPropertyGroupViewModel.IsExpanded = expandedPaths.Contains(allLayerPropertyGroupViewModel.LayerPropertyGroup.Path); allLayerPropertyGroupViewModel.IsExpanded = expandedPaths.Contains(allLayerPropertyGroupViewModel.LayerPropertyGroup.Path);
// Restore the focused element
Execute.PostToUIThread(async () =>
{
await Task.Delay(50);
focusedElement?.Focus();
});
_snackbarMessageQueue.Enqueue("Redid profile update", "UNDO", Undo); _snackbarMessageQueue.Enqueue("Redid profile update", "UNDO", Undo);
} }

View File

@ -42,7 +42,7 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree
} }
} }
public bool CanPasteElement => _profileEditorService.GetCanPaste(); public bool CanPasteElement => _profileEditorService.GetCanPasteProfileElement();
protected override void OnInitialActivate() protected override void OnInitialActivate()
{ {

View File

@ -48,7 +48,7 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
set => SetAndNotify(ref _profileElement, value); set => SetAndNotify(ref _profileElement, value);
} }
public bool CanPasteElement => _profileEditorService.GetCanPaste(); public bool CanPasteElement => _profileEditorService.GetCanPasteProfileElement();
public abstract bool SupportsChildren { get; } public abstract bool SupportsChildren { get; }

View File

@ -107,9 +107,9 @@
}, },
"Stylet": { "Stylet": {
"type": "Direct", "type": "Direct",
"requested": "[1.3.4, )", "requested": "[1.3.5, )",
"resolved": "1.3.4", "resolved": "1.3.5",
"contentHash": "bCEdA+AIi+TM9SQQGLYMsFRIfzZcDUDg2Mznyr72kOkcC/cdBj01/jel4/v2aoKwbFcxVjiqmpgnbsFgMEZ4zQ==", "contentHash": "9vjjaTgf5sZAGHnxQWIslD32MG5gXj7ANgS+w965L5Eh//UC3qwZDrEf226Pf+v1P/ldAJDpUySnOyGlb3TSSw==",
"dependencies": { "dependencies": {
"System.Drawing.Common": "4.6.0" "System.Drawing.Common": "4.6.0"
} }
@ -1410,7 +1410,7 @@
"SharpVectors.Reloaded": "1.6.0", "SharpVectors.Reloaded": "1.6.0",
"SkiaSharp": "2.80.2", "SkiaSharp": "2.80.2",
"SkiaSharp.Views.WPF": "2.80.2", "SkiaSharp.Views.WPF": "2.80.2",
"Stylet": "1.3.4", "Stylet": "1.3.5",
"System.Buffers": "4.5.0", "System.Buffers": "4.5.0",
"System.Numerics.Vectors": "4.5.0", "System.Numerics.Vectors": "4.5.0",
"WriteableBitmapEx": "1.6.5" "WriteableBitmapEx": "1.6.5"