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