mirror of
https://github.com/ppy/osu.git
synced 2025-01-31 02:43:18 +08:00
Merge branch 'master' into skinning-colour-customisation
This commit is contained in:
commit
4f57a67ea4
@ -105,9 +105,7 @@ namespace osu.Game.Rulesets.Osu.Edit
|
|||||||
// is not looking to change the duration of the slider but expand the whole pattern.
|
// is not looking to change the duration of the slider but expand the whole pattern.
|
||||||
if (objectsInScale.Count == 1 && objectsInScale.First().Key is Slider slider)
|
if (objectsInScale.Count == 1 && objectsInScale.First().Key is Slider slider)
|
||||||
{
|
{
|
||||||
var originalInfo = objectsInScale[slider];
|
scaleSlider(slider, scale, actualOrigin, objectsInScale[slider], axisRotation);
|
||||||
Debug.Assert(originalInfo.PathControlPointPositions != null && originalInfo.PathControlPointTypes != null);
|
|
||||||
scaleSlider(slider, scale, originalInfo.PathControlPointPositions, originalInfo.PathControlPointTypes, axisRotation);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -159,21 +157,25 @@ namespace osu.Game.Rulesets.Osu.Edit
|
|||||||
return scale;
|
return scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void scaleSlider(Slider slider, Vector2 scale, Vector2[] originalPathPositions, PathType?[] originalPathTypes, float axisRotation = 0)
|
private void scaleSlider(Slider slider, Vector2 scale, Vector2 origin, OriginalHitObjectState originalInfo, float axisRotation = 0)
|
||||||
{
|
{
|
||||||
|
Debug.Assert(originalInfo.PathControlPointPositions != null && originalInfo.PathControlPointTypes != null);
|
||||||
|
|
||||||
scale = Vector2.ComponentMax(scale, new Vector2(Precision.FLOAT_EPSILON));
|
scale = Vector2.ComponentMax(scale, new Vector2(Precision.FLOAT_EPSILON));
|
||||||
|
|
||||||
// Maintain the path types in case they were defaulted to bezier at some point during scaling
|
// Maintain the path types in case they were defaulted to bezier at some point during scaling
|
||||||
for (int i = 0; i < slider.Path.ControlPoints.Count; i++)
|
for (int i = 0; i < slider.Path.ControlPoints.Count; i++)
|
||||||
{
|
{
|
||||||
slider.Path.ControlPoints[i].Position = GeometryUtils.GetScaledPosition(scale, Vector2.Zero, originalPathPositions[i], axisRotation);
|
slider.Path.ControlPoints[i].Position = GeometryUtils.GetScaledPosition(scale, Vector2.Zero, originalInfo.PathControlPointPositions[i], axisRotation);
|
||||||
slider.Path.ControlPoints[i].Type = originalPathTypes[i];
|
slider.Path.ControlPoints[i].Type = originalInfo.PathControlPointTypes[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Snap the slider's length to the current beat divisor
|
// Snap the slider's length to the current beat divisor
|
||||||
// to calculate the final resulting duration / bounding box before the final checks.
|
// to calculate the final resulting duration / bounding box before the final checks.
|
||||||
slider.SnapTo(snapProvider);
|
slider.SnapTo(snapProvider);
|
||||||
|
|
||||||
|
slider.Position = GeometryUtils.GetScaledPosition(scale, origin, originalInfo.Position, axisRotation);
|
||||||
|
|
||||||
//if sliderhead or sliderend end up outside playfield, revert scaling.
|
//if sliderhead or sliderend end up outside playfield, revert scaling.
|
||||||
Quad scaledQuad = GeometryUtils.GetSurroundingQuad(new OsuHitObject[] { slider });
|
Quad scaledQuad = GeometryUtils.GetSurroundingQuad(new OsuHitObject[] { slider });
|
||||||
(bool xInBounds, bool yInBounds) = isQuadInBounds(scaledQuad);
|
(bool xInBounds, bool yInBounds) = isQuadInBounds(scaledQuad);
|
||||||
@ -182,7 +184,9 @@ namespace osu.Game.Rulesets.Osu.Edit
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
for (int i = 0; i < slider.Path.ControlPoints.Count; i++)
|
for (int i = 0; i < slider.Path.ControlPoints.Count; i++)
|
||||||
slider.Path.ControlPoints[i].Position = originalPathPositions[i];
|
slider.Path.ControlPoints[i].Position = originalInfo.PathControlPointPositions[i];
|
||||||
|
|
||||||
|
slider.Position = originalInfo.Position;
|
||||||
|
|
||||||
// Snap the slider's length again to undo the potentially-invalid length applied by the previous snap.
|
// Snap the slider's length again to undo the potentially-invalid length applied by the previous snap.
|
||||||
slider.SnapTo(snapProvider);
|
slider.SnapTo(snapProvider);
|
||||||
|
@ -10,7 +10,10 @@ using osu.Framework.Graphics.Containers;
|
|||||||
using osu.Framework.Graphics.Sprites;
|
using osu.Framework.Graphics.Sprites;
|
||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterface;
|
||||||
using osu.Game.Graphics.UserInterfaceV2;
|
using osu.Game.Graphics.UserInterfaceV2;
|
||||||
|
using osu.Game.Rulesets.Objects;
|
||||||
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
using osu.Game.Rulesets.Osu.UI;
|
using osu.Game.Rulesets.Osu.UI;
|
||||||
|
using osu.Game.Screens.Edit;
|
||||||
using osu.Game.Screens.Edit.Components.RadioButtons;
|
using osu.Game.Screens.Edit.Components.RadioButtons;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
|
|
||||||
@ -35,6 +38,8 @@ namespace osu.Game.Rulesets.Osu.Edit
|
|||||||
private OsuCheckbox xCheckBox = null!;
|
private OsuCheckbox xCheckBox = null!;
|
||||||
private OsuCheckbox yCheckBox = null!;
|
private OsuCheckbox yCheckBox = null!;
|
||||||
|
|
||||||
|
private BindableList<HitObject> selectedItems { get; } = new BindableList<HitObject>();
|
||||||
|
|
||||||
public PreciseScalePopover(OsuSelectionScaleHandler scaleHandler, OsuGridToolboxGroup gridToolbox)
|
public PreciseScalePopover(OsuSelectionScaleHandler scaleHandler, OsuGridToolboxGroup gridToolbox)
|
||||||
{
|
{
|
||||||
this.scaleHandler = scaleHandler;
|
this.scaleHandler = scaleHandler;
|
||||||
@ -44,8 +49,10 @@ namespace osu.Game.Rulesets.Osu.Edit
|
|||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load(EditorBeatmap editorBeatmap)
|
||||||
{
|
{
|
||||||
|
selectedItems.BindTo(editorBeatmap.SelectedHitObjects);
|
||||||
|
|
||||||
Child = new FillFlowContainer
|
Child = new FillFlowContainer
|
||||||
{
|
{
|
||||||
Width = 220,
|
Width = 220,
|
||||||
@ -191,14 +198,26 @@ namespace osu.Game.Rulesets.Osu.Edit
|
|||||||
updateAxisCheckBoxesEnabled();
|
updateAxisCheckBoxesEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Vector2? getOriginPosition(PreciseScaleInfo scale) =>
|
private Vector2? getOriginPosition(PreciseScaleInfo scale)
|
||||||
scale.Origin switch
|
{
|
||||||
|
switch (scale.Origin)
|
||||||
{
|
{
|
||||||
ScaleOrigin.GridCentre => gridToolbox.StartPosition.Value,
|
case ScaleOrigin.GridCentre:
|
||||||
ScaleOrigin.PlayfieldCentre => OsuPlayfield.BASE_SIZE / 2,
|
return gridToolbox.StartPosition.Value;
|
||||||
ScaleOrigin.SelectionCentre => null,
|
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(scale))
|
case ScaleOrigin.PlayfieldCentre:
|
||||||
};
|
return OsuPlayfield.BASE_SIZE / 2;
|
||||||
|
|
||||||
|
case ScaleOrigin.SelectionCentre:
|
||||||
|
if (selectedItems.Count == 1 && selectedItems.First() is Slider slider)
|
||||||
|
return slider.Position;
|
||||||
|
|
||||||
|
return null;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(scale));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private Axes getAdjustAxis(PreciseScaleInfo scale) => scale.XAxis ? scale.YAxis ? Axes.Both : Axes.X : Axes.Y;
|
private Axes getAdjustAxis(PreciseScaleInfo scale) => scale.XAxis ? scale.YAxis ? Axes.Both : Axes.X : Axes.Y;
|
||||||
|
|
||||||
|
@ -91,20 +91,35 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
drawableObjectPiece.ApplyCustomUpdateState -= applyDimToDrawableHitObject;
|
drawableObjectPiece.ApplyCustomUpdateState -= applyDimToDrawableHitObject;
|
||||||
drawableObjectPiece.ApplyCustomUpdateState += applyDimToDrawableHitObject;
|
drawableObjectPiece.ApplyCustomUpdateState += applyDimToDrawableHitObject;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
applyDim(piece);
|
|
||||||
}
|
|
||||||
|
|
||||||
void applyDim(Drawable piece)
|
// but at the end apply the transforms now regardless of whether this is a DHO or not.
|
||||||
{
|
// the above is just to ensure they don't get overwritten later.
|
||||||
piece.FadeColour(new Color4(195, 195, 195, 255));
|
applyDim(piece);
|
||||||
using (piece.BeginDelayedSequence(InitialLifetimeOffset - OsuHitWindows.MISS_WINDOW))
|
|
||||||
piece.FadeColour(Color4.White, 100);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void applyDimToDrawableHitObject(DrawableHitObject dho, ArmedState _) => applyDim(dho);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void ClearNestedHitObjects()
|
||||||
|
{
|
||||||
|
base.ClearNestedHitObjects();
|
||||||
|
|
||||||
|
// any dimmable pieces that are DHOs will be pooled separately.
|
||||||
|
// `applyDimToDrawableHitObject` is a closure that implicitly captures `this`,
|
||||||
|
// and because of separate pooling of parent and child objects, there is no guarantee that the pieces will be associated with `this` again on re-use.
|
||||||
|
// therefore, clean up the subscription here to avoid crosstalk.
|
||||||
|
// not doing so can result in the callback attempting to read things from `this` when it is in a completely bogus state (not in use or similar).
|
||||||
|
foreach (var piece in DimmablePieces.OfType<DrawableHitObject>())
|
||||||
|
piece.ApplyCustomUpdateState -= applyDimToDrawableHitObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applyDim(Drawable piece)
|
||||||
|
{
|
||||||
|
piece.FadeColour(new Color4(195, 195, 195, 255));
|
||||||
|
using (piece.BeginDelayedSequence(InitialLifetimeOffset - OsuHitWindows.MISS_WINDOW))
|
||||||
|
piece.FadeColour(Color4.White, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applyDimToDrawableHitObject(DrawableHitObject dho, ArmedState _) => applyDim(dho);
|
||||||
|
|
||||||
protected sealed override double InitialLifetimeOffset => HitObject.TimePreempt;
|
protected sealed override double InitialLifetimeOffset => HitObject.TimePreempt;
|
||||||
|
|
||||||
private OsuInputManager osuActionInputManager;
|
private OsuInputManager osuActionInputManager;
|
||||||
|
@ -5,6 +5,7 @@ using osu.Framework.Bindables;
|
|||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Cursor;
|
using osu.Framework.Graphics.Cursor;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Graphics.Cursor;
|
using osu.Game.Graphics.Cursor;
|
||||||
using osu.Game.Graphics.UserInterfaceV2;
|
using osu.Game.Graphics.UserInterfaceV2;
|
||||||
using osu.Game.Localisation;
|
using osu.Game.Localisation;
|
||||||
@ -94,6 +95,11 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
Instantaneous = false,
|
Instantaneous = false,
|
||||||
TabbableContentContainer = this,
|
TabbableContentContainer = this,
|
||||||
},
|
},
|
||||||
|
new FormEnumDropdown<CountdownType>
|
||||||
|
{
|
||||||
|
Caption = EditorSetupStrings.EnableCountdown,
|
||||||
|
HintText = EditorSetupStrings.CountdownDescription,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
251
osu.Game/Graphics/UserInterfaceV2/FormDropdown.cs
Normal file
251
osu.Game/Graphics/UserInterfaceV2/FormDropdown.cs
Normal file
@ -0,0 +1,251 @@
|
|||||||
|
// 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.Extensions.ObjectExtensions;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Colour;
|
||||||
|
using osu.Framework.Graphics.Sprites;
|
||||||
|
using osu.Framework.Graphics.UserInterface;
|
||||||
|
using osu.Framework.Input.Events;
|
||||||
|
using osu.Framework.Localisation;
|
||||||
|
using osu.Game.Graphics.Sprites;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
using osu.Game.Overlays;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Graphics.UserInterfaceV2
|
||||||
|
{
|
||||||
|
public partial class FormDropdown<T> : OsuDropdown<T>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Caption describing this slider bar, displayed on top of the controls.
|
||||||
|
/// </summary>
|
||||||
|
public LocalisableString Caption { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Hint text containing an extended description of this slider bar, displayed in a tooltip when hovering the caption.
|
||||||
|
/// </summary>
|
||||||
|
public LocalisableString HintText { get; init; }
|
||||||
|
|
||||||
|
private FormDropdownHeader header = null!;
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X;
|
||||||
|
|
||||||
|
header.Caption = Caption;
|
||||||
|
header.HintText = HintText;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override DropdownHeader CreateHeader() => header = new FormDropdownHeader
|
||||||
|
{
|
||||||
|
Dropdown = this,
|
||||||
|
};
|
||||||
|
|
||||||
|
protected override DropdownMenu CreateMenu() => new FormDropdownMenu();
|
||||||
|
|
||||||
|
private partial class FormDropdownHeader : DropdownHeader
|
||||||
|
{
|
||||||
|
public FormDropdown<T> Dropdown { get; set; } = null!;
|
||||||
|
|
||||||
|
protected override DropdownSearchBar CreateSearchBar() => SearchBar = new FormDropdownSearchBar();
|
||||||
|
|
||||||
|
private LocalisableString captionText;
|
||||||
|
private LocalisableString hintText;
|
||||||
|
private LocalisableString labelText;
|
||||||
|
|
||||||
|
public LocalisableString Caption
|
||||||
|
{
|
||||||
|
get => captionText;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
captionText = value;
|
||||||
|
|
||||||
|
if (caption.IsNotNull())
|
||||||
|
caption.Caption = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalisableString HintText
|
||||||
|
{
|
||||||
|
get => hintText;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
hintText = value;
|
||||||
|
|
||||||
|
if (caption.IsNotNull())
|
||||||
|
caption.TooltipText = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override LocalisableString Label
|
||||||
|
{
|
||||||
|
get => labelText;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
labelText = value;
|
||||||
|
|
||||||
|
if (label.IsNotNull())
|
||||||
|
label.Text = labelText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected new FormDropdownSearchBar SearchBar { get; set; } = null!;
|
||||||
|
|
||||||
|
private FormFieldCaption caption = null!;
|
||||||
|
private OsuSpriteText label = null!;
|
||||||
|
private SpriteIcon chevron = null!;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private OverlayColourProvider colourProvider { get; set; } = null!;
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X;
|
||||||
|
AutoSizeAxes = Axes.None;
|
||||||
|
Height = 50;
|
||||||
|
|
||||||
|
Masking = true;
|
||||||
|
CornerRadius = 5;
|
||||||
|
|
||||||
|
Foreground.AutoSizeAxes = Axes.None;
|
||||||
|
Foreground.RelativeSizeAxes = Axes.Both;
|
||||||
|
Foreground.Padding = new MarginPadding(9);
|
||||||
|
Foreground.Children = new Drawable[]
|
||||||
|
{
|
||||||
|
caption = new FormFieldCaption
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopLeft,
|
||||||
|
Origin = Anchor.TopLeft,
|
||||||
|
Caption = Caption,
|
||||||
|
TooltipText = HintText,
|
||||||
|
},
|
||||||
|
label = new OsuSpriteText
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Anchor = Anchor.BottomLeft,
|
||||||
|
Origin = Anchor.BottomLeft,
|
||||||
|
},
|
||||||
|
chevron = new SpriteIcon
|
||||||
|
{
|
||||||
|
Icon = FontAwesome.Solid.ChevronDown,
|
||||||
|
Anchor = Anchor.CentreRight,
|
||||||
|
Origin = Anchor.CentreRight,
|
||||||
|
Size = new Vector2(16),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
AddInternal(new HoverClickSounds());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
|
||||||
|
Dropdown.Current.BindDisabledChanged(_ => updateState());
|
||||||
|
SearchBar.SearchTerm.BindValueChanged(_ => updateState(), true);
|
||||||
|
Dropdown.Menu.StateChanged += _ =>
|
||||||
|
{
|
||||||
|
updateState();
|
||||||
|
updateChevron();
|
||||||
|
};
|
||||||
|
SearchBar.TextBox.OnCommit += (_, _) =>
|
||||||
|
{
|
||||||
|
Background.FlashColour(ColourInfo.GradientVertical(colourProvider.Background5, colourProvider.Dark2), 800, Easing.OutQuint);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool OnHover(HoverEvent e)
|
||||||
|
{
|
||||||
|
updateState();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnHoverLost(HoverLostEvent e)
|
||||||
|
{
|
||||||
|
base.OnHoverLost(e);
|
||||||
|
updateState();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateState()
|
||||||
|
{
|
||||||
|
label.Alpha = string.IsNullOrEmpty(SearchBar.SearchTerm.Value) ? 1 : 0;
|
||||||
|
|
||||||
|
caption.Colour = Dropdown.Current.Disabled ? colourProvider.Foreground1 : colourProvider.Content2;
|
||||||
|
label.Colour = Dropdown.Current.Disabled ? colourProvider.Foreground1 : colourProvider.Content1;
|
||||||
|
chevron.Colour = Dropdown.Current.Disabled ? colourProvider.Foreground1 : colourProvider.Content1;
|
||||||
|
DisabledColour = Colour4.White;
|
||||||
|
|
||||||
|
bool dropdownOpen = Dropdown.Menu.State == MenuState.Open;
|
||||||
|
|
||||||
|
if (!Dropdown.Current.Disabled)
|
||||||
|
{
|
||||||
|
BorderThickness = IsHovered || dropdownOpen ? 2 : 0;
|
||||||
|
BorderColour = dropdownOpen ? colourProvider.Highlight1 : colourProvider.Light4;
|
||||||
|
|
||||||
|
if (dropdownOpen)
|
||||||
|
Background.Colour = ColourInfo.GradientVertical(colourProvider.Background5, colourProvider.Dark3);
|
||||||
|
else if (IsHovered)
|
||||||
|
Background.Colour = ColourInfo.GradientVertical(colourProvider.Background5, colourProvider.Dark4);
|
||||||
|
else
|
||||||
|
Background.Colour = colourProvider.Background5;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Background.Colour = colourProvider.Background4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateChevron()
|
||||||
|
{
|
||||||
|
bool open = Dropdown.Menu.State == MenuState.Open;
|
||||||
|
chevron.ScaleTo(open ? new Vector2(1f, -1f) : Vector2.One, 300, Easing.OutQuint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private partial class FormDropdownSearchBar : DropdownSearchBar
|
||||||
|
{
|
||||||
|
public FormTextBox.InnerTextBox TextBox { get; private set; } = null!;
|
||||||
|
|
||||||
|
protected override void PopIn() => this.FadeIn();
|
||||||
|
protected override void PopOut() => this.FadeOut();
|
||||||
|
|
||||||
|
protected override TextBox CreateTextBox() => TextBox = new FormTextBox.InnerTextBox();
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
TextBox.Anchor = Anchor.BottomLeft;
|
||||||
|
TextBox.Origin = Anchor.BottomLeft;
|
||||||
|
TextBox.RelativeSizeAxes = Axes.X;
|
||||||
|
TextBox.Margin = new MarginPadding(9);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private partial class FormDropdownMenu : OsuDropdownMenu
|
||||||
|
{
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OverlayColourProvider colourProvider)
|
||||||
|
{
|
||||||
|
ItemsContainer.Padding = new MarginPadding(9);
|
||||||
|
Margin = new MarginPadding { Top = 5 };
|
||||||
|
|
||||||
|
MaskingContainer.BorderThickness = 2;
|
||||||
|
MaskingContainer.BorderColour = colourProvider.Highlight1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class FormEnumDropdown<T> : FormDropdown<T>
|
||||||
|
where T : struct, Enum
|
||||||
|
{
|
||||||
|
public FormEnumDropdown()
|
||||||
|
{
|
||||||
|
Items = Enum.GetValues<T>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -234,9 +234,12 @@ namespace osu.Game.Screens.Play
|
|||||||
{
|
{
|
||||||
if (LoadedBeatmapSuccessfully)
|
if (LoadedBeatmapSuccessfully)
|
||||||
{
|
{
|
||||||
|
// compare: https://github.com/ppy/osu/blob/ccf1acce56798497edfaf92d3ece933469edcf0a/osu.Game/Screens/Play/Player.cs#L848-L851
|
||||||
|
var scoreCopy = Score.DeepClone();
|
||||||
|
|
||||||
Task.Run(async () =>
|
Task.Run(async () =>
|
||||||
{
|
{
|
||||||
await submitScore(Score.DeepClone()).ConfigureAwait(false);
|
await submitScore(scoreCopy).ConfigureAwait(false);
|
||||||
spectatorClient.EndPlaying(GameplayState);
|
spectatorClient.EndPlaying(GameplayState);
|
||||||
}).FireAndForget();
|
}).FireAndForget();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user