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

Added keyframe multiselect and group movement

This commit is contained in:
Robert 2020-02-17 20:28:13 +01:00
parent 4b1b0248f5
commit b7da732920
3 changed files with 96 additions and 16 deletions

View File

@ -94,5 +94,63 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
foreach (var child in property.Children)
CreateViewModels(child);
}
public void SelectKeyframe(PropertyTrackKeyframeViewModel clicked, bool selectBetween, bool toggle)
{
var keyframeViewModels = PropertyTrackViewModels.SelectMany(t => t.KeyframeViewModels.OrderBy(k => k.Keyframe.Position)).ToList();
if (selectBetween)
{
var selectedIndex = keyframeViewModels.FindIndex(k => k.IsSelected);
// If nothing is selected, select only the clicked
if (selectedIndex == -1)
{
clicked.IsSelected = true;
return;
}
foreach (var keyframeViewModel in keyframeViewModels)
keyframeViewModel.IsSelected = false;
var clickedIndex = keyframeViewModels.IndexOf(clicked);
if (clickedIndex < selectedIndex)
{
foreach (var keyframeViewModel in keyframeViewModels.Skip(clickedIndex).Take(selectedIndex - clickedIndex + 1))
keyframeViewModel.IsSelected = true;
}
else
{
foreach (var keyframeViewModel in keyframeViewModels.Skip(selectedIndex).Take(clickedIndex - selectedIndex + 1))
keyframeViewModel.IsSelected = true;
}
}
else if (toggle)
{
// Toggle only the clicked keyframe, leave others alone
clicked.IsSelected = !clicked.IsSelected;
}
else
{
// Only select the clicked keyframe
foreach (var keyframeViewModel in keyframeViewModels)
keyframeViewModel.IsSelected = false;
clicked.IsSelected = true;
}
}
public void MoveSelectedKeyframes(TimeSpan offset)
{
var keyframeViewModels = PropertyTrackViewModels.SelectMany(t => t.KeyframeViewModels.OrderBy(k => k.Keyframe.Position)).ToList();
foreach (var keyframeViewModel in keyframeViewModels.Where(k => k.IsSelected))
{
// TODO: Not ideal as this stacks them all if they get to 0, oh well
if (keyframeViewModel.Keyframe.Position + offset > TimeSpan.Zero)
{
keyframeViewModel.Keyframe.Position += offset;
keyframeViewModel.Update(LayerPropertiesViewModel.PixelsPerSecond);
}
}
_profileEditorService.UpdateProfilePreview();
}
}
}

View File

@ -46,6 +46,13 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
public void KeyframeMouseDown(object sender, MouseButtonEventArgs e)
{
if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift) && !IsSelected)
PropertyTrackViewModel.PropertyTimelineViewModel.SelectKeyframe(this, true, false);
else if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))
PropertyTrackViewModel.PropertyTimelineViewModel.SelectKeyframe(this, false, true);
else if (!IsSelected)
PropertyTrackViewModel.PropertyTimelineViewModel.SelectKeyframe(this, false, false);
((IInputElement) sender).CaptureMouse();
}
@ -71,25 +78,16 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
else
newTime = TimeSpan.FromMilliseconds(Math.Round(newTime.TotalMilliseconds));
if (!Keyboard.IsKeyDown(Key.LeftShift) && !Keyboard.IsKeyDown(Key.RightShift))
{
Keyframe.Position = newTime;
Update(_pixelsPerSecond);
_profileEditorService.UpdateProfilePreview();
return;
}
// If shift is held, snap to the current time
// Take a tolerance of 5 pixels (half a keyframe width)
var tolerance = 1000f / _pixelsPerSecond * 5;
if (Math.Abs(_profileEditorService.CurrentTime.TotalMilliseconds - newTime.TotalMilliseconds) < tolerance)
Keyframe.Position = _profileEditorService.CurrentTime;
else
Keyframe.Position = newTime;
if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift))
{
var tolerance = 1000f / _pixelsPerSecond * 5;
if (Math.Abs(_profileEditorService.CurrentTime.TotalMilliseconds - newTime.TotalMilliseconds) < tolerance)
newTime = _profileEditorService.CurrentTime;
}
Update(_pixelsPerSecond);
_profileEditorService.UpdateProfilePreview();
PropertyTrackViewModel.PropertyTimelineViewModel.MoveSelectedKeyframes(newTime - Keyframe.Position);
}
}

View File

@ -29,6 +29,8 @@
<ItemsControl.ItemTemplate>
<DataTemplate>
<Ellipse Fill="{StaticResource PrimaryHueMidBrush}"
Stroke="White"
StrokeThickness="0"
Width="10"
Height="10"
Margin="-5,6,0,0"
@ -37,6 +39,28 @@
MouseDown="{s:Action KeyframeMouseDown}"
MouseUp="{s:Action KeyframeMouseUp}"
MouseMove="{s:Action KeyframeMouseMove}">
<Ellipse.Style>
<Style TargetType="{x:Type Ellipse}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsSelected}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="StrokeThickness" To="1" Duration="0:0:0.25"></DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="StrokeThickness" To="0" Duration="0:0:0.25"></DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Ellipse.Style>
<Ellipse.ContextMenu>
<ContextMenu>
<MenuItem Header="Copy" Command="{s:Action Copy}">