1
0
Fork 0
mirror of https://github.com/ppy/osu-tools.git synced 2025-06-08 07:17:01 +09:00
osu-tools/PerformanceCalculatorGUI/Screens/ObjectInspection/ObjectInspector.cs
2023-01-10 17:36:22 -05:00

321 lines
12 KiB
C#

// 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.
using System.Collections.Generic;
using System.Linq;
using osu.Framework;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Input.Events;
using osu.Game.Beatmaps;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
using osu.Game.Overlays;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Catch.UI;
using osu.Game.Rulesets.Difficulty;
using osu.Game.Rulesets.Difficulty.Skills;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu.UI;
using osu.Game.Rulesets.Taiko.UI;
using osu.Game.Rulesets.UI;
using osu.Game.Screens.Edit;
using osu.Game.Screens.Edit.Components;
using osu.Game.Screens.Edit.Components.Timelines.Summary;
using osu.Game.Screens.Menu;
using osuTK.Graphics.ES31;
using osuTK.Input;
using SharpGen.Runtime.Win32;
using osu.Game.Rulesets.Difficulty.Preprocessing;
using FFmpeg.AutoGen;
using System;
using osu.Framework.Timing;
namespace PerformanceCalculatorGUI.Screens.ObjectInspection
{
public partial class ObjectInspector : OsuFocusedOverlayContainer
{
private DependencyContainer dependencies;
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
=> dependencies = new DependencyContainer(base.CreateChildDependencies(parent));
[Cached]
private BindableBeatDivisor beatDivisor = new();
[Resolved]
private Bindable<WorkingBeatmap> beatmap { get; set; }
[Resolved]
private Bindable<IReadOnlyList<Mod>> mods { get; set; }
[Resolved]
private Bindable<RulesetInfo> ruleset { get; set; }
[Resolved]
private Bindable<DifficultyCalculator> difficultyCalculator { get; set; }
private readonly ProcessorWorkingBeatmap processorBeatmap;
private EditorClock clock;
private Container inspectContainer;
private DebugValueList values;
protected override bool BlockNonPositionalInput => true;
protected override bool DimMainContent => false;
private const int bottom_bar_height = 50;
private const int side_bar_width = 215;
public ObjectInspector(ProcessorWorkingBeatmap working)
{
processorBeatmap = working;
}
[BackgroundDependencyLoader]
private void load(OverlayColourProvider colourProvider)
{
var rulesetInstance = ruleset.Value.CreateInstance();
var modifiedMods = mods.Value.Append(rulesetInstance.GetAutoplayMod()).ToList();
var playableBeatmap = processorBeatmap.GetPlayableBeatmap(ruleset.Value, modifiedMods);
processorBeatmap.LoadTrack();
clock = new EditorClock(playableBeatmap, beatDivisor);
clock.ChangeSource(processorBeatmap.Track);
dependencies.CacheAs(clock);
var editorBeatmap = new EditorBeatmap(playableBeatmap);
dependencies.CacheAs(editorBeatmap);
beatmap.Value = processorBeatmap;
// Background
AddInternal(new Container
{
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
CornerRadius = 15f,
RelativeSizeAxes = Axes.Both,
Children = new Drawable[] {
new Box
{
Colour = Colour4.Black,
Alpha = 0.95f,
RelativeSizeAxes = Axes.Both
},
}
});
// Object Inspector Container
AddInternal(inspectContainer = new Container
{
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
Masking = true,
CornerRadius = 15f,
Padding = new MarginPadding() { Left = side_bar_width , Right = 0},
RelativeSizeAxes = Axes.Both,
Child = clock,
});
// layout
AddInternal(new Container
{
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
Masking = true,
CornerRadius = 15f,
RelativeSizeAxes = Axes.Both,
Children = new Drawable[]
{
values = new DebugValueList() { Clock = clock },
new Container
{
Name = "Bottom bar",
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
RelativeSizeAxes = Axes.X,
Height = bottom_bar_height,
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = colourProvider.Background4,
},
new GridContainer
{
RelativeSizeAxes = Axes.Both,
ColumnDimensions = new[]
{
new Dimension(GridSizeMode.Absolute, 170),
new Dimension(),
new Dimension(GridSizeMode.Absolute, 220)
},
Content = new[]
{
new Drawable[]
{
new TimeInfoContainer { RelativeSizeAxes = Axes.Both },
new SummaryTimeline { RelativeSizeAxes = Axes.Both },
new PlaybackControl { RelativeSizeAxes = Axes.Both },
},
}
}
}
},
}
});
dependencies.CacheAs(values);
DrawableRuleset inspectorRuleset = null;
inspectContainer.Add(ruleset.Value.ShortName switch
{
"osu" => new OsuPlayfieldAdjustmentContainer
{
RelativeSizeAxes = Axes.Both,
Margin = new MarginPadding(10) { Bottom = bottom_bar_height },
Children = new Drawable[]
{
new PlayfieldBorder
{
RelativeSizeAxes = Axes.Both,
PlayfieldBorderStyle = { Value = PlayfieldBorderStyle.Corners }
},
inspectorRuleset = new OsuObjectInspectorRuleset(rulesetInstance, playableBeatmap, modifiedMods, difficultyCalculator.Value as ExtendedOsuDifficultyCalculator, processorBeatmap.Track.Rate)
{
RelativeSizeAxes = Axes.Both,
Clock = clock,
ProcessCustomClock = false
}
}
},
"taiko" => new TaikoPlayfieldAdjustmentContainer
{
RelativeSizeAxes = Axes.Both,
Margin = new MarginPadding(10) { Left = 0, Bottom = bottom_bar_height },
Child = inspectorRuleset = new TaikoObjectInspectorRuleset(rulesetInstance, playableBeatmap, modifiedMods, difficultyCalculator.Value as ExtendedTaikoDifficultyCalculator,
processorBeatmap.Track.Rate)
{
RelativeSizeAxes = Axes.Both,
Clock = clock,
ProcessCustomClock = false
}
},
"fruits" => new CatchPlayfieldAdjustmentContainer
{
RelativeSizeAxes = Axes.Both,
Margin = new MarginPadding(10) { Bottom = bottom_bar_height },
Y = 100,
Children = new Drawable[]
{
// guideline bar
new Container{
RelativeSizeAxes = Axes.X,
Height = 3,
Y = 300,
Colour = Colour4.Red,
Children = new Drawable[]{
// shadow
new Circle{Colour = Colour4.Gray, Size = new osuTK.Vector2(10), Y = -3.3f+2, X = -5 },
new Box{ Colour = Colour4.Gray,Size = new osuTK.Vector2(5,20), Y = -8.3f+2, X = 508 },
new Box { Colour = Colour4.Gray, RelativeSizeAxes = Axes.Both, Y = 2},
// main
new Circle{ Size = new osuTK.Vector2(10), Y = -3.3f, X = -5 },
new Box{ Size = new osuTK.Vector2(5,20), Y = -8.3f, X = 508 },
new Box { RelativeSizeAxes = Axes.Both },
}
},
inspectorRuleset = new CatchObjectInspectorRuleset(rulesetInstance, playableBeatmap, modifiedMods, difficultyCalculator.Value as ExtendedCatchDifficultyCalculator, processorBeatmap.Track.Rate)
{
RelativeSizeAxes = Axes.Both,
Clock = clock,
ProcessCustomClock = false
},
}
},
_ => new Container
{
RelativeSizeAxes = Axes.Both,
Child = new OsuSpriteText
{
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
Text = "This ruleset is not supported yet!"
}
}
});
ruleset.BindValueChanged(_ => PopOut());
beatmap.BindValueChanged(_ => PopOut());
}
public static DifficultyHitObject GetCurrentHit(Playfield field, DifficultyHitObject[] difficultyHitObjects, DifficultyHitObject lasthit, IFrameBasedClock clock)
{
var hitList = difficultyHitObjects.Where(hit => { return hit.StartTime < clock.CurrentTime; });
if (hitList.Any() && !(hitList.Last() == lasthit))
{
DifficultyHitObject curhit = hitList.Last();
return curhit;
}
return null;
}
protected override void Update()
{
base.Update();
clock.ProcessFrame();
}
protected override void PopIn()
{
base.PopIn();
this.FadeIn();
}
protected override void PopOut()
{
base.PopOut();
this.FadeOut();
}
protected override bool OnKeyDown(KeyDownEvent e)
{
if (e.Key == Key.Space)
{
if (clock.IsRunning)
clock.Stop();
else
clock.Start();
}
var amt = 0.25;
amt = e.ControlPressed ? amt * 2: amt;
amt = e.ShiftPressed ? amt * 0.5: amt;
if (e.Key == Key.Q)
{
clock.SeekBackward(amount: amt);
}
if (e.Key == Key.E)
{
clock.SeekForward(amount: amt);
}
return base.OnKeyDown(e);
}
}
}