|
@@ -12,7 +12,9 @@ internal class AnimationDataViewModel : ObservableObject, IAnimationHandler
|
|
|
private int _activeFrameBindable;
|
|
|
public DocumentViewModel Document { get; }
|
|
|
protected DocumentInternalParts Internals { get; }
|
|
|
- public ObservableCollection<IKeyFrameHandler> KeyFrames { get; } = new();
|
|
|
+ public IReadOnlyCollection<IKeyFrameHandler> KeyFrames => keyFrames;
|
|
|
+
|
|
|
+ private KeyFrameCollection keyFrames = new KeyFrameCollection();
|
|
|
|
|
|
public int ActiveFrameBindable
|
|
|
{
|
|
@@ -21,7 +23,7 @@ internal class AnimationDataViewModel : ObservableObject, IAnimationHandler
|
|
|
{
|
|
|
if (Document.UpdateableChangeActive)
|
|
|
return;
|
|
|
-
|
|
|
+
|
|
|
Internals.ActionAccumulator.AddFinishedActions(
|
|
|
new ActiveFrame_Action(value),
|
|
|
new EndActiveFrame_Action());
|
|
@@ -34,10 +36,11 @@ internal class AnimationDataViewModel : ObservableObject, IAnimationHandler
|
|
|
Internals = internals;
|
|
|
}
|
|
|
|
|
|
- public void AddRasterClip(Guid targetLayerGuid, int frame, bool cloneFromExisting)
|
|
|
+ public void CreateRasterKeyFrame(Guid targetLayerGuid, int frame, bool cloneFromExisting)
|
|
|
{
|
|
|
if (!Document.UpdateableChangeActive)
|
|
|
- Internals.ActionAccumulator.AddFinishedActions(new CreateRasterClip_Action(targetLayerGuid, frame, cloneFromExisting));
|
|
|
+ Internals.ActionAccumulator.AddFinishedActions(new CreateRasterClip_Action(targetLayerGuid, frame,
|
|
|
+ cloneFromExisting));
|
|
|
}
|
|
|
|
|
|
public void SetActiveFrame(int newFrame)
|
|
@@ -45,4 +48,64 @@ internal class AnimationDataViewModel : ObservableObject, IAnimationHandler
|
|
|
_activeFrameBindable = newFrame;
|
|
|
OnPropertyChanged(nameof(ActiveFrameBindable));
|
|
|
}
|
|
|
+
|
|
|
+ public void AddKeyFrame(IKeyFrameHandler keyFrame)
|
|
|
+ {
|
|
|
+ Guid id = keyFrame.LayerGuid;
|
|
|
+ if (TryFindKeyFrame(id, out KeyFrameGroupViewModel group))
|
|
|
+ {
|
|
|
+ group.Children.Add((KeyFrameViewModel)keyFrame);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ KeyFrameGroupViewModel createdGroup =
|
|
|
+ new KeyFrameGroupViewModel(keyFrame.StartFrame, keyFrame.Duration, id, id);
|
|
|
+ createdGroup.Children.Add((KeyFrameViewModel)keyFrame);
|
|
|
+ keyFrames.Add(createdGroup);
|
|
|
+ }
|
|
|
+
|
|
|
+ keyFrames.NotifyCollectionChanged();
|
|
|
+ }
|
|
|
+
|
|
|
+ public void RemoveKeyFrame(Guid keyFrameId)
|
|
|
+ {
|
|
|
+ TryFindKeyFrame<KeyFrameViewModel>(keyFrameId, out _, (frame, parent) =>
|
|
|
+ {
|
|
|
+ parent.Children.Remove(frame);
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // TODO: Use the same structure functions as layers
|
|
|
+ public bool TryFindKeyFrame<T>(Guid id, out T foundKeyFrame,
|
|
|
+ Action<KeyFrameViewModel, KeyFrameGroupViewModel?> onFound = null) where T : KeyFrameViewModel
|
|
|
+ {
|
|
|
+ return TryFindKeyFrame(keyFrames, null, id, out foundKeyFrame, onFound);
|
|
|
+ }
|
|
|
+
|
|
|
+ private bool TryFindKeyFrame<T>(IList<KeyFrameViewModel> root, KeyFrameGroupViewModel parent, Guid id, out T result,
|
|
|
+ Action<KeyFrameViewModel, KeyFrameGroupViewModel?> onFound) where T : KeyFrameViewModel
|
|
|
+ {
|
|
|
+ for (var i = 0; i < root.Count; i++)
|
|
|
+ {
|
|
|
+ var frame = root[i];
|
|
|
+ if (frame is T targetFrame && targetFrame.Id.Equals(id))
|
|
|
+ {
|
|
|
+ result = targetFrame;
|
|
|
+ onFound?.Invoke(frame, parent);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (frame is KeyFrameGroupViewModel { Children.Count: > 0 } group)
|
|
|
+ {
|
|
|
+ bool found = TryFindKeyFrame(group.Children, group, id, out result, onFound);
|
|
|
+ if (found)
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ result = null;
|
|
|
+ return false;
|
|
|
+ }
|
|
|
}
|