From 074dee3a83a9d456378a91518f4daa8bb9b26e40 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 5 Apr 2018 18:37:51 +0900 Subject: [PATCH] Re-implement mousewheel zoom --- .../Timeline/ScrollingTimelineContainer.cs | 73 +++++++++++++++++-- 1 file changed, 68 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollingTimelineContainer.cs b/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollingTimelineContainer.cs index 07896d63be..e4b19fc2c5 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollingTimelineContainer.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollingTimelineContainer.cs @@ -4,8 +4,12 @@ using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Transforms; +using osu.Framework.Input; +using osu.Framework.MathUtils; using osu.Game.Beatmaps; using osu.Game.Graphics; +using OpenTK; namespace osu.Game.Screens.Edit.Screens.Compose.Timeline { @@ -15,13 +19,15 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline public readonly Bindable Beatmap = new Bindable(); private readonly Container waveformContainer; - private readonly BeatmapWaveformGraph waveform; + + private float currentZoom = 10; public ScrollingTimelineContainer() : base(Direction.Horizontal) { Masking = true; + BeatmapWaveformGraph waveform; Child = waveformContainer = new Container { RelativeSizeAxes = Axes.Y, @@ -34,18 +40,75 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline }; waveform.Beatmap.BindTo(Beatmap); - + WaveformVisible.ValueChanged += visible => waveform.FadeTo(visible ? 1 : 0, 200, Easing.OutQuint); } - private float zoom = 10; - protected override void Update() { base.Update(); waveformContainer.Margin = new MarginPadding { Horizontal = DrawWidth / 2 }; - waveformContainer.Width = DrawWidth * zoom; + waveformContainer.Width = DrawWidth * currentZoom; + } + + protected override bool OnWheel(InputState state) + { + if (!state.Keyboard.ControlPressed) + return base.OnWheel(state); + + setZoomTarget(zoomTarget + state.Mouse.WheelDelta, waveformContainer.ToLocalSpace(state.Mouse.NativeState.Position).X); + return true; + } + + private float zoomTarget = 10; + private void setZoomTarget(float newZoom, float focusPoint) + { + zoomTarget = MathHelper.Clamp(newZoom, 1, 60); + transformZoomTo(zoomTarget, focusPoint, 200, Easing.OutQuint); + } + + private void transformZoomTo(float newZoom, float focusPoint, double duration = 0, Easing easing = Easing.None) + => this.TransformTo(this.PopulateTransform(new TransformZoom(focusPoint, waveformContainer.DrawWidth, DrawWidth, Current), newZoom, duration, easing)); + + private class TransformZoom : Transform + { + private readonly float focusPoint; + private readonly float focusSize; + private readonly float sizeReference; + private readonly float scrollOffset; + + public TransformZoom(float focusPoint, float focusSize, float sizeReference, float scrollOffset) + { + this.focusPoint = focusPoint; + this.focusSize = focusSize; + this.sizeReference = sizeReference; + this.scrollOffset = scrollOffset; + } + + public override string TargetMember => nameof(currentZoom); + + private float valueAt(double time) + { + if (time < StartTime) return StartValue; + if (time >= EndTime) return EndValue; + + return Interpolation.ValueAt(time, StartValue, EndValue, StartTime, EndTime, Easing); + } + + protected override void Apply(ScrollingTimelineContainer d, double time) + { + float newZoom = valueAt(time); + + float focusOffset = focusPoint - scrollOffset; + float expectedWidth = sizeReference * newZoom; + float targetOffset = expectedWidth * (focusPoint / focusSize) - focusOffset; + + d.currentZoom = newZoom; + d.ScrollTo(targetOffset, false); + } + + protected override void ReadIntoStartValue(ScrollingTimelineContainer d) => StartValue = d.currentZoom; } } }