Skip to content

Commit

Permalink
contract sample point pieces based on smallest gap on the timeline
Browse files Browse the repository at this point in the history
It finds the smallest distance between two sample point pieces on the alive timeline blueprints
  • Loading branch information
OliBomby committed Oct 5, 2024
1 parent 9dcce67 commit 48da758
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public partial class SamplePointPiece : HitObjectPointPiece, IHasPopover
private Editor? editor { get; set; }

[Resolved]
private Timeline? timeline { get; set; }
private TimelineBlueprintContainer? timelineBlueprintContainer { get; set; }

private Bindable<bool> samplesVisible = null!;

Expand Down Expand Up @@ -72,9 +72,7 @@ private void load(OsuConfigManager config)
samplesVisible = config.GetBindable<bool>(OsuSetting.EditorTimelineShowSamples);
}

private BindableNumber<float>? timelineZoom;

private bool contracted;
private readonly Bindable<bool> contracted = new Bindable<bool>();

protected override void LoadComplete()
{
Expand All @@ -83,21 +81,19 @@ protected override void LoadComplete()
samplesVisible.BindValueChanged(visible => this.FadeTo(visible.NewValue ? 1 : 0, 200, Easing.OutQuint));
this.FadeTo(samplesVisible.Value ? 1 : 0);

timelineZoom = timeline?.CurrentZoom.GetBoundCopy();
timelineZoom?.BindValueChanged(zoom =>
{
const float zoom_threshold = 40f;
if (timelineBlueprintContainer != null)
contracted.BindTo(timelineBlueprintContainer.SamplePointContracted);

if (zoom.NewValue < zoom_threshold)
contracted.BindValueChanged(v =>
{
if (v.NewValue)
{
contracted = true;
Label.FadeOut(200, Easing.OutQuint);
LabelContainer.ResizeTo(new Vector2(12), 200, Easing.OutQuint);
LabelContainer.CornerRadius = 6;
}
else
{
contracted = false;
Label.FadeIn(200, Easing.OutQuint);
LabelContainer.ResizeTo(new Vector2(Label.Width, 16), 200, Easing.OutQuint);
LabelContainer.CornerRadius = 8;
Expand Down Expand Up @@ -131,7 +127,7 @@ private void updateText()
{
Label.Text = $"{abbreviateBank(GetBankValue(GetSamples()))} {GetVolumeValue(GetSamples())}";

if (!contracted)
if (!contracted.Value)
LabelContainer.ResizeWidthTo(Label.Width, 200, Easing.OutQuint);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,19 @@
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Input.Events;
using osu.Framework.Layout;
using osu.Framework.Utils;
using osu.Game.Graphics;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Screens.Edit.Components.Timelines.Summary.Parts;
using osuTK;
using osuTK.Graphics;

namespace osu.Game.Screens.Edit.Compose.Components.Timeline
{
[Cached]
internal partial class TimelineBlueprintContainer : EditorBlueprintContainer
{
[Resolved(CanBeNull = true)]
Expand All @@ -35,6 +38,8 @@ internal partial class TimelineBlueprintContainer : EditorBlueprintContainer

private bool hitObjectDragged;

private readonly LayoutValue samplePointContractedStateCache = new LayoutValue(Invalidation.DrawSize);

/// <remarks>
/// Positional input must be received outside the container's bounds,
/// in order to handle timeline blueprints which are stacked offscreen.
Expand All @@ -49,6 +54,8 @@ public TimelineBlueprintContainer(HitObjectComposer composer)
Origin = Anchor.Centre;

Height = 0.6f;

AddLayout(samplePointContractedStateCache);
}

[BackgroundDependencyLoader]
Expand Down Expand Up @@ -116,11 +123,43 @@ protected override void Update()
Composer.Playfield.FutureLifetimeExtension = timeline.VisibleRange / 2;
}

updateSamplePointContractedState();

base.Update();

updateStacking();
}

public Bindable<bool> SamplePointContracted = new Bindable<bool>();

private void updateSamplePointContractedState()
{
if (samplePointContractedStateCache.IsValid)
return;

const double minimum_gap = 28;

// Find the smallest time gap between any two sample point pieces
double smallestTimeGap = double.PositiveInfinity;
double lastTime = double.PositiveInfinity;

// The blueprints are ordered in reverse chronological order
foreach (var selectionBlueprint in SelectionBlueprints)
{
var hitObject = selectionBlueprint.Item;

if (hitObject is IHasRepeats hasRepeats)
smallestTimeGap = Math.Min(smallestTimeGap, hasRepeats.Duration / hasRepeats.SpanCount() / 2);

smallestTimeGap = Math.Min(smallestTimeGap, lastTime - hitObject.GetEndTime());
lastTime = hitObject.StartTime;
}

double smallestAbsoluteGap = ((TimelineSelectionBlueprintContainer)SelectionBlueprints).ContentRelativeToAbsoluteFactor.X * smallestTimeGap;
SamplePointContracted.Value = smallestAbsoluteGap < minimum_gap;
samplePointContractedStateCache.Validate();
}

private readonly Stack<HitObject> currentConcurrentObjects = new Stack<HitObject>();

private void updateStacking()
Expand Down Expand Up @@ -288,6 +327,8 @@ protected partial class TimelineSelectionBlueprintContainer : Container<Selectio
{
protected override Container<SelectionBlueprint<HitObject>> Content { get; }

public Vector2 ContentRelativeToAbsoluteFactor => Content.RelativeToAbsoluteFactor;

public TimelineSelectionBlueprintContainer()
{
AddInternal(new TimelinePart<SelectionBlueprint<HitObject>>(Content = new HitObjectOrderedSelectionContainer { RelativeSizeAxes = Axes.Both }) { RelativeSizeAxes = Axes.Both });
Expand Down

0 comments on commit 48da758

Please sign in to comment.