diff --git a/Source/Editor/GUI/CurveEditor.Base.cs b/Source/Editor/GUI/CurveEditor.Base.cs index 0dc6f3b4f..7891eacb1 100644 --- a/Source/Editor/GUI/CurveEditor.Base.cs +++ b/Source/Editor/GUI/CurveEditor.Base.cs @@ -54,6 +54,11 @@ namespace FlaxEditor.GUI /// public event Action EditingEnd; + /// + /// The function for custom view panning. Gets input movement delta (in curve control space) and returns the renaming input delta to process by curve editor itself. + /// + public Func CustomViewPanning; + /// /// The maximum amount of keyframes to use in a single curve. /// diff --git a/Source/Editor/GUI/CurveEditor.Contents.cs b/Source/Editor/GUI/CurveEditor.Contents.cs index 9964c0485..96b796f9f 100644 --- a/Source/Editor/GUI/CurveEditor.Contents.cs +++ b/Source/Editor/GUI/CurveEditor.Contents.cs @@ -78,22 +78,31 @@ namespace FlaxEditor.GUI if (_rightMouseDown) { Vector2 delta = location - _movingViewLastPos; + if (_editor.CustomViewPanning != null) + delta = _editor.CustomViewPanning(delta); delta *= GetUseModeMask(_editor.EnablePanning) * _editor.ViewScale; if (delta.LengthSquared > 0.01f) { _editor._mainPanel.ViewOffset += delta; _movingViewLastPos = location; - switch (_editor.EnablePanning) + if (_editor.CustomViewPanning != null) { - case UseMode.Vertical: - Cursor = CursorType.SizeNS; - break; - case UseMode.Horizontal: - Cursor = CursorType.SizeWE; - break; - case UseMode.On: Cursor = CursorType.SizeAll; - break; + } + else + { + switch (_editor.EnablePanning) + { + case UseMode.Vertical: + Cursor = CursorType.SizeNS; + break; + case UseMode.Horizontal: + Cursor = CursorType.SizeWE; + break; + case UseMode.On: + Cursor = CursorType.SizeAll; + break; + } } } diff --git a/Source/Editor/GUI/Timeline/GUI/KeyframesEditor.cs b/Source/Editor/GUI/Timeline/GUI/KeyframesEditor.cs index 919d76f6b..6942b0fc0 100644 --- a/Source/Editor/GUI/Timeline/GUI/KeyframesEditor.cs +++ b/Source/Editor/GUI/Timeline/GUI/KeyframesEditor.cs @@ -128,12 +128,19 @@ namespace FlaxEditor.GUI { // Calculate delta Vector2 delta = location - _movingViewLastPos; - if (delta.LengthSquared > 0.01f && _editor.EnablePanning) + if (delta.LengthSquared > 0.01f) { - // Move view - _editor.ViewOffset += delta * _editor.ViewScale; - _movingViewLastPos = location; - Cursor = CursorType.SizeAll; + if (_editor.CustomViewPanning != null) + delta = _editor.CustomViewPanning(delta); + if (_editor.EnablePanning) + { + // Move view + _editor.ViewOffset += delta * _editor.ViewScale; + _movingViewLastPos = location; + Cursor = CursorType.SizeAll; + } + else if (_editor.CustomViewPanning != null) + Cursor = CursorType.SizeAll; } return; @@ -560,6 +567,11 @@ namespace FlaxEditor.GUI /// public event Action EditingEnd; + /// + /// The function for custom view panning. Gets input movement delta (in keyframes editor control space) and returns the renaming input delta to process by keyframes editor itself. + /// + public Func CustomViewPanning; + /// /// The maximum amount of keyframes to use. /// diff --git a/Source/Editor/GUI/Timeline/Timeline.cs b/Source/Editor/GUI/Timeline/Timeline.cs index 258dbbe81..7ded468e7 100644 --- a/Source/Editor/GUI/Timeline/Timeline.cs +++ b/Source/Editor/GUI/Timeline/Timeline.cs @@ -1809,6 +1809,30 @@ namespace FlaxEditor.GUI.Timeline { } + /// + /// Custom event for keyframes or curve editor view panning to handle timeline background panning horizontally too. + /// + /// + /// + /// The input delta. + /// The result input delta. + public Vector2 OnKeyframesViewPanning(Vector2 delta) + { + var area = _backgroundArea; + var hScroll = area.HScrollBar.Visible && area.HScrollBar.Enabled; + if (hScroll) + { + bool wasLocked = area.IsLayoutLocked; + area.IsLayoutLocked = true; + area.HScrollBar.TargetValue -= delta.X; + delta.X = 0.0f; + area.IsLayoutLocked = wasLocked; + area.PerformLayout(); + area.Cursor = CursorType.SizeWE; + } + return delta; + } + /// /// Mark timeline as edited. /// diff --git a/Source/Editor/GUI/Timeline/Tracks/AudioTrack.cs b/Source/Editor/GUI/Timeline/Tracks/AudioTrack.cs index 513ae30ad..74e9483e8 100644 --- a/Source/Editor/GUI/Timeline/Tracks/AudioTrack.cs +++ b/Source/Editor/GUI/Timeline/Tracks/AudioTrack.cs @@ -476,7 +476,10 @@ namespace FlaxEditor.GUI.Timeline.Tracks { if (_audioMedia == null || Curve == null || Timeline == null) return; - + Curve.Visible = Visible; + if (!Visible) + return; + Curve.CustomViewPanning = Timeline.OnKeyframesViewPanning; Curve.Bounds = new Rectangle(_audioMedia.X, Y + 1.0f, _audioMedia.Width, Height - 2.0f); var expanded = IsExpanded; diff --git a/Source/Editor/GUI/Timeline/Tracks/CurvePropertyTrack.cs b/Source/Editor/GUI/Timeline/Tracks/CurvePropertyTrack.cs index 6b46978e7..251a3a76e 100644 --- a/Source/Editor/GUI/Timeline/Tracks/CurvePropertyTrack.cs +++ b/Source/Editor/GUI/Timeline/Tracks/CurvePropertyTrack.cs @@ -69,7 +69,7 @@ namespace FlaxEditor.GUI.Timeline.Tracks return base.OnMouseDown(location, button); } - + public override void OnMouseMove(Vector2 location) { base.OnMouseMove(location); @@ -84,7 +84,7 @@ namespace FlaxEditor.GUI.Timeline.Tracks } } } - + public override bool OnMouseUp(Vector2 location, MouseButton button) { if (button == MouseButton.Left && _clicked) @@ -228,6 +228,7 @@ namespace FlaxEditor.GUI.Timeline.Tracks if (!Visible) return; var expanded = IsExpanded; + 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); Curve.ShowCollapsed = !expanded; @@ -238,7 +239,7 @@ namespace FlaxEditor.GUI.Timeline.Tracks Curve.UpdateKeyframes(); if (expanded) { - if(_splitter == null) + if (_splitter == null) _splitter = new Splitter { _track = this, diff --git a/Source/Editor/GUI/Timeline/Tracks/EventTrack.cs b/Source/Editor/GUI/Timeline/Tracks/EventTrack.cs index 32e81e466..255f23bb3 100644 --- a/Source/Editor/GUI/Timeline/Tracks/EventTrack.cs +++ b/Source/Editor/GUI/Timeline/Tracks/EventTrack.cs @@ -281,9 +281,12 @@ namespace FlaxEditor.GUI.Timeline.Tracks private void UpdateEvents() { - if (Events == null) + if (Events == null || Timeline == null) return; - + Events.Visible = Visible; + if (!Visible) + return; + 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); Events.Visible = Visible; diff --git a/Source/Editor/GUI/Timeline/Tracks/KeyframesPropertyTrack.cs b/Source/Editor/GUI/Timeline/Tracks/KeyframesPropertyTrack.cs index 03291b3d2..2c5490f62 100644 --- a/Source/Editor/GUI/Timeline/Tracks/KeyframesPropertyTrack.cs +++ b/Source/Editor/GUI/Timeline/Tracks/KeyframesPropertyTrack.cs @@ -248,11 +248,12 @@ namespace FlaxEditor.GUI.Timeline.Tracks private void UpdateKeyframes() { - if (Keyframes == null) + if (Keyframes == null || Timeline == null) return; Keyframes.Visible = Visible; if (!Visible) return; + 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); Keyframes.UpdateKeyframes();