mirror of
https://github.com/ppy/osu.git
synced 2024-12-15 04:13:00 +08:00
Merge remote-tracking branch 'upstream/master' into LegacyDecoder_changes
This commit is contained in:
commit
50ab5a7d07
20
.idea/.idea.osu.Desktop/.idea/runConfigurations/osu_SDL.xml
Normal file
20
.idea/.idea.osu.Desktop/.idea/runConfigurations/osu_SDL.xml
Normal file
@ -0,0 +1,20 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="osu! SDL" type="DotNetProject" factoryName=".NET Project" folderName="osu!">
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Desktop/bin/Debug/netcoreapp3.1/osu!.dll" />
|
||||
<option name="PROGRAM_PARAMETERS" value="--sdl" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Desktop" />
|
||||
<option name="PASS_PARENT_ENVS" value="1" />
|
||||
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
||||
<option name="USE_MONO" value="0" />
|
||||
<option name="RUNTIME_ARGUMENTS" value="" />
|
||||
<option name="PROJECT_PATH" value="$PROJECT_DIR$/osu.Desktop/osu.Desktop.csproj" />
|
||||
<option name="PROJECT_EXE_PATH_TRACKING" value="1" />
|
||||
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
||||
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
||||
<option name="PROJECT_KIND" value="DotNetCore" />
|
||||
<option name="PROJECT_TFM" value=".NETCoreApp,Version=v3.0" />
|
||||
<method v="2">
|
||||
<option name="Build" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
@ -40,7 +40,7 @@
|
||||
<RepositoryUrl>https://github.com/ppy/osu</RepositoryUrl>
|
||||
<PackageReleaseNotes>Automated release.</PackageReleaseNotes>
|
||||
<Company>ppy Pty Ltd</Company>
|
||||
<Copyright>Copyright (c) 2019 ppy Pty Ltd</Copyright>
|
||||
<Copyright>Copyright (c) 2020 ppy Pty Ltd</Copyright>
|
||||
<PackageTags>osu game</PackageTags>
|
||||
</PropertyGroup>
|
||||
</Project>
|
74
Gemfile.lock
74
Gemfile.lock
@ -1,7 +1,7 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
CFPropertyList (3.0.1)
|
||||
CFPropertyList (3.0.2)
|
||||
addressable (2.7.0)
|
||||
public_suffix (>= 2.0.2, < 5.0)
|
||||
atomos (0.1.3)
|
||||
@ -18,8 +18,8 @@ GEM
|
||||
unf (>= 0.0.5, < 1.0.0)
|
||||
dotenv (2.7.5)
|
||||
emoji_regex (1.0.1)
|
||||
excon (0.67.0)
|
||||
faraday (0.15.4)
|
||||
excon (0.71.1)
|
||||
faraday (0.17.3)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
faraday-cookie_jar (0.0.6)
|
||||
faraday (>= 0.7.4)
|
||||
@ -27,7 +27,7 @@ GEM
|
||||
faraday_middleware (0.13.1)
|
||||
faraday (>= 0.7.4, < 1.0)
|
||||
fastimage (2.1.7)
|
||||
fastlane (2.133.0)
|
||||
fastlane (2.140.0)
|
||||
CFPropertyList (>= 2.3, < 4.0.0)
|
||||
addressable (>= 2.3, < 3.0.0)
|
||||
babosa (>= 1.0.2, < 2.0.0)
|
||||
@ -36,13 +36,13 @@ GEM
|
||||
commander-fastlane (>= 4.4.6, < 5.0.0)
|
||||
dotenv (>= 2.1.1, < 3.0.0)
|
||||
emoji_regex (>= 0.1, < 2.0)
|
||||
excon (>= 0.45.0, < 1.0.0)
|
||||
faraday (< 0.16.0)
|
||||
excon (>= 0.71.0, < 1.0.0)
|
||||
faraday (~> 0.17)
|
||||
faraday-cookie_jar (~> 0.0.6)
|
||||
faraday_middleware (< 0.16.0)
|
||||
faraday_middleware (~> 0.13.1)
|
||||
fastimage (>= 2.1.0, < 3.0.0)
|
||||
gh_inspector (>= 1.1.2, < 2.0.0)
|
||||
google-api-client (>= 0.21.2, < 0.24.0)
|
||||
google-api-client (>= 0.29.2, < 0.37.0)
|
||||
google-cloud-storage (>= 1.15.0, < 2.0.0)
|
||||
highline (>= 1.7.2, < 2.0.0)
|
||||
json (< 3.0.0)
|
||||
@ -61,56 +61,58 @@ GEM
|
||||
tty-screen (>= 0.6.3, < 1.0.0)
|
||||
tty-spinner (>= 0.8.0, < 1.0.0)
|
||||
word_wrap (~> 1.0.0)
|
||||
xcodeproj (>= 1.8.1, < 2.0.0)
|
||||
xcodeproj (>= 1.13.0, < 2.0.0)
|
||||
xcpretty (~> 0.3.0)
|
||||
xcpretty-travis-formatter (>= 0.0.3)
|
||||
fastlane-plugin-clean_testflight_testers (0.3.0)
|
||||
fastlane-plugin-souyuz (0.8.1)
|
||||
souyuz (>= 0.8.1)
|
||||
fastlane-plugin-souyuz (0.9.1)
|
||||
souyuz (= 0.9.1)
|
||||
fastlane-plugin-xamarin (0.6.3)
|
||||
gh_inspector (1.1.3)
|
||||
google-api-client (0.23.9)
|
||||
google-api-client (0.36.4)
|
||||
addressable (~> 2.5, >= 2.5.1)
|
||||
googleauth (>= 0.5, < 0.7.0)
|
||||
googleauth (~> 0.9)
|
||||
httpclient (>= 2.8.1, < 3.0)
|
||||
mime-types (~> 3.0)
|
||||
mini_mime (~> 1.0)
|
||||
representable (~> 3.0)
|
||||
retriable (>= 2.0, < 4.0)
|
||||
signet (~> 0.9)
|
||||
google-cloud-core (1.3.1)
|
||||
signet (~> 0.12)
|
||||
google-cloud-core (1.5.0)
|
||||
google-cloud-env (~> 1.0)
|
||||
google-cloud-env (1.2.1)
|
||||
google-cloud-errors (~> 1.0)
|
||||
google-cloud-env (1.3.0)
|
||||
faraday (~> 0.11)
|
||||
google-cloud-storage (1.16.0)
|
||||
google-cloud-errors (1.0.0)
|
||||
google-cloud-storage (1.25.1)
|
||||
addressable (~> 2.5)
|
||||
digest-crc (~> 0.4)
|
||||
google-api-client (~> 0.23)
|
||||
google-api-client (~> 0.33)
|
||||
google-cloud-core (~> 1.2)
|
||||
googleauth (>= 0.6.2, < 0.10.0)
|
||||
googleauth (0.6.7)
|
||||
googleauth (~> 0.9)
|
||||
mini_mime (~> 1.0)
|
||||
googleauth (0.10.0)
|
||||
faraday (~> 0.12)
|
||||
jwt (>= 1.4, < 3.0)
|
||||
memoist (~> 0.16)
|
||||
multi_json (~> 1.11)
|
||||
os (>= 0.9, < 2.0)
|
||||
signet (~> 0.7)
|
||||
signet (~> 0.12)
|
||||
highline (1.7.10)
|
||||
http-cookie (1.0.3)
|
||||
domain_name (~> 0.5)
|
||||
httpclient (2.8.3)
|
||||
json (2.2.0)
|
||||
json (2.3.0)
|
||||
jwt (2.1.0)
|
||||
memoist (0.16.0)
|
||||
mime-types (3.3)
|
||||
mime-types-data (~> 3.2015)
|
||||
mime-types-data (3.2019.1009)
|
||||
mini_magick (4.9.5)
|
||||
memoist (0.16.2)
|
||||
mini_magick (4.10.1)
|
||||
mini_mime (1.0.2)
|
||||
mini_portile2 (2.4.0)
|
||||
multi_json (1.13.1)
|
||||
multi_json (1.14.1)
|
||||
multi_xml (0.6.0)
|
||||
multipart-post (2.0.0)
|
||||
nanaimo (0.2.6)
|
||||
naturally (2.2.0)
|
||||
nokogiri (1.10.4)
|
||||
nokogiri (1.10.7)
|
||||
mini_portile2 (~> 2.4.0)
|
||||
os (1.0.1)
|
||||
plist (3.5.0)
|
||||
@ -128,12 +130,12 @@ GEM
|
||||
faraday (~> 0.9)
|
||||
jwt (>= 1.5, < 3.0)
|
||||
multi_json (~> 1.10)
|
||||
simctl (1.6.6)
|
||||
simctl (1.6.7)
|
||||
CFPropertyList
|
||||
naturally
|
||||
slack-notifier (2.3.2)
|
||||
souyuz (0.8.1)
|
||||
fastlane (>= 2.29.0)
|
||||
souyuz (0.9.1)
|
||||
fastlane (>= 1.103.0)
|
||||
highline (~> 1.7)
|
||||
nokogiri (~> 1.7)
|
||||
terminal-notifier (2.0.0)
|
||||
@ -141,15 +143,15 @@ GEM
|
||||
unicode-display_width (~> 1.1, >= 1.1.1)
|
||||
tty-cursor (0.7.0)
|
||||
tty-screen (0.7.0)
|
||||
tty-spinner (0.9.1)
|
||||
tty-spinner (0.9.2)
|
||||
tty-cursor (~> 0.7)
|
||||
uber (0.1.0)
|
||||
unf (0.1.4)
|
||||
unf_ext
|
||||
unf_ext (0.0.7.6)
|
||||
unicode-display_width (1.6.0)
|
||||
unicode-display_width (1.6.1)
|
||||
word_wrap (1.0.0)
|
||||
xcodeproj (1.12.0)
|
||||
xcodeproj (1.14.0)
|
||||
CFPropertyList (>= 2.3.3, < 4.0)
|
||||
atomos (~> 0.1.3)
|
||||
claide (>= 1.0.2, < 2.0)
|
||||
|
2
LICENCE
2
LICENCE
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2019 ppy Pty Ltd <contact@ppy.sh>.
|
||||
Copyright (c) 2020 ppy Pty Ltd <contact@ppy.sh>.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -111,7 +111,6 @@ platform :ios do
|
||||
|
||||
souyuz(
|
||||
platform: "ios",
|
||||
build_target: "osu_iOS",
|
||||
plist_path: "../osu.iOS/Info.plist"
|
||||
)
|
||||
end
|
||||
|
@ -54,6 +54,6 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2019.1230.0" />
|
||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2020.111.0" />
|
||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2020.125.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
@ -22,8 +22,9 @@ namespace osu.Desktop
|
||||
{
|
||||
// Back up the cwd before DesktopGameHost changes it
|
||||
var cwd = Environment.CurrentDirectory;
|
||||
bool useSdl = args.Contains("--sdl");
|
||||
|
||||
using (DesktopGameHost host = Host.GetSuitableHost(@"osu", true))
|
||||
using (DesktopGameHost host = Host.GetSuitableHost(@"osu", true, useSdl: useSdl))
|
||||
{
|
||||
host.ExceptionThrown += handleException;
|
||||
|
||||
|
@ -12,7 +12,7 @@
|
||||
<description>click the circles. to the beat.</description>
|
||||
<summary>click the circles.</summary>
|
||||
<releaseNotes>testing</releaseNotes>
|
||||
<copyright>Copyright (c) 2019 ppy Pty Ltd</copyright>
|
||||
<copyright>Copyright (c) 2020 ppy Pty Ltd</copyright>
|
||||
<language>en-AU</language>
|
||||
</metadata>
|
||||
<files>
|
||||
|
@ -36,7 +36,10 @@ namespace osu.Game.Rulesets.Catch.Mods
|
||||
|
||||
//disable keyboard controls
|
||||
public bool OnPressed(CatchAction action) => true;
|
||||
public bool OnReleased(CatchAction action) => true;
|
||||
|
||||
public void OnReleased(CatchAction action)
|
||||
{
|
||||
}
|
||||
|
||||
protected override bool OnMouseMove(MouseMoveEvent e)
|
||||
{
|
||||
|
@ -103,7 +103,9 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
MovableCatcher.X = state.CatcherX.Value;
|
||||
}
|
||||
|
||||
public bool OnReleased(CatchAction action) => false;
|
||||
public void OnReleased(CatchAction action)
|
||||
{
|
||||
}
|
||||
|
||||
public bool AttemptCatch(CatchHitObject obj) => MovableCatcher.AttemptCatch(obj);
|
||||
|
||||
@ -341,24 +343,22 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool OnReleased(CatchAction action)
|
||||
public void OnReleased(CatchAction action)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case CatchAction.MoveLeft:
|
||||
currentDirection++;
|
||||
return true;
|
||||
break;
|
||||
|
||||
case CatchAction.MoveRight:
|
||||
currentDirection--;
|
||||
return true;
|
||||
break;
|
||||
|
||||
case CatchAction.Dash:
|
||||
Dashing = false;
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -54,10 +54,10 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override bool OnMouseUp(MouseUpEvent e)
|
||||
protected override void OnMouseUp(MouseUpEvent e)
|
||||
{
|
||||
EndPlacement();
|
||||
return base.OnMouseUp(e);
|
||||
base.OnMouseUp(e);
|
||||
}
|
||||
|
||||
public override void UpdatePosition(Vector2 screenSpacePosition)
|
||||
|
@ -13,7 +13,7 @@ using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Edit.Blueprints
|
||||
{
|
||||
public class ManiaSelectionBlueprint : SelectionBlueprint
|
||||
public class ManiaSelectionBlueprint : OverlaySelectionBlueprint
|
||||
{
|
||||
public Vector2 ScreenSpaceDragPosition { get; private set; }
|
||||
public Vector2 DragPosition { get; private set; }
|
||||
@ -55,14 +55,12 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints
|
||||
return base.OnMouseDown(e);
|
||||
}
|
||||
|
||||
protected override bool OnDrag(DragEvent e)
|
||||
protected override void OnDrag(DragEvent e)
|
||||
{
|
||||
var result = base.OnDrag(e);
|
||||
base.OnDrag(e);
|
||||
|
||||
ScreenSpaceDragPosition = e.ScreenSpaceMousePosition;
|
||||
DragPosition = DrawableObject.ToLocalSpace(e.ScreenSpaceMousePosition);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override void Show()
|
||||
|
34
osu.Game.Rulesets.Mania/Edit/ManiaBlueprintContainer.cs
Normal file
34
osu.Game.Rulesets.Mania/Edit/ManiaBlueprintContainer.cs
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Mania.Edit.Blueprints;
|
||||
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Screens.Edit.Compose.Components;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Edit
|
||||
{
|
||||
public class ManiaBlueprintContainer : ComposeBlueprintContainer
|
||||
{
|
||||
public ManiaBlueprintContainer(IEnumerable<DrawableHitObject> drawableHitObjects)
|
||||
: base(drawableHitObjects)
|
||||
{
|
||||
}
|
||||
|
||||
public override OverlaySelectionBlueprint CreateBlueprintFor(DrawableHitObject hitObject)
|
||||
{
|
||||
switch (hitObject)
|
||||
{
|
||||
case DrawableNote note:
|
||||
return new NoteSelectionBlueprint(note);
|
||||
|
||||
case DrawableHoldNote holdNote:
|
||||
return new HoldNoteSelectionBlueprint(holdNote);
|
||||
}
|
||||
|
||||
return base.CreateBlueprintFor(hitObject);
|
||||
}
|
||||
}
|
||||
}
|
@ -5,11 +5,8 @@ using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Edit.Tools;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game.Rulesets.Mania.Edit.Blueprints;
|
||||
using osu.Game.Rulesets.Mania.UI;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.UI;
|
||||
@ -52,26 +49,12 @@ namespace osu.Game.Rulesets.Mania.Edit
|
||||
return drawableRuleset;
|
||||
}
|
||||
|
||||
protected override ComposeBlueprintContainer CreateBlueprintContainer() => new ManiaBlueprintContainer(drawableRuleset.Playfield.AllHitObjects);
|
||||
|
||||
protected override IReadOnlyList<HitObjectCompositionTool> CompositionTools => new HitObjectCompositionTool[]
|
||||
{
|
||||
new NoteCompositionTool(),
|
||||
new HoldNoteCompositionTool()
|
||||
};
|
||||
|
||||
public override SelectionHandler CreateSelectionHandler() => new ManiaSelectionHandler();
|
||||
|
||||
public override SelectionBlueprint CreateBlueprintFor(DrawableHitObject hitObject)
|
||||
{
|
||||
switch (hitObject)
|
||||
{
|
||||
case DrawableNote note:
|
||||
return new NoteSelectionBlueprint(note);
|
||||
|
||||
case DrawableHoldNote holdNote:
|
||||
return new HoldNoteSelectionBlueprint(holdNote);
|
||||
}
|
||||
|
||||
return base.CreateBlueprintFor(hitObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ using System;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Mania.Edit.Blueprints;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
using osu.Game.Rulesets.UI;
|
||||
@ -70,10 +71,12 @@ namespace osu.Game.Rulesets.Mania.Edit
|
||||
// When scrolling downwards the anchor position is at the bottom of the screen, however the movement event assumes the anchor is at the top of the screen.
|
||||
// This causes the delta to assume a positive hitobject position, and which can be corrected for by subtracting the parent height.
|
||||
if (scrollingInfo.Direction.Value == ScrollingDirection.Down)
|
||||
delta -= moveEvent.Blueprint.DrawableObject.Parent.DrawHeight;
|
||||
delta -= moveEvent.Blueprint.Parent.DrawHeight; // todo: probably wrong
|
||||
|
||||
foreach (var b in SelectedBlueprints)
|
||||
foreach (var selectionBlueprint in SelectedBlueprints)
|
||||
{
|
||||
var b = (OverlaySelectionBlueprint)selectionBlueprint;
|
||||
|
||||
var hitObject = b.DrawableObject;
|
||||
var objectParent = (HitObjectContainer)hitObject.Parent;
|
||||
|
||||
|
@ -7,7 +7,7 @@ using osu.Game.Rulesets.Objects.Drawables;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Edit.Masks
|
||||
{
|
||||
public abstract class ManiaSelectionBlueprint : SelectionBlueprint
|
||||
public abstract class ManiaSelectionBlueprint : OverlaySelectionBlueprint
|
||||
{
|
||||
protected ManiaSelectionBlueprint(DrawableHitObject drawableObject)
|
||||
: base(drawableObject)
|
||||
|
@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.Mania.Mods
|
||||
{
|
||||
public override string Name => "Fade In";
|
||||
public override string Acronym => "FI";
|
||||
public override IconUsage Icon => OsuIcon.ModHidden;
|
||||
public override IconUsage? Icon => OsuIcon.ModHidden;
|
||||
public override ModType Type => ModType.DifficultyIncrease;
|
||||
public override string Description => @"Keys appear out of nowhere!";
|
||||
public override double ScoreMultiplier => 1;
|
||||
|
@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Mania.Mods
|
||||
public override string Name => "Random";
|
||||
public override string Acronym => "RD";
|
||||
public override ModType Type => ModType.Conversion;
|
||||
public override IconUsage Icon => OsuIcon.Dice;
|
||||
public override IconUsage? Icon => OsuIcon.Dice;
|
||||
public override string Description => @"Shuffle around the keys!";
|
||||
public override double ScoreMultiplier => 1;
|
||||
|
||||
|
@ -171,17 +171,17 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
bodyPiece.Hitting = true;
|
||||
}
|
||||
|
||||
public bool OnReleased(ManiaAction action)
|
||||
public void OnReleased(ManiaAction action)
|
||||
{
|
||||
if (AllJudged)
|
||||
return false;
|
||||
return;
|
||||
|
||||
if (action != Action.Value)
|
||||
return false;
|
||||
return;
|
||||
|
||||
// Make sure a hold was started
|
||||
if (HoldStartTime == null)
|
||||
return false;
|
||||
return;
|
||||
|
||||
Tail.UpdateResult();
|
||||
endHold();
|
||||
@ -189,8 +189,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
// If the key has been released too early, the user should not receive full score for the release
|
||||
if (!Tail.IsHit)
|
||||
HasBroken = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void endHold()
|
||||
|
@ -17,6 +17,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
|
||||
public override bool OnPressed(ManiaAction action) => false; // Handled by the hold note
|
||||
|
||||
public override bool OnReleased(ManiaAction action) => false; // Handled by the hold note
|
||||
public override void OnReleased(ManiaAction action)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -59,6 +59,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
|
||||
public override bool OnPressed(ManiaAction action) => false; // Handled by the hold note
|
||||
|
||||
public override bool OnReleased(ManiaAction action) => false; // Handled by the hold note
|
||||
public override void OnReleased(ManiaAction action)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -77,6 +77,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
return UpdateResult(true);
|
||||
}
|
||||
|
||||
public virtual bool OnReleased(ManiaAction action) => false;
|
||||
public virtual void OnReleased(ManiaAction action)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -191,7 +191,9 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool OnReleased(ManiaAction action) => false;
|
||||
public void OnReleased(ManiaAction action)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos)
|
||||
// This probably shouldn't exist as is, but the columns in the stage are separated by a 1px border
|
||||
|
@ -98,11 +98,10 @@ namespace osu.Game.Rulesets.Mania.UI.Components
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool OnReleased(ManiaAction action)
|
||||
public void OnReleased(ManiaAction action)
|
||||
{
|
||||
if (action == this.action.Value)
|
||||
backgroundOverlay.FadeTo(0, 250, Easing.OutQuint);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -115,11 +115,10 @@ namespace osu.Game.Rulesets.Mania.UI.Components
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool OnReleased(ManiaAction action)
|
||||
public void OnReleased(ManiaAction action)
|
||||
{
|
||||
if (action == this.action.Value)
|
||||
keyIcon.ScaleTo(1f, 125, Easing.OutQuint);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,10 +7,10 @@ using osu.Game.Rulesets.Osu.Objects;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Edit.Blueprints
|
||||
{
|
||||
public abstract class OsuSelectionBlueprint<T> : SelectionBlueprint
|
||||
public abstract class OsuSelectionBlueprint<T> : OverlaySelectionBlueprint
|
||||
where T : OsuHitObject
|
||||
{
|
||||
protected T HitObject => (T)DrawableObject.HitObject;
|
||||
protected new T HitObject => (T)DrawableObject.HitObject;
|
||||
|
||||
protected OsuSelectionBlueprint(DrawableHitObject drawableObject)
|
||||
: base(drawableObject)
|
||||
|
@ -135,13 +135,11 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override bool OnMouseUp(MouseUpEvent e) => RequestSelection != null;
|
||||
|
||||
protected override bool OnClick(ClickEvent e) => RequestSelection != null;
|
||||
|
||||
protected override bool OnDragStart(DragStartEvent e) => e.Button == MouseButton.Left;
|
||||
|
||||
protected override bool OnDrag(DragEvent e)
|
||||
protected override void OnDrag(DragEvent e)
|
||||
{
|
||||
if (ControlPoint == slider.Path.ControlPoints[0])
|
||||
{
|
||||
@ -158,12 +156,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
|
||||
}
|
||||
else
|
||||
ControlPoint.Position.Value += e.Delta;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override bool OnDragEnd(DragEndEvent e) => true;
|
||||
|
||||
/// <summary>
|
||||
/// Updates the state of the circular control point marker.
|
||||
/// </summary>
|
||||
|
@ -108,7 +108,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool OnReleased(PlatformAction action) => action.ActionMethod == PlatformActionMethod.Delete;
|
||||
public void OnReleased(PlatformAction action)
|
||||
{
|
||||
}
|
||||
|
||||
private void selectPiece(PathControlPointPiece piece, MouseButtonEvent e)
|
||||
{
|
||||
|
@ -17,6 +17,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
|
||||
: base(slider)
|
||||
{
|
||||
this.position = position;
|
||||
|
||||
InternalChild = CirclePiece = new HitCirclePiece();
|
||||
|
||||
Select();
|
||||
|
@ -106,11 +106,11 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override bool OnMouseUp(MouseUpEvent e)
|
||||
protected override void OnMouseUp(MouseUpEvent e)
|
||||
{
|
||||
if (state == PlacementState.Body && e.Button == MouseButton.Right)
|
||||
endCurve();
|
||||
return base.OnMouseUp(e);
|
||||
base.OnMouseUp(e);
|
||||
}
|
||||
|
||||
protected override bool OnDoubleClick(DoubleClickEvent e)
|
||||
|
@ -90,19 +90,16 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
|
||||
|
||||
protected override bool OnDragStart(DragStartEvent e) => placementControlPointIndex != null;
|
||||
|
||||
protected override bool OnDrag(DragEvent e)
|
||||
protected override void OnDrag(DragEvent e)
|
||||
{
|
||||
Debug.Assert(placementControlPointIndex != null);
|
||||
|
||||
HitObject.Path.ControlPoints[placementControlPointIndex.Value].Position.Value = e.MousePosition - HitObject.Position;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override bool OnDragEnd(DragEndEvent e)
|
||||
protected override void OnDragEnd(DragEndEvent e)
|
||||
{
|
||||
placementControlPointIndex = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
private BindableList<PathControlPoint> controlPoints => HitObject.Path.ControlPoints;
|
||||
@ -173,7 +170,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
|
||||
new OsuMenuItem("Add control point", MenuItemType.Standard, () => addControlPoint(rightClickPosition)),
|
||||
};
|
||||
|
||||
public override Vector2 SelectionPoint => HeadBlueprint.SelectionPoint;
|
||||
public override Vector2 SelectionPoint => ((DrawableSlider)DrawableObject).HeadCircle.ScreenSpaceDrawQuad.Centre;
|
||||
|
||||
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => BodyPiece.ReceivePositionalInputAt(screenSpacePos);
|
||||
|
||||
|
41
osu.Game.Rulesets.Osu/Edit/OsuBlueprintContainer.cs
Normal file
41
osu.Game.Rulesets.Osu/Edit/OsuBlueprintContainer.cs
Normal file
@ -0,0 +1,41 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles;
|
||||
using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders;
|
||||
using osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||
using osu.Game.Screens.Edit.Compose.Components;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Edit
|
||||
{
|
||||
public class OsuBlueprintContainer : ComposeBlueprintContainer
|
||||
{
|
||||
public OsuBlueprintContainer(IEnumerable<DrawableHitObject> drawableHitObjects)
|
||||
: base(drawableHitObjects)
|
||||
{
|
||||
}
|
||||
|
||||
protected override SelectionHandler CreateSelectionHandler() => new OsuSelectionHandler();
|
||||
|
||||
public override OverlaySelectionBlueprint CreateBlueprintFor(DrawableHitObject hitObject)
|
||||
{
|
||||
switch (hitObject)
|
||||
{
|
||||
case DrawableHitCircle circle:
|
||||
return new HitCircleSelectionBlueprint(circle);
|
||||
|
||||
case DrawableSlider slider:
|
||||
return new SliderSelectionBlueprint(slider);
|
||||
|
||||
case DrawableSpinner spinner:
|
||||
return new SpinnerSelectionBlueprint(spinner);
|
||||
}
|
||||
|
||||
return base.CreateBlueprintFor(hitObject);
|
||||
}
|
||||
}
|
||||
}
|
@ -9,12 +9,7 @@ using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Edit.Tools;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles;
|
||||
using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders;
|
||||
using osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Screens.Edit.Compose.Components;
|
||||
|
||||
@ -37,24 +32,7 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
new SpinnerCompositionTool()
|
||||
};
|
||||
|
||||
public override SelectionHandler CreateSelectionHandler() => new OsuSelectionHandler();
|
||||
|
||||
public override SelectionBlueprint CreateBlueprintFor(DrawableHitObject hitObject)
|
||||
{
|
||||
switch (hitObject)
|
||||
{
|
||||
case DrawableHitCircle circle:
|
||||
return new HitCircleSelectionBlueprint(circle);
|
||||
|
||||
case DrawableSlider slider:
|
||||
return new SliderSelectionBlueprint(slider);
|
||||
|
||||
case DrawableSpinner spinner:
|
||||
return new SpinnerSelectionBlueprint(spinner);
|
||||
}
|
||||
|
||||
return base.CreateBlueprintFor(hitObject);
|
||||
}
|
||||
protected override ComposeBlueprintContainer CreateBlueprintContainer() => new OsuBlueprintContainer(HitObjects);
|
||||
|
||||
protected override DistanceSnapGrid CreateDistanceSnapGrid(IEnumerable<HitObject> selectedHitObjects)
|
||||
{
|
||||
|
@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
public override string Name => "Autopilot";
|
||||
public override string Acronym => "AP";
|
||||
public override IconUsage Icon => OsuIcon.ModAutopilot;
|
||||
public override IconUsage? Icon => OsuIcon.ModAutopilot;
|
||||
public override ModType Type => ModType.Automation;
|
||||
public override string Description => @"Automatic cursor movement - just follow the rhythm.";
|
||||
public override double ScoreMultiplier => 1;
|
||||
|
@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
public override string Description => "Play with blinds on your screen.";
|
||||
public override string Acronym => "BL";
|
||||
|
||||
public override IconUsage Icon => FontAwesome.Solid.Adjust;
|
||||
public override IconUsage? Icon => FontAwesome.Solid.Adjust;
|
||||
public override ModType Type => ModType.DifficultyIncrease;
|
||||
|
||||
public override bool Ranked => false;
|
||||
|
@ -11,7 +11,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
|
||||
public override string Acronym => "DF";
|
||||
|
||||
public override IconUsage Icon => FontAwesome.Solid.CompressArrowsAlt;
|
||||
public override IconUsage? Icon => FontAwesome.Solid.CompressArrowsAlt;
|
||||
|
||||
public override string Description => "Hit them at the right size!";
|
||||
|
||||
|
@ -11,7 +11,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
|
||||
public override string Acronym => "GR";
|
||||
|
||||
public override IconUsage Icon => FontAwesome.Solid.ArrowsAltV;
|
||||
public override IconUsage? Icon => FontAwesome.Solid.ArrowsAltV;
|
||||
|
||||
public override string Description => "Hit them at the right size!";
|
||||
|
||||
|
@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
public override string Name => "Spin In";
|
||||
public override string Acronym => "SI";
|
||||
public override IconUsage Icon => FontAwesome.Solid.Undo;
|
||||
public override IconUsage? Icon => FontAwesome.Solid.Undo;
|
||||
public override ModType Type => ModType.Fun;
|
||||
public override string Description => "Circles spin in. No approach circles.";
|
||||
public override double ScoreMultiplier => 1;
|
||||
|
@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
public override string Name => "Spun Out";
|
||||
public override string Acronym => "SO";
|
||||
public override IconUsage Icon => OsuIcon.ModSpunout;
|
||||
public override IconUsage? Icon => OsuIcon.ModSpunout;
|
||||
public override ModType Type => ModType.DifficultyReduction;
|
||||
public override string Description => @"Spinners will be automatically completed.";
|
||||
public override double ScoreMultiplier => 0.9;
|
||||
|
@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
public override string Name => "Target";
|
||||
public override string Acronym => "TP";
|
||||
public override ModType Type => ModType.Conversion;
|
||||
public override IconUsage Icon => OsuIcon.ModTarget;
|
||||
public override IconUsage? Icon => OsuIcon.ModTarget;
|
||||
public override string Description => @"Practice keeping up with the beat of the song.";
|
||||
public override double ScoreMultiplier => 1;
|
||||
}
|
||||
|
@ -6,7 +6,6 @@ using System.Linq;
|
||||
using osu.Framework.Bindables;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
@ -19,7 +18,6 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
public override string Name => "Traceable";
|
||||
public override string Acronym => "TC";
|
||||
public override IconUsage Icon => FontAwesome.Brands.SnapchatGhost;
|
||||
public override ModType Type => ModType.Fun;
|
||||
public override string Description => "Put your faith in the approach circles...";
|
||||
public override double ScoreMultiplier => 1;
|
||||
|
@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
public override string Name => "Transform";
|
||||
public override string Acronym => "TR";
|
||||
public override IconUsage Icon => FontAwesome.Solid.ArrowsAlt;
|
||||
public override IconUsage? Icon => FontAwesome.Solid.ArrowsAlt;
|
||||
public override ModType Type => ModType.Fun;
|
||||
public override string Description => "Everything rotates. EVERYTHING.";
|
||||
public override double ScoreMultiplier => 1;
|
||||
|
@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
public override string Name => "Wiggle";
|
||||
public override string Acronym => "WG";
|
||||
public override IconUsage Icon => FontAwesome.Solid.Certificate;
|
||||
public override IconUsage? Icon => FontAwesome.Solid.Certificate;
|
||||
public override ModType Type => ModType.Fun;
|
||||
public override string Description => "They just won't stay still...";
|
||||
public override double ScoreMultiplier => 1;
|
||||
|
@ -205,7 +205,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool OnReleased(OsuAction action) => false;
|
||||
public void OnReleased(OsuAction action)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,13 +6,11 @@ using System.Collections.Generic;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osuTK;
|
||||
using osu.Game.Skinning;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
{
|
||||
@ -23,7 +21,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
|
||||
private double animDuration;
|
||||
|
||||
private readonly SkinnableDrawable scaleContainer;
|
||||
private readonly Drawable scaleContainer;
|
||||
|
||||
public DrawableRepeatPoint(RepeatPoint repeatPoint, DrawableSlider drawableSlider)
|
||||
: base(repeatPoint)
|
||||
@ -36,16 +34,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
Blending = BlendingParameters.Additive;
|
||||
Origin = Anchor.Centre;
|
||||
|
||||
InternalChild = scaleContainer = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.ReverseArrow), _ => new SpriteIcon
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Icon = FontAwesome.Solid.ChevronRight,
|
||||
Size = new Vector2(0.35f)
|
||||
}, confineMode: ConfineMode.NoScaling)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
};
|
||||
InternalChild = scaleContainer = new ReverseArrowPiece();
|
||||
}
|
||||
|
||||
private readonly IBindable<float> scaleBindable = new Bindable<float>();
|
||||
@ -65,11 +54,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
|
||||
protected override void UpdateInitialTransforms()
|
||||
{
|
||||
animDuration = Math.Min(150, repeatPoint.SpanDuration / 2);
|
||||
animDuration = Math.Min(300, repeatPoint.SpanDuration);
|
||||
|
||||
this.Animate(
|
||||
d => d.FadeIn(animDuration),
|
||||
d => d.ScaleTo(0.5f).ScaleTo(1f, animDuration * 4, Easing.OutElasticHalf)
|
||||
d => d.ScaleTo(0.5f).ScaleTo(1f, animDuration * 2, Easing.OutElasticHalf)
|
||||
);
|
||||
}
|
||||
|
||||
@ -88,7 +77,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
break;
|
||||
|
||||
case ArmedState.Hit:
|
||||
this.FadeOut(animDuration, Easing.OutQuint)
|
||||
this.FadeOut(animDuration, Easing.Out)
|
||||
.ScaleTo(Scale * 1.5f, animDuration, Easing.Out);
|
||||
break;
|
||||
}
|
||||
|
@ -0,0 +1,43 @@
|
||||
// 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.Audio.Track;
|
||||
using osu.Framework.Graphics;
|
||||
using osuTK;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Skinning;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
{
|
||||
public class ReverseArrowPiece : BeatSyncedContainer
|
||||
{
|
||||
public ReverseArrowPiece()
|
||||
{
|
||||
Divisor = 2;
|
||||
MinimumBeatLength = 200;
|
||||
|
||||
Anchor = Anchor.Centre;
|
||||
Origin = Anchor.Centre;
|
||||
|
||||
Blending = BlendingParameters.Additive;
|
||||
|
||||
Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2);
|
||||
|
||||
Child = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.ReverseArrow), _ => new SpriteIcon
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Icon = FontAwesome.Solid.ChevronRight,
|
||||
Size = new Vector2(0.35f)
|
||||
})
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
};
|
||||
}
|
||||
|
||||
protected override void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, TrackAmplitudes amplitudes) =>
|
||||
Child.ScaleTo(1.3f).ScaleTo(1f, timingPoint.BeatLength, Easing.Out);
|
||||
}
|
||||
}
|
@ -107,7 +107,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool OnReleased(OsuAction action)
|
||||
public void OnReleased(OsuAction action)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
@ -120,8 +120,6 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
updateExpandedState();
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool HandlePositionalInput => true; // OverlayContainer will set this false when we go hidden, but we always want to receive input.
|
||||
|
@ -107,7 +107,9 @@ namespace osu.Game.Rulesets.Osu.UI
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool OnReleased(OsuAction action) => false;
|
||||
public void OnReleased(OsuAction action)
|
||||
{
|
||||
}
|
||||
|
||||
public void Appear() => Schedule(() =>
|
||||
{
|
||||
|
@ -77,11 +77,12 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
|
||||
return result;
|
||||
}
|
||||
|
||||
public override bool OnReleased(TaikoAction action)
|
||||
public override void OnReleased(TaikoAction action)
|
||||
{
|
||||
if (action == HitAction)
|
||||
HitAction = null;
|
||||
return base.OnReleased(action);
|
||||
|
||||
base.OnReleased(action);
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
|
@ -77,7 +77,10 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
|
||||
public Drawable CreateProxiedContent() => proxiedContent.CreateProxy();
|
||||
|
||||
public abstract bool OnPressed(TaikoAction action);
|
||||
public virtual bool OnReleased(TaikoAction action) => false;
|
||||
|
||||
public virtual void OnReleased(TaikoAction action)
|
||||
{
|
||||
}
|
||||
|
||||
public override double LifetimeStart
|
||||
{
|
||||
|
@ -187,7 +187,9 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool OnReleased(TaikoAction action) => false;
|
||||
public void OnReleased(TaikoAction action)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ using System;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using NUnit.Framework;
|
||||
@ -13,7 +14,9 @@ using osu.Game.IPC;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.Formats;
|
||||
using osu.Game.IO;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Tests.Resources;
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.Zip;
|
||||
@ -552,6 +555,83 @@ namespace osu.Game.Tests.Beatmaps.IO
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestUpdateBeatmapInfo()
|
||||
{
|
||||
using (HeadlessGameHost host = new CleanRunHeadlessGameHost(nameof(TestUpdateBeatmapInfo)))
|
||||
{
|
||||
try
|
||||
{
|
||||
var osu = loadOsu(host);
|
||||
var manager = osu.Dependencies.Get<BeatmapManager>();
|
||||
|
||||
var temp = TestResources.GetTestBeatmapForImport();
|
||||
await osu.Dependencies.Get<BeatmapManager>().Import(temp);
|
||||
|
||||
// Update via the beatmap, not the beatmap info, to ensure correct linking
|
||||
BeatmapSetInfo setToUpdate = manager.GetAllUsableBeatmapSets()[0];
|
||||
Beatmap beatmapToUpdate = (Beatmap)manager.GetWorkingBeatmap(setToUpdate.Beatmaps.First(b => b.RulesetID == 0)).Beatmap;
|
||||
beatmapToUpdate.BeatmapInfo.Version = "updated";
|
||||
|
||||
manager.Update(setToUpdate);
|
||||
|
||||
BeatmapInfo updatedInfo = manager.QueryBeatmap(b => b.ID == beatmapToUpdate.BeatmapInfo.ID);
|
||||
Assert.That(updatedInfo.Version, Is.EqualTo("updated"));
|
||||
}
|
||||
finally
|
||||
{
|
||||
host.Exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestUpdateBeatmapFile()
|
||||
{
|
||||
using (HeadlessGameHost host = new CleanRunHeadlessGameHost(nameof(TestUpdateBeatmapFile)))
|
||||
{
|
||||
try
|
||||
{
|
||||
var osu = loadOsu(host);
|
||||
var manager = osu.Dependencies.Get<BeatmapManager>();
|
||||
|
||||
var temp = TestResources.GetTestBeatmapForImport();
|
||||
await osu.Dependencies.Get<BeatmapManager>().Import(temp);
|
||||
|
||||
BeatmapSetInfo setToUpdate = manager.GetAllUsableBeatmapSets()[0];
|
||||
Beatmap beatmapToUpdate = (Beatmap)manager.GetWorkingBeatmap(setToUpdate.Beatmaps.First(b => b.RulesetID == 0)).Beatmap;
|
||||
BeatmapSetFileInfo fileToUpdate = setToUpdate.Files.First(f => beatmapToUpdate.BeatmapInfo.Path.Contains(f.Filename));
|
||||
|
||||
using (var stream = new MemoryStream())
|
||||
{
|
||||
using (var writer = new StreamWriter(stream, Encoding.UTF8, 1024, true))
|
||||
{
|
||||
beatmapToUpdate.HitObjects.Clear();
|
||||
beatmapToUpdate.HitObjects.Add(new HitCircle { StartTime = 5000 });
|
||||
|
||||
new LegacyBeatmapEncoder(beatmapToUpdate).Encode(writer);
|
||||
}
|
||||
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
manager.UpdateFile(setToUpdate, fileToUpdate, stream);
|
||||
}
|
||||
|
||||
// Check that the old file reference has been removed
|
||||
Assert.That(manager.QueryBeatmapSet(s => s.ID == setToUpdate.ID).Files.All(f => f.ID != fileToUpdate.ID));
|
||||
|
||||
// Check that the new file is referenced correctly by attempting a retrieval
|
||||
Beatmap updatedBeatmap = (Beatmap)manager.GetWorkingBeatmap(manager.QueryBeatmap(b => b.ID == beatmapToUpdate.BeatmapInfo.ID)).Beatmap;
|
||||
Assert.That(updatedBeatmap.HitObjects.Count, Is.EqualTo(1));
|
||||
Assert.That(updatedBeatmap.HitObjects[0].StartTime, Is.EqualTo(5000));
|
||||
}
|
||||
finally
|
||||
{
|
||||
host.Exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task<BeatmapSetInfo> LoadOszIntoOsu(OsuGameBase osu, string path = null, bool virtualTrack = false)
|
||||
{
|
||||
var temp = path ?? TestResources.GetTestBeatmapForImport(virtualTrack);
|
||||
|
@ -5,6 +5,7 @@ using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Rulesets.Osu.Beatmaps;
|
||||
using osu.Game.Rulesets.Osu.Edit;
|
||||
@ -19,7 +20,13 @@ namespace osu.Game.Tests.Editor
|
||||
private TestHitObjectComposer composer;
|
||||
|
||||
[Cached(typeof(EditorBeatmap))]
|
||||
private readonly EditorBeatmap editorBeatmap = new EditorBeatmap(new OsuBeatmap());
|
||||
[Cached(typeof(IBeatSnapProvider))]
|
||||
private readonly EditorBeatmap editorBeatmap;
|
||||
|
||||
public TestSceneHitObjectComposerDistanceSnapping()
|
||||
{
|
||||
editorBeatmap = new EditorBeatmap(new OsuBeatmap(), BeatDivisor);
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void Setup() => Schedule(() =>
|
||||
|
82
osu.Game.Tests/Online/TestAPIModSerialization.cs
Normal file
82
osu.Game.Tests/Online/TestAPIModSerialization.cs
Normal file
@ -0,0 +1,82 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Difficulty;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.UI;
|
||||
|
||||
namespace osu.Game.Tests.Online
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestAPIModSerialization
|
||||
{
|
||||
[Test]
|
||||
public void TestAcronymIsPreserved()
|
||||
{
|
||||
var apiMod = new APIMod(new TestMod());
|
||||
|
||||
var deserialized = JsonConvert.DeserializeObject<APIMod>(JsonConvert.SerializeObject(apiMod));
|
||||
|
||||
Assert.That(deserialized.Acronym, Is.EqualTo(apiMod.Acronym));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestRawSettingIsPreserved()
|
||||
{
|
||||
var apiMod = new APIMod(new TestMod { TestSetting = { Value = 2 } });
|
||||
|
||||
var deserialized = JsonConvert.DeserializeObject<APIMod>(JsonConvert.SerializeObject(apiMod));
|
||||
|
||||
Assert.That(deserialized.Settings, Contains.Key("test_setting").With.ContainValue(2.0));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestConvertedModHasCorrectSetting()
|
||||
{
|
||||
var apiMod = new APIMod(new TestMod { TestSetting = { Value = 2 } });
|
||||
|
||||
var deserialized = JsonConvert.DeserializeObject<APIMod>(JsonConvert.SerializeObject(apiMod));
|
||||
var converted = (TestMod)deserialized.ToMod(new TestRuleset());
|
||||
|
||||
Assert.That(converted.TestSetting.Value, Is.EqualTo(2));
|
||||
}
|
||||
|
||||
private class TestRuleset : Ruleset
|
||||
{
|
||||
public override IEnumerable<Mod> GetModsFor(ModType type) => new[] { new TestMod() };
|
||||
|
||||
public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList<Mod> mods = null) => throw new System.NotImplementedException();
|
||||
|
||||
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => throw new System.NotImplementedException();
|
||||
|
||||
public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => throw new System.NotImplementedException();
|
||||
|
||||
public override string Description { get; } = string.Empty;
|
||||
public override string ShortName { get; } = string.Empty;
|
||||
}
|
||||
|
||||
private class TestMod : Mod
|
||||
{
|
||||
public override string Name => "Test Mod";
|
||||
public override string Acronym => "TM";
|
||||
public override double ScoreMultiplier => 1;
|
||||
|
||||
[SettingSource("Test")]
|
||||
public BindableNumber<double> TestSetting { get; } = new BindableDouble
|
||||
{
|
||||
MinValue = 0,
|
||||
MaxValue = 10,
|
||||
Default = 5,
|
||||
Precision = 0.01,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Rulesets.Osu.Beatmaps;
|
||||
using osu.Game.Screens.Edit;
|
||||
@ -14,6 +15,7 @@ namespace osu.Game.Tests.Visual.Editor
|
||||
public class TestSceneComposeScreen : EditorClockTestScene
|
||||
{
|
||||
[Cached(typeof(EditorBeatmap))]
|
||||
[Cached(typeof(IBeatSnapProvider))]
|
||||
private readonly EditorBeatmap editorBeatmap =
|
||||
new EditorBeatmap(new OsuBeatmap
|
||||
{
|
||||
|
@ -66,6 +66,7 @@ namespace osu.Game.Tests.Visual.Editor
|
||||
Dependencies.CacheAs<IAdjustableClock>(clock);
|
||||
Dependencies.CacheAs<IFrameBasedClock>(clock);
|
||||
Dependencies.CacheAs(editorBeatmap);
|
||||
Dependencies.CacheAs<IBeatSnapProvider>(editorBeatmap);
|
||||
|
||||
Child = new OsuHitObjectComposer(new OsuRuleset());
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Screens.Edit;
|
||||
using osu.Game.Screens.Edit.Compose.Components.Timeline;
|
||||
@ -22,12 +23,11 @@ using osuTK.Graphics;
|
||||
namespace osu.Game.Tests.Visual.Editor
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestSceneEditorComposeTimeline : EditorClockTestScene
|
||||
public class TestSceneTimelineBlueprintContainer : EditorClockTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(TimelineArea),
|
||||
typeof(TimelineHitObjectDisplay),
|
||||
typeof(Timeline),
|
||||
typeof(TimelineButton),
|
||||
typeof(CentreMarker)
|
||||
@ -38,7 +38,10 @@ namespace osu.Game.Tests.Visual.Editor
|
||||
{
|
||||
Beatmap.Value = new WaveformTestBeatmap(audio);
|
||||
|
||||
var editorBeatmap = new EditorBeatmap((Beatmap<HitObject>)Beatmap.Value.Beatmap);
|
||||
var editorBeatmap = new EditorBeatmap((Beatmap<HitObject>)Beatmap.Value.Beatmap, BeatDivisor);
|
||||
|
||||
Dependencies.Cache(editorBeatmap);
|
||||
Dependencies.CacheAs<IBeatSnapProvider>(editorBeatmap);
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
@ -55,7 +58,7 @@ namespace osu.Game.Tests.Visual.Editor
|
||||
},
|
||||
new TimelineArea
|
||||
{
|
||||
Child = new TimelineHitObjectDisplay(editorBeatmap),
|
||||
Child = new TimelineBlueprintContainer(),
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.X,
|
@ -19,18 +19,22 @@ using osu.Game.Screens.Play.HUD.HitErrorMeters;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Gameplay
|
||||
{
|
||||
public class TestSceneBarHitErrorMeter : OsuTestScene
|
||||
public class TestSceneHitErrorMeter : OsuTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(HitErrorMeter),
|
||||
typeof(BarHitErrorMeter),
|
||||
typeof(ColourHitErrorMeter)
|
||||
};
|
||||
|
||||
private HitErrorMeter meter;
|
||||
private HitErrorMeter meter2;
|
||||
private BarHitErrorMeter barMeter;
|
||||
private BarHitErrorMeter barMeter2;
|
||||
private ColourHitErrorMeter colourMeter;
|
||||
private ColourHitErrorMeter colourMeter2;
|
||||
private HitWindows hitWindows;
|
||||
|
||||
public TestSceneBarHitErrorMeter()
|
||||
public TestSceneHitErrorMeter()
|
||||
{
|
||||
recreateDisplay(new OsuHitWindows(), 5);
|
||||
|
||||
@ -91,17 +95,31 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
}
|
||||
});
|
||||
|
||||
Add(meter = new BarHitErrorMeter(hitWindows, true)
|
||||
Add(barMeter = new BarHitErrorMeter(hitWindows, true)
|
||||
{
|
||||
Anchor = Anchor.CentreRight,
|
||||
Origin = Anchor.CentreRight,
|
||||
});
|
||||
|
||||
Add(meter2 = new BarHitErrorMeter(hitWindows, false)
|
||||
Add(barMeter2 = new BarHitErrorMeter(hitWindows, false)
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
});
|
||||
|
||||
Add(colourMeter = new ColourHitErrorMeter(hitWindows)
|
||||
{
|
||||
Anchor = Anchor.CentreRight,
|
||||
Origin = Anchor.CentreRight,
|
||||
Margin = new MarginPadding { Right = 50 }
|
||||
});
|
||||
|
||||
Add(colourMeter2 = new ColourHitErrorMeter(hitWindows)
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
Margin = new MarginPadding { Left = 50 }
|
||||
});
|
||||
}
|
||||
|
||||
private void newJudgement(double offset = 0)
|
||||
@ -112,8 +130,10 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
Type = HitResult.Perfect,
|
||||
};
|
||||
|
||||
meter.OnNewJudgement(judgement);
|
||||
meter2.OnNewJudgement(judgement);
|
||||
barMeter.OnNewJudgement(judgement);
|
||||
barMeter2.OnNewJudgement(judgement);
|
||||
colourMeter.OnNewJudgement(judgement);
|
||||
colourMeter2.OnNewJudgement(judgement);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,12 +1,17 @@
|
||||
// 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 System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Screens.Play;
|
||||
|
||||
@ -15,63 +20,125 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
[TestFixture]
|
||||
public class TestSceneSongProgress : OsuTestScene
|
||||
{
|
||||
private readonly SongProgress progress;
|
||||
private readonly TestSongProgressGraph graph;
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(SongProgressBar),
|
||||
};
|
||||
|
||||
private SongProgress progress;
|
||||
private TestSongProgressGraph graph;
|
||||
private readonly Container progressContainer;
|
||||
|
||||
private readonly StopwatchClock clock;
|
||||
private readonly FramedClock framedClock;
|
||||
|
||||
[Cached]
|
||||
private readonly GameplayClock gameplayClock;
|
||||
|
||||
private readonly FramedClock framedClock;
|
||||
|
||||
public TestSceneSongProgress()
|
||||
{
|
||||
clock = new StopwatchClock(true);
|
||||
|
||||
clock = new StopwatchClock();
|
||||
gameplayClock = new GameplayClock(framedClock = new FramedClock(clock));
|
||||
|
||||
Add(progress = new SongProgress
|
||||
Add(progressContainer = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
Anchor = Anchor.BottomCentre,
|
||||
Origin = Anchor.BottomCentre,
|
||||
Height = 100,
|
||||
Y = -100,
|
||||
Child = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = OsuColour.Gray(1),
|
||||
}
|
||||
});
|
||||
|
||||
Add(graph = new TestSongProgressGraph
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = 200,
|
||||
Anchor = Anchor.TopLeft,
|
||||
Origin = Anchor.TopLeft,
|
||||
});
|
||||
|
||||
AddWaitStep("wait some", 5);
|
||||
AddAssert("ensure not created", () => graph.CreationCount == 0);
|
||||
|
||||
AddStep("display values", displayNewValues);
|
||||
AddWaitStep("wait some", 5);
|
||||
AddUntilStep("wait for creation count", () => graph.CreationCount == 1);
|
||||
|
||||
AddStep("Toggle Bar", () => progress.AllowSeeking = !progress.AllowSeeking);
|
||||
AddWaitStep("wait some", 5);
|
||||
AddUntilStep("wait for creation count", () => graph.CreationCount == 1);
|
||||
|
||||
AddStep("Toggle Bar", () => progress.AllowSeeking = !progress.AllowSeeking);
|
||||
AddWaitStep("wait some", 5);
|
||||
AddUntilStep("wait for creation count", () => graph.CreationCount == 1);
|
||||
AddRepeatStep("New Values", displayNewValues, 5);
|
||||
|
||||
AddWaitStep("wait some", 5);
|
||||
AddAssert("ensure debounced", () => graph.CreationCount == 2);
|
||||
}
|
||||
|
||||
private void displayNewValues()
|
||||
[SetUpSteps]
|
||||
public void SetupSteps()
|
||||
{
|
||||
List<HitObject> objects = new List<HitObject>();
|
||||
AddStep("add new song progress", () =>
|
||||
{
|
||||
if (progress != null)
|
||||
{
|
||||
progress.Expire();
|
||||
progress = null;
|
||||
}
|
||||
|
||||
progressContainer.Add(progress = new SongProgress
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
});
|
||||
});
|
||||
|
||||
AddStep("add new big graph", () =>
|
||||
{
|
||||
if (graph != null)
|
||||
{
|
||||
graph.Expire();
|
||||
graph = null;
|
||||
}
|
||||
|
||||
Add(graph = new TestSongProgressGraph
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = 200,
|
||||
Anchor = Anchor.TopLeft,
|
||||
Origin = Anchor.TopLeft,
|
||||
});
|
||||
});
|
||||
|
||||
AddStep("reset clock", clock.Reset);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestGraphRecreation()
|
||||
{
|
||||
AddAssert("ensure not created", () => graph.CreationCount == 0);
|
||||
AddStep("display values", displayRandomValues);
|
||||
AddUntilStep("wait for creation count", () => graph.CreationCount == 1);
|
||||
AddRepeatStep("new values", displayRandomValues, 5);
|
||||
AddWaitStep("wait some", 5);
|
||||
AddAssert("ensure recreation debounced", () => graph.CreationCount == 2);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestDisplay()
|
||||
{
|
||||
AddStep("display max values", displayMaxValues);
|
||||
AddUntilStep("wait for graph", () => graph.CreationCount == 1);
|
||||
AddStep("start", clock.Start);
|
||||
AddStep("allow seeking", () => progress.AllowSeeking.Value = true);
|
||||
AddStep("hide graph", () => progress.ShowGraph.Value = false);
|
||||
AddStep("disallow seeking", () => progress.AllowSeeking.Value = false);
|
||||
AddStep("allow seeking", () => progress.AllowSeeking.Value = true);
|
||||
AddStep("show graph", () => progress.ShowGraph.Value = true);
|
||||
AddStep("stop", clock.Stop);
|
||||
}
|
||||
|
||||
private void displayRandomValues()
|
||||
{
|
||||
var objects = new List<HitObject>();
|
||||
for (double i = 0; i < 5000; i += RNG.NextDouble() * 10 + i / 1000)
|
||||
objects.Add(new HitObject { StartTime = i });
|
||||
|
||||
replaceObjects(objects);
|
||||
}
|
||||
|
||||
private void displayMaxValues()
|
||||
{
|
||||
var objects = new List<HitObject>();
|
||||
for (double i = 0; i < 5000; i++)
|
||||
objects.Add(new HitObject { StartTime = i });
|
||||
|
||||
replaceObjects(objects);
|
||||
}
|
||||
|
||||
private void replaceObjects(List<HitObject> objects)
|
||||
{
|
||||
progress.Objects = objects;
|
||||
graph.Objects = objects;
|
||||
|
||||
|
36
osu.Game.Tests/Visual/Menus/TestSceneSongTicker.cs
Normal file
36
osu.Game.Tests/Visual/Menus/TestSceneSongTicker.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.Overlays;
|
||||
using osu.Game.Screens.Menu;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Menus
|
||||
{
|
||||
public class TestSceneSongTicker : OsuTestScene
|
||||
{
|
||||
[Cached]
|
||||
private MusicController musicController = new MusicController();
|
||||
|
||||
public TestSceneSongTicker()
|
||||
{
|
||||
AddRange(new Drawable[]
|
||||
{
|
||||
musicController,
|
||||
new SongTicker
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
},
|
||||
new NowPlayingOverlay
|
||||
{
|
||||
Origin = Anchor.TopRight,
|
||||
Anchor = Anchor.TopRight,
|
||||
State = { Value = Visibility.Visible }
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
@ -25,7 +26,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
typeof(ChannelTabControl),
|
||||
};
|
||||
|
||||
private readonly ChannelTabControl channelTabControl;
|
||||
private readonly TestTabControl channelTabControl;
|
||||
|
||||
public TestSceneChannelTabControl()
|
||||
{
|
||||
@ -37,7 +38,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
Anchor = Anchor.Centre,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
channelTabControl = new ChannelTabControl
|
||||
channelTabControl = new TestTabControl
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Origin = Anchor.Centre,
|
||||
@ -73,32 +74,40 @@ namespace osu.Game.Tests.Visual.Online
|
||||
channelTabControl.Current.ValueChanged += channel => currentText.Text = "Currently selected channel: " + channel.NewValue;
|
||||
|
||||
AddStep("Add random private channel", addRandomPrivateChannel);
|
||||
AddAssert("There is only one channels", () => channelTabControl.Items.Count() == 2);
|
||||
AddAssert("There is only one channels", () => channelTabControl.Items.Count == 2);
|
||||
AddRepeatStep("Add 3 random private channels", addRandomPrivateChannel, 3);
|
||||
AddAssert("There are four channels", () => channelTabControl.Items.Count() == 5);
|
||||
AddAssert("There are four channels", () => channelTabControl.Items.Count == 5);
|
||||
AddStep("Add random public channel", () => addChannel(RNG.Next().ToString()));
|
||||
|
||||
AddRepeatStep("Select a random channel", () => channelTabControl.Current.Value = channelTabControl.Items.ElementAt(RNG.Next(channelTabControl.Items.Count() - 1)), 20);
|
||||
AddRepeatStep("Select a random channel", () =>
|
||||
{
|
||||
List<Channel> validChannels = channelTabControl.Items.Where(c => !(c is ChannelSelectorTabItem.ChannelSelectorTabChannel)).ToList();
|
||||
channelTabControl.SelectChannel(validChannels[RNG.Next(0, validChannels.Count)]);
|
||||
}, 20);
|
||||
|
||||
Channel channelBefore = channelTabControl.Items.First();
|
||||
AddStep("set first channel", () => channelTabControl.Current.Value = channelBefore);
|
||||
Channel channelBefore = null;
|
||||
AddStep("set first channel", () => channelTabControl.SelectChannel(channelBefore = channelTabControl.Items.First(c => !(c is ChannelSelectorTabItem.ChannelSelectorTabChannel))));
|
||||
|
||||
AddStep("select selector tab", () => channelTabControl.Current.Value = channelTabControl.Items.Last());
|
||||
AddStep("select selector tab", () => channelTabControl.SelectChannel(channelTabControl.Items.Single(c => c is ChannelSelectorTabItem.ChannelSelectorTabChannel)));
|
||||
AddAssert("selector tab is active", () => channelTabControl.ChannelSelectorActive.Value);
|
||||
|
||||
AddAssert("check channel unchanged", () => channelBefore == channelTabControl.Current.Value);
|
||||
|
||||
AddStep("set second channel", () => channelTabControl.Current.Value = channelTabControl.Items.Skip(1).First());
|
||||
AddStep("set second channel", () => channelTabControl.SelectChannel(channelTabControl.Items.GetNext(channelBefore)));
|
||||
AddAssert("selector tab is inactive", () => !channelTabControl.ChannelSelectorActive.Value);
|
||||
|
||||
AddUntilStep("remove all channels", () =>
|
||||
{
|
||||
var first = channelTabControl.Items.First();
|
||||
if (first is ChannelSelectorTabItem.ChannelSelectorTabChannel)
|
||||
return true;
|
||||
foreach (var item in channelTabControl.Items.ToList())
|
||||
{
|
||||
if (item is ChannelSelectorTabItem.ChannelSelectorTabChannel)
|
||||
continue;
|
||||
|
||||
channelTabControl.RemoveChannel(first);
|
||||
return false;
|
||||
channelTabControl.RemoveChannel(item);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
AddAssert("selector tab is active", () => channelTabControl.ChannelSelectorActive.Value);
|
||||
@ -117,5 +126,10 @@ namespace osu.Game.Tests.Visual.Online
|
||||
Type = ChannelType.Public,
|
||||
Name = name
|
||||
});
|
||||
|
||||
private class TestTabControl : ChannelTabControl
|
||||
{
|
||||
public void SelectChannel(Channel channel) => base.SelectTab(TabMap[channel]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -30,29 +30,23 @@ namespace osu.Game.Tests.Visual.Online
|
||||
|
||||
public TestSceneCommentsContainer()
|
||||
{
|
||||
BasicScrollContainer scrollFlow;
|
||||
BasicScrollContainer scroll;
|
||||
CommentsContainer comments;
|
||||
|
||||
Add(scrollFlow = new BasicScrollContainer
|
||||
Add(scroll = new BasicScrollContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = comments = new CommentsContainer()
|
||||
});
|
||||
|
||||
AddStep("Big Black comments", () =>
|
||||
AddStep("Big Black comments", () => comments.ShowComments(CommentableType.Beatmapset, 41823));
|
||||
AddStep("Airman comments", () => comments.ShowComments(CommentableType.Beatmapset, 24313));
|
||||
AddStep("Lazer build comments", () => comments.ShowComments(CommentableType.Build, 4772));
|
||||
AddStep("News comments", () => comments.ShowComments(CommentableType.NewsPost, 715));
|
||||
AddStep("Idle state", () =>
|
||||
{
|
||||
scrollFlow.Clear();
|
||||
scrollFlow.Add(new CommentsContainer(CommentableType.Beatmapset, 41823));
|
||||
});
|
||||
|
||||
AddStep("Airman comments", () =>
|
||||
{
|
||||
scrollFlow.Clear();
|
||||
scrollFlow.Add(new CommentsContainer(CommentableType.Beatmapset, 24313));
|
||||
});
|
||||
|
||||
AddStep("lazer build comments", () =>
|
||||
{
|
||||
scrollFlow.Clear();
|
||||
scrollFlow.Add(new CommentsContainer(CommentableType.Build, 4772));
|
||||
scroll.Clear();
|
||||
scroll.Add(comments = new CommentsContainer());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -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 System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Overlays.Rankings;
|
||||
using osu.Game.Users;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osuTK.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
public class TestSceneRankingsCountryFilter : OsuTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(CountryFilter),
|
||||
typeof(CountryPill)
|
||||
};
|
||||
|
||||
public TestSceneRankingsCountryFilter()
|
||||
{
|
||||
var countryBindable = new Bindable<Country>();
|
||||
|
||||
AddRange(new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.Gray,
|
||||
},
|
||||
new FillFlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Direction = FillDirection.Vertical,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new CountryFilter
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Current = { BindTarget = countryBindable }
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Text = "Some content",
|
||||
Margin = new MarginPadding { Vertical = 20 }
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var country = new Country
|
||||
{
|
||||
FlagName = "BY",
|
||||
FullName = "Belarus"
|
||||
};
|
||||
var unknownCountry = new Country
|
||||
{
|
||||
FlagName = "CK",
|
||||
FullName = "Cook Islands"
|
||||
};
|
||||
|
||||
AddStep("Set country", () => countryBindable.Value = country);
|
||||
AddStep("Set null country", () => countryBindable.Value = null);
|
||||
AddStep("Set country with no flag", () => countryBindable.Value = unknownCountry);
|
||||
}
|
||||
}
|
||||
}
|
@ -437,6 +437,53 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
AddAssert("Selection was random", () => eagerSelectedIDs.Count > 1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestFilteringByUserStarDifficulty()
|
||||
{
|
||||
BeatmapSetInfo set = null;
|
||||
|
||||
loadBeatmaps(new List<BeatmapSetInfo>());
|
||||
|
||||
AddStep("add mixed difficulty set", () =>
|
||||
{
|
||||
set = createTestBeatmapSet(1);
|
||||
set.Beatmaps.Clear();
|
||||
|
||||
for (int i = 1; i <= 15; i++)
|
||||
{
|
||||
set.Beatmaps.Add(new BeatmapInfo
|
||||
{
|
||||
Version = $"Stars: {i}",
|
||||
StarDifficulty = i,
|
||||
});
|
||||
}
|
||||
|
||||
carousel.UpdateBeatmapSet(set);
|
||||
});
|
||||
|
||||
AddStep("select added set", () => carousel.SelectBeatmap(set.Beatmaps[0], false));
|
||||
|
||||
AddStep("filter [5..]", () => carousel.Filter(new FilterCriteria { UserStarDifficulty = { Min = 5 } }));
|
||||
AddUntilStep("Wait for debounce", () => !carousel.PendingFilterTask);
|
||||
checkVisibleItemCount(true, 11);
|
||||
|
||||
AddStep("filter to [0..7]", () => carousel.Filter(new FilterCriteria { UserStarDifficulty = { Max = 7 } }));
|
||||
AddUntilStep("Wait for debounce", () => !carousel.PendingFilterTask);
|
||||
checkVisibleItemCount(true, 7);
|
||||
|
||||
AddStep("filter to [5..7]", () => carousel.Filter(new FilterCriteria { UserStarDifficulty = { Min = 5, Max = 7 } }));
|
||||
AddUntilStep("Wait for debounce", () => !carousel.PendingFilterTask);
|
||||
checkVisibleItemCount(true, 3);
|
||||
|
||||
AddStep("filter [2..2]", () => carousel.Filter(new FilterCriteria { UserStarDifficulty = { Min = 2, Max = 2 } }));
|
||||
AddUntilStep("Wait for debounce", () => !carousel.PendingFilterTask);
|
||||
checkVisibleItemCount(true, 1);
|
||||
|
||||
AddStep("filter to [0..]", () => carousel.Filter(new FilterCriteria { UserStarDifficulty = { Min = 0 } }));
|
||||
AddUntilStep("Wait for debounce", () => !carousel.PendingFilterTask);
|
||||
checkVisibleItemCount(true, 15);
|
||||
}
|
||||
|
||||
private void loadBeatmaps(List<BeatmapSetInfo> beatmapSets = null)
|
||||
{
|
||||
createCarousel();
|
||||
|
62
osu.Game.Tests/Visual/UserInterface/TestSceneModButton.cs
Normal file
62
osu.Game.Tests/Visual/UserInterface/TestSceneModButton.cs
Normal file
@ -0,0 +1,62 @@
|
||||
// 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.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Overlays.Mods;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
|
||||
namespace osu.Game.Tests.Visual.UserInterface
|
||||
{
|
||||
public class TestSceneModButton : OsuTestScene
|
||||
{
|
||||
public TestSceneModButton()
|
||||
{
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new ModButton(new MultiMod(new TestMod1(), new TestMod2(), new TestMod3(), new TestMod4()))
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private class TestMod1 : TestMod
|
||||
{
|
||||
public override string Name => "Test mod 1";
|
||||
|
||||
public override string Acronym => "M1";
|
||||
}
|
||||
|
||||
private class TestMod2 : TestMod
|
||||
{
|
||||
public override string Name => "Test mod 2";
|
||||
|
||||
public override string Acronym => "M2";
|
||||
|
||||
public override IconUsage? Icon => FontAwesome.Solid.Exclamation;
|
||||
}
|
||||
|
||||
private class TestMod3 : TestMod
|
||||
{
|
||||
public override string Name => "Test mod 3";
|
||||
|
||||
public override string Acronym => "M3";
|
||||
|
||||
public override IconUsage? Icon => FontAwesome.Solid.ArrowRight;
|
||||
}
|
||||
|
||||
private class TestMod4 : TestMod
|
||||
{
|
||||
public override string Name => "Test mod 4";
|
||||
|
||||
public override string Acronym => "M4";
|
||||
}
|
||||
|
||||
private abstract class TestMod : Mod, IApplicableMod
|
||||
{
|
||||
public override double ScoreMultiplier => 1.0;
|
||||
}
|
||||
}
|
||||
}
|
@ -25,6 +25,8 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
|
||||
private readonly Mod testCustomisableMod = new TestModCustomisable1();
|
||||
|
||||
private readonly Mod testCustomisableAutoOpenMod = new TestModCustomisable2();
|
||||
|
||||
[Test]
|
||||
public void TestButtonShowsOnCustomisableMod()
|
||||
{
|
||||
@ -53,6 +55,17 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
AddAssert("button enabled", () => modSelect.CustomiseButton.Enabled.Value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestCustomisationOpensOnModSelect()
|
||||
{
|
||||
createModSelect();
|
||||
|
||||
AddStep("open", () => modSelect.Show());
|
||||
AddAssert("Customisation closed", () => modSelect.ModSettingsContainer.Alpha == 0);
|
||||
AddStep("select mod", () => modSelect.SelectMod(testCustomisableAutoOpenMod));
|
||||
AddAssert("Customisation opened", () => modSelect.ModSettingsContainer.Alpha == 1);
|
||||
}
|
||||
|
||||
private void createModSelect()
|
||||
{
|
||||
AddStep("create mod select", () =>
|
||||
@ -128,6 +141,8 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
public override string Name => "Customisable Mod 2";
|
||||
|
||||
public override string Acronym => "CM2";
|
||||
|
||||
public override bool RequiresConfiguration => true;
|
||||
}
|
||||
|
||||
private abstract class TestModCustomisable : Mod, IApplicableMod
|
||||
|
@ -1,7 +1,6 @@
|
||||
// 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;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
@ -62,7 +61,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
waitForCurrent();
|
||||
pushNext();
|
||||
waitForCurrent();
|
||||
AddAssert(@"only 2 items", () => breadcrumbs.Items.Count() == 2);
|
||||
AddAssert(@"only 2 items", () => breadcrumbs.Items.Count == 2);
|
||||
AddStep(@"exit current", () => screenStack.CurrentScreen.Exit());
|
||||
AddAssert(@"current screen is first", () => startScreen == screenStack.CurrentScreen);
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
|
||||
AddStep("Select random", () =>
|
||||
{
|
||||
selector.Current.Value = selector.Items.ElementAt(RNG.Next(selector.Items.Count()));
|
||||
selector.Current.Value = selector.Items.ElementAt(RNG.Next(selector.Items.Count));
|
||||
});
|
||||
AddStep("Toggle disabled state", () => selector.Current.Disabled = !selector.Current.Disabled);
|
||||
}
|
||||
|
@ -541,7 +541,7 @@
|
||||
},
|
||||
{
|
||||
"FlagName": "MK",
|
||||
"FullName": "Macedonia",
|
||||
"FullName": "North Macedonia",
|
||||
"Acronym": "MKD"
|
||||
},
|
||||
{
|
||||
@ -811,7 +811,7 @@
|
||||
},
|
||||
{
|
||||
"FlagName": "CV",
|
||||
"FullName": "Cape Verde",
|
||||
"FullName": "Cabo Verde",
|
||||
"Acronym": "CPV"
|
||||
},
|
||||
{
|
||||
@ -821,7 +821,7 @@
|
||||
},
|
||||
{
|
||||
"FlagName": "SZ",
|
||||
"FullName": "Swaziland",
|
||||
"FullName": "Eswatini",
|
||||
"Acronym": "SWZ"
|
||||
},
|
||||
{
|
||||
|
@ -289,16 +289,15 @@ namespace osu.Game.Tournament.Screens.Ladder.Components
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override bool OnDrag(DragEvent e)
|
||||
protected override void OnDrag(DragEvent e)
|
||||
{
|
||||
if (base.OnDrag(e)) return true;
|
||||
base.OnDrag(e);
|
||||
|
||||
Selected = true;
|
||||
this.MoveToOffset(e.Delta);
|
||||
|
||||
var pos = Position;
|
||||
Match.Position.Value = new Point((int)pos.X, (int)pos.Y);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Remove()
|
||||
|
@ -10,8 +10,8 @@ namespace osu.Game.Tournament.Screens.Ladder.Components
|
||||
{
|
||||
public class ProgressionPath : Path
|
||||
{
|
||||
public DrawableTournamentMatch Source { get; private set; }
|
||||
public DrawableTournamentMatch Destination { get; private set; }
|
||||
public DrawableTournamentMatch Source { get; }
|
||||
public DrawableTournamentMatch Destination { get; }
|
||||
|
||||
public ProgressionPath(DrawableTournamentMatch source, DrawableTournamentMatch destination)
|
||||
{
|
||||
|
@ -22,10 +22,9 @@ namespace osu.Game.Tournament.Screens.Ladder
|
||||
|
||||
protected override bool ComputeIsMaskedAway(RectangleF maskingBounds) => false;
|
||||
|
||||
protected override bool OnDrag(DragEvent e)
|
||||
protected override void OnDrag(DragEvent e)
|
||||
{
|
||||
this.MoveTo(target += e.Delta, 1000, Easing.OutQuint);
|
||||
return true;
|
||||
}
|
||||
|
||||
private const float min_scale = 0.6f;
|
||||
|
@ -61,7 +61,7 @@ namespace osu.Game.Tournament
|
||||
string weightString = weight.ToString();
|
||||
|
||||
// Only exo has an explicit "regular" weight, other fonts do not
|
||||
if (weight == FontWeight.Regular && family != GetFamilyString(TournamentTypeface.Aquatico) && family != GetFamilyString(TournamentTypeface.Aquatico))
|
||||
if (weight == FontWeight.Regular && family != GetFamilyString(TournamentTypeface.Aquatico))
|
||||
weightString = string.Empty;
|
||||
|
||||
return weightString;
|
||||
|
@ -223,9 +223,12 @@ namespace osu.Game.Tournament
|
||||
|
||||
foreach (var r in ladder.Rounds)
|
||||
{
|
||||
foreach (var b in r.Beatmaps)
|
||||
foreach (var b in r.Beatmaps.ToList())
|
||||
{
|
||||
if (b.BeatmapInfo == null && b.ID > 0)
|
||||
if (b.BeatmapInfo != null)
|
||||
continue;
|
||||
|
||||
if (b.ID > 0)
|
||||
{
|
||||
var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = b.ID });
|
||||
API.Perform(req);
|
||||
@ -233,6 +236,10 @@ namespace osu.Game.Tournament
|
||||
|
||||
addedInfo = true;
|
||||
}
|
||||
|
||||
if (b.BeatmapInfo == null)
|
||||
// if online population couldn't be performed, ensure we don't leave a null value behind
|
||||
r.Beatmaps.Remove(b);
|
||||
}
|
||||
}
|
||||
|
||||
@ -296,7 +303,7 @@ namespace osu.Game.Tournament
|
||||
|
||||
private class TournamentInputManager : UserInputManager
|
||||
{
|
||||
protected override MouseButtonEventManager CreateButtonManagerFor(MouseButton button)
|
||||
protected override MouseButtonEventManager CreateButtonEventManagerFor(MouseButton button)
|
||||
{
|
||||
switch (button)
|
||||
{
|
||||
@ -304,7 +311,7 @@ namespace osu.Game.Tournament
|
||||
return new RightMouseManager(button);
|
||||
}
|
||||
|
||||
return base.CreateButtonManagerFor(button);
|
||||
return base.CreateButtonEventManagerFor(button);
|
||||
}
|
||||
|
||||
private class RightMouseManager : MouseButtonEventManager
|
||||
|
@ -19,6 +19,6 @@ namespace osu.Game.Audio
|
||||
|
||||
public IEnumerable<string> LookupNames => new[] { sampleName };
|
||||
|
||||
public int Volume { get; set; } = 100;
|
||||
public int Volume { get; } = 100;
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
@ -26,6 +27,8 @@ using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using Decoder = osu.Game.Beatmaps.Formats.Decoder;
|
||||
using ZipArchive = SharpCompress.Archives.Zip.ZipArchive;
|
||||
|
||||
namespace osu.Game.Beatmaps
|
||||
{
|
||||
@ -56,14 +59,11 @@ namespace osu.Game.Beatmaps
|
||||
protected override string ImportFromStablePath => "Songs";
|
||||
|
||||
private readonly RulesetStore rulesets;
|
||||
|
||||
private readonly BeatmapStore beatmaps;
|
||||
|
||||
private readonly AudioManager audioManager;
|
||||
|
||||
private readonly GameHost host;
|
||||
|
||||
private readonly BeatmapUpdateQueue updateQueue;
|
||||
private readonly Storage exportStorage;
|
||||
|
||||
public BeatmapManager(Storage storage, IDatabaseContextFactory contextFactory, RulesetStore rulesets, IAPIProvider api, AudioManager audioManager, GameHost host = null,
|
||||
WorkingBeatmap defaultBeatmap = null)
|
||||
@ -80,6 +80,7 @@ namespace osu.Game.Beatmaps
|
||||
beatmaps.BeatmapRestored += b => BeatmapRestored?.Invoke(b);
|
||||
|
||||
updateQueue = new BeatmapUpdateQueue(api);
|
||||
exportStorage = storage.GetStorageForDirectory("exports");
|
||||
}
|
||||
|
||||
protected override ArchiveDownloadRequest<BeatmapSetInfo> CreateDownloadRequest(BeatmapSetInfo set, bool minimiseDownloadSize) =>
|
||||
@ -174,6 +175,50 @@ namespace osu.Game.Beatmaps
|
||||
/// <param name="beatmap">The beatmap difficulty to restore.</param>
|
||||
public void Restore(BeatmapInfo beatmap) => beatmaps.Restore(beatmap);
|
||||
|
||||
/// <summary>
|
||||
/// Saves an <see cref="IBeatmap"/> file against a given <see cref="BeatmapInfo"/>.
|
||||
/// </summary>
|
||||
/// <param name="info">The <see cref="BeatmapInfo"/> to save the content against. The file referenced by <see cref="BeatmapInfo.Path"/> will be replaced.</param>
|
||||
/// <param name="beatmapContent">The <see cref="IBeatmap"/> content to write.</param>
|
||||
public void Save(BeatmapInfo info, IBeatmap beatmapContent)
|
||||
{
|
||||
var setInfo = QueryBeatmapSet(s => s.Beatmaps.Any(b => b.ID == info.ID));
|
||||
|
||||
using (var stream = new MemoryStream())
|
||||
{
|
||||
using (var sw = new StreamWriter(stream, Encoding.UTF8, 1024, true))
|
||||
new LegacyBeatmapEncoder(beatmapContent).Encode(sw);
|
||||
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
UpdateFile(setInfo, setInfo.Files.Single(f => string.Equals(f.Filename, info.Path, StringComparison.OrdinalIgnoreCase)), stream);
|
||||
}
|
||||
|
||||
var working = workingCache.FirstOrDefault(w => w.BeatmapInfo?.ID == info.ID);
|
||||
if (working != null)
|
||||
workingCache.Remove(working);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Exports a <see cref="BeatmapSetInfo"/> to an .osz package.
|
||||
/// </summary>
|
||||
/// <param name="set">The <see cref="BeatmapSetInfo"/> to export.</param>
|
||||
public void Export(BeatmapSetInfo set)
|
||||
{
|
||||
var localSet = QueryBeatmapSet(s => s.ID == set.ID);
|
||||
|
||||
using (var archive = ZipArchive.Create())
|
||||
{
|
||||
foreach (var file in localSet.Files)
|
||||
archive.AddEntry(file.Filename, Files.Storage.GetStream(file.FileInfo.StoragePath));
|
||||
|
||||
using (var outputStream = exportStorage.GetStream($"{set}.osz", FileAccess.Write, FileMode.Create))
|
||||
archive.SaveTo(outputStream);
|
||||
|
||||
exportStorage.OpenInNativeExplorer();
|
||||
}
|
||||
}
|
||||
|
||||
private readonly WeakList<WorkingBeatmap> workingCache = new WeakList<WorkingBeatmap>();
|
||||
|
||||
/// <summary>
|
||||
|
@ -63,7 +63,7 @@ namespace osu.Game.Beatmaps.Formats
|
||||
writer.WriteLine(FormattableString.Invariant($"PreviewTime: {beatmap.Metadata.PreviewTime}"));
|
||||
// Todo: Not all countdown types are supported by lazer yet
|
||||
writer.WriteLine(FormattableString.Invariant($"Countdown: {(beatmap.BeatmapInfo.Countdown ? '1' : '0')}"));
|
||||
writer.WriteLine(FormattableString.Invariant($"SampleSet: {toLegacySampleBank(beatmap.ControlPointInfo.SamplePoints[0].SampleBank)}"));
|
||||
writer.WriteLine(FormattableString.Invariant($"SampleSet: {toLegacySampleBank(beatmap.ControlPointInfo.SamplePointAt(double.MinValue).SampleBank)}"));
|
||||
writer.WriteLine(FormattableString.Invariant($"StackLeniency: {beatmap.BeatmapInfo.StackLeniency}"));
|
||||
writer.WriteLine(FormattableString.Invariant($"Mode: {beatmap.BeatmapInfo.RulesetID}"));
|
||||
writer.WriteLine(FormattableString.Invariant($"LetterboxInBreaks: {(beatmap.BeatmapInfo.LetterboxInBreaks ? '1' : '0')}"));
|
||||
|
@ -7,13 +7,11 @@ using osu.Game.Rulesets.Mods;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Storyboards;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Statistics;
|
||||
using osu.Game.IO.Serialization;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Rulesets.UI;
|
||||
@ -76,21 +74,6 @@ namespace osu.Game.Beatmaps
|
||||
return AudioManager.Tracks.GetVirtual(length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves the <see cref="Beatmaps.Beatmap"/>.
|
||||
/// </summary>
|
||||
/// <returns>The absolute path of the output file.</returns>
|
||||
public string Save()
|
||||
{
|
||||
string directory = Path.Combine(Path.GetTempPath(), @"osu!");
|
||||
Directory.CreateDirectory(directory);
|
||||
|
||||
var path = Path.Combine(directory, Guid.NewGuid().ToString().Replace("-", string.Empty) + ".json");
|
||||
using (var sw = new StreamWriter(path))
|
||||
sw.WriteLine(Beatmap.Serialize());
|
||||
return path;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="IBeatmapConverter"/> to convert a <see cref="IBeatmap"/> for a specified <see cref="Ruleset"/>.
|
||||
/// </summary>
|
||||
|
@ -24,7 +24,7 @@ namespace osu.Game.Configuration
|
||||
|
||||
Set(OsuSetting.ShowConvertedBeatmaps, true);
|
||||
Set(OsuSetting.DisplayStarsMinimum, 0.0, 0, 10, 0.1);
|
||||
Set(OsuSetting.DisplayStarsMaximum, 10.0, 0, 10, 0.1);
|
||||
Set(OsuSetting.DisplayStarsMaximum, 10.1, 0, 10.1, 0.1);
|
||||
|
||||
Set(OsuSetting.SongSelectGroupingMode, GroupMode.All);
|
||||
Set(OsuSetting.SongSelectSortingMode, SortMode.Title);
|
||||
@ -85,6 +85,7 @@ namespace osu.Game.Configuration
|
||||
Set(OsuSetting.HitLighting, true);
|
||||
|
||||
Set(OsuSetting.ShowInterface, true);
|
||||
Set(OsuSetting.ShowProgressGraph, true);
|
||||
Set(OsuSetting.ShowHealthDisplayWhenCantFail, true);
|
||||
Set(OsuSetting.KeyOverlay, false);
|
||||
Set(OsuSetting.ScoreMeter, ScoreMeterType.HitErrorBoth);
|
||||
@ -150,6 +151,7 @@ namespace osu.Game.Configuration
|
||||
ScoreMeter,
|
||||
FloatingComments,
|
||||
ShowInterface,
|
||||
ShowProgressGraph,
|
||||
ShowHealthDisplayWhenCantFail,
|
||||
MouseDisableButtons,
|
||||
MouseDisableWheel,
|
||||
|
@ -18,5 +18,14 @@ namespace osu.Game.Configuration
|
||||
|
||||
[Description("Hit Error (both)")]
|
||||
HitErrorBoth,
|
||||
|
||||
[Description("Colour (left)")]
|
||||
ColourLeft,
|
||||
|
||||
[Description("Colour (right)")]
|
||||
ColourRight,
|
||||
|
||||
[Description("Colour (both)")]
|
||||
ColourBoth,
|
||||
}
|
||||
}
|
||||
|
@ -35,16 +35,11 @@ namespace osu.Game.Configuration
|
||||
{
|
||||
public static IEnumerable<Drawable> CreateSettingsControls(this object obj)
|
||||
{
|
||||
foreach (var property in obj.GetType().GetProperties(BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance))
|
||||
foreach (var (attr, property) in obj.GetSettingsSourceProperties())
|
||||
{
|
||||
var attr = property.GetCustomAttribute<SettingSourceAttribute>(true);
|
||||
object value = property.GetValue(obj);
|
||||
|
||||
if (attr == null)
|
||||
continue;
|
||||
|
||||
var prop = property.GetValue(obj);
|
||||
|
||||
switch (prop)
|
||||
switch (value)
|
||||
{
|
||||
case BindableNumber<float> bNumber:
|
||||
yield return new SettingsSlider<float>
|
||||
@ -102,9 +97,22 @@ namespace osu.Game.Configuration
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new InvalidOperationException($"{nameof(SettingSourceAttribute)} was attached to an unsupported type ({prop})");
|
||||
throw new InvalidOperationException($"{nameof(SettingSourceAttribute)} was attached to an unsupported type ({value})");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<(SettingSourceAttribute, PropertyInfo)> GetSettingsSourceProperties(this object obj)
|
||||
{
|
||||
foreach (var property in obj.GetType().GetProperties(BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance))
|
||||
{
|
||||
var attr = property.GetCustomAttribute<SettingSourceAttribute>(true);
|
||||
|
||||
if (attr == null)
|
||||
continue;
|
||||
|
||||
yield return (attr, property);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ namespace osu.Game.Database
|
||||
/// <typeparam name="TFileModel">The associated file join type.</typeparam>
|
||||
public abstract class ArchiveModelManager<TModel, TFileModel> : ICanAcceptFiles, IModelManager<TModel>
|
||||
where TModel : class, IHasFiles<TFileModel>, IHasPrimaryKey, ISoftDelete
|
||||
where TFileModel : INamedFileInfo, new()
|
||||
where TFileModel : class, INamedFileInfo, new()
|
||||
{
|
||||
private const int import_queue_request_concurrency = 1;
|
||||
|
||||
@ -222,9 +222,8 @@ namespace osu.Game.Database
|
||||
{
|
||||
model = CreateModel(archive);
|
||||
|
||||
if (model == null) return Task.FromResult<TModel>(null);
|
||||
|
||||
model.Hash = computeHash(archive);
|
||||
if (model == null)
|
||||
return Task.FromResult<TModel>(null);
|
||||
}
|
||||
catch (TaskCanceledException)
|
||||
{
|
||||
@ -262,18 +261,24 @@ namespace osu.Game.Database
|
||||
/// <remarks>
|
||||
/// In the case of no matching files, a hash will be generated from the passed archive's <see cref="ArchiveReader.Name"/>.
|
||||
/// </remarks>
|
||||
private string computeHash(ArchiveReader reader)
|
||||
private string computeHash(TModel item, ArchiveReader reader = null)
|
||||
{
|
||||
// for now, concatenate all .osu files in the set to create a unique hash.
|
||||
MemoryStream hashable = new MemoryStream();
|
||||
|
||||
foreach (string file in reader.Filenames.Where(f => HashableFileTypes.Any(f.EndsWith)))
|
||||
foreach (TFileModel file in item.Files.Where(f => HashableFileTypes.Any(f.Filename.EndsWith)))
|
||||
{
|
||||
using (Stream s = reader.GetStream(file))
|
||||
using (Stream s = Files.Store.GetStream(file.FileInfo.StoragePath))
|
||||
s.CopyTo(hashable);
|
||||
}
|
||||
|
||||
return hashable.Length > 0 ? hashable.ComputeSHA2Hash() : reader.Name.ComputeSHA2Hash();
|
||||
if (hashable.Length > 0)
|
||||
return hashable.ComputeSHA2Hash();
|
||||
|
||||
if (reader != null)
|
||||
return reader.Name.ComputeSHA2Hash();
|
||||
|
||||
return item.Hash;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -303,6 +308,7 @@ namespace osu.Game.Database
|
||||
LogForModel(item, "Beginning import...");
|
||||
|
||||
item.Files = archive != null ? createFileInfos(archive, Files) : new List<TFileModel>();
|
||||
item.Hash = computeHash(item, archive);
|
||||
|
||||
await Populate(item, archive, cancellationToken);
|
||||
|
||||
@ -358,12 +364,42 @@ namespace osu.Game.Database
|
||||
return item;
|
||||
}, cancellationToken, TaskCreationOptions.HideScheduler, import_scheduler).Unwrap();
|
||||
|
||||
public void UpdateFile(TModel model, TFileModel file, Stream contents)
|
||||
{
|
||||
using (var usage = ContextFactory.GetForWrite())
|
||||
{
|
||||
// Dereference the existing file info, since the file model will be removed.
|
||||
Files.Dereference(file.FileInfo);
|
||||
|
||||
// Remove the file model.
|
||||
usage.Context.Set<TFileModel>().Remove(file);
|
||||
|
||||
// Add the new file info and containing file model.
|
||||
model.Files.Remove(file);
|
||||
model.Files.Add(new TFileModel
|
||||
{
|
||||
Filename = file.Filename,
|
||||
FileInfo = Files.Add(contents)
|
||||
});
|
||||
|
||||
Update(model);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform an update of the specified item.
|
||||
/// TODO: Support file changes.
|
||||
/// TODO: Support file additions/removals.
|
||||
/// </summary>
|
||||
/// <param name="item">The item to update.</param>
|
||||
public void Update(TModel item) => ModelStore.Update(item);
|
||||
public void Update(TModel item)
|
||||
{
|
||||
using (ContextFactory.GetForWrite())
|
||||
{
|
||||
item.Hash = computeHash(item);
|
||||
|
||||
ModelStore.Update(item);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Delete an item from the manager.
|
||||
|
@ -21,7 +21,7 @@ namespace osu.Game.Database
|
||||
/// <typeparam name="TFileModel">The associated file join type.</typeparam>
|
||||
public abstract class DownloadableArchiveModelManager<TModel, TFileModel> : ArchiveModelManager<TModel, TFileModel>, IModelDownloader<TModel>
|
||||
where TModel : class, IHasFiles<TFileModel>, IHasPrimaryKey, ISoftDelete, IEquatable<TModel>
|
||||
where TFileModel : INamedFileInfo, new()
|
||||
where TFileModel : class, INamedFileInfo, new()
|
||||
{
|
||||
public event Action<ArchiveDownloadRequest<TModel>> DownloadBegan;
|
||||
|
||||
|
@ -38,6 +38,11 @@ namespace osu.Game.Graphics.Containers
|
||||
/// </summary>
|
||||
public int Divisor { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// An optional minimum beat length. Any beat length below this will be multiplied by two until valid.
|
||||
/// </summary>
|
||||
public double MinimumBeatLength { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Default length of a beat in milliseconds. Used whenever there is no beatmap or track playing.
|
||||
/// </summary>
|
||||
@ -89,6 +94,9 @@ namespace osu.Game.Graphics.Containers
|
||||
|
||||
double beatLength = timingPoint.BeatLength / Divisor;
|
||||
|
||||
while (beatLength < MinimumBeatLength)
|
||||
beatLength *= 2;
|
||||
|
||||
int beatIndex = (int)((currentTrackTime - timingPoint.Time) / beatLength) - (effectPoint.OmitFirstBarLine ? 1 : 0);
|
||||
|
||||
// The beats before the start of the first control point are off by 1, this should do the trick
|
||||
|
@ -63,7 +63,7 @@ namespace osu.Game.Graphics.Containers
|
||||
}
|
||||
|
||||
public void AddUserLink(User user, Action<SpriteText> creationParameters = null)
|
||||
=> createLink(AddText(user.Username, creationParameters), new LinkDetails(LinkAction.OpenUserProfile, user.Id.ToString()), "View Profile");
|
||||
=> createLink(AddText(user.Username, creationParameters), new LinkDetails(LinkAction.OpenUserProfile, user.Id.ToString()), "view profile");
|
||||
|
||||
private void createLink(IEnumerable<Drawable> drawables, LinkDetails link, string tooltipText, Action action = null)
|
||||
{
|
||||
|
@ -76,12 +76,12 @@ namespace osu.Game.Graphics.Containers
|
||||
return base.OnMouseDown(e);
|
||||
}
|
||||
|
||||
protected override bool OnMouseUp(MouseUpEvent e)
|
||||
protected override void OnMouseUp(MouseUpEvent e)
|
||||
{
|
||||
if (closeOnMouseUp && !base.ReceivePositionalInputAt(e.ScreenSpaceMousePosition))
|
||||
Hide();
|
||||
|
||||
return base.OnMouseUp(e);
|
||||
base.OnMouseUp(e);
|
||||
}
|
||||
|
||||
public virtual bool OnPressed(GlobalAction action)
|
||||
@ -99,7 +99,9 @@ namespace osu.Game.Graphics.Containers
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool OnReleased(GlobalAction action) => false;
|
||||
public void OnReleased(GlobalAction action)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void UpdateState(ValueChangedEvent<Visibility> state)
|
||||
{
|
||||
|
@ -50,15 +50,15 @@ namespace osu.Game.Graphics.Containers
|
||||
return base.OnMouseDown(e);
|
||||
}
|
||||
|
||||
protected override bool OnDrag(DragEvent e)
|
||||
protected override void OnDrag(DragEvent e)
|
||||
{
|
||||
if (rightMouseDragging)
|
||||
{
|
||||
scrollFromMouseEvent(e);
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
return base.OnDrag(e);
|
||||
base.OnDrag(e);
|
||||
}
|
||||
|
||||
protected override bool OnDragStart(DragStartEvent e)
|
||||
@ -72,15 +72,15 @@ namespace osu.Game.Graphics.Containers
|
||||
return base.OnDragStart(e);
|
||||
}
|
||||
|
||||
protected override bool OnDragEnd(DragEndEvent e)
|
||||
protected override void OnDragEnd(DragEndEvent e)
|
||||
{
|
||||
if (rightMouseDragging)
|
||||
{
|
||||
rightMouseDragging = false;
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
return base.OnDragEnd(e);
|
||||
base.OnDragEnd(e);
|
||||
}
|
||||
|
||||
protected override bool OnScroll(ScrollEvent e)
|
||||
@ -162,13 +162,13 @@ namespace osu.Game.Graphics.Containers
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override bool OnMouseUp(MouseUpEvent e)
|
||||
protected override void OnMouseUp(MouseUpEvent e)
|
||||
{
|
||||
if (e.Button != MouseButton.Left) return false;
|
||||
if (e.Button != MouseButton.Left) return;
|
||||
|
||||
box.FadeColour(Color4.White, 100);
|
||||
|
||||
return base.OnMouseUp(e);
|
||||
base.OnMouseUp(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ namespace osu.Game.Graphics.Cursor
|
||||
return base.OnMouseDown(e);
|
||||
}
|
||||
|
||||
protected override bool OnMouseUp(MouseUpEvent e)
|
||||
protected override void OnMouseUp(MouseUpEvent e)
|
||||
{
|
||||
if (!e.IsPressed(MouseButton.Left) && !e.IsPressed(MouseButton.Right))
|
||||
{
|
||||
@ -107,7 +107,7 @@ namespace osu.Game.Graphics.Cursor
|
||||
dragRotationState = DragRotationState.NotDragging;
|
||||
}
|
||||
|
||||
return base.OnMouseUp(e);
|
||||
base.OnMouseUp(e);
|
||||
}
|
||||
|
||||
protected override void PopIn()
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
using System;
|
||||
using osu.Game.Beatmaps;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Graphics
|
||||
@ -35,6 +36,20 @@ namespace osu.Game.Graphics
|
||||
Convert.ToByte(hex.Substring(2, 2), 16),
|
||||
Convert.ToByte(hex.Substring(4, 2), 16),
|
||||
255);
|
||||
|
||||
case 4:
|
||||
return new Color4(
|
||||
(byte)(Convert.ToByte(hex.Substring(0, 1), 16) * 17),
|
||||
(byte)(Convert.ToByte(hex.Substring(1, 1), 16) * 17),
|
||||
(byte)(Convert.ToByte(hex.Substring(2, 1), 16) * 17),
|
||||
(byte)(Convert.ToByte(hex.Substring(3, 1), 16) * 17));
|
||||
|
||||
case 8:
|
||||
return new Color4(
|
||||
Convert.ToByte(hex.Substring(0, 2), 16),
|
||||
Convert.ToByte(hex.Substring(2, 2), 16),
|
||||
Convert.ToByte(hex.Substring(4, 2), 16),
|
||||
Convert.ToByte(hex.Substring(6, 2), 16));
|
||||
}
|
||||
}
|
||||
|
||||
@ -63,6 +78,46 @@ namespace osu.Game.Graphics
|
||||
}
|
||||
}
|
||||
|
||||
public Color4 ForOverlayElement(OverlayColourScheme colourScheme, float saturation, float lightness, float opacity = 1) => Color4.FromHsl(new Vector4(getBaseHue(colourScheme), saturation, lightness, opacity));
|
||||
|
||||
// See https://github.com/ppy/osu-web/blob/4218c288292d7c810b619075471eaea8bbb8f9d8/app/helpers.php#L1463
|
||||
private static float getBaseHue(OverlayColourScheme colourScheme)
|
||||
{
|
||||
float hue;
|
||||
|
||||
switch (colourScheme)
|
||||
{
|
||||
default:
|
||||
throw new ArgumentException($@"{colourScheme} colour scheme does not provide a hue value in {nameof(getBaseHue)}.");
|
||||
|
||||
case OverlayColourScheme.Red:
|
||||
hue = 0;
|
||||
break;
|
||||
|
||||
case OverlayColourScheme.Pink:
|
||||
hue = 333;
|
||||
break;
|
||||
|
||||
case OverlayColourScheme.Orange:
|
||||
hue = 46;
|
||||
break;
|
||||
|
||||
case OverlayColourScheme.Green:
|
||||
hue = 115;
|
||||
break;
|
||||
|
||||
case OverlayColourScheme.Purple:
|
||||
hue = 255;
|
||||
break;
|
||||
|
||||
case OverlayColourScheme.Blue:
|
||||
hue = 200;
|
||||
break;
|
||||
}
|
||||
|
||||
return hue / 360f;
|
||||
}
|
||||
|
||||
// See https://github.com/ppy/osu-web/blob/master/resources/assets/less/colors.less
|
||||
public readonly Color4 PurpleLighter = FromHex(@"eeeeff");
|
||||
public readonly Color4 PurpleLight = FromHex(@"aa88ff");
|
||||
@ -165,4 +220,14 @@ namespace osu.Game.Graphics
|
||||
|
||||
public readonly Color4 ContextMenuGray = FromHex(@"223034");
|
||||
}
|
||||
|
||||
public enum OverlayColourScheme
|
||||
{
|
||||
Red,
|
||||
Pink,
|
||||
Orange,
|
||||
Green,
|
||||
Purple,
|
||||
Blue
|
||||
}
|
||||
}
|
||||
|
@ -67,7 +67,9 @@ namespace osu.Game.Graphics
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool OnReleased(GlobalAction action) => false;
|
||||
public void OnReleased(GlobalAction action)
|
||||
{
|
||||
}
|
||||
|
||||
private volatile int screenShotTasks;
|
||||
|
||||
|
@ -67,7 +67,9 @@ namespace osu.Game.Graphics.UserInterface
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool OnReleased(GlobalAction action) => action == GlobalAction.Back;
|
||||
public void OnReleased(GlobalAction action)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -232,11 +232,11 @@ namespace osu.Game.Graphics.UserInterface
|
||||
return base.OnMouseDown(e);
|
||||
}
|
||||
|
||||
protected override bool OnMouseUp(MouseUpEvent e)
|
||||
protected override void OnMouseUp(MouseUpEvent e)
|
||||
{
|
||||
if (Selected.Value)
|
||||
colourContainer.ResizeWidthTo(hover_width, click_duration, Easing.In);
|
||||
return base.OnMouseUp(e);
|
||||
base.OnMouseUp(e);
|
||||
}
|
||||
|
||||
protected override bool OnHover(HoverEvent e)
|
||||
|
@ -57,6 +57,6 @@ namespace osu.Game.Graphics.UserInterface
|
||||
return true;
|
||||
}
|
||||
|
||||
public string TooltipText => "View in browser";
|
||||
public string TooltipText => "view in browser";
|
||||
}
|
||||
}
|
||||
|
@ -80,7 +80,9 @@ namespace osu.Game.Graphics.UserInterface
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool OnReleased(GlobalAction action) => false;
|
||||
public void OnReleased(GlobalAction action)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool RequestsFocus => HoldFocus;
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ namespace osu.Game.Graphics.UserInterface
|
||||
/// <summary>
|
||||
/// Length of debounce for hover sound playback, in milliseconds. Default is 50ms.
|
||||
/// </summary>
|
||||
public double HoverDebounceTime { get; set; } = 50;
|
||||
public double HoverDebounceTime { get; } = 50;
|
||||
|
||||
protected readonly HoverSampleSet SampleSet;
|
||||
|
||||
|
@ -107,10 +107,10 @@ namespace osu.Game.Graphics.UserInterface
|
||||
return base.OnMouseDown(e);
|
||||
}
|
||||
|
||||
protected override bool OnMouseUp(MouseUpEvent e)
|
||||
protected override void OnMouseUp(MouseUpEvent e)
|
||||
{
|
||||
Content.ScaleTo(1, 1000, Easing.OutElastic);
|
||||
return base.OnMouseUp(e);
|
||||
base.OnMouseUp(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -129,10 +129,10 @@ namespace osu.Game.Graphics.UserInterface
|
||||
return base.OnMouseDown(e);
|
||||
}
|
||||
|
||||
protected override bool OnMouseUp(MouseUpEvent e)
|
||||
protected override void OnMouseUp(MouseUpEvent e)
|
||||
{
|
||||
Content.ScaleTo(1, 1000, Easing.OutElastic);
|
||||
return base.OnMouseUp(e);
|
||||
base.OnMouseUp(e);
|
||||
}
|
||||
|
||||
protected virtual SpriteText CreateText() => new OsuSpriteText
|
||||
|
@ -104,7 +104,7 @@ namespace osu.Game.Graphics.UserInterface
|
||||
|
||||
private class CapsWarning : SpriteIcon, IHasTooltip
|
||||
{
|
||||
public string TooltipText => @"Caps lock is active";
|
||||
public string TooltipText => @"caps lock is active";
|
||||
|
||||
public CapsWarning()
|
||||
{
|
||||
|
@ -128,10 +128,10 @@ namespace osu.Game.Graphics.UserInterface
|
||||
return base.OnMouseDown(e);
|
||||
}
|
||||
|
||||
protected override bool OnMouseUp(MouseUpEvent e)
|
||||
protected override void OnMouseUp(MouseUpEvent e)
|
||||
{
|
||||
Nub.Current.Value = false;
|
||||
return base.OnMouseUp(e);
|
||||
base.OnMouseUp(e);
|
||||
}
|
||||
|
||||
protected override void OnUserChange(T value)
|
||||
|
@ -10,7 +10,6 @@ using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.UserInterface;
|
||||
@ -84,14 +83,6 @@ namespace osu.Game.Graphics.UserInterface
|
||||
set => strip.Colour = value;
|
||||
}
|
||||
|
||||
protected override TabFillFlowContainer CreateTabFlow() => new OsuTabFillFlowContainer
|
||||
{
|
||||
Direction = FillDirection.Full,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Depth = -1,
|
||||
Masking = true
|
||||
};
|
||||
|
||||
protected override void UpdateAfterChildren()
|
||||
{
|
||||
base.UpdateAfterChildren();
|
||||
@ -283,10 +274,5 @@ namespace osu.Game.Graphics.UserInterface
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class OsuTabFillFlowContainer : TabFillFlowContainer
|
||||
{
|
||||
protected override int Compare(Drawable x, Drawable y) => CompareReverseChildID(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user