diff --git a/src/Artemis.Core/Models/Profile/RenderProfileElement.cs b/src/Artemis.Core/Models/Profile/RenderProfileElement.cs
index 20c938211..4c735e94d 100644
--- a/src/Artemis.Core/Models/Profile/RenderProfileElement.cs
+++ b/src/Artemis.Core/Models/Profile/RenderProfileElement.cs
@@ -204,8 +204,7 @@ namespace Artemis.Core
return (TimelinePosition - oldPosition).TotalSeconds;
}
-
-
+
///
/// Overrides the progress of the element
///
diff --git a/src/Artemis.UI.Shared/Services/Interfaces/IProfileEditorService.cs b/src/Artemis.UI.Shared/Services/Interfaces/IProfileEditorService.cs
index b4185660e..ce1f49197 100644
--- a/src/Artemis.UI.Shared/Services/Interfaces/IProfileEditorService.cs
+++ b/src/Artemis.UI.Shared/Services/Interfaces/IProfileEditorService.cs
@@ -84,10 +84,9 @@ namespace Artemis.UI.Shared.Services
/// How close the time must be to snap
/// Enable snapping to timeline segments
/// Enable snapping to the current time of the editor
- /// Enable snapping to visible keyframes
- /// A keyframe to exclude during keyframe snapping
+ /// An optional extra list of times to snap to
///
- TimeSpan SnapToTimeline(TimeSpan time, TimeSpan tolerance, bool snapToSegments, bool snapToCurrentTime, bool snapToKeyframes, BaseLayerPropertyKeyframe excludedKeyframe = null);
+ TimeSpan SnapToTimeline(TimeSpan time, TimeSpan tolerance, bool snapToSegments, bool snapToCurrentTime, List snapTimes = null);
///
/// If a matching registration is found, creates a new supporting
diff --git a/src/Artemis.UI.Shared/Services/ProfileEditorService.cs b/src/Artemis.UI.Shared/Services/ProfileEditorService.cs
index bb651f9bd..23004586a 100644
--- a/src/Artemis.UI.Shared/Services/ProfileEditorService.cs
+++ b/src/Artemis.UI.Shared/Services/ProfileEditorService.cs
@@ -35,7 +35,7 @@ namespace Artemis.UI.Shared.Services
public IReadOnlyList RegisteredPropertyEditors => _registeredPropertyEditors.AsReadOnly();
public Profile SelectedProfile { get; private set; }
public RenderProfileElement SelectedProfileElement { get; private set; }
- public BaseLayerProperty SelectedDataBinding { get; private set; }
+ public ILayerProperty SelectedDataBinding { get; private set; }
public TimeSpan CurrentTime
{
@@ -128,7 +128,7 @@ namespace Artemis.UI.Shared.Services
}
}
- public void ChangeSelectedDataBinding(BaseLayerProperty layerProperty)
+ public void ChangeSelectedDataBinding(ILayerProperty layerProperty)
{
SelectedDataBinding = layerProperty;
OnSelectedDataBindingChanged();
@@ -229,7 +229,7 @@ namespace Artemis.UI.Shared.Services
}
}
- public TimeSpan SnapToTimeline(TimeSpan time, TimeSpan tolerance, bool snapToSegments, bool snapToCurrentTime, bool snapToKeyframes, BaseLayerPropertyKeyframe excludedKeyframe = null)
+ public TimeSpan SnapToTimeline(TimeSpan time, TimeSpan tolerance, bool snapToSegments, bool snapToCurrentTime, List snapTimes = null)
{
if (snapToSegments)
{
@@ -254,17 +254,12 @@ namespace Artemis.UI.Shared.Services
return SelectedProfileElement.StartSegmentLength;
}
- if (snapToKeyframes)
+ if (snapTimes != null)
{
- // Get all visible keyframes
- var keyframes = SelectedProfileElement.GetAllKeyframes()
- .Where(k => k != excludedKeyframe && SelectedProfileElement.IsPropertyGroupExpanded(k.BaseLayerProperty.Parent))
- .ToList();
-
// Find the closest keyframe
- var closeKeyframe = keyframes.FirstOrDefault(k => Math.Abs(time.TotalMilliseconds - k.Position.TotalMilliseconds) < tolerance.TotalMilliseconds);
- if (closeKeyframe != null)
- return closeKeyframe.Position;
+ var closeSnapTime = snapTimes.FirstOrDefault(s => Math.Abs(time.TotalMilliseconds - s.TotalMilliseconds) < tolerance.TotalMilliseconds);
+ if (closeSnapTime != TimeSpan.Zero)
+ return closeSnapTime;
}
return time;
diff --git a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs
index 22467b5ac..dd0743d08 100644
--- a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs
+++ b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs
@@ -16,6 +16,7 @@ using Artemis.UI.Shared;
using Artemis.UI.Shared.Services;
using GongSolutions.Wpf.DragDrop;
using Stylet;
+using static Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree.LayerPropertyGroupTreeViewModel.LayerPropertyGroupType;
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
{
@@ -38,7 +39,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
private TimelineViewModel _timelineViewModel;
private TreeViewModel _treeViewModel;
- public LayerPropertiesViewModel(IProfileEditorService profileEditorService,
+ public LayerPropertiesViewModel(IProfileEditorService profileEditorService,
ICoreService coreService,
ISettingsService settingsService,
ILayerPropertyVmFactory layerPropertyVmFactory,
@@ -397,9 +398,14 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
private void SortProperties()
{
// Get all non-effect properties
- var nonEffectProperties = LayerPropertyGroups.Where(l => l.GroupType != LayerEffectRoot).ToList();
+ var nonEffectProperties = LayerPropertyGroups
+ .Where(l => l.LayerPropertyGroupTreeViewModel.GroupType != LayerEffectRoot)
+ .ToList();
// Order the effects
- var effectProperties = LayerPropertyGroups.Where(l => l.GroupType == LayerEffectRoot).OrderBy(l => l.LayerPropertyGroup.LayerEffect.Order).ToList();
+ var effectProperties = LayerPropertyGroups
+ .Where(l => l.LayerPropertyGroupTreeViewModel.GroupType == LayerEffectRoot)
+ .OrderBy(l => l.LayerPropertyGroup.LayerEffect.Order)
+ .ToList();
// Put the non-effect properties in front
for (var index = 0; index < nonEffectProperties.Count; index++)
@@ -435,7 +441,9 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
var source = dropInfo.Data as LayerPropertyGroupViewModel;
var target = dropInfo.TargetItem as LayerPropertyGroupViewModel;
- if (source == target || target?.GroupType != LayerEffectRoot || source?.GroupType != LayerEffectRoot)
+ if (source == target ||
+ target?.LayerPropertyGroupTreeViewModel.GroupType != LayerEffectRoot ||
+ source?.LayerPropertyGroupTreeViewModel.GroupType != LayerEffectRoot)
return;
dropInfo.DropTargetAdorner = DropTargetAdorners.Insert;
@@ -452,7 +460,9 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
var source = dropInfo.Data as LayerPropertyGroupViewModel;
var target = dropInfo.TargetItem as LayerPropertyGroupViewModel;
- if (source == target || target?.GroupType != LayerEffectRoot || source?.GroupType != LayerEffectRoot)
+ if (source == target ||
+ target?.LayerPropertyGroupTreeViewModel.GroupType != LayerEffectRoot ||
+ source?.LayerPropertyGroupTreeViewModel.GroupType != LayerEffectRoot)
return;
if (dropInfo.InsertPosition == RelativeInsertPosition.BeforeTargetItem)
@@ -481,7 +491,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
private void ApplyCurrentEffectsOrder()
{
var order = 1;
- foreach (var groupViewModel in LayerPropertyGroups.Where(p => p.GroupType == LayerEffectRoot))
+ foreach (var groupViewModel in LayerPropertyGroups.Where(p => p.LayerPropertyGroupTreeViewModel.GroupType == LayerEffectRoot))
{
groupViewModel.UpdateOrder(order);
order++;
@@ -551,16 +561,13 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
private TimeSpan CalculateEndTime()
{
- if (!(ProfileEditorService.SelectedProfileElement is Layer layer))
- return TimeSpan.MaxValue;
-
- var keyframes = GetKeyframes(false);
+ var keyframeTimes = LayerPropertyGroups.SelectMany(g => g.GetAllKeyframePositions(false)).ToList();
// If there are no keyframes, don't stop at all
- if (!keyframes.Any())
+ if (!keyframeTimes.Any())
return TimeSpan.MaxValue;
// If there are keyframes, stop after the last keyframe + 10 sec
- return keyframes.Max(k => k.Position).Add(TimeSpan.FromSeconds(10));
+ return keyframeTimes.Max().Add(TimeSpan.FromSeconds(10));
}
private void CoreServiceOnFrameRendering(object sender, FrameRenderingEventArgs e)
@@ -617,7 +624,8 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
// If holding down shift, snap to the closest segment or keyframe
if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift))
{
- var snappedTime = ProfileEditorService.SnapToTimeline(newTime, TimeSpan.FromMilliseconds(1000f / ProfileEditorService.PixelsPerSecond * 5), true, false, true);
+ var snapTimes = LayerPropertyGroups.SelectMany(g => g.GetAllKeyframePositions(true)).ToList();
+ var snappedTime = ProfileEditorService.SnapToTimeline(newTime, TimeSpan.FromMilliseconds(1000f / ProfileEditorService.PixelsPerSecond * 5), true, false, snapTimes);
ProfileEditorService.CurrentTime = snappedTime;
return;
}
@@ -634,15 +642,6 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
}
}
- private List GetKeyframes(bool visibleOnly)
- {
- var result = new List();
- foreach (var layerPropertyGroupViewModel in LayerPropertyGroups)
- result.AddRange(layerPropertyGroupViewModel.GetKeyframes(visibleOnly));
-
- return result;
- }
-
#endregion
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/LayerPropertyGroupViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/LayerPropertyGroupViewModel.cs
index 3f87b3479..ae3e7091a 100644
--- a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/LayerPropertyGroupViewModel.cs
+++ b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/LayerPropertyGroupViewModel.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using Artemis.Core;
using Artemis.UI.Ninject.Factories;
using Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree;
@@ -69,5 +70,28 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
disposableChild.Dispose();
}
}
+
+ public void UpdateOrder(int order)
+ {
+ LayerPropertyGroup.LayerEffect.Order = order;
+ NotifyOfPropertyChange(nameof(IsExpanded));
+ }
+
+ public List GetAllKeyframePositions(bool expandedOnly)
+ {
+ var result = new List();
+ if (expandedOnly == IsExpanded)
+ return result;
+
+ foreach (var child in Children)
+ {
+ if (child is LayerPropertyViewModel layerPropertyViewModel)
+ result.AddRange(layerPropertyViewModel.LayerPropertyTimelineViewModel.GetAllKeyframePositions());
+ else if (child is LayerPropertyGroupViewModel layerPropertyGroupViewModel)
+ result.AddRange(layerPropertyGroupViewModel.GetAllKeyframePositions(expandedOnly));
+ }
+
+ return result;
+ }
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Timeline/Rails/LayerPropertyTimelineViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Timeline/Rails/LayerPropertyTimelineViewModel.cs
index 370dc0904..36a6e00c8 100644
--- a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Timeline/Rails/LayerPropertyTimelineViewModel.cs
+++ b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Timeline/Rails/LayerPropertyTimelineViewModel.cs
@@ -1,4 +1,6 @@
using System;
+using System.Collections.Generic;
+using System.Linq;
using Artemis.Core;
using Stylet;
@@ -15,6 +17,11 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
LayerPropertyViewModel = layerPropertyViewModel;
}
+ public List GetAllKeyframePositions()
+ {
+ return LayerProperty.Keyframes.Select(k => k.Position).ToList();
+ }
+
public void Dispose()
{
}
@@ -22,5 +29,6 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
public interface ILayerPropertyTimelineViewModel : IScreen, IDisposable
{
+ List GetAllKeyframePositions();
}
}
\ No newline at end of file