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:
parent
0fd30aef2d
commit
dd73c1e4c9
@ -16,7 +16,12 @@ 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>
|
||||||
|
/// The parent group of this layer property, set after construction
|
||||||
|
/// </summary>
|
||||||
|
LayerPropertyGroup LayerPropertyGroup { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the unique path of the property on the layer
|
/// Gets the unique path of the property on the layer
|
||||||
@ -30,13 +35,20 @@ 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
|
||||||
/// </summary>
|
/// </summary>
|
||||||
List<IDataBindingRegistration> GetAllDataBindingRegistrations();
|
List<IDataBindingRegistration> GetAllDataBindingRegistrations();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 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>
|
/// <summary>
|
||||||
/// Updates the layer properties internal state
|
/// Updates the layer properties internal state
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -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">
|
||||||
|
|||||||
@ -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"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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" />
|
||||||
|
|||||||
@ -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,6 +106,7 @@ 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
|
||||||
|
if (FocusManager.GetIsFocusScope(item))
|
||||||
item.Focus();
|
item.Focus();
|
||||||
if (ExpandSelected)
|
if (ExpandSelected)
|
||||||
item.IsExpanded = true;
|
item.IsExpanded = true;
|
||||||
|
|||||||
@ -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}" />
|
||||||
|
|||||||
@ -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");
|
||||||
|
|
||||||
HasBeenPasted = true;
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HasBeenPasted { get; set; }
|
HasBeenPasted = true;
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class KeyframeClipboardModel
|
||||||
|
{
|
||||||
|
// ReSharper disable once UnusedMember.Global - For JSON.NET
|
||||||
|
public KeyframeClipboardModel()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -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>
|
||||||
|
|||||||
@ -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)
|
||||||
@ -227,25 +241,25 @@ 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
|
||||||
|
|||||||
@ -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,6 +222,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("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);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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()
|
||||||
{
|
{
|
||||||
|
|||||||
@ -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; }
|
||||||
|
|
||||||
|
|||||||
@ -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"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user