diff --git a/Source/Editor/Viewport/Previews/AnimatedModelPreview.cs b/Source/Editor/Viewport/Previews/AnimatedModelPreview.cs index 158ccc370..1447b17cb 100644 --- a/Source/Editor/Viewport/Previews/AnimatedModelPreview.cs +++ b/Source/Editor/Viewport/Previews/AnimatedModelPreview.cs @@ -196,6 +196,12 @@ namespace FlaxEditor.Viewport.Previews { _previewModel.UpdateAnimation(); } + else + { + // Invalidate playback timer (preserves playback state, clears ticking info in LastUpdateTime) + _previewModel.IsActive = !_previewModel.IsActive; + _previewModel.IsActive = !_previewModel.IsActive; + } } /// diff --git a/Source/Editor/Viewport/Widgets/ViewportWidgetButton.cs b/Source/Editor/Viewport/Widgets/ViewportWidgetButton.cs index 9f4451cab..5b5eb9892 100644 --- a/Source/Editor/Viewport/Widgets/ViewportWidgetButton.cs +++ b/Source/Editor/Viewport/Widgets/ViewportWidgetButton.cs @@ -15,7 +15,6 @@ namespace FlaxEditor.Viewport.Widgets public class ViewportWidgetButton : Control { private string _text; - private SpriteHandle _icon; private ContextMenu _cm; private bool _checked; private bool _autoCheck; @@ -31,6 +30,11 @@ namespace FlaxEditor.Viewport.Widgets /// public event Action Clicked; + /// + /// The icon. + /// + public SpriteHandle Icon; + /// /// Gets or sets the text. /// @@ -64,7 +68,7 @@ namespace FlaxEditor.Viewport.Widgets : base(0, 0, CalculateButtonWidth(0, icon.IsValid), ViewportWidgetsContainer.WidgetsHeight) { _text = text; - _icon = icon; + Icon = icon; _cm = contextMenu; _autoCheck = autoCheck; @@ -105,10 +109,10 @@ namespace FlaxEditor.Viewport.Widgets Render2D.FillRectangle(textRect, style.BackgroundHighlighted); // Check if has icon - if (_icon.IsValid) + if (Icon.IsValid) { // Draw icon - Render2D.DrawSprite(_icon, iconRect, style.Foreground); + Render2D.DrawSprite(Icon, iconRect, style.Foreground); // Update text rectangle textRect.Location.X += iconSize; @@ -156,7 +160,7 @@ namespace FlaxEditor.Viewport.Widgets var style = Style.Current; if (style != null && style.FontMedium) - Width = CalculateButtonWidth(style.FontMedium.MeasureText(_text).X, _icon.IsValid); + Width = CalculateButtonWidth(style.FontMedium.MeasureText(_text).X, Icon.IsValid); } } } diff --git a/Source/Editor/Windows/Assets/AnimationGraphWindow.cs b/Source/Editor/Windows/Assets/AnimationGraphWindow.cs index 603fc6c7c..404cc4783 100644 --- a/Source/Editor/Windows/Assets/AnimationGraphWindow.cs +++ b/Source/Editor/Windows/Assets/AnimationGraphWindow.cs @@ -8,10 +8,12 @@ using FlaxEditor.CustomEditors; using FlaxEditor.CustomEditors.Editors; using FlaxEditor.GUI; using FlaxEditor.GUI.ContextMenu; +using FlaxEditor.GUI.Input; using FlaxEditor.Scripting; using FlaxEditor.Surface; using FlaxEditor.Viewport.Cameras; using FlaxEditor.Viewport.Previews; +using FlaxEditor.Viewport.Widgets; using FlaxEngine; using FlaxEngine.GUI; using Object = FlaxEngine.Object; @@ -51,6 +53,7 @@ namespace FlaxEditor.Windows.Assets { private readonly AnimationGraphWindow _window; private ContextMenuButton _showFloorButton; + private ViewportWidgetButton _playPauseButton; private StaticModel _floorModel; public AnimationGraphPreview(AnimationGraphWindow window) @@ -63,6 +66,33 @@ namespace FlaxEditor.Windows.Assets _showFloorButton.Icon = Style.Current.CheckBoxTick; _showFloorButton.IndexInParent = 1; + // Playback Speed + { + var playbackSpeed = ViewWidgetButtonMenu.AddButton("Playback Speed"); + var playbackSpeedValue = new FloatValueBox(-1, 90, 2, 70.0f, 0.0f, 10000.0f, 0.001f) + { + Parent = playbackSpeed + }; + playbackSpeedValue.ValueChanged += () => PreviewActor.UpdateSpeed = playbackSpeedValue.Value; + ViewWidgetButtonMenu.VisibleChanged += control => playbackSpeedValue.Value = PreviewActor.UpdateSpeed; + } + + // Play/Pause widget + { + var playPauseWidget = new ViewportWidgetsContainer(ViewportWidgetLocation.UpperRight); + _playPauseButton = new ViewportWidgetButton(null, Editor.Instance.Icons.Pause64) + { + TooltipText = "Animation playback play (F5) or pause (F6)", + Parent = playPauseWidget, + }; + _playPauseButton.Clicked += button => + { + PlayAnimation = !PlayAnimation; + button.Icon = PlayAnimation ? Editor.Instance.Icons.Pause64 : Editor.Instance.Icons.Play64; + }; + playPauseWidget.Parent = this; + } + // Floor model _floorModel = new StaticModel { @@ -101,10 +131,29 @@ namespace FlaxEditor.Windows.Assets } } + /// + public override bool OnKeyDown(KeyboardKeys key) + { + var inputOptions = Editor.Instance.Options.Options.Input; + if (inputOptions.Play.Process(this, key)) + { + PlayAnimation = true; + _playPauseButton.Icon = PlayAnimation ? Editor.Instance.Icons.Pause64 : Editor.Instance.Icons.Play64; + return true; + } + if (inputOptions.Pause.Process(this, key)) + { + PlayAnimation = false; + _playPauseButton.Icon = PlayAnimation ? Editor.Instance.Icons.Pause64 : Editor.Instance.Icons.Play64; + return true; + } + return base.OnKeyDown(key); + } + /// public override void OnDestroy() { - FlaxEngine.Object.Destroy(ref _floorModel); + Object.Destroy(ref _floorModel); _showFloorButton = null; base.OnDestroy();