mirror of
https://github.com/ppy/osu.git
synced 2026-05-20 09:20:15 +08:00
Compare commits
1713 Commits
@@ -2,12 +2,6 @@
|
||||
"version": 1,
|
||||
"isRoot": true,
|
||||
"tools": {
|
||||
"cake.tool": {
|
||||
"version": "0.35.0",
|
||||
"commands": [
|
||||
"dotnet-cake"
|
||||
]
|
||||
},
|
||||
"dotnet-format": {
|
||||
"version": "3.1.37601",
|
||||
"commands": [
|
||||
@@ -20,17 +14,23 @@
|
||||
"jb"
|
||||
]
|
||||
},
|
||||
"nvika": {
|
||||
"version": "2.0.0",
|
||||
"smoogipoo.nvika": {
|
||||
"version": "1.0.1",
|
||||
"commands": [
|
||||
"nvika"
|
||||
]
|
||||
},
|
||||
"codefilesanity": {
|
||||
"version": "15.0.0",
|
||||
"version": "0.0.36",
|
||||
"commands": [
|
||||
"CodeFileSanity"
|
||||
]
|
||||
},
|
||||
"ppy.localisationanalyser.tools": {
|
||||
"version": "2021.608.0",
|
||||
"commands": [
|
||||
"localisation"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-9
@@ -10,14 +10,6 @@ trim_trailing_whitespace = true
|
||||
|
||||
#Roslyn naming styles
|
||||
|
||||
#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,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
|
||||
|
||||
@@ -197,4 +189,4 @@ dotnet_diagnostic.IDE0069.severity = none
|
||||
dotnet_diagnostic.CA2225.severity = none
|
||||
|
||||
# Banned APIs
|
||||
dotnet_diagnostic.RS0030.severity = error
|
||||
dotnet_diagnostic.RS0030.severity = error
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
---
|
||||
name: Feature Request
|
||||
about: Propose a feature you would like to see in the game!
|
||||
---
|
||||
**Describe the new feature:**
|
||||
|
||||
**Proposal designs of the feature:**
|
||||
@@ -1,5 +1,12 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Suggestions or feature request
|
||||
url: https://github.com/ppy/osu/discussions/categories/ideas
|
||||
about: Got something you think should change or be added? Search for or start a new discussion!
|
||||
- name: Help
|
||||
url: https://github.com/ppy/osu/discussions/categories/q-a
|
||||
about: osu! not working as you'd expect? Not sure it's a bug? Check the Q&A section!
|
||||
- name: osu!stable issues
|
||||
url: https://github.com/ppy/osu-stable-issues
|
||||
about: For issues regarding osu!stable (not osu!lazer), open them here.
|
||||
about: For osu!stable bugs (not osu!lazer), check out the dedicated repository. Note that we only accept serious bug reports.
|
||||
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
on: [push, pull_request]
|
||||
name: Continuous Integration
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: Test
|
||||
runs-on: ${{matrix.os.fullname}}
|
||||
env:
|
||||
OSU_EXECUTION_MODE: ${{matrix.threadingMode}}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os:
|
||||
- { prettyname: Windows, fullname: windows-latest }
|
||||
- { prettyname: macOS, fullname: macos-latest }
|
||||
- { prettyname: Linux, fullname: ubuntu-latest }
|
||||
threadingMode: ['SingleThread', 'MultiThreaded']
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Install .NET 5.0.x
|
||||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: "5.0.x"
|
||||
|
||||
# FIXME: libavformat is not included in Ubuntu. Let's fix that.
|
||||
# https://github.com/ppy/osu-framework/issues/4349
|
||||
# Remove this once https://github.com/actions/virtual-environments/issues/3306 has been resolved.
|
||||
- name: Install libavformat-dev
|
||||
if: ${{matrix.os.fullname == 'ubuntu-latest'}}
|
||||
run: |
|
||||
sudo apt-get update && \
|
||||
sudo apt-get -y install libavformat-dev
|
||||
|
||||
- name: Compile
|
||||
run: dotnet build -c Debug -warnaserror osu.Desktop.slnf
|
||||
|
||||
- name: Test
|
||||
run: dotnet test $pwd/*.Tests/bin/Debug/*/*.Tests.dll --logger "trx;LogFileName=TestResults-${{matrix.os.prettyname}}-${{matrix.threadingMode}}.trx"
|
||||
shell: pwsh
|
||||
|
||||
# Attempt to upload results even if test fails.
|
||||
# https://docs.github.com/en/actions/reference/context-and-expression-syntax-for-github-actions#always
|
||||
- name: Upload Test Results
|
||||
uses: actions/upload-artifact@v2
|
||||
if: ${{ always() }}
|
||||
with:
|
||||
name: osu-test-results-${{matrix.os.prettyname}}-${{matrix.threadingMode}}
|
||||
path: ${{github.workspace}}/TestResults/TestResults-${{matrix.os.prettyname}}-${{matrix.threadingMode}}.trx
|
||||
|
||||
inspect-code:
|
||||
name: Code Quality
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
# FIXME: Tools won't run in .NET 5.0 unless you install 3.1.x LTS side by side.
|
||||
# https://itnext.io/how-to-support-multiple-net-sdks-in-github-actions-workflows-b988daa884e
|
||||
- name: Install .NET 3.1.x LTS
|
||||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: "3.1.x"
|
||||
|
||||
- name: Install .NET 5.0.x
|
||||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: "5.0.x"
|
||||
|
||||
- name: Restore Tools
|
||||
run: dotnet tool restore
|
||||
|
||||
- name: Restore Packages
|
||||
run: dotnet restore
|
||||
|
||||
- name: CodeFileSanity
|
||||
run: |
|
||||
# TODO: Add ignore filters and GitHub Workflow Command Reporting in CFS. That way we don't have to do this workaround.
|
||||
# FIXME: Suppress warnings from templates project
|
||||
dotnet codefilesanity | while read -r line; do
|
||||
echo "::warning::$line"
|
||||
done
|
||||
|
||||
# Temporarily disabled due to test failures, but it won't work anyway until the tool is upgraded.
|
||||
# - name: .NET Format (Dry Run)
|
||||
# run: dotnet format --dry-run --check
|
||||
|
||||
- name: InspectCode
|
||||
run: dotnet jb inspectcode $(pwd)/osu.Desktop.slnf --output=$(pwd)/inspectcodereport.xml --cachesDir=$(pwd)/inspectcode --verbosity=WARN
|
||||
|
||||
- name: NVika
|
||||
run: dotnet nvika parsereport "${{github.workspace}}/inspectcodereport.xml" --treatwarningsaserrors
|
||||
@@ -0,0 +1,31 @@
|
||||
# This is a workaround to allow PRs to report their coverage. This will run inside the base repository.
|
||||
# See:
|
||||
# * https://github.com/dorny/test-reporter#recommended-setup-for-public-repositories
|
||||
# * https://docs.github.com/en/actions/reference/authentication-in-a-workflow#permissions-for-the-github_token
|
||||
name: Annotate CI run with test results
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ["Continuous Integration"]
|
||||
types:
|
||||
- completed
|
||||
jobs:
|
||||
annotate:
|
||||
name: Annotate CI run with test results
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event.workflow_run.conclusion != 'cancelled' }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os:
|
||||
- { prettyname: Windows }
|
||||
- { prettyname: macOS }
|
||||
- { prettyname: Linux }
|
||||
threadingMode: ['SingleThread', 'MultiThreaded']
|
||||
steps:
|
||||
- name: Annotate CI run with test results
|
||||
uses: dorny/test-reporter@v1.4.2
|
||||
with:
|
||||
artifact: osu-test-results-${{matrix.os.prettyname}}-${{matrix.threadingMode}}
|
||||
name: Test Results (${{matrix.os.prettyname}}, ${{matrix.threadingMode}})
|
||||
path: "*.trx"
|
||||
reporter: dotnet-trx
|
||||
Vendored
-14
@@ -113,20 +113,6 @@
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build benchmarks",
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
"name": "Cake: Debug Script",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"program": "${workspaceRoot}/build/tools/Cake.CoreCLR/0.30.0/Cake.dll",
|
||||
"args": [
|
||||
"${workspaceRoot}/build/build.cake",
|
||||
"--debug",
|
||||
"--verbosity=diagnostic"
|
||||
],
|
||||
"cwd": "${workspaceRoot}/build",
|
||||
"stopAtEntry": true,
|
||||
"externalConsole": false
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+10
-26
@@ -1,27 +1,11 @@
|
||||
[CmdletBinding()]
|
||||
Param(
|
||||
[string]$Target,
|
||||
[string]$Configuration,
|
||||
[ValidateSet("Quiet", "Minimal", "Normal", "Verbose", "Diagnostic")]
|
||||
[string]$Verbosity,
|
||||
[switch]$ShowDescription,
|
||||
[Alias("WhatIf", "Noop")]
|
||||
[switch]$DryRun,
|
||||
[Parameter(Position = 0, Mandatory = $false, ValueFromRemainingArguments = $true)]
|
||||
[string[]]$ScriptArgs
|
||||
)
|
||||
|
||||
# Build Cake arguments
|
||||
$cakeArguments = "";
|
||||
if ($Target) { $cakeArguments += "-target=$Target" }
|
||||
if ($Configuration) { $cakeArguments += "-configuration=$Configuration" }
|
||||
if ($Verbosity) { $cakeArguments += "-verbosity=$Verbosity" }
|
||||
if ($ShowDescription) { $cakeArguments += "-showdescription" }
|
||||
if ($DryRun) { $cakeArguments += "-dryrun" }
|
||||
if ($Experimental) { $cakeArguments += "-experimental" }
|
||||
$cakeArguments += $ScriptArgs
|
||||
|
||||
dotnet tool restore
|
||||
dotnet cake ./build/InspectCode.cake --bootstrap
|
||||
dotnet cake ./build/InspectCode.cake $cakeArguments
|
||||
exit $LASTEXITCODE
|
||||
|
||||
# Temporarily disabled until the tool is upgraded to 5.0.
|
||||
# The version specified in .config/dotnet-tools.json (3.1.37601) won't run on .NET hosts >=5.0.7.
|
||||
# - cmd: dotnet format --dry-run --check
|
||||
|
||||
dotnet CodeFileSanity
|
||||
dotnet jb inspectcode "osu.Desktop.slnf" --output="inspectcodereport.xml" --caches-home="inspectcode" --verbosity=WARN
|
||||
dotnet nvika parsereport "inspectcodereport.xml" --treatwarningsaserrors
|
||||
|
||||
exit $LASTEXITCODE
|
||||
|
||||
Executable
+6
@@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
dotnet tool restore
|
||||
dotnet CodeFileSanity
|
||||
dotnet jb inspectcode "osu.Desktop.slnf" --output="inspectcodereport.xml" --caches-home="inspectcode" --verbosity=WARN
|
||||
dotnet nvika parsereport "inspectcodereport.xml" --treatwarningsaserrors
|
||||
@@ -97,7 +97,7 @@ Before committing your code, please run a code formatter. This can be achieved b
|
||||
|
||||
We have adopted some cross-platform, compiler integrated analyzers. They can provide warnings when you are editing, building inside IDE or from command line, as-if they are provided by the compiler itself.
|
||||
|
||||
JetBrains ReSharper InspectCode is also used for wider rule sets. You can run it from PowerShell with `.\InspectCode.ps1`, which is [only supported on Windows](https://youtrack.jetbrains.com/issue/RSRP-410004). Alternatively, you can install ReSharper or use Rider to get inline support in your IDE of choice.
|
||||
JetBrains ReSharper InspectCode is also used for wider rule sets. You can run it from PowerShell with `.\InspectCode.ps1`. Alternatively, you can install ReSharper or use Rider to get inline support in your IDE of choice.
|
||||
|
||||
## Contributing
|
||||
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@
|
||||
</PropertyGroup>
|
||||
<ItemGroup Label="Package References">
|
||||
<PackageReference Include="Appveyor.TestLogger" Version="2.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.10.0" />
|
||||
<PackageReference Include="NUnit" Version="3.13.2" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="3.17.0" />
|
||||
<PackageReference Update="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.4" />
|
||||
|
||||
+1
-1
@@ -25,6 +25,6 @@ namespace osu.Game.Rulesets.EmptyFreeform
|
||||
|
||||
protected override IEnumerable<DifficultyHitObject> CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate) => Enumerable.Empty<DifficultyHitObject>();
|
||||
|
||||
protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods) => new Skill[0];
|
||||
protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods, double clockRate) => new Skill[0];
|
||||
}
|
||||
}
|
||||
|
||||
+1
-2
@@ -3,7 +3,6 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.EmptyFreeform.Objects;
|
||||
using osu.Game.Rulesets.EmptyFreeform.Replays;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Scoring;
|
||||
@@ -11,7 +10,7 @@ using osu.Game.Users;
|
||||
|
||||
namespace osu.Game.Rulesets.EmptyFreeform.Mods
|
||||
{
|
||||
public class EmptyFreeformModAutoplay : ModAutoplay<EmptyFreeformHitObject>
|
||||
public class EmptyFreeformModAutoplay : ModAutoplay
|
||||
{
|
||||
public override Score CreateReplayScore(IBeatmap beatmap, IReadOnlyList<Mod> mods) => new Score
|
||||
{
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@
|
||||
</PropertyGroup>
|
||||
<ItemGroup Label="Package References">
|
||||
<PackageReference Include="Appveyor.TestLogger" Version="2.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.10.0" />
|
||||
<PackageReference Include="NUnit" Version="3.13.2" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="3.17.0" />
|
||||
<PackageReference Update="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.4" />
|
||||
|
||||
+1
-2
@@ -4,14 +4,13 @@
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Pippidon.Objects;
|
||||
using osu.Game.Rulesets.Pippidon.Replays;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Users;
|
||||
|
||||
namespace osu.Game.Rulesets.Pippidon.Mods
|
||||
{
|
||||
public class PippidonModAutoplay : ModAutoplay<PippidonHitObject>
|
||||
public class PippidonModAutoplay : ModAutoplay
|
||||
{
|
||||
public override Score CreateReplayScore(IBeatmap beatmap, IReadOnlyList<Mod> mods) => new Score
|
||||
{
|
||||
|
||||
+1
-1
@@ -25,6 +25,6 @@ namespace osu.Game.Rulesets.Pippidon
|
||||
|
||||
protected override IEnumerable<DifficultyHitObject> CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate) => Enumerable.Empty<DifficultyHitObject>();
|
||||
|
||||
protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods) => new Skill[0];
|
||||
protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods, double clockRate) => new Skill[0];
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@
|
||||
</PropertyGroup>
|
||||
<ItemGroup Label="Package References">
|
||||
<PackageReference Include="Appveyor.TestLogger" Version="2.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.10.0" />
|
||||
<PackageReference Include="NUnit" Version="3.13.2" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="3.17.0" />
|
||||
<PackageReference Update="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.4" />
|
||||
|
||||
+1
-1
@@ -25,6 +25,6 @@ namespace osu.Game.Rulesets.EmptyScrolling
|
||||
|
||||
protected override IEnumerable<DifficultyHitObject> CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate) => Enumerable.Empty<DifficultyHitObject>();
|
||||
|
||||
protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods) => new Skill[0];
|
||||
protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods, double clockRate) => new Skill[0];
|
||||
}
|
||||
}
|
||||
|
||||
+1
-2
@@ -3,7 +3,6 @@
|
||||
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.EmptyScrolling.Objects;
|
||||
using osu.Game.Rulesets.EmptyScrolling.Replays;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Users;
|
||||
@@ -11,7 +10,7 @@ using System.Collections.Generic;
|
||||
|
||||
namespace osu.Game.Rulesets.EmptyScrolling.Mods
|
||||
{
|
||||
public class EmptyScrollingModAutoplay : ModAutoplay<EmptyScrollingHitObject>
|
||||
public class EmptyScrollingModAutoplay : ModAutoplay
|
||||
{
|
||||
public override Score CreateReplayScore(IBeatmap beatmap, IReadOnlyList<Mod> mods) => new Score
|
||||
{
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@
|
||||
</PropertyGroup>
|
||||
<ItemGroup Label="Package References">
|
||||
<PackageReference Include="Appveyor.TestLogger" Version="2.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.10.0" />
|
||||
<PackageReference Include="NUnit" Version="3.13.2" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="3.17.0" />
|
||||
<PackageReference Update="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.4" />
|
||||
|
||||
+1
-2
@@ -4,14 +4,13 @@
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Pippidon.Objects;
|
||||
using osu.Game.Rulesets.Pippidon.Replays;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Users;
|
||||
|
||||
namespace osu.Game.Rulesets.Pippidon.Mods
|
||||
{
|
||||
public class PippidonModAutoplay : ModAutoplay<PippidonHitObject>
|
||||
public class PippidonModAutoplay : ModAutoplay
|
||||
{
|
||||
public override Score CreateReplayScore(IBeatmap beatmap, IReadOnlyList<Mod> mods) => new Score
|
||||
{
|
||||
|
||||
+1
-1
@@ -25,6 +25,6 @@ namespace osu.Game.Rulesets.Pippidon
|
||||
|
||||
protected override IEnumerable<DifficultyHitObject> CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate) => Enumerable.Empty<DifficultyHitObject>();
|
||||
|
||||
protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods) => new Skill[0];
|
||||
protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods, double clockRate) => new Skill[0];
|
||||
}
|
||||
}
|
||||
|
||||
+9
-6
@@ -1,24 +1,27 @@
|
||||
clone_depth: 1
|
||||
version: '{branch}-{build}'
|
||||
image: Visual Studio 2019
|
||||
cache:
|
||||
- '%LOCALAPPDATA%\NuGet\v3-cache -> appveyor.yml'
|
||||
|
||||
dotnet_csproj:
|
||||
patch: true
|
||||
file: 'osu.Game\osu.Game.csproj' # Use wildcard when it's able to exclude Xamarin projects
|
||||
version: '0.0.{build}'
|
||||
cache:
|
||||
- '%LOCALAPPDATA%\NuGet\v3-cache -> appveyor.yml'
|
||||
|
||||
before_build:
|
||||
- ps: dotnet --info # Useful when version mismatch between CI and local
|
||||
- ps: nuget restore -verbosity quiet # Only nuget.exe knows both new (.NET Core) and old (Xamarin) projects
|
||||
- cmd: dotnet --info # Useful when version mismatch between CI and local
|
||||
- cmd: nuget restore -verbosity quiet # Only nuget.exe knows both new (.NET Core) and old (Xamarin) projects
|
||||
|
||||
build:
|
||||
project: osu.sln
|
||||
parallel: true
|
||||
verbosity: minimal
|
||||
publish_nuget: true
|
||||
|
||||
after_build:
|
||||
- ps: dotnet tool restore
|
||||
- ps: dotnet format --dry-run --check
|
||||
- ps: .\InspectCode.ps1
|
||||
|
||||
test:
|
||||
assemblies:
|
||||
except:
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
<Project Sdk="Microsoft.Build.Traversal">
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\osu.Desktop\osu.Desktop.csproj" />
|
||||
<ProjectReference Include="..\osu.Game.Rulesets.Catch.Tests\osu.Game.Rulesets.Catch.Tests.csproj" />
|
||||
<ProjectReference Include="..\osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj" />
|
||||
<ProjectReference Include="..\osu.Game.Rulesets.Mania.Tests\osu.Game.Rulesets.Mania.Tests.csproj" />
|
||||
<ProjectReference Include="..\osu.Game.Rulesets.Mania\osu.Game.Rulesets.Mania.csproj" />
|
||||
<ProjectReference Include="..\osu.Game.Rulesets.Osu.Tests\osu.Game.Rulesets.Osu.Tests.csproj" />
|
||||
<ProjectReference Include="..\osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj" />
|
||||
<ProjectReference Include="..\osu.Game.Rulesets.Taiko.Tests\osu.Game.Rulesets.Taiko.Tests.csproj" />
|
||||
<ProjectReference Include="..\osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj" />
|
||||
<ProjectReference Include="..\osu.Game.Tests\osu.Game.Tests.csproj" />
|
||||
<ProjectReference Include="..\osu.Game.Tournament.Tests\osu.Game.Tournament.Tests.csproj" />
|
||||
<ProjectReference Include="..\osu.Game.Tournament\osu.Game.Tournament.csproj" />
|
||||
<ProjectReference Include="..\osu.Game\osu.Game.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,41 +0,0 @@
|
||||
#addin "nuget:?package=CodeFileSanity&version=0.0.36"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// ARGUMENTS
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
var target = Argument("target", "CodeAnalysis");
|
||||
var configuration = Argument("configuration", "Release");
|
||||
|
||||
var rootDirectory = new DirectoryPath("..");
|
||||
var sln = rootDirectory.CombineWithFilePath("osu.sln");
|
||||
var desktopSlnf = rootDirectory.CombineWithFilePath("osu.Desktop.slnf");
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// TASKS
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Task("InspectCode")
|
||||
.Does(() => {
|
||||
var inspectcodereport = "inspectcodereport.xml";
|
||||
var cacheDir = "inspectcode";
|
||||
var verbosity = AppVeyor.IsRunningOnAppVeyor ? "WARN" : "INFO"; // Don't flood CI output
|
||||
|
||||
DotNetCoreTool(rootDirectory.FullPath,
|
||||
"jb", $@"inspectcode ""{desktopSlnf}"" --output=""{inspectcodereport}"" --caches-home=""{cacheDir}"" --verbosity={verbosity}");
|
||||
DotNetCoreTool(rootDirectory.FullPath, "nvika", $@"parsereport ""{inspectcodereport}"" --treatwarningsaserrors");
|
||||
});
|
||||
|
||||
Task("CodeFileSanity")
|
||||
.Does(() => {
|
||||
ValidateCodeSanity(new ValidateCodeSanitySettings {
|
||||
RootDirectory = rootDirectory.FullPath,
|
||||
IsAppveyorBuild = AppVeyor.IsRunningOnAppVeyor
|
||||
});
|
||||
});
|
||||
|
||||
Task("CodeAnalysis")
|
||||
.IsDependentOn("CodeFileSanity")
|
||||
.IsDependentOn("InspectCode");
|
||||
|
||||
RunTarget(target);
|
||||
@@ -1,5 +0,0 @@
|
||||
|
||||
[Nuget]
|
||||
Source=https://api.nuget.org/v3/index.json
|
||||
UseInProcessClient=true
|
||||
LoadDependencies=true
|
||||
+2
-2
@@ -51,7 +51,7 @@
|
||||
<Reference Include="Java.Interop" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.422.0" />
|
||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2021.510.0" />
|
||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.618.0" />
|
||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2021.616.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -20,7 +20,8 @@ namespace osu.Android
|
||||
[Activity(Theme = "@android:style/Theme.NoTitleBar", MainLauncher = true, ScreenOrientation = ScreenOrientation.FullUser, SupportsPictureInPicture = false, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize, HardwareAccelerated = false, LaunchMode = LaunchMode.SingleInstance, Exported = true)]
|
||||
[IntentFilter(new[] { Intent.ActionView }, Categories = new[] { Intent.CategoryDefault }, DataScheme = "content", DataPathPattern = ".*\\\\.osz", DataHost = "*", DataMimeType = "*/*")]
|
||||
[IntentFilter(new[] { Intent.ActionView }, Categories = new[] { Intent.CategoryDefault }, DataScheme = "content", DataPathPattern = ".*\\\\.osk", DataHost = "*", DataMimeType = "*/*")]
|
||||
[IntentFilter(new[] { Intent.ActionSend, Intent.ActionSendMultiple }, Categories = new[] { Intent.CategoryDefault }, DataMimeTypes = new[] { "application/zip", "application/octet-stream", "application/download", "application/x-zip", "application/x-zip-compressed" })]
|
||||
[IntentFilter(new[] { Intent.ActionView }, Categories = new[] { Intent.CategoryDefault }, DataScheme = "content", DataMimeType = "application/x-osu-archive")]
|
||||
[IntentFilter(new[] { Intent.ActionSend, Intent.ActionSendMultiple }, Categories = new[] { Intent.CategoryDefault }, DataMimeTypes = new[] { "application/zip", "application/octet-stream", "application/download", "application/x-zip", "application/x-zip-compressed", "application/x-osu-archive" })]
|
||||
[IntentFilter(new[] { Intent.ActionView }, Categories = new[] { Intent.CategoryBrowsable, Intent.CategoryDefault }, DataSchemes = new[] { "osu", "osump" })]
|
||||
public class OsuGameActivity : AndroidGameActivity
|
||||
{
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace osu.Desktop
|
||||
|
||||
private string getStableInstallPath()
|
||||
{
|
||||
static bool checkExists(string p) => Directory.Exists(Path.Combine(p, "Songs"));
|
||||
static bool checkExists(string p) => Directory.Exists(Path.Combine(p, "Songs")) || File.Exists(Path.Combine(p, "osu!.cfg"));
|
||||
|
||||
string stableInstallPath;
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BenchmarkDotNet" Version="0.12.1" />
|
||||
<PackageReference Include="BenchmarkDotNet" Version="0.13.0" />
|
||||
<PackageReference Include="nunit" Version="3.13.2" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="3.17.0" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
[General]
|
||||
// no version specified means v1
|
||||
@@ -4,10 +4,8 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Rulesets.Catch.Mods;
|
||||
using osu.Game.Rulesets.Catch.Objects;
|
||||
using osu.Game.Rulesets.Catch.Objects.Drawables;
|
||||
@@ -21,12 +19,6 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
{
|
||||
public class TestSceneCatchModHidden : ModTestScene
|
||||
{
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
LocalConfig.SetValue(OsuSetting.IncreaseFirstObjectVisibility, false);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestJuiceStream()
|
||||
{
|
||||
|
||||
@@ -1,8 +1,16 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Screens.Play.HUD;
|
||||
using osu.Game.Skinning;
|
||||
using osu.Game.Tests.Visual;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Tests
|
||||
{
|
||||
@@ -10,5 +18,22 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
public class TestSceneCatchPlayerLegacySkin : LegacySkinPlayerTestScene
|
||||
{
|
||||
protected override Ruleset CreatePlayerRuleset() => new CatchRuleset();
|
||||
|
||||
[Test]
|
||||
public void TestLegacyHUDComboCounterHidden([Values] bool withModifiedSkin)
|
||||
{
|
||||
if (withModifiedSkin)
|
||||
{
|
||||
AddStep("change component scale", () => Player.ChildrenOfType<LegacyScoreCounter>().First().Scale = new Vector2(2f));
|
||||
AddStep("update target", () => Player.ChildrenOfType<SkinnableTargetContainer>().ForEach(LegacySkin.UpdateDrawableTarget));
|
||||
AddStep("exit player", () => Player.Exit());
|
||||
CreateTest(null);
|
||||
}
|
||||
|
||||
AddAssert("legacy HUD combo counter hidden", () =>
|
||||
{
|
||||
return Player.ChildrenOfType<LegacyComboCounter>().All(c => c.ChildrenOfType<Container>().Single().Alpha == 0f);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,7 +216,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
AddStep("enable hit lighting", () => config.SetValue(OsuSetting.HitLighting, true));
|
||||
AddStep("catch fruit", () => attemptCatch(new Fruit()));
|
||||
AddAssert("correct hit lighting colour", () =>
|
||||
catcher.ChildrenOfType<HitExplosion>().First()?.ObjectColour == fruitColour);
|
||||
catcher.ChildrenOfType<HitExplosion>().First()?.Entry?.ObjectColour == fruitColour);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -95,7 +95,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
CircleSize = circleSize
|
||||
};
|
||||
|
||||
SetContents(() =>
|
||||
SetContents(_ =>
|
||||
{
|
||||
var droppedObjectContainer = new Container<CaughtObject>
|
||||
{
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
{
|
||||
scoreProcessor = new ScoreProcessor();
|
||||
|
||||
SetContents(() => new CatchComboDisplay
|
||||
SetContents(_ => new CatchComboDisplay
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
|
||||
@@ -174,8 +174,8 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
|
||||
private void addToPlayfield(DrawableCatchHitObject drawable)
|
||||
{
|
||||
foreach (var mod in SelectedMods.Value.OfType<IApplicableToDrawableHitObjects>())
|
||||
mod.ApplyToDrawableHitObjects(new[] { drawable });
|
||||
foreach (var mod in SelectedMods.Value.OfType<IApplicableToDrawableHitObject>())
|
||||
mod.ApplyToDrawableHitObject(drawable);
|
||||
|
||||
drawableRuleset.Playfield.Add(drawable);
|
||||
}
|
||||
|
||||
@@ -19,22 +19,22 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
AddStep("show pear", () => SetContents(() => createDrawableFruit(0)));
|
||||
AddStep("show grape", () => SetContents(() => createDrawableFruit(1)));
|
||||
AddStep("show pineapple / apple", () => SetContents(() => createDrawableFruit(2)));
|
||||
AddStep("show raspberry / orange", () => SetContents(() => createDrawableFruit(3)));
|
||||
AddStep("show pear", () => SetContents(_ => createDrawableFruit(0)));
|
||||
AddStep("show grape", () => SetContents(_ => createDrawableFruit(1)));
|
||||
AddStep("show pineapple / apple", () => SetContents(_ => createDrawableFruit(2)));
|
||||
AddStep("show raspberry / orange", () => SetContents(_ => createDrawableFruit(3)));
|
||||
|
||||
AddStep("show banana", () => SetContents(createDrawableBanana));
|
||||
AddStep("show banana", () => SetContents(_ => createDrawableBanana()));
|
||||
|
||||
AddStep("show droplet", () => SetContents(() => createDrawableDroplet()));
|
||||
AddStep("show tiny droplet", () => SetContents(createDrawableTinyDroplet));
|
||||
AddStep("show droplet", () => SetContents(_ => createDrawableDroplet()));
|
||||
AddStep("show tiny droplet", () => SetContents(_ => createDrawableTinyDroplet()));
|
||||
|
||||
AddStep("show hyperdash pear", () => SetContents(() => createDrawableFruit(0, true)));
|
||||
AddStep("show hyperdash grape", () => SetContents(() => createDrawableFruit(1, true)));
|
||||
AddStep("show hyperdash pineapple / apple", () => SetContents(() => createDrawableFruit(2, true)));
|
||||
AddStep("show hyperdash raspberry / orange", () => SetContents(() => createDrawableFruit(3, true)));
|
||||
AddStep("show hyperdash pear", () => SetContents(_ => createDrawableFruit(0, true)));
|
||||
AddStep("show hyperdash grape", () => SetContents(_ => createDrawableFruit(1, true)));
|
||||
AddStep("show hyperdash pineapple / apple", () => SetContents(_ => createDrawableFruit(2, true)));
|
||||
AddStep("show hyperdash raspberry / orange", () => SetContents(_ => createDrawableFruit(3, true)));
|
||||
|
||||
AddStep("show hyperdash droplet", () => SetContents(() => createDrawableDroplet(true)));
|
||||
AddStep("show hyperdash droplet", () => SetContents(_ => createDrawableDroplet(true)));
|
||||
}
|
||||
|
||||
private Drawable createDrawableFruit(int indexInBeatmap, bool hyperdash = false) =>
|
||||
|
||||
@@ -14,13 +14,13 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
AddStep("fruit changes visual and hyper", () => SetContents(() => new TestDrawableCatchHitObjectSpecimen(new DrawableFruit(new Fruit
|
||||
AddStep("fruit changes visual and hyper", () => SetContents(_ => new TestDrawableCatchHitObjectSpecimen(new DrawableFruit(new Fruit
|
||||
{
|
||||
IndexInBeatmapBindable = { BindTarget = indexInBeatmap },
|
||||
HyperDashBindable = { BindTarget = hyperDash },
|
||||
}))));
|
||||
|
||||
AddStep("droplet changes hyper", () => SetContents(() => new TestDrawableCatchHitObjectSpecimen(new DrawableDroplet(new Droplet
|
||||
AddStep("droplet changes hyper", () => SetContents(_ => new TestDrawableCatchHitObjectSpecimen(new DrawableDroplet(new Droplet
|
||||
{
|
||||
HyperDashBindable = { BindTarget = hyperDash },
|
||||
}))));
|
||||
|
||||
@@ -32,28 +32,28 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
[TestCase(true, false)]
|
||||
[TestCase(false, true)]
|
||||
[TestCase(false, false)]
|
||||
public override void TestBeatmapComboColours(bool userHasCustomColours, bool useBeatmapSkin)
|
||||
public void TestBeatmapComboColours(bool userHasCustomColours, bool useBeatmapSkin)
|
||||
{
|
||||
TestBeatmap = new CatchCustomSkinWorkingBeatmap(audio, true);
|
||||
base.TestBeatmapComboColours(userHasCustomColours, useBeatmapSkin);
|
||||
PrepareBeatmap(() => new CatchCustomSkinWorkingBeatmap(audio, true));
|
||||
ConfigureTest(useBeatmapSkin, true, userHasCustomColours);
|
||||
AddAssert("is beatmap skin colours", () => TestPlayer.UsableComboColours.SequenceEqual(TestBeatmapSkin.Colours));
|
||||
}
|
||||
|
||||
[TestCase(true)]
|
||||
[TestCase(false)]
|
||||
public override void TestBeatmapComboColoursOverride(bool useBeatmapSkin)
|
||||
public void TestBeatmapComboColoursOverride(bool useBeatmapSkin)
|
||||
{
|
||||
TestBeatmap = new CatchCustomSkinWorkingBeatmap(audio, true);
|
||||
base.TestBeatmapComboColoursOverride(useBeatmapSkin);
|
||||
PrepareBeatmap(() => new CatchCustomSkinWorkingBeatmap(audio, true));
|
||||
ConfigureTest(useBeatmapSkin, false, true);
|
||||
AddAssert("is user custom skin colours", () => TestPlayer.UsableComboColours.SequenceEqual(TestSkin.Colours));
|
||||
}
|
||||
|
||||
[TestCase(true)]
|
||||
[TestCase(false)]
|
||||
public override void TestBeatmapComboColoursOverrideWithDefaultColours(bool useBeatmapSkin)
|
||||
public void TestBeatmapComboColoursOverrideWithDefaultColours(bool useBeatmapSkin)
|
||||
{
|
||||
TestBeatmap = new CatchCustomSkinWorkingBeatmap(audio, true);
|
||||
base.TestBeatmapComboColoursOverrideWithDefaultColours(useBeatmapSkin);
|
||||
PrepareBeatmap(() => new CatchCustomSkinWorkingBeatmap(audio, true));
|
||||
ConfigureTest(useBeatmapSkin, false, false);
|
||||
AddAssert("is default user skin colours", () => TestPlayer.UsableComboColours.SequenceEqual(SkinConfiguration.DefaultComboColours));
|
||||
}
|
||||
|
||||
@@ -61,10 +61,10 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
[TestCase(false, true)]
|
||||
[TestCase(true, false)]
|
||||
[TestCase(false, false)]
|
||||
public override void TestBeatmapNoComboColours(bool useBeatmapSkin, bool useBeatmapColour)
|
||||
public void TestBeatmapNoComboColours(bool useBeatmapSkin, bool useBeatmapColour)
|
||||
{
|
||||
TestBeatmap = new CatchCustomSkinWorkingBeatmap(audio, false);
|
||||
base.TestBeatmapNoComboColours(useBeatmapSkin, useBeatmapColour);
|
||||
PrepareBeatmap(() => new CatchCustomSkinWorkingBeatmap(audio, false));
|
||||
ConfigureTest(useBeatmapSkin, useBeatmapColour, false);
|
||||
AddAssert("is default user skin colours", () => TestPlayer.UsableComboColours.SequenceEqual(SkinConfiguration.DefaultComboColours));
|
||||
}
|
||||
|
||||
@@ -72,10 +72,10 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
[TestCase(false, true)]
|
||||
[TestCase(true, false)]
|
||||
[TestCase(false, false)]
|
||||
public override void TestBeatmapNoComboColoursSkinOverride(bool useBeatmapSkin, bool useBeatmapColour)
|
||||
public void TestBeatmapNoComboColoursSkinOverride(bool useBeatmapSkin, bool useBeatmapColour)
|
||||
{
|
||||
TestBeatmap = new CatchCustomSkinWorkingBeatmap(audio, false);
|
||||
base.TestBeatmapNoComboColoursSkinOverride(useBeatmapSkin, useBeatmapColour);
|
||||
PrepareBeatmap(() => new CatchCustomSkinWorkingBeatmap(audio, false));
|
||||
ConfigureTest(useBeatmapSkin, useBeatmapColour, true);
|
||||
AddAssert("is custom user skin colours", () => TestPlayer.UsableComboColours.SequenceEqual(TestSkin.Colours));
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
[TestCase(false)]
|
||||
public void TestBeatmapHyperDashColours(bool useBeatmapSkin)
|
||||
{
|
||||
TestBeatmap = new CatchCustomSkinWorkingBeatmap(audio, true);
|
||||
PrepareBeatmap(() => new CatchCustomSkinWorkingBeatmap(audio, true));
|
||||
ConfigureTest(useBeatmapSkin, true, true);
|
||||
AddAssert("is custom hyper dash colours", () => ((CatchExposedPlayer)TestPlayer).UsableHyperDashColour == TestBeatmapSkin.HYPER_DASH_COLOUR);
|
||||
AddAssert("is custom hyper dash after image colours", () => ((CatchExposedPlayer)TestPlayer).UsableHyperDashAfterImageColour == TestBeatmapSkin.HYPER_DASH_AFTER_IMAGE_COLOUR);
|
||||
@@ -94,7 +94,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
[TestCase(false)]
|
||||
public void TestBeatmapHyperDashColoursOverride(bool useBeatmapSkin)
|
||||
{
|
||||
TestBeatmap = new CatchCustomSkinWorkingBeatmap(audio, true);
|
||||
PrepareBeatmap(() => new CatchCustomSkinWorkingBeatmap(audio, true));
|
||||
ConfigureTest(useBeatmapSkin, false, true);
|
||||
AddAssert("is custom hyper dash colours", () => ((CatchExposedPlayer)TestPlayer).UsableHyperDashColour == TestSkin.HYPER_DASH_COLOUR);
|
||||
AddAssert("is custom hyper dash after image colours", () => ((CatchExposedPlayer)TestPlayer).UsableHyperDashAfterImageColour == TestSkin.HYPER_DASH_AFTER_IMAGE_COLOUR);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<Import Project="..\osu.TestProject.props" />
|
||||
<ItemGroup Label="Package References">
|
||||
<PackageReference Include="Appveyor.TestLogger" Version="2.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.10.0" />
|
||||
<PackageReference Include="NUnit" Version="3.13.2" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="3.17.0" />
|
||||
<PackageReference Update="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.4" />
|
||||
|
||||
@@ -161,13 +161,13 @@ namespace osu.Game.Rulesets.Catch
|
||||
switch (result)
|
||||
{
|
||||
case HitResult.LargeTickHit:
|
||||
return "large droplet";
|
||||
return "Large droplet";
|
||||
|
||||
case HitResult.SmallTickHit:
|
||||
return "small droplet";
|
||||
return "Small droplet";
|
||||
|
||||
case HitResult.LargeBonus:
|
||||
return "banana";
|
||||
return "Banana";
|
||||
}
|
||||
|
||||
return base.GetDisplayNameForHitResult(result);
|
||||
|
||||
@@ -8,9 +8,7 @@ namespace osu.Game.Rulesets.Catch
|
||||
Fruit,
|
||||
Banana,
|
||||
Droplet,
|
||||
CatcherIdle,
|
||||
CatcherFail,
|
||||
CatcherKiai,
|
||||
Catcher,
|
||||
CatchComboCounter
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,6 @@ namespace osu.Game.Rulesets.Catch.Difficulty
|
||||
{
|
||||
public class CatchDifficultyAttributes : DifficultyAttributes
|
||||
{
|
||||
public double ApproachRate;
|
||||
public double ApproachRate { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty
|
||||
}
|
||||
}
|
||||
|
||||
protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods)
|
||||
protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods, double clockRate)
|
||||
{
|
||||
halfCatcherWidth = Catcher.CalculateCatchWidth(beatmap.BeatmapInfo.BaseDifficulty) * 0.5f;
|
||||
|
||||
@@ -76,7 +76,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty
|
||||
|
||||
return new Skill[]
|
||||
{
|
||||
new Movement(mods, halfCatcherWidth),
|
||||
new Movement(mods, halfCatcherWidth, clockRate),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -39,10 +39,6 @@ namespace osu.Game.Rulesets.Catch.Difficulty
|
||||
tinyTicksMissed = Score.Statistics.GetOrDefault(HitResult.SmallTickMiss);
|
||||
misses = Score.Statistics.GetOrDefault(HitResult.Miss);
|
||||
|
||||
// Don't count scores made with supposedly unranked mods
|
||||
if (mods.Any(m => !m.Ranked))
|
||||
return 0;
|
||||
|
||||
// We are heavily relying on aim in catch the beat
|
||||
double value = Math.Pow(5.0 * Math.Max(1.0, Attributes.StarRating / 0.0049) - 4.0, 2.0) / 100000.0;
|
||||
|
||||
|
||||
@@ -24,8 +24,6 @@ namespace osu.Game.Rulesets.Catch.Difficulty.Preprocessing
|
||||
/// </summary>
|
||||
public readonly double StrainTime;
|
||||
|
||||
public readonly double ClockRate;
|
||||
|
||||
public CatchDifficultyHitObject(HitObject hitObject, HitObject lastObject, double clockRate, float halfCatcherWidth)
|
||||
: base(hitObject, lastObject, clockRate)
|
||||
{
|
||||
@@ -37,7 +35,6 @@ namespace osu.Game.Rulesets.Catch.Difficulty.Preprocessing
|
||||
|
||||
// Every strain interval is hard capped at the equivalent of 375 BPM streaming speed as a safety measure
|
||||
StrainTime = Math.Max(40, DeltaTime);
|
||||
ClockRate = clockRate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,10 +28,21 @@ namespace osu.Game.Rulesets.Catch.Difficulty.Skills
|
||||
private float lastDistanceMoved;
|
||||
private double lastStrainTime;
|
||||
|
||||
public Movement(Mod[] mods, float halfCatcherWidth)
|
||||
/// <summary>
|
||||
/// The speed multiplier applied to the player's catcher.
|
||||
/// </summary>
|
||||
private readonly double catcherSpeedMultiplier;
|
||||
|
||||
public Movement(Mod[] mods, float halfCatcherWidth, double clockRate)
|
||||
: base(mods)
|
||||
{
|
||||
HalfCatcherWidth = halfCatcherWidth;
|
||||
|
||||
// In catch, clockrate adjustments do not only affect the timings of hitobjects,
|
||||
// but also the speed of the player's catcher, which has an impact on difficulty
|
||||
// TODO: Support variable clockrates caused by mods such as ModTimeRamp
|
||||
// (perhaps by using IApplicableToRate within the CatchDifficultyHitObject constructor to set a catcher speed for each object before processing)
|
||||
catcherSpeedMultiplier = clockRate;
|
||||
}
|
||||
|
||||
protected override double StrainValueOf(DifficultyHitObject current)
|
||||
@@ -48,7 +59,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty.Skills
|
||||
|
||||
float distanceMoved = playerPosition - lastPlayerPosition.Value;
|
||||
|
||||
double weightedStrainTime = catchCurrent.StrainTime + 13 + (3 / catchCurrent.ClockRate);
|
||||
double weightedStrainTime = catchCurrent.StrainTime + 13 + (3 / catcherSpeedMultiplier);
|
||||
|
||||
double distanceAddition = (Math.Pow(Math.Abs(distanceMoved), 1.3) / 510);
|
||||
double sqrtStrain = Math.Sqrt(weightedStrainTime);
|
||||
@@ -81,7 +92,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty.Skills
|
||||
playerPosition = catchCurrent.NormalizedPosition;
|
||||
}
|
||||
|
||||
distanceAddition *= 1.0 + edgeDashBonus * ((20 - catchCurrent.LastObject.DistanceToHyperDash) / 20) * Math.Pow((Math.Min(catchCurrent.StrainTime * catchCurrent.ClockRate, 265) / 265), 1.5); // Edge Dashes are easier at lower ms values
|
||||
distanceAddition *= 1.0 + edgeDashBonus * ((20 - catchCurrent.LastObject.DistanceToHyperDash) / 20) * Math.Pow((Math.Min(catchCurrent.StrainTime * catcherSpeedMultiplier, 265) / 265), 1.5); // Edge Dashes are easier at lower ms values
|
||||
}
|
||||
|
||||
lastPlayerPosition = playerPosition;
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Catch.Objects;
|
||||
using osu.Game.Rulesets.Catch.Replays;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Scoring;
|
||||
@@ -11,7 +10,7 @@ using osu.Game.Users;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Mods
|
||||
{
|
||||
public class CatchModAutoplay : ModAutoplay<CatchHitObject>
|
||||
public class CatchModAutoplay : ModAutoplay
|
||||
{
|
||||
public override Score CreateReplayScore(IBeatmap beatmap, IReadOnlyList<Mod> mods) => new Score
|
||||
{
|
||||
|
||||
@@ -10,7 +10,6 @@ namespace osu.Game.Rulesets.Catch.Mods
|
||||
public class CatchModHardRock : ModHardRock, IApplicableToBeatmap
|
||||
{
|
||||
public override double ScoreMultiplier => 1.12;
|
||||
public override bool Ranked => true;
|
||||
|
||||
public void ApplyToBeatmap(IBeatmap beatmap) => CatchBeatmapProcessor.ApplyPositionOffsets(beatmap, this);
|
||||
}
|
||||
|
||||
@@ -28,10 +28,11 @@ namespace osu.Game.Rulesets.Catch.Mods
|
||||
catchPlayfield.CatcherArea.MovableCatcher.CatchFruitOnPlate = false;
|
||||
}
|
||||
|
||||
protected override void ApplyIncreasedVisibilityState(DrawableHitObject hitObject, ArmedState state)
|
||||
=> ApplyNormalVisibilityState(hitObject, state);
|
||||
|
||||
protected override void ApplyNormalVisibilityState(DrawableHitObject hitObject, ArmedState state)
|
||||
{
|
||||
base.ApplyNormalVisibilityState(hitObject, state);
|
||||
|
||||
if (!(hitObject is DrawableCatchHitObject catchDrawable))
|
||||
return;
|
||||
|
||||
@@ -54,7 +55,7 @@ namespace osu.Game.Rulesets.Catch.Mods
|
||||
var offset = hitObject.TimePreempt * fade_out_offset_multiplier;
|
||||
var duration = offset - hitObject.TimePreempt * fade_out_duration_multiplier;
|
||||
|
||||
using (drawable.BeginAbsoluteSequence(hitObject.StartTime - offset, true))
|
||||
using (drawable.BeginAbsoluteSequence(hitObject.StartTime - offset))
|
||||
drawable.FadeOut(duration);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,13 +33,13 @@ namespace osu.Game.Rulesets.Catch.Mods
|
||||
|
||||
private class MouseInputHelper : Drawable, IKeyBindingHandler<CatchAction>, IRequireHighFrequencyMousePosition
|
||||
{
|
||||
private readonly Catcher catcher;
|
||||
private readonly CatcherArea catcherArea;
|
||||
|
||||
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true;
|
||||
|
||||
public MouseInputHelper(CatchPlayfield playfield)
|
||||
{
|
||||
catcher = playfield.CatcherArea.MovableCatcher;
|
||||
catcherArea = playfield.CatcherArea;
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace osu.Game.Rulesets.Catch.Mods
|
||||
|
||||
protected override bool OnMouseMove(MouseMoveEvent e)
|
||||
{
|
||||
catcher.UpdatePosition(e.MousePosition.X / DrawSize.X * CatchPlayfield.WIDTH);
|
||||
catcherArea.SetCatcherPosition(e.MousePosition.X / DrawSize.X * CatchPlayfield.WIDTH);
|
||||
return base.OnMouseMove(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Game.Rulesets.Catch.Skinning.Default;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Objects.Drawables
|
||||
@@ -9,21 +8,11 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables
|
||||
/// <summary>
|
||||
/// Represents a <see cref="Fruit"/> caught by the catcher.
|
||||
/// </summary>
|
||||
public class CaughtFruit : CaughtObject, IHasFruitState
|
||||
public class CaughtFruit : CaughtObject
|
||||
{
|
||||
public Bindable<FruitVisualRepresentation> VisualRepresentation { get; } = new Bindable<FruitVisualRepresentation>();
|
||||
|
||||
public CaughtFruit()
|
||||
: base(CatchSkinComponents.Fruit, _ => new FruitPiece())
|
||||
{
|
||||
}
|
||||
|
||||
public override void CopyStateFrom(IHasCatchObjectState objectState)
|
||||
{
|
||||
base.CopyStateFrom(objectState);
|
||||
|
||||
var fruitState = (IHasFruitState)objectState;
|
||||
VisualRepresentation.Value = fruitState.VisualRepresentation.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables
|
||||
public PalpableCatchHitObject HitObject { get; private set; }
|
||||
public Bindable<Color4> AccentColour { get; } = new Bindable<Color4>();
|
||||
public Bindable<bool> HyperDash { get; } = new Bindable<bool>();
|
||||
public Bindable<int> IndexInBeatmap { get; } = new Bindable<int>();
|
||||
|
||||
public Vector2 DisplaySize => Size * Scale;
|
||||
|
||||
@@ -51,6 +52,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables
|
||||
Rotation = objectState.DisplayRotation;
|
||||
AccentColour.Value = objectState.AccentColour.Value;
|
||||
HyperDash.Value = objectState.HyperDash.Value;
|
||||
IndexInBeatmap.Value = objectState.IndexInBeatmap.Value;
|
||||
}
|
||||
|
||||
protected override void FreeAfterUse()
|
||||
|
||||
@@ -3,17 +3,14 @@
|
||||
|
||||
using JetBrains.Annotations;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.Catch.Skinning.Default;
|
||||
using osu.Game.Skinning;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Objects.Drawables
|
||||
{
|
||||
public class DrawableFruit : DrawablePalpableCatchHitObject, IHasFruitState
|
||||
public class DrawableFruit : DrawablePalpableCatchHitObject
|
||||
{
|
||||
public Bindable<FruitVisualRepresentation> VisualRepresentation { get; } = new Bindable<FruitVisualRepresentation>();
|
||||
|
||||
public DrawableFruit()
|
||||
: this(null)
|
||||
{
|
||||
@@ -27,11 +24,6 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
IndexInBeatmap.BindValueChanged(change =>
|
||||
{
|
||||
VisualRepresentation.Value = (FruitVisualRepresentation)(change.NewValue % 4);
|
||||
}, true);
|
||||
|
||||
ScalingContainer.Child = new SkinnableDrawable(
|
||||
new CatchSkinComponent(CatchSkinComponents.Fruit),
|
||||
_ => new FruitPiece());
|
||||
@@ -44,12 +36,4 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables
|
||||
ScalingContainer.RotateTo((RandomSingle(1) - 0.5f) * 40);
|
||||
}
|
||||
}
|
||||
|
||||
public enum FruitVisualRepresentation
|
||||
{
|
||||
Pear,
|
||||
Grape,
|
||||
Pineapple,
|
||||
Raspberry,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables
|
||||
|
||||
Bindable<bool> HyperDash { get; }
|
||||
|
||||
Bindable<int> IndexInBeatmap { get; }
|
||||
|
||||
Vector2 DisplaySize { get; }
|
||||
|
||||
float DisplayRotation { get; }
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Bindables;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Objects.Drawables
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a visual state of a <see cref="Fruit"/>.
|
||||
/// </summary>
|
||||
public interface IHasFruitState : IHasCatchObjectState
|
||||
{
|
||||
Bindable<FruitVisualRepresentation> VisualRepresentation { get; }
|
||||
}
|
||||
}
|
||||
@@ -9,5 +9,7 @@ namespace osu.Game.Rulesets.Catch.Objects
|
||||
public class Fruit : PalpableCatchHitObject
|
||||
{
|
||||
public override Judgement CreateJudgement() => new CatchJudgement();
|
||||
|
||||
public static FruitVisualRepresentation GetVisualRepresentation(int indexInBeatmap) => (FruitVisualRepresentation)(indexInBeatmap % 4);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
// 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.Rulesets.Catch.Objects
|
||||
{
|
||||
public enum FruitVisualRepresentation
|
||||
{
|
||||
Pear,
|
||||
Grape,
|
||||
Pineapple,
|
||||
Raspberry,
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Scoring
|
||||
{
|
||||
public class CatchHitWindows : HitWindows
|
||||
{
|
||||
public override bool IsHitResultAllowed(HitResult result)
|
||||
{
|
||||
switch (result)
|
||||
{
|
||||
case HitResult.Great:
|
||||
case HitResult.Miss:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,7 @@ namespace osu.Game.Rulesets.Catch.Skinning.Default
|
||||
{
|
||||
public readonly Bindable<Color4> AccentColour = new Bindable<Color4>();
|
||||
public readonly Bindable<bool> HyperDash = new Bindable<bool>();
|
||||
public readonly Bindable<int> IndexInBeatmap = new Bindable<int>();
|
||||
|
||||
[Resolved]
|
||||
protected IHasCatchObjectState ObjectState { get; private set; }
|
||||
@@ -37,6 +38,7 @@ namespace osu.Game.Rulesets.Catch.Skinning.Default
|
||||
|
||||
AccentColour.BindTo(ObjectState.AccentColour);
|
||||
HyperDash.BindTo(ObjectState.HyperDash);
|
||||
IndexInBeatmap.BindTo(ObjectState.IndexInBeatmap);
|
||||
|
||||
HyperDash.BindValueChanged(hyper =>
|
||||
{
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Game.Rulesets.Catch.UI;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Skinning.Default
|
||||
{
|
||||
public class DefaultCatcher : CompositeDrawable
|
||||
{
|
||||
public Bindable<CatcherAnimationState> CurrentState { get; } = new Bindable<CatcherAnimationState>();
|
||||
|
||||
private readonly Sprite sprite;
|
||||
|
||||
private readonly Dictionary<CatcherAnimationState, Texture> textures = new Dictionary<CatcherAnimationState, Texture>();
|
||||
|
||||
public DefaultCatcher()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
InternalChild = sprite = new Sprite
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
FillMode = FillMode.Fit
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(TextureStore store, Bindable<CatcherAnimationState> currentState)
|
||||
{
|
||||
CurrentState.BindTo(currentState);
|
||||
|
||||
textures[CatcherAnimationState.Idle] = store.Get(@"Gameplay/catch/fruit-catcher-idle");
|
||||
textures[CatcherAnimationState.Fail] = store.Get(@"Gameplay/catch/fruit-catcher-fail");
|
||||
textures[CatcherAnimationState.Kiai] = store.Get(@"Gameplay/catch/fruit-catcher-kiai");
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
CurrentState.BindValueChanged(state => sprite.Texture = textures[state.NewValue], true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.Catch.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Catch.Objects;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Skinning.Default
|
||||
{
|
||||
@@ -39,8 +39,10 @@ namespace osu.Game.Rulesets.Catch.Skinning.Default
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
var fruitState = (IHasFruitState)ObjectState;
|
||||
VisualRepresentation.BindTo(fruitState.VisualRepresentation);
|
||||
IndexInBeatmap.BindValueChanged(index =>
|
||||
{
|
||||
VisualRepresentation.Value = Fruit.GetVisualRepresentation(index.NewValue);
|
||||
}, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Game.Rulesets.Catch.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Catch.Objects;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Skinning.Default
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Linq;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Screens.Play.HUD;
|
||||
using osu.Game.Skinning;
|
||||
using osuTK.Graphics;
|
||||
|
||||
@@ -22,59 +24,72 @@ namespace osu.Game.Rulesets.Catch.Skinning.Legacy
|
||||
|
||||
public override Drawable GetDrawableComponent(ISkinComponent component)
|
||||
{
|
||||
if (component is HUDSkinComponent hudComponent)
|
||||
if (component is SkinnableTargetComponent targetComponent)
|
||||
{
|
||||
switch (hudComponent.Component)
|
||||
switch (targetComponent.Target)
|
||||
{
|
||||
case HUDSkinComponents.ComboCounter:
|
||||
// catch may provide its own combo counter; hide the default.
|
||||
return providesComboCounter ? Drawable.Empty() : null;
|
||||
case SkinnableTarget.MainHUDComponents:
|
||||
var components = Source.GetDrawableComponent(component) as SkinnableTargetComponentsContainer;
|
||||
|
||||
if (providesComboCounter && components != null)
|
||||
{
|
||||
// catch may provide its own combo counter; hide the default.
|
||||
// todo: this should be done in an elegant way per ruleset, defining which HUD skin components should be displayed.
|
||||
foreach (var legacyComboCounter in components.OfType<LegacyComboCounter>())
|
||||
legacyComboCounter.HiddenByRulesetImplementation = false;
|
||||
}
|
||||
|
||||
return components;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(component is CatchSkinComponent catchSkinComponent))
|
||||
return null;
|
||||
|
||||
switch (catchSkinComponent.Component)
|
||||
if (component is CatchSkinComponent catchSkinComponent)
|
||||
{
|
||||
case CatchSkinComponents.Fruit:
|
||||
if (GetTexture("fruit-pear") != null)
|
||||
return new LegacyFruitPiece();
|
||||
switch (catchSkinComponent.Component)
|
||||
{
|
||||
case CatchSkinComponents.Fruit:
|
||||
if (GetTexture("fruit-pear") != null)
|
||||
return new LegacyFruitPiece();
|
||||
|
||||
break;
|
||||
return null;
|
||||
|
||||
case CatchSkinComponents.Banana:
|
||||
if (GetTexture("fruit-bananas") != null)
|
||||
return new LegacyBananaPiece();
|
||||
case CatchSkinComponents.Banana:
|
||||
if (GetTexture("fruit-bananas") != null)
|
||||
return new LegacyBananaPiece();
|
||||
|
||||
break;
|
||||
return null;
|
||||
|
||||
case CatchSkinComponents.Droplet:
|
||||
if (GetTexture("fruit-drop") != null)
|
||||
return new LegacyDropletPiece();
|
||||
case CatchSkinComponents.Droplet:
|
||||
if (GetTexture("fruit-drop") != null)
|
||||
return new LegacyDropletPiece();
|
||||
|
||||
break;
|
||||
return null;
|
||||
|
||||
case CatchSkinComponents.CatcherIdle:
|
||||
return this.GetAnimation("fruit-catcher-idle", true, true, true) ??
|
||||
this.GetAnimation("fruit-ryuuta", true, true, true);
|
||||
case CatchSkinComponents.Catcher:
|
||||
var version = Source.GetConfig<LegacySkinConfiguration.LegacySetting, decimal>(LegacySkinConfiguration.LegacySetting.Version)?.Value ?? 1;
|
||||
|
||||
case CatchSkinComponents.CatcherFail:
|
||||
return this.GetAnimation("fruit-catcher-fail", true, true, true) ??
|
||||
this.GetAnimation("fruit-ryuuta", true, true, true);
|
||||
if (version < 2.3m)
|
||||
{
|
||||
if (GetTexture(@"fruit-ryuuta") != null ||
|
||||
GetTexture(@"fruit-ryuuta-0") != null)
|
||||
return new LegacyCatcherOld();
|
||||
}
|
||||
|
||||
case CatchSkinComponents.CatcherKiai:
|
||||
return this.GetAnimation("fruit-catcher-kiai", true, true, true) ??
|
||||
this.GetAnimation("fruit-ryuuta", true, true, true);
|
||||
if (GetTexture(@"fruit-catcher-idle") != null ||
|
||||
GetTexture(@"fruit-catcher-idle-0") != null)
|
||||
return new LegacyCatcherNew();
|
||||
|
||||
case CatchSkinComponents.CatchComboCounter:
|
||||
if (providesComboCounter)
|
||||
return new LegacyCatchComboCounter(Source);
|
||||
return null;
|
||||
|
||||
break;
|
||||
case CatchSkinComponents.CatchComboCounter:
|
||||
if (providesComboCounter)
|
||||
return new LegacyCatchComboCounter(Source);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return Source.GetDrawableComponent(component);
|
||||
}
|
||||
|
||||
public override IBindable<TValue> GetConfig<TLookup, TValue>(TLookup lookup)
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
|
||||
using osu.Framework.Graphics.Textures;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Skinning
|
||||
namespace osu.Game.Rulesets.Catch.Skinning.Legacy
|
||||
{
|
||||
public class LegacyBananaPiece : LegacyCatchHitObjectPiece
|
||||
{
|
||||
+3
-1
@@ -13,12 +13,13 @@ using osu.Game.Skinning;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Skinning
|
||||
namespace osu.Game.Rulesets.Catch.Skinning.Legacy
|
||||
{
|
||||
public abstract class LegacyCatchHitObjectPiece : PoolableDrawable
|
||||
{
|
||||
public readonly Bindable<Color4> AccentColour = new Bindable<Color4>();
|
||||
public readonly Bindable<bool> HyperDash = new Bindable<bool>();
|
||||
public readonly Bindable<int> IndexInBeatmap = new Bindable<int>();
|
||||
|
||||
private readonly Sprite colouredSprite;
|
||||
private readonly Sprite overlaySprite;
|
||||
@@ -64,6 +65,7 @@ namespace osu.Game.Rulesets.Catch.Skinning
|
||||
|
||||
AccentColour.BindTo(ObjectState.AccentColour);
|
||||
HyperDash.BindTo(ObjectState.HyperDash);
|
||||
IndexInBeatmap.BindTo(ObjectState.IndexInBeatmap);
|
||||
|
||||
hyperSprite.Colour = Skin.GetConfig<CatchSkinColour, Color4>(CatchSkinColour.HyperDashFruit)?.Value ??
|
||||
Skin.GetConfig<CatchSkinColour, Color4>(CatchSkinColour.HyperDash)?.Value ??
|
||||
@@ -0,0 +1,69 @@
|
||||
// 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 System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Animations;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Rulesets.Catch.UI;
|
||||
using osu.Game.Skinning;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Skinning.Legacy
|
||||
{
|
||||
public class LegacyCatcherNew : CompositeDrawable
|
||||
{
|
||||
[Resolved]
|
||||
private Bindable<CatcherAnimationState> currentState { get; set; }
|
||||
|
||||
private readonly Dictionary<CatcherAnimationState, Drawable> drawables = new Dictionary<CatcherAnimationState, Drawable>();
|
||||
|
||||
private Drawable currentDrawable;
|
||||
|
||||
public LegacyCatcherNew()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(ISkinSource skin)
|
||||
{
|
||||
foreach (var state in Enum.GetValues(typeof(CatcherAnimationState)).Cast<CatcherAnimationState>())
|
||||
{
|
||||
AddInternal(drawables[state] = getDrawableFor(state).With(d =>
|
||||
{
|
||||
d.Anchor = Anchor.TopCentre;
|
||||
d.Origin = Anchor.TopCentre;
|
||||
d.RelativeSizeAxes = Axes.Both;
|
||||
d.Size = Vector2.One;
|
||||
d.FillMode = FillMode.Fit;
|
||||
d.Alpha = 0;
|
||||
}));
|
||||
}
|
||||
|
||||
currentDrawable = drawables[CatcherAnimationState.Idle];
|
||||
|
||||
Drawable getDrawableFor(CatcherAnimationState state) =>
|
||||
skin.GetAnimation(@$"fruit-catcher-{state.ToString().ToLowerInvariant()}", true, true, true) ??
|
||||
skin.GetAnimation(@"fruit-catcher-idle", true, true, true);
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
currentState.BindValueChanged(state =>
|
||||
{
|
||||
currentDrawable.Alpha = 0;
|
||||
currentDrawable = drawables[state.NewValue];
|
||||
currentDrawable.Alpha = 1;
|
||||
|
||||
(currentDrawable as IFramedAnimation)?.GotoFrame(0);
|
||||
}, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Skinning;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Skinning.Legacy
|
||||
{
|
||||
public class LegacyCatcherOld : CompositeDrawable
|
||||
{
|
||||
public LegacyCatcherOld()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(ISkinSource skin)
|
||||
{
|
||||
InternalChild = skin.GetAnimation(@"fruit-ryuuta", true, true, true).With(d =>
|
||||
{
|
||||
d.Anchor = Anchor.TopCentre;
|
||||
d.Origin = Anchor.TopCentre;
|
||||
d.RelativeSizeAxes = Axes.Both;
|
||||
d.Size = Vector2.One;
|
||||
d.FillMode = FillMode.Fit;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Skinning
|
||||
namespace osu.Game.Rulesets.Catch.Skinning.Legacy
|
||||
{
|
||||
public class LegacyDropletPiece : LegacyCatchHitObjectPiece
|
||||
{
|
||||
@@ -1,23 +1,20 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Game.Rulesets.Catch.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Catch.Objects;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Skinning.Legacy
|
||||
{
|
||||
internal class LegacyFruitPiece : LegacyCatchHitObjectPiece
|
||||
{
|
||||
public readonly Bindable<FruitVisualRepresentation> VisualRepresentation = new Bindable<FruitVisualRepresentation>();
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
var fruitState = (IHasFruitState)ObjectState;
|
||||
VisualRepresentation.BindTo(fruitState.VisualRepresentation);
|
||||
|
||||
VisualRepresentation.BindValueChanged(visual => setTexture(visual.NewValue), true);
|
||||
IndexInBeatmap.BindValueChanged(index =>
|
||||
{
|
||||
setTexture(Fruit.GetVisualRepresentation(index.NewValue));
|
||||
}, true);
|
||||
}
|
||||
|
||||
private void setTexture(FruitVisualRepresentation visualRepresentation)
|
||||
|
||||
@@ -25,9 +25,9 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
{
|
||||
}
|
||||
|
||||
protected override void SkinChanged(ISkinSource skin, bool allowFallback)
|
||||
protected override void SkinChanged(ISkinSource skin)
|
||||
{
|
||||
base.SkinChanged(skin, allowFallback);
|
||||
base.SkinChanged(skin);
|
||||
ComboCounter?.UpdateCombo(currentCombo);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,10 +7,8 @@ using JetBrains.Annotations;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Animations;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Pooling;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Configuration;
|
||||
@@ -25,7 +23,7 @@ using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.UI
|
||||
{
|
||||
public class Catcher : SkinReloadableDrawable, IKeyBindingHandler<CatchAction>
|
||||
public class Catcher : SkinReloadableDrawable
|
||||
{
|
||||
/// <summary>
|
||||
/// The default colour used to tint hyper-dash fruit, along with the moving catcher, its trail
|
||||
@@ -53,6 +51,11 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
/// </summary>
|
||||
public const double BASE_SPEED = 1.0;
|
||||
|
||||
/// <summary>
|
||||
/// The current speed of the catcher.
|
||||
/// </summary>
|
||||
public double Speed => (Dashing ? 1 : 0.5) * BASE_SPEED * hyperDashModifier;
|
||||
|
||||
/// <summary>
|
||||
/// The amount by which caught fruit should be offset from the plate surface to make them look visually "caught".
|
||||
/// </summary>
|
||||
@@ -78,24 +81,23 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
/// </summary>
|
||||
private readonly Container<CaughtObject> droppedObjectTarget;
|
||||
|
||||
public CatcherAnimationState CurrentState { get; private set; }
|
||||
public CatcherAnimationState CurrentState
|
||||
{
|
||||
get => body.AnimationState.Value;
|
||||
private set => body.AnimationState.Value = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The width of the catcher which can receive fruit. Equivalent to "catchMargin" in osu-stable.
|
||||
/// </summary>
|
||||
public const float ALLOWED_CATCH_RANGE = 0.8f;
|
||||
|
||||
/// <summary>
|
||||
/// The drawable catcher for <see cref="CurrentState"/>.
|
||||
/// </summary>
|
||||
internal Drawable CurrentDrawableCatcher => currentCatcher.Drawable;
|
||||
|
||||
private bool dashing;
|
||||
|
||||
public bool Dashing
|
||||
{
|
||||
get => dashing;
|
||||
protected set
|
||||
set
|
||||
{
|
||||
if (value == dashing) return;
|
||||
|
||||
@@ -105,29 +107,28 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
}
|
||||
}
|
||||
|
||||
public Direction VisualDirection
|
||||
{
|
||||
get => Scale.X > 0 ? Direction.Right : Direction.Left;
|
||||
set => Scale = new Vector2((value == Direction.Right ? 1 : -1) * Math.Abs(Scale.X), Scale.Y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Width of the area that can be used to attempt catches during gameplay.
|
||||
/// </summary>
|
||||
private readonly float catchWidth;
|
||||
|
||||
private readonly CatcherSprite catcherIdle;
|
||||
private readonly CatcherSprite catcherKiai;
|
||||
private readonly CatcherSprite catcherFail;
|
||||
|
||||
private CatcherSprite currentCatcher;
|
||||
private readonly SkinnableCatcher body;
|
||||
|
||||
private Color4 hyperDashColour = DEFAULT_HYPER_DASH_COLOUR;
|
||||
private Color4 hyperDashEndGlowColour = DEFAULT_HYPER_DASH_COLOUR;
|
||||
|
||||
private int currentDirection;
|
||||
|
||||
private double hyperDashModifier = 1;
|
||||
private int hyperDashDirection;
|
||||
private float hyperDashTargetPosition;
|
||||
private Bindable<bool> hitLighting;
|
||||
|
||||
private readonly DrawablePool<HitExplosion> hitExplosionPool;
|
||||
private readonly Container<HitExplosion> hitExplosionContainer;
|
||||
private readonly HitExplosionContainer hitExplosionContainer;
|
||||
|
||||
private readonly DrawablePool<CaughtFruit> caughtFruitPool;
|
||||
private readonly DrawablePool<CaughtBanana> caughtBananaPool;
|
||||
@@ -148,7 +149,6 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
hitExplosionPool = new DrawablePool<HitExplosion>(10),
|
||||
caughtFruitPool = new DrawablePool<CaughtFruit>(50),
|
||||
caughtBananaPool = new DrawablePool<CaughtBanana>(100),
|
||||
// less capacity is needed compared to fruit because droplet is not stacked
|
||||
@@ -158,22 +158,8 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.BottomCentre,
|
||||
},
|
||||
catcherIdle = new CatcherSprite(CatcherAnimationState.Idle)
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Alpha = 0,
|
||||
},
|
||||
catcherKiai = new CatcherSprite(CatcherAnimationState.Kiai)
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Alpha = 0,
|
||||
},
|
||||
catcherFail = new CatcherSprite(CatcherAnimationState.Fail)
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Alpha = 0,
|
||||
},
|
||||
hitExplosionContainer = new Container<HitExplosion>
|
||||
body = new SkinnableCatcher(),
|
||||
hitExplosionContainer = new HitExplosionContainer
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.BottomCentre,
|
||||
@@ -186,8 +172,6 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
{
|
||||
hitLighting = config.GetBindable<bool>(OsuSetting.HitLighting);
|
||||
trails = new CatcherTrailDisplay(this);
|
||||
|
||||
updateCatcher();
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
@@ -275,17 +259,16 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
SetHyperDashState();
|
||||
|
||||
if (result.IsHit)
|
||||
updateState(hitObject.Kiai ? CatcherAnimationState.Kiai : CatcherAnimationState.Idle);
|
||||
CurrentState = hitObject.Kiai ? CatcherAnimationState.Kiai : CatcherAnimationState.Idle;
|
||||
else if (!(hitObject is Banana))
|
||||
updateState(CatcherAnimationState.Fail);
|
||||
CurrentState = CatcherAnimationState.Fail;
|
||||
}
|
||||
|
||||
public void OnRevertResult(DrawableCatchHitObject drawableObject, JudgementResult result)
|
||||
{
|
||||
var catchResult = (CatchJudgementResult)result;
|
||||
|
||||
if (CurrentState != catchResult.CatcherAnimationState)
|
||||
updateState(catchResult.CatcherAnimationState);
|
||||
CurrentState = catchResult.CatcherAnimationState;
|
||||
|
||||
if (HyperDashing != catchResult.CatcherHyperDash)
|
||||
{
|
||||
@@ -297,7 +280,6 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
|
||||
caughtObjectContainer.RemoveAll(d => d.HitObject == drawableObject.HitObject);
|
||||
droppedObjectTarget.RemoveAll(d => d.HitObject == drawableObject.HitObject);
|
||||
hitExplosionContainer.RemoveAll(d => d.HitObject == drawableObject.HitObject);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -331,55 +313,6 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdatePosition(float position)
|
||||
{
|
||||
position = Math.Clamp(position, 0, CatchPlayfield.WIDTH);
|
||||
|
||||
if (position == X)
|
||||
return;
|
||||
|
||||
Scale = new Vector2(Math.Abs(Scale.X) * (position > X ? 1 : -1), Scale.Y);
|
||||
X = position;
|
||||
}
|
||||
|
||||
public bool OnPressed(CatchAction action)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case CatchAction.MoveLeft:
|
||||
currentDirection--;
|
||||
return true;
|
||||
|
||||
case CatchAction.MoveRight:
|
||||
currentDirection++;
|
||||
return true;
|
||||
|
||||
case CatchAction.Dash:
|
||||
Dashing = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void OnReleased(CatchAction action)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case CatchAction.MoveLeft:
|
||||
currentDirection++;
|
||||
break;
|
||||
|
||||
case CatchAction.MoveRight:
|
||||
currentDirection--;
|
||||
break;
|
||||
|
||||
case CatchAction.Dash:
|
||||
Dashing = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Drop any fruit off the plate.
|
||||
/// </summary>
|
||||
@@ -399,9 +332,9 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
|
||||
private void updateTrailVisibility() => trails.DisplayTrail = Dashing || HyperDashing;
|
||||
|
||||
protected override void SkinChanged(ISkinSource skin, bool allowFallback)
|
||||
protected override void SkinChanged(ISkinSource skin)
|
||||
{
|
||||
base.SkinChanged(skin, allowFallback);
|
||||
base.SkinChanged(skin);
|
||||
|
||||
hyperDashColour =
|
||||
skin.GetConfig<CatchSkinColour, Color4>(CatchSkinColour.HyperDash)?.Value ??
|
||||
@@ -421,15 +354,6 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
{
|
||||
base.Update();
|
||||
|
||||
if (currentDirection == 0) return;
|
||||
|
||||
var direction = Math.Sign(currentDirection);
|
||||
|
||||
var dashModifier = Dashing ? 1 : 0.5;
|
||||
var speed = BASE_SPEED * dashModifier * hyperDashModifier;
|
||||
|
||||
UpdatePosition((float)(X + direction * Clock.ElapsedFrameTime * speed));
|
||||
|
||||
// Correct overshooting.
|
||||
if ((hyperDashDirection > 0 && hyperDashTargetPosition < X) ||
|
||||
(hyperDashDirection < 0 && hyperDashTargetPosition > X))
|
||||
@@ -439,38 +363,6 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
}
|
||||
}
|
||||
|
||||
private void updateCatcher()
|
||||
{
|
||||
currentCatcher?.Hide();
|
||||
|
||||
switch (CurrentState)
|
||||
{
|
||||
default:
|
||||
currentCatcher = catcherIdle;
|
||||
break;
|
||||
|
||||
case CatcherAnimationState.Fail:
|
||||
currentCatcher = catcherFail;
|
||||
break;
|
||||
|
||||
case CatcherAnimationState.Kiai:
|
||||
currentCatcher = catcherKiai;
|
||||
break;
|
||||
}
|
||||
|
||||
currentCatcher.Show();
|
||||
(currentCatcher.Drawable as IFramedAnimation)?.GotoFrame(0);
|
||||
}
|
||||
|
||||
private void updateState(CatcherAnimationState state)
|
||||
{
|
||||
if (CurrentState == state)
|
||||
return;
|
||||
|
||||
CurrentState = state;
|
||||
updateCatcher();
|
||||
}
|
||||
|
||||
private void placeCaughtObject(DrawablePalpableCatchHitObject drawableObject, Vector2 position)
|
||||
{
|
||||
var caughtObject = getCaughtObject(drawableObject.HitObject);
|
||||
@@ -508,15 +400,8 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
return position;
|
||||
}
|
||||
|
||||
private void addLighting(CatchHitObject hitObject, float x, Color4 colour)
|
||||
{
|
||||
HitExplosion hitExplosion = hitExplosionPool.Get();
|
||||
hitExplosion.HitObject = hitObject;
|
||||
hitExplosion.X = x;
|
||||
hitExplosion.Scale = new Vector2(hitObject.Scale);
|
||||
hitExplosion.ObjectColour = colour;
|
||||
hitExplosionContainer.Add(hitExplosion);
|
||||
}
|
||||
private void addLighting(CatchHitObject hitObject, float x, Color4 colour) =>
|
||||
hitExplosionContainer.Add(new HitExplosionEntry(Time.Current, x, hitObject.Scale, colour, hitObject.RandomSeed));
|
||||
|
||||
private CaughtObject getCaughtObject(PalpableCatchHitObject source)
|
||||
{
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Catch.Judgements;
|
||||
using osu.Game.Rulesets.Catch.Objects.Drawables;
|
||||
@@ -14,13 +16,20 @@ using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.UI
|
||||
{
|
||||
public class CatcherArea : Container
|
||||
public class CatcherArea : Container, IKeyBindingHandler<CatchAction>
|
||||
{
|
||||
public const float CATCHER_SIZE = 106.75f;
|
||||
|
||||
public readonly Catcher MovableCatcher;
|
||||
private readonly CatchComboDisplay comboDisplay;
|
||||
|
||||
/// <summary>
|
||||
/// <c>-1</c> when only left button is pressed.
|
||||
/// <c>1</c> when only right button is pressed.
|
||||
/// <c>0</c> when none or both left and right buttons are pressed.
|
||||
/// </summary>
|
||||
private int currentDirection;
|
||||
|
||||
public CatcherArea(Container<CaughtObject> droppedObjectContainer, BeatmapDifficulty difficulty = null)
|
||||
{
|
||||
Size = new Vector2(CatchPlayfield.WIDTH, CATCHER_SIZE);
|
||||
@@ -63,16 +72,73 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
MovableCatcher.OnRevertResult(hitObject, result);
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
var replayState = (GetContainingInputManager().CurrentState as RulesetInputManagerInputState<CatchAction>)?.LastReplayState as CatchFramedReplayInputHandler.CatchReplayState;
|
||||
|
||||
SetCatcherPosition(
|
||||
replayState?.CatcherX ??
|
||||
(float)(MovableCatcher.X + MovableCatcher.Speed * currentDirection * Clock.ElapsedFrameTime));
|
||||
}
|
||||
|
||||
protected override void UpdateAfterChildren()
|
||||
{
|
||||
base.UpdateAfterChildren();
|
||||
|
||||
var state = (GetContainingInputManager().CurrentState as RulesetInputManagerInputState<CatchAction>)?.LastReplayState as CatchFramedReplayInputHandler.CatchReplayState;
|
||||
|
||||
if (state?.CatcherX != null)
|
||||
MovableCatcher.X = state.CatcherX.Value;
|
||||
|
||||
comboDisplay.X = MovableCatcher.X;
|
||||
}
|
||||
|
||||
public void SetCatcherPosition(float X)
|
||||
{
|
||||
float lastPosition = MovableCatcher.X;
|
||||
float newPosition = Math.Clamp(X, 0, CatchPlayfield.WIDTH);
|
||||
|
||||
MovableCatcher.X = newPosition;
|
||||
|
||||
if (lastPosition < newPosition)
|
||||
MovableCatcher.VisualDirection = Direction.Right;
|
||||
else if (lastPosition > newPosition)
|
||||
MovableCatcher.VisualDirection = Direction.Left;
|
||||
}
|
||||
|
||||
public bool OnPressed(CatchAction action)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case CatchAction.MoveLeft:
|
||||
currentDirection--;
|
||||
return true;
|
||||
|
||||
case CatchAction.MoveRight:
|
||||
currentDirection++;
|
||||
return true;
|
||||
|
||||
case CatchAction.Dash:
|
||||
MovableCatcher.Dashing = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void OnReleased(CatchAction action)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case CatchAction.MoveLeft:
|
||||
currentDirection++;
|
||||
break;
|
||||
|
||||
case CatchAction.MoveRight:
|
||||
currentDirection--;
|
||||
break;
|
||||
|
||||
case CatchAction.Dash:
|
||||
MovableCatcher.Dashing = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Game.Skinning;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.UI
|
||||
{
|
||||
public class CatcherSprite : SkinnableDrawable
|
||||
{
|
||||
protected override bool ApplySizeRestrictionsToDefault => true;
|
||||
|
||||
public CatcherSprite(CatcherAnimationState state)
|
||||
: base(new CatchSkinComponent(componentFromState(state)), _ =>
|
||||
new DefaultCatcherSprite(state), confineMode: ConfineMode.ScaleToFit)
|
||||
{
|
||||
RelativeSizeAxes = Axes.None;
|
||||
Size = new Vector2(CatcherArea.CATCHER_SIZE);
|
||||
|
||||
// Sets the origin roughly to the centre of the catcher's plate to allow for correct scaling.
|
||||
OriginPosition = new Vector2(0.5f, 0.06f) * CatcherArea.CATCHER_SIZE;
|
||||
}
|
||||
|
||||
private static CatchSkinComponents componentFromState(CatcherAnimationState state)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case CatcherAnimationState.Fail:
|
||||
return CatchSkinComponents.CatcherFail;
|
||||
|
||||
case CatcherAnimationState.Kiai:
|
||||
return CatchSkinComponents.CatcherKiai;
|
||||
|
||||
default:
|
||||
return CatchSkinComponents.CatcherIdle;
|
||||
}
|
||||
}
|
||||
|
||||
private class DefaultCatcherSprite : Sprite
|
||||
{
|
||||
private readonly CatcherAnimationState state;
|
||||
|
||||
public DefaultCatcherSprite(CatcherAnimationState state)
|
||||
{
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(TextureStore textures)
|
||||
{
|
||||
Texture = textures.Get($"Gameplay/catch/fruit-catcher-{state.ToString().ToLower()}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Pooling;
|
||||
using osu.Framework.Timing;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.UI
|
||||
{
|
||||
/// <summary>
|
||||
/// A trail of the catcher.
|
||||
/// It also represents a hyper dash afterimage.
|
||||
/// </summary>
|
||||
public class CatcherTrail : PoolableDrawable
|
||||
{
|
||||
public CatcherAnimationState AnimationState
|
||||
{
|
||||
set => body.AnimationState.Value = value;
|
||||
}
|
||||
|
||||
private readonly SkinnableCatcher body;
|
||||
|
||||
public CatcherTrail()
|
||||
{
|
||||
Size = new Vector2(CatcherArea.CATCHER_SIZE);
|
||||
Origin = Anchor.TopCentre;
|
||||
Blending = BlendingParameters.Additive;
|
||||
InternalChild = body = new SkinnableCatcher
|
||||
{
|
||||
// Using a frozen clock because trails should not be animated when the skin has an animated catcher.
|
||||
// TODO: The animation should be frozen at the animation frame at the time of the trail generation.
|
||||
Clock = new FramedClock(new ManualClock()),
|
||||
};
|
||||
}
|
||||
|
||||
protected override void FreeAfterUse()
|
||||
{
|
||||
ClearTransforms();
|
||||
base.FreeAfterUse();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,10 +4,8 @@
|
||||
using System;
|
||||
using JetBrains.Annotations;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Animations;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Pooling;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
@@ -21,11 +19,11 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
{
|
||||
private readonly Catcher catcher;
|
||||
|
||||
private readonly DrawablePool<CatcherTrailSprite> trailPool;
|
||||
private readonly DrawablePool<CatcherTrail> trailPool;
|
||||
|
||||
private readonly Container<CatcherTrailSprite> dashTrails;
|
||||
private readonly Container<CatcherTrailSprite> hyperDashTrails;
|
||||
private readonly Container<CatcherTrailSprite> endGlowSprites;
|
||||
private readonly Container<CatcherTrail> dashTrails;
|
||||
private readonly Container<CatcherTrail> hyperDashTrails;
|
||||
private readonly Container<CatcherTrail> endGlowSprites;
|
||||
|
||||
private Color4 hyperDashTrailsColour = Catcher.DEFAULT_HYPER_DASH_COLOUR;
|
||||
|
||||
@@ -85,10 +83,10 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
trailPool = new DrawablePool<CatcherTrailSprite>(30),
|
||||
dashTrails = new Container<CatcherTrailSprite> { RelativeSizeAxes = Axes.Both },
|
||||
hyperDashTrails = new Container<CatcherTrailSprite> { RelativeSizeAxes = Axes.Both, Colour = Catcher.DEFAULT_HYPER_DASH_COLOUR },
|
||||
endGlowSprites = new Container<CatcherTrailSprite> { RelativeSizeAxes = Axes.Both, Colour = Catcher.DEFAULT_HYPER_DASH_COLOUR },
|
||||
trailPool = new DrawablePool<CatcherTrail>(30),
|
||||
dashTrails = new Container<CatcherTrail> { RelativeSizeAxes = Axes.Both },
|
||||
hyperDashTrails = new Container<CatcherTrail> { RelativeSizeAxes = Axes.Both, Colour = Catcher.DEFAULT_HYPER_DASH_COLOUR },
|
||||
endGlowSprites = new Container<CatcherTrail> { RelativeSizeAxes = Axes.Both, Colour = Catcher.DEFAULT_HYPER_DASH_COLOUR },
|
||||
};
|
||||
}
|
||||
|
||||
@@ -118,17 +116,12 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
Scheduler.AddDelayed(displayTrail, catcher.HyperDashing ? 25 : 50);
|
||||
}
|
||||
|
||||
private CatcherTrailSprite createTrailSprite(Container<CatcherTrailSprite> target)
|
||||
private CatcherTrail createTrailSprite(Container<CatcherTrail> target)
|
||||
{
|
||||
var texture = (catcher.CurrentDrawableCatcher as TextureAnimation)?.CurrentFrame ?? ((Sprite)catcher.CurrentDrawableCatcher).Texture;
|
||||
CatcherTrail sprite = trailPool.Get();
|
||||
|
||||
CatcherTrailSprite sprite = trailPool.Get();
|
||||
|
||||
sprite.Texture = texture;
|
||||
sprite.Anchor = catcher.Anchor;
|
||||
sprite.AnimationState = catcher.CurrentState;
|
||||
sprite.Scale = catcher.Scale;
|
||||
sprite.Blending = BlendingParameters.Additive;
|
||||
sprite.RelativePositionAxes = catcher.RelativePositionAxes;
|
||||
sprite.Position = catcher.Position;
|
||||
|
||||
target.Add(sprite);
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Pooling;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.UI
|
||||
{
|
||||
public class CatcherTrailSprite : PoolableDrawable
|
||||
{
|
||||
public Texture Texture
|
||||
{
|
||||
set => sprite.Texture = value;
|
||||
}
|
||||
|
||||
private readonly Sprite sprite;
|
||||
|
||||
public CatcherTrailSprite()
|
||||
{
|
||||
InternalChild = sprite = new Sprite
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both
|
||||
};
|
||||
|
||||
Size = new Vector2(CatcherArea.CATCHER_SIZE);
|
||||
|
||||
// Sets the origin roughly to the centre of the catcher's plate to allow for correct scaling.
|
||||
OriginPosition = new Vector2(0.5f, 0.06f) * CatcherArea.CATCHER_SIZE;
|
||||
}
|
||||
|
||||
protected override void FreeAfterUse()
|
||||
{
|
||||
ClearTransforms();
|
||||
base.FreeAfterUse();
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -1,11 +1,11 @@
|
||||
// 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.Rulesets.Mania.Edit.Blueprints
|
||||
namespace osu.Game.Rulesets.Catch.UI
|
||||
{
|
||||
public enum HoldNotePosition
|
||||
public enum Direction
|
||||
{
|
||||
Start,
|
||||
End
|
||||
Right = 1,
|
||||
Left = -1
|
||||
}
|
||||
}
|
||||
@@ -5,31 +5,16 @@ using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Effects;
|
||||
using osu.Framework.Graphics.Pooling;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Rulesets.Catch.Objects;
|
||||
using osu.Game.Rulesets.Objects.Pooling;
|
||||
using osu.Game.Utils;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.UI
|
||||
{
|
||||
public class HitExplosion : PoolableDrawable
|
||||
public class HitExplosion : PoolableDrawableWithLifetime<HitExplosionEntry>
|
||||
{
|
||||
private Color4 objectColour;
|
||||
public CatchHitObject HitObject;
|
||||
|
||||
public Color4 ObjectColour
|
||||
{
|
||||
get => objectColour;
|
||||
set
|
||||
{
|
||||
if (objectColour == value) return;
|
||||
|
||||
objectColour = value;
|
||||
onColourChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private readonly CircularContainer largeFaint;
|
||||
private readonly CircularContainer smallFaint;
|
||||
private readonly CircularContainer directionalGlow1;
|
||||
@@ -83,9 +68,19 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
};
|
||||
}
|
||||
|
||||
protected override void PrepareForUse()
|
||||
protected override void OnApply(HitExplosionEntry entry)
|
||||
{
|
||||
base.PrepareForUse();
|
||||
X = entry.Position;
|
||||
Scale = new Vector2(entry.Scale);
|
||||
setColour(entry.ObjectColour);
|
||||
|
||||
using (BeginAbsoluteSequence(entry.LifetimeStart))
|
||||
applyTransforms(entry.RNGSeed);
|
||||
}
|
||||
|
||||
private void applyTransforms(int randomSeed)
|
||||
{
|
||||
ClearTransforms(true);
|
||||
|
||||
const double duration = 400;
|
||||
|
||||
@@ -96,14 +91,13 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
.FadeOut(duration * 2);
|
||||
|
||||
const float angle_variangle = 15; // should be less than 45
|
||||
directionalGlow1.Rotation = RNG.NextSingle(-angle_variangle, angle_variangle);
|
||||
directionalGlow2.Rotation = RNG.NextSingle(-angle_variangle, angle_variangle);
|
||||
directionalGlow1.Rotation = StatelessRNG.NextSingle(-angle_variangle, angle_variangle, randomSeed, 4);
|
||||
directionalGlow2.Rotation = StatelessRNG.NextSingle(-angle_variangle, angle_variangle, randomSeed, 5);
|
||||
|
||||
this.FadeInFromZero(50).Then().FadeOut(duration, Easing.Out);
|
||||
Expire(true);
|
||||
this.FadeInFromZero(50).Then().FadeOut(duration, Easing.Out).Expire();
|
||||
}
|
||||
|
||||
private void onColourChanged()
|
||||
private void setColour(Color4 objectColour)
|
||||
{
|
||||
const float roundness = 100;
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Graphics.Pooling;
|
||||
using osu.Game.Rulesets.Objects.Pooling;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.UI
|
||||
{
|
||||
public class HitExplosionContainer : PooledDrawableWithLifetimeContainer<HitExplosionEntry, HitExplosion>
|
||||
{
|
||||
protected override bool RemoveRewoundEntry => true;
|
||||
|
||||
private readonly DrawablePool<HitExplosion> pool;
|
||||
|
||||
public HitExplosionContainer()
|
||||
{
|
||||
AddInternal(pool = new DrawablePool<HitExplosion>(10));
|
||||
}
|
||||
|
||||
protected override HitExplosion GetDrawable(HitExplosionEntry entry) => pool.Get(d => d.Apply(entry));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Graphics.Performance;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.UI
|
||||
{
|
||||
public class HitExplosionEntry : LifetimeEntry
|
||||
{
|
||||
public readonly float Position;
|
||||
public readonly float Scale;
|
||||
public readonly Color4 ObjectColour;
|
||||
public readonly int RNGSeed;
|
||||
|
||||
public HitExplosionEntry(double startTime, float position, float scale, Color4 objectColour, int rngSeed)
|
||||
{
|
||||
LifetimeStart = startTime;
|
||||
Position = position;
|
||||
Scale = scale;
|
||||
ObjectColour = objectColour;
|
||||
RNGSeed = rngSeed;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.Catch.Skinning.Default;
|
||||
using osu.Game.Skinning;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.UI
|
||||
{
|
||||
/// <summary>
|
||||
/// The visual representation of the <see cref="Catcher"/>.
|
||||
/// It includes the body part of the catcher and the catcher plate.
|
||||
/// </summary>
|
||||
public class SkinnableCatcher : SkinnableDrawable
|
||||
{
|
||||
/// <summary>
|
||||
/// This is used by skin elements to determine which texture of the catcher is used.
|
||||
/// </summary>
|
||||
[Cached]
|
||||
public readonly Bindable<CatcherAnimationState> AnimationState = new Bindable<CatcherAnimationState>();
|
||||
|
||||
public SkinnableCatcher()
|
||||
: base(new CatchSkinComponent(CatchSkinComponents.Catcher), _ => new DefaultCatcher())
|
||||
{
|
||||
Anchor = Anchor.TopCentre;
|
||||
// Sets the origin roughly to the centre of the catcher's plate to allow for correct scaling.
|
||||
OriginPosition = new Vector2(0.5f, 0.06f) * CatcherArea.CATCHER_SIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,31 +1,54 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.UI;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osu.Game.Tests.Visual;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Tests.Editor
|
||||
{
|
||||
public abstract class ManiaSelectionBlueprintTestScene : SelectionBlueprintTestScene
|
||||
{
|
||||
[Cached(Type = typeof(IAdjustableClock))]
|
||||
private readonly IAdjustableClock clock = new StopwatchClock();
|
||||
protected override Container<Drawable> Content => blueprints ?? base.Content;
|
||||
|
||||
protected ManiaSelectionBlueprintTestScene()
|
||||
private readonly Container blueprints;
|
||||
|
||||
[Cached(typeof(Playfield))]
|
||||
public Playfield Playfield { get; }
|
||||
|
||||
private readonly ScrollingTestContainer scrollingTestContainer;
|
||||
|
||||
protected ScrollingDirection Direction
|
||||
{
|
||||
Add(new Column(0)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
AccentColour = Color4.OrangeRed,
|
||||
Clock = new FramedClock(new StopwatchClock()), // No scroll
|
||||
});
|
||||
set => scrollingTestContainer.Direction = value;
|
||||
}
|
||||
|
||||
public ManiaPlayfield Playfield => null;
|
||||
protected ManiaSelectionBlueprintTestScene(int columns)
|
||||
{
|
||||
var stageDefinitions = new List<StageDefinition> { new StageDefinition { Columns = columns } };
|
||||
base.Content.Child = scrollingTestContainer = new ScrollingTestContainer(ScrollingDirection.Up)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
Playfield = new ManiaPlayfield(stageDefinitions)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
blueprints = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
AddToggleStep("Downward scroll", b => Direction = b ? ScrollingDirection.Down : ScrollingDirection.Up);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,55 +1,32 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Mania.Edit.Blueprints;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osu.Game.Tests.Visual;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Tests.Editor
|
||||
{
|
||||
public class TestSceneHoldNoteSelectionBlueprint : ManiaSelectionBlueprintTestScene
|
||||
{
|
||||
private readonly DrawableHoldNote drawableObject;
|
||||
|
||||
protected override Container<Drawable> Content => content ?? base.Content;
|
||||
private readonly Container content;
|
||||
|
||||
public TestSceneHoldNoteSelectionBlueprint()
|
||||
: base(4)
|
||||
{
|
||||
var holdNote = new HoldNote { Column = 0, Duration = 1000 };
|
||||
holdNote.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty());
|
||||
|
||||
base.Content.Child = content = new ScrollingTestContainer(ScrollingDirection.Down)
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Width = 50,
|
||||
Child = drawableObject = new DrawableHoldNote(holdNote)
|
||||
var holdNote = new HoldNote
|
||||
{
|
||||
Height = 300,
|
||||
AccentColour = { Value = OsuColour.Gray(0.3f) }
|
||||
}
|
||||
};
|
||||
Column = i,
|
||||
StartTime = i * 100,
|
||||
Duration = 500
|
||||
};
|
||||
holdNote.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty());
|
||||
|
||||
AddBlueprint(new HoldNoteSelectionBlueprint(drawableObject));
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
foreach (var nested in drawableObject.NestedHitObjects)
|
||||
{
|
||||
double finalPosition = (nested.HitObject.StartTime - drawableObject.HitObject.StartTime) / drawableObject.HitObject.Duration;
|
||||
nested.Y = (float)(-finalPosition * content.DrawHeight);
|
||||
var drawableHitObject = new DrawableHoldNote(holdNote);
|
||||
Playfield.Add(drawableHitObject);
|
||||
AddBlueprint(new HoldNoteSelectionBlueprint(holdNote), drawableHitObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ using osu.Framework.Utils;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.Edit;
|
||||
using osu.Game.Rulesets.Mania.Edit.Blueprints;
|
||||
using osu.Game.Rulesets.Mania.Edit.Blueprints.Components;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Mania.Skinning.Default;
|
||||
@@ -184,8 +184,8 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor
|
||||
AddAssert("head note positioned correctly", () => Precision.AlmostEquals(holdNote.ScreenSpaceDrawQuad.BottomLeft, holdNote.Head.ScreenSpaceDrawQuad.BottomLeft));
|
||||
AddAssert("tail note positioned correctly", () => Precision.AlmostEquals(holdNote.ScreenSpaceDrawQuad.TopLeft, holdNote.Tail.ScreenSpaceDrawQuad.BottomLeft));
|
||||
|
||||
AddAssert("head blueprint positioned correctly", () => this.ChildrenOfType<HoldNoteNoteSelectionBlueprint>().ElementAt(0).DrawPosition == holdNote.Head.DrawPosition);
|
||||
AddAssert("tail blueprint positioned correctly", () => this.ChildrenOfType<HoldNoteNoteSelectionBlueprint>().ElementAt(1).DrawPosition == holdNote.Tail.DrawPosition);
|
||||
AddAssert("head blueprint positioned correctly", () => this.ChildrenOfType<EditNotePiece>().ElementAt(0).DrawPosition == holdNote.Head.DrawPosition);
|
||||
AddAssert("tail blueprint positioned correctly", () => this.ChildrenOfType<EditNotePiece>().ElementAt(1).DrawPosition == holdNote.Tail.DrawPosition);
|
||||
}
|
||||
|
||||
private void setScrollStep(ScrollingDirection direction)
|
||||
|
||||
@@ -15,7 +15,6 @@ using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osu.Game.Tests.Visual;
|
||||
using osuTK;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Tests.Editor
|
||||
@@ -35,7 +34,11 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor
|
||||
[Test]
|
||||
public void TestPlaceBeforeCurrentTimeDownwards()
|
||||
{
|
||||
AddStep("move mouse before current time", () => InputManager.MoveMouseTo(this.ChildrenOfType<Column>().Single().ScreenSpaceDrawQuad.BottomLeft - new Vector2(0, 10)));
|
||||
AddStep("move mouse before current time", () =>
|
||||
{
|
||||
var column = this.ChildrenOfType<Column>().Single();
|
||||
InputManager.MoveMouseTo(column.ScreenSpacePositionAtTime(-100));
|
||||
});
|
||||
|
||||
AddStep("click", () => InputManager.Click(MouseButton.Left));
|
||||
|
||||
@@ -45,7 +48,11 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor
|
||||
[Test]
|
||||
public void TestPlaceAfterCurrentTimeDownwards()
|
||||
{
|
||||
AddStep("move mouse after current time", () => InputManager.MoveMouseTo(this.ChildrenOfType<Column>().Single()));
|
||||
AddStep("move mouse after current time", () =>
|
||||
{
|
||||
var column = this.ChildrenOfType<Column>().Single();
|
||||
InputManager.MoveMouseTo(column.ScreenSpacePositionAtTime(100));
|
||||
});
|
||||
|
||||
AddStep("click", () => InputManager.Click(MouseButton.Left));
|
||||
|
||||
|
||||
@@ -1,40 +1,32 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Rulesets.Mania.Edit.Blueprints;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osu.Game.Tests.Visual;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Tests.Editor
|
||||
{
|
||||
public class TestSceneNoteSelectionBlueprint : ManiaSelectionBlueprintTestScene
|
||||
{
|
||||
protected override Container<Drawable> Content => content ?? base.Content;
|
||||
private readonly Container content;
|
||||
|
||||
public TestSceneNoteSelectionBlueprint()
|
||||
: base(4)
|
||||
{
|
||||
var note = new Note { Column = 0 };
|
||||
note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty());
|
||||
|
||||
DrawableNote drawableObject;
|
||||
|
||||
base.Content.Child = content = new ScrollingTestContainer(ScrollingDirection.Down)
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Size = new Vector2(50, 20),
|
||||
Child = drawableObject = new DrawableNote(note)
|
||||
};
|
||||
var note = new Note
|
||||
{
|
||||
Column = i,
|
||||
StartTime = i * 200,
|
||||
};
|
||||
note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty());
|
||||
|
||||
AddBlueprint(new NoteSelectionBlueprint(drawableObject));
|
||||
var drawableHitObject = new DrawableNote(note);
|
||||
Playfield.Add(drawableHitObject);
|
||||
AddBlueprint(new NoteSelectionBlueprint(note), drawableHitObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
||||
[SetUp]
|
||||
public void SetUp() => Schedule(() =>
|
||||
{
|
||||
SetContents(() => new FillFlowContainer
|
||||
SetContents(_ => new FillFlowContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
SetContents(() => new FillFlowContainer
|
||||
SetContents(_ => new FillFlowContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
@@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Width = 0.5f,
|
||||
Child = new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.ColumnBackground, 0), _ => new DefaultColumnBackground())
|
||||
Child = new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.ColumnBackground), _ => new DefaultColumnBackground())
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both
|
||||
}
|
||||
@@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Width = 0.5f,
|
||||
Child = new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.ColumnBackground, 1), _ => new DefaultColumnBackground())
|
||||
Child = new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.ColumnBackground), _ => new DefaultColumnBackground())
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
SetContents(() => new FillFlowContainer
|
||||
SetContents(_ => new FillFlowContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
||||
{
|
||||
if (hitWindows.IsHitResultAllowed(result))
|
||||
{
|
||||
AddStep("Show " + result.GetDescription(), () => SetContents(() =>
|
||||
AddStep("Show " + result.GetDescription(), () => SetContents(_ =>
|
||||
new DrawableManiaJudgement(new JudgementResult(new HitObject { StartTime = Time.Current }, new Judgement())
|
||||
{
|
||||
Type = result
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
SetContents(() =>
|
||||
SetContents(_ =>
|
||||
{
|
||||
var pool = new DrawablePool<PoolableHitExplosion>(5);
|
||||
hitExplosionPools.Add(pool);
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
SetContents(() => new FillFlowContainer
|
||||
SetContents(_ => new FillFlowContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
@@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Width = 0.5f,
|
||||
Child = new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.KeyArea, 0), _ => new DefaultKeyArea())
|
||||
Child = new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.KeyArea), _ => new DefaultKeyArea())
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both
|
||||
},
|
||||
@@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Width = 0.5f,
|
||||
Child = new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.KeyArea, 1), _ => new DefaultKeyArea())
|
||||
Child = new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.KeyArea), _ => new DefaultKeyArea())
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both
|
||||
},
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
||||
new StageDefinition { Columns = 2 }
|
||||
};
|
||||
|
||||
SetContents(() => new ManiaPlayfield(stageDefinitions));
|
||||
SetContents(_ => new ManiaPlayfield(stageDefinitions));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
||||
new StageDefinition { Columns = 2 }
|
||||
};
|
||||
|
||||
SetContents(() => new ManiaPlayfield(stageDefinitions));
|
||||
SetContents(_ => new ManiaPlayfield(stageDefinitions));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
SetContents(() =>
|
||||
SetContents(_ =>
|
||||
{
|
||||
ManiaAction normalAction = ManiaAction.Key1;
|
||||
ManiaAction specialAction = ManiaAction.Special1;
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
SetContents(() => new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.StageBackground, stageDefinition: new StageDefinition { Columns = 4 }),
|
||||
SetContents(_ => new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.StageBackground, stageDefinition: new StageDefinition { Columns = 4 }),
|
||||
_ => new DefaultStageBackground())
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
SetContents(() => new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.StageForeground, stageDefinition: new StageDefinition { Columns = 4 }), _ => null)
|
||||
SetContents(_ => new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.StageForeground, stageDefinition: new StageDefinition { Columns = 4 }), _ => null)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
// 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 NUnit.Framework;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Mania.UI;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osu.Game.Tests.Visual;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Tests
|
||||
{
|
||||
public class TestSceneDrawableManiaHitObject : OsuTestScene
|
||||
{
|
||||
private readonly ManualClock clock = new ManualClock();
|
||||
|
||||
private Column column;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp() => Schedule(() =>
|
||||
{
|
||||
Child = new ScrollingTestContainer(ScrollingDirection.Down)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
AutoSizeAxes = Axes.X,
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
TimeRange = 2000,
|
||||
Clock = new FramedClock(clock),
|
||||
Child = column = new Column(0)
|
||||
{
|
||||
Action = { Value = ManiaAction.Key1 },
|
||||
Height = 0.85f,
|
||||
AccentColour = Color4.Gray
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
[Test]
|
||||
public void TestHoldNoteHeadVisibility()
|
||||
{
|
||||
DrawableHoldNote note = null;
|
||||
AddStep("Add hold note", () =>
|
||||
{
|
||||
var h = new HoldNote
|
||||
{
|
||||
StartTime = 0,
|
||||
Duration = 1000
|
||||
};
|
||||
h.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty());
|
||||
column.Add(note = new DrawableHoldNote(h));
|
||||
});
|
||||
AddStep("Hold key", () =>
|
||||
{
|
||||
clock.CurrentTime = 0;
|
||||
note.OnPressed(ManiaAction.Key1);
|
||||
});
|
||||
AddStep("progress time", () => clock.CurrentTime = 500);
|
||||
AddAssert("head is visible", () => note.Head.Alpha == 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,13 +5,11 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Replays;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Mania.Replays;
|
||||
using osu.Game.Rulesets.Mania.Scoring;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
@@ -414,14 +412,7 @@ namespace osu.Game.Rulesets.Mania.Tests
|
||||
AddUntilStep("Beatmap at 0", () => Beatmap.Value.Track.CurrentTime == 0);
|
||||
AddUntilStep("Wait until player is loaded", () => currentPlayer.IsCurrentScreen());
|
||||
|
||||
AddUntilStep("wait for head", () => currentPlayer.GameplayClockContainer.GameplayClock.CurrentTime >= time_head);
|
||||
AddAssert("head is visible",
|
||||
() => currentPlayer.ChildrenOfType<DrawableHoldNote>()
|
||||
.Single(note => note.HitObject == beatmap.HitObjects[0])
|
||||
.Head
|
||||
.Alpha == 1);
|
||||
|
||||
AddUntilStep("Wait for completion", () => currentPlayer.ScoreProcessor.HasCompleted.Value);
|
||||
AddUntilStep("Wait for completion", () => currentPlayer.ScoreProcessor?.HasCompleted.Value == true);
|
||||
}
|
||||
|
||||
private class ScoreAccessibleReplayPlayer : ReplayPlayer
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user