Improve keyframes and curves points moving with a mouse

#519
This commit is contained in:
Wojtek Figat
2021-08-04 10:59:43 +02:00
parent 6ee6c8e0be
commit 9464c509fa
2 changed files with 140 additions and 128 deletions

View File

@@ -611,12 +611,14 @@ namespace FlaxEditor.GUI
private bool _rightMouseDown;
internal Vector2 _leftMouseDownPos = Vector2.Minimum;
private Vector2 _rightMouseDownPos = Vector2.Minimum;
private Vector2 _movingViewLastPos;
internal Vector2 _mousePos = Vector2.Minimum;
private float _mouseMoveAmount;
internal bool _isMovingSelection;
internal bool _isMovingTangent;
internal bool _movedKeyframes;
private TangentPoint _movingTangent;
private Vector2 _movingSelectionViewPos;
private Vector2 _movingSelectionStart;
private Vector2[] _movingSelectionOffsets;
private Vector2 _cmShowPos;
/// <summary>
@@ -669,14 +671,13 @@ namespace FlaxEditor.GUI
if (_rightMouseDown)
{
// Calculate delta
Vector2 delta = location - _rightMouseDownPos;
Vector2 delta = location - _movingViewLastPos;
delta *= GetUseModeMask(_editor.EnablePanning);
if (delta.LengthSquared > 0.01f)
{
// Move view
_mouseMoveAmount += delta.Length;
_editor.ViewOffset += delta * _editor.ViewScale;
_rightMouseDownPos = location;
_movingViewLastPos = location;
Cursor = CursorType.SizeAll;
}
@@ -685,99 +686,82 @@ namespace FlaxEditor.GUI
// Moving selection
else if (_isMovingSelection)
{
// Calculate delta (apply view offset)
Vector2 viewDelta = _editor.ViewOffset - _movingSelectionViewPos;
_movingSelectionViewPos = _editor.ViewOffset;
var viewRect = _editor._mainPanel.GetClientArea();
var delta = location - _leftMouseDownPos - viewDelta;
_mouseMoveAmount += delta.Length;
if (delta.LengthSquared > 0.01f)
var locationKeyframes = PointToKeyframes(location, ref viewRect);
var accessor = _editor.Accessor;
var components = accessor.GetCurveComponents();
for (var i = 0; i < _editor._points.Count; i++)
{
// Move selected keyframes
var keyframeDelta = PointToKeyframes(location, ref viewRect) - PointToKeyframes(_leftMouseDownPos - viewDelta, 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 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)
{
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;
if (!_editor.ShowCollapsed)
{
// Move on value axis
value += keyframeDelta.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 += keyframeDelta.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);
// 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(location));
//_editor._mainPanel.ScrollViewTo(PointToParent(_editor._mainPanel, location));
}
_leftMouseDownPos = location;
Cursor = CursorType.SizeAll;
_movedKeyframes = true;
}
return;
}
// Moving tangent
else if (_isMovingTangent)
{
// Calculate delta (apply view offset)
Vector2 viewDelta = _editor.ViewOffset - _movingSelectionViewPos;
_movingSelectionViewPos = _editor.ViewOffset;
var viewRect = _editor._mainPanel.GetClientArea();
var delta = location - _leftMouseDownPos - viewDelta;
_mouseMoveAmount += delta.Length;
if (delta.LengthSquared > 0.01f)
{
// Move selected tangent
var keyframeDelta = PointToKeyframes(location, ref viewRect) - PointToKeyframes(_leftMouseDownPos - viewDelta, ref viewRect);
var direction = _movingTangent.IsIn ? -1.0f : 1.0f;
_movingTangent.TangentValue += direction * keyframeDelta.Y;
_editor.UpdateTangents();
_leftMouseDownPos = location;
Cursor = CursorType.SizeNS;
}
var direction = _movingTangent.IsIn ? -1.0f : 1.0f;
var k = _editor.GetKeyframe(_movingTangent.Index);
var kv = _editor.GetKeyframeValue(k);
var value = _editor.Accessor.GetCurveValue(ref kv, _movingTangent.Component);
_movingTangent.TangentValue = direction * (PointToKeyframes(location, ref viewRect).Y - value);
_editor.UpdateTangents();
Cursor = CursorType.SizeNS;
_movedKeyframes = true;
return;
}
// Selecting
@@ -835,6 +819,7 @@ namespace FlaxEditor.GUI
{
_rightMouseDown = true;
_rightMouseDownPos = location;
_movingViewLastPos = location;
}
// Check if any node is under the mouse
@@ -861,11 +846,17 @@ namespace FlaxEditor.GUI
// Start moving selected nodes
StartMouseCapture();
_mouseMoveAmount = 0;
_isMovingSelection = true;
_movingSelectionViewPos = _editor.ViewOffset;
_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].TimeValue - _movingSelectionStart;
_editor.OnEditingStart();
Focus();
Tooltip?.Hide();
return true;
}
}
@@ -875,12 +866,12 @@ namespace FlaxEditor.GUI
{
// Start moving tangent
StartMouseCapture();
_mouseMoveAmount = 0;
_isMovingTangent = true;
_movedKeyframes = false;
_movingTangent = tangent;
_movingSelectionViewPos = _editor.ViewOffset;
_editor.OnEditingStart();
Focus();
Tooltip?.Hide();
return true;
}
}
@@ -922,16 +913,17 @@ namespace FlaxEditor.GUI
// Editing tangent
if (_isMovingTangent)
{
if (_mouseMoveAmount > 3.0f)
if (_movedKeyframes)
{
_editor.OnEdited();
_editor.OnEditingEnd();
_editor.UpdateKeyframes();
}
}
// Moving keyframes
else if (_isMovingSelection)
{
if (_mouseMoveAmount > 3.0f)
if (_movedKeyframes)
{
_editor.OnEdited();
_editor.OnEditingEnd();
@@ -945,6 +937,7 @@ namespace FlaxEditor.GUI
_isMovingSelection = false;
_isMovingTangent = false;
_movedKeyframes = false;
}
if (_rightMouseDown && button == MouseButton.Right)
{
@@ -953,7 +946,7 @@ namespace FlaxEditor.GUI
Cursor = CursorType.Default;
// Check if no move has been made at all
if (_mouseMoveAmount < 3.0f)
if (Vector2.Distance(ref location, ref _rightMouseDownPos) < 3.0f)
{
var selectionCount = _editor.SelectionCount;
var underMouse = GetChildAt(location);
@@ -993,7 +986,6 @@ namespace FlaxEditor.GUI
_editor.OnShowContextMenu(cm, selectionCount);
cm.Show(this, location);
}
_mouseMoveAmount = 0;
}
if (base.OnMouseUp(location, button))
@@ -1073,6 +1065,20 @@ namespace FlaxEditor.GUI
/// </summary>
public bool IsSelected;
/// <summary>
/// Gets the point time and value on a curve.
/// </summary>
public Vector2 TimeValue
{
get
{
var k = Editor.GetKeyframe(Index);
var time = Editor.GetKeyframeTime(k);
var value = Editor.GetKeyframeValue(k);
return new Vector2(time, Editor.Accessor.GetCurveValue(ref value, Component));
}
}
/// <inheritdoc />
public override void Draw()
{
@@ -2878,7 +2884,8 @@ namespace FlaxEditor.GUI
bounds.Height = Mathf.Max(bounds.Height, 1.0f);
bounds.Location = ApplyUseModeMask(EnablePanning, bounds.Location, _contents.Location);
bounds.Size = ApplyUseModeMask(EnablePanning, bounds.Size, _contents.Size);
_contents.Bounds = bounds;
if (!_contents._isMovingSelection)
_contents.Bounds = bounds;
}
else if (_contents.Bounds == Rectangle.Empty)
{

View File

@@ -72,9 +72,11 @@ namespace FlaxEditor.GUI
internal Vector2 _leftMouseDownPos = Vector2.Minimum;
private Vector2 _rightMouseDownPos = Vector2.Minimum;
internal Vector2 _mousePos = Vector2.Minimum;
private float _mouseMoveAmount;
private Vector2 _movingViewLastPos;
internal bool _isMovingSelection;
private Vector2 _movingSelectionViewPos;
internal bool _movedKeyframes;
private float _movingSelectionStart;
private float[] _movingSelectionOffsets;
private Vector2 _cmShowPos;
/// <summary>
@@ -125,13 +127,12 @@ namespace FlaxEditor.GUI
if (_rightMouseDown)
{
// Calculate delta
Vector2 delta = location - _rightMouseDownPos;
Vector2 delta = location - _movingViewLastPos;
if (delta.LengthSquared > 0.01f && _editor.EnablePanning)
{
// Move view
_mouseMoveAmount += delta.Length;
_editor.ViewOffset += delta * _editor.ViewScale;
_rightMouseDownPos = location;
_movingViewLastPos = location;
Cursor = CursorType.SizeAll;
}
@@ -140,44 +141,38 @@ namespace FlaxEditor.GUI
// Moving selection
else if (_isMovingSelection)
{
// Calculate delta (apply view offset)
Vector2 viewDelta = _editor.ViewOffset - _movingSelectionViewPos;
_movingSelectionViewPos = _editor.ViewOffset;
var viewRect = _editor._mainPanel.GetClientArea();
var delta = location - _leftMouseDownPos - viewDelta;
_mouseMoveAmount += delta.Length;
if (delta.LengthSquared > 0.01f)
var locationKeyframes = PointToKeyframes(location, ref viewRect);
for (var i = 0; i < _editor._points.Count; i++)
{
// Move selected keyframes
var keyframeDelta = PointToKeyframes(location, ref viewRect) - PointToKeyframes(_leftMouseDownPos - viewDelta, ref viewRect);
for (var i = 0; i < _editor._points.Count; i++)
var p = _editor._points[i];
if (p.IsSelected)
{
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)
{
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;
k.Time += keyframeDelta.X;
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;
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(location));
_leftMouseDownPos = location;
{
//_editor._mainPanel.ScrollViewTo(PointToParent(_editor._mainPanel, location));
}
Cursor = CursorType.SizeAll;
_movedKeyframes = true;
}
return;
@@ -234,6 +229,7 @@ namespace FlaxEditor.GUI
{
_rightMouseDown = true;
_rightMouseDownPos = location;
_movingViewLastPos = location;
}
// Check if any node is under the mouse
@@ -258,11 +254,17 @@ namespace FlaxEditor.GUI
// Start moving selected nodes
StartMouseCapture();
_mouseMoveAmount = 0;
_isMovingSelection = true;
_movingSelectionViewPos = _editor.ViewOffset;
_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;
}
}
@@ -303,10 +305,11 @@ namespace FlaxEditor.GUI
// Moving keyframes
if (_isMovingSelection)
{
if (_mouseMoveAmount > 3.0f)
if (_movedKeyframes)
{
_editor.OnEdited();
_editor.OnEditingEnd();
_editor.UpdateKeyframes();
}
}
// Selecting
@@ -316,6 +319,7 @@ namespace FlaxEditor.GUI
}
_isMovingSelection = false;
_movedKeyframes = false;
}
if (_rightMouseDown && button == MouseButton.Right)
{
@@ -324,7 +328,7 @@ namespace FlaxEditor.GUI
Cursor = CursorType.Default;
// Check if no move has been made at all
if (_mouseMoveAmount < 3.0f)
if (Vector2.Distance(ref location, ref _rightMouseDownPos) < 3.0f)
{
var selectionCount = _editor.SelectionCount;
var underMouse = GetChildAt(location);
@@ -362,7 +366,6 @@ namespace FlaxEditor.GUI
}
cm.Show(this, location);
}
_mouseMoveAmount = 0;
}
if (base.OnMouseUp(location, button))
@@ -1045,8 +1048,10 @@ namespace FlaxEditor.GUI
}
// Adjust contents bounds to fill the keyframes area
if (EnablePanning)
if (EnablePanning && !_contents._isMovingSelection)
{
_contents.Bounds = bounds;
}
// Offset the keyframes (parent container changed its location)
var posOffset = _contents.Location;