diff --git a/Source/Editor/GUI/CurveEditor.Base.cs b/Source/Editor/GUI/CurveEditor.Base.cs
index 7891eacb1..1cdd72761 100644
--- a/Source/Editor/GUI/CurveEditor.Base.cs
+++ b/Source/Editor/GUI/CurveEditor.Base.cs
@@ -10,7 +10,7 @@ namespace FlaxEditor.GUI
/// The base class for editors. Allows to use generic curve editor without type information at compile-time.
///
[HideInEditor]
- public abstract class CurveEditorBase : ContainerControl
+ public abstract class CurveEditorBase : ContainerControl, IKeyframesEditor
{
///
/// The UI use mode flags.
@@ -124,6 +124,11 @@ namespace FlaxEditor.GUI
///
public abstract int KeyframesCount { get; }
+ ///
+ /// Clears the selection.
+ ///
+ public abstract void ClearSelection();
+
///
/// Called when curve gets edited.
///
@@ -256,5 +261,20 @@ namespace FlaxEditor.GUI
(mode & UseMode.Vertical) == UseMode.Vertical ? value.Y : defaultValue.Y
);
}
+
+ ///
+ public IKeyframesEditorContext KeyframesEditorContext { get; set; }
+
+ ///
+ public abstract void OnKeyframesDeselect(IKeyframesEditor editor);
+
+ ///
+ public abstract void OnKeyframesSelection(IKeyframesEditor editor, ContainerControl control, Rectangle selection);
+
+ ///
+ public abstract int OnKeyframesSelectionCount();
+
+ ///
+ public abstract void OnKeyframesDelete(IKeyframesEditor editor);
}
}
diff --git a/Source/Editor/GUI/CurveEditor.Contents.cs b/Source/Editor/GUI/CurveEditor.Contents.cs
index 96b796f9f..c914e6c25 100644
--- a/Source/Editor/GUI/CurveEditor.Contents.cs
+++ b/Source/Editor/GUI/CurveEditor.Contents.cs
@@ -40,7 +40,14 @@ namespace FlaxEditor.GUI
private void UpdateSelectionRectangle()
{
var selectionRect = Rectangle.FromPoints(_leftMouseDownPos, _mousePos);
+ if (_editor.KeyframesEditorContext != null)
+ _editor.KeyframesEditorContext.OnKeyframesSelection(_editor, this, selectionRect);
+ else
+ UpdateSelection(ref selectionRect);
+ }
+ internal void UpdateSelection(ref Rectangle selectionRect)
+ {
// Find controls to select
for (int i = 0; i < Children.Count; i++)
{
@@ -49,7 +56,6 @@ namespace FlaxEditor.GUI
p.IsSelected = p.Bounds.Intersects(ref selectionRect);
}
}
-
_editor.UpdateTangents();
}
@@ -74,6 +80,21 @@ namespace FlaxEditor.GUI
{
_mousePos = location;
+ // 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();
+ }
+
// Moving view
if (_rightMouseDown)
{
@@ -256,30 +277,32 @@ namespace FlaxEditor.GUI
// Check if user is pressing control
if (Root.GetKey(KeyboardKeys.Control))
{
- // Add to selection
- keyframe.IsSelected = true;
+ // Toggle selection
+ keyframe.IsSelected = !keyframe.IsSelected;
_editor.UpdateTangents();
}
// Check if node isn't selected
else if (!keyframe.IsSelected)
{
// Select node
- _editor.ClearSelection();
+ if (_editor.KeyframesEditorContext != null)
+ _editor.KeyframesEditorContext.OnKeyframesDeselect(_editor);
+ else
+ _editor.ClearSelection();
keyframe.IsSelected = true;
_editor.UpdateTangents();
}
-
- // Start moving selected nodes
+ if (_editor.ShowCollapsed)
+ {
+ // Synchronize selection for curve points when collapsed so all points fo the keyframe are selected
+ for (var i = 0; i < _editor._points.Count; i++)
+ {
+ var p = _editor._points[i];
+ if (p.Index == keyframe.Index)
+ p.IsSelected = keyframe.IsSelected;
+ }
+ }
StartMouseCapture();
- _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();
Focus();
Tooltip?.Hide();
return true;
@@ -306,7 +329,10 @@ namespace FlaxEditor.GUI
{
// Start selecting
StartMouseCapture();
- _editor.ClearSelection();
+ if (_editor.KeyframesEditorContext != null)
+ _editor.KeyframesEditorContext.OnKeyframesDeselect(_editor);
+ else
+ _editor.ClearSelection();
_editor.UpdateTangents();
Focus();
return true;
@@ -354,11 +380,6 @@ namespace FlaxEditor.GUI
_editor.OnEditingEnd();
}
}
- // Selecting
- else
- {
- UpdateSelectionRectangle();
- }
_isMovingSelection = false;
_isMovingTangent = false;
@@ -388,18 +409,15 @@ namespace FlaxEditor.GUI
var cm = new ContextMenu.ContextMenu();
cm.AddButton("Add keyframe", () => _editor.AddKeyframe(_cmShowPos)).Enabled = _editor.KeyframesCount < _editor.MaxKeyframes;
- if (selectionCount == 0)
+ if (selectionCount > 0)
{
+ cm.AddButton(selectionCount == 1 ? "Edit keyframe" : "Edit keyframes", () => _editor.EditKeyframes(this, location));
}
- else if (selectionCount == 1)
+ var totalSelectionCount = _editor.KeyframesEditorContext?.OnKeyframesSelectionCount() ?? selectionCount;
+ Debug.Log(totalSelectionCount);
+ if (totalSelectionCount > 0)
{
- cm.AddButton("Edit keyframe", () => _editor.EditKeyframes(this, location));
- cm.AddButton("Remove keyframe", _editor.RemoveKeyframes);
- }
- else
- {
- cm.AddButton("Edit keyframes", () => _editor.EditKeyframes(this, location));
- cm.AddButton("Remove keyframes", _editor.RemoveKeyframes);
+ cm.AddButton(totalSelectionCount == 1 ? "Remove keyframe" : "Remove keyframes", _editor.RemoveKeyframes);
}
cm.AddButton("Edit all keyframes", () => _editor.EditAllKeyframes(this, location));
if (_editor.EnableZoom != UseMode.Off || _editor.EnablePanning != UseMode.Off)
@@ -464,5 +482,32 @@ namespace FlaxEditor.GUI
);
}
}
+
+ ///
+ public override void OnKeyframesDeselect(IKeyframesEditor editor)
+ {
+ ClearSelection();
+ }
+
+ ///
+ public override void OnKeyframesSelection(IKeyframesEditor editor, ContainerControl control, Rectangle selection)
+ {
+ if (_points.Count == 0)
+ return;
+ var selectionRect = Rectangle.FromPoints(_contents.PointFromParent(control, selection.UpperLeft), _contents.PointFromParent(control, selection.BottomRight));
+ _contents.UpdateSelection(ref selectionRect);
+ }
+
+ ///
+ public override int OnKeyframesSelectionCount()
+ {
+ return SelectionCount;
+ }
+
+ ///
+ public override void OnKeyframesDelete(IKeyframesEditor editor)
+ {
+ RemoveKeyframesInner();
+ }
}
}
diff --git a/Source/Editor/GUI/CurveEditor.cs b/Source/Editor/GUI/CurveEditor.cs
index b1b0a5a52..edbff94b5 100644
--- a/Source/Editor/GUI/CurveEditor.cs
+++ b/Source/Editor/GUI/CurveEditor.cs
@@ -394,7 +394,24 @@ namespace FlaxEditor.GUI
UpdateKeyframes();
UpdateTangents();
if (value)
+ {
+ // Synchronize selection for curve points when collapsed so all points fo the keyframe are selected
+ for (var i = 0; i < _points.Count; i++)
+ {
+ var p = _points[i];
+ if (p.IsSelected)
+ {
+ for (var j = 0; j < _points.Count; j++)
+ {
+ var q = _points[j];
+ if (q.Index == p.Index)
+ q.IsSelected = true;
+ }
+ }
+ }
+
ShowWholeCurve();
+ }
}
}
@@ -590,6 +607,16 @@ namespace FlaxEditor.GUI
private void RemoveKeyframes()
{
+ if (KeyframesEditorContext != null)
+ KeyframesEditorContext.OnKeyframesDelete(this);
+ else
+ RemoveKeyframesInner();
+ }
+
+ private void RemoveKeyframesInner()
+ {
+ if (SelectionCount == 0)
+ return;
var indicesToRemove = new HashSet();
for (int i = 0; i < _points.Count; i++)
{
@@ -600,8 +627,6 @@ namespace FlaxEditor.GUI
indicesToRemove.Add(p.Index);
}
}
- if (indicesToRemove.Count == 0)
- return;
OnEditingStart();
RemoveKeyframesInternal(indicesToRemove);
@@ -630,14 +655,24 @@ namespace FlaxEditor.GUI
get
{
int result = 0;
- for (int i = 0; i < _points.Count; i++)
- if (_points[i].IsSelected)
- result++;
+ if (ShowCollapsed)
+ {
+ for (int i = 0; i < _points.Count; i++)
+ if (_points[i].Component == 0 && _points[i].IsSelected)
+ result++;
+ }
+ else
+ {
+ for (int i = 0; i < _points.Count; i++)
+ if (_points[i].IsSelected)
+ result++;
+ }
return result;
}
}
- private void ClearSelection()
+ ///
+ public override void ClearSelection()
{
for (int i = 0; i < _points.Count; i++)
{
@@ -645,7 +680,10 @@ namespace FlaxEditor.GUI
}
}
- private void SelectAll()
+ ///
+ /// Selects all keyframes.
+ ///
+ public void SelectAll()
{
for (int i = 0; i < _points.Count; i++)
{
@@ -888,6 +926,7 @@ namespace FlaxEditor.GUI
TickSteps = null;
_tickStrengths = null;
KeyframesChanged = null;
+ KeyframesEditorContext = null;
base.OnDestroy();
}
diff --git a/Source/Editor/GUI/IKeyframesEditor.cs b/Source/Editor/GUI/IKeyframesEditor.cs
new file mode 100644
index 000000000..f23be8dd1
--- /dev/null
+++ b/Source/Editor/GUI/IKeyframesEditor.cs
@@ -0,0 +1,44 @@
+// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
+
+using FlaxEngine;
+using FlaxEngine.GUI;
+
+namespace FlaxEditor.GUI
+{
+ ///
+ /// Interface for keyframes/curves editors.
+ ///
+ public interface IKeyframesEditor
+ {
+ ///
+ /// Gets or sets the keyframes editor collection used by this editor.
+ ///
+ IKeyframesEditorContext KeyframesEditorContext { get; set; }
+
+ ///
+ /// Called when keyframes selection should be cleared for editor.
+ ///
+ /// The source editor.
+ void OnKeyframesDeselect(IKeyframesEditor editor);
+
+ ///
+ /// Called when keyframes selection rectangle gets updated.
+ ///
+ /// The source editor.
+ /// The source selection control.
+ /// The source selection rectangle (in source control local space).
+ void OnKeyframesSelection(IKeyframesEditor editor, ContainerControl control, Rectangle selection);
+
+ ///
+ /// Called to calculate the total amount of selected keyframes in the editor.
+ ///
+ /// The selected keyframes amount.
+ int OnKeyframesSelectionCount();
+
+ ///
+ /// Called when keyframes selection should be deleted for all editors.
+ ///
+ /// The source editor.
+ void OnKeyframesDelete(IKeyframesEditor editor);
+ }
+}
diff --git a/Source/Editor/GUI/IKeyframesEditorContext.cs b/Source/Editor/GUI/IKeyframesEditorContext.cs
new file mode 100644
index 000000000..ed4ee3676
--- /dev/null
+++ b/Source/Editor/GUI/IKeyframesEditorContext.cs
@@ -0,0 +1,39 @@
+// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
+
+using FlaxEngine;
+using FlaxEngine.GUI;
+
+namespace FlaxEditor.GUI
+{
+ ///
+ /// Interface for context for collection of .
+ ///
+ public interface IKeyframesEditorContext
+ {
+ ///
+ /// Called when keyframes selection should be cleared for all editors.
+ ///
+ /// The source editor.
+ void OnKeyframesDeselect(IKeyframesEditor editor);
+
+ ///
+ /// Called when keyframes selection rectangle gets updated.
+ ///
+ /// The source editor.
+ /// The source selection control.
+ /// The source selection rectangle (in source control local space).
+ void OnKeyframesSelection(IKeyframesEditor editor, ContainerControl control, Rectangle selection);
+
+ ///
+ /// Called to calculate the total amount of selected keyframes in the editor.
+ ///
+ /// The selected keyframes amount.
+ int OnKeyframesSelectionCount();
+
+ ///
+ /// Called when keyframes selection should be deleted for all editors.
+ ///
+ /// The source editor.
+ void OnKeyframesDelete(IKeyframesEditor editor);
+ }
+}
diff --git a/Source/Editor/GUI/Timeline/GUI/KeyframesEditor.cs b/Source/Editor/GUI/Timeline/GUI/KeyframesEditor.cs
index 6942b0fc0..ecec528ad 100644
--- a/Source/Editor/GUI/Timeline/GUI/KeyframesEditor.cs
+++ b/Source/Editor/GUI/Timeline/GUI/KeyframesEditor.cs
@@ -15,7 +15,7 @@ namespace FlaxEditor.GUI
///
///
[HideInEditor]
- public class KeyframesEditor : ContainerControl
+ public class KeyframesEditor : ContainerControl, IKeyframesEditor
{
///
/// A single keyframe.
@@ -91,7 +91,14 @@ namespace FlaxEditor.GUI
private void UpdateSelectionRectangle()
{
var selectionRect = Rectangle.FromPoints(_leftMouseDownPos, _mousePos);
+ if (_editor.KeyframesEditorContext != null)
+ _editor.KeyframesEditorContext.OnKeyframesSelection(_editor, this, selectionRect);
+ else
+ UpdateSelection(ref selectionRect);
+ }
+ internal void UpdateSelection(ref Rectangle selectionRect)
+ {
// Find controls to select
for (int i = 0; i < Children.Count; i++)
{
@@ -123,6 +130,21 @@ namespace FlaxEditor.GUI
{
_mousePos = location;
+ // 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();
+ }
+
// Moving view
if (_rightMouseDown)
{
@@ -248,28 +270,20 @@ namespace FlaxEditor.GUI
// Check if user is pressing control
if (Root.GetKey(KeyboardKeys.Control))
{
- // Add to selection
- keyframe.Select();
+ // Toggle selection
+ keyframe.IsSelected = !keyframe.IsSelected;
}
// Check if node isn't selected
else if (!keyframe.IsSelected)
{
// Select node
- _editor.ClearSelection();
- keyframe.Select();
+ if (_editor.KeyframesEditorContext != null)
+ _editor.KeyframesEditorContext.OnKeyframesDeselect(_editor);
+ else
+ _editor.ClearSelection();
+ keyframe.IsSelected = true;
}
-
- // Start moving selected nodes
StartMouseCapture();
- _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();
Focus();
Tooltip?.Hide();
return true;
@@ -281,7 +295,10 @@ namespace FlaxEditor.GUI
{
// Start selecting
StartMouseCapture();
- _editor.ClearSelection();
+ if (_editor.KeyframesEditorContext != null)
+ _editor.KeyframesEditorContext.OnKeyframesDeselect(_editor);
+ else
+ _editor.ClearSelection();
Focus();
return true;
}
@@ -319,11 +336,6 @@ namespace FlaxEditor.GUI
_editor.UpdateKeyframes();
}
}
- // Selecting
- else
- {
- UpdateSelectionRectangle();
- }
_isMovingSelection = false;
_movedKeyframes = false;
@@ -343,7 +355,7 @@ namespace FlaxEditor.GUI
{
// Select node
selectionCount = 1;
- point.Select();
+ point.IsSelected = true;
}
var viewRect = _editor._mainPanel.GetClientArea();
@@ -351,18 +363,15 @@ namespace FlaxEditor.GUI
var cm = new ContextMenu.ContextMenu();
cm.AddButton("Add keyframe", () => _editor.AddKeyframe(_cmShowPos)).Enabled = _editor.Keyframes.Count < _editor.MaxKeyframes;
- if (selectionCount == 0)
+ if (selectionCount > 0)
{
+ cm.AddButton(selectionCount == 1 ? "Edit keyframe" : "Edit keyframes", () => _editor.EditKeyframes(this, location));
}
- else if (selectionCount == 1)
+ var totalSelectionCount = _editor.KeyframesEditorContext?.OnKeyframesSelectionCount() ?? selectionCount;
+ Debug.Log(totalSelectionCount);
+ if (totalSelectionCount > 0)
{
- cm.AddButton("Edit keyframe", () => _editor.EditKeyframes(this, location));
- cm.AddButton("Remove keyframe", _editor.RemoveKeyframes);
- }
- else
- {
- cm.AddButton("Edit keyframes", () => _editor.EditKeyframes(this, location));
- cm.AddButton("Remove keyframes", _editor.RemoveKeyframes);
+ cm.AddButton(totalSelectionCount == 1 ? "Remove keyframe" : "Remove keyframes", _editor.RemoveKeyframes);
}
cm.AddButton("Edit all keyframes", () => _editor.EditAllKeyframes(this, location));
if (_editor.EnableZoom && _editor.EnablePanning)
@@ -482,16 +491,6 @@ namespace FlaxEditor.GUI
return false;
}
- public void Select()
- {
- IsSelected = true;
- }
-
- public void Deselect()
- {
- IsSelected = false;
- }
-
///
/// Updates the tooltip.
///
@@ -980,7 +979,16 @@ namespace FlaxEditor.GUI
private void RemoveKeyframes()
{
- bool edited = false;
+ if (KeyframesEditorContext != null)
+ KeyframesEditorContext.OnKeyframesDelete(this);
+ else
+ RemoveKeyframesInner();
+ }
+
+ private void RemoveKeyframesInner()
+ {
+ if (SelectionCount == 0)
+ return;
var keyframes = new Dictionary(_keyframes.Count);
for (int i = 0; i < _points.Count; i++)
{
@@ -991,12 +999,9 @@ namespace FlaxEditor.GUI
}
else
{
- p.Deselect();
- edited = true;
+ p.IsSelected = false;
}
}
- if (!edited)
- return;
OnEditingStart();
_keyframes.Clear();
@@ -1088,19 +1093,25 @@ namespace FlaxEditor.GUI
}
}
- private void ClearSelection()
+ ///
+ /// Clears the selection.
+ ///
+ public void ClearSelection()
{
for (int i = 0; i < _points.Count; i++)
{
- _points[i].Deselect();
+ _points[i].IsSelected = false;
}
}
- private void SelectAll()
+ ///
+ /// Selects all keyframes.
+ ///
+ public void SelectAll()
{
for (int i = 0; i < _points.Count; i++)
{
- _points[i].Select();
+ _points[i].IsSelected = true;
}
}
@@ -1182,8 +1193,39 @@ namespace FlaxEditor.GUI
// Cleanup
_points.Clear();
_keyframes.Clear();
+ KeyframesEditorContext = null;
base.OnDestroy();
}
+
+ ///
+ public IKeyframesEditorContext KeyframesEditorContext { get; set; }
+
+ ///
+ public void OnKeyframesDeselect(IKeyframesEditor editor)
+ {
+ ClearSelection();
+ }
+
+ ///
+ public void OnKeyframesSelection(IKeyframesEditor editor, ContainerControl control, Rectangle selection)
+ {
+ if (_keyframes.Count == 0)
+ return;
+ var selectionRect = Rectangle.FromPoints(_contents.PointFromParent(control, selection.UpperLeft), _contents.PointFromParent(control, selection.BottomRight));
+ _contents.UpdateSelection(ref selectionRect);
+ }
+
+ ///
+ public int OnKeyframesSelectionCount()
+ {
+ return SelectionCount;
+ }
+
+ ///
+ public void OnKeyframesDelete(IKeyframesEditor editor)
+ {
+ RemoveKeyframesInner();
+ }
}
}
diff --git a/Source/Editor/GUI/Timeline/Timeline.cs b/Source/Editor/GUI/Timeline/Timeline.cs
index 7ded468e7..21b936c75 100644
--- a/Source/Editor/GUI/Timeline/Timeline.cs
+++ b/Source/Editor/GUI/Timeline/Timeline.cs
@@ -21,7 +21,7 @@ namespace FlaxEditor.GUI.Timeline
///
///
[HideInEditor]
- public class Timeline : ContainerControl
+ public class Timeline : ContainerControl, IKeyframesEditorContext
{
private static readonly KeyValuePair[] FPSValues =
{
@@ -2393,5 +2393,49 @@ namespace FlaxEditor.GUI.Timeline
base.OnDestroy();
}
+
+ ///
+ public void OnKeyframesDeselect(IKeyframesEditor editor)
+ {
+ for (int i = 0; i < _tracks.Count; i++)
+ {
+ if (_tracks[i] is IKeyframesEditorContext trackContext)
+ trackContext.OnKeyframesDeselect(editor);
+ }
+ }
+
+ ///
+ public void OnKeyframesSelection(IKeyframesEditor editor, ContainerControl control, Rectangle selection)
+ {
+ var globalControl = _backgroundArea;
+ var globalRect = Rectangle.FromPoints(control.PointToParent(globalControl, selection.UpperLeft), control.PointToParent(globalControl, selection.BottomRight));
+ for (int i = 0; i < _tracks.Count; i++)
+ {
+ if (_tracks[i] is IKeyframesEditorContext trackContext)
+ trackContext.OnKeyframesSelection(editor, globalControl, globalRect);
+ }
+ }
+
+ ///
+ public int OnKeyframesSelectionCount()
+ {
+ int result = 0;
+ for (int i = 0; i < _tracks.Count; i++)
+ {
+ if (_tracks[i] is IKeyframesEditorContext trackContext)
+ result += trackContext.OnKeyframesSelectionCount();
+ }
+ return result;
+ }
+
+ ///
+ public void OnKeyframesDelete(IKeyframesEditor editor)
+ {
+ for (int i = 0; i < _tracks.Count; i++)
+ {
+ if (_tracks[i] is IKeyframesEditorContext trackContext)
+ trackContext.OnKeyframesDelete(editor);
+ }
+ }
}
}
diff --git a/Source/Editor/GUI/Timeline/Tracks/AudioTrack.cs b/Source/Editor/GUI/Timeline/Tracks/AudioTrack.cs
index 74e9483e8..6b7185d65 100644
--- a/Source/Editor/GUI/Timeline/Tracks/AudioTrack.cs
+++ b/Source/Editor/GUI/Timeline/Tracks/AudioTrack.cs
@@ -225,7 +225,7 @@ namespace FlaxEditor.GUI.Timeline.Tracks
/// The child volume track for audio track. Used to animate audio volume over time.
///
///
- class AudioVolumeTrack : Track
+ class AudioVolumeTrack : Track, IKeyframesEditorContext
{
///
/// Gets the archetype.
@@ -478,7 +478,11 @@ namespace FlaxEditor.GUI.Timeline.Tracks
return;
Curve.Visible = Visible;
if (!Visible)
+ {
+ Curve.ClearSelection();
return;
+ }
+ Curve.KeyframesEditorContext = Timeline;
Curve.CustomViewPanning = Timeline.OnKeyframesViewPanning;
Curve.Bounds = new Rectangle(_audioMedia.X, Y + 1.0f, _audioMedia.Width, Height - 2.0f);
@@ -639,5 +643,32 @@ namespace FlaxEditor.GUI.Timeline.Tracks
base.OnDestroy();
}
+
+ ///
+ public void OnKeyframesDeselect(IKeyframesEditor editor)
+ {
+ if (Curve != null && Curve.Visible)
+ Curve.OnKeyframesDeselect(editor);
+ }
+
+ ///
+ public void OnKeyframesSelection(IKeyframesEditor editor, ContainerControl control, Rectangle selection)
+ {
+ if (Curve != null && Curve.Visible)
+ Curve.OnKeyframesSelection(editor, control, selection);
+ }
+
+ ///
+ public int OnKeyframesSelectionCount()
+ {
+ return Curve != null && Curve.Visible ? Curve.OnKeyframesSelectionCount() : 0;
+ }
+
+ ///
+ public void OnKeyframesDelete(IKeyframesEditor editor)
+ {
+ if (Curve != null && Curve.Visible)
+ Curve.OnKeyframesDelete(editor);
+ }
}
}
diff --git a/Source/Editor/GUI/Timeline/Tracks/CurvePropertyTrack.cs b/Source/Editor/GUI/Timeline/Tracks/CurvePropertyTrack.cs
index 251a3a76e..47d077ece 100644
--- a/Source/Editor/GUI/Timeline/Tracks/CurvePropertyTrack.cs
+++ b/Source/Editor/GUI/Timeline/Tracks/CurvePropertyTrack.cs
@@ -15,7 +15,7 @@ namespace FlaxEditor.GUI.Timeline.Tracks
/// The timeline track for animating object property via Curve.
///
///
- public abstract class CurvePropertyTrackBase : MemberTrack
+ public abstract class CurvePropertyTrackBase : MemberTrack, IKeyframesEditorContext
{
private sealed class Splitter : Control
{
@@ -226,8 +226,12 @@ namespace FlaxEditor.GUI.Timeline.Tracks
return;
Curve.Visible = Visible;
if (!Visible)
+ {
+ Curve.ClearSelection();
return;
+ }
var expanded = IsExpanded;
+ Curve.KeyframesEditorContext = Timeline;
Curve.CustomViewPanning = Timeline.OnKeyframesViewPanning;
Curve.Bounds = new Rectangle(Timeline.StartOffset, Y + 1.0f, Timeline.Duration * Timeline.UnitsPerSecond * Timeline.Zoom, Height - 2.0f);
Curve.ViewScale = new Vector2(Timeline.Zoom, Curve.ViewScale.Y);
@@ -240,11 +244,13 @@ namespace FlaxEditor.GUI.Timeline.Tracks
if (expanded)
{
if (_splitter == null)
+ {
_splitter = new Splitter
{
_track = this,
Parent = Curve,
};
+ }
var splitterHeight = 4.0f;
_splitter.Bounds = new Rectangle(0, Curve.Height - splitterHeight, Curve.Width, splitterHeight);
}
@@ -424,6 +430,33 @@ namespace FlaxEditor.GUI.Timeline.Tracks
base.OnDestroy();
}
+
+ ///
+ public void OnKeyframesDeselect(IKeyframesEditor editor)
+ {
+ if (Curve != null && Curve.Visible)
+ Curve.OnKeyframesDeselect(editor);
+ }
+
+ ///
+ public void OnKeyframesSelection(IKeyframesEditor editor, ContainerControl control, Rectangle selection)
+ {
+ if (Curve != null && Curve.Visible)
+ Curve.OnKeyframesSelection(editor, control, selection);
+ }
+
+ ///
+ public int OnKeyframesSelectionCount()
+ {
+ return Curve != null && Curve.Visible ? Curve.OnKeyframesSelectionCount() : 0;
+ }
+
+ ///
+ public void OnKeyframesDelete(IKeyframesEditor editor)
+ {
+ if (Curve != null && Curve.Visible)
+ Curve.OnKeyframesDelete(editor);
+ }
}
///
diff --git a/Source/Editor/GUI/Timeline/Tracks/EventTrack.cs b/Source/Editor/GUI/Timeline/Tracks/EventTrack.cs
index 255f23bb3..736d8c3c7 100644
--- a/Source/Editor/GUI/Timeline/Tracks/EventTrack.cs
+++ b/Source/Editor/GUI/Timeline/Tracks/EventTrack.cs
@@ -16,7 +16,7 @@ namespace FlaxEditor.GUI.Timeline.Tracks
/// The timeline track for invoking events on a certain points in the time.
///
///
- public class EventTrack : MemberTrack
+ public class EventTrack : MemberTrack, IKeyframesEditorContext
{
///
/// Gets the archetype.
@@ -285,7 +285,11 @@ namespace FlaxEditor.GUI.Timeline.Tracks
return;
Events.Visible = Visible;
if (!Visible)
+ {
+ Events.ClearSelection();
return;
+ }
+ Events.KeyframesEditorContext = Timeline;
Events.CustomViewPanning = Timeline.OnKeyframesViewPanning;
Events.Bounds = new Rectangle(Timeline.StartOffset, Y + 1.0f, Timeline.Duration * Timeline.UnitsPerSecond * Timeline.Zoom, Height - 2.0f);
Events.ViewScale = new Vector2(Timeline.Zoom, 1.0f);
@@ -407,5 +411,32 @@ namespace FlaxEditor.GUI.Timeline.Tracks
base.OnDestroy();
}
+
+ ///
+ public void OnKeyframesDeselect(IKeyframesEditor editor)
+ {
+ if (Events != null && Events.Visible)
+ Events.OnKeyframesDeselect(editor);
+ }
+
+ ///
+ public void OnKeyframesSelection(IKeyframesEditor editor, ContainerControl control, Rectangle selection)
+ {
+ if (Events != null && Events.Visible)
+ Events.OnKeyframesSelection(editor, control, selection);
+ }
+
+ ///
+ public int OnKeyframesSelectionCount()
+ {
+ return Events != null && Events.Visible ? Events.OnKeyframesSelectionCount() : 0;
+ }
+
+ ///
+ public void OnKeyframesDelete(IKeyframesEditor editor)
+ {
+ if (Events != null && Events.Visible)
+ Events.OnKeyframesDelete(editor);
+ }
}
}
diff --git a/Source/Editor/GUI/Timeline/Tracks/KeyframesPropertyTrack.cs b/Source/Editor/GUI/Timeline/Tracks/KeyframesPropertyTrack.cs
index 2c5490f62..e760f6ea1 100644
--- a/Source/Editor/GUI/Timeline/Tracks/KeyframesPropertyTrack.cs
+++ b/Source/Editor/GUI/Timeline/Tracks/KeyframesPropertyTrack.cs
@@ -15,7 +15,7 @@ namespace FlaxEditor.GUI.Timeline.Tracks
/// The timeline track for animating object property via keyframes collection.
///
///
- public class KeyframesPropertyTrack : MemberTrack
+ public class KeyframesPropertyTrack : MemberTrack, IKeyframesEditorContext
{
///
/// Gets the archetype.
@@ -252,7 +252,11 @@ namespace FlaxEditor.GUI.Timeline.Tracks
return;
Keyframes.Visible = Visible;
if (!Visible)
+ {
+ Keyframes.ClearSelection();
return;
+ }
+ Keyframes.KeyframesEditorContext = Timeline;
Keyframes.CustomViewPanning = Timeline.OnKeyframesViewPanning;
Keyframes.Bounds = new Rectangle(Timeline.StartOffset, Y + 1.0f, Timeline.Duration * Timeline.UnitsPerSecond * Timeline.Zoom, Height - 2.0f);
Keyframes.ViewScale = new Vector2(Timeline.Zoom, 1.0f);
@@ -387,5 +391,32 @@ namespace FlaxEditor.GUI.Timeline.Tracks
base.OnDestroy();
}
+
+ ///
+ public void OnKeyframesDeselect(IKeyframesEditor editor)
+ {
+ if (Keyframes != null && Keyframes.Visible)
+ Keyframes.OnKeyframesDeselect(editor);
+ }
+
+ ///
+ public void OnKeyframesSelection(IKeyframesEditor editor, ContainerControl control, Rectangle selection)
+ {
+ if (Keyframes != null && Keyframes.Visible)
+ Keyframes.OnKeyframesSelection(editor, control, selection);
+ }
+
+ ///
+ public int OnKeyframesSelectionCount()
+ {
+ return Keyframes != null && Keyframes.Visible ? Keyframes.OnKeyframesSelectionCount() : 0;
+ }
+
+ ///
+ public void OnKeyframesDelete(IKeyframesEditor editor)
+ {
+ if (Keyframes != null && Keyframes.Visible)
+ Keyframes.OnKeyframesDelete(editor);
+ }
}
}