diff --git a/Source/Editor/GUI/CurveEditor.Base.cs b/Source/Editor/GUI/CurveEditor.Base.cs
index 1cdd72761..d767d8ba9 100644
--- a/Source/Editor/GUI/CurveEditor.Base.cs
+++ b/Source/Editor/GUI/CurveEditor.Base.cs
@@ -276,5 +276,8 @@ namespace FlaxEditor.GUI
///
public abstract void OnKeyframesDelete(IKeyframesEditor editor);
+
+ ///
+ public abstract void OnKeyframesMove(IKeyframesEditor editor, ContainerControl control, Vector2 location, bool start, bool end);
}
}
diff --git a/Source/Editor/GUI/CurveEditor.Contents.cs b/Source/Editor/GUI/CurveEditor.Contents.cs
index c914e6c25..b77ea1a10 100644
--- a/Source/Editor/GUI/CurveEditor.Contents.cs
+++ b/Source/Editor/GUI/CurveEditor.Contents.cs
@@ -59,6 +59,97 @@ namespace FlaxEditor.GUI
_editor.UpdateTangents();
}
+ internal void OnMoveStart(Vector2 location)
+ {
+ // Start moving selected keyframes
+ _isMovingSelection = true;
+ _movedKeyframes = false;
+ var viewRect = _editor._mainPanel.GetClientArea();
+ _movingSelectionStart = PointToKeyframes(location, ref viewRect);
+ if (_movingSelectionOffsets == null || _movingSelectionOffsets.Length != _editor._points.Count)
+ _movingSelectionOffsets = new Vector2[_editor._points.Count];
+ for (int i = 0; i < _movingSelectionOffsets.Length; i++)
+ _movingSelectionOffsets[i] = _editor._points[i].Point - _movingSelectionStart;
+ _editor.OnEditingStart();
+ }
+
+ internal void OnMove(Vector2 location)
+ {
+ var viewRect = _editor._mainPanel.GetClientArea();
+ var locationKeyframes = PointToKeyframes(location, ref viewRect);
+ var accessor = _editor.Accessor;
+ var components = accessor.GetCurveComponents();
+ for (var i = 0; i < _editor._points.Count; i++)
+ {
+ var p = _editor._points[i];
+ if (p.IsSelected)
+ {
+ var k = _editor.GetKeyframe(p.Index);
+ float time = _editor.GetKeyframeTime(k);
+ float value = _editor.GetKeyframeValue(k, p.Component);
+
+ float minTime = p.Index != 0 ? _editor.GetKeyframeTime(_editor.GetKeyframe(p.Index - 1)) + Mathf.Epsilon : float.MinValue;
+ float maxTime = p.Index != _editor.KeyframesCount - 1 ? _editor.GetKeyframeTime(_editor.GetKeyframe(p.Index + 1)) - Mathf.Epsilon : float.MaxValue;
+
+ var offset = _movingSelectionOffsets[i];
+
+ if (!_editor.ShowCollapsed)
+ {
+ // Move on value axis
+ value = locationKeyframes.Y + offset.Y;
+ }
+
+ // Let the first selected point of this keyframe to edit time
+ bool isFirstSelected = false;
+ for (var j = 0; j < components; j++)
+ {
+ var idx = p.Index * components + j;
+ if (idx == i)
+ {
+ isFirstSelected = true;
+ break;
+ }
+ if (_editor._points[idx].IsSelected)
+ break;
+ }
+ if (isFirstSelected)
+ {
+ time = locationKeyframes.X + offset.X;
+
+ if (_editor.FPS.HasValue)
+ {
+ float fps = _editor.FPS.Value;
+ time = Mathf.Floor(time * fps) / fps;
+ }
+ time = Mathf.Clamp(time, minTime, maxTime);
+ }
+
+ // TODO: snapping keyframes to grid when moving
+
+ _editor.SetKeyframeInternal(p.Index, time, value, p.Component);
+ }
+ _editor.UpdateKeyframes();
+ _editor.UpdateTooltips();
+ if (_editor.EnablePanning == UseMode.On)
+ {
+ //_editor._mainPanel.ScrollViewTo(PointToParent(_editor._mainPanel, location));
+ }
+ Cursor = CursorType.SizeAll;
+ _movedKeyframes = true;
+ }
+ }
+
+ internal void OnMoveEnd(Vector2 location)
+ {
+ if (_movedKeyframes)
+ {
+ _editor.OnEdited();
+ _editor.OnEditingEnd();
+ _movedKeyframes = false;
+ }
+ _isMovingSelection = false;
+ }
+
///
public override bool IntersectsContent(ref Vector2 locationParent, out Vector2 location)
{
@@ -83,16 +174,10 @@ namespace FlaxEditor.GUI
// Start moving selection if movement started from the keyframe
if (_leftMouseDown && !_isMovingSelection && GetChildAt(_leftMouseDownPos) is KeyframePoint)
{
- // Start moving selected nodes
- _isMovingSelection = true;
- _movedKeyframes = false;
- var viewRect = _editor._mainPanel.GetClientArea();
- _movingSelectionStart = PointToKeyframes(location, ref viewRect);
- if (_movingSelectionOffsets == null || _movingSelectionOffsets.Length != _editor._points.Count)
- _movingSelectionOffsets = new Vector2[_editor._points.Count];
- for (int i = 0; i < _movingSelectionOffsets.Length; i++)
- _movingSelectionOffsets[i] = _editor._points[i].Point - _movingSelectionStart;
- _editor.OnEditingStart();
+ if (_editor.KeyframesEditorContext != null)
+ _editor.KeyframesEditorContext.OnKeyframesMove(_editor, this, location, true, false);
+ else
+ OnMoveStart(location);
}
// Moving view
@@ -132,68 +217,10 @@ namespace FlaxEditor.GUI
// Moving selection
else if (_isMovingSelection)
{
- var viewRect = _editor._mainPanel.GetClientArea();
- var locationKeyframes = PointToKeyframes(location, ref viewRect);
- var accessor = _editor.Accessor;
- var components = accessor.GetCurveComponents();
- for (var i = 0; i < _editor._points.Count; i++)
- {
- var p = _editor._points[i];
- if (p.IsSelected)
- {
- var k = _editor.GetKeyframe(p.Index);
- float time = _editor.GetKeyframeTime(k);
- float value = _editor.GetKeyframeValue(k, p.Component);
-
- float minTime = p.Index != 0 ? _editor.GetKeyframeTime(_editor.GetKeyframe(p.Index - 1)) + Mathf.Epsilon : float.MinValue;
- float maxTime = p.Index != _editor.KeyframesCount - 1 ? _editor.GetKeyframeTime(_editor.GetKeyframe(p.Index + 1)) - Mathf.Epsilon : float.MaxValue;
-
- var offset = _movingSelectionOffsets[i];
-
- if (!_editor.ShowCollapsed)
- {
- // Move on value axis
- value = locationKeyframes.Y + offset.Y;
- }
-
- // Let the first selected point of this keyframe to edit time
- bool isFirstSelected = false;
- for (var j = 0; j < components; j++)
- {
- var idx = p.Index * components + j;
- if (idx == i)
- {
- isFirstSelected = true;
- break;
- }
- if (_editor._points[idx].IsSelected)
- break;
- }
- if (isFirstSelected)
- {
- time = locationKeyframes.X + offset.X;
-
- if (_editor.FPS.HasValue)
- {
- float fps = _editor.FPS.Value;
- time = Mathf.Floor(time * fps) / fps;
- }
- time = Mathf.Clamp(time, minTime, maxTime);
- }
-
- // TODO: snapping keyframes to grid when moving
-
- _editor.SetKeyframeInternal(p.Index, time, value, p.Component);
- }
- _editor.UpdateKeyframes();
- _editor.UpdateTooltips();
- if (_editor.EnablePanning == UseMode.On)
- {
- //_editor._mainPanel.ScrollViewTo(PointToParent(_editor._mainPanel, location));
- }
- Cursor = CursorType.SizeAll;
- _movedKeyframes = true;
- }
+ if (_editor.KeyframesEditorContext != null)
+ _editor.KeyframesEditorContext.OnKeyframesMove(_editor, this, location, false, false);
+ else
+ OnMove(location);
return;
}
// Moving tangent
@@ -374,11 +401,10 @@ namespace FlaxEditor.GUI
// Moving keyframes
else if (_isMovingSelection)
{
- if (_movedKeyframes)
- {
- _editor.OnEdited();
- _editor.OnEditingEnd();
- }
+ if (_editor.KeyframesEditorContext != null)
+ _editor.KeyframesEditorContext.OnKeyframesMove(_editor, this, location, false, true);
+ else
+ OnMoveEnd(location);
}
_isMovingSelection = false;
@@ -509,5 +535,19 @@ namespace FlaxEditor.GUI
{
RemoveKeyframesInner();
}
+
+ ///
+ public override void OnKeyframesMove(IKeyframesEditor editor, ContainerControl control, Vector2 location, bool start, bool end)
+ {
+ if (_points.Count == 0)
+ return;
+ location = _contents.PointFromParent(control, location);
+ if (start)
+ _contents.OnMoveStart(location);
+ else if (end)
+ _contents.OnMoveEnd(location);
+ else
+ _contents.OnMove(location);
+ }
}
}
diff --git a/Source/Editor/GUI/IKeyframesEditor.cs b/Source/Editor/GUI/IKeyframesEditor.cs
index f23be8dd1..b7e37e9f4 100644
--- a/Source/Editor/GUI/IKeyframesEditor.cs
+++ b/Source/Editor/GUI/IKeyframesEditor.cs
@@ -40,5 +40,15 @@ namespace FlaxEditor.GUI
///
/// The source editor.
void OnKeyframesDelete(IKeyframesEditor editor);
+
+ ///
+ /// Called when keyframes selection should be moved.
+ ///
+ /// The source editor.
+ /// The source movement control.
+ /// The source movement location (in source control local space).
+ /// The movement start flag.
+ /// The movement end flag.
+ void OnKeyframesMove(IKeyframesEditor editor, ContainerControl control, Vector2 location, bool start, bool end);
}
}
diff --git a/Source/Editor/GUI/IKeyframesEditorContext.cs b/Source/Editor/GUI/IKeyframesEditorContext.cs
index ed4ee3676..d66a03b19 100644
--- a/Source/Editor/GUI/IKeyframesEditorContext.cs
+++ b/Source/Editor/GUI/IKeyframesEditorContext.cs
@@ -35,5 +35,15 @@ namespace FlaxEditor.GUI
///
/// The source editor.
void OnKeyframesDelete(IKeyframesEditor editor);
+
+ ///
+ /// Called when keyframes selection should be moved.
+ ///
+ /// The source editor.
+ /// The source movement control.
+ /// The source movement location (in source control local space).
+ /// The movement start flag.
+ /// The movement end flag.
+ void OnKeyframesMove(IKeyframesEditor editor, ContainerControl control, Vector2 location, bool start, bool end);
}
}
diff --git a/Source/Editor/GUI/Timeline/GUI/KeyframesEditor.cs b/Source/Editor/GUI/Timeline/GUI/KeyframesEditor.cs
index df0358645..e7e906aab 100644
--- a/Source/Editor/GUI/Timeline/GUI/KeyframesEditor.cs
+++ b/Source/Editor/GUI/Timeline/GUI/KeyframesEditor.cs
@@ -109,6 +109,69 @@ namespace FlaxEditor.GUI
}
}
+ internal void OnMoveStart(Vector2 location)
+ {
+ // Start moving selected nodes
+ _isMovingSelection = true;
+ _movedKeyframes = false;
+ var viewRect = _editor._mainPanel.GetClientArea();
+ _movingSelectionStart = PointToKeyframes(location, ref viewRect).X;
+ if (_movingSelectionOffsets == null || _movingSelectionOffsets.Length != _editor._keyframes.Count)
+ _movingSelectionOffsets = new float[_editor._keyframes.Count];
+ for (int i = 0; i < _movingSelectionOffsets.Length; i++)
+ _movingSelectionOffsets[i] = _editor._keyframes[i].Time - _movingSelectionStart;
+ _editor.OnEditingStart();
+ }
+
+ internal void OnMove(Vector2 location)
+ {
+ var viewRect = _editor._mainPanel.GetClientArea();
+ var locationKeyframes = PointToKeyframes(location, ref viewRect);
+ for (var i = 0; i < _editor._points.Count; i++)
+ {
+ var p = _editor._points[i];
+ if (p.IsSelected)
+ {
+ var k = _editor._keyframes[p.Index];
+
+ float minTime = p.Index != 0 ? _editor._keyframes[p.Index - 1].Time : float.MinValue;
+ float maxTime = p.Index != _editor._keyframes.Count - 1 ? _editor._keyframes[p.Index + 1].Time : float.MaxValue;
+
+ var offset = _movingSelectionOffsets[p.Index];
+ k.Time = locationKeyframes.X + offset;
+ if (_editor.FPS.HasValue)
+ {
+ float fps = _editor.FPS.Value;
+ k.Time = Mathf.Floor(k.Time * fps) / fps;
+ }
+ k.Time = Mathf.Clamp(k.Time, minTime, maxTime);
+
+ // TODO: snapping keyframes to grid when moving
+
+ _editor._keyframes[p.Index] = k;
+ }
+ _editor.UpdateKeyframes();
+ if (_editor.EnablePanning)
+ {
+ //_editor._mainPanel.ScrollViewTo(PointToParent(_editor._mainPanel, location));
+ }
+ Cursor = CursorType.SizeAll;
+ _movedKeyframes = true;
+ }
+ }
+
+ internal void OnMoveEnd(Vector2 location)
+ {
+ if (_movedKeyframes)
+ {
+ _editor.OnEdited();
+ _editor.OnEditingEnd();
+ _editor.UpdateKeyframes();
+ _movedKeyframes = false;
+ }
+ _isMovingSelection = false;
+ }
+
///
public override bool IntersectsContent(ref Vector2 locationParent, out Vector2 location)
{
@@ -133,16 +196,10 @@ namespace FlaxEditor.GUI
// Start moving selection if movement started from the keyframe
if (_leftMouseDown && !_isMovingSelection && GetChildAt(_leftMouseDownPos) is KeyframePoint)
{
- // Start moving selected nodes
- _isMovingSelection = true;
- _movedKeyframes = false;
- var viewRect = _editor._mainPanel.GetClientArea();
- _movingSelectionStart = PointToKeyframes(location, ref viewRect).X;
- if (_movingSelectionOffsets == null || _movingSelectionOffsets.Length != _editor._keyframes.Count)
- _movingSelectionOffsets = new float[_editor._keyframes.Count];
- for (int i = 0; i < _movingSelectionOffsets.Length; i++)
- _movingSelectionOffsets[i] = _editor._keyframes[i].Time - _movingSelectionStart;
- _editor.OnEditingStart();
+ if (_editor.KeyframesEditorContext != null)
+ _editor.KeyframesEditorContext.OnKeyframesMove(_editor, this, location, true, false);
+ else
+ OnMoveStart(location);
}
// Moving view
@@ -170,40 +227,10 @@ namespace FlaxEditor.GUI
// Moving selection
else if (_isMovingSelection)
{
- var viewRect = _editor._mainPanel.GetClientArea();
- var locationKeyframes = PointToKeyframes(location, ref viewRect);
- for (var i = 0; i < _editor._points.Count; i++)
- {
- var p = _editor._points[i];
- if (p.IsSelected)
- {
- var k = _editor._keyframes[p.Index];
-
- float minTime = p.Index != 0 ? _editor._keyframes[p.Index - 1].Time : float.MinValue;
- float maxTime = p.Index != _editor._keyframes.Count - 1 ? _editor._keyframes[p.Index + 1].Time : float.MaxValue;
-
- var offset = _movingSelectionOffsets[p.Index];
- k.Time = locationKeyframes.X + offset;
- if (_editor.FPS.HasValue)
- {
- float fps = _editor.FPS.Value;
- k.Time = Mathf.Floor(k.Time * fps) / fps;
- }
- k.Time = Mathf.Clamp(k.Time, minTime, maxTime);
-
- // TODO: snapping keyframes to grid when moving
-
- _editor._keyframes[p.Index] = k;
- }
- _editor.UpdateKeyframes();
- if (_editor.EnablePanning)
- {
- //_editor._mainPanel.ScrollViewTo(PointToParent(_editor._mainPanel, location));
- }
- Cursor = CursorType.SizeAll;
- _movedKeyframes = true;
- }
-
+ if (_editor.KeyframesEditorContext != null)
+ _editor.KeyframesEditorContext.OnKeyframesMove(_editor, this, location, false, false);
+ else
+ OnMove(location);
return;
}
// Selecting
@@ -329,12 +356,10 @@ namespace FlaxEditor.GUI
// Moving keyframes
if (_isMovingSelection)
{
- if (_movedKeyframes)
- {
- _editor.OnEdited();
- _editor.OnEditingEnd();
- _editor.UpdateKeyframes();
- }
+ if (_editor.KeyframesEditorContext != null)
+ _editor.KeyframesEditorContext.OnKeyframesMove(_editor, this, location, false, true);
+ else
+ OnMoveEnd(location);
}
_isMovingSelection = false;
@@ -1227,5 +1252,17 @@ namespace FlaxEditor.GUI
{
RemoveKeyframesInner();
}
+
+ ///
+ public void OnKeyframesMove(IKeyframesEditor editor, ContainerControl control, Vector2 location, bool start, bool end)
+ {
+ location = _contents.PointFromParent(control, location);
+ if (start)
+ _contents.OnMoveStart(location);
+ else if (end)
+ _contents.OnMoveEnd(location);
+ else
+ _contents.OnMove(location);
+ }
}
}
diff --git a/Source/Editor/GUI/Timeline/Timeline.cs b/Source/Editor/GUI/Timeline/Timeline.cs
index 20386de5d..931d2ce7a 100644
--- a/Source/Editor/GUI/Timeline/Timeline.cs
+++ b/Source/Editor/GUI/Timeline/Timeline.cs
@@ -2458,5 +2458,16 @@ namespace FlaxEditor.GUI.Timeline
trackContext.OnKeyframesDelete(editor);
}
}
+
+ ///
+ public void OnKeyframesMove(IKeyframesEditor editor, ContainerControl control, Vector2 location, bool start, bool end)
+ {
+ location = control.PointToParent(_backgroundArea, location);
+ for (int i = 0; i < _tracks.Count; i++)
+ {
+ if (_tracks[i] is IKeyframesEditorContext trackContext)
+ trackContext.OnKeyframesMove(editor, _backgroundArea, location, start, end);
+ }
+ }
}
}
diff --git a/Source/Editor/GUI/Timeline/Tracks/AudioTrack.cs b/Source/Editor/GUI/Timeline/Tracks/AudioTrack.cs
index 72f4cd7f3..2aed48ee0 100644
--- a/Source/Editor/GUI/Timeline/Tracks/AudioTrack.cs
+++ b/Source/Editor/GUI/Timeline/Tracks/AudioTrack.cs
@@ -670,5 +670,12 @@ namespace FlaxEditor.GUI.Timeline.Tracks
if (Curve != null && Curve.Visible)
Curve.OnKeyframesDelete(editor);
}
+
+ ///
+ public void OnKeyframesMove(IKeyframesEditor editor, ContainerControl control, Vector2 location, bool start, bool end)
+ {
+ if (Curve != null && Curve.Visible)
+ Curve.OnKeyframesMove(editor, control, location, start, end);
+ }
}
}
diff --git a/Source/Editor/GUI/Timeline/Tracks/CurvePropertyTrack.cs b/Source/Editor/GUI/Timeline/Tracks/CurvePropertyTrack.cs
index e6fc59355..7c7c9d9af 100644
--- a/Source/Editor/GUI/Timeline/Tracks/CurvePropertyTrack.cs
+++ b/Source/Editor/GUI/Timeline/Tracks/CurvePropertyTrack.cs
@@ -457,6 +457,13 @@ namespace FlaxEditor.GUI.Timeline.Tracks
if (Curve != null && Curve.Visible)
Curve.OnKeyframesDelete(editor);
}
+
+ ///
+ public void OnKeyframesMove(IKeyframesEditor editor, ContainerControl control, Vector2 location, bool start, bool end)
+ {
+ if (Curve != null && Curve.Visible)
+ Curve.OnKeyframesMove(editor, control, location, start, end);
+ }
}
///
diff --git a/Source/Editor/GUI/Timeline/Tracks/EventTrack.cs b/Source/Editor/GUI/Timeline/Tracks/EventTrack.cs
index fe2b52c9e..3e9e0fefb 100644
--- a/Source/Editor/GUI/Timeline/Tracks/EventTrack.cs
+++ b/Source/Editor/GUI/Timeline/Tracks/EventTrack.cs
@@ -438,5 +438,12 @@ namespace FlaxEditor.GUI.Timeline.Tracks
if (Events != null && Events.Visible)
Events.OnKeyframesDelete(editor);
}
+
+ ///
+ public void OnKeyframesMove(IKeyframesEditor editor, ContainerControl control, Vector2 location, bool start, bool end)
+ {
+ if (Events != null && Events.Visible)
+ Events.OnKeyframesMove(editor, control, location, start, end);
+ }
}
}
diff --git a/Source/Editor/GUI/Timeline/Tracks/KeyframesPropertyTrack.cs b/Source/Editor/GUI/Timeline/Tracks/KeyframesPropertyTrack.cs
index 930e310a7..c78f96fea 100644
--- a/Source/Editor/GUI/Timeline/Tracks/KeyframesPropertyTrack.cs
+++ b/Source/Editor/GUI/Timeline/Tracks/KeyframesPropertyTrack.cs
@@ -418,5 +418,12 @@ namespace FlaxEditor.GUI.Timeline.Tracks
if (Keyframes != null && Keyframes.Visible)
Keyframes.OnKeyframesDelete(editor);
}
+
+ ///
+ public void OnKeyframesMove(IKeyframesEditor editor, ContainerControl control, Vector2 location, bool start, bool end)
+ {
+ if (Keyframes != null && Keyframes.Visible)
+ Keyframes.OnKeyframesMove(editor, control, location, start, end);
+ }
}
}