mirror of
https://github.com/osukey/osukey.git
synced 2025-05-24 15:07:20 +09:00
Merge branch 'master' into optimise-search
This commit is contained in:
commit
6c5ccdfd90
@ -3,15 +3,53 @@
|
|||||||
#
|
#
|
||||||
# https://github.com/ppy/osu-framework/wiki/Testing-local-framework-checkout-with-other-projects
|
# https://github.com/ppy/osu-framework/wiki/Testing-local-framework-checkout-with-other-projects
|
||||||
|
|
||||||
$CSPROJ="osu.Game/osu.Game.csproj"
|
$GAME_CSPROJ="osu.Game/osu.Game.csproj"
|
||||||
|
$ANDROID_PROPS="osu.Android.props"
|
||||||
|
$IOS_PROPS="osu.iOS.props"
|
||||||
$SLN="osu.sln"
|
$SLN="osu.sln"
|
||||||
|
|
||||||
dotnet remove $CSPROJ package ppy.osu.Framework;
|
dotnet remove $GAME_CSPROJ reference ppy.osu.Framework;
|
||||||
dotnet sln $SLN add ../osu-framework/osu.Framework/osu.Framework.csproj ../osu-framework/osu.Framework.NativeLibs/osu.Framework.NativeLibs.csproj;
|
dotnet remove $ANDROID_PROPS reference ppy.osu.Framework.Android;
|
||||||
dotnet add $CSPROJ reference ../osu-framework/osu.Framework/osu.Framework.csproj
|
dotnet remove $IOS_PROPS reference ppy.osu.Framework.iOS;
|
||||||
|
|
||||||
|
dotnet sln $SLN add ../osu-framework/osu.Framework/osu.Framework.csproj `
|
||||||
|
../osu-framework/osu.Framework.NativeLibs/osu.Framework.NativeLibs.csproj `
|
||||||
|
../osu-framework/osu.Framework.Android/osu.Framework.Android.csproj `
|
||||||
|
../osu-framework/osu.Framework.iOS/osu.Framework.iOS.csproj;
|
||||||
|
|
||||||
|
dotnet add $GAME_CSPROJ reference ../osu-framework/osu.Framework/osu.Framework.csproj;
|
||||||
|
dotnet add $ANDROID_PROPS reference ../osu-framework/osu.Framework.Android/osu.Framework.Android.csproj;
|
||||||
|
dotnet add $IOS_PROPS reference ../osu-framework/osu.Framework.iOS/osu.Framework.iOS.csproj;
|
||||||
|
|
||||||
|
# workaround for dotnet add not inserting $(MSBuildThisFileDirectory) on props files
|
||||||
|
(Get-Content "osu.Android.props") -replace "`"..\\osu-framework", "`"`$(MSBuildThisFileDirectory)..\osu-framework" | Set-Content "osu.Android.props"
|
||||||
|
(Get-Content "osu.iOS.props") -replace "`"..\\osu-framework", "`"`$(MSBuildThisFileDirectory)..\osu-framework" | Set-Content "osu.iOS.props"
|
||||||
|
|
||||||
|
# needed because iOS framework nupkg includes a set of properties to work around certain issues during building,
|
||||||
|
# and those get ignored when referencing framework via project, threfore we have to manually include it via props reference.
|
||||||
|
(Get-Content "osu.iOS.props") |
|
||||||
|
Foreach-Object {
|
||||||
|
if ($_ -match "</Project>")
|
||||||
|
{
|
||||||
|
" <Import Project=`"`$(MSBuildThisFileDirectory)../osu-framework/osu.Framework.iOS.props`"/>"
|
||||||
|
}
|
||||||
|
|
||||||
|
$_
|
||||||
|
} | Set-Content "osu.iOS.props"
|
||||||
|
|
||||||
|
$TMP=New-TemporaryFile
|
||||||
|
|
||||||
$SLNF=Get-Content "osu.Desktop.slnf" | ConvertFrom-Json
|
$SLNF=Get-Content "osu.Desktop.slnf" | ConvertFrom-Json
|
||||||
$TMP=New-TemporaryFile
|
|
||||||
$SLNF.solution.projects += ("../osu-framework/osu.Framework/osu.Framework.csproj", "../osu-framework/osu.Framework.NativeLibs/osu.Framework.NativeLibs.csproj")
|
$SLNF.solution.projects += ("../osu-framework/osu.Framework/osu.Framework.csproj", "../osu-framework/osu.Framework.NativeLibs/osu.Framework.NativeLibs.csproj")
|
||||||
ConvertTo-Json $SLNF | Out-File $TMP -Encoding UTF8
|
ConvertTo-Json $SLNF | Out-File $TMP -Encoding UTF8
|
||||||
Move-Item -Path $TMP -Destination "osu.Desktop.slnf" -Force
|
Move-Item -Path $TMP -Destination "osu.Desktop.slnf" -Force
|
||||||
|
|
||||||
|
$SLNF=Get-Content "osu.Android.slnf" | ConvertFrom-Json
|
||||||
|
$SLNF.solution.projects += ("../osu-framework/osu.Framework/osu.Framework.csproj", "../osu-framework/osu.Framework.NativeLibs/osu.Framework.NativeLibs.csproj", "../osu-framework/osu.Framework.Android/osu.Framework.Android.csproj")
|
||||||
|
ConvertTo-Json $SLNF | Out-File $TMP -Encoding UTF8
|
||||||
|
Move-Item -Path $TMP -Destination "osu.Android.slnf" -Force
|
||||||
|
|
||||||
|
$SLNF=Get-Content "osu.iOS.slnf" | ConvertFrom-Json
|
||||||
|
$SLNF.solution.projects += ("../osu-framework/osu.Framework/osu.Framework.csproj", "../osu-framework/osu.Framework.NativeLibs/osu.Framework.NativeLibs.csproj", "../osu-framework/osu.Framework.iOS/osu.Framework.iOS.csproj")
|
||||||
|
ConvertTo-Json $SLNF | Out-File $TMP -Encoding UTF8
|
||||||
|
Move-Item -Path $TMP -Destination "osu.iOS.slnf" -Force
|
||||||
|
@ -5,14 +5,41 @@
|
|||||||
#
|
#
|
||||||
# https://github.com/ppy/osu-framework/wiki/Testing-local-framework-checkout-with-other-projects
|
# https://github.com/ppy/osu-framework/wiki/Testing-local-framework-checkout-with-other-projects
|
||||||
|
|
||||||
CSPROJ="osu.Game/osu.Game.csproj"
|
GAME_CSPROJ="osu.Game/osu.Game.csproj"
|
||||||
|
ANDROID_PROPS="osu.Android.props"
|
||||||
|
IOS_PROPS="osu.iOS.props"
|
||||||
SLN="osu.sln"
|
SLN="osu.sln"
|
||||||
|
|
||||||
dotnet remove $CSPROJ package ppy.osu.Framework
|
dotnet remove $GAME_CSPROJ reference ppy.osu.Framework
|
||||||
dotnet sln $SLN add ../osu-framework/osu.Framework/osu.Framework.csproj ../osu-framework/osu.Framework.NativeLibs/osu.Framework.NativeLibs.csproj
|
dotnet remove $ANDROID_PROPS reference ppy.osu.Framework.Android
|
||||||
dotnet add $CSPROJ reference ../osu-framework/osu.Framework/osu.Framework.csproj
|
dotnet remove $IOS_PROPS reference ppy.osu.Framework.iOS
|
||||||
|
|
||||||
|
dotnet sln $SLN add ../osu-framework/osu.Framework/osu.Framework.csproj \
|
||||||
|
../osu-framework/osu.Framework.NativeLibs/osu.Framework.NativeLibs.csproj \
|
||||||
|
../osu-framework/osu.Framework.Android/osu.Framework.Android.csproj \
|
||||||
|
../osu-framework/osu.Framework.iOS/osu.Framework.iOS.csproj
|
||||||
|
|
||||||
|
dotnet add $GAME_CSPROJ reference ../osu-framework/osu.Framework/osu.Framework.csproj
|
||||||
|
dotnet add $ANDROID_PROPS reference ../osu-framework/osu.Framework.Android/osu.Framework.Android.csproj
|
||||||
|
dotnet add $IOS_PROPS reference ../osu-framework/osu.Framework.iOS/osu.Framework.iOS.csproj
|
||||||
|
|
||||||
|
# workaround for dotnet add not inserting $(MSBuildThisFileDirectory) on props files
|
||||||
|
sed -i.bak 's:"..\\osu-framework:"$(MSBuildThisFileDirectory)..\\osu-framework:g' ./osu.Android.props && rm osu.Android.props.bak
|
||||||
|
sed -i.bak 's:"..\\osu-framework:"$(MSBuildThisFileDirectory)..\\osu-framework:g' ./osu.iOS.props && rm osu.iOS.props.bak
|
||||||
|
|
||||||
|
# needed because iOS framework nupkg includes a set of properties to work around certain issues during building,
|
||||||
|
# and those get ignored when referencing framework via project, threfore we have to manually include it via props reference.
|
||||||
|
sed -i.bak '/<\/Project>/i\
|
||||||
|
<Import Project=\"$(MSBuildThisFileDirectory)../osu-framework/osu.Framework.iOS.props\"/>\
|
||||||
|
' ./osu.iOS.props && rm osu.iOS.props.bak
|
||||||
|
|
||||||
SLNF="osu.Desktop.slnf"
|
|
||||||
tmp=$(mktemp)
|
tmp=$(mktemp)
|
||||||
|
|
||||||
jq '.solution.projects += ["../osu-framework/osu.Framework/osu.Framework.csproj", "../osu-framework/osu.Framework.NativeLibs/osu.Framework.NativeLibs.csproj"]' osu.Desktop.slnf > $tmp
|
jq '.solution.projects += ["../osu-framework/osu.Framework/osu.Framework.csproj", "../osu-framework/osu.Framework.NativeLibs/osu.Framework.NativeLibs.csproj"]' osu.Desktop.slnf > $tmp
|
||||||
mv -f $tmp $SLNF
|
mv -f $tmp osu.Desktop.slnf
|
||||||
|
|
||||||
|
jq '.solution.projects += ["../osu-framework/osu.Framework/osu.Framework.csproj", "../osu-framework/osu.Framework.NativeLibs/osu.Framework.NativeLibs.csproj", "../osu-framework/osu.Framework.Android/osu.Framework.Android.csproj"]' osu.Android.slnf > $tmp
|
||||||
|
mv -f $tmp osu.Android.slnf
|
||||||
|
|
||||||
|
jq '.solution.projects += ["../osu-framework/osu.Framework/osu.Framework.csproj", "../osu-framework/osu.Framework.NativeLibs/osu.Framework.NativeLibs.csproj", "../osu-framework/osu.Framework.iOS/osu.Framework.iOS.csproj"]' osu.iOS.slnf > $tmp
|
||||||
|
mv -f $tmp osu.iOS.slnf
|
||||||
|
@ -8,10 +8,14 @@
|
|||||||
<!-- NullabilityInfoContextSupport is disabled by default for Android -->
|
<!-- NullabilityInfoContextSupport is disabled by default for Android -->
|
||||||
<NullabilityInfoContextSupport>true</NullabilityInfoContextSupport>
|
<NullabilityInfoContextSupport>true</NullabilityInfoContextSupport>
|
||||||
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
|
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
|
||||||
|
<AndroidManifestMerger>manifestmerger.jar</AndroidManifestMerger>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2023.228.0" />
|
<PackageReference Include="ppy.osu.Framework.Android" Version="2023.228.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<AndroidManifestOverlay Include="$(MSBuildThisFileDirectory)osu.Android\Properties\AndroidManifestOverlay.xml" />
|
||||||
|
</ItemGroup>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<!-- Fody does not handle Android build well, and warns when unchanged.
|
<!-- Fody does not handle Android build well, and warns when unchanged.
|
||||||
Since Realm objects are not declared directly in Android projects, simply disable Fody. -->
|
Since Realm objects are not declared directly in Android projects, simply disable Fody. -->
|
||||||
|
15
osu.Android/Properties/AndroidManifestOverlay.xml
Normal file
15
osu.Android/Properties/AndroidManifestOverlay.xml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<queries>
|
||||||
|
<intent>
|
||||||
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
|
<data android:scheme="https" />
|
||||||
|
</intent>
|
||||||
|
<intent>
|
||||||
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
|
<data android:scheme="mailto" />
|
||||||
|
</intent>
|
||||||
|
</queries>
|
||||||
|
</manifest>
|
@ -167,8 +167,8 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
|
|||||||
{
|
{
|
||||||
if (bodySprite != null)
|
if (bodySprite != null)
|
||||||
{
|
{
|
||||||
bodySprite.Origin = Anchor.BottomCentre;
|
bodySprite.Origin = Anchor.TopCentre;
|
||||||
bodySprite.Scale = new Vector2(bodySprite.Scale.X, Math.Abs(bodySprite.Scale.Y) * -1);
|
bodySprite.Anchor = Anchor.BottomCentre; // needs to be flipped due to scale flip in Update.
|
||||||
}
|
}
|
||||||
|
|
||||||
if (light != null)
|
if (light != null)
|
||||||
@ -179,7 +179,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
|
|||||||
if (bodySprite != null)
|
if (bodySprite != null)
|
||||||
{
|
{
|
||||||
bodySprite.Origin = Anchor.TopCentre;
|
bodySprite.Origin = Anchor.TopCentre;
|
||||||
bodySprite.Scale = new Vector2(bodySprite.Scale.X, Math.Abs(bodySprite.Scale.Y));
|
bodySprite.Anchor = Anchor.TopCentre;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (light != null)
|
if (light != null)
|
||||||
@ -211,11 +211,15 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
|
|||||||
base.Update();
|
base.Update();
|
||||||
missFadeTime.Value ??= holdNote.HoldBrokenTime;
|
missFadeTime.Value ??= holdNote.HoldBrokenTime;
|
||||||
|
|
||||||
|
int scaleDirection = (direction.Value == ScrollingDirection.Down ? 1 : -1);
|
||||||
|
|
||||||
// here we go...
|
// here we go...
|
||||||
switch (bodyStyle)
|
switch (bodyStyle)
|
||||||
{
|
{
|
||||||
case LegacyNoteBodyStyle.Stretch:
|
case LegacyNoteBodyStyle.Stretch:
|
||||||
// this is how lazer works by default. nothing required.
|
// this is how lazer works by default. nothing required.
|
||||||
|
if (bodySprite != null)
|
||||||
|
bodySprite.Scale = new Vector2(1, scaleDirection);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -228,7 +232,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
|
|||||||
|
|
||||||
bodySprite.FillMode = FillMode.Stretch;
|
bodySprite.FillMode = FillMode.Stretch;
|
||||||
// i dunno this looks about right??
|
// i dunno this looks about right??
|
||||||
bodySprite.Scale = new Vector2(1, 32800 / sprite.DrawHeight);
|
bodySprite.Scale = new Vector2(1, scaleDirection * 32800 / sprite.DrawHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
BIN
osu.Game.Tests/Resources/Archives/modified-argon-20230305.osk
Normal file
BIN
osu.Game.Tests/Resources/Archives/modified-argon-20230305.osk
Normal file
Binary file not shown.
@ -48,7 +48,9 @@ namespace osu.Game.Tests.Skins
|
|||||||
// Covers BPM counter.
|
// Covers BPM counter.
|
||||||
"Archives/modified-default-20221205.osk",
|
"Archives/modified-default-20221205.osk",
|
||||||
// Covers judgement counter.
|
// Covers judgement counter.
|
||||||
"Archives/modified-default-20230117.osk"
|
"Archives/modified-default-20230117.osk",
|
||||||
|
// Covers player avatar and flag.
|
||||||
|
"Archives/modified-argon-20230305.osk",
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -15,6 +15,7 @@ using osu.Game.Overlays.Settings;
|
|||||||
using osu.Game.Overlays.SkinEditor;
|
using osu.Game.Overlays.SkinEditor;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.Osu.Mods;
|
using osu.Game.Rulesets.Osu.Mods;
|
||||||
|
using osu.Game.Screens.Edit.Components;
|
||||||
using osu.Game.Screens.Play;
|
using osu.Game.Screens.Play;
|
||||||
using osu.Game.Screens.Play.HUD.HitErrorMeters;
|
using osu.Game.Screens.Play.HUD.HitErrorMeters;
|
||||||
using osu.Game.Tests.Beatmaps.IO;
|
using osu.Game.Tests.Beatmaps.IO;
|
||||||
@ -188,6 +189,33 @@ namespace osu.Game.Tests.Visual.Navigation
|
|||||||
AddUntilStep("mod overlay closed", () => songSelect.ModSelectOverlay.State.Value == Visibility.Hidden);
|
AddUntilStep("mod overlay closed", () => songSelect.ModSelectOverlay.State.Value == Visibility.Hidden);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestChangeToNonSkinnableScreen()
|
||||||
|
{
|
||||||
|
advanceToSongSelect();
|
||||||
|
openSkinEditor();
|
||||||
|
AddAssert("blueprint container present", () => skinEditor.ChildrenOfType<SkinBlueprintContainer>().Count(), () => Is.EqualTo(1));
|
||||||
|
AddAssert("placeholder not present", () => skinEditor.ChildrenOfType<NonSkinnableScreenPlaceholder>().Count(), () => Is.Zero);
|
||||||
|
AddAssert("editor sidebars not empty", () => skinEditor.ChildrenOfType<EditorSidebar>().SelectMany(sidebar => sidebar.Children).Count(), () => Is.GreaterThan(0));
|
||||||
|
|
||||||
|
AddStep("add skinnable component", () =>
|
||||||
|
{
|
||||||
|
skinEditor.ChildrenOfType<SkinComponentToolbox.ToolboxComponentButton>().First().TriggerClick();
|
||||||
|
});
|
||||||
|
AddUntilStep("newly added component selected", () => skinEditor.SelectedComponents, () => Has.Count.EqualTo(1));
|
||||||
|
|
||||||
|
AddStep("exit to main menu", () => Game.ScreenStack.CurrentScreen.Exit());
|
||||||
|
AddAssert("selection cleared", () => skinEditor.SelectedComponents, () => Has.Count.Zero);
|
||||||
|
AddAssert("blueprint container not present", () => skinEditor.ChildrenOfType<SkinBlueprintContainer>().Count(), () => Is.Zero);
|
||||||
|
AddAssert("placeholder present", () => skinEditor.ChildrenOfType<NonSkinnableScreenPlaceholder>().Count(), () => Is.EqualTo(1));
|
||||||
|
AddAssert("editor sidebars empty", () => skinEditor.ChildrenOfType<EditorSidebar>().SelectMany(sidebar => sidebar.Children).Count(), () => Is.Zero);
|
||||||
|
|
||||||
|
advanceToSongSelect();
|
||||||
|
AddAssert("blueprint container present", () => skinEditor.ChildrenOfType<SkinBlueprintContainer>().Count(), () => Is.EqualTo(1));
|
||||||
|
AddAssert("placeholder not present", () => skinEditor.ChildrenOfType<NonSkinnableScreenPlaceholder>().Count(), () => Is.Zero);
|
||||||
|
AddAssert("editor sidebars not empty", () => skinEditor.ChildrenOfType<EditorSidebar>().SelectMany(sidebar => sidebar.Children).Count(), () => Is.GreaterThan(0));
|
||||||
|
}
|
||||||
|
|
||||||
private void advanceToSongSelect()
|
private void advanceToSongSelect()
|
||||||
{
|
{
|
||||||
PushAndConfirm(() => songSelect = new TestPlaySongSelect());
|
PushAndConfirm(() => songSelect = new TestPlaySongSelect());
|
||||||
|
@ -516,15 +516,20 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
{
|
{
|
||||||
sets.Clear();
|
sets.Clear();
|
||||||
|
|
||||||
for (int i = 0; i < 20; i++)
|
for (int i = 0; i < 10; i++)
|
||||||
{
|
{
|
||||||
var set = TestResources.CreateTestBeatmapSetInfo(5);
|
var set = TestResources.CreateTestBeatmapSetInfo(5);
|
||||||
|
|
||||||
if (i >= 2 && i < 10)
|
// A total of 6 sets have date submitted (4 don't)
|
||||||
|
// A total of 5 sets have artist string (3 of which also have date submitted)
|
||||||
|
|
||||||
|
if (i >= 2 && i < 8) // i = 2, 3, 4, 5, 6, 7 have submitted date
|
||||||
set.DateSubmitted = DateTimeOffset.Now.AddMinutes(i);
|
set.DateSubmitted = DateTimeOffset.Now.AddMinutes(i);
|
||||||
if (i < 5)
|
if (i < 5) // i = 0, 1, 2, 3, 4 have matching string
|
||||||
set.Beatmaps.ForEach(b => b.Metadata.Artist = zzz_string);
|
set.Beatmaps.ForEach(b => b.Metadata.Artist = zzz_string);
|
||||||
|
|
||||||
|
set.Beatmaps.ForEach(b => b.Metadata.Title = $"submitted: {set.DateSubmitted}");
|
||||||
|
|
||||||
sets.Add(set);
|
sets.Add(set);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -532,15 +537,26 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
loadBeatmaps(sets);
|
loadBeatmaps(sets);
|
||||||
|
|
||||||
AddStep("Sort by date submitted", () => carousel.Filter(new FilterCriteria { Sort = SortMode.DateSubmitted }, false));
|
AddStep("Sort by date submitted", () => carousel.Filter(new FilterCriteria { Sort = SortMode.DateSubmitted }, false));
|
||||||
checkVisibleItemCount(diff: false, count: 8);
|
checkVisibleItemCount(diff: false, count: 10);
|
||||||
checkVisibleItemCount(diff: true, count: 5);
|
checkVisibleItemCount(diff: true, count: 5);
|
||||||
|
|
||||||
|
AddAssert("missing date are at end",
|
||||||
|
() => carousel.Items.OfType<DrawableCarouselBeatmapSet>().Reverse().TakeWhile(i => i.Item is CarouselBeatmapSet s && s.BeatmapSet.DateSubmitted == null).Count(), () => Is.EqualTo(4));
|
||||||
|
AddAssert("rest are at start", () => carousel.Items.OfType<DrawableCarouselBeatmapSet>().TakeWhile(i => i.Item is CarouselBeatmapSet s && s.BeatmapSet.DateSubmitted != null).Count(),
|
||||||
|
() => Is.EqualTo(6));
|
||||||
|
|
||||||
AddStep("Sort by date submitted and string", () => carousel.Filter(new FilterCriteria
|
AddStep("Sort by date submitted and string", () => carousel.Filter(new FilterCriteria
|
||||||
{
|
{
|
||||||
Sort = SortMode.DateSubmitted,
|
Sort = SortMode.DateSubmitted,
|
||||||
SearchText = zzz_string
|
SearchText = zzz_string
|
||||||
}, false));
|
}, false));
|
||||||
checkVisibleItemCount(diff: false, count: 3);
|
checkVisibleItemCount(diff: false, count: 5);
|
||||||
checkVisibleItemCount(diff: true, count: 5);
|
checkVisibleItemCount(diff: true, count: 5);
|
||||||
|
|
||||||
|
AddAssert("missing date are at end",
|
||||||
|
() => carousel.Items.OfType<DrawableCarouselBeatmapSet>().Reverse().TakeWhile(i => i.Item is CarouselBeatmapSet s && s.BeatmapSet.DateSubmitted == null).Count(), () => Is.EqualTo(2));
|
||||||
|
AddAssert("rest are at start", () => carousel.Items.OfType<DrawableCarouselBeatmapSet>().TakeWhile(i => i.Item is CarouselBeatmapSet s && s.BeatmapSet.DateSubmitted != null).Count(),
|
||||||
|
() => Is.EqualTo(3));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -1129,7 +1145,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
{
|
{
|
||||||
// until step required as we are querying against alive items, which are loaded asynchronously inside DrawableCarouselBeatmapSet.
|
// until step required as we are querying against alive items, which are loaded asynchronously inside DrawableCarouselBeatmapSet.
|
||||||
AddUntilStep($"{count} {(diff ? "diffs" : "sets")} visible", () =>
|
AddUntilStep($"{count} {(diff ? "diffs" : "sets")} visible", () =>
|
||||||
carousel.Items.Count(s => (diff ? s.Item is CarouselBeatmap : s.Item is CarouselBeatmapSet) && s.Item.Visible) == count);
|
carousel.Items.Count(s => (diff ? s.Item is CarouselBeatmap : s.Item is CarouselBeatmapSet) && s.Item.Visible), () => Is.EqualTo(count));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkSelectionIsCentered()
|
private void checkSelectionIsCentered()
|
||||||
@ -1190,8 +1206,11 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
foreach (var item in Scroll.Children)
|
foreach (var item in Scroll.Children.OrderBy(c => c.Y))
|
||||||
{
|
{
|
||||||
|
if (item.Item?.Visible != true)
|
||||||
|
continue;
|
||||||
|
|
||||||
yield return item;
|
yield return item;
|
||||||
|
|
||||||
if (item is DrawableCarouselBeatmapSet set)
|
if (item is DrawableCarouselBeatmapSet set)
|
||||||
|
@ -8,12 +8,12 @@ using osu.Game.Overlays.Dialog;
|
|||||||
|
|
||||||
namespace osu.Game.Collections
|
namespace osu.Game.Collections
|
||||||
{
|
{
|
||||||
public partial class DeleteCollectionDialog : DeleteConfirmationDialog
|
public partial class DeleteCollectionDialog : DangerousActionDialog
|
||||||
{
|
{
|
||||||
public DeleteCollectionDialog(Live<BeatmapCollection> collection, Action deleteAction)
|
public DeleteCollectionDialog(Live<BeatmapCollection> collection, Action deleteAction)
|
||||||
{
|
{
|
||||||
BodyText = collection.PerformRead(c => $"{c.Name} ({"beatmap".ToQuantity(c.BeatmapMD5Hashes.Count)})");
|
BodyText = collection.PerformRead(c => $"{c.Name} ({"beatmap".ToQuantity(c.BeatmapMD5Hashes.Count)})");
|
||||||
DeleteAction = deleteAction;
|
DangerousAction = deleteAction;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,16 @@ namespace osu.Game.Localisation.SkinComponents
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static LocalisableString TextElementTextDescription => new TranslatableString(getKey(@"text_element_text_description"), "The text to be displayed.");
|
public static LocalisableString TextElementTextDescription => new TranslatableString(getKey(@"text_element_text_description"), "The text to be displayed.");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// "Corner radius"
|
||||||
|
/// </summary>
|
||||||
|
public static LocalisableString CornerRadius => new TranslatableString(getKey(@"corner_radius"), "Corner radius");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// "How rounded the corners should be."
|
||||||
|
/// </summary>
|
||||||
|
public static LocalisableString CornerRadiusDescription => new TranslatableString(getKey(@"corner_radius_description"), "How rounded the corners should be.");
|
||||||
|
|
||||||
private static string getKey(string key) => $"{prefix}:{key}";
|
private static string getKey(string key) => $"{prefix}:{key}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,12 @@ namespace osu.Game.Localisation
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// "Currently editing"
|
/// "Currently editing"
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static LocalisableString CurrentlyEditing => new TranslatableString(getKey(@"currently_editing"), "Currently editing");
|
public static LocalisableString CurrentlyEditing => new TranslatableString(getKey(@"currently_editing"), @"Currently editing");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// "All layout elements for layers in the current screen will be reset to defaults."
|
||||||
|
/// </summary>
|
||||||
|
public static LocalisableString RevertToDefaultDescription => new TranslatableString(getKey(@"revert_to_default_description"), @"All layout elements for layers in the current screen will be reset to defaults.");
|
||||||
|
|
||||||
private static string getKey(string key) => $@"{prefix}:{key}";
|
private static string getKey(string key) => $@"{prefix}:{key}";
|
||||||
}
|
}
|
||||||
|
@ -8,18 +8,22 @@ using osu.Game.Localisation;
|
|||||||
namespace osu.Game.Overlays.Dialog
|
namespace osu.Game.Overlays.Dialog
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Base class for various confirmation dialogs that concern deletion actions.
|
/// A dialog which provides confirmation for actions which result in permanent consequences.
|
||||||
/// Differs from <see cref="ConfirmDialog"/> in that the confirmation button is a "dangerous" one
|
/// Differs from <see cref="ConfirmDialog"/> in that the confirmation button is a "dangerous" one
|
||||||
/// (requires the confirm button to be held).
|
/// (requires the confirm button to be held).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract partial class DeleteConfirmationDialog : PopupDialog
|
/// <remarks>
|
||||||
|
/// The default implementation comes with text for a generic deletion operation.
|
||||||
|
/// This can be further customised by specifying custom <see cref="PopupDialog.HeaderText"/>.
|
||||||
|
/// </remarks>
|
||||||
|
public abstract partial class DangerousActionDialog : PopupDialog
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The action which performs the deletion.
|
/// The action which performs the deletion.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected Action? DeleteAction { get; set; }
|
protected Action? DangerousAction { get; set; }
|
||||||
|
|
||||||
protected DeleteConfirmationDialog()
|
protected DangerousActionDialog()
|
||||||
{
|
{
|
||||||
HeaderText = DeleteConfirmationDialogStrings.HeaderText;
|
HeaderText = DeleteConfirmationDialogStrings.HeaderText;
|
||||||
|
|
||||||
@ -30,7 +34,7 @@ namespace osu.Game.Overlays.Dialog
|
|||||||
new PopupDialogDangerousButton
|
new PopupDialogDangerousButton
|
||||||
{
|
{
|
||||||
Text = DeleteConfirmationDialogStrings.Confirm,
|
Text = DeleteConfirmationDialogStrings.Confirm,
|
||||||
Action = () => DeleteAction?.Invoke()
|
Action = () => DangerousAction?.Invoke()
|
||||||
},
|
},
|
||||||
new PopupDialogCancelButton
|
new PopupDialogCancelButton
|
||||||
{
|
{
|
@ -7,12 +7,12 @@ using osu.Game.Rulesets.Mods;
|
|||||||
|
|
||||||
namespace osu.Game.Overlays.Mods
|
namespace osu.Game.Overlays.Mods
|
||||||
{
|
{
|
||||||
public partial class DeleteModPresetDialog : DeleteConfirmationDialog
|
public partial class DeleteModPresetDialog : DangerousActionDialog
|
||||||
{
|
{
|
||||||
public DeleteModPresetDialog(Live<ModPreset> modPreset)
|
public DeleteModPresetDialog(Live<ModPreset> modPreset)
|
||||||
{
|
{
|
||||||
BodyText = modPreset.PerformRead(preset => preset.Name);
|
BodyText = modPreset.PerformRead(preset => preset.Name);
|
||||||
DeleteAction = () => modPreset.PerformWrite(preset => preset.DeletePending = true);
|
DangerousAction = () => modPreset.PerformWrite(preset => preset.DeletePending = true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,12 +6,12 @@ using osu.Game.Overlays.Dialog;
|
|||||||
|
|
||||||
namespace osu.Game.Overlays.Settings.Sections.Maintenance
|
namespace osu.Game.Overlays.Settings.Sections.Maintenance
|
||||||
{
|
{
|
||||||
public partial class MassDeleteConfirmationDialog : DeleteConfirmationDialog
|
public partial class MassDeleteConfirmationDialog : DangerousActionDialog
|
||||||
{
|
{
|
||||||
public MassDeleteConfirmationDialog(Action deleteAction)
|
public MassDeleteConfirmationDialog(Action deleteAction)
|
||||||
{
|
{
|
||||||
BodyText = "Everything?";
|
BodyText = "Everything?";
|
||||||
DeleteAction = deleteAction;
|
DangerousAction = deleteAction;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
20
osu.Game/Overlays/Settings/SettingsPercentageSlider.cs
Normal file
20
osu.Game/Overlays/Settings/SettingsPercentageSlider.cs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// 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.Graphics;
|
||||||
|
using osu.Game.Configuration;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
|
||||||
|
namespace osu.Game.Overlays.Settings
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A <see cref="SettingsSlider{TValue,TSlider}"/> that displays its value as a percentage by default.
|
||||||
|
/// Mostly provided for convenience of use with <see cref="SettingSourceAttribute"/>.
|
||||||
|
/// </summary>
|
||||||
|
public partial class SettingsPercentageSlider<TValue> : SettingsSlider<TValue>
|
||||||
|
where TValue : struct, IEquatable<TValue>, IComparable<TValue>, IConvertible
|
||||||
|
{
|
||||||
|
protected override Drawable CreateControl() => ((RoundedSliderBar<TValue>)base.CreateControl()).With(sliderBar => sliderBar.DisplayAsPercentage = true);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,75 @@
|
|||||||
|
// 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.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Framework.Graphics.Sprites;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Graphics.Containers;
|
||||||
|
using osu.Game.Graphics.UserInterfaceV2;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Overlays.SkinEditor
|
||||||
|
{
|
||||||
|
public partial class NonSkinnableScreenPlaceholder : CompositeDrawable
|
||||||
|
{
|
||||||
|
[Resolved]
|
||||||
|
private SkinEditorOverlay? skinEditorOverlay { get; set; }
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OverlayColourProvider colourProvider)
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
|
||||||
|
InternalChildren = new Drawable[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
Colour = colourProvider.Dark6,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Alpha = 0.95f,
|
||||||
|
},
|
||||||
|
new FillFlowContainer
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Spacing = new Vector2(0, 5),
|
||||||
|
Direction = FillDirection.Vertical,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new SpriteIcon
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
Icon = FontAwesome.Solid.ExclamationCircle,
|
||||||
|
Size = new Vector2(24),
|
||||||
|
Y = -5,
|
||||||
|
},
|
||||||
|
new OsuTextFlowContainer(t => t.Font = OsuFont.Default.With(weight: FontWeight.SemiBold, size: 18))
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
TextAnchor = Anchor.Centre,
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Text = "Please navigate to a skinnable screen using the scene library",
|
||||||
|
},
|
||||||
|
new RoundedButton
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
Width = 200,
|
||||||
|
Margin = new MarginPadding { Top = 20 },
|
||||||
|
Action = () => skinEditorOverlay?.Hide(),
|
||||||
|
Text = "Return to game"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -7,15 +7,7 @@ using System.Diagnostics;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Graphics;
|
|
||||||
using osu.Framework.Graphics.Containers;
|
|
||||||
using osu.Framework.Graphics.Shapes;
|
|
||||||
using osu.Framework.Graphics.Sprites;
|
|
||||||
using osu.Framework.Input.Events;
|
using osu.Framework.Input.Events;
|
||||||
using osu.Framework.Testing;
|
|
||||||
using osu.Game.Graphics;
|
|
||||||
using osu.Game.Graphics.Containers;
|
|
||||||
using osu.Game.Graphics.UserInterfaceV2;
|
|
||||||
using osu.Game.Rulesets.Edit;
|
using osu.Game.Rulesets.Edit;
|
||||||
using osu.Game.Screens.Edit.Compose.Components;
|
using osu.Game.Screens.Edit.Compose.Components;
|
||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
@ -26,16 +18,16 @@ namespace osu.Game.Overlays.SkinEditor
|
|||||||
{
|
{
|
||||||
public partial class SkinBlueprintContainer : BlueprintContainer<ISerialisableDrawable>
|
public partial class SkinBlueprintContainer : BlueprintContainer<ISerialisableDrawable>
|
||||||
{
|
{
|
||||||
private readonly Drawable target;
|
private readonly ISerialisableDrawableContainer targetContainer;
|
||||||
|
|
||||||
private readonly List<BindableList<ISerialisableDrawable>> targetComponents = new List<BindableList<ISerialisableDrawable>>();
|
private readonly List<BindableList<ISerialisableDrawable>> targetComponents = new List<BindableList<ISerialisableDrawable>>();
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private SkinEditor editor { get; set; } = null!;
|
private SkinEditor editor { get; set; } = null!;
|
||||||
|
|
||||||
public SkinBlueprintContainer(Drawable target)
|
public SkinBlueprintContainer(ISerialisableDrawableContainer targetContainer)
|
||||||
{
|
{
|
||||||
this.target = target;
|
this.targetContainer = targetContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void LoadComplete()
|
protected override void LoadComplete()
|
||||||
@ -44,22 +36,10 @@ namespace osu.Game.Overlays.SkinEditor
|
|||||||
|
|
||||||
SelectedItems.BindTo(editor.SelectedComponents);
|
SelectedItems.BindTo(editor.SelectedComponents);
|
||||||
|
|
||||||
// track each target container on the current screen.
|
var bindableList = new BindableList<ISerialisableDrawable> { BindTarget = targetContainer.Components };
|
||||||
var targetContainers = target.ChildrenOfType<ISerialisableDrawableContainer>().ToArray();
|
bindableList.BindCollectionChanged(componentsChanged, true);
|
||||||
|
|
||||||
if (targetContainers.Length == 0)
|
targetComponents.Add(bindableList);
|
||||||
{
|
|
||||||
AddInternal(new NonSkinnableScreenPlaceholder());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var targetContainer in targetContainers)
|
|
||||||
{
|
|
||||||
var bindableList = new BindableList<ISerialisableDrawable> { BindTarget = targetContainer.Components };
|
|
||||||
bindableList.BindCollectionChanged(componentsChanged, true);
|
|
||||||
|
|
||||||
targetComponents.Add(bindableList);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void componentsChanged(object? sender, NotifyCollectionChangedEventArgs e) => Schedule(() =>
|
private void componentsChanged(object? sender, NotifyCollectionChangedEventArgs e) => Schedule(() =>
|
||||||
@ -160,65 +140,5 @@ namespace osu.Game.Overlays.SkinEditor
|
|||||||
foreach (var list in targetComponents)
|
foreach (var list in targetComponents)
|
||||||
list.UnbindAll();
|
list.UnbindAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
public partial class NonSkinnableScreenPlaceholder : CompositeDrawable
|
|
||||||
{
|
|
||||||
[Resolved]
|
|
||||||
private SkinEditorOverlay? skinEditorOverlay { get; set; }
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load(OverlayColourProvider colourProvider)
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both;
|
|
||||||
|
|
||||||
InternalChildren = new Drawable[]
|
|
||||||
{
|
|
||||||
new Box
|
|
||||||
{
|
|
||||||
Colour = colourProvider.Dark6,
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Alpha = 0.95f,
|
|
||||||
},
|
|
||||||
new FillFlowContainer
|
|
||||||
{
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
AutoSizeAxes = Axes.Y,
|
|
||||||
Spacing = new Vector2(0, 5),
|
|
||||||
Direction = FillDirection.Vertical,
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
new SpriteIcon
|
|
||||||
{
|
|
||||||
Anchor = Anchor.TopCentre,
|
|
||||||
Origin = Anchor.TopCentre,
|
|
||||||
Icon = FontAwesome.Solid.ExclamationCircle,
|
|
||||||
Size = new Vector2(24),
|
|
||||||
Y = -5,
|
|
||||||
},
|
|
||||||
new OsuTextFlowContainer(t => t.Font = OsuFont.Default.With(weight: FontWeight.SemiBold, size: 18))
|
|
||||||
{
|
|
||||||
Anchor = Anchor.TopCentre,
|
|
||||||
Origin = Anchor.TopCentre,
|
|
||||||
TextAnchor = Anchor.Centre,
|
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
AutoSizeAxes = Axes.Y,
|
|
||||||
Text = "Please navigate to a skinnable screen using the scene library",
|
|
||||||
},
|
|
||||||
new RoundedButton
|
|
||||||
{
|
|
||||||
Anchor = Anchor.TopCentre,
|
|
||||||
Origin = Anchor.TopCentre,
|
|
||||||
Width = 200,
|
|
||||||
Margin = new MarginPadding { Top = 20 },
|
|
||||||
Action = () => skinEditorOverlay?.Hide(),
|
|
||||||
Text = "Return to game"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ using osu.Framework.Input;
|
|||||||
using osu.Framework.Input.Bindings;
|
using osu.Framework.Input.Bindings;
|
||||||
using osu.Framework.Input.Events;
|
using osu.Framework.Input.Events;
|
||||||
using osu.Framework.Localisation;
|
using osu.Framework.Localisation;
|
||||||
|
using Web = osu.Game.Resources.Localisation.Web;
|
||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
using osu.Game.Database;
|
using osu.Game.Database;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
@ -24,6 +25,7 @@ using osu.Game.Graphics.Containers;
|
|||||||
using osu.Game.Graphics.Cursor;
|
using osu.Game.Graphics.Cursor;
|
||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterface;
|
||||||
using osu.Game.Localisation;
|
using osu.Game.Localisation;
|
||||||
|
using osu.Game.Overlays.Dialog;
|
||||||
using osu.Game.Overlays.OSD;
|
using osu.Game.Overlays.OSD;
|
||||||
using osu.Game.Overlays.Settings;
|
using osu.Game.Overlays.Settings;
|
||||||
using osu.Game.Screens.Edit;
|
using osu.Game.Screens.Edit;
|
||||||
@ -97,6 +99,9 @@ namespace osu.Game.Overlays.SkinEditor
|
|||||||
[Resolved]
|
[Resolved]
|
||||||
private OnScreenDisplay? onScreenDisplay { get; set; }
|
private OnScreenDisplay? onScreenDisplay { get; set; }
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private IDialogOverlay? dialogOverlay { get; set; }
|
||||||
|
|
||||||
public SkinEditor()
|
public SkinEditor()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -147,8 +152,8 @@ namespace osu.Game.Overlays.SkinEditor
|
|||||||
{
|
{
|
||||||
Items = new[]
|
Items = new[]
|
||||||
{
|
{
|
||||||
new EditorMenuItem(Resources.Localisation.Web.CommonStrings.ButtonsSave, MenuItemType.Standard, () => Save()),
|
new EditorMenuItem(Web.CommonStrings.ButtonsSave, MenuItemType.Standard, () => Save()),
|
||||||
new EditorMenuItem(CommonStrings.RevertToDefault, MenuItemType.Destructive, revert),
|
new EditorMenuItem(CommonStrings.RevertToDefault, MenuItemType.Destructive, () => dialogOverlay?.Push(new RevertConfirmDialog(revert))),
|
||||||
new EditorMenuItemSpacer(),
|
new EditorMenuItemSpacer(),
|
||||||
new EditorMenuItem(CommonStrings.Exit, MenuItemType.Standard, () => skinEditorOverlay?.Hide()),
|
new EditorMenuItem(CommonStrings.Exit, MenuItemType.Standard, () => skinEditorOverlay?.Hide()),
|
||||||
},
|
},
|
||||||
@ -304,7 +309,8 @@ namespace osu.Game.Overlays.SkinEditor
|
|||||||
changeHandler?.Dispose();
|
changeHandler?.Dispose();
|
||||||
|
|
||||||
// Immediately clear the previous blueprint container to ensure it doesn't try to interact with the old target.
|
// Immediately clear the previous blueprint container to ensure it doesn't try to interact with the old target.
|
||||||
content?.Clear();
|
if (content?.Child is SkinBlueprintContainer)
|
||||||
|
content.Clear();
|
||||||
|
|
||||||
Scheduler.AddOnce(loadBlueprintContainer);
|
Scheduler.AddOnce(loadBlueprintContainer);
|
||||||
Scheduler.AddOnce(populateSettings);
|
Scheduler.AddOnce(populateSettings);
|
||||||
@ -323,17 +329,18 @@ namespace osu.Game.Overlays.SkinEditor
|
|||||||
foreach (var toolbox in componentsSidebar.OfType<SkinComponentToolbox>())
|
foreach (var toolbox in componentsSidebar.OfType<SkinComponentToolbox>())
|
||||||
toolbox.Expire();
|
toolbox.Expire();
|
||||||
|
|
||||||
if (target.NewValue == null)
|
componentsSidebar.Clear();
|
||||||
return;
|
SelectedComponents.Clear();
|
||||||
|
|
||||||
Debug.Assert(content != null);
|
Debug.Assert(content != null);
|
||||||
|
|
||||||
SelectedComponents.Clear();
|
|
||||||
|
|
||||||
var skinComponentsContainer = getTarget(target.NewValue);
|
var skinComponentsContainer = getTarget(target.NewValue);
|
||||||
|
|
||||||
if (skinComponentsContainer == null)
|
if (target.NewValue == null || skinComponentsContainer == null)
|
||||||
|
{
|
||||||
|
content.Child = new NonSkinnableScreenPlaceholder();
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
changeHandler = new SkinEditorChangeHandler(skinComponentsContainer);
|
changeHandler = new SkinEditorChangeHandler(skinComponentsContainer);
|
||||||
changeHandler.CanUndo.BindValueChanged(v => undoMenuItem.Action.Disabled = !v.NewValue, true);
|
changeHandler.CanUndo.BindValueChanged(v => undoMenuItem.Action.Disabled = !v.NewValue, true);
|
||||||
@ -668,6 +675,16 @@ namespace osu.Game.Overlays.SkinEditor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public partial class RevertConfirmDialog : DangerousActionDialog
|
||||||
|
{
|
||||||
|
public RevertConfirmDialog(Action revert)
|
||||||
|
{
|
||||||
|
HeaderText = CommonStrings.RevertToDefault;
|
||||||
|
BodyText = SkinEditorStrings.RevertToDefaultDescription;
|
||||||
|
DangerousAction = revert;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#region Delegation of IEditorChangeHandler
|
#region Delegation of IEditorChangeHandler
|
||||||
|
|
||||||
public event Action? OnStateChange
|
public event Action? OnStateChange
|
||||||
|
@ -7,7 +7,6 @@ using System.Linq;
|
|||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Localisation;
|
using osu.Framework.Localisation;
|
||||||
using osu.Game.Configuration;
|
using osu.Game.Configuration;
|
||||||
using osu.Game.Graphics.UserInterface;
|
|
||||||
using osu.Game.Overlays.Settings;
|
using osu.Game.Overlays.Settings;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
using osu.Game.Rulesets.Judgements;
|
using osu.Game.Rulesets.Judgements;
|
||||||
@ -33,7 +32,7 @@ namespace osu.Game.Rulesets.Mods
|
|||||||
|
|
||||||
public override string SettingDescription => base.SettingDescription.Replace(MinimumAccuracy.ToString(), MinimumAccuracy.Value.ToString("##%", NumberFormatInfo.InvariantInfo));
|
public override string SettingDescription => base.SettingDescription.Replace(MinimumAccuracy.ToString(), MinimumAccuracy.Value.ToString("##%", NumberFormatInfo.InvariantInfo));
|
||||||
|
|
||||||
[SettingSource("Minimum accuracy", "Trigger a failure if your accuracy goes below this value.", SettingControlType = typeof(SettingsSlider<double, PercentSlider>))]
|
[SettingSource("Minimum accuracy", "Trigger a failure if your accuracy goes below this value.", SettingControlType = typeof(SettingsPercentageSlider<double>))]
|
||||||
public BindableNumber<double> MinimumAccuracy { get; } = new BindableDouble
|
public BindableNumber<double> MinimumAccuracy { get; } = new BindableDouble
|
||||||
{
|
{
|
||||||
MinValue = 0.60,
|
MinValue = 0.60,
|
||||||
@ -69,12 +68,4 @@ namespace osu.Game.Rulesets.Mods
|
|||||||
return scoreProcessor.ComputeAccuracy(score);
|
return scoreProcessor.ComputeAccuracy(score);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public partial class PercentSlider : RoundedSliderBar<double>
|
|
||||||
{
|
|
||||||
public PercentSlider()
|
|
||||||
{
|
|
||||||
DisplayAsPercentage = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -7,12 +7,12 @@ using osu.Game.Overlays.Dialog;
|
|||||||
|
|
||||||
namespace osu.Game.Screens.Edit
|
namespace osu.Game.Screens.Edit
|
||||||
{
|
{
|
||||||
public partial class DeleteDifficultyConfirmationDialog : DeleteConfirmationDialog
|
public partial class DeleteDifficultyConfirmationDialog : DangerousActionDialog
|
||||||
{
|
{
|
||||||
public DeleteDifficultyConfirmationDialog(BeatmapInfo beatmapInfo, Action deleteAction)
|
public DeleteDifficultyConfirmationDialog(BeatmapInfo beatmapInfo, Action deleteAction)
|
||||||
{
|
{
|
||||||
BodyText = $"\"{beatmapInfo.DifficultyName}\" difficulty";
|
BodyText = $"\"{beatmapInfo.DifficultyName}\" difficulty";
|
||||||
DeleteAction = deleteAction;
|
DangerousAction = deleteAction;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
58
osu.Game/Screens/Play/HUD/PlayerAvatar.cs
Normal file
58
osu.Game/Screens/Play/HUD/PlayerAvatar.cs
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
// 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.Allocation;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Game.Configuration;
|
||||||
|
using osu.Game.Localisation.SkinComponents;
|
||||||
|
using osu.Game.Overlays.Settings;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
using osu.Game.Users.Drawables;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Play.HUD
|
||||||
|
{
|
||||||
|
public partial class PlayerAvatar : CompositeDrawable, ISerialisableDrawable
|
||||||
|
{
|
||||||
|
[SettingSource(typeof(SkinnableComponentStrings), nameof(SkinnableComponentStrings.CornerRadius), nameof(SkinnableComponentStrings.CornerRadiusDescription),
|
||||||
|
SettingControlType = typeof(SettingsPercentageSlider<float>))]
|
||||||
|
public new BindableFloat CornerRadius { get; set; } = new BindableFloat(0.25f)
|
||||||
|
{
|
||||||
|
MinValue = 0,
|
||||||
|
MaxValue = 0.5f,
|
||||||
|
Precision = 0.01f
|
||||||
|
};
|
||||||
|
|
||||||
|
private readonly UpdateableAvatar avatar;
|
||||||
|
|
||||||
|
private const float default_size = 80f;
|
||||||
|
|
||||||
|
public PlayerAvatar()
|
||||||
|
{
|
||||||
|
Size = new Vector2(default_size);
|
||||||
|
|
||||||
|
InternalChild = avatar = new UpdateableAvatar(isInteractive: false)
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Masking = true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(GameplayState gameplayState)
|
||||||
|
{
|
||||||
|
avatar.User = gameplayState.Score.ScoreInfo.User;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
|
||||||
|
CornerRadius.BindValueChanged(e => avatar.CornerRadius = e.NewValue * default_size, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool UsesFixedAnchor { get; set; }
|
||||||
|
}
|
||||||
|
}
|
36
osu.Game/Screens/Play/HUD/PlayerFlag.cs
Normal file
36
osu.Game/Screens/Play/HUD/PlayerFlag.cs
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
// 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.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
using osu.Game.Users.Drawables;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Play.HUD
|
||||||
|
{
|
||||||
|
public partial class PlayerFlag : CompositeDrawable, ISerialisableDrawable
|
||||||
|
{
|
||||||
|
private readonly UpdateableFlag flag;
|
||||||
|
|
||||||
|
private const float default_size = 40f;
|
||||||
|
|
||||||
|
public PlayerFlag()
|
||||||
|
{
|
||||||
|
Size = new Vector2(default_size, default_size / 1.4f);
|
||||||
|
InternalChild = flag = new UpdateableFlag
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(GameplayState gameplayState)
|
||||||
|
{
|
||||||
|
flag.CountryCode = gameplayState.Score.ScoreInfo.User.CountryCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool UsesFixedAnchor { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -10,7 +10,7 @@ using osu.Game.Scoring;
|
|||||||
|
|
||||||
namespace osu.Game.Screens.Select
|
namespace osu.Game.Screens.Select
|
||||||
{
|
{
|
||||||
public partial class BeatmapClearScoresDialog : DeleteConfirmationDialog
|
public partial class BeatmapClearScoresDialog : DangerousActionDialog
|
||||||
{
|
{
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private ScoreManager scoreManager { get; set; } = null!;
|
private ScoreManager scoreManager { get; set; } = null!;
|
||||||
@ -18,7 +18,7 @@ namespace osu.Game.Screens.Select
|
|||||||
public BeatmapClearScoresDialog(BeatmapInfo beatmapInfo, Action onCompletion)
|
public BeatmapClearScoresDialog(BeatmapInfo beatmapInfo, Action onCompletion)
|
||||||
{
|
{
|
||||||
BodyText = $"All local scores on {beatmapInfo.GetDisplayTitle()}";
|
BodyText = $"All local scores on {beatmapInfo.GetDisplayTitle()}";
|
||||||
DeleteAction = () =>
|
DangerousAction = () =>
|
||||||
{
|
{
|
||||||
Task.Run(() => scoreManager.Delete(beatmapInfo))
|
Task.Run(() => scoreManager.Delete(beatmapInfo))
|
||||||
.ContinueWith(_ => onCompletion);
|
.ContinueWith(_ => onCompletion);
|
||||||
|
@ -7,7 +7,7 @@ using osu.Game.Overlays.Dialog;
|
|||||||
|
|
||||||
namespace osu.Game.Screens.Select
|
namespace osu.Game.Screens.Select
|
||||||
{
|
{
|
||||||
public partial class BeatmapDeleteDialog : DeleteConfirmationDialog
|
public partial class BeatmapDeleteDialog : DangerousActionDialog
|
||||||
{
|
{
|
||||||
private readonly BeatmapSetInfo beatmapSet;
|
private readonly BeatmapSetInfo beatmapSet;
|
||||||
|
|
||||||
@ -20,7 +20,7 @@ namespace osu.Game.Screens.Select
|
|||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(BeatmapManager beatmapManager)
|
private void load(BeatmapManager beatmapManager)
|
||||||
{
|
{
|
||||||
DeleteAction = () => beatmapManager.Delete(beatmapSet);
|
DangerousAction = () => beatmapManager.Delete(beatmapSet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,7 @@ namespace osu.Game.Screens.Select.Carousel
|
|||||||
if (!(other is CarouselBeatmapSet otherSet))
|
if (!(other is CarouselBeatmapSet otherSet))
|
||||||
return base.CompareTo(criteria, other);
|
return base.CompareTo(criteria, other);
|
||||||
|
|
||||||
int comparison = 0;
|
int comparison;
|
||||||
|
|
||||||
switch (criteria.Sort)
|
switch (criteria.Sort)
|
||||||
{
|
{
|
||||||
@ -87,11 +87,7 @@ namespace osu.Game.Screens.Select.Carousel
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SortMode.DateRanked:
|
case SortMode.DateRanked:
|
||||||
// Beatmaps which have no ranked date should already be filtered away in this mode.
|
comparison = Nullable.Compare(otherSet.BeatmapSet.DateRanked, BeatmapSet.DateRanked);
|
||||||
if (BeatmapSet.DateRanked == null || otherSet.BeatmapSet.DateRanked == null)
|
|
||||||
break;
|
|
||||||
|
|
||||||
comparison = otherSet.BeatmapSet.DateRanked.Value.CompareTo(BeatmapSet.DateRanked.Value);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SortMode.LastPlayed:
|
case SortMode.LastPlayed:
|
||||||
@ -111,11 +107,7 @@ namespace osu.Game.Screens.Select.Carousel
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SortMode.DateSubmitted:
|
case SortMode.DateSubmitted:
|
||||||
// Beatmaps which have no submitted date should already be filtered away in this mode.
|
comparison = Nullable.Compare(otherSet.BeatmapSet.DateSubmitted, BeatmapSet.DateSubmitted);
|
||||||
if (BeatmapSet.DateSubmitted == null || otherSet.BeatmapSet.DateSubmitted == null)
|
|
||||||
break;
|
|
||||||
|
|
||||||
comparison = otherSet.BeatmapSet.DateSubmitted.Value.CompareTo(BeatmapSet.DateSubmitted.Value);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,12 +145,7 @@ namespace osu.Game.Screens.Select.Carousel
|
|||||||
{
|
{
|
||||||
base.Filter(criteria);
|
base.Filter(criteria);
|
||||||
|
|
||||||
bool filtered = Items.All(i => i.Filtered.Value);
|
Filtered.Value = Items.All(i => i.Filtered.Value);
|
||||||
|
|
||||||
filtered |= criteria.Sort == SortMode.DateRanked && BeatmapSet.DateRanked == null;
|
|
||||||
filtered |= criteria.Sort == SortMode.DateSubmitted && BeatmapSet.DateSubmitted == null;
|
|
||||||
|
|
||||||
Filtered.Value = filtered;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString() => BeatmapSet.ToString();
|
public override string ToString() => BeatmapSet.ToString();
|
||||||
|
@ -8,14 +8,14 @@ using osu.Game.Localisation;
|
|||||||
|
|
||||||
namespace osu.Game.Screens.Select.Carousel
|
namespace osu.Game.Screens.Select.Carousel
|
||||||
{
|
{
|
||||||
public partial class UpdateLocalConfirmationDialog : DeleteConfirmationDialog
|
public partial class UpdateLocalConfirmationDialog : DangerousActionDialog
|
||||||
{
|
{
|
||||||
public UpdateLocalConfirmationDialog(Action onConfirm)
|
public UpdateLocalConfirmationDialog(Action onConfirm)
|
||||||
{
|
{
|
||||||
HeaderText = PopupDialogStrings.UpdateLocallyModifiedText;
|
HeaderText = PopupDialogStrings.UpdateLocallyModifiedText;
|
||||||
BodyText = PopupDialogStrings.UpdateLocallyModifiedDescription;
|
BodyText = PopupDialogStrings.UpdateLocallyModifiedDescription;
|
||||||
Icon = FontAwesome.Solid.ExclamationTriangle;
|
Icon = FontAwesome.Solid.ExclamationTriangle;
|
||||||
DeleteAction = onConfirm;
|
DangerousAction = onConfirm;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ using osu.Game.Beatmaps;
|
|||||||
|
|
||||||
namespace osu.Game.Screens.Select
|
namespace osu.Game.Screens.Select
|
||||||
{
|
{
|
||||||
public partial class LocalScoreDeleteDialog : DeleteConfirmationDialog
|
public partial class LocalScoreDeleteDialog : DangerousActionDialog
|
||||||
{
|
{
|
||||||
private readonly ScoreInfo score;
|
private readonly ScoreInfo score;
|
||||||
|
|
||||||
@ -28,7 +28,7 @@ namespace osu.Game.Screens.Select
|
|||||||
BodyText = $"{score.User} ({score.DisplayAccuracy}, {score.Rank})";
|
BodyText = $"{score.User} ({score.DisplayAccuracy}, {score.Rank})";
|
||||||
|
|
||||||
Icon = FontAwesome.Regular.TrashAlt;
|
Icon = FontAwesome.Regular.TrashAlt;
|
||||||
DeleteAction = () => scoreManager.Delete(score);
|
DangerousAction = () => scoreManager.Delete(score);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ using osu.Game.Overlays.Dialog;
|
|||||||
|
|
||||||
namespace osu.Game.Screens.Select
|
namespace osu.Game.Screens.Select
|
||||||
{
|
{
|
||||||
public partial class SkinDeleteDialog : DeleteConfirmationDialog
|
public partial class SkinDeleteDialog : DangerousActionDialog
|
||||||
{
|
{
|
||||||
private readonly Skin skin;
|
private readonly Skin skin;
|
||||||
|
|
||||||
@ -20,7 +20,7 @@ namespace osu.Game.Screens.Select
|
|||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(SkinManager manager)
|
private void load(SkinManager manager)
|
||||||
{
|
{
|
||||||
DeleteAction = () =>
|
DangerousAction = () =>
|
||||||
{
|
{
|
||||||
manager.Delete(skin.SkinInfo.Value);
|
manager.Delete(skin.SkinInfo.Value);
|
||||||
manager.CurrentSkinInfo.SetDefault();
|
manager.CurrentSkinInfo.SetDefault();
|
||||||
|
@ -58,7 +58,11 @@ namespace osu.Game.Storyboards.Drawables
|
|||||||
using (drawableVideo.BeginAbsoluteSequence(Video.StartTime))
|
using (drawableVideo.BeginAbsoluteSequence(Video.StartTime))
|
||||||
{
|
{
|
||||||
Schedule(() => drawableVideo.PlaybackPosition = Time.Current - Video.StartTime);
|
Schedule(() => drawableVideo.PlaybackPosition = Time.Current - Video.StartTime);
|
||||||
|
|
||||||
drawableVideo.FadeIn(500);
|
drawableVideo.FadeIn(500);
|
||||||
|
|
||||||
|
using (drawableVideo.BeginDelayedSequence(drawableVideo.Duration - 500))
|
||||||
|
drawableVideo.FadeOut(500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
@ -30,14 +28,14 @@ namespace osu.Game.Users.Drawables
|
|||||||
/// Perform an action in addition to showing the country ranking.
|
/// Perform an action in addition to showing the country ranking.
|
||||||
/// This should be used to perform auxiliary tasks and not as a primary action for clicking a flag (to maintain a consistent UX).
|
/// This should be used to perform auxiliary tasks and not as a primary action for clicking a flag (to maintain a consistent UX).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Action Action;
|
public Action? Action;
|
||||||
|
|
||||||
public UpdateableFlag(CountryCode countryCode = CountryCode.Unknown)
|
public UpdateableFlag(CountryCode countryCode = CountryCode.Unknown)
|
||||||
{
|
{
|
||||||
CountryCode = countryCode;
|
CountryCode = countryCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override Drawable CreateDrawable(CountryCode countryCode)
|
protected override Drawable? CreateDrawable(CountryCode countryCode)
|
||||||
{
|
{
|
||||||
if (countryCode == CountryCode.Unknown && !ShowPlaceholderOnUnknown)
|
if (countryCode == CountryCode.Unknown && !ShowPlaceholderOnUnknown)
|
||||||
return null;
|
return null;
|
||||||
@ -56,8 +54,8 @@ namespace osu.Game.Users.Drawables
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
[Resolved(canBeNull: true)]
|
[Resolved]
|
||||||
private RankingsOverlay rankingsOverlay { get; set; }
|
private RankingsOverlay? rankingsOverlay { get; set; }
|
||||||
|
|
||||||
protected override bool OnClick(ClickEvent e)
|
protected override bool OnClick(ClickEvent e)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user