mirror of
https://github.com/ppy/osu.git
synced 2024-12-14 16:52:54 +08:00
Merge pull request #21434 from jai-x/control-point-scroll-into-view
Ensure currently selected control point will scroll into view
This commit is contained in:
commit
b29054d30d
@ -10,6 +10,8 @@ using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Screens.Edit;
|
||||
@ -26,6 +28,7 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue);
|
||||
|
||||
private TimingScreen timingScreen;
|
||||
private EditorBeatmap editorBeatmap;
|
||||
|
||||
protected override bool ScrollUsingMouseWheel => false;
|
||||
|
||||
@ -35,8 +38,11 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
|
||||
Beatmap.Value = CreateWorkingBeatmap(Ruleset.Value);
|
||||
Beatmap.Disabled = true;
|
||||
}
|
||||
|
||||
var editorBeatmap = new EditorBeatmap(Beatmap.Value.GetPlayableBeatmap(Ruleset.Value));
|
||||
private void reloadEditorBeatmap()
|
||||
{
|
||||
editorBeatmap = new EditorBeatmap(Beatmap.Value.GetPlayableBeatmap(Ruleset.Value));
|
||||
|
||||
Child = new DependencyProvidingContainer
|
||||
{
|
||||
@ -58,7 +64,9 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
{
|
||||
AddStep("Stop clock", () => EditorClock.Stop());
|
||||
|
||||
AddUntilStep("wait for rows to load", () => Child.ChildrenOfType<EffectRowAttribute>().Any());
|
||||
AddStep("Reload Editor Beatmap", reloadEditorBeatmap);
|
||||
|
||||
AddUntilStep("Wait for rows to load", () => Child.ChildrenOfType<EffectRowAttribute>().Any());
|
||||
}
|
||||
|
||||
[Test]
|
||||
@ -95,6 +103,37 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
AddUntilStep("Selection changed", () => timingScreen.SelectedGroup.Value.Time == 69670);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestScrollControlGroupIntoView()
|
||||
{
|
||||
AddStep("Add many control points", () =>
|
||||
{
|
||||
editorBeatmap.ControlPointInfo.Clear();
|
||||
|
||||
editorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint());
|
||||
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
editorBeatmap.ControlPointInfo.Add((i + 1) * 1000, new EffectControlPoint
|
||||
{
|
||||
KiaiMode = Convert.ToBoolean(i % 2),
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
AddStep("Select first effect point", () =>
|
||||
{
|
||||
InputManager.MoveMouseTo(Child.ChildrenOfType<EffectRowAttribute>().First());
|
||||
InputManager.Click(MouseButton.Left);
|
||||
});
|
||||
|
||||
AddStep("Seek to beginning", () => EditorClock.Seek(0));
|
||||
|
||||
AddStep("Seek to last point", () => EditorClock.Seek(101 * 1000));
|
||||
|
||||
AddUntilStep("Scrolled to end", () => timingScreen.ChildrenOfType<OsuScrollContainer>().First().IsScrolledToEnd());
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
Beatmap.Disabled = false;
|
||||
|
@ -1,8 +1,7 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions.LocalisationExtensions;
|
||||
using osu.Framework.Graphics;
|
||||
@ -20,6 +19,8 @@ namespace osu.Game.Screens.Edit
|
||||
{
|
||||
public abstract partial class EditorTable : TableContainer
|
||||
{
|
||||
public event Action<Drawable>? OnRowSelected;
|
||||
|
||||
private const float horizontal_inset = 20;
|
||||
|
||||
protected const float ROW_HEIGHT = 25;
|
||||
@ -45,7 +46,18 @@ namespace osu.Game.Screens.Edit
|
||||
});
|
||||
}
|
||||
|
||||
protected override Drawable CreateHeader(int index, TableColumn column) => new HeaderText(column?.Header ?? default);
|
||||
protected void SetSelectedRow(object? item)
|
||||
{
|
||||
foreach (var b in BackgroundFlow)
|
||||
{
|
||||
b.Selected = ReferenceEquals(b.Item, item);
|
||||
|
||||
if (b.Selected)
|
||||
OnRowSelected?.Invoke(b);
|
||||
}
|
||||
}
|
||||
|
||||
protected override Drawable CreateHeader(int index, TableColumn? column) => new HeaderText(column?.Header ?? default);
|
||||
|
||||
private partial class HeaderText : OsuSpriteText
|
||||
{
|
||||
@ -84,11 +96,6 @@ namespace osu.Game.Screens.Edit
|
||||
Alpha = 0,
|
||||
},
|
||||
};
|
||||
|
||||
// todo delete
|
||||
Action = () =>
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
private Color4 colourHover;
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@ -23,10 +21,10 @@ namespace osu.Game.Screens.Edit.Timing
|
||||
public partial class ControlPointTable : EditorTable
|
||||
{
|
||||
[Resolved]
|
||||
private Bindable<ControlPointGroup> selectedGroup { get; set; }
|
||||
private Bindable<ControlPointGroup> selectedGroup { get; set; } = null!;
|
||||
|
||||
[Resolved]
|
||||
private EditorClock clock { get; set; }
|
||||
private EditorClock clock { get; set; } = null!;
|
||||
|
||||
public const float TIMING_COLUMN_WIDTH = 230;
|
||||
|
||||
@ -37,7 +35,7 @@ namespace osu.Game.Screens.Edit.Timing
|
||||
Content = null;
|
||||
BackgroundFlow.Clear();
|
||||
|
||||
if (value?.Any() != true)
|
||||
if (!value.Any())
|
||||
return;
|
||||
|
||||
foreach (var group in value)
|
||||
@ -63,19 +61,10 @@ namespace osu.Game.Screens.Edit.Timing
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
selectedGroup.BindValueChanged(_ =>
|
||||
{
|
||||
// TODO: This should scroll the selected row into view.
|
||||
updateSelectedGroup();
|
||||
}, true);
|
||||
selectedGroup.BindValueChanged(_ => updateSelectedGroup(), true);
|
||||
}
|
||||
|
||||
private void updateSelectedGroup()
|
||||
{
|
||||
// TODO: This should scroll the selected row into view.
|
||||
foreach (var b in BackgroundFlow)
|
||||
b.Selected = ReferenceEquals(b.Item, selectedGroup?.Value);
|
||||
}
|
||||
private void updateSelectedGroup() => SetSelectedRow(selectedGroup.Value);
|
||||
|
||||
private TableColumn[] createHeaders()
|
||||
{
|
||||
@ -92,32 +81,38 @@ namespace osu.Game.Screens.Edit.Timing
|
||||
{
|
||||
return new Drawable[]
|
||||
{
|
||||
new FillFlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Width = TIMING_COLUMN_WIDTH,
|
||||
Spacing = new Vector2(5),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = group.Time.ToEditorFormattedString(),
|
||||
Font = OsuFont.GetFont(size: TEXT_SIZE, weight: FontWeight.Bold),
|
||||
Width = 70,
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
},
|
||||
new ControlGroupAttributes(group, c => c is TimingControlPoint)
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
}
|
||||
}
|
||||
},
|
||||
new ControlGroupAttributes(group, c => !(c is TimingControlPoint))
|
||||
new ControlGroupTiming(group),
|
||||
new ControlGroupAttributes(group, c => c is not TimingControlPoint)
|
||||
};
|
||||
}
|
||||
|
||||
private partial class ControlGroupTiming : FillFlowContainer
|
||||
{
|
||||
public ControlGroupTiming(ControlPointGroup group)
|
||||
{
|
||||
Name = @"ControlGroupTiming";
|
||||
RelativeSizeAxes = Axes.Y;
|
||||
Width = TIMING_COLUMN_WIDTH;
|
||||
Spacing = new Vector2(5);
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = group.Time.ToEditorFormattedString(),
|
||||
Font = OsuFont.GetFont(size: TEXT_SIZE, weight: FontWeight.Bold),
|
||||
Width = 70,
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
},
|
||||
new ControlGroupAttributes(group, c => c is TimingControlPoint)
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private partial class ControlGroupAttributes : CompositeDrawable
|
||||
{
|
||||
private readonly Func<ControlPoint, bool> matchFunction;
|
||||
@ -132,6 +127,7 @@ namespace osu.Game.Screens.Edit.Timing
|
||||
|
||||
AutoSizeAxes = Axes.X;
|
||||
RelativeSizeAxes = Axes.Y;
|
||||
Name = @"ControlGroupAttributes";
|
||||
|
||||
InternalChild = fill = new FillFlowContainer
|
||||
{
|
||||
@ -161,7 +157,6 @@ namespace osu.Game.Screens.Edit.Timing
|
||||
fill.ChildrenEnumerable = controlPoints
|
||||
.Where(matchFunction)
|
||||
.Select(createAttribute)
|
||||
.Where(c => c != null)
|
||||
// arbitrary ordering to make timing points first.
|
||||
// probably want to explicitly define order in the future.
|
||||
.OrderByDescending(c => c.GetType().Name);
|
||||
@ -184,7 +179,7 @@ namespace osu.Game.Screens.Edit.Timing
|
||||
return new SampleRowAttribute(sample);
|
||||
}
|
||||
|
||||
return null;
|
||||
throw new ArgumentOutOfRangeException(nameof(controlPoint), $"Control point type {controlPoint.GetType()} is not supported");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
@ -50,24 +48,24 @@ namespace osu.Game.Screens.Edit.Timing
|
||||
|
||||
public partial class ControlPointList : CompositeDrawable
|
||||
{
|
||||
private OsuButton deleteButton;
|
||||
private ControlPointTable table;
|
||||
private OsuButton deleteButton = null!;
|
||||
private ControlPointTable table = null!;
|
||||
private OsuScrollContainer scroll = null!;
|
||||
private RoundedButton addButton = null!;
|
||||
|
||||
private readonly IBindableList<ControlPointGroup> controlPointGroups = new BindableList<ControlPointGroup>();
|
||||
|
||||
private RoundedButton addButton;
|
||||
[Resolved]
|
||||
private EditorClock clock { get; set; } = null!;
|
||||
|
||||
[Resolved]
|
||||
private EditorClock clock { get; set; }
|
||||
protected EditorBeatmap Beatmap { get; private set; } = null!;
|
||||
|
||||
[Resolved]
|
||||
protected EditorBeatmap Beatmap { get; private set; }
|
||||
private Bindable<ControlPointGroup?> selectedGroup { get; set; } = null!;
|
||||
|
||||
[Resolved]
|
||||
private Bindable<ControlPointGroup> selectedGroup { get; set; }
|
||||
|
||||
[Resolved(canBeNull: true)]
|
||||
private IEditorChangeHandler changeHandler { get; set; }
|
||||
private IEditorChangeHandler? changeHandler { get; set; }
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OverlayColourProvider colours)
|
||||
@ -88,7 +86,7 @@ namespace osu.Game.Screens.Edit.Timing
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Width = ControlPointTable.TIMING_COLUMN_WIDTH + margins,
|
||||
},
|
||||
new OsuScrollContainer
|
||||
scroll = new OsuScrollContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = table = new ControlPointTable(),
|
||||
@ -142,6 +140,8 @@ namespace osu.Game.Screens.Edit.Timing
|
||||
table.ControlGroups = controlPointGroups;
|
||||
changeHandler?.SaveState();
|
||||
}, true);
|
||||
|
||||
table.OnRowSelected += drawable => scroll.ScrollIntoView(drawable);
|
||||
}
|
||||
|
||||
protected override bool OnClick(ClickEvent e)
|
||||
@ -159,7 +159,7 @@ namespace osu.Game.Screens.Edit.Timing
|
||||
addButton.Enabled.Value = clock.CurrentTimeAccurate != selectedGroup.Value?.Time;
|
||||
}
|
||||
|
||||
private Type trackedType;
|
||||
private Type? trackedType;
|
||||
|
||||
/// <summary>
|
||||
/// Given the user has selected a control point group, we want to track any group which is
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
@ -20,19 +18,19 @@ namespace osu.Game.Screens.Edit.Verify
|
||||
{
|
||||
public partial class IssueTable : EditorTable
|
||||
{
|
||||
[Resolved]
|
||||
private VerifyScreen verify { get; set; }
|
||||
|
||||
private Bindable<Issue> selectedIssue;
|
||||
private Bindable<Issue> selectedIssue = null!;
|
||||
|
||||
[Resolved]
|
||||
private EditorClock clock { get; set; }
|
||||
private VerifyScreen verify { get; set; } = null!;
|
||||
|
||||
[Resolved]
|
||||
private EditorBeatmap editorBeatmap { get; set; }
|
||||
private EditorClock clock { get; set; } = null!;
|
||||
|
||||
[Resolved]
|
||||
private Editor editor { get; set; }
|
||||
private EditorBeatmap editorBeatmap { get; set; } = null!;
|
||||
|
||||
[Resolved]
|
||||
private Editor editor { get; set; } = null!;
|
||||
|
||||
public IEnumerable<Issue> Issues
|
||||
{
|
||||
@ -41,7 +39,7 @@ namespace osu.Game.Screens.Edit.Verify
|
||||
Content = null;
|
||||
BackgroundFlow.Clear();
|
||||
|
||||
if (value == null)
|
||||
if (!value.Any())
|
||||
return;
|
||||
|
||||
foreach (var issue in value)
|
||||
@ -79,7 +77,7 @@ namespace osu.Game.Screens.Edit.Verify
|
||||
selectedIssue = verify.SelectedIssue.GetBoundCopy();
|
||||
selectedIssue.BindValueChanged(issue =>
|
||||
{
|
||||
foreach (var b in BackgroundFlow) b.Selected = b.Item == issue.NewValue;
|
||||
SetSelectedRow(issue.NewValue);
|
||||
}, true);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user