1
0
mirror of https://github.com/ppy/osu.git synced 2024-11-11 10:33:30 +08:00

functionality is done

This commit is contained in:
Givikap120 2023-09-03 02:09:01 +03:00
parent 50235cc245
commit b0398b6259
8 changed files with 287 additions and 230 deletions

View File

@ -0,0 +1,29 @@
// 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;
namespace osu.Game.Beatmaps
{
public class BeatmapShortInfo : IEquatable<BeatmapShortInfo>
{
public StarDifficulty StarDifficulty;
public float CircleSize;
public float DrainRate;
public float ApproachRate;
public float OverallDifficulty;
public double BPM;
public bool Equals(BeatmapShortInfo? other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return StarDifficulty.Stars == other.StarDifficulty.Stars &&
CircleSize.Equals(other.CircleSize) &&
DrainRate.Equals(other.DrainRate) &&
ApproachRate.Equals(other.ApproachRate) &&
OverallDifficulty.Equals(other.OverallDifficulty) &&
BPM.Equals(other.BPM);
}
}
}

View File

@ -1,24 +1,21 @@
// 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.Linq;
#nullable disable
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Extensions.LocalisationExtensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Colour;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Localisation;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.Drawables;
using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
using osu.Game.Online;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests;
using osu.Game.Overlays.BeatmapSet;
using osu.Game.Resources.Localisation.Web;
using osu.Game.Screens.Select.Details;
using osuTK;
using osuTK.Graphics;
@ -26,33 +23,161 @@ namespace osu.Game.Overlays.Mods
{
public partial class ModMapInfoContainer : Container
{
private ModMapInfoDisplay starRatingDisplay = null!;
private Container content;
private Container innerContent;
private Box background;
private Box innerBackground;
private StarRatingDisplay starRatingDisplay;
private BPMDisplay bpmDisplay;
private VerticalAttributeDisplay circleSizeDisplay;
private VerticalAttributeDisplay drainRateDisplay;
private VerticalAttributeDisplay approachRateDisplay;
private VerticalAttributeDisplay overallDifficultyDisplay;
[Resolved]
private OsuColour colours { get; set; } = null!;
private OverlayColourProvider colourProvider { get; set; }
[Resolved]
private Bindable<BeatmapInfo> adjustedInfo { get; set; } = null!;
private Bindable<double> starRatingValue = new Bindable<double>();
private Bindable<BeatmapShortInfo> adjustedInfo { get; set; }
//public ModMapInfoContainer()
//{
//
//}
public ModMapInfoContainer()
{
// values as ModSelectOverlay footer buttons
const float shear = ShearedOverlayContainer.SHEAR;
const float corner_radius = 7;
const float border_thickness = 2;
InternalChild = content = new InputBlockingContainer
{
Origin = Anchor.BottomRight,
Anchor = Anchor.BottomRight,
AutoSizeAxes = Axes.X,
Height = 50, // as ModSelectOverlay footer buttons
Shear = new Vector2(shear, 0),
CornerRadius = corner_radius,
BorderThickness = border_thickness,
Masking = true,
Children = new Drawable[]
{
background = new Box
{
RelativeSizeAxes = Axes.Both
},
new FillFlowContainer // divide inner and outer content
{
Origin = Anchor.BottomLeft,
Anchor = Anchor.BottomLeft,
AutoSizeAxes = Axes.X,
RelativeSizeAxes = Axes.Y,
Direction = FillDirection.Horizontal,
Children = new Drawable[]
{
innerContent = new Container
{
AutoSizeAxes = Axes.X,
RelativeSizeAxes = Axes.Y,
BorderThickness = border_thickness,
CornerRadius = corner_radius,
Masking = true,
Children = new Drawable[]
{
innerBackground = new Box
{
RelativeSizeAxes = Axes.Both
},
new FillFlowContainer // actual inner content
{
Origin = Anchor.CentreLeft,
Anchor = Anchor.CentreLeft,
AutoSizeAxes = Axes.X,
Direction = FillDirection.Horizontal,
Margin = new MarginPadding { Horizontal = 15 },
Children = new Drawable[]
{
new Container // wrap to reserve space for StarRatingDisplay
{
Width = 70, // can be up to 70px on extra high SR
Child = starRatingDisplay = new StarRatingDisplay(default, animated: true)
{
Origin = Anchor.CentreLeft,
Anchor = Anchor.CentreLeft,
Shear = new Vector2(-shear, 0),
}
},
new Container // wrap to reserve space for BPM
{
Origin = Anchor.CentreLeft,
Anchor = Anchor.CentreLeft,
Width = 70,
Child = bpmDisplay = new BPMDisplay
{
Origin = Anchor.CentreLeft,
Anchor = Anchor.CentreLeft,
Shear = new Vector2(-shear, 0),
}
}
}
}
}
},
new FillFlowContainer<VerticalAttributeDisplay> // outer content
{
Origin = Anchor.CentreLeft,
Anchor = Anchor.CentreLeft,
AutoSizeAxes = Axes.X,
RelativeSizeAxes = Axes.Y,
Direction = FillDirection.Horizontal,
Children = new[]
{
circleSizeDisplay = new VerticalAttributeDisplay("CS"),
drainRateDisplay = new VerticalAttributeDisplay("HP"),
approachRateDisplay = new VerticalAttributeDisplay("AR"),
overallDifficultyDisplay = new VerticalAttributeDisplay("OD"),
}
}
}
}
}
};
}
protected override void LoadComplete()
{
starRatingDisplay = new ModMapInfoDisplay("Star Rating", colours.ForStarDifficulty);
starRatingDisplay.Current.BindTo(starRatingValue);
adjustedInfo.BindValueChanged(e => { UpdateValues(); }, true);
Content.Add(starRatingDisplay);
background.Colour = colourProvider.Background4;
innerBackground.Colour = colourProvider.Background3;
Color4 glow_colour = colourProvider.Background1;
adjustedInfo.BindValueChanged(e => { updateValues(); }, true);
content.BorderColour = ColourInfo.GradientVertical(background.Colour, glow_colour);
innerContent.BorderColour = ColourInfo.GradientVertical(innerBackground.Colour, glow_colour);
}
private void updateValues()
public void UpdateValues()
{
starRatingValue.Value = adjustedInfo.Value.StarRating;
if (adjustedInfo.Value == null) return;
starRatingDisplay.Current.Value = adjustedInfo.Value.StarDifficulty;
bpmDisplay.Current.Value = adjustedInfo.Value.BPM;
circleSizeDisplay.Current.Value = adjustedInfo.Value.CircleSize;
drainRateDisplay.Current.Value = adjustedInfo.Value.DrainRate;
approachRateDisplay.Current.Value = adjustedInfo.Value.ApproachRate;
overallDifficultyDisplay.Current.Value = adjustedInfo.Value.OverallDifficulty;
}
private partial class BPMDisplay : RollingCounter<double>
{
protected override double RollingDuration => 500;
protected override LocalisableString FormatCount(double count) => count.ToLocalisableString("0 BPM");
protected override OsuSpriteText CreateSpriteText() => new OsuSpriteText
{
Font = OsuFont.Default.With(size: 20, weight: FontWeight.SemiBold)
};
}
}
}

View File

@ -1,185 +0,0 @@
// 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;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Extensions.LocalisationExtensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.UserInterface;
using osu.Framework.Localisation;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
using osu.Game.Localisation;
using osuTK;
namespace osu.Game.Overlays.Mods
{
public partial class ModMapInfoDisplay : Container, IHasCurrentValue<double>
{
public const float HEIGHT = 42;
private const float transition_duration = 200;
private readonly Box contentBackground;
private readonly Box labelBackground;
private readonly FillFlowContainer content;
//public Bindable<double> Current
//{
// get => current.Current;
// set => current.Current = value;
//}
//private readonly BindableWithCurrent<double> current = new BindableWithCurrent<double>();
public Bindable<double> Current { get; set; } = new BindableWithCurrent<double>();
//[Resolved]
//private OsuColour colours { get; set; } = null!;
[Resolved]
private OverlayColourProvider colourProvider { get; set; } = null!;
protected Func<double, osuTK.Graphics.Color4> GetColor;
/// <summary>
/// Text to display in the left area of the display.
/// </summary>
protected LocalisableString Label;
protected virtual float ValueAreaWidth => 56;
protected virtual string CounterFormat => @"0.00";
protected override Container<Drawable> Content => content;
protected readonly RollingCounter<double> Counter;
public ModMapInfoDisplay(LocalisableString label, Func<double, osuTK.Graphics.Color4> colorFunc)
{
Label = label;
GetColor = colorFunc;
Height = HEIGHT;
AutoSizeAxes = Axes.X;
InternalChild = new InputBlockingContainer
{
RelativeSizeAxes = Axes.Y,
AutoSizeAxes = Axes.X,
Masking = true,
CornerRadius = ModSelectPanel.CORNER_RADIUS,
Shear = new Vector2(ShearedOverlayContainer.SHEAR, 0),
Children = new Drawable[]
{
contentBackground = new Box
{
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
RelativeSizeAxes = Axes.Y,
Width = ValueAreaWidth + ModSelectPanel.CORNER_RADIUS
},
new GridContainer
{
RelativeSizeAxes = Axes.Y,
AutoSizeAxes = Axes.X,
ColumnDimensions = new[]
{
new Dimension(GridSizeMode.AutoSize),
new Dimension(GridSizeMode.Absolute, ValueAreaWidth)
},
Content = new[]
{
new Drawable[]
{
new Container
{
RelativeSizeAxes = Axes.Y,
AutoSizeAxes = Axes.X,
Masking = true,
CornerRadius = ModSelectPanel.CORNER_RADIUS,
Children = new Drawable[]
{
labelBackground = new Box
{
RelativeSizeAxes = Axes.Both
},
new OsuSpriteText
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Margin = new MarginPadding { Horizontal = 18 },
Shear = new Vector2(-ShearedOverlayContainer.SHEAR, 0),
Text = Label,
Font = OsuFont.Default.With(size: 17, weight: FontWeight.SemiBold)
}
}
},
content = new FillFlowContainer
{
AutoSizeAxes = Axes.Both,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Direction = FillDirection.Horizontal,
Shear = new Vector2(-ShearedOverlayContainer.SHEAR, 0),
Spacing = new Vector2(2, 0),
Child = Counter = new EffectCounter(CounterFormat)
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Current = { BindTarget = Current }
}
}
}
}
}
}
};
}
[BackgroundDependencyLoader]
private void load()
{
labelBackground.Colour = colourProvider.Background4;
}
protected override void LoadComplete()
{
Current.BindValueChanged(e =>
{
//var effect = CalculateEffectForComparison(e.NewValue.CompareTo(Current.Default));
setColours(e.NewValue);
}, true);
}
/// <summary>
/// Fades colours of text and its background according to displayed value.
/// </summary>
/// <param name="value">value</param>
private void setColours(double value)
{
contentBackground.FadeColour(GetColor(value), transition_duration, Easing.OutQuint);
}
private partial class EffectCounter : RollingCounter<double>
{
private readonly string? format;
public EffectCounter(string? format)
{
this.format = format;
}
protected override double RollingDuration => 500;
protected override LocalisableString FormatCount(double count) => count.ToLocalisableString(format);
protected override OsuSpriteText CreateSpriteText() => new OsuSpriteText
{
Font = OsuFont.Default.With(size: 17, weight: FontWeight.SemiBold)
};
}
}
}

View File

@ -222,13 +222,18 @@ namespace osu.Game.Overlays.Mods
});
}
aboveColumnsContent.Add(mapInfoContainer = new ModMapInfoContainer
FooterContent.Add(mapInfoContainer = new ModMapInfoContainer
{
Anchor = Anchor.TopLeft,
Origin = Anchor.TopLeft
Anchor = Anchor.BottomRight,
Origin = Anchor.BottomRight,
Padding = new MarginPadding
{
Vertical = PADDING,
Horizontal = 70
},
});
FooterContent.Child = footerButtonFlow = new FillFlowContainer<ShearedButton>
FooterContent.Add(footerButtonFlow = new FillFlowContainer<ShearedButton>
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
@ -248,7 +253,7 @@ namespace osu.Game.Overlays.Mods
DarkerColour = colours.Pink2,
LighterColour = colours.Pink1
})
};
});
globalAvailableMods.BindTo(game.AvailableMods);
}
@ -413,7 +418,7 @@ namespace osu.Game.Overlays.Mods
if (mapInfoContainer == null)
return;
//mapInfoDisplay.Current.Value = 5;
mapInfoContainer.UpdateValues();
}
private void updateCustomisation()

View File

@ -0,0 +1,76 @@
// 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 osu.Framework.Bindables;
using osu.Framework.Extensions.LocalisationExtensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.UserInterface;
using osu.Framework.Localisation;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
using osuTK;
namespace osu.Game.Overlays.Mods
{
public partial class VerticalAttributeDisplay : Container, IHasCurrentValue<double>
{
public Bindable<double> Current
{
get => current.Current;
set => current.Current = value;
}
private readonly BindableWithCurrent<double> current = new BindableWithCurrent<double>();
/// <summary>
/// Text to display in the top area of the display.
/// </summary>
public LocalisableString Label { get; protected set; }
public VerticalAttributeDisplay(LocalisableString label)
{
Label = label;
AutoSizeAxes = Axes.X;
Origin = Anchor = Anchor.CentreLeft;
Shear = new Vector2(-ShearedOverlayContainer.SHEAR, 0);
InternalChild = new FillFlowContainer
{
Origin = Anchor.CentreLeft,
Anchor = Anchor.CentreLeft,
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Vertical,
Children = new Drawable[]
{
new OsuSpriteText
{
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
Text = Label,
Margin = new MarginPadding { Horizontal = 15 }, // to reserve space for 0.XX value
Font = OsuFont.Default.With(size: 20, weight: FontWeight.Bold)
},
new EffectCounter()
{
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
Current = { BindTarget = Current }
}
}
};
}
private partial class EffectCounter : RollingCounter<double>
{
protected override double RollingDuration => 500;
protected override LocalisableString FormatCount(double count) => count.ToLocalisableString("0.##");
protected override OsuSpriteText CreateSpriteText() => new OsuSpriteText
{
Font = OsuFont.Default.With(size: 18, weight: FontWeight.SemiBold)
};
}
}
}

View File

@ -4,7 +4,6 @@
#nullable disable
using System;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
@ -31,9 +30,6 @@ namespace osu.Game.Screens.Select
public readonly BeatmapDetails Details;
//[Cached]
//public Bindable<BeatmapInfo> AdjustedInfo { get; private set; } = new Bindable<BeatmapInfo>();
protected Bindable<BeatmapDetailAreaTabItem> CurrentTab => tabControl.Current;
protected Bindable<bool> CurrentModsFilter => tabControl.CurrentModsFilter;

View File

@ -46,10 +46,8 @@ namespace osu.Game.Screens.Select.Details
private IBeatmapInfo beatmapInfo;
#nullable enable
[Resolved]
private Bindable<BeatmapInfo>? adjustedInfo { get; set; } = null;
#nullable disable
[Resolved(canBeNull: true)]
private Bindable<BeatmapShortInfo> adjustedInfo { get; set; } = null;
public IBeatmapInfo BeatmapInfo
{
@ -104,19 +102,30 @@ namespace osu.Game.Screens.Select.Details
private ModSettingChangeTracker modSettingChangeTracker;
private ScheduledDelegate debouncedStatisticsUpdate;
private StarDifficulty latestStarDifficulty = new StarDifficulty();
private void updateBindedInfo()
{
if (adjustedInfo == null) return;
BeatmapInfo adjusted = (BeatmapInfo)beatmapInfo;
adjusted.Difficulty.CircleSize = FirstValue.Value.adjustedValue ?? 0;
adjusted.Difficulty.DrainRate = HpDrain.Value.adjustedValue ?? 0;
adjusted.Difficulty.ApproachRate = ApproachRate.Value.adjustedValue ?? 5;
adjusted.Difficulty.OverallDifficulty = Accuracy.Value.adjustedValue ?? 0;
adjusted.StarRating = starDifficulty.Value.adjustedValue ?? 0;
// sadly need to calculate this to prevent additional data transportation
double rate = 1;
foreach (var mod in mods.Value.OfType<IApplicableToRate>())
rate = mod.ApplyToRate(0, rate);
double bpm = 0;
if (beatmapInfo != null) bpm = beatmapInfo.BPM * rate;
BeatmapShortInfo adjusted = new BeatmapShortInfo()
{
CircleSize = FirstValue.Value.adjustedValue ?? FirstValue.Value.baseValue,
DrainRate = HpDrain.Value.adjustedValue ?? HpDrain.Value.baseValue,
ApproachRate = ApproachRate.Value.adjustedValue ?? ApproachRate.Value.baseValue,
OverallDifficulty = Accuracy.Value.adjustedValue ?? Accuracy.Value.baseValue,
BPM = bpm,
StarDifficulty = latestStarDifficulty
};
adjustedInfo.Value = adjusted;
adjustedInfo.TriggerChange();
}
private void modsChanged(ValueChangedEvent<IReadOnlyList<Mod>> mods)
@ -165,6 +174,7 @@ namespace osu.Game.Screens.Select.Details
Accuracy.Value = (baseDifficulty?.OverallDifficulty ?? 0, adjustedDifficulty?.OverallDifficulty);
ApproachRate.Value = (baseDifficulty?.ApproachRate ?? 0, adjustedDifficulty?.ApproachRate);
updateBindedInfo(); // to faster UI response (without SR calculation)
updateStarDifficulty();
}
@ -199,6 +209,7 @@ namespace osu.Game.Screens.Select.Details
return;
starDifficulty.Value = ((float)normalDifficulty.Value.Stars, (float)moddedDifficulty.Value.Stars);
latestStarDifficulty = moddedDifficulty ?? default;
updateBindedInfo();
}), starDifficultyCancellationSource.Token, TaskContinuationOptions.OnlyOnRanToCompletion, TaskScheduler.Current);

View File

@ -100,7 +100,7 @@ namespace osu.Game.Screens.Select
private Bindable<IReadOnlyList<Mod>> selectedMods { get; set; } = null!;
[Cached]
private Bindable<BeatmapInfo> adjustedInfo { get; set; } = new Bindable<BeatmapInfo>();
private Bindable<BeatmapShortInfo> adjustedInfo { get; set; } = new Bindable<BeatmapShortInfo>();
protected BeatmapCarousel Carousel { get; private set; } = null!;