mirror of
https://github.com/ppy/osu-tools.git
synced 2025-06-09 09:35:15 +09:00
Refactor difficulty values container into using Bindable<DifficultyHitObject>
This commit is contained in:
parent
7ebc7a55f3
commit
c360777ab0
5 changed files with 135 additions and 312 deletions
|
@ -4,7 +4,6 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
|
@ -14,7 +13,6 @@ using osu.Game.Rulesets;
|
|||
using osu.Game.Rulesets.Catch.Difficulty.Preprocessing;
|
||||
using osu.Game.Rulesets.Catch.Edit;
|
||||
using osu.Game.Rulesets.Catch.UI;
|
||||
using osu.Game.Rulesets.Difficulty.Preprocessing;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.UI;
|
||||
|
||||
|
@ -25,20 +23,13 @@ namespace PerformanceCalculatorGUI.Screens.ObjectInspection
|
|||
private readonly CatchDifficultyHitObject[] difficultyHitObjects;
|
||||
|
||||
[Resolved]
|
||||
private ObjectDifficultyValuesContainer debugValueList { get; set; }
|
||||
private ObjectDifficultyValuesContainer objectDifficultyValuesContainer { get; set; }
|
||||
|
||||
private DifficultyHitObject lasthit;
|
||||
|
||||
private Bindable<DifficultyHitObject> focusedDiffHitBind;
|
||||
|
||||
public CatchObjectInspectorRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList<Mod> mods, ExtendedCatchDifficultyCalculator difficultyCalculator, double clockRate,
|
||||
Bindable<DifficultyHitObject> diffHitBind)
|
||||
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();
|
||||
focusedDiffHitBind = diffHitBind;
|
||||
focusedDiffHitBind.ValueChanged += (ValueChangedEvent<DifficultyHitObject> newHit) => UpdateDebugList(debugValueList, newHit.NewValue);
|
||||
}
|
||||
|
||||
public override bool PropagatePositionalInputSubTree => false;
|
||||
|
@ -50,32 +41,7 @@ namespace PerformanceCalculatorGUI.Screens.ObjectInspection
|
|||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
var hitList = difficultyHitObjects.Where(hit => hit.StartTime < Clock.CurrentTime);
|
||||
|
||||
if (hitList.Any() && hitList.Last() != lasthit)
|
||||
{
|
||||
lasthit = hitList.Last();
|
||||
focusedDiffHitBind.Value = lasthit;
|
||||
}
|
||||
|
||||
focusedDiffHitBind.Value = null;
|
||||
}
|
||||
|
||||
public void UpdateDebugList(ObjectDifficultyValuesContainer valueList, DifficultyHitObject curDiffHit)
|
||||
{
|
||||
if (curDiffHit == null) return;
|
||||
|
||||
CatchDifficultyHitObject catchDiffHit = (CatchDifficultyHitObject)curDiffHit;
|
||||
|
||||
string groupName = catchDiffHit.BaseObject.GetType().Name;
|
||||
valueList.AddGroup(groupName, new string[] { "Fruit", "Droplet" });
|
||||
|
||||
Dictionary<string, Dictionary<string, object>> infoDict = valueList.InfoDictionary.Value;
|
||||
infoDict[groupName] = new Dictionary<string, object>
|
||||
{
|
||||
{ "Strain Time", catchDiffHit.StrainTime },
|
||||
{ "Normalized Position", catchDiffHit.NormalizedPosition },
|
||||
};
|
||||
objectDifficultyValuesContainer.CurrentDifficultyHitObject.Value = difficultyHitObjects.LastOrDefault(x => x.StartTime < Clock.CurrentTime);
|
||||
}
|
||||
|
||||
private partial class CatchObjectInspectorPlayfield : CatchEditorPlayfield
|
||||
|
|
|
@ -8,31 +8,40 @@ using osu.Framework.Bindables;
|
|||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Catch;
|
||||
using osu.Game.Rulesets.Catch.Difficulty.Preprocessing;
|
||||
using osu.Game.Rulesets.Difficulty.Preprocessing;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Rulesets.Osu.Difficulty.Evaluators;
|
||||
using osu.Game.Rulesets.Osu.Difficulty.Preprocessing;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Taiko;
|
||||
using osu.Game.Rulesets.Taiko.Difficulty.Preprocessing;
|
||||
using osuTK;
|
||||
|
||||
namespace PerformanceCalculatorGUI.Screens.ObjectInspection
|
||||
{
|
||||
public partial class ObjectDifficultyValuesContainer : Container
|
||||
{
|
||||
public Bindable<Dictionary<string, Dictionary<string, object>>> InfoDictionary;
|
||||
[Resolved]
|
||||
private Bindable<RulesetInfo> ruleset { get; set; }
|
||||
|
||||
private readonly Dictionary<string, Dictionary<string, object>> infoDictionary;
|
||||
|
||||
private Box bgBox;
|
||||
private TextFlowContainer flowContainer;
|
||||
private Bindable<DifficultyHitObject> focusedDiffHit = new();
|
||||
|
||||
public ObjectDifficultyValuesContainer(Bindable<DifficultyHitObject> diffHitBind)
|
||||
public Bindable<DifficultyHitObject> CurrentDifficultyHitObject { get; } = new();
|
||||
|
||||
public ObjectDifficultyValuesContainer()
|
||||
{
|
||||
focusedDiffHit.BindTo(diffHitBind);
|
||||
focusedDiffHit.ValueChanged += (ValueChangedEvent<DifficultyHitObject> _) => UpdateValues();
|
||||
CurrentDifficultyHitObject.ValueChanged += h => updateValues(h.NewValue);
|
||||
|
||||
InfoDictionary = new Bindable<Dictionary<string, Dictionary<string, object>>>
|
||||
{
|
||||
Value = new Dictionary<string, Dictionary<string, object>>()
|
||||
};
|
||||
infoDictionary = new Dictionary<string, Dictionary<string, object>>();
|
||||
RelativeSizeAxes = Axes.Y;
|
||||
Width = 215;
|
||||
}
|
||||
|
@ -42,17 +51,17 @@ namespace PerformanceCalculatorGUI.Screens.ObjectInspection
|
|||
{
|
||||
Children = new Drawable[]
|
||||
{
|
||||
bgBox = new Box
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = colors.Background5,
|
||||
Alpha = 0.95f,
|
||||
},
|
||||
new OsuScrollContainer()
|
||||
new OsuScrollContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
ScrollbarAnchor = Anchor.TopLeft,
|
||||
Child = flowContainer = new TextFlowContainer()
|
||||
Child = flowContainer = new TextFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Masking = false,
|
||||
|
@ -63,16 +72,101 @@ namespace PerformanceCalculatorGUI.Screens.ObjectInspection
|
|||
};
|
||||
}
|
||||
|
||||
public void UpdateValues()
|
||||
private void updateValues(DifficultyHitObject hitObject)
|
||||
{
|
||||
if (hitObject == null)
|
||||
{
|
||||
flowContainer.Text = "";
|
||||
return;
|
||||
}
|
||||
|
||||
switch (ruleset.Value.ShortName)
|
||||
{
|
||||
case OsuRuleset.SHORT_NAME:
|
||||
{
|
||||
drawOsuValues(hitObject as OsuDifficultyHitObject);
|
||||
break;
|
||||
}
|
||||
|
||||
case TaikoRuleset.SHORT_NAME:
|
||||
{
|
||||
drawTaikoValues(hitObject as TaikoDifficultyHitObject);
|
||||
break;
|
||||
}
|
||||
|
||||
case CatchRuleset.SHORT_NAME:
|
||||
{
|
||||
drawCatchValues(hitObject as CatchDifficultyHitObject);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void drawOsuValues(OsuDifficultyHitObject hitObject)
|
||||
{
|
||||
var groupName = hitObject.BaseObject.GetType().Name;
|
||||
addGroup(groupName, new[] { "Slider", "HitCircle", "Spinner" });
|
||||
infoDictionary[groupName] = new Dictionary<string, object>
|
||||
{
|
||||
{ "Position", (hitObject.BaseObject as OsuHitObject)!.StackedPosition },
|
||||
{ "Strain Time", hitObject.StrainTime },
|
||||
{ "Aim Difficulty", AimEvaluator.EvaluateDifficultyOf(hitObject, true) },
|
||||
{ "Speed Difficulty", SpeedEvaluator.EvaluateDifficultyOf(hitObject) },
|
||||
{ "Rhythm Diff", SpeedEvaluator.EvaluateDifficultyOf(hitObject) },
|
||||
{ "Flashlight Diff", SpeedEvaluator.EvaluateDifficultyOf(hitObject) },
|
||||
};
|
||||
|
||||
if (hitObject.Angle is not null)
|
||||
infoDictionary[groupName].Add("Angle", MathUtils.RadiansToDegrees(hitObject.Angle.Value));
|
||||
|
||||
if (hitObject.BaseObject is Slider)
|
||||
{
|
||||
infoDictionary[groupName].Add("FL Travel Time", FlashlightEvaluator.EvaluateDifficultyOf(hitObject, false));
|
||||
infoDictionary[groupName].Add("Travel Time", hitObject.TravelTime);
|
||||
infoDictionary[groupName].Add("Travel Distance", hitObject.TravelDistance);
|
||||
infoDictionary[groupName].Add("Min Jump Dist", hitObject.MinimumJumpDistance);
|
||||
infoDictionary[groupName].Add("Min Jump Time", hitObject.MinimumJumpTime);
|
||||
}
|
||||
|
||||
redrawValues();
|
||||
}
|
||||
|
||||
private void drawTaikoValues(TaikoDifficultyHitObject hitObject)
|
||||
{
|
||||
var groupName = hitObject.BaseObject.GetType().Name;
|
||||
addGroup(groupName, new[] { "Hit", "Swell", "DrumRoll" });
|
||||
infoDictionary[groupName] = new Dictionary<string, object>
|
||||
{
|
||||
{ "Delta Time", hitObject.DeltaTime },
|
||||
{ "Rhythm Difficulty", hitObject.Rhythm.Difficulty },
|
||||
{ "Rhythm Ratio", hitObject.Rhythm.Ratio }
|
||||
};
|
||||
|
||||
redrawValues();
|
||||
}
|
||||
|
||||
private void drawCatchValues(CatchDifficultyHitObject hitObject)
|
||||
{
|
||||
var groupName = hitObject.BaseObject.GetType().Name;
|
||||
addGroup(groupName, new[] { "Fruit", "Droplet" });
|
||||
infoDictionary[groupName] = new Dictionary<string, object>
|
||||
{
|
||||
{ "Strain Time", hitObject.StrainTime },
|
||||
{ "Normalized Position", hitObject.NormalizedPosition },
|
||||
};
|
||||
|
||||
redrawValues();
|
||||
}
|
||||
|
||||
private void redrawValues()
|
||||
{
|
||||
flowContainer.Text = "";
|
||||
|
||||
foreach (KeyValuePair<string, Dictionary<string, object>> GroupPair in InfoDictionary.Value)
|
||||
foreach (KeyValuePair<string, Dictionary<string, object>> groupPair in infoDictionary)
|
||||
{
|
||||
// Big text
|
||||
string groupName = GroupPair.Key;
|
||||
Dictionary<string, object> groupDict = GroupPair.Value;
|
||||
flowContainer.AddText($"- {GroupPair.Key}\n", t =>
|
||||
Dictionary<string, object> groupDict = groupPair.Value;
|
||||
flowContainer.AddText($"- {groupPair.Key}\n", t =>
|
||||
{
|
||||
t.Font = OsuFont.Torus.With(size: 28, weight: "Bold");
|
||||
t.Colour = Colour4.Pink;
|
||||
|
@ -117,53 +211,16 @@ namespace PerformanceCalculatorGUI.Screens.ObjectInspection
|
|||
}
|
||||
}
|
||||
|
||||
public void AddGroup(string name, string[] overrides = null)
|
||||
private void addGroup(string name, string[] overrides = null)
|
||||
{
|
||||
overrides ??= Array.Empty<string>();
|
||||
|
||||
foreach (string other in overrides)
|
||||
{
|
||||
InfoDictionary.Value.Remove(other);
|
||||
infoDictionary.Remove(other);
|
||||
}
|
||||
|
||||
InfoDictionary.Value[name] = new Dictionary<string, object>();
|
||||
}
|
||||
|
||||
public bool GroupExists(string name)
|
||||
{
|
||||
return InfoDictionary.Value.ContainsKey(name);
|
||||
}
|
||||
|
||||
public void SetValue(string group, string name, object value)
|
||||
{
|
||||
InfoDictionary.Value.TryGetValue(group, out var exists);
|
||||
|
||||
if (exists == null)
|
||||
{
|
||||
AddGroup(group);
|
||||
}
|
||||
|
||||
if (value is double val)
|
||||
{
|
||||
value = Math.Truncate(val * 1000) / 1000;
|
||||
}
|
||||
|
||||
if (value is float val2)
|
||||
{
|
||||
value = Math.Truncate(val2 * 1000) / 1000;
|
||||
}
|
||||
|
||||
if (value is Vector2 val3)
|
||||
{
|
||||
value = new Vector2((float)(Math.Truncate(val3.X * 100) / 100), (float)Math.Truncate(val3.Y * 100) / 100);
|
||||
}
|
||||
|
||||
InfoDictionary.Value[group][name] = value;
|
||||
}
|
||||
|
||||
public object GetValue(string group, string name)
|
||||
{
|
||||
return InfoDictionary.Value[group][name];
|
||||
infoDictionary[name] = new Dictionary<string, object>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@ using osu.Game.Overlays;
|
|||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Catch.UI;
|
||||
using osu.Game.Rulesets.Difficulty;
|
||||
using osu.Game.Rulesets.Difficulty.Preprocessing;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu.UI;
|
||||
using osu.Game.Rulesets.Taiko.UI;
|
||||
|
@ -54,9 +53,7 @@ namespace PerformanceCalculatorGUI.Screens.ObjectInspection
|
|||
private EditorClock clock;
|
||||
private Container inspectContainer;
|
||||
|
||||
private ObjectDifficultyValuesContainer values;
|
||||
|
||||
private Bindable<DifficultyHitObject> focusedDiffHitBind;
|
||||
private ObjectDifficultyValuesContainer difficultyValuesContainer;
|
||||
|
||||
protected override bool BlockNonPositionalInput => true;
|
||||
|
||||
|
@ -88,7 +85,6 @@ namespace PerformanceCalculatorGUI.Screens.ObjectInspection
|
|||
dependencies.CacheAs(editorBeatmap);
|
||||
|
||||
beatmap.Value = processorBeatmap;
|
||||
focusedDiffHitBind = new Bindable<DifficultyHitObject>();
|
||||
|
||||
// Background
|
||||
AddRange(new Drawable[]
|
||||
|
@ -132,9 +128,9 @@ namespace PerformanceCalculatorGUI.Screens.ObjectInspection
|
|||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
values = new ObjectDifficultyValuesContainer(focusedDiffHitBind)
|
||||
difficultyValuesContainer = new ObjectDifficultyValuesContainer
|
||||
{
|
||||
Padding = new MarginPadding { Bottom = 5 },
|
||||
Padding = new MarginPadding { Bottom = 5 }
|
||||
},
|
||||
|
||||
new Container
|
||||
|
@ -176,7 +172,7 @@ namespace PerformanceCalculatorGUI.Screens.ObjectInspection
|
|||
}
|
||||
});
|
||||
|
||||
dependencies.CacheAs(values);
|
||||
dependencies.CacheAs(difficultyValuesContainer);
|
||||
|
||||
inspectContainer.Add(ruleset.Value.ShortName switch
|
||||
{
|
||||
|
@ -192,7 +188,7 @@ namespace PerformanceCalculatorGUI.Screens.ObjectInspection
|
|||
PlayfieldBorderStyle = { Value = PlayfieldBorderStyle.Corners }
|
||||
},
|
||||
new OsuObjectInspectorRuleset(rulesetInstance, playableBeatmap, modifiedMods, difficultyCalculator.Value as ExtendedOsuDifficultyCalculator,
|
||||
processorBeatmap.Track.Rate, focusedDiffHitBind)
|
||||
processorBeatmap.Track.Rate)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Clock = clock,
|
||||
|
@ -205,7 +201,7 @@ namespace PerformanceCalculatorGUI.Screens.ObjectInspection
|
|||
RelativeSizeAxes = Axes.Both,
|
||||
Margin = new MarginPadding(10) { Left = 0, Bottom = bottom_bar_height },
|
||||
Child = new TaikoObjectInspectorRuleset(rulesetInstance, playableBeatmap, modifiedMods, difficultyCalculator.Value as ExtendedTaikoDifficultyCalculator,
|
||||
processorBeatmap.Track.Rate, focusedDiffHitBind)
|
||||
processorBeatmap.Track.Rate)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Clock = clock,
|
||||
|
@ -220,7 +216,7 @@ namespace PerformanceCalculatorGUI.Screens.ObjectInspection
|
|||
Children = new Drawable[]
|
||||
{
|
||||
new CatchObjectInspectorRuleset(rulesetInstance, playableBeatmap, modifiedMods, difficultyCalculator.Value as ExtendedCatchDifficultyCalculator,
|
||||
processorBeatmap.Track.Rate, focusedDiffHitBind)
|
||||
processorBeatmap.Track.Rate)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Clock = clock,
|
||||
|
|
|
@ -4,19 +4,10 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Difficulty.Preprocessing;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Osu.Difficulty.Evaluators;
|
||||
using osu.Game.Rulesets.Osu.Difficulty.Preprocessing;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Osu.UI;
|
||||
using osu.Game.Rulesets.UI;
|
||||
|
||||
|
@ -27,144 +18,35 @@ namespace PerformanceCalculatorGUI.Screens.ObjectInspection
|
|||
private readonly OsuDifficultyHitObject[] difficultyHitObjects;
|
||||
|
||||
[Resolved]
|
||||
private ObjectDifficultyValuesContainer debugValueList { get; set; }
|
||||
private ObjectDifficultyValuesContainer objectDifficultyValuesContainer { get; set; }
|
||||
|
||||
private DifficultyHitObject lasthit;
|
||||
|
||||
private Bindable<DifficultyHitObject> focusedDiffHitBind;
|
||||
|
||||
public OsuObjectInspectorRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList<Mod> mods, ExtendedOsuDifficultyCalculator difficultyCalculator, double clockRate,
|
||||
Bindable<DifficultyHitObject> diffHitBind)
|
||||
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();
|
||||
focusedDiffHitBind = diffHitBind;
|
||||
focusedDiffHitBind.ValueChanged += (ValueChangedEvent<DifficultyHitObject> newHit) => UpdateDebugList(debugValueList, newHit.NewValue);
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
var hitList = difficultyHitObjects.Where(hit => hit.StartTime < Clock.CurrentTime);
|
||||
|
||||
if (hitList.Any() && hitList.Last() != lasthit)
|
||||
{
|
||||
lasthit = hitList.Last();
|
||||
focusedDiffHitBind.Value = lasthit;
|
||||
}
|
||||
|
||||
focusedDiffHitBind.Value = null;
|
||||
objectDifficultyValuesContainer.CurrentDifficultyHitObject.Value = difficultyHitObjects.LastOrDefault(x => x.StartTime < Clock.CurrentTime);
|
||||
}
|
||||
|
||||
public override bool PropagatePositionalInputSubTree => false;
|
||||
|
||||
public override bool PropagateNonPositionalInputSubTree => false;
|
||||
|
||||
protected override Playfield CreatePlayfield() => new OsuObjectInspectorPlayfield(difficultyHitObjects);
|
||||
|
||||
public void UpdateDebugList(ObjectDifficultyValuesContainer valueList, DifficultyHitObject curDiffHit)
|
||||
{
|
||||
if (curDiffHit == null) return;
|
||||
|
||||
OsuDifficultyHitObject osuDiffHit = (OsuDifficultyHitObject)curDiffHit;
|
||||
OsuHitObject baseHit = (OsuHitObject)osuDiffHit.BaseObject;
|
||||
|
||||
string groupName = osuDiffHit.BaseObject.GetType().Name;
|
||||
Dictionary<string, Dictionary<string, object>> infoDict = valueList.InfoDictionary.Value;
|
||||
|
||||
valueList.AddGroup(groupName, new string[] { "Slider", "HitCircle", "Spinner" });
|
||||
infoDict[groupName] = new Dictionary<string, object>
|
||||
{
|
||||
{ "Position", baseHit.StackedPosition },
|
||||
{ "Strain Time", osuDiffHit.StrainTime },
|
||||
{ "Aim Difficulty", AimEvaluator.EvaluateDifficultyOf(osuDiffHit, true) },
|
||||
{ "Speed Difficulty", SpeedEvaluator.EvaluateDifficultyOf(osuDiffHit) },
|
||||
{ "Rhythm Diff", SpeedEvaluator.EvaluateDifficultyOf(osuDiffHit) },
|
||||
{ "Flashlight Diff", SpeedEvaluator.EvaluateDifficultyOf(osuDiffHit) },
|
||||
};
|
||||
|
||||
if (osuDiffHit.Angle is not null)
|
||||
infoDict[groupName].Add("Angle", MathUtils.RadiansToDegrees(osuDiffHit.Angle.Value));
|
||||
|
||||
if (osuDiffHit.BaseObject is Slider)
|
||||
{
|
||||
infoDict[groupName].Add("FL Travel Time", FlashlightEvaluator.EvaluateDifficultyOf(osuDiffHit, false));
|
||||
infoDict[groupName].Add("Travel Time", osuDiffHit.TravelTime);
|
||||
infoDict[groupName].Add("Travel Distance", osuDiffHit.TravelDistance);
|
||||
infoDict[groupName].Add("Min Jump Dist", osuDiffHit.MinimumJumpDistance);
|
||||
infoDict[groupName].Add("Min Jump Time", osuDiffHit.MinimumJumpTime);
|
||||
}
|
||||
}
|
||||
protected override Playfield CreatePlayfield() => new OsuObjectInspectorPlayfield();
|
||||
|
||||
private partial class OsuObjectInspectorPlayfield : OsuPlayfield
|
||||
{
|
||||
private readonly IReadOnlyList<OsuDifficultyHitObject> difficultyHitObjects;
|
||||
|
||||
protected override GameplayCursorContainer CreateCursor() => null;
|
||||
|
||||
public OsuObjectInspectorPlayfield(IReadOnlyList<OsuDifficultyHitObject> difficultyHitObjects)
|
||||
public OsuObjectInspectorPlayfield()
|
||||
{
|
||||
this.difficultyHitObjects = difficultyHitObjects;
|
||||
HitPolicy = new AnyOrderHitPolicy();
|
||||
DisplayJudgements.Value = false;
|
||||
}
|
||||
|
||||
protected override void OnHitObjectAdded(HitObject hitObject)
|
||||
{
|
||||
base.OnHitObjectAdded(hitObject);
|
||||
}
|
||||
|
||||
protected override void OnHitObjectRemoved(HitObject hitObject)
|
||||
{
|
||||
base.OnHitObjectRemoved(hitObject);
|
||||
}
|
||||
|
||||
protected override void OnNewDrawableHitObject(DrawableHitObject d)
|
||||
{
|
||||
d.ApplyCustomUpdateState += updateState;
|
||||
}
|
||||
|
||||
private void updateState(DrawableHitObject hitObject, ArmedState state)
|
||||
{
|
||||
if (state == ArmedState.Idle)
|
||||
return;
|
||||
|
||||
if (hitObject is DrawableHitCircle circle)
|
||||
{
|
||||
using (circle.BeginAbsoluteSequence(circle.HitStateUpdateTime))
|
||||
{
|
||||
circle.ApproachCircle
|
||||
.FadeOutFromOne()
|
||||
.Expire();
|
||||
|
||||
circle.ApproachCircle.ScaleTo(1.1f, 300, Easing.OutQuint);
|
||||
}
|
||||
}
|
||||
|
||||
if (hitObject is DrawableSliderRepeat repeat)
|
||||
{
|
||||
repeat.Arrow.ApplyTransformsAt(hitObject.StateUpdateTime, true);
|
||||
repeat.Arrow.ClearTransformsAfter(hitObject.StateUpdateTime, true);
|
||||
}
|
||||
|
||||
// adjust the visuals of top-level object types to make them stay on screen for longer than usual.
|
||||
switch (hitObject)
|
||||
{
|
||||
case DrawableSlider _:
|
||||
case DrawableHitCircle _:
|
||||
// Get the existing fade out transform
|
||||
var existing = hitObject.Transforms.LastOrDefault(t => t.TargetMember == nameof(Alpha));
|
||||
|
||||
if (existing == null)
|
||||
return;
|
||||
|
||||
hitObject.RemoveTransform(existing);
|
||||
|
||||
using (hitObject.BeginAbsoluteSequence(hitObject.HitStateUpdateTime))
|
||||
hitObject.FadeOut().Expire();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,17 +4,10 @@
|
|||
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.Difficulty.Preprocessing;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Taiko;
|
||||
using osu.Game.Rulesets.Taiko.Difficulty.Preprocessing;
|
||||
using osu.Game.Rulesets.Taiko.Objects;
|
||||
using osu.Game.Rulesets.Taiko.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Taiko.UI;
|
||||
using osu.Game.Rulesets.UI;
|
||||
|
||||
|
@ -25,106 +18,35 @@ namespace PerformanceCalculatorGUI.Screens.ObjectInspection
|
|||
private readonly TaikoDifficultyHitObject[] difficultyHitObjects;
|
||||
|
||||
[Resolved]
|
||||
private ObjectDifficultyValuesContainer debugValueList { get; set; }
|
||||
private ObjectDifficultyValuesContainer objectDifficultyValuesContainer { get; set; }
|
||||
|
||||
private DifficultyHitObject lasthit;
|
||||
|
||||
private Bindable<DifficultyHitObject> focusedDiffHitBind;
|
||||
|
||||
public TaikoObjectInspectorRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList<Mod> mods, ExtendedTaikoDifficultyCalculator difficultyCalculator, double clockRate,
|
||||
Bindable<DifficultyHitObject> diffHitBind)
|
||||
public TaikoObjectInspectorRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList<Mod> mods, ExtendedTaikoDifficultyCalculator difficultyCalculator, double clockRate)
|
||||
: base(ruleset, beatmap, mods)
|
||||
{
|
||||
difficultyHitObjects = difficultyCalculator.GetDifficultyHitObjects(beatmap, clockRate)
|
||||
.Cast<TaikoDifficultyHitObject>().ToArray();
|
||||
focusedDiffHitBind = diffHitBind;
|
||||
focusedDiffHitBind.ValueChanged += (ValueChangedEvent<DifficultyHitObject> newHit) => UpdateDebugList(debugValueList, newHit.NewValue);
|
||||
}
|
||||
|
||||
public override bool PropagatePositionalInputSubTree => false;
|
||||
|
||||
public override bool PropagateNonPositionalInputSubTree => false;
|
||||
|
||||
protected override Playfield CreatePlayfield() => new TaikoObjectInspectorPlayfield(difficultyHitObjects);
|
||||
protected override Playfield CreatePlayfield() => new TaikoObjectInspectorPlayfield();
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
var hitList = difficultyHitObjects.Where(hit => hit.StartTime < Clock.CurrentTime);
|
||||
|
||||
if (hitList.Any() && hitList.Last() != lasthit)
|
||||
{
|
||||
lasthit = hitList.Last();
|
||||
focusedDiffHitBind.Value = lasthit;
|
||||
}
|
||||
|
||||
focusedDiffHitBind.Value = null;
|
||||
}
|
||||
|
||||
protected void UpdateDebugList(ObjectDifficultyValuesContainer valueList, DifficultyHitObject curDiffHit)
|
||||
{
|
||||
if (curDiffHit == null) return;
|
||||
|
||||
TaikoDifficultyHitObject taikoDiffHit = (TaikoDifficultyHitObject)curDiffHit;
|
||||
|
||||
string groupName = taikoDiffHit.BaseObject.GetType().Name;
|
||||
valueList.AddGroup(groupName, new string[] { "Hit", "Swell", "DrumRoll" });
|
||||
|
||||
Dictionary<string, Dictionary<string, object>> infoDict = valueList.InfoDictionary.Value;
|
||||
infoDict[groupName] = new Dictionary<string, object>
|
||||
{
|
||||
{ "Delta Time", taikoDiffHit.DeltaTime },
|
||||
{ "Rhythm Difficulty", taikoDiffHit.Rhythm.Difficulty },
|
||||
{ "Rhythm Ratio", taikoDiffHit.Rhythm.Ratio }
|
||||
};
|
||||
objectDifficultyValuesContainer.CurrentDifficultyHitObject.Value = difficultyHitObjects.LastOrDefault(x => x.StartTime < Clock.CurrentTime);
|
||||
}
|
||||
|
||||
private partial class TaikoObjectInspectorPlayfield : TaikoPlayfield
|
||||
{
|
||||
private readonly IReadOnlyList<TaikoDifficultyHitObject> difficultyHitObjects;
|
||||
|
||||
protected override GameplayCursorContainer CreateCursor() => null;
|
||||
|
||||
public TaikoObjectInspectorPlayfield(IReadOnlyList<TaikoDifficultyHitObject> difficultyHitObjects)
|
||||
public TaikoObjectInspectorPlayfield()
|
||||
{
|
||||
this.difficultyHitObjects = difficultyHitObjects;
|
||||
DisplayJudgements.Value = false;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
foreach (var dho in difficultyHitObjects)
|
||||
{
|
||||
HitObjectContainer.Add(new TaikoInspectorDrawableHitObject(dho));
|
||||
}
|
||||
}
|
||||
|
||||
private partial class TaikoInspectorDrawableHitObject : DrawableTaikoHitObject
|
||||
{
|
||||
private readonly TaikoDifficultyHitObject dho;
|
||||
|
||||
public TaikoInspectorDrawableHitObject(TaikoDifficultyHitObject dho)
|
||||
: base(new TaikoInspectorHitObject(dho.BaseObject))
|
||||
{
|
||||
this.dho = dho;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
}
|
||||
|
||||
public override bool OnPressed(KeyBindingPressEvent<TaikoAction> e) => true;
|
||||
|
||||
private class TaikoInspectorHitObject : TaikoHitObject
|
||||
{
|
||||
public TaikoInspectorHitObject(HitObject obj)
|
||||
{
|
||||
StartTime = obj.StartTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue