mirror of
https://github.com/ppy/osu.git
synced 2024-11-06 09:47:52 +08:00
Merge remote-tracking branch 'upstream/master' into lookup-players-for-ruleset
This commit is contained in:
commit
bedd136c81
@ -7,6 +7,12 @@
|
||||
"commands": [
|
||||
"dotnet-cake"
|
||||
]
|
||||
},
|
||||
"dotnet-format": {
|
||||
"version": "3.1.37601",
|
||||
"commands": [
|
||||
"dotnet-format"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
165
.editorconfig
165
.editorconfig
@ -12,16 +12,171 @@ trim_trailing_whitespace = true
|
||||
|
||||
#PascalCase for public and protected members
|
||||
dotnet_naming_style.pascalcase.capitalization = pascal_case
|
||||
dotnet_naming_symbols.public_members.applicable_accessibilities = public,internal,protected,protected_internal
|
||||
dotnet_naming_symbols.public_members.applicable_kinds = property,method,field,event,delegate
|
||||
dotnet_naming_rule.public_members_pascalcase.severity = suggestion
|
||||
dotnet_naming_symbols.public_members.applicable_accessibilities = public,internal,protected,protected_internal,private_protected
|
||||
dotnet_naming_symbols.public_members.applicable_kinds = property,method,field,event
|
||||
dotnet_naming_rule.public_members_pascalcase.severity = error
|
||||
dotnet_naming_rule.public_members_pascalcase.symbols = public_members
|
||||
dotnet_naming_rule.public_members_pascalcase.style = pascalcase
|
||||
|
||||
#camelCase for private members
|
||||
dotnet_naming_style.camelcase.capitalization = camel_case
|
||||
|
||||
dotnet_naming_symbols.private_members.applicable_accessibilities = private
|
||||
dotnet_naming_symbols.private_members.applicable_kinds = property,method,field,event,delegate
|
||||
dotnet_naming_rule.private_members_camelcase.severity = suggestion
|
||||
dotnet_naming_symbols.private_members.applicable_kinds = property,method,field,event
|
||||
dotnet_naming_rule.private_members_camelcase.severity = warning
|
||||
dotnet_naming_rule.private_members_camelcase.symbols = private_members
|
||||
dotnet_naming_rule.private_members_camelcase.style = camelcase
|
||||
|
||||
dotnet_naming_symbols.local_function.applicable_kinds = local_function
|
||||
dotnet_naming_rule.local_function_camelcase.severity = warning
|
||||
dotnet_naming_rule.local_function_camelcase.symbols = local_function
|
||||
dotnet_naming_rule.local_function_camelcase.style = camelcase
|
||||
|
||||
#all_lower for private and local constants/static readonlys
|
||||
dotnet_naming_style.all_lower.capitalization = all_lower
|
||||
dotnet_naming_style.all_lower.word_separator = _
|
||||
|
||||
dotnet_naming_symbols.private_constants.applicable_accessibilities = private
|
||||
dotnet_naming_symbols.private_constants.required_modifiers = const
|
||||
dotnet_naming_symbols.private_constants.applicable_kinds = field
|
||||
dotnet_naming_rule.private_const_all_lower.severity = warning
|
||||
dotnet_naming_rule.private_const_all_lower.symbols = private_constants
|
||||
dotnet_naming_rule.private_const_all_lower.style = all_lower
|
||||
|
||||
dotnet_naming_symbols.private_static_readonly.applicable_accessibilities = private
|
||||
dotnet_naming_symbols.private_static_readonly.required_modifiers = static,readonly
|
||||
dotnet_naming_symbols.private_static_readonly.applicable_kinds = field
|
||||
dotnet_naming_rule.private_static_readonly_all_lower.severity = warning
|
||||
dotnet_naming_rule.private_static_readonly_all_lower.symbols = private_static_readonly
|
||||
dotnet_naming_rule.private_static_readonly_all_lower.style = all_lower
|
||||
|
||||
dotnet_naming_symbols.local_constants.applicable_kinds = local
|
||||
dotnet_naming_symbols.local_constants.required_modifiers = const
|
||||
dotnet_naming_rule.local_const_all_lower.severity = warning
|
||||
dotnet_naming_rule.local_const_all_lower.symbols = local_constants
|
||||
dotnet_naming_rule.local_const_all_lower.style = all_lower
|
||||
|
||||
#ALL_UPPER for non private constants/static readonlys
|
||||
dotnet_naming_style.all_upper.capitalization = all_upper
|
||||
dotnet_naming_style.all_upper.word_separator = _
|
||||
|
||||
dotnet_naming_symbols.public_constants.applicable_accessibilities = public,internal,protected,protected_internal,private_protected
|
||||
dotnet_naming_symbols.public_constants.required_modifiers = const
|
||||
dotnet_naming_symbols.public_constants.applicable_kinds = field
|
||||
dotnet_naming_rule.public_const_all_upper.severity = warning
|
||||
dotnet_naming_rule.public_const_all_upper.symbols = public_constants
|
||||
dotnet_naming_rule.public_const_all_upper.style = all_upper
|
||||
|
||||
dotnet_naming_symbols.public_static_readonly.applicable_accessibilities = public,internal,protected,protected_internal,private_protected
|
||||
dotnet_naming_symbols.public_static_readonly.required_modifiers = static,readonly
|
||||
dotnet_naming_symbols.public_static_readonly.applicable_kinds = field
|
||||
dotnet_naming_rule.public_static_readonly_all_upper.severity = warning
|
||||
dotnet_naming_rule.public_static_readonly_all_upper.symbols = public_static_readonly
|
||||
dotnet_naming_rule.public_static_readonly_all_upper.style = all_upper
|
||||
|
||||
#Roslyn formating options
|
||||
|
||||
#Formatting - indentation options
|
||||
csharp_indent_case_contents = true
|
||||
csharp_indent_case_contents_when_block = false
|
||||
csharp_indent_labels = one_less_than_current
|
||||
csharp_indent_switch_labels = true
|
||||
|
||||
#Formatting - new line options
|
||||
csharp_new_line_before_catch = true
|
||||
csharp_new_line_before_else = true
|
||||
csharp_new_line_before_finally = true
|
||||
csharp_new_line_before_open_brace = all
|
||||
#csharp_new_line_before_members_in_anonymous_types = true
|
||||
#csharp_new_line_before_members_in_object_initializers = true # Currently no effect in VS/dotnet format (16.4), and makes Rider confusing
|
||||
csharp_new_line_between_query_expression_clauses = true
|
||||
|
||||
#Formatting - organize using options
|
||||
dotnet_sort_system_directives_first = true
|
||||
|
||||
#Formatting - spacing options
|
||||
csharp_space_after_cast = false
|
||||
csharp_space_after_colon_in_inheritance_clause = true
|
||||
csharp_space_after_keywords_in_control_flow_statements = true
|
||||
csharp_space_before_colon_in_inheritance_clause = true
|
||||
csharp_space_between_method_call_empty_parameter_list_parentheses = false
|
||||
csharp_space_between_method_call_name_and_opening_parenthesis = false
|
||||
csharp_space_between_method_call_parameter_list_parentheses = false
|
||||
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
|
||||
csharp_space_between_method_declaration_parameter_list_parentheses = false
|
||||
|
||||
#Formatting - wrapping options
|
||||
csharp_preserve_single_line_blocks = true
|
||||
csharp_preserve_single_line_statements = true
|
||||
|
||||
#Roslyn language styles
|
||||
|
||||
#Style - type names
|
||||
dotnet_style_predefined_type_for_locals_parameters_members = true:silent
|
||||
dotnet_style_predefined_type_for_member_access = true:silent
|
||||
csharp_style_var_when_type_is_apparent = true:none
|
||||
csharp_style_var_for_built_in_types = true:none
|
||||
csharp_style_var_elsewhere = true:silent
|
||||
|
||||
#Style - modifiers
|
||||
dotnet_style_require_accessibility_modifiers = for_non_interface_members:warning
|
||||
csharp_preferred_modifier_order = public,private,protected,internal,new,abstract,virtual,sealed,override,static,readonly,extern,unsafe,volatile,async:warning
|
||||
|
||||
#Style - parentheses
|
||||
# Skipped because roslyn cannot separate +-*/ with << >>
|
||||
|
||||
#Style - expression bodies
|
||||
csharp_style_expression_bodied_accessors = true:silent
|
||||
csharp_style_expression_bodied_constructors = false:none
|
||||
csharp_style_expression_bodied_indexers = true:silent
|
||||
csharp_style_expression_bodied_methods = true:silent
|
||||
csharp_style_expression_bodied_operators = true:silent
|
||||
csharp_style_expression_bodied_properties = true:silent
|
||||
|
||||
#Style - expression preferences
|
||||
dotnet_style_object_initializer = true:warning
|
||||
dotnet_style_collection_initializer = true:warning
|
||||
dotnet_style_prefer_inferred_anonymous_type_member_names = true:warning
|
||||
dotnet_style_prefer_auto_properties = true:silent
|
||||
dotnet_style_prefer_conditional_expression_over_assignment = true:silent
|
||||
dotnet_style_prefer_conditional_expression_over_return = true:silent
|
||||
dotnet_style_prefer_compound_assignment = true:silent
|
||||
|
||||
#Style - null/type checks
|
||||
dotnet_style_coalesce_expression = true:warning
|
||||
dotnet_style_null_propagation = true:warning
|
||||
csharp_style_pattern_matching_over_is_with_cast_check = true:silent
|
||||
csharp_style_pattern_matching_over_as_with_null_check = true:silent
|
||||
csharp_style_throw_expression = true:silent
|
||||
csharp_style_conditional_delegate_call = true:suggestion
|
||||
|
||||
#Style - unused
|
||||
dotnet_code_quality_unused_parameters = non_public:silent
|
||||
csharp_style_unused_value_expression_statement_preference = discard_variable:silent
|
||||
csharp_style_unused_value_assignment_preference = discard_variable:silent
|
||||
|
||||
#Style - variable declaration
|
||||
csharp_style_inlined_variable_declaration = true:silent
|
||||
csharp_style_deconstructed_variable_declaration = true:silent
|
||||
|
||||
#Style - other C# 7.x features
|
||||
csharp_style_expression_bodied_local_functions = true:silent
|
||||
dotnet_style_prefer_inferred_tuple_names = true:warning
|
||||
csharp_prefer_simple_default_expression = true:warning
|
||||
csharp_style_pattern_local_over_anonymous_function = true:silent
|
||||
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent
|
||||
|
||||
#Supressing roslyn built-in analyzers
|
||||
# Suppress: EC112
|
||||
|
||||
#Field can be readonly
|
||||
dotnet_diagnostic.IDE0044.severity = silent
|
||||
#Private method is unused
|
||||
dotnet_diagnostic.IDE0051.severity = silent
|
||||
#Private member is unused
|
||||
dotnet_diagnostic.IDE0052.severity = silent
|
||||
|
||||
#Rules for disposable
|
||||
dotnet_diagnostic.IDE0067.severity = none
|
||||
dotnet_diagnostic.IDE0068.severity = none
|
||||
dotnet_diagnostic.IDE0069.severity = none
|
12
README.md
12
README.md
@ -19,9 +19,9 @@ Detailed changelogs are published on the [official osu! site](https://osu.ppy.sh
|
||||
## Requirements
|
||||
|
||||
- A desktop platform with the [.NET Core SDK 3.0](https://www.microsoft.com/net/learn/get-started) or higher installed.
|
||||
- When running on linux, please have a system-wide ffmpeg installation available to support video decoding.
|
||||
- When running on Linux, please have a system-wide FFmpeg installation available to support video decoding.
|
||||
- When running on Windows 7 or 8.1, **[additional prerequisites](https://docs.microsoft.com/en-us/dotnet/core/windows-prerequisites?tabs=netcore2x)** may be required to correctly run .NET Core applications if your operating system is not up-to-date with the latest service packs.
|
||||
- When working with the codebase, we recommend using an IDE with intellisense and syntax highlighting, such as [Visual Studio 2019+](https://visualstudio.microsoft.com/vs/), [Jetbrains Rider](https://www.jetbrains.com/rider/) or [Visual Studio Code](https://code.visualstudio.com/).
|
||||
- When working with the codebase, we recommend using an IDE with intelligent code completion and syntax highlighting, such as [Visual Studio 2019+](https://visualstudio.microsoft.com/vs/), [JetBrains Rider](https://www.jetbrains.com/rider/) or [Visual Studio Code](https://code.visualstudio.com/).
|
||||
|
||||
## Running osu!
|
||||
|
||||
@ -68,7 +68,7 @@ dotnet run --project osu.Desktop
|
||||
|
||||
If you are not interested in debugging osu!, you can add `-c Release` to gain performance. In this case, you must replace `Debug` with `Release` in any commands mentioned in this document.
|
||||
|
||||
If the build fails, try to restore nuget packages with `dotnet restore`.
|
||||
If the build fails, try to restore NuGet packages with `dotnet restore`.
|
||||
|
||||
### Testing with resource/framework modifications
|
||||
|
||||
@ -76,11 +76,11 @@ Sometimes it may be necessary to cross-test changes in [osu-resources](https://g
|
||||
|
||||
### Code analysis
|
||||
|
||||
Code analysis can be run with `powershell ./build.ps1` or `build.sh`. This is currently only supported under windows due to [resharper cli shortcomings](https://youtrack.jetbrains.com/issue/RSRP-410004). Alternatively, you can install resharper or use rider to get inline support in your IDE of choice.
|
||||
Code analysis can be run with `powershell ./build.ps1` or `build.sh`. This is currently only supported under Windows due to [ReSharper CLI shortcomings](https://youtrack.jetbrains.com/issue/RSRP-410004). Alternatively, you can install ReSharper or use Rider to get inline support in your IDE of choice.
|
||||
|
||||
## Contributing
|
||||
|
||||
We welcome all contributions, but keep in mind that we already have a lot of the UI designed. If you wish to work on something with the intention on having it included in the official distribution, please open an issue for discussion and we will give you what you need from a design perspective to proceed. If you want to make *changes* to the design, we recommend you open an issue with your intentions before spending too much time, to ensure no effort is wasted.
|
||||
We welcome all contributions, but keep in mind that we already have a lot of the UI designed. If you wish to work on something with the intention of having it included in the official distribution, please open an issue for discussion and we will give you what you need from a design perspective to proceed. If you want to make *changes* to the design, we recommend you open an issue with your intentions before spending too much time, to ensure no effort is wasted.
|
||||
|
||||
If you're unsure of what you can help with, check out the [list of open issues](https://github.com/ppy/osu/issues) (especially those with the ["good first issue"](https://github.com/ppy/osu/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A%22good+first+issue%22) label).
|
||||
|
||||
@ -88,7 +88,7 @@ Before starting, please make sure you are familiar with the [development and tes
|
||||
|
||||
Note that while we already have certain standards in place, nothing is set in stone. If you have an issue with the way code is structured; with any libraries we are using; with any processes involved with contributing, *please* bring it up. We welcome all feedback so we can make contributing to this project as pain-free as possible.
|
||||
|
||||
For those interested, we love to reward quality contributions via [bounties](https://docs.google.com/spreadsheets/d/1jNXfj_S3Pb5PErA-czDdC9DUu4IgUbe1Lt8E7CYUJuE/view?&rm=minimal#gid=523803337), paid out via paypal or osu! supporter tags. Don't hesitate to [request a bounty](https://docs.google.com/forms/d/e/1FAIpQLSet_8iFAgPMG526pBZ2Kic6HSh7XPM3fE8xPcnWNkMzINDdYg/viewform) for your work on this project.
|
||||
For those interested, we love to reward quality contributions via [bounties](https://docs.google.com/spreadsheets/d/1jNXfj_S3Pb5PErA-czDdC9DUu4IgUbe1Lt8E7CYUJuE/view?&rm=minimal#gid=523803337), paid out via PayPal or osu!supporter tags. Don't hesitate to [request a bounty](https://docs.google.com/forms/d/e/1FAIpQLSet_8iFAgPMG526pBZ2Kic6HSh7XPM3fE8xPcnWNkMzINDdYg/viewform) for your work on this project.
|
||||
|
||||
## Licence
|
||||
|
||||
|
@ -11,6 +11,7 @@ var target = Argument("target", "Build");
|
||||
var configuration = Argument("configuration", "Release");
|
||||
|
||||
var rootDirectory = new DirectoryPath("..");
|
||||
var sln = rootDirectory.CombineWithFilePath("osu.sln");
|
||||
var desktopBuilds = rootDirectory.CombineWithFilePath("build/Desktop.proj");
|
||||
var desktopSlnf = rootDirectory.CombineWithFilePath("osu.Desktop.slnf");
|
||||
|
||||
@ -60,8 +61,12 @@ Task("CodeFileSanity")
|
||||
});
|
||||
});
|
||||
|
||||
Task("DotnetFormat")
|
||||
.Does(() => DotNetCoreTool(sln.FullPath, "format", "--dry-run --check"));
|
||||
|
||||
Task("Build")
|
||||
.IsDependentOn("CodeFileSanity")
|
||||
.IsDependentOn("DotnetFormat")
|
||||
.IsDependentOn("InspectCode")
|
||||
.IsDependentOn("Test");
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
|
@ -40,8 +40,10 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
beatmap.HitObjects.Add(new Fruit { StartTime = 1008, X = 56 / 512f, });
|
||||
|
||||
for (int i = 0; i < 512; i++)
|
||||
{
|
||||
if (i % 5 < 3)
|
||||
beatmap.HitObjects.Add(new Fruit { X = i % 10 < 5 ? 0.02f : 0.98f, StartTime = 2000 + i * 100, NewCombo = i % 8 == 0 });
|
||||
}
|
||||
|
||||
return beatmap;
|
||||
}
|
||||
|
@ -195,11 +195,16 @@ namespace osu.Game.Rulesets.Catch.Beatmaps
|
||||
{
|
||||
if (currentObject is Fruit)
|
||||
objectWithDroplets.Add(currentObject);
|
||||
|
||||
if (currentObject is JuiceStream)
|
||||
{
|
||||
foreach (var currentJuiceElement in currentObject.NestedHitObjects)
|
||||
{
|
||||
if (!(currentJuiceElement is TinyDroplet))
|
||||
objectWithDroplets.Add((CatchHitObject)currentJuiceElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
objectWithDroplets.Sort((h1, h2) => h1.StartTime.CompareTo(h2.StartTime));
|
||||
|
||||
|
@ -27,12 +27,14 @@ namespace osu.Game.Rulesets.Catch.Objects
|
||||
return;
|
||||
|
||||
for (double i = StartTime; i <= EndTime; i += spacing)
|
||||
{
|
||||
AddNested(new Banana
|
||||
{
|
||||
Samples = Samples,
|
||||
StartTime = i
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public double EndTime => StartTime + Duration;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
|
@ -109,8 +109,10 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
||||
{
|
||||
// Generate a new pattern by copying the last hit objects in reverse-column order
|
||||
for (int i = RandomStart; i < TotalColumns; i++)
|
||||
{
|
||||
if (PreviousPattern.ColumnHasObject(i))
|
||||
addToPattern(pattern, RandomStart + TotalColumns - i - 1);
|
||||
}
|
||||
|
||||
return pattern;
|
||||
}
|
||||
@ -132,8 +134,10 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
||||
{
|
||||
// Generate a new pattern by placing on the already filled columns
|
||||
for (int i = RandomStart; i < TotalColumns; i++)
|
||||
{
|
||||
if (PreviousPattern.ColumnHasObject(i))
|
||||
addToPattern(pattern, i);
|
||||
}
|
||||
|
||||
return pattern;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
|
@ -24,6 +24,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
public TestSceneDrawableJudgement()
|
||||
{
|
||||
foreach (HitResult result in Enum.GetValues(typeof(HitResult)).OfType<HitResult>().Skip(1))
|
||||
{
|
||||
AddStep("Show " + result.GetDescription(), () => SetContents(() =>
|
||||
new DrawableOsuJudgement(new JudgementResult(new HitObject(), new Judgement()) { Type = result }, null)
|
||||
{
|
||||
@ -32,4 +33,5 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,8 +29,10 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
};
|
||||
|
||||
for (int i = 0; i < 512; i++)
|
||||
{
|
||||
if (i % 32 < 20)
|
||||
beatmap.HitObjects.Add(new HitCircle { Position = new Vector2(256, 192), StartTime = i * 100 });
|
||||
}
|
||||
|
||||
return beatmap;
|
||||
}
|
||||
|
@ -2,8 +2,12 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Osu.UI;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osuTK;
|
||||
@ -12,11 +16,36 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
{
|
||||
public class DrawableOsuEditRuleset : DrawableOsuRuleset
|
||||
{
|
||||
/// <summary>
|
||||
/// Hit objects are intentionally made to fade out at a constant slower rate than in gameplay.
|
||||
/// This allows a mapper to gain better historical context and use recent hitobjects as reference / snap points.
|
||||
/// </summary>
|
||||
private const double editor_hit_object_fade_out_extension = 500;
|
||||
|
||||
public DrawableOsuEditRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList<Mod> mods)
|
||||
: base(ruleset, beatmap, mods)
|
||||
{
|
||||
}
|
||||
|
||||
public override DrawableHitObject<OsuHitObject> CreateDrawableRepresentation(OsuHitObject h)
|
||||
=> base.CreateDrawableRepresentation(h)?.With(d => d.ApplyCustomUpdateState += updateState);
|
||||
|
||||
private void updateState(DrawableHitObject hitObject, ArmedState state)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case ArmedState.Miss:
|
||||
// Get the existing fade out transform
|
||||
var existing = hitObject.Transforms.LastOrDefault(t => t.TargetMember == nameof(Alpha));
|
||||
if (existing == null)
|
||||
return;
|
||||
|
||||
using (hitObject.BeginAbsoluteSequence(existing.StartTime))
|
||||
hitObject.FadeOut(editor_hit_object_fade_out_extension).Expire();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected override Playfield CreatePlayfield() => new OsuPlayfieldNoCursor();
|
||||
|
||||
public override PlayfieldAdjustmentContainer CreatePlayfieldAdjustmentContainer() => new OsuPlayfieldAdjustmentContainer { Size = Vector2.One };
|
||||
|
@ -55,8 +55,10 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
}
|
||||
|
||||
for (int i = 0; i < amountWiggles; i++)
|
||||
{
|
||||
using (drawable.BeginAbsoluteSequence(osuObject.StartTime - osuObject.TimePreempt + i * wiggle_duration, true))
|
||||
wiggle();
|
||||
}
|
||||
|
||||
// Keep wiggling sliders and spinners for their duration
|
||||
if (!(osuObject is IHasEndTime endTime))
|
||||
@ -65,8 +67,10 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
amountWiggles = (int)(endTime.Duration / wiggle_duration);
|
||||
|
||||
for (int i = 0; i < amountWiggles; i++)
|
||||
{
|
||||
using (drawable.BeginAbsoluteSequence(osuObject.StartTime + i * wiggle_duration, true))
|
||||
wiggle();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -133,12 +133,14 @@ namespace osu.Game.Rulesets.Osu.Objects
|
||||
var sampleList = new List<HitSampleInfo>();
|
||||
|
||||
if (firstSample != null)
|
||||
{
|
||||
sampleList.Add(new HitSampleInfo
|
||||
{
|
||||
Bank = firstSample.Bank,
|
||||
Volume = firstSample.Volume,
|
||||
Name = @"slidertick",
|
||||
});
|
||||
}
|
||||
|
||||
switch (e.Type)
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
|
@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
|
@ -225,8 +225,10 @@ namespace osu.Game.Tests.NonVisual
|
||||
private void fastForwardToPoint(double destination)
|
||||
{
|
||||
for (int i = 0; i < 1000; i++)
|
||||
{
|
||||
if (handler.SetFrameFromTime(destination) == null)
|
||||
return;
|
||||
}
|
||||
|
||||
throw new TimeoutException("Seek was never fulfilled");
|
||||
}
|
||||
|
@ -25,7 +25,9 @@ namespace osu.Game.Tests.Skins
|
||||
var comboColors = decoder.Decode(stream).ComboColours;
|
||||
|
||||
List<Color4> expectedColors;
|
||||
|
||||
if (hasColours)
|
||||
{
|
||||
expectedColors = new List<Color4>
|
||||
{
|
||||
new Color4(142, 199, 255, 255),
|
||||
@ -33,6 +35,7 @@ namespace osu.Game.Tests.Skins
|
||||
new Color4(128, 255, 255, 255),
|
||||
new Color4(100, 100, 100, 100),
|
||||
};
|
||||
}
|
||||
else
|
||||
expectedColors = new DefaultSkin().Configuration.ComboColours;
|
||||
|
||||
|
@ -130,12 +130,14 @@ namespace osu.Game.Tests.Visual.Online
|
||||
AddRepeatStep("add many messages", () =>
|
||||
{
|
||||
for (int i = 0; i < messages_per_call; i++)
|
||||
{
|
||||
testChannel.AddNewMessages(new Message(sequence++)
|
||||
{
|
||||
Sender = longUsernameUser,
|
||||
Content = "Many messages! " + Guid.NewGuid(),
|
||||
Timestamp = DateTimeOffset.Now
|
||||
});
|
||||
}
|
||||
}, Channel.MAX_HISTORY / messages_per_call + 5);
|
||||
|
||||
AddAssert("Ensure no adjacent day separators", () =>
|
||||
@ -143,8 +145,10 @@ namespace osu.Game.Tests.Visual.Online
|
||||
var indices = chatDisplay.FillFlow.OfType<DrawableChannel.DaySeparator>().Select(ds => chatDisplay.FillFlow.IndexOf(ds));
|
||||
|
||||
foreach (var i in indices)
|
||||
{
|
||||
if (i < chatDisplay.FillFlow.Count && chatDisplay.FillFlow[i + 1] is DrawableChannel.DaySeparator)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
@ -467,8 +467,10 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
private void advanceSelection(bool diff, int direction = 1, int count = 1)
|
||||
{
|
||||
if (count == 1)
|
||||
{
|
||||
AddStep($"select {(direction > 0 ? "next" : "prev")} {(diff ? "diff" : "set")}", () =>
|
||||
carousel.SelectNext(direction, !diff));
|
||||
}
|
||||
else
|
||||
{
|
||||
AddRepeatStep($"select {(direction > 0 ? "next" : "prev")} {(diff ? "diff" : "set")}", () =>
|
||||
|
@ -132,11 +132,13 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
changeRuleset(1);
|
||||
|
||||
if (rulesetsInSameBeatmap)
|
||||
{
|
||||
AddStep("import multi-ruleset map", () =>
|
||||
{
|
||||
var usableRulesets = rulesets.AvailableRulesets.Where(r => r.ID != 2).ToArray();
|
||||
manager.Import(createTestBeatmapSet(0, usableRulesets)).Wait();
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
addRulesetImportStep(1);
|
||||
|
@ -109,16 +109,20 @@ namespace osu.Game.Tests.Visual
|
||||
AddAssert("check OsuGame DI members", () =>
|
||||
{
|
||||
foreach (var type in requiredGameDependencies)
|
||||
{
|
||||
if (game.Dependencies.Get(type) == null)
|
||||
throw new Exception($"{type} has not been cached");
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
AddAssert("check OsuGameBase DI members", () =>
|
||||
{
|
||||
foreach (var type in requiredGameBaseDependencies)
|
||||
{
|
||||
if (gameBase.Dependencies.Get(type) == null)
|
||||
throw new Exception($"{type} has not been cached");
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
145
osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs
Normal file
145
osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs
Normal file
@ -0,0 +1,145 @@
|
||||
// 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.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Tests.Visual.UserInterface
|
||||
{
|
||||
public class TestSceneStatefulMenuItem : ManualInputManagerTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(OsuMenu),
|
||||
typeof(StatefulMenuItem),
|
||||
typeof(TernaryStateMenuItem),
|
||||
typeof(DrawableStatefulMenuItem),
|
||||
};
|
||||
|
||||
[Test]
|
||||
public void TestTernaryMenuItem()
|
||||
{
|
||||
OsuMenu menu = null;
|
||||
|
||||
Bindable<TernaryState> state = new Bindable<TernaryState>(TernaryState.Indeterminate);
|
||||
|
||||
AddStep("create menu", () =>
|
||||
{
|
||||
state.Value = TernaryState.Indeterminate;
|
||||
|
||||
Child = menu = new OsuMenu(Direction.Vertical, true)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Items = new[]
|
||||
{
|
||||
new TernaryStateMenuItem("First"),
|
||||
new TernaryStateMenuItem("Second") { State = { BindTarget = state } },
|
||||
new TernaryStateMenuItem("Third") { State = { Value = TernaryState.True } },
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
checkState(TernaryState.Indeterminate);
|
||||
|
||||
click();
|
||||
checkState(TernaryState.True);
|
||||
|
||||
click();
|
||||
checkState(TernaryState.False);
|
||||
|
||||
click();
|
||||
checkState(TernaryState.True);
|
||||
|
||||
click();
|
||||
checkState(TernaryState.False);
|
||||
|
||||
AddStep("change state via bindable", () => state.Value = TernaryState.True);
|
||||
|
||||
void click() =>
|
||||
AddStep("click", () =>
|
||||
{
|
||||
InputManager.MoveMouseTo(menu.ScreenSpaceDrawQuad.Centre);
|
||||
InputManager.Click(MouseButton.Left);
|
||||
});
|
||||
|
||||
void checkState(TernaryState expected)
|
||||
=> AddAssert($"state is {expected}", () => state.Value == expected);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestCustomState()
|
||||
{
|
||||
AddStep("create menu", () =>
|
||||
{
|
||||
Child = new OsuMenu(Direction.Vertical, true)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Items = new[]
|
||||
{
|
||||
new TestMenuItem("First", MenuItemType.Standard, getNextState),
|
||||
new TestMenuItem("Second", MenuItemType.Standard, getNextState) { State = { Value = TestStates.State2 } },
|
||||
new TestMenuItem("Third", MenuItemType.Standard, getNextState) { State = { Value = TestStates.State3 } },
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
private TestStates getNextState(TestStates state)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case TestStates.State1:
|
||||
return TestStates.State2;
|
||||
|
||||
case TestStates.State2:
|
||||
return TestStates.State3;
|
||||
|
||||
case TestStates.State3:
|
||||
return TestStates.State1;
|
||||
}
|
||||
|
||||
return TestStates.State1;
|
||||
}
|
||||
|
||||
private class TestMenuItem : StatefulMenuItem<TestStates>
|
||||
{
|
||||
public TestMenuItem(string text, MenuItemType type, Func<TestStates, TestStates> changeStateFunc)
|
||||
: base(text, changeStateFunc, type)
|
||||
{
|
||||
}
|
||||
|
||||
public override IconUsage? GetIconForState(TestStates state)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case TestStates.State1:
|
||||
return FontAwesome.Solid.DiceOne;
|
||||
|
||||
case TestStates.State2:
|
||||
return FontAwesome.Solid.DiceTwo;
|
||||
|
||||
case TestStates.State3:
|
||||
return FontAwesome.Solid.DiceThree;
|
||||
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(state), state, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private enum TestStates
|
||||
{
|
||||
State1,
|
||||
State2,
|
||||
State3
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
|
||||
namespace osu.Game.Tests.Visual.UserInterface
|
||||
{
|
||||
public class TestSceneToggleMenuItem : OsuTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(OsuMenu),
|
||||
typeof(ToggleMenuItem),
|
||||
typeof(DrawableStatefulMenuItem)
|
||||
};
|
||||
|
||||
public TestSceneToggleMenuItem()
|
||||
{
|
||||
Add(new OsuMenu(Direction.Vertical, true)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Items = new[]
|
||||
{
|
||||
new ToggleMenuItem("First"),
|
||||
new ToggleMenuItem("Second") { State = { Value = true } }
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -102,7 +102,8 @@ namespace osu.Game.Tournament.Tests.Components
|
||||
Content = "Okay okay, calm down guys. Let's do this!"
|
||||
}));
|
||||
|
||||
AddStep("multiple messages", () => testChannel.AddNewMessages(new Message(nextMessageId())
|
||||
AddStep("multiple messages", () => testChannel.AddNewMessages(
|
||||
new Message(nextMessageId())
|
||||
{
|
||||
Sender = admin,
|
||||
Content = "I spam you!"
|
||||
|
@ -131,6 +131,7 @@ namespace osu.Game.Tournament.Components
|
||||
});
|
||||
|
||||
if (!string.IsNullOrEmpty(mods))
|
||||
{
|
||||
AddInternal(new Sprite
|
||||
{
|
||||
Texture = textures.Get($"mods/{mods}"),
|
||||
@ -140,6 +141,7 @@ namespace osu.Game.Tournament.Components
|
||||
Scale = new Vector2(0.5f)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void matchChanged(ValueChangedEvent<TournamentMatch> match)
|
||||
{
|
||||
|
@ -29,6 +29,7 @@ namespace osu.Game.Tournament.Components
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
InternalChild = video = new VideoSprite(stream)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
@ -36,6 +37,7 @@ namespace osu.Game.Tournament.Components
|
||||
Clock = new FramedClock(manualClock = new ManualClock())
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public bool Loop
|
||||
{
|
||||
|
@ -60,6 +60,7 @@ namespace osu.Game.Tournament.IPC
|
||||
const string file_ipc_channel_filename = "ipc-channel.txt";
|
||||
|
||||
if (Storage.Exists(file_ipc_filename))
|
||||
{
|
||||
scheduled = Scheduler.AddDelayed(delegate
|
||||
{
|
||||
try
|
||||
@ -135,6 +136,7 @@ namespace osu.Game.Tournament.IPC
|
||||
}
|
||||
}, 250, true);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Error(e, "Stable installation could not be found; disabling file based IPC");
|
||||
|
@ -266,6 +266,7 @@ namespace osu.Game.Tournament.Screens.Editors
|
||||
drawableContainer.Clear();
|
||||
|
||||
if (Model.BeatmapInfo != null)
|
||||
{
|
||||
drawableContainer.Child = new TournamentBeatmapPanel(Model.BeatmapInfo, Model.Mods)
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
@ -276,6 +277,7 @@ namespace osu.Game.Tournament.Screens.Editors
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override RoundRow CreateDrawable(TournamentRound model) => new RoundRow(model);
|
||||
}
|
||||
|
@ -81,8 +81,10 @@ namespace osu.Game.Tournament.Screens.Ladder
|
||||
LadderInfo.Matches.ItemsRemoved += matches =>
|
||||
{
|
||||
foreach (var p in matches)
|
||||
{
|
||||
foreach (var d in MatchesContainer.Where(d => d.Match == p))
|
||||
d.Expire();
|
||||
}
|
||||
|
||||
layout.Invalidate();
|
||||
};
|
||||
|
@ -164,6 +164,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro
|
||||
if (team != null)
|
||||
{
|
||||
foreach (var p in team.Players)
|
||||
{
|
||||
players.Add(new OsuSpriteText
|
||||
{
|
||||
Text = p.Username,
|
||||
@ -174,6 +175,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class TeamDisplay : DrawableTournamentTeam
|
||||
{
|
||||
|
@ -169,6 +169,7 @@ namespace osu.Game.Tournament
|
||||
|
||||
// link matches to rounds
|
||||
foreach (var round in ladder.Rounds)
|
||||
{
|
||||
foreach (var id in round.Matches)
|
||||
{
|
||||
var found = ladder.Matches.FirstOrDefault(p => p.ID == id);
|
||||
@ -180,6 +181,7 @@ namespace osu.Game.Tournament
|
||||
found.Date.Value = round.StartDate.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addedInfo |= addPlayers();
|
||||
addedInfo |= addBeatmaps();
|
||||
@ -197,12 +199,13 @@ namespace osu.Game.Tournament
|
||||
bool addedInfo = false;
|
||||
|
||||
foreach (var t in ladder.Teams)
|
||||
{
|
||||
foreach (var p in t.Players)
|
||||
if (string.IsNullOrEmpty(p.Username))
|
||||
{
|
||||
PopulateUser(p);
|
||||
addedInfo = true;
|
||||
}
|
||||
}
|
||||
|
||||
return addedInfo;
|
||||
}
|
||||
@ -215,7 +218,9 @@ namespace osu.Game.Tournament
|
||||
bool addedInfo = false;
|
||||
|
||||
foreach (var r in ladder.Rounds)
|
||||
{
|
||||
foreach (var b in r.Beatmaps)
|
||||
{
|
||||
if (b.BeatmapInfo == null && b.ID > 0)
|
||||
{
|
||||
var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = b.ID });
|
||||
@ -224,6 +229,8 @@ namespace osu.Game.Tournament
|
||||
|
||||
addedInfo = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return addedInfo;
|
||||
}
|
||||
|
@ -144,16 +144,16 @@ namespace osu.Game.Beatmaps.Formats
|
||||
var endTime = split.Length > 3 ? double.Parse(split[3], CultureInfo.InvariantCulture) : double.MaxValue;
|
||||
var groupNumber = split.Length > 4 ? int.Parse(split[4]) : 0;
|
||||
timelineGroup = storyboardSprite?.AddTrigger(triggerName, startTime, endTime, groupNumber);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case "L":
|
||||
{
|
||||
var startTime = double.Parse(split[1], CultureInfo.InvariantCulture);
|
||||
var loopCount = int.Parse(split[2]);
|
||||
timelineGroup = storyboardSprite?.AddLoop(startTime, loopCount);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
@ -171,16 +171,16 @@ namespace osu.Game.Beatmaps.Formats
|
||||
var startValue = float.Parse(split[4], CultureInfo.InvariantCulture);
|
||||
var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue;
|
||||
timelineGroup?.Alpha.Add(easing, startTime, endTime, startValue, endValue);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case "S":
|
||||
{
|
||||
var startValue = float.Parse(split[4], CultureInfo.InvariantCulture);
|
||||
var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue;
|
||||
timelineGroup?.Scale.Add(easing, startTime, endTime, new Vector2(startValue), new Vector2(endValue));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case "V":
|
||||
{
|
||||
@ -189,16 +189,16 @@ namespace osu.Game.Beatmaps.Formats
|
||||
var endX = split.Length > 6 ? float.Parse(split[6], CultureInfo.InvariantCulture) : startX;
|
||||
var endY = split.Length > 7 ? float.Parse(split[7], CultureInfo.InvariantCulture) : startY;
|
||||
timelineGroup?.Scale.Add(easing, startTime, endTime, new Vector2(startX, startY), new Vector2(endX, endY));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case "R":
|
||||
{
|
||||
var startValue = float.Parse(split[4], CultureInfo.InvariantCulture);
|
||||
var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue;
|
||||
timelineGroup?.Rotation.Add(easing, startTime, endTime, MathHelper.RadiansToDegrees(startValue), MathHelper.RadiansToDegrees(endValue));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case "M":
|
||||
{
|
||||
@ -208,24 +208,24 @@ namespace osu.Game.Beatmaps.Formats
|
||||
var endY = split.Length > 7 ? float.Parse(split[7], CultureInfo.InvariantCulture) : startY;
|
||||
timelineGroup?.X.Add(easing, startTime, endTime, startX, endX);
|
||||
timelineGroup?.Y.Add(easing, startTime, endTime, startY, endY);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case "MX":
|
||||
{
|
||||
var startValue = float.Parse(split[4], CultureInfo.InvariantCulture);
|
||||
var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue;
|
||||
timelineGroup?.X.Add(easing, startTime, endTime, startValue, endValue);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case "MY":
|
||||
{
|
||||
var startValue = float.Parse(split[4], CultureInfo.InvariantCulture);
|
||||
var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue;
|
||||
timelineGroup?.Y.Add(easing, startTime, endTime, startValue, endValue);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case "C":
|
||||
{
|
||||
@ -238,8 +238,8 @@ namespace osu.Game.Beatmaps.Formats
|
||||
timelineGroup?.Colour.Add(easing, startTime, endTime,
|
||||
new Color4(startRed / 255f, startGreen / 255f, startBlue / 255f, 1),
|
||||
new Color4(endRed / 255f, endGreen / 255f, endBlue / 255f, 1));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case "P":
|
||||
{
|
||||
@ -259,17 +259,19 @@ namespace osu.Game.Beatmaps.Formats
|
||||
timelineGroup?.FlipV.Add(easing, startTime, endTime, true, startTime == endTime);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
throw new InvalidDataException($@"Unknown command type: {commandType}");
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string parseLayer(string value) => Enum.Parse(typeof(StoryLayer), value).ToString();
|
||||
|
||||
|
@ -133,8 +133,10 @@ namespace osu.Game.Beatmaps
|
||||
obj.ApplyDefaults(converted.ControlPointInfo, converted.BeatmapInfo.BaseDifficulty);
|
||||
|
||||
foreach (var mod in mods.OfType<IApplicableToHitObject>())
|
||||
{
|
||||
foreach (var obj in converted.HitObjects)
|
||||
mod.ApplyToHitObject(obj);
|
||||
}
|
||||
|
||||
processor?.PostProcess();
|
||||
|
||||
|
@ -264,9 +264,12 @@ namespace osu.Game.Database
|
||||
{
|
||||
// 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)))
|
||||
{
|
||||
using (Stream s = reader.GetStream(file))
|
||||
s.CopyTo(hashable);
|
||||
}
|
||||
|
||||
return hashable.Length > 0 ? hashable.ComputeSHA2Hash() : null;
|
||||
}
|
||||
@ -485,12 +488,16 @@ namespace osu.Game.Database
|
||||
|
||||
// import files to manager
|
||||
foreach (string file in reader.Filenames)
|
||||
{
|
||||
using (Stream s = reader.GetStream(file))
|
||||
{
|
||||
fileInfos.Add(new TFileModel
|
||||
{
|
||||
Filename = FileSafety.PathStandardise(file.Substring(prefix.Length)),
|
||||
FileInfo = files.Add(s)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return fileInfos;
|
||||
}
|
||||
@ -651,8 +658,10 @@ namespace osu.Game.Database
|
||||
private void handleEvent(Action a)
|
||||
{
|
||||
if (delayingEvents)
|
||||
{
|
||||
lock (queuedEvents)
|
||||
queuedEvents.Add(a);
|
||||
}
|
||||
else
|
||||
a.Invoke();
|
||||
}
|
||||
|
@ -43,9 +43,11 @@ namespace osu.Game.Graphics.Containers
|
||||
|
||||
// if we don't have enough time for the second shake, skip it.
|
||||
if (!maximumLength.HasValue || maximumLength >= ShakeDuration * 4)
|
||||
{
|
||||
sequence = sequence
|
||||
.MoveToX(shake_amount, ShakeDuration, Easing.InOutSine).Then()
|
||||
.MoveToX(-shake_amount, ShakeDuration, Easing.InOutSine).Then();
|
||||
}
|
||||
|
||||
sequence.MoveToX(0, ShakeDuration / 2, Easing.InSine);
|
||||
}
|
||||
|
133
osu.Game/Graphics/UserInterface/DrawableOsuMenuItem.cs
Normal file
133
osu.Game/Graphics/UserInterface/DrawableOsuMenuItem.cs
Normal file
@ -0,0 +1,133 @@
|
||||
// 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.Audio;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Graphics.UserInterface
|
||||
{
|
||||
public class DrawableOsuMenuItem : Menu.DrawableMenuItem
|
||||
{
|
||||
public const int MARGIN_HORIZONTAL = 17;
|
||||
public const int MARGIN_VERTICAL = 4;
|
||||
private const int text_size = 17;
|
||||
private const int transition_length = 80;
|
||||
|
||||
private SampleChannel sampleClick;
|
||||
private SampleChannel sampleHover;
|
||||
|
||||
private TextContainer text;
|
||||
|
||||
public DrawableOsuMenuItem(MenuItem item)
|
||||
: base(item)
|
||||
{
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(AudioManager audio)
|
||||
{
|
||||
sampleHover = audio.Samples.Get(@"UI/generic-hover");
|
||||
sampleClick = audio.Samples.Get(@"UI/generic-select");
|
||||
|
||||
BackgroundColour = Color4.Transparent;
|
||||
BackgroundColourHover = OsuColour.FromHex(@"172023");
|
||||
|
||||
updateTextColour();
|
||||
}
|
||||
|
||||
private void updateTextColour()
|
||||
{
|
||||
switch ((Item as OsuMenuItem)?.Type)
|
||||
{
|
||||
default:
|
||||
case MenuItemType.Standard:
|
||||
text.Colour = Color4.White;
|
||||
break;
|
||||
|
||||
case MenuItemType.Destructive:
|
||||
text.Colour = Color4.Red;
|
||||
break;
|
||||
|
||||
case MenuItemType.Highlighted:
|
||||
text.Colour = OsuColour.FromHex(@"ffcc22");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool OnHover(HoverEvent e)
|
||||
{
|
||||
sampleHover.Play();
|
||||
text.BoldText.FadeIn(transition_length, Easing.OutQuint);
|
||||
text.NormalText.FadeOut(transition_length, Easing.OutQuint);
|
||||
return base.OnHover(e);
|
||||
}
|
||||
|
||||
protected override void OnHoverLost(HoverLostEvent e)
|
||||
{
|
||||
text.BoldText.FadeOut(transition_length, Easing.OutQuint);
|
||||
text.NormalText.FadeIn(transition_length, Easing.OutQuint);
|
||||
base.OnHoverLost(e);
|
||||
}
|
||||
|
||||
protected override bool OnClick(ClickEvent e)
|
||||
{
|
||||
sampleClick.Play();
|
||||
return base.OnClick(e);
|
||||
}
|
||||
|
||||
protected sealed override Drawable CreateContent() => text = CreateTextContainer();
|
||||
protected virtual TextContainer CreateTextContainer() => new TextContainer();
|
||||
|
||||
protected class TextContainer : Container, IHasText
|
||||
{
|
||||
public string Text
|
||||
{
|
||||
get => NormalText.Text;
|
||||
set
|
||||
{
|
||||
NormalText.Text = value;
|
||||
BoldText.Text = value;
|
||||
}
|
||||
}
|
||||
|
||||
public readonly SpriteText NormalText;
|
||||
public readonly SpriteText BoldText;
|
||||
|
||||
public TextContainer()
|
||||
{
|
||||
Anchor = Anchor.CentreLeft;
|
||||
Origin = Anchor.CentreLeft;
|
||||
|
||||
AutoSizeAxes = Axes.Both;
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
NormalText = new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
Font = OsuFont.GetFont(size: text_size),
|
||||
Margin = new MarginPadding { Horizontal = MARGIN_HORIZONTAL, Vertical = MARGIN_VERTICAL },
|
||||
},
|
||||
BoldText = new OsuSpriteText
|
||||
{
|
||||
AlwaysPresent = true,
|
||||
Alpha = 0,
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold),
|
||||
Margin = new MarginPadding { Horizontal = MARGIN_HORIZONTAL, Vertical = MARGIN_VERTICAL },
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
72
osu.Game/Graphics/UserInterface/DrawableStatefulMenuItem.cs
Normal file
72
osu.Game/Graphics/UserInterface/DrawableStatefulMenuItem.cs
Normal file
@ -0,0 +1,72 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Graphics.UserInterface
|
||||
{
|
||||
public class DrawableStatefulMenuItem : DrawableOsuMenuItem
|
||||
{
|
||||
protected new StatefulMenuItem Item => (StatefulMenuItem)base.Item;
|
||||
|
||||
public DrawableStatefulMenuItem(StatefulMenuItem item)
|
||||
: base(item)
|
||||
{
|
||||
}
|
||||
|
||||
protected override TextContainer CreateTextContainer() => new ToggleTextContainer(Item);
|
||||
|
||||
private class ToggleTextContainer : TextContainer
|
||||
{
|
||||
private readonly StatefulMenuItem menuItem;
|
||||
private readonly Bindable<object> state;
|
||||
private readonly SpriteIcon stateIcon;
|
||||
|
||||
public ToggleTextContainer(StatefulMenuItem menuItem)
|
||||
{
|
||||
this.menuItem = menuItem;
|
||||
|
||||
state = menuItem.State.GetBoundCopy();
|
||||
|
||||
Add(stateIcon = new SpriteIcon
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
Size = new Vector2(10),
|
||||
Margin = new MarginPadding { Horizontal = MARGIN_HORIZONTAL },
|
||||
AlwaysPresent = true,
|
||||
});
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
state.BindValueChanged(updateState, true);
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
// Todo: This is bad. This can maybe be done better with a refactor of DrawableOsuMenuItem.
|
||||
stateIcon.X = BoldText.DrawWidth + 10;
|
||||
}
|
||||
|
||||
private void updateState(ValueChangedEvent<object> state)
|
||||
{
|
||||
var icon = menuItem.GetIconForState(state.NewValue);
|
||||
|
||||
if (icon == null)
|
||||
stateIcon.Alpha = 0;
|
||||
else
|
||||
{
|
||||
stateIcon.Alpha = 1;
|
||||
stateIcon.Icon = icon.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -6,6 +6,7 @@ using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Effects;
|
||||
using osu.Framework.Graphics.UserInterface;
|
||||
|
||||
namespace osu.Game.Graphics.UserInterface
|
||||
{
|
||||
@ -35,5 +36,7 @@ namespace osu.Game.Graphics.UserInterface
|
||||
|
||||
protected override void AnimateOpen() => this.FadeIn(fade_duration, Easing.OutQuint);
|
||||
protected override void AnimateClose() => this.FadeOut(fade_duration, Easing.OutQuint);
|
||||
|
||||
protected override Menu CreateSubMenu() => new OsuContextMenu();
|
||||
}
|
||||
}
|
||||
|
@ -1,18 +1,12 @@
|
||||
// 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.Audio;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osuTK.Graphics;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Graphics.UserInterface
|
||||
@ -45,7 +39,16 @@ namespace osu.Game.Graphics.UserInterface
|
||||
}
|
||||
}
|
||||
|
||||
protected override DrawableMenuItem CreateDrawableMenuItem(MenuItem item) => new DrawableOsuMenuItem(item);
|
||||
protected override DrawableMenuItem CreateDrawableMenuItem(MenuItem item)
|
||||
{
|
||||
switch (item)
|
||||
{
|
||||
case StatefulMenuItem stateful:
|
||||
return new DrawableStatefulMenuItem(stateful);
|
||||
}
|
||||
|
||||
return new DrawableOsuMenuItem(item);
|
||||
}
|
||||
|
||||
protected override ScrollContainer<Drawable> CreateScrollContainer(Direction direction) => new OsuScrollContainer(direction);
|
||||
|
||||
@ -53,122 +56,5 @@ namespace osu.Game.Graphics.UserInterface
|
||||
{
|
||||
Anchor = Direction == Direction.Horizontal ? Anchor.BottomLeft : Anchor.TopRight
|
||||
};
|
||||
|
||||
protected class DrawableOsuMenuItem : DrawableMenuItem
|
||||
{
|
||||
private const int margin_horizontal = 17;
|
||||
private const int text_size = 17;
|
||||
private const int transition_length = 80;
|
||||
public const int MARGIN_VERTICAL = 4;
|
||||
|
||||
private SampleChannel sampleClick;
|
||||
private SampleChannel sampleHover;
|
||||
|
||||
private TextContainer text;
|
||||
|
||||
public DrawableOsuMenuItem(MenuItem item)
|
||||
: base(item)
|
||||
{
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(AudioManager audio)
|
||||
{
|
||||
sampleHover = audio.Samples.Get(@"UI/generic-hover");
|
||||
sampleClick = audio.Samples.Get(@"UI/generic-select");
|
||||
|
||||
BackgroundColour = Color4.Transparent;
|
||||
BackgroundColourHover = OsuColour.FromHex(@"172023");
|
||||
|
||||
updateTextColour();
|
||||
}
|
||||
|
||||
private void updateTextColour()
|
||||
{
|
||||
switch ((Item as OsuMenuItem)?.Type)
|
||||
{
|
||||
default:
|
||||
case MenuItemType.Standard:
|
||||
text.Colour = Color4.White;
|
||||
break;
|
||||
|
||||
case MenuItemType.Destructive:
|
||||
text.Colour = Color4.Red;
|
||||
break;
|
||||
|
||||
case MenuItemType.Highlighted:
|
||||
text.Colour = OsuColour.FromHex(@"ffcc22");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool OnHover(HoverEvent e)
|
||||
{
|
||||
sampleHover.Play();
|
||||
text.BoldText.FadeIn(transition_length, Easing.OutQuint);
|
||||
text.NormalText.FadeOut(transition_length, Easing.OutQuint);
|
||||
return base.OnHover(e);
|
||||
}
|
||||
|
||||
protected override void OnHoverLost(HoverLostEvent e)
|
||||
{
|
||||
text.BoldText.FadeOut(transition_length, Easing.OutQuint);
|
||||
text.NormalText.FadeIn(transition_length, Easing.OutQuint);
|
||||
base.OnHoverLost(e);
|
||||
}
|
||||
|
||||
protected override bool OnClick(ClickEvent e)
|
||||
{
|
||||
sampleClick.Play();
|
||||
return base.OnClick(e);
|
||||
}
|
||||
|
||||
protected sealed override Drawable CreateContent() => text = CreateTextContainer();
|
||||
protected virtual TextContainer CreateTextContainer() => new TextContainer();
|
||||
|
||||
protected class TextContainer : Container, IHasText
|
||||
{
|
||||
public string Text
|
||||
{
|
||||
get => NormalText.Text;
|
||||
set
|
||||
{
|
||||
NormalText.Text = value;
|
||||
BoldText.Text = value;
|
||||
}
|
||||
}
|
||||
|
||||
public readonly SpriteText NormalText;
|
||||
public readonly SpriteText BoldText;
|
||||
|
||||
public TextContainer()
|
||||
{
|
||||
Anchor = Anchor.CentreLeft;
|
||||
Origin = Anchor.CentreLeft;
|
||||
|
||||
AutoSizeAxes = Axes.Both;
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
NormalText = new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
Font = OsuFont.GetFont(size: text_size),
|
||||
Margin = new MarginPadding { Horizontal = margin_horizontal, Vertical = MARGIN_VERTICAL },
|
||||
},
|
||||
BoldText = new OsuSpriteText
|
||||
{
|
||||
AlwaysPresent = true,
|
||||
Alpha = 0,
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold),
|
||||
Margin = new MarginPadding { Horizontal = margin_horizontal, Vertical = MARGIN_VERTICAL },
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,9 +11,8 @@ namespace osu.Game.Graphics.UserInterface
|
||||
public readonly MenuItemType Type;
|
||||
|
||||
public OsuMenuItem(string text, MenuItemType type = MenuItemType.Standard)
|
||||
: base(text)
|
||||
: this(text, type, null)
|
||||
{
|
||||
Type = type;
|
||||
}
|
||||
|
||||
public OsuMenuItem(string text, MenuItemType type, Action action)
|
||||
|
@ -51,9 +51,11 @@ namespace osu.Game.Graphics.UserInterface
|
||||
});
|
||||
|
||||
if (isEnumType && AddEnumEntriesAutomatically)
|
||||
{
|
||||
foreach (var val in (T[])Enum.GetValues(typeof(T)))
|
||||
AddItem(val);
|
||||
}
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
|
@ -43,9 +43,12 @@ namespace osu.Game.Graphics.UserInterface
|
||||
protected override string FormatCount(double count)
|
||||
{
|
||||
string format = new string('0', (int)LeadingZeroes);
|
||||
|
||||
if (UseCommaSeparator)
|
||||
{
|
||||
for (int i = format.Length - 3; i > 0; i -= 3)
|
||||
format = format.Insert(i, @",");
|
||||
}
|
||||
|
||||
return ((long)count).ToString(format);
|
||||
}
|
||||
|
105
osu.Game/Graphics/UserInterface/StatefulMenuItem.cs
Normal file
105
osu.Game/Graphics/UserInterface/StatefulMenuItem.cs
Normal file
@ -0,0 +1,105 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
|
||||
namespace osu.Game.Graphics.UserInterface
|
||||
{
|
||||
/// <summary>
|
||||
/// An <see cref="OsuMenuItem"/> which contains and displays a state.
|
||||
/// </summary>
|
||||
public abstract class StatefulMenuItem : OsuMenuItem
|
||||
{
|
||||
/// <summary>
|
||||
/// The current state that should be displayed.
|
||||
/// </summary>
|
||||
public readonly Bindable<object> State = new Bindable<object>();
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="StatefulMenuItem"/>.
|
||||
/// </summary>
|
||||
/// <param name="text">The text to display.</param>
|
||||
/// <param name="changeStateFunc">A function that mutates a state to another state after this <see cref="StatefulMenuItem"/> is pressed.</param>
|
||||
/// <param name="type">The type of action which this <see cref="StatefulMenuItem"/> performs.</param>
|
||||
protected StatefulMenuItem(string text, Func<object, object> changeStateFunc, MenuItemType type = MenuItemType.Standard)
|
||||
: this(text, changeStateFunc, type, null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="StatefulMenuItem"/>.
|
||||
/// </summary>
|
||||
/// <param name="text">The text to display.</param>
|
||||
/// <param name="changeStateFunc">A function that mutates a state to another state after this <see cref="StatefulMenuItem"/> is pressed.</param>
|
||||
/// <param name="type">The type of action which this <see cref="StatefulMenuItem"/> performs.</param>
|
||||
/// <param name="action">A delegate to be invoked when this <see cref="StatefulMenuItem"/> is pressed.</param>
|
||||
protected StatefulMenuItem(string text, Func<object, object> changeStateFunc, MenuItemType type, Action<object> action)
|
||||
: base(text, type)
|
||||
{
|
||||
Action.Value = () =>
|
||||
{
|
||||
State.Value = changeStateFunc?.Invoke(State.Value) ?? State.Value;
|
||||
action?.Invoke(State.Value);
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the icon to be displayed for a state.
|
||||
/// </summary>
|
||||
/// <param name="state">The state to retrieve the relevant icon for.</param>
|
||||
/// <returns>The icon to be displayed for <paramref name="state"/>.</returns>
|
||||
public abstract IconUsage? GetIconForState(object state);
|
||||
}
|
||||
|
||||
public abstract class StatefulMenuItem<T> : StatefulMenuItem
|
||||
where T : struct
|
||||
{
|
||||
/// <summary>
|
||||
/// The current state that should be displayed.
|
||||
/// </summary>
|
||||
public new readonly Bindable<T> State = new Bindable<T>();
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="StatefulMenuItem"/>.
|
||||
/// </summary>
|
||||
/// <param name="text">The text to display.</param>
|
||||
/// <param name="changeStateFunc">A function that mutates a state to another state after this <see cref="StatefulMenuItem"/> is pressed.</param>
|
||||
/// <param name="type">The type of action which this <see cref="StatefulMenuItem"/> performs.</param>
|
||||
protected StatefulMenuItem(string text, Func<T, T> changeStateFunc, MenuItemType type = MenuItemType.Standard)
|
||||
: this(text, changeStateFunc, type, null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="StatefulMenuItem"/>.
|
||||
/// </summary>
|
||||
/// <param name="text">The text to display.</param>
|
||||
/// <param name="changeStateFunc">A function that mutates a state to another state after this <see cref="StatefulMenuItem"/> is pressed.</param>
|
||||
/// <param name="type">The type of action which this <see cref="StatefulMenuItem"/> performs.</param>
|
||||
/// <param name="action">A delegate to be invoked when this <see cref="StatefulMenuItem"/> is pressed.</param>
|
||||
protected StatefulMenuItem(string text, Func<T, T> changeStateFunc, MenuItemType type, Action<T> action)
|
||||
: base(text, o => changeStateFunc?.Invoke((T)o) ?? o, type, o => action?.Invoke((T)o))
|
||||
{
|
||||
base.State.BindValueChanged(state =>
|
||||
{
|
||||
if (state.NewValue == null)
|
||||
base.State.Value = default(T);
|
||||
|
||||
State.Value = (T)base.State.Value;
|
||||
}, true);
|
||||
|
||||
State.BindValueChanged(state => base.State.Value = state.NewValue);
|
||||
}
|
||||
|
||||
public sealed override IconUsage? GetIconForState(object state) => GetIconForState((T)state);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the icon to be displayed for a state.
|
||||
/// </summary>
|
||||
/// <param name="state">The state to retrieve the relevant icon for.</param>
|
||||
/// <returns>The icon to be displayed for <paramref name="state"/>.</returns>
|
||||
public abstract IconUsage? GetIconForState(T state);
|
||||
}
|
||||
}
|
27
osu.Game/Graphics/UserInterface/TernaryState.cs
Normal file
27
osu.Game/Graphics/UserInterface/TernaryState.cs
Normal file
@ -0,0 +1,27 @@
|
||||
// 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.
|
||||
|
||||
namespace osu.Game.Graphics.UserInterface
|
||||
{
|
||||
/// <summary>
|
||||
/// An on/off state with an extra indeterminate state.
|
||||
/// </summary>
|
||||
public enum TernaryState
|
||||
{
|
||||
/// <summary>
|
||||
/// The current state is false.
|
||||
/// </summary>
|
||||
False,
|
||||
|
||||
/// <summary>
|
||||
/// The current state is a combination of <see cref="False"/> and <see cref="True"/>.
|
||||
/// The state becomes <see cref="True"/> if the <see cref="TernaryStateMenuItem"/> is pressed.
|
||||
/// </summary>
|
||||
Indeterminate,
|
||||
|
||||
/// <summary>
|
||||
/// The current state is true.
|
||||
/// </summary>
|
||||
True
|
||||
}
|
||||
}
|
79
osu.Game/Graphics/UserInterface/TernaryStateMenuItem.cs
Normal file
79
osu.Game/Graphics/UserInterface/TernaryStateMenuItem.cs
Normal file
@ -0,0 +1,79 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
|
||||
namespace osu.Game.Graphics.UserInterface
|
||||
{
|
||||
/// <summary>
|
||||
/// An <see cref="OsuMenuItem"/> with three possible states.
|
||||
/// </summary>
|
||||
public class TernaryStateMenuItem : StatefulMenuItem<TernaryState>
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="TernaryStateMenuItem"/>.
|
||||
/// </summary>
|
||||
/// <param name="text">The text to display.</param>
|
||||
/// <param name="type">The type of action which this <see cref="TernaryStateMenuItem"/> performs.</param>
|
||||
public TernaryStateMenuItem(string text, MenuItemType type = MenuItemType.Standard)
|
||||
: this(text, type, null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="TernaryStateMenuItem"/>.
|
||||
/// </summary>
|
||||
/// <param name="text">The text to display.</param>
|
||||
/// <param name="type">The type of action which this <see cref="TernaryStateMenuItem"/> performs.</param>
|
||||
/// <param name="action">A delegate to be invoked when this <see cref="TernaryStateMenuItem"/> is pressed.</param>
|
||||
public TernaryStateMenuItem(string text, MenuItemType type, Action<TernaryState> action)
|
||||
: this(text, getNextState, type, action)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="TernaryStateMenuItem"/>.
|
||||
/// </summary>
|
||||
/// <param name="text">The text to display.</param>
|
||||
/// <param name="changeStateFunc">A function that mutates a state to another state after this <see cref="TernaryStateMenuItem"/> is pressed.</param>
|
||||
/// <param name="type">The type of action which this <see cref="TernaryStateMenuItem"/> performs.</param>
|
||||
/// <param name="action">A delegate to be invoked when this <see cref="TernaryStateMenuItem"/> is pressed.</param>
|
||||
protected TernaryStateMenuItem(string text, Func<TernaryState, TernaryState> changeStateFunc, MenuItemType type, Action<TernaryState> action)
|
||||
: base(text, changeStateFunc, type, action)
|
||||
{
|
||||
}
|
||||
|
||||
public override IconUsage? GetIconForState(TernaryState state)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case TernaryState.Indeterminate:
|
||||
return FontAwesome.Solid.DotCircle;
|
||||
|
||||
case TernaryState.True:
|
||||
return FontAwesome.Solid.Check;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static TernaryState getNextState(TernaryState state)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case TernaryState.False:
|
||||
return TernaryState.True;
|
||||
|
||||
case TernaryState.Indeterminate:
|
||||
return TernaryState.True;
|
||||
|
||||
case TernaryState.True:
|
||||
return TernaryState.False;
|
||||
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(state), state, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
37
osu.Game/Graphics/UserInterface/ToggleMenuItem.cs
Normal file
37
osu.Game/Graphics/UserInterface/ToggleMenuItem.cs
Normal file
@ -0,0 +1,37 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
|
||||
namespace osu.Game.Graphics.UserInterface
|
||||
{
|
||||
/// <summary>
|
||||
/// An <see cref="OsuMenuItem"/> which displays an enabled or disabled state.
|
||||
/// </summary>
|
||||
public class ToggleMenuItem : StatefulMenuItem<bool>
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="ToggleMenuItem"/>.
|
||||
/// </summary>
|
||||
/// <param name="text">The text to display.</param>
|
||||
/// <param name="type">The type of action which this <see cref="ToggleMenuItem"/> performs.</param>
|
||||
public ToggleMenuItem(string text, MenuItemType type = MenuItemType.Standard)
|
||||
: this(text, type, null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="ToggleMenuItem"/>.
|
||||
/// </summary>
|
||||
/// <param name="text">The text to display.</param>
|
||||
/// <param name="type">The type of action which this <see cref="ToggleMenuItem"/> performs.</param>
|
||||
/// <param name="action">A delegate to be invoked when this <see cref="ToggleMenuItem"/> is pressed.</param>
|
||||
public ToggleMenuItem(string text, MenuItemType type, Action<bool> action)
|
||||
: base(text, value => !value, type, action)
|
||||
{
|
||||
}
|
||||
|
||||
public override IconUsage? GetIconForState(bool state) => state ? (IconUsage?)FontAwesome.Solid.Check : null;
|
||||
}
|
||||
}
|
@ -46,6 +46,7 @@ namespace osu.Game.Input
|
||||
continue;
|
||||
|
||||
foreach (var insertable in group.Skip(count).Take(aimCount - count))
|
||||
{
|
||||
// insert any defaults which are missing.
|
||||
usage.Context.DatabasedKeyBinding.Add(new DatabasedKeyBinding
|
||||
{
|
||||
@ -57,6 +58,7 @@ namespace osu.Game.Input
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve <see cref="DatabasedKeyBinding"/>s for a specified ruleset/variant content.
|
||||
|
@ -220,7 +220,7 @@ namespace osu.Game.Online.Chat
|
||||
break;
|
||||
}
|
||||
|
||||
var channel = availableChannels.Where(c => c.Name == content || c.Name == $"#{content}").FirstOrDefault();
|
||||
var channel = availableChannels.FirstOrDefault(c => c.Name == content || c.Name == $"#{content}");
|
||||
|
||||
if (channel == null)
|
||||
{
|
||||
|
@ -75,8 +75,10 @@ namespace osu.Game.Online.Leaderboards
|
||||
int i = 0;
|
||||
|
||||
foreach (var s in scrollFlow.Children)
|
||||
{
|
||||
using (s.BeginDelayedSequence(i++ * 50, true))
|
||||
s.Show();
|
||||
}
|
||||
|
||||
scrollContainer.ScrollTo(0f, false);
|
||||
}, (showScoresCancellationSource = new CancellationTokenSource()).Token));
|
||||
@ -342,16 +344,20 @@ namespace osu.Game.Online.Leaderboards
|
||||
else
|
||||
{
|
||||
if (bottomY - fadeBottom > 0 && FadeBottom)
|
||||
{
|
||||
c.Colour = ColourInfo.GradientVertical(
|
||||
Color4.White.Opacity(Math.Min(1 - (topY - fadeBottom) / LeaderboardScore.HEIGHT, 1)),
|
||||
Color4.White.Opacity(Math.Min(1 - (bottomY - fadeBottom) / LeaderboardScore.HEIGHT, 1)));
|
||||
}
|
||||
else if (FadeTop)
|
||||
{
|
||||
c.Colour = ColourInfo.GradientVertical(
|
||||
Color4.White.Opacity(Math.Min(1 - (fadeTop - topY) / LeaderboardScore.HEIGHT, 1)),
|
||||
Color4.White.Opacity(Math.Min(1 - (fadeTop - bottomY) / LeaderboardScore.HEIGHT, 1)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract LeaderboardScore CreateDrawableScore(ScoreInfo model, int index);
|
||||
}
|
||||
|
@ -402,8 +402,10 @@ namespace osu.Game
|
||||
nextBeatmap.Track.Completed += currentTrackCompleted;
|
||||
|
||||
using (var oldBeatmap = beatmap.OldValue)
|
||||
{
|
||||
if (oldBeatmap?.Track != null)
|
||||
oldBeatmap.Track.Completed -= currentTrackCompleted;
|
||||
}
|
||||
|
||||
nextBeatmap?.LoadBeatmapAsync();
|
||||
}
|
||||
|
@ -292,9 +292,11 @@ namespace osu.Game
|
||||
var extension = Path.GetExtension(paths.First())?.ToLowerInvariant();
|
||||
|
||||
foreach (var importer in fileImporters)
|
||||
{
|
||||
if (importer.HandledExtensions.Contains(extension))
|
||||
await importer.Import(paths);
|
||||
}
|
||||
}
|
||||
|
||||
public string[] HandledExtensions => fileImporters.SelectMany(i => i.HandledExtensions).ToArray();
|
||||
|
||||
|
@ -130,6 +130,7 @@ namespace osu.Game.Overlays.Changelog
|
||||
});
|
||||
|
||||
if (entry.GithubUser.UserId != null)
|
||||
{
|
||||
title.AddUserLink(new User
|
||||
{
|
||||
Username = entry.GithubUser.OsuUsername,
|
||||
@ -139,18 +140,23 @@ namespace osu.Game.Overlays.Changelog
|
||||
t.Font = fontMedium;
|
||||
t.Colour = entryColour;
|
||||
});
|
||||
}
|
||||
else if (entry.GithubUser.GithubUrl != null)
|
||||
{
|
||||
title.AddLink(entry.GithubUser.DisplayName, entry.GithubUser.GithubUrl, t =>
|
||||
{
|
||||
t.Font = fontMedium;
|
||||
t.Colour = entryColour;
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
title.AddText(entry.GithubUser.DisplayName, t =>
|
||||
{
|
||||
t.Font = fontSmall;
|
||||
t.Colour = entryColour;
|
||||
});
|
||||
}
|
||||
|
||||
ChangelogEntries.Add(titleContainer);
|
||||
|
||||
|
@ -68,12 +68,14 @@ namespace osu.Game.Overlays.Changelog
|
||||
}
|
||||
|
||||
if (build != null)
|
||||
{
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new ChangelogBuildWithNavigation(build) { SelectBuild = SelectBuild },
|
||||
new Comments(build)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public class ChangelogBuildWithNavigation : ChangelogBuild
|
||||
{
|
||||
|
@ -162,11 +162,13 @@ namespace osu.Game.Overlays.Comments
|
||||
foreach (var c in response.Comments)
|
||||
{
|
||||
if (c.IsTopLevel)
|
||||
{
|
||||
page.Add(new DrawableComment(c)
|
||||
{
|
||||
ShowDeleted = { BindTarget = ShowDeleted }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
LoadComponentAsync(page, loaded =>
|
||||
{
|
||||
|
@ -149,8 +149,10 @@ namespace osu.Game.Overlays.Direct
|
||||
icons.Add(new GroupedDifficultyIcon(SetInfo.Beatmaps.FindAll(b => b.Ruleset.Equals(ruleset)), ruleset, this is DirectListPanel ? Color4.White : colours.Gray5));
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var b in SetInfo.Beatmaps.OrderBy(beatmap => beatmap.StarDifficulty))
|
||||
icons.Add(new DifficultyIcon(b));
|
||||
}
|
||||
|
||||
return icons;
|
||||
}
|
||||
|
@ -194,8 +194,10 @@ namespace osu.Game.Overlays.Mods
|
||||
start = Mods.Length - 1;
|
||||
|
||||
for (int i = start; i < Mods.Length && i >= 0; i += direction)
|
||||
{
|
||||
if (SelectAt(i))
|
||||
return;
|
||||
}
|
||||
|
||||
Deselect();
|
||||
}
|
||||
|
@ -112,6 +112,7 @@ namespace osu.Game.Overlays.Mods
|
||||
if (selected == null) continue;
|
||||
|
||||
foreach (var type in modTypes)
|
||||
{
|
||||
if (type.IsInstanceOfType(selected))
|
||||
{
|
||||
if (immediate)
|
||||
@ -121,6 +122,7 @@ namespace osu.Game.Overlays.Mods
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Select one or more mods in this section and deselects all other ones.
|
||||
|
@ -81,9 +81,11 @@ namespace osu.Game.Rulesets.Difficulty.Utils
|
||||
yield return array[i];
|
||||
|
||||
if (Count == capacity)
|
||||
{
|
||||
for (int i = 0; i < marker; ++i)
|
||||
yield return array[i];
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
}
|
||||
|
@ -113,8 +113,10 @@ namespace osu.Game.Rulesets.Objects.Drawables
|
||||
if (samples.Length > 0)
|
||||
{
|
||||
if (HitObject.SampleControlPoint == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(HitObject.SampleControlPoint), $"{nameof(HitObject)}s must always have an attached {nameof(HitObject.SampleControlPoint)}."
|
||||
+ $" This is an indication that {nameof(HitObject.ApplyDefaults)} has not been invoked on {this}.");
|
||||
}
|
||||
|
||||
samples = samples.Select(s => HitObject.SampleControlPoint.ApplyTo(s)).ToArray();
|
||||
foreach (var s in samples)
|
||||
|
@ -74,9 +74,12 @@ namespace osu.Game.Rulesets.Objects.Legacy
|
||||
string[] pointSplit = split[5].Split('|');
|
||||
|
||||
int pointCount = 1;
|
||||
|
||||
foreach (var t in pointSplit)
|
||||
{
|
||||
if (t.Length > 1)
|
||||
pointCount++;
|
||||
}
|
||||
|
||||
var points = new Vector2[pointCount];
|
||||
|
||||
|
@ -185,8 +185,10 @@ namespace osu.Game.Rulesets.Objects
|
||||
ReadOnlySpan<Vector2> cpSpan = ControlPoints.Slice(start, end - start);
|
||||
|
||||
foreach (Vector2 t in calculateSubpath(cpSpan))
|
||||
{
|
||||
if (calculatedPath.Count == 0 || calculatedPath.Last() != t)
|
||||
calculatedPath.Add(t);
|
||||
}
|
||||
|
||||
start = end;
|
||||
}
|
||||
|
@ -69,8 +69,10 @@ namespace osu.Game.Rulesets
|
||||
|
||||
//add any other modes
|
||||
foreach (var r in instances.Where(r => r.LegacyID == null))
|
||||
{
|
||||
if (context.RulesetInfo.FirstOrDefault(ri => ri.InstantiationInfo == r.RulesetInfo.InstantiationInfo) == null)
|
||||
context.RulesetInfo.Add(r.RulesetInfo);
|
||||
}
|
||||
|
||||
context.SaveChanges();
|
||||
|
||||
|
@ -436,9 +436,11 @@ namespace osu.Game.Rulesets.UI
|
||||
return h.HitWindows;
|
||||
|
||||
foreach (var n in h.NestedHitObjects)
|
||||
{
|
||||
if (h.HitWindows.WindowFor(HitResult.Miss) > 0)
|
||||
return n.HitWindows;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
@ -130,10 +130,14 @@ namespace osu.Game.Rulesets.UI
|
||||
base.Update();
|
||||
|
||||
if (beatmap != null)
|
||||
{
|
||||
foreach (var mod in mods)
|
||||
{
|
||||
if (mod is IUpdatableByPlayfield updatable)
|
||||
updatable.Update(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the container that will be used to contain the <see cref="DrawableHitObject"/>s.
|
||||
|
@ -57,11 +57,13 @@ namespace osu.Game.Screens.Multi.Components
|
||||
var beatmap = CurrentItem.Value?.Beatmap;
|
||||
|
||||
if (beatmap == null)
|
||||
{
|
||||
textFlow.AddText("No beatmap selected", s =>
|
||||
{
|
||||
s.Font = s.Font.With(size: TextSize);
|
||||
s.Colour = colours.PinkLight;
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
textFlow.AddLink(new[]
|
||||
|
@ -100,10 +100,12 @@ namespace osu.Game.Screens.Play.HUD
|
||||
if (text.Alpha > 0 || button.Progress.Value > 0 || button.IsHovered)
|
||||
Alpha = 1;
|
||||
else
|
||||
{
|
||||
Alpha = Interpolation.ValueAt(
|
||||
MathHelper.Clamp(Clock.ElapsedFrameTime, 0, 200),
|
||||
Alpha, MathHelper.Clamp(1 - positionalAdjust, 0.04f, 1), 0, 200, Easing.OutQuint);
|
||||
}
|
||||
}
|
||||
|
||||
private class Button : HoldToConfirmContainer, IKeyBindingHandler<GlobalAction>
|
||||
{
|
||||
|
@ -181,8 +181,11 @@ namespace osu.Game.Screens.Play
|
||||
this.FadeIn(500, Easing.OutExpo);
|
||||
|
||||
if (!IsHovered && !IsDragged)
|
||||
{
|
||||
using (BeginDelayedSequence(1000))
|
||||
scheduledHide = Schedule(Hide);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case Visibility.Hidden:
|
||||
|
@ -44,10 +44,14 @@ namespace osu.Game.Screens.Select.Carousel
|
||||
criteria.Artist.Matches(Beatmap.Metadata.ArtistUnicode);
|
||||
|
||||
if (match)
|
||||
{
|
||||
foreach (var criteriaTerm in criteria.SearchTerms)
|
||||
{
|
||||
match &=
|
||||
Beatmap.Metadata.SearchableTerms.Any(term => term.IndexOf(criteriaTerm, StringComparison.InvariantCultureIgnoreCase) >= 0) ||
|
||||
Beatmap.Version.IndexOf(criteriaTerm, StringComparison.InvariantCultureIgnoreCase) >= 0;
|
||||
}
|
||||
}
|
||||
|
||||
Filtered.Value = !match;
|
||||
}
|
||||
|
@ -251,11 +251,13 @@ namespace osu.Game.Screens.Select
|
||||
{
|
||||
// if we have no beatmaps but osu-stable is found, let's prompt the user to import.
|
||||
if (!beatmaps.GetAllUsableBeatmapSetsEnumerable().Any() && beatmaps.StableInstallationAvailable)
|
||||
{
|
||||
dialogOverlay.Push(new ImportFromStablePopup(() =>
|
||||
{
|
||||
Task.Run(beatmaps.ImportFromStableAsync).ContinueWith(_ => scores.ImportFromStableAsync(), TaskContinuationOptions.OnlyOnRanToCompletion);
|
||||
Task.Run(skins.ImportFromStableAsync);
|
||||
}));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -332,6 +334,7 @@ namespace osu.Game.Screens.Select
|
||||
if (e.NewValue is DummyWorkingBeatmap) return;
|
||||
|
||||
if (this.IsCurrentScreen() && !Carousel.SelectBeatmap(e.NewValue?.BeatmapInfo, false))
|
||||
{
|
||||
// If selecting new beatmap without bypassing filters failed, there's possibly a ruleset mismatch
|
||||
if (e.NewValue?.BeatmapInfo?.Ruleset != null && !e.NewValue.BeatmapInfo.Ruleset.Equals(decoupledRuleset.Value))
|
||||
{
|
||||
@ -339,6 +342,7 @@ namespace osu.Game.Screens.Select
|
||||
Carousel.SelectBeatmap(e.NewValue.BeatmapInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We need to keep track of the last selected beatmap ignoring debounce to play the correct selection sounds.
|
||||
private BeatmapInfo beatmapNoDebounce;
|
||||
|
@ -35,9 +35,12 @@ namespace osu.Game.Skinning
|
||||
: base(skin)
|
||||
{
|
||||
Stream stream = storage?.GetStream(filename);
|
||||
|
||||
if (stream != null)
|
||||
{
|
||||
using (LineBufferedReader reader = new LineBufferedReader(stream))
|
||||
Configuration = new LegacySkinDecoder().Decode(reader);
|
||||
}
|
||||
else
|
||||
Configuration = new DefaultSkinConfiguration();
|
||||
|
||||
|
@ -22,17 +22,19 @@ namespace osu.Game.Skinning
|
||||
|
||||
if (animatable)
|
||||
{
|
||||
for (int i = 0;; i++)
|
||||
for (int i = 0; true; i++)
|
||||
{
|
||||
if ((texture = getFrameTexture(i)) == null)
|
||||
break;
|
||||
|
||||
if (animation == null)
|
||||
{
|
||||
animation = new TextureAnimation
|
||||
{
|
||||
DefaultFrameLength = default_frame_time,
|
||||
Repeat = looping
|
||||
};
|
||||
}
|
||||
|
||||
animation.AddFrame(texture);
|
||||
}
|
||||
@ -42,10 +44,12 @@ namespace osu.Game.Skinning
|
||||
return animation;
|
||||
|
||||
if ((texture = source.GetTexture(componentName)) != null)
|
||||
{
|
||||
return new Sprite
|
||||
{
|
||||
Texture = texture
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
@ -81,9 +81,13 @@ namespace osu.Game.Skinning
|
||||
var ch = skin.GetSample(s);
|
||||
|
||||
if (ch == null && allowFallback)
|
||||
{
|
||||
foreach (var lookup in s.LookupNames)
|
||||
{
|
||||
if ((ch = samples.Get($"Gameplay/{lookup}")) != null)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ch != null)
|
||||
{
|
||||
@ -91,9 +95,11 @@ namespace osu.Game.Skinning
|
||||
ch.Volume.Value = s.Volume / 100.0;
|
||||
|
||||
if (adjustments != null)
|
||||
{
|
||||
foreach (var adjustment in adjustments)
|
||||
ch.AddAdjustment(adjustment.property, adjustment.bindable);
|
||||
}
|
||||
}
|
||||
|
||||
return ch;
|
||||
}).Where(c => c != null).ToArray();
|
||||
@ -104,8 +110,10 @@ namespace osu.Game.Skinning
|
||||
base.Dispose(isDisposing);
|
||||
|
||||
if (channels != null)
|
||||
{
|
||||
foreach (var c in channels)
|
||||
c.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -65,6 +65,7 @@ namespace osu.Game.Storyboards
|
||||
public virtual IEnumerable<CommandTimeline<T>.TypedCommand> GetCommands<T>(CommandTimelineSelector<T> timelineSelector, double offset = 0)
|
||||
{
|
||||
if (offset != 0)
|
||||
{
|
||||
return timelineSelector(this).Commands.Select(command =>
|
||||
new CommandTimeline<T>.TypedCommand
|
||||
{
|
||||
@ -74,6 +75,7 @@ namespace osu.Game.Storyboards
|
||||
StartValue = command.StartValue,
|
||||
EndValue = command.EndValue,
|
||||
});
|
||||
}
|
||||
|
||||
return timelineSelector(this).Commands;
|
||||
}
|
||||
|
@ -105,9 +105,13 @@ namespace osu.Game.Storyboards
|
||||
var commands = TimelineGroup.GetCommands(timelineSelector);
|
||||
foreach (var loop in loops)
|
||||
commands = commands.Concat(loop.GetCommands(timelineSelector));
|
||||
|
||||
if (triggeredGroups != null)
|
||||
{
|
||||
foreach (var pair in triggeredGroups)
|
||||
commands = commands.Concat(pair.Item1.GetCommands(timelineSelector, pair.Item2));
|
||||
}
|
||||
|
||||
return commands;
|
||||
}
|
||||
|
||||
|
@ -72,11 +72,15 @@ namespace osu.Game.Tests.Beatmaps
|
||||
break;
|
||||
|
||||
if (objectCounter >= ourMapping.Objects.Count)
|
||||
{
|
||||
Assert.Fail($"The conversion did not generate a hitobject, but should have, for hitobject at time: {expectedMapping.StartTime}:\n"
|
||||
+ $"Expected: {JsonConvert.SerializeObject(expectedMapping.Objects[objectCounter])}\n");
|
||||
}
|
||||
else if (objectCounter >= expectedMapping.Objects.Count)
|
||||
{
|
||||
Assert.Fail($"The conversion generated a hitobject, but should not have, for hitobject at time: {ourMapping.StartTime}:\n"
|
||||
+ $"Received: {JsonConvert.SerializeObject(ourMapping.Objects[objectCounter])}\n");
|
||||
}
|
||||
else if (!expectedMapping.Objects[objectCounter].Equals(ourMapping.Objects[objectCounter]))
|
||||
{
|
||||
Assert.Fail($"The conversion generated differing hitobjects for object at time: {expectedMapping.StartTime}:\n"
|
||||
|
@ -37,9 +37,12 @@ namespace osu.Game.Tests.Visual
|
||||
Add(testContainer = new GridContainer { RelativeSizeAxes = Axes.Both });
|
||||
|
||||
cells = new Drawable[rows, cols];
|
||||
|
||||
for (int r = 0; r < rows; r++)
|
||||
{
|
||||
for (int c = 0; c < cols; c++)
|
||||
cells[r, c] = new Container { RelativeSizeAxes = Axes.Both };
|
||||
}
|
||||
|
||||
testContainer.Content = cells.ToJagged();
|
||||
}
|
||||
|
@ -46,6 +46,7 @@ namespace osu.Game.Users
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
InternalChild = new Sprite
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
@ -55,6 +56,7 @@ namespace osu.Game.Users
|
||||
Origin = Anchor.Centre
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
|
@ -4,7 +4,6 @@
|
||||
using System.Threading.Tasks;
|
||||
using Foundation;
|
||||
using osu.Framework.iOS;
|
||||
using osu.Framework.Threading;
|
||||
using UIKit;
|
||||
|
||||
namespace osu.iOS
|
||||
|
@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
|
@ -12,7 +12,7 @@
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeLocalFunctionBody/@EntryIndexedValue">HINT</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeMethodOrOperatorBody/@EntryIndexedValue">HINT</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeModifiersOrder/@EntryIndexedValue">WARNING</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeRedundantParentheses/@EntryIndexedValue"></s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeRedundantParentheses/@EntryIndexedValue">WARNING</s:String>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeRedundantParentheses/@EntryIndexRemoved">True</s:Boolean>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeTypeMemberModifiers/@EntryIndexedValue">WARNING</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeTypeModifiers/@EntryIndexedValue">WARNING</s:String>
|
||||
@ -70,11 +70,20 @@
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConvertToStaticClass/@EntryIndexedValue">WARNING</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=DoubleNegationOperator/@EntryIndexedValue">WARNING</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EmptyGeneralCatchClause/@EntryIndexedValue">DO_NOT_SHOW</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EnforceDoWhileStatementBraces/@EntryIndexedValue">WARNING</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EnforceFixedStatementBraces/@EntryIndexedValue">WARNING</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EnforceForeachStatementBraces/@EntryIndexedValue">WARNING</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EnforceForStatementBraces/@EntryIndexedValue">WARNING</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EnforceIfStatementBraces/@EntryIndexedValue">WARNING</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EnforceLockStatementBraces/@EntryIndexedValue">WARNING</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EnforceUsingStatementBraces/@EntryIndexedValue">WARNING</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EnforceWhileStatementBraces/@EntryIndexedValue">WARNING</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EventNeverSubscribedTo_002EGlobal/@EntryIndexedValue">HINT</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EventNeverSubscribedTo_002ELocal/@EntryIndexedValue">WARNING</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=FieldCanBeMadeReadOnly_002EGlobal/@EntryIndexedValue">DO_NOT_SHOW</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=FieldCanBeMadeReadOnly_002ELocal/@EntryIndexedValue">WARNING</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ForCanBeConvertedToForeach/@EntryIndexedValue">HINT</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ForStatementConditionIsTrue/@EntryIndexedValue">DO_NOT_SHOW</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=IdentifierTypo/@EntryIndexedValue">HINT</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ImpureMethodCallOnReadonlyValueField/@EntryIndexedValue">HINT</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=InconsistentNaming/@EntryIndexedValue">ERROR</s:String>
|
||||
@ -125,6 +134,7 @@
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantExplicitParamsArrayCreation/@EntryIndexedValue">WARNING</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantImmediateDelegateInvocation/@EntryIndexedValue">WARNING</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantLambdaSignatureParentheses/@EntryIndexedValue">WARNING</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantTypeSpecificationInDefaultExpression/@EntryIndexedValue">WARNING</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantLinebreak/@EntryIndexedValue">WARNING</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantSpace/@EntryIndexedValue">WARNING</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantUsingDirective/@EntryIndexedValue">ERROR</s:String>
|
||||
@ -171,7 +181,7 @@
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleCallToAny/@EntryIndexedValue">WARNING</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleCallToCount/@EntryIndexedValue">WARNING</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleCallToFirst/@EntryIndexedValue">WARNING</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleCallToFirstOrDefault/@EntryIndexedValue">HINT</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleCallToFirstOrDefault/@EntryIndexedValue">WARNING</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleCallToLast/@EntryIndexedValue">WARNING</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleCallToLastOrDefault/@EntryIndexedValue">WARNING</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleCallToSingle/@EntryIndexedValue">WARNING</s:String>
|
||||
@ -201,6 +211,7 @@
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UnusedMethodReturnValue_002ELocal/@EntryIndexedValue">HINT</s:String>
|
||||
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UnusedParameter_002EGlobal/@EntryIndexedValue">HINT</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UnusedParameter_002ELocal/@EntryIndexedValue">HINT</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UseCollectionCountProperty/@EntryIndexedValue">WARNING</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UseFormatSpecifierInFormatString/@EntryIndexedValue">WARNING</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UseFormatSpecifierInInterpolation/@EntryIndexedValue">WARNING</s:String>
|
||||
@ -218,9 +229,14 @@
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=WrongIndentSize/@EntryIndexedValue">WARNING</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeCleanup/Profiles/=Code_0020Cleanup_0020_0028peppy_0029/@EntryIndexedValue"><?xml version="1.0" encoding="utf-16"?><Profile name="Code Cleanup (peppy)"><CSArrangeThisQualifier>True</CSArrangeThisQualifier><CSUseVar><BehavourStyle>CAN_CHANGE_TO_EXPLICIT</BehavourStyle><LocalVariableStyle>ALWAYS_EXPLICIT</LocalVariableStyle><ForeachVariableStyle>ALWAYS_EXPLICIT</ForeachVariableStyle></CSUseVar><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName></RegionName></CSOptimizeUsings><CSShortenReferences>True</CSShortenReferences><CSReformatCode>True</CSReformatCode><CSUpdateFileHeader>True</CSUpdateFileHeader><CSCodeStyleAttributes ArrangeTypeAccessModifier="False" ArrangeTypeMemberAccessModifier="False" SortModifiers="True" RemoveRedundantParentheses="True" AddMissingParentheses="False" ArrangeBraces="False" ArrangeAttributes="False" ArrangeArgumentsStyle="False" /><XAMLCollapseEmptyTags>False</XAMLCollapseEmptyTags><CSFixBuiltinTypeReferences>True</CSFixBuiltinTypeReferences><CSArrangeQualifiers>True</CSArrangeQualifiers></Profile></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeCleanup/RecentlyUsedProfile/@EntryValue">Code Cleanup (peppy)</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_FOR/@EntryValue">Required</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_FOREACH/@EntryValue">Required</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_WHILE/@EntryValue">Required</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_DOWHILE/@EntryValue">RequiredForMultiline</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_FIXED/@EntryValue">RequiredForMultiline</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_FOR/@EntryValue">RequiredForMultiline</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_FOREACH/@EntryValue">RequiredForMultiline</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_IFELSE/@EntryValue">RequiredForMultiline</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_LOCK/@EntryValue">RequiredForMultiline</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_USING/@EntryValue">RequiredForMultiline</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_WHILE/@EntryValue">RequiredForMultiline</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/DEFAULT_INTERNAL_MODIFIER/@EntryValue">Explicit</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/LOCAL_FUNCTION_BODY/@EntryValue">ExpressionBody</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/METHOD_OR_OPERATOR_BODY/@EntryValue">ExpressionBody</s:String>
|
||||
@ -239,6 +255,10 @@
|
||||
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/BLANK_LINES_BEFORE_CASE/@EntryValue">1</s:Int64>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/CASE_BLOCK_BRACES/@EntryValue">NEXT_LINE</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/EMPTY_BLOCK_STYLE/@EntryValue">MULTILINE</s:String>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INDENT_NESTED_FOR_STMT/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INDENT_NESTED_FOREACH_STMT/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INDENT_NESTED_LOCK_STMT/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INDENT_NESTED_WHILE_STMT/@EntryValue">True</s:Boolean>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INITIALIZER_BRACES/@EntryValue">NEXT_LINE</s:String>
|
||||
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_BLANK_LINES_IN_CODE/@EntryValue">1</s:Int64>
|
||||
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_BLANK_LINES_IN_DECLARATIONS/@EntryValue">1</s:Int64>
|
||||
|
Loading…
Reference in New Issue
Block a user