From 1b741dada30dc3d68db3e85180f4327e596a792d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 27 Jun 2024 14:46:57 +0200 Subject: [PATCH] Show distance in pixels to previous/next object in osu! hitobject inspector --- .../Edit/OsuHitObjectComposer.cs | 5 +++ .../Edit/OsuHitObjectInspector.cs | 42 +++++++++++++++++++ .../Compose/Components/EditorInspector.cs | 2 +- .../Compose/Components/HitObjectInspector.cs | 15 +++++-- 4 files changed, 59 insertions(+), 5 deletions(-) create mode 100644 osu.Game.Rulesets.Osu/Edit/OsuHitObjectInspector.cs diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index 41f6b41f82..cf867b4795 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -101,8 +101,13 @@ namespace osu.Game.Rulesets.Osu.Edit updatePositionSnapGrid(); + RightToolbox.Clear(); RightToolbox.AddRange(new EditorToolboxGroup[] { + new EditorToolboxGroup("inspector") + { + Child = new OsuHitObjectInspector(), + }, OsuGridToolboxGroup, new TransformToolboxGroup { diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectInspector.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectInspector.cs new file mode 100644 index 0000000000..27e7d5497c --- /dev/null +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectInspector.cs @@ -0,0 +1,42 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Diagnostics; +using System.Linq; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Screens.Edit.Compose.Components; + +namespace osu.Game.Rulesets.Osu.Edit +{ + public partial class OsuHitObjectInspector : HitObjectInspector + { + protected override void AddInspectorValues() + { + base.AddInspectorValues(); + + if (EditorBeatmap.SelectedHitObjects.Count > 0) + { + var firstInSelection = (OsuHitObject)EditorBeatmap.SelectedHitObjects.MinBy(ho => ho.StartTime)!; + var lastInSelection = (OsuHitObject)EditorBeatmap.SelectedHitObjects.MaxBy(ho => ho.GetEndTime())!; + + Debug.Assert(firstInSelection != null && lastInSelection != null); + + var precedingObject = (OsuHitObject?)EditorBeatmap.HitObjects.LastOrDefault(ho => ho.GetEndTime() < firstInSelection.StartTime); + var nextObject = (OsuHitObject?)EditorBeatmap.HitObjects.FirstOrDefault(ho => ho.StartTime > lastInSelection.GetEndTime()); + + if (precedingObject != null && precedingObject is not Spinner) + { + AddHeader("To previous"); + AddValue($"{(firstInSelection.StackedPosition - precedingObject.StackedEndPosition).Length:#,0.##}px"); + } + + if (nextObject != null && nextObject is not Spinner) + { + AddHeader("To next"); + AddValue($"{(nextObject.StackedPosition - lastInSelection.StackedEndPosition).Length:#,0.##}px"); + } + } + } + } +} diff --git a/osu.Game/Screens/Edit/Compose/Components/EditorInspector.cs b/osu.Game/Screens/Edit/Compose/Components/EditorInspector.cs index 442454f97a..5837dd7946 100644 --- a/osu.Game/Screens/Edit/Compose/Components/EditorInspector.cs +++ b/osu.Game/Screens/Edit/Compose/Components/EditorInspector.cs @@ -10,7 +10,7 @@ using osu.Game.Overlays; namespace osu.Game.Screens.Edit.Compose.Components { - internal partial class EditorInspector : CompositeDrawable + public partial class EditorInspector : CompositeDrawable { protected OsuTextFlowContainer InspectorText = null!; diff --git a/osu.Game/Screens/Edit/Compose/Components/HitObjectInspector.cs b/osu.Game/Screens/Edit/Compose/Components/HitObjectInspector.cs index ac339dc9d9..2f19888e9e 100644 --- a/osu.Game/Screens/Edit/Compose/Components/HitObjectInspector.cs +++ b/osu.Game/Screens/Edit/Compose/Components/HitObjectInspector.cs @@ -9,7 +9,7 @@ using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Screens.Edit.Compose.Components { - internal partial class HitObjectInspector : EditorInspector + public partial class HitObjectInspector : EditorInspector { protected override void LoadComplete() { @@ -29,6 +29,16 @@ namespace osu.Game.Screens.Edit.Compose.Components rollingTextUpdate?.Cancel(); rollingTextUpdate = null; + AddInspectorValues(); + + // I'd hope there's a better way to do this, but I don't want to bind to each and every property above to watch for changes. + // This is a good middle-ground for the time being. + if (EditorBeatmap.SelectedHitObjects.Count > 0) + rollingTextUpdate ??= Scheduler.AddDelayed(updateInspectorText, 250); + } + + protected virtual void AddInspectorValues() + { switch (EditorBeatmap.SelectedHitObjects.Count) { case 0: @@ -90,9 +100,6 @@ namespace osu.Game.Screens.Edit.Compose.Components AddValue($"{duration.Duration:#,0.##}ms"); } - // I'd hope there's a better way to do this, but I don't want to bind to each and every property above to watch for changes. - // This is a good middle-ground for the time being. - rollingTextUpdate ??= Scheduler.AddDelayed(updateInspectorText, 250); break; default: