Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change ObjectInspector to work via object selection #208

Open
wants to merge 26 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
ee7ec3c
osu select by cursor inspector function
Givikap120 Jun 28, 2024
4f2d98a
new way of doing things
Givikap120 Jul 12, 2024
e6ddcf3
removed unnecessary things
Givikap120 Jul 12, 2024
fd1deb7
removed temporary unused things
Givikap120 Jul 12, 2024
c1e8c38
fixed issues with osu inspector
Givikap120 Jul 13, 2024
35fef60
moved inspectors to ruleset-respective folders
Givikap120 Jul 13, 2024
3a9d68d
Added basic taiko functionality
Givikap120 Jul 18, 2024
8d3eadd
implemented catch
Givikap120 Jul 18, 2024
f073b85
Merge branch 'ppy:master' into pp_dev_helper
Givikap120 Jul 18, 2024
af0c080
Update PerformanceCalculatorGUI.csproj
Givikap120 Jul 18, 2024
2659546
Update CatchSelectableDrawableObject.cs
Givikap120 Jul 18, 2024
2b8cab4
changed abstractions structure
Givikap120 Jul 19, 2024
c1a3b39
Added catch support and pooling
Givikap120 Jul 19, 2024
0830dd1
reverted useless ObjectInspector changes
Givikap120 Jul 19, 2024
1cea094
code factor fix
Givikap120 Jul 19, 2024
7a1a2fd
minor fixes
Givikap120 Jul 19, 2024
0b37191
moved selection logic to the object itself
Givikap120 Aug 1, 2024
c513681
fixed pausing/resuming working incorrectly
Givikap120 Aug 2, 2024
d248e51
Fixed Strong notes being outlined incorrectly
Givikap120 Aug 2, 2024
66e41d1
Merge branch 'master' into pp_dev_helper
stanriders Dec 4, 2024
e9ef567
Cleanup
stanriders Dec 4, 2024
08cc7d3
Change catch inspector to use bindables for selection, remove pooling…
stanriders Dec 4, 2024
701e327
Remove unused class
stanriders Dec 5, 2024
1c6359e
remvoe outdated comments
Givikap120 Dec 5, 2024
61e1ce0
Refactor taiko
stanriders Dec 5, 2024
3d62ad1
Merge branch 'pp_dev_helper' of https://github.com/Givikap120/osu-too…
stanriders Dec 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// Copyright (c) ppy Pty Ltd <[email protected]>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

#nullable enable
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general we don't #nullable enable in new files.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm planning to go over the whole project and enabling nullables everywhere after I'm done refactoring this pr


using System.Collections.Generic;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Input.Events;
using osu.Game.Beatmaps;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Catch.Difficulty.Preprocessing;
using osu.Game.Rulesets.Catch.Edit;
using osu.Game.Rulesets.Catch.Objects;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.UI;
using osuTK.Input;

namespace PerformanceCalculatorGUI.Screens.ObjectInspection.Catch
{
public partial class CatchObjectInspectorRuleset : DrawableCatchEditorRuleset
{
private readonly CatchDifficultyHitObject[] difficultyHitObjects;
private CatchObjectInspectorPlayfield inspectorPlayfield;

[Resolved]
private ObjectDifficultyValuesContainer difficultyValuesContainer { get; set; }

public CatchObjectInspectorRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList<Mod> mods, ExtendedCatchDifficultyCalculator difficultyCalculator, double clockRate)
: base(ruleset, beatmap, mods)
{
difficultyHitObjects = difficultyCalculator.GetDifficultyHitObjects(beatmap, clockRate)
.Cast<CatchDifficultyHitObject>().ToArray();
}

protected override void LoadComplete()
{
base.LoadComplete();

inspectorPlayfield.SelectedObject.BindValueChanged(value =>
{
difficultyValuesContainer.CurrentDifficultyHitObject.Value = difficultyHitObjects.FirstOrDefault(x => x.BaseObject.StartTime == value.NewValue?.HitObject.StartTime);
});
}

public override bool PropagatePositionalInputSubTree => true;

public override bool PropagateNonPositionalInputSubTree => false;

public override bool AllowBackwardsSeeks => true;

protected override Playfield CreatePlayfield() => inspectorPlayfield = new CatchObjectInspectorPlayfield(Beatmap.Difficulty);

private partial class CatchObjectInspectorPlayfield : CatchEditorPlayfield
{
public readonly Bindable<CatchSelectableHitObject?> SelectedObject = new Bindable<CatchSelectableHitObject?>();

public CatchObjectInspectorPlayfield(IBeatmapDifficultyInfo difficulty)
: base(difficulty)
{
DisplayJudgements.Value = false;
}

protected override void OnHitObjectAdded(HitObject hitObject)
{
base.OnHitObjectAdded(hitObject);

// Potential room for pooling here?
switch (hitObject)
{
case Fruit fruit:
{
HitObjectContainer.Add(new CatchSelectableHitObject(fruit)
{
PlayfieldSelectedObject = { BindTarget = SelectedObject }
});

break;
}

case JuiceStream juiceStream:
{
foreach (var nested in juiceStream.NestedHitObjects)
{
if (nested is TinyDroplet)
continue;

HitObjectContainer.Add(new CatchSelectableHitObject((CatchHitObject)nested)
{
PlayfieldSelectedObject = { BindTarget = SelectedObject }
});
}

break;
}
}
}

protected override GameplayCursorContainer CreateCursor() => null!;

protected override bool OnClick(ClickEvent e)
{
if (e.Button == MouseButton.Left)
{
SelectedObject.Value?.Deselect();
SelectedObject.Value = null;
}

return false;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// Copyright (c) ppy Pty Ltd <[email protected]>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

#nullable enable

using osu.Framework.Allocation;
using osu.Game.Rulesets.Catch.Objects.Drawables;
using osu.Game.Rulesets.Catch.Objects;
using osuTK;
using osu.Game.Graphics.UserInterface;
using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components;
using osu.Framework.Input.Events;
using osuTK.Input;
using osu.Framework.Bindables;

namespace PerformanceCalculatorGUI.Screens.ObjectInspection.Catch
{
public partial class CatchSelectableHitObject : DrawableCatchHitObject
{
// This is HitCirclePiece instead of FruitOutline because FruitOutline doesn't register input for some reason
private HitCirclePiece outline = null!;
private SelectionState state;

public readonly Bindable<CatchSelectableHitObject?> PlayfieldSelectedObject = new Bindable<CatchSelectableHitObject?>();

public CatchSelectableHitObject(CatchHitObject hitObject)
: base(hitObject)
{
X = hitObject.EffectiveX;
state = SelectionState.NotSelected;
}

[BackgroundDependencyLoader]
private void load()
{
AddInternal(outline = new HitCirclePiece
{
Alpha = 0,
Scale = HitObject is Droplet ? new Vector2(HitObject.Scale) * 0.5f : new Vector2(HitObject.Scale)
});

PlayfieldSelectedObject.BindValueChanged(x =>
{
if (x.NewValue != this)
{
Deselect();
}
});
}

protected override bool OnClick(ClickEvent e)
{
if (e.Button != MouseButton.Left)
return false;

if (!IsHovered)
return false;

if (state == SelectionState.Selected)
{
Deselect();
PlayfieldSelectedObject.Value = null;

return true;
}

state = SelectionState.Selected;
outline.Show();
PlayfieldSelectedObject.Value = this;

return true;
}

public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => outline.ReceivePositionalInputAt(screenSpacePos);

public override bool HandlePositionalInput => ShouldBeAlive || IsPresent;

public void Deselect()
{
if (IsLoaded)
{
state = SelectionState.NotSelected;
outline.Hide();
}
}
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ private void updateValues(DifficultyHitObject hitObject)
}

hitObjectTypeText.Text = hitObject.BaseObject.GetType().Name;
flowContainer.Add(new ObjectInspectorDifficultyValue("Start Time", hitObject.StartTime));

switch (hitObject)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
using osu.Game.Screens.Edit.Components;
using osu.Game.Screens.Edit.Components.Timelines.Summary;
using osuTK.Input;
using PerformanceCalculatorGUI.Screens.ObjectInspection.Catch;
using PerformanceCalculatorGUI.Screens.ObjectInspection.Osu;
using PerformanceCalculatorGUI.Screens.ObjectInspection.Taiko;

namespace PerformanceCalculatorGUI.Screens.ObjectInspection
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,33 +12,35 @@
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Osu.Difficulty.Preprocessing;
using osu.Game.Rulesets.Osu.Edit;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.Objects.Drawables;
using osu.Game.Rulesets.Osu.UI;
using osu.Game.Rulesets.UI;

namespace PerformanceCalculatorGUI.Screens.ObjectInspection
namespace PerformanceCalculatorGUI.Screens.ObjectInspection.Osu
{
public partial class OsuObjectInspectorRuleset : DrawableOsuEditorRuleset
{
private readonly OsuDifficultyHitObject[] difficultyHitObjects;

[Resolved]
private ObjectDifficultyValuesContainer objectDifficultyValuesContainer { get; set; }
private ObjectDifficultyValuesContainer difficultyValuesContainer { get; set; }

public OsuObjectInspectorRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList<Mod> mods, ExtendedOsuDifficultyCalculator difficultyCalculator, double clockRate)
: base(ruleset, beatmap, mods)
{
difficultyHitObjects = difficultyCalculator.GetDifficultyHitObjects(beatmap, clockRate).Cast<OsuDifficultyHitObject>().ToArray();
}

protected override void Update()
protected override void LoadComplete()
{
base.Update();
objectDifficultyValuesContainer.CurrentDifficultyHitObject.Value = difficultyHitObjects.LastOrDefault(x => x.StartTime <= Clock.CurrentTime);
base.LoadComplete();
KeyBindingInputManager.AllowGameplayInputs = false;
((OsuObjectInspectorPlayfield)Playfield).Pool.SelectedObject.BindValueChanged(value =>
difficultyValuesContainer.CurrentDifficultyHitObject.Value = difficultyHitObjects.FirstOrDefault(x => x.BaseObject == value.NewValue));
}

public override bool PropagatePositionalInputSubTree => false;

public override bool PropagatePositionalInputSubTree => true;
public override bool PropagateNonPositionalInputSubTree => false;

public override bool AllowBackwardsSeeks => true;
Expand All @@ -48,15 +50,42 @@ protected override void Update()
private partial class OsuObjectInspectorPlayfield : OsuPlayfield
{
private readonly IReadOnlyList<OsuDifficultyHitObject> difficultyHitObjects;
protected override GameplayCursorContainer CreateCursor() => null;

public OsuSelectableObjectPool Pool { get; private set; }

public OsuObjectInspectorPlayfield(IReadOnlyList<OsuDifficultyHitObject> difficultyHitObjects)
{
this.difficultyHitObjects = difficultyHitObjects;
}

[BackgroundDependencyLoader]
private void load()
{
AddInternal(Pool = new OsuSelectableObjectPool { RelativeSizeAxes = Axes.Both });
HitPolicy = new AnyOrderHitPolicy();
DisplayJudgements.Value = false;
}

protected override GameplayCursorContainer CreateCursor() => null;

protected override void OnHitObjectAdded(HitObject hitObject)
{
base.OnHitObjectAdded(hitObject);

if (hitObject is Spinner) return;

Pool.AddSelectableObject((OsuHitObject)hitObject);
}

protected override void OnHitObjectRemoved(HitObject hitObject)
{
base.OnHitObjectRemoved(hitObject);

if (hitObject is Spinner) return;

Pool.RemoveSelectableObject((OsuHitObject)hitObject);
}

protected override void OnNewDrawableHitObject(DrawableHitObject d)
{
base.OnNewDrawableHitObject(d);
Expand Down
Loading
Loading