diff --git a/src/Artemis.Core/Services/CoreService.cs b/src/Artemis.Core/Services/CoreService.cs
index 80203346f..af70048f2 100644
--- a/src/Artemis.Core/Services/CoreService.cs
+++ b/src/Artemis.Core/Services/CoreService.cs
@@ -99,7 +99,7 @@ namespace Artemis.Core.Services
{
try
{
- if (!ModuleUpdatingDisabled)
+ if (!ModuleUpdatingDisabled && _modules != null)
{
lock (_modules)
{
diff --git a/src/Artemis.UI/Behaviors/TreeViewSelectionBehavior.cs b/src/Artemis.UI/Behaviors/TreeViewSelectionBehavior.cs
index 338f12bcf..2c05e51bd 100644
--- a/src/Artemis.UI/Behaviors/TreeViewSelectionBehavior.cs
+++ b/src/Artemis.UI/Behaviors/TreeViewSelectionBehavior.cs
@@ -97,7 +97,7 @@ namespace Artemis.UI.Behaviors
// Update state of all items starting with given, with optional recursion
private void UpdateTreeViewItem(TreeViewItem item, bool recurse)
{
- if (SelectedItem == null) return;
+// if (SelectedItem == null) return;
var model = item.DataContext;
// If the selected item is this model and is not yet selected - select and return
diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs
index b6f1db1ac..4a1d2ca94 100644
--- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs
+++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs
@@ -44,7 +44,6 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
PopulateProperties(_profileEditorService.SelectedProfileElement, null);
_profileEditorService.SelectedProfileElementChanged += (sender, args) => PopulateProperties(args.ProfileElement, args.PreviousProfileElement);
- _profileEditorService.SelectedProfileChanged += (sender, args) => PopulateProperties(_profileEditorService.SelectedProfileElement, null);
_profileEditorService.CurrentTimeChanged += ProfileEditorServiceOnCurrentTimeChanged;
}
@@ -112,6 +111,11 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
layer.LayerPropertyRegistered += LayerOnPropertyRegistered;
layer.LayerPropertyRemoved += LayerOnPropertyRemoved;
}
+ else
+ {
+ foreach (var layerPropertyViewModel in _layerPropertyViewModels.ToList())
+ RemovePropertyViewModel(layerPropertyViewModel);
+ }
}
private void LayerOnPropertyRegistered(object sender, LayerPropertyEventArgs e)
diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/BrushPropertyInputView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/BrushPropertyInputView.xaml
index 7145487ff..70bb43b15 100644
--- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/BrushPropertyInputView.xaml
+++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/BrushPropertyInputView.xaml
@@ -9,7 +9,7 @@
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
-
+
-
+
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/BrushPropertyInputViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/BrushPropertyInputViewModel.cs
index 9f4a36c8c..ebdb311d4 100644
--- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/BrushPropertyInputViewModel.cs
+++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/BrushPropertyInputViewModel.cs
@@ -59,6 +59,11 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree.P
NotifyOfPropertyChange(() => BrushInputValue);
}
+ public override void ApplyInputDrag(object startValue, double dragDistance)
+ {
+ throw new NotImplementedException();
+ }
+
protected override void OnInitialized()
{
UpdateEnumValues();
diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/EnumPropertyInputView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/EnumPropertyInputView.xaml
index ab41fbd94..489314187 100644
--- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/EnumPropertyInputView.xaml
+++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/EnumPropertyInputView.xaml
@@ -10,7 +10,7 @@
d:DesignHeight="450" d:DesignWidth="800"
d:DataContext="{d:DesignInstance local:EnumPropertyInputViewModel}">
-
+
-
+
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/EnumPropertyInputViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/EnumPropertyInputViewModel.cs
index f1e1d7932..738ef2ce3 100644
--- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/EnumPropertyInputViewModel.cs
+++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/EnumPropertyInputViewModel.cs
@@ -27,6 +27,11 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree.P
NotifyOfPropertyChange(() => EnumInputValue);
}
+ public override void ApplyInputDrag(object startValue, double dragDistance)
+ {
+ throw new NotImplementedException();
+ }
+
protected override void OnInitialized()
{
EnumValues = EnumUtilities.GetAllValuesAndDescriptions(LayerPropertyViewModel.LayerProperty.Type);
diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/FloatPropertyInputView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/FloatPropertyInputView.xaml
index b283cb6e0..aa28bdda5 100644
--- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/FloatPropertyInputView.xaml
+++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/FloatPropertyInputView.xaml
@@ -10,14 +10,41 @@
d:DesignHeight="450" d:DesignWidth="800"
d:DataContext="{d:DesignInstance local:FloatPropertyInputViewModel}">
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ Visibility="{Binding InputFieldEnabled, Converter={StaticResource BoolToVisibilityConverter}, Mode=OneWay}"
+ LostFocus="{s:Action InputLostFocus}"
+ KeyDown="{s:Action InputKeyDown}"
+ IsVisibleChanged="{s:Action InputIsVisibleChanged}" />
+
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/FloatPropertyInputViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/FloatPropertyInputViewModel.cs
index 36fa963fb..f892993a3 100644
--- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/FloatPropertyInputViewModel.cs
+++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/FloatPropertyInputViewModel.cs
@@ -12,6 +12,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree.P
public sealed override List CompatibleTypes { get; } = new List {typeof(float)};
+
public float FloatInputValue
{
get => (float?) InputValue ?? 0f;
@@ -22,5 +23,11 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree.P
{
NotifyOfPropertyChange(() => FloatInputValue);
}
+
+ public override void ApplyInputDrag(object startValue, double dragDistance)
+ {
+ var floatStartValue = (float) startValue;
+ FloatInputValue = (float) (floatStartValue + dragDistance);
+ }
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/IntPropertyInputView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/IntPropertyInputView.xaml
index 72e469a2b..80bc7ecb7 100644
--- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/IntPropertyInputView.xaml
+++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/IntPropertyInputView.xaml
@@ -10,14 +10,13 @@
d:DesignHeight="450" d:DesignWidth="800"
d:DataContext="{d:DesignInstance local:IntPropertyInputViewModel}">
-
+
-
+ Text="{Binding IntInputValue}" />
+
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/IntPropertyInputViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/IntPropertyInputViewModel.cs
index 6f1a890b3..9708a01ed 100644
--- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/IntPropertyInputViewModel.cs
+++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/IntPropertyInputViewModel.cs
@@ -22,5 +22,10 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree.P
{
NotifyOfPropertyChange(() => IntInputValue);
}
+
+ public override void ApplyInputDrag(object startValue, double dragDistance)
+ {
+ throw new NotImplementedException();
+ }
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/PropertyInputViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/PropertyInputViewModel.cs
index d1c0db1d2..ac7f00e2e 100644
--- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/PropertyInputViewModel.cs
+++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/PropertyInputViewModel.cs
@@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Input;
using Artemis.UI.Exceptions;
using Artemis.UI.Services.Interfaces;
using Stylet;
@@ -15,11 +17,11 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree.P
}
protected IProfileEditorService ProfileEditorService { get; set; }
+ public abstract List CompatibleTypes { get; }
public bool Initialized { get; private set; }
-
- public abstract List CompatibleTypes { get; }
public LayerPropertyViewModel LayerPropertyViewModel { get; private set; }
+ public bool InputFieldEnabled { get; set; }
protected object InputValue
{
@@ -46,18 +48,10 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree.P
OnInitialized();
}
- ///
- /// Called by the view, prevents scrolling into view when scrubbing through the timeline
- ///
- ///
- ///
- public void OnRequestBringIntoView(object sender, RequestBringIntoViewEventArgs e)
- {
- e.Handled = true;
- }
-
public abstract void Update();
+ public abstract void ApplyInputDrag(object startValue, double dragDistance);
+
protected virtual void OnInitialized()
{
}
@@ -70,5 +64,70 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree.P
ProfileEditorService.UpdateSelectedProfileElement();
}
+
+ #region Mouse-based mutations
+
+ private Point _mouseDragStartPoint;
+ private object _startValue;
+
+ // ReSharper disable once UnusedMember.Global - Called from view
+ public void InputMouseDown(object sender, MouseButtonEventArgs e)
+ {
+ _startValue = InputValue;
+ ((IInputElement) sender).CaptureMouse();
+ _mouseDragStartPoint = e.GetPosition((IInputElement) sender);
+ }
+
+ // ReSharper disable once UnusedMember.Global - Called from view
+ public void InputMouseUp(object sender, MouseEventArgs e)
+ {
+ var position = e.GetPosition((IInputElement) sender);
+ if (position == _mouseDragStartPoint)
+ InputFieldEnabled = true;
+
+ ((IInputElement) sender).ReleaseMouseCapture();
+ }
+
+ // ReSharper disable once UnusedMember.Global - Called from view
+ public void InputMouseMove(object sender, MouseEventArgs e)
+ {
+ if (e.LeftButton == MouseButtonState.Pressed)
+ {
+ var position = e.GetPosition((IInputElement) sender);
+ ApplyInputDrag(_startValue, position.X - _mouseDragStartPoint.X);
+ }
+ }
+
+ // ReSharper disable once UnusedMember.Global - Called from view
+ public void InputIsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
+ {
+ if (InputFieldEnabled)
+ {
+ ((UIElement) sender).Focus();
+ if (sender is TextBox textBox)
+ textBox.SelectAll();
+ }
+ }
+
+ // ReSharper disable once UnusedMember.Global - Called from view
+ public void InputLostFocus(object sender, RoutedEventArgs e)
+ {
+ InputFieldEnabled = false;
+ }
+
+ // ReSharper disable once UnusedMember.Global - Called from view
+ public void InputKeyDown(object sender, KeyEventArgs e)
+ {
+ if (e.Key == Key.Enter)
+ InputFieldEnabled = false;
+ else if (e.Key == Key.Escape)
+ {
+ if (sender is TextBox textBox)
+ textBox.Text = _startValue.ToString();
+ InputFieldEnabled = false;
+ }
+ }
+
+ #endregion
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/SKColorPropertyInputView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/SKColorPropertyInputView.xaml
index 057e78127..5884fc22f 100644
--- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/SKColorPropertyInputView.xaml
+++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/SKColorPropertyInputView.xaml
@@ -15,11 +15,11 @@
-
+
-
+
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/SKColorPropertyInputViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/SKColorPropertyInputViewModel.cs
index ed5ca0332..b4223241a 100644
--- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/SKColorPropertyInputViewModel.cs
+++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/SKColorPropertyInputViewModel.cs
@@ -23,5 +23,10 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree.P
{
NotifyOfPropertyChange(() => SKColorInputValue);
}
+
+ public override void ApplyInputDrag(object startValue, double dragDistance)
+ {
+ throw new NotImplementedException();
+ }
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/SKPointPropertyInputView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/SKPointPropertyInputView.xaml
index d0958778e..2a10df499 100644
--- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/SKPointPropertyInputView.xaml
+++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/SKPointPropertyInputView.xaml
@@ -10,15 +10,14 @@
d:DesignHeight="25" d:DesignWidth="800"
d:DataContext="{d:DesignInstance local:SKPointPropertyInputViewModel}">
-
+
+ Text="{Binding X}" />
,
-
+ Text="{Binding Y}" />
+
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/SKPointPropertyInputViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/SKPointPropertyInputViewModel.cs
index 31182ef04..0c48e1872 100644
--- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/SKPointPropertyInputViewModel.cs
+++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/SKPointPropertyInputViewModel.cs
@@ -34,5 +34,10 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree.P
NotifyOfPropertyChange(() => X);
NotifyOfPropertyChange(() => Y);
}
+
+ public override void ApplyInputDrag(object startValue, double dragDistance)
+ {
+ throw new NotImplementedException();
+ }
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/SKSizePropertyInputView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/SKSizePropertyInputView.xaml
index 7e3054d4c..127b6219e 100644
--- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/SKSizePropertyInputView.xaml
+++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/SKSizePropertyInputView.xaml
@@ -10,15 +10,14 @@
d:DesignHeight="450" d:DesignWidth="800"
d:DataContext="{d:DesignInstance local:SKSizePropertyInputViewModel}">
-
+
+ Text="{Binding Height}" />
,
-
+ Text="{Binding Width}" />
+
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/SKSizePropertyInputViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/SKSizePropertyInputViewModel.cs
index 8deb5b199..1722da57a 100644
--- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/SKSizePropertyInputViewModel.cs
+++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/SKSizePropertyInputViewModel.cs
@@ -34,5 +34,10 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree.P
NotifyOfPropertyChange(() => Width);
NotifyOfPropertyChange(() => Height);
}
+
+ public override void ApplyInputDrag(object startValue, double dragDistance)
+ {
+ throw new NotImplementedException();
+ }
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/PropertyTimelineView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/PropertyTimelineView.xaml
index 7c92513b7..a3afcc31c 100644
--- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/PropertyTimelineView.xaml
+++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/PropertyTimelineView.xaml
@@ -9,15 +9,47 @@
d:DesignHeight="25"
d:DesignWidth="800"
d:DataContext="{d:DesignInstance local:PropertyTimelineViewModel}">
-
-
-
-
-
-
-
+
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/PropertyTimelineViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/PropertyTimelineViewModel.cs
index 9842485a5..1cd074eeb 100644
--- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/PropertyTimelineViewModel.cs
+++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/PropertyTimelineViewModel.cs
@@ -1,7 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Shapes;
+using Artemis.Core.Models.Surface;
using Artemis.UI.Ninject.Factories;
+using Artemis.UI.Screens.SurfaceEditor;
+using Artemis.UI.Screens.SurfaceEditor.Visualization;
using Artemis.UI.Services.Interfaces;
using Stylet;
@@ -24,12 +32,15 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
_profileEditorService.SelectedProfileElementUpdated += (sender, args) => Update();
LayerPropertiesViewModel.PixelsPerSecondChanged += (sender, args) => UpdateKeyframePositions();
+
+ Execute.PostToUIThread(() => SelectionRectangle = new RectangleGeometry());
}
public LayerPropertiesViewModel LayerPropertiesViewModel { get; }
public double Width { get; set; }
public BindableCollection PropertyTrackViewModels { get; set; }
+ public RectangleGeometry SelectionRectangle { get; set; }
public void UpdateEndTime()
{
@@ -88,6 +99,119 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
UpdateEndTime();
}
+ #region Keyframe selection
+
+ private Point _mouseDragStartPoint;
+
+ // ReSharper disable once UnusedMember.Global - Called from view
+ public void TimelineCanvasMouseDown(object sender, MouseButtonEventArgs e)
+ {
+ ((IInputElement) sender).CaptureMouse();
+
+ SelectionRectangle.Rect = new Rect();
+ _mouseDragStartPoint = e.GetPosition((IInputElement) sender);
+ }
+
+ // ReSharper disable once UnusedMember.Global - Called from view
+ public void TimelineCanvasMouseUp(object sender, MouseEventArgs e)
+ {
+ var position = e.GetPosition((IInputElement)sender);
+ var selectedRect = new Rect(_mouseDragStartPoint, position);
+ SelectionRectangle.Rect = selectedRect;
+
+ // Find all keyframes in the rectangle
+ var selectedKeyframes = new List();
+ var hitTestParams = new GeometryHitTestParameters(SelectionRectangle);
+ var resultCallback = new HitTestResultCallback(result => HitTestResultBehavior.Continue);
+ var filterCallback = new HitTestFilterCallback(element =>
+ {
+ if (element is Ellipse ellipse)
+ selectedKeyframes.Add((PropertyTrackKeyframeViewModel) ellipse.DataContext);
+ return HitTestFilterBehavior.Continue;
+ });
+ VisualTreeHelper.HitTest((Visual) sender, filterCallback, resultCallback, hitTestParams);
+
+ var keyframeViewModels = PropertyTrackViewModels.SelectMany(t => t.KeyframeViewModels.OrderBy(k => k.Keyframe.Position)).ToList();
+ foreach (var keyframeViewModel in keyframeViewModels)
+ keyframeViewModel.IsSelected = selectedKeyframes.Contains(keyframeViewModel);
+
+ ((IInputElement) sender).ReleaseMouseCapture();
+ }
+
+ public void TimelineCanvasMouseMove(object sender, MouseEventArgs e)
+ {
+ if (e.LeftButton == MouseButtonState.Pressed)
+ {
+ var position = e.GetPosition((IInputElement) sender);
+ var selectedRect = new Rect(_mouseDragStartPoint, position);
+ SelectionRectangle.Rect = selectedRect;
+ }
+ }
+
+ 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;
+ }
+ }
+
+ #endregion
+
+ #region Keyframe movement
+
+ 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();
+ }
+
+ #endregion
+
private void CreateViewModels(LayerPropertyViewModel property)
{
PropertyTrackViewModels.Add(_propertyTrackVmFactory.Create(this, property));
diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/PropertyTrackKeyframeViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/PropertyTrackKeyframeViewModel.cs
index 800a34045..5b2f037c5 100644
--- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/PropertyTrackKeyframeViewModel.cs
+++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/PropertyTrackKeyframeViewModel.cs
@@ -46,13 +46,26 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
public void KeyframeMouseDown(object sender, MouseButtonEventArgs e)
{
+ if (e.LeftButton == MouseButtonState.Released)
+ return;
+ 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();
+ e.Handled = true;
}
public void KeyframeMouseUp(object sender, MouseButtonEventArgs e)
{
+ if (e.LeftButton == MouseButtonState.Released)
+ return;
((IInputElement) sender).ReleaseMouseCapture();
_profileEditorService.UpdateSelectedProfileElement();
+ e.Handled = true;
}
public void KeyframeMouseMove(object sender, MouseEventArgs e)
@@ -71,26 +84,18 @@ 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);
}
+ e.Handled = true;
}
#endregion
diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/PropertyTrackView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/PropertyTrackView.xaml
index c86f4cd8e..f50ebdd43 100644
--- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/PropertyTrackView.xaml
+++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/PropertyTrackView.xaml
@@ -29,6 +29,8 @@
+
+
+