diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 8be6479043..b85862270b 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -1,2 +1,8 @@ # Normalize all the line endings 32a74f95a5c80a0ed18e693f13a47522099df5c3 +# Partial everything +7bc8908ca9c026fed1d831eb6e58df7624a8d614 +# Add a few more missing partial specs +212d78865a6b5f091173a347bad5686834d1d5fe +# Add partial specs in mobile projects too +00c11b2b4e389e48f3995d63484a6bc66a7afbdb diff --git a/.github/ISSUE_TEMPLATE/bug-issue.yml b/.github/ISSUE_TEMPLATE/bug-issue.yml index 91ca622f55..ff6d869e72 100644 --- a/.github/ISSUE_TEMPLATE/bug-issue.yml +++ b/.github/ISSUE_TEMPLATE/bug-issue.yml @@ -58,7 +58,8 @@ body: The default places to find the logs on desktop platforms are as follows: - `%AppData%/osu/logs` *on Windows* - - `~/.local/share/osu/logs` *on Linux & macOS* + - `~/.local/share/osu/logs` *on Linux* + - `~/Library/Application Support/osu/logs` *on macOS* If you have selected a custom location for the game files, you can find the `logs` folder there. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 56b3ebe87b..213c5082ab 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,7 +31,7 @@ jobs: run: dotnet tool restore - name: Restore Packages - run: dotnet restore + run: dotnet restore osu.Desktop.slnf - name: Restore inspectcode cache uses: actions/cache@v3 @@ -113,27 +113,36 @@ jobs: with: dotnet-version: "6.0.x" - - name: Setup MSBuild - uses: microsoft/setup-msbuild@v1 + - name: Install .NET workloads + run: dotnet workload install maui-android - - name: Build - run: msbuild osu.Android/osu.Android.csproj /restore /p:Configuration=Debug + - name: Compile + run: dotnet build -c Debug osu.Android.slnf build-only-ios: name: Build only (iOS) - runs-on: macos-latest + # change to macos-latest once GitHub finishes migrating all repositories to macOS 12. + runs-on: macos-12 timeout-minutes: 60 steps: - name: Checkout uses: actions/checkout@v2 + # see https://github.com/actions/runner-images/issues/6771#issuecomment-1354713617 + # remove once all workflow VMs use Xcode 14.1 + - name: Set Xcode Version + shell: bash + run: | + sudo xcode-select -s "/Applications/Xcode_14.1.app" + echo "MD_APPLE_SDK_ROOT=/Applications/Xcode_14.1.app" >> $GITHUB_ENV + - name: Install .NET 6.0.x uses: actions/setup-dotnet@v1 with: dotnet-version: "6.0.x" - # Contrary to seemingly any other msbuild, msbuild running on macOS/Mono - # cannot accept .sln(f) files as arguments. - # Build just the main game for now. + - name: Install .NET Workloads + run: dotnet workload install maui-ios + - name: Build - run: msbuild osu.iOS/osu.iOS.csproj /restore /p:Configuration=Debug + run: dotnet build -c Debug osu.iOS diff --git a/.github/workflows/report-nunit.yml b/.github/workflows/report-nunit.yml index bfc9620174..99e39f6f56 100644 --- a/.github/workflows/report-nunit.yml +++ b/.github/workflows/report-nunit.yml @@ -28,7 +28,7 @@ jobs: timeout-minutes: 5 steps: - name: Annotate CI run with test results - uses: dorny/test-reporter@v1.4.2 + uses: dorny/test-reporter@v1.6.0 with: artifact: osu-test-results-${{matrix.os.prettyname}}-${{matrix.threadingMode}} name: Test Results (${{matrix.os.prettyname}}, ${{matrix.threadingMode}}) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ae2bdd2e82..9f7d88f5c7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,136 +2,87 @@ Thank you for showing interest in the development of osu!. We aim to provide a good collaborating environment for everyone involved, and as such have decided to list some of the most important things to keep in mind in the process. The guidelines below have been chosen based on past experience. -These are not "official rules" *per se*, but following them will help everyone deal with things in the most efficient manner. - ## Table of contents -1. [I would like to submit an issue!](#i-would-like-to-submit-an-issue) -2. [I would like to submit a pull request!](#i-would-like-to-submit-a-pull-request) +1. [Reporting bugs](#reporting-bugs) +2. [Providing general feedback](#providing-general-feedback) +3. [Issue or discussion?](#issue-or-discussion) +4. [Submitting pull requests](#submitting-pull-requests) +5. [Resources](#resources) -## I would like to submit an issue! +## Reporting bugs -Issues, bug reports and feature suggestions are welcomed, though please keep in mind that at any point in time, hundreds of issues are open, which vary in severity and the amount of time needed to address them. As such it's not uncommon for issues to remain unresolved for a long time or even closed outright if they are deemed not important enough to fix in the foreseeable future. Issues that are required to "go live" or otherwise achieve parity with stable are prioritised the most. +A **bug** is a situation in which there is something clearly *and objectively* wrong with the game. Examples of applicable bug reports are: -* **Before submitting an issue, try searching existing issues first.** +- The game crashes to desktop when I start a beatmap +- Friends appear twice in the friend listing +- The game slows down a lot when I play this specific map +- A piece of text is overlapping another piece of text on the screen - For housekeeping purposes, we close issues that overlap with or duplicate other pre-existing issues - you can help us not to have to do that by searching existing issues yourself first. The issue search box, as well as the issue tag system, are tools you can use to check if an issue has been reported before. +To track bug reports, we primarily use GitHub **issues**. When opening an issue, please keep in mind the following: -* **When submitting a bug report, please try to include as much detail as possible.** +- Before opening the issue, please search for any similar existing issues using the text search bar and the issue labels. This includes both open and closed issues (we may have already fixed something, but the fix hasn't yet been released). +- When opening the issue, please fill out as much of the issue template as you can. In particular, please make sure to include logs and screenshots as much as possible. The instructions on how to find the log files are included in the issue template. +- We may ask you for follow-up information to reproduce or debug the problem. Please look out for this and provide follow-up info if we request it. - Bugs are not equal - some of them will be reproducible every time on pretty much all hardware, while others will be hard to track down due to being specific to particular hardware or even somewhat random in nature. As such, providing as much detail as possible when reporting a bug is hugely appreciated. A good starting set of information consists of: +If we cannot reproduce the issue, it is deemed low priority, or it is deemed to be specific to your setup in some way, the issue may be downgraded to a discussion. This will be done by a maintainer for you. - * the in-game logs, which are located at: - * `%AppData%/osu/logs` (on Windows), - * `~/.local/share/osu/logs` (on Linux and macOS), - * `Android/data/sh.ppy.osulazer/files/logs` (on Android), - * on iOS they can be obtained by connecting your device to your desktop and [copying the `logs` directory from the app's own document storage using iTunes](https://support.apple.com/en-us/HT201301#copy-to-computer), - * your system specifications (including the operating system and platform you are playing on), - * a reproduction scenario (list of steps you have performed leading up to the occurrence of the bug), - * a video or picture of the bug, if at all possible. +## Providing general feedback -* **Provide more information when asked to do so.** +If you wish to: - Sometimes when a bug is more elusive or complicated, none of the information listed above will pinpoint a concrete cause of the problem. In this case we will most likely ask you for additional info, such as a Windows Event Log dump or a copy of your local osu! database (`client.db`). Providing that information is beneficial to both parties - we can track down the problem better, and hopefully fix it for you at some point once we know where it is! +- provide *subjective* feedback on the game (about how the UI looks, about how the default skin works, about game mechanics, about how the PP and scoring systems work, etc.), +- suggest a new feature to be added to the game, +- report a non-specific problem with the game that you think may be connected to your hardware or operating system specifically, -* **When submitting a feature proposal, please describe it in the most understandable way you can.** +then it is generally best to start with a **discussion** first. Discussions are a good avenue to group subjective feedback on a single topic, or gauge interest in a particular feature request. - Communicating your idea for a feature can often be hard, and we would like to avoid any misunderstandings. As such, please try to explain your idea in a short, but understandable manner - it's best to avoid jargon or terms and references that could be considered obscure. A mock-up picture (doesn't have to be good!) of the feature can also go a long way in explaining. +When opening a discussion, please keep in mind the following: -* **Refrain from posting "+1" comments.** +- Use the search function to see if your idea has been proposed before, or if there is already a thread about a particular issue you wish to raise. +- If proposing a feature, please try to explain the feature in as much detail as possible. +- If you're reporting a non-specific problem, please provide applicable logs, screenshots, or video that illustrate the issue. - If an issue has already been created, saying that you also experience it without providing any additional details doesn't really help us in any way. To express support for a proposal or indicate that you are also affected by a particular bug, you can use comment reactions instead. +If a discussion gathers enough traction, then it may be converted into an issue. This will be done by a maintainer for you. -* **Refrain from asking if an issue has been resolved yet.** +## Issue or discussion? - As mentioned above, the issue tracker has hundreds of issues open at any given time. Currently the game is being worked on by two members of the core team, and a handful of outside contributors who offer their free time to help out. As such, it can happen that an issue gets placed on the backburner due to being less important; generally posting a comment demanding its resolution some months or years after it is reported is not very likely to increase its priority. +We realise that the line between an issue and a discussion may be fuzzy, so while we ask you to use your best judgement based on the description above, please don't think about it too hard either. Feedback in a slightly wrong place is better than no feedback at all. -* **Avoid long discussions about non-development topics.** +When in doubt, it's probably best to start with a discussion first. We will escalate to issues as needed. - GitHub is mostly a developer space, and as such isn't really fit for lengthened discussions about gameplay mechanics (which might not even be in any way confirmed for the final release) and similar non-technical matters. Such matters are probably best addressed at the osu! forums. +## Submitting pull requests -## I would like to submit a pull request! +While pull requests from unaffiliated contributors are welcome, please note that due to significant community interest and limited review throughput, the core team's primary focus is on the issues which are currently [on the roadmap](https://github.com/orgs/ppy/projects/7/views/6). Reviewing PRs that fall outside of the scope of the roadmap is done on a best-effort basis, so please be aware that it may take a while before a core maintainer gets around to review your change. -We also welcome pull requests from unaffiliated contributors. The [issue tracker](https://github.com/ppy/osu/issues) should provide plenty of issues that you can work on; we also mark issues that we think would be good for newcomers with the [`good-first-issue`](https://github.com/ppy/osu/issues?q=is%3Aissue+is%3Aopen+label%3Agood-first-issue) label. +The [issue tracker](https://github.com/ppy/osu/issues) should provide plenty of issues to start with. We also have a [`good-first-issue`](https://github.com/ppy/osu/issues?q=is%3Aissue+is%3Aopen+label%3Agood-first-issue) label, although from experience it is not used very often, as it is relatively rare that we can spot an issue that will definitively be a good first issue for a new contributor regardless of their programming experience. -However, do keep in mind that the core team is committed to bringing osu!(lazer) up to par with osu!(stable) first and foremost, so depending on what your contribution concerns, it might not be merged and released right away. Our approach to managing issues and their priorities is described [in the wiki](https://github.com/ppy/osu/wiki/Project-management). +In the case of simple issues, a direct PR is okay. However, if you decide to work on an existing issue which doesn't seem trivial, **please ask us first**. This way we can try to estimate if it is a good fit for you and provide the correct direction on how to address it. In addition, note that while we do not rule out external contributors from working on roadmapped issues, we will generally prefer to handle them ourselves unless they're not very time sensitive. -Here are some key things to note before jumping in: +If you'd like to propose a subjective change to one of the visual aspects of the game, or there is a bigger task you'd like to work on, but there is no corresponding issue or discussion thread yet for it, **please open a discussion or issue first** to avoid wasted effort. This in particular applies if you want to work on [one of the available designs from the osu! public Figma library](https://www.figma.com/file/6m10GiGEncVFWmgOoSyakH/osu!-Figma-Library). -* **Make sure you are comfortable with C\# and your development environment.** +Aside from the above, below is a brief checklist of things to watch out when you're preparing your code changes: - While we are accepting of all kinds of contributions, we also have a certain quality standard we'd like to uphold and limited time to review your code. Therefore, we would like to avoid providing entry-level advice, and as such if you're not very familiar with C\# as a programming language, we'd recommend that you start off with a few personal projects to get acquainted with the language's syntax, toolchain and principles of object-oriented programming first. +- Make sure you're comfortable with the principles of object-oriented programming, the syntax of C\# and your development environment. +- Make sure you are familiar with [git](https://git-scm.com/) and [the pull request workflow](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/proposing-changes-to-your-work-with-pull-requests). +- Please do not make code changes via the GitHub web interface. +- Please add tests for your changes. We expect most new features and bugfixes to have test coverage, unless the effort of adding them is prohibitive. The visual testing methodology we use is described in more detail [here](https://github.com/ppy/osu-framework/wiki/Development-and-Testing). +- Please run tests and code style analysis (via `InspectCode.{ps1,sh}` scripts in the root of this repository) before opening the PR. This is particularly important if you're a first-time contributor, as CI will not run for your PR until we allow it to do so. - In addition, please take the time to take a look at and get acquainted with the [development and testing](https://github.com/ppy/osu-framework/wiki/Development-and-Testing) procedure we have set up. +After you're done with your changes and you wish to open the PR, please observe the following recommendations: -* **Make sure you are familiar with git and the pull request workflow.** +- Please submit the pull request from a [topic branch](https://git-scm.com/book/en/v2/Git-Branching-Branching-Workflows#_topic_branch) (not `master`), and keep the *Allow edits from maintainers* check box selected, so that we can push fixes to your PR if necessary. +- Please avoid pushing untested or incomplete code. +- Please do not force-push or rebase unless we ask you to. +- Please do not merge `master` continually if there are no conflicts to resolve. We will do this for you when the change is ready for merge. - [git](https://git-scm.com/) is a distributed version control system that might not be very intuitive at the beginning if you're not familiar with version control. In particular, projects using git have a particular workflow for submitting code changes, which is called the pull request workflow. +We are highly committed to quality when it comes to the osu! project. This means that contributions from less experienced community members can take multiple rounds of review to get to a mergeable state. We try our utmost best to never conflate a person with the code they authored, and to keep the discussion focused on the code at all times. Please consider our comments and requests a learning experience. - To make things run more smoothly, we recommend that you look up some online resources to familiarise yourself with the git vocabulary and commands, and practice working with forks and submitting pull requests at your own pace. A high-level overview of the process can be found in [this article by GitHub](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/proposing-changes-to-your-work-with-pull-requests). +If you're uncertain about some part of the codebase or some inner workings of the game and framework, please reach out either by leaving a comment in the relevant issue, discussion, or PR thread, or by posting a message in the [development Discord server](https://discord.gg/ppy). We will try to help you as much as we can. -* **Double-check designs before starting work on new functionality.** +## Resources - When implementing new features, keep in mind that we already have a lot of the UI designed. If you wish to work on something with the intention of having it included in the official distribution, please open an issue for discussion and we will give you what you need from a design perspective to proceed. If you want to make *changes* to the design, we recommend you open an issue with your intentions before spending too much time to ensure no effort is wasted. - -* **Make sure to submit pull requests off of a topic branch.** - - As described in the article linked in the previous point, topic branches help you parallelise your work and separate it from the main `master` branch, and additionally are easier for maintainers to work with. Working with multiple `master` branches across many remotes is difficult to keep track of, and it's easy to make a mistake and push to the wrong `master` branch by accident. - -* **Refrain from making changes through the GitHub web interface.** - - Even though GitHub provides an option to edit code or replace files in the repository using the web interface, we strongly discourage using it in most scenarios. Editing files this way is inefficient and likely to introduce whitespace or file encoding changes that make it more difficult to review the code. - - Code written through the web interface will also very likely be questioned outright by the reviewers, as it is likely that it has not been properly tested or that it will fail continuous integration checks. We strongly encourage using an IDE like [Visual Studio](https://visualstudio.microsoft.com/), [Visual Studio Code](https://code.visualstudio.com/) or [JetBrains Rider](https://www.jetbrains.com/rider/) instead. - -* **Add tests for your code whenever possible.** - - Automated tests are an essential part of a quality and reliable codebase. They help to make the code more maintainable by ensuring it is safe to reorganise (or refactor) the code in various ways, and also prevent regressions - bugs that resurface after having been fixed at some point in the past. If it is viable, please put in the time to add tests, so that the changes you make can last for a (hopefully) very long time. - -* **Run tests before opening a pull request.** - - Tying into the previous point, sometimes changes in one part of the codebase can result in unpredictable changes in behaviour in other pieces of the code. This is why it is best to always try to run tests before opening a PR. - - Continuous integration will always run the tests for you (and us), too, but it is best not to rely on it, as there might be many builds queued at any time. Running tests on your own will help you be more certain that at the point of clicking the "Create pull request" button, your changes are as ready as can be. - -* **Run code style analysis before opening a pull request.** - - As part of continuous integration, we also run code style analysis, which is supposed to make sure that your code is formatted the same way as all the pre-existing code in the repository. The reason we enforce a particular code style everywhere is to make sure the codebase is consistent in that regard - having one whitespace convention in one place and another one elsewhere causes disorganisation. - -* **Make sure that the pull request is complete before opening it.** - - Whether it's fixing a bug or implementing new functionality, it's best that you make sure that the change you want to submit as a pull request is as complete as it can be before clicking the *Create pull request* button. Having to track if a pull request is ready for review or not places additional burden on reviewers. - - Draft pull requests are an option, but use them sparingly and within reason. They are best suited to discuss code changes that cannot be easily described in natural language or have a potential large impact on the future direction of the project. When in doubt, don't open drafts unless a maintainer asks you to do so. - -* **Only push code when it's ready.** - - As an extension of the above, when making changes to an already-open PR, please try to only push changes you are reasonably certain of. Pushing after every commit causes the continuous integration build queue to grow in size, slowing down work and taking up time that could be spent verifying other changes. - -* **Make sure to keep the *Allow edits from maintainers* check box checked.** - - To speed up the merging process, collaborators and team members will sometimes want to push changes to your branch themselves, to make minor code style adjustments or to otherwise refactor the code without having to describe how they'd like the code to look like in painstaking detail. Having the *Allow edits from maintainers* check box checked lets them do that; without it they are forced to report issues back to you and wait for you to address them. - -* **Refrain from continually merging the master branch back to the PR.** - - Unless there are merge conflicts that need resolution, there is no need to keep merging `master` back to a branch over and over again. One of the maintainers will merge `master` themselves before merging the PR itself anyway, and continual merge commits can cause CI to get overwhelmed due to queueing up too many builds. - -* **Refrain from force-pushing to the PR branch.** - - Force-pushing should be avoided, as it can lead to accidentally overwriting a maintainer's changes or CI building wrong commits. We value all history in the project, so there is no need to squash or amend commits in most cases. - - The cases in which force-pushing is warranted are very rare (such as accidentally leaking sensitive info in one of the files committed, adding unrelated files, or mis-merging a dependent PR). - -* **Be patient when waiting for the code to be reviewed and merged.** - - As much as we'd like to review all contributions as fast as possible, our time is limited, as team members have to work on their own tasks in addition to reviewing code. As such, work needs to be prioritised, and it can unfortunately take weeks or months for your PR to be merged, depending on how important it is deemed to be. - -* **Don't mistake criticism of code for criticism of your person.** - - As mentioned before, we are highly committed to quality when it comes to the osu! project. This means that contributions from less experienced community members can take multiple rounds of review to get to a mergeable state. We try our utmost best to never conflate a person with the code they authored, and to keep the discussion focused on the code at all times. Please consider our comments and requests a learning experience, and don't treat it as a personal attack. - -* **Feel free to reach out for help.** - - If you're uncertain about some part of the codebase or some inner workings of the game and framework, please reach out either by leaving a comment in the relevant issue or PR thread, or by posting a message in the [development Discord server](https://discord.gg/ppy). We will try to help you as much as we can. - - When it comes to which form of communication is best, GitHub generally lends better to longer-form discussions, while Discord is better for snappy call-and-response answers. Use your best discretion when deciding, and try to keep a single discussion in one place instead of moving back and forth. +- [Development roadmap](https://github.com/orgs/ppy/projects/7/views/6): What the core team is currently working on +- [`ppy/osu-framework` wiki](https://github.com/ppy/osu-framework/wiki): Contains introductory information about osu!framework, the bespoke 2D game framework we use for the game +- [`ppy/osu` wiki](https://github.com/ppy/osu/wiki): Contains articles about various technical aspects of the game +- [Public Figma library](https://www.figma.com/file/6m10GiGEncVFWmgOoSyakH/osu!-Figma-Library): Contains finished and draft designs for osu! diff --git a/README.md b/README.md index 75d61dad4d..f3f025fa10 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ If you are looking to install or test osu! without setting up a development envi **Latest build:** -| [Windows 8.1+ (x64)](https://github.com/ppy/osu/releases/latest/download/install.exe) | macOS 10.15+ ([Intel](https://github.com/ppy/osu/releases/latest/download/osu.app.Intel.zip), [Apple Silicon](https://github.com/ppy/osu/releases/latest/download/osu.app.Apple.Silicon.zip)) | [Linux (x64)](https://github.com/ppy/osu/releases/latest/download/osu.AppImage) | [iOS 10+](https://osu.ppy.sh/home/testflight) | [Android 5+](https://github.com/ppy/osu/releases/latest/download/sh.ppy.osulazer.apk) | +| [Windows 8.1+ (x64)](https://github.com/ppy/osu/releases/latest/download/install.exe) | macOS 10.15+ ([Intel](https://github.com/ppy/osu/releases/latest/download/osu.app.Intel.zip), [Apple Silicon](https://github.com/ppy/osu/releases/latest/download/osu.app.Apple.Silicon.zip)) | [Linux (x64)](https://github.com/ppy/osu/releases/latest/download/osu.AppImage) | [iOS 13.4+](https://osu.ppy.sh/home/testflight) | [Android 5+](https://github.com/ppy/osu/releases/latest/download/sh.ppy.osulazer.apk) | | ------------- | ------------- | ------------- | ------------- | ------------- | - The iOS testflight link may fill up (Apple has a hard limit of 10,000 users). We reset it occasionally when this happens. Please do not ask about this. Check back regularly for link resets or follow [peppy](https://twitter.com/ppy) on twitter for announcements of link resets. @@ -101,9 +101,7 @@ JetBrains ReSharper InspectCode is also used for wider rule sets. You can run it ## Contributing -When it comes to contributing to the project, the two main things you can do to help out are reporting issues and submitting pull requests. Based on past experiences, we have prepared a [list of contributing guidelines](CONTRIBUTING.md) that should hopefully ease you into our collaboration process and answer the most frequently-asked questions. - -Note that while we already have certain standards in place, nothing is set in stone. If you have an issue with the way code is structured, with any libraries we are using, or with any processes involved with contributing, *please* bring it up. We welcome all feedback so we can make contributing to this project as painless as possible. +When it comes to contributing to the project, the two main things you can do to help out are reporting issues and submitting pull requests. Please refer to the [contributing guidelines](CONTRIBUTING.md) to understand how to help in the most effective way possible. If you wish to help with localisation efforts, head over to [crowdin](https://crowdin.com/project/osu-web). diff --git a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/TestSceneOsuGame.cs b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/TestSceneOsuGame.cs index 5973db908c..ca73074789 100644 --- a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/TestSceneOsuGame.cs +++ b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/TestSceneOsuGame.cs @@ -9,7 +9,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.EmptyFreeform.Tests { - public class TestSceneOsuGame : OsuTestScene + public partial class TestSceneOsuGame : OsuTestScene { [BackgroundDependencyLoader] private void load() diff --git a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/TestSceneOsuPlayer.cs b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/TestSceneOsuPlayer.cs index 0f2ddf82a5..4b99fa7e09 100644 --- a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/TestSceneOsuPlayer.cs +++ b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/TestSceneOsuPlayer.cs @@ -7,7 +7,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.EmptyFreeform.Tests { [TestFixture] - public class TestSceneOsuPlayer : PlayerTestScene + public partial class TestSceneOsuPlayer : PlayerTestScene { protected override Ruleset CreatePlayerRuleset() => new EmptyFreeformRuleset(); } diff --git a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/EmptyFreeformInputManager.cs b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/EmptyFreeformInputManager.cs index b292a28c0d..feac0f22f5 100644 --- a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/EmptyFreeformInputManager.cs +++ b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/EmptyFreeformInputManager.cs @@ -7,7 +7,7 @@ using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.EmptyFreeform { - public class EmptyFreeformInputManager : RulesetInputManager + public partial class EmptyFreeformInputManager : RulesetInputManager { public EmptyFreeformInputManager(RulesetInfo ruleset) : base(ruleset, 0, SimultaneousBindingMode.Unique) diff --git a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/EmptyFreeformRuleset.cs b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/EmptyFreeformRuleset.cs index 1e88f87f09..d7ef84541f 100644 --- a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/EmptyFreeformRuleset.cs +++ b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/EmptyFreeformRuleset.cs @@ -21,7 +21,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.EmptyFreeform { - public class EmptyFreeformRuleset : Ruleset + public partial class EmptyFreeformRuleset : Ruleset { public override string Description => "a very emptyfreeformruleset ruleset"; @@ -56,7 +56,7 @@ namespace osu.Game.Rulesets.EmptyFreeform public override Drawable CreateIcon() => new Icon(ShortName[0]); - public class Icon : CompositeDrawable + public partial class Icon : CompositeDrawable { public Icon(char c) { diff --git a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/Objects/Drawables/DrawableEmptyFreeformHitObject.cs b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/Objects/Drawables/DrawableEmptyFreeformHitObject.cs index 0f38e9fdf8..744e207b57 100644 --- a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/Objects/Drawables/DrawableEmptyFreeformHitObject.cs +++ b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/Objects/Drawables/DrawableEmptyFreeformHitObject.cs @@ -9,7 +9,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.EmptyFreeform.Objects.Drawables { - public class DrawableEmptyFreeformHitObject : DrawableHitObject + public partial class DrawableEmptyFreeformHitObject : DrawableHitObject { public DrawableEmptyFreeformHitObject(EmptyFreeformHitObject hitObject) : base(hitObject) diff --git a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/UI/DrawableEmptyFreeformRuleset.cs b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/UI/DrawableEmptyFreeformRuleset.cs index 290f35f516..608e8d3c07 100644 --- a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/UI/DrawableEmptyFreeformRuleset.cs +++ b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/UI/DrawableEmptyFreeformRuleset.cs @@ -17,7 +17,7 @@ using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.EmptyFreeform.UI { [Cached] - public class DrawableEmptyFreeformRuleset : DrawableRuleset + public partial class DrawableEmptyFreeformRuleset : DrawableRuleset { public DrawableEmptyFreeformRuleset(EmptyFreeformRuleset ruleset, IBeatmap beatmap, IReadOnlyList mods = null) : base(ruleset, beatmap, mods) diff --git a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/UI/EmptyFreeformPlayfield.cs b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/UI/EmptyFreeformPlayfield.cs index 9df5935c45..532e88d55e 100644 --- a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/UI/EmptyFreeformPlayfield.cs +++ b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/UI/EmptyFreeformPlayfield.cs @@ -8,7 +8,7 @@ using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.EmptyFreeform.UI { [Cached] - public class EmptyFreeformPlayfield : Playfield + public partial class EmptyFreeformPlayfield : Playfield { [BackgroundDependencyLoader] private void load() diff --git a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/osu.Game.Rulesets.EmptyFreeform.csproj b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/osu.Game.Rulesets.EmptyFreeform.csproj index 092a013614..d09e7647e0 100644 --- a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/osu.Game.Rulesets.EmptyFreeform.csproj +++ b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/osu.Game.Rulesets.EmptyFreeform.csproj @@ -1,6 +1,6 @@  - netstandard2.1 + net6.0 osu.Game.Rulesets.EmptyFreeform Library AnyCPU @@ -12,4 +12,4 @@ - \ No newline at end of file + diff --git a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/TestSceneOsuGame.cs b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/TestSceneOsuGame.cs index b75a5ec187..c105e9c040 100644 --- a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/TestSceneOsuGame.cs +++ b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/TestSceneOsuGame.cs @@ -9,7 +9,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Pippidon.Tests { - public class TestSceneOsuGame : OsuTestScene + public partial class TestSceneOsuGame : OsuTestScene { [BackgroundDependencyLoader] private void load() diff --git a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/TestSceneOsuPlayer.cs b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/TestSceneOsuPlayer.cs index f00528900c..793d3933d7 100644 --- a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/TestSceneOsuPlayer.cs +++ b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/TestSceneOsuPlayer.cs @@ -7,7 +7,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Pippidon.Tests { [TestFixture] - public class TestSceneOsuPlayer : PlayerTestScene + public partial class TestSceneOsuPlayer : PlayerTestScene { protected override Ruleset CreatePlayerRuleset() => new PippidonRuleset(); } diff --git a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/Objects/Drawables/DrawablePippidonHitObject.cs b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/Objects/Drawables/DrawablePippidonHitObject.cs index 399d6adda2..29203f0a20 100644 --- a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/Objects/Drawables/DrawablePippidonHitObject.cs +++ b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/Objects/Drawables/DrawablePippidonHitObject.cs @@ -16,7 +16,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Pippidon.Objects.Drawables { - public class DrawablePippidonHitObject : DrawableHitObject + public partial class DrawablePippidonHitObject : DrawableHitObject { private const double time_preempt = 600; private const double time_fadein = 400; diff --git a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/PippidonInputManager.cs b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/PippidonInputManager.cs index aa7fa3188b..85b264bc67 100644 --- a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/PippidonInputManager.cs +++ b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/PippidonInputManager.cs @@ -7,7 +7,7 @@ using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Pippidon { - public class PippidonInputManager : RulesetInputManager + public partial class PippidonInputManager : RulesetInputManager { public PippidonInputManager(RulesetInfo ruleset) : base(ruleset, 0, SimultaneousBindingMode.Unique) diff --git a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/PippidonRulesetIcon.cs b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/PippidonRulesetIcon.cs index ff10233b50..1a672d10dd 100644 --- a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/PippidonRulesetIcon.cs +++ b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/PippidonRulesetIcon.cs @@ -8,7 +8,7 @@ using osu.Framework.Graphics.Textures; namespace osu.Game.Rulesets.Pippidon { - public class PippidonRulesetIcon : Sprite + public partial class PippidonRulesetIcon : Sprite { private readonly Ruleset ruleset; diff --git a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/UI/DrawablePippidonRuleset.cs b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/UI/DrawablePippidonRuleset.cs index d923963bef..982a80cb7a 100644 --- a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/UI/DrawablePippidonRuleset.cs +++ b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/UI/DrawablePippidonRuleset.cs @@ -17,7 +17,7 @@ using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Pippidon.UI { [Cached] - public class DrawablePippidonRuleset : DrawableRuleset + public partial class DrawablePippidonRuleset : DrawableRuleset { public DrawablePippidonRuleset(PippidonRuleset ruleset, IBeatmap beatmap, IReadOnlyList mods = null) : base(ruleset, beatmap, mods) diff --git a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/UI/PippidonCursorContainer.cs b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/UI/PippidonCursorContainer.cs index 9de3f4ba14..20dd2e7c31 100644 --- a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/UI/PippidonCursorContainer.cs +++ b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/UI/PippidonCursorContainer.cs @@ -10,7 +10,7 @@ using osuTK; namespace osu.Game.Rulesets.Pippidon.UI { - public class PippidonCursorContainer : GameplayCursorContainer + public partial class PippidonCursorContainer : GameplayCursorContainer { private Sprite cursorSprite; private Texture cursorTexture; diff --git a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/UI/PippidonPlayfield.cs b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/UI/PippidonPlayfield.cs index b5a97c5ea3..62e162ae4b 100644 --- a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/UI/PippidonPlayfield.cs +++ b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/UI/PippidonPlayfield.cs @@ -8,7 +8,7 @@ using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Pippidon.UI { [Cached] - public class PippidonPlayfield : Playfield + public partial class PippidonPlayfield : Playfield { protected override GameplayCursorContainer CreateCursor() => new PippidonCursorContainer(); diff --git a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/UI/PippidonPlayfieldAdjustmentContainer.cs b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/UI/PippidonPlayfieldAdjustmentContainer.cs index 9236683827..b46e795bbc 100644 --- a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/UI/PippidonPlayfieldAdjustmentContainer.cs +++ b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/UI/PippidonPlayfieldAdjustmentContainer.cs @@ -7,7 +7,7 @@ using osuTK; namespace osu.Game.Rulesets.Pippidon.UI { - public class PippidonPlayfieldAdjustmentContainer : PlayfieldAdjustmentContainer + public partial class PippidonPlayfieldAdjustmentContainer : PlayfieldAdjustmentContainer { public PippidonPlayfieldAdjustmentContainer() { diff --git a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/osu.Game.Rulesets.Pippidon.csproj b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/osu.Game.Rulesets.Pippidon.csproj index a3607343c9..9c8867f4ef 100644 --- a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/osu.Game.Rulesets.Pippidon.csproj +++ b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/osu.Game.Rulesets.Pippidon.csproj @@ -1,6 +1,6 @@  - netstandard2.1 + net6.0 osu.Game.Rulesets.Pippidon Library AnyCPU @@ -12,4 +12,4 @@ - \ No newline at end of file + diff --git a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/TestSceneOsuGame.cs b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/TestSceneOsuGame.cs index ffe921b54c..a9a3c2eb5b 100644 --- a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/TestSceneOsuGame.cs +++ b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/TestSceneOsuGame.cs @@ -9,7 +9,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.EmptyScrolling.Tests { - public class TestSceneOsuGame : OsuTestScene + public partial class TestSceneOsuGame : OsuTestScene { [BackgroundDependencyLoader] private void load() diff --git a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/TestSceneOsuPlayer.cs b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/TestSceneOsuPlayer.cs index 9460576196..2be3862833 100644 --- a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/TestSceneOsuPlayer.cs +++ b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/TestSceneOsuPlayer.cs @@ -7,7 +7,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.EmptyScrolling.Tests { [TestFixture] - public class TestSceneOsuPlayer : PlayerTestScene + public partial class TestSceneOsuPlayer : PlayerTestScene { protected override Ruleset CreatePlayerRuleset() => new EmptyScrollingRuleset(); } diff --git a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/EmptyScrollingInputManager.cs b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/EmptyScrollingInputManager.cs index 632e04f301..a7b4ae61f0 100644 --- a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/EmptyScrollingInputManager.cs +++ b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/EmptyScrollingInputManager.cs @@ -7,7 +7,7 @@ using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.EmptyScrolling { - public class EmptyScrollingInputManager : RulesetInputManager + public partial class EmptyScrollingInputManager : RulesetInputManager { public EmptyScrollingInputManager(RulesetInfo ruleset) : base(ruleset, 0, SimultaneousBindingMode.Unique) diff --git a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/Objects/Drawables/DrawableEmptyScrollingHitObject.cs b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/Objects/Drawables/DrawableEmptyScrollingHitObject.cs index b5ff0cde7c..a3c3b89105 100644 --- a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/Objects/Drawables/DrawableEmptyScrollingHitObject.cs +++ b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/Objects/Drawables/DrawableEmptyScrollingHitObject.cs @@ -9,7 +9,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.EmptyScrolling.Objects.Drawables { - public class DrawableEmptyScrollingHitObject : DrawableHitObject + public partial class DrawableEmptyScrollingHitObject : DrawableHitObject { public DrawableEmptyScrollingHitObject(EmptyScrollingHitObject hitObject) : base(hitObject) diff --git a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/UI/DrawableEmptyScrollingRuleset.cs b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/UI/DrawableEmptyScrollingRuleset.cs index 620a4abc51..99598fc113 100644 --- a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/UI/DrawableEmptyScrollingRuleset.cs +++ b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/UI/DrawableEmptyScrollingRuleset.cs @@ -18,7 +18,7 @@ using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.EmptyScrolling.UI { [Cached] - public class DrawableEmptyScrollingRuleset : DrawableScrollingRuleset + public partial class DrawableEmptyScrollingRuleset : DrawableScrollingRuleset { public DrawableEmptyScrollingRuleset(EmptyScrollingRuleset ruleset, IBeatmap beatmap, IReadOnlyList mods = null) : base(ruleset, beatmap, mods) diff --git a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/UI/EmptyScrollingPlayfield.cs b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/UI/EmptyScrollingPlayfield.cs index 56620e44b3..3770ba8172 100644 --- a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/UI/EmptyScrollingPlayfield.cs +++ b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/UI/EmptyScrollingPlayfield.cs @@ -8,7 +8,7 @@ using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.EmptyScrolling.UI { [Cached] - public class EmptyScrollingPlayfield : ScrollingPlayfield + public partial class EmptyScrollingPlayfield : ScrollingPlayfield { [BackgroundDependencyLoader] private void load() diff --git a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/osu.Game.Rulesets.EmptyScrolling.csproj b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/osu.Game.Rulesets.EmptyScrolling.csproj index 2ea52429ab..5bf3884f53 100644 --- a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/osu.Game.Rulesets.EmptyScrolling.csproj +++ b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/osu.Game.Rulesets.EmptyScrolling.csproj @@ -1,6 +1,6 @@  - netstandard2.1 + net6.0 osu.Game.Rulesets.EmptyScrolling Library AnyCPU @@ -12,4 +12,4 @@ - \ No newline at end of file + diff --git a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/TestSceneOsuGame.cs b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/TestSceneOsuGame.cs index b75a5ec187..c105e9c040 100644 --- a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/TestSceneOsuGame.cs +++ b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/TestSceneOsuGame.cs @@ -9,7 +9,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Pippidon.Tests { - public class TestSceneOsuGame : OsuTestScene + public partial class TestSceneOsuGame : OsuTestScene { [BackgroundDependencyLoader] private void load() diff --git a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/TestSceneOsuPlayer.cs b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/TestSceneOsuPlayer.cs index f00528900c..793d3933d7 100644 --- a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/TestSceneOsuPlayer.cs +++ b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/TestSceneOsuPlayer.cs @@ -7,7 +7,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Pippidon.Tests { [TestFixture] - public class TestSceneOsuPlayer : PlayerTestScene + public partial class TestSceneOsuPlayer : PlayerTestScene { protected override Ruleset CreatePlayerRuleset() => new PippidonRuleset(); } diff --git a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/Objects/Drawables/DrawablePippidonHitObject.cs b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/Objects/Drawables/DrawablePippidonHitObject.cs index e458cacef9..554d03c79f 100644 --- a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/Objects/Drawables/DrawablePippidonHitObject.cs +++ b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/Objects/Drawables/DrawablePippidonHitObject.cs @@ -17,7 +17,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Pippidon.Objects.Drawables { - public class DrawablePippidonHitObject : DrawableHitObject + public partial class DrawablePippidonHitObject : DrawableHitObject { private BindableNumber currentLane; diff --git a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/PippidonInputManager.cs b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/PippidonInputManager.cs index c9e6e6faaa..a31c1bf832 100644 --- a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/PippidonInputManager.cs +++ b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/PippidonInputManager.cs @@ -7,7 +7,7 @@ using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Pippidon { - public class PippidonInputManager : RulesetInputManager + public partial class PippidonInputManager : RulesetInputManager { public PippidonInputManager(RulesetInfo ruleset) : base(ruleset, 0, SimultaneousBindingMode.Unique) diff --git a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/PippidonRulesetIcon.cs b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/PippidonRulesetIcon.cs index 6b87d93951..75005a3743 100644 --- a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/PippidonRulesetIcon.cs +++ b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/PippidonRulesetIcon.cs @@ -9,7 +9,7 @@ using osu.Framework.Graphics.Textures; namespace osu.Game.Rulesets.Pippidon { - public class PippidonRulesetIcon : Sprite + public partial class PippidonRulesetIcon : Sprite { private readonly Ruleset ruleset; diff --git a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/UI/DrawablePippidonRuleset.cs b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/UI/DrawablePippidonRuleset.cs index 9a73dd7790..1e7e09be67 100644 --- a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/UI/DrawablePippidonRuleset.cs +++ b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/UI/DrawablePippidonRuleset.cs @@ -18,7 +18,7 @@ using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Pippidon.UI { [Cached] - public class DrawablePippidonRuleset : DrawableScrollingRuleset + public partial class DrawablePippidonRuleset : DrawableScrollingRuleset { public DrawablePippidonRuleset(PippidonRuleset ruleset, IBeatmap beatmap, IReadOnlyList mods = null) : base(ruleset, beatmap, mods) diff --git a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/UI/PippidonCharacter.cs b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/UI/PippidonCharacter.cs index 98dba622d0..33d349da62 100644 --- a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/UI/PippidonCharacter.cs +++ b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/UI/PippidonCharacter.cs @@ -15,7 +15,7 @@ using osuTK; namespace osu.Game.Rulesets.Pippidon.UI { - public class PippidonCharacter : BeatSyncedContainer, IKeyBindingHandler + public partial class PippidonCharacter : BeatSyncedContainer, IKeyBindingHandler { public readonly BindableInt LanePosition = new BindableInt { diff --git a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/UI/PippidonPlayfield.cs b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/UI/PippidonPlayfield.cs index ab8c6bb2e9..a90326e935 100644 --- a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/UI/PippidonPlayfield.cs +++ b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/UI/PippidonPlayfield.cs @@ -16,7 +16,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Pippidon.UI { [Cached] - public class PippidonPlayfield : ScrollingPlayfield + public partial class PippidonPlayfield : ScrollingPlayfield { public const float LANE_HEIGHT = 70; @@ -60,7 +60,7 @@ namespace osu.Game.Rulesets.Pippidon.UI }); } - private class LaneContainer : BeatSyncedContainer + private partial class LaneContainer : BeatSyncedContainer { private OsuColour colours; private FillFlowContainer fill; @@ -99,7 +99,7 @@ namespace osu.Game.Rulesets.Pippidon.UI } } - private class Lane : CompositeDrawable + private partial class Lane : CompositeDrawable { public Lane() { diff --git a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/osu.Game.Rulesets.Pippidon.csproj b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/osu.Game.Rulesets.Pippidon.csproj index a3607343c9..9c8867f4ef 100644 --- a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/osu.Game.Rulesets.Pippidon.csproj +++ b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/osu.Game.Rulesets.Pippidon.csproj @@ -1,6 +1,6 @@  - netstandard2.1 + net6.0 osu.Game.Rulesets.Pippidon Library AnyCPU @@ -12,4 +12,4 @@ - \ No newline at end of file + diff --git a/appveyor.yml b/appveyor.yml index 5be73f9875..ed48a997e8 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,6 +1,6 @@ clone_depth: 1 version: '{branch}-{build}' -image: Visual Studio 2019 +image: Visual Studio 2022 cache: - '%LOCALAPPDATA%\NuGet\v3-cache -> appveyor.yml' @@ -11,6 +11,8 @@ dotnet_csproj: before_build: - cmd: dotnet --info # Useful when version mismatch between CI and local + - cmd: dotnet workload install maui-android # Change to `dotnet workload restore` once there's no old projects + - cmd: dotnet workload install maui-ios # Change to `dotnet workload restore` once there's no old projects - cmd: nuget restore -verbosity quiet # Only nuget.exe knows both new (.NET Core) and old (Xamarin) projects build: diff --git a/appveyor_deploy.yml b/appveyor_deploy.yml index adf98848bc..175c8d0f1b 100644 --- a/appveyor_deploy.yml +++ b/appveyor_deploy.yml @@ -1,6 +1,6 @@ clone_depth: 1 version: '{build}' -image: Visual Studio 2019 +image: Visual Studio 2022 test: off skip_non_tags: true configuration: Release @@ -83,4 +83,4 @@ artifacts: deploy: - provider: Environment - name: nuget \ No newline at end of file + name: nuget diff --git a/osu.Android.props b/osu.Android.props index 647c7b179c..c6cf7812d1 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -1,61 +1,20 @@  - 8.0 - bin\$(Configuration) - 4 - 2.0 - false - false - Library - 512 - Off - True - Xamarin.Android.Net.AndroidClientHandler - v10.0 - false - true - armeabi-v7a;x86;arm64-v8a - true - cjk,mideast,other,rare,west - SdkOnly - prompt - - - True - portable - False - DEBUG;TRACE - false - true - false - - - false - None - True - false - False + 21.0 + android-x86;android-arm;android-arm64 + apk + CJK;Mideast;Rare;West;Other; + Xamarin.Android.Net.AndroidMessageHandler + + true true - - osu.licenseheader - - - - - - - - - - - - - - - - - + + + + true + diff --git a/osu.Android/AndroidJoystickSettings.cs b/osu.Android/AndroidJoystickSettings.cs index 26e921a426..bf69461f0d 100644 --- a/osu.Android/AndroidJoystickSettings.cs +++ b/osu.Android/AndroidJoystickSettings.cs @@ -11,7 +11,7 @@ using osu.Game.Overlays.Settings; namespace osu.Android { - public class AndroidJoystickSettings : SettingsSubsection + public partial class AndroidJoystickSettings : SettingsSubsection { protected override LocalisableString Header => JoystickSettingsStrings.JoystickGamepad; diff --git a/osu.Android/Properties/AndroidManifest.xml b/osu.Android/AndroidManifest.xml similarity index 68% rename from osu.Android/Properties/AndroidManifest.xml rename to osu.Android/AndroidManifest.xml index 165a64a424..bc2f49b1a9 100644 --- a/osu.Android/Properties/AndroidManifest.xml +++ b/osu.Android/AndroidManifest.xml @@ -1,5 +1,5 @@  - - + + \ No newline at end of file diff --git a/osu.Android/AndroidMouseSettings.cs b/osu.Android/AndroidMouseSettings.cs index 54b787fd17..d6d7750448 100644 --- a/osu.Android/AndroidMouseSettings.cs +++ b/osu.Android/AndroidMouseSettings.cs @@ -14,7 +14,7 @@ using osu.Game.Overlays.Settings.Sections.Input; namespace osu.Android { - public class AndroidMouseSettings : SettingsSubsection + public partial class AndroidMouseSettings : SettingsSubsection { private readonly AndroidMouseHandler mouseHandler; diff --git a/osu.Android/GameplayScreenRotationLocker.cs b/osu.Android/GameplayScreenRotationLocker.cs index 9e849bdc7c..3c39a820cc 100644 --- a/osu.Android/GameplayScreenRotationLocker.cs +++ b/osu.Android/GameplayScreenRotationLocker.cs @@ -11,7 +11,7 @@ using osu.Game; namespace osu.Android { - public class GameplayScreenRotationLocker : Component + public partial class GameplayScreenRotationLocker : Component { private Bindable localUserPlaying; diff --git a/osu.Android/OsuGameActivity.cs b/osu.Android/OsuGameActivity.cs index be40db7508..ca3d628447 100644 --- a/osu.Android/OsuGameActivity.cs +++ b/osu.Android/OsuGameActivity.cs @@ -7,6 +7,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Reflection; using System.Threading.Tasks; using Android.App; using Android.Content; @@ -74,11 +75,23 @@ namespace osu.Android Debug.Assert(Resources?.DisplayMetrics != null); Point displaySize = new Point(); +#pragma warning disable 618 // GetSize is deprecated WindowManager.DefaultDisplay.GetSize(displaySize); +#pragma warning restore 618 float smallestWidthDp = Math.Min(displaySize.X, displaySize.Y) / Resources.DisplayMetrics.Density; bool isTablet = smallestWidthDp >= 600f; RequestedOrientation = DefaultOrientation = isTablet ? ScreenOrientation.FullUser : ScreenOrientation.SensorLandscape; + + // Currently (SDK 6.0.200), BundleAssemblies is not runnable for net6-android. + // The assembly files are not available as files either after native AOT. + // Manually load them so that they can be loaded by RulesetStore.loadFromAppDomain. + // REMEMBER to fully uninstall previous version every time when investigating this! + // Don't forget osu.Game.Tests.Android too. + Assembly.Load("osu.Game.Rulesets.Osu"); + Assembly.Load("osu.Game.Rulesets.Taiko"); + Assembly.Load("osu.Game.Rulesets.Catch"); + Assembly.Load("osu.Game.Rulesets.Mania"); } protected override void OnNewIntent(Intent intent) => handleIntent(intent); @@ -127,7 +140,7 @@ namespace osu.Android cursor.MoveToFirst(); - int filenameColumn = cursor.GetColumnIndex(OpenableColumns.DisplayName); + int filenameColumn = cursor.GetColumnIndex(IOpenableColumns.DisplayName); string filename = cursor.GetString(filenameColumn); // SharpCompress requires archive streams to be seekable, which the stream opened by diff --git a/osu.Android/OsuGameAndroid.cs b/osu.Android/OsuGameAndroid.cs index 6b88f21bcd..0227d2aec2 100644 --- a/osu.Android/OsuGameAndroid.cs +++ b/osu.Android/OsuGameAndroid.cs @@ -5,7 +5,7 @@ using System; using Android.App; -using Android.OS; +using Microsoft.Maui.Devices; using osu.Framework.Allocation; using osu.Framework.Android.Input; using osu.Framework.Input.Handlers; @@ -14,11 +14,10 @@ using osu.Game; using osu.Game.Overlays.Settings; using osu.Game.Updater; using osu.Game.Utils; -using Xamarin.Essentials; namespace osu.Android { - public class OsuGameAndroid : OsuGame + public partial class OsuGameAndroid : OsuGame { [Cached] private readonly OsuGameActivity gameActivity; @@ -48,7 +47,7 @@ namespace osu.Android // https://stackoverflow.com/questions/52977079/android-sdk-28-versioncode-in-packageinfo-has-been-deprecated string versionName = string.Empty; - if (Build.VERSION.SdkInt >= BuildVersionCodes.P) + if (OperatingSystem.IsAndroidVersionAtLeast(28)) { versionName = packageInfo.LongVersionCode.ToString(); // ensure we only read the trailing portion of long (the part we are interested in). diff --git a/osu.Android/osu.Android.csproj b/osu.Android/osu.Android.csproj index 004cc8c39c..1507bfaa29 100644 --- a/osu.Android/osu.Android.csproj +++ b/osu.Android/osu.Android.csproj @@ -1,73 +1,22 @@ - - + - Debug - AnyCPU - 8.0.30703 - 2.0 - {D1D5F9A8-B40B-40E6-B02F-482D03346D3D} - {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - {122416d6-6b49-4ee2-a1e8-b825f31c79fe} + net6.0-android + Exe osu.Android osu.Android - Properties\AndroidManifest.xml - armeabi-v7a;x86;arm64-v8a - false - - - cjk;mideast;other;rare;west - d8 - r8 - - - None - cjk;mideast;other;rare;west - true + true + + false + 0.0.0 + 1 + $(Version) - - - - - - + + + + + - - - - - - {58f6c80c-1253-4a0e-a465-b8c85ebeadf3} - osu.Game.Rulesets.Catch - - - {48f4582b-7687-4621-9cbe-5c24197cb536} - osu.Game.Rulesets.Mania - - - {c92a607b-1fdd-4954-9f92-03ff547d9080} - osu.Game.Rulesets.Osu - - - {f167e17a-7de6-4af5-b920-a5112296c695} - osu.Game.Rulesets.Taiko - - - {2a66dd92-adb1-4994-89e2-c94e04acda0d} - osu.Game - - - - - - - - 5.0.0 - - - - - - - \ No newline at end of file + diff --git a/osu.Desktop/DiscordRichPresence.cs b/osu.Desktop/DiscordRichPresence.cs index 9cf68d88d9..2c4577f239 100644 --- a/osu.Desktop/DiscordRichPresence.cs +++ b/osu.Desktop/DiscordRichPresence.cs @@ -20,7 +20,7 @@ using LogLevel = osu.Framework.Logging.LogLevel; namespace osu.Desktop { - internal class DiscordRichPresence : Component + internal partial class DiscordRichPresence : Component { private const string client_id = "367827983903490050"; diff --git a/osu.Desktop/OsuGameDesktop.cs b/osu.Desktop/OsuGameDesktop.cs index 09f7292845..4c93c2286f 100644 --- a/osu.Desktop/OsuGameDesktop.cs +++ b/osu.Desktop/OsuGameDesktop.cs @@ -26,7 +26,7 @@ using SDL2; namespace osu.Desktop { - internal class OsuGameDesktop : OsuGame + internal partial class OsuGameDesktop : OsuGame { private OsuSchemeLinkIPCChannel? osuSchemeLinkIPCChannel; diff --git a/osu.Desktop/Security/ElevatedPrivilegesChecker.cs b/osu.Desktop/Security/ElevatedPrivilegesChecker.cs index cc4337fb02..6665733656 100644 --- a/osu.Desktop/Security/ElevatedPrivilegesChecker.cs +++ b/osu.Desktop/Security/ElevatedPrivilegesChecker.cs @@ -16,7 +16,7 @@ namespace osu.Desktop.Security /// /// Checks if the game is running with elevated privileges (as admin in Windows, root in Unix) and displays a warning notification if so. /// - public class ElevatedPrivilegesChecker : Component + public partial class ElevatedPrivilegesChecker : Component { [Resolved] private INotificationOverlay notifications { get; set; } = null!; @@ -63,7 +63,7 @@ namespace osu.Desktop.Security return false; } - private class ElevatedPrivilegesNotification : SimpleNotification + private partial class ElevatedPrivilegesNotification : SimpleNotification { public override bool IsImportant => true; diff --git a/osu.Desktop/Updater/SquirrelUpdateManager.cs b/osu.Desktop/Updater/SquirrelUpdateManager.cs index 84bac9da7c..3d4db88471 100644 --- a/osu.Desktop/Updater/SquirrelUpdateManager.cs +++ b/osu.Desktop/Updater/SquirrelUpdateManager.cs @@ -17,7 +17,7 @@ using UpdateManager = osu.Game.Updater.UpdateManager; namespace osu.Desktop.Updater { [SupportedOSPlatform("windows")] - public class SquirrelUpdateManager : UpdateManager + public partial class SquirrelUpdateManager : UpdateManager { private Squirrel.UpdateManager? updateManager; private INotificationOverlay notificationOverlay = null!; diff --git a/osu.Desktop/Windows/GameplayWinKeyBlocker.cs b/osu.Desktop/Windows/GameplayWinKeyBlocker.cs index 284d25306d..560f6fdd7f 100644 --- a/osu.Desktop/Windows/GameplayWinKeyBlocker.cs +++ b/osu.Desktop/Windows/GameplayWinKeyBlocker.cs @@ -10,7 +10,7 @@ using osu.Game.Screens.Play; namespace osu.Desktop.Windows { - public class GameplayWinKeyBlocker : Component + public partial class GameplayWinKeyBlocker : Component { private Bindable disableWinKey = null!; private IBindable localUserPlaying = null!; diff --git a/osu.Game.Rulesets.Catch.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Rulesets.Catch.Tests.Android/AndroidManifest.xml similarity index 96% rename from osu.Game.Rulesets.Catch.Tests.Android/Properties/AndroidManifest.xml rename to osu.Game.Rulesets.Catch.Tests.Android/AndroidManifest.xml index f8c3fcd894..bf7c0bfeca 100644 --- a/osu.Game.Rulesets.Catch.Tests.Android/Properties/AndroidManifest.xml +++ b/osu.Game.Rulesets.Catch.Tests.Android/AndroidManifest.xml @@ -1,6 +1,6 @@  - + \ No newline at end of file diff --git a/osu.Game.Rulesets.Catch.Tests.Android/osu.Game.Rulesets.Catch.Tests.Android.csproj b/osu.Game.Rulesets.Catch.Tests.Android/osu.Game.Rulesets.Catch.Tests.Android.csproj index 94fdba4a3e..4ee3219442 100644 --- a/osu.Game.Rulesets.Catch.Tests.Android/osu.Game.Rulesets.Catch.Tests.Android.csproj +++ b/osu.Game.Rulesets.Catch.Tests.Android/osu.Game.Rulesets.Catch.Tests.Android.csproj @@ -1,49 +1,24 @@ - - + - Debug - AnyCPU - 8.0.30703 - 2.0 - {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D} - {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - {122416d6-6b49-4ee2-a1e8-b825f31c79fe} + net6.0-android + Exe osu.Game.Rulesets.Catch.Tests osu.Game.Rulesets.Catch.Tests.Android - Properties\AndroidManifest.xml - armeabi-v7a;x86;arm64-v8a - - - None - cjk;mideast;other;rare;west - true - - - - - - - + %(RecursiveDir)%(Filename)%(Extension) + + + %(RecursiveDir)%(Filename)%(Extension) + Android\%(RecursiveDir)%(Filename)%(Extension) + - - {58f6c80c-1253-4a0e-a465-b8c85ebeadf3} - osu.Game.Rulesets.Catch - - - {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D} - osu.Game - + + - - - 5.0.0 - - - \ No newline at end of file diff --git a/osu.Game.Rulesets.Catch.Tests.iOS/Application.cs b/osu.Game.Rulesets.Catch.Tests.iOS/Application.cs index 71d943ece1..1fcb0aa427 100644 --- a/osu.Game.Rulesets.Catch.Tests.iOS/Application.cs +++ b/osu.Game.Rulesets.Catch.Tests.iOS/Application.cs @@ -3,7 +3,6 @@ #nullable disable -using osu.Framework.iOS; using UIKit; namespace osu.Game.Rulesets.Catch.Tests.iOS @@ -12,7 +11,7 @@ namespace osu.Game.Rulesets.Catch.Tests.iOS { public static void Main(string[] args) { - UIApplication.Main(args, typeof(GameUIApplication), typeof(AppDelegate)); + UIApplication.Main(args, null, typeof(AppDelegate)); } } } diff --git a/osu.Game.Rulesets.Catch.Tests.iOS/Info.plist b/osu.Game.Rulesets.Catch.Tests.iOS/Info.plist index 16a2b99997..5ace6c07f5 100644 --- a/osu.Game.Rulesets.Catch.Tests.iOS/Info.plist +++ b/osu.Game.Rulesets.Catch.Tests.iOS/Info.plist @@ -13,7 +13,7 @@ LSRequiresIPhoneOS MinimumOSVersion - 10.0 + 13.4 UIDeviceFamily 1 diff --git a/osu.Game.Rulesets.Catch.Tests.iOS/osu.Game.Rulesets.Catch.Tests.iOS.csproj b/osu.Game.Rulesets.Catch.Tests.iOS/osu.Game.Rulesets.Catch.Tests.iOS.csproj index be6044bbd0..acf12bb0ac 100644 --- a/osu.Game.Rulesets.Catch.Tests.iOS/osu.Game.Rulesets.Catch.Tests.iOS.csproj +++ b/osu.Game.Rulesets.Catch.Tests.iOS/osu.Game.Rulesets.Catch.Tests.iOS.csproj @@ -1,35 +1,19 @@ - - + - Debug - iPhoneSimulator - {4004C7B7-1A62-43F1-9DF2-52450FA67E70} Exe + net6.0-ios + 13.4 osu.Game.Rulesets.Catch.Tests osu.Game.Rulesets.Catch.Tests.iOS - - - - Linker.xml - - - %(RecursiveDir)%(Filename)%(Extension) - - {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D} - osu.Game - - - {58F6C80C-1253-4A0E-A465-B8C85EBEADF3} - osu.Game.Rulesets.Catch - + + - - \ No newline at end of file + diff --git a/osu.Game.Rulesets.Catch.Tests/CatchSkinnableTestScene.cs b/osu.Game.Rulesets.Catch.Tests/CatchSkinnableTestScene.cs index be6622f06e..2af851a561 100644 --- a/osu.Game.Rulesets.Catch.Tests/CatchSkinnableTestScene.cs +++ b/osu.Game.Rulesets.Catch.Tests/CatchSkinnableTestScene.cs @@ -7,7 +7,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Catch.Tests { - public abstract class CatchSkinnableTestScene : SkinnableTestScene + public abstract partial class CatchSkinnableTestScene : SkinnableTestScene { protected override Ruleset CreateRulesetForSkinProvider() => new CatchRuleset(); } diff --git a/osu.Game.Rulesets.Catch.Tests/Editor/CatchEditorTestSceneContainer.cs b/osu.Game.Rulesets.Catch.Tests/Editor/CatchEditorTestSceneContainer.cs index 78f56b4937..39508359a4 100644 --- a/osu.Game.Rulesets.Catch.Tests/Editor/CatchEditorTestSceneContainer.cs +++ b/osu.Game.Rulesets.Catch.Tests/Editor/CatchEditorTestSceneContainer.cs @@ -16,7 +16,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Catch.Tests.Editor { - public class CatchEditorTestSceneContainer : Container + public partial class CatchEditorTestSceneContainer : Container { [Cached(typeof(Playfield))] public readonly ScrollingPlayfield Playfield; @@ -57,7 +57,7 @@ namespace osu.Game.Rulesets.Catch.Tests.Editor }; } - private class TestCatchPlayfield : CatchEditorPlayfield + private partial class TestCatchPlayfield : CatchEditorPlayfield { public TestCatchPlayfield() : base(new BeatmapDifficulty { CircleSize = 0 }) diff --git a/osu.Game.Rulesets.Catch.Tests/Editor/CatchPlacementBlueprintTestScene.cs b/osu.Game.Rulesets.Catch.Tests/Editor/CatchPlacementBlueprintTestScene.cs index 9060fa5aa0..aae759d934 100644 --- a/osu.Game.Rulesets.Catch.Tests/Editor/CatchPlacementBlueprintTestScene.cs +++ b/osu.Game.Rulesets.Catch.Tests/Editor/CatchPlacementBlueprintTestScene.cs @@ -21,7 +21,7 @@ using osuTK.Input; namespace osu.Game.Rulesets.Catch.Tests.Editor { - public abstract class CatchPlacementBlueprintTestScene : PlacementBlueprintTestScene + public abstract partial class CatchPlacementBlueprintTestScene : PlacementBlueprintTestScene { protected const double TIME_SNAP = 100; diff --git a/osu.Game.Rulesets.Catch.Tests/Editor/CatchSelectionBlueprintTestScene.cs b/osu.Game.Rulesets.Catch.Tests/Editor/CatchSelectionBlueprintTestScene.cs index 60fb31d1e0..033dca587e 100644 --- a/osu.Game.Rulesets.Catch.Tests/Editor/CatchSelectionBlueprintTestScene.cs +++ b/osu.Game.Rulesets.Catch.Tests/Editor/CatchSelectionBlueprintTestScene.cs @@ -17,7 +17,7 @@ using osuTK; namespace osu.Game.Rulesets.Catch.Tests.Editor { - public abstract class CatchSelectionBlueprintTestScene : SelectionBlueprintTestScene + public abstract partial class CatchSelectionBlueprintTestScene : SelectionBlueprintTestScene { protected ScrollingHitObjectContainer HitObjectContainer => contentContainer.Playfield.HitObjectContainer; @@ -62,7 +62,7 @@ namespace osu.Game.Rulesets.Catch.Tests.Editor InputManager.MoveMouseTo(pos); }); - private class EditorBeatmapDependencyContainer : Container + private partial class EditorBeatmapDependencyContainer : Container { [Cached] private readonly EditorClock editorClock; diff --git a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneBananaShowerPlacementBlueprint.cs b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneBananaShowerPlacementBlueprint.cs index d08acc90cd..2db4102513 100644 --- a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneBananaShowerPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneBananaShowerPlacementBlueprint.cs @@ -20,7 +20,7 @@ using osuTK.Input; namespace osu.Game.Rulesets.Catch.Tests.Editor { - public class TestSceneBananaShowerPlacementBlueprint : CatchPlacementBlueprintTestScene + public partial class TestSceneBananaShowerPlacementBlueprint : CatchPlacementBlueprintTestScene { protected override DrawableHitObject CreateHitObject(HitObject hitObject) => new DrawableBananaShower((BananaShower)hitObject); diff --git a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneCatchDistanceSnapGrid.cs b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneCatchDistanceSnapGrid.cs index 405bab971c..1e057cf3fb 100644 --- a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneCatchDistanceSnapGrid.cs +++ b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneCatchDistanceSnapGrid.cs @@ -20,7 +20,7 @@ using osuTK; namespace osu.Game.Rulesets.Catch.Tests.Editor { - public class TestSceneCatchDistanceSnapGrid : OsuManualInputManagerTestScene + public partial class TestSceneCatchDistanceSnapGrid : OsuManualInputManagerTestScene { private readonly ManualClock manualClock = new ManualClock(); diff --git a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneEditor.cs b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneEditor.cs index 9ecfd5f5c5..5593f3d319 100644 --- a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneEditor.cs +++ b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneEditor.cs @@ -9,7 +9,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Catch.Tests.Editor { [TestFixture] - public class TestSceneEditor : EditorTestScene + public partial class TestSceneEditor : EditorTestScene { protected override Ruleset CreateEditorRuleset() => new CatchRuleset(); } diff --git a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneFruitPlacementBlueprint.cs b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneFruitPlacementBlueprint.cs index 94574b564d..93b24d92fb 100644 --- a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneFruitPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneFruitPlacementBlueprint.cs @@ -17,7 +17,7 @@ using osuTK.Input; namespace osu.Game.Rulesets.Catch.Tests.Editor { - public class TestSceneFruitPlacementBlueprint : CatchPlacementBlueprintTestScene + public partial class TestSceneFruitPlacementBlueprint : CatchPlacementBlueprintTestScene { protected override DrawableHitObject CreateHitObject(HitObject hitObject) => new DrawableFruit((Fruit)hitObject); diff --git a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamPlacementBlueprint.cs b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamPlacementBlueprint.cs index 691ebc7efc..18d3d29bdc 100644 --- a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamPlacementBlueprint.cs @@ -19,7 +19,7 @@ using osuTK.Input; namespace osu.Game.Rulesets.Catch.Tests.Editor { - public class TestSceneJuiceStreamPlacementBlueprint : CatchPlacementBlueprintTestScene + public partial class TestSceneJuiceStreamPlacementBlueprint : CatchPlacementBlueprintTestScene { private const double velocity_factor = 0.5; diff --git a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamSelectionBlueprint.cs b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamSelectionBlueprint.cs index 8635a88d79..f25b66c360 100644 --- a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamSelectionBlueprint.cs @@ -19,7 +19,7 @@ using osuTK.Input; namespace osu.Game.Rulesets.Catch.Tests.Editor { - public class TestSceneJuiceStreamSelectionBlueprint : CatchSelectionBlueprintTestScene + public partial class TestSceneJuiceStreamSelectionBlueprint : CatchSelectionBlueprintTestScene { private JuiceStream hitObject; diff --git a/osu.Game.Rulesets.Catch.Tests/Mods/TestSceneCatchModFlashlight.cs b/osu.Game.Rulesets.Catch.Tests/Mods/TestSceneCatchModFlashlight.cs index 538fc7fac6..f89ed5ce8e 100644 --- a/osu.Game.Rulesets.Catch.Tests/Mods/TestSceneCatchModFlashlight.cs +++ b/osu.Game.Rulesets.Catch.Tests/Mods/TestSceneCatchModFlashlight.cs @@ -7,7 +7,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Catch.Tests.Mods { - public class TestSceneCatchModFlashlight : ModTestScene + public partial class TestSceneCatchModFlashlight : ModTestScene { protected override Ruleset CreatePlayerRuleset() => new CatchRuleset(); diff --git a/osu.Game.Rulesets.Catch.Tests/Mods/TestSceneCatchModNoScope.cs b/osu.Game.Rulesets.Catch.Tests/Mods/TestSceneCatchModNoScope.cs index bbe543e73e..c48bf7adc9 100644 --- a/osu.Game.Rulesets.Catch.Tests/Mods/TestSceneCatchModNoScope.cs +++ b/osu.Game.Rulesets.Catch.Tests/Mods/TestSceneCatchModNoScope.cs @@ -14,10 +14,40 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Catch.Tests.Mods { - public class TestSceneCatchModNoScope : ModTestScene + public partial class TestSceneCatchModNoScope : ModTestScene { protected override Ruleset CreatePlayerRuleset() => new CatchRuleset(); + [Test] + public void TestAlwaysHidden() + { + CreateModTest(new ModTestData + { + Mod = new CatchModNoScope + { + HiddenComboCount = { Value = 0 }, + }, + Autoplay = true, + PassCondition = () => Player.ScoreProcessor.Combo.Value == 2, + Beatmap = new Beatmap + { + HitObjects = new List + { + new Fruit + { + X = CatchPlayfield.CENTER_X * 0.5f, + StartTime = 1000, + }, + new Fruit + { + X = CatchPlayfield.CENTER_X * 1.5f, + StartTime = 2000, + } + } + } + }); + } + [Test] public void TestVisibleDuringBreak() { diff --git a/osu.Game.Rulesets.Catch.Tests/Mods/TestSceneCatchModPerfect.cs b/osu.Game.Rulesets.Catch.Tests/Mods/TestSceneCatchModPerfect.cs index 3e06e78dba..71df523951 100644 --- a/osu.Game.Rulesets.Catch.Tests/Mods/TestSceneCatchModPerfect.cs +++ b/osu.Game.Rulesets.Catch.Tests/Mods/TestSceneCatchModPerfect.cs @@ -11,7 +11,7 @@ using osuTK; namespace osu.Game.Rulesets.Catch.Tests.Mods { - public class TestSceneCatchModPerfect : ModPerfectTestScene + public partial class TestSceneCatchModPerfect : ModPerfectTestScene { protected override Ruleset CreatePlayerRuleset() => new CatchRuleset(); diff --git a/osu.Game.Rulesets.Catch.Tests/Mods/TestSceneCatchModRelax.cs b/osu.Game.Rulesets.Catch.Tests/Mods/TestSceneCatchModRelax.cs index c01aff0aa0..5835ccaf78 100644 --- a/osu.Game.Rulesets.Catch.Tests/Mods/TestSceneCatchModRelax.cs +++ b/osu.Game.Rulesets.Catch.Tests/Mods/TestSceneCatchModRelax.cs @@ -4,8 +4,10 @@ using System.Collections.Generic; using System.Linq; using NUnit.Framework; +using osu.Framework.Graphics.Containers; using osu.Framework.Testing; using osu.Game.Beatmaps; +using osu.Game.Graphics.Cursor; using osu.Game.Rulesets.Catch.Mods; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.UI; @@ -16,7 +18,7 @@ using osuTK; namespace osu.Game.Rulesets.Catch.Tests.Mods { - public class TestSceneCatchModRelax : ModTestScene + public partial class TestSceneCatchModRelax : ModTestScene { protected override Ruleset CreatePlayerRuleset() => new CatchRuleset(); @@ -55,6 +57,21 @@ namespace osu.Game.Rulesets.Catch.Tests.Mods } }); + [Test] + public void TestGameCursorHidden() + { + CreateModTest(new ModTestData + { + Mod = new CatchModRelax(), + Autoplay = false, + PassCondition = () => + { + InputManager.MoveMouseTo(this.ChildrenOfType().Single()); + return this.ChildrenOfType().Single().State.Value == Visibility.Hidden; + } + }); + } + private bool passCondition() { var playfield = this.ChildrenOfType().Single(); diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs index 202228c9e7..40dc7d2403 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs @@ -16,7 +16,7 @@ using osuTK; namespace osu.Game.Rulesets.Catch.Tests { - public class TestSceneAutoJuiceStream : TestSceneCatchPlayer + public partial class TestSceneAutoJuiceStream : TestSceneCatchPlayer { protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) { diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneBananaShower.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneBananaShower.cs index 0ddc58eb25..402f8f548d 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneBananaShower.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneBananaShower.cs @@ -10,7 +10,7 @@ using osu.Game.Rulesets.Catch.Objects; namespace osu.Game.Rulesets.Catch.Tests { [TestFixture] - public class TestSceneBananaShower : TestSceneCatchPlayer + public partial class TestSceneBananaShower : TestSceneCatchPlayer { [Test] public void TestBananaShower() diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchModHidden.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchModHidden.cs index 7e1c39f6a8..05d3361dc3 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchModHidden.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchModHidden.cs @@ -19,7 +19,7 @@ using osuTK; namespace osu.Game.Rulesets.Catch.Tests { - public class TestSceneCatchModHidden : ModTestScene + public partial class TestSceneCatchModHidden : ModTestScene { [Test] public void TestJuiceStream() diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchPlayer.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchPlayer.cs index 16942f3f35..01cce88d9d 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchPlayer.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchPlayer.cs @@ -9,7 +9,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Catch.Tests { [TestFixture] - public class TestSceneCatchPlayer : PlayerTestScene + public partial class TestSceneCatchPlayer : PlayerTestScene { protected override Ruleset CreatePlayerRuleset() => new CatchRuleset(); } diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchPlayerLegacySkin.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchPlayerLegacySkin.cs index 2078e1453f..8f3f39be9b 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchPlayerLegacySkin.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchPlayerLegacySkin.cs @@ -16,7 +16,7 @@ using osuTK; namespace osu.Game.Rulesets.Catch.Tests { [TestFixture] - public class TestSceneCatchPlayerLegacySkin : LegacySkinPlayerTestScene + public partial class TestSceneCatchPlayerLegacySkin : LegacySkinPlayerTestScene { protected override Ruleset CreatePlayerRuleset() => new CatchRuleset(); diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchReplay.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchReplay.cs index 6e12dacf29..cbf900ebc0 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchReplay.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchReplay.cs @@ -11,7 +11,7 @@ using osu.Game.Rulesets.Catch.UI; namespace osu.Game.Rulesets.Catch.Tests { - public class TestSceneCatchReplay : TestSceneCatchPlayer + public partial class TestSceneCatchReplay : TestSceneCatchPlayer { protected override bool Autoplay => true; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchSkinConfiguration.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchSkinConfiguration.cs index a2d4e7fb1e..75ab4ad9d2 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchSkinConfiguration.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchSkinConfiguration.cs @@ -23,7 +23,7 @@ using Direction = osu.Game.Rulesets.Catch.UI.Direction; namespace osu.Game.Rulesets.Catch.Tests { - public class TestSceneCatchSkinConfiguration : OsuTestScene + public partial class TestSceneCatchSkinConfiguration : OsuTestScene { private Catcher catcher; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchStacker.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchStacker.cs index 1405e0018d..c8979381fe 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchStacker.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchStacker.cs @@ -11,7 +11,7 @@ using osu.Game.Rulesets.Catch.UI; namespace osu.Game.Rulesets.Catch.Tests { [TestFixture] - public class TestSceneCatchStacker : TestSceneCatchPlayer + public partial class TestSceneCatchStacker : TestSceneCatchPlayer { protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) { diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchTouchInput.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchTouchInput.cs index cf6a8169c4..836adcc912 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchTouchInput.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchTouchInput.cs @@ -15,7 +15,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Catch.Tests { [TestFixture] - public class TestSceneCatchTouchInput : OsuTestScene + public partial class TestSceneCatchTouchInput : OsuTestScene { [Test] public void TestBasic() diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs index 2dc99077d3..e8231b07ad 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs @@ -27,7 +27,7 @@ using osuTK; namespace osu.Game.Rulesets.Catch.Tests { [TestFixture] - public class TestSceneCatcher : OsuTestScene + public partial class TestSceneCatcher : OsuTestScene { [Resolved] private OsuConfigManager config { get; set; } @@ -324,7 +324,7 @@ namespace osu.Game.Rulesets.Catch.Tests } } - public class TestCatcher : Catcher + public partial class TestCatcher : Catcher { public IEnumerable CaughtObjects => this.ChildrenOfType(); diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs index 150c1f8406..99c2fc570d 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs @@ -23,7 +23,7 @@ using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Catch.Tests { [TestFixture] - public class TestSceneCatcherArea : CatchSkinnableTestScene + public partial class TestSceneCatcherArea : CatchSkinnableTestScene { private RulesetInfo catchRuleset; @@ -120,7 +120,7 @@ namespace osu.Game.Rulesets.Catch.Tests catchRuleset = rulesets.GetRuleset(2); } - private class TestCatcherArea : CatcherArea + private partial class TestCatcherArea : CatcherArea { public TestCatcherArea(IBeatmapDifficultyInfo beatmapDifficulty) { diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneComboCounter.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneComboCounter.cs index f3161f32be..391297a252 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneComboCounter.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneComboCounter.cs @@ -19,7 +19,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Catch.Tests { - public class TestSceneComboCounter : CatchSkinnableTestScene + public partial class TestSceneComboCounter : CatchSkinnableTestScene { private ScoreProcessor scoreProcessor = null!; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs index 94c870a444..11d6419507 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs @@ -21,7 +21,7 @@ using osuTK; namespace osu.Game.Rulesets.Catch.Tests { - public class TestSceneDrawableHitObjects : OsuTestScene + public partial class TestSceneDrawableHitObjects : OsuTestScene { private DrawableCatchRuleset drawableRuleset; private double playfieldTime => drawableRuleset.Playfield.Time.Current; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjectsHidden.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjectsHidden.cs index 868f498e8c..007f309f3f 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjectsHidden.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjectsHidden.cs @@ -8,7 +8,7 @@ using osu.Game.Rulesets.Catch.Mods; namespace osu.Game.Rulesets.Catch.Tests { - public class TestSceneDrawableHitObjectsHidden : TestSceneDrawableHitObjects + public partial class TestSceneDrawableHitObjectsHidden : TestSceneDrawableHitObjects { [SetUp] public void SetUp() => Schedule(() => diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneFruitObjects.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneFruitObjects.cs index 7d72633e34..223c4e57fc 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneFruitObjects.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneFruitObjects.cs @@ -15,7 +15,7 @@ using osu.Game.Rulesets.Catch.Objects.Drawables; namespace osu.Game.Rulesets.Catch.Tests { [TestFixture] - public class TestSceneFruitObjects : CatchSkinnableTestScene + public partial class TestSceneFruitObjects : CatchSkinnableTestScene { protected override void LoadComplete() { @@ -58,7 +58,7 @@ namespace osu.Game.Rulesets.Catch.Tests private Drawable createDrawableTinyDroplet() => new TestDrawableCatchHitObjectSpecimen(new DrawableTinyDroplet(new TinyDroplet())); } - public class TestDrawableCatchHitObjectSpecimen : CompositeDrawable + public partial class TestDrawableCatchHitObjectSpecimen : CompositeDrawable { public readonly ManualClock ManualClock; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneFruitRandomness.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneFruitRandomness.cs index c7d130b440..995daaceb1 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneFruitRandomness.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneFruitRandomness.cs @@ -12,7 +12,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Catch.Tests { - public class TestSceneFruitRandomness : OsuTestScene + public partial class TestSceneFruitRandomness : OsuTestScene { private readonly DrawableFruit drawableFruit; private readonly DrawableBanana drawableBanana; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneFruitVisualChange.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneFruitVisualChange.cs index f7abd8d519..4b2873e0a8 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneFruitVisualChange.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneFruitVisualChange.cs @@ -9,7 +9,7 @@ using osu.Game.Rulesets.Catch.Objects.Drawables; namespace osu.Game.Rulesets.Catch.Tests { - public class TestSceneFruitVisualChange : TestSceneFruitObjects + public partial class TestSceneFruitVisualChange : TestSceneFruitObjects { private readonly Bindable indexInBeatmap = new Bindable(); private readonly Bindable hyperDash = new Bindable(); diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDash.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDash.cs index 4886942dc6..f8c43a221e 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDash.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDash.cs @@ -17,7 +17,7 @@ using osuTK; namespace osu.Game.Rulesets.Catch.Tests { [TestFixture] - public class TestSceneHyperDash : TestSceneCatchPlayer + public partial class TestSceneHyperDash : TestSceneCatchPlayer { protected override bool Autoplay => true; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDashColouring.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDashColouring.cs index cf49b7fe12..b343174e6b 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDashColouring.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDashColouring.cs @@ -24,7 +24,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Catch.Tests { - public class TestSceneHyperDashColouring : OsuTestScene + public partial class TestSceneHyperDashColouring : OsuTestScene { [Resolved] private SkinManager skins { get; set; } diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneJuiceStream.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneJuiceStream.cs index 81589459c4..c91f07891c 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneJuiceStream.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneJuiceStream.cs @@ -14,7 +14,7 @@ using osuTK; namespace osu.Game.Rulesets.Catch.Tests { - public class TestSceneJuiceStream : TestSceneCatchPlayer + public partial class TestSceneJuiceStream : TestSceneCatchPlayer { [Test] public void TestJuiceStreamEndingCombo() diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneLegacyBeatmapSkin.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneLegacyBeatmapSkin.cs index 786353bb00..aa66fc8741 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneLegacyBeatmapSkin.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneLegacyBeatmapSkin.cs @@ -18,7 +18,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Catch.Tests { - public class TestSceneLegacyBeatmapSkin : LegacyBeatmapSkinColourTest + public partial class TestSceneLegacyBeatmapSkin : LegacyBeatmapSkinColourTest { [Resolved] private AudioManager audio { get; set; } @@ -105,7 +105,7 @@ namespace osu.Game.Rulesets.Catch.Tests protected override ExposedPlayer CreateTestPlayer(bool userHasCustomColours) => new CatchExposedPlayer(userHasCustomColours); - private class CatchExposedPlayer : ExposedPlayer + private partial class CatchExposedPlayer : ExposedPlayer { public CatchExposedPlayer(bool userHasCustomColours) : base(userHasCustomColours) diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmap.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmap.cs index ac39b91f00..f009c10a9c 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmap.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmap.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Collections.Generic; using System.Linq; using osu.Game.Beatmaps; diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs index 9f5d007114..7774a7da09 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Objects; using System.Collections.Generic; diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs index 835f7c2d27..ab61b14ac4 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Rulesets.Catch/CatchInputManager.cs b/osu.Game.Rulesets.Catch/CatchInputManager.cs index 0f76953003..1ef9e55d2d 100644 --- a/osu.Game.Rulesets.Catch/CatchInputManager.cs +++ b/osu.Game.Rulesets.Catch/CatchInputManager.cs @@ -9,7 +9,7 @@ using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Catch { [Cached] - public class CatchInputManager : RulesetInputManager + public partial class CatchInputManager : RulesetInputManager { public CatchInputManager(RulesetInfo ruleset) : base(ruleset, 0, SimultaneousBindingMode.Unique) diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs index f37479f84a..42cfde268e 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; @@ -51,7 +49,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty protected override IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate) { - CatchHitObject lastObject = null; + CatchHitObject? lastObject = null; List objects = new List(); diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceAttributes.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceAttributes.cs index ccdfd30200..1335fc2d23 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceAttributes.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceAttributes.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Game.Rulesets.Difficulty; namespace osu.Game.Rulesets.Catch.Difficulty diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs index 2a07b8019e..b30b85be2d 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Rulesets.Catch/Difficulty/Preprocessing/CatchDifficultyHitObject.cs b/osu.Game.Rulesets.Catch/Difficulty/Preprocessing/CatchDifficultyHitObject.cs index c44480776f..3bcfce3a56 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/Preprocessing/CatchDifficultyHitObject.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/Preprocessing/CatchDifficultyHitObject.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Collections.Generic; using osu.Game.Rulesets.Catch.Objects; diff --git a/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs b/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs index 827c28f7de..cfb3fe40be 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using osu.Game.Rulesets.Catch.Difficulty.Preprocessing; using osu.Game.Rulesets.Difficulty.Preprocessing; diff --git a/osu.Game.Rulesets.Catch/Edit/BananaShowerCompositionTool.cs b/osu.Game.Rulesets.Catch/Edit/BananaShowerCompositionTool.cs index e64a51f03a..31075db7d1 100644 --- a/osu.Game.Rulesets.Catch/Edit/BananaShowerCompositionTool.cs +++ b/osu.Game.Rulesets.Catch/Edit/BananaShowerCompositionTool.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Edit.Blueprints; diff --git a/osu.Game.Rulesets.Catch/Edit/Blueprints/BananaShowerPlacementBlueprint.cs b/osu.Game.Rulesets.Catch/Edit/Blueprints/BananaShowerPlacementBlueprint.cs index 86fdf09a72..5f22ef5c12 100644 --- a/osu.Game.Rulesets.Catch/Edit/Blueprints/BananaShowerPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Catch/Edit/Blueprints/BananaShowerPlacementBlueprint.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using osu.Framework.Input.Events; using osu.Game.Rulesets.Catch.Edit.Blueprints.Components; @@ -12,7 +10,7 @@ using osuTK.Input; namespace osu.Game.Rulesets.Catch.Edit.Blueprints { - public class BananaShowerPlacementBlueprint : CatchPlacementBlueprint + public partial class BananaShowerPlacementBlueprint : CatchPlacementBlueprint { private readonly TimeSpanOutline outline; diff --git a/osu.Game.Rulesets.Catch/Edit/Blueprints/BananaShowerSelectionBlueprint.cs b/osu.Game.Rulesets.Catch/Edit/Blueprints/BananaShowerSelectionBlueprint.cs index 7e4aca180c..f6dd67889e 100644 --- a/osu.Game.Rulesets.Catch/Edit/Blueprints/BananaShowerSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Catch/Edit/Blueprints/BananaShowerSelectionBlueprint.cs @@ -1,13 +1,11 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Game.Rulesets.Catch.Objects; namespace osu.Game.Rulesets.Catch.Edit.Blueprints { - public class BananaShowerSelectionBlueprint : CatchSelectionBlueprint + public partial class BananaShowerSelectionBlueprint : CatchSelectionBlueprint { public BananaShowerSelectionBlueprint(BananaShower hitObject) : base(hitObject) diff --git a/osu.Game.Rulesets.Catch/Edit/Blueprints/CatchPlacementBlueprint.cs b/osu.Game.Rulesets.Catch/Edit/Blueprints/CatchPlacementBlueprint.cs index 8a1ced7eea..d2d605a6fe 100644 --- a/osu.Game.Rulesets.Catch/Edit/Blueprints/CatchPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Catch/Edit/Blueprints/CatchPlacementBlueprint.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Edit; @@ -12,7 +10,7 @@ using osuTK; namespace osu.Game.Rulesets.Catch.Edit.Blueprints { - public class CatchPlacementBlueprint : PlacementBlueprint + public partial class CatchPlacementBlueprint : PlacementBlueprint where THitObject : CatchHitObject, new() { protected new THitObject HitObject => (THitObject)base.HitObject; @@ -20,7 +18,7 @@ namespace osu.Game.Rulesets.Catch.Edit.Blueprints protected ScrollingHitObjectContainer HitObjectContainer => (ScrollingHitObjectContainer)playfield.HitObjectContainer; [Resolved] - private Playfield playfield { get; set; } + private Playfield playfield { get; set; } = null!; public CatchPlacementBlueprint() : base(new THitObject()) diff --git a/osu.Game.Rulesets.Catch/Edit/Blueprints/CatchSelectionBlueprint.cs b/osu.Game.Rulesets.Catch/Edit/Blueprints/CatchSelectionBlueprint.cs index e7c04cd132..8220fb88b4 100644 --- a/osu.Game.Rulesets.Catch/Edit/Blueprints/CatchSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Catch/Edit/Blueprints/CatchSelectionBlueprint.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Edit; @@ -12,7 +10,7 @@ using osuTK; namespace osu.Game.Rulesets.Catch.Edit.Blueprints { - public abstract class CatchSelectionBlueprint : HitObjectSelectionBlueprint + public abstract partial class CatchSelectionBlueprint : HitObjectSelectionBlueprint where THitObject : CatchHitObject { protected override bool AlwaysShowWhenSelected => true; @@ -31,7 +29,7 @@ namespace osu.Game.Rulesets.Catch.Edit.Blueprints protected ScrollingHitObjectContainer HitObjectContainer => (ScrollingHitObjectContainer)playfield.HitObjectContainer; [Resolved] - private Playfield playfield { get; set; } + private Playfield playfield { get; set; } = null!; protected CatchSelectionBlueprint(THitObject hitObject) : base(hitObject) diff --git a/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/EditablePath.cs b/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/EditablePath.cs index 8473eda663..74d6565600 100644 --- a/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/EditablePath.cs +++ b/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/EditablePath.cs @@ -1,13 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; -using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -20,7 +17,7 @@ using osuTK; namespace osu.Game.Rulesets.Catch.Edit.Blueprints.Components { - public abstract class EditablePath : CompositeDrawable + public abstract partial class EditablePath : CompositeDrawable { public int PathId => path.InvalidationID; @@ -42,9 +39,8 @@ namespace osu.Game.Rulesets.Catch.Edit.Blueprints.Components private readonly List previousVertexStates = new List(); - [Resolved(CanBeNull = true)] - [CanBeNull] - private IBeatSnapProvider beatSnapProvider { get; set; } + [Resolved] + private IBeatSnapProvider? beatSnapProvider { get; set; } protected EditablePath(Func positionToTime) { diff --git a/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/FruitOutline.cs b/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/FruitOutline.cs index 86006a99fc..c7805544ea 100644 --- a/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/FruitOutline.cs +++ b/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/FruitOutline.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -13,7 +11,7 @@ using osuTK; namespace osu.Game.Rulesets.Catch.Edit.Blueprints.Components { - public class FruitOutline : CompositeDrawable + public partial class FruitOutline : CompositeDrawable { public FruitOutline() { diff --git a/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/NestedOutlineContainer.cs b/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/NestedOutlineContainer.cs index a6f1732bc1..c1f46539fa 100644 --- a/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/NestedOutlineContainer.cs +++ b/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/NestedOutlineContainer.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Collections.Generic; using System.Linq; using osu.Framework.Graphics; @@ -13,7 +11,7 @@ using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Catch.Edit.Blueprints.Components { - public class NestedOutlineContainer : CompositeDrawable + public partial class NestedOutlineContainer : CompositeDrawable { private readonly List nestedHitObjects = new List(); diff --git a/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/PlacementEditablePath.cs b/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/PlacementEditablePath.cs index 27df064be4..3a7d6d87f2 100644 --- a/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/PlacementEditablePath.cs +++ b/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/PlacementEditablePath.cs @@ -1,15 +1,13 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using osu.Game.Rulesets.Catch.Objects; using osuTK; namespace osu.Game.Rulesets.Catch.Edit.Blueprints.Components { - public class PlacementEditablePath : EditablePath + public partial class PlacementEditablePath : EditablePath { /// /// The original position of the last added vertex. diff --git a/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/ScrollingPath.cs b/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/ScrollingPath.cs index 3a62b07816..a22abcb76d 100644 --- a/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/ScrollingPath.cs +++ b/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/ScrollingPath.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Collections.Generic; using System.Linq; using osu.Framework.Graphics; @@ -15,7 +13,7 @@ using osuTK; namespace osu.Game.Rulesets.Catch.Edit.Blueprints.Components { - public class ScrollingPath : CompositeDrawable + public partial class ScrollingPath : CompositeDrawable { private readonly Path drawablePath; diff --git a/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/SelectionEditablePath.cs b/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/SelectionEditablePath.cs index 4576e9f8ee..c7a26ca15a 100644 --- a/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/SelectionEditablePath.cs +++ b/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/SelectionEditablePath.cs @@ -1,12 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; -using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.UserInterface; @@ -18,16 +15,15 @@ using osuTK.Input; namespace osu.Game.Rulesets.Catch.Edit.Blueprints.Components { - public class SelectionEditablePath : EditablePath, IHasContextMenu + public partial class SelectionEditablePath : EditablePath, IHasContextMenu { public MenuItem[] ContextMenuItems => getContextMenuItems().ToArray(); // To handle when the editor is scrolled while dragging. private Vector2 dragStartPosition; - [Resolved(CanBeNull = true)] - [CanBeNull] - private IEditorChangeHandler changeHandler { get; set; } + [Resolved] + private IEditorChangeHandler? changeHandler { get; set; } public SelectionEditablePath(Func positionToTime) : base(positionToTime) diff --git a/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/TimeSpanOutline.cs b/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/TimeSpanOutline.cs index 2586a81ef5..9d450cd355 100644 --- a/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/TimeSpanOutline.cs +++ b/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/TimeSpanOutline.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -15,7 +13,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Catch.Edit.Blueprints.Components { - public class TimeSpanOutline : CompositeDrawable + public partial class TimeSpanOutline : CompositeDrawable { private const float border_width = 4; diff --git a/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/VertexPiece.cs b/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/VertexPiece.cs index 236d27753a..07d7c72698 100644 --- a/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/VertexPiece.cs +++ b/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/VertexPiece.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -12,10 +10,10 @@ using osuTK; namespace osu.Game.Rulesets.Catch.Edit.Blueprints.Components { - public class VertexPiece : Circle + public partial class VertexPiece : Circle { [Resolved] - private OsuColour osuColour { get; set; } + private OsuColour osuColour { get; set; } = null!; public VertexPiece() { diff --git a/osu.Game.Rulesets.Catch/Edit/Blueprints/FruitPlacementBlueprint.cs b/osu.Game.Rulesets.Catch/Edit/Blueprints/FruitPlacementBlueprint.cs index 686840ae55..72592891fb 100644 --- a/osu.Game.Rulesets.Catch/Edit/Blueprints/FruitPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Catch/Edit/Blueprints/FruitPlacementBlueprint.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Input.Events; using osu.Game.Rulesets.Catch.Edit.Blueprints.Components; using osu.Game.Rulesets.Catch.Objects; @@ -11,7 +9,7 @@ using osuTK.Input; namespace osu.Game.Rulesets.Catch.Edit.Blueprints { - public class FruitPlacementBlueprint : CatchPlacementBlueprint + public partial class FruitPlacementBlueprint : CatchPlacementBlueprint { private readonly FruitOutline outline; diff --git a/osu.Game.Rulesets.Catch/Edit/Blueprints/FruitSelectionBlueprint.cs b/osu.Game.Rulesets.Catch/Edit/Blueprints/FruitSelectionBlueprint.cs index b5a25dbf62..2737b283ef 100644 --- a/osu.Game.Rulesets.Catch/Edit/Blueprints/FruitSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Catch/Edit/Blueprints/FruitSelectionBlueprint.cs @@ -1,14 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Game.Rulesets.Catch.Edit.Blueprints.Components; using osu.Game.Rulesets.Catch.Objects; namespace osu.Game.Rulesets.Catch.Edit.Blueprints { - public class FruitSelectionBlueprint : CatchSelectionBlueprint + public partial class FruitSelectionBlueprint : CatchSelectionBlueprint { private readonly FruitOutline outline; diff --git a/osu.Game.Rulesets.Catch/Edit/Blueprints/JuiceStreamPlacementBlueprint.cs b/osu.Game.Rulesets.Catch/Edit/Blueprints/JuiceStreamPlacementBlueprint.cs index fcdd055b56..03ec674abb 100644 --- a/osu.Game.Rulesets.Catch/Edit/Blueprints/JuiceStreamPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Catch/Edit/Blueprints/JuiceStreamPlacementBlueprint.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Input; using osu.Framework.Input.Events; @@ -14,7 +12,7 @@ using osuTK.Input; namespace osu.Game.Rulesets.Catch.Edit.Blueprints { - public class JuiceStreamPlacementBlueprint : CatchPlacementBlueprint + public partial class JuiceStreamPlacementBlueprint : CatchPlacementBlueprint { private readonly ScrollingPath scrollingPath; @@ -24,7 +22,7 @@ namespace osu.Game.Rulesets.Catch.Edit.Blueprints private int lastEditablePathId = -1; - private InputManager inputManager; + private InputManager inputManager = null!; public JuiceStreamPlacementBlueprint() { diff --git a/osu.Game.Rulesets.Catch/Edit/Blueprints/JuiceStreamSelectionBlueprint.cs b/osu.Game.Rulesets.Catch/Edit/Blueprints/JuiceStreamSelectionBlueprint.cs index fc2b5e08fe..49d778ad08 100644 --- a/osu.Game.Rulesets.Catch/Edit/Blueprints/JuiceStreamSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Catch/Edit/Blueprints/JuiceStreamSelectionBlueprint.cs @@ -1,11 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Collections.Generic; using System.Linq; -using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Caching; using osu.Framework.Graphics; @@ -22,7 +19,7 @@ using osuTK.Input; namespace osu.Game.Rulesets.Catch.Edit.Blueprints { - public class JuiceStreamSelectionBlueprint : CatchSelectionBlueprint + public partial class JuiceStreamSelectionBlueprint : CatchSelectionBlueprint { public override Quad SelectionQuad => HitObjectContainer.ToScreenSpace(getBoundingBox().Offset(new Vector2(0, HitObjectContainer.DrawHeight))); @@ -53,9 +50,8 @@ namespace osu.Game.Rulesets.Catch.Edit.Blueprints private Vector2 rightMouseDownPosition; - [Resolved(CanBeNull = true)] - [CanBeNull] - private EditorBeatmap editorBeatmap { get; set; } + [Resolved] + private EditorBeatmap? editorBeatmap { get; set; } public JuiceStreamSelectionBlueprint(JuiceStream hitObject) : base(hitObject) diff --git a/osu.Game.Rulesets.Catch/Edit/CatchBeatmapVerifier.cs b/osu.Game.Rulesets.Catch/Edit/CatchBeatmapVerifier.cs index 6570a19a92..c7a41a4e22 100644 --- a/osu.Game.Rulesets.Catch/Edit/CatchBeatmapVerifier.cs +++ b/osu.Game.Rulesets.Catch/Edit/CatchBeatmapVerifier.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Collections.Generic; using System.Linq; using osu.Game.Rulesets.Catch.Edit.Checks; diff --git a/osu.Game.Rulesets.Catch/Edit/CatchBlueprintContainer.cs b/osu.Game.Rulesets.Catch/Edit/CatchBlueprintContainer.cs index a0a11424d0..3979d30616 100644 --- a/osu.Game.Rulesets.Catch/Edit/CatchBlueprintContainer.cs +++ b/osu.Game.Rulesets.Catch/Edit/CatchBlueprintContainer.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Game.Rulesets.Catch.Edit.Blueprints; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Edit; @@ -11,7 +9,7 @@ using osu.Game.Screens.Edit.Compose.Components; namespace osu.Game.Rulesets.Catch.Edit { - public class CatchBlueprintContainer : ComposeBlueprintContainer + public partial class CatchBlueprintContainer : ComposeBlueprintContainer { public CatchBlueprintContainer(CatchHitObjectComposer composer) : base(composer) @@ -20,7 +18,7 @@ namespace osu.Game.Rulesets.Catch.Edit protected override SelectionHandler CreateSelectionHandler() => new CatchSelectionHandler(); - public override HitObjectSelectionBlueprint CreateHitObjectBlueprintFor(HitObject hitObject) + public override HitObjectSelectionBlueprint? CreateHitObjectBlueprintFor(HitObject hitObject) { switch (hitObject) { diff --git a/osu.Game.Rulesets.Catch/Edit/CatchDistanceSnapGrid.cs b/osu.Game.Rulesets.Catch/Edit/CatchDistanceSnapGrid.cs index 718c76abfc..cf6ddc66ed 100644 --- a/osu.Game.Rulesets.Catch/Edit/CatchDistanceSnapGrid.cs +++ b/osu.Game.Rulesets.Catch/Edit/CatchDistanceSnapGrid.cs @@ -1,12 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; -using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -24,7 +21,7 @@ namespace osu.Game.Rulesets.Catch.Edit /// The guide lines used in the osu!catch editor to compose patterns that can be caught with constant speed. /// Currently, only forward placement (an object is snapped based on the previous object, not the opposite) is supported. /// - public class CatchDistanceSnapGrid : CompositeDrawable + public partial class CatchDistanceSnapGrid : CompositeDrawable { public double StartTime { get; set; } @@ -39,7 +36,7 @@ namespace osu.Game.Rulesets.Catch.Edit private readonly List verticalLineVertices = new List(); [Resolved] - private Playfield playfield { get; set; } + private Playfield playfield { get; set; } = null!; private ScrollingHitObjectContainer hitObjectContainer => (ScrollingHitObjectContainer)playfield.HitObjectContainer; @@ -106,8 +103,7 @@ namespace osu.Game.Rulesets.Catch.Edit } } - [CanBeNull] - public SnapResult GetSnappedPosition(Vector2 screenSpacePosition) + public SnapResult? GetSnappedPosition(Vector2 screenSpacePosition) { double time = hitObjectContainer.TimeAtScreenSpacePosition(screenSpacePosition); @@ -121,9 +117,7 @@ namespace osu.Game.Rulesets.Catch.Edit return new SnapResult(originPosition, StartTime); } - return enumerateSnappingCandidates(time) - .OrderBy(pos => Vector2.DistanceSquared(screenSpacePosition, pos.ScreenSpacePosition)) - .FirstOrDefault(); + return enumerateSnappingCandidates(time).MinBy(pos => Vector2.DistanceSquared(screenSpacePosition, pos.ScreenSpacePosition)); } private IEnumerable enumerateSnappingCandidates(double time) diff --git a/osu.Game.Rulesets.Catch/Edit/CatchEditorPlayfield.cs b/osu.Game.Rulesets.Catch/Edit/CatchEditorPlayfield.cs index b9a875fe8a..c9481c2757 100644 --- a/osu.Game.Rulesets.Catch/Edit/CatchEditorPlayfield.cs +++ b/osu.Game.Rulesets.Catch/Edit/CatchEditorPlayfield.cs @@ -1,14 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.UI; namespace osu.Game.Rulesets.Catch.Edit { - public class CatchEditorPlayfield : CatchPlayfield + public partial class CatchEditorPlayfield : CatchPlayfield { // TODO fixme: the size of the catcher is not changed when circle size is changed in setup screen. public CatchEditorPlayfield(IBeatmapDifficultyInfo difficulty) diff --git a/osu.Game.Rulesets.Catch/Edit/CatchEditorPlayfieldAdjustmentContainer.cs b/osu.Game.Rulesets.Catch/Edit/CatchEditorPlayfieldAdjustmentContainer.cs index 0a0f91c781..0271005dd1 100644 --- a/osu.Game.Rulesets.Catch/Edit/CatchEditorPlayfieldAdjustmentContainer.cs +++ b/osu.Game.Rulesets.Catch/Edit/CatchEditorPlayfieldAdjustmentContainer.cs @@ -10,7 +10,7 @@ using osuTK; namespace osu.Game.Rulesets.Catch.Edit { - public class CatchEditorPlayfieldAdjustmentContainer : PlayfieldAdjustmentContainer + public partial class CatchEditorPlayfieldAdjustmentContainer : PlayfieldAdjustmentContainer { protected override Container Content => content; private readonly Container content; @@ -29,7 +29,7 @@ namespace osu.Game.Rulesets.Catch.Edit }; } - private class ScalingContainer : Container + private partial class ScalingContainer : Container { public ScalingContainer() { diff --git a/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs b/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs index 220bc49203..ea5f54a775 100644 --- a/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs +++ b/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs @@ -1,12 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; -using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.EnumExtensions; @@ -28,13 +25,13 @@ using osuTK; namespace osu.Game.Rulesets.Catch.Edit { - public class CatchHitObjectComposer : DistancedHitObjectComposer + public partial class CatchHitObjectComposer : DistancedHitObjectComposer { private const float distance_snap_radius = 50; - private CatchDistanceSnapGrid distanceSnapGrid; + private CatchDistanceSnapGrid distanceSnapGrid = null!; - private InputManager inputManager; + private InputManager inputManager = null!; private readonly BindableDouble timeRangeMultiplier = new BindableDouble(1) { @@ -117,7 +114,7 @@ namespace osu.Game.Rulesets.Catch.Edit return base.OnPressed(e); } - protected override DrawableRuleset CreateDrawableRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList mods = null) => + protected override DrawableRuleset CreateDrawableRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList? mods = null) => new DrawableCatchEditorRuleset(ruleset, beatmap, mods) { TimeRangeMultiplier = { BindTarget = timeRangeMultiplier, } @@ -150,8 +147,7 @@ namespace osu.Game.Rulesets.Catch.Edit protected override ComposeBlueprintContainer CreateBlueprintContainer() => new CatchBlueprintContainer(this); - [CanBeNull] - private PalpableCatchHitObject getLastSnappableHitObject(double time) + private PalpableCatchHitObject? getLastSnappableHitObject(double time) { var hitObject = EditorBeatmap.HitObjects.OfType().LastOrDefault(h => h.GetEndTime() < time && !(h is BananaShower)); @@ -168,8 +164,7 @@ namespace osu.Game.Rulesets.Catch.Edit } } - [CanBeNull] - private PalpableCatchHitObject getDistanceSnapGridSourceHitObject() + private PalpableCatchHitObject? getDistanceSnapGridSourceHitObject() { switch (BlueprintContainer.CurrentTool) { @@ -188,7 +183,8 @@ namespace osu.Game.Rulesets.Catch.Edit if (EditorBeatmap.PlacementObject.Value is JuiceStream) { // Juice stream path is not subject to snapping. - return null; + if (BlueprintContainer.CurrentPlacement.PlacementActive is PlacementBlueprint.PlacementState.Active) + return null; } double timeAtCursor = ((CatchPlayfield)Playfield).TimeAtScreenSpacePosition(inputManager.CurrentState.Mouse.Position); diff --git a/osu.Game.Rulesets.Catch/Edit/CatchHitObjectUtils.cs b/osu.Game.Rulesets.Catch/Edit/CatchHitObjectUtils.cs index 889d3909bd..bd33080109 100644 --- a/osu.Game.Rulesets.Catch/Edit/CatchHitObjectUtils.cs +++ b/osu.Game.Rulesets.Catch/Edit/CatchHitObjectUtils.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Collections.Generic; using System.Linq; using osu.Game.Rulesets.Catch.Objects; diff --git a/osu.Game.Rulesets.Catch/Edit/CatchSelectionHandler.cs b/osu.Game.Rulesets.Catch/Edit/CatchSelectionHandler.cs index 5aac521d0b..418351e2f3 100644 --- a/osu.Game.Rulesets.Catch/Edit/CatchSelectionHandler.cs +++ b/osu.Game.Rulesets.Catch/Edit/CatchSelectionHandler.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; @@ -18,12 +16,12 @@ using Direction = osu.Framework.Graphics.Direction; namespace osu.Game.Rulesets.Catch.Edit { - public class CatchSelectionHandler : EditorSelectionHandler + public partial class CatchSelectionHandler : EditorSelectionHandler { protected ScrollingHitObjectContainer HitObjectContainer => (ScrollingHitObjectContainer)playfield.HitObjectContainer; [Resolved] - private Playfield playfield { get; set; } + private Playfield playfield { get; set; } = null!; public override bool HandleMovement(MoveSelectionEvent moveEvent) { diff --git a/osu.Game.Rulesets.Catch/Edit/DrawableCatchEditorRuleset.cs b/osu.Game.Rulesets.Catch/Edit/DrawableCatchEditorRuleset.cs index 67238f66d4..7ad2106ab9 100644 --- a/osu.Game.Rulesets.Catch/Edit/DrawableCatchEditorRuleset.cs +++ b/osu.Game.Rulesets.Catch/Edit/DrawableCatchEditorRuleset.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Collections.Generic; using osu.Framework.Bindables; using osu.Game.Beatmaps; @@ -12,11 +10,11 @@ using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Catch.Edit { - public class DrawableCatchEditorRuleset : DrawableCatchRuleset + public partial class DrawableCatchEditorRuleset : DrawableCatchRuleset { public readonly BindableDouble TimeRangeMultiplier = new BindableDouble(1); - public DrawableCatchEditorRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList mods = null) + public DrawableCatchEditorRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList? mods = null) : base(ruleset, beatmap, mods) { } diff --git a/osu.Game.Rulesets.Catch/Edit/FruitCompositionTool.cs b/osu.Game.Rulesets.Catch/Edit/FruitCompositionTool.cs index 5c13692b51..f776fe39c1 100644 --- a/osu.Game.Rulesets.Catch/Edit/FruitCompositionTool.cs +++ b/osu.Game.Rulesets.Catch/Edit/FruitCompositionTool.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Edit.Blueprints; diff --git a/osu.Game.Rulesets.Catch/Edit/JuiceStreamCompositionTool.cs b/osu.Game.Rulesets.Catch/Edit/JuiceStreamCompositionTool.cs index 85cf89f700..cb66e2952e 100644 --- a/osu.Game.Rulesets.Catch/Edit/JuiceStreamCompositionTool.cs +++ b/osu.Game.Rulesets.Catch/Edit/JuiceStreamCompositionTool.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Edit.Blueprints; diff --git a/osu.Game.Rulesets.Catch/Judgements/CatchBananaJudgement.cs b/osu.Game.Rulesets.Catch/Judgements/CatchBananaJudgement.cs index 15f6e4a64d..b919102215 100644 --- a/osu.Game.Rulesets.Catch/Judgements/CatchBananaJudgement.cs +++ b/osu.Game.Rulesets.Catch/Judgements/CatchBananaJudgement.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Catch/Judgements/CatchDropletJudgement.cs b/osu.Game.Rulesets.Catch/Judgements/CatchDropletJudgement.cs index 90aa6f41a1..8fd7b93e4c 100644 --- a/osu.Game.Rulesets.Catch/Judgements/CatchDropletJudgement.cs +++ b/osu.Game.Rulesets.Catch/Judgements/CatchDropletJudgement.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Catch.Judgements diff --git a/osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs b/osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs index e5d6429660..ccafe0abc4 100644 --- a/osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs +++ b/osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Catch/Judgements/CatchJudgementResult.cs b/osu.Game.Rulesets.Catch/Judgements/CatchJudgementResult.cs index 6cc79f9619..4cec61d016 100644 --- a/osu.Game.Rulesets.Catch/Judgements/CatchJudgementResult.cs +++ b/osu.Game.Rulesets.Catch/Judgements/CatchJudgementResult.cs @@ -1,9 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - -using JetBrains.Annotations; using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; @@ -22,7 +19,7 @@ namespace osu.Game.Rulesets.Catch.Judgements /// public bool CatcherHyperDash; - public CatchJudgementResult([NotNull] HitObject hitObject, [NotNull] Judgement judgement) + public CatchJudgementResult(HitObject hitObject, Judgement judgement) : base(hitObject, judgement) { } diff --git a/osu.Game.Rulesets.Catch/Judgements/CatchTinyDropletJudgement.cs b/osu.Game.Rulesets.Catch/Judgements/CatchTinyDropletJudgement.cs index c9052e3c39..d957d4171b 100644 --- a/osu.Game.Rulesets.Catch/Judgements/CatchTinyDropletJudgement.cs +++ b/osu.Game.Rulesets.Catch/Judgements/CatchTinyDropletJudgement.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Catch.Judgements diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModFlashlight.cs b/osu.Game.Rulesets.Catch/Mods/CatchModFlashlight.cs index a9e9e8fbd5..40450c6729 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModFlashlight.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModFlashlight.cs @@ -11,7 +11,7 @@ using osuTK; namespace osu.Game.Rulesets.Catch.Mods { - public class CatchModFlashlight : ModFlashlight + public partial class CatchModFlashlight : ModFlashlight { public override double ScoreMultiplier => UsesDefaultConfiguration ? 1.12 : 1; @@ -36,7 +36,7 @@ namespace osu.Game.Rulesets.Catch.Mods base.ApplyToDrawableRuleset(drawableRuleset); } - private class CatchFlashlight : Flashlight + private partial class CatchFlashlight : Flashlight { private readonly CatchPlayfield playfield; diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModNoScope.cs b/osu.Game.Rulesets.Catch/Mods/CatchModNoScope.cs index 19b4a39f97..ddeea51ecb 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModNoScope.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModNoScope.cs @@ -26,6 +26,9 @@ namespace osu.Game.Rulesets.Catch.Mods var catchPlayfield = (CatchPlayfield)playfield; bool shouldAlwaysShowCatcher = IsBreakTime.Value; float targetAlpha = shouldAlwaysShowCatcher ? 1 : ComboBasedAlpha; + + // AlwaysPresent required for catcher to still act on input when fully hidden. + catchPlayfield.CatcherArea.AlwaysPresent = true; catchPlayfield.CatcherArea.Alpha = (float)Interpolation.Lerp(catchPlayfield.CatcherArea.Alpha, targetAlpha, Math.Clamp(catchPlayfield.Time.Elapsed / TRANSITION_DURATION, 0, 1)); } } diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs b/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs index 3f7560844c..83ad96d5b4 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs @@ -15,7 +15,7 @@ using osuTK; namespace osu.Game.Rulesets.Catch.Mods { - public class CatchModRelax : ModRelax, IApplicableToDrawableRuleset, IApplicableToPlayer + public partial class CatchModRelax : ModRelax, IApplicableToDrawableRuleset, IApplicableToPlayer { public override LocalisableString Description => @"Use the mouse to control the catcher."; @@ -35,7 +35,7 @@ namespace osu.Game.Rulesets.Catch.Mods } } - private class MouseInputHelper : Drawable, IKeyBindingHandler, IRequireHighFrequencyMousePosition + private partial class MouseInputHelper : Drawable, IKeyBindingHandler, IRequireHighFrequencyMousePosition { private readonly CatcherArea catcherArea; diff --git a/osu.Game.Rulesets.Catch/Objects/BananaShower.cs b/osu.Game.Rulesets.Catch/Objects/BananaShower.cs index e5541e49c1..b45f95a8e6 100644 --- a/osu.Game.Rulesets.Catch/Objects/BananaShower.cs +++ b/osu.Game.Rulesets.Catch/Objects/BananaShower.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Threading; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Types; diff --git a/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs index cd2b8348e2..f4bd515995 100644 --- a/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using Newtonsoft.Json; using osu.Framework.Bindables; diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtBanana.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtBanana.cs index 31a27b6047..bfeb37b1b7 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtBanana.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtBanana.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Game.Rulesets.Catch.Skinning.Default; namespace osu.Game.Rulesets.Catch.Objects.Drawables @@ -10,7 +8,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables /// /// Represents a caught by the catcher. /// - public class CaughtBanana : CaughtObject + public partial class CaughtBanana : CaughtObject { public CaughtBanana() : base(CatchSkinComponents.Banana, _ => new BananaPiece()) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtDroplet.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtDroplet.cs index 6d5dd0ed25..d228c629c0 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtDroplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtDroplet.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Game.Rulesets.Catch.Skinning.Default; namespace osu.Game.Rulesets.Catch.Objects.Drawables @@ -10,7 +8,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables /// /// Represents a caught by the catcher. /// - public class CaughtDroplet : CaughtObject + public partial class CaughtDroplet : CaughtObject { public override bool StaysOnPlate => false; diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtFruit.cs index 89757748ab..99dcac5268 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtFruit.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Game.Rulesets.Catch.Skinning.Default; namespace osu.Game.Rulesets.Catch.Objects.Drawables @@ -10,7 +8,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables /// /// Represents a caught by the catcher. /// - public class CaughtFruit : CaughtObject + public partial class CaughtFruit : CaughtObject { public CaughtFruit() : base(CatchSkinComponents.Fruit, _ => new FruitPiece()) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs index 8ac5eac227..0c26c52171 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -17,9 +15,9 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables /// Represents a caught by the catcher. /// [Cached(typeof(IHasCatchObjectState))] - public abstract class CaughtObject : SkinnableDrawable, IHasCatchObjectState + public abstract partial class CaughtObject : SkinnableDrawable, IHasCatchObjectState { - public PalpableCatchHitObject HitObject { get; private set; } + public PalpableCatchHitObject HitObject { get; private set; } = null!; public Bindable AccentColour { get; } = new Bindable(); public Bindable HyperDash { get; } = new Bindable(); public Bindable IndexInBeatmap { get; } = new Bindable(); diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBanana.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBanana.cs index 80a4150d98..26e304cf3f 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBanana.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBanana.cs @@ -1,9 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - -using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Rulesets.Catch.Skinning.Default; @@ -11,14 +8,14 @@ using osu.Game.Skinning; namespace osu.Game.Rulesets.Catch.Objects.Drawables { - public class DrawableBanana : DrawablePalpableCatchHitObject + public partial class DrawableBanana : DrawablePalpableCatchHitObject { public DrawableBanana() : this(null) { } - public DrawableBanana([CanBeNull] Banana h) + public DrawableBanana(Banana? h) : base(h) { } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBananaShower.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBananaShower.cs index f061f206ff..03adbce885 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBananaShower.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBananaShower.cs @@ -1,16 +1,13 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - -using JetBrains.Annotations; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Objects.Drawables; namespace osu.Game.Rulesets.Catch.Objects.Drawables { - public class DrawableBananaShower : DrawableCatchHitObject + public partial class DrawableBananaShower : DrawableCatchHitObject { private readonly Container bananaContainer; @@ -19,7 +16,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables { } - public DrawableBananaShower([CanBeNull] BananaShower s) + public DrawableBananaShower(BananaShower? s) : base(s) { RelativeSizeAxes = Axes.X; diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs index 23264edf3d..7f8c17861d 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs @@ -15,7 +15,7 @@ using osu.Game.Utils; namespace osu.Game.Rulesets.Catch.Objects.Drawables { - public abstract class DrawableCatchHitObject : DrawableHitObject + public abstract partial class DrawableCatchHitObject : DrawableHitObject { public readonly Bindable OriginalXBindable = new Bindable(); public readonly Bindable XOffsetBindable = new Bindable(); @@ -53,6 +53,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables XOffsetBindable.UnbindFrom(HitObject.XOffsetBindable); } + [CanBeNull] public Func CheckPosition; protected override JudgementResult CreateResult(Judgement judgement) => new CatchJudgementResult(HitObject, judgement); diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs index a81d87480a..8f32cdcc31 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs @@ -1,9 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - -using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Rulesets.Catch.Skinning.Default; @@ -11,14 +8,14 @@ using osu.Game.Skinning; namespace osu.Game.Rulesets.Catch.Objects.Drawables { - public class DrawableDroplet : DrawablePalpableCatchHitObject + public partial class DrawableDroplet : DrawablePalpableCatchHitObject { public DrawableDroplet() : this(null) { } - public DrawableDroplet([CanBeNull] CatchHitObject h) + public DrawableDroplet(CatchHitObject? h) : base(h) { } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs index d7fd79929b..52c53523e6 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs @@ -1,9 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - -using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Rulesets.Catch.Skinning.Default; @@ -11,14 +8,14 @@ using osu.Game.Skinning; namespace osu.Game.Rulesets.Catch.Objects.Drawables { - public class DrawableFruit : DrawablePalpableCatchHitObject + public partial class DrawableFruit : DrawablePalpableCatchHitObject { public DrawableFruit() : this(null) { } - public DrawableFruit([CanBeNull] Fruit h) + public DrawableFruit(Fruit? h) : base(h) { } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableJuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableJuiceStream.cs index 12a44c909e..41ecf59276 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableJuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableJuiceStream.cs @@ -1,16 +1,13 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - -using JetBrains.Annotations; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Objects.Drawables; namespace osu.Game.Rulesets.Catch.Objects.Drawables { - public class DrawableJuiceStream : DrawableCatchHitObject + public partial class DrawableJuiceStream : DrawableCatchHitObject { private readonly Container dropletContainer; @@ -19,7 +16,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables { } - public DrawableJuiceStream([CanBeNull] JuiceStream s) + public DrawableJuiceStream(JuiceStream? s) : base(s) { RelativeSizeAxes = Axes.X; diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawablePalpableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawablePalpableCatchHitObject.cs index dd09b6c06d..4a9661f108 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawablePalpableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawablePalpableCatchHitObject.cs @@ -1,9 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - -using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -14,7 +11,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Catch.Objects.Drawables { [Cached(typeof(IHasCatchObjectState))] - public abstract class DrawablePalpableCatchHitObject : DrawableCatchHitObject, IHasCatchObjectState + public abstract partial class DrawablePalpableCatchHitObject : DrawableCatchHitObject, IHasCatchObjectState { public new PalpableCatchHitObject HitObject => (PalpableCatchHitObject)base.HitObject; @@ -42,7 +39,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables public float DisplayRotation => ScalingContainer.Rotation; - protected DrawablePalpableCatchHitObject([CanBeNull] CatchHitObject h) + protected DrawablePalpableCatchHitObject(CatchHitObject? h) : base(h) { Origin = Anchor.Centre; diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableTinyDroplet.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableTinyDroplet.cs index 8c48b62c7e..f820ccdc62 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableTinyDroplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableTinyDroplet.cs @@ -1,13 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - -using JetBrains.Annotations; - namespace osu.Game.Rulesets.Catch.Objects.Drawables { - public class DrawableTinyDroplet : DrawableDroplet + public partial class DrawableTinyDroplet : DrawableDroplet { protected override float ScaleFactor => base.ScaleFactor / 2; @@ -16,7 +12,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables { } - public DrawableTinyDroplet([CanBeNull] TinyDroplet h) + public DrawableTinyDroplet(TinyDroplet? h) : base(h) { } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/IHasCatchObjectState.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/IHasCatchObjectState.cs index f30ef0831a..18fc0db6e3 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/IHasCatchObjectState.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/IHasCatchObjectState.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Bindables; using osuTK; using osuTK.Graphics; diff --git a/osu.Game.Rulesets.Catch/Objects/Droplet.cs b/osu.Game.Rulesets.Catch/Objects/Droplet.cs index ecaa4bfaf4..9c1004a04b 100644 --- a/osu.Game.Rulesets.Catch/Objects/Droplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/Droplet.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Game.Rulesets.Catch.Judgements; using osu.Game.Rulesets.Judgements; diff --git a/osu.Game.Rulesets.Catch/Objects/Fruit.cs b/osu.Game.Rulesets.Catch/Objects/Fruit.cs index bdf8b3f28d..4818fe2cad 100644 --- a/osu.Game.Rulesets.Catch/Objects/Fruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Fruit.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Game.Rulesets.Catch.Judgements; using osu.Game.Rulesets.Judgements; diff --git a/osu.Game.Rulesets.Catch/Objects/FruitVisualRepresentation.cs b/osu.Game.Rulesets.Catch/Objects/FruitVisualRepresentation.cs index e5d013dafc..7ec7050245 100644 --- a/osu.Game.Rulesets.Catch/Objects/FruitVisualRepresentation.cs +++ b/osu.Game.Rulesets.Catch/Objects/FruitVisualRepresentation.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - namespace osu.Game.Rulesets.Catch.Objects { public enum FruitVisualRepresentation diff --git a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs index 015457e84f..96e2d5c4e5 100644 --- a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; @@ -142,13 +140,8 @@ namespace osu.Game.Rulesets.Catch.Objects set { path.ControlPoints.Clear(); - path.ExpectedDistance.Value = null; - - if (value != null) - { - path.ControlPoints.AddRange(value.ControlPoints.Select(c => new PathControlPoint(c.Position, c.Type))); - path.ExpectedDistance.Value = value.ExpectedDistance.Value; - } + path.ControlPoints.AddRange(value.ControlPoints.Select(c => new PathControlPoint(c.Position, c.Type))); + path.ExpectedDistance.Value = value.ExpectedDistance.Value; } } diff --git a/osu.Game.Rulesets.Catch/Objects/PalpableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/PalpableCatchHitObject.cs index c9bc9ca2ac..197029aeeb 100644 --- a/osu.Game.Rulesets.Catch/Objects/PalpableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/PalpableCatchHitObject.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using Newtonsoft.Json; using osu.Framework.Bindables; using osu.Game.Rulesets.Objects; @@ -34,13 +32,13 @@ namespace osu.Game.Rulesets.Catch.Objects /// public bool HyperDash => hyperDash.Value; - private CatchHitObject hyperDashTarget; + private CatchHitObject? hyperDashTarget; /// /// The target fruit if we are to initiate a hyperdash. /// [JsonIgnore] - public CatchHitObject HyperDashTarget + public CatchHitObject? HyperDashTarget { get => hyperDashTarget; set diff --git a/osu.Game.Rulesets.Catch/Objects/TinyDroplet.cs b/osu.Game.Rulesets.Catch/Objects/TinyDroplet.cs index 6bd5f0ac2a..1bf160b5a6 100644 --- a/osu.Game.Rulesets.Catch/Objects/TinyDroplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/TinyDroplet.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Game.Rulesets.Catch.Judgements; using osu.Game.Rulesets.Judgements; diff --git a/osu.Game.Rulesets.Catch/Properties/AssemblyInfo.cs b/osu.Game.Rulesets.Catch/Properties/AssemblyInfo.cs index 6c7f0478a7..26f20b223a 100644 --- a/osu.Game.Rulesets.Catch/Properties/AssemblyInfo.cs +++ b/osu.Game.Rulesets.Catch/Properties/AssemblyInfo.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Runtime.CompilerServices; // We publish our internal attributes to other sub-projects of the framework. diff --git a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs index ba3d529212..b6a42407da 100644 --- a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs +++ b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs @@ -1,13 +1,11 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Catch.Scoring { - public class CatchScoreProcessor : ScoreProcessor + public partial class CatchScoreProcessor : ScoreProcessor { public CatchScoreProcessor() : base(new CatchRuleset()) diff --git a/osu.Game.Rulesets.Catch/Skinning/Argon/ArgonBananaPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Argon/ArgonBananaPiece.cs index 9a657c9216..8cdb490922 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Argon/ArgonBananaPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Argon/ArgonBananaPiece.cs @@ -15,7 +15,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Catch.Skinning.Argon { - internal class ArgonBananaPiece : ArgonFruitPiece + internal partial class ArgonBananaPiece : ArgonFruitPiece { private Container stabilisedPieceContainer = null!; diff --git a/osu.Game.Rulesets.Catch/Skinning/Argon/ArgonCatcher.cs b/osu.Game.Rulesets.Catch/Skinning/Argon/ArgonCatcher.cs index 4db0df4a34..82374085c8 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Argon/ArgonCatcher.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Argon/ArgonCatcher.cs @@ -10,7 +10,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Catch.Skinning.Argon { - public class ArgonCatcher : CompositeDrawable + public partial class ArgonCatcher : CompositeDrawable { [BackgroundDependencyLoader] private void load() diff --git a/osu.Game.Rulesets.Catch/Skinning/Argon/ArgonDropletPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Argon/ArgonDropletPiece.cs index 267f8a06a3..38fe7916f5 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Argon/ArgonDropletPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Argon/ArgonDropletPiece.cs @@ -13,7 +13,7 @@ using osuTK; namespace osu.Game.Rulesets.Catch.Skinning.Argon { - internal class ArgonDropletPiece : CatchHitObjectPiece + internal partial class ArgonDropletPiece : CatchHitObjectPiece { protected override Drawable HyperBorderPiece => hyperBorderPiece; diff --git a/osu.Game.Rulesets.Catch/Skinning/Argon/ArgonFruitPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Argon/ArgonFruitPiece.cs index 28538d48b3..4b5319e859 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Argon/ArgonFruitPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Argon/ArgonFruitPiece.cs @@ -13,7 +13,7 @@ using osuTK; namespace osu.Game.Rulesets.Catch.Skinning.Argon { - internal class ArgonFruitPiece : CatchHitObjectPiece + internal partial class ArgonFruitPiece : CatchHitObjectPiece { protected override Drawable HyperBorderPiece => hyperBorderPiece; diff --git a/osu.Game.Rulesets.Catch/Skinning/Argon/ArgonHitExplosion.cs b/osu.Game.Rulesets.Catch/Skinning/Argon/ArgonHitExplosion.cs index 90dca49dfd..a3c0c8c108 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Argon/ArgonHitExplosion.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Argon/ArgonHitExplosion.cs @@ -16,7 +16,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Catch.Skinning.Argon { - public class ArgonHitExplosion : CompositeDrawable, IHitExplosion + public partial class ArgonHitExplosion : CompositeDrawable, IHitExplosion { public override bool RemoveWhenNotAlive => true; diff --git a/osu.Game.Rulesets.Catch/Skinning/Argon/ArgonJudgementPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Argon/ArgonJudgementPiece.cs deleted file mode 100644 index 59e8b5a0b3..0000000000 --- a/osu.Game.Rulesets.Catch/Skinning/Argon/ArgonJudgementPiece.cs +++ /dev/null @@ -1,193 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System; -using osu.Framework.Allocation; -using osu.Framework.Extensions; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; -using osu.Framework.Utils; -using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; -using osu.Game.Rulesets.Judgements; -using osu.Game.Rulesets.Scoring; -using osuTK; -using osuTK.Graphics; - -namespace osu.Game.Rulesets.Catch.Skinning.Argon -{ - public class ArgonJudgementPiece : CompositeDrawable, IAnimatableJudgement - { - protected readonly HitResult Result; - - protected SpriteText JudgementText { get; private set; } = null!; - - private RingExplosion? ringExplosion; - - [Resolved] - private OsuColour colours { get; set; } = null!; - - public ArgonJudgementPiece(HitResult result) - { - Result = result; - Origin = Anchor.Centre; - Y = 160; - } - - [BackgroundDependencyLoader] - private void load() - { - AutoSizeAxes = Axes.Both; - - InternalChildren = new Drawable[] - { - JudgementText = new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Text = Result.GetDescription().ToUpperInvariant(), - Colour = colours.ForHitResult(Result), - Blending = BlendingParameters.Additive, - Spacing = new Vector2(10, 0), - Font = OsuFont.Default.With(size: 28, weight: FontWeight.Regular), - }, - }; - - if (Result.IsHit()) - { - AddInternal(ringExplosion = new RingExplosion(Result) - { - Colour = colours.ForHitResult(Result), - }); - } - } - - /// - /// Plays the default animation for this judgement piece. - /// - /// - /// The base implementation only handles fade (for all result types) and misses. - /// Individual rulesets are recommended to implement their appropriate hit animations. - /// - public virtual void PlayAnimation() - { - switch (Result) - { - default: - JudgementText - .ScaleTo(Vector2.One) - .ScaleTo(new Vector2(1.4f), 1800, Easing.OutQuint); - break; - - case HitResult.Miss: - this.ScaleTo(1.6f); - this.ScaleTo(1, 100, Easing.In); - - this.MoveTo(Vector2.Zero); - this.MoveToOffset(new Vector2(0, 100), 800, Easing.InQuint); - - this.RotateTo(0); - this.RotateTo(40, 800, Easing.InQuint); - break; - } - - this.FadeOutFromOne(800); - - ringExplosion?.PlayAnimation(); - } - - public Drawable? GetAboveHitObjectsProxiedContent() => null; - - private class RingExplosion : CompositeDrawable - { - private readonly float travel = 52; - - public RingExplosion(HitResult result) - { - const float thickness = 4; - - const float small_size = 9; - const float large_size = 14; - - Anchor = Anchor.Centre; - Origin = Anchor.Centre; - - Blending = BlendingParameters.Additive; - - int countSmall = 0; - int countLarge = 0; - - switch (result) - { - case HitResult.Meh: - countSmall = 3; - travel *= 0.3f; - break; - - case HitResult.Ok: - case HitResult.Good: - countSmall = 4; - travel *= 0.6f; - break; - - case HitResult.Great: - case HitResult.Perfect: - countSmall = 4; - countLarge = 4; - break; - } - - for (int i = 0; i < countSmall; i++) - AddInternal(new RingPiece(thickness) { Size = new Vector2(small_size) }); - - for (int i = 0; i < countLarge; i++) - AddInternal(new RingPiece(thickness) { Size = new Vector2(large_size) }); - } - - public void PlayAnimation() - { - foreach (var c in InternalChildren) - { - const float start_position_ratio = 0.3f; - - float direction = RNG.NextSingle(0, 360); - float distance = RNG.NextSingle(travel / 2, travel); - - c.MoveTo(new Vector2( - MathF.Cos(direction) * distance * start_position_ratio, - MathF.Sin(direction) * distance * start_position_ratio - )); - - c.MoveTo(new Vector2( - MathF.Cos(direction) * distance, - MathF.Sin(direction) * distance - ), 600, Easing.OutQuint); - } - - this.FadeOutFromOne(1000, Easing.OutQuint); - } - - public class RingPiece : CircularContainer - { - public RingPiece(float thickness = 9) - { - Anchor = Anchor.Centre; - Origin = Anchor.Centre; - - Masking = true; - BorderThickness = thickness; - BorderColour = Color4.White; - - Child = new Box - { - AlwaysPresent = true, - Alpha = 0, - RelativeSizeAxes = Axes.Both - }; - } - } - } - } -} diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/BananaPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Default/BananaPiece.cs index 359756f159..80ee9d5a0c 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/BananaPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/BananaPiece.cs @@ -5,7 +5,7 @@ using osu.Framework.Graphics; namespace osu.Game.Rulesets.Catch.Skinning.Default { - public class BananaPiece : CatchHitObjectPiece + public partial class BananaPiece : CatchHitObjectPiece { protected override Drawable BorderPiece { get; } diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/BananaPulpFormation.cs b/osu.Game.Rulesets.Catch/Skinning/Default/BananaPulpFormation.cs index ee1cc68f7d..26c8558e74 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/BananaPulpFormation.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/BananaPulpFormation.cs @@ -5,7 +5,7 @@ using osuTK; namespace osu.Game.Rulesets.Catch.Skinning.Default { - public class BananaPulpFormation : PulpFormation + public partial class BananaPulpFormation : PulpFormation { public BananaPulpFormation() { diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/BorderPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Default/BorderPiece.cs index 8d8ee49af7..f0bdcfa1ba 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/BorderPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/BorderPiece.cs @@ -9,7 +9,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Catch.Skinning.Default { - public class BorderPiece : Circle + public partial class BorderPiece : Circle { public BorderPiece() { diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/CatchHitObjectPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Default/CatchHitObjectPiece.cs index e84e4d4ad2..7cc425966d 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/CatchHitObjectPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/CatchHitObjectPiece.cs @@ -11,7 +11,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Catch.Skinning.Default { - public abstract class CatchHitObjectPiece : CompositeDrawable + public abstract partial class CatchHitObjectPiece : CompositeDrawable { public readonly Bindable AccentColour = new Bindable(); public readonly Bindable HyperDash = new Bindable(); diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/DefaultCatcher.cs b/osu.Game.Rulesets.Catch/Skinning/Default/DefaultCatcher.cs index e423f21b98..72208b763b 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/DefaultCatcher.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/DefaultCatcher.cs @@ -12,7 +12,7 @@ using osu.Game.Rulesets.Catch.UI; namespace osu.Game.Rulesets.Catch.Skinning.Default { - public class DefaultCatcher : CompositeDrawable + public partial class DefaultCatcher : CompositeDrawable { public Bindable CurrentState { get; } = new Bindable(); diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/DefaultHitExplosion.cs b/osu.Game.Rulesets.Catch/Skinning/Default/DefaultHitExplosion.cs index 2650ba765b..3af178fe4d 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/DefaultHitExplosion.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/DefaultHitExplosion.cs @@ -14,7 +14,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Catch.Skinning.Default { - public class DefaultHitExplosion : CompositeDrawable, IHitExplosion + public partial class DefaultHitExplosion : CompositeDrawable, IHitExplosion { private CircularContainer largeFaint = null!; private CircularContainer smallFaint = null!; diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/DropletPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Default/DropletPiece.cs index 59e74bff74..f002457b61 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/DropletPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/DropletPiece.cs @@ -7,7 +7,7 @@ using osuTK; namespace osu.Game.Rulesets.Catch.Skinning.Default { - public class DropletPiece : CatchHitObjectPiece + public partial class DropletPiece : CatchHitObjectPiece { protected override Drawable HyperBorderPiece { get; } diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/FruitPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Default/FruitPiece.cs index 3bd8032649..31e30d8073 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/FruitPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/FruitPiece.cs @@ -7,7 +7,7 @@ using osu.Game.Rulesets.Catch.Objects; namespace osu.Game.Rulesets.Catch.Skinning.Default { - internal class FruitPiece : CatchHitObjectPiece + internal partial class FruitPiece : CatchHitObjectPiece { /// /// Because we're adding a border around the fruit, we need to scale down some. diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/FruitPulpFormation.cs b/osu.Game.Rulesets.Catch/Skinning/Default/FruitPulpFormation.cs index f097361d2a..c031e50e34 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/FruitPulpFormation.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/FruitPulpFormation.cs @@ -7,7 +7,7 @@ using osuTK; namespace osu.Game.Rulesets.Catch.Skinning.Default { - public class FruitPulpFormation : PulpFormation + public partial class FruitPulpFormation : PulpFormation { public readonly Bindable VisualRepresentation = new Bindable(); diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/HyperBorderPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Default/HyperBorderPiece.cs index c8895f32f4..c025c8e435 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/HyperBorderPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/HyperBorderPiece.cs @@ -6,7 +6,7 @@ using osu.Game.Rulesets.Catch.UI; namespace osu.Game.Rulesets.Catch.Skinning.Default { - public class HyperBorderPiece : BorderPiece + public partial class HyperBorderPiece : BorderPiece { public HyperBorderPiece() { diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/HyperDropletBorderPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Default/HyperDropletBorderPiece.cs index 53a487b97f..1462bc3515 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/HyperDropletBorderPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/HyperDropletBorderPiece.cs @@ -3,7 +3,7 @@ namespace osu.Game.Rulesets.Catch.Skinning.Default { - public class HyperDropletBorderPiece : HyperBorderPiece + public partial class HyperDropletBorderPiece : HyperBorderPiece { public HyperDropletBorderPiece() { diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/Pulp.cs b/osu.Game.Rulesets.Catch/Skinning/Default/Pulp.cs index 96c6233b41..4b4d6f3788 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/Pulp.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/Pulp.cs @@ -10,7 +10,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Catch.Skinning.Default { - public class Pulp : Circle + public partial class Pulp : Circle { public readonly Bindable AccentColour = new Bindable(); diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/PulpFormation.cs b/osu.Game.Rulesets.Catch/Skinning/Default/PulpFormation.cs index 8753aa4077..21502e6fa0 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/PulpFormation.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/PulpFormation.cs @@ -10,7 +10,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Catch.Skinning.Default { - public abstract class PulpFormation : CompositeDrawable + public abstract partial class PulpFormation : CompositeDrawable { public readonly Bindable AccentColour = new Bindable(); diff --git a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyBananaPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyBananaPiece.cs index 310da8bf78..26832b7271 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyBananaPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyBananaPiece.cs @@ -5,7 +5,7 @@ using osu.Framework.Graphics.Textures; namespace osu.Game.Rulesets.Catch.Skinning.Legacy { - public class LegacyBananaPiece : LegacyCatchHitObjectPiece + public partial class LegacyBananaPiece : LegacyCatchHitObjectPiece { protected override void LoadComplete() { diff --git a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyCatchComboCounter.cs b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyCatchComboCounter.cs index b4d29988d9..eba837a52d 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyCatchComboCounter.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyCatchComboCounter.cs @@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.Catch.Skinning.Legacy /// /// A combo counter implementation that visually behaves almost similar to stable's osu!catch combo counter. /// - public class LegacyCatchComboCounter : CompositeDrawable, ICatchComboCounter + public partial class LegacyCatchComboCounter : CompositeDrawable, ICatchComboCounter { private readonly LegacyRollingCounter counter; diff --git a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyCatchHitObjectPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyCatchHitObjectPiece.cs index 1231ed6d5a..2184ecc363 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyCatchHitObjectPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyCatchHitObjectPiece.cs @@ -15,7 +15,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Catch.Skinning.Legacy { - public abstract class LegacyCatchHitObjectPiece : PoolableDrawable + public abstract partial class LegacyCatchHitObjectPiece : PoolableDrawable { protected readonly Bindable IndexInBeatmap = new Bindable(); diff --git a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyCatcherNew.cs b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyCatcherNew.cs index 667622e6f2..f6b2c52498 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyCatcherNew.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyCatcherNew.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -15,7 +14,7 @@ using osuTK; namespace osu.Game.Rulesets.Catch.Skinning.Legacy { - public class LegacyCatcherNew : CompositeDrawable + public partial class LegacyCatcherNew : CompositeDrawable { [Resolved] private Bindable currentState { get; set; } = null!; @@ -32,7 +31,7 @@ namespace osu.Game.Rulesets.Catch.Skinning.Legacy [BackgroundDependencyLoader] private void load(ISkinSource skin) { - foreach (var state in Enum.GetValues(typeof(CatcherAnimationState)).Cast()) + foreach (var state in Enum.GetValues()) { AddInternal(drawables[state] = getDrawableFor(state).With(d => { diff --git a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyCatcherOld.cs b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyCatcherOld.cs index 5f09d1e254..1e21d8eab1 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyCatcherOld.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyCatcherOld.cs @@ -9,7 +9,7 @@ using osuTK; namespace osu.Game.Rulesets.Catch.Skinning.Legacy { - public class LegacyCatcherOld : CompositeDrawable + public partial class LegacyCatcherOld : CompositeDrawable { public LegacyCatcherOld() { diff --git a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyDropletPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyDropletPiece.cs index 7007f1cc29..7ffd682698 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyDropletPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyDropletPiece.cs @@ -6,7 +6,7 @@ using osuTK; namespace osu.Game.Rulesets.Catch.Skinning.Legacy { - public class LegacyDropletPiece : LegacyCatchHitObjectPiece + public partial class LegacyDropletPiece : LegacyCatchHitObjectPiece { public LegacyDropletPiece() { diff --git a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyFruitPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyFruitPiece.cs index f002bab219..85b60561dd 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyFruitPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyFruitPiece.cs @@ -5,7 +5,7 @@ using osu.Game.Rulesets.Catch.Objects; namespace osu.Game.Rulesets.Catch.Skinning.Legacy { - internal class LegacyFruitPiece : LegacyCatchHitObjectPiece + internal partial class LegacyFruitPiece : LegacyCatchHitObjectPiece { protected override void LoadComplete() { diff --git a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyHitExplosion.cs b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyHitExplosion.cs index 393a1076af..47660503dc 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyHitExplosion.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyHitExplosion.cs @@ -13,7 +13,7 @@ using osuTK; namespace osu.Game.Rulesets.Catch.Skinning.Legacy { - public class LegacyHitExplosion : CompositeDrawable, IHitExplosion + public partial class LegacyHitExplosion : CompositeDrawable, IHitExplosion { [Resolved] private Catcher catcher { get; set; } = null!; diff --git a/osu.Game.Rulesets.Catch/UI/CatchComboDisplay.cs b/osu.Game.Rulesets.Catch/UI/CatchComboDisplay.cs index 03f0bc6a55..dbbe905879 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchComboDisplay.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchComboDisplay.cs @@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Catch.UI /// /// Represents a component that displays a skinned and handles combo judgement results for updating it accordingly. /// - public class CatchComboDisplay : SkinnableDrawable + public partial class CatchComboDisplay : SkinnableDrawable { private int currentCombo; @@ -29,7 +29,7 @@ namespace osu.Game.Rulesets.Catch.UI { } - [Resolved(canBeNull: true)] + [Resolved] private Player? player { get; set; } protected override void LoadComplete() diff --git a/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs b/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs new file mode 100644 index 0000000000..4ae61ef8c7 --- /dev/null +++ b/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs @@ -0,0 +1,15 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics; +using osu.Game.Rulesets.UI; + +namespace osu.Game.Rulesets.Catch.UI +{ + public partial class CatchCursorContainer : GameplayCursorContainer + { + // Just hide the cursor. + // The main goal here is to show that we have a cursor so the game never shows the global one. + protected override Drawable CreateCursor() => Empty(); + } +} diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index ce000b0fad..c33d021876 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Beatmaps; @@ -10,12 +8,13 @@ using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects.Drawables; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; using osuTK; namespace osu.Game.Rulesets.Catch.UI { - public class CatchPlayfield : ScrollingPlayfield + public partial class CatchPlayfield : ScrollingPlayfield { /// /// The width of the playfield. @@ -38,9 +37,9 @@ namespace osu.Game.Rulesets.Catch.UI // only check the X position; handle all vertical space. base.ReceivePositionalInputAt(new Vector2(screenSpacePos.X, ScreenSpaceDrawQuad.Centre.Y)); - internal Catcher Catcher { get; private set; } + internal Catcher Catcher { get; private set; } = null!; - internal CatcherArea CatcherArea { get; private set; } + internal CatcherArea CatcherArea { get; private set; } = null!; private readonly IBeatmapDifficultyInfo difficulty; @@ -49,6 +48,8 @@ namespace osu.Game.Rulesets.Catch.UI this.difficulty = difficulty; } + protected override GameplayCursorContainer CreateCursor() => new CatchCursorContainer(); + [BackgroundDependencyLoader] private void load() { diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfieldAdjustmentContainer.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfieldAdjustmentContainer.cs index 82b85f54e4..74cbc665c0 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfieldAdjustmentContainer.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfieldAdjustmentContainer.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.UI; @@ -10,7 +8,7 @@ using osuTK; namespace osu.Game.Rulesets.Catch.UI { - public class CatchPlayfieldAdjustmentContainer : PlayfieldAdjustmentContainer + public partial class CatchPlayfieldAdjustmentContainer : PlayfieldAdjustmentContainer { private const float playfield_size_adjust = 0.8f; @@ -42,7 +40,7 @@ namespace osu.Game.Rulesets.Catch.UI /// /// A which scales its content relative to a target width. /// - private class ScalingContainer : Container + private partial class ScalingContainer : Container { protected override void Update() { diff --git a/osu.Game.Rulesets.Catch/UI/CatchReplayRecorder.cs b/osu.Game.Rulesets.Catch/UI/CatchReplayRecorder.cs index c118c14e3f..32ede8f205 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchReplayRecorder.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchReplayRecorder.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Collections.Generic; using osu.Game.Rulesets.Catch.Replays; using osu.Game.Rulesets.Replays; @@ -12,7 +10,7 @@ using osuTK; namespace osu.Game.Rulesets.Catch.UI { - public class CatchReplayRecorder : ReplayRecorder + public partial class CatchReplayRecorder : ReplayRecorder { private readonly CatchPlayfield playfield; diff --git a/osu.Game.Rulesets.Catch/UI/CatchTouchInputMapper.cs b/osu.Game.Rulesets.Catch/UI/CatchTouchInputMapper.cs index 12d695393f..10e43cf74a 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchTouchInputMapper.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchTouchInputMapper.cs @@ -11,11 +11,10 @@ using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Game.Graphics; using osuTK; -using osuTK.Input; namespace osu.Game.Rulesets.Catch.UI { - public class CatchTouchInputMapper : VisibilityContainer + public partial class CatchTouchInputMapper : VisibilityContainer { public override bool PropagatePositionalInputSubTree => true; public override bool PropagateNonPositionalInputSubTree => true; @@ -106,41 +105,17 @@ namespace osu.Game.Rulesets.Catch.UI return false; } - protected override bool OnMouseDown(MouseDownEvent e) - { - return updateAction(e.Button, getTouchCatchActionFromInput(e.ScreenSpaceMousePosition)); - } - protected override bool OnTouchDown(TouchDownEvent e) { return updateAction(e.Touch.Source, getTouchCatchActionFromInput(e.ScreenSpaceTouch.Position)); } - protected override bool OnMouseMove(MouseMoveEvent e) - { - Show(); - - TouchCatchAction? action = getTouchCatchActionFromInput(e.ScreenSpaceMousePosition); - - // multiple mouse buttons may be pressed and handling the same action. - foreach (MouseButton button in e.PressedButtons) - updateAction(button, action); - - return false; - } - protected override void OnTouchMove(TouchMoveEvent e) { updateAction(e.Touch.Source, getTouchCatchActionFromInput(e.ScreenSpaceTouch.Position)); base.OnTouchMove(e); } - protected override void OnMouseUp(MouseUpEvent e) - { - updateAction(e.Button, null); - base.OnMouseUp(e); - } - protected override void OnTouchUp(TouchUpEvent e) { updateAction(e.Touch.Source, null); @@ -205,7 +180,7 @@ namespace osu.Game.Rulesets.Catch.UI protected override void PopOut() => mainContent.FadeOut(300, Easing.OutQuint); - private class InputArea : CompositeDrawable, IKeyBindingHandler + private partial class InputArea : CompositeDrawable, IKeyBindingHandler { private readonly TouchCatchAction handledAction; diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs index 61fefcfd99..411330f6fc 100644 --- a/osu.Game.Rulesets.Catch/UI/Catcher.cs +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -1,11 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; +using System.Diagnostics; using System.Linq; -using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -26,7 +24,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Catch.UI { [Cached] - public class Catcher : SkinReloadableDrawable + public partial class Catcher : SkinReloadableDrawable { /// /// The size of the catcher at 1x scale. @@ -123,7 +121,7 @@ namespace osu.Game.Rulesets.Catch.UI private double hyperDashModifier = 1; private int hyperDashDirection; private float hyperDashTargetPosition; - private Bindable hitLighting; + private Bindable hitLighting = null!; private readonly HitExplosionContainer hitExplosionContainer; @@ -131,7 +129,7 @@ namespace osu.Game.Rulesets.Catch.UI private readonly DrawablePool caughtBananaPool; private readonly DrawablePool caughtDropletPool; - public Catcher([NotNull] DroppedObjectContainer droppedObjectTarget, IBeatmapDifficultyInfo difficulty = null) + public Catcher(DroppedObjectContainer droppedObjectTarget, IBeatmapDifficultyInfo? difficulty = null) { this.droppedObjectTarget = droppedObjectTarget; @@ -231,9 +229,8 @@ namespace osu.Game.Rulesets.Catch.UI // droplet doesn't affect the catcher state if (hitObject is TinyDroplet) return; - if (result.IsHit && hitObject.HyperDash) + if (result.IsHit && hitObject.HyperDashTarget is CatchHitObject target) { - var target = hitObject.HyperDashTarget; double timeDifference = target.StartTime - hitObject.StartTime; double positionDifference = target.EffectiveX - X; double velocity = positionDifference / Math.Max(1.0, timeDifference - 1000.0 / 60.0); @@ -385,7 +382,7 @@ namespace osu.Game.Rulesets.Catch.UI private void addLighting(JudgementResult judgementResult, Color4 colour, float x) => hitExplosionContainer.Add(new HitExplosionEntry(Time.Current, judgementResult, colour, x)); - private CaughtObject getCaughtObject(PalpableCatchHitObject source) + private CaughtObject? getCaughtObject(PalpableCatchHitObject source) { switch (source) { @@ -406,6 +403,7 @@ namespace osu.Game.Rulesets.Catch.UI private CaughtObject getDroppedObject(CaughtObject caughtObject) { var droppedObject = getCaughtObject(caughtObject.HitObject); + Debug.Assert(droppedObject != null); droppedObject.CopyStateFrom(caughtObject); droppedObject.Anchor = Anchor.TopLeft; diff --git a/osu.Game.Rulesets.Catch/UI/CatcherAnimationState.cs b/osu.Game.Rulesets.Catch/UI/CatcherAnimationState.cs index 82591eb47f..566e9d1911 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherAnimationState.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherAnimationState.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - namespace osu.Game.Rulesets.Catch.UI { public enum CatcherAnimationState diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 7a29ba9801..4f7535d13a 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -21,7 +19,7 @@ namespace osu.Game.Rulesets.Catch.UI /// It holds a as a child and translates input to the catcher movement. /// It also holds a combo display that is above the catcher, and judgment results are translated to the catcher and the combo display. /// - public class CatcherArea : Container, IKeyBindingHandler + public partial class CatcherArea : Container, IKeyBindingHandler { public Catcher Catcher { @@ -35,7 +33,7 @@ namespace osu.Game.Rulesets.Catch.UI private readonly CatcherTrailDisplay catcherTrails; - private Catcher catcher; + private Catcher catcher = null!; /// /// -1 when only left button is pressed. diff --git a/osu.Game.Rulesets.Catch/UI/CatcherTrail.cs b/osu.Game.Rulesets.Catch/UI/CatcherTrail.cs index afaa037574..762f95828a 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherTrail.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherTrail.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Timing; using osu.Game.Rulesets.Objects.Pooling; @@ -14,7 +12,7 @@ namespace osu.Game.Rulesets.Catch.UI /// A trail of the catcher. /// It also represents a hyper dash afterimage. /// - public class CatcherTrail : PoolableDrawableWithLifetime + public partial class CatcherTrail : PoolableDrawableWithLifetime { private readonly SkinnableCatcher body; diff --git a/osu.Game.Rulesets.Catch/UI/CatcherTrailAnimation.cs b/osu.Game.Rulesets.Catch/UI/CatcherTrailAnimation.cs index 02bc5be863..0a5281cd10 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherTrailAnimation.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherTrailAnimation.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - namespace osu.Game.Rulesets.Catch.UI { public enum CatcherTrailAnimation diff --git a/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs b/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs index d255937fed..e3e01c1b39 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs @@ -1,10 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using osu.Framework.Allocation; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Pooling; @@ -19,7 +18,7 @@ namespace osu.Game.Rulesets.Catch.UI /// Represents a component responsible for displaying /// the appropriate catcher trails when requested to. /// - public class CatcherTrailDisplay : PooledDrawableWithLifetimeContainer + public partial class CatcherTrailDisplay : PooledDrawableWithLifetimeContainer { /// /// The most recent time a dash trail was added to this container. @@ -41,7 +40,7 @@ namespace osu.Game.Rulesets.Catch.UI private readonly Container hyperDashAfterImages; [Resolved] - private ISkinSource skin { get; set; } + private ISkinSource skin { get; set; } = null!; public CatcherTrailDisplay() { @@ -130,7 +129,7 @@ namespace osu.Game.Rulesets.Catch.UI { base.Dispose(isDisposing); - if (skin != null) + if (skin.IsNotNull()) skin.SourceChanged -= skinSourceChanged; } } diff --git a/osu.Game.Rulesets.Catch/UI/CatcherTrailEntry.cs b/osu.Game.Rulesets.Catch/UI/CatcherTrailEntry.cs index 78d6979b78..3a40ab26cc 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherTrailEntry.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherTrailEntry.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Graphics.Performance; using osuTK; diff --git a/osu.Game.Rulesets.Catch/UI/Direction.cs b/osu.Game.Rulesets.Catch/UI/Direction.cs index 15e4aed86b..65f064b7fb 100644 --- a/osu.Game.Rulesets.Catch/UI/Direction.cs +++ b/osu.Game.Rulesets.Catch/UI/Direction.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - namespace osu.Game.Rulesets.Catch.UI { public enum Direction diff --git a/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs b/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs index e02b915508..7930a07551 100644 --- a/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; @@ -21,13 +19,13 @@ using osu.Game.Scoring; namespace osu.Game.Rulesets.Catch.UI { - public class DrawableCatchRuleset : DrawableScrollingRuleset + public partial class DrawableCatchRuleset : DrawableScrollingRuleset { protected override ScrollVisualisationMethod VisualisationMethod => ScrollVisualisationMethod.Constant; protected override bool UserScrollSpeedAdjustment => false; - public DrawableCatchRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList mods = null) + public DrawableCatchRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList? mods = null) : base(ruleset, beatmap, mods) { Direction.Value = ScrollingDirection.Down; @@ -54,6 +52,6 @@ namespace osu.Game.Rulesets.Catch.UI protected override PassThroughInputManager CreateInputManager() => new CatchInputManager(Ruleset.RulesetInfo); - public override DrawableHitObject CreateDrawableRepresentation(CatchHitObject h) => null; + public override DrawableHitObject? CreateDrawableRepresentation(CatchHitObject h) => null; } } diff --git a/osu.Game.Rulesets.Catch/UI/DroppedObjectContainer.cs b/osu.Game.Rulesets.Catch/UI/DroppedObjectContainer.cs index 1e4da479d2..df1e932ad5 100644 --- a/osu.Game.Rulesets.Catch/UI/DroppedObjectContainer.cs +++ b/osu.Game.Rulesets.Catch/UI/DroppedObjectContainer.cs @@ -1,15 +1,13 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Catch.Objects.Drawables; namespace osu.Game.Rulesets.Catch.UI { - public class DroppedObjectContainer : Container + public partial class DroppedObjectContainer : Container { public DroppedObjectContainer() { diff --git a/osu.Game.Rulesets.Catch/UI/HitExplosion.cs b/osu.Game.Rulesets.Catch/UI/HitExplosion.cs index 9b32893efe..c53957100a 100644 --- a/osu.Game.Rulesets.Catch/UI/HitExplosion.cs +++ b/osu.Game.Rulesets.Catch/UI/HitExplosion.cs @@ -8,7 +8,7 @@ using osu.Game.Skinning; namespace osu.Game.Rulesets.Catch.UI { - public class HitExplosion : PoolableDrawableWithLifetime + public partial class HitExplosion : PoolableDrawableWithLifetime { private readonly SkinnableDrawable skinnableExplosion; diff --git a/osu.Game.Rulesets.Catch/UI/HitExplosionContainer.cs b/osu.Game.Rulesets.Catch/UI/HitExplosionContainer.cs index 2004c971ad..1e2d94433c 100644 --- a/osu.Game.Rulesets.Catch/UI/HitExplosionContainer.cs +++ b/osu.Game.Rulesets.Catch/UI/HitExplosionContainer.cs @@ -1,15 +1,13 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Pooling; using osu.Game.Rulesets.Objects.Pooling; namespace osu.Game.Rulesets.Catch.UI { - public class HitExplosionContainer : PooledDrawableWithLifetimeContainer + public partial class HitExplosionContainer : PooledDrawableWithLifetimeContainer { protected override bool RemoveRewoundEntry => true; diff --git a/osu.Game.Rulesets.Catch/UI/ICatchComboCounter.cs b/osu.Game.Rulesets.Catch/UI/ICatchComboCounter.cs index 5d027edbaa..cfb6879067 100644 --- a/osu.Game.Rulesets.Catch/UI/ICatchComboCounter.cs +++ b/osu.Game.Rulesets.Catch/UI/ICatchComboCounter.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Graphics; using osuTK.Graphics; diff --git a/osu.Game.Rulesets.Catch/UI/SkinnableCatcher.cs b/osu.Game.Rulesets.Catch/UI/SkinnableCatcher.cs index fa6ccf6bd6..bcc59a5e4f 100644 --- a/osu.Game.Rulesets.Catch/UI/SkinnableCatcher.cs +++ b/osu.Game.Rulesets.Catch/UI/SkinnableCatcher.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -16,7 +14,7 @@ namespace osu.Game.Rulesets.Catch.UI /// The visual representation of the . /// It includes the body part of the catcher and the catcher plate. /// - public class SkinnableCatcher : SkinnableDrawable + public partial class SkinnableCatcher : SkinnableDrawable { /// /// This is used by skin elements to determine which texture of the catcher is used. diff --git a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj index e2f95ca177..ecce7c1b3f 100644 --- a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj +++ b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj @@ -1,6 +1,6 @@  - netstandard2.1 + net6.0 Library true catch the fruit. to the beat. @@ -15,4 +15,4 @@ - \ No newline at end of file + diff --git a/osu.Game.Rulesets.Mania.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Rulesets.Mania.Tests.Android/AndroidManifest.xml similarity index 95% rename from osu.Game.Rulesets.Mania.Tests.Android/Properties/AndroidManifest.xml rename to osu.Game.Rulesets.Mania.Tests.Android/AndroidManifest.xml index de7935b2ef..4a1545a423 100644 --- a/osu.Game.Rulesets.Mania.Tests.Android/Properties/AndroidManifest.xml +++ b/osu.Game.Rulesets.Mania.Tests.Android/AndroidManifest.xml @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania.Tests.Android/osu.Game.Rulesets.Mania.Tests.Android.csproj b/osu.Game.Rulesets.Mania.Tests.Android/osu.Game.Rulesets.Mania.Tests.Android.csproj index 9674186039..25335754d2 100644 --- a/osu.Game.Rulesets.Mania.Tests.Android/osu.Game.Rulesets.Mania.Tests.Android.csproj +++ b/osu.Game.Rulesets.Mania.Tests.Android/osu.Game.Rulesets.Mania.Tests.Android.csproj @@ -1,49 +1,24 @@ - - + - Debug - AnyCPU - 8.0.30703 - 2.0 - {531F1092-DB27-445D-AA33-2A77C7187C99} - {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - {122416d6-6b49-4ee2-a1e8-b825f31c79fe} + net6.0-android + Exe osu.Game.Rulesets.Mania.Tests osu.Game.Rulesets.Mania.Tests.Android - Properties\AndroidManifest.xml - armeabi-v7a;x86;arm64-v8a - - - None - cjk;mideast;other;rare;west - true - - - - - - - + %(RecursiveDir)%(Filename)%(Extension) + + + %(RecursiveDir)%(Filename)%(Extension) + Android\%(RecursiveDir)%(Filename)%(Extension) + - - {48f4582b-7687-4621-9cbe-5c24197cb536} - osu.Game.Rulesets.Mania - - - {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D} - osu.Game - + + - - - 5.0.0 - - - \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania.Tests.iOS/Application.cs b/osu.Game.Rulesets.Mania.Tests.iOS/Application.cs index 2d1015387a..a508198f7f 100644 --- a/osu.Game.Rulesets.Mania.Tests.iOS/Application.cs +++ b/osu.Game.Rulesets.Mania.Tests.iOS/Application.cs @@ -3,7 +3,6 @@ #nullable disable -using osu.Framework.iOS; using UIKit; namespace osu.Game.Rulesets.Mania.Tests.iOS @@ -12,7 +11,7 @@ namespace osu.Game.Rulesets.Mania.Tests.iOS { public static void Main(string[] args) { - UIApplication.Main(args, typeof(GameUIApplication), typeof(AppDelegate)); + UIApplication.Main(args, null, typeof(AppDelegate)); } } } diff --git a/osu.Game.Rulesets.Mania.Tests.iOS/Info.plist b/osu.Game.Rulesets.Mania.Tests.iOS/Info.plist index 82d1c8ea24..ff5dde856e 100644 --- a/osu.Game.Rulesets.Mania.Tests.iOS/Info.plist +++ b/osu.Game.Rulesets.Mania.Tests.iOS/Info.plist @@ -13,7 +13,7 @@ LSRequiresIPhoneOS MinimumOSVersion - 10.0 + 13.4 UIDeviceFamily 1 diff --git a/osu.Game.Rulesets.Mania.Tests.iOS/osu.Game.Rulesets.Mania.Tests.iOS.csproj b/osu.Game.Rulesets.Mania.Tests.iOS/osu.Game.Rulesets.Mania.Tests.iOS.csproj index 88ad484bc1..51e07dd6c1 100644 --- a/osu.Game.Rulesets.Mania.Tests.iOS/osu.Game.Rulesets.Mania.Tests.iOS.csproj +++ b/osu.Game.Rulesets.Mania.Tests.iOS/osu.Game.Rulesets.Mania.Tests.iOS.csproj @@ -1,35 +1,19 @@ - - + - Debug - iPhoneSimulator - {39FD990E-B6CE-4B2A-999F-BC008CF2C64C} Exe + net6.0-ios + 13.4 osu.Game.Rulesets.Mania.Tests osu.Game.Rulesets.Mania.Tests.iOS - - - - Linker.xml - - - %(RecursiveDir)%(Filename)%(Extension) - - {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D} - osu.Game - - - {48F4582B-7687-4621-9CBE-5C24197CB536} - osu.Game.Rulesets.Mania - + + - - \ No newline at end of file + diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/ManiaPlacementBlueprintTestScene.cs b/osu.Game.Rulesets.Mania.Tests/Editor/ManiaPlacementBlueprintTestScene.cs index 0e4f612999..d2a44122aa 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/ManiaPlacementBlueprintTestScene.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/ManiaPlacementBlueprintTestScene.cs @@ -21,7 +21,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Mania.Tests.Editor { - public abstract class ManiaPlacementBlueprintTestScene : PlacementBlueprintTestScene + public abstract partial class ManiaPlacementBlueprintTestScene : PlacementBlueprintTestScene { private readonly Column column; diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/ManiaSelectionBlueprintTestScene.cs b/osu.Game.Rulesets.Mania.Tests/Editor/ManiaSelectionBlueprintTestScene.cs index 4cadcf138b..2fda012f07 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/ManiaSelectionBlueprintTestScene.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/ManiaSelectionBlueprintTestScene.cs @@ -15,7 +15,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Mania.Tests.Editor { - public abstract class ManiaSelectionBlueprintTestScene : SelectionBlueprintTestScene + public abstract partial class ManiaSelectionBlueprintTestScene : SelectionBlueprintTestScene { protected override Container Content => blueprints ?? base.Content; diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneEditor.cs b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneEditor.cs index 99850f33b8..0a21098d0d 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneEditor.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneEditor.cs @@ -14,7 +14,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Mania.Tests.Editor { [TestFixture] - public class TestSceneEditor : EditorTestScene + public partial class TestSceneEditor : EditorTestScene { private readonly Bindable direction = new Bindable(); diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneHoldNotePlacementBlueprint.cs b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneHoldNotePlacementBlueprint.cs index ddec1f3432..4b332c3faa 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneHoldNotePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneHoldNotePlacementBlueprint.cs @@ -12,7 +12,7 @@ using osu.Game.Rulesets.Objects.Drawables; namespace osu.Game.Rulesets.Mania.Tests.Editor { - public class TestSceneHoldNotePlacementBlueprint : ManiaPlacementBlueprintTestScene + public partial class TestSceneHoldNotePlacementBlueprint : ManiaPlacementBlueprintTestScene { protected override DrawableHitObject CreateHitObject(HitObject hitObject) => new DrawableHoldNote((HoldNote)hitObject); protected override PlacementBlueprint CreateBlueprint() => new HoldNotePlacementBlueprint(); diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneHoldNoteSelectionBlueprint.cs b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneHoldNoteSelectionBlueprint.cs index b70d4e4fa6..a65f949cec 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneHoldNoteSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneHoldNoteSelectionBlueprint.cs @@ -11,7 +11,7 @@ using osu.Game.Rulesets.Mania.Objects.Drawables; namespace osu.Game.Rulesets.Mania.Tests.Editor { - public class TestSceneHoldNoteSelectionBlueprint : ManiaSelectionBlueprintTestScene + public partial class TestSceneHoldNoteSelectionBlueprint : ManiaSelectionBlueprintTestScene { public TestSceneHoldNoteSelectionBlueprint() : base(4) diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaBeatSnapGrid.cs b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaBeatSnapGrid.cs index ef140995ec..aca555552f 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaBeatSnapGrid.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaBeatSnapGrid.cs @@ -24,7 +24,7 @@ using osuTK; namespace osu.Game.Rulesets.Mania.Tests.Editor { - public class TestSceneManiaBeatSnapGrid : EditorClockTestScene + public partial class TestSceneManiaBeatSnapGrid : EditorClockTestScene { [Cached(typeof(IScrollingInfo))] private ScrollingTestContainer.TestScrollingInfo scrollingInfo = new ScrollingTestContainer.TestScrollingInfo(); @@ -83,13 +83,14 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor public ManiaPlayfield Playfield { get; } } - public class TestHitObjectComposer : HitObjectComposer + public partial class TestHitObjectComposer : HitObjectComposer { public override Playfield Playfield { get; } public override IEnumerable HitObjects => Enumerable.Empty(); public override bool CursorInPlacementArea => false; public TestHitObjectComposer(Playfield playfield) + : base(new ManiaRuleset()) { Playfield = playfield; } diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaComposeScreen.cs b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaComposeScreen.cs index e082b90d3b..a1f4b234c4 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaComposeScreen.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaComposeScreen.cs @@ -22,7 +22,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Mania.Tests.Editor { - public class TestSceneManiaComposeScreen : EditorClockTestScene + public partial class TestSceneManiaComposeScreen : EditorClockTestScene { [Resolved] private SkinManager skins { get; set; } diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaHitObjectComposer.cs index a3985be936..8e0b51dcf8 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaHitObjectComposer.cs @@ -27,7 +27,7 @@ using osuTK.Input; namespace osu.Game.Rulesets.Mania.Tests.Editor { - public class TestSceneManiaHitObjectComposer : EditorClockTestScene + public partial class TestSceneManiaHitObjectComposer : EditorClockTestScene { private TestComposer composer; @@ -193,7 +193,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor private void setScrollStep(ScrollingDirection direction) => AddStep($"set scroll direction = {direction}", () => ((Bindable)composer.Composer.ScrollingInfo.Direction).Value = direction); - private class TestComposer : CompositeDrawable + private partial class TestComposer : CompositeDrawable { [Cached(typeof(EditorBeatmap))] [Cached(typeof(IBeatSnapProvider))] diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneNotePlacementBlueprint.cs b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneNotePlacementBlueprint.cs index 28c002eef8..a446f13cbf 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneNotePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneNotePlacementBlueprint.cs @@ -21,7 +21,7 @@ using osuTK.Input; namespace osu.Game.Rulesets.Mania.Tests.Editor { - public class TestSceneNotePlacementBlueprint : ManiaPlacementBlueprintTestScene + public partial class TestSceneNotePlacementBlueprint : ManiaPlacementBlueprintTestScene { [SetUp] public void Setup() => Schedule(() => diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneNoteSelectionBlueprint.cs b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneNoteSelectionBlueprint.cs index f61d416e3b..86e87e7486 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneNoteSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneNoteSelectionBlueprint.cs @@ -11,7 +11,7 @@ using osu.Game.Rulesets.Mania.Objects.Drawables; namespace osu.Game.Rulesets.Mania.Tests.Editor { - public class TestSceneNoteSelectionBlueprint : ManiaSelectionBlueprintTestScene + public partial class TestSceneNoteSelectionBlueprint : ManiaSelectionBlueprintTestScene { public TestSceneNoteSelectionBlueprint() : base(4) diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaInputTestScene.cs b/osu.Game.Rulesets.Mania.Tests/ManiaInputTestScene.cs index e456659ac4..c85583c1fd 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaInputTestScene.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaInputTestScene.cs @@ -12,7 +12,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Mania.Tests { - public abstract class ManiaInputTestScene : OsuTestScene + public abstract partial class ManiaInputTestScene : OsuTestScene { private readonly Container content; protected override Container Content => content ?? base.Content; @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Mania.Tests base.Content.Add(content = new LocalInputManager(keys)); } - private class LocalInputManager : ManiaInputManager + private partial class LocalInputManager : ManiaInputManager { public LocalInputManager(int variant) : base(new ManiaRuleset().RulesetInfo, variant) @@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.Mania.Tests protected override KeyBindingContainer CreateKeyBindingContainer(RulesetInfo ruleset, int variant, SimultaneousBindingMode unique) => new LocalKeyBindingContainer(ruleset, variant, unique); - private class LocalKeyBindingContainer : RulesetKeyBindingContainer + private partial class LocalKeyBindingContainer : RulesetKeyBindingContainer { public LocalKeyBindingContainer(RulesetInfo ruleset, int variant, SimultaneousBindingMode unique) : base(ruleset, variant, unique) diff --git a/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModConstantSpeed.cs b/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModConstantSpeed.cs index 60363aaeef..dc4f660a45 100644 --- a/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModConstantSpeed.cs +++ b/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModConstantSpeed.cs @@ -13,7 +13,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Mania.Tests.Mods { - public class TestSceneManiaModConstantSpeed : ModTestScene + public partial class TestSceneManiaModConstantSpeed : ModTestScene { protected override Ruleset CreatePlayerRuleset() => new ManiaRuleset(); diff --git a/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModFlashlight.cs b/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModFlashlight.cs index 0e222fea89..001d53c887 100644 --- a/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModFlashlight.cs +++ b/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModFlashlight.cs @@ -7,7 +7,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Mania.Tests.Mods { - public class TestSceneManiaModFlashlight : ModTestScene + public partial class TestSceneManiaModFlashlight : ModTestScene { protected override Ruleset CreatePlayerRuleset() => new ManiaRuleset(); diff --git a/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModHoldOff.cs b/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModHoldOff.cs index d27a79c41d..3011a93755 100644 --- a/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModHoldOff.cs +++ b/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModHoldOff.cs @@ -13,7 +13,7 @@ using osu.Game.Rulesets.Mania.Beatmaps; namespace osu.Game.Rulesets.Mania.Tests.Mods { - public class TestSceneManiaModHoldOff : ModTestScene + public partial class TestSceneManiaModHoldOff : ModTestScene { protected override Ruleset CreatePlayerRuleset() => new ManiaRuleset(); diff --git a/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModInvert.cs b/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModInvert.cs index f2cc254e38..2977241dc6 100644 --- a/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModInvert.cs +++ b/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModInvert.cs @@ -7,7 +7,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Mania.Tests.Mods { - public class TestSceneManiaModInvert : ModTestScene + public partial class TestSceneManiaModInvert : ModTestScene { protected override Ruleset CreatePlayerRuleset() => new ManiaRuleset(); diff --git a/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModPerfect.cs b/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModPerfect.cs index 2e3b21aed7..97a6ee28f4 100644 --- a/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModPerfect.cs +++ b/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModPerfect.cs @@ -8,7 +8,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Mania.Tests.Mods { - public class TestSceneManiaModPerfect : ModPerfectTestScene + public partial class TestSceneManiaModPerfect : ModPerfectTestScene { protected override Ruleset CreatePlayerRuleset() => new ManiaRuleset(); diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/ColumnTestContainer.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/ColumnTestContainer.cs index d3e90170b2..0c55cebf0d 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/ColumnTestContainer.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/ColumnTestContainer.cs @@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning /// /// A container to be used in a to provide a resolvable dependency. /// - public class ColumnTestContainer : Container + public partial class ColumnTestContainer : Container { protected override Container Content => content; diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaHitObjectTestScene.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaHitObjectTestScene.cs index 75175c43d8..25e120edc5 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaHitObjectTestScene.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaHitObjectTestScene.cs @@ -15,7 +15,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning /// /// A test scene for a mania hitobject. /// - public abstract class ManiaHitObjectTestScene : ManiaSkinnableTestScene + public abstract partial class ManiaHitObjectTestScene : ManiaSkinnableTestScene { [SetUp] public void SetUp() => Schedule(() => diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaSkinnableTestScene.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaSkinnableTestScene.cs index 2c5535a65f..30bd600d9d 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaSkinnableTestScene.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaSkinnableTestScene.cs @@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning /// /// A test scene for skinnable mania components. /// - public abstract class ManiaSkinnableTestScene : SkinnableTestScene + public abstract partial class ManiaSkinnableTestScene : SkinnableTestScene { [Cached(Type = typeof(IScrollingInfo))] private readonly TestScrollingInfo scrollingInfo = new TestScrollingInfo(); diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneBarLine.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneBarLine.cs index 1bfe55b074..ab9f57ecc3 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneBarLine.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneBarLine.cs @@ -11,7 +11,7 @@ using osu.Game.Rulesets.Mania.UI; namespace osu.Game.Rulesets.Mania.Tests.Skinning { - public class TestSceneBarLine : ManiaSkinnableTestScene + public partial class TestSceneBarLine : ManiaSkinnableTestScene { [Test] public void TestMinor() diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneColumnBackground.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneColumnBackground.cs index 3dece20308..3881aae22e 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneColumnBackground.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneColumnBackground.cs @@ -12,7 +12,7 @@ using osuTK; namespace osu.Game.Rulesets.Mania.Tests.Skinning { - public class TestSceneColumnBackground : ManiaSkinnableTestScene + public partial class TestSceneColumnBackground : ManiaSkinnableTestScene { [BackgroundDependencyLoader] private void load() diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneColumnHitObjectArea.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneColumnHitObjectArea.cs index 1fb9d448a9..9cccc2dd86 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneColumnHitObjectArea.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneColumnHitObjectArea.cs @@ -12,7 +12,7 @@ using osuTK; namespace osu.Game.Rulesets.Mania.Tests.Skinning { - public class TestSceneColumnHitObjectArea : ManiaSkinnableTestScene + public partial class TestSceneColumnHitObjectArea : ManiaSkinnableTestScene { [BackgroundDependencyLoader] private void load() diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneDrawableJudgement.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneDrawableJudgement.cs index 8b12d37fe9..2a9727dbd4 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneDrawableJudgement.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneDrawableJudgement.cs @@ -17,7 +17,7 @@ using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Mania.Tests.Skinning { - public class TestSceneDrawableJudgement : ManiaSkinnableTestScene + public partial class TestSceneDrawableJudgement : ManiaSkinnableTestScene { public TestSceneDrawableJudgement() { diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneHitExplosion.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneHitExplosion.cs index 744721f1a3..30dd83123d 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneHitExplosion.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneHitExplosion.cs @@ -20,7 +20,7 @@ using osuTK; namespace osu.Game.Rulesets.Mania.Tests.Skinning { [TestFixture] - public class TestSceneHitExplosion : ManiaSkinnableTestScene + public partial class TestSceneHitExplosion : ManiaSkinnableTestScene { private readonly List> hitExplosionPools = new List>(); diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneHoldNote.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneHoldNote.cs index 0947ddfeb0..0b9ca42af8 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneHoldNote.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneHoldNote.cs @@ -15,7 +15,7 @@ using osu.Game.Rulesets.Mania.Objects.Drawables; namespace osu.Game.Rulesets.Mania.Tests.Skinning { - public class TestSceneHoldNote : ManiaHitObjectTestScene + public partial class TestSceneHoldNote : ManiaHitObjectTestScene { [Test] public void TestHoldNote() diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneNote.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneNote.cs index 85995e6994..d049d88ea8 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneNote.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneNote.cs @@ -10,7 +10,7 @@ using osu.Game.Rulesets.Mania.Objects.Drawables; namespace osu.Game.Rulesets.Mania.Tests.Skinning { - public class TestSceneNote : ManiaHitObjectTestScene + public partial class TestSceneNote : ManiaHitObjectTestScene { protected override DrawableManiaHitObject CreateHitObject() { diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/TestScenePlayfield.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/TestScenePlayfield.cs index 9817719c94..f85e303940 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/TestScenePlayfield.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/TestScenePlayfield.cs @@ -11,7 +11,7 @@ using osu.Game.Rulesets.Mania.UI; namespace osu.Game.Rulesets.Mania.Tests.Skinning { - public class TestScenePlayfield : ManiaSkinnableTestScene + public partial class TestScenePlayfield : ManiaSkinnableTestScene { private List stageDefinitions = new List(); diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneStage.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneStage.cs index 07aa0b845f..25e24929c9 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneStage.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneStage.cs @@ -9,7 +9,7 @@ using osu.Game.Rulesets.Mania.UI; namespace osu.Game.Rulesets.Mania.Tests.Skinning { - public class TestSceneStage : ManiaSkinnableTestScene + public partial class TestSceneStage : ManiaSkinnableTestScene { [BackgroundDependencyLoader] private void load() diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneStageBackground.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneStageBackground.cs index 5c8e038eed..0557a201c8 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneStageBackground.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneStageBackground.cs @@ -10,7 +10,7 @@ using osu.Game.Skinning; namespace osu.Game.Rulesets.Mania.Tests.Skinning { - public class TestSceneStageBackground : ManiaSkinnableTestScene + public partial class TestSceneStageBackground : ManiaSkinnableTestScene { [BackgroundDependencyLoader] private void load() diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneStageForeground.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneStageForeground.cs index f9c17ee7f4..04d2eee83e 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneStageForeground.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneStageForeground.cs @@ -9,7 +9,7 @@ using osu.Game.Skinning; namespace osu.Game.Rulesets.Mania.Tests.Skinning { - public class TestSceneStageForeground : ManiaSkinnableTestScene + public partial class TestSceneStageForeground : ManiaSkinnableTestScene { [BackgroundDependencyLoader] private void load() diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs index 3abeb8a5f6..9fdd93bcc9 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs @@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Mania.Tests { [TestFixture] [HeadlessTest] - public class TestSceneAutoGeneration : OsuTestScene + public partial class TestSceneAutoGeneration : OsuTestScene { /// /// The number of frames which are generated at the start of a replay regardless of hitobject content. diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneColumn.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneColumn.cs index 83491b6fe9..b96fab9ec0 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneColumn.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneColumn.cs @@ -24,7 +24,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Mania.Tests { [TestFixture] - public class TestSceneColumn : ManiaInputTestScene + public partial class TestSceneColumn : ManiaInputTestScene { [Cached(typeof(IReadOnlyList))] private IReadOnlyList mods { get; set; } = Array.Empty(); diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneDrawableManiaHitObject.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneDrawableManiaHitObject.cs index d273f5cb35..51c2bac6d1 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneDrawableManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneDrawableManiaHitObject.cs @@ -20,7 +20,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Mania.Tests { - public class TestSceneDrawableManiaHitObject : OsuTestScene + public partial class TestSceneDrawableManiaHitObject : OsuTestScene { private readonly ManualClock clock = new ManualClock(); diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs index 0cba2076be..42e2099e3f 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs @@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.Mania.Tests /// x : button press /// o : button release /// - public class TestSceneHoldNoteInput : RateAdjustedBeatmapTestScene + public partial class TestSceneHoldNoteInput : RateAdjustedBeatmapTestScene { private const double time_before_head = 250; private const double time_head = 1500; @@ -572,7 +572,7 @@ namespace osu.Game.Rulesets.Mania.Tests AddUntilStep("Wait for completion", () => currentPlayer.ScoreProcessor?.HasCompleted.Value == true); } - private class ScoreAccessibleReplayPlayer : ReplayPlayer + private partial class ScoreAccessibleReplayPlayer : ReplayPlayer { public new ScoreProcessor ScoreProcessor => base.ScoreProcessor; diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneManiaHitObjectSamples.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneManiaHitObjectSamples.cs index 00f0fcefd9..7021c081b7 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneManiaHitObjectSamples.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneManiaHitObjectSamples.cs @@ -10,7 +10,7 @@ using osu.Game.Tests.Beatmaps; namespace osu.Game.Rulesets.Mania.Tests { - public class TestSceneManiaHitObjectSamples : HitObjectSampleTest + public partial class TestSceneManiaHitObjectSamples : HitObjectSampleTest { protected override Ruleset CreatePlayerRuleset() => new ManiaRuleset(); protected override IResourceStore RulesetResources => new DllResourceStore(Assembly.GetAssembly(typeof(TestSceneManiaHitObjectSamples))); diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneManiaPlayer.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneManiaPlayer.cs index 9abedc22f9..98046320cb 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneManiaPlayer.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneManiaPlayer.cs @@ -7,7 +7,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Mania.Tests { - public class TestSceneManiaPlayer : PlayerTestScene + public partial class TestSceneManiaPlayer : PlayerTestScene { protected override Ruleset CreatePlayerRuleset() => new ManiaRuleset(); } diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs index df831d8c9f..31ff57395c 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs @@ -29,7 +29,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Mania.Tests { [TestFixture] - public class TestSceneNotes : OsuTestScene + public partial class TestSceneNotes : OsuTestScene { [Test] public void TestVariousNotes() @@ -105,7 +105,7 @@ namespace osu.Game.Rulesets.Mania.Tests private bool verifyAnchors(DrawableHoldNote holdNote, Anchor expectedAnchor) => verifyAnchors((DrawableHitObject)holdNote, expectedAnchor) && holdNote.NestedHitObjects.All(n => verifyAnchors(n, expectedAnchor)); - private class NoteContainer : Container + private partial class NoteContainer : Container { private readonly Container content; protected override Container Content => content; diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneOutOfOrderHits.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneOutOfOrderHits.cs index 464dbecee5..e49b259615 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneOutOfOrderHits.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneOutOfOrderHits.cs @@ -24,7 +24,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Mania.Tests { - public class TestSceneOutOfOrderHits : RateAdjustedBeatmapTestScene + public partial class TestSceneOutOfOrderHits : RateAdjustedBeatmapTestScene { [Test] public void TestPreviousHitWindowDoesNotExtendPastNextObject() @@ -171,7 +171,7 @@ namespace osu.Game.Rulesets.Mania.Tests AddUntilStep("Wait for completion", () => currentPlayer.ScoreProcessor.HasCompleted.Value); } - private class ScoreAccessibleReplayPlayer : ReplayPlayer + private partial class ScoreAccessibleReplayPlayer : ReplayPlayer { public new ScoreProcessor ScoreProcessor => base.ScoreProcessor; diff --git a/osu.Game.Rulesets.Mania.Tests/TestScenePlayfieldCoveringContainer.cs b/osu.Game.Rulesets.Mania.Tests/TestScenePlayfieldCoveringContainer.cs index 64e7eafb1b..f497c88bcc 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestScenePlayfieldCoveringContainer.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestScenePlayfieldCoveringContainer.cs @@ -14,7 +14,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Mania.Tests { - public class TestScenePlayfieldCoveringContainer : OsuTestScene + public partial class TestScenePlayfieldCoveringContainer : OsuTestScene { private readonly ScrollingTestContainer scrollingContainer; private readonly PlayfieldCoveringWrapper cover; diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneStage.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneStage.cs index 6387dac957..86499a7c6e 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneStage.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneStage.cs @@ -24,7 +24,7 @@ using osuTK; namespace osu.Game.Rulesets.Mania.Tests { [TestFixture] - public class TestSceneStage : ManiaInputTestScene + public partial class TestSceneStage : ManiaInputTestScene { private const int columns = 4; diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneTimingBasedNoteColouring.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneTimingBasedNoteColouring.cs index 9f2e3d2502..81557c198d 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneTimingBasedNoteColouring.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneTimingBasedNoteColouring.cs @@ -24,7 +24,7 @@ using osu.Game.Rulesets.Mania.UI; namespace osu.Game.Rulesets.Mania.Tests { [TestFixture] - public class TestSceneTimingBasedNoteColouring : OsuTestScene + public partial class TestSceneTimingBasedNoteColouring : OsuTestScene { private Bindable configTimingBasedNoteColouring; diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs index 308238d87a..77f93b4ef9 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs @@ -35,8 +35,8 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy protected PatternGenerator(LegacyRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern, IBeatmap originalBeatmap) : base(hitObject, beatmap, previousPattern) { - if (random == null) throw new ArgumentNullException(nameof(random)); - if (originalBeatmap == null) throw new ArgumentNullException(nameof(originalBeatmap)); + ArgumentNullException.ThrowIfNull(random); + ArgumentNullException.ThrowIfNull(originalBeatmap); Random = random; OriginalBeatmap = originalBeatmap; diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs index b2e89c3410..931673f337 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs @@ -33,9 +33,9 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns protected PatternGenerator(HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern) { - if (hitObject == null) throw new ArgumentNullException(nameof(hitObject)); - if (beatmap == null) throw new ArgumentNullException(nameof(beatmap)); - if (previousPattern == null) throw new ArgumentNullException(nameof(previousPattern)); + ArgumentNullException.ThrowIfNull(hitObject); + ArgumentNullException.ThrowIfNull(beatmap); + ArgumentNullException.ThrowIfNull(previousPattern); HitObject = hitObject; Beatmap = beatmap; diff --git a/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs b/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs index d367c82ed8..99a80ef28d 100644 --- a/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs +++ b/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs @@ -4,6 +4,7 @@ using System; using osu.Framework.Configuration.Tracking; using osu.Game.Configuration; +using osu.Game.Localisation; using osu.Game.Rulesets.Configuration; using osu.Game.Rulesets.Mania.UI; @@ -30,8 +31,8 @@ namespace osu.Game.Rulesets.Mania.Configuration new TrackedSetting(ManiaRulesetSetting.ScrollTime, scrollTime => new SettingDescription( rawValue: scrollTime, - name: "Scroll Speed", - value: $"{scrollTime}ms (speed {(int)Math.Round(DrawableManiaRuleset.MAX_TIME_RANGE / scrollTime)})" + name: RulesetSettingsStrings.ScrollSpeed, + value: RulesetSettingsStrings.ScrollSpeedTooltip(scrollTime, (int)Math.Round(DrawableManiaRuleset.MAX_TIME_RANGE / scrollTime)) ) ) }; diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/Components/EditBodyPiece.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/Components/EditBodyPiece.cs index 52995b73f4..be1cc9a7fe 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/Components/EditBodyPiece.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/Components/EditBodyPiece.cs @@ -10,7 +10,7 @@ using osu.Game.Rulesets.Mania.Skinning.Default; namespace osu.Game.Rulesets.Mania.Edit.Blueprints.Components { - public class EditBodyPiece : DefaultBodyPiece + public partial class EditBodyPiece : DefaultBodyPiece { [BackgroundDependencyLoader] private void load(OsuColour colours) diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/Components/EditNotePiece.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/Components/EditNotePiece.cs index 23475ef924..ef7ce9073c 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/Components/EditNotePiece.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/Components/EditNotePiece.cs @@ -10,7 +10,7 @@ using osu.Game.Rulesets.Mania.Skinning.Default; namespace osu.Game.Rulesets.Mania.Edit.Blueprints.Components { - public class EditNotePiece : CompositeDrawable + public partial class EditNotePiece : CompositeDrawable { public EditNotePiece() { diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePlacementBlueprint.cs index 7c720b30aa..21beee0769 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePlacementBlueprint.cs @@ -16,7 +16,7 @@ using osuTK.Input; namespace osu.Game.Rulesets.Mania.Edit.Blueprints { - public class HoldNotePlacementBlueprint : ManiaPlacementBlueprint + public partial class HoldNotePlacementBlueprint : ManiaPlacementBlueprint { private readonly EditBodyPiece bodyPiece; private readonly EditNotePiece headPiece; diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs index f76f170af0..8ec5213d5f 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs @@ -15,7 +15,7 @@ using osuTK; namespace osu.Game.Rulesets.Mania.Edit.Blueprints { - public class HoldNoteSelectionBlueprint : ManiaSelectionBlueprint + public partial class HoldNoteSelectionBlueprint : ManiaSelectionBlueprint { [Resolved] private OsuColour colours { get; set; } diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs index 7c7c802111..5e0512b5dc 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs @@ -15,7 +15,7 @@ using osuTK.Input; namespace osu.Game.Rulesets.Mania.Edit.Blueprints { - public abstract class ManiaPlacementBlueprint : PlacementBlueprint + public abstract partial class ManiaPlacementBlueprint : PlacementBlueprint where T : ManiaHitObject { protected new T HitObject => (T)base.HitObject; diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs index 5aa3b44f0d..cf4bca0030 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs @@ -13,7 +13,7 @@ using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Mania.Edit.Blueprints { - public abstract class ManiaSelectionBlueprint : HitObjectSelectionBlueprint + public abstract partial class ManiaSelectionBlueprint : HitObjectSelectionBlueprint where T : ManiaHitObject { [Resolved] diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/NotePlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/NotePlacementBlueprint.cs index e3cb830b80..d77abca350 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/NotePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/NotePlacementBlueprint.cs @@ -12,7 +12,7 @@ using osuTK.Input; namespace osu.Game.Rulesets.Mania.Edit.Blueprints { - public class NotePlacementBlueprint : ManiaPlacementBlueprint + public partial class NotePlacementBlueprint : ManiaPlacementBlueprint { private readonly EditNotePiece piece; diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/NoteSelectionBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/NoteSelectionBlueprint.cs index 929fdc29e0..a1392f09fa 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/NoteSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/NoteSelectionBlueprint.cs @@ -9,7 +9,7 @@ using osu.Game.Rulesets.Mania.Objects; namespace osu.Game.Rulesets.Mania.Edit.Blueprints { - public class NoteSelectionBlueprint : ManiaSelectionBlueprint + public partial class NoteSelectionBlueprint : ManiaSelectionBlueprint { public NoteSelectionBlueprint(Note note) : base(note) diff --git a/osu.Game.Rulesets.Mania/Edit/DrawableManiaEditorRuleset.cs b/osu.Game.Rulesets.Mania/Edit/DrawableManiaEditorRuleset.cs index a3a9591964..4a070e70b4 100644 --- a/osu.Game.Rulesets.Mania/Edit/DrawableManiaEditorRuleset.cs +++ b/osu.Game.Rulesets.Mania/Edit/DrawableManiaEditorRuleset.cs @@ -14,7 +14,7 @@ using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Mania.Edit { - public class DrawableManiaEditorRuleset : DrawableManiaRuleset + public partial class DrawableManiaEditorRuleset : DrawableManiaRuleset { public new IScrollingInfo ScrollingInfo => base.ScrollingInfo; diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs b/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs index b0019d8b6e..d1d5492b7a 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs @@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Mania.Edit /// /// A grid which displays coloured beat divisor lines in proximity to the selection or placement cursor. /// - public class ManiaBeatSnapGrid : Component + public partial class ManiaBeatSnapGrid : Component { private const double visible_range = 750; @@ -166,7 +166,7 @@ namespace osu.Game.Rulesets.Mania.Edit } } - private class DrawableGridLine : DrawableHitObject + private partial class DrawableGridLine : DrawableHitObject { [Resolved] private IScrollingInfo scrollingInfo { get; set; } diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaBlueprintContainer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaBlueprintContainer.cs index f438d6497c..05d8ccc73f 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaBlueprintContainer.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaBlueprintContainer.cs @@ -11,7 +11,7 @@ using osu.Game.Screens.Edit.Compose.Components; namespace osu.Game.Rulesets.Mania.Edit { - public class ManiaBlueprintContainer : ComposeBlueprintContainer + public partial class ManiaBlueprintContainer : ComposeBlueprintContainer { public ManiaBlueprintContainer(HitObjectComposer composer) : base(composer) diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaEditorPlayfield.cs b/osu.Game.Rulesets.Mania/Edit/ManiaEditorPlayfield.cs index 6683ab6bdc..0a697ca986 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaEditorPlayfield.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaEditorPlayfield.cs @@ -9,7 +9,7 @@ using System.Collections.Generic; namespace osu.Game.Rulesets.Mania.Edit { - public class ManiaEditorPlayfield : ManiaPlayfield + public partial class ManiaEditorPlayfield : ManiaPlayfield { public ManiaEditorPlayfield(List stages) : base(stages) diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs index 3585fd4e8c..5e577a2964 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs @@ -21,7 +21,7 @@ using osuTK; namespace osu.Game.Rulesets.Mania.Edit { - public class ManiaHitObjectComposer : HitObjectComposer + public partial class ManiaHitObjectComposer : HitObjectComposer { private DrawableManiaEditorRuleset drawableRuleset; private ManiaBeatSnapGrid beatSnapGrid; diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs index 7b9742a706..5e6ae9bb11 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs @@ -13,7 +13,7 @@ using osu.Game.Screens.Edit.Compose.Components; namespace osu.Game.Rulesets.Mania.Edit { - public class ManiaSelectionHandler : EditorSelectionHandler + public partial class ManiaSelectionHandler : EditorSelectionHandler { [Resolved] private HitObjectComposer composer { get; set; } diff --git a/osu.Game.Rulesets.Mania/Edit/Setup/ManiaSetupSection.cs b/osu.Game.Rulesets.Mania/Edit/Setup/ManiaSetupSection.cs index 81c41ab628..508733ad14 100644 --- a/osu.Game.Rulesets.Mania/Edit/Setup/ManiaSetupSection.cs +++ b/osu.Game.Rulesets.Mania/Edit/Setup/ManiaSetupSection.cs @@ -10,7 +10,7 @@ using osu.Game.Screens.Edit.Setup; namespace osu.Game.Rulesets.Mania.Edit.Setup { - public class ManiaSetupSection : RulesetSetupSection + public partial class ManiaSetupSection : RulesetSetupSection { private LabelledSwitchButton specialStyle; diff --git a/osu.Game.Rulesets.Mania/ManiaInputManager.cs b/osu.Game.Rulesets.Mania/ManiaInputManager.cs index e8e90d198a..9ad24d6256 100644 --- a/osu.Game.Rulesets.Mania/ManiaInputManager.cs +++ b/osu.Game.Rulesets.Mania/ManiaInputManager.cs @@ -11,7 +11,7 @@ using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Mania { [Cached] // Used for touch input, see ColumnTouchInputArea. - public class ManiaInputManager : RulesetInputManager + public partial class ManiaInputManager : RulesetInputManager { public ManiaInputManager(RulesetInfo ruleset, int variant) : base(ruleset, variant, SimultaneousBindingMode.Unique) diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index 6162184c9a..0cec0ee075 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -52,7 +52,7 @@ namespace osu.Game.Rulesets.Mania public override ScoreProcessor CreateScoreProcessor() => new ManiaScoreProcessor(); - public override HealthProcessor CreateHealthProcessor(double drainStartTime) => new ManiaHealthProcessor(drainStartTime, 0.5); + public override HealthProcessor CreateHealthProcessor(double drainStartTime) => new ManiaHealthProcessor(drainStartTime); public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new ManiaBeatmapConverter(beatmap, this); diff --git a/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs b/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs index e239068d1d..f5a5771386 100644 --- a/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs +++ b/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs @@ -6,13 +6,14 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Graphics.UserInterface; +using osu.Game.Localisation; using osu.Game.Overlays.Settings; using osu.Game.Rulesets.Mania.Configuration; using osu.Game.Rulesets.Mania.UI; namespace osu.Game.Rulesets.Mania { - public class ManiaSettingsSubsection : RulesetSettingsSubsection + public partial class ManiaSettingsSubsection : RulesetSettingsSubsection { protected override LocalisableString Header => "osu!mania"; @@ -30,26 +31,26 @@ namespace osu.Game.Rulesets.Mania { new SettingsEnumDropdown { - LabelText = "Scrolling direction", + LabelText = RulesetSettingsStrings.ScrollingDirection, Current = config.GetBindable(ManiaRulesetSetting.ScrollDirection) }, new SettingsSlider { - LabelText = "Scroll speed", + LabelText = RulesetSettingsStrings.ScrollSpeed, Current = config.GetBindable(ManiaRulesetSetting.ScrollTime), KeyboardStep = 5 }, new SettingsCheckbox { - LabelText = "Timing-based note colouring", + LabelText = RulesetSettingsStrings.TimingBasedColouring, Current = config.GetBindable(ManiaRulesetSetting.TimingBasedNoteColouring), } }; } - private class ManiaScrollSlider : OsuSliderBar + private partial class ManiaScrollSlider : OsuSliderBar { - public override LocalisableString TooltipText => $"{Current.Value}ms (speed {(int)Math.Round(DrawableManiaRuleset.MAX_TIME_RANGE / Current.Value)})"; + public override LocalisableString TooltipText => RulesetSettingsStrings.ScrollSpeedTooltip(Current.Value, (int)Math.Round(DrawableManiaRuleset.MAX_TIME_RANGE / Current.Value)); } } } diff --git a/osu.Game.Rulesets.Mania/MathUtils/LegacySortHelper.cs b/osu.Game.Rulesets.Mania/MathUtils/LegacySortHelper.cs index 1a67117c03..4d93826240 100644 --- a/osu.Game.Rulesets.Mania/MathUtils/LegacySortHelper.cs +++ b/osu.Game.Rulesets.Mania/MathUtils/LegacySortHelper.cs @@ -22,8 +22,7 @@ namespace osu.Game.Rulesets.Mania.MathUtils public static void Sort(T[] keys, IComparer comparer) { - if (keys == null) - throw new ArgumentNullException(nameof(keys)); + ArgumentNullException.ThrowIfNull(keys); if (keys.Length == 0) return; diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModFlashlight.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModFlashlight.cs index 947915cdf9..2539945c20 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModFlashlight.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModFlashlight.cs @@ -11,7 +11,7 @@ using osuTK; namespace osu.Game.Rulesets.Mania.Mods { - public class ManiaModFlashlight : ModFlashlight + public partial class ManiaModFlashlight : ModFlashlight { public override double ScoreMultiplier => 1; public override Type[] IncompatibleMods => new[] { typeof(ModHidden) }; @@ -29,7 +29,7 @@ namespace osu.Game.Rulesets.Mania.Mods protected override Flashlight CreateFlashlight() => new ManiaFlashlight(this); - private class ManiaFlashlight : Flashlight + private partial class ManiaFlashlight : Flashlight { private readonly LayoutValue flashlightProperties = new LayoutValue(Invalidation.DrawSize); diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs index a607ed572d..8381b8b24b 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs @@ -11,7 +11,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables /// Visualises a . Although this derives DrawableManiaHitObject, /// this does not handle input/sound like a normal hit object. /// - public class DrawableBarLine : DrawableManiaHitObject + public partial class DrawableBarLine : DrawableManiaHitObject { public DrawableBarLine(BarLine barLine) : base(barLine) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 86d4ad0a36..759d2346e8 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables /// /// Visualises a hit object. /// - public class DrawableHoldNote : DrawableManiaHitObject, IKeyBindingHandler + public partial class DrawableHoldNote : DrawableManiaHitObject, IKeyBindingHandler { public override bool DisplayResult => false; diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteHead.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteHead.cs index ac646ea427..1aa6ee2507 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteHead.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteHead.cs @@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables /// /// The head of a . /// - public class DrawableHoldNoteHead : DrawableNote + public partial class DrawableHoldNoteHead : DrawableNote { protected override ManiaSkinComponents Component => ManiaSkinComponents.HoldNoteHead; diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTail.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTail.cs index 3084f71be2..bf477277c6 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTail.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTail.cs @@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables /// /// The tail of a . /// - public class DrawableHoldNoteTail : DrawableNote + public partial class DrawableHoldNoteTail : DrawableNote { /// /// Lenience of release hit windows. This is to make cases where the hold note release diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs index daec5ddbe7..ce6a83f79f 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables /// /// Visualises a hit object. /// - public class DrawableHoldNoteTick : DrawableManiaHitObject + public partial class DrawableHoldNoteTick : DrawableManiaHitObject { /// /// References the time at which the user started holding the hold note. diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs index 51f8ab1cf8..8498fd36de 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs @@ -14,7 +14,7 @@ using osu.Game.Rulesets.Mania.UI; namespace osu.Game.Rulesets.Mania.Objects.Drawables { - public abstract class DrawableManiaHitObject : DrawableHitObject + public abstract partial class DrawableManiaHitObject : DrawableHitObject { /// /// The which causes this to be hit. @@ -90,7 +90,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables public virtual void MissForcefully() => ApplyResult(r => r.Type = r.Judgement.MinResult); } - public abstract class DrawableManiaHitObject : DrawableManiaHitObject + public abstract partial class DrawableManiaHitObject : DrawableManiaHitObject where TObject : ManiaHitObject { public new TObject HitObject => (TObject)base.HitObject; diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index cf3149b065..0819e8401c 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables /// /// Visualises a hit object. /// - public class DrawableNote : DrawableManiaHitObject, IKeyBindingHandler + public partial class DrawableNote : DrawableManiaHitObject, IKeyBindingHandler { [Resolved] private OsuColour colours { get; set; } diff --git a/osu.Game.Rulesets.Mania/Scoring/ManiaHealthProcessor.cs b/osu.Game.Rulesets.Mania/Scoring/ManiaHealthProcessor.cs index 3f0491e53f..16f7af0d0a 100644 --- a/osu.Game.Rulesets.Mania/Scoring/ManiaHealthProcessor.cs +++ b/osu.Game.Rulesets.Mania/Scoring/ManiaHealthProcessor.cs @@ -8,11 +8,11 @@ using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Mania.Scoring { - public class ManiaHealthProcessor : DrainingHealthProcessor + public partial class ManiaHealthProcessor : DrainingHealthProcessor { /// - public ManiaHealthProcessor(double drainStartTime, double drainLenience = 0) - : base(drainStartTime, drainLenience) + public ManiaHealthProcessor(double drainStartTime) + : base(drainStartTime, 1.0) { } diff --git a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs index dbf3d02955..f724972a29 100644 --- a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs +++ b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs @@ -7,7 +7,7 @@ using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Mania.Scoring { - internal class ManiaScoreProcessor : ScoreProcessor + internal partial class ManiaScoreProcessor : ScoreProcessor { public ManiaScoreProcessor() : base(new ManiaRuleset()) diff --git a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonColumnBackground.cs b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonColumnBackground.cs index 598a765d3c..52e6079877 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonColumnBackground.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonColumnBackground.cs @@ -16,7 +16,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Mania.Skinning.Argon { - public class ArgonColumnBackground : CompositeDrawable, IKeyBindingHandler + public partial class ArgonColumnBackground : CompositeDrawable, IKeyBindingHandler { private readonly IBindable direction = new Bindable(); diff --git a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHitExplosion.cs b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHitExplosion.cs index af179d5580..e32de6f3f3 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHitExplosion.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHitExplosion.cs @@ -15,7 +15,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Mania.Skinning.Argon { - public class ArgonHitExplosion : CompositeDrawable, IHitExplosion + public partial class ArgonHitExplosion : CompositeDrawable, IHitExplosion { public override bool RemoveWhenNotAlive => true; diff --git a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHitTarget.cs b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHitTarget.cs index 9e449623d5..4ffb4a435b 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHitTarget.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHitTarget.cs @@ -11,7 +11,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Mania.Skinning.Argon { - public class ArgonHitTarget : CompositeDrawable + public partial class ArgonHitTarget : CompositeDrawable { private readonly IBindable direction = new Bindable(); diff --git a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldBodyPiece.cs b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldBodyPiece.cs index 757190c4ae..1f52f5f15f 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldBodyPiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldBodyPiece.cs @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon /// /// Represents length-wise portion of a hold note. /// - public class ArgonHoldBodyPiece : CompositeDrawable, IHoldNoteBody + public partial class ArgonHoldBodyPiece : CompositeDrawable, IHoldNoteBody { protected readonly Bindable AccentColour = new Bindable(); protected readonly IBindable IsHitting = new Bindable(); diff --git a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldNoteTailPiece.cs b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldNoteTailPiece.cs index 00cd37b6cf..a2166a6708 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldNoteTailPiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldNoteTailPiece.cs @@ -14,7 +14,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Mania.Skinning.Argon { - internal class ArgonHoldNoteTailPiece : CompositeDrawable + internal partial class ArgonHoldNoteTailPiece : CompositeDrawable { private readonly IBindable direction = new Bindable(); private readonly IBindable accentColour = new Bindable(); diff --git a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonJudgementPiece.cs b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonJudgementPiece.cs index e7dfec256d..4ce3c50f7c 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonJudgementPiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonJudgementPiece.cs @@ -3,7 +3,6 @@ using System; using osu.Framework.Allocation; -using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -18,20 +17,18 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Mania.Skinning.Argon { - public class ArgonJudgementPiece : CompositeDrawable, IAnimatableJudgement + public partial class ArgonJudgementPiece : JudgementPiece, IAnimatableJudgement { - protected readonly HitResult Result; - - protected SpriteText JudgementText { get; private set; } = null!; - private RingExplosion? ringExplosion; [Resolved] private OsuColour colours { get; set; } = null!; public ArgonJudgementPiece(HitResult result) + : base(result) { - Result = result; + AutoSizeAxes = Axes.Both; + Origin = Anchor.Centre; Y = 160; } @@ -39,22 +36,6 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon [BackgroundDependencyLoader] private void load() { - AutoSizeAxes = Axes.Both; - - InternalChildren = new Drawable[] - { - JudgementText = new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Text = Result.GetDescription().ToUpperInvariant(), - Colour = colours.ForHitResult(Result), - Blending = BlendingParameters.Additive, - Spacing = new Vector2(10, 0), - Font = OsuFont.Default.With(size: 28, weight: FontWeight.Regular), - }, - }; - if (Result.IsHit()) { AddInternal(ringExplosion = new RingExplosion(Result) @@ -64,6 +45,16 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon } } + protected override SpriteText CreateJudgementText() => + new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Blending = BlendingParameters.Additive, + Spacing = new Vector2(10, 0), + Font = OsuFont.Default.With(size: 28, weight: FontWeight.Regular), + }; + /// /// Plays the default animation for this judgement piece. /// @@ -100,7 +91,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon public Drawable? GetAboveHitObjectsProxiedContent() => null; - private class RingExplosion : CompositeDrawable + private partial class RingExplosion : CompositeDrawable { private readonly float travel = 52; @@ -169,7 +160,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon this.FadeOutFromOne(1000, Easing.OutQuint); } - public class RingPiece : CircularContainer + public partial class RingPiece : CircularContainer { public RingPiece(float thickness = 9) { diff --git a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonKeyArea.cs b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonKeyArea.cs index 7670c9bdf2..95e24f8811 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonKeyArea.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonKeyArea.cs @@ -19,7 +19,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Mania.Skinning.Argon { - public class ArgonKeyArea : CompositeDrawable, IKeyBindingHandler + public partial class ArgonKeyArea : CompositeDrawable, IKeyBindingHandler { private readonly IBindable direction = new Bindable(); diff --git a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonNotePiece.cs b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonNotePiece.cs index 454a6b012b..25b1965c18 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonNotePiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonNotePiece.cs @@ -16,7 +16,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Mania.Skinning.Argon { - internal class ArgonNotePiece : CompositeDrawable + internal partial class ArgonNotePiece : CompositeDrawable { public const float NOTE_HEIGHT = 42; diff --git a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonStageBackground.cs b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonStageBackground.cs index 1881695b14..ec99177f98 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonStageBackground.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonStageBackground.cs @@ -6,7 +6,7 @@ using osu.Framework.Graphics.Containers; namespace osu.Game.Rulesets.Mania.Skinning.Argon { - public class ArgonStageBackground : CompositeDrawable + public partial class ArgonStageBackground : CompositeDrawable { public ArgonStageBackground() { diff --git a/osu.Game.Rulesets.Mania/Skinning/Argon/ManiaArgonSkinTransformer.cs b/osu.Game.Rulesets.Mania/Skinning/Argon/ManiaArgonSkinTransformer.cs index eb7f63fbe2..057b7eb0d9 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Argon/ManiaArgonSkinTransformer.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Argon/ManiaArgonSkinTransformer.cs @@ -27,6 +27,10 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon switch (lookup) { case GameplaySkinComponentLookup resultComponent: + // This should eventually be moved to a skin setting, when supported. + if (Skin is ArgonProSkin && resultComponent.Component >= HitResult.Great) + return Drawable.Empty(); + return new ArgonJudgementPiece(resultComponent.Component); case ManiaSkinComponentLookup maniaComponent: diff --git a/osu.Game.Rulesets.Mania/Skinning/Default/DefaultBodyPiece.cs b/osu.Game.Rulesets.Mania/Skinning/Default/DefaultBodyPiece.cs index f0e214b190..9f5ee0846f 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Default/DefaultBodyPiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Default/DefaultBodyPiece.cs @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Default /// /// Represents length-wise portion of a hold note. /// - public class DefaultBodyPiece : CompositeDrawable, IHoldNoteBody + public partial class DefaultBodyPiece : CompositeDrawable, IHoldNoteBody { protected readonly Bindable AccentColour = new Bindable(); protected readonly IBindable IsHitting = new Bindable(); @@ -64,7 +64,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Default private void onAccentChanged(ValueChangedEvent accent) => Background.Colour = accent.NewValue.Opacity(0.7f); - private class ForegroundPiece : CompositeDrawable + private partial class ForegroundPiece : CompositeDrawable { public readonly Bindable AccentColour = new Bindable(); public readonly IBindable IsHitting = new Bindable(); diff --git a/osu.Game.Rulesets.Mania/Skinning/Default/DefaultNotePiece.cs b/osu.Game.Rulesets.Mania/Skinning/Default/DefaultNotePiece.cs index 569740deee..e789335584 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Default/DefaultNotePiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Default/DefaultNotePiece.cs @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Default /// /// Represents the static hit markers of notes. /// - internal class DefaultNotePiece : CompositeDrawable + internal partial class DefaultNotePiece : CompositeDrawable { public const float NOTE_HEIGHT = 12; diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/HitTargetInsetContainer.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/HitTargetInsetContainer.cs index 3c89e2c04a..608cde7272 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/HitTargetInsetContainer.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/HitTargetInsetContainer.cs @@ -11,7 +11,7 @@ using osu.Game.Skinning; namespace osu.Game.Rulesets.Mania.Skinning.Legacy { - public class HitTargetInsetContainer : Container + public partial class HitTargetInsetContainer : Container { private readonly IBindable direction = new Bindable(); diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyBodyPiece.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyBodyPiece.cs index 52bca2aaa0..c928ebb3e0 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyBodyPiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyBodyPiece.cs @@ -16,7 +16,7 @@ using osuTK; namespace osu.Game.Rulesets.Mania.Skinning.Legacy { - public class LegacyBodyPiece : LegacyManiaColumnElement + public partial class LegacyBodyPiece : LegacyManiaColumnElement { private DrawableHoldNote holdNote = null!; diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyColumnBackground.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyColumnBackground.cs index 0ed96cf6f1..ab996519a7 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyColumnBackground.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyColumnBackground.cs @@ -15,7 +15,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Mania.Skinning.Legacy { - public class LegacyColumnBackground : LegacyManiaColumnElement, IKeyBindingHandler + public partial class LegacyColumnBackground : LegacyManiaColumnElement, IKeyBindingHandler { private readonly IBindable direction = new Bindable(); diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHitExplosion.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHitExplosion.cs index 6b0e1e5d8a..6c56db613c 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHitExplosion.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHitExplosion.cs @@ -15,7 +15,7 @@ using osuTK; namespace osu.Game.Rulesets.Mania.Skinning.Legacy { - public class LegacyHitExplosion : LegacyManiaColumnElement, IHitExplosion + public partial class LegacyHitExplosion : LegacyManiaColumnElement, IHitExplosion { public const double FADE_IN_DURATION = 80; diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHitTarget.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHitTarget.cs index ed78cb6086..3a08a9d818 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHitTarget.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHitTarget.cs @@ -14,7 +14,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Mania.Skinning.Legacy { - public class LegacyHitTarget : CompositeDrawable + public partial class LegacyHitTarget : CompositeDrawable { private readonly IBindable direction = new Bindable(); diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHoldNoteHeadPiece.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHoldNoteHeadPiece.cs index c3ed0111be..19c3d8e7f8 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHoldNoteHeadPiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHoldNoteHeadPiece.cs @@ -6,7 +6,7 @@ using osu.Game.Skinning; namespace osu.Game.Rulesets.Mania.Skinning.Legacy { - public class LegacyHoldNoteHeadPiece : LegacyNotePiece + public partial class LegacyHoldNoteHeadPiece : LegacyNotePiece { protected override Drawable? GetAnimation(ISkinSource skin) { diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHoldNoteTailPiece.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHoldNoteTailPiece.cs index 13edc6e495..387c5b393a 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHoldNoteTailPiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHoldNoteTailPiece.cs @@ -8,7 +8,7 @@ using osu.Game.Skinning; namespace osu.Game.Rulesets.Mania.Skinning.Legacy { - public class LegacyHoldNoteTailPiece : LegacyNotePiece + public partial class LegacyHoldNoteTailPiece : LegacyNotePiece { protected override void OnDirectionChanged(ValueChangedEvent direction) { diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyKeyArea.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyKeyArea.cs index e7dca3d946..48b92a8486 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyKeyArea.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyKeyArea.cs @@ -15,7 +15,7 @@ using osuTK; namespace osu.Game.Rulesets.Mania.Skinning.Legacy { - public class LegacyKeyArea : LegacyManiaColumnElement, IKeyBindingHandler + public partial class LegacyKeyArea : LegacyManiaColumnElement, IKeyBindingHandler { private readonly IBindable direction = new Bindable(); diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyManiaColumnElement.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyManiaColumnElement.cs index 4ffef18781..7e3fb0438c 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyManiaColumnElement.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyManiaColumnElement.cs @@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy /// /// A which is placed somewhere within a . /// - public class LegacyManiaColumnElement : CompositeDrawable + public partial class LegacyManiaColumnElement : CompositeDrawable { [Resolved] protected Column Column { get; private set; } = null!; diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyManiaJudgementPiece.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyManiaJudgementPiece.cs index 670a0aad6e..d21a8cd140 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyManiaJudgementPiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyManiaJudgementPiece.cs @@ -13,7 +13,7 @@ using osu.Game.Skinning; namespace osu.Game.Rulesets.Mania.Skinning.Legacy { - public class LegacyManiaJudgementPiece : CompositeDrawable, IAnimatableJudgement + public partial class LegacyManiaJudgementPiece : CompositeDrawable, IAnimatableJudgement { private readonly HitResult result; private readonly Drawable animation; diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyNotePiece.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyNotePiece.cs index 8c5a594b3b..4291ec3c13 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyNotePiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyNotePiece.cs @@ -14,7 +14,7 @@ using osuTK; namespace osu.Game.Rulesets.Mania.Skinning.Legacy { - public class LegacyNotePiece : LegacyManiaColumnElement + public partial class LegacyNotePiece : LegacyManiaColumnElement { private readonly IBindable direction = new Bindable(); diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyStageBackground.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyStageBackground.cs index d039551cd7..758c8dd347 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyStageBackground.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyStageBackground.cs @@ -16,7 +16,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Mania.Skinning.Legacy { - public class LegacyStageBackground : CompositeDrawable + public partial class LegacyStageBackground : CompositeDrawable { private Drawable leftSprite; private Drawable rightSprite; @@ -77,7 +77,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy rightSprite.Scale = new Vector2(1, DrawHeight / rightSprite.Height); } - private class ColumnBackground : CompositeDrawable + private partial class ColumnBackground : CompositeDrawable { private readonly int columnIndex; private readonly bool isLastColumn; diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyStageForeground.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyStageForeground.cs index 8e72e970ab..1a47fe5076 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyStageForeground.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyStageForeground.cs @@ -11,7 +11,7 @@ using osuTK; namespace osu.Game.Rulesets.Mania.Skinning.Legacy { - public class LegacyStageForeground : CompositeDrawable + public partial class LegacyStageForeground : CompositeDrawable { private readonly IBindable direction = new Bindable(); diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index de7424773b..6ca830a82f 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -26,7 +26,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Mania.UI { [Cached] - public class Column : ScrollingPlayfield, IKeyBindingHandler + public partial class Column : ScrollingPlayfield, IKeyBindingHandler { public const float COLUMN_WIDTH = 80; public const float SPECIAL_COLUMN_WIDTH = 70; @@ -134,6 +134,9 @@ namespace osu.Game.Rulesets.Mania.UI protected override void Dispose(bool isDisposing) { + // must happen before children are disposed in base call to prevent illegal accesses to the hit explosion pool. + NewResult -= OnNewResult; + base.Dispose(isDisposing); if (skin != null) @@ -185,7 +188,7 @@ namespace osu.Game.Rulesets.Mania.UI // This probably shouldn't exist as is, but the columns in the stage are separated by a 1px border => DrawRectangle.Inflate(new Vector2(Stage.COLUMN_SPACING / 2, 0)).Contains(ToLocalSpace(screenSpacePos)); - public class ColumnTouchInputArea : Drawable + public partial class ColumnTouchInputArea : Drawable { private readonly Column column; @@ -206,18 +209,6 @@ namespace osu.Game.Rulesets.Mania.UI keyBindingContainer = maniaInputManager?.KeyBindingContainer; } - protected override bool OnMouseDown(MouseDownEvent e) - { - keyBindingContainer?.TriggerPressed(column.Action.Value); - return base.OnMouseDown(e); - } - - protected override void OnMouseUp(MouseUpEvent e) - { - keyBindingContainer?.TriggerReleased(column.Action.Value); - base.OnMouseUp(e); - } - protected override bool OnTouchDown(TouchDownEvent e) { keyBindingContainer?.TriggerPressed(column.Action.Value); diff --git a/osu.Game.Rulesets.Mania/UI/ColumnFlow.cs b/osu.Game.Rulesets.Mania/UI/ColumnFlow.cs index 9b3f6d7033..0bc0bf4caf 100644 --- a/osu.Game.Rulesets.Mania/UI/ColumnFlow.cs +++ b/osu.Game.Rulesets.Mania/UI/ColumnFlow.cs @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Mania.UI /// Content can be added to individual columns via . /// /// The type of content in each column. - public class ColumnFlow : CompositeDrawable + public partial class ColumnFlow : CompositeDrawable where TContent : Drawable { /// diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs index e5a9ca1e85..c93be91a84 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs @@ -11,7 +11,7 @@ using osu.Game.Skinning; namespace osu.Game.Rulesets.Mania.UI.Components { - public class ColumnHitObjectArea : HitObjectArea + public partial class ColumnHitObjectArea : HitObjectArea { public readonly Container Explosions; diff --git a/osu.Game.Rulesets.Mania/UI/Components/DefaultColumnBackground.cs b/osu.Game.Rulesets.Mania/UI/Components/DefaultColumnBackground.cs index 3680e7ea0a..fe34712c68 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/DefaultColumnBackground.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/DefaultColumnBackground.cs @@ -17,7 +17,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Mania.UI.Components { - public class DefaultColumnBackground : CompositeDrawable, IKeyBindingHandler + public partial class DefaultColumnBackground : CompositeDrawable, IKeyBindingHandler { private readonly IBindable direction = new Bindable(); diff --git a/osu.Game.Rulesets.Mania/UI/Components/DefaultHitTarget.cs b/osu.Game.Rulesets.Mania/UI/Components/DefaultHitTarget.cs index 97aa897782..bfc5fbc8f7 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/DefaultHitTarget.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/DefaultHitTarget.cs @@ -16,7 +16,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Mania.UI.Components { - public class DefaultHitTarget : CompositeDrawable + public partial class DefaultHitTarget : CompositeDrawable { private const float hit_target_bar_height = 2; diff --git a/osu.Game.Rulesets.Mania/UI/Components/DefaultKeyArea.cs b/osu.Game.Rulesets.Mania/UI/Components/DefaultKeyArea.cs index 600c9feb73..77ab9f60c1 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/DefaultKeyArea.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/DefaultKeyArea.cs @@ -19,7 +19,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Mania.UI.Components { - public class DefaultKeyArea : CompositeDrawable, IKeyBindingHandler + public partial class DefaultKeyArea : CompositeDrawable, IKeyBindingHandler { private const float key_icon_size = 10; private const float key_icon_corner_radius = 3; diff --git a/osu.Game.Rulesets.Mania/UI/Components/DefaultStageBackground.cs b/osu.Game.Rulesets.Mania/UI/Components/DefaultStageBackground.cs index 20d80580bf..ef34fc04ee 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/DefaultStageBackground.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/DefaultStageBackground.cs @@ -11,7 +11,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Mania.UI.Components { - public class DefaultStageBackground : CompositeDrawable + public partial class DefaultStageBackground : CompositeDrawable { public DefaultStageBackground() { diff --git a/osu.Game.Rulesets.Mania/UI/Components/HitObjectArea.cs b/osu.Game.Rulesets.Mania/UI/Components/HitObjectArea.cs index 7f4b8eacde..41b2dba173 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/HitObjectArea.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/HitObjectArea.cs @@ -14,7 +14,7 @@ using osu.Game.Skinning; namespace osu.Game.Rulesets.Mania.UI.Components { - public class HitObjectArea : SkinReloadableDrawable + public partial class HitObjectArea : SkinReloadableDrawable { protected readonly IBindable Direction = new Bindable(); public readonly HitObjectContainer HitObjectContainer; diff --git a/osu.Game.Rulesets.Mania/UI/DefaultHitExplosion.cs b/osu.Game.Rulesets.Mania/UI/DefaultHitExplosion.cs index 59716ee3e2..e0663e9878 100644 --- a/osu.Game.Rulesets.Mania/UI/DefaultHitExplosion.cs +++ b/osu.Game.Rulesets.Mania/UI/DefaultHitExplosion.cs @@ -19,7 +19,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Mania.UI { - public class DefaultHitExplosion : CompositeDrawable, IHitExplosion + public partial class DefaultHitExplosion : CompositeDrawable, IHitExplosion { private const float default_large_faint_size = 0.8f; diff --git a/osu.Game.Rulesets.Mania/UI/DrawableManiaJudgement.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaJudgement.cs index 923fc6863c..896dfb2b23 100644 --- a/osu.Game.Rulesets.Mania/UI/DrawableManiaJudgement.cs +++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaJudgement.cs @@ -10,7 +10,7 @@ using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Mania.UI { - public class DrawableManiaJudgement : DrawableJudgement + public partial class DrawableManiaJudgement : DrawableJudgement { public DrawableManiaJudgement(JudgementResult result, DrawableHitObject judgedObject) : base(result, judgedObject) @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Mania.UI protected override Drawable CreateDefaultJudgement(HitResult result) => new DefaultManiaJudgementPiece(result); - private class DefaultManiaJudgementPiece : DefaultJudgementPiece + private partial class DefaultManiaJudgementPiece : DefaultJudgementPiece { public DefaultManiaJudgementPiece(HitResult result) : base(result) diff --git a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs index ea3b438ec8..af8758fb5e 100644 --- a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs @@ -30,7 +30,7 @@ using osu.Game.Scoring; namespace osu.Game.Rulesets.Mania.UI { - public class DrawableManiaRuleset : DrawableScrollingRuleset + public partial class DrawableManiaRuleset : DrawableScrollingRuleset { /// /// The minimum time range. This occurs at a of 40. diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 99b36bd366..e3ebadc836 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -19,7 +19,7 @@ using osuTK; namespace osu.Game.Rulesets.Mania.UI { [Cached] - public class ManiaPlayfield : ScrollingPlayfield + public partial class ManiaPlayfield : ScrollingPlayfield { public IReadOnlyList Stages => stages; @@ -29,8 +29,7 @@ namespace osu.Game.Rulesets.Mania.UI public ManiaPlayfield(List stageDefinitions) { - if (stageDefinitions == null) - throw new ArgumentNullException(nameof(stageDefinitions)); + ArgumentNullException.ThrowIfNull(stageDefinitions); if (stageDefinitions.Count <= 0) throw new ArgumentException("Can't have zero or fewer stages."); diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfieldAdjustmentContainer.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfieldAdjustmentContainer.cs index 8020fcb3cc..d4621ab8f3 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfieldAdjustmentContainer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfieldAdjustmentContainer.cs @@ -8,7 +8,7 @@ using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Mania.UI { - public class ManiaPlayfieldAdjustmentContainer : PlayfieldAdjustmentContainer + public partial class ManiaPlayfieldAdjustmentContainer : PlayfieldAdjustmentContainer { public ManiaPlayfieldAdjustmentContainer() { diff --git a/osu.Game.Rulesets.Mania/UI/ManiaReplayRecorder.cs b/osu.Game.Rulesets.Mania/UI/ManiaReplayRecorder.cs index 87d6c25ac2..56ac38a737 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaReplayRecorder.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaReplayRecorder.cs @@ -12,7 +12,7 @@ using osuTK; namespace osu.Game.Rulesets.Mania.UI { - public class ManiaReplayRecorder : ReplayRecorder + public partial class ManiaReplayRecorder : ReplayRecorder { public ManiaReplayRecorder(Score score) : base(score) diff --git a/osu.Game.Rulesets.Mania/UI/ManiaScrollingDirection.cs b/osu.Game.Rulesets.Mania/UI/ManiaScrollingDirection.cs index 44fe4b1b30..4a8843c999 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaScrollingDirection.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaScrollingDirection.cs @@ -1,15 +1,18 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - +using osu.Framework.Localisation; +using osu.Game.Localisation; using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Mania.UI { public enum ManiaScrollingDirection { + [LocalisableDescription(typeof(RulesetSettingsStrings), nameof(RulesetSettingsStrings.ScrollingDirectionUp))] Up = ScrollingDirection.Up, + + [LocalisableDescription(typeof(RulesetSettingsStrings), nameof(RulesetSettingsStrings.ScrollingDirectionDown))] Down = ScrollingDirection.Down } } diff --git a/osu.Game.Rulesets.Mania/UI/PlayfieldCoveringWrapper.cs b/osu.Game.Rulesets.Mania/UI/PlayfieldCoveringWrapper.cs index d397e7cc18..46cba01771 100644 --- a/osu.Game.Rulesets.Mania/UI/PlayfieldCoveringWrapper.cs +++ b/osu.Game.Rulesets.Mania/UI/PlayfieldCoveringWrapper.cs @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Mania.UI /// /// A that has its contents partially hidden by an adjustable "cover". This is intended to be used in a playfield. /// - public class PlayfieldCoveringWrapper : CompositeDrawable + public partial class PlayfieldCoveringWrapper : CompositeDrawable { /// /// The complete cover, including gradient and fill. diff --git a/osu.Game.Rulesets.Mania/UI/PoolableHitExplosion.cs b/osu.Game.Rulesets.Mania/UI/PoolableHitExplosion.cs index 8e5c8f9b75..4f6a84c60b 100644 --- a/osu.Game.Rulesets.Mania/UI/PoolableHitExplosion.cs +++ b/osu.Game.Rulesets.Mania/UI/PoolableHitExplosion.cs @@ -11,7 +11,7 @@ using osu.Game.Skinning; namespace osu.Game.Rulesets.Mania.UI { - public class PoolableHitExplosion : PoolableDrawable + public partial class PoolableHitExplosion : PoolableDrawable { public const double DURATION = 200; diff --git a/osu.Game.Rulesets.Mania/UI/Stage.cs b/osu.Game.Rulesets.Mania/UI/Stage.cs index 8aeaa9cf35..c1d3e85bf1 100644 --- a/osu.Game.Rulesets.Mania/UI/Stage.cs +++ b/osu.Game.Rulesets.Mania/UI/Stage.cs @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Mania.UI /// /// A collection of s. /// - public class Stage : ScrollingPlayfield + public partial class Stage : ScrollingPlayfield { [Cached] public readonly StageDefinition Definition; @@ -156,6 +156,9 @@ namespace osu.Game.Rulesets.Mania.UI protected override void Dispose(bool isDisposing) { + // must happen before children are disposed in base call to prevent illegal accesses to the judgement pool. + NewResult -= OnNewResult; + base.Dispose(isDisposing); if (currentSkin != null) diff --git a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj index 4f6840f9ca..72f172188e 100644 --- a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj +++ b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj @@ -1,6 +1,6 @@  - netstandard2.1 + net6.0 Library true smash the keys. to the beat. @@ -15,4 +15,4 @@ - \ No newline at end of file + diff --git a/osu.Game.Rulesets.Osu.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Rulesets.Osu.Tests.Android/AndroidManifest.xml similarity index 95% rename from osu.Game.Rulesets.Osu.Tests.Android/Properties/AndroidManifest.xml rename to osu.Game.Rulesets.Osu.Tests.Android/AndroidManifest.xml index 3ce17ccc27..45d27dda70 100644 --- a/osu.Game.Rulesets.Osu.Tests.Android/Properties/AndroidManifest.xml +++ b/osu.Game.Rulesets.Osu.Tests.Android/AndroidManifest.xml @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/osu.Game.Rulesets.Osu.Tests.Android/osu.Game.Rulesets.Osu.Tests.Android.csproj b/osu.Game.Rulesets.Osu.Tests.Android/osu.Game.Rulesets.Osu.Tests.Android.csproj index f4b673f10b..e8a46a9828 100644 --- a/osu.Game.Rulesets.Osu.Tests.Android/osu.Game.Rulesets.Osu.Tests.Android.csproj +++ b/osu.Game.Rulesets.Osu.Tests.Android/osu.Game.Rulesets.Osu.Tests.Android.csproj @@ -1,49 +1,27 @@ - - + - Debug - AnyCPU - 8.0.30703 - 2.0 - {90CAB706-39CB-4B93-9629-3218A6FF8E9B} - {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - {122416d6-6b49-4ee2-a1e8-b825f31c79fe} + net6.0-android + Exe osu.Game.Rulesets.Osu.Tests osu.Game.Rulesets.Osu.Tests.Android - Properties\AndroidManifest.xml - armeabi-v7a;x86;arm64-v8a - - - None - cjk;mideast;other;rare;west - true - - - - - - - + %(RecursiveDir)%(Filename)%(Extension) + + + %(RecursiveDir)%(Filename)%(Extension) + Android\%(RecursiveDir)%(Filename)%(Extension) + - - {c92a607b-1fdd-4954-9f92-03ff547d9080} - osu.Game.Rulesets.Osu - - - {2a66dd92-adb1-4994-89e2-c94e04acda0d} - osu.Game - + + - - 5.0.0 - + - \ No newline at end of file diff --git a/osu.Game.Rulesets.Osu.Tests.iOS/Application.cs b/osu.Game.Rulesets.Osu.Tests.iOS/Application.cs index ad23f3ee33..6ef29fa68e 100644 --- a/osu.Game.Rulesets.Osu.Tests.iOS/Application.cs +++ b/osu.Game.Rulesets.Osu.Tests.iOS/Application.cs @@ -3,7 +3,6 @@ #nullable disable -using osu.Framework.iOS; using UIKit; namespace osu.Game.Rulesets.Osu.Tests.iOS @@ -12,7 +11,7 @@ namespace osu.Game.Rulesets.Osu.Tests.iOS { public static void Main(string[] args) { - UIApplication.Main(args, typeof(GameUIApplication), typeof(AppDelegate)); + UIApplication.Main(args, null, typeof(AppDelegate)); } } } diff --git a/osu.Game.Rulesets.Osu.Tests.iOS/Info.plist b/osu.Game.Rulesets.Osu.Tests.iOS/Info.plist index a88b74695c..1e33f2ff16 100644 --- a/osu.Game.Rulesets.Osu.Tests.iOS/Info.plist +++ b/osu.Game.Rulesets.Osu.Tests.iOS/Info.plist @@ -13,7 +13,7 @@ LSRequiresIPhoneOS MinimumOSVersion - 10.0 + 13.4 UIDeviceFamily 1 diff --git a/osu.Game.Rulesets.Osu.Tests.iOS/osu.Game.Rulesets.Osu.Tests.iOS.csproj b/osu.Game.Rulesets.Osu.Tests.iOS/osu.Game.Rulesets.Osu.Tests.iOS.csproj index 545abcec6c..7d50deb8ba 100644 --- a/osu.Game.Rulesets.Osu.Tests.iOS/osu.Game.Rulesets.Osu.Tests.iOS.csproj +++ b/osu.Game.Rulesets.Osu.Tests.iOS/osu.Game.Rulesets.Osu.Tests.iOS.csproj @@ -1,35 +1,20 @@ - - + - Debug - iPhoneSimulator - {6653CA6F-DB06-4604-A3FD-762E25C2AF96} + Exe + net6.0-ios + 13.4 Exe osu.Game.Rulesets.Osu.Tests osu.Game.Rulesets.Osu.Tests.iOS - - - - Linker.xml - - - %(RecursiveDir)%(Filename)%(Extension) - - {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D} - osu.Game - - - {C92A607B-1FDD-4954-9F92-03FF547D9080} - osu.Game.Rulesets.Osu - + + - - \ No newline at end of file + diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneHitCirclePlacementBlueprint.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneHitCirclePlacementBlueprint.cs index 4d84d3e79f..587bd2de44 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneHitCirclePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneHitCirclePlacementBlueprint.cs @@ -13,7 +13,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Osu.Tests.Editor { - public class TestSceneHitCirclePlacementBlueprint : PlacementBlueprintTestScene + public partial class TestSceneHitCirclePlacementBlueprint : PlacementBlueprintTestScene { protected override DrawableHitObject CreateHitObject(HitObject hitObject) => new DrawableHitCircle((HitCircle)hitObject); protected override PlacementBlueprint CreateBlueprint() => new HitCirclePlacementBlueprint(); diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneHitCircleSelectionBlueprint.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneHitCircleSelectionBlueprint.cs index fde62c7a53..9ffbd25a40 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneHitCircleSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneHitCircleSelectionBlueprint.cs @@ -15,7 +15,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Tests.Editor { - public class TestSceneHitCircleSelectionBlueprint : SelectionBlueprintTestScene + public partial class TestSceneHitCircleSelectionBlueprint : SelectionBlueprintTestScene { private HitCircle hitCircle; private DrawableHitCircle drawableObject; @@ -61,7 +61,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor AddAssert("blueprint positioned over hitobject", () => blueprint.CirclePiece.Position == hitCircle.StackedPosition); } - private class TestBlueprint : HitCircleSelectionBlueprint + private partial class TestBlueprint : HitCircleSelectionBlueprint { public new HitCirclePiece CirclePiece => base.CirclePiece; diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneObjectBeatSnap.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneObjectBeatSnap.cs index a8829ef88c..56894242c8 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneObjectBeatSnap.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneObjectBeatSnap.cs @@ -14,7 +14,7 @@ using osuTK.Input; namespace osu.Game.Rulesets.Osu.Tests.Editor { [TestFixture] - public class TestSceneObjectBeatSnap : TestSceneOsuEditor + public partial class TestSceneObjectBeatSnap : TestSceneOsuEditor { private OsuPlayfield playfield; diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneObjectMerging.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneObjectMerging.cs index 5c5384e0b7..e7ac38c20e 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneObjectMerging.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneObjectMerging.cs @@ -14,7 +14,7 @@ using osuTK.Input; namespace osu.Game.Rulesets.Osu.Tests.Editor { - public class TestSceneObjectMerging : TestSceneOsuEditor + public partial class TestSceneObjectMerging : TestSceneOsuEditor { private OsuSelectionHandler selectionHandler => Editor.ChildrenOfType().First(); diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneObjectObjectSnap.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneObjectObjectSnap.cs index 6e8c7ff2bd..3b8a5a90a5 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneObjectObjectSnap.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneObjectObjectSnap.cs @@ -17,7 +17,7 @@ using osuTK.Input; namespace osu.Game.Rulesets.Osu.Tests.Editor { [TestFixture] - public class TestSceneObjectObjectSnap : TestSceneOsuEditor + public partial class TestSceneObjectObjectSnap : TestSceneOsuEditor { private OsuPlayfield playfield; diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuComposerSelection.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuComposerSelection.cs index 800e6c0711..8641663ce8 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuComposerSelection.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuComposerSelection.cs @@ -21,7 +21,7 @@ using osuTK.Input; namespace osu.Game.Rulesets.Osu.Tests.Editor { [TestFixture] - public class TestSceneOsuComposerSelection : TestSceneOsuEditor + public partial class TestSceneOsuComposerSelection : TestSceneOsuEditor { protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new TestBeatmap(ruleset, false); diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuDistanceSnapGrid.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuDistanceSnapGrid.cs index 1b67fc2ca9..7579e8077b 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuDistanceSnapGrid.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuDistanceSnapGrid.cs @@ -27,7 +27,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Tests.Editor { - public class TestSceneOsuDistanceSnapGrid : OsuManualInputManagerTestScene + public partial class TestSceneOsuDistanceSnapGrid : OsuManualInputManagerTestScene { private const float beat_length = 100; @@ -217,7 +217,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor return Precision.AlmostEquals(expectedDistance, Vector2.Distance(snappedPosition, grid_position)); }); - private class SnappingCursorContainer : CompositeDrawable + private partial class SnappingCursorContainer : CompositeDrawable { public Func GetSnapPosition; diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditor.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditor.cs index 859290dbec..41a099e6e9 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditor.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditor.cs @@ -9,7 +9,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Osu.Tests.Editor { [TestFixture] - public class TestSceneOsuEditor : EditorTestScene + public partial class TestSceneOsuEditor : EditorTestScene { protected override Ruleset CreateEditorRuleset() => new OsuRuleset(); } diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorGrids.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorGrids.cs index f9cea5761b..59146bc05e 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorGrids.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorGrids.cs @@ -15,7 +15,7 @@ using osuTK.Input; namespace osu.Game.Rulesets.Osu.Tests.Editor { - public class TestSceneOsuEditorGrids : EditorTestScene + public partial class TestSceneOsuEditorGrids : EditorTestScene { protected override Ruleset CreateEditorRuleset() => new OsuRuleset(); diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorSelectInvalidPath.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorSelectInvalidPath.cs index 536739bd48..bb29504ec3 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorSelectInvalidPath.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorSelectInvalidPath.cs @@ -14,7 +14,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Tests.Editor { - public class TestSceneOsuEditorSelectInvalidPath : EditorTestScene + public partial class TestSceneOsuEditorSelectInvalidPath : EditorTestScene { protected override Ruleset CreateEditorRuleset() => new OsuRuleset(); diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestScenePathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestScenePathControlPointVisualiser.cs index 6d93c3fcf9..d1a04e28e5 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestScenePathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestScenePathControlPointVisualiser.cs @@ -18,7 +18,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Tests.Editor { - public class TestScenePathControlPointVisualiser : OsuManualInputManagerTestScene + public partial class TestScenePathControlPointVisualiser : OsuManualInputManagerTestScene { private Slider slider; private PathControlPointVisualiser visualiser; diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderControlPointPiece.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderControlPointPiece.cs index a177079b8c..112aab884b 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderControlPointPiece.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderControlPointPiece.cs @@ -23,7 +23,7 @@ using osuTK.Input; namespace osu.Game.Rulesets.Osu.Tests.Editor { - public class TestSceneSliderControlPointPiece : SelectionBlueprintTestScene + public partial class TestSceneSliderControlPointPiece : SelectionBlueprintTestScene { private Slider slider; private DrawableSlider drawableObject; @@ -349,7 +349,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor private void assertControlPointPosition(int index, Vector2 position) => AddAssert($"control point {index} at {position}", () => Precision.AlmostEquals(position, slider.Path.ControlPoints[index].Position, 1)); - private class TestSliderBlueprint : SliderSelectionBlueprint + private partial class TestSliderBlueprint : SliderSelectionBlueprint { public new SliderBodyPiece BodyPiece => base.BodyPiece; public new TestSliderCircleOverlay HeadOverlay => (TestSliderCircleOverlay)base.HeadOverlay; @@ -364,7 +364,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor protected override SliderCircleOverlay CreateCircleOverlay(Slider slider, SliderPosition position) => new TestSliderCircleOverlay(slider, position); } - private class TestSliderCircleOverlay : SliderCircleOverlay + private partial class TestSliderCircleOverlay : SliderCircleOverlay { public new HitCirclePiece CirclePiece => base.CirclePiece; diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderLengthValidity.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderLengthValidity.cs index 31b593e816..77e828e80a 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderLengthValidity.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderLengthValidity.cs @@ -19,7 +19,7 @@ using osuTK.Input; namespace osu.Game.Rulesets.Osu.Tests.Editor { [TestFixture] - public class TestSceneSliderLengthValidity : TestSceneOsuEditor + public partial class TestSceneSliderLengthValidity : TestSceneOsuEditor { private OsuPlayfield playfield; diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderPlacementBlueprint.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderPlacementBlueprint.cs index 5c3c537541..7542e00a94 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderPlacementBlueprint.cs @@ -18,7 +18,7 @@ using osuTK.Input; namespace osu.Game.Rulesets.Osu.Tests.Editor { - public class TestSceneSliderPlacementBlueprint : PlacementBlueprintTestScene + public partial class TestSceneSliderPlacementBlueprint : PlacementBlueprintTestScene { [SetUp] public void Setup() => Schedule(() => diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderSelectionBlueprint.cs index f84204f01c..ad740b2977 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderSelectionBlueprint.cs @@ -20,7 +20,7 @@ using osuTK.Input; namespace osu.Game.Rulesets.Osu.Tests.Editor { - public class TestSceneSliderSelectionBlueprint : SelectionBlueprintTestScene + public partial class TestSceneSliderSelectionBlueprint : SelectionBlueprintTestScene { private Slider slider; private DrawableSlider drawableObject; @@ -194,7 +194,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor private void checkControlPointSelected(int index, bool selected) => AddAssert($"control point {index} {(selected ? "selected" : "not selected")}", () => blueprint.ControlPointVisualiser.Pieces[index].IsSelected.Value == selected); - private class TestSliderBlueprint : SliderSelectionBlueprint + private partial class TestSliderBlueprint : SliderSelectionBlueprint { public new SliderBodyPiece BodyPiece => base.BodyPiece; public new TestSliderCircleOverlay HeadOverlay => (TestSliderCircleOverlay)base.HeadOverlay; @@ -209,7 +209,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor protected override SliderCircleOverlay CreateCircleOverlay(Slider slider, SliderPosition position) => new TestSliderCircleOverlay(slider, position); } - private class TestSliderCircleOverlay : SliderCircleOverlay + private partial class TestSliderCircleOverlay : SliderCircleOverlay { public new HitCirclePiece CirclePiece => base.CirclePiece; diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderSnapping.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderSnapping.cs index e864afe056..e9d50d5118 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderSnapping.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderSnapping.cs @@ -26,7 +26,7 @@ using osuTK.Input; namespace osu.Game.Rulesets.Osu.Tests.Editor { - public class TestSceneSliderSnapping : EditorTestScene + public partial class TestSceneSliderSnapping : EditorTestScene { private const double beat_length = 1000; diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderSplitting.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderSplitting.cs index 015952c59a..b2ac462c8f 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderSplitting.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderSplitting.cs @@ -19,7 +19,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Tests.Editor { - public class TestSceneSliderSplitting : EditorTestScene + public partial class TestSceneSliderSplitting : EditorTestScene { protected override Ruleset CreateEditorRuleset() => new OsuRuleset(); diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderStreamConversion.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderStreamConversion.cs index 0601dc6068..53465d43c9 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderStreamConversion.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderStreamConversion.cs @@ -15,7 +15,7 @@ using osuTK.Input; namespace osu.Game.Rulesets.Osu.Tests.Editor { - public class TestSceneSliderStreamConversion : TestSceneOsuEditor + public partial class TestSceneSliderStreamConversion : TestSceneOsuEditor { private BindableBeatDivisor beatDivisor => (BindableBeatDivisor)Editor.Dependencies.Get(typeof(BindableBeatDivisor)); diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderVelocityAdjust.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderVelocityAdjust.cs index ef9e332253..bb8c52bdfc 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderVelocityAdjust.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderVelocityAdjust.cs @@ -22,7 +22,7 @@ using osuTK.Input; namespace osu.Game.Rulesets.Osu.Tests.Editor { - public class TestSceneSliderVelocityAdjust : OsuGameTestScene + public partial class TestSceneSliderVelocityAdjust : OsuGameTestScene { private Screens.Edit.Editor editor => Game.ScreenStack.CurrentScreen as Screens.Edit.Editor; diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSpinnerPlacementBlueprint.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSpinnerPlacementBlueprint.cs index 53ef675cb3..6378097800 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSpinnerPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSpinnerPlacementBlueprint.cs @@ -13,7 +13,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Osu.Tests.Editor { - public class TestSceneSpinnerPlacementBlueprint : PlacementBlueprintTestScene + public partial class TestSceneSpinnerPlacementBlueprint : PlacementBlueprintTestScene { protected override DrawableHitObject CreateHitObject(HitObject hitObject) => new DrawableSpinner((Spinner)hitObject); diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSpinnerSelectionBlueprint.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSpinnerSelectionBlueprint.cs index a1b946dd4c..c899f58c5a 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSpinnerSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSpinnerSelectionBlueprint.cs @@ -15,7 +15,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Tests.Editor { - public class TestSceneSpinnerSelectionBlueprint : SelectionBlueprintTestScene + public partial class TestSceneSpinnerSelectionBlueprint : SelectionBlueprintTestScene { public TestSceneSpinnerSelectionBlueprint() { diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSliderScaling.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSliderScaling.cs index efe195d872..64d23090d0 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSliderScaling.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSliderScaling.cs @@ -19,7 +19,7 @@ using osuTK.Input; namespace osu.Game.Rulesets.Osu.Tests.Editor { [TestFixture] - public class TestSliderScaling : TestSceneOsuEditor + public partial class TestSliderScaling : TestSceneOsuEditor { private OsuPlayfield playfield; diff --git a/osu.Game.Rulesets.Osu.Tests/LegacyMainCirclePieceTest.cs b/osu.Game.Rulesets.Osu.Tests/LegacyMainCirclePieceTest.cs index b6c8103e3c..baaa24959f 100644 --- a/osu.Game.Rulesets.Osu.Tests/LegacyMainCirclePieceTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/LegacyMainCirclePieceTest.cs @@ -18,7 +18,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Osu.Tests { [HeadlessTest] - public class LegacyMainCirclePieceTest : OsuTestScene + public partial class LegacyMainCirclePieceTest : OsuTestScene { [Resolved] private IRenderer renderer { get; set; } = null!; @@ -101,7 +101,7 @@ namespace osu.Game.Rulesets.Osu.Tests AddAssert("check overlay sprite", () => piece.OverlaySprite?.Texture?.AssetName == expectedOverlay); } - private class TestLegacyMainCirclePiece : LegacyMainCirclePiece + private partial class TestLegacyMainCirclePiece : LegacyMainCirclePiece { public new Sprite? CircleSprite => base.CircleSprite.ChildrenOfType().DistinctBy(s => s.Texture.AssetName).SingleOrDefault(); public new Sprite? OverlaySprite => base.OverlaySprite.ChildrenOfType().DistinctBy(s => s.Texture.AssetName).SingleOrDefault(); diff --git a/osu.Game.Rulesets.Osu.Tests/Mods/OsuModTestScene.cs b/osu.Game.Rulesets.Osu.Tests/Mods/OsuModTestScene.cs index d3cb3bcf59..82d7ac6bba 100644 --- a/osu.Game.Rulesets.Osu.Tests/Mods/OsuModTestScene.cs +++ b/osu.Game.Rulesets.Osu.Tests/Mods/OsuModTestScene.cs @@ -5,7 +5,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Osu.Tests.Mods { - public abstract class OsuModTestScene : ModTestScene + public abstract partial class OsuModTestScene : ModTestScene { protected override Ruleset CreatePlayerRuleset() => new OsuRuleset(); } diff --git a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModAlternate.cs b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModAlternate.cs index 521c10c10c..88c81c7a39 100644 --- a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModAlternate.cs +++ b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModAlternate.cs @@ -15,7 +15,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Tests.Mods { - public class TestSceneOsuModAlternate : OsuModTestScene + public partial class TestSceneOsuModAlternate : OsuModTestScene { [Test] public void TestInputAlternating() => CreateModTest(new ModTestData diff --git a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModAutoplay.cs b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModAutoplay.cs index 3563995234..8fdab9f1f9 100644 --- a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModAutoplay.cs +++ b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModAutoplay.cs @@ -15,7 +15,7 @@ using osu.Game.Rulesets.Osu.UI; namespace osu.Game.Rulesets.Osu.Tests.Mods { - public class TestSceneOsuModAutoplay : OsuModTestScene + public partial class TestSceneOsuModAutoplay : OsuModTestScene { [Test] public void TestSpmUnaffectedByRateAdjust() diff --git a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModDifficultyAdjust.cs b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModDifficultyAdjust.cs index 88b6b9dd56..472c341bdd 100644 --- a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModDifficultyAdjust.cs +++ b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModDifficultyAdjust.cs @@ -15,7 +15,7 @@ using osu.Game.Rulesets.Osu.Objects.Drawables; namespace osu.Game.Rulesets.Osu.Tests.Mods { - public class TestSceneOsuModDifficultyAdjust : OsuModTestScene + public partial class TestSceneOsuModDifficultyAdjust : OsuModTestScene { [Test] public void TestNoAdjustment() => CreateModTest(new ModTestData diff --git a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModDoubleTime.cs b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModDoubleTime.cs index 8df8afe147..f895b91151 100644 --- a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModDoubleTime.cs +++ b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModDoubleTime.cs @@ -7,7 +7,7 @@ using osu.Game.Rulesets.Osu.Mods; namespace osu.Game.Rulesets.Osu.Tests.Mods { - public class TestSceneOsuModDoubleTime : OsuModTestScene + public partial class TestSceneOsuModDoubleTime : OsuModTestScene { [TestCase(0.5)] [TestCase(1.01)] diff --git a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModFlashlight.cs b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModFlashlight.cs index 704a548c61..a353914cd5 100644 --- a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModFlashlight.cs +++ b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModFlashlight.cs @@ -6,7 +6,7 @@ using osu.Game.Rulesets.Osu.Mods; namespace osu.Game.Rulesets.Osu.Tests.Mods { - public class TestSceneOsuModFlashlight : OsuModTestScene + public partial class TestSceneOsuModFlashlight : OsuModTestScene { [TestCase(600)] [TestCase(120)] diff --git a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModFreezeFrame.cs b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModFreezeFrame.cs index 7d7b2d9071..57d2b94188 100644 --- a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModFreezeFrame.cs +++ b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModFreezeFrame.cs @@ -6,7 +6,7 @@ using osu.Game.Rulesets.Osu.Mods; namespace osu.Game.Rulesets.Osu.Tests.Mods { - public class TestSceneOsuModFreezeFrame : OsuModTestScene + public partial class TestSceneOsuModFreezeFrame : OsuModTestScene { [Test] public void TestFreezeFrame() diff --git a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModHidden.cs b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModHidden.cs index e692f8ecbc..3f84ac6935 100644 --- a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModHidden.cs +++ b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModHidden.cs @@ -13,7 +13,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Tests.Mods { - public class TestSceneOsuModHidden : OsuModTestScene + public partial class TestSceneOsuModHidden : OsuModTestScene { [Test] public void TestDefaultBeatmapTest() => CreateModTest(new ModTestData diff --git a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModMagnetised.cs b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModMagnetised.cs index 9b49e60363..8a5a7706d1 100644 --- a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModMagnetised.cs +++ b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModMagnetised.cs @@ -6,7 +6,7 @@ using osu.Game.Rulesets.Osu.Mods; namespace osu.Game.Rulesets.Osu.Tests.Mods { - public class TestSceneOsuModMagnetised : OsuModTestScene + public partial class TestSceneOsuModMagnetised : OsuModTestScene { [TestCase(0.1f)] [TestCase(0.5f)] diff --git a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModMuted.cs b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModMuted.cs index 68669d1a53..ac341d73b8 100644 --- a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModMuted.cs +++ b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModMuted.cs @@ -9,7 +9,7 @@ using osu.Game.Rulesets.Osu.Mods; namespace osu.Game.Rulesets.Osu.Tests.Mods { - public class TestSceneOsuModMuted : OsuModTestScene + public partial class TestSceneOsuModMuted : OsuModTestScene { /// /// Ensures that a final volume combo of 0 (i.e. "always muted" mode) constantly plays metronome and completely mutes track. @@ -45,8 +45,8 @@ namespace osu.Game.Rulesets.Osu.Tests.Mods InverseMuting = { Value = false }, })); - AddAssert("mute combo count = 0", () => muted.MuteComboCount.Value == 0); - AddAssert("inverse muting = false", () => muted.InverseMuting.Value == false); + AddAssert("mute combo count copied", () => muted.MuteComboCount.Value, () => Is.EqualTo(0)); + AddAssert("inverse muting copied", () => muted.InverseMuting.Value, () => Is.False); } } } diff --git a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModNoScope.cs b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModNoScope.cs index da6fac3269..9dfa76fc8e 100644 --- a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModNoScope.cs +++ b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModNoScope.cs @@ -18,7 +18,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Tests.Mods { - public class TestSceneOsuModNoScope : OsuModTestScene + public partial class TestSceneOsuModNoScope : OsuModTestScene { [Test] public void TestVisibleDuringBreak() diff --git a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModPerfect.cs b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModPerfect.cs index 985baa8cf5..f0496efc19 100644 --- a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModPerfect.cs +++ b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModPerfect.cs @@ -11,7 +11,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Tests.Mods { - public class TestSceneOsuModPerfect : ModPerfectTestScene + public partial class TestSceneOsuModPerfect : ModPerfectTestScene { protected override Ruleset CreatePlayerRuleset() => new OsuRuleset(); diff --git a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModRandom.cs b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModRandom.cs index c24ba6d530..060a845137 100644 --- a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModRandom.cs +++ b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModRandom.cs @@ -12,7 +12,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Tests.Mods { - public class TestSceneOsuModRandom : OsuModTestScene + public partial class TestSceneOsuModRandom : OsuModTestScene { [TestCase(1)] [TestCase(7)] diff --git a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModRepel.cs b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModRepel.cs index 6bd41e2fa5..8a3d645b05 100644 --- a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModRepel.cs +++ b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModRepel.cs @@ -6,7 +6,7 @@ using osu.Game.Rulesets.Osu.Mods; namespace osu.Game.Rulesets.Osu.Tests.Mods { - public class TestSceneOsuModRepel : OsuModTestScene + public partial class TestSceneOsuModRepel : OsuModTestScene { [TestCase(0.1f)] [TestCase(0.5f)] diff --git a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModSingleTap.cs b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModSingleTap.cs index 1aed84be10..402c680b46 100644 --- a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModSingleTap.cs +++ b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModSingleTap.cs @@ -14,7 +14,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Tests.Mods { - public class TestSceneOsuModSingleTap : OsuModTestScene + public partial class TestSceneOsuModSingleTap : OsuModTestScene { [Test] public void TestInputSingular() => CreateModTest(new ModTestData diff --git a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModSpunOut.cs b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModSpunOut.cs index e121e6103d..de3ea5f148 100644 --- a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModSpunOut.cs +++ b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModSpunOut.cs @@ -21,7 +21,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Tests.Mods { - public class TestSceneOsuModSpunOut : OsuModTestScene + public partial class TestSceneOsuModSpunOut : OsuModTestScene { protected override bool AllowFail => true; diff --git a/osu.Game.Rulesets.Osu.Tests/OsuHitObjectGenerationUtilsTest.cs b/osu.Game.Rulesets.Osu.Tests/OsuHitObjectGenerationUtilsTest.cs new file mode 100644 index 0000000000..daa914cac2 --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests/OsuHitObjectGenerationUtilsTest.cs @@ -0,0 +1,91 @@ +// Copyright (c) ppy Pty Ltd . 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.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.UI; +using osu.Game.Rulesets.Osu.Utils; +using osuTK; + +namespace osu.Game.Rulesets.Osu.Tests +{ + [TestFixture] + public class OsuHitObjectGenerationUtilsTest + { + private static Slider createTestSlider() + { + var slider = new Slider + { + Position = new Vector2(128, 128), + Path = new SliderPath + { + ControlPoints = + { + new PathControlPoint(new Vector2(), PathType.Linear), + new PathControlPoint(new Vector2(-64, -128), PathType.Linear), // absolute position: (64, 0) + new PathControlPoint(new Vector2(-128, 0), PathType.Linear) // absolute position: (0, 128) + } + }, + RepeatCount = 1 + }; + slider.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + return slider; + } + + [Test] + public void TestReflectSliderHorizontallyAlongPlayfield() + { + var slider = createTestSlider(); + + OsuHitObjectGenerationUtils.ReflectHorizontallyAlongPlayfield(slider); + + Assert.That(slider.Position, Is.EqualTo(new Vector2(OsuPlayfield.BASE_SIZE.X - 128, 128))); + Assert.That(slider.NestedHitObjects.OfType().Single().Position, Is.EqualTo(new Vector2(OsuPlayfield.BASE_SIZE.X - 0, 128))); + Assert.That(slider.Path.ControlPoints.Select(point => point.Position), Is.EquivalentTo(new[] + { + new Vector2(), + new Vector2(64, -128), + new Vector2(128, 0) + })); + } + + [Test] + public void TestReflectSliderVerticallyAlongPlayfield() + { + var slider = createTestSlider(); + + OsuHitObjectGenerationUtils.ReflectVerticallyAlongPlayfield(slider); + + Assert.That(slider.Position, Is.EqualTo(new Vector2(128, OsuPlayfield.BASE_SIZE.Y - 128))); + Assert.That(slider.NestedHitObjects.OfType().Single().Position, Is.EqualTo(new Vector2(0, OsuPlayfield.BASE_SIZE.Y - 128))); + Assert.That(slider.Path.ControlPoints.Select(point => point.Position), Is.EquivalentTo(new[] + { + new Vector2(), + new Vector2(-64, 128), + new Vector2(-128, 0) + })); + } + + [Test] + public void TestFlipSliderInPlaceHorizontally() + { + var slider = createTestSlider(); + + OsuHitObjectGenerationUtils.FlipSliderInPlaceHorizontally(slider); + + Assert.That(slider.Position, Is.EqualTo(new Vector2(128, 128))); + Assert.That(slider.NestedHitObjects.OfType().Single().Position, Is.EqualTo(new Vector2(256, 128))); + Assert.That(slider.Path.ControlPoints.Select(point => point.Position), Is.EquivalentTo(new[] + { + new Vector2(), + new Vector2(64, -128), + new Vector2(128, 0) + })); + } + } +} diff --git a/osu.Game.Rulesets.Osu.Tests/OsuSkinnableTestScene.cs b/osu.Game.Rulesets.Osu.Tests/OsuSkinnableTestScene.cs index 415e4ebedd..574618c528 100644 --- a/osu.Game.Rulesets.Osu.Tests/OsuSkinnableTestScene.cs +++ b/osu.Game.Rulesets.Osu.Tests/OsuSkinnableTestScene.cs @@ -9,7 +9,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Osu.Tests { - public abstract class OsuSkinnableTestScene : SkinnableTestScene + public abstract partial class OsuSkinnableTestScene : SkinnableTestScene { private Container content; diff --git a/osu.Game.Rulesets.Osu.Tests/TestPlayfieldBorder.cs b/osu.Game.Rulesets.Osu.Tests/TestPlayfieldBorder.cs index 106a7f499f..5366a86bc0 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestPlayfieldBorder.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestPlayfieldBorder.cs @@ -12,7 +12,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Tests { - public class TestPlayfieldBorder : OsuTestScene + public partial class TestPlayfieldBorder : OsuTestScene { public TestPlayfieldBorder() { diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneAccuracyHeatmap.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneAccuracyHeatmap.cs index 805f4e6567..f99518997b 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneAccuracyHeatmap.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneAccuracyHeatmap.cs @@ -20,7 +20,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Tests { - public class TestSceneAccuracyHeatmap : OsuManualInputManagerTestScene + public partial class TestSceneAccuracyHeatmap : OsuManualInputManagerTestScene { private Box background; private Drawable object1; @@ -91,7 +91,7 @@ namespace osu.Game.Rulesets.Osu.Tests return true; } - private class TestAccuracyHeatmap : AccuracyHeatmap + private partial class TestAccuracyHeatmap : AccuracyHeatmap { public TestAccuracyHeatmap(ScoreInfo score) : base(score, new TestBeatmap(new OsuRuleset().RulesetInfo)) @@ -102,7 +102,7 @@ namespace osu.Game.Rulesets.Osu.Tests => base.AddPoint(start, end, hitPoint, radius); } - private class BorderCircle : CircularContainer + private partial class BorderCircle : CircularContainer { public BorderCircle() { diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneCursorParticles.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneCursorParticles.cs index 7f0ecaca2b..f6e460284b 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneCursorParticles.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneCursorParticles.cs @@ -22,7 +22,7 @@ using osuTK.Input; namespace osu.Game.Rulesets.Osu.Tests { - public class TestSceneCursorParticles : TestSceneOsuPlayer + public partial class TestSceneCursorParticles : TestSceneOsuPlayer { protected override bool Autoplay => autoplay; protected override bool HasCustomSteps => true; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneCursorTrail.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneCursorTrail.cs index 30f0891344..9582ee491b 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneCursorTrail.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneCursorTrail.cs @@ -23,7 +23,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Tests { - public class TestSceneCursorTrail : OsuTestScene + public partial class TestSceneCursorTrail : OsuTestScene { [Resolved] private IRenderer renderer { get; set; } @@ -83,7 +83,7 @@ namespace osu.Game.Rulesets.Osu.Tests }); [Cached(typeof(ISkinSource))] - private class LegacySkinContainer : Container, ISkinSource + private partial class LegacySkinContainer : Container, ISkinSource { private readonly IRenderer renderer; private readonly bool disjoint; @@ -131,7 +131,7 @@ namespace osu.Game.Rulesets.Osu.Tests } } - private class MovingCursorInputManager : ManualInputManager + private partial class MovingCursorInputManager : ManualInputManager { public MovingCursorInputManager() { diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs index cfa1841fb7..ff71300733 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs @@ -22,7 +22,7 @@ using osu.Game.Skinning; namespace osu.Game.Rulesets.Osu.Tests { - public class TestSceneDrawableJudgement : OsuSkinnableTestScene + public partial class TestSceneDrawableJudgement : OsuSkinnableTestScene { [Resolved] private OsuConfigManager config { get; set; } @@ -106,7 +106,7 @@ namespace osu.Game.Rulesets.Osu.Tests }); } - private class TestDrawableOsuJudgement : DrawableOsuJudgement + private partial class TestDrawableOsuJudgement : DrawableOsuJudgement { public new SkinnableSprite Lighting => base.Lighting; public new SkinnableDrawable JudgementBody => base.JudgementBody; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs index 1e625cd4e6..eefaa3cae3 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs @@ -21,7 +21,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Tests { - public class TestSceneFollowPoints : OsuTestScene + public partial class TestSceneFollowPoints : OsuTestScene { private Container hitObjectContainer; private FollowPointRenderer followPointRenderer; @@ -278,7 +278,7 @@ namespace osu.Game.Rulesets.Osu.Tests private FollowPointConnection getGroup(int index) => followPointRenderer.ChildrenOfType().Single(c => c.Entry == getEntry(index)); - private class TestHitObjectContainer : Container + private partial class TestHitObjectContainer : Container { protected override int Compare(Drawable x, Drawable y) { diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneGameplayCursor.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneGameplayCursor.cs index 628082c2a9..907422858e 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneGameplayCursor.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneGameplayCursor.cs @@ -28,7 +28,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Tests { [TestFixture] - public class TestSceneGameplayCursor : OsuSkinnableTestScene + public partial class TestSceneGameplayCursor : OsuSkinnableTestScene { [Cached] private GameplayState gameplayState; @@ -135,7 +135,7 @@ namespace osu.Game.Rulesets.Osu.Tests } } - private class ClickingCursorContainer : OsuCursorContainer + private partial class ClickingCursorContainer : OsuCursorContainer { private bool pressed; @@ -161,7 +161,7 @@ namespace osu.Game.Rulesets.Osu.Tests } } - private class MovingCursorInputManager : ManualInputManager + private partial class MovingCursorInputManager : ManualInputManager { public MovingCursorInputManager() { diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs index be224b88ce..a418df605f 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs @@ -18,7 +18,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Tests { [TestFixture] - public class TestSceneHitCircle : OsuSkinnableTestScene + public partial class TestSceneHitCircle : OsuSkinnableTestScene { private int depthIndex; @@ -105,7 +105,7 @@ namespace osu.Game.Rulesets.Osu.Tests Depth = depthIndex++ }; - protected class TestDrawableHitCircle : DrawableHitCircle + protected partial class TestDrawableHitCircle : DrawableHitCircle { private readonly bool auto; private readonly double hitOffset; @@ -131,7 +131,7 @@ namespace osu.Game.Rulesets.Osu.Tests } } - protected class TestOsuPlayfield : OsuPlayfield + protected partial class TestOsuPlayfield : OsuPlayfield { public TestOsuPlayfield() { diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleApplication.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleApplication.cs index 0bc65ac8e6..bcbff20016 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleApplication.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleApplication.cs @@ -14,7 +14,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Tests { - public class TestSceneHitCircleApplication : OsuTestScene + public partial class TestSceneHitCircleApplication : OsuTestScene { [Test] public void TestApplyNewCircle() diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleArea.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleArea.cs index 20aed514db..71174e3295 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleArea.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleArea.cs @@ -18,7 +18,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Tests { - public class TestSceneHitCircleArea : OsuManualInputManagerTestScene + public partial class TestSceneHitCircleArea : OsuManualInputManagerTestScene { private HitCircle hitCircle; private DrawableHitCircle drawableHitCircle; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleComboChange.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleComboChange.cs index 85951a95a2..34c67e8b9c 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleComboChange.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleComboChange.cs @@ -8,7 +8,7 @@ using osu.Game.Rulesets.Osu.Objects; namespace osu.Game.Rulesets.Osu.Tests { - public class TestSceneHitCircleComboChange : TestSceneHitCircle + public partial class TestSceneHitCircleComboChange : TestSceneHitCircle { private readonly Bindable comboIndex = new Bindable(); diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleHidden.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleHidden.cs index a469f3dd99..b3498b9651 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleHidden.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleHidden.cs @@ -9,7 +9,7 @@ using osu.Game.Rulesets.Osu.Mods; namespace osu.Game.Rulesets.Osu.Tests { [TestFixture] - public class TestSceneHitCircleHidden : TestSceneHitCircle + public partial class TestSceneHitCircleHidden : TestSceneHitCircle { [SetUp] public void SetUp() => Schedule(() => diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleKiai.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleKiai.cs index e694871408..2c9f1acd2c 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleKiai.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleKiai.cs @@ -10,7 +10,7 @@ using osu.Game.Beatmaps.ControlPoints; namespace osu.Game.Rulesets.Osu.Tests { [TestFixture] - public class TestSceneHitCircleKiai : TestSceneHitCircle + public partial class TestSceneHitCircleKiai : TestSceneHitCircle { [SetUp] public void SetUp() => Schedule(() => diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleLongCombo.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleLongCombo.cs index bcf2449e32..93f1123341 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleLongCombo.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleLongCombo.cs @@ -11,7 +11,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Tests { [TestFixture] - public class TestSceneHitCircleLongCombo : TestSceneOsuPlayer + public partial class TestSceneHitCircleLongCombo : TestSceneOsuPlayer { protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) { diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs index bb28b2b217..e70d45fb45 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs @@ -21,7 +21,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Tests { - public class TestSceneLegacyBeatmapSkin : LegacyBeatmapSkinColourTest + public partial class TestSceneLegacyBeatmapSkin : LegacyBeatmapSkinColourTest { [Resolved] private AudioManager audio { get; set; } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneMissHitWindowJudgements.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneMissHitWindowJudgements.cs index 0c6afe6c3d..0d3fd77568 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneMissHitWindowJudgements.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneMissHitWindowJudgements.cs @@ -19,7 +19,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Tests { - public class TestSceneMissHitWindowJudgements : ModTestScene + public partial class TestSceneMissHitWindowJudgements : ModTestScene { protected override Ruleset CreatePlayerRuleset() => new OsuRuleset(); diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneNoSpinnerStacking.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneNoSpinnerStacking.cs index 9e524a1608..1f0e264cf7 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneNoSpinnerStacking.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneNoSpinnerStacking.cs @@ -11,7 +11,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Tests { [TestFixture] - public class TestSceneNoSpinnerStacking : TestSceneOsuPlayer + public partial class TestSceneNoSpinnerStacking : TestSceneOsuPlayer { protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) { diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneObjectOrderedHitPolicy.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneObjectOrderedHitPolicy.cs index ed1891b7d9..5d9316a21b 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneObjectOrderedHitPolicy.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneObjectOrderedHitPolicy.cs @@ -28,7 +28,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Tests { - public class TestSceneObjectOrderedHitPolicy : RateAdjustedBeatmapTestScene + public partial class TestSceneObjectOrderedHitPolicy : RateAdjustedBeatmapTestScene { private const double early_miss_window = 1000; // time after -1000 to -500 is considered a miss private const double late_miss_window = 500; // time after +500 is considered a miss @@ -474,7 +474,7 @@ namespace osu.Game.Rulesets.Osu.Tests protected override DifficultyRange[] GetRanges() => ranges; } - private class ScoreAccessibleReplayPlayer : ReplayPlayer + private partial class ScoreAccessibleReplayPlayer : ReplayPlayer { public new ScoreProcessor ScoreProcessor => base.ScoreProcessor; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuHitObjectSamples.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuHitObjectSamples.cs index 3bc55278d9..4d0b2cc406 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuHitObjectSamples.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuHitObjectSamples.cs @@ -10,7 +10,7 @@ using osu.Game.Tests.Beatmaps; namespace osu.Game.Rulesets.Osu.Tests { - public class TestSceneOsuHitObjectSamples : HitObjectSampleTest + public partial class TestSceneOsuHitObjectSamples : HitObjectSampleTest { protected override Ruleset CreatePlayerRuleset() => new OsuRuleset(); diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuPlayer.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuPlayer.cs index 6f378fc8b4..53c4e49807 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuPlayer.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuPlayer.cs @@ -9,7 +9,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Osu.Tests { [TestFixture] - public class TestSceneOsuPlayer : PlayerTestScene + public partial class TestSceneOsuPlayer : PlayerTestScene { protected override Ruleset CreatePlayerRuleset() => new OsuRuleset(); } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneResumeOverlay.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneResumeOverlay.cs index e0d33c0e09..b66974d4b1 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneResumeOverlay.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneResumeOverlay.cs @@ -12,7 +12,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Osu.Tests { - public class TestSceneResumeOverlay : OsuManualInputManagerTestScene + public partial class TestSceneResumeOverlay : OsuManualInputManagerTestScene { public TestSceneResumeOverlay() { @@ -48,7 +48,7 @@ namespace osu.Game.Rulesets.Osu.Tests AddAssert("dismissed", () => resumeFired && resume.State.Value == Visibility.Hidden); } - private class ManualOsuInputManager : OsuInputManager + private partial class ManualOsuInputManager : OsuInputManager { public ManualOsuInputManager(RulesetInfo ruleset) : base(ruleset) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneShaking.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneShaking.cs index dd767bf5e0..bee7831625 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneShaking.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneShaking.cs @@ -13,7 +13,7 @@ using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Osu.Tests { - public class TestSceneShaking : TestSceneHitCircle + public partial class TestSceneShaking : TestSceneHitCircle { private readonly List scheduledTasks = new List(); diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs index 878150e467..09b906cb10 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs @@ -29,7 +29,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Osu.Tests { [TestFixture] - public class TestSceneSkinFallbacks : TestSceneOsuPlayer + public partial class TestSceneSkinFallbacks : TestSceneOsuPlayer { private readonly TestSource testUserSkin; private readonly TestSource testBeatmapSkin; @@ -119,7 +119,7 @@ namespace osu.Game.Rulesets.Osu.Tests protected override ISkin GetSkin() => skin; } - public class SkinProvidingPlayer : TestPlayer + public partial class SkinProvidingPlayer : TestPlayer { private readonly TestSource userSkin; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs index a9ee276a9e..1e9f931b74 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs @@ -26,7 +26,7 @@ using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Rulesets.Osu.Tests { [TestFixture] - public class TestSceneSlider : OsuSkinnableTestScene + public partial class TestSceneSlider : OsuSkinnableTestScene { private int depthIndex; @@ -160,9 +160,9 @@ namespace osu.Game.Rulesets.Osu.Tests static bool assertSamples(HitObject hitObject) => hitObject.Samples.All(s => s.Name != HitSampleInfo.HIT_CLAP && s.Name != HitSampleInfo.HIT_WHISTLE); } - private Drawable testSimpleBig(int repeats = 0) => createSlider(2, repeats: repeats); + private Drawable testSimpleBig(int repeats = 0) => createSlider(repeats: repeats); - private Drawable testSimpleBigLargeStackOffset(int repeats = 0) => createSlider(2, repeats: repeats, stackHeight: 10); + private Drawable testSimpleBigLargeStackOffset(int repeats = 0) => createSlider(repeats: repeats, stackHeight: 10); private Drawable testDistanceOverflow(int repeats = 0) { diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderApplication.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderApplication.cs index 728aa27da2..88b70a8836 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderApplication.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderApplication.cs @@ -22,7 +22,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Tests { - public class TestSceneSliderApplication : OsuTestScene + public partial class TestSceneSliderApplication : OsuTestScene { [Resolved] private SkinManager skinManager { get; set; } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderComboChange.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderComboChange.cs index b48789a709..dc8842a20a 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderComboChange.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderComboChange.cs @@ -9,7 +9,7 @@ using osu.Game.Rulesets.Osu.Objects.Drawables; namespace osu.Game.Rulesets.Osu.Tests { - public class TestSceneSliderComboChange : TestSceneSlider + public partial class TestSceneSliderComboChange : TestSceneSlider { private readonly Bindable comboIndex = new Bindable(); diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderFollowCircleInput.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderFollowCircleInput.cs index 7a6e19575e..0af0ff5604 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderFollowCircleInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderFollowCircleInput.cs @@ -24,7 +24,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Tests { [HeadlessTest] - public class TestSceneSliderFollowCircleInput : RateAdjustedBeatmapTestScene + public partial class TestSceneSliderFollowCircleInput : RateAdjustedBeatmapTestScene { private List? judgementResults; private ScoreAccessibleReplayPlayer? currentPlayer; @@ -101,7 +101,7 @@ namespace osu.Game.Rulesets.Osu.Tests AddUntilStep("Wait for completion", () => currentPlayer?.ScoreProcessor.HasCompleted.Value == true); } - private class ScoreAccessibleReplayPlayer : ReplayPlayer + private partial class ScoreAccessibleReplayPlayer : ReplayPlayer { public new ScoreProcessor ScoreProcessor => base.ScoreProcessor; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderHidden.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderHidden.cs index f70bdf8aa2..eb13995ad0 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderHidden.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderHidden.cs @@ -9,7 +9,7 @@ using osu.Game.Rulesets.Osu.Mods; namespace osu.Game.Rulesets.Osu.Tests { [TestFixture] - public class TestSceneSliderHidden : TestSceneSlider + public partial class TestSceneSliderHidden : TestSceneSlider { [SetUp] public void SetUp() => Schedule(() => diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs index e3cf5e9b05..5f27cdc191 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs @@ -24,7 +24,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Tests { - public class TestSceneSliderInput : RateAdjustedBeatmapTestScene + public partial class TestSceneSliderInput : RateAdjustedBeatmapTestScene { private const double time_before_slider = 250; private const double time_slider_start = 1500; @@ -384,7 +384,7 @@ namespace osu.Game.Rulesets.Osu.Tests AddUntilStep("Wait for completion", () => currentPlayer.ScoreProcessor.HasCompleted.Value); } - private class ScoreAccessibleReplayPlayer : ReplayPlayer + private partial class ScoreAccessibleReplayPlayer : ReplayPlayer { public new ScoreProcessor ScoreProcessor => base.ScoreProcessor; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSnaking.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSnaking.cs index 0118ed6513..630049f408 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSnaking.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSnaking.cs @@ -30,7 +30,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Tests { [TestFixture] - public class TestSceneSliderSnaking : TestSceneOsuPlayer + public partial class TestSceneSliderSnaking : TestSceneOsuPlayer { [Resolved] private AudioManager audioManager { get; set; } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSmoke.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSmoke.cs index 1cb64b71fc..d5d3cbb146 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSmoke.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSmoke.cs @@ -14,7 +14,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Tests { - public class TestSceneSmoke : OsuSkinnableTestScene + public partial class TestSceneSmoke : OsuSkinnableTestScene { [Test] public void TestSmoking() @@ -66,7 +66,7 @@ namespace osu.Game.Rulesets.Osu.Tests }); } - private class SmokingInputManager : ManualInputManager + private partial class SmokingInputManager : ManualInputManager { public double Duration { get; init; } @@ -102,7 +102,7 @@ namespace osu.Game.Rulesets.Osu.Tests } } - private class TestSmokeContainer : SmokeContainer + private partial class TestSmokeContainer : SmokeContainer { public double Duration { get; init; } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs index 8dc8f82b86..74d0fb42a3 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs @@ -20,7 +20,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Tests { [TestFixture] - public class TestSceneSpinner : OsuSkinnableTestScene + public partial class TestSceneSpinner : OsuSkinnableTestScene { private int depthIndex; @@ -93,7 +93,7 @@ namespace osu.Game.Rulesets.Osu.Tests return drawableSpinner; } - private class TestDrawableSpinner : DrawableSpinner + private partial class TestDrawableSpinner : DrawableSpinner { private readonly bool auto; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerApplication.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerApplication.cs index 14fa77245a..1ae17432be 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerApplication.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerApplication.cs @@ -14,7 +14,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Tests { - public class TestSceneSpinnerApplication : OsuTestScene + public partial class TestSceneSpinnerApplication : OsuTestScene { [Test] public void TestApplyNewSpinner() diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerHidden.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerHidden.cs index b7bc36722a..1aaba23e56 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerHidden.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerHidden.cs @@ -9,7 +9,7 @@ using osu.Game.Rulesets.Osu.Mods; namespace osu.Game.Rulesets.Osu.Tests { [TestFixture] - public class TestSceneSpinnerHidden : TestSceneSpinner + public partial class TestSceneSpinnerHidden : TestSceneSpinner { [SetUp] public void SetUp() => Schedule(() => diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs index 13ea46eadf..116c974f32 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs @@ -26,7 +26,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Tests { - public class TestSceneSpinnerRotation : TestSceneOsuPlayer + public partial class TestSceneSpinnerRotation : TestSceneOsuPlayer { private const double spinner_start_time = 100; private const double spinner_duration = 6000; @@ -221,7 +221,7 @@ namespace osu.Game.Rulesets.Osu.Tests } }; - private class ScoreExposedPlayer : TestPlayer + private partial class ScoreExposedPlayer : TestPlayer { public new ScoreProcessor ScoreProcessor => base.ScoreProcessor; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneStartTimeOrderedHitPolicy.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneStartTimeOrderedHitPolicy.cs index 96b26403e1..29e6fc4301 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneStartTimeOrderedHitPolicy.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneStartTimeOrderedHitPolicy.cs @@ -27,7 +27,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Tests { - public class TestSceneStartTimeOrderedHitPolicy : RateAdjustedBeatmapTestScene + public partial class TestSceneStartTimeOrderedHitPolicy : RateAdjustedBeatmapTestScene { private const double early_miss_window = 1000; // time after -1000 to -500 is considered a miss private const double late_miss_window = 500; // time after +500 is considered a miss @@ -434,7 +434,7 @@ namespace osu.Game.Rulesets.Osu.Tests protected override DifficultyRange[] GetRanges() => ranges; } - private class ScoreAccessibleReplayPlayer : ReplayPlayer + private partial class ScoreAccessibleReplayPlayer : ReplayPlayer { public new ScoreProcessor ScoreProcessor => base.ScoreProcessor; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneTrianglesSpinnerRotation.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneTrianglesSpinnerRotation.cs index 80e3af6cc0..1fef408088 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneTrianglesSpinnerRotation.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneTrianglesSpinnerRotation.cs @@ -28,7 +28,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Tests { - public class TestSceneTrianglesSpinnerRotation : TestSceneOsuPlayer + public partial class TestSceneTrianglesSpinnerRotation : TestSceneOsuPlayer { private const double spinner_start_time = 100; private const double spinner_duration = 6000; @@ -136,7 +136,7 @@ namespace osu.Game.Rulesets.Osu.Tests } }; - private class ScoreExposedPlayer : TestPlayer + private partial class ScoreExposedPlayer : TestPlayer { public new ScoreProcessor ScoreProcessor => base.ScoreProcessor; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/BlueprintPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/BlueprintPiece.cs index 55b7efc8af..41ab5a81b8 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/BlueprintPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/BlueprintPiece.cs @@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints /// A piece of a selection or placement blueprint which visualises an . /// /// The type of which this visualises. - public abstract class BlueprintPiece : CompositeDrawable + public abstract partial class BlueprintPiece : CompositeDrawable where T : OsuHitObject { /// diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCircleOverlapMarker.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCircleOverlapMarker.cs index f16b6c138e..e5cc8595d1 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCircleOverlapMarker.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCircleOverlapMarker.cs @@ -20,7 +20,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components { - public class HitCircleOverlapMarker : BlueprintPiece + public partial class HitCircleOverlapMarker : BlueprintPiece { /// /// Hit objects are intentionally made to fade out at a constant slower rate than in gameplay. diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs index 984fbb83a8..1fed19da03 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs @@ -12,7 +12,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components { - public class HitCirclePiece : BlueprintPiece + public partial class HitCirclePiece : BlueprintPiece { public HitCirclePiece() { diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCirclePlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCirclePlacementBlueprint.cs index ff4f61986f..26d18c7a17 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCirclePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCirclePlacementBlueprint.cs @@ -11,7 +11,7 @@ using osuTK.Input; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles { - public class HitCirclePlacementBlueprint : PlacementBlueprint + public partial class HitCirclePlacementBlueprint : PlacementBlueprint { public new HitCircle HitObject => (HitCircle)base.HitObject; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCircleSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCircleSelectionBlueprint.cs index 73756d9326..1b3e7f3a8f 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCircleSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCircleSelectionBlueprint.cs @@ -12,7 +12,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles { - public class HitCircleSelectionBlueprint : OsuSelectionBlueprint + public partial class HitCircleSelectionBlueprint : OsuSelectionBlueprint { protected new DrawableHitCircle DrawableObject => (DrawableHitCircle)base.DrawableObject; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs index 11527c9537..3e161089cd 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs @@ -13,7 +13,7 @@ using osu.Game.Screens.Edit; namespace osu.Game.Rulesets.Osu.Edit.Blueprints { - public abstract class OsuSelectionBlueprint : HitObjectSelectionBlueprint + public abstract partial class OsuSelectionBlueprint : HitObjectSelectionBlueprint where T : OsuHitObject { [Resolved] diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointConnectionPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointConnectionPiece.cs index 0b9ccc5c37..28e0d650c4 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointConnectionPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointConnectionPiece.cs @@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components /// /// A visualisation of the line between two s. /// - public class PathControlPointConnectionPiece : CompositeDrawable + public partial class PathControlPointConnectionPiece : CompositeDrawable { public readonly PathControlPoint ControlPoint; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs index 5dec5d1cb0..d83f35d13f 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs @@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components /// /// A visualisation of a single in a . /// - public class PathControlPointPiece : BlueprintPiece, IHasTooltip + public partial class PathControlPointPiece : BlueprintPiece, IHasTooltip { public Action RequestSelection; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index c7e3516d62..66d99e0bf1 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -29,7 +29,7 @@ using osuTK.Input; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { - public class PathControlPointVisualiser : CompositeDrawable, IKeyBindingHandler, IHasContextMenu + public partial class PathControlPointVisualiser : CompositeDrawable, IKeyBindingHandler, IHasContextMenu { public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true; // allow context menu to appear outside of the playfield. @@ -133,6 +133,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components switch (e.Action) { case NotifyCollectionChangedAction.Add: + Debug.Assert(e.NewItems != null); + // If inserting in the path (not appending), // update indices of existing connections after insert location if (e.NewStartingIndex < Pieces.Count) @@ -164,6 +166,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components break; case NotifyCollectionChangedAction.Remove: + Debug.Assert(e.OldItems != null); + foreach (var point in e.OldItems.Cast()) { foreach (var piece in Pieces.Where(p => p.ControlPoint == point).ToArray()) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs index da2a6ced67..ecd840dda6 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs @@ -13,7 +13,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { - public class SliderBodyPiece : BlueprintPiece + public partial class SliderBodyPiece : BlueprintPiece { private readonly ManualSliderBody body; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderCircleOverlay.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderCircleOverlay.cs index d48d43d532..3341a632c1 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderCircleOverlay.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderCircleOverlay.cs @@ -10,7 +10,7 @@ using osu.Game.Rulesets.Osu.Objects; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders { - public class SliderCircleOverlay : CompositeDrawable + public partial class SliderCircleOverlay : CompositeDrawable { protected readonly HitCirclePiece CirclePiece; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs index dd5335a743..f91d35e2e1 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs @@ -23,7 +23,7 @@ using osuTK.Input; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders { - public class SliderPlacementBlueprint : PlacementBlueprint + public partial class SliderPlacementBlueprint : PlacementBlueprint { public new Slider HitObject => (Slider)base.HitObject; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs index 3718f0c6bc..a51c223785 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs @@ -29,7 +29,7 @@ using osuTK.Input; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders { - public class SliderSelectionBlueprint : OsuSelectionBlueprint + public partial class SliderSelectionBlueprint : OsuSelectionBlueprint { protected new DrawableSlider DrawableObject => (DrawableSlider)base.DrawableObject; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/Components/SpinnerPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/Components/SpinnerPiece.cs index b5a13a22ce..cc58acdc80 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/Components/SpinnerPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/Components/SpinnerPiece.cs @@ -12,7 +12,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners.Components { - public class SpinnerPiece : BlueprintPiece + public partial class SpinnerPiece : BlueprintPiece { private readonly Circle circle; private readonly Circle ring; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs index 97d53d8e95..73ee5df9dc 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs @@ -4,6 +4,8 @@ #nullable disable using System; +using JetBrains.Annotations; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Input.Events; using osu.Game.Rulesets.Edit; @@ -14,7 +16,7 @@ using osuTK.Input; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners { - public class SpinnerPlacementBlueprint : PlacementBlueprint + public partial class SpinnerPlacementBlueprint : PlacementBlueprint { public new Spinner HitObject => (Spinner)base.HitObject; @@ -22,6 +24,10 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners private bool isPlacingEnd; + [Resolved(CanBeNull = true)] + [CanBeNull] + private IBeatSnapProvider beatSnapProvider { get; set; } + public SpinnerPlacementBlueprint() : base(new Spinner { Position = OsuPlayfield.BASE_SIZE / 2 }) { @@ -33,7 +39,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners base.Update(); if (isPlacingEnd) - HitObject.EndTime = Math.Max(HitObject.StartTime, EditorClock.CurrentTime); + updateEndTimeFromCurrent(); piece.UpdateFrom(HitObject); } @@ -45,7 +51,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners if (e.Button != MouseButton.Right) return false; - HitObject.EndTime = EditorClock.CurrentTime; + updateEndTimeFromCurrent(); EndPlacement(true); } else @@ -61,5 +67,12 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners return true; } + + private void updateEndTimeFromCurrent() + { + HitObject.EndTime = beatSnapProvider == null + ? Math.Max(HitObject.StartTime, EditorClock.CurrentTime) + : Math.Max(HitObject.StartTime + beatSnapProvider.GetBeatLengthAtTime(HitObject.StartTime), beatSnapProvider.SnapTime(EditorClock.CurrentTime)); + } } } diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerSelectionBlueprint.cs index 5240c0bfeb..a80ec68c10 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerSelectionBlueprint.cs @@ -9,7 +9,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners { - public class SpinnerSelectionBlueprint : OsuSelectionBlueprint + public partial class SpinnerSelectionBlueprint : OsuSelectionBlueprint { private readonly SpinnerPiece piece; diff --git a/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditorRuleset.cs b/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditorRuleset.cs index a5f7707cb3..14e7b93f3a 100644 --- a/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditorRuleset.cs +++ b/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditorRuleset.cs @@ -12,7 +12,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Edit { - public class DrawableOsuEditorRuleset : DrawableOsuRuleset + public partial class DrawableOsuEditorRuleset : DrawableOsuRuleset { public DrawableOsuEditorRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList mods) : base(ruleset, beatmap, mods) @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Osu.Edit public override PlayfieldAdjustmentContainer CreatePlayfieldAdjustmentContainer() => new OsuPlayfieldAdjustmentContainer { Size = Vector2.One }; - private class OsuEditorPlayfield : OsuPlayfield + private partial class OsuEditorPlayfield : OsuPlayfield { protected override GameplayCursorContainer CreateCursor() => null; diff --git a/osu.Game.Rulesets.Osu/Edit/OsuBlueprintContainer.cs b/osu.Game.Rulesets.Osu/Edit/OsuBlueprintContainer.cs index c0fb0ae7db..173a664902 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuBlueprintContainer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuBlueprintContainer.cs @@ -13,7 +13,7 @@ using osu.Game.Screens.Edit.Compose.Components; namespace osu.Game.Rulesets.Osu.Edit { - public class OsuBlueprintContainer : ComposeBlueprintContainer + public partial class OsuBlueprintContainer : ComposeBlueprintContainer { public OsuBlueprintContainer(HitObjectComposer composer) : base(composer) diff --git a/osu.Game.Rulesets.Osu/Edit/OsuDistanceSnapGrid.cs b/osu.Game.Rulesets.Osu/Edit/OsuDistanceSnapGrid.cs index 23bf67ff29..848c994974 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuDistanceSnapGrid.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuDistanceSnapGrid.cs @@ -10,7 +10,7 @@ using osu.Game.Screens.Edit.Compose.Components; namespace osu.Game.Rulesets.Osu.Edit { - public class OsuDistanceSnapGrid : CircularDistanceSnapGrid + public partial class OsuDistanceSnapGrid : CircularDistanceSnapGrid { public OsuDistanceSnapGrid(OsuHitObject hitObject, [CanBeNull] OsuHitObject nextHitObject = null) : base(hitObject, hitObject.StackedEndPosition, hitObject.GetEndTime(), nextHitObject?.StartTime - 1) diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index 1460fae4d7..09ddc420a7 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -30,7 +30,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Edit { - public class OsuHitObjectComposer : DistancedHitObjectComposer + public partial class OsuHitObjectComposer : DistancedHitObjectComposer { public OsuHitObjectComposer(Ruleset ruleset) : base(ruleset) diff --git a/osu.Game.Rulesets.Osu/Edit/OsuRectangularPositionSnapGrid.cs b/osu.Game.Rulesets.Osu/Edit/OsuRectangularPositionSnapGrid.cs index 35dad1a4fb..3234b03a3e 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuRectangularPositionSnapGrid.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuRectangularPositionSnapGrid.cs @@ -15,7 +15,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Edit { - public class OsuRectangularPositionSnapGrid : RectangularPositionSnapGrid, IKeyBindingHandler + public partial class OsuRectangularPositionSnapGrid : RectangularPositionSnapGrid, IKeyBindingHandler { private static readonly int[] grid_sizes = { 4, 8, 16, 32 }; diff --git a/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs b/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs index eddc1390f0..6d5280e528 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs @@ -22,7 +22,7 @@ using osuTK.Input; namespace osu.Game.Rulesets.Osu.Edit { - public class OsuSelectionHandler : EditorSelectionHandler + public partial class OsuSelectionHandler : EditorSelectionHandler { [Resolved(CanBeNull = true)] private IDistanceSnapProvider? snapProvider { get; set; } diff --git a/osu.Game.Rulesets.Osu/Edit/Setup/OsuSetupSection.cs b/osu.Game.Rulesets.Osu/Edit/Setup/OsuSetupSection.cs index 2889832ff1..ac567559b8 100644 --- a/osu.Game.Rulesets.Osu/Edit/Setup/OsuSetupSection.cs +++ b/osu.Game.Rulesets.Osu/Edit/Setup/OsuSetupSection.cs @@ -10,7 +10,7 @@ using osu.Game.Screens.Edit.Setup; namespace osu.Game.Rulesets.Osu.Edit.Setup { - public class OsuSetupSection : RulesetSetupSection + public partial class OsuSetupSection : RulesetSetupSection { private LabelledSliderBar stackLeniency; diff --git a/osu.Game.Rulesets.Osu/Mods/InputBlockingMod.cs b/osu.Game.Rulesets.Osu/Mods/InputBlockingMod.cs index e4e8905722..7db4e2625b 100644 --- a/osu.Game.Rulesets.Osu/Mods/InputBlockingMod.cs +++ b/osu.Game.Rulesets.Osu/Mods/InputBlockingMod.cs @@ -18,7 +18,7 @@ using osu.Game.Utils; namespace osu.Game.Rulesets.Osu.Mods { - public abstract class InputBlockingMod : Mod, IApplicableToDrawableRuleset, IUpdatableByPlayfield + public abstract partial class InputBlockingMod : Mod, IApplicableToDrawableRuleset, IUpdatableByPlayfield { public override double ScoreMultiplier => 1.0; public override Type[] IncompatibleMods => new[] { typeof(ModAutoplay), typeof(ModRelax), typeof(OsuModCinema) }; @@ -96,7 +96,7 @@ namespace osu.Game.Rulesets.Osu.Mods return false; } - private class InputInterceptor : Component, IKeyBindingHandler + private partial class InputInterceptor : Component, IKeyBindingHandler { private readonly InputBlockingMod mod; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs index 4c72667f15..2e2d320313 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs @@ -20,7 +20,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Mods { - public class OsuModBlinds : Mod, IApplicableToDrawableRuleset, IApplicableToHealthProcessor + public partial class OsuModBlinds : Mod, IApplicableToDrawableRuleset, IApplicableToHealthProcessor { public override string Name => "Blinds"; public override LocalisableString Description => "Play with blinds on your screen."; @@ -49,7 +49,7 @@ namespace osu.Game.Rulesets.Osu.Mods /// /// Element for the Blinds mod drawing 2 black boxes covering the whole screen which resize inside a restricted area with some leniency. /// - public class DrawableOsuBlinds : Container + public partial class DrawableOsuBlinds : Container { /// /// Black background boxes behind blind panel textures. @@ -204,7 +204,7 @@ namespace osu.Game.Rulesets.Osu.Mods /// public void AnimateClosedness(float value) => this.TransformTo(nameof(easing), value, 200, Easing.OutQuint); - public class ModBlindsPanel : Sprite + public partial class ModBlindsPanel : Sprite { [BackgroundDependencyLoader] private void load(TextureStore textures) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs index 1a86901d9c..efeac9a180 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs @@ -17,7 +17,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Mods { - public class OsuModFlashlight : ModFlashlight, IApplicableToDrawableHitObject + public partial class OsuModFlashlight : ModFlashlight, IApplicableToDrawableHitObject { public override double ScoreMultiplier => UsesDefaultConfiguration ? 1.12 : 1; public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(OsuModBlinds)).ToArray(); @@ -53,7 +53,7 @@ namespace osu.Game.Rulesets.Osu.Mods s.Tracking.ValueChanged += flashlight.OnSliderTrackingChange; } - private class OsuFlashlight : Flashlight, IRequireHighFrequencyMousePosition + private partial class OsuFlashlight : Flashlight, IRequireHighFrequencyMousePosition { private readonly double followDelay; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs index 5430929143..19d4a1bf83 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs @@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Osu.Mods { var osuObject = (OsuHitObject)hitObject; - OsuHitObjectGenerationUtils.ReflectVertically(osuObject); + OsuHitObjectGenerationUtils.ReflectVerticallyAlongPlayfield(osuObject); } } } diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModMirror.cs b/osu.Game.Rulesets.Osu/Mods/OsuModMirror.cs index 0a54d58718..6d01808fb5 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModMirror.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModMirror.cs @@ -27,16 +27,16 @@ namespace osu.Game.Rulesets.Osu.Mods switch (Reflection.Value) { case MirrorType.Horizontal: - OsuHitObjectGenerationUtils.ReflectHorizontally(osuObject); + OsuHitObjectGenerationUtils.ReflectHorizontallyAlongPlayfield(osuObject); break; case MirrorType.Vertical: - OsuHitObjectGenerationUtils.ReflectVertically(osuObject); + OsuHitObjectGenerationUtils.ReflectVerticallyAlongPlayfield(osuObject); break; case MirrorType.Both: - OsuHitObjectGenerationUtils.ReflectHorizontally(osuObject); - OsuHitObjectGenerationUtils.ReflectVertically(osuObject); + OsuHitObjectGenerationUtils.ReflectHorizontallyAlongPlayfield(osuObject); + OsuHitObjectGenerationUtils.ReflectVerticallyAlongPlayfield(osuObject); break; } } diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModRandom.cs b/osu.Game.Rulesets.Osu/Mods/OsuModRandom.cs index 1621bb50b1..307d731fd4 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModRandom.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModRandom.cs @@ -65,6 +65,11 @@ namespace osu.Game.Rulesets.Osu.Mods flowDirection = !flowDirection; } + if (positionInfos[i].HitObject is Slider slider && random.NextDouble() < 0.5) + { + OsuHitObjectGenerationUtils.FlipSliderInPlaceHorizontally(slider); + } + if (i == 0) { positionInfos[i].DistanceFromPrevious = (float)(random.NextDouble() * OsuPlayfield.BASE_SIZE.Y / 2); diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModStrictTracking.cs b/osu.Game.Rulesets.Osu/Mods/OsuModStrictTracking.cs index af37f1e2e5..7e4ffc7408 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModStrictTracking.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModStrictTracking.cs @@ -19,7 +19,7 @@ using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Osu.Mods { - public class OsuModStrictTracking : Mod, IApplicableAfterBeatmapConversion, IApplicableToDrawableHitObject, IApplicableToDrawableRuleset + public partial class OsuModStrictTracking : Mod, IApplicableAfterBeatmapConversion, IApplicableToDrawableHitObject, IApplicableToDrawableRuleset { public override string Name => @"Strict Tracking"; public override string Acronym => @"ST"; @@ -79,7 +79,7 @@ namespace osu.Game.Rulesets.Osu.Mods public override Judgement CreateJudgement() => new OsuJudgement(); } - private class StrictTrackingDrawableSliderTail : DrawableSliderTail + private partial class StrictTrackingDrawableSliderTail : DrawableSliderTail { public override bool DisplayResult => true; } diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTargetPractice.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTargetPractice.cs index 55c20eebe9..77cf340b95 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTargetPractice.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTargetPractice.cs @@ -17,7 +17,6 @@ using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Overlays.Settings; using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.Beatmaps; @@ -196,8 +195,8 @@ namespace osu.Game.Rulesets.Osu.Mods private IEnumerable generateBeats(IBeatmap beatmap, IReadOnlyCollection originalHitObjects) { - double startTime = originalHitObjects.First().StartTime; - double endTime = originalHitObjects.Last().GetEndTime(); + double startTime = beatmap.HitObjects.First().StartTime; + double endTime = beatmap.GetLastObjectTime(); var beats = beatmap.ControlPointInfo.TimingPoints // Ignore timing points after endTime diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs index 8c95da9be1..d588127cb9 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections /// /// A single follow point positioned between two adjacent s. /// - public class FollowPoint : PoolableDrawable, IAnimationTimeReference + public partial class FollowPoint : PoolableDrawable, IAnimationTimeReference { private const float width = 8; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointConnection.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointConnection.cs index 1a9d12e860..20c36b7804 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointConnection.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointConnection.cs @@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections /// /// Visualises the s between two s. /// - public class FollowPointConnection : PoolableDrawableWithLifetime + public partial class FollowPointConnection : PoolableDrawableWithLifetime { // Todo: These shouldn't be constants public const int SPACING = 32; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs index 306b034645..144eaffe82 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections /// /// Visualises connections between s. /// - public class FollowPointRenderer : PooledDrawableWithLifetimeContainer + public partial class FollowPointRenderer : PooledDrawableWithLifetimeContainer { public new IReadOnlyList Entries => lifetimeEntries; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index 6201199cc3..3458069dd1 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -24,7 +24,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Objects.Drawables { - public class DrawableHitCircle : DrawableOsuHitObject, IHasApproachCircle + public partial class DrawableHitCircle : DrawableOsuHitObject, IHasApproachCircle { public OsuAction? HitAction => HitArea.HitAction; protected virtual OsuSkinComponents CirclePieceComponent => OsuSkinComponents.HitCircle; @@ -231,7 +231,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected override JudgementResult CreateResult(Judgement judgement) => new OsuHitCircleJudgementResult(HitObject, judgement); - public class HitReceptor : CompositeDrawable, IKeyBindingHandler + public partial class HitReceptor : CompositeDrawable, IKeyBindingHandler { // IsHovered is used public override bool HandlePositionalInput => true; @@ -274,7 +274,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables } } - private class ProxyableSkinnableDrawable : SkinnableDrawable + private partial class ProxyableSkinnableDrawable : SkinnableDrawable { public override bool RemoveWhenNotAlive => false; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index d9d0d28477..df0ba344d8 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -17,7 +17,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Objects.Drawables { - public abstract class DrawableOsuHitObject : DrawableHitObject + public abstract partial class DrawableOsuHitObject : DrawableHitObject { public readonly IBindable PositionBindable = new Bindable(); public readonly IBindable StackHeightBindable = new Bindable(); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs index b4abdde911..b4004ff572 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs @@ -12,7 +12,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Objects.Drawables { - public class DrawableOsuJudgement : DrawableJudgement + public partial class DrawableOsuJudgement : DrawableJudgement { protected SkinnableLighting Lighting { get; private set; } @@ -67,7 +67,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected override Drawable CreateDefaultJudgement(HitResult result) => new OsuJudgementPiece(result); - private class OsuJudgementPiece : DefaultJudgementPiece + private partial class OsuJudgementPiece : DefaultJudgementPiece { public OsuJudgementPiece(HitResult result) : base(result) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index a4745b365b..4601af45d8 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -21,7 +21,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Objects.Drawables { - public class DrawableSlider : DrawableOsuHitObject + public partial class DrawableSlider : DrawableOsuHitObject { public new Slider HitObject => (Slider)base.HitObject; @@ -327,7 +327,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => SliderBody?.ReceivePositionalInputAt(screenSpacePos) ?? base.ReceivePositionalInputAt(screenSpacePos); - private class DefaultSliderBody : PlaySliderBody + private partial class DefaultSliderBody : PlaySliderBody { } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderBall.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderBall.cs index 35d5c1f478..e1766adc20 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderBall.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderBall.cs @@ -19,7 +19,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Objects.Drawables { - public class DrawableSliderBall : CircularContainer, ISliderProgress, IRequireHighFrequencyMousePosition + public partial class DrawableSliderBall : CircularContainer, ISliderProgress, IRequireHighFrequencyMousePosition { public const float FOLLOW_AREA = 2.4f; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs index d1d749d7e2..b8a1efabe0 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs @@ -12,7 +12,7 @@ using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Osu.Objects.Drawables { - public class DrawableSliderHead : DrawableHitCircle + public partial class DrawableSliderHead : DrawableHitCircle { public new SliderHeadCircle HitObject => (SliderHeadCircle)base.HitObject; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs index 08602e168c..3446d41fb4 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs @@ -17,7 +17,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Objects.Drawables { - public class DrawableSliderRepeat : DrawableOsuHitObject, ITrackSnaking + public partial class DrawableSliderRepeat : DrawableOsuHitObject, ITrackSnaking { public new SliderRepeat HitObject => (SliderRepeat)base.HitObject; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs index a59cd92d62..2c1b68e05a 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs @@ -15,7 +15,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Objects.Drawables { - public class DrawableSliderTail : DrawableOsuHitObject, IRequireTracking + public partial class DrawableSliderTail : DrawableOsuHitObject, IRequireTracking { public new SliderTailCircle HitObject => (SliderTailCircle)base.HitObject; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs index 563c7e85aa..6d0ae93e62 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs @@ -14,7 +14,7 @@ using osu.Framework.Graphics.Containers; namespace osu.Game.Rulesets.Osu.Objects.Drawables { - public class DrawableSliderTick : DrawableOsuHitObject, IRequireTracking + public partial class DrawableSliderTick : DrawableOsuHitObject, IRequireTracking { public const double ANIM_DURATION = 150; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index 83a9408570..eed5c3e2e3 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -24,7 +24,7 @@ using osu.Game.Skinning; namespace osu.Game.Rulesets.Osu.Objects.Drawables { - public class DrawableSpinner : DrawableOsuHitObject + public partial class DrawableSpinner : DrawableOsuHitObject { public new Spinner HitObject => (Spinner)base.HitObject; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerBonusTick.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerBonusTick.cs index 841f74b751..f1f4ec983e 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerBonusTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerBonusTick.cs @@ -5,7 +5,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { - public class DrawableSpinnerBonusTick : DrawableSpinnerTick + public partial class DrawableSpinnerBonusTick : DrawableSpinnerTick { public DrawableSpinnerBonusTick() : base(null) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerTick.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerTick.cs index 4975ca1248..b9ce07363c 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerTick.cs @@ -7,7 +7,7 @@ using osu.Framework.Graphics; namespace osu.Game.Rulesets.Osu.Objects.Drawables { - public class DrawableSpinnerTick : DrawableOsuHitObject + public partial class DrawableSpinnerTick : DrawableOsuHitObject { public override bool DisplayResult => false; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/SkinnableLighting.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/SkinnableLighting.cs index 4af4767a3e..68b61f9b2b 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/SkinnableLighting.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/SkinnableLighting.cs @@ -10,7 +10,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Objects.Drawables { - public class SkinnableLighting : SkinnableSprite + public partial class SkinnableLighting : SkinnableSprite { private DrawableHitObject targetObject; private JudgementResult targetResult; diff --git a/osu.Game.Rulesets.Osu/OsuInputManager.cs b/osu.Game.Rulesets.Osu/OsuInputManager.cs index 1e59e19246..7dede9e283 100644 --- a/osu.Game.Rulesets.Osu/OsuInputManager.cs +++ b/osu.Game.Rulesets.Osu/OsuInputManager.cs @@ -15,7 +15,7 @@ using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Osu { - public class OsuInputManager : RulesetInputManager + public partial class OsuInputManager : RulesetInputManager { public IEnumerable PressedActions => KeyBindingContainer.PressedActions; @@ -65,7 +65,7 @@ namespace osu.Game.Rulesets.Osu return base.HandleMouseTouchStateChange(e); } - private class OsuKeyBindingContainer : RulesetKeyBindingContainer + private partial class OsuKeyBindingContainer : RulesetKeyBindingContainer { private bool allowGameplayInputs = true; diff --git a/osu.Game.Rulesets.Osu/Replays/OsuAutoGeneratorBase.cs b/osu.Game.Rulesets.Osu/Replays/OsuAutoGeneratorBase.cs index 1cb3208c30..74e16f7e0b 100644 --- a/osu.Game.Rulesets.Osu/Replays/OsuAutoGeneratorBase.cs +++ b/osu.Game.Rulesets.Osu/Replays/OsuAutoGeneratorBase.cs @@ -82,10 +82,10 @@ namespace osu.Game.Rulesets.Osu.Replays private class ReplayFrameComparer : IComparer { - public int Compare(ReplayFrame f1, ReplayFrame f2) + public int Compare(ReplayFrame? f1, ReplayFrame? f2) { - if (f1 == null) throw new ArgumentNullException(nameof(f1)); - if (f2 == null) throw new ArgumentNullException(nameof(f2)); + ArgumentNullException.ThrowIfNull(f1); + ArgumentNullException.ThrowIfNull(f2); return f1.Time.CompareTo(f2.Time); } diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs index 34a1bd40e9..50d4eb6258 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs @@ -11,7 +11,7 @@ using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Osu.Scoring { - public class OsuScoreProcessor : ScoreProcessor + public partial class OsuScoreProcessor : ScoreProcessor { public OsuScoreProcessor() : base(new OsuRuleset()) diff --git a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonCursor.cs b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonCursor.cs index 446f3c83ae..4ca6abfdf7 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonCursor.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonCursor.cs @@ -13,7 +13,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Skinning.Argon { - public class ArgonCursor : OsuCursorSprite + public partial class ArgonCursor : OsuCursorSprite { public ArgonCursor() { diff --git a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonCursorTrail.cs b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonCursorTrail.cs index 9bb3122a3b..28991b4a62 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonCursorTrail.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonCursorTrail.cs @@ -9,7 +9,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Skinning.Argon { - public class ArgonCursorTrail : CursorTrail + public partial class ArgonCursorTrail : CursorTrail { protected override float IntervalMultiplier => 0.4f; diff --git a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonFollowCircle.cs b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonFollowCircle.cs index 83c5f6295a..fca3e70236 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonFollowCircle.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonFollowCircle.cs @@ -1,35 +1,64 @@ // Copyright (c) ppy Pty Ltd . 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.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Utils; +using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables; +using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Skinning.Argon { - public class ArgonFollowCircle : FollowCircle + public partial class ArgonFollowCircle : FollowCircle { + private readonly CircularContainer circleContainer; + private readonly Box circleFill; + + private readonly IBindable accentColour = new Bindable(); + + [Resolved(canBeNull: true)] + private DrawableHitObject? parentObject { get; set; } + public ArgonFollowCircle() { - InternalChild = new CircularContainer + InternalChild = circleContainer = new CircularContainer { RelativeSizeAxes = Axes.Both, Masking = true, BorderThickness = 4, - BorderColour = ColourInfo.GradientVertical(Colour4.FromHex("FC618F"), Colour4.FromHex("BB1A41")), Blending = BlendingParameters.Additive, - Child = new Box + Child = circleFill = new Box { - Colour = ColourInfo.GradientVertical(Colour4.FromHex("FC618F"), Colour4.FromHex("BB1A41")), RelativeSizeAxes = Axes.Both, Alpha = 0.3f, } }; } + [BackgroundDependencyLoader] + private void load() + { + if (parentObject != null) + accentColour.BindTo(parentObject.AccentColour); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + accentColour.BindValueChanged(colour => + { + circleContainer.BorderColour = ColourInfo.GradientVertical(colour.NewValue, colour.NewValue.Darken(0.5f)); + circleFill.Colour = ColourInfo.GradientVertical(colour.NewValue, colour.NewValue.Darken(0.5f)); + }, true); + } + protected override void OnSliderPress() { const float duration = 300f; diff --git a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonFollowPoint.cs b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonFollowPoint.cs index 47dae3c30a..2f44264040 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonFollowPoint.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonFollowPoint.cs @@ -10,7 +10,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Skinning.Argon { - public class ArgonFollowPoint : CompositeDrawable + public partial class ArgonFollowPoint : CompositeDrawable { public ArgonFollowPoint() { diff --git a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonJudgementPiece.cs b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonJudgementPiece.cs index bb68c7298f..6f55d93eff 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonJudgementPiece.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonJudgementPiece.cs @@ -3,7 +3,6 @@ using System; using osu.Framework.Allocation; -using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; @@ -17,42 +16,24 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Skinning.Argon { - public class ArgonJudgementPiece : CompositeDrawable, IAnimatableJudgement + public partial class ArgonJudgementPiece : JudgementPiece, IAnimatableJudgement { - protected readonly HitResult Result; - - protected SpriteText JudgementText { get; private set; } = null!; - private RingExplosion? ringExplosion; [Resolved] private OsuColour colours { get; set; } = null!; public ArgonJudgementPiece(HitResult result) + : base(result) { - Result = result; + AutoSizeAxes = Axes.Both; + Origin = Anchor.Centre; } [BackgroundDependencyLoader] private void load() { - AutoSizeAxes = Axes.Both; - - InternalChildren = new Drawable[] - { - JudgementText = new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Text = Result.GetDescription().ToUpperInvariant(), - Colour = colours.ForHitResult(Result), - Blending = BlendingParameters.Additive, - Spacing = new Vector2(5, 0), - Font = OsuFont.Default.With(size: 20, weight: FontWeight.Bold), - }, - }; - if (Result.IsHit()) { AddInternal(ringExplosion = new RingExplosion(Result) @@ -62,6 +43,16 @@ namespace osu.Game.Rulesets.Osu.Skinning.Argon } } + protected override SpriteText CreateJudgementText() => + new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Blending = BlendingParameters.Additive, + Spacing = new Vector2(5, 0), + Font = OsuFont.Default.With(size: 20, weight: FontWeight.Bold), + }; + /// /// Plays the default animation for this judgement piece. /// @@ -99,7 +90,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Argon public Drawable? GetAboveHitObjectsProxiedContent() => JudgementText.CreateProxy(); - private class RingExplosion : CompositeDrawable + private partial class RingExplosion : CompositeDrawable { private readonly float travel = 52; diff --git a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonMainCirclePiece.cs b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonMainCirclePiece.cs index 4ac71e4225..db458ec48a 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonMainCirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonMainCirclePiece.cs @@ -21,7 +21,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Skinning.Argon { - public class ArgonMainCirclePiece : CompositeDrawable + public partial class ArgonMainCirclePiece : CompositeDrawable { public const float BORDER_THICKNESS = (OsuHitObject.OBJECT_RADIUS * 2) * (2f / 58); @@ -198,7 +198,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Argon drawableObject.ApplyCustomUpdateState -= updateStateTransforms; } - private class FlashPiece : Circle + private partial class FlashPiece : Circle { public FlashPiece() { diff --git a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonReverseArrow.cs b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonReverseArrow.cs index 9d44db3614..f93e26b2ca 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonReverseArrow.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonReverseArrow.cs @@ -15,7 +15,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Skinning.Argon { - public class ArgonReverseArrow : CompositeDrawable + public partial class ArgonReverseArrow : CompositeDrawable { private Bindable accentColour = null!; diff --git a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSliderBall.cs b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSliderBall.cs index 3df9edd225..d6ce793c7e 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSliderBall.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSliderBall.cs @@ -2,6 +2,8 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; @@ -14,13 +16,15 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Skinning.Argon { - public class ArgonSliderBall : CircularContainer + public partial class ArgonSliderBall : CircularContainer { private readonly Box fill; private readonly SpriteIcon icon; private readonly Vector2 defaultIconScale = new Vector2(0.6f, 0.8f); + private readonly IBindable accentColour = new Bindable(); + [Resolved(canBeNull: true)] private DrawableHitObject? parentObject { get; set; } @@ -37,7 +41,6 @@ namespace osu.Game.Rulesets.Osu.Skinning.Argon { fill = new Box { - Colour = ColourInfo.GradientVertical(Colour4.FromHex("FC618F"), Colour4.FromHex("BB1A41")), RelativeSizeAxes = Axes.Both, Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -53,10 +56,22 @@ namespace osu.Game.Rulesets.Osu.Skinning.Argon }; } + [BackgroundDependencyLoader] + private void load() + { + if (parentObject != null) + accentColour.BindTo(parentObject.AccentColour); + } + protected override void LoadComplete() { base.LoadComplete(); + accentColour.BindValueChanged(colour => + { + fill.Colour = ColourInfo.GradientVertical(colour.NewValue, colour.NewValue.Darken(0.5f)); + }, true); + if (parentObject != null) { parentObject.ApplyCustomUpdateState += updateStateTransforms; diff --git a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSliderBody.cs b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSliderBody.cs index e1642d126d..c3d08116ac 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSliderBody.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSliderBody.cs @@ -7,7 +7,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Skinning.Argon { - public class ArgonSliderBody : PlaySliderBody + public partial class ArgonSliderBody : PlaySliderBody { protected override void LoadComplete() { @@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Argon protected override Default.DrawableSliderPath CreateSliderPath() => new DrawableSliderPath(); - private class DrawableSliderPath : Default.DrawableSliderPath + private partial class DrawableSliderPath : Default.DrawableSliderPath { protected override Color4 ColourAt(float position) { diff --git a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSliderScorePoint.cs b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSliderScorePoint.cs index 4c6b9a2f17..7479c2aced 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSliderScorePoint.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSliderScorePoint.cs @@ -12,7 +12,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Skinning.Argon { - public class ArgonSliderScorePoint : CircularContainer + public partial class ArgonSliderScorePoint : CircularContainer { private Bindable accentColour = null!; diff --git a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinner.cs b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinner.cs index 95438e9588..d5a9cf46c5 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinner.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinner.cs @@ -15,7 +15,7 @@ using osu.Game.Rulesets.Osu.Objects.Drawables; namespace osu.Game.Rulesets.Osu.Skinning.Argon { - public class ArgonSpinner : CompositeDrawable + public partial class ArgonSpinner : CompositeDrawable { private DrawableSpinner drawableSpinner = null!; diff --git a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinnerDisc.cs b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinnerDisc.cs index f99d4275bd..bdc93eb63f 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinnerDisc.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinnerDisc.cs @@ -18,7 +18,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Skinning.Argon { - public class ArgonSpinnerDisc : CompositeDrawable + public partial class ArgonSpinnerDisc : CompositeDrawable { private const float initial_scale = 1f; private const float idle_alpha = 0.2f; diff --git a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinnerProgressArc.cs b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinnerProgressArc.cs index e998f55755..31cdc0dc0f 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinnerProgressArc.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinnerProgressArc.cs @@ -14,7 +14,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Skinning.Argon { - public class ArgonSpinnerProgressArc : CompositeDrawable + public partial class ArgonSpinnerProgressArc : CompositeDrawable { private const float arc_fill = 0.15f; private const float arc_radius = 0.12f; diff --git a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinnerRingArc.cs b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinnerRingArc.cs index 57fb57a09e..702c5c2675 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinnerRingArc.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinnerRingArc.cs @@ -12,7 +12,7 @@ using osu.Game.Rulesets.Osu.Objects.Drawables; namespace osu.Game.Rulesets.Osu.Skinning.Argon { - public class ArgonSpinnerRingArc : CompositeDrawable + public partial class ArgonSpinnerRingArc : CompositeDrawable { private const float arc_fill = 0.31f; private const float arc_fill_complete = 0.50f; diff --git a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinnerTicks.cs b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinnerTicks.cs index 0203432088..4f0e1256d4 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinnerTicks.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinnerTicks.cs @@ -12,7 +12,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Skinning.Argon { - public class ArgonSpinnerTicks : CompositeDrawable + public partial class ArgonSpinnerTicks : CompositeDrawable { [BackgroundDependencyLoader] private void load() diff --git a/osu.Game.Rulesets.Osu/Skinning/Argon/OsuArgonSkinTransformer.cs b/osu.Game.Rulesets.Osu/Skinning/Argon/OsuArgonSkinTransformer.cs index 86194d2c43..f98a47097d 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Argon/OsuArgonSkinTransformer.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Argon/OsuArgonSkinTransformer.cs @@ -19,6 +19,10 @@ namespace osu.Game.Rulesets.Osu.Skinning.Argon switch (lookup) { case GameplaySkinComponentLookup resultComponent: + // This should eventually be moved to a skin setting, when supported. + if (Skin is ArgonProSkin && resultComponent.Component >= HitResult.Great) + return Drawable.Empty(); + return new ArgonJudgementPiece(resultComponent.Component); case OsuSkinComponentLookup osuComponent: diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/CirclePiece.cs b/osu.Game.Rulesets.Osu/Skinning/Default/CirclePiece.cs index 4a679cda2c..f4761e0ea8 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/CirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/CirclePiece.cs @@ -13,7 +13,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Skinning.Default { - public class CirclePiece : CompositeDrawable + public partial class CirclePiece : CompositeDrawable { [Resolved] private DrawableHitObject drawableObject { get; set; } = null!; diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/DefaultApproachCircle.cs b/osu.Game.Rulesets.Osu/Skinning/Default/DefaultApproachCircle.cs index 3a67ad526e..b65f46c414 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/DefaultApproachCircle.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/DefaultApproachCircle.cs @@ -11,7 +11,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Skinning.Default { - public class DefaultApproachCircle : SkinnableSprite + public partial class DefaultApproachCircle : SkinnableSprite { private readonly IBindable accentColour = new Bindable(); diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/DefaultFollowCircle.cs b/osu.Game.Rulesets.Osu/Skinning/Default/DefaultFollowCircle.cs index aaace89cd5..3c41d473f4 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/DefaultFollowCircle.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/DefaultFollowCircle.cs @@ -10,7 +10,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Skinning.Default { - public class DefaultFollowCircle : FollowCircle + public partial class DefaultFollowCircle : FollowCircle { public DefaultFollowCircle() { diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSliderBall.cs b/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSliderBall.cs index 97bb4a3697..c911943bfb 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSliderBall.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSliderBall.cs @@ -15,7 +15,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Skinning.Default { - public class DefaultSliderBall : CompositeDrawable + public partial class DefaultSliderBall : CompositeDrawable { private Box box = null!; diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSmokeSegment.cs b/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSmokeSegment.cs index 27a2dc3960..47c4bcc52c 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSmokeSegment.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSmokeSegment.cs @@ -6,7 +6,7 @@ using osu.Framework.Graphics.Textures; namespace osu.Game.Rulesets.Osu.Skinning.Default { - public class DefaultSmokeSegment : SmokeSegment + public partial class DefaultSmokeSegment : SmokeSegment { [BackgroundDependencyLoader] private void load(TextureStore textures) diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSpinner.cs b/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSpinner.cs index a975030630..071fbe6add 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSpinner.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSpinner.cs @@ -15,7 +15,7 @@ using osu.Game.Rulesets.Osu.Objects.Drawables; namespace osu.Game.Rulesets.Osu.Skinning.Default { - public class DefaultSpinner : CompositeDrawable + public partial class DefaultSpinner : CompositeDrawable { private DrawableSpinner drawableSpinner = null!; diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSpinnerDisc.cs b/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSpinnerDisc.cs index b58daf7174..75f3247448 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSpinnerDisc.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSpinnerDisc.cs @@ -18,7 +18,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Skinning.Default { - public class DefaultSpinnerDisc : CompositeDrawable + public partial class DefaultSpinnerDisc : CompositeDrawable { private DrawableSpinner drawableSpinner = null!; diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/DrawableSliderPath.cs b/osu.Game.Rulesets.Osu/Skinning/Default/DrawableSliderPath.cs index 883524f334..6f41d33c3d 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/DrawableSliderPath.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/DrawableSliderPath.cs @@ -6,7 +6,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Skinning.Default { - public abstract class DrawableSliderPath : SmoothPath + public abstract partial class DrawableSliderPath : SmoothPath { public const float BORDER_PORTION = 0.128f; public const float GRADIENT_PORTION = 1 - BORDER_PORTION; diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/ExplodePiece.cs b/osu.Game.Rulesets.Osu/Skinning/Default/ExplodePiece.cs index f8010a9971..91bf75617a 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/ExplodePiece.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/ExplodePiece.cs @@ -11,7 +11,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Skinning.Default { - public class ExplodePiece : Container + public partial class ExplodePiece : Container { [Resolved] private DrawableHitObject drawableObject { get; set; } = null!; diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/FlashPiece.cs b/osu.Game.Rulesets.Osu/Skinning/Default/FlashPiece.cs index 06ee64d8b3..789137117e 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/FlashPiece.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/FlashPiece.cs @@ -9,7 +9,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Skinning.Default { - public class FlashPiece : Container + public partial class FlashPiece : Container { public FlashPiece() { diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/GlowPiece.cs b/osu.Game.Rulesets.Osu/Skinning/Default/GlowPiece.cs index f5e01b802e..65cbdc3d2f 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/GlowPiece.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/GlowPiece.cs @@ -9,7 +9,7 @@ using osu.Framework.Graphics.Textures; namespace osu.Game.Rulesets.Osu.Skinning.Default { - public class GlowPiece : Container + public partial class GlowPiece : Container { public GlowPiece() { diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/KiaiFlash.cs b/osu.Game.Rulesets.Osu/Skinning/Default/KiaiFlash.cs index 506f679836..11c2fd97e8 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/KiaiFlash.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/KiaiFlash.cs @@ -11,7 +11,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Skinning.Default { - public class KiaiFlash : BeatSyncedContainer + public partial class KiaiFlash : BeatSyncedContainer { private const double fade_length = 80; diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/MainCirclePiece.cs b/osu.Game.Rulesets.Osu/Skinning/Default/MainCirclePiece.cs index 6d56d21349..20fa4e5342 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/MainCirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/MainCirclePiece.cs @@ -14,7 +14,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Skinning.Default { - public class MainCirclePiece : CompositeDrawable + public partial class MainCirclePiece : CompositeDrawable { private readonly CirclePiece circle; private readonly RingPiece ring; diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/ManualSliderBody.cs b/osu.Game.Rulesets.Osu/Skinning/Default/ManualSliderBody.cs index d73c94eb9b..d171f56f40 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/ManualSliderBody.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/ManualSliderBody.cs @@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Default /// /// A with the ability to set the drawn vertices manually. /// - public class ManualSliderBody : SliderBody + public partial class ManualSliderBody : SliderBody { public new void SetVertices(IReadOnlyList vertices) { diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/NumberPiece.cs b/osu.Game.Rulesets.Osu/Skinning/Default/NumberPiece.cs index 60cfecfb5a..eb49b7b852 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/NumberPiece.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/NumberPiece.cs @@ -12,7 +12,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Skinning.Default { - public class NumberPiece : Container + public partial class NumberPiece : Container { private readonly SkinnableSpriteText number; diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/PlaySliderBody.cs b/osu.Game.Rulesets.Osu/Skinning/Default/PlaySliderBody.cs index 96af59abe2..539777dd6b 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/PlaySliderBody.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/PlaySliderBody.cs @@ -12,7 +12,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Skinning.Default { - public abstract class PlaySliderBody : SnakingSliderBody + public abstract partial class PlaySliderBody : SnakingSliderBody { protected IBindable ScaleBindable { get; private set; } = null!; diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/ReverseArrowPiece.cs b/osu.Game.Rulesets.Osu/Skinning/Default/ReverseArrowPiece.cs index 222e8d4348..3fe7872ff7 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/ReverseArrowPiece.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/ReverseArrowPiece.cs @@ -14,7 +14,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Skinning.Default { - public class ReverseArrowPiece : BeatSyncedContainer + public partial class ReverseArrowPiece : BeatSyncedContainer { [Resolved] private DrawableHitObject drawableRepeat { get; set; } = null!; diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/RingPiece.cs b/osu.Game.Rulesets.Osu/Skinning/Default/RingPiece.cs index e813a7e274..46d48f62e7 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/RingPiece.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/RingPiece.cs @@ -10,7 +10,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Skinning.Default { - public class RingPiece : CircularContainer + public partial class RingPiece : CircularContainer { public RingPiece(float thickness = 9) { diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerBackgroundLayer.cs b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerBackgroundLayer.cs index a1184a15cd..039c4825fa 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerBackgroundLayer.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerBackgroundLayer.cs @@ -6,7 +6,7 @@ using osu.Framework.Graphics; namespace osu.Game.Rulesets.Osu.Skinning.Default { - public class SpinnerBackgroundLayer : SpinnerFill + public partial class SpinnerBackgroundLayer : SpinnerFill { [BackgroundDependencyLoader] private void load() diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerCentreLayer.cs b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerCentreLayer.cs index 3dd5aed6ae..f5c90bafbf 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerCentreLayer.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerCentreLayer.cs @@ -15,7 +15,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Skinning.Default { - public class SpinnerCentreLayer : CompositeDrawable, IHasAccentColour + public partial class SpinnerCentreLayer : CompositeDrawable, IHasAccentColour { private DrawableSpinner spinner = null!; diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerFill.cs b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerFill.cs index f574ae589e..93f93b8521 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerFill.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerFill.cs @@ -10,7 +10,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Skinning.Default { - public class SpinnerFill : CircularContainer, IHasAccentColour + public partial class SpinnerFill : CircularContainer, IHasAccentColour { public readonly Box Disc; diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerRotationTracker.cs b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerRotationTracker.cs index 3a9f73404d..bf06f513b7 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerRotationTracker.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerRotationTracker.cs @@ -16,7 +16,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Skinning.Default { - public class SpinnerRotationTracker : CircularContainer + public partial class SpinnerRotationTracker : CircularContainer { public override bool IsPresent => true; // handle input when hidden diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerSpmCalculator.cs b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerSpmCalculator.cs index 9feaa0966a..0bd5fd4cac 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerSpmCalculator.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerSpmCalculator.cs @@ -12,7 +12,7 @@ using osu.Game.Rulesets.Objects.Drawables; namespace osu.Game.Rulesets.Osu.Skinning.Default { - public class SpinnerSpmCalculator : Component + public partial class SpinnerSpmCalculator : Component { private readonly Queue records = new Queue(); private const double spm_count_duration = 595; // not using hundreds to avoid frame rounding issues diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerTicks.cs b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerTicks.cs index e518ae1da8..f5f8d456f3 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerTicks.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerTicks.cs @@ -14,7 +14,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Skinning.Default { - public class SpinnerTicks : Container, IHasAccentColour + public partial class SpinnerTicks : Container, IHasAccentColour { public SpinnerTicks() { diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/TrianglesPiece.cs b/osu.Game.Rulesets.Osu/Skinning/Default/TrianglesPiece.cs index fa23c60d57..f1143cf14d 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/TrianglesPiece.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/TrianglesPiece.cs @@ -5,7 +5,7 @@ using osu.Game.Graphics.Backgrounds; namespace osu.Game.Rulesets.Osu.Skinning.Default { - public class TrianglesPiece : Triangles + public partial class TrianglesPiece : Triangles { protected override bool CreateNewTriangles => false; protected override float SpawnRatio => 0.5f; diff --git a/osu.Game.Rulesets.Osu/Skinning/FollowCircle.cs b/osu.Game.Rulesets.Osu/Skinning/FollowCircle.cs index 9eb8e66c83..355d3f9a2f 100644 --- a/osu.Game.Rulesets.Osu/Skinning/FollowCircle.cs +++ b/osu.Game.Rulesets.Osu/Skinning/FollowCircle.cs @@ -10,7 +10,7 @@ using osu.Game.Rulesets.Osu.Objects.Drawables; namespace osu.Game.Rulesets.Osu.Skinning { - public abstract class FollowCircle : CompositeDrawable + public abstract partial class FollowCircle : CompositeDrawable { [Resolved] protected DrawableHitObject? ParentObject { get; private set; } diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyApproachCircle.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyApproachCircle.cs index 4dd4f9562a..e9342bbdbb 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyApproachCircle.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyApproachCircle.cs @@ -11,7 +11,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Skinning.Legacy { - public class LegacyApproachCircle : SkinnableSprite + public partial class LegacyApproachCircle : SkinnableSprite { private readonly IBindable accentColour = new Bindable(); diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursor.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursor.cs index b2ffc171be..b0c01d2925 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursor.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursor.cs @@ -9,7 +9,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Skinning.Legacy { - public class LegacyCursor : OsuCursorSprite + public partial class LegacyCursor : OsuCursorSprite { private readonly ISkin skin; private bool spin; diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorParticles.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorParticles.cs index a28b480753..e022e5534d 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorParticles.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorParticles.cs @@ -23,7 +23,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Skinning.Legacy { - public class LegacyCursorParticles : CompositeDrawable, IKeyBindingHandler + public partial class LegacyCursorParticles : CompositeDrawable, IKeyBindingHandler { public bool Active => breakSpewer.Active.Value || kiaiSpewer.Active.Value; @@ -140,7 +140,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy breakSpewer.Direction = SpewDirection.None; } - private class LegacyCursorParticleSpewer : ParticleSpewer, IRequireHighFrequencyMousePosition + private partial class LegacyCursorParticleSpewer : ParticleSpewer, IRequireHighFrequencyMousePosition { private const int particle_duration_min = 300; private const int particle_duration_max = 1000; diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorTrail.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorTrail.cs index 9a59fd73b2..af71e2a5d9 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorTrail.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorTrail.cs @@ -13,7 +13,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Skinning.Legacy { - public class LegacyCursorTrail : CursorTrail + public partial class LegacyCursorTrail : CursorTrail { private readonly ISkin skin; private const double disjoint_trail_time_separation = 1000 / 60.0; diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyFollowCircle.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyFollowCircle.cs index 0d12fb01f5..f8dcb9e8a2 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyFollowCircle.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyFollowCircle.cs @@ -7,7 +7,7 @@ using osu.Framework.Graphics; namespace osu.Game.Rulesets.Osu.Skinning.Legacy { - public class LegacyFollowCircle : FollowCircle + public partial class LegacyFollowCircle : FollowCircle { public LegacyFollowCircle(Drawable animationContent) { diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyMainCirclePiece.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyMainCirclePiece.cs index e155c1b816..cadac4d319 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyMainCirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyMainCirclePiece.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.ObjectExtensions; @@ -18,7 +19,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Skinning.Legacy { - public class LegacyMainCirclePiece : CompositeDrawable + public partial class LegacyMainCirclePiece : CompositeDrawable { public override bool RemoveCompletedTransforms => false; @@ -29,8 +30,8 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy private readonly bool hasNumber; - protected Drawable CircleSprite = null!; - protected Drawable OverlaySprite = null!; + protected LegacyKiaiFlashingDrawable CircleSprite = null!; + protected LegacyKiaiFlashingDrawable OverlaySprite = null!; protected Container OverlayLayer { get; private set; } = null!; @@ -65,7 +66,6 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy // at this point, any further texture fetches should be correctly using the priority source if the base texture was retrieved using it. // the conditional above handles the case where a sliderendcircle.png is retrieved from the skin, but sliderendcircleoverlay.png doesn't exist. // expected behaviour in this scenario is not showing the overlay, rather than using hitcircleoverlay.png. - InternalChildren = new[] { CircleSprite = new LegacyKiaiFlashingDrawable(() => new Sprite { Texture = skin.GetTexture(circleName) }) @@ -114,7 +114,21 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy { base.LoadComplete(); - accentColour.BindValueChanged(colour => CircleSprite.Colour = LegacyColourCompatibility.DisallowZeroAlpha(colour.NewValue), true); + accentColour.BindValueChanged(colour => + { + Color4 objectColour = colour.NewValue; + int add = Math.Max(25, 300 - (int)(objectColour.R * 255) - (int)(objectColour.G * 255) - (int)(objectColour.B * 255)); + + var kiaiTintColour = new Color4( + (byte)Math.Min((byte)(objectColour.R * 255) + add, 255), + (byte)Math.Min((byte)(objectColour.G * 255) + add, 255), + (byte)Math.Min((byte)(objectColour.B * 255) + add, 255), + 255); + + CircleSprite.Colour = LegacyColourCompatibility.DisallowZeroAlpha(colour.NewValue); + OverlaySprite.KiaiGlowColour = CircleSprite.KiaiGlowColour = LegacyColourCompatibility.DisallowZeroAlpha(kiaiTintColour); + }, true); + if (hasNumber) indexInCurrentCombo.BindValueChanged(index => hitCircleText.Text = (index.NewValue + 1).ToString(), true); diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyNewStyleSpinner.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyNewStyleSpinner.cs index f950d3e43e..67a6d5e41a 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyNewStyleSpinner.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyNewStyleSpinner.cs @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy /// Legacy skinned spinner with two main spinning layers, one fixed overlay and one final spinning overlay. /// No background layer. /// - public class LegacyNewStyleSpinner : LegacySpinner + public partial class LegacyNewStyleSpinner : LegacySpinner { private Sprite glow = null!; private Sprite discBottom = null!; diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyOldStyleSpinner.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyOldStyleSpinner.cs index e5efb668bc..c57487cf75 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyOldStyleSpinner.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyOldStyleSpinner.cs @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy /// /// Legacy skinned spinner with one main spinning layer and a background layer. /// - public class LegacyOldStyleSpinner : LegacySpinner + public partial class LegacyOldStyleSpinner : LegacySpinner { private Sprite disc = null!; private Sprite metreSprite = null!; diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyReverseArrow.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyReverseArrow.cs index 773cc7ae3c..fbe094ef81 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyReverseArrow.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyReverseArrow.cs @@ -11,7 +11,7 @@ using osu.Game.Skinning; namespace osu.Game.Rulesets.Osu.Skinning.Legacy { - public class LegacyReverseArrow : CompositeDrawable + public partial class LegacyReverseArrow : CompositeDrawable { [Resolved(canBeNull: true)] private DrawableHitObject? drawableHitObject { get; set; } diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBall.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBall.cs index 60d71ae843..2aa843581e 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBall.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBall.cs @@ -13,7 +13,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Skinning.Legacy { - public class LegacySliderBall : CompositeDrawable + public partial class LegacySliderBall : CompositeDrawable { private readonly Drawable animationContent; diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs index 29a0745193..b39092a467 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs @@ -11,7 +11,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Skinning.Legacy { - public class LegacySliderBody : PlaySliderBody + public partial class LegacySliderBody : PlaySliderBody { protected override DrawableSliderPath CreateSliderPath() => new LegacyDrawableSliderPath(); @@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy return base.GetBodyAccentColour(skin, hitObjectAccentColour).Opacity(0.7f); } - private class LegacyDrawableSliderPath : DrawableSliderPath + private partial class LegacyDrawableSliderPath : DrawableSliderPath { private const float shadow_portion = 1 - (OsuLegacySkinTransformer.LEGACY_CIRCLE_RADIUS / OsuHitObject.OBJECT_RADIUS); diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderHeadHitCircle.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderHeadHitCircle.cs index 08b579697c..bc69e66fb3 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderHeadHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderHeadHitCircle.cs @@ -9,7 +9,7 @@ using osu.Game.Rulesets.Osu.Objects.Drawables; namespace osu.Game.Rulesets.Osu.Skinning.Legacy { - public class LegacySliderHeadHitCircle : LegacyMainCirclePiece + public partial class LegacySliderHeadHitCircle : LegacyMainCirclePiece { [Resolved(canBeNull: true)] private DrawableHitObject? drawableHitObject { get; set; } diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySmokeSegment.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySmokeSegment.cs index c9c7e86e86..0e93ef7ad5 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySmokeSegment.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySmokeSegment.cs @@ -6,7 +6,7 @@ using osu.Game.Skinning; namespace osu.Game.Rulesets.Osu.Skinning.Legacy { - public class LegacySmokeSegment : SmokeSegment + public partial class LegacySmokeSegment : SmokeSegment { [BackgroundDependencyLoader] private void load(ISkinSource skin) diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySpinner.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySpinner.cs index 66b195962b..d8f837ae5e 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySpinner.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySpinner.cs @@ -16,7 +16,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Skinning.Legacy { - public abstract class LegacySpinner : CompositeDrawable, IHasApproachCircle + public abstract partial class LegacySpinner : CompositeDrawable, IHasApproachCircle { public const float SPRITE_SCALE = 0.625f; diff --git a/osu.Game.Rulesets.Osu/Skinning/NonPlayfieldSprite.cs b/osu.Game.Rulesets.Osu/Skinning/NonPlayfieldSprite.cs index 2a13f07cdb..548a14f5eb 100644 --- a/osu.Game.Rulesets.Osu/Skinning/NonPlayfieldSprite.cs +++ b/osu.Game.Rulesets.Osu/Skinning/NonPlayfieldSprite.cs @@ -11,7 +11,7 @@ namespace osu.Game.Rulesets.Osu.Skinning /// A sprite which is displayed within the playfield, but historically was not considered part of the playfield. /// Performs scale adjustment to undo the scale applied by (osu! ruleset specifically). /// - public class NonPlayfieldSprite : Sprite + public partial class NonPlayfieldSprite : Sprite { public override Texture? Texture { diff --git a/osu.Game.Rulesets.Osu/Skinning/SliderBody.cs b/osu.Game.Rulesets.Osu/Skinning/SliderBody.cs index 1411b27c09..283687adfd 100644 --- a/osu.Game.Rulesets.Osu/Skinning/SliderBody.cs +++ b/osu.Game.Rulesets.Osu/Skinning/SliderBody.cs @@ -14,7 +14,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Skinning { - public abstract class SliderBody : CompositeDrawable + public abstract partial class SliderBody : CompositeDrawable { private DrawableSliderPath path; @@ -107,7 +107,7 @@ namespace osu.Game.Rulesets.Osu.Skinning protected virtual DrawableSliderPath CreateSliderPath() => new DefaultDrawableSliderPath(); - private class DefaultDrawableSliderPath : DrawableSliderPath + private partial class DefaultDrawableSliderPath : DrawableSliderPath { private const float opacity_at_centre = 0.3f; private const float opacity_at_edge = 0.8f; diff --git a/osu.Game.Rulesets.Osu/Skinning/SmokeSegment.cs b/osu.Game.Rulesets.Osu/Skinning/SmokeSegment.cs index 66d74ae13e..a824f202ec 100644 --- a/osu.Game.Rulesets.Osu/Skinning/SmokeSegment.cs +++ b/osu.Game.Rulesets.Osu/Skinning/SmokeSegment.cs @@ -21,7 +21,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Skinning { - public abstract class SmokeSegment : Drawable, ITexturedShaderDrawable + public abstract partial class SmokeSegment : Drawable, ITexturedShaderDrawable { // fade anim values private const double initial_fade_out_duration = 4000; diff --git a/osu.Game.Rulesets.Osu/Skinning/SnakingSliderBody.cs b/osu.Game.Rulesets.Osu/Skinning/SnakingSliderBody.cs index 8ba9e75d19..f8ee465cd6 100644 --- a/osu.Game.Rulesets.Osu/Skinning/SnakingSliderBody.cs +++ b/osu.Game.Rulesets.Osu/Skinning/SnakingSliderBody.cs @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Osu.Skinning /// /// A which changes its curve depending on the snaking progress. /// - public abstract class SnakingSliderBody : SliderBody, ISliderProgress + public abstract partial class SnakingSliderBody : SliderBody, ISliderProgress { public readonly List CurrentCurve = new List(); diff --git a/osu.Game.Rulesets.Osu/Statistics/AccuracyHeatmap.cs b/osu.Game.Rulesets.Osu/Statistics/AccuracyHeatmap.cs index acf32da73f..0249b6d9b1 100644 --- a/osu.Game.Rulesets.Osu/Statistics/AccuracyHeatmap.cs +++ b/osu.Game.Rulesets.Osu/Statistics/AccuracyHeatmap.cs @@ -20,7 +20,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Statistics { - public class AccuracyHeatmap : CompositeDrawable + public partial class AccuracyHeatmap : CompositeDrawable { /// /// Size of the inner circle containing the "hit" points, relative to the size of this . @@ -233,7 +233,7 @@ namespace osu.Game.Rulesets.Osu.Statistics bufferedGrid.ForceRedraw(); } - private class HitPoint : Circle + private partial class HitPoint : Circle { /// /// The base colour which will be lightened/darkened depending on the value of this . diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs index 1b2ef23674..9ecabd1d5e 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs @@ -24,7 +24,7 @@ using osuTK.Graphics.ES30; namespace osu.Game.Rulesets.Osu.UI.Cursor { - public class CursorTrail : Drawable, IRequireHighFrequencyMousePosition + public partial class CursorTrail : Drawable, IRequireHighFrequencyMousePosition { private const int max_sprites = 2048; diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs index 6d435f01b0..66c86ee09d 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs @@ -16,7 +16,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.UI.Cursor { - public class OsuCursor : SkinReloadableDrawable + public partial class OsuCursor : SkinReloadableDrawable { private const float size = 28; @@ -66,7 +66,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor public void Contract() => expandTarget.ScaleTo(released_scale, 400, Easing.OutQuad); - private class DefaultCursor : OsuCursorSprite + private partial class DefaultCursor : OsuCursorSprite { public DefaultCursor() { diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs index 26fe08972e..5d7648b073 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs @@ -21,7 +21,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.UI.Cursor { - public class OsuCursorContainer : GameplayCursorContainer, IKeyBindingHandler + public partial class OsuCursorContainer : GameplayCursorContainer, IKeyBindingHandler { protected override Drawable CreateCursor() => new OsuCursor(); @@ -165,7 +165,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor ActiveCursor.ScaleTo(CursorScale.Value * 0.8f, 450, Easing.OutQuint); } - private class DefaultCursorTrail : CursorTrail + private partial class DefaultCursorTrail : CursorTrail { [BackgroundDependencyLoader] private void load(TextureStore textures) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorSprite.cs b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorSprite.cs index 03ef79a262..aaf8949084 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorSprite.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorSprite.cs @@ -8,7 +8,7 @@ using osu.Framework.Graphics.Containers; namespace osu.Game.Rulesets.Osu.UI.Cursor { - public abstract class OsuCursorSprite : CompositeDrawable + public abstract partial class OsuCursorSprite : CompositeDrawable { /// /// The an optional piece of the cursor to expand when in a clicked state. diff --git a/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs b/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs index 5f430dc921..d1fa0d09cc 100644 --- a/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs @@ -22,7 +22,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.UI { - public class DrawableOsuRuleset : DrawableRuleset + public partial class DrawableOsuRuleset : DrawableRuleset { protected new OsuRulesetConfigManager Config => (OsuRulesetConfigManager)base.Config; diff --git a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs index e9a6c84c0b..ed02284a4b 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs @@ -29,7 +29,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.UI { [Cached] - public class OsuPlayfield : Playfield + public partial class OsuPlayfield : Playfield { private readonly PlayfieldBorder playfieldBorder; private readonly ProxyContainer approachCircles; @@ -67,7 +67,7 @@ namespace osu.Game.Rulesets.Osu.UI HitPolicy = new StartTimeOrderedHitPolicy(); var hitWindows = new OsuHitWindows(); - foreach (var result in Enum.GetValues(typeof(HitResult)).OfType().Where(r => r > HitResult.None && hitWindows.IsHitResultAllowed(r))) + foreach (var result in Enum.GetValues().Where(r => r > HitResult.None && hitWindows.IsHitResultAllowed(r))) poolDictionary.Add(result, new DrawableJudgementPool(result, onJudgementLoaded)); AddRangeInternal(poolDictionary.Values); @@ -181,12 +181,12 @@ namespace osu.Game.Rulesets.Osu.UI public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => HitObjectContainer.ReceivePositionalInputAt(screenSpacePos); - private class ProxyContainer : LifetimeManagementContainer + private partial class ProxyContainer : LifetimeManagementContainer { public void Add(Drawable proxy) => AddInternal(proxy); } - private class DrawableJudgementPool : DrawablePool + private partial class DrawableJudgementPool : DrawablePool { private readonly HitResult result; private readonly Action onLoaded; diff --git a/osu.Game.Rulesets.Osu/UI/OsuPlayfieldAdjustmentContainer.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfieldAdjustmentContainer.cs index 80f4eb3000..b45d552c7f 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuPlayfieldAdjustmentContainer.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfieldAdjustmentContainer.cs @@ -10,7 +10,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.UI { - public class OsuPlayfieldAdjustmentContainer : PlayfieldAdjustmentContainer + public partial class OsuPlayfieldAdjustmentContainer : PlayfieldAdjustmentContainer { protected override Container Content => content; private readonly ScalingContainer content; @@ -48,7 +48,7 @@ namespace osu.Game.Rulesets.Osu.UI /// /// A which scales its content relative to a target width. /// - private class ScalingContainer : Container + private partial class ScalingContainer : Container { internal bool PlayfieldShift { get; set; } diff --git a/osu.Game.Rulesets.Osu/UI/OsuReplayRecorder.cs b/osu.Game.Rulesets.Osu/UI/OsuReplayRecorder.cs index 5964a9b9b6..66a4f467a9 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuReplayRecorder.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuReplayRecorder.cs @@ -12,7 +12,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.UI { - public class OsuReplayRecorder : ReplayRecorder + public partial class OsuReplayRecorder : ReplayRecorder { public OsuReplayRecorder(Score score) : base(score) diff --git a/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs b/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs index 412505331b..e951197643 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs @@ -19,7 +19,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.UI { - public class OsuResumeOverlay : ResumeOverlay + public partial class OsuResumeOverlay : ResumeOverlay { private Container cursorScaleContainer; private OsuClickToResumeCursor clickToResumeCursor; @@ -69,7 +69,7 @@ namespace osu.Game.Rulesets.Osu.UI protected override bool OnHover(HoverEvent e) => true; - public class OsuClickToResumeCursor : OsuCursor, IKeyBindingHandler + public partial class OsuClickToResumeCursor : OsuCursor, IKeyBindingHandler { public override bool HandlePositionalInput => true; diff --git a/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs b/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs index eff4b30362..64c4e7eef6 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs @@ -1,18 +1,17 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; +using osu.Game.Localisation; using osu.Game.Overlays.Settings; using osu.Game.Rulesets.Osu.Configuration; using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Osu.UI { - public class OsuSettingsSubsection : RulesetSettingsSubsection + public partial class OsuSettingsSubsection : RulesetSettingsSubsection { protected override LocalisableString Header => "osu!"; @@ -30,23 +29,23 @@ namespace osu.Game.Rulesets.Osu.UI { new SettingsCheckbox { - LabelText = "Snaking in sliders", + LabelText = RulesetSettingsStrings.SnakingInSliders, Current = config.GetBindable(OsuRulesetSetting.SnakingInSliders) }, new SettingsCheckbox { ClassicDefault = false, - LabelText = "Snaking out sliders", + LabelText = RulesetSettingsStrings.SnakingOutSliders, Current = config.GetBindable(OsuRulesetSetting.SnakingOutSliders) }, new SettingsCheckbox { - LabelText = "Cursor trail", + LabelText = RulesetSettingsStrings.CursorTrail, Current = config.GetBindable(OsuRulesetSetting.ShowCursorTrail) }, new SettingsEnumDropdown { - LabelText = "Playfield border style", + LabelText = RulesetSettingsStrings.PlayfieldBorderStyle, Current = config.GetBindable(OsuRulesetSetting.PlayfieldBorderStyle), }, }; diff --git a/osu.Game.Rulesets.Osu/UI/SmokeContainer.cs b/osu.Game.Rulesets.Osu/UI/SmokeContainer.cs index bf5618dc90..389440ba2d 100644 --- a/osu.Game.Rulesets.Osu/UI/SmokeContainer.cs +++ b/osu.Game.Rulesets.Osu/UI/SmokeContainer.cs @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Osu.UI /// /// Manages smoke trails generated from user input. /// - public class SmokeContainer : Container, IRequireHighFrequencyMousePosition, IKeyBindingHandler + public partial class SmokeContainer : Container, IRequireHighFrequencyMousePosition, IKeyBindingHandler { private SmokeSkinnableDrawable? currentSegmentSkinnable; @@ -61,7 +61,7 @@ namespace osu.Game.Rulesets.Osu.UI private void addPosition() => (currentSegmentSkinnable?.Drawable as SmokeSegment)?.AddPosition(lastMousePosition, Time.Current); - private class SmokeSkinnableDrawable : SkinnableDrawable + private partial class SmokeSkinnableDrawable : SkinnableDrawable { public override bool RemoveWhenNotAlive => true; diff --git a/osu.Game.Rulesets.Osu/Utils/OsuHitObjectGenerationUtils.cs b/osu.Game.Rulesets.Osu/Utils/OsuHitObjectGenerationUtils.cs index 3a8b3f67d0..aa4cd0af14 100644 --- a/osu.Game.Rulesets.Osu/Utils/OsuHitObjectGenerationUtils.cs +++ b/osu.Game.Rulesets.Osu/Utils/OsuHitObjectGenerationUtils.cs @@ -112,44 +112,46 @@ namespace osu.Game.Rulesets.Osu.Utils /// Reflects the position of the in the playfield horizontally. /// /// The object to reflect. - public static void ReflectHorizontally(OsuHitObject osuObject) + public static void ReflectHorizontallyAlongPlayfield(OsuHitObject osuObject) { osuObject.Position = new Vector2(OsuPlayfield.BASE_SIZE.X - osuObject.X, osuObject.Position.Y); - if (!(osuObject is Slider slider)) + if (osuObject is not Slider slider) return; - // No need to update the head and tail circles, since slider handles that when the new slider path is set - slider.NestedHitObjects.OfType().ForEach(h => h.Position = new Vector2(OsuPlayfield.BASE_SIZE.X - h.Position.X, h.Position.Y)); - slider.NestedHitObjects.OfType().ForEach(h => h.Position = new Vector2(OsuPlayfield.BASE_SIZE.X - h.Position.X, h.Position.Y)); + void reflectNestedObject(OsuHitObject nested) => nested.Position = new Vector2(OsuPlayfield.BASE_SIZE.X - nested.Position.X, nested.Position.Y); + static void reflectControlPoint(PathControlPoint point) => point.Position = new Vector2(-point.Position.X, point.Position.Y); - var controlPoints = slider.Path.ControlPoints.Select(p => new PathControlPoint(p.Position, p.Type)).ToArray(); - foreach (var point in controlPoints) - point.Position = new Vector2(-point.Position.X, point.Position.Y); - - slider.Path = new SliderPath(controlPoints, slider.Path.ExpectedDistance.Value); + modifySlider(slider, reflectNestedObject, reflectControlPoint); } /// /// Reflects the position of the in the playfield vertically. /// /// The object to reflect. - public static void ReflectVertically(OsuHitObject osuObject) + public static void ReflectVerticallyAlongPlayfield(OsuHitObject osuObject) { osuObject.Position = new Vector2(osuObject.Position.X, OsuPlayfield.BASE_SIZE.Y - osuObject.Y); - if (!(osuObject is Slider slider)) + if (osuObject is not Slider slider) return; - // No need to update the head and tail circles, since slider handles that when the new slider path is set - slider.NestedHitObjects.OfType().ForEach(h => h.Position = new Vector2(h.Position.X, OsuPlayfield.BASE_SIZE.Y - h.Position.Y)); - slider.NestedHitObjects.OfType().ForEach(h => h.Position = new Vector2(h.Position.X, OsuPlayfield.BASE_SIZE.Y - h.Position.Y)); + void reflectNestedObject(OsuHitObject nested) => nested.Position = new Vector2(nested.Position.X, OsuPlayfield.BASE_SIZE.Y - nested.Position.Y); + static void reflectControlPoint(PathControlPoint point) => point.Position = new Vector2(point.Position.X, -point.Position.Y); - var controlPoints = slider.Path.ControlPoints.Select(p => new PathControlPoint(p.Position, p.Type)).ToArray(); - foreach (var point in controlPoints) - point.Position = new Vector2(point.Position.X, -point.Position.Y); + modifySlider(slider, reflectNestedObject, reflectControlPoint); + } - slider.Path = new SliderPath(controlPoints, slider.Path.ExpectedDistance.Value); + /// + /// Flips the position of the around its start position horizontally. + /// + /// The slider to be flipped. + public static void FlipSliderInPlaceHorizontally(Slider slider) + { + void flipNestedObject(OsuHitObject nested) => nested.Position = new Vector2(slider.X - (nested.X - slider.X), nested.Y); + static void flipControlPoint(PathControlPoint point) => point.Position = new Vector2(-point.Position.X, point.Position.Y); + + modifySlider(slider, flipNestedObject, flipControlPoint); } /// @@ -160,14 +162,20 @@ namespace osu.Game.Rulesets.Osu.Utils public static void RotateSlider(Slider slider, float rotation) { void rotateNestedObject(OsuHitObject nested) => nested.Position = rotateVector(nested.Position - slider.Position, rotation) + slider.Position; + void rotateControlPoint(PathControlPoint point) => point.Position = rotateVector(point.Position, rotation); + modifySlider(slider, rotateNestedObject, rotateControlPoint); + } + + private static void modifySlider(Slider slider, Action modifyNestedObject, Action modifyControlPoint) + { // No need to update the head and tail circles, since slider handles that when the new slider path is set - slider.NestedHitObjects.OfType().ForEach(rotateNestedObject); - slider.NestedHitObjects.OfType().ForEach(rotateNestedObject); + slider.NestedHitObjects.OfType().ForEach(modifyNestedObject); + slider.NestedHitObjects.OfType().ForEach(modifyNestedObject); var controlPoints = slider.Path.ControlPoints.Select(p => new PathControlPoint(p.Position, p.Type)).ToArray(); foreach (var point in controlPoints) - point.Position = rotateVector(point.Position, rotation); + modifyControlPoint(point); slider.Path = new SliderPath(controlPoints, slider.Path.ExpectedDistance.Value); } diff --git a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj index 98f1e69bd1..bf776fe5dd 100644 --- a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj +++ b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj @@ -1,6 +1,6 @@  - netstandard2.1 + net6.0 Library true click the circles. to the beat. @@ -15,4 +15,4 @@ - \ No newline at end of file + diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Rulesets.Taiko.Tests.Android/AndroidManifest.xml similarity index 95% rename from osu.Game.Rulesets.Taiko.Tests.Android/Properties/AndroidManifest.xml rename to osu.Game.Rulesets.Taiko.Tests.Android/AndroidManifest.xml index d9de0fde4e..452b9683ec 100644 --- a/osu.Game.Rulesets.Taiko.Tests.Android/Properties/AndroidManifest.xml +++ b/osu.Game.Rulesets.Taiko.Tests.Android/AndroidManifest.xml @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/osu.Game.Rulesets.Taiko.Tests.Android.csproj b/osu.Game.Rulesets.Taiko.Tests.Android/osu.Game.Rulesets.Taiko.Tests.Android.csproj index 4d4dabebe6..a639326ebd 100644 --- a/osu.Game.Rulesets.Taiko.Tests.Android/osu.Game.Rulesets.Taiko.Tests.Android.csproj +++ b/osu.Game.Rulesets.Taiko.Tests.Android/osu.Game.Rulesets.Taiko.Tests.Android.csproj @@ -1,49 +1,24 @@ - - + - Debug - AnyCPU - 8.0.30703 - 2.0 - {3701A0A1-8476-42C6-B5C4-D24129B4A484} - {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - {122416d6-6b49-4ee2-a1e8-b825f31c79fe} + net6.0-android + Exe osu.Game.Rulesets.Taiko.Tests osu.Game.Rulesets.Taiko.Tests.Android - Properties\AndroidManifest.xml - armeabi-v7a;x86;arm64-v8a - - - None - cjk;mideast;other;rare;west - true - - - - - - - + %(RecursiveDir)%(Filename)%(Extension) + + + %(RecursiveDir)%(Filename)%(Extension) + Android\%(RecursiveDir)%(Filename)%(Extension) + - - {f167e17a-7de6-4af5-b920-a5112296c695} - osu.Game.Rulesets.Taiko - - - {2a66dd92-adb1-4994-89e2-c94e04acda0d} - osu.Game - + + - - - 5.0.0 - - - \ No newline at end of file diff --git a/osu.Game.Rulesets.Taiko.Tests.iOS/Application.cs b/osu.Game.Rulesets.Taiko.Tests.iOS/Application.cs index 1ebbd61a94..0e3a953728 100644 --- a/osu.Game.Rulesets.Taiko.Tests.iOS/Application.cs +++ b/osu.Game.Rulesets.Taiko.Tests.iOS/Application.cs @@ -3,7 +3,6 @@ #nullable disable -using osu.Framework.iOS; using UIKit; namespace osu.Game.Rulesets.Taiko.Tests.iOS @@ -12,7 +11,7 @@ namespace osu.Game.Rulesets.Taiko.Tests.iOS { public static void Main(string[] args) { - UIApplication.Main(args, typeof(GameUIApplication), typeof(AppDelegate)); + UIApplication.Main(args, null, typeof(AppDelegate)); } } } diff --git a/osu.Game.Rulesets.Taiko.Tests.iOS/Info.plist b/osu.Game.Rulesets.Taiko.Tests.iOS/Info.plist index 9628475b3e..76cb3c0db0 100644 --- a/osu.Game.Rulesets.Taiko.Tests.iOS/Info.plist +++ b/osu.Game.Rulesets.Taiko.Tests.iOS/Info.plist @@ -13,7 +13,7 @@ LSRequiresIPhoneOS MinimumOSVersion - 10.0 + 13.4 UIDeviceFamily 1 diff --git a/osu.Game.Rulesets.Taiko.Tests.iOS/osu.Game.Rulesets.Taiko.Tests.iOS.csproj b/osu.Game.Rulesets.Taiko.Tests.iOS/osu.Game.Rulesets.Taiko.Tests.iOS.csproj index 8ee640cd99..e648a11299 100644 --- a/osu.Game.Rulesets.Taiko.Tests.iOS/osu.Game.Rulesets.Taiko.Tests.iOS.csproj +++ b/osu.Game.Rulesets.Taiko.Tests.iOS/osu.Game.Rulesets.Taiko.Tests.iOS.csproj @@ -1,35 +1,19 @@ - - + - Debug - iPhoneSimulator - {7E408809-66AC-49D1-AF4D-98834F9B979A} Exe + net6.0-ios + 13.4 osu.Game.Rulesets.Taiko.Tests osu.Game.Rulesets.Taiko.Tests.iOS - - - - Linker.xml - - - %(RecursiveDir)%(Filename)%(Extension) - - {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D} - osu.Game - - - {F167E17A-7DE6-4AF5-B920-A5112296C695} - osu.Game.Rulesets.Taiko - + + - - \ No newline at end of file + diff --git a/osu.Game.Rulesets.Taiko.Tests/DrawableTaikoRulesetTestScene.cs b/osu.Game.Rulesets.Taiko.Tests/DrawableTaikoRulesetTestScene.cs index 01719bfea6..a222fe8275 100644 --- a/osu.Game.Rulesets.Taiko.Tests/DrawableTaikoRulesetTestScene.cs +++ b/osu.Game.Rulesets.Taiko.Tests/DrawableTaikoRulesetTestScene.cs @@ -16,7 +16,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Taiko.Tests { - public abstract class DrawableTaikoRulesetTestScene : OsuTestScene + public abstract partial class DrawableTaikoRulesetTestScene : OsuTestScene { protected const int DEFAULT_PLAYFIELD_CONTAINER_HEIGHT = 768; diff --git a/osu.Game.Rulesets.Taiko.Tests/DrawableTestHit.cs b/osu.Game.Rulesets.Taiko.Tests/DrawableTestHit.cs index 6a585b840d..157a96eec8 100644 --- a/osu.Game.Rulesets.Taiko.Tests/DrawableTestHit.cs +++ b/osu.Game.Rulesets.Taiko.Tests/DrawableTestHit.cs @@ -12,7 +12,7 @@ using osu.Game.Rulesets.Taiko.Objects.Drawables; namespace osu.Game.Rulesets.Taiko.Tests { - public class DrawableTestHit : DrawableHit + public partial class DrawableTestHit : DrawableHit { public readonly HitResult Type; diff --git a/osu.Game.Rulesets.Taiko.Tests/DrawableTestStrongHit.cs b/osu.Game.Rulesets.Taiko.Tests/DrawableTestStrongHit.cs index 7355e1dbca..747c599721 100644 --- a/osu.Game.Rulesets.Taiko.Tests/DrawableTestStrongHit.cs +++ b/osu.Game.Rulesets.Taiko.Tests/DrawableTestStrongHit.cs @@ -11,7 +11,7 @@ using osu.Game.Rulesets.Taiko.Objects.Drawables; namespace osu.Game.Rulesets.Taiko.Tests { - public class DrawableTestStrongHit : DrawableTestHit + public partial class DrawableTestStrongHit : DrawableTestHit { private readonly bool hitBoth; diff --git a/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneEditor.cs b/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneEditor.cs index 5915b9fdfa..3ee9171e7e 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneEditor.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneEditor.cs @@ -9,7 +9,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Taiko.Tests.Editor { [TestFixture] - public class TestSceneEditor : EditorTestScene + public partial class TestSceneEditor : EditorTestScene { protected override Ruleset CreateEditorRuleset() => new TaikoRuleset(); } diff --git a/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneTaikoEditorSaving.cs b/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneTaikoEditorSaving.cs index 06c06f6e28..93b26624de 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneTaikoEditorSaving.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneTaikoEditorSaving.cs @@ -10,7 +10,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Taiko.Tests.Editor { - public class TestSceneTaikoEditorSaving : EditorSavingTestScene + public partial class TestSceneTaikoEditorSaving : EditorSavingTestScene { protected override Ruleset CreateRuleset() => new TaikoRuleset(); diff --git a/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneTaikoHitObjectComposer.cs b/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneTaikoHitObjectComposer.cs index 8d17918a92..ed73730c4a 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneTaikoHitObjectComposer.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneTaikoHitObjectComposer.cs @@ -16,7 +16,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Taiko.Tests.Editor { - public class TestSceneTaikoHitObjectComposer : EditorClockTestScene + public partial class TestSceneTaikoHitObjectComposer : EditorClockTestScene { [SetUp] public void Setup() => Schedule(() => @@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.Taiko.Tests.Editor { } - private class TestComposer : CompositeDrawable + private partial class TestComposer : CompositeDrawable { [Cached(typeof(EditorBeatmap))] [Cached(typeof(IBeatSnapProvider))] diff --git a/osu.Game.Rulesets.Taiko.Tests/HitObjectApplicationTestScene.cs b/osu.Game.Rulesets.Taiko.Tests/HitObjectApplicationTestScene.cs index 09a6a2f16c..e8688f36bc 100644 --- a/osu.Game.Rulesets.Taiko.Tests/HitObjectApplicationTestScene.cs +++ b/osu.Game.Rulesets.Taiko.Tests/HitObjectApplicationTestScene.cs @@ -16,7 +16,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Taiko.Tests { - public abstract class HitObjectApplicationTestScene : OsuTestScene + public abstract partial class HitObjectApplicationTestScene : OsuTestScene { [Cached(typeof(IScrollingInfo))] private ScrollingTestContainer.TestScrollingInfo info = new ScrollingTestContainer.TestScrollingInfo diff --git a/osu.Game.Rulesets.Taiko.Tests/Judgements/JudgementTest.cs b/osu.Game.Rulesets.Taiko.Tests/Judgements/JudgementTest.cs index 7f2f27b2b8..eb2d96ec51 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Judgements/JudgementTest.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Judgements/JudgementTest.cs @@ -19,7 +19,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Taiko.Tests.Judgements { - public class JudgementTest : RateAdjustedBeatmapTestScene + public partial class JudgementTest : RateAdjustedBeatmapTestScene { private ScoreAccessibleReplayPlayer currentPlayer = null!; protected List JudgementResults { get; private set; } = null!; @@ -77,7 +77,7 @@ namespace osu.Game.Rulesets.Taiko.Tests.Judgements return beatmap; } - private class ScoreAccessibleReplayPlayer : ReplayPlayer + private partial class ScoreAccessibleReplayPlayer : ReplayPlayer { public new ScoreProcessor ScoreProcessor => base.ScoreProcessor; diff --git a/osu.Game.Rulesets.Taiko.Tests/Judgements/TestSceneDrumRollJudgements.cs b/osu.Game.Rulesets.Taiko.Tests/Judgements/TestSceneDrumRollJudgements.cs index 2c28c3dad5..a9231b4783 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Judgements/TestSceneDrumRollJudgements.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Judgements/TestSceneDrumRollJudgements.cs @@ -10,7 +10,7 @@ using osu.Game.Rulesets.Taiko.Replays; namespace osu.Game.Rulesets.Taiko.Tests.Judgements { - public class TestSceneDrumRollJudgements : JudgementTest + public partial class TestSceneDrumRollJudgements : JudgementTest { [Test] public void TestHitAllDrumRoll() diff --git a/osu.Game.Rulesets.Taiko.Tests/Judgements/TestSceneHitJudgements.cs b/osu.Game.Rulesets.Taiko.Tests/Judgements/TestSceneHitJudgements.cs index d2d5cdb6ac..3bf94eb62e 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Judgements/TestSceneHitJudgements.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Judgements/TestSceneHitJudgements.cs @@ -11,7 +11,7 @@ using osu.Game.Rulesets.Taiko.Replays; namespace osu.Game.Rulesets.Taiko.Tests.Judgements { - public class TestSceneHitJudgements : JudgementTest + public partial class TestSceneHitJudgements : JudgementTest { [Test] public void TestHitCentreHit() diff --git a/osu.Game.Rulesets.Taiko.Tests/Judgements/TestSceneSwellJudgements.cs b/osu.Game.Rulesets.Taiko.Tests/Judgements/TestSceneSwellJudgements.cs index 7bdfcf0b07..ccc829f09e 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Judgements/TestSceneSwellJudgements.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Judgements/TestSceneSwellJudgements.cs @@ -11,7 +11,7 @@ using osu.Game.Rulesets.Taiko.Replays; namespace osu.Game.Rulesets.Taiko.Tests.Judgements { - public class TestSceneSwellJudgements : JudgementTest + public partial class TestSceneSwellJudgements : JudgementTest { [Test] public void TestHitAllSwell() diff --git a/osu.Game.Rulesets.Taiko.Tests/Mods/TaikoModTestScene.cs b/osu.Game.Rulesets.Taiko.Tests/Mods/TaikoModTestScene.cs index 3090facf8c..7760c5a30b 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Mods/TaikoModTestScene.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Mods/TaikoModTestScene.cs @@ -5,7 +5,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Taiko.Tests.Mods { - public abstract class TaikoModTestScene : ModTestScene + public abstract partial class TaikoModTestScene : ModTestScene { protected sealed override Ruleset CreatePlayerRuleset() => new TaikoRuleset(); } diff --git a/osu.Game.Rulesets.Taiko.Tests/Mods/TestSceneTaikoModFlashlight.cs b/osu.Game.Rulesets.Taiko.Tests/Mods/TestSceneTaikoModFlashlight.cs index d55ce17e6c..05a408c621 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Mods/TestSceneTaikoModFlashlight.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Mods/TestSceneTaikoModFlashlight.cs @@ -10,7 +10,7 @@ using osuTK; namespace osu.Game.Rulesets.Taiko.Tests.Mods { - public class TestSceneTaikoModFlashlight : TaikoModTestScene + public partial class TestSceneTaikoModFlashlight : TaikoModTestScene { [TestCase(1f)] [TestCase(0.5f)] @@ -38,11 +38,11 @@ namespace osu.Game.Rulesets.Taiko.Tests.Mods }); } - private class TestTaikoModFlashlight : TaikoModFlashlight + private partial class TestTaikoModFlashlight : TaikoModFlashlight { protected override Flashlight CreateFlashlight() => new TestTaikoFlashlight(this, Playfield); - public class TestTaikoFlashlight : TaikoFlashlight + public partial class TestTaikoFlashlight : TaikoFlashlight { public TestTaikoFlashlight(TaikoModFlashlight modFlashlight, TaikoPlayfield taikoPlayfield) : base(modFlashlight, taikoPlayfield) diff --git a/osu.Game.Rulesets.Taiko.Tests/Mods/TestSceneTaikoModHidden.cs b/osu.Game.Rulesets.Taiko.Tests/Mods/TestSceneTaikoModHidden.cs index 7abbb9d186..edc53429b1 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Mods/TestSceneTaikoModHidden.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Mods/TestSceneTaikoModHidden.cs @@ -7,7 +7,7 @@ using osu.Game.Rulesets.Taiko.Mods; namespace osu.Game.Rulesets.Taiko.Tests.Mods { - public class TestSceneTaikoModHidden : TaikoModTestScene + public partial class TestSceneTaikoModHidden : TaikoModTestScene { [Test] public void TestDefaultBeatmapTest() => CreateModTest(new ModTestData diff --git a/osu.Game.Rulesets.Taiko.Tests/Mods/TestSceneTaikoModPerfect.cs b/osu.Game.Rulesets.Taiko.Tests/Mods/TestSceneTaikoModPerfect.cs index 92503a9f03..aed08f33e0 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Mods/TestSceneTaikoModPerfect.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Mods/TestSceneTaikoModPerfect.cs @@ -10,7 +10,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Taiko.Tests.Mods { - public class TestSceneTaikoModPerfect : ModPerfectTestScene + public partial class TestSceneTaikoModPerfect : ModPerfectTestScene { protected override Ruleset CreatePlayerRuleset() => new TestTaikoRuleset(); @@ -31,11 +31,11 @@ namespace osu.Game.Rulesets.Taiko.Tests.Mods [TestCase(true)] public void TestSwell(bool shouldMiss) => CreateHitObjectTest(new HitObjectTestData(new Swell { StartTime = 1000, EndTime = 3000 }, false), shouldMiss); - private class TestTaikoRuleset : TaikoRuleset + private partial class TestTaikoRuleset : TaikoRuleset { public override HealthProcessor CreateHealthProcessor(double drainStartTime) => new TestTaikoHealthProcessor(); - private class TestTaikoHealthProcessor : TaikoHealthProcessor + private partial class TestTaikoHealthProcessor : TaikoHealthProcessor { protected override void Reset(bool storeResults) { diff --git a/osu.Game.Rulesets.Taiko.Tests/Skinning/TaikoSkinnableTestScene.cs b/osu.Game.Rulesets.Taiko.Tests/Skinning/TaikoSkinnableTestScene.cs index 82be26b422..38530282b7 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Skinning/TaikoSkinnableTestScene.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Skinning/TaikoSkinnableTestScene.cs @@ -7,7 +7,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Taiko.Tests.Skinning { - public abstract class TaikoSkinnableTestScene : SkinnableTestScene + public abstract partial class TaikoSkinnableTestScene : SkinnableTestScene { protected override Ruleset CreateRulesetForSkinProvider() => new TaikoRuleset(); } diff --git a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableBarLine.cs b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableBarLine.cs index a4aa0e1fad..7fd90685e3 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableBarLine.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableBarLine.cs @@ -18,7 +18,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Taiko.Tests.Skinning { [TestFixture] - public class TestSceneDrawableBarLine : TaikoSkinnableTestScene + public partial class TestSceneDrawableBarLine : TaikoSkinnableTestScene { [Cached(typeof(IScrollingInfo))] private ScrollingTestContainer.TestScrollingInfo info = new ScrollingTestContainer.TestScrollingInfo diff --git a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableDrumRoll.cs index 25cb3f7886..3b2f4f2fb2 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableDrumRoll.cs @@ -16,7 +16,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Taiko.Tests.Skinning { [TestFixture] - public class TestSceneDrawableDrumRoll : TaikoSkinnableTestScene + public partial class TestSceneDrawableDrumRoll : TaikoSkinnableTestScene { [Cached(typeof(IScrollingInfo))] private ScrollingTestContainer.TestScrollingInfo info = new ScrollingTestContainer.TestScrollingInfo diff --git a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableHit.cs b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableHit.cs index adfd27c5d6..9567eac80f 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableHit.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableHit.cs @@ -16,7 +16,7 @@ using osu.Game.Tests.Gameplay; namespace osu.Game.Rulesets.Taiko.Tests.Skinning { [TestFixture] - public class TestSceneDrawableHit : TaikoSkinnableTestScene + public partial class TestSceneDrawableHit : TaikoSkinnableTestScene { [Cached] private GameplayState gameplayState = TestGameplayState.Create(new TaikoRuleset()); diff --git a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableSwell.cs b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableSwell.cs index b8c0f6f11e..c130b5f366 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableSwell.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableSwell.cs @@ -11,7 +11,7 @@ using osu.Game.Rulesets.Taiko.Objects.Drawables; namespace osu.Game.Rulesets.Taiko.Tests.Skinning { [TestFixture] - public class TestSceneDrawableSwell : TaikoSkinnableTestScene + public partial class TestSceneDrawableSwell : TaikoSkinnableTestScene { [Test] public void TestHits() diff --git a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableTaikoMascot.cs b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableTaikoMascot.cs index 71ce4c08d0..e4e68c7207 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableTaikoMascot.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableTaikoMascot.cs @@ -25,7 +25,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Taiko.Tests.Skinning { [TestFixture] - public class TestSceneDrawableTaikoMascot : TaikoSkinnableTestScene + public partial class TestSceneDrawableTaikoMascot : TaikoSkinnableTestScene { [Cached(typeof(IScrollingInfo))] private ScrollingTestContainer.TestScrollingInfo info = new ScrollingTestContainer.TestScrollingInfo diff --git a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneHitExplosion.cs b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneHitExplosion.cs index 0ddc607336..924f903ce9 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneHitExplosion.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneHitExplosion.cs @@ -18,7 +18,7 @@ using osu.Game.Screens.Ranking; namespace osu.Game.Rulesets.Taiko.Tests.Skinning { [TestFixture] - public class TestSceneHitExplosion : TaikoSkinnableTestScene + public partial class TestSceneHitExplosion : TaikoSkinnableTestScene { protected override double TimePerAction => 100; diff --git a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneInputDrum.cs b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneInputDrum.cs index f342bfe78e..cb5d0d1f91 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneInputDrum.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneInputDrum.cs @@ -13,7 +13,7 @@ using osuTK; namespace osu.Game.Rulesets.Taiko.Tests.Skinning { [TestFixture] - public class TestSceneInputDrum : TaikoSkinnableTestScene + public partial class TestSceneInputDrum : TaikoSkinnableTestScene { [BackgroundDependencyLoader] private void load() diff --git a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneKiaiHitExplosion.cs b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneKiaiHitExplosion.cs index e1a3c736fe..5f98f2f27a 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneKiaiHitExplosion.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneKiaiHitExplosion.cs @@ -12,7 +12,7 @@ using osu.Game.Rulesets.Taiko.UI; namespace osu.Game.Rulesets.Taiko.Tests.Skinning { [TestFixture] - public class TestSceneKiaiHitExplosion : TaikoSkinnableTestScene + public partial class TestSceneKiaiHitExplosion : TaikoSkinnableTestScene { [Test] public void TestKiaiHits() diff --git a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneTaikoKiaiGlow.cs b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneTaikoKiaiGlow.cs new file mode 100644 index 0000000000..a5e2eb0dbb --- /dev/null +++ b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneTaikoKiaiGlow.cs @@ -0,0 +1,37 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Taiko.Skinning.Legacy; + +namespace osu.Game.Rulesets.Taiko.Tests.Skinning +{ + public partial class TestSceneTaikoKiaiGlow : TaikoSkinnableTestScene + { + [Test] + public void TestKiaiGlow() + { + AddStep("Create kiai glow", () => SetContents(_ => new LegacyKiaiGlow())); + AddToggleStep("Toggle kiai mode", setUpBeatmap); + } + + private void setUpBeatmap(bool withKiai) + { + var controlPointInfo = new ControlPointInfo(); + + controlPointInfo.Add(0, new TimingControlPoint { BeatLength = 500 }); + + if (withKiai) + controlPointInfo.Add(0, new EffectControlPoint { KiaiMode = true }); + + Beatmap.Value = CreateWorkingBeatmap(new Beatmap + { + ControlPointInfo = controlPointInfo + }); + + Beatmap.Value.Track.Start(); + } + } +} diff --git a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneTaikoPlayfield.cs b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneTaikoPlayfield.cs index eff9f58751..eb2762cb2d 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneTaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneTaikoPlayfield.cs @@ -17,7 +17,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Taiko.Tests.Skinning { - public class TestSceneTaikoPlayfield : TaikoSkinnableTestScene + public partial class TestSceneTaikoPlayfield : TaikoSkinnableTestScene { [Cached(typeof(IScrollingInfo))] private ScrollingTestContainer.TestScrollingInfo info = new ScrollingTestContainer.TestScrollingInfo diff --git a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneTaikoScroller.cs b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneTaikoScroller.cs index a9304b01ad..826cf2acab 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneTaikoScroller.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneTaikoScroller.cs @@ -14,7 +14,7 @@ using osu.Game.Skinning; namespace osu.Game.Rulesets.Taiko.Tests.Skinning { - public class TestSceneTaikoScroller : TaikoSkinnableTestScene + public partial class TestSceneTaikoScroller : TaikoSkinnableTestScene { private readonly ManualClock clock = new ManualClock(); diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneBarLineApplication.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneBarLineApplication.cs index 867ee13bea..00292d5473 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneBarLineApplication.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneBarLineApplication.cs @@ -9,7 +9,7 @@ using osu.Game.Rulesets.Taiko.Objects.Drawables; namespace osu.Game.Rulesets.Taiko.Tests { - public class TestSceneBarLineApplication : HitObjectApplicationTestScene + public partial class TestSceneBarLineApplication : HitObjectApplicationTestScene { [Test] public void TestApplyNewBarLine() diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneBarLineGeneration.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneBarLineGeneration.cs index bd52af7615..7b8c8926f0 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneBarLineGeneration.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneBarLineGeneration.cs @@ -12,7 +12,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Taiko.Tests { - public class TestSceneBarLineGeneration : OsuTestScene + public partial class TestSceneBarLineGeneration : OsuTestScene { [Test] public void TestCloseBarLineGeneration() diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumRollApplication.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumRollApplication.cs index eceeaf5083..b01bd11149 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumRollApplication.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumRollApplication.cs @@ -9,7 +9,7 @@ using osu.Game.Rulesets.Taiko.Objects.Drawables; namespace osu.Game.Rulesets.Taiko.Tests { - public class TestSceneDrumRollApplication : HitObjectApplicationTestScene + public partial class TestSceneDrumRollApplication : HitObjectApplicationTestScene { [Test] public void TestApplyNewDrumRoll() diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumTouchInputArea.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumTouchInputArea.cs index 7210419c0e..6514b760bb 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumTouchInputArea.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumTouchInputArea.cs @@ -10,7 +10,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Taiko.Tests { [TestFixture] - public class TestSceneDrumTouchInputArea : OsuTestScene + public partial class TestSceneDrumTouchInputArea : OsuTestScene { private DrumTouchInputArea drumTouchInputArea = null!; diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneFlyingHits.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneFlyingHits.cs index c787683620..e0ff617b59 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneFlyingHits.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneFlyingHits.cs @@ -16,7 +16,7 @@ using osu.Game.Rulesets.Taiko.UI; namespace osu.Game.Rulesets.Taiko.Tests { [TestFixture] - public class TestSceneFlyingHits : DrawableTaikoRulesetTestScene + public partial class TestSceneFlyingHits : DrawableTaikoRulesetTestScene { [TestCase(HitType.Centre)] [TestCase(HitType.Rim)] diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneHitApplication.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneHitApplication.cs index b337519c85..301620edc9 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneHitApplication.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneHitApplication.cs @@ -9,7 +9,7 @@ using osu.Game.Rulesets.Taiko.Objects.Drawables; namespace osu.Game.Rulesets.Taiko.Tests { - public class TestSceneHitApplication : HitObjectApplicationTestScene + public partial class TestSceneHitApplication : HitObjectApplicationTestScene { [Test] public void TestApplyNewHit() diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneHits.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneHits.cs index 5350a81f55..91209e5ec5 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneHits.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneHits.cs @@ -23,7 +23,7 @@ using osuTK; namespace osu.Game.Rulesets.Taiko.Tests { [TestFixture] - public class TestSceneHits : DrawableTaikoRulesetTestScene + public partial class TestSceneHits : DrawableTaikoRulesetTestScene { private const double default_duration = 3000; private const float scroll_time = 1000; diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneSampleOutput.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneSampleOutput.cs index e6c28a532a..dcdda6014c 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneSampleOutput.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneSampleOutput.cs @@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Taiko.Tests /// Taiko has some interesting rules for legacy mappings. /// [HeadlessTest] - public class TestSceneSampleOutput : TestSceneTaikoPlayer + public partial class TestSceneSampleOutput : TestSceneTaikoPlayer { public override void SetUpSteps() { diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoHitObjectSamples.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoHitObjectSamples.cs index c674f87f80..1d1e82fb07 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoHitObjectSamples.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoHitObjectSamples.cs @@ -8,7 +8,7 @@ using osu.Game.Tests.Beatmaps; namespace osu.Game.Rulesets.Taiko.Tests { - public class TestSceneTaikoHitObjectSamples : HitObjectSampleTest + public partial class TestSceneTaikoHitObjectSamples : HitObjectSampleTest { protected override Ruleset CreatePlayerRuleset() => new TaikoRuleset(); diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayer.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayer.cs index 5e984b19f8..8c903f748c 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayer.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayer.cs @@ -7,7 +7,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Taiko.Tests { - public class TestSceneTaikoPlayer : PlayerTestScene + public partial class TestSceneTaikoPlayer : PlayerTestScene { protected override Ruleset CreatePlayerRuleset() => new TaikoRuleset(); } diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayerLegacySkin.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayerLegacySkin.cs index 13df24c988..39776229fa 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayerLegacySkin.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayerLegacySkin.cs @@ -6,7 +6,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Taiko.Tests { - public class TestSceneTaikoPlayerLegacySkin : LegacySkinPlayerTestScene + public partial class TestSceneTaikoPlayerLegacySkin : LegacySkinPlayerTestScene { protected override Ruleset CreatePlayerRuleset() => new TaikoRuleset(); diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.cs index 2169ac5581..08c06b08f2 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.cs @@ -13,7 +13,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Taiko.Tests { - public class TestSceneTaikoSuddenDeath : TestSceneTaikoPlayer + public partial class TestSceneTaikoSuddenDeath : TestSceneTaikoPlayer { protected override bool AllowFail => true; diff --git a/osu.Game.Rulesets.Taiko/Edit/Blueprints/DrumRollPlacementBlueprint.cs b/osu.Game.Rulesets.Taiko/Edit/Blueprints/DrumRollPlacementBlueprint.cs index dfbcd1cce3..4b4e2b5847 100644 --- a/osu.Game.Rulesets.Taiko/Edit/Blueprints/DrumRollPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Taiko/Edit/Blueprints/DrumRollPlacementBlueprint.cs @@ -7,7 +7,7 @@ using osu.Game.Rulesets.Taiko.Objects; namespace osu.Game.Rulesets.Taiko.Edit.Blueprints { - public class DrumRollPlacementBlueprint : TaikoSpanPlacementBlueprint + public partial class DrumRollPlacementBlueprint : TaikoSpanPlacementBlueprint { public DrumRollPlacementBlueprint() : base(new DrumRoll()) diff --git a/osu.Game.Rulesets.Taiko/Edit/Blueprints/HitPiece.cs b/osu.Game.Rulesets.Taiko/Edit/Blueprints/HitPiece.cs index 86f32ca17c..84bc547372 100644 --- a/osu.Game.Rulesets.Taiko/Edit/Blueprints/HitPiece.cs +++ b/osu.Game.Rulesets.Taiko/Edit/Blueprints/HitPiece.cs @@ -10,7 +10,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Taiko.Edit.Blueprints { - public class HitPiece : CompositeDrawable + public partial class HitPiece : CompositeDrawable { public HitPiece() { diff --git a/osu.Game.Rulesets.Taiko/Edit/Blueprints/HitPlacementBlueprint.cs b/osu.Game.Rulesets.Taiko/Edit/Blueprints/HitPlacementBlueprint.cs index 863a2c9eac..0a1f5380b5 100644 --- a/osu.Game.Rulesets.Taiko/Edit/Blueprints/HitPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Taiko/Edit/Blueprints/HitPlacementBlueprint.cs @@ -12,7 +12,7 @@ using osuTK.Input; namespace osu.Game.Rulesets.Taiko.Edit.Blueprints { - public class HitPlacementBlueprint : PlacementBlueprint + public partial class HitPlacementBlueprint : PlacementBlueprint { private readonly HitPiece piece; diff --git a/osu.Game.Rulesets.Taiko/Edit/Blueprints/LengthPiece.cs b/osu.Game.Rulesets.Taiko/Edit/Blueprints/LengthPiece.cs index e201d58f7a..af02522a05 100644 --- a/osu.Game.Rulesets.Taiko/Edit/Blueprints/LengthPiece.cs +++ b/osu.Game.Rulesets.Taiko/Edit/Blueprints/LengthPiece.cs @@ -10,7 +10,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Taiko.Edit.Blueprints { - public class LengthPiece : CompositeDrawable + public partial class LengthPiece : CompositeDrawable { public LengthPiece() { diff --git a/osu.Game.Rulesets.Taiko/Edit/Blueprints/SwellPlacementBlueprint.cs b/osu.Game.Rulesets.Taiko/Edit/Blueprints/SwellPlacementBlueprint.cs index 1d08af47d3..2080293428 100644 --- a/osu.Game.Rulesets.Taiko/Edit/Blueprints/SwellPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Taiko/Edit/Blueprints/SwellPlacementBlueprint.cs @@ -7,7 +7,7 @@ using osu.Game.Rulesets.Taiko.Objects; namespace osu.Game.Rulesets.Taiko.Edit.Blueprints { - public class SwellPlacementBlueprint : TaikoSpanPlacementBlueprint + public partial class SwellPlacementBlueprint : TaikoSpanPlacementBlueprint { public SwellPlacementBlueprint() : base(new Swell()) diff --git a/osu.Game.Rulesets.Taiko/Edit/Blueprints/TaikoSelectionBlueprint.cs b/osu.Game.Rulesets.Taiko/Edit/Blueprints/TaikoSelectionBlueprint.cs index 4c67a37417..34695cbdd6 100644 --- a/osu.Game.Rulesets.Taiko/Edit/Blueprints/TaikoSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Taiko/Edit/Blueprints/TaikoSelectionBlueprint.cs @@ -10,7 +10,7 @@ using osuTK; namespace osu.Game.Rulesets.Taiko.Edit.Blueprints { - public class TaikoSelectionBlueprint : HitObjectSelectionBlueprint + public partial class TaikoSelectionBlueprint : HitObjectSelectionBlueprint { public TaikoSelectionBlueprint(HitObject hitObject) : base(hitObject) diff --git a/osu.Game.Rulesets.Taiko/Edit/Blueprints/TaikoSpanPlacementBlueprint.cs b/osu.Game.Rulesets.Taiko/Edit/Blueprints/TaikoSpanPlacementBlueprint.cs index 70364cabf1..fcf2573d64 100644 --- a/osu.Game.Rulesets.Taiko/Edit/Blueprints/TaikoSpanPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Taiko/Edit/Blueprints/TaikoSpanPlacementBlueprint.cs @@ -16,7 +16,7 @@ using osuTK.Input; namespace osu.Game.Rulesets.Taiko.Edit.Blueprints { - public class TaikoSpanPlacementBlueprint : PlacementBlueprint + public partial class TaikoSpanPlacementBlueprint : PlacementBlueprint { private readonly HitPiece headPiece; private readonly HitPiece tailPiece; diff --git a/osu.Game.Rulesets.Taiko/Edit/TaikoBlueprintContainer.cs b/osu.Game.Rulesets.Taiko/Edit/TaikoBlueprintContainer.cs index 6107c8009a..6be22f3af0 100644 --- a/osu.Game.Rulesets.Taiko/Edit/TaikoBlueprintContainer.cs +++ b/osu.Game.Rulesets.Taiko/Edit/TaikoBlueprintContainer.cs @@ -10,7 +10,7 @@ using osu.Game.Screens.Edit.Compose.Components; namespace osu.Game.Rulesets.Taiko.Edit { - public class TaikoBlueprintContainer : ComposeBlueprintContainer + public partial class TaikoBlueprintContainer : ComposeBlueprintContainer { public TaikoBlueprintContainer(HitObjectComposer composer) : base(composer) diff --git a/osu.Game.Rulesets.Taiko/Edit/TaikoHitObjectComposer.cs b/osu.Game.Rulesets.Taiko/Edit/TaikoHitObjectComposer.cs index 161799c980..cff5731181 100644 --- a/osu.Game.Rulesets.Taiko/Edit/TaikoHitObjectComposer.cs +++ b/osu.Game.Rulesets.Taiko/Edit/TaikoHitObjectComposer.cs @@ -9,7 +9,7 @@ using osu.Game.Screens.Edit.Compose.Components; namespace osu.Game.Rulesets.Taiko.Edit { - public class TaikoHitObjectComposer : HitObjectComposer + public partial class TaikoHitObjectComposer : HitObjectComposer { public TaikoHitObjectComposer(TaikoRuleset ruleset) : base(ruleset) diff --git a/osu.Game.Rulesets.Taiko/Edit/TaikoSelectionHandler.cs b/osu.Game.Rulesets.Taiko/Edit/TaikoSelectionHandler.cs index 80e4e8f406..b727c0a61b 100644 --- a/osu.Game.Rulesets.Taiko/Edit/TaikoSelectionHandler.cs +++ b/osu.Game.Rulesets.Taiko/Edit/TaikoSelectionHandler.cs @@ -16,7 +16,7 @@ using osu.Game.Screens.Edit.Compose.Components; namespace osu.Game.Rulesets.Taiko.Edit { - public class TaikoSelectionHandler : EditorSelectionHandler + public partial class TaikoSelectionHandler : EditorSelectionHandler { private readonly Bindable selectionRimState = new Bindable(); private readonly Bindable selectionStrongState = new Bindable(); diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModClassic.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModClassic.cs index f7fdd447d6..3b3b3e606c 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModClassic.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModClassic.cs @@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Taiko.Mods public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) { drawableTaikoRuleset = (DrawableTaikoRuleset)drawableRuleset; - drawableTaikoRuleset.LockPlayfieldAspect.Value = false; + drawableTaikoRuleset.LockPlayfieldMaxAspect.Value = false; var playfield = (TaikoPlayfield)drawableRuleset.Playfield; playfield.ClassicHitTargetPosition.Value = true; diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs index 46569c2495..733772e21f 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs @@ -12,7 +12,7 @@ using osuTK; namespace osu.Game.Rulesets.Taiko.Mods { - public class TaikoModFlashlight : ModFlashlight + public partial class TaikoModFlashlight : ModFlashlight { public override double ScoreMultiplier => UsesDefaultConfiguration ? 1.12 : 1; @@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Taiko.Mods base.ApplyToDrawableRuleset(drawableRuleset); } - public class TaikoFlashlight : Flashlight + public partial class TaikoFlashlight : Flashlight { private readonly LayoutValue flashlightProperties = new LayoutValue(Invalidation.RequiredParentSizeToFit | Invalidation.DrawInfo); private readonly TaikoPlayfield taikoPlayfield; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs index 2405d5b73f..65a6fd4499 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs @@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables /// /// A line that scrolls alongside hit objects in the playfield and visualises control points. /// - public class DrawableBarLine : DrawableHitObject + public partial class DrawableBarLine : DrawableHitObject { public new BarLine HitObject => (BarLine)base.HitObject; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs index 0bb14c791e..005d2ab1ac 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs @@ -22,7 +22,7 @@ using osuTK; namespace osu.Game.Rulesets.Taiko.Objects.Drawables { - public class DrawableDrumRoll : DrawableTaikoStrongableHitObject + public partial class DrawableDrumRoll : DrawableTaikoStrongableHitObject { /// /// Number of rolling hits required to reach the dark/final colour. @@ -173,7 +173,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables (MainPiece.Drawable as IHasAccentColour)?.FadeAccent(newColour, fadeDuration); } - public class StrongNestedHit : DrawableStrongNestedHit + public partial class StrongNestedHit : DrawableStrongNestedHit { public new DrawableDrumRoll ParentHitObject => (DrawableDrumRoll)base.ParentHitObject; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs index b01adc880a..45e25ee7dc 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs @@ -15,7 +15,7 @@ using osu.Game.Skinning; namespace osu.Game.Rulesets.Taiko.Objects.Drawables { - public class DrawableDrumRollTick : DrawableTaikoStrongableHitObject + public partial class DrawableDrumRollTick : DrawableTaikoStrongableHitObject { public BindableBool IsFirstTick = new BindableBool(); @@ -88,7 +88,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables protected override DrawableStrongNestedHit CreateStrongNestedHit(DrumRollTick.StrongNestedHit hitObject) => new StrongNestedHit(hitObject); - public class StrongNestedHit : DrawableStrongNestedHit + public partial class StrongNestedHit : DrawableStrongNestedHit { public new DrawableDrumRollTick ParentHitObject => (DrawableDrumRollTick)base.ParentHitObject; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableFlyingHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableFlyingHit.cs index 5ce72028e0..0cd265ecab 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableFlyingHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableFlyingHit.cs @@ -11,7 +11,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables /// /// A hit used specifically for drum rolls, where spawning flying hits is required. /// - public class DrawableFlyingHit : DrawableHit + public partial class DrawableFlyingHit : DrawableHit { public DrawableFlyingHit(DrawableDrumRollTick drumRollTick) : base(new IgnoreHit diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs index 59c9640beb..ff4edf35fa 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs @@ -19,7 +19,7 @@ using osu.Game.Skinning; namespace osu.Game.Rulesets.Taiko.Objects.Drawables { - public class DrawableHit : DrawableTaikoStrongableHitObject + public partial class DrawableHit : DrawableTaikoStrongableHitObject { /// /// A list of keys which can result in hits for this HitObject. @@ -220,7 +220,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables protected override DrawableStrongNestedHit CreateStrongNestedHit(Hit.StrongNestedHit hitObject) => new StrongNestedHit(hitObject); - public class StrongNestedHit : DrawableStrongNestedHit + public partial class StrongNestedHit : DrawableStrongNestedHit { public new DrawableHit ParentHitObject => (DrawableHit)base.ParentHitObject; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongNestedHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongNestedHit.cs index 01ee91a5c7..4ea30453d1 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongNestedHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongNestedHit.cs @@ -11,7 +11,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables /// /// Used as a nested hitobject to provide s for s. /// - public abstract class DrawableStrongNestedHit : DrawableTaikoHitObject + public abstract partial class DrawableStrongNestedHit : DrawableTaikoHitObject { public new DrawableTaikoHitObject ParentHitObject => (DrawableTaikoHitObject)base.ParentHitObject; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs index 753f85f23f..8441e3a749 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs @@ -21,7 +21,7 @@ using osu.Game.Skinning; namespace osu.Game.Rulesets.Taiko.Objects.Drawables { - public class DrawableSwell : DrawableTaikoHitObject + public partial class DrawableSwell : DrawableTaikoHitObject { private const float target_ring_thick_border = 1.4f; private const float target_ring_thin_border = 1f; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs index 5d44fce254..3a5c006962 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs @@ -11,7 +11,7 @@ using osu.Game.Skinning; namespace osu.Game.Rulesets.Taiko.Objects.Drawables { - public class DrawableSwellTick : DrawableTaikoHitObject + public partial class DrawableSwellTick : DrawableTaikoHitObject { public override bool DisplayResult => false; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs index 400c2f40b1..6172b75d2c 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs @@ -18,7 +18,7 @@ using osuTK; namespace osu.Game.Rulesets.Taiko.Objects.Drawables { - public abstract class DrawableTaikoHitObject : DrawableHitObject, IKeyBindingHandler + public abstract partial class DrawableTaikoHitObject : DrawableHitObject, IKeyBindingHandler { protected readonly Container Content; private readonly Container proxiedContent; @@ -105,13 +105,13 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables } } - private class ProxiedContentContainer : Container + private partial class ProxiedContentContainer : Container { public override bool RemoveWhenNotAlive => false; } } - public abstract class DrawableTaikoHitObject : DrawableTaikoHitObject + public abstract partial class DrawableTaikoHitObject : DrawableTaikoHitObject where TObject : TaikoHitObject { public override Vector2 OriginPosition => new Vector2(DrawHeight / 2); diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoStrongableHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoStrongableHitObject.cs index 4b58cc60e6..4d7cdf3243 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoStrongableHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoStrongableHitObject.cs @@ -12,7 +12,7 @@ using osuTK; namespace osu.Game.Rulesets.Taiko.Objects.Drawables { - public abstract class DrawableTaikoStrongableHitObject : DrawableTaikoHitObject + public abstract partial class DrawableTaikoStrongableHitObject : DrawableTaikoHitObject where TObject : TaikoStrongableHitObject where TStrongNestedObject : StrongNestedHitObject { diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoHealthProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoHealthProcessor.cs index a663817aa8..7c70beb0a4 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoHealthProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoHealthProcessor.cs @@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Taiko.Scoring /// A for the taiko ruleset. /// Taiko fails if the player has not half-filled their health by the end of the map. /// - public class TaikoHealthProcessor : AccumulatingHealthProcessor + public partial class TaikoHealthProcessor : AccumulatingHealthProcessor { /// /// A value used for calculating . diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index 3b0bb952dd..4b60ee3ccb 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -7,7 +7,7 @@ using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Taiko.Scoring { - internal class TaikoScoreProcessor : ScoreProcessor + internal partial class TaikoScoreProcessor : ScoreProcessor { public TaikoScoreProcessor() : base(new TaikoRuleset()) diff --git a/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonBarLine.cs b/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonBarLine.cs index 402e88b64d..32afb8e6ac 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonBarLine.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonBarLine.cs @@ -12,7 +12,7 @@ using osuTK; namespace osu.Game.Rulesets.Taiko.Skinning.Argon { - public class ArgonBarLine : CompositeDrawable + public partial class ArgonBarLine : CompositeDrawable { private Container majorEdgeContainer = null!; diff --git a/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonCentreCirclePiece.cs b/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonCentreCirclePiece.cs index 551a5af078..dedb276d58 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonCentreCirclePiece.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonCentreCirclePiece.cs @@ -10,7 +10,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Taiko.Skinning.Argon { - public class ArgonCentreCirclePiece : ArgonCirclePiece + public partial class ArgonCentreCirclePiece : ArgonCirclePiece { [BackgroundDependencyLoader] private void load() diff --git a/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonCirclePiece.cs b/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonCirclePiece.cs index c22c0e9e79..d7e37899ce 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonCirclePiece.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonCirclePiece.cs @@ -14,7 +14,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Taiko.Skinning.Argon { - public abstract class ArgonCirclePiece : BeatSyncedContainer + public abstract partial class ArgonCirclePiece : BeatSyncedContainer { public const float ICON_SIZE = 20 / 70f; diff --git a/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonElongatedCirclePiece.cs b/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonElongatedCirclePiece.cs index f86f181b2e..17386cc659 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonElongatedCirclePiece.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonElongatedCirclePiece.cs @@ -8,7 +8,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Taiko.Skinning.Argon { - public class ArgonElongatedCirclePiece : ArgonCirclePiece + public partial class ArgonElongatedCirclePiece : ArgonCirclePiece { public ArgonElongatedCirclePiece() { diff --git a/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonHitExplosion.cs b/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonHitExplosion.cs index 05bb9bcb9a..a47fd7e62e 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonHitExplosion.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonHitExplosion.cs @@ -15,7 +15,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Taiko.Skinning.Argon { - public class ArgonHitExplosion : CompositeDrawable, IAnimatableHitExplosion + public partial class ArgonHitExplosion : CompositeDrawable, IAnimatableHitExplosion { private readonly TaikoSkinComponents component; private readonly Circle outer; diff --git a/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonHitTarget.cs b/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonHitTarget.cs index ec2eccd595..0ddcd6feb2 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonHitTarget.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonHitTarget.cs @@ -10,7 +10,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Taiko.Skinning.Argon { - public class ArgonHitTarget : CompositeDrawable + public partial class ArgonHitTarget : CompositeDrawable { /// /// Thickness of all drawn line pieces. diff --git a/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonInputDrum.cs b/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonInputDrum.cs index 528e75aabb..e7b0a5537a 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonInputDrum.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonInputDrum.cs @@ -17,7 +17,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Taiko.Skinning.Argon { - public class ArgonInputDrum : AspectContainer + public partial class ArgonInputDrum : AspectContainer { private const float rim_size = 0.3f; @@ -91,7 +91,7 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Argon /// /// A half-drum. Contains one centre and one rim hit. /// - private class TaikoHalfDrum : CompositeDrawable, IKeyBindingHandler + private partial class TaikoHalfDrum : CompositeDrawable, IKeyBindingHandler { /// /// The key to be used for the rim of the half-drum. diff --git a/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonJudgementPiece.cs b/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonJudgementPiece.cs index baaf9e41e2..bbd62ff85b 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonJudgementPiece.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonJudgementPiece.cs @@ -3,7 +3,6 @@ using System; using osu.Framework.Allocation; -using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -18,20 +17,16 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Taiko.Skinning.Argon { - public class ArgonJudgementPiece : CompositeDrawable, IAnimatableJudgement + public partial class ArgonJudgementPiece : JudgementPiece, IAnimatableJudgement { - protected readonly HitResult Result; - - protected SpriteText JudgementText { get; private set; } = null!; - private RingExplosion? ringExplosion; [Resolved] private OsuColour colours { get; set; } = null!; public ArgonJudgementPiece(HitResult result) + : base(result) { - Result = result; RelativePositionAxes = Axes.Both; RelativeSizeAxes = Axes.Both; } @@ -39,21 +34,6 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Argon [BackgroundDependencyLoader] private void load() { - InternalChildren = new Drawable[] - { - JudgementText = new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Text = Result.GetDescription().ToUpperInvariant(), - Colour = colours.ForHitResult(Result), - Blending = BlendingParameters.Additive, - Spacing = new Vector2(10, 0), - RelativePositionAxes = Axes.Both, - Font = OsuFont.Default.With(size: 20, weight: FontWeight.Regular), - }, - }; - if (Result.IsHit()) { AddInternal(ringExplosion = new RingExplosion(Result) @@ -64,6 +44,17 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Argon } } + protected override SpriteText CreateJudgementText() => + new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Blending = BlendingParameters.Additive, + Spacing = new Vector2(10, 0), + RelativePositionAxes = Axes.Both, + Font = OsuFont.Default.With(size: 20, weight: FontWeight.Regular), + }; + /// /// Plays the default animation for this judgement piece. /// @@ -105,7 +96,7 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Argon public Drawable? GetAboveHitObjectsProxiedContent() => null; - private class RingExplosion : CompositeDrawable + private partial class RingExplosion : CompositeDrawable { private readonly float travel = 58; @@ -174,7 +165,7 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Argon this.FadeOutFromOne(1000, Easing.OutQuint); } - public class RingPiece : CircularContainer + public partial class RingPiece : CircularContainer { public RingPiece(float thickness = 9) { diff --git a/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonPlayfieldBackgroundLeft.cs b/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonPlayfieldBackgroundLeft.cs index ebde83b607..07ac37b04c 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonPlayfieldBackgroundLeft.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonPlayfieldBackgroundLeft.cs @@ -8,7 +8,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Taiko.Skinning.Argon { - public class ArgonPlayfieldBackgroundLeft : CompositeDrawable + public partial class ArgonPlayfieldBackgroundLeft : CompositeDrawable { public ArgonPlayfieldBackgroundLeft() { diff --git a/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonPlayfieldBackgroundRight.cs b/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonPlayfieldBackgroundRight.cs index bd0f3ab276..41a3e3bb33 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonPlayfieldBackgroundRight.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonPlayfieldBackgroundRight.cs @@ -8,7 +8,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Taiko.Skinning.Argon { - public class ArgonPlayfieldBackgroundRight : CompositeDrawable + public partial class ArgonPlayfieldBackgroundRight : CompositeDrawable { public ArgonPlayfieldBackgroundRight() { diff --git a/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonRimCirclePiece.cs b/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonRimCirclePiece.cs index fd81221be3..b32326a90f 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonRimCirclePiece.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonRimCirclePiece.cs @@ -10,7 +10,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Taiko.Skinning.Argon { - public class ArgonRimCirclePiece : ArgonCirclePiece + public partial class ArgonRimCirclePiece : ArgonCirclePiece { [BackgroundDependencyLoader] private void load() diff --git a/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonSwellCirclePiece.cs b/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonSwellCirclePiece.cs index 82a6e34128..d93d8598f6 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonSwellCirclePiece.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonSwellCirclePiece.cs @@ -10,7 +10,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Taiko.Skinning.Argon { - public class ArgonSwellCirclePiece : ArgonCirclePiece + public partial class ArgonSwellCirclePiece : ArgonCirclePiece { [BackgroundDependencyLoader] private void load() diff --git a/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonTickPiece.cs b/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonTickPiece.cs index df63d4948e..5baa320201 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonTickPiece.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonTickPiece.cs @@ -14,7 +14,7 @@ using osuTK; namespace osu.Game.Rulesets.Taiko.Skinning.Argon { - public class ArgonTickPiece : CompositeDrawable + public partial class ArgonTickPiece : CompositeDrawable { private readonly Bindable isFirstTick = new Bindable(); diff --git a/osu.Game.Rulesets.Taiko/Skinning/Argon/RingPiece.cs b/osu.Game.Rulesets.Taiko/Skinning/Argon/RingPiece.cs index 534a1c71a3..719c1c36fa 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Argon/RingPiece.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Argon/RingPiece.cs @@ -8,7 +8,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Taiko.Skinning.Argon { - public class RingPiece : CircularContainer + public partial class RingPiece : CircularContainer { private readonly float relativeBorderThickness; diff --git a/osu.Game.Rulesets.Taiko/Skinning/Argon/TaikoArgonSkinTransformer.cs b/osu.Game.Rulesets.Taiko/Skinning/Argon/TaikoArgonSkinTransformer.cs index a5d091a1c8..780018af4e 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Argon/TaikoArgonSkinTransformer.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Argon/TaikoArgonSkinTransformer.cs @@ -19,6 +19,10 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Argon switch (component) { case GameplaySkinComponentLookup resultComponent: + // This should eventually be moved to a skin setting, when supported. + if (Skin is ArgonProSkin && resultComponent.Component >= HitResult.Great) + return Drawable.Empty(); + return new ArgonJudgementPiece(resultComponent.Component); case TaikoSkinComponentLookup taikoComponent: diff --git a/osu.Game.Rulesets.Taiko/Skinning/Default/CentreHitCirclePiece.cs b/osu.Game.Rulesets.Taiko/Skinning/Default/CentreHitCirclePiece.cs index 339ab35795..4ed5c3d0df 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Default/CentreHitCirclePiece.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Default/CentreHitCirclePiece.cs @@ -10,7 +10,7 @@ using osuTK; namespace osu.Game.Rulesets.Taiko.Skinning.Default { - public class CentreHitCirclePiece : CirclePiece + public partial class CentreHitCirclePiece : CirclePiece { public CentreHitCirclePiece() { @@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Default /// /// The symbol used for centre hit pieces. /// - public class CentreHitSymbolPiece : Container + public partial class CentreHitSymbolPiece : Container { public CentreHitSymbolPiece() { diff --git a/osu.Game.Rulesets.Taiko/Skinning/Default/CirclePiece.cs b/osu.Game.Rulesets.Taiko/Skinning/Default/CirclePiece.cs index 7ddc413d98..bde502bbed 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Default/CirclePiece.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Default/CirclePiece.cs @@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Default /// for a usage example. /// /// - public abstract class CirclePiece : BeatSyncedContainer, IHasAccentColour + public abstract partial class CirclePiece : BeatSyncedContainer, IHasAccentColour { public const float SYMBOL_SIZE = TaikoHitObject.DEFAULT_SIZE; public const float SYMBOL_BORDER = 8; diff --git a/osu.Game.Rulesets.Taiko/Skinning/Default/DefaultBarLine.cs b/osu.Game.Rulesets.Taiko/Skinning/Default/DefaultBarLine.cs index 973e685bc7..09965054e0 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Default/DefaultBarLine.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Default/DefaultBarLine.cs @@ -12,7 +12,7 @@ using osuTK; namespace osu.Game.Rulesets.Taiko.Skinning.Default { - public class DefaultBarLine : CompositeDrawable + public partial class DefaultBarLine : CompositeDrawable { /// /// The vertical offset of the triangles from the line tracker. diff --git a/osu.Game.Rulesets.Taiko/Skinning/Default/DefaultHitExplosion.cs b/osu.Game.Rulesets.Taiko/Skinning/Default/DefaultHitExplosion.cs index 2e76396a4d..8a70c4bde8 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Default/DefaultHitExplosion.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Default/DefaultHitExplosion.cs @@ -15,7 +15,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Taiko.Skinning.Default { - internal class DefaultHitExplosion : CircularContainer, IAnimatableHitExplosion + internal partial class DefaultHitExplosion : CircularContainer, IAnimatableHitExplosion { private readonly HitResult result; diff --git a/osu.Game.Rulesets.Taiko/Skinning/Default/DefaultInputDrum.cs b/osu.Game.Rulesets.Taiko/Skinning/Default/DefaultInputDrum.cs index 3d0578dbc0..6d19db999c 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Default/DefaultInputDrum.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Default/DefaultInputDrum.cs @@ -15,7 +15,7 @@ using osuTK; namespace osu.Game.Rulesets.Taiko.Skinning.Default { - public class DefaultInputDrum : AspectContainer + public partial class DefaultInputDrum : AspectContainer { public DefaultInputDrum() { @@ -64,7 +64,7 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Default /// /// A half-drum. Contains one centre and one rim hit. /// - private class TaikoHalfDrum : Container, IKeyBindingHandler + private partial class TaikoHalfDrum : Container, IKeyBindingHandler { /// /// The key to be used for the rim of the half-drum. diff --git a/osu.Game.Rulesets.Taiko/Skinning/Default/DefaultJudgementPiece.cs b/osu.Game.Rulesets.Taiko/Skinning/Default/DefaultJudgementPiece.cs index c85a8db788..c78d7719d0 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Default/DefaultJudgementPiece.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Default/DefaultJudgementPiece.cs @@ -6,7 +6,7 @@ using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Taiko.Skinning.Default { - public class DefaultJudgementPiece : Rulesets.Judgements.DefaultJudgementPiece + public partial class DefaultJudgementPiece : Rulesets.Judgements.DefaultJudgementPiece { public DefaultJudgementPiece(HitResult result) : base(result) diff --git a/osu.Game.Rulesets.Taiko/Skinning/Default/DefaultKiaiHitExplosion.cs b/osu.Game.Rulesets.Taiko/Skinning/Default/DefaultKiaiHitExplosion.cs index ae68d63d97..750fb505a0 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Default/DefaultKiaiHitExplosion.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Default/DefaultKiaiHitExplosion.cs @@ -12,7 +12,7 @@ using osuTK; namespace osu.Game.Rulesets.Taiko.Skinning.Default { - public class DefaultKiaiHitExplosion : CircularContainer + public partial class DefaultKiaiHitExplosion : CircularContainer { public override bool RemoveWhenNotAlive => true; diff --git a/osu.Game.Rulesets.Taiko/Skinning/Default/ElongatedCirclePiece.cs b/osu.Game.Rulesets.Taiko/Skinning/Default/ElongatedCirclePiece.cs index 210841bca0..11d82a3714 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Default/ElongatedCirclePiece.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Default/ElongatedCirclePiece.cs @@ -7,7 +7,7 @@ using osu.Game.Graphics; namespace osu.Game.Rulesets.Taiko.Skinning.Default { - public class ElongatedCirclePiece : CirclePiece + public partial class ElongatedCirclePiece : CirclePiece { public ElongatedCirclePiece() { diff --git a/osu.Game.Rulesets.Taiko/Skinning/Default/RimHitCirclePiece.cs b/osu.Game.Rulesets.Taiko/Skinning/Default/RimHitCirclePiece.cs index c6165495d8..0920d58a34 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Default/RimHitCirclePiece.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Default/RimHitCirclePiece.cs @@ -11,7 +11,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Taiko.Skinning.Default { - public class RimHitCirclePiece : CirclePiece + public partial class RimHitCirclePiece : CirclePiece { public RimHitCirclePiece() { @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Default /// /// The symbol used for rim hit pieces. /// - public class RimHitSymbolPiece : CircularContainer + public partial class RimHitSymbolPiece : CircularContainer { public RimHitSymbolPiece() { diff --git a/osu.Game.Rulesets.Taiko/Skinning/Default/SwellSymbolPiece.cs b/osu.Game.Rulesets.Taiko/Skinning/Default/SwellSymbolPiece.cs index 2f59cac3ff..d40b518aa3 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Default/SwellSymbolPiece.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Default/SwellSymbolPiece.cs @@ -10,7 +10,7 @@ using osuTK; namespace osu.Game.Rulesets.Taiko.Skinning.Default { - public class SwellCirclePiece : CirclePiece + public partial class SwellCirclePiece : CirclePiece { public SwellCirclePiece() { @@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Default /// /// The symbol used for swell pieces. /// - public class SwellSymbolPiece : Container + public partial class SwellSymbolPiece : Container { public SwellSymbolPiece() { diff --git a/osu.Game.Rulesets.Taiko/Skinning/Default/TickPiece.cs b/osu.Game.Rulesets.Taiko/Skinning/Default/TickPiece.cs index a1eaef53ba..8bd8d5f4b4 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Default/TickPiece.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Default/TickPiece.cs @@ -13,7 +13,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Taiko.Skinning.Default { - public class TickPiece : CompositeDrawable + public partial class TickPiece : CompositeDrawable { /// /// Any tick that is not the first for a drumroll is not filled, but is instead displayed diff --git a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyBarLine.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyBarLine.cs index 2b528ae8ce..01100bfd63 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyBarLine.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyBarLine.cs @@ -9,7 +9,7 @@ using osuTK; namespace osu.Game.Rulesets.Taiko.Skinning.Legacy { - public class LegacyBarLine : Sprite + public partial class LegacyBarLine : Sprite { [BackgroundDependencyLoader] private void load(ISkinSource skin) diff --git a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyCirclePiece.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyCirclePiece.cs index a5867ff51c..37eb95b86f 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyCirclePiece.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyCirclePiece.cs @@ -18,7 +18,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Taiko.Skinning.Legacy { - public class LegacyCirclePiece : CompositeDrawable, IHasAccentColour + public partial class LegacyCirclePiece : CompositeDrawable, IHasAccentColour { private Drawable backgroundLayer = null!; private Drawable? foregroundLayer; diff --git a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyDrumRoll.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyDrumRoll.cs index 1249231d92..5543a31ec9 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyDrumRoll.cs @@ -13,7 +13,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Taiko.Skinning.Legacy { - public class LegacyDrumRoll : CompositeDrawable, IHasAccentColour + public partial class LegacyDrumRoll : CompositeDrawable, IHasAccentColour { public override Quad ScreenSpaceDrawQuad { diff --git a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyHit.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyHit.cs index d93317f0e2..87c9d72d22 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyHit.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyHit.cs @@ -7,7 +7,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Taiko.Skinning.Legacy { - public class LegacyHit : LegacyCirclePiece + public partial class LegacyHit : LegacyCirclePiece { private readonly TaikoSkinComponents component; diff --git a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyHitExplosion.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyHitExplosion.cs index ff1546381b..b9a432f3bd 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyHitExplosion.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyHitExplosion.cs @@ -10,7 +10,7 @@ using osu.Game.Rulesets.Taiko.UI; namespace osu.Game.Rulesets.Taiko.Skinning.Legacy { - public class LegacyHitExplosion : CompositeDrawable, IAnimatableHitExplosion + public partial class LegacyHitExplosion : CompositeDrawable, IAnimatableHitExplosion { private readonly Drawable sprite; diff --git a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyInputDrum.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyInputDrum.cs index 0abb365750..8ad419f8bd 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyInputDrum.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyInputDrum.cs @@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy /// /// A component of the playfield that captures input and displays input as a drum. /// - internal class LegacyInputDrum : Container + internal partial class LegacyInputDrum : Container { private Container content = null!; private LegacyHalfDrum left = null!; @@ -96,7 +96,7 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy /// /// A half-drum. Contains one centre and one rim hit. /// - private class LegacyHalfDrum : Container, IKeyBindingHandler + private partial class LegacyHalfDrum : Container, IKeyBindingHandler { /// /// The key to be used for the rim of the half-drum. diff --git a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyKiaiGlow.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyKiaiGlow.cs new file mode 100644 index 0000000000..623243e9e1 --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyKiaiGlow.cs @@ -0,0 +1,65 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Framework.Allocation; +using osu.Framework.Audio.Track; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Sprites; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Graphics.Containers; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Scoring; +using osu.Game.Skinning; +using osuTK; + +namespace osu.Game.Rulesets.Taiko.Skinning.Legacy +{ + internal partial class LegacyKiaiGlow : BeatSyncedContainer + { + private bool isKiaiActive; + + private Sprite sprite = null!; + + [BackgroundDependencyLoader(true)] + private void load(ISkinSource skin, HealthProcessor? healthProcessor) + { + Child = sprite = new Sprite + { + Texture = skin.GetTexture("taiko-glow"), + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Alpha = 0, + Scale = new Vector2(0.7f), + Colour = new Colour4(255, 228, 0, 255), + }; + + if (healthProcessor != null) + healthProcessor.NewJudgement += onNewJudgement; + } + + protected override void Update() + { + base.Update(); + + if (isKiaiActive) + sprite.Alpha = (float)Math.Min(1, sprite.Alpha + Math.Abs(Clock.ElapsedFrameTime) / 100f); + else + sprite.Alpha = (float)Math.Max(0, sprite.Alpha - Math.Abs(Clock.ElapsedFrameTime) / 600f); + } + + protected override void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, ChannelAmplitudes amplitudes) + { + isKiaiActive = effectPoint.KiaiMode; + } + + private void onNewJudgement(JudgementResult result) + { + if (!result.IsHit || !isKiaiActive) + return; + + sprite.ScaleTo(0.85f).Then() + .ScaleTo(0.7f, 80, Easing.OutQuad); + } + } +} diff --git a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyTaikoScroller.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyTaikoScroller.cs index 4a2426bff5..2964473f89 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyTaikoScroller.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyTaikoScroller.cs @@ -15,7 +15,7 @@ using osuTK; namespace osu.Game.Rulesets.Taiko.Skinning.Legacy { - public class LegacyTaikoScroller : CompositeDrawable + public partial class LegacyTaikoScroller : CompositeDrawable { public Bindable LastResult = new Bindable(); @@ -87,7 +87,7 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy } } - private class ScrollerSprite : CompositeDrawable + private partial class ScrollerSprite : CompositeDrawable { private Sprite passingSprite = null!; private Sprite failingSprite = null!; diff --git a/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacyHitTarget.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacyHitTarget.cs index 21102f6eec..492782f0d1 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacyHitTarget.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacyHitTarget.cs @@ -11,7 +11,7 @@ using osuTK; namespace osu.Game.Rulesets.Taiko.Skinning.Legacy { - public class TaikoLegacyHitTarget : CompositeDrawable + public partial class TaikoLegacyHitTarget : CompositeDrawable { private Container content = null!; diff --git a/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacyPlayfieldBackgroundRight.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacyPlayfieldBackgroundRight.cs index 3186f615a7..85870d0fd6 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacyPlayfieldBackgroundRight.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacyPlayfieldBackgroundRight.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Allocation; using osu.Framework.Audio.Track; using osu.Framework.Graphics; @@ -12,11 +13,11 @@ using osuTK; namespace osu.Game.Rulesets.Taiko.Skinning.Legacy { - public class TaikoLegacyPlayfieldBackgroundRight : BeatSyncedContainer + public partial class TaikoLegacyPlayfieldBackgroundRight : BeatSyncedContainer { private Sprite kiai = null!; - private bool kiaiDisplayed; + private bool isKiaiActive; [BackgroundDependencyLoader] private void load(ISkinSource skin) @@ -41,17 +42,19 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy }; } + protected override void Update() + { + base.Update(); + + if (isKiaiActive) + kiai.Alpha = (float)Math.Min(1, kiai.Alpha + Math.Abs(Clock.ElapsedFrameTime) / 200f); + else + kiai.Alpha = (float)Math.Max(0, kiai.Alpha - Math.Abs(Clock.ElapsedFrameTime) / 200f); + } + protected override void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, ChannelAmplitudes amplitudes) { - base.OnNewBeat(beatIndex, timingPoint, effectPoint, amplitudes); - - if (effectPoint.KiaiMode != kiaiDisplayed) - { - kiaiDisplayed = effectPoint.KiaiMode; - - kiai.ClearTransforms(); - kiai.FadeTo(kiaiDisplayed ? 1 : 0, 200); - } + isKiaiActive = effectPoint.KiaiMode; } } } diff --git a/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacySkinTransformer.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacySkinTransformer.cs index 7bf99306f0..d61f9ac35d 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacySkinTransformer.cs @@ -129,6 +129,12 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy case TaikoSkinComponents.Mascot: return new DrawableTaikoMascot(); + case TaikoSkinComponents.KiaiGlow: + if (GetTexture("taiko-glow") != null) + return new LegacyKiaiGlow(); + + return null; + default: throw new UnsupportedSkinComponentException(lookup); } diff --git a/osu.Game.Rulesets.Taiko/TaikoInputManager.cs b/osu.Game.Rulesets.Taiko/TaikoInputManager.cs index d36fe5d496..ca06a0a77e 100644 --- a/osu.Game.Rulesets.Taiko/TaikoInputManager.cs +++ b/osu.Game.Rulesets.Taiko/TaikoInputManager.cs @@ -11,7 +11,7 @@ using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Taiko { [Cached] // Used for touch input, see DrumTouchInputArea. - public class TaikoInputManager : RulesetInputManager + public partial class TaikoInputManager : RulesetInputManager { public TaikoInputManager(RulesetInfo ruleset) : base(ruleset, 0, SimultaneousBindingMode.Unique) diff --git a/osu.Game.Rulesets.Taiko/TaikoSkinComponents.cs b/osu.Game.Rulesets.Taiko/TaikoSkinComponents.cs index bf48898dd2..b8e3313e1b 100644 --- a/osu.Game.Rulesets.Taiko/TaikoSkinComponents.cs +++ b/osu.Game.Rulesets.Taiko/TaikoSkinComponents.cs @@ -21,5 +21,6 @@ namespace osu.Game.Rulesets.Taiko TaikoExplosionKiai, Scroller, Mascot, + KiaiGlow } } diff --git a/osu.Game.Rulesets.Taiko/UI/BarLinePlayfield.cs b/osu.Game.Rulesets.Taiko/UI/BarLinePlayfield.cs index cb878e8ea0..ebdf9ef191 100644 --- a/osu.Game.Rulesets.Taiko/UI/BarLinePlayfield.cs +++ b/osu.Game.Rulesets.Taiko/UI/BarLinePlayfield.cs @@ -8,7 +8,7 @@ using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Taiko.UI { - public class BarLinePlayfield : ScrollingPlayfield + public partial class BarLinePlayfield : ScrollingPlayfield { [BackgroundDependencyLoader] private void load() diff --git a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoJudgement.cs b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoJudgement.cs index 24d2fd7be7..f91fe586f2 100644 --- a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoJudgement.cs +++ b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoJudgement.cs @@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Taiko.UI /// /// Text that is shown as judgement when a hit object is hit or missed. /// - public class DrawableTaikoJudgement : DrawableJudgement + public partial class DrawableTaikoJudgement : DrawableJudgement { public DrawableTaikoJudgement() { diff --git a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoMascot.cs b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoMascot.cs index dd0b61cdf5..0dfb796c74 100644 --- a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoMascot.cs +++ b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoMascot.cs @@ -16,10 +16,10 @@ using osu.Game.Screens.Play; namespace osu.Game.Rulesets.Taiko.UI { - public class DrawableTaikoMascot : BeatSyncedContainer + public partial class DrawableTaikoMascot : BeatSyncedContainer { public readonly Bindable State; - public readonly Bindable LastResult; + public readonly Bindable LastResult; private readonly Dictionary animations; @@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Taiko.UI Origin = Anchor = Anchor.BottomLeft; State = new Bindable(startingState); - LastResult = new Bindable(); + LastResult = new Bindable(); animations = new Dictionary(); } @@ -63,7 +63,7 @@ namespace osu.Game.Rulesets.Taiko.UI LastResult.BindValueChanged(onNewResult); } - private void onNewResult(ValueChangedEvent resultChangedEvent) + private void onNewResult(ValueChangedEvent resultChangedEvent) { var result = resultChangedEvent.NewValue; if (result == null) diff --git a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs index c3d93a344d..146daa8c27 100644 --- a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs @@ -27,11 +27,11 @@ using osuTK; namespace osu.Game.Rulesets.Taiko.UI { - public class DrawableTaikoRuleset : DrawableScrollingRuleset + public partial class DrawableTaikoRuleset : DrawableScrollingRuleset { public new BindableDouble TimeRange => base.TimeRange; - public readonly BindableBool LockPlayfieldAspect = new BindableBool(true); + public readonly BindableBool LockPlayfieldMaxAspect = new BindableBool(true); protected override ScrollVisualisationMethod VisualisationMethod => ScrollVisualisationMethod.Overlapping; @@ -78,7 +78,7 @@ namespace osu.Game.Rulesets.Taiko.UI public override PlayfieldAdjustmentContainer CreatePlayfieldAdjustmentContainer() => new TaikoPlayfieldAdjustmentContainer { - LockPlayfieldAspect = { BindTarget = LockPlayfieldAspect } + LockPlayfieldMaxAspect = { BindTarget = LockPlayfieldMaxAspect } }; protected override PassThroughInputManager CreateInputManager() => new TaikoInputManager(Ruleset.RulesetInfo); diff --git a/osu.Game.Rulesets.Taiko/UI/DrumRollHitContainer.cs b/osu.Game.Rulesets.Taiko/UI/DrumRollHitContainer.cs index ae37840825..87ee852171 100644 --- a/osu.Game.Rulesets.Taiko/UI/DrumRollHitContainer.cs +++ b/osu.Game.Rulesets.Taiko/UI/DrumRollHitContainer.cs @@ -6,7 +6,7 @@ using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Taiko.UI { - internal class DrumRollHitContainer : ScrollingHitObjectContainer + internal partial class DrumRollHitContainer : ScrollingHitObjectContainer { // TODO: this usage is buggy. // Because `LifetimeStart` is set based on scrolling, lifetime is not same as the time when the object is created. diff --git a/osu.Game.Rulesets.Taiko/UI/DrumSamplePlayer.cs b/osu.Game.Rulesets.Taiko/UI/DrumSamplePlayer.cs index b65e2af3d8..6454fb5afa 100644 --- a/osu.Game.Rulesets.Taiko/UI/DrumSamplePlayer.cs +++ b/osu.Game.Rulesets.Taiko/UI/DrumSamplePlayer.cs @@ -10,7 +10,7 @@ using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Taiko.UI { - internal class DrumSamplePlayer : CompositeDrawable, IKeyBindingHandler + internal partial class DrumSamplePlayer : CompositeDrawable, IKeyBindingHandler { private readonly DrumSampleTriggerSource leftRimSampleTriggerSource; private readonly DrumSampleTriggerSource leftCentreSampleTriggerSource; diff --git a/osu.Game.Rulesets.Taiko/UI/DrumSampleTriggerSource.cs b/osu.Game.Rulesets.Taiko/UI/DrumSampleTriggerSource.cs index 3279d128d3..4809791af8 100644 --- a/osu.Game.Rulesets.Taiko/UI/DrumSampleTriggerSource.cs +++ b/osu.Game.Rulesets.Taiko/UI/DrumSampleTriggerSource.cs @@ -8,7 +8,7 @@ using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Taiko.UI { - public class DrumSampleTriggerSource : GameplaySampleTriggerSource + public partial class DrumSampleTriggerSource : GameplaySampleTriggerSource { public DrumSampleTriggerSource(HitObjectContainer hitObjectContainer) : base(hitObjectContainer) diff --git a/osu.Game.Rulesets.Taiko/UI/DrumTouchInputArea.cs b/osu.Game.Rulesets.Taiko/UI/DrumTouchInputArea.cs index a7d9bd18c5..0232c10d65 100644 --- a/osu.Game.Rulesets.Taiko/UI/DrumTouchInputArea.cs +++ b/osu.Game.Rulesets.Taiko/UI/DrumTouchInputArea.cs @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Taiko.UI /// /// An overlay that captures and displays osu!taiko mouse and touch input. /// - public class DrumTouchInputArea : VisibilityContainer + public partial class DrumTouchInputArea : VisibilityContainer { // visibility state affects our child. we always want to handle input. public override bool PropagatePositionalInputSubTree => true; @@ -107,24 +107,6 @@ namespace osu.Game.Rulesets.Taiko.UI return false; } - protected override bool OnMouseDown(MouseDownEvent e) - { - if (!validMouse(e)) - return false; - - handleDown(e.Button, e.ScreenSpaceMousePosition); - return true; - } - - protected override void OnMouseUp(MouseUpEvent e) - { - if (!validMouse(e)) - return; - - handleUp(e.Button); - base.OnMouseUp(e); - } - protected override bool OnTouchDown(TouchDownEvent e) { handleDown(e.Touch.Source, e.ScreenSpaceTouchDownPosition); @@ -181,7 +163,7 @@ namespace osu.Game.Rulesets.Taiko.UI mainContent.FadeOut(300); } - private class QuarterCircle : CompositeDrawable, IKeyBindingHandler + private partial class QuarterCircle : CompositeDrawable, IKeyBindingHandler { private readonly Circle overlay; diff --git a/osu.Game.Rulesets.Taiko/UI/HitExplosion.cs b/osu.Game.Rulesets.Taiko/UI/HitExplosion.cs index 8f2b702472..1a2652acf9 100644 --- a/osu.Game.Rulesets.Taiko/UI/HitExplosion.cs +++ b/osu.Game.Rulesets.Taiko/UI/HitExplosion.cs @@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Taiko.UI /// /// A circle explodes from the hit target to indicate a hitobject has been hit. /// - internal class HitExplosion : PoolableDrawable + internal partial class HitExplosion : PoolableDrawable { public override bool RemoveWhenNotAlive => true; public override bool RemoveCompletedTransforms => false; diff --git a/osu.Game.Rulesets.Taiko/UI/HitExplosionPool.cs b/osu.Game.Rulesets.Taiko/UI/HitExplosionPool.cs index badf34554c..02a78b0f1c 100644 --- a/osu.Game.Rulesets.Taiko/UI/HitExplosionPool.cs +++ b/osu.Game.Rulesets.Taiko/UI/HitExplosionPool.cs @@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Taiko.UI /// /// Pool for hit explosions of a specific type. /// - internal class HitExplosionPool : DrawablePool + internal partial class HitExplosionPool : DrawablePool { private readonly HitResult hitResult; diff --git a/osu.Game.Rulesets.Taiko/UI/InputDrum.cs b/osu.Game.Rulesets.Taiko/UI/InputDrum.cs index 2f42a5aaf6..725857ed34 100644 --- a/osu.Game.Rulesets.Taiko/UI/InputDrum.cs +++ b/osu.Game.Rulesets.Taiko/UI/InputDrum.cs @@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Taiko.UI /// /// A component of the playfield that captures input and displays input as a drum. /// - internal class InputDrum : Container + internal partial class InputDrum : Container { public InputDrum() { diff --git a/osu.Game.Rulesets.Taiko/UI/KiaiHitExplosion.cs b/osu.Game.Rulesets.Taiko/UI/KiaiHitExplosion.cs index 627e06e186..6c1e981a97 100644 --- a/osu.Game.Rulesets.Taiko/UI/KiaiHitExplosion.cs +++ b/osu.Game.Rulesets.Taiko/UI/KiaiHitExplosion.cs @@ -12,7 +12,7 @@ using osuTK; namespace osu.Game.Rulesets.Taiko.UI { - public class KiaiHitExplosion : Container + public partial class KiaiHitExplosion : Container { public override bool RemoveWhenNotAlive => true; diff --git a/osu.Game.Rulesets.Taiko/UI/PlayfieldBackgroundLeft.cs b/osu.Game.Rulesets.Taiko/UI/PlayfieldBackgroundLeft.cs index 2a8890a95d..f676d051eb 100644 --- a/osu.Game.Rulesets.Taiko/UI/PlayfieldBackgroundLeft.cs +++ b/osu.Game.Rulesets.Taiko/UI/PlayfieldBackgroundLeft.cs @@ -11,7 +11,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Taiko.UI { - internal class PlayfieldBackgroundLeft : CompositeDrawable + internal partial class PlayfieldBackgroundLeft : CompositeDrawable { [BackgroundDependencyLoader] private void load(OsuColour colours) diff --git a/osu.Game.Rulesets.Taiko/UI/PlayfieldBackgroundRight.cs b/osu.Game.Rulesets.Taiko/UI/PlayfieldBackgroundRight.cs index 44bfdacf37..7b2dbc5f5a 100644 --- a/osu.Game.Rulesets.Taiko/UI/PlayfieldBackgroundRight.cs +++ b/osu.Game.Rulesets.Taiko/UI/PlayfieldBackgroundRight.cs @@ -12,7 +12,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Taiko.UI { - public class PlayfieldBackgroundRight : CompositeDrawable + public partial class PlayfieldBackgroundRight : CompositeDrawable { [BackgroundDependencyLoader] private void load(OsuColour colours) diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoHitTarget.cs b/osu.Game.Rulesets.Taiko/UI/TaikoHitTarget.cs index 6401c6d09f..a2f8dc83db 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoHitTarget.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoHitTarget.cs @@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.Taiko.UI /// /// A component that is displayed at the hit position in the taiko playfield. /// - internal class TaikoHitTarget : Container + internal partial class TaikoHitTarget : Container { /// /// Thickness of all drawn line pieces. diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoMascotAnimation.cs b/osu.Game.Rulesets.Taiko/UI/TaikoMascotAnimation.cs index 0f214b8436..7b1e31112e 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoMascotAnimation.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoMascotAnimation.cs @@ -14,7 +14,7 @@ using osuTK; namespace osu.Game.Rulesets.Taiko.UI { - public sealed class TaikoMascotAnimation : BeatSyncedContainer + public sealed partial class TaikoMascotAnimation : BeatSyncedContainer { private readonly TextureAnimation textureAnimation; @@ -73,7 +73,7 @@ namespace osu.Game.Rulesets.Taiko.UI } } - private class ManualMascotTextureAnimation : TextureAnimation + private partial class ManualMascotTextureAnimation : TextureAnimation { private readonly TaikoMascotAnimationState state; @@ -103,7 +103,7 @@ namespace osu.Game.Rulesets.Taiko.UI } } - private class ClearMascotTextureAnimation : TextureAnimation + private partial class ClearMascotTextureAnimation : TextureAnimation { private const float clear_animation_speed = 1000 / 10f; diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs index 45a3b80931..9f9debe7d7 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs @@ -28,7 +28,7 @@ using osuTK; namespace osu.Game.Rulesets.Taiko.UI { - public class TaikoPlayfield : ScrollingPlayfield + public partial class TaikoPlayfield : ScrollingPlayfield { /// /// Default height of a when inside a . @@ -112,6 +112,10 @@ namespace osu.Game.Rulesets.Taiko.UI FillMode = FillMode.Fit, Children = new[] { + new SkinnableDrawable(new TaikoSkinComponentLookup(TaikoSkinComponents.KiaiGlow), _ => Empty()) + { + RelativeSizeAxes = Axes.Both, + }, hitExplosionContainer = new Container { RelativeSizeAxes = Axes.Both, @@ -186,7 +190,7 @@ namespace osu.Game.Rulesets.Taiko.UI var hitWindows = new TaikoHitWindows(); - foreach (var result in Enum.GetValues(typeof(HitResult)).OfType().Where(r => hitWindows.IsHitResultAllowed(r))) + foreach (var result in Enum.GetValues().Where(r => hitWindows.IsHitResultAllowed(r))) { judgementPools.Add(result, new DrawablePool(15)); explosionPools.Add(result, new HitExplosionPool(result)); @@ -342,7 +346,7 @@ namespace osu.Game.Rulesets.Taiko.UI kiaiExplosionContainer.Add(new KiaiHitExplosion(drawableObject, type)); } - private class ProxyContainer : LifetimeManagementContainer + private partial class ProxyContainer : LifetimeManagementContainer { public void Add(Drawable proxy) => AddInternal(proxy); diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs index 9cf530e903..42732d90e4 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs @@ -8,12 +8,12 @@ using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Taiko.UI { - public class TaikoPlayfieldAdjustmentContainer : PlayfieldAdjustmentContainer + public partial class TaikoPlayfieldAdjustmentContainer : PlayfieldAdjustmentContainer { private const float default_relative_height = TaikoPlayfield.DEFAULT_HEIGHT / 768; private const float default_aspect = 16f / 9f; - public readonly IBindable LockPlayfieldAspect = new BindableBool(true); + public readonly IBindable LockPlayfieldMaxAspect = new BindableBool(true); protected override void Update() { @@ -21,7 +21,12 @@ namespace osu.Game.Rulesets.Taiko.UI float height = default_relative_height; - if (LockPlayfieldAspect.Value) + // Players coming from stable expect to be able to change the aspect ratio regardless of the window size. + // We originally wanted to limit this more, but there was considerable pushback from the community. + // + // As a middle-ground, the aspect ratio can still be adjusted in the downwards direction but has a maximum limit. + // This is still a bit weird, because readability changes with window size, but it is what it is. + if (LockPlayfieldMaxAspect.Value && Parent.ChildSize.X / Parent.ChildSize.Y > default_aspect) height *= Math.Clamp(Parent.ChildSize.X / Parent.ChildSize.Y, 0.4f, 4) / default_aspect; Height = height; diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoReplayRecorder.cs b/osu.Game.Rulesets.Taiko/UI/TaikoReplayRecorder.cs index e6391d1386..57ff3b59d5 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoReplayRecorder.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoReplayRecorder.cs @@ -10,7 +10,7 @@ using osuTK; namespace osu.Game.Rulesets.Taiko.UI { - public class TaikoReplayRecorder : ReplayRecorder + public partial class TaikoReplayRecorder : ReplayRecorder { public TaikoReplayRecorder(Score score) : base(score) diff --git a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj index b752c13d18..f0e1cb8e8f 100644 --- a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj +++ b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj @@ -1,6 +1,6 @@  - netstandard2.1 + net6.0 Library true bash the drum. to the beat. diff --git a/osu.Game.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Tests.Android/AndroidManifest.xml similarity index 95% rename from osu.Game.Tests.Android/Properties/AndroidManifest.xml rename to osu.Game.Tests.Android/AndroidManifest.xml index 4a63f0c357..f25b2e5328 100644 --- a/osu.Game.Tests.Android/Properties/AndroidManifest.xml +++ b/osu.Game.Tests.Android/AndroidManifest.xml @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/osu.Game.Tests.Android/MainActivity.cs b/osu.Game.Tests.Android/MainActivity.cs index 6c4f9bac58..bdb947fbb4 100644 --- a/osu.Game.Tests.Android/MainActivity.cs +++ b/osu.Game.Tests.Android/MainActivity.cs @@ -3,7 +3,9 @@ #nullable disable +using System.Reflection; using Android.App; +using Android.OS; using osu.Framework.Android; namespace osu.Game.Tests.Android @@ -12,5 +14,16 @@ namespace osu.Game.Tests.Android public class MainActivity : AndroidGameActivity { protected override Framework.Game CreateGame() => new OsuTestBrowser(); + + protected override void OnCreate(Bundle savedInstanceState) + { + base.OnCreate(savedInstanceState); + + // See the comment in OsuGameActivity + Assembly.Load("osu.Game.Rulesets.Osu"); + Assembly.Load("osu.Game.Rulesets.Taiko"); + Assembly.Load("osu.Game.Rulesets.Catch"); + Assembly.Load("osu.Game.Rulesets.Mania"); + } } } diff --git a/osu.Game.Tests.Android/osu.Game.Tests.Android.csproj b/osu.Game.Tests.Android/osu.Game.Tests.Android.csproj index afafec6b1f..b745d91980 100644 --- a/osu.Game.Tests.Android/osu.Game.Tests.Android.csproj +++ b/osu.Game.Tests.Android/osu.Game.Tests.Android.csproj @@ -1,88 +1,34 @@ - - + - Debug - AnyCPU - 8.0.30703 - 2.0 - {5CC222DC-5716-4499-B897-DCBDDA4A5CF9} - {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - {122416d6-6b49-4ee2-a1e8-b825f31c79fe} + net6.0-android + Exe osu.Game.Tests osu.Game.Tests.Android - Properties\AndroidManifest.xml - armeabi-v7a;x86;arm64-v8a - - - - - - $(NoWarn);CA2007 - - None - cjk;mideast;other;rare;west - true - - + %(RecursiveDir)%(Filename)%(Extension) - - + + %(RecursiveDir)%(Filename)%(Extension) - - - %(RecursiveDir)%(Filename)%(Extension) - - - %(RecursiveDir)%(Filename)%(Extension) - - - %(RecursiveDir)%(Filename)%(Extension) - - - %(RecursiveDir)%(Filename)%(Extension) - - - %(RecursiveDir)%(Filename)%(Extension) - - - %(RecursiveDir)%(Filename)%(Extension) - + Android\%(RecursiveDir)%(Filename)%(Extension) + - - {58f6c80c-1253-4a0e-a465-b8c85ebeadf3} - osu.Game.Rulesets.Catch - - - {48f4582b-7687-4621-9cbe-5c24197cb536} - osu.Game.Rulesets.Mania - - - {c92a607b-1fdd-4954-9f92-03ff547d9080} - osu.Game.Rulesets.Osu - - - {f167e17a-7de6-4af5-b920-a5112296c695} - osu.Game.Rulesets.Taiko - - - {2a66dd92-adb1-4994-89e2-c94e04acda0d} - osu.Game - + + + + + - - 5.0.0 - - diff --git a/osu.Game.Tests.iOS/Application.cs b/osu.Game.Tests.iOS/Application.cs index cf36fea139..4678be4fb8 100644 --- a/osu.Game.Tests.iOS/Application.cs +++ b/osu.Game.Tests.iOS/Application.cs @@ -3,7 +3,6 @@ #nullable disable -using osu.Framework.iOS; using UIKit; namespace osu.Game.Tests.iOS @@ -12,7 +11,7 @@ namespace osu.Game.Tests.iOS { public static void Main(string[] args) { - UIApplication.Main(args, typeof(GameUIApplication), typeof(AppDelegate)); + UIApplication.Main(args, null, typeof(AppDelegate)); } } } diff --git a/osu.Game.Tests.iOS/Info.plist b/osu.Game.Tests.iOS/Info.plist index 31e2b3f257..ac661f6263 100644 --- a/osu.Game.Tests.iOS/Info.plist +++ b/osu.Game.Tests.iOS/Info.plist @@ -13,7 +13,7 @@ LSRequiresIPhoneOS MinimumOSVersion - 10.0 + 13.4 UIDeviceFamily 1 diff --git a/osu.Game.Tests.iOS/osu.Game.Tests.iOS.csproj b/osu.Game.Tests.iOS/osu.Game.Tests.iOS.csproj index 05b3cad6da..79771fcd50 100644 --- a/osu.Game.Tests.iOS/osu.Game.Tests.iOS.csproj +++ b/osu.Game.Tests.iOS/osu.Game.Tests.iOS.csproj @@ -1,54 +1,26 @@ - - + - Debug - iPhoneSimulator Exe - {65FF8E19-6934-469B-B690-23C6D6E56A17} + net6.0-ios + 13.4 osu.Game.Tests osu.Game.Tests.iOS - - - - Linker.xml - - - %(RecursiveDir)%(Filename)%(Extension) - - $(NoWarn);CA2007 - - - {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D} - osu.Game - - - {C92A607B-1FDD-4954-9F92-03FF547D9080} - osu.Game.Rulesets.Osu - - - {58F6C80C-1253-4A0E-A465-B8C85EBEADF3} - osu.Game.Rulesets.Catch - - - {48F4582B-7687-4621-9CBE-5C24197CB536} - osu.Game.Rulesets.Mania - - - {F167E17A-7DE6-4AF5-B920-A5112296C695} - osu.Game.Rulesets.Taiko - + + + + + - diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index c6bdd25e8b..5787bd6066 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -314,6 +314,24 @@ namespace osu.Game.Tests.Beatmaps.Formats } } + [Test] + public void TestGetLastObjectTime() + { + var decoder = new LegacyBeatmapDecoder(); + + using (var resStream = TestResources.OpenResource("mania-last-object-not-latest.osu")) + using (var stream = new LineBufferedReader(resStream)) + { + var beatmap = decoder.Decode(stream); + + Assert.That(beatmap.HitObjects.Last().StartTime, Is.EqualTo(2494)); + Assert.That(beatmap.HitObjects.Last().GetEndTime(), Is.EqualTo(2494)); + + Assert.That(beatmap.HitObjects.Max(h => h.GetEndTime()), Is.EqualTo(2582)); + Assert.That(beatmap.GetLastObjectTime(), Is.EqualTo(2582)); + } + } + [Test] public void TestDecodeBeatmapComboOffsetsOsu() { diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyScoreDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyScoreDecoderTest.cs index cd6e5e7919..93cda34ef7 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyScoreDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyScoreDecoderTest.cs @@ -16,7 +16,9 @@ using osu.Game.Rulesets; using osu.Game.Rulesets.Catch; using osu.Game.Rulesets.Mania; using osu.Game.Rulesets.Mania.Mods; +using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Osu.Mods; using osu.Game.Rulesets.Osu.Replays; using osu.Game.Rulesets.Osu.UI; using osu.Game.Rulesets.Replays; @@ -179,6 +181,40 @@ namespace osu.Game.Tests.Beatmaps.Formats }); } + [Test] + public void TestSoloScoreData() + { + var ruleset = new OsuRuleset().RulesetInfo; + + var scoreInfo = TestResources.CreateTestScoreInfo(ruleset); + scoreInfo.Mods = new Mod[] + { + new OsuModDoubleTime { SpeedChange = { Value = 1.1 } } + }; + + var beatmap = new TestBeatmap(ruleset); + var score = new Score + { + ScoreInfo = scoreInfo, + Replay = new Replay + { + Frames = new List + { + new OsuReplayFrame(2000, OsuPlayfield.BASE_SIZE / 2, OsuAction.LeftButton) + } + } + }; + + var decodedAfterEncode = encodeThenDecode(LegacyBeatmapDecoder.LATEST_VERSION, score, beatmap); + + Assert.Multiple(() => + { + Assert.That(decodedAfterEncode.ScoreInfo.Statistics, Is.EqualTo(scoreInfo.Statistics)); + Assert.That(decodedAfterEncode.ScoreInfo.MaximumStatistics, Is.EqualTo(scoreInfo.MaximumStatistics)); + Assert.That(decodedAfterEncode.ScoreInfo.Mods, Is.EqualTo(scoreInfo.Mods)); + }); + } + private static Score encodeThenDecode(int beatmapVersion, Score score, TestBeatmap beatmap) { var encodeStream = new MemoryStream(); diff --git a/osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs b/osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs index 6eb103316f..ab40092b3f 100644 --- a/osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs +++ b/osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs @@ -22,7 +22,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Tests.Beatmaps { [HeadlessTest] - public class TestSceneBeatmapDifficultyCache : OsuTestScene + public partial class TestSceneBeatmapDifficultyCache : OsuTestScene { public const double BASE_STARS = 5.55; @@ -162,7 +162,7 @@ namespace osu.Game.Tests.Beatmaps Assert.AreEqual(expectedBracket, actualBracket); } - private class TestBeatmapDifficultyCache : BeatmapDifficultyCache + private partial class TestBeatmapDifficultyCache : BeatmapDifficultyCache { public Func ComputeDifficulty { get; set; } diff --git a/osu.Game.Tests/Beatmaps/TestSceneEditorBeatmap.cs b/osu.Game.Tests/Beatmaps/TestSceneEditorBeatmap.cs index 81d0e6f3ef..bb24560a44 100644 --- a/osu.Game.Tests/Beatmaps/TestSceneEditorBeatmap.cs +++ b/osu.Game.Tests/Beatmaps/TestSceneEditorBeatmap.cs @@ -18,7 +18,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Tests.Beatmaps { [HeadlessTest] - public class TestSceneEditorBeatmap : EditorClockTestScene + public partial class TestSceneEditorBeatmap : EditorClockTestScene { /// /// Tests that the addition event is correctly invoked after a hitobject is added. diff --git a/osu.Game.Tests/Beatmaps/WorkingBeatmapManagerTest.cs b/osu.Game.Tests/Beatmaps/WorkingBeatmapManagerTest.cs index 4ef466efbf..89b8c8927d 100644 --- a/osu.Game.Tests/Beatmaps/WorkingBeatmapManagerTest.cs +++ b/osu.Game.Tests/Beatmaps/WorkingBeatmapManagerTest.cs @@ -19,7 +19,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Tests.Beatmaps { [HeadlessTest] - public class WorkingBeatmapManagerTest : OsuTestScene + public partial class WorkingBeatmapManagerTest : OsuTestScene { private BeatmapManager beatmaps = null!; diff --git a/osu.Game.Tests/Chat/MessageFormatterTests.cs b/osu.Game.Tests/Chat/MessageFormatterTests.cs index ebfa9bd8b7..3c35dc311f 100644 --- a/osu.Game.Tests/Chat/MessageFormatterTests.cs +++ b/osu.Game.Tests/Chat/MessageFormatterTests.cs @@ -26,6 +26,16 @@ namespace osu.Game.Tests.Chat MessageFormatter.WebsiteRootUrl = originalWebsiteRootUrl; } + [Test] + public void TestUnsupportedProtocolLink() + { + Message result = MessageFormatter.FormatMessage(new Message { Content = "This is a gopher://really-old-protocol we don't support." }); + + Assert.AreEqual(result.Content, result.DisplayContent); + Assert.AreEqual(1, result.Links.Count); + Assert.AreEqual("gopher://really-old-protocol", result.Links[0].Url); + } + [Test] public void TestBareLink() { diff --git a/osu.Game.Tests/Chat/TestSceneChannelManager.cs b/osu.Game.Tests/Chat/TestSceneChannelManager.cs index c9a78cbf59..3a4c55c65c 100644 --- a/osu.Game.Tests/Chat/TestSceneChannelManager.cs +++ b/osu.Game.Tests/Chat/TestSceneChannelManager.cs @@ -18,7 +18,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Tests.Chat { [HeadlessTest] - public class TestSceneChannelManager : OsuTestScene + public partial class TestSceneChannelManager : OsuTestScene { private ChannelManager channelManager; private int currentMessageId; @@ -75,6 +75,8 @@ namespace osu.Game.Tests.Chat return false; }; }); + + AddUntilStep("wait for notifications client", () => channelManager.NotificationsConnected); } [Test] @@ -183,7 +185,7 @@ namespace osu.Game.Tests.Chat LastMessageId = 0, }; - private class ChannelManagerContainer : CompositeDrawable + private partial class ChannelManagerContainer : CompositeDrawable { [Cached] public ChannelManager ChannelManager { get; } diff --git a/osu.Game.Tests/Database/BackgroundBeatmapProcessorTests.cs b/osu.Game.Tests/Database/BackgroundBeatmapProcessorTests.cs index 4012e3f851..ddb60606ec 100644 --- a/osu.Game.Tests/Database/BackgroundBeatmapProcessorTests.cs +++ b/osu.Game.Tests/Database/BackgroundBeatmapProcessorTests.cs @@ -15,7 +15,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Tests.Database { [HeadlessTest] - public class BackgroundBeatmapProcessorTests : OsuTestScene, ILocalUserPlayInfo + public partial class BackgroundBeatmapProcessorTests : OsuTestScene, ILocalUserPlayInfo { public IBindable IsPlaying => isPlaying; @@ -124,7 +124,7 @@ namespace osu.Game.Tests.Database }); } - public class TestBackgroundBeatmapProcessor : BackgroundBeatmapProcessor + public partial class TestBackgroundBeatmapProcessor : BackgroundBeatmapProcessor { protected override int TimeToSleepDuringGameplay => 10; } diff --git a/osu.Game.Tests/Database/BeatmapImporterTests.cs b/osu.Game.Tests/Database/BeatmapImporterTests.cs index 56964aa8b2..446eb72b04 100644 --- a/osu.Game.Tests/Database/BeatmapImporterTests.cs +++ b/osu.Game.Tests/Database/BeatmapImporterTests.cs @@ -564,7 +564,7 @@ namespace osu.Game.Tests.Database var imported = await importer.Import( progressNotification, - new ImportTask(zipStream, string.Empty) + new[] { new ImportTask(zipStream, string.Empty) } ); realm.Run(r => r.Refresh()); @@ -1052,7 +1052,7 @@ namespace osu.Game.Tests.Database { string? temp = path ?? TestResources.GetTestBeatmapForImport(virtualTrack); - var importedSet = await importer.Import(new ImportTask(temp), batchImport); + var importedSet = await importer.Import(new ImportTask(temp), new ImportParameters { Batch = batchImport }); Assert.NotNull(importedSet); Debug.Assert(importedSet != null); diff --git a/osu.Game.Tests/Database/RealmTest.cs b/osu.Game.Tests/Database/RealmTest.cs index 1b1878942b..d2779e3038 100644 --- a/osu.Game.Tests/Database/RealmTest.cs +++ b/osu.Game.Tests/Database/RealmTest.cs @@ -18,7 +18,7 @@ using osu.Game.Rulesets; namespace osu.Game.Tests.Database { [TestFixture] - public abstract class RealmTest + public abstract partial class RealmTest { protected void RunTestWithRealm([InstantHandle] Action testAction, [CallerMemberName] string caller = "") { @@ -107,7 +107,7 @@ namespace osu.Game.Tests.Database protected static RulesetInfo CreateRuleset() => new RulesetInfo("osu", "osu!", string.Empty, 0) { Available = true }; - private class RealmTestGame : Framework.Game + private partial class RealmTestGame : Framework.Game { public RealmTestGame([InstantHandle] Func work) { diff --git a/osu.Game.Tests/Database/TestRealmKeyBindingStore.cs b/osu.Game.Tests/Database/TestRealmKeyBindingStore.cs index 362b37124d..f4467867db 100644 --- a/osu.Game.Tests/Database/TestRealmKeyBindingStore.cs +++ b/osu.Game.Tests/Database/TestRealmKeyBindingStore.cs @@ -20,7 +20,7 @@ using Realms; namespace osu.Game.Tests.Database { [TestFixture] - public class TestRealmKeyBindingStore + public partial class TestRealmKeyBindingStore { private NativeStorage storage; @@ -123,7 +123,7 @@ namespace osu.Game.Tests.Database storage.DeleteDirectory(string.Empty); } - public class TestKeyBindingContainer : KeyBindingContainer + public partial class TestKeyBindingContainer : KeyBindingContainer { public override IEnumerable DefaultKeyBindings => new[] diff --git a/osu.Game.Tests/Editing/TestSceneHitObjectComposerDistanceSnapping.cs b/osu.Game.Tests/Editing/TestSceneHitObjectComposerDistanceSnapping.cs index 495a221159..f556f6e2fe 100644 --- a/osu.Game.Tests/Editing/TestSceneHitObjectComposerDistanceSnapping.cs +++ b/osu.Game.Tests/Editing/TestSceneHitObjectComposerDistanceSnapping.cs @@ -20,7 +20,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Tests.Editing { [HeadlessTest] - public class TestSceneHitObjectComposerDistanceSnapping : EditorClockTestScene + public partial class TestSceneHitObjectComposerDistanceSnapping : EditorClockTestScene { private TestHitObjectComposer composer = null!; @@ -251,7 +251,7 @@ namespace osu.Game.Tests.Editing private void assertSnappedDistance(float distance, float expectedDistance, HitObject? referenceObject = null) => AddAssert($"distance = {distance} -> distance = {expectedDistance} (snapped)", () => composer.FindSnappedDistance(referenceObject ?? new HitObject(), distance), () => Is.EqualTo(expectedDistance).Within(Precision.FLOAT_EPSILON)); - private class TestHitObjectComposer : OsuHitObjectComposer + private partial class TestHitObjectComposer : OsuHitObjectComposer { public new EditorBeatmap EditorBeatmap => base.EditorBeatmap; diff --git a/osu.Game.Tests/Editing/TestSceneHitObjectContainerEventBuffer.cs b/osu.Game.Tests/Editing/TestSceneHitObjectContainerEventBuffer.cs index c3e171684c..745c636166 100644 --- a/osu.Game.Tests/Editing/TestSceneHitObjectContainerEventBuffer.cs +++ b/osu.Game.Tests/Editing/TestSceneHitObjectContainerEventBuffer.cs @@ -16,7 +16,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Tests.Editing { [HeadlessTest] - public class TestSceneHitObjectContainerEventBuffer : OsuTestScene + public partial class TestSceneHitObjectContainerEventBuffer : OsuTestScene { private readonly TestHitObject testObj = new TestHitObject(); @@ -139,7 +139,7 @@ namespace osu.Game.Tests.Editing => AddAssert($"began = {began}, finished = {finished}, transferred = {transferred}", () => (beganUsage == testObj) == began && (finishedUsage == testObj) == finished && (transferredUsage == testObj) == transferred); - private class TestPlayfield : Playfield + private partial class TestPlayfield : Playfield { public TestPlayfield() { @@ -165,11 +165,11 @@ namespace osu.Game.Tests.Editing public override string ToString() => "TestHitObject"; } - private class TestDrawableHitObject : DrawableHitObject + private partial class TestDrawableHitObject : DrawableHitObject { } - private class TestDrawable : Drawable + private partial class TestDrawable : Drawable { public new void Schedule(Action action) => base.Schedule(action); } diff --git a/osu.Game.Tests/Editing/TransactionalCommitComponentTest.cs b/osu.Game.Tests/Editing/TransactionalCommitComponentTest.cs index 3d7286c396..7280631e32 100644 --- a/osu.Game.Tests/Editing/TransactionalCommitComponentTest.cs +++ b/osu.Game.Tests/Editing/TransactionalCommitComponentTest.cs @@ -10,7 +10,7 @@ using osu.Game.Screens.Edit; namespace osu.Game.Tests.Editing { [TestFixture] - public class TransactionalCommitComponentTest + public partial class TransactionalCommitComponentTest { private TestHandler handler; @@ -89,7 +89,7 @@ namespace osu.Game.Tests.Editing Assert.That(() => handler.EndChange(), Throws.TypeOf()); } - private class TestHandler : TransactionalCommitComponent + private partial class TestHandler : TransactionalCommitComponent { public int StateUpdateCount { get; private set; } diff --git a/osu.Game.Tests/Gameplay/TestSceneDrainingHealthProcessor.cs b/osu.Game.Tests/Gameplay/TestSceneDrainingHealthProcessor.cs index c4e8bbfccf..fd0bff101f 100644 --- a/osu.Game.Tests/Gameplay/TestSceneDrainingHealthProcessor.cs +++ b/osu.Game.Tests/Gameplay/TestSceneDrainingHealthProcessor.cs @@ -21,7 +21,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Tests.Gameplay { [HeadlessTest] - public class TestSceneDrainingHealthProcessor : OsuTestScene + public partial class TestSceneDrainingHealthProcessor : OsuTestScene { private HealthProcessor processor; private ManualClock clock; diff --git a/osu.Game.Tests/Gameplay/TestSceneDrawableHitObject.cs b/osu.Game.Tests/Gameplay/TestSceneDrawableHitObject.cs index 91e33b759c..04fc4cafbd 100644 --- a/osu.Game.Tests/Gameplay/TestSceneDrawableHitObject.cs +++ b/osu.Game.Tests/Gameplay/TestSceneDrawableHitObject.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics; using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring; @@ -16,7 +17,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Tests.Gameplay { [HeadlessTest] - public class TestSceneDrawableHitObject : OsuTestScene + public partial class TestSceneDrawableHitObject : OsuTestScene { [Test] public void TestEntryLifetime() @@ -137,7 +138,32 @@ namespace osu.Game.Tests.Gameplay AddAssert("DHO state is correct", () => dho.State.Value == ArmedState.Miss); } - private class TestDrawableHitObject : DrawableHitObject + [Test] + public void TestResultSetBeforeLoadComplete() + { + TestDrawableHitObject dho = null; + HitObjectLifetimeEntry lifetimeEntry = null; + AddStep("Create lifetime entry", () => + { + var hitObject = new HitObject { StartTime = Time.Current }; + lifetimeEntry = new HitObjectLifetimeEntry(hitObject) + { + Result = new JudgementResult(hitObject, hitObject.CreateJudgement()) + { + Type = HitResult.Great + } + }; + }); + AddStep("Create DHO and apply entry", () => + { + dho = new TestDrawableHitObject(); + dho.Apply(lifetimeEntry); + Child = dho; + }); + AddAssert("DHO state is correct", () => dho.State.Value, () => Is.EqualTo(ArmedState.Hit)); + } + + private partial class TestDrawableHitObject : DrawableHitObject { public const double INITIAL_LIFETIME_OFFSET = 100; public const double LIFETIME_ON_APPLY = 222; diff --git a/osu.Game.Tests/Gameplay/TestSceneHitObjectAccentColour.cs b/osu.Game.Tests/Gameplay/TestSceneHitObjectAccentColour.cs index 255d6400c8..f38c2c9416 100644 --- a/osu.Game.Tests/Gameplay/TestSceneHitObjectAccentColour.cs +++ b/osu.Game.Tests/Gameplay/TestSceneHitObjectAccentColour.cs @@ -25,7 +25,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Gameplay { [HeadlessTest] - public class TestSceneHitObjectAccentColour : OsuTestScene + public partial class TestSceneHitObjectAccentColour : OsuTestScene { [Resolved] private OsuConfigManager config { get; set; } @@ -84,7 +84,7 @@ namespace osu.Game.Tests.Gameplay AddAssert("combo colour is green", () => hitObject.AccentColour.Value == Color4.Green); } - private class TestDrawableHitObject : DrawableHitObject + private partial class TestDrawableHitObject : DrawableHitObject { public TestDrawableHitObject() : base(new TestHitObjectWithCombo()) diff --git a/osu.Game.Tests/Gameplay/TestSceneHitObjectContainer.cs b/osu.Game.Tests/Gameplay/TestSceneHitObjectContainer.cs index 79e64ba2a2..8322833187 100644 --- a/osu.Game.Tests/Gameplay/TestSceneHitObjectContainer.cs +++ b/osu.Game.Tests/Gameplay/TestSceneHitObjectContainer.cs @@ -14,7 +14,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Tests.Gameplay { [HeadlessTest] - public class TestSceneHitObjectContainer : OsuTestScene + public partial class TestSceneHitObjectContainer : OsuTestScene { private HitObjectContainer container; @@ -66,7 +66,7 @@ namespace osu.Game.Tests.Gameplay AddAssert("second object index is 0", () => container.IndexOf(secondObject) == 1); } - private class TestDrawableHitObject : DrawableHitObject + private partial class TestDrawableHitObject : DrawableHitObject { public TestDrawableHitObject([NotNull] HitObject hitObject) : base(hitObject) diff --git a/osu.Game.Tests/Gameplay/TestSceneHitObjectSamples.cs b/osu.Game.Tests/Gameplay/TestSceneHitObjectSamples.cs index e25d08f98c..769ca1f9a9 100644 --- a/osu.Game.Tests/Gameplay/TestSceneHitObjectSamples.cs +++ b/osu.Game.Tests/Gameplay/TestSceneHitObjectSamples.cs @@ -13,7 +13,7 @@ using static osu.Game.Skinning.SkinConfiguration; namespace osu.Game.Tests.Gameplay { - public class TestSceneHitObjectSamples : HitObjectSampleTest + public partial class TestSceneHitObjectSamples : HitObjectSampleTest { protected override Ruleset CreatePlayerRuleset() => new OsuRuleset(); protected override IResourceStore RulesetResources => TestResources.GetStore(); diff --git a/osu.Game.Tests/Gameplay/TestSceneMasterGameplayClockContainer.cs b/osu.Game.Tests/Gameplay/TestSceneMasterGameplayClockContainer.cs index abd734b96c..393217f371 100644 --- a/osu.Game.Tests/Gameplay/TestSceneMasterGameplayClockContainer.cs +++ b/osu.Game.Tests/Gameplay/TestSceneMasterGameplayClockContainer.cs @@ -17,7 +17,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Tests.Gameplay { [HeadlessTest] - public class TestSceneMasterGameplayClockContainer : OsuTestScene + public partial class TestSceneMasterGameplayClockContainer : OsuTestScene { private OsuConfigManager localConfig; @@ -73,16 +73,6 @@ namespace osu.Game.Tests.Gameplay } [Test] - [FlakyTest] - /* - * Fail rate around 0.15% - * - * TearDown : osu.Framework.Testing.Drawables.Steps.AssertButton+TracedException : gameplay clock time = 2500 - * --TearDown - * at osu.Framework.Threading.ScheduledDelegate.RunTaskInternal() - * at osu.Framework.Threading.Scheduler.Update() - * at osu.Framework.Graphics.Drawable.UpdateSubTree() - */ public void TestSeekPerformsInGameplayTime( [Values(1.0, 0.5, 2.0)] double clockRate, [Values(0.0, 200.0, -200.0)] double userOffset, @@ -92,6 +82,9 @@ namespace osu.Game.Tests.Gameplay ClockBackedTestWorkingBeatmap working = null; GameplayClockContainer gameplayClockContainer = null; + // ReSharper disable once NotAccessedVariable + BindableDouble trackAdjustment = null; // keeping a reference for track adjustment + if (setAudioOffsetBeforeConstruction) AddStep($"preset audio offset to {userOffset}", () => localConfig.SetValue(OsuSetting.AudioOffset, userOffset)); @@ -103,16 +96,16 @@ namespace osu.Game.Tests.Gameplay gameplayClockContainer.Reset(startClock: !whileStopped); }); - AddStep($"set clock rate to {clockRate}", () => working.Track.AddAdjustment(AdjustableProperty.Frequency, new BindableDouble(clockRate))); + AddStep($"set clock rate to {clockRate}", () => working.Track.AddAdjustment(AdjustableProperty.Frequency, trackAdjustment = new BindableDouble(clockRate))); if (!setAudioOffsetBeforeConstruction) AddStep($"set audio offset to {userOffset}", () => localConfig.SetValue(OsuSetting.AudioOffset, userOffset)); AddStep("seek to 2500", () => gameplayClockContainer.Seek(2500)); - AddStep("gameplay clock time = 2500", () => Assert.AreEqual(gameplayClockContainer.CurrentTime, 2500, 10f)); + AddAssert("gameplay clock time = 2500", () => gameplayClockContainer.CurrentTime, () => Is.EqualTo(2500).Within(10f)); AddStep("seek to 10000", () => gameplayClockContainer.Seek(10000)); - AddStep("gameplay clock time = 10000", () => Assert.AreEqual(gameplayClockContainer.CurrentTime, 10000, 10f)); + AddAssert("gameplay clock time = 10000", () => gameplayClockContainer.CurrentTime, () => Is.EqualTo(10000).Within(10f)); } protected override void Dispose(bool isDisposing) diff --git a/osu.Game.Tests/Gameplay/TestSceneProxyContainer.cs b/osu.Game.Tests/Gameplay/TestSceneProxyContainer.cs index 1893e43f43..be69b77e8b 100644 --- a/osu.Game.Tests/Gameplay/TestSceneProxyContainer.cs +++ b/osu.Game.Tests/Gameplay/TestSceneProxyContainer.cs @@ -17,7 +17,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Tests.Gameplay { [HeadlessTest] - public class TestSceneProxyContainer : OsuTestScene + public partial class TestSceneProxyContainer : OsuTestScene { private HitObjectContainer hitObjectContainer; private ProxyContainer proxyContainer; @@ -62,14 +62,14 @@ namespace osu.Game.Tests.Gameplay proxyContainer.AddProxy(drawableHitObject); } - private class ProxyContainer : LifetimeManagementContainer + private partial class ProxyContainer : LifetimeManagementContainer { public IReadOnlyList AliveChildren => AliveInternalChildren; public void AddProxy(Drawable d) => AddInternal(d.CreateProxy()); } - private class TestDrawableHitObject : DrawableHitObject + private partial class TestDrawableHitObject : DrawableHitObject { protected override double InitialLifetimeOffset => 100; diff --git a/osu.Game.Tests/Gameplay/TestSceneScoreProcessor.cs b/osu.Game.Tests/Gameplay/TestSceneScoreProcessor.cs index d5219f6391..90c7688443 100644 --- a/osu.Game.Tests/Gameplay/TestSceneScoreProcessor.cs +++ b/osu.Game.Tests/Gameplay/TestSceneScoreProcessor.cs @@ -8,6 +8,7 @@ using System.Collections.Generic; using System.Linq; using NUnit.Framework; using osu.Framework.Testing; +using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Online.Spectator; using osu.Game.Rulesets.Judgements; @@ -22,7 +23,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Tests.Gameplay { [HeadlessTest] - public class TestSceneScoreProcessor : OsuTestScene + public partial class TestSceneScoreProcessor : OsuTestScene { [Test] public void TestNoScoreIncreaseFromMiss() @@ -139,6 +140,29 @@ namespace osu.Game.Tests.Gameplay Assert.That(score.MaximumStatistics[HitResult.LargeBonus], Is.EqualTo(1)); } + [Test] + public void TestAccuracyModes() + { + var beatmap = new Beatmap + { + HitObjects = Enumerable.Range(0, 4).Select(_ => new TestHitObject(HitResult.Great)).ToList() + }; + + var scoreProcessor = new ScoreProcessor(new OsuRuleset()); + scoreProcessor.ApplyBeatmap(beatmap); + + Assert.That(scoreProcessor.Accuracy.Value, Is.EqualTo(1)); + Assert.That(scoreProcessor.MinimumAccuracy.Value, Is.EqualTo(0)); + Assert.That(scoreProcessor.MaximumAccuracy.Value, Is.EqualTo(1)); + + scoreProcessor.ApplyResult(new JudgementResult(beatmap.HitObjects[0], beatmap.HitObjects[0].CreateJudgement()) { Type = HitResult.Ok }); + scoreProcessor.ApplyResult(new JudgementResult(beatmap.HitObjects[1], beatmap.HitObjects[1].CreateJudgement()) { Type = HitResult.Great }); + + Assert.That(scoreProcessor.Accuracy.Value, Is.EqualTo((double)(100 + 300) / (2 * 300)).Within(Precision.DOUBLE_EPSILON)); + Assert.That(scoreProcessor.MinimumAccuracy.Value, Is.EqualTo((double)(100 + 300) / (4 * 300)).Within(Precision.DOUBLE_EPSILON)); + Assert.That(scoreProcessor.MaximumAccuracy.Value, Is.EqualTo((double)(100 + 3 * 300) / (4 * 300)).Within(Precision.DOUBLE_EPSILON)); + } + private class TestJudgement : Judgement { public override HitResult MaxResult { get; } diff --git a/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs b/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs index 577933eae3..2cad7d33c2 100644 --- a/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs +++ b/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs @@ -33,7 +33,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Tests.Gameplay { [HeadlessTest] - public class TestSceneStoryboardSamples : OsuTestScene, IStorageResourceProvider + public partial class TestSceneStoryboardSamples : OsuTestScene, IStorageResourceProvider { [Resolved] private OsuConfigManager config { get; set; } @@ -199,7 +199,7 @@ namespace osu.Game.Tests.Gameplay protected internal override ISkin GetSkin() => new TestSkin("test-sample", resources); } - private class TestDrawableStoryboardSample : DrawableStoryboardSample + private partial class TestDrawableStoryboardSample : DrawableStoryboardSample { public TestDrawableStoryboardSample(StoryboardSampleInfo sampleInfo) : base(sampleInfo) diff --git a/osu.Game.Tests/ImportTest.cs b/osu.Game.Tests/ImportTest.cs index 23ca31ee42..9e2c9cd7e0 100644 --- a/osu.Game.Tests/ImportTest.cs +++ b/osu.Game.Tests/ImportTest.cs @@ -15,7 +15,7 @@ using osu.Game.Tests.Resources; namespace osu.Game.Tests { - public abstract class ImportTest + public abstract partial class ImportTest { protected virtual TestOsuGameBase LoadOsuIntoHost(GameHost host, bool withBeatmap = false) { @@ -45,7 +45,7 @@ namespace osu.Game.Tests Assert.IsTrue(task.Wait(timeout), failureMessage); } - public class TestOsuGameBase : OsuGameBase + public partial class TestOsuGameBase : OsuGameBase { public RealmAccess Realm => Dependencies.Get(); diff --git a/osu.Game.Tests/Input/ConfineMouseTrackerTest.cs b/osu.Game.Tests/Input/ConfineMouseTrackerTest.cs index a91d4553de..3c296b2ff5 100644 --- a/osu.Game.Tests/Input/ConfineMouseTrackerTest.cs +++ b/osu.Game.Tests/Input/ConfineMouseTrackerTest.cs @@ -15,7 +15,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Tests.Input { [HeadlessTest] - public class ConfineMouseTrackerTest : OsuGameTestScene + public partial class ConfineMouseTrackerTest : OsuGameTestScene { [Resolved] private FrameworkConfigManager frameworkConfigManager { get; set; } diff --git a/osu.Game.Tests/Mods/MultiModIncompatibilityTest.cs b/osu.Game.Tests/Mods/MultiModIncompatibilityTest.cs index b8a3828a64..ca5240a39d 100644 --- a/osu.Game.Tests/Mods/MultiModIncompatibilityTest.cs +++ b/osu.Game.Tests/Mods/MultiModIncompatibilityTest.cs @@ -60,6 +60,6 @@ namespace osu.Game.Tests.Mods /// This local helper is used rather than , because the aforementioned method flattens multi mods. /// > private static IEnumerable getMultiMods(Ruleset ruleset) - => Enum.GetValues(typeof(ModType)).Cast().SelectMany(ruleset.GetModsFor).OfType(); + => Enum.GetValues().SelectMany(ruleset.GetModsFor).OfType(); } } diff --git a/osu.Game.Tests/Mods/SettingsSourceAttributeTest.cs b/osu.Game.Tests/Mods/SettingsSourceAttributeTest.cs index dd105787fa..bf59862787 100644 --- a/osu.Game.Tests/Mods/SettingsSourceAttributeTest.cs +++ b/osu.Game.Tests/Mods/SettingsSourceAttributeTest.cs @@ -12,7 +12,7 @@ using osu.Game.Overlays.Settings; namespace osu.Game.Tests.Mods { [TestFixture] - public class SettingsSourceAttributeTest + public partial class SettingsSourceAttributeTest { [Test] public void TestOrdering() @@ -60,11 +60,11 @@ namespace osu.Game.Tests.Mods public BindableInt UnorderedSetting { get; set; } = new BindableInt(); } - private class CustomSettingsControl : SettingsItem + private partial class CustomSettingsControl : SettingsItem { protected override Drawable CreateControl() => new CustomControl(); - private class CustomControl : Drawable, IHasCurrentValue + private partial class CustomControl : Drawable, IHasCurrentValue { public Bindable Current { get; set; } = new Bindable(); } diff --git a/osu.Game.Tests/NonVisual/FirstAvailableHitWindowsTest.cs b/osu.Game.Tests/NonVisual/FirstAvailableHitWindowsTest.cs index 14da07bc2d..9a32b8e894 100644 --- a/osu.Game.Tests/NonVisual/FirstAvailableHitWindowsTest.cs +++ b/osu.Game.Tests/NonVisual/FirstAvailableHitWindowsTest.cs @@ -18,7 +18,7 @@ using osu.Game.Scoring; namespace osu.Game.Tests.NonVisual { - public class FirstAvailableHitWindowsTest + public partial class FirstAvailableHitWindowsTest { private TestDrawableRuleset testDrawableRuleset; @@ -76,7 +76,7 @@ namespace osu.Game.Tests.NonVisual } [SuppressMessage("ReSharper", "UnassignedGetOnlyAutoProperty")] - private class TestDrawableRuleset : DrawableRuleset + private partial class TestDrawableRuleset : DrawableRuleset { public List HitObjects; public override IEnumerable Objects => HitObjects; diff --git a/osu.Game.Tests/NonVisual/GameplayClockContainerTest.cs b/osu.Game.Tests/NonVisual/GameplayClockContainerTest.cs index 363c7a459e..d67a3cb824 100644 --- a/osu.Game.Tests/NonVisual/GameplayClockContainerTest.cs +++ b/osu.Game.Tests/NonVisual/GameplayClockContainerTest.cs @@ -10,7 +10,7 @@ using osu.Game.Screens.Play; namespace osu.Game.Tests.NonVisual { [TestFixture] - public class GameplayClockContainerTest + public partial class GameplayClockContainerTest { [TestCase(0)] [TestCase(1)] @@ -22,7 +22,7 @@ namespace osu.Game.Tests.NonVisual Assert.That(gameplayClock.GetTrueGameplayRate(), Is.EqualTo(2)); } - private class TestGameplayClockContainer : GameplayClockContainer + private partial class TestGameplayClockContainer : GameplayClockContainer { public TestGameplayClockContainer(IFrameBasedClock underlyingClock) : base(underlyingClock) diff --git a/osu.Game.Tests/NonVisual/Multiplayer/StatefulMultiplayerClientTest.cs b/osu.Game.Tests/NonVisual/Multiplayer/StatefulMultiplayerClientTest.cs index d1c5e2d8b3..ae6a76f6cd 100644 --- a/osu.Game.Tests/NonVisual/Multiplayer/StatefulMultiplayerClientTest.cs +++ b/osu.Game.Tests/NonVisual/Multiplayer/StatefulMultiplayerClientTest.cs @@ -16,7 +16,7 @@ using osu.Game.Tests.Visual.Multiplayer; namespace osu.Game.Tests.NonVisual.Multiplayer { [HeadlessTest] - public class StatefulMultiplayerClientTest : MultiplayerTestScene + public partial class StatefulMultiplayerClientTest : MultiplayerTestScene { [Test] public void TestUserAddedOnJoin() diff --git a/osu.Game.Tests/NonVisual/OngoingOperationTrackerTest.cs b/osu.Game.Tests/NonVisual/OngoingOperationTrackerTest.cs index 03ca3a0a1a..0bcae05f44 100644 --- a/osu.Game.Tests/NonVisual/OngoingOperationTrackerTest.cs +++ b/osu.Game.Tests/NonVisual/OngoingOperationTrackerTest.cs @@ -17,7 +17,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Tests.NonVisual { [HeadlessTest] - public class OngoingOperationTrackerTest : OsuTestScene + public partial class OngoingOperationTrackerTest : OsuTestScene { private OngoingOperationTracker tracker; private IBindable operationInProgress; @@ -94,7 +94,7 @@ namespace osu.Game.Tests.NonVisual AddAssert("operation ended", () => !screen.OngoingOperationTracker.InProgress.Value); } - private class TestScreenWithTracker : OsuScreen + private partial class TestScreenWithTracker : OsuScreen { public OngoingOperationTracker OngoingOperationTracker { get; private set; } diff --git a/osu.Game.Tests/NonVisual/Skinning/LegacySkinAnimationTest.cs b/osu.Game.Tests/NonVisual/Skinning/LegacySkinAnimationTest.cs index 5c247bace9..197e9404ff 100644 --- a/osu.Game.Tests/NonVisual/Skinning/LegacySkinAnimationTest.cs +++ b/osu.Game.Tests/NonVisual/Skinning/LegacySkinAnimationTest.cs @@ -22,7 +22,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Tests.NonVisual.Skinning { [HeadlessTest] - public class LegacySkinAnimationTest : OsuTestScene + public partial class LegacySkinAnimationTest : OsuTestScene { private const string animation_name = "animation"; private const int frame_count = 6; diff --git a/osu.Game.Tests/Online/TestDummyAPIRequestHandling.cs b/osu.Game.Tests/Online/TestDummyAPIRequestHandling.cs index 61fdae0ca1..f41c3ad6af 100644 --- a/osu.Game.Tests/Online/TestDummyAPIRequestHandling.cs +++ b/osu.Game.Tests/Online/TestDummyAPIRequestHandling.cs @@ -14,7 +14,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Tests.Online { [HeadlessTest] - public class TestDummyAPIRequestHandling : OsuTestScene + public partial class TestDummyAPIRequestHandling : OsuTestScene { [Test] public void TestGenericRequestHandling() diff --git a/osu.Game.Tests/Online/TestSceneBeatmapDownloading.cs b/osu.Game.Tests/Online/TestSceneBeatmapDownloading.cs index 641c1ad523..c959132332 100644 --- a/osu.Game.Tests/Online/TestSceneBeatmapDownloading.cs +++ b/osu.Game.Tests/Online/TestSceneBeatmapDownloading.cs @@ -15,7 +15,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Tests.Online { [HeadlessTest] - public class TestSceneBeatmapDownloading : OsuTestScene + public partial class TestSceneBeatmapDownloading : OsuTestScene { private BeatmapModelDownloader beatmaps; private ProgressNotification recentNotification; diff --git a/osu.Game.Tests/Online/TestSceneOnlinePlayBeatmapAvailabilityTracker.cs b/osu.Game.Tests/Online/TestSceneOnlinePlayBeatmapAvailabilityTracker.cs index e7590df3e0..585fd516bd 100644 --- a/osu.Game.Tests/Online/TestSceneOnlinePlayBeatmapAvailabilityTracker.cs +++ b/osu.Game.Tests/Online/TestSceneOnlinePlayBeatmapAvailabilityTracker.cs @@ -34,7 +34,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Tests.Online { [HeadlessTest] - public class TestSceneOnlinePlayBeatmapAvailabilityTracker : OsuTestScene + public partial class TestSceneOnlinePlayBeatmapAvailabilityTracker : OsuTestScene { private RulesetStore rulesets; private TestBeatmapManager beatmaps; @@ -226,12 +226,12 @@ namespace osu.Game.Tests.Online this.testBeatmapManager = testBeatmapManager; } - public override Live ImportModel(BeatmapSetInfo item, ArchiveReader archive = null, bool batchImport = false, CancellationToken cancellationToken = default) + public override Live ImportModel(BeatmapSetInfo item, ArchiveReader archive = null, ImportParameters parameters = default, CancellationToken cancellationToken = default) { if (!testBeatmapManager.AllowImport.Wait(TimeSpan.FromSeconds(10), cancellationToken)) throw new TimeoutException("Timeout waiting for import to be allowed."); - return (testBeatmapManager.CurrentImport = base.ImportModel(item, archive, batchImport, cancellationToken)); + return (testBeatmapManager.CurrentImport = base.ImportModel(item, archive, parameters, cancellationToken)); } } } diff --git a/osu.Game.Tests/OnlinePlay/TestSceneCatchUpSyncManager.cs b/osu.Game.Tests/OnlinePlay/TestSceneCatchUpSyncManager.cs index 6015c92663..1d568a9dc2 100644 --- a/osu.Game.Tests/OnlinePlay/TestSceneCatchUpSyncManager.cs +++ b/osu.Game.Tests/OnlinePlay/TestSceneCatchUpSyncManager.cs @@ -16,7 +16,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Tests.OnlinePlay { [HeadlessTest] - public class TestSceneCatchUpSyncManager : OsuTestScene + public partial class TestSceneCatchUpSyncManager : OsuTestScene { private GameplayClockContainer master; private SpectatorSyncManager syncManager; diff --git a/osu.Game.Tests/Resources/Archives/modified-default-20221205.osk b/osu.Game.Tests/Resources/Archives/modified-default-20221205.osk new file mode 100644 index 0000000000..ae421fc323 Binary files /dev/null and b/osu.Game.Tests/Resources/Archives/modified-default-20221205.osk differ diff --git a/osu.Game.Tests/Resources/TestResources.cs b/osu.Game.Tests/Resources/TestResources.cs index 9c85f61330..adf28afc8e 100644 --- a/osu.Game.Tests/Resources/TestResources.cs +++ b/osu.Game.Tests/Resources/TestResources.cs @@ -12,6 +12,7 @@ using System.Threading; using NUnit.Framework; using osu.Framework.Extensions; using osu.Framework.IO.Stores; +using osu.Framework.Logging; using osu.Framework.Testing; using osu.Framework.Utils; using osu.Game.Beatmaps; @@ -93,10 +94,12 @@ namespace osu.Game.Tests.Resources { // Create random metadata, then we can check if sorting works based on these Artist = "Some Artist " + RNG.Next(0, 9), - Title = $"Some Song (set id {setId}) {Guid.NewGuid()}", + Title = $"Some Song (set id {setId:000}) {Guid.NewGuid()}", Author = { Username = "Some Guy " + RNG.Next(0, 9) }, }; + Logger.Log($"🛠️ Generating beatmap set \"{metadata}\" for test consumption."); + var beatmapSet = new BeatmapSetInfo { OnlineID = setId, diff --git a/osu.Game.Tests/Resources/mania-last-object-not-latest.osu b/osu.Game.Tests/Resources/mania-last-object-not-latest.osu new file mode 100644 index 0000000000..51893383d8 --- /dev/null +++ b/osu.Game.Tests/Resources/mania-last-object-not-latest.osu @@ -0,0 +1,39 @@ +osu file format v14 + +[General] +SampleSet: Normal +StackLeniency: 0.7 +Mode: 3 + +[Difficulty] +HPDrainRate:3 +CircleSize:5 +OverallDifficulty:8 +ApproachRate:8 +SliderMultiplier:3.59999990463257 +SliderTickRate:2 + +[TimingPoints] +24,352.941176470588,4,1,1,100,1,0 +6376,-50,4,1,1,100,0,0 + +[HitObjects] +51,192,24,1,0,0:0:0:0: +153,192,200,1,0,0:0:0:0: +358,192,376,1,0,0:0:0:0: +460,192,553,1,0,0:0:0:0: +460,192,729,128,0,1435:0:0:0:0: +358,192,906,128,0,1612:0:0:0:0: +256,192,1082,128,0,1788:0:0:0:0: +153,192,1259,128,0,1965:0:0:0:0: +51,192,1435,128,0,2141:0:0:0:0: +51,192,2318,1,12,0:0:0:0: +153,192,2318,1,4,0:0:0:0: +256,192,2318,1,6,0:0:0:0: +358,192,2318,1,14,0:0:0:0: +460,192,2318,1,0,0:0:0:0: +51,192,2494,128,0,2582:0:0:0:0: +153,192,2494,128,14,2582:0:0:0:0: +256,192,2494,128,6,2582:0:0:0:0: +358,192,2494,128,4,2582:0:0:0:0: +460,192,2494,1,12,0:0:0:0:0: diff --git a/osu.Game.Tests/Rulesets/Scoring/ScoreProcessorTest.cs b/osu.Game.Tests/Rulesets/Scoring/ScoreProcessorTest.cs index 7a45d1e7cf..826c610f56 100644 --- a/osu.Game.Tests/Rulesets/Scoring/ScoreProcessorTest.cs +++ b/osu.Game.Tests/Rulesets/Scoring/ScoreProcessorTest.cs @@ -7,6 +7,7 @@ using System; using System.Collections.Generic; using System.Linq; using NUnit.Framework; +using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Rulesets; using osu.Game.Rulesets.Difficulty; @@ -22,7 +23,7 @@ using osu.Game.Tests.Beatmaps; namespace osu.Game.Tests.Rulesets.Scoring { - public class ScoreProcessorTest + public partial class ScoreProcessorTest { private ScoreProcessor scoreProcessor; private IBeatmap beatmap; @@ -355,6 +356,28 @@ namespace osu.Game.Tests.Rulesets.Scoring } #pragma warning restore CS0618 + [Test] + public void TestAccuracyWhenNearPerfect() + { + const int count_judgements = 1000; + const int count_misses = 1; + + double actual = new TestScoreProcessor().ComputeAccuracy(new ScoreInfo + { + Statistics = new Dictionary + { + { HitResult.Great, count_judgements - count_misses }, + { HitResult.Miss, count_misses } + } + }); + + const double expected = (count_judgements - count_misses) / (double)count_judgements; + + Assert.That(actual, Is.Not.EqualTo(0.0)); + Assert.That(actual, Is.Not.EqualTo(1.0)); + Assert.That(actual, Is.EqualTo(expected).Within(Precision.FLOAT_EPSILON)); + } + private class TestRuleset : Ruleset { public override IEnumerable GetModsFor(ModType type) => throw new NotImplementedException(); @@ -394,7 +417,7 @@ namespace osu.Game.Tests.Rulesets.Scoring } } - private class TestScoreProcessor : ScoreProcessor + private partial class TestScoreProcessor : ScoreProcessor { protected override double DefaultAccuracyPortion => 0.5; protected override double DefaultComboPortion => 0.5; diff --git a/osu.Game.Tests/Rulesets/TestSceneBrokenRulesetHandling.cs b/osu.Game.Tests/Rulesets/TestSceneBrokenRulesetHandling.cs index ecc4b3ec63..c3a6b7c474 100644 --- a/osu.Game.Tests/Rulesets/TestSceneBrokenRulesetHandling.cs +++ b/osu.Game.Tests/Rulesets/TestSceneBrokenRulesetHandling.cs @@ -18,7 +18,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Tests.Rulesets { [HeadlessTest] - public class TestSceneBrokenRulesetHandling : OsuTestScene + public partial class TestSceneBrokenRulesetHandling : OsuTestScene { [Resolved] private OsuGameBase gameBase { get; set; } = null!; diff --git a/osu.Game.Tests/Rulesets/TestSceneDrawableRulesetDependencies.cs b/osu.Game.Tests/Rulesets/TestSceneDrawableRulesetDependencies.cs index 29534348dc..3fba21050e 100644 --- a/osu.Game.Tests/Rulesets/TestSceneDrawableRulesetDependencies.cs +++ b/osu.Game.Tests/Rulesets/TestSceneDrawableRulesetDependencies.cs @@ -29,7 +29,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Tests.Rulesets { [HeadlessTest] - public class TestSceneDrawableRulesetDependencies : OsuTestScene + public partial class TestSceneDrawableRulesetDependencies : OsuTestScene { [Test] public void TestDisposalDoesNotDisposeParentStores() @@ -63,7 +63,7 @@ namespace osu.Game.Tests.Rulesets AddAssert("parent shader manager not disposed", () => !shaderManager.IsDisposed); } - private class DrawableWithDependencies : CompositeDrawable + private partial class DrawableWithDependencies : CompositeDrawable { public TestTextureStore ParentTextureStore { get; private set; } public TestSampleStore ParentSampleStore { get; private set; } diff --git a/osu.Game.Tests/Rulesets/TestSceneRulesetSkinProvidingContainer.cs b/osu.Game.Tests/Rulesets/TestSceneRulesetSkinProvidingContainer.cs index a29fc9f1fb..11f3fe660d 100644 --- a/osu.Game.Tests/Rulesets/TestSceneRulesetSkinProvidingContainer.cs +++ b/osu.Game.Tests/Rulesets/TestSceneRulesetSkinProvidingContainer.cs @@ -21,7 +21,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Tests.Rulesets { [HeadlessTest] - public class TestSceneRulesetSkinProvidingContainer : OsuTestScene + public partial class TestSceneRulesetSkinProvidingContainer : OsuTestScene { private SkinRequester requester; @@ -64,7 +64,7 @@ namespace osu.Game.Tests.Rulesets }); } - private class SkinRequester : Drawable, ISkin + private partial class SkinRequester : Drawable, ISkin { private ISkinSource skin; diff --git a/osu.Game.Tests/Skins/IO/ImportSkinTest.cs b/osu.Game.Tests/Skins/IO/ImportSkinTest.cs index 5c20f46787..0bd40e9962 100644 --- a/osu.Game.Tests/Skins/IO/ImportSkinTest.cs +++ b/osu.Game.Tests/Skins/IO/ImportSkinTest.cs @@ -360,7 +360,7 @@ namespace osu.Game.Tests.Skins.IO private async Task> loadSkinIntoOsu(OsuGameBase osu, ImportTask import, bool batchImport = false) { var skinManager = osu.Dependencies.Get(); - return await skinManager.Import(import, batchImport); + return await skinManager.Import(import, new ImportParameters { Batch = batchImport }); } } } diff --git a/osu.Game.Tests/Skins/SkinDeserialisationTest.cs b/osu.Game.Tests/Skins/SkinDeserialisationTest.cs index ff665499ae..39e8ec5215 100644 --- a/osu.Game.Tests/Skins/SkinDeserialisationTest.cs +++ b/osu.Game.Tests/Skins/SkinDeserialisationTest.cs @@ -42,7 +42,9 @@ namespace osu.Game.Tests.Skins // Covers longest combo counter "Archives/modified-default-20221012.osk", // Covers TextElement and BeatmapInfoDrawable - "Archives/modified-default-20221102.osk" + "Archives/modified-default-20221102.osk", + // Covers BPM counter. + "Archives/modified-default-20221205.osk" }; /// diff --git a/osu.Game.Tests/Skins/TestSceneBeatmapSkinLookupDisables.cs b/osu.Game.Tests/Skins/TestSceneBeatmapSkinLookupDisables.cs index a31c624f78..0bbf4406fb 100644 --- a/osu.Game.Tests/Skins/TestSceneBeatmapSkinLookupDisables.cs +++ b/osu.Game.Tests/Skins/TestSceneBeatmapSkinLookupDisables.cs @@ -23,7 +23,7 @@ namespace osu.Game.Tests.Skins { [TestFixture] [HeadlessTest] - public class TestSceneBeatmapSkinLookupDisables : OsuTestScene + public partial class TestSceneBeatmapSkinLookupDisables : OsuTestScene { private UserSkinSource userSource; private BeatmapSkinSource beatmapSource; @@ -88,7 +88,7 @@ namespace osu.Game.Tests.Skins } } - public class SkinRequester : Drawable, ISkin + public partial class SkinRequester : Drawable, ISkin { private ISkinSource skin; diff --git a/osu.Game.Tests/Skins/TestSceneBeatmapSkinResources.cs b/osu.Game.Tests/Skins/TestSceneBeatmapSkinResources.cs index e82a5b57d9..5256bcb3af 100644 --- a/osu.Game.Tests/Skins/TestSceneBeatmapSkinResources.cs +++ b/osu.Game.Tests/Skins/TestSceneBeatmapSkinResources.cs @@ -17,7 +17,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Tests.Skins { [HeadlessTest] - public class TestSceneBeatmapSkinResources : OsuTestScene + public partial class TestSceneBeatmapSkinResources : OsuTestScene { [Resolved] private BeatmapManager beatmaps { get; set; } diff --git a/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs b/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs index 8c6f137dc0..816834989c 100644 --- a/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs +++ b/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs @@ -27,7 +27,7 @@ namespace osu.Game.Tests.Skins { [TestFixture] [HeadlessTest] - public class TestSceneSkinConfigurationLookup : OsuTestScene + public partial class TestSceneSkinConfigurationLookup : OsuTestScene { private UserSkinSource userSource; private BeatmapSkinSource beatmapSource; @@ -211,7 +211,7 @@ namespace osu.Game.Tests.Skins } } - public class SkinRequester : Drawable, ISkin + public partial class SkinRequester : Drawable, ISkin { private ISkinSource skin; diff --git a/osu.Game.Tests/Skins/TestSceneSkinProvidingContainer.cs b/osu.Game.Tests/Skins/TestSceneSkinProvidingContainer.cs index ad71296a11..df314b56a9 100644 --- a/osu.Game.Tests/Skins/TestSceneSkinProvidingContainer.cs +++ b/osu.Game.Tests/Skins/TestSceneSkinProvidingContainer.cs @@ -20,7 +20,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Tests.Skins { [HeadlessTest] - public class TestSceneSkinProvidingContainer : OsuTestScene + public partial class TestSceneSkinProvidingContainer : OsuTestScene { [Resolved] private IRenderer renderer { get; set; } @@ -59,7 +59,7 @@ namespace osu.Game.Tests.Skins }); } - private class TestSkinProvidingContainer : SkinProvidingContainer + private partial class TestSkinProvidingContainer : SkinProvidingContainer { private readonly IEnumerable sources; diff --git a/osu.Game.Tests/Skins/TestSceneSkinResources.cs b/osu.Game.Tests/Skins/TestSceneSkinResources.cs index 22d6d08355..748668b6ca 100644 --- a/osu.Game.Tests/Skins/TestSceneSkinResources.cs +++ b/osu.Game.Tests/Skins/TestSceneSkinResources.cs @@ -26,7 +26,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Tests.Skins { [HeadlessTest] - public class TestSceneSkinResources : OsuTestScene + public partial class TestSceneSkinResources : OsuTestScene { [Resolved] private SkinManager skins { get; set; } = null!; diff --git a/osu.Game.Tests/Testing/TestSceneRulesetDependencies.cs b/osu.Game.Tests/Testing/TestSceneRulesetDependencies.cs index 79b44c109a..f1533a32b9 100644 --- a/osu.Game.Tests/Testing/TestSceneRulesetDependencies.cs +++ b/osu.Game.Tests/Testing/TestSceneRulesetDependencies.cs @@ -30,7 +30,7 @@ namespace osu.Game.Tests.Testing /// provided ruleset below are cached at the base implementation. /// [HeadlessTest] - public class TestSceneRulesetDependencies : OsuTestScene + public partial class TestSceneRulesetDependencies : OsuTestScene { protected override Ruleset CreateRuleset() => new TestRuleset(); diff --git a/osu.Game.Tests/Utils/NamingUtilsTest.cs b/osu.Game.Tests/Utils/NamingUtilsTest.cs index 62e688db90..1f7e06f996 100644 --- a/osu.Game.Tests/Utils/NamingUtilsTest.cs +++ b/osu.Game.Tests/Utils/NamingUtilsTest.cs @@ -11,7 +11,7 @@ namespace osu.Game.Tests.Utils public class NamingUtilsTest { [Test] - public void TestEmptySet() + public void TestNextBestNameEmptySet() { string nextBestName = NamingUtils.GetNextBestName(Enumerable.Empty(), "New Difficulty"); @@ -19,7 +19,7 @@ namespace osu.Game.Tests.Utils } [Test] - public void TestNotTaken() + public void TestNextBestNameNotTaken() { string[] existingNames = { @@ -34,7 +34,7 @@ namespace osu.Game.Tests.Utils } [Test] - public void TestNotTakenButClose() + public void TestNextBestNameNotTakenButClose() { string[] existingNames = { @@ -49,7 +49,7 @@ namespace osu.Game.Tests.Utils } [Test] - public void TestAlreadyTaken() + public void TestNextBestNameAlreadyTaken() { string[] existingNames = { @@ -62,7 +62,7 @@ namespace osu.Game.Tests.Utils } [Test] - public void TestAlreadyTakenWithDifferentCase() + public void TestNextBestNameAlreadyTakenWithDifferentCase() { string[] existingNames = { @@ -75,7 +75,7 @@ namespace osu.Game.Tests.Utils } [Test] - public void TestAlreadyTakenWithBrackets() + public void TestNextBestNameAlreadyTakenWithBrackets() { string[] existingNames = { @@ -88,7 +88,7 @@ namespace osu.Game.Tests.Utils } [Test] - public void TestMultipleAlreadyTaken() + public void TestNextBestNameMultipleAlreadyTaken() { string[] existingNames = { @@ -104,7 +104,7 @@ namespace osu.Game.Tests.Utils } [Test] - public void TestEvenMoreAlreadyTaken() + public void TestNextBestNameEvenMoreAlreadyTaken() { string[] existingNames = Enumerable.Range(1, 30).Select(i => $"New Difficulty ({i})").Append("New Difficulty").ToArray(); @@ -114,7 +114,7 @@ namespace osu.Game.Tests.Utils } [Test] - public void TestMultipleAlreadyTakenWithGaps() + public void TestNextBestNameMultipleAlreadyTakenWithGaps() { string[] existingNames = { @@ -128,5 +128,153 @@ namespace osu.Game.Tests.Utils Assert.AreEqual("New Difficulty (2)", nextBestName); } + + [Test] + public void TestNextBestFilenameEmptySet() + { + string nextBestFilename = NamingUtils.GetNextBestFilename(Enumerable.Empty(), "test_file.osr"); + + Assert.AreEqual("test_file.osr", nextBestFilename); + } + + [Test] + public void TestNextBestFilenameNotTaken() + { + string[] existingFiles = + { + "this file exists.zip", + "that file exists.too", + "three.4", + }; + + string nextBestFilename = NamingUtils.GetNextBestFilename(existingFiles, "test_file.osr"); + + Assert.AreEqual("test_file.osr", nextBestFilename); + } + + [Test] + public void TestNextBestFilenameNotTakenButClose() + { + string[] existingFiles = + { + "replay_file(1).osr", + "replay_file (not a number).zip", + "replay_file (1 <- now THAT is a number right here).lol", + }; + + string nextBestFilename = NamingUtils.GetNextBestFilename(existingFiles, "replay_file.osr"); + + Assert.AreEqual("replay_file.osr", nextBestFilename); + } + + [Test] + public void TestNextBestFilenameAlreadyTaken() + { + string[] existingFiles = + { + "replay_file.osr", + }; + + string nextBestFilename = NamingUtils.GetNextBestFilename(existingFiles, "replay_file.osr"); + + Assert.AreEqual("replay_file (1).osr", nextBestFilename); + } + + [Test] + public void TestNextBestFilenameAlreadyTakenDifferentCase() + { + string[] existingFiles = + { + "replay_file.osr", + "RePlAy_FiLe (1).OsR", + "REPLAY_FILE (2).OSR", + }; + + string nextBestFilename = NamingUtils.GetNextBestFilename(existingFiles, "replay_file.osr"); + Assert.AreEqual("replay_file (3).osr", nextBestFilename); + } + + [Test] + public void TestNextBestFilenameAlreadyTakenWithBrackets() + { + string[] existingFiles = + { + "replay_file.osr", + "replay_file (copy).osr", + }; + + string nextBestFilename = NamingUtils.GetNextBestFilename(existingFiles, "replay_file.osr"); + Assert.AreEqual("replay_file (1).osr", nextBestFilename); + + nextBestFilename = NamingUtils.GetNextBestFilename(existingFiles, "replay_file (copy).osr"); + Assert.AreEqual("replay_file (copy) (1).osr", nextBestFilename); + } + + [Test] + public void TestNextBestFilenameMultipleAlreadyTaken() + { + string[] existingFiles = + { + "replay_file.osr", + "replay_file (1).osr", + "replay_file (2).osr", + "replay_file (3).osr", + }; + + string nextBestFilename = NamingUtils.GetNextBestFilename(existingFiles, "replay_file.osr"); + + Assert.AreEqual("replay_file (4).osr", nextBestFilename); + } + + [Test] + public void TestNextBestFilenameMultipleAlreadyTakenWithGaps() + { + string[] existingFiles = + { + "replay_file.osr", + "replay_file (1).osr", + "replay_file (2).osr", + "replay_file (4).osr", + "replay_file (5).osr", + }; + + string nextBestFilename = NamingUtils.GetNextBestFilename(existingFiles, "replay_file.osr"); + + Assert.AreEqual("replay_file (3).osr", nextBestFilename); + } + + [Test] + public void TestNextBestFilenameNoExtensions() + { + string[] existingFiles = + { + "those", + "are definitely", + "files", + }; + + string nextBestFilename = NamingUtils.GetNextBestFilename(existingFiles, "surely"); + Assert.AreEqual("surely", nextBestFilename); + + nextBestFilename = NamingUtils.GetNextBestFilename(existingFiles, "those"); + Assert.AreEqual("those (1)", nextBestFilename); + } + + [Test] + public void TestNextBestFilenameDifferentExtensions() + { + string[] existingFiles = + { + "replay_file.osr", + "replay_file (1).osr", + "replay_file.txt", + }; + + string nextBestFilename = NamingUtils.GetNextBestFilename(existingFiles, "replay_file.osr"); + Assert.AreEqual("replay_file (2).osr", nextBestFilename); + + nextBestFilename = NamingUtils.GetNextBestFilename(existingFiles, "replay_file.txt"); + Assert.AreEqual("replay_file (1).txt", nextBestFilename); + } } } diff --git a/osu.Game.Tests/Visual/Audio/TestSceneAudioFilter.cs b/osu.Game.Tests/Visual/Audio/TestSceneAudioFilter.cs index 15903b2074..cc72731493 100644 --- a/osu.Game.Tests/Visual/Audio/TestSceneAudioFilter.cs +++ b/osu.Game.Tests/Visual/Audio/TestSceneAudioFilter.cs @@ -19,7 +19,7 @@ using osu.Game.Graphics.UserInterface; namespace osu.Game.Tests.Visual.Audio { - public class TestSceneAudioFilter : OsuTestScene + public partial class TestSceneAudioFilter : OsuTestScene { private OsuSpriteText lowPassText; private AudioFilter lowPassFilter; diff --git a/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenDefault.cs b/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenDefault.cs index d9dfa1d876..fbdaad1cd8 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenDefault.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenDefault.cs @@ -32,7 +32,7 @@ using osu.Game.Tests.Beatmaps; namespace osu.Game.Tests.Visual.Background { [TestFixture] - public class TestSceneBackgroundScreenDefault : OsuTestScene + public partial class TestSceneBackgroundScreenDefault : OsuTestScene { private BackgroundScreenStack stack; private TestBackgroundScreenDefault screen; @@ -252,7 +252,7 @@ namespace osu.Game.Tests.Visual.Background private WorkingBeatmap createTestWorkingBeatmapWithUniqueBackground() => new UniqueBackgroundTestWorkingBeatmap(renderer, Audio); private WorkingBeatmap createTestWorkingBeatmapWithStoryboard() => new TestWorkingBeatmapWithStoryboard(Audio); - private class TestBackgroundScreenDefault : BackgroundScreenDefault + private partial class TestBackgroundScreenDefault : BackgroundScreenDefault { private bool? lastLoadTriggerCausedChange; @@ -289,7 +289,7 @@ namespace osu.Game.Tests.Visual.Background protected override Texture GetBackground() => renderer.CreateTexture(1, 1); } - private class TestWorkingBeatmapWithStoryboard : TestWorkingBeatmap + private partial class TestWorkingBeatmapWithStoryboard : TestWorkingBeatmap { public TestWorkingBeatmapWithStoryboard(AudioManager audioManager) : base(new Beatmap(), createStoryboard(), audioManager) @@ -315,7 +315,7 @@ namespace osu.Game.Tests.Visual.Background public Drawable CreateDrawable() => new DrawableTestStoryboardElement(); } - private class DrawableTestStoryboardElement : OsuSpriteText + private partial class DrawableTestStoryboardElement : OsuSpriteText { public override bool RemoveWhenNotAlive => false; diff --git a/osu.Game.Tests/Visual/Background/TestSceneSeasonalBackgroundLoader.cs b/osu.Game.Tests/Visual/Background/TestSceneSeasonalBackgroundLoader.cs index c9920cd01f..54a722cee0 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneSeasonalBackgroundLoader.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneSeasonalBackgroundLoader.cs @@ -20,7 +20,7 @@ using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Tests.Visual.Background { - public class TestSceneSeasonalBackgroundLoader : ScreenTestScene + public partial class TestSceneSeasonalBackgroundLoader : ScreenTestScene { [Resolved] private OsuConfigManager config { get; set; } diff --git a/osu.Game.Tests/Visual/Background/TestSceneTriangleBorderShader.cs b/osu.Game.Tests/Visual/Background/TestSceneTriangleBorderShader.cs index 64512bc651..185b83d1cc 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneTriangleBorderShader.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneTriangleBorderShader.cs @@ -12,7 +12,7 @@ using osu.Framework.Graphics.Rendering; namespace osu.Game.Tests.Visual.Background { - public class TestSceneTriangleBorderShader : OsuTestScene + public partial class TestSceneTriangleBorderShader : OsuTestScene { private readonly TriangleBorder border; @@ -41,7 +41,7 @@ namespace osu.Game.Tests.Visual.Background AddSliderStep("Thickness", 0f, 1f, 0.02f, t => border.Thickness = t); } - private class TriangleBorder : Sprite + private partial class TriangleBorder : Sprite { private float thickness = 0.02f; diff --git a/osu.Game.Tests/Visual/Background/TestSceneTrianglesBackground.cs b/osu.Game.Tests/Visual/Background/TestSceneTrianglesBackground.cs index 81a3249efb..d3cdf928e8 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneTrianglesBackground.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneTrianglesBackground.cs @@ -8,7 +8,7 @@ using osu.Framework.Graphics.Shapes; namespace osu.Game.Tests.Visual.Background { - public class TestSceneTrianglesBackground : OsuTestScene + public partial class TestSceneTrianglesBackground : OsuTestScene { private readonly Triangles triangles; diff --git a/osu.Game.Tests/Visual/Background/TestSceneTrianglesV2Background.cs b/osu.Game.Tests/Visual/Background/TestSceneTrianglesV2Background.cs index 0c3a21d510..ae1f3de6bf 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneTrianglesV2Background.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneTrianglesV2Background.cs @@ -7,12 +7,14 @@ using osu.Framework.Graphics.Shapes; using osuTK; using osuTK.Graphics; using osu.Game.Graphics.Backgrounds; +using osu.Framework.Graphics.Colour; namespace osu.Game.Tests.Visual.Background { - public class TestSceneTrianglesV2Background : OsuTestScene + public partial class TestSceneTrianglesV2Background : OsuTestScene { private readonly TrianglesV2 triangles; + private readonly Box box; public TestSceneTrianglesV2Background() { @@ -23,27 +25,44 @@ namespace osu.Game.Tests.Visual.Background RelativeSizeAxes = Axes.Both, Colour = Color4.Gray }, - new Container + new FillFlowContainer { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Size = new Vector2(500, 100), - Masking = true, - CornerRadius = 40, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 5), Children = new Drawable[] { - new Box + new Container { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Red + Size = new Vector2(500, 100), + Masking = true, + CornerRadius = 40, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Red + }, + triangles = new TrianglesV2 + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both + } + } }, - triangles = new TrianglesV2 + new Container { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - ColourTop = Color4.White, - ColourBottom = Color4.Red + Size = new Vector2(500, 100), + Masking = true, + CornerRadius = 40, + Child = box = new Box + { + RelativeSizeAxes = Axes.Both + } } } } @@ -54,8 +73,16 @@ namespace osu.Game.Tests.Visual.Background { base.LoadComplete(); - AddSliderStep("Spawn ratio", 0f, 2f, 1f, s => triangles.SpawnRatio = s); + AddSliderStep("Spawn ratio", 0f, 10f, 1f, s => + { + triangles.SpawnRatio = s; + triangles.Reset(1234); + }); AddSliderStep("Thickness", 0f, 1f, 0.02f, t => triangles.Thickness = t); + + AddStep("White colour", () => box.Colour = triangles.Colour = Color4.White); + AddStep("Vertical gradient", () => box.Colour = triangles.Colour = ColourInfo.GradientVertical(Color4.White, Color4.Red)); + AddStep("Horizontal gradient", () => box.Colour = triangles.Colour = ColourInfo.GradientHorizontal(Color4.White, Color4.Red)); } } } diff --git a/osu.Game.Tests/Visual/Background/TestSceneUserDimBackgrounds.cs b/osu.Game.Tests/Visual/Background/TestSceneUserDimBackgrounds.cs index 917434ae22..5df5337a96 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneUserDimBackgrounds.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneUserDimBackgrounds.cs @@ -37,7 +37,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.Background { [TestFixture] - public class TestSceneUserDimBackgrounds : ScreenTestScene + public partial class TestSceneUserDimBackgrounds : ScreenTestScene { private DummySongSelect songSelect; private TestPlayerLoader playerLoader; @@ -299,7 +299,7 @@ namespace osu.Game.Tests.Visual.Background rulesets?.Dispose(); } - private class DummySongSelect : PlaySongSelect + private partial class DummySongSelect : PlaySongSelect { private FadeAccessibleBackground background; @@ -346,7 +346,7 @@ namespace osu.Game.Tests.Visual.Background public bool IsBackgroundCurrent() => background?.IsCurrentScreen() == true; } - private class FadeAccessibleResults : ResultsScreen + private partial class FadeAccessibleResults : ResultsScreen { public FadeAccessibleResults(ScoreInfo score) : base(score, true) @@ -358,7 +358,7 @@ namespace osu.Game.Tests.Visual.Background public Vector2 ExpectedBackgroundBlur => new Vector2(BACKGROUND_BLUR); } - private class LoadBlockingTestPlayer : TestPlayer + private partial class LoadBlockingTestPlayer : TestPlayer { protected override BackgroundScreen CreateBackground() => new FadeAccessibleBackground(Beatmap.Value); @@ -400,7 +400,7 @@ namespace osu.Game.Tests.Visual.Background } } - private class TestPlayerLoader : PlayerLoader + private partial class TestPlayerLoader : PlayerLoader { private FadeAccessibleBackground background; @@ -419,7 +419,7 @@ namespace osu.Game.Tests.Visual.Background protected override BackgroundScreen CreateBackground() => background = new FadeAccessibleBackground(Beatmap.Value); } - private class FadeAccessibleBackground : BackgroundScreenBeatmap + private partial class FadeAccessibleBackground : BackgroundScreenBeatmap { protected override DimmableBackground CreateFadeContainer() => dimmable = new TestDimmableBackground { RelativeSizeAxes = Axes.Both }; @@ -439,7 +439,7 @@ namespace osu.Game.Tests.Visual.Background } } - private class TestDimmableBackground : BackgroundScreenBeatmap.DimmableBackground + private partial class TestDimmableBackground : BackgroundScreenBeatmap.DimmableBackground { public Color4 CurrentColour => Content.Colour; public float CurrentAlpha => Content.Alpha; diff --git a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs index 7cad6f504b..ff35f5e8a9 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs @@ -15,7 +15,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.Background { - public class TestSceneUserDimContainer : OsuTestScene + public partial class TestSceneUserDimContainer : OsuTestScene { private TestUserDimContainer userDimContainer; @@ -104,7 +104,7 @@ namespace osu.Game.Tests.Visual.Background AddAssert("no dim", () => userDimContainer.DimEqual(0)); } - private class TestUserDimContainer : UserDimContainer + private partial class TestUserDimContainer : UserDimContainer { public bool DimEqual(float expectedDimLevel) => Content.Colour == OsuColour.Gray(1f - expectedDimLevel); diff --git a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCard.cs b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCard.cs index f95e3b9990..d4018be7fc 100644 --- a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCard.cs +++ b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCard.cs @@ -26,7 +26,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Beatmaps { - public class TestSceneBeatmapCard : OsuManualInputManagerTestScene + public partial class TestSceneBeatmapCard : OsuManualInputManagerTestScene { /// /// All cards on this scene use a common online ID to ensure that map download, preview tracks, etc. can be tested manually with online sources. diff --git a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCardDifficultyList.cs b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCardDifficultyList.cs index b609b06921..9f3e36ad76 100644 --- a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCardDifficultyList.cs +++ b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCardDifficultyList.cs @@ -13,7 +13,7 @@ using osu.Game.Overlays; namespace osu.Game.Tests.Visual.Beatmaps { - public class TestSceneBeatmapCardDifficultyList : OsuTestScene + public partial class TestSceneBeatmapCardDifficultyList : OsuTestScene { [Cached] private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue); diff --git a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCardDownloadButton.cs b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCardDownloadButton.cs index 82e18e45bb..ed80def57d 100644 --- a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCardDownloadButton.cs +++ b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCardDownloadButton.cs @@ -18,7 +18,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Beatmaps { - public class TestSceneBeatmapCardDownloadButton : OsuTestScene + public partial class TestSceneBeatmapCardDownloadButton : OsuTestScene { private DownloadButton downloadButton; diff --git a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCardFavouriteButton.cs b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCardFavouriteButton.cs index 9540d9e4f7..c33033624a 100644 --- a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCardFavouriteButton.cs +++ b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCardFavouriteButton.cs @@ -19,7 +19,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Beatmaps { - public class TestSceneBeatmapCardFavouriteButton : OsuManualInputManagerTestScene + public partial class TestSceneBeatmapCardFavouriteButton : OsuManualInputManagerTestScene { private DummyAPIAccess dummyAPI => (DummyAPIAccess)API; diff --git a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCardThumbnail.cs b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCardThumbnail.cs index 5afda0ad0c..f44fe2b90c 100644 --- a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCardThumbnail.cs +++ b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCardThumbnail.cs @@ -17,7 +17,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Beatmaps { - public class TestSceneBeatmapCardThumbnail : OsuManualInputManagerTestScene + public partial class TestSceneBeatmapCardThumbnail : OsuManualInputManagerTestScene { private PlayButton playButton => this.ChildrenOfType().Single(); diff --git a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapSetOnlineStatusPill.cs b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapSetOnlineStatusPill.cs index ada521f7f6..8a11d60875 100644 --- a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapSetOnlineStatusPill.cs +++ b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapSetOnlineStatusPill.cs @@ -19,7 +19,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Beatmaps { - public class TestSceneBeatmapSetOnlineStatusPill : ThemeComparisonTestScene + public partial class TestSceneBeatmapSetOnlineStatusPill : ThemeComparisonTestScene { protected override Drawable CreateContent() => new FillFlowContainer { diff --git a/osu.Game.Tests/Visual/Beatmaps/TestSceneDifficultySpectrumDisplay.cs b/osu.Game.Tests/Visual/Beatmaps/TestSceneDifficultySpectrumDisplay.cs index 94b2d10fcf..11fa6ed92d 100644 --- a/osu.Game.Tests/Visual/Beatmaps/TestSceneDifficultySpectrumDisplay.cs +++ b/osu.Game.Tests/Visual/Beatmaps/TestSceneDifficultySpectrumDisplay.cs @@ -13,7 +13,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Beatmaps { - public class TestSceneDifficultySpectrumDisplay : OsuTestScene + public partial class TestSceneDifficultySpectrumDisplay : OsuTestScene { private DifficultySpectrumDisplay display; diff --git a/osu.Game.Tests/Visual/Collections/TestSceneManageCollectionsDialog.cs b/osu.Game.Tests/Visual/Collections/TestSceneManageCollectionsDialog.cs index 77e781bfe4..1e9982f8d4 100644 --- a/osu.Game.Tests/Visual/Collections/TestSceneManageCollectionsDialog.cs +++ b/osu.Game.Tests/Visual/Collections/TestSceneManageCollectionsDialog.cs @@ -21,7 +21,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Collections { - public class TestSceneManageCollectionsDialog : OsuManualInputManagerTestScene + public partial class TestSceneManageCollectionsDialog : OsuManualInputManagerTestScene { protected override Container Content { get; } = new Container { RelativeSizeAxes = Axes.Both }; diff --git a/osu.Game.Tests/Visual/Colours/TestSceneStarDifficultyColours.cs b/osu.Game.Tests/Visual/Colours/TestSceneStarDifficultyColours.cs index 13d7a33600..55a2efa89d 100644 --- a/osu.Game.Tests/Visual/Colours/TestSceneStarDifficultyColours.cs +++ b/osu.Game.Tests/Visual/Colours/TestSceneStarDifficultyColours.cs @@ -16,7 +16,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Colours { - public class TestSceneStarDifficultyColours : OsuTestScene + public partial class TestSceneStarDifficultyColours : OsuTestScene { [Resolved] private OsuColour colours { get; set; } diff --git a/osu.Game.Tests/Visual/Components/TestSceneIdleTracker.cs b/osu.Game.Tests/Visual/Components/TestSceneIdleTracker.cs index 9dd75b6e5e..aad30ff450 100644 --- a/osu.Game.Tests/Visual/Components/TestSceneIdleTracker.cs +++ b/osu.Game.Tests/Visual/Components/TestSceneIdleTracker.cs @@ -14,7 +14,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.Components { [TestFixture] - public class TestSceneIdleTracker : OsuManualInputManagerTestScene + public partial class TestSceneIdleTracker : OsuManualInputManagerTestScene { private IdleTrackingBox box1; private IdleTrackingBox box2; @@ -154,7 +154,7 @@ namespace osu.Game.Tests.Visual.Components AddUntilStep("wait for all idle", () => box1.IsIdle && box2.IsIdle && box3.IsIdle && box4.IsIdle); } - private class IdleTrackingBox : CompositeDrawable + private partial class IdleTrackingBox : CompositeDrawable { private readonly IdleTracker idleTracker; diff --git a/osu.Game.Tests/Visual/Components/TestScenePollingComponent.cs b/osu.Game.Tests/Visual/Components/TestScenePollingComponent.cs index 3c89267610..4bab8d0ccc 100644 --- a/osu.Game.Tests/Visual/Components/TestScenePollingComponent.cs +++ b/osu.Game.Tests/Visual/Components/TestScenePollingComponent.cs @@ -19,7 +19,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.Components { [HeadlessTest] - public class TestScenePollingComponent : OsuTestScene + public partial class TestScenePollingComponent : OsuTestScene { private Container pollBox; private TestPoller poller; @@ -132,7 +132,7 @@ namespace osu.Game.Tests.Visual.Components protected override double TimePerAction => 500; - public class TestPoller : PollingComponent + public partial class TestPoller : PollingComponent { public event Action OnPoll; @@ -143,7 +143,7 @@ namespace osu.Game.Tests.Visual.Components } } - public class TestSlowPoller : TestPoller + public partial class TestSlowPoller : TestPoller { protected override Task Poll() => Task.Delay((int)(TimeBetweenPolls.Value / 2f / Clock.Rate)).ContinueWith(_ => base.Poll()); } diff --git a/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs b/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs index 94a71ed50c..b334616125 100644 --- a/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs +++ b/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs @@ -13,7 +13,7 @@ using osu.Game.Beatmaps; namespace osu.Game.Tests.Visual.Components { - public class TestScenePreviewTrackManager : OsuTestScene, IPreviewTrackOwner + public partial class TestScenePreviewTrackManager : OsuTestScene, IPreviewTrackOwner { private readonly IAdjustableAudioComponent gameTrackAudio = new AudioAdjustments(); @@ -201,7 +201,7 @@ namespace osu.Game.Tests.Visual.Components return track; } - private class TestTrackOwner : CompositeDrawable, IPreviewTrackOwner + private partial class TestTrackOwner : CompositeDrawable, IPreviewTrackOwner { private readonly PreviewTrack track; private readonly bool registerAsOwner; @@ -227,7 +227,7 @@ namespace osu.Game.Tests.Visual.Components } } - public class TestPreviewTrackManager : PreviewTrackManager + public partial class TestPreviewTrackManager : PreviewTrackManager { public bool AllowUpdate = true; @@ -248,7 +248,7 @@ namespace osu.Game.Tests.Visual.Components return base.UpdateSubTree(); } - public class TestPreviewTrack : TrackManagerPreviewTrack + public partial class TestPreviewTrack : TrackManagerPreviewTrack { private readonly ITrackStore trackManager; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs b/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs index f2d27b9117..56b16301be 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs @@ -21,7 +21,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Editing { - public class TestSceneBeatDivisorControl : OsuManualInputManagerTestScene + public partial class TestSceneBeatDivisorControl : OsuManualInputManagerTestScene { private BeatDivisorControl beatDivisorControl; private BindableBeatDivisor bindableBeatDivisor; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneBlueprintOrdering.cs b/osu.Game.Tests/Visual/Editing/TestSceneBlueprintOrdering.cs index 796a3cf9fc..7728adecae 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneBlueprintOrdering.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneBlueprintOrdering.cs @@ -24,7 +24,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Editing { - public class TestSceneBlueprintOrdering : EditorTestScene + public partial class TestSceneBlueprintOrdering : EditorTestScene { protected override Ruleset CreateEditorRuleset() => new OsuRuleset(); diff --git a/osu.Game.Tests/Visual/Editing/TestSceneComposeScreen.cs b/osu.Game.Tests/Visual/Editing/TestSceneComposeScreen.cs index 0df44b9ac4..035092ecb7 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneComposeScreen.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneComposeScreen.cs @@ -21,7 +21,7 @@ using osu.Game.Skinning; namespace osu.Game.Tests.Visual.Editing { [TestFixture] - public class TestSceneComposeScreen : EditorClockTestScene + public partial class TestSceneComposeScreen : EditorClockTestScene { private EditorBeatmap editorBeatmap = null!; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneComposeSelectBox.cs b/osu.Game.Tests/Visual/Editing/TestSceneComposeSelectBox.cs index 52e44efb30..7a0b3d0c1a 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneComposeSelectBox.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneComposeSelectBox.cs @@ -15,7 +15,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Editing { - public class TestSceneComposeSelectBox : OsuManualInputManagerTestScene + public partial class TestSceneComposeSelectBox : OsuManualInputManagerTestScene { private Container selectionArea; private SelectionBox selectionBox; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneComposerSelection.cs b/osu.Game.Tests/Visual/Editing/TestSceneComposerSelection.cs index 31fc107892..ffb8a67c68 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneComposerSelection.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneComposerSelection.cs @@ -26,7 +26,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Editing { - public class TestSceneComposerSelection : EditorTestScene + public partial class TestSceneComposerSelection : EditorTestScene { protected override Ruleset CreateEditorRuleset() => new OsuRuleset(); diff --git a/osu.Game.Tests/Visual/Editing/TestSceneDesignSection.cs b/osu.Game.Tests/Visual/Editing/TestSceneDesignSection.cs index 1ecbc24d90..9a66e1676d 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneDesignSection.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneDesignSection.cs @@ -20,7 +20,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Editing { - public class TestSceneDesignSection : OsuManualInputManagerTestScene + public partial class TestSceneDesignSection : OsuManualInputManagerTestScene { private TestDesignSection designSection; private EditorBeatmap editorBeatmap { get; set; } @@ -97,7 +97,7 @@ namespace osu.Game.Tests.Visual.Editing AddAssert($"beatmap value is {expectedFinalValue}", () => editorBeatmap.BeatmapInfo.CountdownOffset == expectedFinalValue); } - private class TestDesignSection : DesignSection + private partial class TestDesignSection : DesignSection { public new LabelledSwitchButton EnableCountdown => base.EnableCountdown; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneDifficultyDelete.cs b/osu.Game.Tests/Visual/Editing/TestSceneDifficultyDelete.cs index 4366b1c0bb..280e6de97e 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneDifficultyDelete.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneDifficultyDelete.cs @@ -18,7 +18,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Editing { - public class TestSceneDifficultyDelete : EditorTestScene + public partial class TestSceneDifficultyDelete : EditorTestScene { protected override Ruleset CreateEditorRuleset() => new OsuRuleset(); protected override bool IsolateSavingFromDatabase => false; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneDifficultySwitching.cs b/osu.Game.Tests/Visual/Editing/TestSceneDifficultySwitching.cs index 1f88fa8f35..69070b0b64 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneDifficultySwitching.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneDifficultySwitching.cs @@ -20,7 +20,7 @@ using osu.Game.Tests.Beatmaps.IO; namespace osu.Game.Tests.Visual.Editing { - public class TestSceneDifficultySwitching : EditorTestScene + public partial class TestSceneDifficultySwitching : EditorTestScene { protected override Ruleset CreateEditorRuleset() => new OsuRuleset(); diff --git a/osu.Game.Tests/Visual/Editing/TestSceneDistanceSnapGrid.cs b/osu.Game.Tests/Visual/Editing/TestSceneDistanceSnapGrid.cs index 01a49c7dea..21b925a257 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneDistanceSnapGrid.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneDistanceSnapGrid.cs @@ -20,7 +20,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.Editing { - public class TestSceneDistanceSnapGrid : EditorClockTestScene + public partial class TestSceneDistanceSnapGrid : EditorClockTestScene { private const double beat_length = 100; private const int beat_snap_distance = 10; @@ -108,7 +108,7 @@ namespace osu.Game.Tests.Visual.Editing AddStep("check correct interval count", () => Assert.That((end_time / grid.DistanceBetweenTicks) * multiplier, Is.EqualTo(grid.MaxIntervals))); } - private class TestDistanceSnapGrid : DistanceSnapGrid + private partial class TestDistanceSnapGrid : DistanceSnapGrid { public new float DistanceBetweenTicks => base.DistanceBetweenTicks; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs index 80a5b4832b..3f89bf9e9c 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs @@ -20,6 +20,8 @@ using osu.Game.Rulesets.Catch; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.UI; +using osu.Game.Rulesets.Taiko; +using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Screens.Edit; using osu.Game.Screens.Edit.Setup; using osu.Game.Storyboards; @@ -31,7 +33,7 @@ using SharpCompress.Archives.Zip; namespace osu.Game.Tests.Visual.Editing { - public class TestSceneEditorBeatmapCreation : EditorTestScene + public partial class TestSceneEditorBeatmapCreation : EditorTestScene { protected override Ruleset CreateEditorRuleset() => new OsuRuleset(); @@ -395,5 +397,52 @@ namespace osu.Game.Tests.Visual.Editing return set != null && set.PerformRead(s => s.Beatmaps.Count == 2 && s.Files.Count == 2); }); } + + [Test] + public void TestCreateNewDifficultyForInconvertibleRuleset() + { + Guid setId = Guid.Empty; + + AddStep("retrieve set ID", () => setId = EditorBeatmap.BeatmapInfo.BeatmapSet!.ID); + AddStep("save beatmap", () => Editor.Save()); + AddStep("try to create new taiko difficulty", () => Editor.CreateNewDifficulty(new TaikoRuleset().RulesetInfo)); + + AddUntilStep("wait for created", () => + { + string? difficultyName = Editor.ChildrenOfType().SingleOrDefault()?.BeatmapInfo.DifficultyName; + return difficultyName != null && difficultyName == "New Difficulty"; + }); + AddAssert("new difficulty persisted", () => + { + var set = beatmapManager.QueryBeatmapSet(s => s.ID == setId); + return set != null && set.PerformRead(s => s.Beatmaps.Count == 2 && s.Files.Count == 2); + }); + + AddStep("add timing point", () => EditorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = 1000 })); + AddStep("add hitobjects", () => EditorBeatmap.AddRange(new[] + { + new Hit + { + StartTime = 0 + }, + new Hit + { + StartTime = 1000 + } + })); + AddStep("save beatmap", () => Editor.Save()); + AddStep("try to create new catch difficulty", () => Editor.CreateNewDifficulty(new CatchRuleset().RulesetInfo)); + + AddUntilStep("wait for created", () => + { + string? difficultyName = Editor.ChildrenOfType().SingleOrDefault()?.BeatmapInfo.DifficultyName; + return difficultyName != null && difficultyName == "New Difficulty (1)"; + }); + AddAssert("new difficulty persisted", () => + { + var set = beatmapManager.QueryBeatmapSet(s => s.ID == setId); + return set != null && set.PerformRead(s => s.Beatmaps.Count == 3 && s.Files.Count == 3); + }); + } } } diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorBindings.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorBindings.cs index 5771d64775..61723aab7e 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorBindings.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorBindings.cs @@ -11,7 +11,7 @@ namespace osu.Game.Tests.Visual.Editing /// /// Test editor hotkeys at a high level to ensure they all work well together. /// - public class TestSceneEditorBindings : EditorTestScene + public partial class TestSceneEditorBindings : EditorTestScene { protected override Ruleset CreateEditorRuleset() => new OsuRuleset(); diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorChangeStates.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorChangeStates.cs index 109a49310a..278b6e9626 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorChangeStates.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorChangeStates.cs @@ -11,7 +11,7 @@ using osu.Game.Rulesets.Osu.Objects; namespace osu.Game.Tests.Visual.Editing { - public class TestSceneEditorChangeStates : EditorTestScene + public partial class TestSceneEditorChangeStates : EditorTestScene { protected override Ruleset CreateEditorRuleset() => new OsuRuleset(); diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorClipboard.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorClipboard.cs index 0a5a1febe4..d26bb6bb8a 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorClipboard.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorClipboard.cs @@ -21,7 +21,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Editing { - public class TestSceneEditorClipboard : EditorTestScene + public partial class TestSceneEditorClipboard : EditorTestScene { protected override Ruleset CreateEditorRuleset() => new OsuRuleset(); diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorClock.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorClock.cs index 319f8ab9dc..82d2542190 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorClock.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorClock.cs @@ -14,7 +14,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Editing { [TestFixture] - public class TestSceneEditorClock : EditorClockTestScene + public partial class TestSceneEditorClock : EditorClockTestScene { [Cached] private EditorBeatmap editorBeatmap = new EditorBeatmap(new TestBeatmap(new OsuRuleset().RulesetInfo)); diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorComposeRadioButtons.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorComposeRadioButtons.cs index 6a69347651..e11d2e9dbf 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorComposeRadioButtons.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorComposeRadioButtons.cs @@ -13,7 +13,7 @@ using osu.Game.Screens.Edit.Components.RadioButtons; namespace osu.Game.Tests.Visual.Editing { [TestFixture] - public class TestSceneEditorComposeRadioButtons : OsuTestScene + public partial class TestSceneEditorComposeRadioButtons : OsuTestScene { [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Aquamarine); diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorMenuBar.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorMenuBar.cs index 913155aafb..699b99c57f 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorMenuBar.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorMenuBar.cs @@ -15,7 +15,7 @@ using osu.Game.Screens.Edit.Components.Menus; namespace osu.Game.Tests.Visual.Editing { [TestFixture] - public class TestSceneEditorMenuBar : OsuTestScene + public partial class TestSceneEditorMenuBar : OsuTestScene { [Cached] private readonly OverlayColourProvider overlayColour = new OverlayColourProvider(OverlayColourScheme.Aquamarine); diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorNavigation.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorNavigation.cs index 327d581e37..5914290d40 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorNavigation.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorNavigation.cs @@ -17,7 +17,7 @@ using osu.Game.Tests.Resources; namespace osu.Game.Tests.Visual.Editing { - public class TestSceneEditorNavigation : OsuGameTestScene + public partial class TestSceneEditorNavigation : OsuGameTestScene { [Test] public void TestEditorGameplayTestAlwaysUsesOriginalRuleset() diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorSamplePlayback.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorSamplePlayback.cs index 43a3cb1342..8b941d7597 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorSamplePlayback.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorSamplePlayback.cs @@ -13,7 +13,7 @@ using osu.Game.Skinning; namespace osu.Game.Tests.Visual.Editing { - public class TestSceneEditorSamplePlayback : EditorTestScene + public partial class TestSceneEditorSamplePlayback : EditorTestScene { protected override Ruleset CreateEditorRuleset() => new OsuRuleset(); diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorSaving.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorSaving.cs index d7e9cc1bc0..70118e0b67 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorSaving.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorSaving.cs @@ -20,7 +20,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Editing { - public class TestSceneEditorSaving : EditorSavingTestScene + public partial class TestSceneEditorSaving : EditorSavingTestScene { [Test] public void TestCantExitWithoutSaving() diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorScreenModes.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorScreenModes.cs index 962260e1bd..a9d054881b 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorScreenModes.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorScreenModes.cs @@ -12,7 +12,7 @@ using osu.Game.Screens.Edit; namespace osu.Game.Tests.Visual.Editing { - public class TestSceneEditorScreenModes : EditorTestScene + public partial class TestSceneEditorScreenModes : EditorTestScene { protected override Ruleset CreateEditorRuleset() => new OsuRuleset(); diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorSeekSnapping.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorSeekSnapping.cs index aa4bccd728..9df5df6b39 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorSeekSnapping.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorSeekSnapping.cs @@ -17,7 +17,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.Editing { [TestFixture] - public class TestSceneEditorSeekSnapping : EditorClockTestScene + public partial class TestSceneEditorSeekSnapping : EditorClockTestScene { public TestSceneEditorSeekSnapping() { @@ -315,7 +315,7 @@ namespace osu.Game.Tests.Visual.Editing AddStep("Reset", () => EditorClock.Seek(0)); } - private class TimingPointVisualiser : CompositeDrawable + private partial class TimingPointVisualiser : CompositeDrawable { private readonly double length; @@ -386,7 +386,7 @@ namespace osu.Game.Tests.Visual.Editing tracker.X = (float)(Time.Current / length); } - private class TimingPointTimeline : CompositeDrawable + private partial class TimingPointTimeline : CompositeDrawable { public TimingPointTimeline(TimingControlPoint timingPoint, double endTime, double fullDuration) { diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorSeeking.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorSeeking.cs index 8ef84fb094..b2b3dd9632 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorSeeking.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorSeeking.cs @@ -12,7 +12,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Editing { - public class TestSceneEditorSeeking : EditorTestScene + public partial class TestSceneEditorSeeking : EditorTestScene { protected override Ruleset CreateEditorRuleset() => new OsuRuleset(); diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorSummaryTimeline.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorSummaryTimeline.cs index 3657878075..f255dd08a8 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorSummaryTimeline.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorSummaryTimeline.cs @@ -6,6 +6,7 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Osu; using osu.Game.Screens.Edit; using osu.Game.Screens.Edit.Components.Timelines.Summary; @@ -14,14 +15,20 @@ using osuTK; namespace osu.Game.Tests.Visual.Editing { [TestFixture] - public class TestSceneEditorSummaryTimeline : EditorClockTestScene + public partial class TestSceneEditorSummaryTimeline : EditorClockTestScene { [Cached(typeof(EditorBeatmap))] private readonly EditorBeatmap editorBeatmap; public TestSceneEditorSummaryTimeline() { - editorBeatmap = new EditorBeatmap(CreateBeatmap(new OsuRuleset().RulesetInfo)); + var beatmap = CreateBeatmap(new OsuRuleset().RulesetInfo); + + beatmap.ControlPointInfo.Add(100000, new TimingControlPoint { BeatLength = 100 }); + beatmap.ControlPointInfo.Add(50000, new DifficultyControlPoint { SliderVelocity = 2 }); + beatmap.BeatmapInfo.Bookmarks = new[] { 75000, 125000 }; + + editorBeatmap = new EditorBeatmap(beatmap); } protected override void LoadComplete() diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorTestGameplay.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorTestGameplay.cs index ee6c322ee3..2250868a39 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorTestGameplay.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorTestGameplay.cs @@ -27,7 +27,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Editing { - public class TestSceneEditorTestGameplay : EditorTestScene + public partial class TestSceneEditorTestGameplay : EditorTestScene { protected override bool IsolateSavingFromDatabase => false; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectComposer.cs b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectComposer.cs index 1c87eb49c9..7ab0188114 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectComposer.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectComposer.cs @@ -29,7 +29,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Editing { [TestFixture] - public class TestSceneHitObjectComposer : EditorClockTestScene + public partial class TestSceneHitObjectComposer : EditorClockTestScene { private OsuHitObjectComposer hitObjectComposer; private EditorBeatmapContainer editorBeatmapContainer; @@ -168,7 +168,7 @@ namespace osu.Game.Tests.Visual.Editing AddAssert("distance spacing increased by 0.5", () => editorBeatmap.BeatmapInfo.DistanceSpacing == originalSpacing + 0.5); } - public class EditorBeatmapContainer : Container + public partial class EditorBeatmapContainer : Container { private readonly IWorkingBeatmap working; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectDifficultyPointAdjustments.cs b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectDifficultyPointAdjustments.cs index a429c6f58b..ab82678eb9 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectDifficultyPointAdjustments.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectDifficultyPointAdjustments.cs @@ -23,7 +23,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Editing { - public class TestSceneHitObjectDifficultyPointAdjustments : EditorTestScene + public partial class TestSceneHitObjectDifficultyPointAdjustments : EditorTestScene { protected override Ruleset CreateEditorRuleset() => new OsuRuleset(); diff --git a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSamplePointAdjustments.cs b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSamplePointAdjustments.cs index 6313842dfd..e8dcc6f19b 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSamplePointAdjustments.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSamplePointAdjustments.cs @@ -23,7 +23,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Editing { - public class TestSceneHitObjectSamplePointAdjustments : EditorTestScene + public partial class TestSceneHitObjectSamplePointAdjustments : EditorTestScene { protected override Ruleset CreateEditorRuleset() => new OsuRuleset(); diff --git a/osu.Game.Tests/Visual/Editing/TestSceneLabelledTimeSignature.cs b/osu.Game.Tests/Visual/Editing/TestSceneLabelledTimeSignature.cs index 328e41ebea..e91596b872 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneLabelledTimeSignature.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneLabelledTimeSignature.cs @@ -13,7 +13,7 @@ using osu.Game.Screens.Edit.Timing; namespace osu.Game.Tests.Visual.Editing { - public class TestSceneLabelledTimeSignature : OsuManualInputManagerTestScene + public partial class TestSceneLabelledTimeSignature : OsuManualInputManagerTestScene { private LabelledTimeSignature timeSignature; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneMetadataSection.cs b/osu.Game.Tests/Visual/Editing/TestSceneMetadataSection.cs index d87bbd8a10..a9f8e19e30 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneMetadataSection.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneMetadataSection.cs @@ -13,7 +13,7 @@ using osu.Game.Screens.Edit.Setup; namespace osu.Game.Tests.Visual.Editing { - public class TestSceneMetadataSection : OsuTestScene + public partial class TestSceneMetadataSection : OsuTestScene { [Cached] private EditorBeatmap editorBeatmap = new EditorBeatmap(new Beatmap @@ -141,7 +141,7 @@ namespace osu.Game.Tests.Visual.Editing AddAssert($"romanised title is {(editable ? "" : "not ")}editable", () => metadataSection.RomanisedTitleTextBox.ReadOnly == !editable); } - private class TestMetadataSection : MetadataSection + private partial class TestMetadataSection : MetadataSection { public new LabelledTextBox ArtistTextBox => base.ArtistTextBox; public new LabelledTextBox RomanisedArtistTextBox => base.RomanisedArtistTextBox; diff --git a/osu.Game.Tests/Visual/Editing/TestScenePlaybackControl.cs b/osu.Game.Tests/Visual/Editing/TestScenePlaybackControl.cs index 674476d644..6fa52d5bbc 100644 --- a/osu.Game.Tests/Visual/Editing/TestScenePlaybackControl.cs +++ b/osu.Game.Tests/Visual/Editing/TestScenePlaybackControl.cs @@ -10,7 +10,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Editing { [TestFixture] - public class TestScenePlaybackControl : EditorClockTestScene + public partial class TestScenePlaybackControl : EditorClockTestScene { [BackgroundDependencyLoader] private void load() diff --git a/osu.Game.Tests/Visual/Editing/TestScenePreviewTime.cs b/osu.Game.Tests/Visual/Editing/TestScenePreviewTime.cs new file mode 100644 index 0000000000..3319788c8a --- /dev/null +++ b/osu.Game.Tests/Visual/Editing/TestScenePreviewTime.cs @@ -0,0 +1,35 @@ +// Copyright (c) ppy Pty Ltd . 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.Testing; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Osu; +using osu.Game.Screens.Edit.Components.Timelines.Summary.Parts; + +namespace osu.Game.Tests.Visual.Editing +{ + public partial class TestScenePreviewTime : EditorTestScene + { + protected override Ruleset CreateEditorRuleset() => new OsuRuleset(); + + [Test] + public void TestSceneSetPreviewTimingPoint() + { + AddStep("seek to 1000", () => EditorClock.Seek(1000)); + AddAssert("time is 1000", () => EditorClock.CurrentTime == 1000); + AddStep("set current time as preview point", () => Editor.SetPreviewPointToCurrentTime()); + AddAssert("preview time is 1000", () => EditorBeatmap.PreviewTime.Value == 1000); + } + + [Test] + public void TestScenePreviewTimeline() + { + AddStep("set preview time to -1", () => EditorBeatmap.PreviewTime.Value = -1); + AddAssert("preview time line should not show", () => !Editor.ChildrenOfType().Single().Children.Any()); + AddStep("set preview time to 1000", () => EditorBeatmap.PreviewTime.Value = 1000); + AddAssert("preview time line should show", () => Editor.ChildrenOfType().Single().Children.Single().Alpha == 1); + } + } +} diff --git a/osu.Game.Tests/Visual/Editing/TestSceneRectangularPositionSnapGrid.cs b/osu.Game.Tests/Visual/Editing/TestSceneRectangularPositionSnapGrid.cs index 7ad12c37bc..e73a45e154 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneRectangularPositionSnapGrid.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneRectangularPositionSnapGrid.cs @@ -16,7 +16,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.Editing { - public class TestSceneRectangularPositionSnapGrid : OsuManualInputManagerTestScene + public partial class TestSceneRectangularPositionSnapGrid : OsuManualInputManagerTestScene { private Container content; protected override Container Content => content; @@ -64,7 +64,7 @@ namespace osu.Game.Tests.Visual.Editing })); } - private class SnappingCursorContainer : CompositeDrawable + private partial class SnappingCursorContainer : CompositeDrawable { public Func GetSnapPosition; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneSelectionBlueprintDeselection.cs b/osu.Game.Tests/Visual/Editing/TestSceneSelectionBlueprintDeselection.cs index 5c933468be..24f50d36a2 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneSelectionBlueprintDeselection.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneSelectionBlueprintDeselection.cs @@ -12,7 +12,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Editing { - public class TestSceneSelectionBlueprintDeselection : EditorTestScene + public partial class TestSceneSelectionBlueprintDeselection : EditorTestScene { protected override Ruleset CreateEditorRuleset() => new OsuRuleset(); diff --git a/osu.Game.Tests/Visual/Editing/TestSceneSetupScreen.cs b/osu.Game.Tests/Visual/Editing/TestSceneSetupScreen.cs index ddb458d570..c0e681b8b4 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneSetupScreen.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneSetupScreen.cs @@ -20,7 +20,7 @@ using osu.Game.Screens.Edit.Setup; namespace osu.Game.Tests.Visual.Editing { [TestFixture] - public class TestSceneSetupScreen : EditorClockTestScene + public partial class TestSceneSetupScreen : EditorClockTestScene { [Cached(typeof(EditorBeatmap))] [Cached(typeof(IBeatSnapProvider))] diff --git a/osu.Game.Tests/Visual/Editing/TestSceneTapButton.cs b/osu.Game.Tests/Visual/Editing/TestSceneTapButton.cs index f36524290a..8562fb746a 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneTapButton.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneTapButton.cs @@ -13,7 +13,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Editing { - public class TestSceneTapButton : OsuManualInputManagerTestScene + public partial class TestSceneTapButton : OsuManualInputManagerTestScene { private TapButton tapButton; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneTapTimingControl.cs b/osu.Game.Tests/Visual/Editing/TestSceneTapTimingControl.cs index 6ed63515e9..f38df89e82 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneTapTimingControl.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneTapTimingControl.cs @@ -23,7 +23,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Editing { [TestFixture] - public class TestSceneTapTimingControl : EditorClockTestScene + public partial class TestSceneTapTimingControl : EditorClockTestScene { private EditorBeatmap editorBeatmap => editorBeatmapContainer?.EditorBeatmap; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneTimelineBlueprintContainer.cs b/osu.Game.Tests/Visual/Editing/TestSceneTimelineBlueprintContainer.cs index c098b683a6..b63296a48d 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneTimelineBlueprintContainer.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneTimelineBlueprintContainer.cs @@ -10,7 +10,7 @@ using osu.Game.Screens.Edit.Compose.Components.Timeline; namespace osu.Game.Tests.Visual.Editing { [TestFixture] - public class TestSceneTimelineBlueprintContainer : TimelineTestScene + public partial class TestSceneTimelineBlueprintContainer : TimelineTestScene { public override Drawable CreateTestComponent() => new TimelineBlueprintContainer(Composer); diff --git a/osu.Game.Tests/Visual/Editing/TestSceneTimelineHitObjectBlueprint.cs b/osu.Game.Tests/Visual/Editing/TestSceneTimelineHitObjectBlueprint.cs index 603dbf4c67..709d796e97 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneTimelineHitObjectBlueprint.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneTimelineHitObjectBlueprint.cs @@ -18,7 +18,7 @@ using static osu.Game.Screens.Edit.Compose.Components.Timeline.TimelineHitObject namespace osu.Game.Tests.Visual.Editing { - public class TestSceneTimelineHitObjectBlueprint : TimelineTestScene + public partial class TestSceneTimelineHitObjectBlueprint : TimelineTestScene { public override Drawable CreateTestComponent() => new TimelineBlueprintContainer(Composer); diff --git a/osu.Game.Tests/Visual/Editing/TestSceneTimelineSelection.cs b/osu.Game.Tests/Visual/Editing/TestSceneTimelineSelection.cs index 54ad4e25e4..50eeb9a54b 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneTimelineSelection.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneTimelineSelection.cs @@ -20,7 +20,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Editing { - public class TestSceneTimelineSelection : EditorTestScene + public partial class TestSceneTimelineSelection : EditorTestScene { protected override Ruleset CreateEditorRuleset() => new OsuRuleset(); diff --git a/osu.Game.Tests/Visual/Editing/TestSceneTimelineTickDisplay.cs b/osu.Game.Tests/Visual/Editing/TestSceneTimelineTickDisplay.cs index b02f0b09b4..41fb3ed8b9 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneTimelineTickDisplay.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneTimelineTickDisplay.cs @@ -13,7 +13,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Editing { [TestFixture] - public class TestSceneTimelineTickDisplay : TimelineTestScene + public partial class TestSceneTimelineTickDisplay : TimelineTestScene { public override Drawable CreateTestComponent() => Empty(); // tick display is implicitly inside the timeline. diff --git a/osu.Game.Tests/Visual/Editing/TestSceneTimelineZoom.cs b/osu.Game.Tests/Visual/Editing/TestSceneTimelineZoom.cs index 11ac102814..19f4678c15 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneTimelineZoom.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneTimelineZoom.cs @@ -8,7 +8,7 @@ using osu.Framework.Graphics; namespace osu.Game.Tests.Visual.Editing { - public class TestSceneTimelineZoom : TimelineTestScene + public partial class TestSceneTimelineZoom : TimelineTestScene { public override Drawable CreateTestComponent() => Empty(); diff --git a/osu.Game.Tests/Visual/Editing/TestSceneTimingScreen.cs b/osu.Game.Tests/Visual/Editing/TestSceneTimingScreen.cs index e7805bf393..216c35de65 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneTimingScreen.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneTimingScreen.cs @@ -10,6 +10,8 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Testing; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Graphics.Containers; using osu.Game.Overlays; using osu.Game.Rulesets.Edit; using osu.Game.Screens.Edit; @@ -20,12 +22,13 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Editing { [TestFixture] - public class TestSceneTimingScreen : EditorClockTestScene + public partial class TestSceneTimingScreen : EditorClockTestScene { [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue); private TimingScreen timingScreen; + private EditorBeatmap editorBeatmap; protected override bool ScrollUsingMouseWheel => false; @@ -35,8 +38,11 @@ namespace osu.Game.Tests.Visual.Editing Beatmap.Value = CreateWorkingBeatmap(Ruleset.Value); Beatmap.Disabled = true; + } - var editorBeatmap = new EditorBeatmap(Beatmap.Value.GetPlayableBeatmap(Ruleset.Value)); + private void reloadEditorBeatmap() + { + editorBeatmap = new EditorBeatmap(Beatmap.Value.GetPlayableBeatmap(Ruleset.Value)); Child = new DependencyProvidingContainer { @@ -58,7 +64,9 @@ namespace osu.Game.Tests.Visual.Editing { AddStep("Stop clock", () => EditorClock.Stop()); - AddUntilStep("wait for rows to load", () => Child.ChildrenOfType().Any()); + AddStep("Reload Editor Beatmap", reloadEditorBeatmap); + + AddUntilStep("Wait for rows to load", () => Child.ChildrenOfType().Any()); } [Test] @@ -95,6 +103,37 @@ namespace osu.Game.Tests.Visual.Editing AddUntilStep("Selection changed", () => timingScreen.SelectedGroup.Value.Time == 69670); } + [Test] + public void TestScrollControlGroupIntoView() + { + AddStep("Add many control points", () => + { + editorBeatmap.ControlPointInfo.Clear(); + + editorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint()); + + for (int i = 0; i < 100; i++) + { + editorBeatmap.ControlPointInfo.Add((i + 1) * 1000, new EffectControlPoint + { + KiaiMode = Convert.ToBoolean(i % 2), + }); + } + }); + + AddStep("Select first effect point", () => + { + InputManager.MoveMouseTo(Child.ChildrenOfType().First()); + InputManager.Click(MouseButton.Left); + }); + + AddStep("Seek to beginning", () => EditorClock.Seek(0)); + + AddStep("Seek to last point", () => EditorClock.Seek(101 * 1000)); + + AddUntilStep("Scrolled to end", () => timingScreen.ChildrenOfType().First().IsScrolledToEnd()); + } + protected override void Dispose(bool isDisposing) { Beatmap.Disabled = false; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneWaveform.cs b/osu.Game.Tests/Visual/Editing/TestSceneWaveform.cs index 82b0d70cff..4c2b77bb1d 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneWaveform.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneWaveform.cs @@ -20,7 +20,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.Editing { [TestFixture] - public class TestSceneWaveform : OsuTestScene + public partial class TestSceneWaveform : OsuTestScene { private IWorkingBeatmap waveformBeatmap; @@ -104,7 +104,7 @@ namespace osu.Game.Tests.Visual.Editing AddUntilStep("wait for load", () => graph.Loaded.IsSet); } - public class TestWaveformGraph : WaveformGraph + public partial class TestWaveformGraph : WaveformGraph { public readonly ManualResetEventSlim Loaded = new ManualResetEventSlim(); diff --git a/osu.Game.Tests/Visual/Editing/TestSceneZoomableScrollContainer.cs b/osu.Game.Tests/Visual/Editing/TestSceneZoomableScrollContainer.cs index 89c5b9b23b..a141e4d431 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneZoomableScrollContainer.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneZoomableScrollContainer.cs @@ -21,9 +21,9 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Editing { - public class TestSceneZoomableScrollContainer : OsuManualInputManagerTestScene + public partial class TestSceneZoomableScrollContainer : OsuManualInputManagerTestScene { - private ZoomableScrollContainer scrollContainer; + private TestZoomableScrollContainer scrollContainer; private Drawable innerBox; [SetUpSteps] @@ -47,7 +47,7 @@ namespace osu.Game.Tests.Visual.Editing RelativeSizeAxes = Axes.Both, Colour = OsuColour.Gray(30) }, - scrollContainer = new ZoomableScrollContainer(1, 60, 1) + scrollContainer = new TestZoomableScrollContainer(1, 60, 1) { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -93,6 +93,14 @@ namespace osu.Game.Tests.Visual.Editing AddAssert("Inner container width matches scroll container", () => innerBox.DrawWidth == scrollContainer.DrawWidth); } + [Test] + public void TestWidthUpdatesOnSecondZoomSetup() + { + AddAssert("Inner container width = 1x", () => innerBox.DrawWidth == scrollContainer.DrawWidth); + AddStep("reload zoom", () => scrollContainer.SetupZoom(10, 10, 60)); + AddAssert("Inner container width = 10x", () => innerBox.DrawWidth == scrollContainer.DrawWidth * 10); + } + [Test] public void TestZoom0() { @@ -190,5 +198,15 @@ namespace osu.Game.Tests.Visual.Editing private Quad scrollQuad => scrollContainer.ScreenSpaceDrawQuad; private Quad boxQuad => innerBox.ScreenSpaceDrawQuad; + + private partial class TestZoomableScrollContainer : ZoomableScrollContainer + { + public TestZoomableScrollContainer(int minimum, float maximum, float initial) + : base(minimum, maximum, initial) + { + } + + public new void SetupZoom(float initial, float minimum, float maximum) => base.SetupZoom(initial, minimum, maximum); + } } } diff --git a/osu.Game.Tests/Visual/Editing/TimelineTestScene.cs b/osu.Game.Tests/Visual/Editing/TimelineTestScene.cs index c2b1ba3aba..cb45ad5a07 100644 --- a/osu.Game.Tests/Visual/Editing/TimelineTestScene.cs +++ b/osu.Game.Tests/Visual/Editing/TimelineTestScene.cs @@ -23,7 +23,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.Editing { - public abstract class TimelineTestScene : EditorClockTestScene + public abstract partial class TimelineTestScene : EditorClockTestScene { protected TimelineArea TimelineArea { get; private set; } @@ -87,7 +87,7 @@ namespace osu.Game.Tests.Visual.Editing public abstract Drawable CreateTestComponent(); - private class AudioVisualiser : CompositeDrawable + private partial class AudioVisualiser : CompositeDrawable { private readonly Drawable marker; @@ -126,7 +126,7 @@ namespace osu.Game.Tests.Visual.Editing } } - private class StartStopButton : OsuButton + private partial class StartStopButton : OsuButton { [Resolved] private EditorClock editorClock { get; set; } diff --git a/osu.Game.Tests/Visual/Gameplay/OsuPlayerTestScene.cs b/osu.Game.Tests/Visual/Gameplay/OsuPlayerTestScene.cs index f173170da5..7ff059ff77 100644 --- a/osu.Game.Tests/Visual/Gameplay/OsuPlayerTestScene.cs +++ b/osu.Game.Tests/Visual/Gameplay/OsuPlayerTestScene.cs @@ -11,7 +11,7 @@ namespace osu.Game.Tests.Visual.Gameplay /// /// A with an arbitrary ruleset value to test with. /// - public abstract class OsuPlayerTestScene : PlayerTestScene + public abstract partial class OsuPlayerTestScene : PlayerTestScene { protected override Ruleset CreatePlayerRuleset() => new OsuRuleset(); } diff --git a/osu.Game.Tests/Visual/Gameplay/SkinnableHUDComponentTestScene.cs b/osu.Game.Tests/Visual/Gameplay/SkinnableHUDComponentTestScene.cs index ea4aa98f86..545b3c2cf4 100644 --- a/osu.Game.Tests/Visual/Gameplay/SkinnableHUDComponentTestScene.cs +++ b/osu.Game.Tests/Visual/Gameplay/SkinnableHUDComponentTestScene.cs @@ -9,7 +9,7 @@ using osu.Game.Skinning; namespace osu.Game.Tests.Visual.Gameplay { - public abstract class SkinnableHUDComponentTestScene : SkinnableTestScene + public abstract partial class SkinnableHUDComponentTestScene : SkinnableTestScene { protected override Ruleset CreateRulesetForSkinProvider() => new OsuRuleset(); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneAllRulesetPlayers.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneAllRulesetPlayers.cs index a8d7148bd2..e86302bbd1 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneAllRulesetPlayers.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneAllRulesetPlayers.cs @@ -20,7 +20,7 @@ namespace osu.Game.Tests.Visual.Gameplay /// A base class which runs test for all available rulesets. /// Steps to be run for each ruleset should be added via . /// - public abstract class TestSceneAllRulesetPlayers : RateAdjustedBeatmapTestScene + public abstract partial class TestSceneAllRulesetPlayers : RateAdjustedBeatmapTestScene { protected Player Player { get; private set; } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs index f2fe55d719..5442b3bfef 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs @@ -19,7 +19,7 @@ using osu.Game.Users.Drawables; namespace osu.Game.Tests.Visual.Gameplay { [Description("Player instantiated with an autoplay mod.")] - public class TestSceneAutoplay : TestSceneAllRulesetPlayers + public partial class TestSceneAutoplay : TestSceneAllRulesetPlayers { protected new TestReplayPlayer Player => (TestReplayPlayer)base.Player; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneBeatmapOffsetControl.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneBeatmapOffsetControl.cs index cfd282c404..6eae795630 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneBeatmapOffsetControl.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneBeatmapOffsetControl.cs @@ -14,7 +14,7 @@ using osu.Game.Tests.Visual.Ranking; namespace osu.Game.Tests.Visual.Gameplay { - public class TestSceneBeatmapOffsetControl : OsuTestScene + public partial class TestSceneBeatmapOffsetControl : OsuTestScene { private BeatmapOffsetControl offsetControl; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneBeatmapSkinFallbacks.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneBeatmapSkinFallbacks.cs index 8ad97eb33c..5cd8c00935 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneBeatmapSkinFallbacks.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneBeatmapSkinFallbacks.cs @@ -26,7 +26,7 @@ using osu.Game.Storyboards; namespace osu.Game.Tests.Visual.Gameplay { - public class TestSceneBeatmapSkinFallbacks : OsuPlayerTestScene + public partial class TestSceneBeatmapSkinFallbacks : OsuPlayerTestScene { private ISkin currentBeatmapSkin; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneBezierConverter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneBezierConverter.cs index 28a9d17882..a40eab5948 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneBezierConverter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneBezierConverter.cs @@ -14,7 +14,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Gameplay { - public class TestSceneBezierConverter : OsuTestScene + public partial class TestSceneBezierConverter : OsuTestScene { private readonly SmoothPath drawablePath; private readonly SmoothPath controlPointDrawablePath; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneBreakTracker.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneBreakTracker.cs index e31b325d54..c010b2c809 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneBreakTracker.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneBreakTracker.cs @@ -14,7 +14,7 @@ using osu.Game.Screens.Play; namespace osu.Game.Tests.Visual.Gameplay { [TestFixture] - public class TestSceneBreakTracker : OsuTestScene + public partial class TestSceneBreakTracker : OsuTestScene { private readonly BreakOverlay breakOverlay; @@ -161,7 +161,7 @@ namespace osu.Game.Tests.Visual.Gameplay }); } - private class TestBreakTracker : BreakTracker + private partial class TestBreakTracker : BreakTracker { public readonly FramedClock FramedManualClock; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneClicksPerSecondCalculator.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneClicksPerSecondCalculator.cs index 2dad5e2c32..6b8e0e1088 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneClicksPerSecondCalculator.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneClicksPerSecondCalculator.cs @@ -15,7 +15,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Gameplay { - public class TestSceneClicksPerSecondCalculator : OsuTestScene + public partial class TestSceneClicksPerSecondCalculator : OsuTestScene { private ClicksPerSecondCalculator calculator = null!; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneColourHitErrorMeter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneColourHitErrorMeter.cs index a953db4f19..0784aac298 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneColourHitErrorMeter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneColourHitErrorMeter.cs @@ -19,7 +19,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Gameplay { - public class TestSceneColourHitErrorMeter : OsuTestScene + public partial class TestSceneColourHitErrorMeter : OsuTestScene { private DependencyProvidingContainer dependencyContainer = null!; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneCompletionCancellation.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneCompletionCancellation.cs index 13ceb05aff..434d853992 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneCompletionCancellation.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneCompletionCancellation.cs @@ -19,7 +19,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Gameplay { - public class TestSceneCompletionCancellation : OsuPlayerTestScene + public partial class TestSceneCompletionCancellation : OsuPlayerTestScene { [Resolved] private AudioManager audio { get; set; } @@ -122,7 +122,7 @@ namespace osu.Game.Tests.Visual.Gameplay protected override TestPlayer CreatePlayer(Ruleset ruleset) => new FakeRankingPushPlayer(); - public class FakeRankingPushPlayer : TestPlayer + public partial class FakeRankingPushPlayer : TestPlayer { public bool ResultsCreated { get; private set; } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs index 334d8f1452..287b7d43b4 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs @@ -33,7 +33,7 @@ using JetBrains.Annotations; namespace osu.Game.Tests.Visual.Gameplay { - public class TestSceneDrawableScrollingRuleset : OsuTestScene + public partial class TestSceneDrawableScrollingRuleset : OsuTestScene { /// /// The amount of time visible by the "view window" of the playfield. @@ -305,7 +305,7 @@ namespace osu.Game.Tests.Visual.Gameplay public override string ShortName { get; } = string.Empty; } - private class TestDrawableScrollingRuleset : DrawableScrollingRuleset + private partial class TestDrawableScrollingRuleset : DrawableScrollingRuleset { public bool RelativeScaleBeatLengthsOverride { get; set; } @@ -342,7 +342,7 @@ namespace osu.Game.Tests.Visual.Gameplay protected override Playfield CreatePlayfield() => new TestPlayfield(); } - private class TestPlayfield : ScrollingPlayfield + private partial class TestPlayfield : ScrollingPlayfield { public TestPlayfield() { @@ -427,7 +427,7 @@ namespace osu.Game.Tests.Visual.Gameplay } } - private class DrawableTestHitObject : DrawableHitObject + private partial class DrawableTestHitObject : DrawableHitObject { public DrawableTestHitObject([CanBeNull] TestHitObject hitObject) : base(hitObject) @@ -457,7 +457,7 @@ namespace osu.Game.Tests.Visual.Gameplay protected override void Update() => LifetimeEnd = HitObject.EndTime; } - private class DrawableTestPooledHitObject : DrawableTestHitObject + private partial class DrawableTestPooledHitObject : DrawableTestHitObject { public DrawableTestPooledHitObject() : base(null) @@ -467,7 +467,7 @@ namespace osu.Game.Tests.Visual.Gameplay } } - private class DrawableTestParentHitObject : DrawableTestHitObject + private partial class DrawableTestParentHitObject : DrawableTestHitObject { private readonly Container container; @@ -491,7 +491,7 @@ namespace osu.Game.Tests.Visual.Gameplay protected override void ClearNestedHitObjects() => container.Clear(false); } - private class DrawableTestPooledParentHitObject : DrawableTestParentHitObject + private partial class DrawableTestPooledParentHitObject : DrawableTestParentHitObject { public DrawableTestPooledParentHitObject() : base(null) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableStoryboardSprite.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableStoryboardSprite.cs index 3fc456c411..ec4bb1a86b 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableStoryboardSprite.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableStoryboardSprite.cs @@ -17,7 +17,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Gameplay { - public class TestSceneDrawableStoryboardSprite : SkinnableTestScene + public partial class TestSceneDrawableStoryboardSprite : SkinnableTestScene { protected override Ruleset CreateRulesetForSkinProvider() => new OsuRuleset(); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs index ce01bf2fb5..6cb1101173 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs @@ -13,7 +13,7 @@ using osu.Game.Screens.Play; namespace osu.Game.Tests.Visual.Gameplay { - public class TestSceneFailAnimation : TestSceneAllRulesetPlayers + public partial class TestSceneFailAnimation : TestSceneAllRulesetPlayers { protected override Player CreatePlayer(Ruleset ruleset) { @@ -39,7 +39,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddAssert("frequency only ever decreased", () => !((FailPlayer)Player).FrequencyIncreased); } - private class FailPlayer : TestPlayer + private partial class FailPlayer : TestPlayer { public new FailOverlay FailOverlay => base.FailOverlay; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs index 5e87eff717..e779c6c1cb 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs @@ -13,7 +13,7 @@ using osu.Game.Screens.Play; namespace osu.Game.Tests.Visual.Gameplay { - public class TestSceneFailJudgement : TestSceneAllRulesetPlayers + public partial class TestSceneFailJudgement : TestSceneAllRulesetPlayers { protected override Player CreatePlayer(Ruleset ruleset) { @@ -37,7 +37,7 @@ namespace osu.Game.Tests.Visual.Gameplay }); } - private class FailPlayer : TestPlayer + private partial class FailPlayer : TestPlayer { public new HealthProcessor HealthProcessor => base.HealthProcessor; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneFailingLayer.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneFailingLayer.cs index 90e36ecae2..235ada2d63 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneFailingLayer.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneFailingLayer.cs @@ -16,7 +16,7 @@ using osu.Game.Screens.Play.HUD; namespace osu.Game.Tests.Visual.Gameplay { - public class TestSceneFailingLayer : OsuTestScene + public partial class TestSceneFailingLayer : OsuTestScene { private FailingLayer layer; @@ -111,7 +111,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddUntilStep("layer fade is visible", () => layer.IsPresent); } - private class HealthProcessorContainer : Container + private partial class HealthProcessorContainer : Container { [Cached(typeof(HealthProcessor))] private readonly HealthProcessor healthProcessor; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneFrameStabilityContainer.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneFrameStabilityContainer.cs index ef74024b4b..534348bed3 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneFrameStabilityContainer.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneFrameStabilityContainer.cs @@ -12,7 +12,7 @@ using osu.Game.Rulesets.UI; namespace osu.Game.Tests.Visual.Gameplay { - public class TestSceneFrameStabilityContainer : OsuTestScene + public partial class TestSceneFrameStabilityContainer : OsuTestScene { private readonly ManualClock manualClock; @@ -145,7 +145,7 @@ namespace osu.Game.Tests.Visual.Gameplay private void checkRate(double rate) => AddAssert($"clock rate is {rate}", () => consumer.Clock.Rate, () => Is.EqualTo(rate)); - public class ClockConsumingChild : CompositeDrawable + public partial class ClockConsumingChild : CompositeDrawable { private readonly OsuSpriteText text; private readonly OsuSpriteText text2; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayLeaderboard.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayLeaderboard.cs index 30d2cc6423..d4000c07e7 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayLeaderboard.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayLeaderboard.cs @@ -18,7 +18,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Gameplay { [TestFixture] - public class TestSceneGameplayLeaderboard : OsuTestScene + public partial class TestSceneGameplayLeaderboard : OsuTestScene { private TestGameplayLeaderboard leaderboard; @@ -169,7 +169,7 @@ namespace osu.Game.Tests.Visual.Gameplay leaderboardScore.TotalScore.BindTo(score); } - private class TestGameplayLeaderboard : GameplayLeaderboard + private partial class TestGameplayLeaderboard : GameplayLeaderboard { public float Spacing => Flow.Spacing.Y; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs index f3a6302da0..aa5e5985c3 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs @@ -19,7 +19,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Gameplay { [Description("player pause/fail screens")] - public class TestSceneGameplayMenuOverlay : OsuManualInputManagerTestScene + public partial class TestSceneGameplayMenuOverlay : OsuManualInputManagerTestScene { private FailOverlay failOverlay; private PauseOverlay pauseOverlay; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs index bd55ed8bd6..1dffeed01b 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs @@ -17,7 +17,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Gameplay { - public class TestSceneGameplayRewinding : OsuPlayerTestScene + public partial class TestSceneGameplayRewinding : OsuPlayerTestScene { [Resolved] private AudioManager audioManager { get; set; } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySamplePlayback.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySamplePlayback.cs index 1fe2dfd4df..3d35860fef 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySamplePlayback.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySamplePlayback.cs @@ -14,7 +14,7 @@ using osu.Game.Skinning; namespace osu.Game.Tests.Visual.Gameplay { - public class TestSceneGameplaySamplePlayback : PlayerTestScene + public partial class TestSceneGameplaySamplePlayback : PlayerTestScene { [Test] public void TestAllSamplesStopDuringSeek() diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs index b6da562bd0..e184d50d7c 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs @@ -18,7 +18,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Gameplay { - public class TestSceneGameplaySampleTriggerSource : PlayerTestScene + public partial class TestSceneGameplaySampleTriggerSource : PlayerTestScene { private TestGameplaySampleTriggerSource sampleTriggerSource; protected override Ruleset CreatePlayerRuleset() => new OsuRuleset(); @@ -124,7 +124,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddRepeatStep("trigger sample", () => sampleTriggerSource.Play(), 10); } - public class TestGameplaySampleTriggerSource : GameplaySampleTriggerSource + public partial class TestGameplaySampleTriggerSource : GameplaySampleTriggerSource { public TestGameplaySampleTriggerSource(HitObjectContainer hitObjectContainer) : base(hitObjectContainer) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs index 75510fa822..29fadd151f 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Diagnostics; using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; @@ -24,7 +25,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Gameplay { - public class TestSceneHUDOverlay : OsuManualInputManagerTestScene + public partial class TestSceneHUDOverlay : OsuManualInputManagerTestScene { private OsuConfigManager localConfig = null!; @@ -187,18 +188,22 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestInputDoesntWorkWhenHUDHidden() { - SongProgressBar getSongProgress() => hudOverlay.ChildrenOfType().Single(); + SongProgressBar? getSongProgress() => hudOverlay.ChildrenOfType().SingleOrDefault(); bool seeked = false; createNew(); + AddUntilStep("wait for song progress", () => getSongProgress() != null); + AddStep("bind seek", () => { seeked = false; var progress = getSongProgress(); + Debug.Assert(progress != null); + progress.ShowHandle = true; progress.OnSeek += _ => seeked = true; }); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorMeter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorMeter.cs index b90b9b437d..e2ff2780e0 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorMeter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorMeter.cs @@ -31,7 +31,7 @@ using osu.Game.Screens.Play.HUD.HitErrorMeters; namespace osu.Game.Tests.Visual.Gameplay { - public class TestSceneHitErrorMeter : OsuTestScene + public partial class TestSceneHitErrorMeter : OsuTestScene { [Cached(typeof(ScoreProcessor))] private TestScoreProcessor scoreProcessor = new TestScoreProcessor(); @@ -263,7 +263,7 @@ namespace osu.Game.Tests.Visual.Gameplay } [SuppressMessage("ReSharper", "UnassignedGetOnlyAutoProperty")] - private class TestDrawableRuleset : DrawableRuleset + private partial class TestDrawableRuleset : DrawableRuleset { public HitWindows HitWindows; @@ -305,7 +305,7 @@ namespace osu.Game.Tests.Visual.Gameplay public override void CancelResume() => throw new NotImplementedException(); } - private class TestScoreProcessor : ScoreProcessor + private partial class TestScoreProcessor : ScoreProcessor { public TestScoreProcessor() : base(new OsuRuleset()) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHoldForMenuButton.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHoldForMenuButton.cs index 50fd1b2a51..3c225d60e0 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneHoldForMenuButton.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHoldForMenuButton.cs @@ -15,7 +15,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Gameplay { [Description("'Hold to Quit' UI element")] - public class TestSceneHoldForMenuButton : OsuManualInputManagerTestScene + public partial class TestSceneHoldForMenuButton : OsuManualInputManagerTestScene { private bool exitAction; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyBindings.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyBindings.cs index c690203f82..53c07304cf 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyBindings.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyBindings.cs @@ -20,7 +20,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Gameplay { [HeadlessTest] - public class TestSceneKeyBindings : OsuManualInputManagerTestScene + public partial class TestSceneKeyBindings : OsuManualInputManagerTestScene { private readonly ActionReceiver receiver; @@ -71,7 +71,7 @@ namespace osu.Game.Tests.Visual.Gameplay Down, } - private class TestKeyBindingContainer : DatabasedKeyBindingContainer + private partial class TestKeyBindingContainer : DatabasedKeyBindingContainer { public TestKeyBindingContainer() : base(new TestRuleset().RulesetInfo, 0) @@ -79,7 +79,7 @@ namespace osu.Game.Tests.Visual.Gameplay } } - private class ActionReceiver : CompositeDrawable, IKeyBindingHandler + private partial class ActionReceiver : CompositeDrawable, IKeyBindingHandler { public bool ReceivedAction; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs index bfda6f50cb..890ac21b40 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs @@ -13,7 +13,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Gameplay { [TestFixture] - public class TestSceneKeyCounter : OsuManualInputManagerTestScene + public partial class TestSceneKeyCounter : OsuManualInputManagerTestScene { public TestSceneKeyCounter() { diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs index c18a78fe3c..dadf3ca65f 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs @@ -15,7 +15,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Gameplay { - public class TestSceneLeadIn : RateAdjustedBeatmapTestScene + public partial class TestSceneLeadIn : RateAdjustedBeatmapTestScene { private LeadInPlayer player = null!; @@ -106,7 +106,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddUntilStep("player loaded", () => player.IsLoaded && player.Alpha == 1); } - private class LeadInPlayer : TestPlayer + private partial class LeadInPlayer : TestPlayer { public LeadInPlayer() : base(false, false) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneMedalOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneMedalOverlay.cs index 3fd36d509d..626406e4d2 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneMedalOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneMedalOverlay.cs @@ -10,7 +10,7 @@ using osu.Game.Users; namespace osu.Game.Tests.Visual.Gameplay { [TestFixture] - public class TestSceneMedalOverlay : OsuTestScene + public partial class TestSceneMedalOverlay : OsuTestScene { public TestSceneMedalOverlay() { diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneModValidity.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneModValidity.cs index 0c6b656ab6..b26f48d028 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneModValidity.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneModValidity.cs @@ -10,7 +10,7 @@ using osu.Game.Rulesets.Mods; namespace osu.Game.Tests.Visual.Gameplay { [HeadlessTest] - public class TestSceneModValidity : TestSceneAllRulesetPlayers + public partial class TestSceneModValidity : TestSceneAllRulesetPlayers { protected override void AddCheckSteps() { diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneNightcoreBeatContainer.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneNightcoreBeatContainer.cs index 966138c0b3..84334ba0a9 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneNightcoreBeatContainer.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneNightcoreBeatContainer.cs @@ -13,7 +13,7 @@ using osu.Game.Tests.Visual.UserInterface; namespace osu.Game.Tests.Visual.Gameplay { - public class TestSceneNightcoreBeatContainer : TestSceneBeatSyncedContainer + public partial class TestSceneNightcoreBeatContainer : TestSceneBeatSyncedContainer { protected override void LoadComplete() { diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneOverlayActivation.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneOverlayActivation.cs index 789e7e770f..269d104fa3 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneOverlayActivation.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneOverlayActivation.cs @@ -10,7 +10,7 @@ using osu.Game.Rulesets; namespace osu.Game.Tests.Visual.Gameplay { - public class TestSceneOverlayActivation : OsuPlayerTestScene + public partial class TestSceneOverlayActivation : OsuPlayerTestScene { protected new OverlayTestPlayer Player => base.Player as OverlayTestPlayer; @@ -64,7 +64,7 @@ namespace osu.Game.Tests.Visual.Gameplay protected override TestPlayer CreatePlayer(Ruleset ruleset) => new OverlayTestPlayer(); - protected class OverlayTestPlayer : TestPlayer + protected partial class OverlayTestPlayer : TestPlayer { public new OverlayActivation OverlayActivationMode => base.OverlayActivationMode.Value; } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneParticleExplosion.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneParticleExplosion.cs index bddf051871..2d48ac81e2 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneParticleExplosion.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneParticleExplosion.cs @@ -13,7 +13,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Gameplay { [TestFixture] - public class TestSceneParticleExplosion : OsuTestScene + public partial class TestSceneParticleExplosion : OsuTestScene { private ParticleExplosion explosion; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneParticleSpewer.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneParticleSpewer.cs index 66441c8bad..c73d57dc2b 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneParticleSpewer.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneParticleSpewer.cs @@ -18,7 +18,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Gameplay { [TestFixture] - public class TestSceneParticleSpewer : OsuTestScene + public partial class TestSceneParticleSpewer : OsuTestScene { private TestParticleSpewer spewer; @@ -88,7 +88,7 @@ namespace osu.Game.Tests.Visual.Gameplay Size = new Vector2(0.5f), }; - private class TestParticleSpewer : ParticleSpewer + private partial class TestParticleSpewer : ParticleSpewer { public const int MAX_DURATION = 1500; private const int rate = 250; diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs index d0371acce7..7880a849a2 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs @@ -21,7 +21,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Gameplay { - public class TestScenePause : OsuPlayerTestScene + public partial class TestScenePause : OsuPlayerTestScene { protected new PausePlayer Player => (PausePlayer)base.Player; @@ -396,7 +396,7 @@ namespace osu.Game.Tests.Visual.Gameplay protected override TestPlayer CreatePlayer(Ruleset ruleset) => new PausePlayer(); - protected class PausePlayer : TestPlayer + protected partial class PausePlayer : TestPlayer { public double LastPauseTime { get; private set; } public double LastResumeTime { get; private set; } diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePauseWhenInactive.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePauseWhenInactive.cs index e1c755b90c..b770f72f19 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePauseWhenInactive.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePauseWhenInactive.cs @@ -20,7 +20,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Gameplay { [HeadlessTest] // we alter unsafe properties on the game host to test inactive window state. - public class TestScenePauseWhenInactive : OsuPlayerTestScene + public partial class TestScenePauseWhenInactive : OsuPlayerTestScene { [Resolved] private GameHost host { get; set; } diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePerformancePointsCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePerformancePointsCounter.cs index a86e707400..9622caabf5 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePerformancePointsCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePerformancePointsCounter.cs @@ -21,7 +21,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Gameplay { - public class TestScenePerformancePointsCounter : OsuTestScene + public partial class TestScenePerformancePointsCounter : OsuTestScene { private DependencyProvidingContainer dependencyContainer; diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs index 6b24ac7384..2ea27c2fef 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs @@ -32,7 +32,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Gameplay { - public class TestScenePlayerLoader : ScreenTestScene + public partial class TestScenePlayerLoader : ScreenTestScene { private TestPlayerLoader loader; private TestPlayer player; @@ -451,7 +451,7 @@ namespace osu.Game.Tests.Visual.Gameplay private EpilepsyWarning getWarning() => loader.ChildrenOfType().SingleOrDefault(); - private class TestPlayerLoader : PlayerLoader + private partial class TestPlayerLoader : PlayerLoader { public new VisualSettings VisualSettings => base.VisualSettings; @@ -482,7 +482,7 @@ namespace osu.Game.Tests.Visual.Gameplay public ScoreRank AdjustRank(ScoreRank rank, double accuracy) => rank; } - protected class SlowLoadPlayer : TestPlayer + protected partial class SlowLoadPlayer : TestPlayer { public readonly ManualResetEventSlim AllowLoad = new ManualResetEventSlim(false); diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLocalScoreImport.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLocalScoreImport.cs index 38a091dd85..80c4e4bce9 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLocalScoreImport.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLocalScoreImport.cs @@ -27,7 +27,7 @@ using osu.Game.Tests.Resources; namespace osu.Game.Tests.Visual.Gameplay { - public class TestScenePlayerLocalScoreImport : PlayerTestScene + public partial class TestScenePlayerLocalScoreImport : PlayerTestScene { private BeatmapManager beatmaps = null!; private RulesetStore rulesets = null!; diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerReferenceLeaking.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerReferenceLeaking.cs index ec0eea62d9..b1209e3a4f 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerReferenceLeaking.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerReferenceLeaking.cs @@ -12,7 +12,7 @@ using osu.Game.Storyboards; namespace osu.Game.Tests.Visual.Gameplay { - public class TestScenePlayerReferenceLeaking : TestSceneAllRulesetPlayers + public partial class TestScenePlayerReferenceLeaking : TestSceneAllRulesetPlayers { private readonly WeakList workingWeakReferences = new WeakList(); diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs index d1bdfb1dfa..1a7ea20cc0 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs @@ -26,7 +26,7 @@ using osu.Game.Tests.Beatmaps; namespace osu.Game.Tests.Visual.Gameplay { - public class TestScenePlayerScoreSubmission : PlayerTestScene + public partial class TestScenePlayerScoreSubmission : PlayerTestScene { protected override bool AllowFail => allowFail; @@ -181,7 +181,8 @@ namespace osu.Game.Tests.Visual.Gameplay AddUntilStep("wait for fail", () => Player.GameplayState.HasFailed); AddStep("exit", () => Player.Exit()); - AddAssert("ensure failing submission", () => Player.SubmittedScore?.ScoreInfo.Passed == false); + AddUntilStep("wait for submission", () => Player.SubmittedScore != null); + AddAssert("ensure failing submission", () => Player.SubmittedScore.ScoreInfo.Passed == false); } [Test] @@ -209,7 +210,9 @@ namespace osu.Game.Tests.Visual.Gameplay addFakeHit(); AddStep("exit", () => Player.Exit()); - AddAssert("ensure failing submission", () => Player.SubmittedScore?.ScoreInfo.Passed == false); + + AddUntilStep("wait for submission", () => Player.SubmittedScore != null); + AddAssert("ensure failing submission", () => Player.SubmittedScore.ScoreInfo.Passed == false); } [Test] @@ -257,7 +260,7 @@ namespace osu.Game.Tests.Visual.Gameplay { prepareTestAPI(true); - createPlayerTest(false, createRuleset: () => new OsuRuleset + createPlayerTest(createRuleset: () => new OsuRuleset { RulesetInfo = { @@ -345,7 +348,7 @@ namespace osu.Game.Tests.Visual.Gameplay }); } - protected class FakeImportingPlayer : TestPlayer + protected partial class FakeImportingPlayer : TestPlayer { public bool ScoreImportStarted { get; set; } public SemaphoreSlim AllowImportCompletion { get; } diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePoolingRuleset.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePoolingRuleset.cs index 618ffbcb0e..55ee6c9fc9 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePoolingRuleset.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePoolingRuleset.cs @@ -31,7 +31,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.Gameplay { - public class TestScenePoolingRuleset : OsuTestScene + public partial class TestScenePoolingRuleset : OsuTestScene { private const double time_between_objects = 1000; @@ -194,7 +194,7 @@ namespace osu.Game.Tests.Visual.Gameplay public override string ShortName { get; } = string.Empty; } - private class TestDrawablePoolingRuleset : DrawableRuleset + private partial class TestDrawablePoolingRuleset : DrawableRuleset { public int PoolSize; @@ -210,7 +210,7 @@ namespace osu.Game.Tests.Visual.Gameplay protected override Playfield CreatePlayfield() => new TestPlayfield(PoolSize); } - private class TestPlayfield : Playfield + private partial class TestPlayfield : Playfield { private readonly int poolSize; @@ -283,7 +283,7 @@ namespace osu.Game.Tests.Visual.Gameplay public double Duration { get; set; } } - private class DrawableTestHitObject : DrawableHitObject + private partial class DrawableTestHitObject : DrawableHitObject { public DrawableTestHitObject() : base(null) @@ -335,7 +335,7 @@ namespace osu.Game.Tests.Visual.Gameplay { } - private class DrawableTestKilledHitObject : DrawableHitObject + private partial class DrawableTestKilledHitObject : DrawableHitObject { public DrawableTestKilledHitObject() : base(null) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneReplay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneReplay.cs index faa6a429c5..c476aae202 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneReplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneReplay.cs @@ -15,7 +15,7 @@ using osu.Game.Screens.Play; namespace osu.Game.Tests.Visual.Gameplay { [Description("Player instantiated with a replay.")] - public class TestSceneReplay : TestSceneAllRulesetPlayers + public partial class TestSceneReplay : TestSceneAllRulesetPlayers { protected override Player CreatePlayer(Ruleset ruleset) { @@ -31,7 +31,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddAssert("cannot fail", () => !((ScoreAccessibleReplayPlayer)Player).AllowFail); } - private class ScoreAccessibleReplayPlayer : ReplayPlayer + private partial class ScoreAccessibleReplayPlayer : ReplayPlayer { public new ScoreProcessor ScoreProcessor => base.ScoreProcessor; public new HUDOverlay HUDOverlay => base.HUDOverlay; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayDownloadButton.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayDownloadButton.cs index cd227630c1..6ccf73d8ff 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayDownloadButton.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayDownloadButton.cs @@ -24,7 +24,7 @@ using APIUser = osu.Game.Online.API.Requests.Responses.APIUser; namespace osu.Game.Tests.Visual.Gameplay { [TestFixture] - public class TestSceneReplayDownloadButton : OsuManualInputManagerTestScene + public partial class TestSceneReplayDownloadButton : OsuManualInputManagerTestScene { private const long online_score_id = 2553163309; @@ -107,7 +107,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddUntilStep("wait for load", () => downloadButton.IsLoaded); - AddAssert("state is available", () => downloadButton.State.Value == DownloadState.NotDownloaded); + checkState(DownloadState.NotDownloaded); AddStep("click button", () => { @@ -133,7 +133,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddUntilStep("wait for load", () => downloadButton.IsLoaded); - AddAssert("state is not downloaded", () => downloadButton.State.Value == DownloadState.NotDownloaded); + checkState(DownloadState.NotDownloaded); AddAssert("button is not enabled", () => !downloadButton.ChildrenOfType().First().Enabled.Value); } @@ -155,7 +155,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddUntilStep("wait for load", () => downloadButton.IsLoaded); - AddUntilStep("state is not downloaded", () => downloadButton.State.Value == DownloadState.NotDownloaded); + checkState(DownloadState.NotDownloaded); AddAssert("button is not enabled", () => !downloadButton.ChildrenOfType().First().Enabled.Value); } @@ -174,17 +174,16 @@ namespace osu.Game.Tests.Visual.Gameplay }); AddUntilStep("wait for load", () => downloadButton.IsLoaded); - - AddUntilStep("state is not downloaded", () => downloadButton.State.Value == DownloadState.NotDownloaded); + checkState(DownloadState.NotDownloaded); AddStep("import score", () => imported = scoreManager.Import(getScoreInfo(true))); - AddUntilStep("state is available", () => downloadButton.State.Value == DownloadState.LocallyAvailable); + checkState(DownloadState.LocallyAvailable); AddAssert("button is enabled", () => downloadButton.ChildrenOfType().First().Enabled.Value); AddStep("delete score", () => scoreManager.Delete(imported.Value)); - AddUntilStep("state is not downloaded", () => downloadButton.State.Value == DownloadState.NotDownloaded); + checkState(DownloadState.NotDownloaded); AddAssert("button is not enabled", () => !downloadButton.ChildrenOfType().First().Enabled.Value); } @@ -202,10 +201,13 @@ namespace osu.Game.Tests.Visual.Gameplay AddUntilStep("wait for load", () => downloadButton.IsLoaded); - AddAssert("state is unknown", () => downloadButton.State.Value == DownloadState.Unknown); + checkState(DownloadState.Unknown); AddAssert("button is not enabled", () => !downloadButton.ChildrenOfType().First().Enabled.Value); } + private void checkState(DownloadState expectedState) => + AddUntilStep($"state is {expectedState}", () => downloadButton.State.Value, () => Is.EqualTo(expectedState)); + private ScoreInfo getScoreInfo(bool replayAvailable, bool hasOnlineId = true) => new ScoreInfo { OnlineID = hasOnlineId ? online_score_id : 0, @@ -219,7 +221,7 @@ namespace osu.Game.Tests.Visual.Gameplay } }; - private class TestReplayDownloadButton : ReplayDownloadButton + private partial class TestReplayDownloadButton : ReplayDownloadButton { public void SetDownloadState(DownloadState state) => State.Value = state; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayPlayer.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayPlayer.cs index 6319b91a38..e0a6a60ff2 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayPlayer.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayPlayer.cs @@ -10,7 +10,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Gameplay { - public class TestSceneReplayPlayer : RateAdjustedBeatmapTestScene + public partial class TestSceneReplayPlayer : RateAdjustedBeatmapTestScene { protected TestReplayPlayer Player; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecorder.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecorder.cs index b3401c916b..65b409a6f7 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecorder.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecorder.cs @@ -31,7 +31,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Gameplay { - public class TestSceneReplayRecorder : OsuManualInputManagerTestScene + public partial class TestSceneReplayRecorder : OsuManualInputManagerTestScene { private TestRulesetInputManager playbackManager; private TestRulesetInputManager recordingManager; @@ -218,7 +218,7 @@ namespace osu.Game.Tests.Visual.Gameplay } } - public class TestInputConsumer : CompositeDrawable, IKeyBindingHandler + public partial class TestInputConsumer : CompositeDrawable, IKeyBindingHandler { public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => Parent.ReceivePositionalInputAt(screenSpacePos); @@ -261,7 +261,7 @@ namespace osu.Game.Tests.Visual.Gameplay } } - public class TestRulesetInputManager : RulesetInputManager + public partial class TestRulesetInputManager : RulesetInputManager { public TestRulesetInputManager(RulesetInfo ruleset, int variant, SimultaneousBindingMode unique) : base(ruleset, variant, unique) @@ -271,7 +271,7 @@ namespace osu.Game.Tests.Visual.Gameplay protected override KeyBindingContainer CreateKeyBindingContainer(RulesetInfo ruleset, int variant, SimultaneousBindingMode unique) => new TestKeyBindingContainer(); - internal class TestKeyBindingContainer : KeyBindingContainer + internal partial class TestKeyBindingContainer : KeyBindingContainer { public override IEnumerable DefaultKeyBindings => new[] { @@ -299,7 +299,7 @@ namespace osu.Game.Tests.Visual.Gameplay Down, } - internal class TestReplayRecorder : ReplayRecorder + internal partial class TestReplayRecorder : ReplayRecorder { public TestReplayRecorder(Score target) : base(target) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneScoring.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneScoring.cs index f8b5085a70..8fff07e6d8 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneScoring.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneScoring.cs @@ -28,7 +28,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Gameplay { - public class TestSceneScoring : OsuTestScene + public partial class TestSceneScoring : OsuTestScene { private GraphContainer graphs = null!; private SettingsSlider sliderMaxCombo = null!; @@ -279,7 +279,7 @@ namespace osu.Game.Tests.Visual.Gameplay } } - public class GraphContainer : Container, IHasCustomTooltip> + public partial class GraphContainer : Container, IHasCustomTooltip> { public readonly BindableList MissLocations = new BindableList(); public readonly BindableList NonPerfectLocations = new BindableList(); @@ -439,7 +439,7 @@ namespace osu.Game.Tests.Visual.Gameplay public IEnumerable TooltipContent => Content.OfType(); - public class GraphTooltip : CompositeDrawable, ITooltip> + public partial class GraphTooltip : CompositeDrawable, ITooltip> { private readonly GraphContainer graphContainer; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneScrollingHitObjects.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneScrollingHitObjects.cs index 6d036f8e9b..317d01553a 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneScrollingHitObjects.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneScrollingHitObjects.cs @@ -29,7 +29,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.Gameplay { [TestFixture] - public class TestSceneScrollingHitObjects : OsuTestScene + public partial class TestSceneScrollingHitObjects : OsuTestScene { [Cached(typeof(IReadOnlyList))] private IReadOnlyList mods { get; set; } = Array.Empty(); @@ -252,7 +252,7 @@ namespace osu.Game.Tests.Visual.Gameplay private void setScrollAlgorithm(ScrollVisualisationMethod algorithm) => scrollContainers.ForEach(c => c.ScrollAlgorithm = algorithm); - private class TestPlayfield : ScrollingPlayfield + private partial class TestPlayfield : ScrollingPlayfield { public new ScrollingDirection Direction => base.Direction.Value; @@ -279,7 +279,7 @@ namespace osu.Game.Tests.Visual.Gameplay protected override ScrollingHitObjectContainer CreateScrollingHitObjectContainer() => new TestScrollingHitObjectContainer(); } - private class TestDrawableControlPoint : DrawableHitObject + private partial class TestDrawableControlPoint : DrawableHitObject { public TestDrawableControlPoint(ScrollingDirection direction, double time) : base(new HitObject { StartTime = time, HitWindows = HitWindows.Empty }) @@ -320,7 +320,7 @@ namespace osu.Game.Tests.Visual.Gameplay } } - private class TestDrawableHitObject : DrawableHitObject + private partial class TestDrawableHitObject : DrawableHitObject { public TestDrawableHitObject(TestHitObject hitObject) : base(hitObject) @@ -336,7 +336,7 @@ namespace osu.Game.Tests.Visual.Gameplay } } - private class TestScrollingHitObjectContainer : ScrollingHitObjectContainer + private partial class TestScrollingHitObjectContainer : ScrollingHitObjectContainer { protected override RectangleF GetConservativeBoundingBox(HitObjectLifetimeEntry entry) { diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs index 578718b7c9..48dbda9da6 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs @@ -18,7 +18,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Gameplay { - public class TestSceneSkinEditor : PlayerTestScene + public partial class TestSceneSkinEditor : PlayerTestScene { private SkinEditor? skinEditor; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorComponentsList.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorComponentsList.cs index f88b4be3d8..05a550a24d 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorComponentsList.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorComponentsList.cs @@ -13,7 +13,7 @@ using osu.Game.Skinning.Editor; namespace osu.Game.Tests.Visual.Gameplay { - public class TestSceneSkinEditorComponentsList : SkinnableTestScene + public partial class TestSceneSkinEditorComponentsList : SkinnableTestScene { [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs index 6c02ddab14..ad3911f50b 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs @@ -18,7 +18,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Gameplay { - public class TestSceneSkinEditorMultipleSkins : SkinnableTestScene + public partial class TestSceneSkinEditorMultipleSkins : SkinnableTestScene { [Cached] private readonly ScoreProcessor scoreProcessor = new ScoreProcessor(new OsuRuleset()); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableAccuracyCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableAccuracyCounter.cs index 1288f2a9f1..6f079778c5 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableAccuracyCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableAccuracyCounter.cs @@ -14,7 +14,7 @@ using osu.Game.Skinning; namespace osu.Game.Tests.Visual.Gameplay { - public class TestSceneSkinnableAccuracyCounter : SkinnableHUDComponentTestScene + public partial class TestSceneSkinnableAccuracyCounter : SkinnableHUDComponentTestScene { [Cached] private ScoreProcessor scoreProcessor = new ScoreProcessor(new OsuRuleset()); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableComboCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableComboCounter.cs index ef56f456ea..93fa953ef4 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableComboCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableComboCounter.cs @@ -14,7 +14,7 @@ using osu.Game.Skinning; namespace osu.Game.Tests.Visual.Gameplay { - public class TestSceneSkinnableComboCounter : SkinnableHUDComponentTestScene + public partial class TestSceneSkinnableComboCounter : SkinnableHUDComponentTestScene { [Cached] private ScoreProcessor scoreProcessor = new ScoreProcessor(new OsuRuleset()); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs index 97974d2368..c02cec8c75 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs @@ -24,7 +24,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.Gameplay { - public class TestSceneSkinnableDrawable : OsuTestScene + public partial class TestSceneSkinnableDrawable : OsuTestScene { [Test] public void TestConfineScaleDown() @@ -160,7 +160,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddAssert("consumer using base source", () => consumer.Drawable is BaseSourceBox); } - private class SwitchableSkinProvidingContainer : SkinProvidingContainer + private partial class SwitchableSkinProvidingContainer : SkinProvidingContainer { private bool allow = true; @@ -178,7 +178,7 @@ namespace osu.Game.Tests.Visual.Gameplay } } - private class ExposedSkinnableDrawable : SkinnableDrawable + private partial class ExposedSkinnableDrawable : SkinnableDrawable { public new Drawable Drawable => base.Drawable; @@ -188,7 +188,7 @@ namespace osu.Game.Tests.Visual.Gameplay } } - private class DefaultBox : DrawWidthBox + private partial class DefaultBox : DrawWidthBox { public DefaultBox() { @@ -196,7 +196,7 @@ namespace osu.Game.Tests.Visual.Gameplay } } - private class DrawWidthBox : Container + private partial class DrawWidthBox : Container { private readonly OsuSpriteText text; @@ -224,7 +224,7 @@ namespace osu.Game.Tests.Visual.Gameplay } } - private class NamedBox : Container + private partial class NamedBox : Container { public NamedBox(string name) { @@ -246,7 +246,7 @@ namespace osu.Game.Tests.Visual.Gameplay } } - private class SkinConsumer : SkinnableDrawable + private partial class SkinConsumer : SkinnableDrawable { public new Drawable Drawable => base.Drawable; public int SkinChangedCount { get; private set; } @@ -263,7 +263,7 @@ namespace osu.Game.Tests.Visual.Gameplay } } - private class BaseSourceBox : NamedBox + private partial class BaseSourceBox : NamedBox { public BaseSourceBox() : base("Base Source") @@ -271,7 +271,7 @@ namespace osu.Game.Tests.Visual.Gameplay } } - private class SecondarySourceBox : NamedBox + private partial class SecondarySourceBox : NamedBox { public SecondarySourceBox() : base("Secondary Source") @@ -316,7 +316,7 @@ namespace osu.Game.Tests.Visual.Gameplay } [Cached(typeof(ISkinSource))] - private class SkinSourceContainer : Container, ISkinSource + private partial class SkinSourceContainer : Container, ISkinSource { public Drawable GetDrawableComponent(ISkinComponentLookup componentLookupName) => new BaseSourceBox(); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs index 485c76ac5c..1f2329af4a 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs @@ -23,7 +23,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Gameplay { - public class TestSceneSkinnableHUDOverlay : SkinnableTestScene + public partial class TestSceneSkinnableHUDOverlay : SkinnableTestScene { private HUDOverlay hudOverlay; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHealthDisplay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHealthDisplay.cs index 2d6ad28b90..7f6c9d7804 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHealthDisplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHealthDisplay.cs @@ -16,7 +16,7 @@ using osu.Game.Skinning; namespace osu.Game.Tests.Visual.Gameplay { - public class TestSceneSkinnableHealthDisplay : SkinnableHUDComponentTestScene + public partial class TestSceneSkinnableHealthDisplay : SkinnableHUDComponentTestScene { [Cached(typeof(HealthProcessor))] private HealthProcessor healthProcessor = new DrainingHealthProcessor(0); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableScoreCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableScoreCounter.cs index 1b3538cc21..c95e8ee5b2 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableScoreCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableScoreCounter.cs @@ -13,7 +13,7 @@ using osu.Game.Skinning; namespace osu.Game.Tests.Visual.Gameplay { - public class TestSceneSkinnableScoreCounter : SkinnableHUDComponentTestScene + public partial class TestSceneSkinnableScoreCounter : SkinnableHUDComponentTestScene { [Cached] private ScoreProcessor scoreProcessor = new ScoreProcessor(new OsuRuleset()); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableSound.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableSound.cs index 8122d8defb..5c69062e67 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableSound.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableSound.cs @@ -20,7 +20,7 @@ using osu.Game.Skinning; namespace osu.Game.Tests.Visual.Gameplay { - public class TestSceneSkinnableSound : OsuTestScene + public partial class TestSceneSkinnableSound : OsuTestScene { private TestSkinSourceContainer skinSource; private PausableSkinnableSound skinnableSound; @@ -131,7 +131,7 @@ namespace osu.Game.Tests.Visual.Gameplay } [Cached(typeof(ISkinSource))] - private class TestSkinSourceContainer : Container, ISkinSource, ISamplePlaybackDisabler + private partial class TestSkinSourceContainer : Container, ISkinSource, ISamplePlaybackDisabler { [Resolved] private ISkinSource source { get; set; } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs index 1bba62a5cf..8b1a8307ca 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs @@ -15,7 +15,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Gameplay { [TestFixture] - public class TestSceneSkipOverlay : OsuManualInputManagerTestScene + public partial class TestSceneSkipOverlay : OsuManualInputManagerTestScene { private TestSkipOverlay skip; private int requestCount; @@ -162,7 +162,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddAssert($"request count is {expected}", () => requestCount, () => Is.EqualTo(expected)); } - private class TestSkipOverlay : SkipOverlay + private partial class TestSkipOverlay : SkipOverlay { public TestSkipOverlay(double startTime) : base(startTime) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSliderPath.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSliderPath.cs index 7044ddad37..dfa9fdf03b 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSliderPath.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSliderPath.cs @@ -14,7 +14,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Gameplay { - public class TestSceneSliderPath : OsuTestScene + public partial class TestSceneSliderPath : OsuTestScene { private readonly SmoothPath drawablePath; private SliderPath path; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSoloGameplayLeaderboard.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSoloGameplayLeaderboard.cs index 881870921c..8ae6a2a5fc 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSoloGameplayLeaderboard.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSoloGameplayLeaderboard.cs @@ -19,7 +19,7 @@ using osu.Game.Screens.Select; namespace osu.Game.Tests.Visual.Gameplay { - public class TestSceneSoloGameplayLeaderboard : OsuTestScene + public partial class TestSceneSoloGameplayLeaderboard : OsuTestScene { [Cached] private readonly ScoreProcessor scoreProcessor = new ScoreProcessor(new OsuRuleset()); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs index 6127aa304c..2e579cc522 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs @@ -17,7 +17,7 @@ using osu.Game.Skinning; namespace osu.Game.Tests.Visual.Gameplay { [TestFixture] - public class TestSceneSongProgress : SkinnableHUDComponentTestScene + public partial class TestSceneSongProgress : SkinnableHUDComponentTestScene { private GameplayClockContainer gameplayClockContainer = null!; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgressGraph.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgressGraph.cs index 2fa3c0c7ec..5a61502978 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgressGraph.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgressGraph.cs @@ -14,7 +14,7 @@ using osu.Game.Screens.Play.HUD; namespace osu.Game.Tests.Visual.Gameplay { [TestFixture] - public class TestSceneSongProgressGraph : OsuTestScene + public partial class TestSceneSongProgressGraph : OsuTestScene { private TestSongProgressGraph graph; @@ -59,7 +59,7 @@ namespace osu.Game.Tests.Visual.Gameplay graph.Objects = objects; } - private class TestSongProgressGraph : SongProgressGraph + private partial class TestSongProgressGraph : SongProgressGraph { public int CreationCount { get; private set; } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs index 929af7f84d..ffd034e4d2 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs @@ -28,7 +28,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Gameplay { - public class TestSceneSpectator : ScreenTestScene + public partial class TestSceneSpectator : ScreenTestScene { private readonly APIUser streamingUser = new APIUser { Id = MultiplayerTestScene.PLAYER_1_ID, Username = "Test user" }; @@ -261,7 +261,7 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestFinalFramesPurgedBeforeEndingPlay() { - AddStep("begin playing", () => spectatorClient.BeginPlaying(TestGameplayState.Create(new OsuRuleset()), new Score())); + AddStep("begin playing", () => spectatorClient.BeginPlaying(0, TestGameplayState.Create(new OsuRuleset()), new Score())); AddStep("send frames and finish play", () => { @@ -388,7 +388,7 @@ namespace osu.Game.Tests.Visual.Gameplay /// /// Used for the sole purpose of adding as a resolvable dependency. /// - private class DependenciesScreen : OsuScreen + private partial class DependenciesScreen : OsuScreen { [Cached(typeof(SpectatorClient))] public readonly TestSpectatorClient SpectatorClient = new TestSpectatorClient(); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorHost.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorHost.cs index 083be3539d..1c09c29748 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorHost.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorHost.cs @@ -15,7 +15,7 @@ using osu.Game.Tests.Visual.Spectator; namespace osu.Game.Tests.Visual.Gameplay { - public class TestSceneSpectatorHost : PlayerTestScene + public partial class TestSceneSpectatorHost : PlayerTestScene { protected override Ruleset CreatePlayerRuleset() => new ManiaRuleset(); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs index 9c41c70a0e..794860b9ec 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs @@ -35,7 +35,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.Gameplay { - public class TestSceneSpectatorPlayback : OsuManualInputManagerTestScene + public partial class TestSceneSpectatorPlayback : OsuManualInputManagerTestScene { private TestRulesetInputManager playbackManager; private TestRulesetInputManager recordingManager; @@ -147,7 +147,7 @@ namespace osu.Game.Tests.Visual.Gameplay } }; - spectatorClient.BeginPlaying(TestGameplayState.Create(new OsuRuleset()), recordingScore); + spectatorClient.BeginPlaying(0, TestGameplayState.Create(new OsuRuleset()), recordingScore); spectatorClient.OnNewFrames += onNewFrames; }); } @@ -257,7 +257,7 @@ namespace osu.Game.Tests.Visual.Gameplay } } - public class TestInputConsumer : CompositeDrawable, IKeyBindingHandler + public partial class TestInputConsumer : CompositeDrawable, IKeyBindingHandler { public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => Parent.ReceivePositionalInputAt(screenSpacePos); @@ -300,7 +300,7 @@ namespace osu.Game.Tests.Visual.Gameplay } } - public class TestRulesetInputManager : RulesetInputManager + public partial class TestRulesetInputManager : RulesetInputManager { public TestRulesetInputManager(RulesetInfo ruleset, int variant, SimultaneousBindingMode unique) : base(ruleset, variant, unique) @@ -310,7 +310,7 @@ namespace osu.Game.Tests.Visual.Gameplay protected override KeyBindingContainer CreateKeyBindingContainer(RulesetInfo ruleset, int variant, SimultaneousBindingMode unique) => new TestKeyBindingContainer(); - internal class TestKeyBindingContainer : KeyBindingContainer + internal partial class TestKeyBindingContainer : KeyBindingContainer { public override IEnumerable DefaultKeyBindings => new[] { @@ -360,7 +360,7 @@ namespace osu.Game.Tests.Visual.Gameplay Down, } - internal class TestReplayRecorder : ReplayRecorder + internal partial class TestReplayRecorder : ReplayRecorder { public List SentFrames = new List(); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneStarCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneStarCounter.cs index 708a5e94de..699c8ea20a 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneStarCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneStarCounter.cs @@ -13,7 +13,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Gameplay { [TestFixture] - public class TestSceneStarCounter : OsuTestScene + public partial class TestSceneStarCounter : OsuTestScene { private readonly StarCounter starCounter; private readonly OsuSpriteText starsLabel; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs index eaf22ba9cc..dbce62cbef 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs @@ -20,7 +20,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.Gameplay { [TestFixture] - public class TestSceneStoryboard : OsuTestScene + public partial class TestSceneStoryboard : OsuTestScene { private Container storyboardContainer = null!; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardSamplePlayback.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardSamplePlayback.cs index f0e184d727..a9d4508f70 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardSamplePlayback.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardSamplePlayback.cs @@ -23,7 +23,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Gameplay { - public class TestSceneStoryboardSamplePlayback : PlayerTestScene + public partial class TestSceneStoryboardSamplePlayback : PlayerTestScene { private Storyboard storyboard; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs index a26a7e97be..0d88fb01a8 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs @@ -26,7 +26,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Gameplay { - public class TestSceneStoryboardWithOutro : PlayerTestScene + public partial class TestSceneStoryboardWithOutro : PlayerTestScene { protected override bool HasCustomSteps => true; @@ -198,7 +198,7 @@ namespace osu.Game.Tests.Visual.Gameplay return storyboard; } - protected class OutroPlayer : TestPlayer + protected partial class OutroPlayer : TestPlayer { public void ExitViaPause() => PerformExit(true); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneUnknownMod.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneUnknownMod.cs index a31347589b..cb5631e599 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneUnknownMod.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneUnknownMod.cs @@ -10,7 +10,7 @@ using osu.Game.Rulesets.Osu; namespace osu.Game.Tests.Visual.Gameplay { - public class TestSceneUnknownMod : ModTestScene + public partial class TestSceneUnknownMod : ModTestScene { protected override Ruleset CreatePlayerRuleset() => new OsuRuleset(); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneUnstableRateCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneUnstableRateCounter.cs index 60b8691bfb..2f572b46c9 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneUnstableRateCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneUnstableRateCounter.cs @@ -17,7 +17,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Gameplay { - public class TestSceneUnstableRateCounter : OsuTestScene + public partial class TestSceneUnstableRateCounter : OsuTestScene { [Cached(typeof(ScoreProcessor))] private TestScoreProcessor scoreProcessor = new TestScoreProcessor(); @@ -103,7 +103,7 @@ namespace osu.Game.Tests.Visual.Gameplay }); } - private class TestScoreProcessor : ScoreProcessor + private partial class TestScoreProcessor : ScoreProcessor { public TestScoreProcessor() : base(new OsuRuleset()) diff --git a/osu.Game.Tests/Visual/Menus/IntroTestScene.cs b/osu.Game.Tests/Visual/Menus/IntroTestScene.cs index e0f0df0554..b09dbc1a91 100644 --- a/osu.Game.Tests/Visual/Menus/IntroTestScene.cs +++ b/osu.Game.Tests/Visual/Menus/IntroTestScene.cs @@ -17,7 +17,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.Menus { [TestFixture] - public abstract class IntroTestScene : OsuTestScene + public abstract partial class IntroTestScene : OsuTestScene { [Cached] private OsuLogo logo; diff --git a/osu.Game.Tests/Visual/Menus/TestSceneDisclaimer.cs b/osu.Game.Tests/Visual/Menus/TestSceneDisclaimer.cs index 57f16bbcce..45e5a7c270 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneDisclaimer.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneDisclaimer.cs @@ -10,7 +10,7 @@ using osu.Game.Screens.Menu; namespace osu.Game.Tests.Visual.Menus { - public class TestSceneDisclaimer : ScreenTestScene + public partial class TestSceneDisclaimer : ScreenTestScene { [BackgroundDependencyLoader] private void load() diff --git a/osu.Game.Tests/Visual/Menus/TestSceneIntroCircles.cs b/osu.Game.Tests/Visual/Menus/TestSceneIntroCircles.cs index 85a3a51ddb..0c024248ea 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneIntroCircles.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneIntroCircles.cs @@ -9,7 +9,7 @@ using osu.Game.Screens.Menu; namespace osu.Game.Tests.Visual.Menus { [TestFixture] - public class TestSceneIntroCircles : IntroTestScene + public partial class TestSceneIntroCircles : IntroTestScene { protected override bool IntroReliesOnTrack => false; protected override IntroScreen CreateScreen() => new IntroCircles(); diff --git a/osu.Game.Tests/Visual/Menus/TestSceneIntroTriangles.cs b/osu.Game.Tests/Visual/Menus/TestSceneIntroTriangles.cs index 7ab04a22e5..23373892d1 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneIntroTriangles.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneIntroTriangles.cs @@ -9,7 +9,7 @@ using osu.Game.Screens.Menu; namespace osu.Game.Tests.Visual.Menus { [TestFixture] - public class TestSceneIntroTriangles : IntroTestScene + public partial class TestSceneIntroTriangles : IntroTestScene { protected override bool IntroReliesOnTrack => true; protected override IntroScreen CreateScreen() => new IntroTriangles(); diff --git a/osu.Game.Tests/Visual/Menus/TestSceneIntroWelcome.cs b/osu.Game.Tests/Visual/Menus/TestSceneIntroWelcome.cs index ae63022823..2ccf184525 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneIntroWelcome.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneIntroWelcome.cs @@ -10,7 +10,7 @@ using osu.Game.Screens.Menu; namespace osu.Game.Tests.Visual.Menus { [TestFixture] - public class TestSceneIntroWelcome : IntroTestScene + public partial class TestSceneIntroWelcome : IntroTestScene { protected override bool IntroReliesOnTrack => false; protected override IntroScreen CreateScreen() => new IntroWelcome(); diff --git a/osu.Game.Tests/Visual/Menus/TestSceneLoader.cs b/osu.Game.Tests/Visual/Menus/TestSceneLoader.cs index 1f2eb57b79..aac9614ddb 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneLoader.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneLoader.cs @@ -19,7 +19,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.Menus { [TestFixture] - public class TestSceneLoader : ScreenTestScene + public partial class TestSceneLoader : ScreenTestScene { private TestLoader loader; @@ -68,7 +68,7 @@ namespace osu.Game.Tests.Visual.Menus AddUntilStep("not current", () => !loader.IsCurrentScreen()); } - private class TestLoader : Loader + private partial class TestLoader : Loader { public readonly ManualResetEventSlim AllowLoad = new ManualResetEventSlim(); @@ -80,7 +80,7 @@ namespace osu.Game.Tests.Visual.Menus protected override OsuScreen CreateLoadableScreen() => screen = new TestScreen(); protected override ShaderPrecompiler CreateShaderPrecompiler() => new TestShaderPrecompiler(AllowLoad); - private class TestShaderPrecompiler : ShaderPrecompiler + private partial class TestShaderPrecompiler : ShaderPrecompiler { private readonly ManualResetEventSlim allowLoad; @@ -92,7 +92,7 @@ namespace osu.Game.Tests.Visual.Menus protected override bool AllLoaded => allowLoad.IsSet; } - private class TestScreen : OsuScreen + private partial class TestScreen : OsuScreen { public TestScreen() { diff --git a/osu.Game.Tests/Visual/Menus/TestSceneLoginPanel.cs b/osu.Game.Tests/Visual/Menus/TestSceneLoginPanel.cs index dbe7b9cc74..738220f5ce 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneLoginPanel.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneLoginPanel.cs @@ -16,7 +16,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Menus { [TestFixture] - public class TestSceneLoginPanel : OsuManualInputManagerTestScene + public partial class TestSceneLoginPanel : OsuManualInputManagerTestScene { private LoginPanel loginPanel; private int hideCount; diff --git a/osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs b/osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs index 720e32a242..f17433244b 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs @@ -16,7 +16,7 @@ using osu.Game.Tests.Resources; namespace osu.Game.Tests.Visual.Menus { - public class TestSceneMusicActionHandling : OsuGameTestScene + public partial class TestSceneMusicActionHandling : OsuGameTestScene { private GlobalActionContainer globalActionContainer => Game.ChildrenOfType().First(); diff --git a/osu.Game.Tests/Visual/Menus/TestSceneSideOverlays.cs b/osu.Game.Tests/Visual/Menus/TestSceneSideOverlays.cs index 7a2b4d5ca5..e5e092b382 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneSideOverlays.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneSideOverlays.cs @@ -13,7 +13,7 @@ using osu.Game.Overlays; namespace osu.Game.Tests.Visual.Menus { - public class TestSceneSideOverlays : OsuGameTestScene + public partial class TestSceneSideOverlays : OsuGameTestScene { [SetUpSteps] public override void SetUpSteps() diff --git a/osu.Game.Tests/Visual/Menus/TestSceneSongTicker.cs b/osu.Game.Tests/Visual/Menus/TestSceneSongTicker.cs index ba73361566..c54c66df7e 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneSongTicker.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneSongTicker.cs @@ -10,7 +10,7 @@ using osu.Game.Screens.Menu; namespace osu.Game.Tests.Visual.Menus { - public class TestSceneSongTicker : OsuTestScene + public partial class TestSceneSongTicker : OsuTestScene { public TestSceneSongTicker() { diff --git a/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs b/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs index 4473f315b9..aef6f9ade0 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs @@ -26,7 +26,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Menus { [TestFixture] - public class TestSceneToolbar : OsuManualInputManagerTestScene + public partial class TestSceneToolbar : OsuManualInputManagerTestScene { private TestToolbar toolbar; @@ -201,7 +201,24 @@ namespace osu.Game.Tests.Visual.Menus AddAssert("volume not changed", () => Audio.Volume.Value == 0.5); } - public class TestToolbar : Toolbar + [Test] + public void TestRulesetSelectorOverflow() + { + AddStep("set toolbar width", () => + { + toolbar.RelativeSizeAxes = Axes.None; + toolbar.Width = 400; + }); + AddStep("move mouse over news toggle button", () => + { + var button = toolbar.ChildrenOfType().Single(); + InputManager.MoveMouseTo(button); + }); + AddAssert("no ruleset toggle buttons hovered", () => !toolbar.ChildrenOfType().Any(button => button.IsHovered)); + AddUntilStep("toolbar gradient visible", () => toolbar.ChildrenOfType().Single().Children.All(d => d.Alpha > 0)); + } + + public partial class TestToolbar : Toolbar { public new Bindable OverlayActivationMode => base.OverlayActivationMode as Bindable; } diff --git a/osu.Game.Tests/Visual/Menus/TestSceneToolbarClock.cs b/osu.Game.Tests/Visual/Menus/TestSceneToolbarClock.cs index d96f80df40..f38ad5af15 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneToolbarClock.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneToolbarClock.cs @@ -18,7 +18,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.Menus { [TestFixture] - public class TestSceneToolbarClock : OsuManualInputManagerTestScene + public partial class TestSceneToolbarClock : OsuManualInputManagerTestScene { private Bindable clockDisplayMode; diff --git a/osu.Game.Tests/Visual/Menus/TestSceneToolbarUserButton.cs b/osu.Game.Tests/Visual/Menus/TestSceneToolbarUserButton.cs index 2901501b30..2bdfc8959d 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneToolbarUserButton.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneToolbarUserButton.cs @@ -14,7 +14,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.Menus { [TestFixture] - public class TestSceneToolbarUserButton : OsuManualInputManagerTestScene + public partial class TestSceneToolbarUserButton : OsuManualInputManagerTestScene { public TestSceneToolbarUserButton() { diff --git a/osu.Game.Tests/Visual/Mods/TestSceneModFailCondition.cs b/osu.Game.Tests/Visual/Mods/TestSceneModFailCondition.cs index 23c1eda7f7..49256c7a01 100644 --- a/osu.Game.Tests/Visual/Mods/TestSceneModFailCondition.cs +++ b/osu.Game.Tests/Visual/Mods/TestSceneModFailCondition.cs @@ -14,7 +14,7 @@ using osu.Game.Screens.Play; namespace osu.Game.Tests.Visual.Mods { - public class TestSceneModFailCondition : ModTestScene + public partial class TestSceneModFailCondition : ModTestScene { private bool restartRequested; diff --git a/osu.Game.Tests/Visual/Multiplayer/MultiplayerGameplayLeaderboardTestScene.cs b/osu.Game.Tests/Visual/Multiplayer/MultiplayerGameplayLeaderboardTestScene.cs index 631f2e707a..649c662e41 100644 --- a/osu.Game.Tests/Visual/Multiplayer/MultiplayerGameplayLeaderboardTestScene.cs +++ b/osu.Game.Tests/Visual/Multiplayer/MultiplayerGameplayLeaderboardTestScene.cs @@ -26,7 +26,7 @@ using osu.Game.Screens.Play.HUD; namespace osu.Game.Tests.Visual.Multiplayer { - public abstract class MultiplayerGameplayLeaderboardTestScene : OsuTestScene + public abstract partial class MultiplayerGameplayLeaderboardTestScene : OsuTestScene { protected const int TOTAL_USERS = 16; @@ -117,11 +117,9 @@ namespace osu.Game.Tests.Visual.Multiplayer BeatmapID = 0, RulesetID = 0, Mods = user.Mods, - MaximumScoringValues = new ScoringValues + MaximumStatistics = new Dictionary { - BaseScore = 10000, - MaxCombo = 1000, - CountBasicHitObjects = 1000 + { HitResult.Perfect, 100 } } }; } diff --git a/osu.Game.Tests/Visual/Multiplayer/QueueModeTestScene.cs b/osu.Game.Tests/Visual/Multiplayer/QueueModeTestScene.cs index ca4d926866..0e9863a9f5 100644 --- a/osu.Game.Tests/Visual/Multiplayer/QueueModeTestScene.cs +++ b/osu.Game.Tests/Visual/Multiplayer/QueueModeTestScene.cs @@ -24,7 +24,7 @@ using osu.Game.Tests.Resources; namespace osu.Game.Tests.Visual.Multiplayer { - public abstract class QueueModeTestScene : ScreenTestScene + public abstract partial class QueueModeTestScene : ScreenTestScene { protected abstract QueueMode Mode { get; } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneAllPlayersQueueMode.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneAllPlayersQueueMode.cs index 5947cabf7f..7b1abd104f 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneAllPlayersQueueMode.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneAllPlayersQueueMode.cs @@ -23,7 +23,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneAllPlayersQueueMode : QueueModeTestScene + public partial class TestSceneAllPlayersQueueMode : QueueModeTestScene { protected override QueueMode Mode => QueueMode.AllPlayers; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneCreateMultiplayerMatchButton.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneCreateMultiplayerMatchButton.cs index 317e410f37..11b0f8b91c 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneCreateMultiplayerMatchButton.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneCreateMultiplayerMatchButton.cs @@ -10,7 +10,7 @@ using osu.Game.Screens.OnlinePlay.Multiplayer; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneCreateMultiplayerMatchButton : MultiplayerTestScene + public partial class TestSceneCreateMultiplayerMatchButton : MultiplayerTestScene { private CreateMultiplayerMatchButton button; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableLoungeRoom.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableLoungeRoom.cs index be1f21a7b2..4de911b6b6 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableLoungeRoom.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableLoungeRoom.cs @@ -21,7 +21,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneDrawableLoungeRoom : OsuManualInputManagerTestScene + public partial class TestSceneDrawableLoungeRoom : OsuManualInputManagerTestScene { private readonly Room room = new Room { diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs index 23ef440a4d..4ffccdbf0e 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs @@ -27,7 +27,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneDrawableRoom : OsuTestScene + public partial class TestSceneDrawableRoom : OsuTestScene { [Cached] protected readonly OverlayColourProvider ColourProvider = new OverlayColourProvider(OverlayColourScheme.Plum); diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomParticipantsList.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomParticipantsList.cs index b26481387d..98abc93994 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomParticipantsList.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomParticipantsList.cs @@ -15,7 +15,7 @@ using osu.Game.Users.Drawables; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneDrawableRoomParticipantsList : OnlinePlayTestScene + public partial class TestSceneDrawableRoomParticipantsList : OnlinePlayTestScene { private DrawableRoomParticipantsList list; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs index 73d1222156..312135402f 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs @@ -33,7 +33,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneDrawableRoomPlaylist : MultiplayerTestScene + public partial class TestSceneDrawableRoomPlaylist : MultiplayerTestScene { private TestPlaylist playlist; @@ -390,7 +390,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddUntilStep("wait for items to load", () => playlist.ItemMap.Values.All(i => i.IsLoaded)); } - private class TestPlaylist : DrawableRoomPlaylist + private partial class TestPlaylist : DrawableRoomPlaylist { public new IReadOnlyDictionary> ItemMap => base.ItemMap; } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneFreeModSelectOverlay.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneFreeModSelectOverlay.cs index 457af3e4af..45f671618e 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneFreeModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneFreeModSelectOverlay.cs @@ -19,7 +19,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneFreeModSelectOverlay : MultiplayerTestScene + public partial class TestSceneFreeModSelectOverlay : MultiplayerTestScene { private FreeModSelectOverlay freeModSelectOverlay; private readonly Bindable>> availableMods = new Bindable>>(); diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneGameplayChatDisplay.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneGameplayChatDisplay.cs index a08791ecff..979cb4424e 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneGameplayChatDisplay.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneGameplayChatDisplay.cs @@ -18,7 +18,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneGameplayChatDisplay : OsuManualInputManagerTestScene + public partial class TestSceneGameplayChatDisplay : OsuManualInputManagerTestScene { private GameplayChatDisplay chatDisplay; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneHostOnlyQueueMode.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneHostOnlyQueueMode.cs index 800b523a9d..145c655c0a 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneHostOnlyQueueMode.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneHostOnlyQueueMode.cs @@ -17,7 +17,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneHostOnlyQueueMode : QueueModeTestScene + public partial class TestSceneHostOnlyQueueMode : QueueModeTestScene { protected override QueueMode Mode => QueueMode.HostOnly; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs index 3d6d4f0a90..d99d764449 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs @@ -19,7 +19,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneLoungeRoomsContainer : OnlinePlayTestScene + public partial class TestSceneLoungeRoomsContainer : OnlinePlayTestScene { protected new TestRoomManager RoomManager => (TestRoomManager)base.RoomManager; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapDetailArea.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapDetailArea.cs index b113352117..63a0ada3dc 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapDetailArea.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapDetailArea.cs @@ -15,7 +15,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneMatchBeatmapDetailArea : OnlinePlayTestScene + public partial class TestSceneMatchBeatmapDetailArea : OnlinePlayTestScene { public override void SetUpSteps() { diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchLeaderboard.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchLeaderboard.cs index d2468ae005..defb3006cc 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchLeaderboard.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchLeaderboard.cs @@ -15,7 +15,7 @@ using APIUser = osu.Game.Online.API.Requests.Responses.APIUser; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneMatchLeaderboard : OnlinePlayTestScene + public partial class TestSceneMatchLeaderboard : OnlinePlayTestScene { public override void SetUpSteps() { diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchStartControl.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchStartControl.cs index 12e7394c93..3efc7fbd30 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchStartControl.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchStartControl.cs @@ -28,7 +28,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneMatchStartControl : OsuManualInputManagerTestScene + public partial class TestSceneMatchStartControl : OsuManualInputManagerTestScene { private readonly Mock multiplayerClient = new Mock(); private readonly Mock availabilityTracker = new Mock(); diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiHeader.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiHeader.cs index 70c6271d24..3d85a47ca9 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiHeader.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiHeader.cs @@ -12,7 +12,7 @@ using osu.Game.Screens.OnlinePlay; namespace osu.Game.Tests.Visual.Multiplayer { [TestFixture] - public class TestSceneMultiHeader : OsuTestScene + public partial class TestSceneMultiHeader : OsuTestScene { public TestSceneMultiHeader() { @@ -31,7 +31,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("push multi screen", () => screenStack.CurrentScreen.Push(new TestOnlinePlaySubScreen(++index))); } - private class TestOnlinePlaySubScreen : OsuScreen, IOnlinePlaySubScreen + private partial class TestOnlinePlaySubScreen : OsuScreen, IOnlinePlaySubScreen { private readonly int index; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorLeaderboard.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorLeaderboard.cs index 4fda4c1c50..049c02ffde 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorLeaderboard.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorLeaderboard.cs @@ -16,7 +16,7 @@ using osu.Game.Screens.Play.HUD; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneMultiSpectatorLeaderboard : MultiplayerTestScene + public partial class TestSceneMultiSpectatorLeaderboard : MultiplayerTestScene { private Dictionary clocks; private MultiSpectatorLeaderboard leaderboard; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs index 13fde4fd72..c2036984c1 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs @@ -30,7 +30,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneMultiSpectatorScreen : MultiplayerTestScene + public partial class TestSceneMultiSpectatorScreen : MultiplayerTestScene { [Resolved] private OsuGameBase game { get; set; } = null!; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs index 6098a3e794..5033347b15 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs @@ -46,7 +46,7 @@ using ReadyButton = osu.Game.Screens.OnlinePlay.Components.ReadyButton; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneMultiplayer : ScreenTestScene + public partial class TestSceneMultiplayer : ScreenTestScene { private BeatmapManager beatmaps = null!; private BeatmapSetInfo importedSet = null!; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs index 95fd449dd3..a612167d57 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs @@ -15,7 +15,7 @@ using osu.Game.Screens.Play.HUD; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneMultiplayerGameplayLeaderboard : MultiplayerGameplayLeaderboardTestScene + public partial class TestSceneMultiplayerGameplayLeaderboard : MultiplayerGameplayLeaderboardTestScene { protected override MultiplayerRoomUser CreateUser(int userId) { @@ -47,7 +47,7 @@ namespace osu.Game.Tests.Visual.Multiplayer }); } - private class TestLeaderboard : MultiplayerGameplayLeaderboard + private partial class TestLeaderboard : MultiplayerGameplayLeaderboard { public Dictionary> UserMods => UserScores.ToDictionary(kvp => kvp.Key, kvp => kvp.Value.ScoreProcessor.Mods); diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs index 93ccf3977b..48f74cf308 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs @@ -12,7 +12,7 @@ using osu.Game.Screens.Play.HUD; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneMultiplayerGameplayLeaderboardTeams : MultiplayerGameplayLeaderboardTestScene + public partial class TestSceneMultiplayerGameplayLeaderboardTeams : MultiplayerGameplayLeaderboardTestScene { private int team; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerLoungeSubScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerLoungeSubScreen.cs index 1a3fefa603..cf25e06799 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerLoungeSubScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerLoungeSubScreen.cs @@ -18,7 +18,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneMultiplayerLoungeSubScreen : OnlinePlayTestScene + public partial class TestSceneMultiplayerLoungeSubScreen : OnlinePlayTestScene { protected new TestRoomManager RoomManager => (TestRoomManager)base.RoomManager; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchFooter.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchFooter.cs index 83e7ef6a81..d636373fbd 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchFooter.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchFooter.cs @@ -10,7 +10,7 @@ using osu.Game.Screens.OnlinePlay.Multiplayer.Match; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneMultiplayerMatchFooter : MultiplayerTestScene + public partial class TestSceneMultiplayerMatchFooter : MultiplayerTestScene { public override void SetUpSteps() { diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSongSelect.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSongSelect.cs index b87321c047..c0b6a0beab 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSongSelect.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSongSelect.cs @@ -31,7 +31,7 @@ using osu.Game.Tests.Resources; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneMultiplayerMatchSongSelect : MultiplayerTestScene + public partial class TestSceneMultiplayerMatchSongSelect : MultiplayerTestScene { private BeatmapManager manager; private RulesetStore rulesets; @@ -112,7 +112,7 @@ namespace osu.Game.Tests.Visual.Multiplayer .All(b => b.Mod.GetType() != type)); } - private class TestMultiplayerMatchSongSelect : MultiplayerMatchSongSelect + private partial class TestMultiplayerMatchSongSelect : MultiplayerMatchSongSelect { public new Bindable> Mods => base.Mods; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs index 9fc42dc68b..8816787ceb 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs @@ -39,7 +39,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneMultiplayerMatchSubScreen : MultiplayerTestScene + public partial class TestSceneMultiplayerMatchSubScreen : MultiplayerTestScene { private MultiplayerMatchSubScreen screen; @@ -286,7 +286,7 @@ namespace osu.Game.Tests.Visual.Multiplayer }); } - private class TestMultiplayerMatchSubScreen : MultiplayerMatchSubScreen + private partial class TestMultiplayerMatchSubScreen : MultiplayerMatchSubScreen { [Resolved(canBeNull: true)] [CanBeNull] diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs index edd1491865..2da29ccc95 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs @@ -23,7 +23,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneMultiplayerParticipantsList : MultiplayerTestScene + public partial class TestSceneMultiplayerParticipantsList : MultiplayerTestScene { [SetUpSteps] public void SetupSteps() diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlayer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlayer.cs index f6a6b3c667..45c5c67fff 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlayer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlayer.cs @@ -14,7 +14,7 @@ using osu.Game.Screens.OnlinePlay.Multiplayer; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneMultiplayerPlayer : MultiplayerTestScene + public partial class TestSceneMultiplayerPlayer : MultiplayerTestScene { private MultiplayerPlayer player; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlaylist.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlaylist.cs index 8dbad4e330..d7578b4114 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlaylist.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlaylist.cs @@ -27,7 +27,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneMultiplayerPlaylist : MultiplayerTestScene + public partial class TestSceneMultiplayerPlaylist : MultiplayerTestScene { private MultiplayerPlaylist list; private BeatmapManager beatmaps; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerQueueList.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerQueueList.cs index 63677ce378..bb37f1a5a7 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerQueueList.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerQueueList.cs @@ -25,7 +25,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneMultiplayerQueueList : MultiplayerTestScene + public partial class TestSceneMultiplayerQueueList : MultiplayerTestScene { private MultiplayerQueueList playlist; private BeatmapManager beatmaps; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerResults.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerResults.cs index a638702ceb..f030466fff 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerResults.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerResults.cs @@ -11,7 +11,7 @@ using osu.Game.Tests.Resources; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneMultiplayerResults : ScreenTestScene + public partial class TestSceneMultiplayerResults : ScreenTestScene { [Test] public void TestDisplayResults() diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerSpectateButton.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerSpectateButton.cs index 9b4cb722f3..816ba4ca32 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerSpectateButton.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerSpectateButton.cs @@ -26,7 +26,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneMultiplayerSpectateButton : MultiplayerTestScene + public partial class TestSceneMultiplayerSpectateButton : MultiplayerTestScene { private MultiplayerSpectateButton spectateButton; private MatchStartControl startControl; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerSpectatorPlayerGrid.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerSpectatorPlayerGrid.cs index 089b4a020d..8fd05dcaa9 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerSpectatorPlayerGrid.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerSpectatorPlayerGrid.cs @@ -14,7 +14,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneMultiplayerSpectatorPlayerGrid : OsuManualInputManagerTestScene + public partial class TestSceneMultiplayerSpectatorPlayerGrid : OsuManualInputManagerTestScene { private PlayerGrid grid; @@ -105,7 +105,7 @@ namespace osu.Game.Tests.Visual.Multiplayer bool checkAction() => Precision.AlmostEquals(grid.MaximisedFacade.DrawSize, grid.Content.ElementAt(index).DrawSize, 10) == shouldBeMaximised; } - private class GridContent : Box + private partial class GridContent : Box { public GridContent() { diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs index 56260941a8..68fd39a066 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs @@ -14,7 +14,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneMultiplayerTeamResults : ScreenTestScene + public partial class TestSceneMultiplayerTeamResults : ScreenTestScene { [Test] public void TestScaling() diff --git a/osu.Game.Tests/Visual/Multiplayer/TestScenePlaylistsRoomSettingsPlaylist.cs b/osu.Game.Tests/Visual/Multiplayer/TestScenePlaylistsRoomSettingsPlaylist.cs index bbccdb0d17..ae27db0dd1 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestScenePlaylistsRoomSettingsPlaylist.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestScenePlaylistsRoomSettingsPlaylist.cs @@ -3,6 +3,7 @@ #nullable disable +using System; using System.Collections.Generic; using System.Linq; using NUnit.Framework; @@ -25,7 +26,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestScenePlaylistsRoomSettingsPlaylist : OnlinePlayTestScene + public partial class TestScenePlaylistsRoomSettingsPlaylist : OnlinePlayTestScene { private TestPlaylist playlist; @@ -46,10 +47,14 @@ namespace osu.Game.Tests.Visual.Multiplayer AddAssert("item removed", () => !playlist.Items.Contains(selectedItem)); } - [Test] - public void TestNextItemSelectedAfterDeletion() + [TestCase(true)] + [TestCase(false)] + public void TestNextItemSelectedAfterDeletion(bool allowSelection) { - createPlaylist(); + createPlaylist(p => + { + p.AllowSelection = allowSelection; + }); moveToItem(0); AddStep("click", () => InputManager.Click(MouseButton.Left)); @@ -57,7 +62,7 @@ namespace osu.Game.Tests.Visual.Multiplayer moveToDeleteButton(0); AddStep("click delete button", () => InputManager.Click(MouseButton.Left)); - AddAssert("item 0 is selected", () => playlist.SelectedItem.Value == playlist.Items[0]); + AddAssert("item 0 is " + (allowSelection ? "selected" : "not selected"), () => playlist.SelectedItem.Value == (allowSelection ? playlist.Items[0] : null)); } [Test] @@ -117,7 +122,7 @@ namespace osu.Game.Tests.Visual.Multiplayer InputManager.MoveMouseTo(item.ChildrenOfType().ElementAt(0), offset); }); - private void createPlaylist() + private void createPlaylist(Action setupPlaylist = null) { AddStep("create playlist", () => { @@ -154,12 +159,14 @@ namespace osu.Game.Tests.Visual.Multiplayer } }); } + + setupPlaylist?.Invoke(playlist); }); AddUntilStep("wait for items to load", () => playlist.ItemMap.Values.All(i => i.IsLoaded)); } - private class TestPlaylist : PlaylistsRoomSettingsPlaylist + private partial class TestPlaylist : PlaylistsRoomSettingsPlaylist { public new IReadOnlyDictionary> ItemMap => base.ItemMap; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestScenePlaylistsSongSelect.cs b/osu.Game.Tests/Visual/Multiplayer/TestScenePlaylistsSongSelect.cs index 2eddf1a17e..b0b753fc22 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestScenePlaylistsSongSelect.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestScenePlaylistsSongSelect.cs @@ -24,7 +24,7 @@ using osu.Game.Tests.Visual.OnlinePlay; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestScenePlaylistsSongSelect : OnlinePlayTestScene + public partial class TestScenePlaylistsSongSelect : OnlinePlayTestScene { private BeatmapManager manager; @@ -154,7 +154,7 @@ namespace osu.Game.Tests.Visual.Multiplayer }); } - private class TestPlaylistsSongSelect : PlaylistsSongSelect + private partial class TestPlaylistsSongSelect : PlaylistsSongSelect { public new MatchBeatmapDetailArea BeatmapDetails => (MatchBeatmapDetailArea)base.BeatmapDetails; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneRankRangePill.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneRankRangePill.cs index cb80fb56df..aaf1a850af 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneRankRangePill.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneRankRangePill.cs @@ -16,7 +16,7 @@ using osu.Game.Screens.OnlinePlay.Lounge.Components; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneRankRangePill : OsuTestScene + public partial class TestSceneRankRangePill : OsuTestScene { private readonly Mock multiplayerClient = new Mock(); diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneStarRatingRangeDisplay.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneStarRatingRangeDisplay.cs index 5bccabcf2f..e46ae978d7 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneStarRatingRangeDisplay.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneStarRatingRangeDisplay.cs @@ -12,7 +12,7 @@ using osu.Game.Tests.Visual.OnlinePlay; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneStarRatingRangeDisplay : OnlinePlayTestScene + public partial class TestSceneStarRatingRangeDisplay : OnlinePlayTestScene { public override void SetUpSteps() { diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs index ef2a431b8f..32e90153d8 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs @@ -27,7 +27,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneTeamVersus : ScreenTestScene + public partial class TestSceneTeamVersus : ScreenTestScene { private BeatmapManager beatmaps; private BeatmapSetInfo importedSet; diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneButtonSystemNavigation.cs b/osu.Game.Tests/Visual/Navigation/TestSceneButtonSystemNavigation.cs index bff30b83f9..64ea6003bc 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneButtonSystemNavigation.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneButtonSystemNavigation.cs @@ -12,7 +12,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Navigation { - public class TestSceneButtonSystemNavigation : OsuGameTestScene + public partial class TestSceneButtonSystemNavigation : OsuGameTestScene { private ButtonSystem buttons => ((MainMenu)Game.ScreenStack.CurrentScreen).ChildrenOfType().Single(); diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneChangeAndUseGameplayBindings.cs b/osu.Game.Tests/Visual/Navigation/TestSceneChangeAndUseGameplayBindings.cs index c3d7bde68f..d937b9e6d7 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneChangeAndUseGameplayBindings.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneChangeAndUseGameplayBindings.cs @@ -20,7 +20,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Navigation { - public class TestSceneChangeAndUseGameplayBindings : OsuGameTestScene + public partial class TestSceneChangeAndUseGameplayBindings : OsuGameTestScene { [Test] public void TestGameplayKeyBindings() diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneEditDefaultSkin.cs b/osu.Game.Tests/Visual/Navigation/TestSceneEditDefaultSkin.cs index 010ed23c9b..7d39d48378 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneEditDefaultSkin.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneEditDefaultSkin.cs @@ -13,7 +13,7 @@ using osu.Game.Skinning.Editor; namespace osu.Game.Tests.Visual.Navigation { - public class TestSceneEditDefaultSkin : OsuGameTestScene + public partial class TestSceneEditDefaultSkin : OsuGameTestScene { private SkinManager skinManager => Game.Dependencies.Get(); private SkinEditorOverlay skinEditor => Game.Dependencies.Get(); diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneFirstRunGame.cs b/osu.Game.Tests/Visual/Navigation/TestSceneFirstRunGame.cs index fe26d59812..7f7a81d787 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneFirstRunGame.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneFirstRunGame.cs @@ -13,7 +13,7 @@ using osu.Game.Overlays.Notifications; namespace osu.Game.Tests.Visual.Navigation { [System.ComponentModel.Description("game with first-run setup overlay")] - public class TestSceneFirstRunGame : OsuGameTestScene + public partial class TestSceneFirstRunGame : OsuGameTestScene { public override void SetUpSteps() { @@ -32,7 +32,7 @@ namespace osu.Game.Tests.Visual.Navigation protected override TestOsuGame CreateTestGame() => new FirstRunGame(LocalStorage, API); - private class FirstRunGame : TestOsuGame + private partial class FirstRunGame : TestOsuGame { public FirstRunGame(Storage storage, IAPIProvider api, string[] args = null) : base(storage, api, args) diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneInterProcessCommunication.cs b/osu.Game.Tests/Visual/Navigation/TestSceneInterProcessCommunication.cs index 1c2b1fe37d..346f1d9f90 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneInterProcessCommunication.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneInterProcessCommunication.cs @@ -19,7 +19,7 @@ namespace osu.Game.Tests.Visual.Navigation { [TestFixture] [Ignore("This test cannot be run headless, as it requires the game host running the nested game to have IPC bound.")] - public class TestSceneInterProcessCommunication : OsuGameTestScene + public partial class TestSceneInterProcessCommunication : OsuGameTestScene { private HeadlessGameHost ipcSenderHost = null!; diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneMouseWheelVolumeAdjust.cs b/osu.Game.Tests/Visual/Navigation/TestSceneMouseWheelVolumeAdjust.cs index 2592936ab6..a89f5fb647 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneMouseWheelVolumeAdjust.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneMouseWheelVolumeAdjust.cs @@ -12,7 +12,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Navigation { - public class TestSceneMouseWheelVolumeAdjust : OsuGameTestScene + public partial class TestSceneMouseWheelVolumeAdjust : OsuGameTestScene { public override void SetUpSteps() { diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneOsuGame.cs b/osu.Game.Tests/Visual/Navigation/TestSceneOsuGame.cs index 6070b1456f..de303fe074 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneOsuGame.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneOsuGame.cs @@ -30,7 +30,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Navigation { [TestFixture] - public class TestSceneOsuGame : OsuGameTestScene + public partial class TestSceneOsuGame : OsuGameTestScene { private IReadOnlyList requiredGameDependencies => new[] { diff --git a/osu.Game.Tests/Visual/Navigation/TestScenePerformFromScreen.cs b/osu.Game.Tests/Visual/Navigation/TestScenePerformFromScreen.cs index ce0543875b..1c8fa775b9 100644 --- a/osu.Game.Tests/Visual/Navigation/TestScenePerformFromScreen.cs +++ b/osu.Game.Tests/Visual/Navigation/TestScenePerformFromScreen.cs @@ -22,7 +22,7 @@ using static osu.Game.Tests.Visual.Navigation.TestSceneScreenNavigation; namespace osu.Game.Tests.Visual.Navigation { - public class TestScenePerformFromScreen : OsuGameTestScene + public partial class TestScenePerformFromScreen : OsuGameTestScene { private bool actionPerformed; @@ -237,7 +237,7 @@ namespace osu.Game.Tests.Visual.Navigation AddUntilStep("beatmap updated", () => Game.Beatmap.Value.BeatmapSetInfo.OnlineID == 241526); } - public class DialogBlockingScreen : OsuScreen + public partial class DialogBlockingScreen : OsuScreen { [Resolved] private IDialogOverlay dialogOverlay { get; set; } @@ -260,7 +260,7 @@ namespace osu.Game.Tests.Visual.Navigation } } - public class TestScreenWithNestedStack : OsuScreen, IHasSubScreenStack + public partial class TestScreenWithNestedStack : OsuScreen, IHasSubScreenStack { public DialogBlockingScreen Blocker { get; private set; } @@ -285,7 +285,7 @@ namespace osu.Game.Tests.Visual.Navigation } } - public class TestLoadBlockingScreen : OsuScreen + public partial class TestLoadBlockingScreen : OsuScreen { public readonly ManualResetEventSlim LoadEvent = new ManualResetEventSlim(); diff --git a/osu.Game.Tests/Visual/Navigation/TestScenePresentBeatmap.cs b/osu.Game.Tests/Visual/Navigation/TestScenePresentBeatmap.cs index 02b348b439..c054792168 100644 --- a/osu.Game.Tests/Visual/Navigation/TestScenePresentBeatmap.cs +++ b/osu.Game.Tests/Visual/Navigation/TestScenePresentBeatmap.cs @@ -9,8 +9,10 @@ using NUnit.Framework; using osu.Framework.Screens; using osu.Framework.Testing; using osu.Game.Beatmaps; +using osu.Game.Configuration; using osu.Game.Extensions; using osu.Game.Rulesets; +using osu.Game.Rulesets.Catch; using osu.Game.Rulesets.Mania; using osu.Game.Rulesets.Osu; using osu.Game.Screens.Menu; @@ -18,7 +20,7 @@ using osu.Game.Screens.Select; namespace osu.Game.Tests.Visual.Navigation { - public class TestScenePresentBeatmap : OsuGameTestScene + public partial class TestScenePresentBeatmap : OsuGameTestScene { [Test] public void TestFromMainMenu() @@ -71,17 +73,51 @@ namespace osu.Game.Tests.Visual.Navigation } [Test] - public void TestFromSongSelectDifferentRuleset() + public void TestFromSongSelectDifferentRulesetWithConvertDisallowed() { - var firstImport = importBeatmap(1); - presentAndConfirm(firstImport); + AddStep("Set converts disallowed", () => Game.LocalConfig.SetValue(OsuSetting.ShowConvertedBeatmaps, false)); - var secondImport = importBeatmap(3, new ManiaRuleset().RulesetInfo); - confirmBeatmapInSongSelect(secondImport); - presentAndConfirm(secondImport); + var osuImport = importBeatmap(1); + presentAndConfirm(osuImport); - presentSecondDifficultyAndConfirm(firstImport, 1); - presentSecondDifficultyAndConfirm(secondImport, 3); + var maniaImport = importBeatmap(2, new ManiaRuleset().RulesetInfo); + confirmBeatmapInSongSelect(maniaImport); + presentAndConfirm(maniaImport); + + var catchImport = importBeatmap(3, new CatchRuleset().RulesetInfo); + confirmBeatmapInSongSelect(catchImport); + presentAndConfirm(catchImport); + + // Ruleset is always changed. + presentSecondDifficultyAndConfirm(maniaImport, 2); + presentSecondDifficultyAndConfirm(osuImport, 1); + presentSecondDifficultyAndConfirm(catchImport, 3); + } + + [Test] + public void TestFromSongSelectDifferentRulesetWithConvertAllowed() + { + AddStep("Set converts allowed", () => Game.LocalConfig.SetValue(OsuSetting.ShowConvertedBeatmaps, true)); + + var osuImport = importBeatmap(1); + presentAndConfirm(osuImport); + + var maniaImport = importBeatmap(2, new ManiaRuleset().RulesetInfo); + confirmBeatmapInSongSelect(maniaImport); + presentAndConfirm(maniaImport); + + var catchImport = importBeatmap(3, new CatchRuleset().RulesetInfo); + confirmBeatmapInSongSelect(catchImport); + presentAndConfirm(catchImport); + + // force ruleset to osu!mania + presentSecondDifficultyAndConfirm(maniaImport, 2); + + // ruleset is not changed as we can convert osu! beatmap. + presentSecondDifficultyAndConfirm(osuImport, 1, expectedRulesetOnlineID: 3); + + // ruleset is changed as we cannot convert. + presentSecondDifficultyAndConfirm(catchImport, 3); } private void returnToMenu() @@ -112,19 +148,19 @@ namespace osu.Game.Tests.Visual.Navigation imported = Game.BeatmapManager.Import(new BeatmapSetInfo { Hash = Guid.NewGuid().ToString(), - OnlineID = i, + OnlineID = i * 1024, Beatmaps = { new BeatmapInfo { - OnlineID = i * 1024, + OnlineID = i * 1024 + 1, Metadata = metadata, Difficulty = new BeatmapDifficulty(), Ruleset = ruleset ?? new OsuRuleset().RulesetInfo }, new BeatmapInfo { - OnlineID = i * 2048, + OnlineID = i * 1024 + 2, Metadata = metadata, Difficulty = new BeatmapDifficulty(), Ruleset = ruleset ?? new OsuRuleset().RulesetInfo @@ -156,14 +192,14 @@ namespace osu.Game.Tests.Visual.Navigation AddAssert("correct ruleset selected", () => Game.Ruleset.Value, () => Is.EqualTo(getImport().Beatmaps.First().Ruleset)); } - private void presentSecondDifficultyAndConfirm(Func getImport, int importedID) + private void presentSecondDifficultyAndConfirm(Func getImport, int importedID, int? expectedRulesetOnlineID = null) { - Predicate pred = b => b.OnlineID == importedID * 2048; + Predicate pred = b => b.OnlineID == importedID * 1024 + 2; AddStep("present difficulty", () => Game.PresentBeatmap(getImport(), pred)); AddUntilStep("wait for song select", () => Game.ScreenStack.CurrentScreen is Screens.Select.SongSelect songSelect && songSelect.IsLoaded); - AddUntilStep("correct beatmap displayed", () => Game.Beatmap.Value.BeatmapInfo.OnlineID, () => Is.EqualTo(importedID * 2048)); - AddAssert("correct ruleset selected", () => Game.Ruleset.Value, () => Is.EqualTo(getImport().Beatmaps.First().Ruleset)); + AddUntilStep("correct beatmap displayed", () => Game.Beatmap.Value.BeatmapInfo.OnlineID, () => Is.EqualTo(importedID * 1024 + 2)); + AddAssert("correct ruleset selected", () => Game.Ruleset.Value.OnlineID, () => Is.EqualTo(expectedRulesetOnlineID ?? getImport().Beatmaps.First().Ruleset.OnlineID)); } } } diff --git a/osu.Game.Tests/Visual/Navigation/TestScenePresentScore.cs b/osu.Game.Tests/Visual/Navigation/TestScenePresentScore.cs index 003cec0d07..4bcd6b100a 100644 --- a/osu.Game.Tests/Visual/Navigation/TestScenePresentScore.cs +++ b/osu.Game.Tests/Visual/Navigation/TestScenePresentScore.cs @@ -24,7 +24,7 @@ using osu.Game.Screens.Select; namespace osu.Game.Tests.Visual.Navigation { - public class TestScenePresentScore : OsuGameTestScene + public partial class TestScenePresentScore : OsuGameTestScene { private BeatmapSetInfo beatmap; diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs index e500efede3..7bde2e747d 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs @@ -19,6 +19,7 @@ using osu.Game.Configuration; using osu.Game.Graphics.UserInterface; using osu.Game.Online.Leaderboards; using osu.Game.Overlays; +using osu.Game.Overlays.BeatmapListing; using osu.Game.Overlays.Mods; using osu.Game.Overlays.Toolbar; using osu.Game.Rulesets.Mods; @@ -26,6 +27,7 @@ using osu.Game.Rulesets.Osu.Mods; using osu.Game.Scoring; using osu.Game.Screens.Menu; using osu.Game.Screens.OnlinePlay.Lounge; +using osu.Game.Screens.OnlinePlay.Match.Components; using osu.Game.Screens.OnlinePlay.Playlists; using osu.Game.Screens.Play; using osu.Game.Screens.Ranking; @@ -38,7 +40,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Navigation { - public class TestSceneScreenNavigation : OsuGameTestScene + public partial class TestSceneScreenNavigation : OsuGameTestScene { private const float click_padding = 25; @@ -79,7 +81,25 @@ namespace osu.Game.Tests.Visual.Navigation AddUntilStep("wait for return to playlist screen", () => playlistScreen.CurrentSubScreen is PlaylistsRoomSubScreen); + AddStep("go back to song select", () => + { + InputManager.MoveMouseTo(playlistScreen.ChildrenOfType().Single(b => b.Text == "Edit playlist")); + InputManager.Click(MouseButton.Left); + }); + + AddUntilStep("wait for song select", () => (playlistScreen.CurrentSubScreen as PlaylistsSongSelect)?.BeatmapSetsLoaded == true); + + AddStep("press home button", () => + { + InputManager.MoveMouseTo(Game.Toolbar.ChildrenOfType().Single()); + InputManager.Click(MouseButton.Left); + }); + + AddAssert("confirmation dialog shown", () => Game.ChildrenOfType().Single().CurrentDialog is not null); + pushEscape(); + pushEscape(); + AddAssert("confirmation dialog shown", () => Game.ChildrenOfType().Single().CurrentDialog is not null); AddStep("confirm exit", () => InputManager.Key(Key.Enter)); @@ -175,11 +195,17 @@ namespace osu.Game.Tests.Visual.Navigation AddUntilStep("wait for player", () => { DismissAnyNotifications(); - return (player = Game.ScreenStack.CurrentScreen as Player) != null; + player = Game.ScreenStack.CurrentScreen as Player; + return player?.IsLoaded == true; }); AddAssert("retry count is 0", () => player.RestartCount == 0); + // todo: see https://github.com/ppy/osu/issues/22220 + // tests are supposed to be immune to this edge case by the logic in TestPlayer, + // but we're running a full game instance here, so we have to work around it manually. + AddStep("end spectator before retry", () => Game.SpectatorClient.EndPlaying(player.GameplayState)); + AddStep("attempt to retry", () => player.ChildrenOfType().First().Action()); AddUntilStep("wait for old player gone", () => Game.ScreenStack.CurrentScreen != player); @@ -515,6 +541,28 @@ namespace osu.Game.Tests.Visual.Navigation AddWaitStep("wait two frames", 2); } + [Test] + public void TestFeaturedArtistDisclaimerDialog() + { + BeatmapListingOverlay getBeatmapListingOverlay() => Game.ChildrenOfType().FirstOrDefault(); + + AddStep("Wait for notifications to load", () => Game.SearchBeatmapSet(string.Empty)); + AddUntilStep("wait for dialog overlay", () => Game.ChildrenOfType().SingleOrDefault() != null); + + AddUntilStep("Wait for beatmap overlay to load", () => getBeatmapListingOverlay()?.State.Value == Visibility.Visible); + AddAssert("featured artist filter is on", () => getBeatmapListingOverlay().ChildrenOfType().First().Current.Contains(SearchGeneral.FeaturedArtists)); + AddStep("toggle featured artist filter", + () => getBeatmapListingOverlay().ChildrenOfType>().First(i => i.Value == SearchGeneral.FeaturedArtists).TriggerClick()); + + AddAssert("disclaimer dialog is shown", () => Game.ChildrenOfType().Single().CurrentDialog != null); + AddAssert("featured artist filter is still on", () => getBeatmapListingOverlay().ChildrenOfType().First().Current.Contains(SearchGeneral.FeaturedArtists)); + + AddStep("confirm", () => InputManager.Key(Key.Enter)); + AddAssert("dialog dismissed", () => Game.ChildrenOfType().Single().CurrentDialog == null); + + AddUntilStep("featured artist filter is off", () => !getBeatmapListingOverlay().ChildrenOfType().First().Current.Contains(SearchGeneral.FeaturedArtists)); + } + [Test] public void TestMainOverlaysClosesNotificationOverlay() { @@ -694,7 +742,7 @@ namespace osu.Game.Tests.Visual.Navigation ConfirmAtMainMenu(); } - public class TestPlaySongSelect : PlaySongSelect + public partial class TestPlaySongSelect : PlaySongSelect { public ModSelectOverlay ModSelectOverlay => ModSelect; diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneSkinEditorNavigation.cs b/osu.Game.Tests/Visual/Navigation/TestSceneSkinEditorNavigation.cs index 2f0f2f68a5..845cfdd6df 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneSkinEditorNavigation.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneSkinEditorNavigation.cs @@ -24,7 +24,7 @@ using static osu.Game.Tests.Visual.Navigation.TestSceneScreenNavigation; namespace osu.Game.Tests.Visual.Navigation { - public class TestSceneSkinEditorNavigation : OsuGameTestScene + public partial class TestSceneSkinEditorNavigation : OsuGameTestScene { private TestPlaySongSelect songSelect; private SkinEditor skinEditor => Game.ChildrenOfType().FirstOrDefault(); @@ -219,7 +219,7 @@ namespace osu.Game.Tests.Visual.Navigation AddStep("Click gameplay scene button", () => { - InputManager.MoveMouseTo(skinEditor.ChildrenOfType().First(b => b.Text == "Gameplay")); + InputManager.MoveMouseTo(skinEditor.ChildrenOfType().First(b => b.Text.ToString() == "Gameplay")); InputManager.Click(MouseButton.Left); }); diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneStartupBeatmapDisplay.cs b/osu.Game.Tests/Visual/Navigation/TestSceneStartupBeatmapDisplay.cs index bd3dcb8597..25cef8440a 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneStartupBeatmapDisplay.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneStartupBeatmapDisplay.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Linq; using NUnit.Framework; using osu.Framework.Graphics.Containers; @@ -15,7 +13,7 @@ using osu.Game.Overlays.BeatmapSet; namespace osu.Game.Tests.Visual.Navigation { - public class TestSceneStartupBeatmapDisplay : OsuGameTestScene + public partial class TestSceneStartupBeatmapDisplay : OsuGameTestScene { private const int requested_beatmap_id = 75; private const int requested_beatmap_set_id = 1; @@ -50,7 +48,7 @@ namespace osu.Game.Tests.Visual.Navigation public void TestBeatmapLink() { AddUntilStep("Beatmap overlay displayed", () => Game.ChildrenOfType().FirstOrDefault()?.State.Value == Visibility.Visible); - AddUntilStep("Beatmap overlay showing content", () => Game.ChildrenOfType().FirstOrDefault()?.Beatmap.Value.OnlineID == requested_beatmap_id); + AddUntilStep("Beatmap overlay showing content", () => Game.ChildrenOfType().FirstOrDefault()?.Beatmap.Value?.OnlineID == requested_beatmap_id); } } } diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneStartupBeatmapSetDisplay.cs b/osu.Game.Tests/Visual/Navigation/TestSceneStartupBeatmapSetDisplay.cs index 1072508e33..f885c2f44c 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneStartupBeatmapSetDisplay.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneStartupBeatmapSetDisplay.cs @@ -14,7 +14,7 @@ using osu.Game.Overlays; namespace osu.Game.Tests.Visual.Navigation { - public class TestSceneStartupBeatmapSetDisplay : OsuGameTestScene + public partial class TestSceneStartupBeatmapSetDisplay : OsuGameTestScene { private const int requested_beatmap_set_id = 1; diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneStartupImport.cs b/osu.Game.Tests/Visual/Navigation/TestSceneStartupImport.cs index 552eb82419..e795166d3e 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneStartupImport.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneStartupImport.cs @@ -9,7 +9,7 @@ using osu.Game.Tests.Resources; namespace osu.Game.Tests.Visual.Navigation { - public class TestSceneStartupImport : OsuGameTestScene + public partial class TestSceneStartupImport : OsuGameTestScene { private string? importFilename; diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneStartupRuleset.cs b/osu.Game.Tests/Visual/Navigation/TestSceneStartupRuleset.cs index 1aadff7a20..621dabe869 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneStartupRuleset.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneStartupRuleset.cs @@ -10,7 +10,7 @@ using osu.Game.Configuration; namespace osu.Game.Tests.Visual.Navigation { [TestFixture] - public class TestSceneStartupRuleset : OsuGameTestScene + public partial class TestSceneStartupRuleset : OsuGameTestScene { protected override TestOsuGame CreateTestGame() { diff --git a/osu.Game.Tests/Visual/Navigation/TestSettingsMigration.cs b/osu.Game.Tests/Visual/Navigation/TestSettingsMigration.cs index 2879536034..c32aa7f5f9 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSettingsMigration.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSettingsMigration.cs @@ -9,7 +9,7 @@ using osu.Game.Configuration; namespace osu.Game.Tests.Visual.Navigation { - public class TestSettingsMigration : OsuGameTestScene + public partial class TestSettingsMigration : OsuGameTestScene { public override void RecycleLocalStorage(bool isDisposing) { diff --git a/osu.Game.Tests/Visual/Online/TestSceneAccountCreationOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneAccountCreationOverlay.cs index b9d800e6fd..0f920643f0 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneAccountCreationOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneAccountCreationOverlay.cs @@ -18,7 +18,7 @@ using osu.Game.Users; namespace osu.Game.Tests.Visual.Online { - public class TestSceneAccountCreationOverlay : OsuTestScene + public partial class TestSceneAccountCreationOverlay : OsuTestScene { private readonly Container userPanelArea; private readonly AccountCreationOverlay accountCreation; diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapAvailability.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapAvailability.cs index c78a36d2bd..36f8d2d9bd 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapAvailability.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapAvailability.cs @@ -11,7 +11,7 @@ using osu.Game.Overlays.BeatmapSet; namespace osu.Game.Tests.Visual.Online { [TestFixture] - public class TestSceneBeatmapAvailability : OsuTestScene + public partial class TestSceneBeatmapAvailability : OsuTestScene { private readonly BeatmapAvailability container; diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapDownloadButton.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapDownloadButton.cs index ba600332bb..40e34a52b6 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapDownloadButton.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapDownloadButton.cs @@ -16,7 +16,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Online { - public class TestSceneBeatmapDownloadButton : OsuTestScene + public partial class TestSceneBeatmapDownloadButton : OsuTestScene { private TestDownloadButton downloadButton; @@ -139,7 +139,7 @@ namespace osu.Game.Tests.Visual.Online return apiBeatmapSet; } - private class TestDownloadButton : BeatmapDownloadButton + private partial class TestDownloadButton : BeatmapDownloadButton { public new bool DownloadEnabled => base.DownloadEnabled; diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapListingOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapListingOverlay.cs index 1e0a09d37a..5e49cb633e 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapListingOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapListingOverlay.cs @@ -25,7 +25,7 @@ using APIUser = osu.Game.Online.API.Requests.Responses.APIUser; namespace osu.Game.Tests.Visual.Online { - public class TestSceneBeatmapListingOverlay : OsuManualInputManagerTestScene + public partial class TestSceneBeatmapListingOverlay : OsuManualInputManagerTestScene { private readonly List setsForResponse = new List(); @@ -80,6 +80,15 @@ namespace osu.Game.Tests.Visual.Online AddStep("reset size", () => localConfig.SetValue(OsuSetting.BeatmapListingCardSize, BeatmapCardSize.Normal)); } + [Test] + public void TestFeaturedArtistFilter() + { + AddAssert("is visible", () => overlay.State.Value == Visibility.Visible); + AddAssert("featured artist filter is on", () => overlay.ChildrenOfType().First().Current.Contains(SearchGeneral.FeaturedArtists)); + AddStep("toggle featured artist filter", () => overlay.ChildrenOfType>().First(i => i.Value == SearchGeneral.FeaturedArtists).TriggerClick()); + AddAssert("featured artist filter is off", () => !overlay.ChildrenOfType().First().Current.Contains(SearchGeneral.FeaturedArtists)); + } + [Test] public void TestHideViaBack() { diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapRulesetSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapRulesetSelector.cs index b73028be5b..36c3576da6 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapRulesetSelector.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapRulesetSelector.cs @@ -14,7 +14,7 @@ using osu.Game.Overlays.BeatmapSet; namespace osu.Game.Tests.Visual.Online { - public class TestSceneBeatmapRulesetSelector : OsuTestScene + public partial class TestSceneBeatmapRulesetSelector : OsuTestScene { [Cached] private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue); diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs index bb4823fb1d..5d13421195 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs @@ -14,6 +14,8 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Testing; using osu.Game.Beatmaps.Drawables; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.BeatmapSet.Scores; using osu.Game.Resources.Localisation.Web; @@ -24,7 +26,7 @@ using APIUser = osu.Game.Online.API.Requests.Responses.APIUser; namespace osu.Game.Tests.Visual.Online { - public class TestSceneBeatmapSetOverlay : OsuTestScene + public partial class TestSceneBeatmapSetOverlay : OsuTestScene { private readonly TestBeatmapSetOverlay overlay; @@ -54,6 +56,8 @@ namespace osu.Game.Tests.Visual.Online { overlay.ShowBeatmapSet(new APIBeatmapSet { + Genre = new BeatmapSetOnlineGenre { Id = 15, Name = "Future genre" }, + Language = new BeatmapSetOnlineLanguage { Id = 15, Name = "Future language" }, OnlineID = 1235, Title = @"an awesome beatmap", Artist = @"naru narusegawa", @@ -239,6 +243,44 @@ namespace osu.Game.Tests.Visual.Online AddStep(@"show without reload", overlay.Show); } + [TestCase(BeatmapSetLookupType.BeatmapId)] + [TestCase(BeatmapSetLookupType.SetId)] + public void TestFetchLookupType(BeatmapSetLookupType lookupType) + { + string type = string.Empty; + + AddStep("register request handling", () => + { + ((DummyAPIAccess)API).HandleRequest = req => + { + switch (req) + { + case GetBeatmapSetRequest getBeatmapSet: + type = getBeatmapSet.Type.ToString(); + return true; + } + + return false; + }; + }); + + AddStep(@"fetch", () => + { + switch (lookupType) + { + case BeatmapSetLookupType.BeatmapId: + overlay.FetchAndShowBeatmap(55); + break; + + case BeatmapSetLookupType.SetId: + overlay.FetchAndShowBeatmapSet(55); + break; + } + }); + + AddAssert(@"type is correct", () => type == lookupType.ToString()); + } + private APIBeatmapSet createManyDifficultiesBeatmapSet() { var set = getBeatmapSet(); @@ -283,7 +325,7 @@ namespace osu.Game.Tests.Visual.Online AddAssert($"is download button {(shown ? "shown" : "hidden")}", () => overlay.Header.HeaderContent.DownloadButtonsVisible == shown); } - private class TestBeatmapSetOverlay : BeatmapSetOverlay + private partial class TestBeatmapSetOverlay : BeatmapSetOverlay { public new BeatmapSetHeader Header => base.Header; } diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlayDetails.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlayDetails.cs index 31cebc2f0b..69c9faa9d3 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlayDetails.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlayDetails.cs @@ -16,7 +16,7 @@ using osu.Game.Screens.Select.Details; namespace osu.Game.Tests.Visual.Online { - public class TestSceneBeatmapSetOverlayDetails : OsuTestScene + public partial class TestSceneBeatmapSetOverlayDetails : OsuTestScene { private RatingsExposingDetails details; @@ -63,7 +63,7 @@ namespace osu.Game.Tests.Visual.Online }; } - private class RatingsExposingDetails : Details + private partial class RatingsExposingDetails : Details { public new UserRatings Ratings => base.Ratings; } diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlaySuccessRate.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlaySuccessRate.cs index 26e1e49ca3..59c96ec719 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlaySuccessRate.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlaySuccessRate.cs @@ -22,7 +22,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.Online { - public class TestSceneBeatmapSetOverlaySuccessRate : OsuTestScene + public partial class TestSceneBeatmapSetOverlaySuccessRate : OsuTestScene { private GraphExposingSuccessRate successRate; @@ -104,7 +104,7 @@ namespace osu.Game.Tests.Visual.Online AddAssert("graph max values correct", () => successRate.ChildrenOfType().All(graph => graph.MaxValue == 0)); } - private class GraphExposingSuccessRate : SuccessRate + private partial class GraphExposingSuccessRate : SuccessRate { public new FailRetryGraph Graph => base.Graph; } diff --git a/osu.Game.Tests/Visual/Online/TestSceneBundledBeatmapDownloader.cs b/osu.Game.Tests/Visual/Online/TestSceneBundledBeatmapDownloader.cs index 08c6914f83..0f2786f9ef 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBundledBeatmapDownloader.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBundledBeatmapDownloader.cs @@ -9,7 +9,7 @@ using osu.Game.Beatmaps.Drawables; namespace osu.Game.Tests.Visual.Online { [Ignore("Only for visual testing")] - public class TestSceneBundledBeatmapDownloader : OsuTestScene + public partial class TestSceneBundledBeatmapDownloader : OsuTestScene { private BundledBeatmapDownloader downloader; diff --git a/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs index c5ac3dd442..8d61c5df9f 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs @@ -18,7 +18,7 @@ using osu.Game.Overlays.Changelog; namespace osu.Game.Tests.Visual.Online { [TestFixture] - public class TestSceneChangelogOverlay : OsuTestScene + public partial class TestSceneChangelogOverlay : OsuTestScene { private DummyAPIAccess dummyAPI => (DummyAPIAccess)API; @@ -201,7 +201,7 @@ namespace osu.Game.Tests.Visual.Online AddStep("show build", () => changelog.ShowBuild(requestedBuild)); } - private class TestChangelogOverlay : ChangelogOverlay + private partial class TestChangelogOverlay : ChangelogOverlay { public new List Streams => base.Streams; diff --git a/osu.Game.Tests/Visual/Online/TestSceneChangelogSupporterPromo.cs b/osu.Game.Tests/Visual/Online/TestSceneChangelogSupporterPromo.cs index 018d40d1bc..96996db940 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChangelogSupporterPromo.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChangelogSupporterPromo.cs @@ -12,7 +12,7 @@ using osu.Game.Overlays.Changelog; namespace osu.Game.Tests.Visual.Online { - public class TestSceneChangelogSupporterPromo : OsuTestScene + public partial class TestSceneChangelogSupporterPromo : OsuTestScene { [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple); diff --git a/osu.Game.Tests/Visual/Online/TestSceneChannelList.cs b/osu.Game.Tests/Visual/Online/TestSceneChannelList.cs index 8e17c490b1..a0cca5f53d 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChannelList.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChannelList.cs @@ -20,7 +20,7 @@ using osu.Game.Overlays.Chat.Listing; namespace osu.Game.Tests.Visual.Online { [TestFixture] - public class TestSceneChannelList : OsuTestScene + public partial class TestSceneChannelList : OsuTestScene { [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Pink); diff --git a/osu.Game.Tests/Visual/Online/TestSceneChannelListing.cs b/osu.Game.Tests/Visual/Online/TestSceneChannelListing.cs index 214c05e64d..2d2d7fc0ff 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChannelListing.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChannelListing.cs @@ -19,7 +19,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Online { [TestFixture] - public class TestSceneChannelListing : OsuTestScene + public partial class TestSceneChannelListing : OsuTestScene { [Cached] private readonly OverlayColourProvider overlayColours = new OverlayColourProvider(OverlayColourScheme.Pink); diff --git a/osu.Game.Tests/Visual/Online/TestSceneChatLineTruncation.cs b/osu.Game.Tests/Visual/Online/TestSceneChatLineTruncation.cs index 79dc17cfa6..32d95ec8dc 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChatLineTruncation.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChatLineTruncation.cs @@ -15,7 +15,7 @@ using osu.Game.Overlays.Chat; namespace osu.Game.Tests.Visual.Online { [TestFixture] - public class TestSceneChatLineTruncation : OsuTestScene + public partial class TestSceneChatLineTruncation : OsuTestScene { private readonly TestChatLineContainer textContainer; @@ -86,7 +86,7 @@ namespace osu.Game.Tests.Visual.Online } } - private class TestChatLineContainer : FillFlowContainer + private partial class TestChatLineContainer : FillFlowContainer { protected override int Compare(Drawable x, Drawable y) { diff --git a/osu.Game.Tests/Visual/Online/TestSceneChatLink.cs b/osu.Game.Tests/Visual/Online/TestSceneChatLink.cs index de44986001..f5cf4c1ff2 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChatLink.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChatLink.cs @@ -20,7 +20,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.Online { [TestFixture] - public class TestSceneChatLink : OsuTestScene + public partial class TestSceneChatLink : OsuTestScene { private readonly TestChatLineContainer textContainer; private Color4 linkColour; @@ -130,11 +130,11 @@ namespace osu.Game.Tests.Visual.Online Color4 textColour = isAction && hasBackground ? Color4Extensions.FromHex(newLine.Message.Sender.Colour) : Color4.White; - var linkCompilers = newLine.ContentFlow.Where(d => d is DrawableLinkCompiler).ToList(); + var linkCompilers = newLine.DrawableContentFlow.Where(d => d is DrawableLinkCompiler).ToList(); var linkSprites = linkCompilers.SelectMany(comp => ((DrawableLinkCompiler)comp).Parts); return linkSprites.All(d => d.Colour == linkColour) - && newLine.ContentFlow.Except(linkSprites.Concat(linkCompilers)).All(d => d.Colour == textColour); + && newLine.DrawableContentFlow.Except(linkSprites.Concat(linkCompilers)).All(d => d.Colour == textColour); } } } @@ -207,7 +207,7 @@ namespace osu.Game.Tests.Visual.Online } } - private class TestChatLineContainer : FillFlowContainer + private partial class TestChatLineContainer : FillFlowContainer { protected override int Compare(Drawable x, Drawable y) { diff --git a/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs index 0b75a2aa05..a8369dd6d9 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs @@ -34,7 +34,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Online { [TestFixture] - public class TestSceneChatOverlay : OsuManualInputManagerTestScene + public partial class TestSceneChatOverlay : OsuManualInputManagerTestScene { private TestChatOverlay chatOverlay; private ChannelManager channelManager; @@ -530,6 +530,52 @@ namespace osu.Game.Tests.Visual.Online }); } + [Test] + public void TestTextBoxSavePerChannel() + { + var testPMChannel = new Channel(testUser); + + AddStep("show overlay", () => chatOverlay.Show()); + joinTestChannel(0); + joinChannel(testPMChannel); + + AddAssert("listing is visible", () => listingIsVisible); + AddStep("search for 'number 2'", () => chatOverlayTextBox.Text = "number 2"); + AddAssert("'number 2' saved to selector", () => channelManager.CurrentChannel.Value.TextBoxMessage.Value == "number 2"); + + AddStep("select normal channel", () => clickDrawable(getChannelListItem(testChannel1))); + AddAssert("text box cleared on normal channel", () => chatOverlayTextBox.Text == string.Empty); + AddAssert("nothing saved on normal channel", () => channelManager.CurrentChannel.Value.TextBoxMessage.Value == string.Empty); + AddStep("type '727'", () => chatOverlayTextBox.Text = "727"); + AddAssert("'727' saved to normal channel", () => channelManager.CurrentChannel.Value.TextBoxMessage.Value == "727"); + + AddStep("select PM channel", () => clickDrawable(getChannelListItem(testPMChannel))); + AddAssert("text box cleared on PM channel", () => chatOverlayTextBox.Text == string.Empty); + AddAssert("nothing saved on PM channel", () => channelManager.CurrentChannel.Value.TextBoxMessage.Value == string.Empty); + AddStep("type 'hello'", () => chatOverlayTextBox.Text = "hello"); + AddAssert("'hello' saved to PM channel", () => channelManager.CurrentChannel.Value.TextBoxMessage.Value == "hello"); + + AddStep("select normal channel", () => clickDrawable(getChannelListItem(testChannel1))); + AddAssert("text box contains '727'", () => chatOverlayTextBox.Text == "727"); + + AddStep("select PM channel", () => clickDrawable(getChannelListItem(testPMChannel))); + AddAssert("text box contains 'hello'", () => chatOverlayTextBox.Text == "hello"); + AddStep("click close button", () => + { + ChannelListItemCloseButton closeButton = getChannelListItem(testPMChannel).ChildrenOfType().Single(); + clickDrawable(closeButton); + }); + + AddAssert("listing is visible", () => listingIsVisible); + AddAssert("text box contains 'channel 2'", () => chatOverlayTextBox.Text == "number 2"); + AddUntilStep("only channel 2 visible", () => + { + IEnumerable listingItems = chatOverlay.ChildrenOfType() + .Where(item => item.IsPresent); + return listingItems.Count() == 1 && listingItems.Single().Channel == testChannel2; + }); + } + private void joinTestChannel(int i) { AddStep($"Join test channel {i}", () => channelManager.JoinChannel(testChannels[i])); @@ -621,7 +667,7 @@ namespace osu.Game.Tests.Visual.Online }; } - private class TestChatOverlay : ChatOverlay + private partial class TestChatOverlay : ChatOverlay { public bool SlowLoading { get; set; } @@ -635,7 +681,7 @@ namespace osu.Game.Tests.Visual.Online } } - private class SlowLoadingDrawableChannel : DrawableChannel + private partial class SlowLoadingDrawableChannel : DrawableChannel { public readonly ManualResetEventSlim LoadEvent = new ManualResetEventSlim(); diff --git a/osu.Game.Tests/Visual/Online/TestSceneChatTextBox.cs b/osu.Game.Tests/Visual/Online/TestSceneChatTextBox.cs index 5d28d553a0..1e80acd56b 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChatTextBox.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChatTextBox.cs @@ -18,7 +18,7 @@ using osu.Game.Overlays.Chat; namespace osu.Game.Tests.Visual.Online { [TestFixture] - public class TestSceneChatTextBox : OsuTestScene + public partial class TestSceneChatTextBox : OsuTestScene { [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Pink); diff --git a/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs b/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs index b4ffcd42b5..d925141510 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs @@ -25,7 +25,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Online { - public class TestSceneCommentActions : OsuManualInputManagerTestScene + public partial class TestSceneCommentActions : OsuManualInputManagerTestScene { private Container content = null!; protected override Container Content => content; @@ -77,14 +77,14 @@ namespace osu.Game.Tests.Visual.Online { var comments = this.ChildrenOfType(); var ourComment = comments.SingleOrDefault(x => x.Comment.Id == 1); - return ourComment != null && ourComment.ChildrenOfType().Any(x => x.Text == "Delete"); + return ourComment != null && ourComment.ChildrenOfType().Any(x => x.Text == "delete"); }); AddAssert("Second doesn't", () => { var comments = this.ChildrenOfType(); var ourComment = comments.Single(x => x.Comment.Id == 2); - return ourComment.ChildrenOfType().All(x => x.Text != "Delete"); + return ourComment.ChildrenOfType().All(x => x.Text != "delete"); }); } @@ -102,7 +102,7 @@ namespace osu.Game.Tests.Visual.Online }); AddStep("It has delete button", () => { - var btn = ourComment.ChildrenOfType().Single(x => x.Text == "Delete"); + var btn = ourComment.ChildrenOfType().Single(x => x.Text == "delete"); InputManager.MoveMouseTo(btn); }); AddStep("Click delete button", () => @@ -175,7 +175,7 @@ namespace osu.Game.Tests.Visual.Online }); AddStep("It has delete button", () => { - var btn = ourComment.ChildrenOfType().Single(x => x.Text == "Delete"); + var btn = ourComment.ChildrenOfType().Single(x => x.Text == "delete"); InputManager.MoveMouseTo(btn); }); AddStep("Click delete button", () => @@ -189,7 +189,7 @@ namespace osu.Game.Tests.Visual.Online if (request is not CommentDeleteRequest req) return false; - req.TriggerFailure(new Exception()); + req.TriggerFailure(new InvalidOperationException()); delete = true; return false; }; @@ -245,7 +245,7 @@ namespace osu.Game.Tests.Visual.Online }); AddStep("Click the button", () => { - var btn = targetComment.ChildrenOfType().Single(x => x.Text == "Report"); + var btn = targetComment.ChildrenOfType().Single(x => x.Text == "report"); InputManager.MoveMouseTo(btn); InputManager.Click(MouseButton.Left); }); diff --git a/osu.Game.Tests/Visual/Online/TestSceneCommentReportButton.cs b/osu.Game.Tests/Visual/Online/TestSceneCommentReportButton.cs index fb56a41507..d2e73b8673 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneCommentReportButton.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneCommentReportButton.cs @@ -14,7 +14,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Online { - public class TestSceneCommentReportButton : ThemeComparisonTestScene + public partial class TestSceneCommentReportButton : ThemeComparisonTestScene { [SetUpSteps] public void SetUpSteps() diff --git a/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs index a94b9e61c0..291ccd634d 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs @@ -20,7 +20,7 @@ using osu.Game.Overlays.Comments; namespace osu.Game.Tests.Visual.Online { [TestFixture] - public class TestSceneCommentsContainer : OsuTestScene + public partial class TestSceneCommentsContainer : OsuTestScene { [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple); diff --git a/osu.Game.Tests/Visual/Online/TestSceneCommentsHeader.cs b/osu.Game.Tests/Visual/Online/TestSceneCommentsHeader.cs index 95b718041e..43d80ee0ac 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneCommentsHeader.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneCommentsHeader.cs @@ -12,7 +12,7 @@ using osu.Game.Overlays.Comments; namespace osu.Game.Tests.Visual.Online { [TestFixture] - public class TestSceneCommentsHeader : OsuTestScene + public partial class TestSceneCommentsHeader : OsuTestScene { [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue); diff --git a/osu.Game.Tests/Visual/Online/TestSceneCurrentlyPlayingDisplay.cs b/osu.Game.Tests/Visual/Online/TestSceneCurrentlyPlayingDisplay.cs index 62f8f72929..4f825e1191 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneCurrentlyPlayingDisplay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneCurrentlyPlayingDisplay.cs @@ -20,7 +20,7 @@ using osu.Game.Users; namespace osu.Game.Tests.Visual.Online { - public class TestSceneCurrentlyPlayingDisplay : OsuTestScene + public partial class TestSceneCurrentlyPlayingDisplay : OsuTestScene { private readonly APIUser streamingUser = new APIUser { Id = 2, Username = "Test user" }; @@ -66,7 +66,7 @@ namespace osu.Game.Tests.Visual.Online AddUntilStep("Panel no longer present", () => !currentlyPlaying.ChildrenOfType().Any()); } - internal class TestUserLookupCache : UserLookupCache + internal partial class TestUserLookupCache : UserLookupCache { private static readonly string[] usernames = { diff --git a/osu.Game.Tests/Visual/Online/TestSceneDashboardOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneDashboardOverlay.cs index 074fea0604..504be45b44 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneDashboardOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneDashboardOverlay.cs @@ -8,7 +8,7 @@ using osu.Game.Overlays; namespace osu.Game.Tests.Visual.Online { - public class TestSceneDashboardOverlay : OsuTestScene + public partial class TestSceneDashboardOverlay : OsuTestScene { protected override bool UseOnlineAPI => true; diff --git a/osu.Game.Tests/Visual/Online/TestSceneDrawableChannel.cs b/osu.Game.Tests/Visual/Online/TestSceneDrawableChannel.cs index dc1e00ee8f..4830c7b856 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneDrawableChannel.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneDrawableChannel.cs @@ -13,7 +13,7 @@ using osu.Game.Overlays.Chat; namespace osu.Game.Tests.Visual.Online { [TestFixture] - public class TestSceneDrawableChannel : OsuTestScene + public partial class TestSceneDrawableChannel : OsuTestScene { private Channel channel = null!; private DrawableChannel drawableChannel = null!; diff --git a/osu.Game.Tests/Visual/Online/TestSceneDrawableComment.cs b/osu.Game.Tests/Visual/Online/TestSceneDrawableComment.cs index cab0ffa3ba..ac80463d3a 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneDrawableComment.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneDrawableComment.cs @@ -15,7 +15,7 @@ using osu.Game.Overlays.Comments; namespace osu.Game.Tests.Visual.Online { - public class TestSceneDrawableComment : OsuTestScene + public partial class TestSceneDrawableComment : OsuTestScene { [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple); diff --git a/osu.Game.Tests/Visual/Online/TestSceneExternalLinkButton.cs b/osu.Game.Tests/Visual/Online/TestSceneExternalLinkButton.cs index 4185d56833..90ec3160d8 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneExternalLinkButton.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneExternalLinkButton.cs @@ -10,7 +10,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Online { - public class TestSceneExternalLinkButton : OsuTestScene + public partial class TestSceneExternalLinkButton : OsuTestScene { public TestSceneExternalLinkButton() { diff --git a/osu.Game.Tests/Visual/Online/TestSceneFavouriteButton.cs b/osu.Game.Tests/Visual/Online/TestSceneFavouriteButton.cs index 3206640f9a..3954fd5cff 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneFavouriteButton.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneFavouriteButton.cs @@ -12,7 +12,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Online { - public class TestSceneFavouriteButton : OsuTestScene + public partial class TestSceneFavouriteButton : OsuTestScene { private FavouriteButton favourite; diff --git a/osu.Game.Tests/Visual/Online/TestSceneFriendDisplay.cs b/osu.Game.Tests/Visual/Online/TestSceneFriendDisplay.cs index 5454c87dff..7925b252b6 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneFriendDisplay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneFriendDisplay.cs @@ -16,7 +16,7 @@ using osu.Game.Users; namespace osu.Game.Tests.Visual.Online { - public class TestSceneFriendDisplay : OsuTestScene + public partial class TestSceneFriendDisplay : OsuTestScene { protected override bool UseOnlineAPI => true; diff --git a/osu.Game.Tests/Visual/Online/TestSceneFullscreenOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneFullscreenOverlay.cs index b7e918207f..16d31c916e 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneFullscreenOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneFullscreenOverlay.cs @@ -12,7 +12,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.Online { [TestFixture] - public class TestSceneFullscreenOverlay : OsuTestScene + public partial class TestSceneFullscreenOverlay : OsuTestScene { private FullscreenOverlay overlay; @@ -40,7 +40,7 @@ namespace osu.Game.Tests.Visual.Online AddAssert("fire count 3", () => fireCount == 3); } - private class TestFullscreenOverlay : FullscreenOverlay + private partial class TestFullscreenOverlay : FullscreenOverlay { public TestFullscreenOverlay() : base(OverlayColourScheme.Pink) @@ -57,11 +57,11 @@ namespace osu.Game.Tests.Visual.Online protected override OverlayHeader CreateHeader() => new TestHeader(); - internal class TestHeader : OverlayHeader + internal partial class TestHeader : OverlayHeader { protected override OverlayTitle CreateTitle() => new TestTitle(); - internal class TestTitle : OverlayTitle + internal partial class TestTitle : OverlayTitle { } } diff --git a/osu.Game.Tests/Visual/Online/TestSceneGraph.cs b/osu.Game.Tests/Visual/Online/TestSceneGraph.cs index 8b0536651d..357ed7548c 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneGraph.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneGraph.cs @@ -13,7 +13,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Online { [TestFixture] - public class TestSceneGraph : OsuTestScene + public partial class TestSceneGraph : OsuTestScene { public TestSceneGraph() { diff --git a/osu.Game.Tests/Visual/Online/TestSceneHistoricalSection.cs b/osu.Game.Tests/Visual/Online/TestSceneHistoricalSection.cs index afc20dedff..fdc567d4ad 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneHistoricalSection.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneHistoricalSection.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -11,12 +9,14 @@ using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays; +using osu.Game.Overlays.Profile; using osu.Game.Overlays.Profile.Sections; +using osu.Game.Rulesets.Osu; namespace osu.Game.Tests.Visual.Online { [TestFixture] - public class TestSceneHistoricalSection : OsuTestScene + public partial class TestSceneHistoricalSection : OsuTestScene { protected override bool UseOnlineAPI => true; @@ -39,8 +39,8 @@ namespace osu.Game.Tests.Visual.Online Child = section = new HistoricalSection(), }); - AddStep("Show peppy", () => section.User.Value = new APIUser { Id = 2 }); - AddStep("Show WubWoofWolf", () => section.User.Value = new APIUser { Id = 39828 }); + AddStep("Show peppy", () => section.User.Value = new UserProfileData(new APIUser { Id = 2 }, new OsuRuleset().RulesetInfo)); + AddStep("Show WubWoofWolf", () => section.User.Value = new UserProfileData(new APIUser { Id = 39828 }, new OsuRuleset().RulesetInfo)); } } } diff --git a/osu.Game.Tests/Visual/Online/TestSceneHomeNewsPanel.cs b/osu.Game.Tests/Visual/Online/TestSceneHomeNewsPanel.cs index 181b086b00..a58845ca7e 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneHomeNewsPanel.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneHomeNewsPanel.cs @@ -15,7 +15,7 @@ using System.Collections.Generic; namespace osu.Game.Tests.Visual.Online { - public class TestSceneHomeNewsPanel : OsuTestScene + public partial class TestSceneHomeNewsPanel : OsuTestScene { [Cached] private readonly OverlayColourProvider overlayColour = new OverlayColourProvider(OverlayColourScheme.Purple); diff --git a/osu.Game.Tests/Visual/Online/TestSceneKudosuHistory.cs b/osu.Game.Tests/Visual/Online/TestSceneKudosuHistory.cs index 7f0a00c474..25a56196eb 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneKudosuHistory.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneKudosuHistory.cs @@ -1,25 +1,26 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Game.Overlays.Profile.Sections.Kudosu; using System.Collections.Generic; using System; using osu.Framework.Graphics.Containers; -using osu.Game.Graphics; using osu.Framework.Allocation; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics; using osu.Game.Online.API.Requests.Responses; using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Game.Overlays; namespace osu.Game.Tests.Visual.Online { - public class TestSceneKudosuHistory : OsuTestScene + public partial class TestSceneKudosuHistory : OsuTestScene { private readonly Box background; + [Cached] + private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Pink); + public TestSceneKudosuHistory() { FillFlowContainer content; @@ -44,9 +45,9 @@ namespace osu.Game.Tests.Visual.Online } [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load() { - background.Colour = colours.GreySeaFoam; + background.Colour = colourProvider.Background4; } private readonly IEnumerable items = new[] diff --git a/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs index 5579ecedbd..0a6bab468a 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs @@ -20,7 +20,7 @@ using osu.Game.Rulesets.Mods; namespace osu.Game.Tests.Visual.Online { - public class TestSceneLeaderboardModSelector : OsuTestScene + public partial class TestSceneLeaderboardModSelector : OsuTestScene { public TestSceneLeaderboardModSelector() { diff --git a/osu.Game.Tests/Visual/Online/TestSceneLeaderboardScopeSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardScopeSelector.cs index 8c38027df3..0231775189 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneLeaderboardScopeSelector.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardScopeSelector.cs @@ -12,7 +12,7 @@ using osu.Game.Overlays; namespace osu.Game.Tests.Visual.Online { - public class TestSceneLeaderboardScopeSelector : OsuTestScene + public partial class TestSceneLeaderboardScopeSelector : OsuTestScene { [Cached] private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue); diff --git a/osu.Game.Tests/Visual/Online/TestSceneMessageNotifier.cs b/osu.Game.Tests/Visual/Online/TestSceneMessageNotifier.cs index 57514cdf37..ba2b160fd1 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneMessageNotifier.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneMessageNotifier.cs @@ -23,7 +23,7 @@ using APIUser = osu.Game.Online.API.Requests.Responses.APIUser; namespace osu.Game.Tests.Visual.Online { - public class TestSceneMessageNotifier : OsuManualInputManagerTestScene + public partial class TestSceneMessageNotifier : OsuManualInputManagerTestScene { private APIUser friend; private Channel publicChannel; @@ -228,7 +228,7 @@ namespace osu.Game.Tests.Visual.Online InputManager.Click(MouseButton.Left); } - private class TestContainer : Container + private partial class TestContainer : Container { [Cached] public ChannelManager ChannelManager { get; } diff --git a/osu.Game.Tests/Visual/Online/TestSceneNewsCard.cs b/osu.Game.Tests/Visual/Online/TestSceneNewsCard.cs index 8d73165d99..001e6d925e 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneNewsCard.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneNewsCard.cs @@ -14,7 +14,7 @@ using System; namespace osu.Game.Tests.Visual.Online { - public class TestSceneNewsCard : OsuTestScene + public partial class TestSceneNewsCard : OsuTestScene { [Cached] private readonly OverlayColourProvider overlayColour = new OverlayColourProvider(OverlayColourScheme.Purple); diff --git a/osu.Game.Tests/Visual/Online/TestSceneNewsHeader.cs b/osu.Game.Tests/Visual/Online/TestSceneNewsHeader.cs index cad045623b..2413c32d61 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneNewsHeader.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneNewsHeader.cs @@ -11,7 +11,7 @@ using osu.Framework.Allocation; namespace osu.Game.Tests.Visual.Online { - public class TestSceneNewsHeader : OsuTestScene + public partial class TestSceneNewsHeader : OsuTestScene { [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple); @@ -47,7 +47,7 @@ namespace osu.Game.Tests.Visual.Online AddAssert("1 tab total", () => header.TabCount == 1); } - private class TestHeader : NewsHeader + private partial class TestHeader : NewsHeader { public int TabCount => TabControl.Items.Count; } diff --git a/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs index 3e5dd91b2c..0e272c9cc8 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs @@ -15,7 +15,7 @@ using osu.Game.Overlays; namespace osu.Game.Tests.Visual.Online { - public class TestSceneNewsOverlay : OsuTestScene + public partial class TestSceneNewsOverlay : OsuTestScene { private DummyAPIAccess dummyAPI => (DummyAPIAccess)API; diff --git a/osu.Game.Tests/Visual/Online/TestSceneNewsSidebar.cs b/osu.Game.Tests/Visual/Online/TestSceneNewsSidebar.cs index 266e98db15..ce5fc888aa 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneNewsSidebar.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneNewsSidebar.cs @@ -16,7 +16,7 @@ using static osu.Game.Overlays.News.Sidebar.YearsPanel; namespace osu.Game.Tests.Visual.Online { - public class TestSceneNewsSidebar : OsuTestScene + public partial class TestSceneNewsSidebar : OsuTestScene { [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple); @@ -211,7 +211,7 @@ namespace osu.Game.Tests.Visual.Online } }; - private class TestNewsSidebar : NewsSidebar + private partial class TestNewsSidebar : NewsSidebar { public Action YearChanged; diff --git a/osu.Game.Tests/Visual/Online/TestSceneNowPlayingCommand.cs b/osu.Game.Tests/Visual/Online/TestSceneNowPlayingCommand.cs index 2df9089a8a..4675410164 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneNowPlayingCommand.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneNowPlayingCommand.cs @@ -11,12 +11,13 @@ using osu.Game.Beatmaps; using osu.Game.Online.API; using osu.Game.Online.Chat; using osu.Game.Rulesets; +using osu.Game.Rulesets.Mods; using osu.Game.Users; namespace osu.Game.Tests.Visual.Online { [HeadlessTest] - public class TestSceneNowPlayingCommand : OsuTestScene + public partial class TestSceneNowPlayingCommand : OsuTestScene { [Cached(typeof(IChannelPostTarget))] private PostTarget postTarget { get; set; } @@ -33,7 +34,7 @@ namespace osu.Game.Tests.Visual.Online { AddStep("Set activity", () => api.Activity.Value = new UserActivity.InLobby(null)); - AddStep("Run command", () => Add(new NowPlayingCommand())); + AddStep("Run command", () => Add(new NowPlayingCommand(new Channel()))); AddAssert("Check correct response", () => postTarget.LastMessage.Contains("is listening")); } @@ -43,7 +44,7 @@ namespace osu.Game.Tests.Visual.Online { AddStep("Set activity", () => api.Activity.Value = new UserActivity.Editing(new BeatmapInfo())); - AddStep("Run command", () => Add(new NowPlayingCommand())); + AddStep("Run command", () => Add(new NowPlayingCommand(new Channel()))); AddAssert("Check correct response", () => postTarget.LastMessage.Contains("is editing")); } @@ -53,7 +54,7 @@ namespace osu.Game.Tests.Visual.Online { AddStep("Set activity", () => api.Activity.Value = new UserActivity.InSoloGame(new BeatmapInfo(), new RulesetInfo())); - AddStep("Run command", () => Add(new NowPlayingCommand())); + AddStep("Run command", () => Add(new NowPlayingCommand(new Channel()))); AddAssert("Check correct response", () => postTarget.LastMessage.Contains("is playing")); } @@ -69,7 +70,7 @@ namespace osu.Game.Tests.Visual.Online BeatmapInfo = { OnlineID = hasOnlineId ? 1234 : -1 } }); - AddStep("Run command", () => Add(new NowPlayingCommand())); + AddStep("Run command", () => Add(new NowPlayingCommand(new Channel()))); if (hasOnlineId) AddAssert("Check link presence", () => postTarget.LastMessage.Contains("/b/1234")); @@ -77,7 +78,19 @@ namespace osu.Game.Tests.Visual.Online AddAssert("Check link not present", () => !postTarget.LastMessage.Contains("https://")); } - public class PostTarget : Component, IChannelPostTarget + [Test] + public void TestModPresence() + { + AddStep("Set activity", () => api.Activity.Value = new UserActivity.InSoloGame(new BeatmapInfo(), new RulesetInfo())); + + AddStep("Add Hidden mod", () => SelectedMods.Value = new[] { Ruleset.Value.CreateInstance().CreateMod() }); + + AddStep("Run command", () => Add(new NowPlayingCommand(new Channel()))); + + AddAssert("Check mod is present", () => postTarget.LastMessage.Contains("+HD")); + } + + public partial class PostTarget : Component, IChannelPostTarget { public void PostMessage(string text, bool isAction = false, Channel target = null) { diff --git a/osu.Game.Tests/Visual/Online/TestSceneOfflineCommentsContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneOfflineCommentsContainer.cs index 07ccfcec88..4016fa7b68 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneOfflineCommentsContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneOfflineCommentsContainer.cs @@ -19,7 +19,7 @@ using APIUser = osu.Game.Online.API.Requests.Responses.APIUser; namespace osu.Game.Tests.Visual.Online { - public class TestSceneOfflineCommentsContainer : OsuTestScene + public partial class TestSceneOfflineCommentsContainer : OsuTestScene { [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue); @@ -184,7 +184,7 @@ namespace osu.Game.Tests.Visual.Online PinnedComments = new List(), }; - private class TestCommentsContainer : CommentsContainer + private partial class TestCommentsContainer : CommentsContainer { public new void AppendComments([NotNull] CommentBundle bundle) => base.AppendComments(bundle); diff --git a/osu.Game.Tests/Visual/Online/TestSceneOnlineBeatmapListingOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneOnlineBeatmapListingOverlay.cs index 388c0a9d60..ecfa76f395 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneOnlineBeatmapListingOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneOnlineBeatmapListingOverlay.cs @@ -9,7 +9,7 @@ using NUnit.Framework; namespace osu.Game.Tests.Visual.Online { [Description("uses online API")] - public class TestSceneOnlineBeatmapListingOverlay : OsuTestScene + public partial class TestSceneOnlineBeatmapListingOverlay : OsuTestScene { protected override bool UseOnlineAPI => true; diff --git a/osu.Game.Tests/Visual/Online/TestSceneOnlineBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneOnlineBeatmapSetOverlay.cs index 0d9c47db7b..01b0b39661 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneOnlineBeatmapSetOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneOnlineBeatmapSetOverlay.cs @@ -8,7 +8,7 @@ using osu.Game.Overlays; namespace osu.Game.Tests.Visual.Online { - public class TestSceneOnlineBeatmapSetOverlay : OsuTestScene + public partial class TestSceneOnlineBeatmapSetOverlay : OsuTestScene { private readonly BeatmapSetOverlay overlay; diff --git a/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs index b4bac5ee7e..6c8430e955 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs @@ -18,7 +18,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.Online { [TestFixture] - public class TestSceneOnlineViewContainer : OsuTestScene + public partial class TestSceneOnlineViewContainer : OsuTestScene { private readonly TestOnlineViewContainer onlineView; @@ -67,7 +67,7 @@ namespace osu.Game.Tests.Visual.Online AddUntilStep("loading animation is visible", () => onlineView.LoadingSpinner.IsPresent); } - private class TestOnlineViewContainer : OnlineViewContainer + private partial class TestOnlineViewContainer : OnlineViewContainer { public new LoadingSpinner LoadingSpinner => base.LoadingSpinner; diff --git a/osu.Game.Tests/Visual/Online/TestScenePlayHistorySubsection.cs b/osu.Game.Tests/Visual/Online/TestScenePlayHistorySubsection.cs index 118da682a7..106433d7ce 100644 --- a/osu.Game.Tests/Visual/Online/TestScenePlayHistorySubsection.cs +++ b/osu.Game.Tests/Visual/Online/TestScenePlayHistorySubsection.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Game.Overlays.Profile.Sections.Historical; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -14,15 +12,17 @@ using System.Linq; using osu.Framework.Testing; using osu.Framework.Graphics.Shapes; using osu.Game.Online.API.Requests.Responses; +using osu.Game.Overlays.Profile; +using osu.Game.Rulesets.Osu; namespace osu.Game.Tests.Visual.Online { - public class TestScenePlayHistorySubsection : OsuTestScene + public partial class TestScenePlayHistorySubsection : OsuTestScene { [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Red); - private readonly Bindable user = new Bindable(); + private readonly Bindable user = new Bindable(); private readonly PlayHistorySubsection section; public TestScenePlayHistorySubsection() @@ -45,49 +45,49 @@ namespace osu.Game.Tests.Visual.Online [Test] public void TestNullValues() { - AddStep("Load user", () => user.Value = user_with_null_values); + AddStep("Load user", () => user.Value = new UserProfileData(user_with_null_values, new OsuRuleset().RulesetInfo)); AddAssert("Section is hidden", () => section.Alpha == 0); } [Test] public void TestEmptyValues() { - AddStep("Load user", () => user.Value = user_with_empty_values); + AddStep("Load user", () => user.Value = new UserProfileData(user_with_empty_values, new OsuRuleset().RulesetInfo)); AddAssert("Section is hidden", () => section.Alpha == 0); } [Test] public void TestOneValue() { - AddStep("Load user", () => user.Value = user_with_one_value); + AddStep("Load user", () => user.Value = new UserProfileData(user_with_one_value, new OsuRuleset().RulesetInfo)); AddAssert("Section is hidden", () => section.Alpha == 0); } [Test] public void TestTwoValues() { - AddStep("Load user", () => user.Value = user_with_two_values); + AddStep("Load user", () => user.Value = new UserProfileData(user_with_two_values, new OsuRuleset().RulesetInfo)); AddAssert("Section is visible", () => section.Alpha == 1); } [Test] public void TestConstantValues() { - AddStep("Load user", () => user.Value = user_with_constant_values); + AddStep("Load user", () => user.Value = new UserProfileData(user_with_constant_values, new OsuRuleset().RulesetInfo)); AddAssert("Section is visible", () => section.Alpha == 1); } [Test] public void TestConstantZeroValues() { - AddStep("Load user", () => user.Value = user_with_zero_values); + AddStep("Load user", () => user.Value = new UserProfileData(user_with_zero_values, new OsuRuleset().RulesetInfo)); AddAssert("Section is visible", () => section.Alpha == 1); } [Test] public void TestFilledValues() { - AddStep("Load user", () => user.Value = user_with_filled_values); + AddStep("Load user", () => user.Value = new UserProfileData(user_with_filled_values, new OsuRuleset().RulesetInfo)); AddAssert("Section is visible", () => section.Alpha == 1); AddAssert("Array length is the same", () => user_with_filled_values.MonthlyPlayCounts.Length == getChartValuesLength()); } @@ -95,7 +95,7 @@ namespace osu.Game.Tests.Visual.Online [Test] public void TestMissingValues() { - AddStep("Load user", () => user.Value = user_with_missing_values); + AddStep("Load user", () => user.Value = new UserProfileData(user_with_missing_values, new OsuRuleset().RulesetInfo)); AddAssert("Section is visible", () => section.Alpha == 1); AddAssert("Array length is 7", () => getChartValuesLength() == 7); } diff --git a/osu.Game.Tests/Visual/Online/TestSceneProfileRulesetSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneProfileRulesetSelector.cs index 3068ba0185..bb2ef1c1b0 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneProfileRulesetSelector.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneProfileRulesetSelector.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Graphics; using osu.Game.Overlays.Profile.Header.Components; using osu.Game.Rulesets.Catch; @@ -13,35 +11,35 @@ using osu.Framework.Bindables; using osu.Game.Overlays; using osu.Framework.Allocation; using osu.Game.Online.API.Requests.Responses; +using osu.Game.Overlays.Profile; namespace osu.Game.Tests.Visual.Online { - public class TestSceneProfileRulesetSelector : OsuTestScene + public partial class TestSceneProfileRulesetSelector : OsuTestScene { [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Pink); public TestSceneProfileRulesetSelector() { - ProfileRulesetSelector selector; - var user = new Bindable(); + var user = new Bindable(); - Child = selector = new ProfileRulesetSelector + Child = new ProfileRulesetSelector { Anchor = Anchor.Centre, Origin = Anchor.Centre, User = { BindTarget = user } }; + AddStep("User on osu ruleset", () => user.Value = new UserProfileData(new APIUser { Id = 0, PlayMode = "osu" }, new OsuRuleset().RulesetInfo)); + AddStep("User on taiko ruleset", () => user.Value = new UserProfileData(new APIUser { Id = 1, PlayMode = "osu" }, new TaikoRuleset().RulesetInfo)); + AddStep("User on catch ruleset", () => user.Value = new UserProfileData(new APIUser { Id = 2, PlayMode = "osu" }, new CatchRuleset().RulesetInfo)); + AddStep("User on mania ruleset", () => user.Value = new UserProfileData(new APIUser { Id = 3, PlayMode = "osu" }, new ManiaRuleset().RulesetInfo)); - AddStep("set osu! as default", () => selector.SetDefaultRuleset(new OsuRuleset().RulesetInfo)); - AddStep("set taiko as default", () => selector.SetDefaultRuleset(new TaikoRuleset().RulesetInfo)); - AddStep("set catch as default", () => selector.SetDefaultRuleset(new CatchRuleset().RulesetInfo)); - AddStep("set mania as default", () => selector.SetDefaultRuleset(new ManiaRuleset().RulesetInfo)); + AddStep("User with osu as default", () => user.Value = new UserProfileData(new APIUser { Id = 0, PlayMode = "osu" }, new OsuRuleset().RulesetInfo)); + AddStep("User with taiko as default", () => user.Value = new UserProfileData(new APIUser { Id = 1, PlayMode = "taiko" }, new OsuRuleset().RulesetInfo)); + AddStep("User with catch as default", () => user.Value = new UserProfileData(new APIUser { Id = 2, PlayMode = "fruits" }, new OsuRuleset().RulesetInfo)); + AddStep("User with mania as default", () => user.Value = new UserProfileData(new APIUser { Id = 3, PlayMode = "mania" }, new OsuRuleset().RulesetInfo)); - AddStep("User with osu as default", () => user.Value = new APIUser { Id = 0, PlayMode = "osu" }); - AddStep("User with taiko as default", () => user.Value = new APIUser { Id = 1, PlayMode = "taiko" }); - AddStep("User with catch as default", () => user.Value = new APIUser { Id = 2, PlayMode = "fruits" }); - AddStep("User with mania as default", () => user.Value = new APIUser { Id = 3, PlayMode = "mania" }); AddStep("null user", () => user.Value = null); } } diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankGraph.cs b/osu.Game.Tests/Visual/Online/TestSceneRankGraph.cs index d05f1f02f7..55817e38a6 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankGraph.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankGraph.cs @@ -19,7 +19,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Online { [TestFixture] - public class TestSceneRankGraph : OsuTestScene + public partial class TestSceneRankGraph : OsuTestScene { [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Pink); diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsCountryFilter.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsCountryFilter.cs index 6a39db4870..dfefcd735e 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsCountryFilter.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsCountryFilter.cs @@ -16,7 +16,7 @@ using osu.Framework.Allocation; namespace osu.Game.Tests.Visual.Online { - public class TestSceneRankingsCountryFilter : OsuTestScene + public partial class TestSceneRankingsCountryFilter : OsuTestScene { [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Green); diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs index c776cfe377..5aef91bef1 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs @@ -12,7 +12,7 @@ using osu.Game.Users; namespace osu.Game.Tests.Visual.Online { - public class TestSceneRankingsHeader : OsuTestScene + public partial class TestSceneRankingsHeader : OsuTestScene { [Cached] private readonly OverlayColourProvider overlayColour = new OverlayColourProvider(OverlayColourScheme.Green); diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs index 5476049882..d1c1164768 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs @@ -15,7 +15,7 @@ using osu.Game.Users; namespace osu.Game.Tests.Visual.Online { - public class TestSceneRankingsOverlay : OsuTestScene + public partial class TestSceneRankingsOverlay : OsuTestScene { protected override bool UseOnlineAPI => true; @@ -69,7 +69,7 @@ namespace osu.Game.Tests.Visual.Online }; } - private class TestRankingsOverlay : RankingsOverlay + private partial class TestRankingsOverlay : RankingsOverlay { public new Bindable Country => base.Country; } diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsSpotlightSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsSpotlightSelector.cs index 5aafcf3f6b..119d79e2a9 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsSpotlightSelector.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsSpotlightSelector.cs @@ -15,7 +15,7 @@ using osu.Game.Overlays.Rankings; namespace osu.Game.Tests.Visual.Online { - public class TestSceneRankingsSpotlightSelector : OsuTestScene + public partial class TestSceneRankingsSpotlightSelector : OsuTestScene { protected override bool UseOnlineAPI => true; diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsTables.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsTables.cs index 81b76d19ac..cd5e1cef08 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsTables.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsTables.cs @@ -16,7 +16,7 @@ using osu.Game.Users; namespace osu.Game.Tests.Visual.Online { - public class TestSceneRankingsTables : OsuTestScene + public partial class TestSceneRankingsTables : OsuTestScene { [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Green); diff --git a/osu.Game.Tests/Visual/Online/TestSceneScoreboardTime.cs b/osu.Game.Tests/Visual/Online/TestSceneScoreboardTime.cs index 8f03f240f7..ab85cd4a15 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneScoreboardTime.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneScoreboardTime.cs @@ -14,7 +14,7 @@ using osu.Game.Overlays.BeatmapSet.Scores; namespace osu.Game.Tests.Visual.Online { - public class TestSceneScoreboardTime : OsuTestScene + public partial class TestSceneScoreboardTime : OsuTestScene { private StopwatchClock stopwatch; diff --git a/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs index a0f76c4e14..2bfbf76c10 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs @@ -26,7 +26,7 @@ using APIUser = osu.Game.Online.API.Requests.Responses.APIUser; namespace osu.Game.Tests.Visual.Online { - public class TestSceneScoresContainer : OsuTestScene + public partial class TestSceneScoresContainer : OsuTestScene { [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue); @@ -313,7 +313,7 @@ namespace osu.Game.Tests.Visual.Online Position = 1337, }; - private class TestScoresContainer : ScoresContainer + private partial class TestScoresContainer : ScoresContainer { public new APIScoresCollection Scores { diff --git a/osu.Game.Tests/Visual/Online/TestSceneShowMoreButton.cs b/osu.Game.Tests/Visual/Online/TestSceneShowMoreButton.cs index 32262c18a8..905a085386 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneShowMoreButton.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneShowMoreButton.cs @@ -10,7 +10,7 @@ using osu.Game.Overlays; namespace osu.Game.Tests.Visual.Online { - public class TestSceneShowMoreButton : OsuTestScene + public partial class TestSceneShowMoreButton : OsuTestScene { [Cached] private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Green); diff --git a/osu.Game.Tests/Visual/Online/TestSceneSoloStatisticsWatcher.cs b/osu.Game.Tests/Visual/Online/TestSceneSoloStatisticsWatcher.cs new file mode 100644 index 0000000000..e62e53bd02 --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneSoloStatisticsWatcher.cs @@ -0,0 +1,302 @@ +// Copyright (c) ppy Pty Ltd . 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 NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Testing; +using osu.Game.Models; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests; +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Online.Solo; +using osu.Game.Online.Spectator; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Osu; +using osu.Game.Scoring; +using osu.Game.Users; + +namespace osu.Game.Tests.Visual.Online +{ + [HeadlessTest] + public partial class TestSceneSoloStatisticsWatcher : OsuTestScene + { + protected override bool UseOnlineAPI => false; + + private SoloStatisticsWatcher watcher = null!; + + [Resolved] + private SpectatorClient spectatorClient { get; set; } = null!; + + private DummyAPIAccess dummyAPI => (DummyAPIAccess)API; + + private Action? handleGetUsersRequest; + private Action? handleGetUserRequest; + + private IDisposable? subscription; + + private readonly Dictionary<(int userId, string rulesetName), UserStatistics> serverSideStatistics = new Dictionary<(int userId, string rulesetName), UserStatistics>(); + + [SetUpSteps] + public void SetUpSteps() + { + AddStep("clear server-side stats", () => serverSideStatistics.Clear()); + AddStep("set up request handling", () => + { + handleGetUserRequest = null; + handleGetUsersRequest = null; + + dummyAPI.HandleRequest = request => + { + switch (request) + { + case GetUsersRequest getUsersRequest: + if (handleGetUsersRequest != null) + { + handleGetUsersRequest?.Invoke(getUsersRequest); + } + else + { + int userId = getUsersRequest.UserIds.Single(); + var response = new GetUsersResponse + { + Users = new List + { + new APIUser + { + Id = userId, + RulesetsStatistics = new Dictionary + { + ["osu"] = tryGetStatistics(userId, "osu"), + ["taiko"] = tryGetStatistics(userId, "taiko"), + ["fruits"] = tryGetStatistics(userId, "fruits"), + ["mania"] = tryGetStatistics(userId, "mania"), + } + } + } + }; + getUsersRequest.TriggerSuccess(response); + } + + return true; + + case GetUserRequest getUserRequest: + if (handleGetUserRequest != null) + { + handleGetUserRequest.Invoke(getUserRequest); + } + else + { + int userId = int.Parse(getUserRequest.Lookup); + string rulesetName = getUserRequest.Ruleset.ShortName; + var response = new APIUser + { + Id = userId, + Statistics = tryGetStatistics(userId, rulesetName) + }; + getUserRequest.TriggerSuccess(response); + } + + return true; + + default: + return false; + } + }; + }); + + AddStep("create watcher", () => + { + Child = watcher = new SoloStatisticsWatcher(); + }); + } + + private UserStatistics tryGetStatistics(int userId, string rulesetName) + => serverSideStatistics.TryGetValue((userId, rulesetName), out var stats) ? stats : new UserStatistics(); + + [Test] + public void TestStatisticsUpdateFiredAfterRegistrationAddedAndScoreProcessed() + { + int userId = getUserId(); + long scoreId = getScoreId(); + setUpUser(userId); + + var ruleset = new OsuRuleset().RulesetInfo; + + SoloStatisticsUpdate? update = null; + registerForUpdates(scoreId, ruleset, receivedUpdate => update = receivedUpdate); + + feignScoreProcessing(userId, ruleset, 5_000_000); + + AddStep("signal score processed", () => ((ISpectatorClient)spectatorClient).UserScoreProcessed(userId, scoreId)); + AddUntilStep("update received", () => update != null); + AddAssert("values before are correct", () => update!.Before.TotalScore, () => Is.EqualTo(4_000_000)); + AddAssert("values after are correct", () => update!.After.TotalScore, () => Is.EqualTo(5_000_000)); + } + + [Test] + public void TestStatisticsUpdateFiredAfterScoreProcessedAndRegistrationAdded() + { + int userId = getUserId(); + setUpUser(userId); + + long scoreId = getScoreId(); + var ruleset = new OsuRuleset().RulesetInfo; + + // note ordering - in this test processing completes *before* the registration is added. + feignScoreProcessing(userId, ruleset, 5_000_000); + + SoloStatisticsUpdate? update = null; + registerForUpdates(scoreId, ruleset, receivedUpdate => update = receivedUpdate); + + AddStep("signal score processed", () => ((ISpectatorClient)spectatorClient).UserScoreProcessed(userId, scoreId)); + AddUntilStep("update received", () => update != null); + AddAssert("values before are correct", () => update!.Before.TotalScore, () => Is.EqualTo(4_000_000)); + AddAssert("values after are correct", () => update!.After.TotalScore, () => Is.EqualTo(5_000_000)); + } + + [Test] + public void TestStatisticsUpdateNotFiredIfUserLoggedOut() + { + int userId = getUserId(); + setUpUser(userId); + + long scoreId = getScoreId(); + var ruleset = new OsuRuleset().RulesetInfo; + + SoloStatisticsUpdate? update = null; + registerForUpdates(scoreId, ruleset, receivedUpdate => update = receivedUpdate); + + feignScoreProcessing(userId, ruleset, 5_000_000); + + AddStep("log out user", () => dummyAPI.Logout()); + + AddStep("signal score processed", () => ((ISpectatorClient)spectatorClient).UserScoreProcessed(userId, scoreId)); + AddWaitStep("wait a bit", 5); + AddAssert("update not received", () => update == null); + + AddStep("log in user", () => dummyAPI.Login("user", "password")); + } + + [Test] + public void TestStatisticsUpdateNotFiredIfAnotherUserLoggedIn() + { + int userId = getUserId(); + setUpUser(userId); + + long scoreId = getScoreId(); + var ruleset = new OsuRuleset().RulesetInfo; + + SoloStatisticsUpdate? update = null; + registerForUpdates(scoreId, ruleset, receivedUpdate => update = receivedUpdate); + + feignScoreProcessing(userId, ruleset, 5_000_000); + + AddStep("change user", () => dummyAPI.LocalUser.Value = new APIUser { Id = getUserId() }); + + AddStep("signal score processed", () => ((ISpectatorClient)spectatorClient).UserScoreProcessed(userId, scoreId)); + AddWaitStep("wait a bit", 5); + AddAssert("update not received", () => update == null); + } + + [Test] + public void TestStatisticsUpdateNotFiredIfScoreIdDoesNotMatch() + { + int userId = getUserId(); + setUpUser(userId); + + long scoreId = getScoreId(); + var ruleset = new OsuRuleset().RulesetInfo; + + SoloStatisticsUpdate? update = null; + registerForUpdates(scoreId, ruleset, receivedUpdate => update = receivedUpdate); + + feignScoreProcessing(userId, ruleset, 5_000_000); + + AddStep("signal another score processed", () => ((ISpectatorClient)spectatorClient).UserScoreProcessed(userId, getScoreId())); + AddWaitStep("wait a bit", 5); + AddAssert("update not received", () => update == null); + } + + // the behaviour exercised in this test may not be final, it is mostly assumed for simplicity. + // in the long run we may want each score's update to be entirely isolated from others, rather than have prior unobserved updates merge into the latest. + [Test] + public void TestIgnoredScoreUpdateIsMergedIntoNextOne() + { + int userId = getUserId(); + setUpUser(userId); + + long firstScoreId = getScoreId(); + var ruleset = new OsuRuleset().RulesetInfo; + + feignScoreProcessing(userId, ruleset, 5_000_000); + + AddStep("signal score processed", () => ((ISpectatorClient)spectatorClient).UserScoreProcessed(userId, firstScoreId)); + + long secondScoreId = getScoreId(); + + feignScoreProcessing(userId, ruleset, 6_000_000); + + SoloStatisticsUpdate? update = null; + registerForUpdates(secondScoreId, ruleset, receivedUpdate => update = receivedUpdate); + + AddStep("signal score processed", () => ((ISpectatorClient)spectatorClient).UserScoreProcessed(userId, secondScoreId)); + AddUntilStep("update received", () => update != null); + AddAssert("values before are correct", () => update!.Before.TotalScore, () => Is.EqualTo(4_000_000)); + AddAssert("values after are correct", () => update!.After.TotalScore, () => Is.EqualTo(6_000_000)); + } + + [Test] + public void TestStatisticsUpdateNotFiredAfterSubscriptionDisposal() + { + int userId = getUserId(); + setUpUser(userId); + + long scoreId = getScoreId(); + var ruleset = new OsuRuleset().RulesetInfo; + + SoloStatisticsUpdate? update = null; + registerForUpdates(scoreId, ruleset, receivedUpdate => update = receivedUpdate); + AddStep("unsubscribe", () => subscription!.Dispose()); + + feignScoreProcessing(userId, ruleset, 5_000_000); + + AddStep("signal score processed", () => ((ISpectatorClient)spectatorClient).UserScoreProcessed(userId, scoreId)); + AddWaitStep("wait a bit", 5); + AddAssert("update not received", () => update == null); + } + + private int nextUserId = 2000; + private long nextScoreId = 50000; + + private int getUserId() => ++nextUserId; + private long getScoreId() => ++nextScoreId; + + private void setUpUser(int userId) + { + AddStep("fetch initial stats", () => + { + serverSideStatistics[(userId, "osu")] = new UserStatistics { TotalScore = 4_000_000 }; + serverSideStatistics[(userId, "taiko")] = new UserStatistics { TotalScore = 3_000_000 }; + serverSideStatistics[(userId, "fruits")] = new UserStatistics { TotalScore = 2_000_000 }; + serverSideStatistics[(userId, "mania")] = new UserStatistics { TotalScore = 1_000_000 }; + + dummyAPI.LocalUser.Value = new APIUser { Id = userId }; + }); + } + + private void registerForUpdates(long scoreId, RulesetInfo rulesetInfo, Action onUpdateReady) => + AddStep("register for updates", () => subscription = watcher.RegisterForStatisticsUpdateAfter( + new ScoreInfo(Beatmap.Value.BeatmapInfo, new OsuRuleset().RulesetInfo, new RealmUser()) + { + Ruleset = rulesetInfo, + OnlineID = scoreId + }, + onUpdateReady)); + + private void feignScoreProcessing(int userId, RulesetInfo rulesetInfo, long newTotalScore) + => AddStep("feign score processing", () => serverSideStatistics[(userId, rulesetInfo.ShortName)] = new UserStatistics { TotalScore = newTotalScore }); + } +} diff --git a/osu.Game.Tests/Visual/Online/TestSceneSpotlightsLayout.cs b/osu.Game.Tests/Visual/Online/TestSceneSpotlightsLayout.cs index d7feade128..4cbcaaac85 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneSpotlightsLayout.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneSpotlightsLayout.cs @@ -17,7 +17,7 @@ using osu.Game.Rulesets.Taiko; namespace osu.Game.Tests.Visual.Online { - public class TestSceneSpotlightsLayout : OsuTestScene + public partial class TestSceneSpotlightsLayout : OsuTestScene { protected override bool UseOnlineAPI => true; diff --git a/osu.Game.Tests/Visual/Online/TestSceneStandAloneChatDisplay.cs b/osu.Game.Tests/Visual/Online/TestSceneStandAloneChatDisplay.cs index 34ecad7dc1..d7f79d3e30 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneStandAloneChatDisplay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneStandAloneChatDisplay.cs @@ -20,7 +20,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Online { - public class TestSceneStandAloneChatDisplay : OsuManualInputManagerTestScene + public partial class TestSceneStandAloneChatDisplay : OsuManualInputManagerTestScene { private readonly APIUser admin = new APIUser { @@ -50,6 +50,8 @@ namespace osu.Game.Tests.Visual.Online private ChannelManager channelManager; private TestStandAloneChatDisplay chatDisplay; + private TestStandAloneChatDisplay chatWithTextBox; + private TestStandAloneChatDisplay chatWithTextBox2; private int messageIdSequence; private Channel testChannel; @@ -73,7 +75,12 @@ namespace osu.Game.Tests.Visual.Online messageIdSequence = 0; channelManager.CurrentChannel.Value = testChannel = new Channel(); - Children = new[] + reinitialiseDrawableDisplay(); + }); + + private void reinitialiseDrawableDisplay() + { + Children = new Drawable[] { chatDisplay = new TestStandAloneChatDisplay { @@ -83,22 +90,38 @@ namespace osu.Game.Tests.Visual.Online Size = new Vector2(400, 80), Channel = { Value = testChannel }, }, - new TestStandAloneChatDisplay(true) + new FillFlowContainer { Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, Margin = new MarginPadding(20), - Size = new Vector2(400, 150), - Channel = { Value = testChannel }, + Children = new[] + { + chatWithTextBox = new TestStandAloneChatDisplay(true) + { + Margin = new MarginPadding(20), + Size = new Vector2(400, 150), + Channel = { Value = testChannel }, + }, + chatWithTextBox2 = new TestStandAloneChatDisplay(true) + { + Margin = new MarginPadding(20), + Size = new Vector2(400, 150), + Channel = { Value = testChannel }, + }, + } } }; - }); + } [Test] public void TestSystemMessageOrdering() { var standardMessage = new Message(messageIdSequence++) { + Timestamp = DateTimeOffset.Now, Sender = admin, Content = "I am a wang!" }; @@ -106,14 +129,45 @@ namespace osu.Game.Tests.Visual.Online var infoMessage1 = new InfoMessage($"the system is calling {messageIdSequence++}"); var infoMessage2 = new InfoMessage($"the system is calling {messageIdSequence++}"); + var standardMessage2 = new Message(messageIdSequence++) + { + Timestamp = DateTimeOffset.Now, + Sender = admin, + Content = "I am a wang!" + }; + AddStep("message from admin", () => testChannel.AddNewMessages(standardMessage)); AddStep("message from system", () => testChannel.AddNewMessages(infoMessage1)); AddStep("message from system", () => testChannel.AddNewMessages(infoMessage2)); + AddStep("message from admin", () => testChannel.AddNewMessages(standardMessage2)); - AddAssert("message order is correct", () => testChannel.Messages.Count == 3 - && testChannel.Messages[0] == standardMessage - && testChannel.Messages[1] == infoMessage1 - && testChannel.Messages[2] == infoMessage2); + AddAssert("count is correct", () => testChannel.Messages.Count, () => Is.EqualTo(4)); + + AddAssert("message order is correct", () => testChannel.Messages, () => Is.EqualTo(new[] + { + standardMessage, + infoMessage1, + infoMessage2, + standardMessage2 + })); + + AddAssert("displayed order is correct", () => chatDisplay.DrawableChannel.ChildrenOfType().Select(c => c.Message), () => Is.EqualTo(new[] + { + standardMessage, + infoMessage1, + infoMessage2, + standardMessage2 + })); + + AddStep("reinit drawable channel", reinitialiseDrawableDisplay); + + AddAssert("displayed order is still correct", () => chatDisplay.DrawableChannel.ChildrenOfType().Select(c => c.Message), () => Is.EqualTo(new[] + { + standardMessage, + infoMessage1, + infoMessage2, + standardMessage2 + })); } [Test] @@ -314,6 +368,13 @@ namespace osu.Game.Tests.Visual.Online checkScrolledToBottom(); } + [Test] + public void TestTextBoxSync() + { + AddStep("type 'hello' to text box 1", () => chatWithTextBox.ChildrenOfType().Single().Text = "hello"); + AddAssert("text box 2 contains 'hello'", () => chatWithTextBox2.ChildrenOfType().Single().Text == "hello"); + } + private void fillChat(int count = 10) { AddStep("fill chat", () => @@ -401,7 +462,7 @@ namespace osu.Game.Tests.Visual.Online private void checkNotScrolledToBottom() => AddUntilStep("not scrolled to bottom", () => !chatDisplay.ScrolledToBottom); - private class TestStandAloneChatDisplay : StandAloneChatDisplay + private partial class TestStandAloneChatDisplay : StandAloneChatDisplay { public TestStandAloneChatDisplay(bool textBox = false) : base(textBox) diff --git a/osu.Game.Tests/Visual/Online/TestSceneTotalCommentsCounter.cs b/osu.Game.Tests/Visual/Online/TestSceneTotalCommentsCounter.cs index d4355d2f11..8af87dd597 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneTotalCommentsCounter.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneTotalCommentsCounter.cs @@ -12,7 +12,7 @@ using osu.Game.Overlays; namespace osu.Game.Tests.Visual.Online { - public class TestSceneTotalCommentsCounter : OsuTestScene + public partial class TestSceneTotalCommentsCounter : OsuTestScene { [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue); diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserHistoryGraph.cs b/osu.Game.Tests/Visual/Online/TestSceneUserHistoryGraph.cs index 42a8462604..454242270d 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserHistoryGraph.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserHistoryGraph.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -12,7 +10,7 @@ using osu.Game.Overlays.Profile.Sections.Historical; namespace osu.Game.Tests.Visual.Online { - public class TestSceneUserHistoryGraph : OsuTestScene + public partial class TestSceneUserHistoryGraph : OsuTestScene { [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Pink); diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs b/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs index 2a70fd7df3..4c1df850b2 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs @@ -17,7 +17,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Online { [TestFixture] - public class TestSceneUserPanel : OsuTestScene + public partial class TestSceneUserPanel : OsuTestScene { private readonly Bindable activity = new Bindable(); private readonly Bindable status = new Bindable(); @@ -132,7 +132,7 @@ namespace osu.Game.Tests.Visual.Online private UserActivity soloGameStatusForRuleset(int rulesetId) => new UserActivity.InSoloGame(null, rulesetStore.GetRuleset(rulesetId)); - private class TestUserListPanel : UserListPanel + private partial class TestUserListPanel : UserListPanel { public TestUserListPanel(APIUser user) : base(user) diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs index 1abe06ed76..513c473830 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Linq; using NUnit.Framework; @@ -11,16 +9,17 @@ using osu.Framework.Testing; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays; using osu.Game.Overlays.Profile; +using osu.Game.Rulesets.Osu; using osu.Game.Users; namespace osu.Game.Tests.Visual.Online { - public class TestSceneUserProfileHeader : OsuTestScene + public partial class TestSceneUserProfileHeader : OsuTestScene { [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Green); - private ProfileHeader header; + private ProfileHeader header = null!; [SetUpSteps] public void SetUpSteps() @@ -31,36 +30,37 @@ namespace osu.Game.Tests.Visual.Online [Test] public void TestBasic() { - AddStep("Show example user", () => header.User.Value = TestSceneUserProfileOverlay.TEST_USER); + AddStep("Show example user", () => header.User.Value = new UserProfileData(TestSceneUserProfileOverlay.TEST_USER, new OsuRuleset().RulesetInfo)); } [Test] public void TestOnlineState() { - AddStep("Show online user", () => header.User.Value = new APIUser + AddStep("Show online user", () => header.User.Value = new UserProfileData(new APIUser { Id = 1001, Username = "IAmOnline", LastVisit = DateTimeOffset.Now, IsOnline = true, - }); + }, new OsuRuleset().RulesetInfo)); - AddStep("Show offline user", () => header.User.Value = new APIUser + AddStep("Show offline user", () => header.User.Value = new UserProfileData(new APIUser { Id = 1002, Username = "IAmOffline", LastVisit = DateTimeOffset.Now.AddDays(-10), IsOnline = false, - }); + }, new OsuRuleset().RulesetInfo)); } [Test] public void TestRankedState() { - AddStep("Show ranked user", () => header.User.Value = new APIUser + AddStep("Show ranked user", () => header.User.Value = new UserProfileData(new APIUser { Id = 2001, Username = "RankedUser", + Groups = new[] { new APIUserGroup { Colour = "#EB47D0", ShortName = "DEV", Name = "Developers" } }, Statistics = new UserStatistics { IsRanked = true, @@ -72,9 +72,9 @@ namespace osu.Game.Tests.Visual.Online Data = Enumerable.Range(2345, 45).Concat(Enumerable.Range(2109, 40)).ToArray() }, } - }); + }, new OsuRuleset().RulesetInfo)); - AddStep("Show unranked user", () => header.User.Value = new APIUser + AddStep("Show unranked user", () => header.User.Value = new UserProfileData(new APIUser { Id = 2002, Username = "UnrankedUser", @@ -88,7 +88,7 @@ namespace osu.Game.Tests.Visual.Online Data = Enumerable.Range(2345, 85).ToArray() }, } - }); + }, new OsuRuleset().RulesetInfo)); } } } diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs index 7064a08151..f7e88e4437 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs @@ -1,24 +1,82 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Linq; using NUnit.Framework; +using osu.Framework.Graphics.Containers; +using osu.Framework.Testing; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays; -using osu.Game.Overlays.Profile; using osu.Game.Users; namespace osu.Game.Tests.Visual.Online { [TestFixture] - public class TestSceneUserProfileOverlay : OsuTestScene + public partial class TestSceneUserProfileOverlay : OsuTestScene { - protected override bool UseOnlineAPI => true; + private DummyAPIAccess dummyAPI => (DummyAPIAccess)API; - private readonly TestUserProfileOverlay profile; + private UserProfileOverlay profile = null!; + + [SetUpSteps] + public void SetUp() + { + AddStep("create profile overlay", () => Child = profile = new UserProfileOverlay()); + } + + [Test] + public void TestBlank() + { + AddStep("show overlay", () => profile.Show()); + } + + [Test] + public void TestActualUser() + { + AddStep("set up request handling", () => + { + dummyAPI.HandleRequest = req => + { + if (req is GetUserRequest getUserRequest) + { + getUserRequest.TriggerSuccess(TEST_USER); + return true; + } + + return false; + }; + }); + AddStep("show user", () => profile.ShowUser(new APIUser { Id = 1 })); + AddToggleStep("toggle visibility", visible => profile.State.Value = visible ? Visibility.Visible : Visibility.Hidden); + AddStep("log out", () => dummyAPI.Logout()); + AddStep("log back in", () => dummyAPI.Login("username", "password")); + } + + [Test] + public void TestLoading() + { + GetUserRequest pendingRequest = null!; + + AddStep("set up request handling", () => + { + dummyAPI.HandleRequest = req => + { + if (req is GetUserRequest getUserRequest) + { + pendingRequest = getUserRequest; + return true; + } + + return false; + }; + }); + AddStep("show user", () => profile.ShowUser(new APIUser { Id = 1 })); + AddWaitStep("wait some", 3); + AddStep("complete request", () => pendingRequest.TriggerSuccess(TEST_USER)); + } public static readonly APIUser TEST_USER = new APIUser { @@ -28,7 +86,21 @@ namespace osu.Game.Tests.Visual.Online CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c1.jpg", JoinDate = DateTimeOffset.Now.AddDays(-1), LastVisit = DateTimeOffset.Now, - ProfileOrder = new[] { "me" }, + Groups = new[] + { + new APIUserGroup { Colour = "#EB47D0", ShortName = "DEV", Name = "Developers" }, + new APIUserGroup { Colour = "#A347EB", ShortName = "BN", Name = "Beatmap Nominators", Playmodes = new[] { "osu", "taiko" } } + }, + ProfileOrder = new[] + { + @"me", + @"recent_activity", + @"beatmaps", + @"historical", + @"kudosu", + @"top_ranks", + @"medals" + }, Statistics = new UserStatistics { IsRanked = true, @@ -65,61 +137,12 @@ namespace osu.Game.Tests.Visual.Online Title = "osu!volunteer", Colour = "ff0000", Achievements = Array.Empty(), + PlayMode = "osu", + Kudosu = new APIUser.KudosuCount + { + Available = 10, + Total = 50 + } }; - - public TestSceneUserProfileOverlay() - { - Add(profile = new TestUserProfileOverlay()); - } - - protected override void LoadComplete() - { - base.LoadComplete(); - - AddStep("Show offline dummy", () => profile.ShowUser(TEST_USER)); - - AddStep("Show null dummy", () => profile.ShowUser(new APIUser - { - Username = @"Null", - Id = 1, - })); - - AddStep("Show ppy", () => profile.ShowUser(new APIUser - { - Username = @"peppy", - Id = 2, - IsSupporter = true, - CountryCode = CountryCode.AU, - CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg" - })); - - AddStep("Show flyte", () => profile.ShowUser(new APIUser - { - Username = @"flyte", - Id = 3103765, - CountryCode = CountryCode.JP, - CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c6.jpg" - })); - - AddStep("Show bancho", () => profile.ShowUser(new APIUser - { - Username = @"BanchoBot", - Id = 3, - IsBot = true, - CountryCode = CountryCode.SH, - CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c4.jpg" - })); - - AddStep("Show ppy from username", () => profile.ShowUser(new APIUser { Username = @"peppy" })); - AddStep("Show flyte from username", () => profile.ShowUser(new APIUser { Username = @"flyte" })); - - AddStep("Hide", profile.Hide); - AddStep("Show without reload", profile.Show); - } - - private class TestUserProfileOverlay : UserProfileOverlay - { - public new ProfileHeader Header => base.Header; - } } } diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserProfilePreviousUsernames.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfilePreviousUsernames.cs index 4260fff02d..921738d331 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserProfilePreviousUsernames.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfilePreviousUsernames.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using NUnit.Framework; using osu.Framework.Graphics; @@ -12,9 +10,9 @@ using osu.Game.Overlays.Profile.Header.Components; namespace osu.Game.Tests.Visual.Online { [TestFixture] - public class TestSceneUserProfilePreviousUsernames : OsuTestScene + public partial class TestSceneUserProfilePreviousUsernames : OsuTestScene { - private PreviousUsernames container; + private PreviousUsernames container = null!; [SetUp] public void SetUp() => Schedule(() => @@ -50,7 +48,7 @@ namespace osu.Game.Tests.Visual.Online AddUntilStep("Is hidden", () => container.Alpha == 0); } - private static readonly APIUser[] users = + private static readonly APIUser?[] users = { new APIUser { Id = 1, PreviousUsernames = new[] { "username1" } }, new APIUser { Id = 2, PreviousUsernames = new[] { "longusername", "longerusername" } }, diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserProfileRecentSection.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfileRecentSection.cs index 7875a9dfbc..9d0ea80533 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserProfileRecentSection.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfileRecentSection.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Collections.Generic; using System.Linq; using NUnit.Framework; @@ -20,7 +18,7 @@ using osu.Game.Overlays.Profile.Sections.Recent; namespace osu.Game.Tests.Visual.Online { [TestFixture] - public class TestSceneUserProfileRecentSection : OsuTestScene + public partial class TestSceneUserProfileRecentSection : OsuTestScene { [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Green); diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserProfileScores.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfileScores.cs index 4bbb72c862..5249e8694d 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserProfileScores.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfileScores.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -18,7 +16,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Online { - public class TestSceneUserProfileScores : OsuTestScene + public partial class TestSceneUserProfileScores : OsuTestScene { public TestSceneUserProfileScores() { @@ -138,7 +136,7 @@ namespace osu.Game.Tests.Visual.Online }); } - private class ColourProvidedContainer : Container + private partial class ColourProvidedContainer : Container { [Cached] private readonly OverlayColourProvider colourProvider; diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserRanks.cs b/osu.Game.Tests/Visual/Online/TestSceneUserRanks.cs index d517aaa105..a3825f4694 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserRanks.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserRanks.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -12,12 +10,14 @@ using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays; +using osu.Game.Overlays.Profile; using osu.Game.Overlays.Profile.Sections; +using osu.Game.Rulesets.Osu; namespace osu.Game.Tests.Visual.Online { [TestFixture] - public class TestSceneUserRanks : OsuTestScene + public partial class TestSceneUserRanks : OsuTestScene { protected override bool UseOnlineAPI => true; @@ -46,7 +46,7 @@ namespace osu.Game.Tests.Visual.Online } }); - AddStep("Show cookiezi", () => ranks.User.Value = new APIUser { Id = 124493 }); + AddStep("Show cookiezi", () => ranks.User.Value = new UserProfileData(new APIUser { Id = 124493 }, new OsuRuleset().RulesetInfo)); } } } diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserRequest.cs b/osu.Game.Tests/Visual/Online/TestSceneUserRequest.cs index 32d427ba6d..1ffb438355 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserRequest.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserRequest.cs @@ -20,7 +20,7 @@ using osu.Game.Rulesets.Taiko; namespace osu.Game.Tests.Visual.Online { [TestFixture] - public class TestSceneUserRequest : OsuTestScene + public partial class TestSceneUserRequest : OsuTestScene { [Resolved] private IAPIProvider api { get; set; } @@ -71,7 +71,7 @@ namespace osu.Game.Tests.Visual.Online api.Queue(request); } - private class UserTestContainer : FillFlowContainer + private partial class UserTestContainer : FillFlowContainer { public readonly Bindable User = new Bindable(); diff --git a/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs b/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs index fdc15af73d..ce1a9ac6a7 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs @@ -15,7 +15,7 @@ using osu.Framework.Graphics.Containers; namespace osu.Game.Tests.Visual.Online { [TestFixture] - public class TestSceneVotePill : OsuTestScene + public partial class TestSceneVotePill : OsuTestScene { [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue); @@ -98,7 +98,7 @@ namespace osu.Game.Tests.Visual.Online }; } - private class TestPill : VotePill + private partial class TestPill : VotePill { public new Box Background => base.Background; diff --git a/osu.Game.Tests/Visual/Online/TestSceneWikiHeader.cs b/osu.Game.Tests/Visual/Online/TestSceneWikiHeader.cs index 99e301f3ba..4e71c5977e 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneWikiHeader.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneWikiHeader.cs @@ -16,7 +16,7 @@ using osu.Game.Overlays.Wiki; namespace osu.Game.Tests.Visual.Online { - public class TestSceneWikiHeader : OsuTestScene + public partial class TestSceneWikiHeader : OsuTestScene { [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Orange); @@ -97,7 +97,7 @@ namespace osu.Game.Tests.Visual.Online }; } - private class TestHeader : WikiHeader + private partial class TestHeader : WikiHeader { public IReadOnlyList TabControlItems => TabControl.Items; } diff --git a/osu.Game.Tests/Visual/Online/TestSceneWikiMainPage.cs b/osu.Game.Tests/Visual/Online/TestSceneWikiMainPage.cs index 03b94aded7..8876f0fd3b 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneWikiMainPage.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneWikiMainPage.cs @@ -12,7 +12,7 @@ using osu.Game.Overlays.Wiki; namespace osu.Game.Tests.Visual.Online { - public class TestSceneWikiMainPage : OsuTestScene + public partial class TestSceneWikiMainPage : OsuTestScene { [Cached] private readonly OverlayColourProvider overlayColour = new OverlayColourProvider(OverlayColourScheme.Orange); diff --git a/osu.Game.Tests/Visual/Online/TestSceneWikiMarkdownContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneWikiMarkdownContainer.cs index 863b352618..b353123649 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneWikiMarkdownContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneWikiMarkdownContainer.cs @@ -16,13 +16,17 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Testing; using osu.Framework.Utils; using osu.Game.Graphics.Containers.Markdown; +using osu.Game.Graphics.Containers.Markdown.Footnotes; using osu.Game.Overlays; using osu.Game.Overlays.Wiki.Markdown; +using osu.Game.Users.Drawables; +using osuTK.Input; namespace osu.Game.Tests.Visual.Online { - public class TestSceneWikiMarkdownContainer : OsuTestScene + public partial class TestSceneWikiMarkdownContainer : OsuManualInputManagerTestScene { + private OverlayScrollContainer scrollContainer; private TestMarkdownContainer markdownContainer; [Cached] @@ -38,15 +42,25 @@ namespace osu.Game.Tests.Visual.Online Colour = overlayColour.Background5, RelativeSizeAxes = Axes.Both, }, - new BasicScrollContainer + scrollContainer = new OverlayScrollContainer { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding(20), - Child = markdownContainer = new TestMarkdownContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - } + } + }; + + scrollContainer.Child = new DependencyProvidingContainer + { + CachedDependencies = new (Type, object)[] + { + (typeof(OverlayScrollContainer), scrollContainer) + }, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Child = markdownContainer = new TestMarkdownContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, } }; }); @@ -197,9 +211,66 @@ Line after image"; markdownContainer.CurrentPath = @"https://dev.ppy.sh"; markdownContainer.Text = "::{flag=\"AU\"}:: ::{flag=\"ZZ\"}::"; }); + AddAssert("Two flags visible", () => markdownContainer.ChildrenOfType().Count(), () => Is.EqualTo(2)); } - private class TestMarkdownContainer : WikiMarkdownContainer + [Test] + public void TestHeadingWithIdAttribute() + { + AddStep("Add heading with ID", () => + { + markdownContainer.Text = "# This is a heading with an ID {#this-is-the-id}"; + }); + AddAssert("ID not visible", () => markdownContainer.ChildrenOfType().All(spriteText => spriteText.Text != "{#this-is-the-id}")); + } + + [Test] + public void TestFootnotes() + { + AddStep("set content", () => markdownContainer.Text = @"This text has a footnote[^test]. + +Here's some more text[^test2] with another footnote! + +# Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam efficitur laoreet posuere. Ut accumsan tortor in ipsum tincidunt ultrices. Suspendisse a malesuada tellus. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Fusce a sagittis nibh. In et velit sit amet mauris aliquet consectetur quis vehicula lorem. Etiam sit amet tellus ac velit ornare maximus. Donec quis metus eget libero ullamcorper imperdiet id vitae arcu. Vivamus iaculis rhoncus purus malesuada mollis. Vestibulum dictum at nisi sed tincidunt. Suspendisse finibus, ipsum ut dapibus commodo, leo eros porttitor sapien, non scelerisque nisi ligula sed ex. Pellentesque magna orci, hendrerit eu iaculis sit amet, ullamcorper in urna. Vivamus dictum mauris orci, nec facilisis dolor fringilla eu. Sed at porttitor nisi, at venenatis urna. Ut at orci vitae libero semper ullamcorper eu ut risus. Mauris hendrerit varius enim, ut varius nisi feugiat mattis. + +## In at eros urna. Sed ipsum lorem, tempor sit amet purus in, vehicula pellentesque leo. Fusce volutpat pellentesque velit sit amet porttitor. Nulla eget erat ex. Praesent eu lacinia est, quis vehicula lacus. Donec consequat ultrices neque, at finibus quam efficitur vel. Vestibulum molestie nisl sit amet metus semper, at vestibulum massa rhoncus. Quisque imperdiet suscipit augue, et dignissim odio eleifend ut. + +Aliquam sed vestibulum mauris, ut lobortis elit. Sed quis lacinia erat. Nam ultricies, risus non pellentesque sollicitudin, mauris dolor tincidunt neque, ac porta ipsum dui quis libero. Integer eget velit neque. Vestibulum venenatis mauris vitae rutrum vestibulum. Maecenas suscipit eu purus eu tempus. Nam dui nisl, bibendum condimentum mollis et, gravida vel dui. Sed et eros rutrum, facilisis sapien eu, mattis ligula. Fusce finibus pulvinar dolor quis consequat. + +Donec ipsum felis, feugiat vel fermentum at, commodo eu sapien. Suspendisse nec enim vitae felis laoreet laoreet. Phasellus purus quam, fermentum a pharetra vel, tempor et urna. Integer vitae quam diam. Aliquam tincidunt tortor a iaculis convallis. Suspendisse potenti. Cras quis risus quam. Nullam tincidunt in lorem posuere sagittis. + +Phasellus eu nunc nec ligula semper fringilla. Aliquam magna neque, placerat sed urna tristique, laoreet pharetra nulla. Vivamus maximus turpis purus, eu viverra dolor sodales porttitor. Praesent bibendum sapien purus, sed ultricies dolor iaculis sed. Fusce congue hendrerit malesuada. Nulla nulla est, auctor ac fringilla sed, ornare a lorem. Donec quis velit imperdiet, imperdiet sem non, pellentesque sapien. Maecenas in orci id ipsum placerat facilisis non sed nisi. Duis dictum lorem sodales odio dictum eleifend. Vestibulum bibendum euismod quam, eget pharetra orci facilisis sed. Vivamus at diam non ipsum consequat tristique. Pellentesque gravida dignissim pellentesque. Donec ullamcorper lacinia orci, id consequat purus faucibus quis. Phasellus metus nunc, iaculis a interdum vel, congue sed erat. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Etiam eros libero, hendrerit luctus nulla vitae, luctus maximus nunc. + +[^test]: This is a **footnote**. +[^test2]: This is another footnote [with a link](https://google.com/)!"); + AddStep("shrink scroll height", () => scrollContainer.Height = 0.5f); + + AddStep("press second footnote link", () => + { + InputManager.MoveMouseTo(markdownContainer.ChildrenOfType().ElementAt(1)); + InputManager.Click(MouseButton.Left); + }); + AddUntilStep("second footnote scrolled into view", () => + { + var footnote = markdownContainer.ChildrenOfType().ElementAt(1); + return scrollContainer.ScreenSpaceDrawQuad.Contains(footnote.ScreenSpaceDrawQuad.TopLeft) + && scrollContainer.ScreenSpaceDrawQuad.Contains(footnote.ScreenSpaceDrawQuad.BottomRight); + }); + + AddStep("press first footnote backlink", () => + { + InputManager.MoveMouseTo(markdownContainer.ChildrenOfType().First()); + InputManager.Click(MouseButton.Left); + }); + AddUntilStep("first footnote link scrolled into view", () => + { + var footnote = markdownContainer.ChildrenOfType().First(); + return scrollContainer.ScreenSpaceDrawQuad.Contains(footnote.ScreenSpaceDrawQuad.TopLeft) + && scrollContainer.ScreenSpaceDrawQuad.Contains(footnote.ScreenSpaceDrawQuad.BottomRight); + }); + } + + private partial class TestMarkdownContainer : WikiMarkdownContainer { public LinkInline Link; @@ -208,7 +279,7 @@ Line after image"; UrlAdded = link => Link = link, }; - private class TestMarkdownTextFlowContainer : OsuMarkdownTextFlowContainer + private partial class TestMarkdownTextFlowContainer : OsuMarkdownTextFlowContainer { public Action UrlAdded; diff --git a/osu.Game.Tests/Visual/Online/TestSceneWikiOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneWikiOverlay.cs index 27cd74bb1f..b0e4303ca4 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneWikiOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneWikiOverlay.cs @@ -4,8 +4,11 @@ #nullable disable using System; +using System.Linq; using System.Net; using NUnit.Framework; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Testing; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; @@ -13,7 +16,7 @@ using osu.Game.Overlays; namespace osu.Game.Tests.Visual.Online { - public class TestSceneWikiOverlay : OsuTestScene + public partial class TestSceneWikiOverlay : OsuTestScene { private DummyAPIAccess dummyAPI => (DummyAPIAccess)API; @@ -29,6 +32,15 @@ namespace osu.Game.Tests.Visual.Online AddStep("Show main page", () => wiki.Show()); } + [Test] + public void TestCancellationDoesntShowError() + { + AddStep("Show main page", () => wiki.Show()); + AddStep("Show another page", () => wiki.ShowPage("Article_styling_criteria/Formatting")); + + AddUntilStep("Current path is not error", () => wiki.CurrentPath != "error"); + } + [Test] public void TestArticlePage() { @@ -56,7 +68,9 @@ namespace osu.Game.Tests.Visual.Online public void TestErrorPage() { setUpWikiResponse(responseArticlePage); - AddStep("Show Error Page", () => wiki.ShowPage("Error")); + AddStep("Show nonexistent page", () => wiki.ShowPage("This_page_will_error_out")); + AddUntilStep("Wait for error page", () => wiki.CurrentPath == "error"); + AddUntilStep("Error message correct", () => wiki.ChildrenOfType().Any(text => text.Text == "\"This_page_will_error_out\".")); } private void setUpWikiResponse(APIWikiPage r, string redirectionPath = null) diff --git a/osu.Game.Tests/Visual/Online/TestSceneWikiSidebar.cs b/osu.Game.Tests/Visual/Online/TestSceneWikiSidebar.cs index 33e3ee7023..89944b3a8a 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneWikiSidebar.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneWikiSidebar.cs @@ -14,7 +14,7 @@ using osu.Game.Overlays.Wiki; namespace osu.Game.Tests.Visual.Online { - public class TestSceneWikiSidebar : OsuTestScene + public partial class TestSceneWikiSidebar : OsuTestScene { [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Orange); diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsLoungeSubScreen.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsLoungeSubScreen.cs index 8ca37a241b..0c536cb1d4 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsLoungeSubScreen.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsLoungeSubScreen.cs @@ -17,7 +17,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Playlists { - public class TestScenePlaylistsLoungeSubScreen : OnlinePlayTestScene + public partial class TestScenePlaylistsLoungeSubScreen : OnlinePlayTestScene { protected new TestRoomManager RoomManager => (TestRoomManager)base.RoomManager; @@ -95,7 +95,7 @@ namespace osu.Game.Tests.Visual.Playlists loungeScreen.ChildrenOfType().First().ScreenSpaceDrawQuad .Contains(room.ScreenSpaceDrawQuad.Centre); - private class TestLoungeSubScreen : PlaylistsLoungeSubScreen + private partial class TestLoungeSubScreen : PlaylistsLoungeSubScreen { public new Bindable SelectedRoom => base.SelectedRoom; } diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs index c71bdb3a06..1053789b27 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Online.Rooms; using osu.Game.Screens.OnlinePlay; using osu.Game.Screens.OnlinePlay.Playlists; @@ -17,7 +18,7 @@ using osu.Game.Tests.Visual.OnlinePlay; namespace osu.Game.Tests.Visual.Playlists { - public class TestScenePlaylistsMatchSettingsOverlay : OnlinePlayTestScene + public partial class TestScenePlaylistsMatchSettingsOverlay : OnlinePlayTestScene { protected new TestRoomManager RoomManager => (TestRoomManager)base.RoomManager; @@ -146,9 +147,9 @@ namespace osu.Game.Tests.Visual.Playlists AddUntilStep("error not displayed", () => !settings.ErrorText.IsPresent); } - private class TestRoomSettings : PlaylistsRoomSettingsOverlay + private partial class TestRoomSettings : PlaylistsRoomSettingsOverlay { - public TriangleButton ApplyButton => ((MatchSettings)Settings).ApplyButton; + public RoundedButton ApplyButton => ((MatchSettings)Settings).ApplyButton; public OsuTextBox NameField => ((MatchSettings)Settings).NameField; public OsuDropdown DurationField => ((MatchSettings)Settings).DurationField; diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsParticipantsList.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsParticipantsList.cs index 9a0dda056a..c4a1200cb1 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsParticipantsList.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsParticipantsList.cs @@ -13,7 +13,7 @@ using osu.Game.Users; namespace osu.Game.Tests.Visual.Playlists { - public class TestScenePlaylistsParticipantsList : OnlinePlayTestScene + public partial class TestScenePlaylistsParticipantsList : OnlinePlayTestScene { public override void SetUpSteps() { diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsResultsScreen.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsResultsScreen.cs index 26fa740159..cb422d8c06 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsResultsScreen.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsResultsScreen.cs @@ -28,7 +28,7 @@ using osu.Game.Tests.Resources; namespace osu.Game.Tests.Visual.Playlists { - public class TestScenePlaylistsResultsScreen : ScreenTestScene + public partial class TestScenePlaylistsResultsScreen : ScreenTestScene { private const int scores_per_result = 10; private const int real_user_position = 200; @@ -365,7 +365,7 @@ namespace osu.Game.Tests.Visual.Playlists }; } - private class TestResultsScreen : PlaylistsResultsScreen + private partial class TestResultsScreen : PlaylistsResultsScreen { public new LoadingSpinner LeftSpinner => base.LeftSpinner; public new LoadingSpinner CentreSpinner => base.CentreSpinner; diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomCreation.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomCreation.cs index b304b34275..bdae91de59 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomCreation.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomCreation.cs @@ -33,7 +33,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Playlists { - public class TestScenePlaylistsRoomCreation : OnlinePlayTestScene + public partial class TestScenePlaylistsRoomCreation : OnlinePlayTestScene { private BeatmapManager manager; @@ -219,7 +219,7 @@ namespace osu.Game.Tests.Visual.Playlists importedBeatmap = manager.Import(beatmap.BeatmapInfo.BeatmapSet)?.Value.Detach(); }); - private class TestPlaylistsRoomSubScreen : PlaylistsRoomSubScreen + private partial class TestPlaylistsRoomSubScreen : PlaylistsRoomSubScreen { public new Bindable SelectedItem => base.SelectedItem; diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsScreen.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsScreen.cs index af3d2d9d9a..71e284ecfe 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsScreen.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsScreen.cs @@ -8,7 +8,7 @@ using NUnit.Framework; namespace osu.Game.Tests.Visual.Playlists { [TestFixture] - public class TestScenePlaylistsScreen : ScreenTestScene + public partial class TestScenePlaylistsScreen : ScreenTestScene { protected override bool UseOnlineAPI => true; diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneAccuracyCircle.cs b/osu.Game.Tests/Visual/Ranking/TestSceneAccuracyCircle.cs index 3e2043cea5..0145a1dfef 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneAccuracyCircle.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneAccuracyCircle.cs @@ -22,7 +22,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Ranking { - public class TestSceneAccuracyCircle : OsuTestScene + public partial class TestSceneAccuracyCircle : OsuTestScene { [TestCase(0.2, ScoreRank.D)] [TestCase(0.5, ScoreRank.D)] diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneContractedPanelMiddleContent.cs b/osu.Game.Tests/Visual/Ranking/TestSceneContractedPanelMiddleContent.cs index 83242fe363..e92e74598d 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneContractedPanelMiddleContent.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneContractedPanelMiddleContent.cs @@ -21,7 +21,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Ranking { - public class TestSceneContractedPanelMiddleContent : OsuTestScene + public partial class TestSceneContractedPanelMiddleContent : OsuTestScene { [Test] public void TestShowPanel() @@ -45,7 +45,7 @@ namespace osu.Game.Tests.Visual.Ranking Child = new ContractedPanelMiddleContentContainer(workingBeatmap, score); } - private class ContractedPanelMiddleContentContainer : Container + private partial class ContractedPanelMiddleContentContainer : Container { [Cached] private Bindable workingBeatmap { get; set; } diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneExpandedPanelMiddleContent.cs b/osu.Game.Tests/Visual/Ranking/TestSceneExpandedPanelMiddleContent.cs index 62e9adcf25..bd7a11b4bb 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneExpandedPanelMiddleContent.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneExpandedPanelMiddleContent.cs @@ -27,7 +27,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Ranking { - public class TestSceneExpandedPanelMiddleContent : OsuTestScene + public partial class TestSceneExpandedPanelMiddleContent : OsuTestScene { [Resolved] private RulesetStore rulesetStore { get; set; } @@ -105,7 +105,7 @@ namespace osu.Game.Tests.Visual.Ranking private bool containsAny(string text, params string[] stringsToMatch) => stringsToMatch.Any(text.Contains); - private class ExpandedPanelMiddleContentContainer : Container + private partial class ExpandedPanelMiddleContentContainer : Container { public ExpandedPanelMiddleContentContainer(ScoreInfo score) { diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneExpandedPanelTopContent.cs b/osu.Game.Tests/Visual/Ranking/TestSceneExpandedPanelTopContent.cs index 94f6fa8839..be7be6d4f1 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneExpandedPanelTopContent.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneExpandedPanelTopContent.cs @@ -13,7 +13,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Ranking { - public class TestSceneExpandedPanelTopContent : OsuTestScene + public partial class TestSceneExpandedPanelTopContent : OsuTestScene { public TestSceneExpandedPanelTopContent() { diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneHitEventTimingDistributionGraph.cs b/osu.Game.Tests/Visual/Ranking/TestSceneHitEventTimingDistributionGraph.cs index e014d79402..a40cb41e2c 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneHitEventTimingDistributionGraph.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneHitEventTimingDistributionGraph.cs @@ -17,7 +17,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Ranking { - public class TestSceneHitEventTimingDistributionGraph : OsuTestScene + public partial class TestSceneHitEventTimingDistributionGraph : OsuTestScene { private HitEventTimingDistributionGraph graph = null!; private readonly BindableFloat width = new BindableFloat(600); diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneOverallRanking.cs b/osu.Game.Tests/Visual/Ranking/TestSceneOverallRanking.cs new file mode 100644 index 0000000000..355a572f95 --- /dev/null +++ b/osu.Game.Tests/Visual/Ranking/TestSceneOverallRanking.cs @@ -0,0 +1,117 @@ +// Copyright (c) ppy Pty Ltd . 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.Game.Online.Solo; +using osu.Game.Scoring; +using osu.Game.Screens.Ranking.Statistics.User; +using osu.Game.Users; + +namespace osu.Game.Tests.Visual.Ranking +{ + public partial class TestSceneOverallRanking : OsuTestScene + { + private OverallRanking overallRanking = null!; + + [Test] + public void TestUpdatePending() + { + createDisplay(); + } + + [Test] + public void TestAllIncreased() + { + createDisplay(); + displayUpdate( + new UserStatistics + { + GlobalRank = 12_345, + Accuracy = 98.99, + MaxCombo = 2_322, + RankedScore = 23_123_543_456, + TotalScore = 123_123_543_456, + PP = 5_072 + }, + new UserStatistics + { + GlobalRank = 1_234, + Accuracy = 99.07, + MaxCombo = 2_352, + RankedScore = 23_124_231_435, + TotalScore = 123_124_231_435, + PP = 5_434 + }); + } + + [Test] + public void TestAllDecreased() + { + createDisplay(); + displayUpdate( + new UserStatistics + { + GlobalRank = 1_234, + Accuracy = 99.07, + MaxCombo = 2_352, + RankedScore = 23_124_231_435, + TotalScore = 123_124_231_435, + PP = 5_434 + }, + new UserStatistics + { + GlobalRank = 12_345, + Accuracy = 98.99, + MaxCombo = 2_322, + RankedScore = 23_123_543_456, + TotalScore = 123_123_543_456, + PP = 5_072 + }); + } + + [Test] + public void TestNoChanges() + { + var statistics = new UserStatistics + { + GlobalRank = 12_345, + Accuracy = 98.99, + MaxCombo = 2_322, + RankedScore = 23_123_543_456, + TotalScore = 123_123_543_456, + PP = 5_072 + }; + + createDisplay(); + displayUpdate(statistics, statistics); + } + + [Test] + public void TestNotRanked() + { + var statistics = new UserStatistics + { + GlobalRank = null, + Accuracy = 98.99, + MaxCombo = 2_322, + RankedScore = 23_123_543_456, + TotalScore = 123_123_543_456, + PP = null + }; + + createDisplay(); + displayUpdate(statistics, statistics); + } + + private void createDisplay() => AddStep("create display", () => Child = overallRanking = new OverallRanking + { + Width = 400, + Anchor = Anchor.Centre, + Origin = Anchor.Centre + }); + + private void displayUpdate(UserStatistics before, UserStatistics after) => + AddStep("display update", () => overallRanking.StatisticsUpdate.Value = new SoloStatisticsUpdate(new ScoreInfo(), before, after)); + } +} diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneResultsScreen.cs b/osu.Game.Tests/Visual/Ranking/TestSceneResultsScreen.cs index 89d6206fd7..42068ff117 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneResultsScreen.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneResultsScreen.cs @@ -35,7 +35,7 @@ using Realms; namespace osu.Game.Tests.Visual.Ranking { [TestFixture] - public class TestSceneResultsScreen : OsuManualInputManagerTestScene + public partial class TestSceneResultsScreen : OsuManualInputManagerTestScene { [Resolved] private BeatmapManager beatmaps { get; set; } @@ -309,7 +309,7 @@ namespace osu.Game.Tests.Visual.Ranking private UnrankedSoloResultsScreen createUnrankedSoloResultsScreen() => new UnrankedSoloResultsScreen(TestResources.CreateTestScoreInfo()); - private class TestResultsContainer : Container + private partial class TestResultsContainer : Container { [Cached(typeof(Player))] private readonly Player player = new TestPlayer(); @@ -328,7 +328,7 @@ namespace osu.Game.Tests.Visual.Ranking } } - private class TestResultsScreen : ResultsScreen + private partial class TestResultsScreen : ResultsScreen { public HotkeyRetryOverlay RetryOverlay; @@ -362,7 +362,7 @@ namespace osu.Game.Tests.Visual.Ranking } } - private class DelayedFetchResultsScreen : TestResultsScreen + private partial class DelayedFetchResultsScreen : TestResultsScreen { private readonly Task fetchWaitTask; @@ -398,7 +398,7 @@ namespace osu.Game.Tests.Visual.Ranking } } - private class UnrankedSoloResultsScreen : SoloResultsScreen + private partial class UnrankedSoloResultsScreen : SoloResultsScreen { public HotkeyRetryOverlay RetryOverlay; diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneScorePanel.cs b/osu.Game.Tests/Visual/Ranking/TestSceneScorePanel.cs index 77fcd04fbd..b87e5adfb1 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneScorePanel.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneScorePanel.cs @@ -12,7 +12,7 @@ using osu.Game.Tests.Resources; namespace osu.Game.Tests.Visual.Ranking { - public class TestSceneScorePanel : OsuTestScene + public partial class TestSceneScorePanel : OsuTestScene { private ScorePanel panel; diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneScorePanelList.cs b/osu.Game.Tests/Visual/Ranking/TestSceneScorePanelList.cs index 871224f3e4..f08a6c9eca 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneScorePanelList.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneScorePanelList.cs @@ -19,7 +19,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Ranking { - public class TestSceneScorePanelList : OsuManualInputManagerTestScene + public partial class TestSceneScorePanelList : OsuManualInputManagerTestScene { private ScorePanelList list; diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneSimpleStatisticTable.cs b/osu.Game.Tests/Visual/Ranking/TestSceneSimpleStatisticTable.cs index 57a3907b6e..81d146614a 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneSimpleStatisticTable.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneSimpleStatisticTable.cs @@ -15,7 +15,7 @@ using osu.Game.Screens.Ranking.Statistics; namespace osu.Game.Tests.Visual.Ranking { - public class TestSceneSimpleStatisticTable : OsuTestScene + public partial class TestSceneSimpleStatisticTable : OsuTestScene { private Container container; diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneStatisticsPanel.cs b/osu.Game.Tests/Visual/Ranking/TestSceneStatisticsPanel.cs index 8214c52edc..fcd5f97fcc 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneStatisticsPanel.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneStatisticsPanel.cs @@ -27,7 +27,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Ranking { - public class TestSceneStatisticsPanel : OsuTestScene + public partial class TestSceneStatisticsPanel : OsuTestScene { [Test] public void TestScoreWithTimeStatistics() diff --git a/osu.Game.Tests/Visual/Settings/TestSceneDirectorySelector.cs b/osu.Game.Tests/Visual/Settings/TestSceneDirectorySelector.cs index 16110e5595..ce6973aacf 100644 --- a/osu.Game.Tests/Visual/Settings/TestSceneDirectorySelector.cs +++ b/osu.Game.Tests/Visual/Settings/TestSceneDirectorySelector.cs @@ -9,7 +9,7 @@ using osu.Game.Tests.Visual.UserInterface; namespace osu.Game.Tests.Visual.Settings { - public class TestSceneDirectorySelector : ThemeComparisonTestScene + public partial class TestSceneDirectorySelector : ThemeComparisonTestScene { protected override Drawable CreateContent() => new OsuDirectorySelector { diff --git a/osu.Game.Tests/Visual/Settings/TestSceneFileSelector.cs b/osu.Game.Tests/Visual/Settings/TestSceneFileSelector.cs index 97bf0d212a..f61e3ca557 100644 --- a/osu.Game.Tests/Visual/Settings/TestSceneFileSelector.cs +++ b/osu.Game.Tests/Visual/Settings/TestSceneFileSelector.cs @@ -13,7 +13,7 @@ using osu.Game.Tests.Visual.UserInterface; namespace osu.Game.Tests.Visual.Settings { - public class TestSceneFileSelector : ThemeComparisonTestScene + public partial class TestSceneFileSelector : ThemeComparisonTestScene { [Resolved] private OsuColour colours { get; set; } diff --git a/osu.Game.Tests/Visual/Settings/TestSceneKeyBindingPanel.cs b/osu.Game.Tests/Visual/Settings/TestSceneKeyBindingPanel.cs index bd54591b9b..da48086717 100644 --- a/osu.Game.Tests/Visual/Settings/TestSceneKeyBindingPanel.cs +++ b/osu.Game.Tests/Visual/Settings/TestSceneKeyBindingPanel.cs @@ -17,7 +17,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Settings { [TestFixture] - public class TestSceneKeyBindingPanel : OsuManualInputManagerTestScene + public partial class TestSceneKeyBindingPanel : OsuManualInputManagerTestScene { private readonly KeyBindingPanel panel; diff --git a/osu.Game.Tests/Visual/Settings/TestSceneLatencyCertifierScreen.cs b/osu.Game.Tests/Visual/Settings/TestSceneLatencyCertifierScreen.cs index caffc54d47..84c153c15b 100644 --- a/osu.Game.Tests/Visual/Settings/TestSceneLatencyCertifierScreen.cs +++ b/osu.Game.Tests/Visual/Settings/TestSceneLatencyCertifierScreen.cs @@ -10,7 +10,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Settings { - public class TestSceneLatencyCertifierScreen : ScreenTestScene + public partial class TestSceneLatencyCertifierScreen : ScreenTestScene { private LatencyCertifierScreen latencyCertifier = null!; diff --git a/osu.Game.Tests/Visual/Settings/TestSceneMigrationScreens.cs b/osu.Game.Tests/Visual/Settings/TestSceneMigrationScreens.cs index e32757c6f6..91320fdb1c 100644 --- a/osu.Game.Tests/Visual/Settings/TestSceneMigrationScreens.cs +++ b/osu.Game.Tests/Visual/Settings/TestSceneMigrationScreens.cs @@ -14,7 +14,7 @@ using osu.Game.Overlays.Settings.Sections.Maintenance; namespace osu.Game.Tests.Visual.Settings { - public class TestSceneMigrationScreens : ScreenTestScene + public partial class TestSceneMigrationScreens : ScreenTestScene { [Cached(typeof(INotificationOverlay))] private readonly NotificationOverlay notifications; @@ -43,7 +43,7 @@ namespace osu.Game.Tests.Visual.Settings AddStep("Push screen", () => Stack.Push(new TestMigrationSelectScreen(false))); } - private class TestMigrationSelectScreen : MigrationSelectScreen + private partial class TestMigrationSelectScreen : MigrationSelectScreen { private readonly bool deleteSuccess; @@ -54,7 +54,7 @@ namespace osu.Game.Tests.Visual.Settings protected override void BeginMigration(DirectoryInfo target) => this.Push(new TestMigrationRunScreen(deleteSuccess)); - private class TestMigrationRunScreen : MigrationRunScreen + private partial class TestMigrationRunScreen : MigrationRunScreen { private readonly bool success; diff --git a/osu.Game.Tests/Visual/Settings/TestSceneRestoreDefaultValueButton.cs b/osu.Game.Tests/Visual/Settings/TestSceneRestoreDefaultValueButton.cs index 289969af3e..6e52881f5e 100644 --- a/osu.Game.Tests/Visual/Settings/TestSceneRestoreDefaultValueButton.cs +++ b/osu.Game.Tests/Visual/Settings/TestSceneRestoreDefaultValueButton.cs @@ -15,7 +15,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Settings { - public class TestSceneRestoreDefaultValueButton : OsuTestScene + public partial class TestSceneRestoreDefaultValueButton : OsuTestScene { [Resolved] private OsuColour colours { get; set; } diff --git a/osu.Game.Tests/Visual/Settings/TestSceneSettingsItem.cs b/osu.Game.Tests/Visual/Settings/TestSceneSettingsItem.cs index 6ff53663ba..384508f375 100644 --- a/osu.Game.Tests/Visual/Settings/TestSceneSettingsItem.cs +++ b/osu.Game.Tests/Visual/Settings/TestSceneSettingsItem.cs @@ -17,7 +17,7 @@ using osu.Game.Overlays; namespace osu.Game.Tests.Visual.Settings { [TestFixture] - public class TestSceneSettingsItem : OsuTestScene + public partial class TestSceneSettingsItem : OsuTestScene { [Test] public void TestRestoreDefaultValueButtonVisibility() diff --git a/osu.Game.Tests/Visual/Settings/TestSceneSettingsNumberBox.cs b/osu.Game.Tests/Visual/Settings/TestSceneSettingsNumberBox.cs index 53e1f0e0bf..fc261611db 100644 --- a/osu.Game.Tests/Visual/Settings/TestSceneSettingsNumberBox.cs +++ b/osu.Game.Tests/Visual/Settings/TestSceneSettingsNumberBox.cs @@ -11,7 +11,7 @@ using osu.Game.Overlays.Settings; namespace osu.Game.Tests.Visual.Settings { - public class TestSceneSettingsNumberBox : OsuTestScene + public partial class TestSceneSettingsNumberBox : OsuTestScene { private SettingsNumberBox numberBox; private OsuTextBox textBox; diff --git a/osu.Game.Tests/Visual/Settings/TestSceneSettingsPanel.cs b/osu.Game.Tests/Visual/Settings/TestSceneSettingsPanel.cs index ad60c98e05..24c2eee783 100644 --- a/osu.Game.Tests/Visual/Settings/TestSceneSettingsPanel.cs +++ b/osu.Game.Tests/Visual/Settings/TestSceneSettingsPanel.cs @@ -18,7 +18,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Settings { [TestFixture] - public class TestSceneSettingsPanel : OsuManualInputManagerTestScene + public partial class TestSceneSettingsPanel : OsuManualInputManagerTestScene { private SettingsPanel settings; private DialogOverlay dialogOverlay; @@ -62,7 +62,6 @@ namespace osu.Game.Tests.Visual.Settings section.Children.Where(f => f.IsPresent) .OfType() .OfType() - .Where(f => !(f is IHasFilterableChildren)) .All(f => f.FilterTerms.Any(t => t.ToString().Contains("scaling"))) )); diff --git a/osu.Game.Tests/Visual/Settings/TestSceneSettingsSource.cs b/osu.Game.Tests/Visual/Settings/TestSceneSettingsSource.cs index 3cf6f7febf..30811bab32 100644 --- a/osu.Game.Tests/Visual/Settings/TestSceneSettingsSource.cs +++ b/osu.Game.Tests/Visual/Settings/TestSceneSettingsSource.cs @@ -15,7 +15,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Settings { [TestFixture] - public class TestSceneSettingsSource : OsuTestScene + public partial class TestSceneSettingsSource : OsuTestScene { public TestSceneSettingsSource() { diff --git a/osu.Game.Tests/Visual/Settings/TestSceneTabletSettings.cs b/osu.Game.Tests/Visual/Settings/TestSceneTabletSettings.cs index 5e75bd7bc1..5ca08e0bba 100644 --- a/osu.Game.Tests/Visual/Settings/TestSceneTabletSettings.cs +++ b/osu.Game.Tests/Visual/Settings/TestSceneTabletSettings.cs @@ -20,7 +20,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Settings { [TestFixture] - public class TestSceneTabletSettings : OsuTestScene + public partial class TestSceneTabletSettings : OsuTestScene { private TestTabletHandler tabletHandler; private TabletSettings settings; diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneAdvancedStats.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneAdvancedStats.cs index 1042341337..8650119dd4 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneAdvancedStats.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneAdvancedStats.cs @@ -22,7 +22,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.SongSelect { [System.ComponentModel.Description("Advanced beatmap statistics display")] - public class TestSceneAdvancedStats : OsuTestScene + public partial class TestSceneAdvancedStats : OsuTestScene { private TestAdvancedStats advancedStats; @@ -164,7 +164,7 @@ namespace osu.Game.Tests.Visual.SongSelect private bool barIsBlue(AdvancedStats.StatisticRow row) => row.ModBar.AccentColour == colours.BlueDark; private bool barIsRed(AdvancedStats.StatisticRow row) => row.ModBar.AccentColour == colours.Red; - private class TestAdvancedStats : AdvancedStats + private partial class TestAdvancedStats : AdvancedStats { public new StatisticRow FirstValue => base.FirstValue; public new StatisticRow HpDrain => base.HpDrain; diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs index d4d9f89c6a..ea9508ecff 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs @@ -16,7 +16,9 @@ using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Rulesets; +using osu.Game.Rulesets.Catch; using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Taiko; using osu.Game.Screens.Select; using osu.Game.Screens.Select.Carousel; using osu.Game.Screens.Select.Filter; @@ -26,7 +28,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.SongSelect { [TestFixture] - public class TestSceneBeatmapCarousel : OsuManualInputManagerTestScene + public partial class TestSceneBeatmapCarousel : OsuManualInputManagerTestScene { private TestBeatmapCarousel carousel; private RulesetStore rulesets; @@ -72,7 +74,7 @@ namespace osu.Game.Tests.Visual.SongSelect var visibleBeatmapPanels = carousel.Items.OfType().Where(p => p.IsPresent).ToArray(); return visibleBeatmapPanels.Length == 1 - && visibleBeatmapPanels.Count(p => ((CarouselBeatmap)p.Item).BeatmapInfo.Ruleset.OnlineID == 0) == 1; + && visibleBeatmapPanels.Count(p => ((CarouselBeatmap)p.Item)!.BeatmapInfo.Ruleset.OnlineID == 0) == 1; }); AddStep("filter to ruleset 1", () => carousel.Filter(new FilterCriteria @@ -86,8 +88,8 @@ namespace osu.Game.Tests.Visual.SongSelect var visibleBeatmapPanels = carousel.Items.OfType().Where(p => p.IsPresent).ToArray(); return visibleBeatmapPanels.Length == 2 - && visibleBeatmapPanels.Count(p => ((CarouselBeatmap)p.Item).BeatmapInfo.Ruleset.OnlineID == 0) == 1 - && visibleBeatmapPanels.Count(p => ((CarouselBeatmap)p.Item).BeatmapInfo.Ruleset.OnlineID == 1) == 1; + && visibleBeatmapPanels.Count(p => ((CarouselBeatmap)p.Item)!.BeatmapInfo.Ruleset.OnlineID == 0) == 1 + && visibleBeatmapPanels.Count(p => ((CarouselBeatmap)p.Item)!.BeatmapInfo.Ruleset.OnlineID == 1) == 1; }); AddStep("filter to ruleset 2", () => carousel.Filter(new FilterCriteria @@ -101,8 +103,8 @@ namespace osu.Game.Tests.Visual.SongSelect var visibleBeatmapPanels = carousel.Items.OfType().Where(p => p.IsPresent).ToArray(); return visibleBeatmapPanels.Length == 2 - && visibleBeatmapPanels.Count(p => ((CarouselBeatmap)p.Item).BeatmapInfo.Ruleset.OnlineID == 0) == 1 - && visibleBeatmapPanels.Count(p => ((CarouselBeatmap)p.Item).BeatmapInfo.Ruleset.OnlineID == 2) == 1; + && visibleBeatmapPanels.Count(p => ((CarouselBeatmap)p.Item!).BeatmapInfo.Ruleset.OnlineID == 0) == 1 + && visibleBeatmapPanels.Count(p => ((CarouselBeatmap)p.Item!).BeatmapInfo.Ruleset.OnlineID == 2) == 1; }); } @@ -926,10 +928,7 @@ namespace osu.Game.Tests.Visual.SongSelect // 10 sets that go osu! -> taiko -> catch -> osu! -> ... for (int i = 0; i < 10; i++) - { - var rulesetInfo = rulesets.AvailableRulesets.ElementAt(i % 3); - sets.Add(TestResources.CreateTestBeatmapSetInfo(5, new[] { rulesetInfo })); - } + sets.Add(TestResources.CreateTestBeatmapSetInfo(5, new[] { getRuleset(i) })); // Sort mode is important to keep the ruleset order loadBeatmaps(sets, () => new FilterCriteria { Sort = SortMode.Title }); @@ -937,13 +936,29 @@ namespace osu.Game.Tests.Visual.SongSelect for (int i = 1; i < 10; i++) { - var rulesetInfo = rulesets.AvailableRulesets.ElementAt(i % 3); + var rulesetInfo = getRuleset(i % 3); + AddStep($"Set ruleset to {rulesetInfo.ShortName}", () => { carousel.Filter(new FilterCriteria { Ruleset = rulesetInfo, Sort = SortMode.Title }, false); }); waitForSelection(i + 1, 1); } + + static RulesetInfo getRuleset(int index) + { + switch (index % 3) + { + default: + return new OsuRuleset().RulesetInfo; + + case 1: + return new TaikoRuleset().RulesetInfo; + + case 2: + return new CatchRuleset().RulesetInfo; + } + } } [Test] @@ -953,10 +968,7 @@ namespace osu.Game.Tests.Visual.SongSelect // 10 sets that go taiko, osu!, osu!, osu!, taiko, osu!, osu!, osu!, ... for (int i = 0; i < 10; i++) - { - var rulesetInfo = rulesets.AvailableRulesets.ElementAt(i % 4 == 0 ? 1 : 0); - sets.Add(TestResources.CreateTestBeatmapSetInfo(5, new[] { rulesetInfo })); - } + sets.Add(TestResources.CreateTestBeatmapSetInfo(5, new[] { getRuleset(i) })); // Sort mode is important to keep the ruleset order loadBeatmaps(sets, () => new FilterCriteria { Sort = SortMode.Title }); @@ -974,6 +986,18 @@ namespace osu.Game.Tests.Visual.SongSelect carousel.Filter(new FilterCriteria { Sort = SortMode.Title }, false); }); } + + static RulesetInfo getRuleset(int index) + { + switch (index % 4) + { + case 0: + return new TaikoRuleset().RulesetInfo; + + default: + return new OsuRuleset().RulesetInfo; + } + } } private void loadBeatmaps(List beatmapSets = null, Func initialCriteria = null, Action carouselAdjust = null, int? count = null, @@ -1069,7 +1093,7 @@ namespace osu.Game.Tests.Visual.SongSelect return Precision.AlmostEquals( carousel.ScreenSpaceDrawQuad.Centre, carousel.Items - .First(i => i.Item.State.Value == CarouselItemState.Selected) + .First(i => i.Item?.State.Value == CarouselItemState.Selected) .ScreenSpaceDrawQuad.Centre, 100); }); } @@ -1103,7 +1127,7 @@ namespace osu.Game.Tests.Visual.SongSelect if (currentlySelected == null) return true; - return currentlySelected.Item.Visible; + return currentlySelected.Item!.Visible; } private void checkInvisibleDifficultiesUnselectable() @@ -1112,7 +1136,7 @@ namespace osu.Game.Tests.Visual.SongSelect AddAssert("Selection is visible", selectedBeatmapVisible); } - private class TestBeatmapCarousel : BeatmapCarousel + private partial class TestBeatmapCarousel : BeatmapCarousel { public bool PendingFilterTask => PendingFilter != null; diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs index e33cfe280e..20cc1e544e 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs @@ -14,7 +14,7 @@ using osu.Game.Screens.Select; namespace osu.Game.Tests.Visual.SongSelect { [System.ComponentModel.Description("PlaySongSelect beatmap details")] - public class TestSceneBeatmapDetails : OsuTestScene + public partial class TestSceneBeatmapDetails : OsuTestScene { private BeatmapDetails details; diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs index a144111fd3..a470ed47d4 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs @@ -30,7 +30,7 @@ using osuTK; namespace osu.Game.Tests.Visual.SongSelect { [TestFixture] - public class TestSceneBeatmapInfoWedge : OsuTestScene + public partial class TestSceneBeatmapInfoWedge : OsuTestScene { private RulesetStore rulesets; private TestBeatmapInfoWedge infoWedge; @@ -267,7 +267,7 @@ namespace osu.Game.Tests.Visual.SongSelect }; } - private class TestBeatmapInfoWedge : BeatmapInfoWedge + private partial class TestBeatmapInfoWedge : BeatmapInfoWedge { public new Container DisplayedContent => base.DisplayedContent; diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs index 1839821bb5..ef0ad6c25c 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs @@ -27,7 +27,7 @@ using osuTK; namespace osu.Game.Tests.Visual.SongSelect { - public class TestSceneBeatmapLeaderboard : OsuTestScene + public partial class TestSceneBeatmapLeaderboard : OsuTestScene { private readonly FailableLeaderboard leaderboard; @@ -381,7 +381,7 @@ namespace osu.Game.Tests.Visual.SongSelect }; } - private class FailableLeaderboard : BeatmapLeaderboard + private partial class FailableLeaderboard : BeatmapLeaderboard { public new void SetErrorState(LeaderboardState state) => base.SetErrorState(state); public new void SetScores(IEnumerable? scores, ScoreInfo? userScore = null) => base.SetScores(scores, userScore); diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs index c42b51c1a6..c2537cff79 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs @@ -22,7 +22,7 @@ using osuTK; namespace osu.Game.Tests.Visual.SongSelect { - public class TestSceneBeatmapMetadataDisplay : OsuTestScene + public partial class TestSceneBeatmapMetadataDisplay : OsuTestScene { private BeatmapMetadataDisplay display; @@ -119,7 +119,7 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep("finish loading", () => display.Loading = false); } - private class TestBeatmapDifficultyCache : BeatmapDifficultyCache + private partial class TestBeatmapDifficultyCache : BeatmapDifficultyCache { private TaskCompletionSource calculationBlocker; diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapOptionsOverlay.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapOptionsOverlay.cs index 5ad82f1ffd..46a26d2e98 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapOptionsOverlay.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapOptionsOverlay.cs @@ -11,7 +11,7 @@ using osu.Game.Screens.Select.Options; namespace osu.Game.Tests.Visual.SongSelect { [Description("bottom beatmap details")] - public class TestSceneBeatmapOptionsOverlay : OsuTestScene + public partial class TestSceneBeatmapOptionsOverlay : OsuTestScene { public TestSceneBeatmapOptionsOverlay() { diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapRecommendations.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapRecommendations.cs index 504ded5406..a368e901f5 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapRecommendations.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapRecommendations.cs @@ -23,7 +23,7 @@ using osu.Game.Users; namespace osu.Game.Tests.Visual.SongSelect { - public class TestSceneBeatmapRecommendations : OsuGameTestScene + public partial class TestSceneBeatmapRecommendations : OsuGameTestScene { [Resolved] private IRulesetStore rulesetStore { get; set; } diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneDifficultyRangeFilterControl.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneDifficultyRangeFilterControl.cs deleted file mode 100644 index 7ae2c6e5e2..0000000000 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneDifficultyRangeFilterControl.cs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) ppy Pty Ltd . 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.Game.Screens.Select; -using osuTK; - -namespace osu.Game.Tests.Visual.SongSelect -{ - public class TestSceneDifficultyRangeFilterControl : OsuTestScene - { - [Test] - public void TestBasic() - { - AddStep("create control", () => - { - Child = new DifficultyRangeFilterControl - { - Width = 200, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Scale = new Vector2(3), - }; - }); - } - } -} diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneFilterControl.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneFilterControl.cs index dadcd43db5..64e2447cca 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneFilterControl.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneFilterControl.cs @@ -24,7 +24,7 @@ using Realms; namespace osu.Game.Tests.Visual.SongSelect { - public class TestSceneFilterControl : OsuManualInputManagerTestScene + public partial class TestSceneFilterControl : OsuManualInputManagerTestScene { protected override Container Content { get; } = new Container { RelativeSizeAxes = Axes.Both }; diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index b6b9e8926b..a61171abad 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -42,7 +42,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.SongSelect { [TestFixture] - public class TestScenePlaySongSelect : ScreenTestScene + public partial class TestScenePlaySongSelect : ScreenTestScene { private BeatmapManager manager = null!; private RulesetStore rulesets = null!; @@ -208,7 +208,7 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep("select next and enter", () => { InputManager.MoveMouseTo(songSelect!.Carousel.ChildrenOfType() - .First(b => !((CarouselBeatmap)b.Item).BeatmapInfo.Equals(songSelect!.Carousel.SelectedBeatmapInfo))); + .First(b => !((CarouselBeatmap)b.Item!).BeatmapInfo.Equals(songSelect!.Carousel.SelectedBeatmapInfo))); InputManager.Click(MouseButton.Left); @@ -235,7 +235,7 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep("select next and enter", () => { InputManager.MoveMouseTo(songSelect!.Carousel.ChildrenOfType() - .First(b => !((CarouselBeatmap)b.Item).BeatmapInfo.Equals(songSelect!.Carousel.SelectedBeatmapInfo))); + .First(b => !((CarouselBeatmap)b.Item!).BeatmapInfo.Equals(songSelect!.Carousel.SelectedBeatmapInfo))); InputManager.PressButton(MouseButton.Left); @@ -614,7 +614,7 @@ namespace osu.Game.Tests.Visual.SongSelect AddAssert("selected only shows expected ruleset (plus converts)", () => { - var selectedPanel = songSelect!.Carousel.ChildrenOfType().First(s => s.Item.State.Value == CarouselItemState.Selected); + var selectedPanel = songSelect!.Carousel.ChildrenOfType().First(s => s.Item!.State.Value == CarouselItemState.Selected); // special case for converts checked here. return selectedPanel.ChildrenOfType().All(i => @@ -1064,6 +1064,7 @@ namespace osu.Game.Tests.Visual.SongSelect AddAssert("options enabled", () => songSelect.ChildrenOfType().Single().Enabled.Value); AddStep("delete all beatmaps", () => manager.Delete()); + AddWaitStep("wait for debounce", 1); AddAssert("options disabled", () => !songSelect.ChildrenOfType().Single().Enabled.Value); } @@ -1141,7 +1142,7 @@ namespace osu.Game.Tests.Visual.SongSelect rulesets.Dispose(); } - private class TestSongSelect : PlaySongSelect + private partial class TestSongSelect : PlaySongSelect { public Action? StartRequested; diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectFooter.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectFooter.cs index 0a88abface..646dedc2be 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectFooter.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectFooter.cs @@ -13,7 +13,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.SongSelect { - public class TestSceneSongSelectFooter : OsuManualInputManagerTestScene + public partial class TestSceneSongSelectFooter : OsuManualInputManagerTestScene { private FooterButtonRandom randomButton; diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneTopLocalRank.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneTopLocalRank.cs index cced9b8b89..cf0de14541 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneTopLocalRank.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneTopLocalRank.cs @@ -20,7 +20,7 @@ using osuTK; namespace osu.Game.Tests.Visual.SongSelect { - public class TestSceneTopLocalRank : OsuTestScene + public partial class TestSceneTopLocalRank : OsuTestScene { private RulesetStore rulesets = null!; private BeatmapManager beatmapManager = null!; diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneUpdateBeatmapSetButton.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneUpdateBeatmapSetButton.cs index 96cfbe4dd1..11d55bc0bd 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneUpdateBeatmapSetButton.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneUpdateBeatmapSetButton.cs @@ -22,7 +22,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.SongSelect { [TestFixture] - public class TestSceneUpdateBeatmapSetButton : OsuManualInputManagerTestScene + public partial class TestSceneUpdateBeatmapSetButton : OsuManualInputManagerTestScene { private BeatmapCarousel carousel = null!; @@ -136,7 +136,7 @@ namespace osu.Game.Tests.Visual.SongSelect if (testRequest.Progress >= 0.5f) { - testRequest.TriggerFailure(new Exception()); + testRequest.TriggerFailure(new InvalidOperationException()); return true; } } diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScoreContainer.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScoreContainer.cs index 39fd9fda2b..0476198e41 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScoreContainer.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScoreContainer.cs @@ -19,7 +19,7 @@ using osu.Game.Users; namespace osu.Game.Tests.Visual.SongSelect { - public class TestSceneUserTopScoreContainer : OsuTestScene + public partial class TestSceneUserTopScoreContainer : OsuTestScene { [Cached(typeof(IDialogOverlay))] private readonly DialogOverlay dialogOverlay; diff --git a/osu.Game.Tests/Visual/TestMultiplayerComponents.cs b/osu.Game.Tests/Visual/TestMultiplayerComponents.cs index 0458f41358..1814fb70c8 100644 --- a/osu.Game.Tests/Visual/TestMultiplayerComponents.cs +++ b/osu.Game.Tests/Visual/TestMultiplayerComponents.cs @@ -30,7 +30,7 @@ namespace osu.Game.Tests.Visual /// ///

///
- public class TestMultiplayerComponents : OsuScreen + public partial class TestMultiplayerComponents : OsuScreen { public Screens.OnlinePlay.Multiplayer.Multiplayer MultiplayerScreen => multiplayerScreen; @@ -91,7 +91,7 @@ namespace osu.Game.Tests.Visual return true; } - private class TestMultiplayer : Screens.OnlinePlay.Multiplayer.Multiplayer + private partial class TestMultiplayer : Screens.OnlinePlay.Multiplayer.Multiplayer { public new TestMultiplayerRoomManager RoomManager { get; private set; } public TestRoomRequestsHandler RequestsHandler { get; private set; } diff --git a/osu.Game.Tests/Visual/TestSceneOsuScreenStack.cs b/osu.Game.Tests/Visual/TestSceneOsuScreenStack.cs index 7588546f42..7f01a67903 100644 --- a/osu.Game.Tests/Visual/TestSceneOsuScreenStack.cs +++ b/osu.Game.Tests/Visual/TestSceneOsuScreenStack.cs @@ -16,7 +16,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual { [TestFixture] - public class TestSceneOsuScreenStack : OsuTestScene + public partial class TestSceneOsuScreenStack : OsuTestScene { private TestOsuScreenStack stack; @@ -90,7 +90,7 @@ namespace osu.Game.Tests.Visual AddAssert("allows adjustments 11", () => musicController.AllowTrackAdjustments); } - public class TestScreen : ScreenWithBeatmapBackground + public partial class TestScreen : ScreenWithBeatmapBackground { private readonly string screenText; @@ -112,7 +112,7 @@ namespace osu.Game.Tests.Visual } } - private class NoParallaxTestScreen : TestScreen + private partial class NoParallaxTestScreen : TestScreen { public NoParallaxTestScreen(string screenText) : base(screenText) @@ -122,22 +122,22 @@ namespace osu.Game.Tests.Visual public override float BackgroundParallaxAmount => 0.0f; } - private class TestOsuScreenStack : OsuScreenStack + private partial class TestOsuScreenStack : OsuScreenStack { public new float ParallaxAmount => base.ParallaxAmount; } - private class AllowScreen : OsuScreen + private partial class AllowScreen : OsuScreen { public override bool? AllowTrackAdjustments => true; } - public class DisallowScreen : OsuScreen + public partial class DisallowScreen : OsuScreen { public override bool? AllowTrackAdjustments => false; } - private class InheritScreen : OsuScreen + private partial class InheritScreen : OsuScreen { } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneBackButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneBackButton.cs index 9b84cf2a9e..837de60053 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneBackButton.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneBackButton.cs @@ -12,7 +12,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneBackButton : OsuTestScene + public partial class TestSceneBackButton : OsuTestScene { public TestSceneBackButton() { diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs index 368babc9b5..5d97714ab5 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs @@ -26,7 +26,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestSceneBeatSyncedContainer : OsuTestScene + public partial class TestSceneBeatSyncedContainer : OsuTestScene { private TestBeatSyncedContainer beatContainer; @@ -171,7 +171,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddAssert("effect has kiai", () => actualEffectPoint != null && ((EffectControlPoint)actualEffectPoint).KiaiMode); } - private class TestBeatSyncedContainer : BeatSyncedContainer + private partial class TestBeatSyncedContainer : BeatSyncedContainer { private const int flash_layer_height = 150; @@ -321,7 +321,7 @@ namespace osu.Game.Tests.Visual.UserInterface } } - private class InfoString : FillFlowContainer + private partial class InfoString : FillFlowContainer { private const int text_size = 20; private const int margin = 7; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapListingCardSizeTabControl.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapListingCardSizeTabControl.cs index bc846d8bcb..f93c9a3d5d 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapListingCardSizeTabControl.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapListingCardSizeTabControl.cs @@ -16,7 +16,7 @@ using osu.Game.Overlays.BeatmapListing; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneBeatmapListingCardSizeTabControl : OsuTestScene + public partial class TestSceneBeatmapListingCardSizeTabControl : OsuTestScene { [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapListingSearchControl.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapListingSearchControl.cs index e8454e8d0f..0aae182db4 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapListingSearchControl.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapListingSearchControl.cs @@ -19,7 +19,7 @@ using osuTK; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneBeatmapListingSearchControl : OsuTestScene + public partial class TestSceneBeatmapListingSearchControl : OsuTestScene { [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapListingSortTabControl.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapListingSortTabControl.cs index 0ef13385ec..316035275f 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapListingSortTabControl.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapListingSortTabControl.cs @@ -17,7 +17,7 @@ using osuTK; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneBeatmapListingSortTabControl : OsuTestScene + public partial class TestSceneBeatmapListingSortTabControl : OsuTestScene { private readonly BeatmapListingSortTabControl control; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapSearchFilter.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapSearchFilter.cs index ff1dce1a4e..7f7ba6966b 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapSearchFilter.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapSearchFilter.cs @@ -14,7 +14,7 @@ using osuTK; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneBeatmapSearchFilter : OsuTestScene + public partial class TestSceneBeatmapSearchFilter : OsuTestScene { [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneBreadcrumbControl.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneBreadcrumbControl.cs index a387148c2c..eeb2d1e70f 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneBreadcrumbControl.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneBreadcrumbControl.cs @@ -14,7 +14,7 @@ using osu.Game.Graphics.UserInterface; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestSceneBreadcrumbControl : OsuTestScene + public partial class TestSceneBreadcrumbControl : OsuTestScene { private readonly TestBreadcrumbControl breadcrumbs; @@ -62,7 +62,7 @@ namespace osu.Game.Tests.Visual.UserInterface Circles, } - private class TestBreadcrumbControl : BreadcrumbControl + private partial class TestBreadcrumbControl : BreadcrumbControl { public BreadcrumbTabItem GetDrawable(BreadcrumbTab tab) => (BreadcrumbTabItem)TabContainer.First(t => t.Value == tab); } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneBreadcrumbControlHeader.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneBreadcrumbControlHeader.cs index 8e2502dad1..cc203b3043 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneBreadcrumbControlHeader.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneBreadcrumbControlHeader.cs @@ -11,7 +11,7 @@ using osu.Game.Overlays; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneBreadcrumbControlHeader : OsuTestScene + public partial class TestSceneBreadcrumbControlHeader : OsuTestScene { private static readonly string[] items = { "first", "second", "third", "fourth", "fifth" }; @@ -48,7 +48,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep($"Remove {item} item", () => header.RemoveItem(item)); } - private class TestHeader : BreadcrumbControlOverlayHeader + private partial class TestHeader : BreadcrumbControlOverlayHeader { public TestHeader() { @@ -77,7 +77,7 @@ namespace osu.Game.Tests.Visual.UserInterface protected override OverlayTitle CreateTitle() => new TestTitle(); } - private class TestTitle : OverlayTitle + private partial class TestTitle : OverlayTitle { public TestTitle() { diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneButtonSystem.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneButtonSystem.cs index cbd4c69180..ac811aeb65 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneButtonSystem.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneButtonSystem.cs @@ -17,7 +17,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestSceneButtonSystem : OsuManualInputManagerTestScene + public partial class TestSceneButtonSystem : OsuManualInputManagerTestScene { private OsuLogo logo; private ButtonSystem buttons; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneButtonsInput.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneButtonsInput.cs new file mode 100644 index 0000000000..985f613b63 --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneButtonsInput.cs @@ -0,0 +1,129 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics; +using osu.Game.Overlays.Settings; +using NUnit.Framework; +using osuTK; +using osu.Game.Overlays; +using osu.Game.Graphics.UserInterfaceV2; +using osu.Game.Graphics.UserInterface; +using osu.Framework.Allocation; +using osu.Game.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osuTK.Graphics; +using osu.Game.Graphics.Sprites; + +namespace osu.Game.Tests.Visual.UserInterface +{ + public partial class TestSceneButtonsInput : OsuManualInputManagerTestScene + { + private const int width = 500; + + [Cached] + private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Green); + + private readonly SettingsButton settingsButton; + private readonly OsuClickableContainer clickableContainer; + private readonly RoundedButton roundedButton; + private readonly ShearedButton shearedButton; + + public TestSceneButtonsInput() + { + Add(new FillFlowContainer + { + AutoSizeAxes = Axes.Y, + Width = 500, + Spacing = new Vector2(0, 5), + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + clickableContainer = new OsuClickableContainer + { + RelativeSizeAxes = Axes.X, + Height = 40, + Enabled = { Value = true }, + Masking = true, + CornerRadius = 20, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Red + }, + new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Text = "Rounded clickable container" + } + } + }, + settingsButton = new SettingsButton + { + Enabled = { Value = true }, + Text = "Settings button" + }, + roundedButton = new RoundedButton + { + RelativeSizeAxes = Axes.X, + Enabled = { Value = true }, + Text = "Rounded button" + }, + shearedButton = new ShearedButton(width) + { + Text = "Sheared button", + LighterColour = Colour4.FromHex("#FFFFFF"), + DarkerColour = Colour4.FromHex("#FFCC22"), + TextColour = Colour4.Black, + Height = 40, + Enabled = { Value = true }, + Padding = new MarginPadding(0) + } + } + }); + } + + [Test] + public void TestSettingsButtonInput() + { + AddStep("Move cursor to button", () => InputManager.MoveMouseTo(settingsButton)); + AddAssert("Button is hovered", () => settingsButton.IsHovered); + AddStep("Move cursor to padded area", () => InputManager.MoveMouseTo(settingsButton.ScreenSpaceDrawQuad.TopLeft + new Vector2(SettingsPanel.CONTENT_MARGINS / 2f, 10))); + AddAssert("Cursor within a button", () => settingsButton.ScreenSpaceDrawQuad.Contains(InputManager.CurrentState.Mouse.Position)); + AddAssert("Button is not hovered", () => !settingsButton.IsHovered); + } + + [Test] + public void TestRoundedButtonInput() + { + AddStep("Move cursor to button", () => InputManager.MoveMouseTo(roundedButton)); + AddAssert("Button is hovered", () => roundedButton.IsHovered); + AddStep("Move cursor to corner", () => InputManager.MoveMouseTo(roundedButton.ScreenSpaceDrawQuad.TopLeft + Vector2.One)); + AddAssert("Cursor within a button", () => roundedButton.ScreenSpaceDrawQuad.Contains(InputManager.CurrentState.Mouse.Position)); + AddAssert("Button is not hovered", () => !roundedButton.IsHovered); + } + + [Test] + public void TestShearedButtonInput() + { + AddStep("Move cursor to button", () => InputManager.MoveMouseTo(shearedButton)); + AddAssert("Button is hovered", () => shearedButton.IsHovered); + AddStep("Move cursor to corner", () => InputManager.MoveMouseTo(shearedButton.ScreenSpaceDrawQuad.TopLeft + Vector2.One)); + AddAssert("Cursor within a button", () => shearedButton.ScreenSpaceDrawQuad.Contains(InputManager.CurrentState.Mouse.Position)); + AddAssert("Button is not hovered", () => !shearedButton.IsHovered); + } + + [Test] + public void TestRoundedClickableContainerInput() + { + AddStep("Move cursor to button", () => InputManager.MoveMouseTo(clickableContainer)); + AddAssert("Button is hovered", () => clickableContainer.IsHovered); + AddStep("Move cursor to corner", () => InputManager.MoveMouseTo(clickableContainer.ScreenSpaceDrawQuad.TopLeft + Vector2.One)); + AddAssert("Cursor within a button", () => clickableContainer.ScreenSpaceDrawQuad.Contains(InputManager.CurrentState.Mouse.Position)); + AddAssert("Button is not hovered", () => !clickableContainer.IsHovered); + } + } +} diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneColourPicker.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneColourPicker.cs index eba0e8cfed..d2acf89dc8 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneColourPicker.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneColourPicker.cs @@ -15,7 +15,7 @@ using osu.Game.Overlays; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneColourPicker : OsuTestScene + public partial class TestSceneColourPicker : OsuTestScene { private readonly Bindable colour = new Bindable(Colour4.Aquamarine); @@ -79,7 +79,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("set red", () => colour.Value = Colour4.Red); } - private class ColourProvidingContainer : Container + private partial class ColourProvidingContainer : Container { [Cached] private OverlayColourProvider provider { get; } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneCommentEditor.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneCommentEditor.cs index fd4ec2f3dc..e7840d4a2a 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneCommentEditor.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneCommentEditor.cs @@ -1,13 +1,16 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - +using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Localisation; +using osu.Framework.Testing; +using osu.Game.Graphics.UserInterface; using osu.Game.Overlays; using osu.Game.Overlays.Comments; using osuTK; @@ -15,13 +18,13 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneCommentEditor : OsuManualInputManagerTestScene + public partial class TestSceneCommentEditor : OsuManualInputManagerTestScene { [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue); - private TestCommentEditor commentEditor; - private TestCancellableCommentEditor cancellableCommentEditor; + private TestCommentEditor commentEditor = null!; + private TestCancellableCommentEditor cancellableCommentEditor = null!; [SetUp] public void SetUp() => Schedule(() => @@ -45,15 +48,16 @@ namespace osu.Game.Tests.Visual.UserInterface { AddStep("click on text box", () => { - InputManager.MoveMouseTo(commentEditor); + InputManager.MoveMouseTo(commentEditor.ChildrenOfType().Single()); InputManager.Click(MouseButton.Left); }); AddStep("enter text", () => commentEditor.Current.Value = "text"); AddStep("press Enter", () => InputManager.Key(Key.Enter)); + AddUntilStep("button is loading", () => commentEditor.IsSpinnerShown); AddAssert("text committed", () => commentEditor.CommittedText == "text"); - AddAssert("button is loading", () => commentEditor.IsLoading); + AddUntilStep("button is not loading", () => !commentEditor.IsSpinnerShown); } [Test] @@ -61,14 +65,14 @@ namespace osu.Game.Tests.Visual.UserInterface { AddStep("click on text box", () => { - InputManager.MoveMouseTo(commentEditor); + InputManager.MoveMouseTo(commentEditor.ChildrenOfType().Single()); InputManager.Click(MouseButton.Left); }); AddStep("press Enter", () => InputManager.Key(Key.Enter)); - AddAssert("no text committed", () => commentEditor.CommittedText == null); - AddAssert("button is not loading", () => !commentEditor.IsLoading); + AddAssert("button is not loading", () => !commentEditor.IsSpinnerShown); + AddAssert("no text committed", () => commentEditor.CommittedText.Length == 0); } [Test] @@ -76,7 +80,7 @@ namespace osu.Game.Tests.Visual.UserInterface { AddStep("click on text box", () => { - InputManager.MoveMouseTo(commentEditor); + InputManager.MoveMouseTo(commentEditor.ChildrenOfType().Single()); InputManager.Click(MouseButton.Left); }); AddStep("enter text", () => commentEditor.Current.Value = "some other text"); @@ -87,8 +91,9 @@ namespace osu.Game.Tests.Visual.UserInterface InputManager.Click(MouseButton.Left); }); + AddUntilStep("button is loading", () => commentEditor.IsSpinnerShown); AddAssert("text committed", () => commentEditor.CommittedText == "some other text"); - AddAssert("button is loading", () => commentEditor.IsLoading); + AddUntilStep("button is not loading", () => !commentEditor.IsSpinnerShown); } [Test] @@ -96,40 +101,39 @@ namespace osu.Game.Tests.Visual.UserInterface { AddStep("click cancel button", () => { - InputManager.MoveMouseTo(cancellableCommentEditor.ButtonsContainer); + InputManager.MoveMouseTo(cancellableCommentEditor.ButtonsContainer[1]); InputManager.Click(MouseButton.Left); }); AddAssert("cancel action fired", () => cancellableCommentEditor.Cancelled); } - private class TestCommentEditor : CommentEditor + private partial class TestCommentEditor : CommentEditor { public new Bindable Current => base.Current; public new FillFlowContainer ButtonsContainer => base.ButtonsContainer; - public string CommittedText { get; private set; } + public string CommittedText { get; private set; } = string.Empty; - public TestCommentEditor() - { - OnCommit = onCommit; - } + public bool IsSpinnerShown => this.ChildrenOfType().Single().IsPresent; - private void onCommit(string value) + protected override void OnCommit(string value) { + ShowLoadingSpinner = true; CommittedText = value; - Scheduler.AddDelayed(() => IsLoading = false, 1000); + Scheduler.AddDelayed(() => ShowLoadingSpinner = false, 1000); } - protected override string FooterText => @"Footer text. And it is pretty long. Cool."; - protected override string CommitButtonText => @"Commit"; - protected override string TextBoxPlaceholder => @"This text box is empty"; + protected override LocalisableString FooterText => @"Footer text. And it is pretty long. Cool."; + protected override LocalisableString CommitButtonText => @"Commit"; + protected override LocalisableString TextBoxPlaceholder => @"This text box is empty"; } - private class TestCancellableCommentEditor : CancellableCommentEditor + private partial class TestCancellableCommentEditor : CancellableCommentEditor { public new FillFlowContainer ButtonsContainer => base.ButtonsContainer; - protected override string FooterText => @"Wow, another one. Sicc"; + + protected override LocalisableString FooterText => @"Wow, another one. Sicc"; public bool Cancelled { get; private set; } @@ -138,8 +142,12 @@ namespace osu.Game.Tests.Visual.UserInterface OnCancel = () => Cancelled = true; } - protected override string CommitButtonText => @"Save"; - protected override string TextBoxPlaceholder => @"Multiline textboxes soon"; + protected override void OnCommit(string text) + { + } + + protected override LocalisableString CommitButtonText => @"Save"; + protected override LocalisableString TextBoxPlaceholder => @"Multiline textboxes soon"; } } } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneCommentRepliesButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneCommentRepliesButton.cs index 115833b034..1bfa389a25 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneCommentRepliesButton.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneCommentRepliesButton.cs @@ -16,7 +16,7 @@ using osu.Framework.Testing; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneCommentRepliesButton : OsuTestScene + public partial class TestSceneCommentRepliesButton : OsuTestScene { [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue); @@ -54,7 +54,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddAssert("Icon facing downwards", () => button.Icon.Scale.Y == 1); } - private class TestButton : CommentRepliesButton + private partial class TestButton : CommentRepliesButton { public SpriteIcon Icon => this.ChildrenOfType().First(); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneContextMenu.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneContextMenu.cs index bd77c4725c..3491b7dbc1 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneContextMenu.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneContextMenu.cs @@ -19,7 +19,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestSceneContextMenu : OsuTestScene + public partial class TestSceneContextMenu : OsuTestScene { private const int start_time = 0; private const int duration = 1000; @@ -113,12 +113,12 @@ namespace osu.Game.Tests.Visual.UserInterface }; } - private class MyContextMenuContainer : Container, IHasContextMenu + private partial class MyContextMenuContainer : Container, IHasContextMenu { public MenuItem[] ContextMenuItems => makeMenu(); } - private class AnotherContextMenuContainer : Container, IHasContextMenu + private partial class AnotherContextMenuContainer : Container, IHasContextMenu { public MenuItem[] ContextMenuItems { diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneCursors.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneCursors.cs index 75c47f0b1b..01d4eb83f3 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneCursors.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneCursors.cs @@ -20,7 +20,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestSceneCursors : OsuManualInputManagerTestScene + public partial class TestSceneCursors : OsuManualInputManagerTestScene { private readonly GlobalCursorDisplay globalCursorDisplay; private readonly CustomCursorBox[] cursorBoxes = new CustomCursorBox[6]; @@ -239,7 +239,7 @@ namespace osu.Game.Tests.Visual.UserInterface private bool checkAtMouse(CursorContainer cursorContainer) => Precision.AlmostEquals(InputManager.CurrentState.Mouse.Position, cursorContainer.ToScreenSpace(cursorContainer.ActiveCursor.DrawPosition)); - private class CustomCursorBox : Container, IProvideCursor + private partial class CustomCursorBox : Container, IProvideCursor { public bool SmoothTransition; @@ -290,11 +290,11 @@ namespace osu.Game.Tests.Visual.UserInterface } } - private class TestCursorContainer : CursorContainer + private partial class TestCursorContainer : CursorContainer { protected override Drawable CreateCursor() => new TestCursor(); - private class TestCursor : CircularContainer + private partial class TestCursor : CircularContainer { public TestCursor() { diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneDashboardBeatmapListing.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneDashboardBeatmapListing.cs index 2b6a93143f..6092f35050 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneDashboardBeatmapListing.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneDashboardBeatmapListing.cs @@ -17,7 +17,7 @@ using APIUser = osu.Game.Online.API.Requests.Responses.APIUser; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneDashboardBeatmapListing : OsuTestScene + public partial class TestSceneDashboardBeatmapListing : OsuTestScene { [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs index c1a9768cf0..7635c61867 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs @@ -32,7 +32,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneDeleteLocalScore : OsuManualInputManagerTestScene + public partial class TestSceneDeleteLocalScore : OsuManualInputManagerTestScene { private readonly ContextMenuContainer contextMenuContainer; private readonly BeatmapLeaderboard leaderboard; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneDialogOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneDialogOverlay.cs index a8e6142bab..81b692004b 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneDialogOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneDialogOverlay.cs @@ -15,7 +15,7 @@ using osu.Game.Overlays.Dialog; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestSceneDialogOverlay : OsuTestScene + public partial class TestSceneDialogOverlay : OsuTestScene { private DialogOverlay overlay; @@ -114,7 +114,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddAssert("dialog displayed", () => overlay.CurrentDialog == dialog); } - public class SlowLoadingDialogOverlay : DialogOverlay + public partial class SlowLoadingDialogOverlay : DialogOverlay { public ManualResetEventSlim LoadEvent = new ManualResetEventSlim(); @@ -166,7 +166,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddAssert("dialog is not part of hierarchy", () => testDialog.Parent == null); } - private class TestPopupDialog : PopupDialog + private partial class TestPopupDialog : PopupDialog { } } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneDifficultyMultiplierDisplay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneDifficultyMultiplierDisplay.cs index 984276b27e..890c7295b4 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneDifficultyMultiplierDisplay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneDifficultyMultiplierDisplay.cs @@ -12,7 +12,7 @@ using osu.Game.Overlays.Mods; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestSceneDifficultyMultiplierDisplay : OsuTestScene + public partial class TestSceneDifficultyMultiplierDisplay : OsuTestScene { [Cached] private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Green); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneDrawableDate.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneDrawableDate.cs index 59e85ae085..108ad8b7c1 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneDrawableDate.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneDrawableDate.cs @@ -13,7 +13,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneDrawableDate : OsuTestScene + public partial class TestSceneDrawableDate : OsuTestScene { public TestSceneDrawableDate() { @@ -36,7 +36,7 @@ namespace osu.Game.Tests.Visual.UserInterface }; } - private class PokeyDrawableDate : CompositeDrawable + private partial class PokeyDrawableDate : CompositeDrawable { public PokeyDrawableDate(DateTimeOffset date) { diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneEditorSidebar.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneEditorSidebar.cs index ee07acef52..72dacb7558 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneEditorSidebar.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneEditorSidebar.cs @@ -16,7 +16,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneEditorSidebar : OsuTestScene + public partial class TestSceneEditorSidebar : OsuTestScene { [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneExpandingBar.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneExpandingBar.cs index 2d97513206..9d850c0fc5 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneExpandingBar.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneExpandingBar.cs @@ -11,7 +11,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneExpandingBar : OsuTestScene + public partial class TestSceneExpandingBar : OsuTestScene { public TestSceneExpandingBar() { diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneExpandingContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneExpandingContainer.cs index 704185b117..3f4f86e424 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneExpandingContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneExpandingContainer.cs @@ -14,7 +14,7 @@ using osuTK; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneExpandingContainer : OsuManualInputManagerTestScene + public partial class TestSceneExpandingContainer : OsuManualInputManagerTestScene { private TestExpandingContainer container; private SettingsToolboxGroup toolboxGroup; @@ -149,7 +149,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddAssert("container still expanded", () => container.Expanded.Value); } - private class TestExpandingContainer : ExpandingContainer + private partial class TestExpandingContainer : ExpandingContainer { public TestExpandingContainer() : base(120, 250) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneFPSCounter.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneFPSCounter.cs index d78707045b..a91e6e3350 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneFPSCounter.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneFPSCounter.cs @@ -12,7 +12,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneFPSCounter : OsuTestScene + public partial class TestSceneFPSCounter : OsuTestScene { [SetUpSteps] public void SetUpSteps() diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenBehaviour.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenBehaviour.cs index 8fa4f7ec0e..ec8ef0ad50 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenBehaviour.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenBehaviour.cs @@ -10,7 +10,7 @@ using osu.Game.Overlays.FirstRunSetup; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneFirstRunScreenBehaviour : OsuManualInputManagerTestScene + public partial class TestSceneFirstRunScreenBehaviour : OsuManualInputManagerTestScene { [Cached] private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenBundledBeatmaps.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenBundledBeatmaps.cs index 6cc4ac709b..e9460e45d3 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenBundledBeatmaps.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenBundledBeatmaps.cs @@ -10,7 +10,7 @@ using osu.Game.Overlays.FirstRunSetup; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneFirstRunScreenBundledBeatmaps : OsuManualInputManagerTestScene + public partial class TestSceneFirstRunScreenBundledBeatmaps : OsuManualInputManagerTestScene { [Cached] private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenImportFromStable.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenImportFromStable.cs index 3c3d5933e4..e6fc889a70 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenImportFromStable.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenImportFromStable.cs @@ -17,7 +17,7 @@ using osu.Game.Overlays.FirstRunSetup; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneFirstRunScreenImportFromStable : OsuManualInputManagerTestScene + public partial class TestSceneFirstRunScreenImportFromStable : OsuManualInputManagerTestScene { [Cached] private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenUIScale.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenUIScale.cs index 98ad77fbae..8ba94cf9ae 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenUIScale.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenUIScale.cs @@ -10,7 +10,7 @@ using osu.Game.Overlays.FirstRunSetup; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneFirstRunScreenUIScale : OsuManualInputManagerTestScene + public partial class TestSceneFirstRunScreenUIScale : OsuManualInputManagerTestScene { [Cached] private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunSetupOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunSetupOverlay.cs index 16d564f0ee..77ed97e3ed 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunSetupOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunSetupOverlay.cs @@ -25,7 +25,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneFirstRunSetupOverlay : OsuManualInputManagerTestScene + public partial class TestSceneFirstRunSetupOverlay : OsuManualInputManagerTestScene { private FirstRunSetupOverlay overlay; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneFooterButtonMods.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneFooterButtonMods.cs index a4b5faae26..24b4060a42 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneFooterButtonMods.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneFooterButtonMods.cs @@ -14,7 +14,7 @@ using osu.Game.Screens.Select; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneFooterButtonMods : OsuTestScene + public partial class TestSceneFooterButtonMods : OsuTestScene { private readonly TestFooterButtonMods footerButtonMods; @@ -81,7 +81,7 @@ namespace osu.Game.Tests.Visual.UserInterface return expectedValue == footerButtonMods.MultiplierText.Current.Value; } - private class TestFooterButtonMods : FooterButtonMods + private partial class TestFooterButtonMods : FooterButtonMods { public new OsuSpriteText MultiplierText => base.MultiplierText; } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneFriendsOnlineStatusControl.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneFriendsOnlineStatusControl.cs index ad5e498c8b..c75c2a7877 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneFriendsOnlineStatusControl.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneFriendsOnlineStatusControl.cs @@ -14,7 +14,7 @@ using osu.Game.Overlays.Dashboard.Friends; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneFriendsOnlineStatusControl : OsuTestScene + public partial class TestSceneFriendsOnlineStatusControl : OsuTestScene { [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneHistoryTextBox.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneHistoryTextBox.cs index 8ed5dd43cc..ed59572cab 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneHistoryTextBox.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneHistoryTextBox.cs @@ -11,7 +11,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestSceneHistoryTextBox : OsuManualInputManagerTestScene + public partial class TestSceneHistoryTextBox : OsuManualInputManagerTestScene { private const string temp = "Temp message"; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneHoldToConfirmOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneHoldToConfirmOverlay.cs index 235dbc1fcb..801bef62c8 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneHoldToConfirmOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneHoldToConfirmOverlay.cs @@ -10,7 +10,7 @@ using osu.Game.Screens.Menu; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneHoldToConfirmOverlay : OsuTestScene + public partial class TestSceneHoldToConfirmOverlay : OsuTestScene { protected override double TimePerAction => 100; // required for the early exit test, since hold-to-confirm delay is 200ms @@ -59,7 +59,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddUntilStep("wait until fired again", () => overlay.Fired); } - private class TestHoldToConfirmOverlay : ExitConfirmOverlay + private partial class TestHoldToConfirmOverlay : ExitConfirmOverlay { public void Begin() => BeginConfirm(); } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneIconButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneIconButton.cs index 35d250c7ac..454fa7cd05 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneIconButton.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneIconButton.cs @@ -16,7 +16,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestSceneIconButton : OsuTestScene + public partial class TestSceneIconButton : OsuTestScene { public TestSceneIconButton() { @@ -38,7 +38,7 @@ namespace osu.Game.Tests.Visual.UserInterface }; } - private class ColouredIconButton : IconButton + private partial class ColouredIconButton : IconButton { public ColouredIconButton() { @@ -47,7 +47,7 @@ namespace osu.Game.Tests.Visual.UserInterface } } - private class NamedIconButton : Container + private partial class NamedIconButton : Container { public NamedIconButton(string name, IconButton button) { diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledColourPalette.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledColourPalette.cs index d7a69616f3..91a60009dc 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledColourPalette.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledColourPalette.cs @@ -18,7 +18,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneLabelledColourPalette : OsuManualInputManagerTestScene + public partial class TestSceneLabelledColourPalette : OsuManualInputManagerTestScene { private LabelledColourPalette component; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledDrawable.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledDrawable.cs index 7ce0fceff9..0dffc9da51 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledDrawable.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledDrawable.cs @@ -17,7 +17,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneLabelledDrawable : OsuTestScene + public partial class TestSceneLabelledDrawable : OsuTestScene { [TestCase(false)] [TestCase(true)] @@ -88,7 +88,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddAssert($"description {(hasDescription ? "visible" : "hidden")}", () => component.ChildrenOfType().ElementAt(1).IsPresent == hasDescription); } - private class PaddedLabelledDrawable : LabelledDrawable + private partial class PaddedLabelledDrawable : LabelledDrawable { public PaddedLabelledDrawable() : base(true) @@ -104,7 +104,7 @@ namespace osu.Game.Tests.Visual.UserInterface }; } - private class NonPaddedLabelledDrawable : LabelledDrawable + private partial class NonPaddedLabelledDrawable : LabelledDrawable { public NonPaddedLabelledDrawable() : base(false) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledDropdown.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledDropdown.cs index cd14d6bde3..a2cfae3c7f 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledDropdown.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledDropdown.cs @@ -9,7 +9,7 @@ using osu.Game.Graphics.UserInterfaceV2; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneLabelledDropdown : OsuTestScene + public partial class TestSceneLabelledDropdown : OsuTestScene { [Test] public void TestLabelledDropdown() diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledSliderBar.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledSliderBar.cs index 5548375af2..6181891e13 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledSliderBar.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledSliderBar.cs @@ -17,7 +17,7 @@ using osu.Game.Overlays; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneLabelledSliderBar : OsuTestScene + public partial class TestSceneLabelledSliderBar : OsuTestScene { [Test] public void TestBasic() => createSliderBar(); @@ -101,7 +101,7 @@ namespace osu.Game.Tests.Visual.UserInterface }); } - private class OverlayColourContainer : Container + private partial class OverlayColourContainer : Container { [Cached] private OverlayColourProvider colourProvider; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledSwitchButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledSwitchButton.cs index 03434ff0a1..c4af47bd0f 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledSwitchButton.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledSwitchButton.cs @@ -10,7 +10,7 @@ using osu.Game.Graphics.UserInterfaceV2; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneLabelledSwitchButton : OsuTestScene + public partial class TestSceneLabelledSwitchButton : OsuTestScene { [TestCase(false)] [TestCase(true)] diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledTextBox.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledTextBox.cs index 3f93e60773..8046554819 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledTextBox.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledTextBox.cs @@ -12,7 +12,7 @@ using osu.Game.Graphics.UserInterfaceV2; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestSceneLabelledTextBox : OsuTestScene + public partial class TestSceneLabelledTextBox : OsuTestScene { [TestCase(false)] [TestCase(true)] diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLoadingLayer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLoadingLayer.cs index 2fc6405b88..dc40ecde43 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneLoadingLayer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLoadingLayer.cs @@ -10,12 +10,13 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Utils; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osu.Game.Graphics.UserInterfaceV2; using osuTK; using osuTK.Graphics; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneLoadingLayer : OsuTestScene + public partial class TestSceneLoadingLayer : OsuTestScene { private TestLoadingLayer overlay; @@ -49,8 +50,8 @@ namespace osu.Game.Tests.Visual.UserInterface Children = new Drawable[] { new OsuSpriteText { Text = "Sample content" }, - new TriangleButton { Text = "can't puush me", Width = 200, }, - new TriangleButton { Text = "puush me", Width = 200, Action = () => { } }, + new RoundedButton { Text = "can't puush me", Width = 200, }, + new RoundedButton { Text = "puush me", Width = 200, Action = () => { } }, } }, overlay = new TestLoadingLayer(true), @@ -87,7 +88,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("hide", () => overlay.Hide()); } - private class TestLoadingLayer : LoadingLayer + private partial class TestLoadingLayer : LoadingLayer { public new Box BackgroundDimLayer => base.BackgroundDimLayer; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLoadingSpinner.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLoadingSpinner.cs index 8c9b9186b1..40e786592a 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneLoadingSpinner.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLoadingSpinner.cs @@ -10,7 +10,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneLoadingSpinner : OsuGridTestScene + public partial class TestSceneLoadingSpinner : OsuGridTestScene { public TestSceneLoadingSpinner() : base(2, 2) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLogoAnimation.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLogoAnimation.cs index b565cb359b..f9d92aabc6 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneLogoAnimation.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLogoAnimation.cs @@ -13,7 +13,7 @@ using osu.Game.Graphics.Sprites; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestSceneLogoAnimation : OsuTestScene + public partial class TestSceneLogoAnimation : OsuTestScene { [BackgroundDependencyLoader] private void load(LargeTextureStore textures) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLogoTrackingContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLogoTrackingContainer.cs index d069e742dd..5926f07a11 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneLogoTrackingContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLogoTrackingContainer.cs @@ -18,7 +18,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneLogoTrackingContainer : OsuTestScene + public partial class TestSceneLogoTrackingContainer : OsuTestScene { private OsuLogo logo; private TestLogoTrackingContainer trackingContainer; @@ -277,7 +277,7 @@ namespace osu.Game.Tests.Visual.UserInterface Schedule(moveLogoFacade); } - private class TestLogoTrackingContainer : LogoTrackingContainer + private partial class TestLogoTrackingContainer : LogoTrackingContainer { /// /// Check that the logo is tracking the position of the facade, with an acceptable precision lenience. diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs index 72cddc0ad2..a11000214c 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs @@ -22,7 +22,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestSceneModColumn : OsuManualInputManagerTestScene + public partial class TestSceneModColumn : OsuManualInputManagerTestScene { [Cached] private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Green); @@ -294,7 +294,7 @@ namespace osu.Game.Tests.Visual.UserInterface modState.Filtered.Value = filter?.Invoke(modState.Mod) == false; } - private class TestModColumn : ModColumn + private partial class TestModColumn : ModColumn { public new bool SelectionAnimationRunning => base.SelectionAnimationRunning; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModDifficultyAdjustSettings.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModDifficultyAdjustSettings.cs index 181f46a996..f45f5b9f59 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModDifficultyAdjustSettings.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModDifficultyAdjustSettings.cs @@ -21,7 +21,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneModDifficultyAdjustSettings : OsuManualInputManagerTestScene + public partial class TestSceneModDifficultyAdjustSettings : OsuManualInputManagerTestScene { private OsuModDifficultyAdjust modDifficultyAdjust; @@ -126,6 +126,21 @@ namespace osu.Game.Tests.Visual.UserInterface checkBindableAtValue("Circle Size", 9); } + [Test] + public void TestExtendedLimitsRetainedAfterBoundCopyCreation() + { + setExtendedLimits(true); + setSliderValue("Circle Size", 11); + + checkSliderAtValue("Circle Size", 11); + checkBindableAtValue("Circle Size", 11); + + AddStep("create bound copy", () => _ = modDifficultyAdjust.CircleSize.GetBoundCopy()); + + checkSliderAtValue("Circle Size", 11); + checkBindableAtValue("Circle Size", 11); + } + [Test] public void TestResetToDefault() { diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModDisplay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModDisplay.cs index c65d1f8c5e..bd5a0d8645 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModDisplay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModDisplay.cs @@ -11,7 +11,7 @@ using osu.Game.Screens.Play.HUD; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneModDisplay : OsuTestScene + public partial class TestSceneModDisplay : OsuTestScene { [Test] public void TestMode([Values] ExpansionMode mode) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModFlowDisplay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModFlowDisplay.cs index c45ea3a40c..f0efabe2f7 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModFlowDisplay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModFlowDisplay.cs @@ -11,7 +11,7 @@ using osu.Game.Screens.Play.HUD; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneModFlowDisplay : OsuTestScene + public partial class TestSceneModFlowDisplay : OsuTestScene { private ModFlowDisplay modFlow; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModIcon.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModIcon.cs index ce9aa682d1..897d5fd9f5 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModIcon.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModIcon.cs @@ -11,7 +11,7 @@ using osu.Game.Rulesets.UI; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneModIcon : OsuTestScene + public partial class TestSceneModIcon : OsuTestScene { [Test] public void TestShowAllMods() diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModPanel.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModPanel.cs index 9c0b36073b..64bdc167c2 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModPanel.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModPanel.cs @@ -18,7 +18,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestSceneModPanel : OsuManualInputManagerTestScene + public partial class TestSceneModPanel : OsuManualInputManagerTestScene { [Cached] private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Green); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs index 901f234db6..1090764788 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs @@ -25,7 +25,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneModPresetColumn : OsuManualInputManagerTestScene + public partial class TestSceneModPresetColumn : OsuManualInputManagerTestScene { protected override bool UseFreshStoragePerRun => true; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetPanel.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetPanel.cs index bcd5579f03..35e352534b 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetPanel.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetPanel.cs @@ -21,7 +21,7 @@ using osuTK; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestSceneModPresetPanel : OsuTestScene + public partial class TestSceneModPresetPanel : OsuTestScene { [Cached] private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Green); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs index 0292ce5905..eff320a575 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs @@ -28,7 +28,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestSceneModSelectOverlay : OsuManualInputManagerTestScene + public partial class TestSceneModSelectOverlay : OsuManualInputManagerTestScene { protected override bool UseFreshStoragePerRun => true; @@ -584,7 +584,7 @@ namespace osu.Game.Tests.Visual.UserInterface private ModPanel getPanelForMod(Type modType) => modSelectOverlay.ChildrenOfType().Single(panel => panel.Mod.GetType() == modType); - private class TestModSelectOverlay : UserModSelectOverlay + private partial class TestModSelectOverlay : UserModSelectOverlay { protected override bool ShowPresets => true; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSettingsArea.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSettingsArea.cs index a9c3872643..dac1f94c28 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSettingsArea.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSettingsArea.cs @@ -16,7 +16,7 @@ using osu.Game.Rulesets.Osu.Mods; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestSceneModSettingsArea : OsuTestScene + public partial class TestSceneModSettingsArea : OsuTestScene { [Cached] private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Green); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSwitchSmall.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSwitchSmall.cs index ff9cc09806..07312379b3 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSwitchSmall.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSwitchSmall.cs @@ -22,7 +22,7 @@ using osuTK; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestSceneModSwitchSmall : OsuTestScene + public partial class TestSceneModSwitchSmall : OsuTestScene { [Test] public void TestOsu() => createSwitchTestFor(new OsuRuleset()); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSwitchTiny.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSwitchTiny.cs index ddb5845df8..34dd139428 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSwitchTiny.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSwitchTiny.cs @@ -22,7 +22,7 @@ using osuTK; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestSceneModSwitchTiny : OsuTestScene + public partial class TestSceneModSwitchTiny : OsuTestScene { [Test] public void TestOsu() => createSwitchTestFor(new OsuRuleset()); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModsEffectDisplay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModsEffectDisplay.cs index 42eceb3242..a1c8bef1de 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModsEffectDisplay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModsEffectDisplay.cs @@ -18,7 +18,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestSceneModsEffectDisplay : OsuTestScene + public partial class TestSceneModsEffectDisplay : OsuTestScene { [Cached] private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Green); @@ -53,7 +53,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddUntilStep("colours are correct", () => testDisplay.Container.Colour == colourProvider.Background5 && background.Colour == colours.ForModType(ModType.DifficultyIncrease)); } - private class TestDisplay : ModsEffectDisplay + private partial class TestDisplay : ModsEffectDisplay { public Container Container => Content; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneNotificationOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneNotificationOverlay.cs index 7ed08d8dff..3cd5daf7a1 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneNotificationOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneNotificationOverlay.cs @@ -21,7 +21,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestSceneNotificationOverlay : OsuManualInputManagerTestScene + public partial class TestSceneNotificationOverlay : OsuManualInputManagerTestScene { private NotificationOverlay notificationOverlay = null!; @@ -617,12 +617,12 @@ namespace osu.Game.Tests.Visual.UserInterface notificationOverlay.Post(new SimpleNotification { Text = @"Spam incoming!!" }); } - private class BackgroundNotification : SimpleNotification + private partial class BackgroundNotification : SimpleNotification { public override bool IsImportant => false; } - private class BackgroundProgressNotification : ProgressNotification + private partial class BackgroundProgressNotification : ProgressNotification { public override bool IsImportant => false; } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs index f7f35b8361..d07b90025f 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs @@ -12,7 +12,7 @@ using osu.Game.Rulesets.Osu; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestSceneNowPlayingOverlay : OsuTestScene + public partial class TestSceneNowPlayingOverlay : OsuTestScene { [Cached] private MusicController musicController = new MusicController(); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOnScreenDisplay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOnScreenDisplay.cs index 2d8d7a5de3..f2123061e5 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOnScreenDisplay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOnScreenDisplay.cs @@ -14,7 +14,7 @@ using osu.Game.Overlays.OSD; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestSceneOnScreenDisplay : OsuTestScene + public partial class TestSceneOnScreenDisplay : OsuTestScene { [BackgroundDependencyLoader] private void load() @@ -95,7 +95,7 @@ namespace osu.Game.Tests.Visual.UserInterface Setting4 } - private class EmptyToast : Toast + private partial class EmptyToast : Toast { public EmptyToast() : base("", "", "") @@ -103,7 +103,7 @@ namespace osu.Game.Tests.Visual.UserInterface } } - private class LengthyToast : Toast + private partial class LengthyToast : Toast { public LengthyToast() : base("Toast with a very very very long text", "A very very very very very very long text also", "A very very very very very long shortcut") @@ -111,7 +111,7 @@ namespace osu.Game.Tests.Visual.UserInterface } } - private class TestOnScreenDisplay : OnScreenDisplay + private partial class TestOnScreenDisplay : OnScreenDisplay { protected override void DisplayTemporarily(Drawable toDisplay) => toDisplay.FadeIn().ResizeHeightTo(110); } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuAnimatedButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuAnimatedButton.cs index bab2121d70..eba3885a2b 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuAnimatedButton.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuAnimatedButton.cs @@ -11,7 +11,7 @@ using osuTK; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneOsuAnimatedButton : OsuTestScene + public partial class TestSceneOsuAnimatedButton : OsuTestScene { [Test] public void TestRelativeSized() @@ -104,7 +104,7 @@ namespace osu.Game.Tests.Visual.UserInterface }); } - public class BaseContainer : OsuAnimatedButton + public partial class BaseContainer : OsuAnimatedButton { public BaseContainer(string text) { diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuButton.cs deleted file mode 100644 index d4c2bfd422..0000000000 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuButton.cs +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -#nullable disable - -using NUnit.Framework; -using osu.Framework.Graphics; -using osu.Game.Graphics.UserInterface; -using osuTK; - -namespace osu.Game.Tests.Visual.UserInterface -{ - public class TestSceneOsuButton : OsuTestScene - { - [Test] - public void TestToggleEnabled() - { - OsuButton button = null; - - AddStep("add button", () => Child = button = new OsuButton - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(200), - Text = "Button" - }); - - AddToggleStep("toggle enabled", toggle => - { - for (int i = 0; i < 6; i++) - button.Action = toggle ? () => { } : null; - }); - } - - [Test] - public void TestInitiallyDisabled() - { - AddStep("add button", () => Child = new OsuButton - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(200), - Text = "Button" - }); - } - } -} diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuDropdown.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuDropdown.cs index 2cda95bda4..770b9dece1 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuDropdown.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuDropdown.cs @@ -9,7 +9,7 @@ using osu.Game.Graphics.UserInterface; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneOsuDropdown : ThemeComparisonTestScene + public partial class TestSceneOsuDropdown : ThemeComparisonTestScene { protected override Drawable CreateContent() => new OsuEnumDropdown diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuFont.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuFont.cs index f534fc0fac..7b3f97a16e 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuFont.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuFont.cs @@ -13,7 +13,7 @@ using osu.Game.Graphics.Sprites; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneOsuFont : OsuTestScene + public partial class TestSceneOsuFont : OsuTestScene { private OsuSpriteText spriteText; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuHoverContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuHoverContainer.cs index d4b15c06c5..ab5a70f448 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuHoverContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuHoverContainer.cs @@ -14,7 +14,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestSceneOsuHoverContainer : OsuManualInputManagerTestScene + public partial class TestSceneOsuHoverContainer : OsuManualInputManagerTestScene { private OsuHoverTestContainer hoverContainer; private Box colourContainer; @@ -181,7 +181,7 @@ namespace osu.Game.Tests.Visual.UserInterface private void doMoveOut() => InputManager.MoveMouseTo(new Vector2(InputManager.ScreenSpaceDrawQuad.TopLeft.X, InputManager.ScreenSpaceDrawQuad.TopLeft.Y)); - private sealed class OsuHoverTestContainer : OsuHoverContainer + private sealed partial class OsuHoverTestContainer : OsuHoverContainer { public static readonly Color4 HOVER_COLOUR = Color4.Red; public static readonly Color4 IDLE_COLOUR = Color4.Green; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuIcon.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuIcon.cs index 1e1c3b3282..a1254678b7 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuIcon.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuIcon.cs @@ -21,7 +21,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestSceneOsuIcon : OsuTestScene + public partial class TestSceneOsuIcon : OsuTestScene { public TestSceneOsuIcon() { @@ -60,7 +60,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("change icons", () => flow.Children.ForEach(i => i.SpriteIcon.Icon = new IconUsage((char)(i.SpriteIcon.Icon.Icon + 1)))); } - private class Icon : Container, IHasTooltip + private partial class Icon : Container, IHasTooltip { public LocalisableString TooltipText { get; } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuLogo.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuLogo.cs index e23a960a7e..24a27f71e8 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuLogo.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuLogo.cs @@ -9,7 +9,7 @@ using osu.Game.Screens.Menu; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneOsuLogo : OsuTestScene + public partial class TestSceneOsuLogo : OsuTestScene { [Test] public void TestBasic() diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs index cdccb817b9..1e2485c6e2 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs @@ -13,7 +13,7 @@ using osu.Game.Overlays; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneOsuMarkdownContainer : OsuTestScene + public partial class TestSceneOsuMarkdownContainer : OsuTestScene { private OsuMarkdownContainer markdownContainer; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMenu.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMenu.cs index 5349a1b8a0..addaab5d35 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMenu.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMenu.cs @@ -12,7 +12,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneOsuMenu : OsuManualInputManagerTestScene + public partial class TestSceneOsuMenu : OsuManualInputManagerTestScene { private OsuMenu menu; private bool actionPerformed; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuPopover.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuPopover.cs index 6cc89a6df8..4ff7befe71 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuPopover.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuPopover.cs @@ -18,7 +18,7 @@ using osuTK; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneOsuPopover : OsuGridTestScene + public partial class TestSceneOsuPopover : OsuGridTestScene { public TestSceneOsuPopover() : base(1, 2) @@ -33,7 +33,7 @@ namespace osu.Game.Tests.Visual.UserInterface Text = @"No OverlayColourProvider", Font = OsuFont.Default.With(size: 40) }, - new TriangleButtonWithPopover() + new RoundedButtonWithPopover() } }; @@ -50,15 +50,15 @@ namespace osu.Game.Tests.Visual.UserInterface Text = @"With OverlayColourProvider (orange)", Font = OsuFont.Default.With(size: 40) }, - new TriangleButtonWithPopover() + new RoundedButtonWithPopover() } } }; } - private class TriangleButtonWithPopover : TriangleButton, IHasPopover + private partial class RoundedButtonWithPopover : RoundedButton, IHasPopover { - public TriangleButtonWithPopover() + public RoundedButtonWithPopover() { Width = 100; Height = 30; @@ -91,7 +91,7 @@ namespace osu.Game.Tests.Visual.UserInterface }; } - private class ColourProvidingContainer : Container + private partial class ColourProvidingContainer : Container { [Cached] private OverlayColourProvider provider { get; } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuTextBox.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuTextBox.cs index cc510f007b..929537e675 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuTextBox.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuTextBox.cs @@ -16,7 +16,7 @@ using osuTK; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneOsuTextBox : ThemeComparisonTestScene + public partial class TestSceneOsuTextBox : ThemeComparisonTestScene { private IEnumerable numberBoxes => this.ChildrenOfType(); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayContainer.cs new file mode 100644 index 0000000000..d9c2774611 --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayContainer.cs @@ -0,0 +1,106 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Game.Overlays.Volume; +using osuTK; +using osuTK.Graphics; +using osuTK.Input; +using Box = osu.Framework.Graphics.Shapes.Box; + +namespace osu.Game.Tests.Visual.UserInterface +{ + public partial class TestSceneOverlayContainer : OsuManualInputManagerTestScene + { + [SetUp] + public void SetUp() => Schedule(() => Child = new TestOverlay + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Size = new Vector2(0.5f) + }); + + [Test] + public void TestScrollBlocked() + { + OsuScrollContainer scroll = null!; + + AddStep("add scroll container", () => + { + Add(scroll = new OsuScrollContainer + { + RelativeSizeAxes = Axes.Both, + Depth = float.MaxValue, + Child = new Box + { + RelativeSizeAxes = Axes.X, + Height = DrawHeight * 10, + Colour = ColourInfo.GradientVertical(Colour4.Black, Colour4.White), + } + }); + }); + + AddStep("perform scroll", () => + { + InputManager.MoveMouseTo(Content); + InputManager.ScrollVerticalBy(-10); + }); + + AddAssert("scroll didn't receive input", () => scroll.Current == 0); + } + + [Test] + public void TestAltScrollNotBlocked() + { + bool scrollReceived = false; + + AddStep("add volume control receptor", () => Add(new VolumeControlReceptor + { + RelativeSizeAxes = Axes.Both, + Depth = float.MaxValue, + ScrollActionRequested = (_, _, _) => scrollReceived = true, + })); + + AddStep("hold alt", () => InputManager.PressKey(Key.AltLeft)); + AddStep("perform scroll", () => + { + InputManager.MoveMouseTo(Content); + InputManager.ScrollVerticalBy(10); + }); + + AddAssert("receptor received scroll input", () => scrollReceived); + AddStep("release alt", () => InputManager.ReleaseKey(Key.AltLeft)); + } + + private partial class TestOverlay : OsuFocusedOverlayContainer + { + [BackgroundDependencyLoader] + private void load() + { + State.Value = Visibility.Visible; + + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both + }, + new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Text = "Overlay content", + Colour = Color4.Black, + }, + }; + } + } + } +} diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeader.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeader.cs index a5493559d6..e90041774e 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeader.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeader.cs @@ -13,7 +13,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneOverlayHeader : OsuTestScene + public partial class TestSceneOverlayHeader : OsuTestScene { private readonly FillFlowContainer flow; @@ -70,7 +70,7 @@ namespace osu.Game.Tests.Visual.UserInterface }); } - private class ColourProvidedContainer : Container + private partial class ColourProvidedContainer : Container { [Cached] private readonly OverlayColourProvider colourProvider; @@ -85,7 +85,7 @@ namespace osu.Game.Tests.Visual.UserInterface } } - private class TestNoBackgroundHeader : OverlayHeader + private partial class TestNoBackgroundHeader : OverlayHeader { protected override OverlayTitle CreateTitle() => new TestTitle(); @@ -95,20 +95,20 @@ namespace osu.Game.Tests.Visual.UserInterface } } - private class TestNoControlHeader : OverlayHeader + private partial class TestNoControlHeader : OverlayHeader { protected override Drawable CreateBackground() => new OverlayHeaderBackground(@"Headers/changelog"); protected override OverlayTitle CreateTitle() => new TestTitle(); } - private class TestStringTabControlHeader : TabControlOverlayHeader + private partial class TestStringTabControlHeader : TabControlOverlayHeader { protected override Drawable CreateBackground() => new OverlayHeaderBackground(@"Headers/news"); protected override OverlayTitle CreateTitle() => new TestTitle(); - protected override Drawable CreateTitleContent() => new OverlayRulesetSelector(); + protected override Drawable CreateTabControlContent() => new OverlayRulesetSelector(); public TestStringTabControlHeader() { @@ -117,7 +117,7 @@ namespace osu.Game.Tests.Visual.UserInterface } } - private class TestEnumTabControlHeader : TabControlOverlayHeader + private partial class TestEnumTabControlHeader : TabControlOverlayHeader { public TestEnumTabControlHeader() { @@ -136,7 +136,7 @@ namespace osu.Game.Tests.Visual.UserInterface Tabs } - private class TestBreadcrumbControlHeader : BreadcrumbControlOverlayHeader + private partial class TestBreadcrumbControlHeader : BreadcrumbControlOverlayHeader { protected override OverlayTitle CreateTitle() => new TestTitle(); @@ -150,7 +150,7 @@ namespace osu.Game.Tests.Visual.UserInterface } } - private class TestTitle : OverlayTitle + private partial class TestTitle : OverlayTitle { public TestTitle() { diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeaderBackground.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeaderBackground.cs index 11507e561f..7a445427f5 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeaderBackground.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeaderBackground.cs @@ -10,7 +10,7 @@ using osuTK; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneOverlayHeaderBackground : OsuTestScene + public partial class TestSceneOverlayHeaderBackground : OsuTestScene { public TestSceneOverlayHeaderBackground() { diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayRulesetSelector.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayRulesetSelector.cs index 5a1ce9e791..432e448038 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayRulesetSelector.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayRulesetSelector.cs @@ -18,7 +18,7 @@ using osu.Framework.Allocation; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneOverlayRulesetSelector : OsuTestScene + public partial class TestSceneOverlayRulesetSelector : OsuTestScene { private readonly OverlayRulesetSelector selector; private readonly Bindable ruleset = new Bindable(); @@ -44,7 +44,7 @@ namespace osu.Game.Tests.Visual.UserInterface }); } - private class ColourProvidedContainer : Container + private partial class ColourProvidedContainer : Container { [Cached] private readonly OverlayColourProvider colourProvider; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayScrollContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayScrollContainer.cs index 7b3e82ff6d..926bc01aea 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayScrollContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayScrollContainer.cs @@ -15,7 +15,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneOverlayScrollContainer : OsuManualInputManagerTestScene + public partial class TestSceneOverlayScrollContainer : OsuManualInputManagerTestScene { [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue); @@ -100,7 +100,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddAssert("invocation count is 1", () => invocationCount == 1); } - private class TestScrollContainer : OverlayScrollContainer + private partial class TestScrollContainer : OverlayScrollContainer { public new ScrollToTopButton Button => base.Button; } diff --git a/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs b/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs index 1907a56735..b9e3592389 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs @@ -13,7 +13,7 @@ using osu.Game.Overlays; namespace osu.Game.Tests.Visual.UserInterface { - public class TestScenePageSelector : OsuTestScene + public partial class TestScenePageSelector : OsuTestScene { [Cached] private OverlayColourProvider provider { get; } = new OverlayColourProvider(OverlayColourScheme.Green); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneParallaxContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneParallaxContainer.cs index 6ab69f32ef..92d4981d4a 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneParallaxContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneParallaxContainer.cs @@ -10,7 +10,7 @@ using osu.Game.Screens.Backgrounds; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneParallaxContainer : OsuTestScene + public partial class TestSceneParallaxContainer : OsuTestScene { public TestSceneParallaxContainer() { diff --git a/osu.Game.Tests/Visual/UserInterface/TestScenePlaylistOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestScenePlaylistOverlay.cs index d87bcfa5dd..c723988d6a 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestScenePlaylistOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestScenePlaylistOverlay.cs @@ -20,7 +20,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.UserInterface { - public class TestScenePlaylistOverlay : OsuManualInputManagerTestScene + public partial class TestScenePlaylistOverlay : OsuManualInputManagerTestScene { protected override bool UseFreshStoragePerRun => true; diff --git a/osu.Game.Tests/Visual/UserInterface/TestScenePopupDialog.cs b/osu.Game.Tests/Visual/UserInterface/TestScenePopupDialog.cs index 218677fd03..9537ab63be 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestScenePopupDialog.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestScenePopupDialog.cs @@ -13,7 +13,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.UserInterface { - public class TestScenePopupDialog : OsuManualInputManagerTestScene + public partial class TestScenePopupDialog : OsuManualInputManagerTestScene { private TestPopupDialog dialog; @@ -52,7 +52,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("release button", () => InputManager.ReleaseButton(MouseButton.Left)); } - private class TestPopupDialog : PopupDialog + private partial class TestPopupDialog : PopupDialog { public PopupDialogDangerousButton DangerousButton { get; } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneProfileSubsectionHeader.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneProfileSubsectionHeader.cs index 9738ff33c3..c51095f360 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneProfileSubsectionHeader.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneProfileSubsectionHeader.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using NUnit.Framework; using osu.Game.Overlays.Profile.Sections; using osu.Framework.Testing; @@ -13,12 +11,12 @@ using osu.Framework.Allocation; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneProfileSubsectionHeader : OsuTestScene + public partial class TestSceneProfileSubsectionHeader : OsuTestScene { [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Pink); - private ProfileSubsectionHeader header; + private ProfileSubsectionHeader header = null!; [Test] public void TestHiddenCounter() diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneRangeSlider.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneRangeSlider.cs new file mode 100644 index 0000000000..b780764e7f --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneRangeSlider.cs @@ -0,0 +1,79 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Testing; +using osu.Game.Graphics.UserInterface; +using osu.Game.Overlays; +using osuTK; + +namespace osu.Game.Tests.Visual.UserInterface +{ + public partial class TestSceneRangeSlider : OsuTestScene + { + [Cached] + private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Red); + + private readonly BindableNumber customStart = new BindableNumber + { + MinValue = 0, + MaxValue = 100, + Precision = 0.1f + }; + + private readonly BindableNumber customEnd = new BindableNumber(100) + { + MinValue = 0, + MaxValue = 100, + Precision = 0.1f + }; + + private RangeSlider rangeSlider = null!; + + [SetUpSteps] + public void SetUpSteps() + { + AddStep("create control", () => Child = rangeSlider = new RangeSlider + { + Width = 200, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Scale = new Vector2(3), + LowerBound = customStart, + UpperBound = customEnd, + TooltipSuffix = "suffix", + NubWidth = Nub.HEIGHT * 2, + DefaultStringLowerBound = "Start", + DefaultStringUpperBound = "End", + MinRange = 10 + }); + } + + [Test] + public void TestAdjustRange() + { + AddAssert("Initial lower bound is correct", () => rangeSlider.LowerBound.Value, () => Is.EqualTo(0).Within(0.1f)); + AddAssert("Initial upper bound is correct", () => rangeSlider.UpperBound.Value, () => Is.EqualTo(100).Within(0.1f)); + + AddStep("Adjust range", () => + { + customStart.Value = 50; + customEnd.Value = 75; + }); + + AddAssert("Adjusted lower bound is correct", () => rangeSlider.LowerBound.Value, () => Is.EqualTo(50).Within(0.1f)); + AddAssert("Adjusted upper bound is correct", () => rangeSlider.UpperBound.Value, () => Is.EqualTo(75).Within(0.1f)); + + AddStep("Test nub pushing", () => + { + customStart.Value = 90; + }); + + AddAssert("Pushed lower bound is correct", () => rangeSlider.LowerBound.Value, () => Is.EqualTo(90).Within(0.1f)); + AddAssert("Pushed upper bound is correct", () => rangeSlider.UpperBound.Value, () => Is.EqualTo(100).Within(0.1f)); + } + } +} diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneRankingsSortTabControl.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneRankingsSortTabControl.cs index a95ae190dd..f364a48616 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneRankingsSortTabControl.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneRankingsSortTabControl.cs @@ -10,7 +10,7 @@ using osu.Game.Overlays.Rankings; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneRankingsSortTabControl : OsuTestScene + public partial class TestSceneRankingsSortTabControl : OsuTestScene { [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Green); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneRoundedButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneRoundedButton.cs index 2587960275..cbf67c49a6 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneRoundedButton.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneRoundedButton.cs @@ -9,14 +9,13 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Testing; -using osu.Game.Graphics; using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Overlays; using osu.Game.Overlays.Settings; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneRoundedButton : ThemeComparisonTestScene + public partial class TestSceneRoundedButton : ThemeComparisonTestScene { private readonly BindableBool enabled = new BindableBool(true); @@ -37,7 +36,7 @@ namespace osu.Game.Tests.Visual.UserInterface }, new SettingsButton { - Text = "Test button", + Text = "Test settings button", Anchor = Anchor.Centre, Origin = Anchor.Centre, Enabled = { BindTarget = enabled }, @@ -56,8 +55,8 @@ namespace osu.Game.Tests.Visual.UserInterface public void TestBackgroundColour() { AddStep("set red scheme", () => CreateThemedContent(OverlayColourScheme.Red)); - AddAssert("rounded button has correct colour", () => Cell(0, 1).ChildrenOfType().First().BackgroundColour == new OsuColour().Blue3); - AddAssert("settings button has correct colour", () => Cell(0, 1).ChildrenOfType().First().BackgroundColour == new OverlayColourProvider(OverlayColourScheme.Red).Highlight1); + AddAssert("rounded button has correct colour", () => Cell(0, 1).ChildrenOfType().First().BackgroundColour == new OverlayColourProvider(OverlayColourScheme.Red).Colour3); + AddAssert("settings button has correct colour", () => Cell(0, 1).ChildrenOfType().First().BackgroundColour == new OverlayColourProvider(OverlayColourScheme.Red).Colour3); } } } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneSafeAreaHandling.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneSafeAreaHandling.cs index 90365ec939..453cdd1357 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneSafeAreaHandling.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneSafeAreaHandling.cs @@ -14,7 +14,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneSafeAreaHandling : OsuGameTestScene + public partial class TestSceneSafeAreaHandling : OsuGameTestScene { private SafeAreaDefiningContainer safeAreaContainer; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneScalingContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneScalingContainer.cs index 67c47492b0..26fa26a0b8 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneScalingContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneScalingContainer.cs @@ -17,7 +17,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestSceneScalingContainer : OsuTestScene + public partial class TestSceneScalingContainer : OsuTestScene { private OsuConfigManager osuConfigManager { get; set; } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneScreenBreadcrumbControl.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneScreenBreadcrumbControl.cs index b3ee0af78b..3d35f2c9cc 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneScreenBreadcrumbControl.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneScreenBreadcrumbControl.cs @@ -11,13 +11,14 @@ using osu.Framework.Screens; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Screens; using osuTK; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestSceneScreenBreadcrumbControl : OsuTestScene + public partial class TestSceneScreenBreadcrumbControl : OsuTestScene { private readonly ScreenBreadcrumbControl breadcrumbs; private readonly OsuScreenStack screenStack; @@ -79,7 +80,7 @@ namespace osu.Game.Tests.Visual.UserInterface private void pushNext() => AddStep(@"push next screen", () => ((TestScreen)screenStack.CurrentScreen).PushNext()); private void waitForCurrent() => AddUntilStep("current screen", () => screenStack.CurrentScreen.IsCurrentScreen()); - private abstract class TestScreen : OsuScreen + private abstract partial class TestScreen : OsuScreen { protected abstract string NextTitle { get; } protected abstract TestScreen CreateNextScreen(); @@ -109,7 +110,7 @@ namespace osu.Game.Tests.Visual.UserInterface Origin = Anchor.TopCentre, Text = Title, }, - new TriangleButton + new RoundedButton { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, @@ -122,14 +123,14 @@ namespace osu.Game.Tests.Visual.UserInterface } } - private class TestScreenOne : TestScreen + private partial class TestScreenOne : TestScreen { public override string Title => @"Screen One"; protected override string NextTitle => @"Two"; protected override TestScreen CreateNextScreen() => new TestScreenTwo(); } - private class TestScreenTwo : TestScreen + private partial class TestScreenTwo : TestScreen { public override string Title => @"Screen Two"; protected override string NextTitle => @"One"; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneSectionsContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneSectionsContainer.cs index f71d797363..05fffc903d 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneSectionsContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneSectionsContainer.cs @@ -20,7 +20,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneSectionsContainer : OsuManualInputManagerTestScene + public partial class TestSceneSectionsContainer : OsuManualInputManagerTestScene { private SectionsContainer container; private float custom; @@ -196,7 +196,7 @@ namespace osu.Game.Tests.Visual.UserInterface InputManager.ScrollVerticalBy(direction); } - private class TestSection : TestBox + private partial class TestSection : TestBox { public bool Selected { @@ -210,7 +210,7 @@ namespace osu.Game.Tests.Visual.UserInterface } } - private class TestBox : Container + private partial class TestBox : Container { private readonly Box background; private readonly OsuSpriteText text; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneSegmentedGraph.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneSegmentedGraph.cs new file mode 100644 index 0000000000..80941569af --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneSegmentedGraph.cs @@ -0,0 +1,154 @@ +// Copyright (c) ppy Pty Ltd . 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.Diagnostics; +using System.Linq; +using osu.Framework.Graphics; +using osu.Game.Graphics.UserInterface; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Osu; +using osuTK; + +namespace osu.Game.Tests.Visual.UserInterface +{ + public partial class TestSceneSegmentedGraph : OsuTestScene + { + private readonly SegmentedGraph graph; + + public TestSceneSegmentedGraph() + { + Children = new Drawable[] + { + graph = new SegmentedGraph(6) + { + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(1, 0.5f), + }, + }; + + graph.TierColours = new[] + { + Colour4.Red, + Colour4.OrangeRed, + Colour4.Orange, + Colour4.Yellow, + Colour4.YellowGreen, + Colour4.Green + }; + + AddStep("values from 1-10", () => graph.Values = Enumerable.Range(1, 10).ToArray()); + AddStep("values from 1-100", () => graph.Values = Enumerable.Range(1, 100).ToArray()); + AddStep("values from 1-500", () => graph.Values = Enumerable.Range(1, 500).ToArray()); + AddStep("sin() function of size 100", () => sinFunction()); + AddStep("sin() function of size 500", () => sinFunction(500)); + AddStep("bumps of size 100", () => bumps()); + AddStep("bumps of size 500", () => bumps(500)); + AddStep("100 random values", () => randomValues()); + AddStep("500 random values", () => randomValues(500)); + AddStep("beatmap density with granularity of 200", () => beatmapDensity()); + AddStep("beatmap density with granularity of 300", () => beatmapDensity(300)); + AddStep("reversed values from 1-10", () => graph.Values = Enumerable.Range(1, 10).Reverse().ToArray()); + AddStep("change colour", () => + { + graph.TierColours = new[] + { + Colour4.White, + Colour4.LightBlue, + Colour4.Aqua, + Colour4.Blue + }; + }); + AddStep("reset colour", () => + { + graph.TierColours = new[] + { + Colour4.Red, + Colour4.OrangeRed, + Colour4.Orange, + Colour4.Yellow, + Colour4.YellowGreen, + Colour4.Green + }; + }); + } + + private void sinFunction(int size = 100) + { + const int max_value = 255; + graph.Values = new int[size]; + + float step = 2 * MathF.PI / size; + float x = 0; + + for (int i = 0; i < size; i++) + { + graph.Values[i] = (int)(max_value * MathF.Sin(x)); + x += step; + } + } + + private void bumps(int size = 100) + { + const int max_value = 255; + graph.Values = new int[size]; + + float step = 2 * MathF.PI / size; + float x = 0; + + for (int i = 0; i < size; i++) + { + graph.Values[i] = (int)(max_value * Math.Abs(MathF.Sin(x))); + x += step; + } + } + + private void randomValues(int size = 100) + { + Random rng = new Random(); + + graph.Values = new int[size]; + + for (int i = 0; i < size; i++) + { + graph.Values[i] = rng.Next(255); + } + } + + private void beatmapDensity(int granularity = 200) + { + var ruleset = new OsuRuleset(); + var beatmap = CreateBeatmap(ruleset.RulesetInfo); + IEnumerable objects = beatmap.HitObjects; + + // Taken from SongProgressGraph + graph.Values = new int[granularity]; + + if (!objects.Any()) + return; + + double firstHit = objects.First().StartTime; + double lastHit = objects.Max(o => o.GetEndTime()); + + if (lastHit == 0) + lastHit = objects.Last().StartTime; + + double interval = (lastHit - firstHit + 1) / granularity; + + foreach (var h in objects) + { + double endTime = h.GetEndTime(); + + Debug.Assert(endTime >= h.StartTime); + + int startRange = (int)((h.StartTime - firstHit) / interval); + int endRange = (int)((endTime - firstHit) / interval); + for (int i = startRange; i <= endRange; i++) + graph.Values[i]++; + } + } + } +} diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneSettingsCheckbox.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneSettingsCheckbox.cs index 466c83b1ac..a0fe5fce32 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneSettingsCheckbox.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneSettingsCheckbox.cs @@ -15,7 +15,7 @@ using osuTK; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneSettingsCheckbox : OsuTestScene + public partial class TestSceneSettingsCheckbox : OsuTestScene { [TestCase] public void TestCheckbox() @@ -56,7 +56,7 @@ namespace osu.Game.Tests.Visual.UserInterface }); } - private class OverlayColourContainer : Container + private partial class OverlayColourContainer : Container { [Cached] private OverlayColourProvider colourProvider; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneSettingsToolboxGroup.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneSettingsToolboxGroup.cs index 9fb0905a4f..f96d2feba8 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneSettingsToolboxGroup.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneSettingsToolboxGroup.cs @@ -18,7 +18,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestSceneSettingsToolboxGroup : OsuManualInputManagerTestScene + public partial class TestSceneSettingsToolboxGroup : OsuManualInputManagerTestScene { private SettingsToolboxGroup group; @@ -55,6 +55,16 @@ namespace osu.Game.Tests.Visual.UserInterface }; }); + [Test] + public void TestDisplay() + { + AddRepeatStep("toggle expanded state", () => + { + InputManager.MoveMouseTo(group.ChildrenOfType().Single()); + InputManager.Click(MouseButton.Left); + }, 5); + } + [Test] public void TestClickExpandButtonMultipleTimes() { diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneShearedButtons.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneShearedButtons.cs index 6c485aff34..118d32ee70 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneShearedButtons.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneShearedButtons.cs @@ -17,7 +17,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestSceneShearedButtons : OsuManualInputManagerTestScene + public partial class TestSceneShearedButtons : OsuManualInputManagerTestScene { [Cached] private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Green); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneShearedOverlayContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneShearedOverlayContainer.cs index c0fb315e03..fb06760568 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneShearedOverlayContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneShearedOverlayContainer.cs @@ -22,7 +22,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestSceneShearedOverlayContainer : OsuManualInputManagerTestScene + public partial class TestSceneShearedOverlayContainer : OsuManualInputManagerTestScene { private TestShearedOverlayContainer overlay; @@ -66,7 +66,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddAssert("overlay dismissed", () => overlay.State.Value == Visibility.Hidden); } - public class TestShearedOverlayContainer : ShearedOverlayContainer + public partial class TestShearedOverlayContainer : ShearedOverlayContainer { public TestShearedOverlayContainer() : base(OverlayColourScheme.Green) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneShearedOverlayHeader.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneShearedOverlayHeader.cs index 09292ee92b..aeea0681eb 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneShearedOverlayHeader.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneShearedOverlayHeader.cs @@ -12,7 +12,7 @@ using osu.Game.Overlays; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestSceneShearedOverlayHeader : OsuTestScene + public partial class TestSceneShearedOverlayHeader : OsuTestScene { [Cached] private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Green); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneShearedSearchTextBox.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneShearedSearchTextBox.cs index 78e06f7e32..0072864335 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneShearedSearchTextBox.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneShearedSearchTextBox.cs @@ -12,7 +12,7 @@ using osu.Game.Overlays; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneShearedSearchTextBox : OsuTestScene + public partial class TestSceneShearedSearchTextBox : OsuTestScene { [Test] public void TestAllColourSchemes() diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneSizePreservingSpriteText.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneSizePreservingSpriteText.cs index c4568d9aeb..7339ea7b23 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneSizePreservingSpriteText.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneSizePreservingSpriteText.cs @@ -13,7 +13,7 @@ using osu.Game.Graphics; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneSizePreservingSpriteText : OsuGridTestScene + public partial class TestSceneSizePreservingSpriteText : OsuGridTestScene { private readonly List parentContainers = new List(); private readonly List childContainers = new List(); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs index 72929a4555..6988bac2ee 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs @@ -14,7 +14,7 @@ using osuTK; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneStarRatingDisplay : OsuTestScene + public partial class TestSceneStarRatingDisplay : OsuTestScene { [TestCase(StarRatingDisplaySize.Regular)] [TestCase(StarRatingDisplaySize.Small)] diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs index 11acb31fef..88187f1808 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs @@ -13,7 +13,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneStatefulMenuItem : OsuManualInputManagerTestScene + public partial class TestSceneStatefulMenuItem : OsuManualInputManagerTestScene { [Test] public void TestTernaryRadioMenuItem() diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneSwitchButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneSwitchButton.cs index 4d90a11405..f3ab5dbff8 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneSwitchButton.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneSwitchButton.cs @@ -11,7 +11,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneSwitchButton : OsuManualInputManagerTestScene + public partial class TestSceneSwitchButton : OsuManualInputManagerTestScene { private SwitchButton switchButton; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneTabControl.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneTabControl.cs index b868abcc45..24c4ed79b1 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneTabControl.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneTabControl.cs @@ -13,7 +13,7 @@ using osuTK; namespace osu.Game.Tests.Visual.UserInterface { [Description("SongSelect filter control")] - public class TestSceneTabControl : OsuTestScene + public partial class TestSceneTabControl : OsuTestScene { public TestSceneTabControl() { diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneToggleMenuItem.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneToggleMenuItem.cs index 92cfeef369..41a6f35624 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneToggleMenuItem.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneToggleMenuItem.cs @@ -8,7 +8,7 @@ using osu.Game.Graphics.UserInterface; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneToggleMenuItem : OsuTestScene + public partial class TestSceneToggleMenuItem : OsuTestScene { public TestSceneToggleMenuItem() { diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneToolbarRulesetSelector.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneToolbarRulesetSelector.cs index de67b85c7d..651c5376b5 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneToolbarRulesetSelector.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneToolbarRulesetSelector.cs @@ -14,7 +14,7 @@ using osu.Game.Rulesets; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneToolbarRulesetSelector : OsuTestScene + public partial class TestSceneToolbarRulesetSelector : OsuTestScene { [Resolved] private RulesetStore rulesets { get; set; } @@ -65,7 +65,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddAssert("mode line has moved", () => selector.ModeButtonLine.DrawPosition.X > 0); } - private class TestSelector : ToolbarRulesetSelector + private partial class TestSelector : ToolbarRulesetSelector { public new Drawable ModeButtonLine => base.ModeButtonLine; } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneTwoLayerButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneTwoLayerButton.cs index a11efb69bd..20b0ab5801 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneTwoLayerButton.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneTwoLayerButton.cs @@ -11,7 +11,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneTwoLayerButton : OsuTestScene + public partial class TestSceneTwoLayerButton : OsuTestScene { public TestSceneTwoLayerButton() { diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs index 32f47d77e1..48fe517f8a 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs @@ -21,7 +21,7 @@ using osuTK; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneUpdateableBeatmapBackgroundSprite : OsuTestScene + public partial class TestSceneUpdateableBeatmapBackgroundSprite : OsuTestScene { protected override bool UseOnlineAPI => true; @@ -138,7 +138,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddUntilStep("all unloaded", () => !loadedBackgrounds.Any()); } - private class TestUpdateableBeatmapBackgroundSprite : UpdateableBeatmapBackgroundSprite + private partial class TestUpdateableBeatmapBackgroundSprite : UpdateableBeatmapBackgroundSprite { protected override double UnloadDelay => 2000; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapSetCover.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapSetCover.cs index 8176871481..a1a546d4a7 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapSetCover.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapSetCover.cs @@ -20,7 +20,7 @@ using osuTK; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneUpdateableBeatmapSetCover : OsuTestScene + public partial class TestSceneUpdateableBeatmapSetCover : OsuTestScene { [Test] public void TestLocal([Values] BeatmapSetCoverType coverType) @@ -139,7 +139,7 @@ namespace osu.Game.Tests.Visual.UserInterface Covers = new BeatmapSetOnlineCovers { Cover = coverUrl } }; - private class TestUpdateableOnlineBeatmapSetCover : UpdateableOnlineBeatmapSetCover + private partial class TestUpdateableOnlineBeatmapSetCover : UpdateableOnlineBeatmapSetCover { private readonly int loadDelay; @@ -163,7 +163,7 @@ namespace osu.Game.Tests.Visual.UserInterface } } - private class TestOnlineBeatmapSetCover : OnlineBeatmapSetCover + private partial class TestOnlineBeatmapSetCover : OnlineBeatmapSetCover { private readonly int loadDelay; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneUprightAspectMaintainingContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneUprightAspectMaintainingContainer.cs index 67c26829df..15570b7927 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneUprightAspectMaintainingContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneUprightAspectMaintainingContainer.cs @@ -17,7 +17,7 @@ using osuTK; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneUprightAspectMaintainingContainer : OsuGridTestScene + public partial class TestSceneUprightAspectMaintainingContainer : OsuGridTestScene { private const int rows = 3; private const int columns = 4; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneUserListToolbar.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneUserListToolbar.cs index 5e2e2ccff6..8737f7312e 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneUserListToolbar.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneUserListToolbar.cs @@ -13,7 +13,7 @@ using osuTK; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneUserListToolbar : OsuTestScene + public partial class TestSceneUserListToolbar : OsuTestScene { [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneVolumeOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneVolumeOverlay.cs index b5b4542eac..52543c68ce 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneVolumeOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneVolumeOverlay.cs @@ -9,7 +9,7 @@ using osu.Game.Overlays.Volume; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneVolumeOverlay : OsuTestScene + public partial class TestSceneVolumeOverlay : OsuTestScene { private VolumeOverlay volume; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneVolumePieces.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneVolumePieces.cs index 9ce71a5347..7cedef96e3 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneVolumePieces.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneVolumePieces.cs @@ -10,7 +10,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneVolumePieces : OsuTestScene + public partial class TestSceneVolumePieces : OsuTestScene { protected override void LoadComplete() { diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneWaveContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneWaveContainer.cs index 6a4934cf47..7851571b36 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneWaveContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneWaveContainer.cs @@ -17,7 +17,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestSceneWaveContainer : OsuTestScene + public partial class TestSceneWaveContainer : OsuTestScene { [BackgroundDependencyLoader] private void load(OsuColour colours) diff --git a/osu.Game.Tests/Visual/UserInterface/ThemeComparisonTestScene.cs b/osu.Game.Tests/Visual/UserInterface/ThemeComparisonTestScene.cs index 8fb0fd84a1..05ffd1fbef 100644 --- a/osu.Game.Tests/Visual/UserInterface/ThemeComparisonTestScene.cs +++ b/osu.Game.Tests/Visual/UserInterface/ThemeComparisonTestScene.cs @@ -14,7 +14,7 @@ using osu.Game.Overlays; namespace osu.Game.Tests.Visual.UserInterface { - public abstract class ThemeComparisonTestScene : OsuGridTestScene + public abstract partial class ThemeComparisonTestScene : OsuGridTestScene { protected ThemeComparisonTestScene() : base(1, 2) diff --git a/osu.Game.Tournament.Tests/Components/TestSceneDateTextBox.cs b/osu.Game.Tournament.Tests/Components/TestSceneDateTextBox.cs index 0e6e8f54bd..f547acd635 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneDateTextBox.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneDateTextBox.cs @@ -11,7 +11,7 @@ using osuTK.Input; namespace osu.Game.Tournament.Tests.Components { - public class TestSceneDateTextBox : OsuManualInputManagerTestScene + public partial class TestSceneDateTextBox : OsuManualInputManagerTestScene { private DateTextBox textBox; diff --git a/osu.Game.Tournament.Tests/Components/TestSceneDrawableTournamentMatch.cs b/osu.Game.Tournament.Tests/Components/TestSceneDrawableTournamentMatch.cs index 66093b80a1..cb923a1f9a 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneDrawableTournamentMatch.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneDrawableTournamentMatch.cs @@ -10,7 +10,7 @@ using osu.Game.Tournament.Screens.Ladder.Components; namespace osu.Game.Tournament.Tests.Components { - public class TestSceneDrawableTournamentMatch : TournamentTestScene + public partial class TestSceneDrawableTournamentMatch : TournamentTestScene { public TestSceneDrawableTournamentMatch() { diff --git a/osu.Game.Tournament.Tests/Components/TestSceneDrawableTournamentTeam.cs b/osu.Game.Tournament.Tests/Components/TestSceneDrawableTournamentTeam.cs index 4ea7e8008a..dd7c613c6c 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneDrawableTournamentTeam.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneDrawableTournamentTeam.cs @@ -14,7 +14,7 @@ using osu.Game.Tournament.Screens.Ladder.Components; namespace osu.Game.Tournament.Tests.Components { - public class TestSceneDrawableTournamentTeam : OsuGridTestScene + public partial class TestSceneDrawableTournamentTeam : OsuGridTestScene { public TestSceneDrawableTournamentTeam() : base(4, 3) diff --git a/osu.Game.Tournament.Tests/Components/TestSceneMatchHeader.cs b/osu.Game.Tournament.Tests/Components/TestSceneMatchHeader.cs index 55d58fef6e..2347c84ba8 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneMatchHeader.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneMatchHeader.cs @@ -11,7 +11,7 @@ using osuTK; namespace osu.Game.Tournament.Tests.Components { - public class TestSceneMatchHeader : TournamentTestScene + public partial class TestSceneMatchHeader : TournamentTestScene { public TestSceneMatchHeader() { diff --git a/osu.Game.Tournament.Tests/Components/TestSceneMatchScoreDisplay.cs b/osu.Game.Tournament.Tests/Components/TestSceneMatchScoreDisplay.cs index 53301c34d4..9b1fc17591 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneMatchScoreDisplay.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneMatchScoreDisplay.cs @@ -11,7 +11,7 @@ using osu.Game.Tournament.Screens.Gameplay.Components; namespace osu.Game.Tournament.Tests.Components { - public class TestSceneMatchScoreDisplay : TournamentTestScene + public partial class TestSceneMatchScoreDisplay : TournamentTestScene { [Cached(Type = typeof(MatchIPCInfo))] private MatchIPCInfo matchInfo = new MatchIPCInfo(); diff --git a/osu.Game.Tournament.Tests/Components/TestSceneRoundDisplay.cs b/osu.Game.Tournament.Tests/Components/TestSceneRoundDisplay.cs index 514a797068..cb22e7e7c7 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneRoundDisplay.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneRoundDisplay.cs @@ -9,7 +9,7 @@ using osu.Game.Tournament.Models; namespace osu.Game.Tournament.Tests.Components { - public class TestSceneRoundDisplay : TournamentTestScene + public partial class TestSceneRoundDisplay : TournamentTestScene { public TestSceneRoundDisplay() { diff --git a/osu.Game.Tournament.Tests/Components/TestSceneSongBar.cs b/osu.Game.Tournament.Tests/Components/TestSceneSongBar.cs index 992baa48a3..f793c33878 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneSongBar.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneSongBar.cs @@ -14,7 +14,7 @@ using osu.Game.Tournament.Models; namespace osu.Game.Tournament.Tests.Components { [TestFixture] - public class TestSceneSongBar : OsuTestScene + public partial class TestSceneSongBar : OsuTestScene { [Cached] private readonly LadderInfo ladder = new LadderInfo(); diff --git a/osu.Game.Tournament.Tests/Components/TestSceneTournamentBeatmapPanel.cs b/osu.Game.Tournament.Tests/Components/TestSceneTournamentBeatmapPanel.cs index adfe048ce4..057566d426 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneTournamentBeatmapPanel.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneTournamentBeatmapPanel.cs @@ -14,7 +14,7 @@ using osu.Game.Tournament.Models; namespace osu.Game.Tournament.Tests.Components { - public class TestSceneTournamentBeatmapPanel : TournamentTestScene + public partial class TestSceneTournamentBeatmapPanel : TournamentTestScene { /// /// Warning: the below API instance is actually the online API, rather than the dummy API provided by the test. diff --git a/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs b/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs index eb8b0dfbe6..d9ae8df651 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs @@ -15,7 +15,7 @@ using osu.Game.Tournament.Models; namespace osu.Game.Tournament.Tests.Components { - public class TestSceneTournamentMatchChatDisplay : OsuTestScene + public partial class TestSceneTournamentMatchChatDisplay : OsuTestScene { private readonly Channel testChannel = new Channel(); private readonly Channel testChannel2 = new Channel(); diff --git a/osu.Game.Tournament.Tests/Components/TestSceneTournamentModDisplay.cs b/osu.Game.Tournament.Tests/Components/TestSceneTournamentModDisplay.cs index 263617ddf7..cea4306ff8 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneTournamentModDisplay.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneTournamentModDisplay.cs @@ -16,7 +16,7 @@ using osuTK; namespace osu.Game.Tournament.Tests.Components { - public class TestSceneTournamentModDisplay : TournamentTestScene + public partial class TestSceneTournamentModDisplay : TournamentTestScene { [Resolved] private IAPIProvider api { get; set; } diff --git a/osu.Game.Tournament.Tests/NonVisual/DataLoadTest.cs b/osu.Game.Tournament.Tests/NonVisual/DataLoadTest.cs index df77b31191..256a984a7c 100644 --- a/osu.Game.Tournament.Tests/NonVisual/DataLoadTest.cs +++ b/osu.Game.Tournament.Tests/NonVisual/DataLoadTest.cs @@ -17,7 +17,7 @@ using osu.Game.Tests; namespace osu.Game.Tournament.Tests.NonVisual { - public class DataLoadTest : TournamentHostTest + public partial class DataLoadTest : TournamentHostTest { [Test] public void TestRulesetGetsValidOnlineID() @@ -78,7 +78,7 @@ namespace osu.Game.Tournament.Tests.NonVisual } } - public class TestTournament : TournamentGameBase + public partial class TestTournament : TournamentGameBase { private readonly bool resetRuleset; private readonly Action runOnLoadComplete; diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneDrawingsScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneDrawingsScreen.cs index e0c6aaf834..10ed850002 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneDrawingsScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneDrawingsScreen.cs @@ -12,7 +12,7 @@ using osu.Game.Tournament.Screens.Drawings; namespace osu.Game.Tournament.Tests.Screens { - public class TestSceneDrawingsScreen : TournamentTestScene + public partial class TestSceneDrawingsScreen : TournamentTestScene { [BackgroundDependencyLoader] private void load(Storage storage) diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneGameplayScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneGameplayScreen.cs index 4fc15c365f..f127a930a6 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneGameplayScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneGameplayScreen.cs @@ -15,7 +15,7 @@ using osu.Game.Tournament.Screens.Gameplay.Components; namespace osu.Game.Tournament.Tests.Screens { - public class TestSceneGameplayScreen : TournamentTestScene + public partial class TestSceneGameplayScreen : TournamentTestScene { [Cached] private TournamentMatchChatDisplay chat = new TournamentMatchChatDisplay { Width = 0.5f }; diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneLadderEditorScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneLadderEditorScreen.cs index 7aade4fb82..5c4e1b2a5a 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneLadderEditorScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneLadderEditorScreen.cs @@ -10,7 +10,7 @@ using osu.Game.Tournament.Screens.Editors; namespace osu.Game.Tournament.Tests.Screens { - public class TestSceneLadderEditorScreen : TournamentTestScene + public partial class TestSceneLadderEditorScreen : TournamentTestScene { [BackgroundDependencyLoader] private void load() diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneLadderScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneLadderScreen.cs index 1f817a1b22..20f729bb8d 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneLadderScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneLadderScreen.cs @@ -10,7 +10,7 @@ using osu.Game.Tournament.Screens.Ladder; namespace osu.Game.Tournament.Tests.Screens { - public class TestSceneLadderScreen : TournamentTestScene + public partial class TestSceneLadderScreen : TournamentTestScene { [BackgroundDependencyLoader] private void load() diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneMapPoolScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneMapPoolScreen.cs index e0f91cc359..5695cb5574 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneMapPoolScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneMapPoolScreen.cs @@ -14,7 +14,7 @@ using osu.Game.Tournament.Screens.MapPool; namespace osu.Game.Tournament.Tests.Screens { - public class TestSceneMapPoolScreen : TournamentTestScene + public partial class TestSceneMapPoolScreen : TournamentTestScene { private MapPoolScreen screen; diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneRoundEditorScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneRoundEditorScreen.cs index 656663ece7..ebeb69012d 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneRoundEditorScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneRoundEditorScreen.cs @@ -7,7 +7,7 @@ using osu.Game.Tournament.Screens.Editors; namespace osu.Game.Tournament.Tests.Screens { - public class TestSceneRoundEditorScreen : TournamentTestScene + public partial class TestSceneRoundEditorScreen : TournamentTestScene { public TestSceneRoundEditorScreen() { diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneScheduleScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneScheduleScreen.cs index 6061314796..fd0de3d63a 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneScheduleScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneScheduleScreen.cs @@ -12,7 +12,7 @@ using osu.Game.Tournament.Screens.Schedule; namespace osu.Game.Tournament.Tests.Screens { - public class TestSceneScheduleScreen : TournamentTestScene + public partial class TestSceneScheduleScreen : TournamentTestScene { [BackgroundDependencyLoader] private void load() diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneSeedingEditorScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneSeedingEditorScreen.cs index 94321e708f..cfb533149d 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneSeedingEditorScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneSeedingEditorScreen.cs @@ -9,7 +9,7 @@ using osu.Game.Tournament.Screens.Editors; namespace osu.Game.Tournament.Tests.Screens { - public class TestSceneSeedingEditorScreen : TournamentTestScene + public partial class TestSceneSeedingEditorScreen : TournamentTestScene { [Cached] private readonly LadderInfo ladder = new LadderInfo(); diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneSeedingScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneSeedingScreen.cs index 2581ed4b7e..c9620bc0b9 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneSeedingScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneSeedingScreen.cs @@ -14,7 +14,7 @@ using osu.Game.Tournament.Screens.TeamIntro; namespace osu.Game.Tournament.Tests.Screens { - public class TestSceneSeedingScreen : TournamentTestScene + public partial class TestSceneSeedingScreen : TournamentTestScene { [Cached] private readonly LadderInfo ladder = new LadderInfo diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneSetupScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneSetupScreen.cs index 9070590b15..84c8b9a141 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneSetupScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneSetupScreen.cs @@ -8,7 +8,7 @@ using osu.Game.Tournament.Screens.Setup; namespace osu.Game.Tournament.Tests.Screens { - public class TestSceneSetupScreen : TournamentTestScene + public partial class TestSceneSetupScreen : TournamentTestScene { [BackgroundDependencyLoader] private void load() diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneShowcaseScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneShowcaseScreen.cs index 44e7c48887..6287679c27 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneShowcaseScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneShowcaseScreen.cs @@ -8,7 +8,7 @@ using osu.Game.Tournament.Screens.Showcase; namespace osu.Game.Tournament.Tests.Screens { - public class TestSceneShowcaseScreen : TournamentTestScene + public partial class TestSceneShowcaseScreen : TournamentTestScene { [BackgroundDependencyLoader] private void load() diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneStablePathSelectScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneStablePathSelectScreen.cs index 27e5c59600..dbd9cb2817 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneStablePathSelectScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneStablePathSelectScreen.cs @@ -7,14 +7,14 @@ using osu.Game.Tournament.Screens.Setup; namespace osu.Game.Tournament.Tests.Screens { - public class TestSceneStablePathSelectScreen : TournamentTestScene + public partial class TestSceneStablePathSelectScreen : TournamentTestScene { public TestSceneStablePathSelectScreen() { AddStep("Add screen", () => Add(new StablePathSelectTestScreen())); } - private class StablePathSelectTestScreen : StablePathSelectScreen + private partial class StablePathSelectTestScreen : StablePathSelectScreen { protected override void ChangePath() { diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneTeamEditorScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneTeamEditorScreen.cs index b38430ece5..63c08800ad 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneTeamEditorScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneTeamEditorScreen.cs @@ -7,7 +7,7 @@ using osu.Game.Tournament.Screens.Editors; namespace osu.Game.Tournament.Tests.Screens { - public class TestSceneTeamEditorScreen : TournamentTestScene + public partial class TestSceneTeamEditorScreen : TournamentTestScene { public TestSceneTeamEditorScreen() { diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneTeamIntroScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneTeamIntroScreen.cs index fccc09c14e..5c26bc203c 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneTeamIntroScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneTeamIntroScreen.cs @@ -11,7 +11,7 @@ using osu.Game.Tournament.Screens.TeamIntro; namespace osu.Game.Tournament.Tests.Screens { - public class TestSceneTeamIntroScreen : TournamentTestScene + public partial class TestSceneTeamIntroScreen : TournamentTestScene { [Cached] private readonly LadderInfo ladder = new LadderInfo(); diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneTeamWinScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneTeamWinScreen.cs index 3b48c2eee5..43e16873c6 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneTeamWinScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneTeamWinScreen.cs @@ -10,7 +10,7 @@ using osu.Game.Tournament.Screens.TeamWin; namespace osu.Game.Tournament.Tests.Screens { - public class TestSceneTeamWinScreen : TournamentTestScene + public partial class TestSceneTeamWinScreen : TournamentTestScene { [Test] public void TestBasic() diff --git a/osu.Game.Tournament.Tests/TestSceneTournamentSceneManager.cs b/osu.Game.Tournament.Tests/TestSceneTournamentSceneManager.cs index e961a3c670..859d0591c3 100644 --- a/osu.Game.Tournament.Tests/TestSceneTournamentSceneManager.cs +++ b/osu.Game.Tournament.Tests/TestSceneTournamentSceneManager.cs @@ -7,7 +7,7 @@ using osu.Framework.Allocation; namespace osu.Game.Tournament.Tests { - public class TestSceneTournamentSceneManager : TournamentTestScene + public partial class TestSceneTournamentSceneManager : TournamentTestScene { [BackgroundDependencyLoader] private void load() diff --git a/osu.Game.Tournament.Tests/TournamentTestBrowser.cs b/osu.Game.Tournament.Tests/TournamentTestBrowser.cs index 1adbe07709..1a9122c117 100644 --- a/osu.Game.Tournament.Tests/TournamentTestBrowser.cs +++ b/osu.Game.Tournament.Tests/TournamentTestBrowser.cs @@ -9,7 +9,7 @@ using osu.Game.Graphics.Backgrounds; namespace osu.Game.Tournament.Tests { - public class TournamentTestBrowser : TournamentGameBase + public partial class TournamentTestBrowser : TournamentGameBase { protected override void LoadComplete() { diff --git a/osu.Game.Tournament.Tests/TournamentTestScene.cs b/osu.Game.Tournament.Tests/TournamentTestScene.cs index b440034f34..cab78422a2 100644 --- a/osu.Game.Tournament.Tests/TournamentTestScene.cs +++ b/osu.Game.Tournament.Tests/TournamentTestScene.cs @@ -18,7 +18,7 @@ using osu.Game.Tournament.Models; namespace osu.Game.Tournament.Tests { - public abstract class TournamentTestScene : OsuTestScene + public abstract partial class TournamentTestScene : OsuTestScene { private TournamentMatch match; @@ -165,7 +165,7 @@ namespace osu.Game.Tournament.Tests protected override ITestSceneTestRunner CreateRunner() => new TournamentTestSceneTestRunner(); - public class TournamentTestSceneTestRunner : TournamentGameBase, ITestSceneTestRunner + public partial class TournamentTestSceneTestRunner : TournamentGameBase, ITestSceneTestRunner { private TestSceneTestRunner.TestRunner runner; diff --git a/osu.Game.Tournament/Components/ControlPanel.cs b/osu.Game.Tournament/Components/ControlPanel.cs index f43d494d5a..c3e66e80eb 100644 --- a/osu.Game.Tournament/Components/ControlPanel.cs +++ b/osu.Game.Tournament/Components/ControlPanel.cs @@ -16,7 +16,7 @@ namespace osu.Game.Tournament.Components /// An element anchored to the right-hand area of a screen that provides streamer level controls. /// Should be off-screen. /// - public class ControlPanel : Container + public partial class ControlPanel : Container { private readonly FillFlowContainer buttons; @@ -57,7 +57,7 @@ namespace osu.Game.Tournament.Components }; } - public class Spacer : CompositeDrawable + public partial class Spacer : CompositeDrawable { public Spacer(float height = 20) { diff --git a/osu.Game.Tournament/Components/DateTextBox.cs b/osu.Game.Tournament/Components/DateTextBox.cs index 76d12a6b03..192d8c9fd1 100644 --- a/osu.Game.Tournament/Components/DateTextBox.cs +++ b/osu.Game.Tournament/Components/DateTextBox.cs @@ -10,7 +10,7 @@ using osu.Game.Overlays.Settings; namespace osu.Game.Tournament.Components { - public class DateTextBox : SettingsTextBox + public partial class DateTextBox : SettingsTextBox { public new Bindable Current { diff --git a/osu.Game.Tournament/Components/DrawableTeamFlag.cs b/osu.Game.Tournament/Components/DrawableTeamFlag.cs index 348fd8cd76..317d685ee7 100644 --- a/osu.Game.Tournament/Components/DrawableTeamFlag.cs +++ b/osu.Game.Tournament/Components/DrawableTeamFlag.cs @@ -15,7 +15,7 @@ using osuTK; namespace osu.Game.Tournament.Components { - public class DrawableTeamFlag : Container + public partial class DrawableTeamFlag : Container { private readonly TournamentTeam team; diff --git a/osu.Game.Tournament/Components/DrawableTeamHeader.cs b/osu.Game.Tournament/Components/DrawableTeamHeader.cs index ceaf8d5e6e..1648e7373b 100644 --- a/osu.Game.Tournament/Components/DrawableTeamHeader.cs +++ b/osu.Game.Tournament/Components/DrawableTeamHeader.cs @@ -8,7 +8,7 @@ using osuTK; namespace osu.Game.Tournament.Components { - public class DrawableTeamHeader : TournamentSpriteTextWithBackground + public partial class DrawableTeamHeader : TournamentSpriteTextWithBackground { public DrawableTeamHeader(TeamColour colour) { diff --git a/osu.Game.Tournament/Components/DrawableTeamTitle.cs b/osu.Game.Tournament/Components/DrawableTeamTitle.cs index e64e08a921..68cc46be19 100644 --- a/osu.Game.Tournament/Components/DrawableTeamTitle.cs +++ b/osu.Game.Tournament/Components/DrawableTeamTitle.cs @@ -10,7 +10,7 @@ using osu.Game.Tournament.Models; namespace osu.Game.Tournament.Components { - public class DrawableTeamTitle : TournamentSpriteTextWithBackground + public partial class DrawableTeamTitle : TournamentSpriteTextWithBackground { private readonly TournamentTeam team; diff --git a/osu.Game.Tournament/Components/DrawableTeamTitleWithHeader.cs b/osu.Game.Tournament/Components/DrawableTeamTitleWithHeader.cs index dbc9fa7f16..27113b0d21 100644 --- a/osu.Game.Tournament/Components/DrawableTeamTitleWithHeader.cs +++ b/osu.Game.Tournament/Components/DrawableTeamTitleWithHeader.cs @@ -10,7 +10,7 @@ using osuTK; namespace osu.Game.Tournament.Components { - public class DrawableTeamTitleWithHeader : CompositeDrawable + public partial class DrawableTeamTitleWithHeader : CompositeDrawable { public DrawableTeamTitleWithHeader(TournamentTeam team, TeamColour colour) { diff --git a/osu.Game.Tournament/Components/DrawableTeamWithPlayers.cs b/osu.Game.Tournament/Components/DrawableTeamWithPlayers.cs index 0bb35d534c..9606670ad8 100644 --- a/osu.Game.Tournament/Components/DrawableTeamWithPlayers.cs +++ b/osu.Game.Tournament/Components/DrawableTeamWithPlayers.cs @@ -13,7 +13,7 @@ using osuTK.Graphics; namespace osu.Game.Tournament.Components { - public class DrawableTeamWithPlayers : CompositeDrawable + public partial class DrawableTeamWithPlayers : CompositeDrawable { public DrawableTeamWithPlayers(TournamentTeam team, TeamColour colour) { diff --git a/osu.Game.Tournament/Components/DrawableTournamentHeaderLogo.cs b/osu.Game.Tournament/Components/DrawableTournamentHeaderLogo.cs index 9f5b825e30..c83fceb01d 100644 --- a/osu.Game.Tournament/Components/DrawableTournamentHeaderLogo.cs +++ b/osu.Game.Tournament/Components/DrawableTournamentHeaderLogo.cs @@ -11,7 +11,7 @@ using osu.Framework.Graphics.Textures; namespace osu.Game.Tournament.Components { - public class DrawableTournamentHeaderLogo : CompositeDrawable + public partial class DrawableTournamentHeaderLogo : CompositeDrawable { public DrawableTournamentHeaderLogo() { @@ -21,7 +21,7 @@ namespace osu.Game.Tournament.Components RelativeSizeAxes = Axes.X; } - private class LogoSprite : Sprite + private partial class LogoSprite : Sprite { [BackgroundDependencyLoader] private void load(TextureStore textures) diff --git a/osu.Game.Tournament/Components/DrawableTournamentHeaderText.cs b/osu.Game.Tournament/Components/DrawableTournamentHeaderText.cs index 67eeee7de4..7a1f448cb4 100644 --- a/osu.Game.Tournament/Components/DrawableTournamentHeaderText.cs +++ b/osu.Game.Tournament/Components/DrawableTournamentHeaderText.cs @@ -11,7 +11,7 @@ using osu.Framework.Graphics.Textures; namespace osu.Game.Tournament.Components { - public class DrawableTournamentHeaderText : CompositeDrawable + public partial class DrawableTournamentHeaderText : CompositeDrawable { public DrawableTournamentHeaderText(bool center = true) { @@ -25,7 +25,7 @@ namespace osu.Game.Tournament.Components RelativeSizeAxes = Axes.X; } - private class TextSprite : Sprite + private partial class TextSprite : Sprite { [BackgroundDependencyLoader] private void load(TextureStore textures) diff --git a/osu.Game.Tournament/Components/DrawableTournamentTeam.cs b/osu.Game.Tournament/Components/DrawableTournamentTeam.cs index eb1dde21e7..0036f5f115 100644 --- a/osu.Game.Tournament/Components/DrawableTournamentTeam.cs +++ b/osu.Game.Tournament/Components/DrawableTournamentTeam.cs @@ -12,7 +12,7 @@ using osu.Game.Tournament.Models; namespace osu.Game.Tournament.Components { - public abstract class DrawableTournamentTeam : CompositeDrawable + public abstract partial class DrawableTournamentTeam : CompositeDrawable { public readonly TournamentTeam Team; diff --git a/osu.Game.Tournament/Components/IPCErrorDialog.cs b/osu.Game.Tournament/Components/IPCErrorDialog.cs index a32e01fb48..995bbffffc 100644 --- a/osu.Game.Tournament/Components/IPCErrorDialog.cs +++ b/osu.Game.Tournament/Components/IPCErrorDialog.cs @@ -8,7 +8,7 @@ using osu.Game.Overlays.Dialog; namespace osu.Game.Tournament.Components { - public class IPCErrorDialog : PopupDialog + public partial class IPCErrorDialog : PopupDialog { public IPCErrorDialog(string headerText, string bodyText) { diff --git a/osu.Game.Tournament/Components/RoundDisplay.cs b/osu.Game.Tournament/Components/RoundDisplay.cs index 98ef09aa58..6018cc6ffb 100644 --- a/osu.Game.Tournament/Components/RoundDisplay.cs +++ b/osu.Game.Tournament/Components/RoundDisplay.cs @@ -10,7 +10,7 @@ using osu.Game.Tournament.Models; namespace osu.Game.Tournament.Components { - public class RoundDisplay : CompositeDrawable + public partial class RoundDisplay : CompositeDrawable { public RoundDisplay(TournamentMatch match) { diff --git a/osu.Game.Tournament/Components/SongBar.cs b/osu.Game.Tournament/Components/SongBar.cs index a9056166be..aeceece160 100644 --- a/osu.Game.Tournament/Components/SongBar.cs +++ b/osu.Game.Tournament/Components/SongBar.cs @@ -22,7 +22,7 @@ using osuTK.Graphics; namespace osu.Game.Tournament.Components { - public class SongBar : CompositeDrawable + public partial class SongBar : CompositeDrawable { private TournamentBeatmap beatmap; @@ -242,7 +242,7 @@ namespace osu.Game.Tournament.Components }; } - public class DiffPiece : TextFlowContainer + public partial class DiffPiece : TextFlowContainer { public DiffPiece(params (string heading, string content)[] tuples) { diff --git a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs index 462743cc3d..1157b50377 100644 --- a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs +++ b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs @@ -19,7 +19,7 @@ using osuTK.Graphics; namespace osu.Game.Tournament.Components { - public class TournamentBeatmapPanel : CompositeDrawable + public partial class TournamentBeatmapPanel : CompositeDrawable { public readonly TournamentBeatmap Beatmap; @@ -32,7 +32,7 @@ namespace osu.Game.Tournament.Components public TournamentBeatmapPanel(TournamentBeatmap beatmap, string mod = null) { - if (beatmap == null) throw new ArgumentNullException(nameof(beatmap)); + ArgumentNullException.ThrowIfNull(beatmap); Beatmap = beatmap; this.mod = mod; diff --git a/osu.Game.Tournament/Components/TournamentMatchChatDisplay.cs b/osu.Game.Tournament/Components/TournamentMatchChatDisplay.cs index ca2b400e8b..8a0dd6e336 100644 --- a/osu.Game.Tournament/Components/TournamentMatchChatDisplay.cs +++ b/osu.Game.Tournament/Components/TournamentMatchChatDisplay.cs @@ -15,7 +15,7 @@ using osu.Game.Tournament.Models; namespace osu.Game.Tournament.Components { - public class TournamentMatchChatDisplay : StandAloneChatDisplay + public partial class TournamentMatchChatDisplay : StandAloneChatDisplay { private readonly Bindable chatChannel = new Bindable(); @@ -75,7 +75,7 @@ namespace osu.Game.Tournament.Components protected override StandAloneDrawableChannel CreateDrawableChannel(Channel channel) => new MatchChannel(channel); - public class MatchChannel : StandAloneDrawableChannel + public partial class MatchChannel : StandAloneDrawableChannel { public MatchChannel(Channel channel) : base(channel) @@ -84,7 +84,7 @@ namespace osu.Game.Tournament.Components } } - protected class MatchMessage : StandAloneMessage + protected partial class MatchMessage : StandAloneMessage { public MatchMessage(Message message) : base(message) diff --git a/osu.Game.Tournament/Components/TournamentModIcon.cs b/osu.Game.Tournament/Components/TournamentModIcon.cs index 6697a993c3..76b6151519 100644 --- a/osu.Game.Tournament/Components/TournamentModIcon.cs +++ b/osu.Game.Tournament/Components/TournamentModIcon.cs @@ -18,7 +18,7 @@ namespace osu.Game.Tournament.Components /// /// Mod icon displayed in tournament usages, allowing user overridden graphics. /// - public class TournamentModIcon : CompositeDrawable + public partial class TournamentModIcon : CompositeDrawable { private readonly string modAcronym; diff --git a/osu.Game.Tournament/Components/TournamentSpriteTextWithBackground.cs b/osu.Game.Tournament/Components/TournamentSpriteTextWithBackground.cs index b088670caa..3a16662463 100644 --- a/osu.Game.Tournament/Components/TournamentSpriteTextWithBackground.cs +++ b/osu.Game.Tournament/Components/TournamentSpriteTextWithBackground.cs @@ -10,7 +10,7 @@ using osu.Game.Graphics; namespace osu.Game.Tournament.Components { - public class TournamentSpriteTextWithBackground : CompositeDrawable + public partial class TournamentSpriteTextWithBackground : CompositeDrawable { public readonly TournamentSpriteText Text; diff --git a/osu.Game.Tournament/Components/TourneyVideo.cs b/osu.Game.Tournament/Components/TourneyVideo.cs index 2e79998e66..b9ce84b735 100644 --- a/osu.Game.Tournament/Components/TourneyVideo.cs +++ b/osu.Game.Tournament/Components/TourneyVideo.cs @@ -15,7 +15,7 @@ using osu.Game.Tournament.IO; namespace osu.Game.Tournament.Components { - public class TourneyVideo : CompositeDrawable + public partial class TourneyVideo : CompositeDrawable { private readonly string filename; private readonly bool drawFallbackGradient; diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index ad564c58c3..7babb3ea5a 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -22,7 +22,7 @@ using osu.Game.Tournament.Models; namespace osu.Game.Tournament.IPC { - public class FileBasedIPC : MatchIPCInfo + public partial class FileBasedIPC : MatchIPCInfo { public Storage IPCStorage { get; private set; } @@ -127,7 +127,7 @@ namespace osu.Game.Tournament.IPC using (var stream = IPCStorage.GetStream(file_ipc_state_filename)) using (var sr = new StreamReader(stream)) { - State.Value = (TourneyState)Enum.Parse(typeof(TourneyState), sr.ReadLine().AsNonNull()); + State.Value = Enum.Parse(sr.ReadLine().AsNonNull()); } } catch (Exception) @@ -245,8 +245,10 @@ namespace osu.Game.Tournament.IPC { string stableInstallPath; +#pragma warning disable CA1416 using (RegistryKey key = Registry.ClassesRoot.OpenSubKey("osu")) stableInstallPath = key?.OpenSubKey(@"shell\open\command")?.GetValue(string.Empty)?.ToString()?.Split('"')[1].Replace("osu!.exe", ""); +#pragma warning restore CA1416 if (ipcFileExistsInDirectory(stableInstallPath)) return stableInstallPath; diff --git a/osu.Game.Tournament/IPC/MatchIPCInfo.cs b/osu.Game.Tournament/IPC/MatchIPCInfo.cs index f438923803..3bf790d58e 100644 --- a/osu.Game.Tournament/IPC/MatchIPCInfo.cs +++ b/osu.Game.Tournament/IPC/MatchIPCInfo.cs @@ -10,7 +10,7 @@ using osu.Game.Tournament.Models; namespace osu.Game.Tournament.IPC { - public class MatchIPCInfo : Component + public partial class MatchIPCInfo : Component { public Bindable Beatmap { get; } = new Bindable(); public Bindable Mods { get; } = new Bindable(); diff --git a/osu.Game.Tournament/SaveChangesOverlay.cs b/osu.Game.Tournament/SaveChangesOverlay.cs index b5e08fc005..1bc576bc63 100644 --- a/osu.Game.Tournament/SaveChangesOverlay.cs +++ b/osu.Game.Tournament/SaveChangesOverlay.cs @@ -13,7 +13,7 @@ using osuTK; namespace osu.Game.Tournament { - internal class SaveChangesOverlay : CompositeDrawable + internal partial class SaveChangesOverlay : CompositeDrawable { [Resolved] private TournamentGame tournamentGame { get; set; } = null!; @@ -70,7 +70,7 @@ namespace osu.Game.Tournament private async Task checkForChanges() { - string serialisedLadder = await Task.Run(() => tournamentGame.GetSerialisedLadder()); + string serialisedLadder = await Task.Run(() => tournamentGame.GetSerialisedLadder()).ConfigureAwait(false); // If a save hasn't been triggered by the user yet, populate the initial value lastSerialisedLadder ??= serialisedLadder; diff --git a/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs b/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs index 763f576afe..6f7234b8c3 100644 --- a/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs +++ b/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs @@ -13,7 +13,7 @@ using osu.Game.Tournament.Models; namespace osu.Game.Tournament.Screens { - public abstract class BeatmapInfoScreen : TournamentMatchScreen + public abstract partial class BeatmapInfoScreen : TournamentMatchScreen { protected readonly SongBar SongBar; diff --git a/osu.Game.Tournament/Screens/Drawings/Components/Group.cs b/osu.Game.Tournament/Screens/Drawings/Components/Group.cs index 0b1a5328ab..b397f807f0 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/Group.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/Group.cs @@ -16,7 +16,7 @@ using osuTK.Graphics; namespace osu.Game.Tournament.Screens.Drawings.Components { - public class Group : Container + public partial class Group : Container { public readonly string GroupName; diff --git a/osu.Game.Tournament/Screens/Drawings/Components/GroupContainer.cs b/osu.Game.Tournament/Screens/Drawings/Components/GroupContainer.cs index 62b3c4e8ff..37e15b7e45 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/GroupContainer.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/GroupContainer.cs @@ -14,7 +14,7 @@ using osuTK; namespace osu.Game.Tournament.Screens.Drawings.Components { - public class GroupContainer : Container + public partial class GroupContainer : Container { private readonly List groups = new List(); diff --git a/osu.Game.Tournament/Screens/Drawings/Components/GroupTeam.cs b/osu.Game.Tournament/Screens/Drawings/Components/GroupTeam.cs index 80bdad8b7b..167a576424 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/GroupTeam.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/GroupTeam.cs @@ -12,7 +12,7 @@ using osuTK; namespace osu.Game.Tournament.Screens.Drawings.Components { - public class GroupTeam : DrawableTournamentTeam + public partial class GroupTeam : DrawableTournamentTeam { private readonly FillFlowContainer innerContainer; diff --git a/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs b/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs index 8092c24ccb..c2b15dd3e9 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs @@ -20,7 +20,7 @@ using osuTK.Graphics; namespace osu.Game.Tournament.Screens.Drawings.Components { - public class ScrollingTeamContainer : Container + public partial class ScrollingTeamContainer : Container { public event Action OnScrollStarted; public event Action OnSelected; @@ -309,7 +309,7 @@ namespace osu.Game.Tournament.Screens.Drawings.Components Scrolling } - public class ScrollingTeam : DrawableTournamentTeam + public partial class ScrollingTeam : DrawableTournamentTeam { public const float WIDTH = 58; public const float HEIGHT = 44; diff --git a/osu.Game.Tournament/Screens/Drawings/Components/StorageBackedTeamList.cs b/osu.Game.Tournament/Screens/Drawings/Components/StorageBackedTeamList.cs index c230607343..74afb42c1a 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/StorageBackedTeamList.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/StorageBackedTeamList.cs @@ -45,7 +45,7 @@ namespace osu.Game.Tournament.Screens.Drawings.Components continue; // ReSharper disable once PossibleNullReferenceException - string[] split = line.Split(':'); + string[] split = line.Split(':', StringSplitOptions.TrimEntries); if (split.Length < 2) { @@ -55,9 +55,9 @@ namespace osu.Game.Tournament.Screens.Drawings.Components teams.Add(new TournamentTeam { - FullName = { Value = split[1].Trim(), }, - Acronym = { Value = split.Length >= 3 ? split[2].Trim() : null, }, - FlagName = { Value = split[0].Trim() } + FullName = { Value = split[1], }, + Acronym = { Value = split.Length >= 3 ? split[2] : null, }, + FlagName = { Value = split[0] } }); } } diff --git a/osu.Game.Tournament/Screens/Drawings/Components/VisualiserContainer.cs b/osu.Game.Tournament/Screens/Drawings/Components/VisualiserContainer.cs index 663162d1ca..676eec14cd 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/VisualiserContainer.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/VisualiserContainer.cs @@ -14,7 +14,7 @@ using osu.Framework.Utils; namespace osu.Game.Tournament.Screens.Drawings.Components { - public class VisualiserContainer : Container + public partial class VisualiserContainer : Container { /// /// Number of lines in the visualiser. @@ -61,7 +61,7 @@ namespace osu.Game.Tournament.Screens.Drawings.Components allLines.Remove(allLines.First()); } - private class VisualiserLine : Container + private partial class VisualiserLine : Container { /// /// Time offset. diff --git a/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs b/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs index 5ac25f97b5..23d0edf26e 100644 --- a/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs +++ b/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs @@ -24,7 +24,7 @@ using osuTK.Graphics; namespace osu.Game.Tournament.Screens.Drawings { - public class DrawingsScreen : TournamentScreen + public partial class DrawingsScreen : TournamentScreen { private const string results_filename = "drawings_results.txt"; diff --git a/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs index 4261828df2..4ee3108034 100644 --- a/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs @@ -23,7 +23,7 @@ using osuTK.Graphics; namespace osu.Game.Tournament.Screens.Editors { [Cached] - public class LadderEditorScreen : LadderScreen, IHasContextMenu + public partial class LadderEditorScreen : LadderScreen, IHasContextMenu { [Cached] private LadderEditorInfo editorInfo = new LadderEditorInfo(); @@ -86,7 +86,7 @@ namespace osu.Game.Tournament.Screens.Editors MatchesContainer.FirstOrDefault(p => p.Match == match)?.Remove(); } - private class JoinVisualiser : CompositeDrawable + private partial class JoinVisualiser : CompositeDrawable { private readonly Container matchesContainer; public readonly TournamentMatch Source; diff --git a/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs index 0bd5ddb257..75131c282d 100644 --- a/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs @@ -20,11 +20,11 @@ using osuTK; namespace osu.Game.Tournament.Screens.Editors { - public class RoundEditorScreen : TournamentEditorScreen + public partial class RoundEditorScreen : TournamentEditorScreen { protected override BindableList Storage => LadderInfo.Rounds; - public class RoundRow : CompositeDrawable, IModelBacked + public partial class RoundRow : CompositeDrawable, IModelBacked { public TournamentRound Model { get; } @@ -113,7 +113,7 @@ namespace osu.Game.Tournament.Screens.Editors AutoSizeAxes = Axes.Y; } - public class RoundBeatmapEditor : CompositeDrawable + public partial class RoundBeatmapEditor : CompositeDrawable { private readonly TournamentRound round; private readonly FillFlowContainer flow; @@ -141,7 +141,7 @@ namespace osu.Game.Tournament.Screens.Editors flow.Add(new RoundBeatmapRow(round, user)); } - public class RoundBeatmapRow : CompositeDrawable + public partial class RoundBeatmapRow : CompositeDrawable { public RoundBeatmap Model { get; } diff --git a/osu.Game.Tournament/Screens/Editors/SeedingEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/SeedingEditorScreen.cs index 348661e2a3..a4358b4396 100644 --- a/osu.Game.Tournament/Screens/Editors/SeedingEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/SeedingEditorScreen.cs @@ -20,7 +20,7 @@ using osuTK; namespace osu.Game.Tournament.Screens.Editors { - public class SeedingEditorScreen : TournamentEditorScreen + public partial class SeedingEditorScreen : TournamentEditorScreen { private readonly TournamentTeam team; @@ -32,7 +32,7 @@ namespace osu.Game.Tournament.Screens.Editors this.team = team; } - public class SeedingResultRow : CompositeDrawable, IModelBacked + public partial class SeedingResultRow : CompositeDrawable, IModelBacked { public SeedingResult Model { get; } @@ -106,7 +106,7 @@ namespace osu.Game.Tournament.Screens.Editors AutoSizeAxes = Axes.Y; } - public class SeedingBeatmapEditor : CompositeDrawable + public partial class SeedingBeatmapEditor : CompositeDrawable { private readonly SeedingResult round; private readonly FillFlowContainer flow; @@ -134,7 +134,7 @@ namespace osu.Game.Tournament.Screens.Editors flow.Add(new SeedingBeatmapRow(round, user)); } - public class SeedingBeatmapRow : CompositeDrawable + public partial class SeedingBeatmapRow : CompositeDrawable { private readonly SeedingResult result; public SeedingBeatmap Model { get; } diff --git a/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs index da27c09e01..c9d897ca11 100644 --- a/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -23,7 +22,7 @@ using osuTK; namespace osu.Game.Tournament.Screens.Editors { - public class TeamEditorScreen : TournamentEditorScreen + public partial class TeamEditorScreen : TournamentEditorScreen { protected override BindableList Storage => LadderInfo.Teams; @@ -44,7 +43,7 @@ namespace osu.Game.Tournament.Screens.Editors { var countries = new List(); - foreach (var country in Enum.GetValues(typeof(CountryCode)).Cast().Skip(1)) + foreach (var country in Enum.GetValues().Skip(1)) { countries.Add(new TournamentTeam { @@ -54,13 +53,11 @@ namespace osu.Game.Tournament.Screens.Editors }); } - Debug.Assert(countries != null); - foreach (var c in countries) Storage.Add(c); } - public class TeamRow : CompositeDrawable, IModelBacked + public partial class TeamRow : CompositeDrawable, IModelBacked { public TournamentTeam Model { get; } @@ -181,7 +178,7 @@ namespace osu.Game.Tournament.Screens.Editors drawableContainer.Child = new DrawableTeamFlag(Model); } - public class PlayerEditor : CompositeDrawable + public partial class PlayerEditor : CompositeDrawable { private readonly TournamentTeam team; private readonly FillFlowContainer flow; @@ -209,7 +206,7 @@ namespace osu.Game.Tournament.Screens.Editors flow.Add(new PlayerRow(team, player)); } - public class PlayerRow : CompositeDrawable + public partial class PlayerRow : CompositeDrawable { private readonly TournamentUser user; diff --git a/osu.Game.Tournament/Screens/Editors/TournamentEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/TournamentEditorScreen.cs index 8c55026c67..0fb6c1367b 100644 --- a/osu.Game.Tournament/Screens/Editors/TournamentEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/TournamentEditorScreen.cs @@ -4,6 +4,7 @@ #nullable disable using System.Collections.Specialized; +using System.Diagnostics; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -20,7 +21,7 @@ using osuTK; namespace osu.Game.Tournament.Screens.Editors { - public abstract class TournamentEditorScreen : TournamentScreen + public abstract partial class TournamentEditorScreen : TournamentScreen where TDrawable : Drawable, IModelBacked where TModel : class, new() { @@ -102,10 +103,14 @@ namespace osu.Game.Tournament.Screens.Editors switch (args.Action) { case NotifyCollectionChangedAction.Add: + Debug.Assert(args.NewItems != null); + args.NewItems.Cast().ForEach(i => flow.Add(CreateDrawable(i))); break; case NotifyCollectionChangedAction.Remove: + Debug.Assert(args.OldItems != null); + args.OldItems.Cast().ForEach(i => flow.RemoveAll(d => d.Model == i, true)); break; } diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs b/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs index 91a75bf86f..8f7484980d 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs @@ -12,7 +12,7 @@ using osuTK; namespace osu.Game.Tournament.Screens.Gameplay.Components { - public class MatchHeader : Container + public partial class MatchHeader : Container { private TeamScoreDisplay teamDisplay1; private TeamScoreDisplay teamDisplay2; diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/MatchRoundDisplay.cs b/osu.Game.Tournament/Screens/Gameplay/Components/MatchRoundDisplay.cs index 78206c6d47..d2b61220f0 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/MatchRoundDisplay.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/MatchRoundDisplay.cs @@ -10,7 +10,7 @@ using osu.Game.Tournament.Models; namespace osu.Game.Tournament.Screens.Gameplay.Components { - public class MatchRoundDisplay : TournamentSpriteTextWithBackground + public partial class MatchRoundDisplay : TournamentSpriteTextWithBackground { private readonly Bindable currentMatch = new Bindable(); diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/TeamDisplay.cs b/osu.Game.Tournament/Screens/Gameplay/Components/TeamDisplay.cs index 1eceddd871..60d1678326 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/TeamDisplay.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/TeamDisplay.cs @@ -12,7 +12,7 @@ using osuTK; namespace osu.Game.Tournament.Screens.Gameplay.Components { - public class TeamDisplay : DrawableTournamentTeam + public partial class TeamDisplay : DrawableTournamentTeam { private readonly TeamScore score; diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/TeamScore.cs b/osu.Game.Tournament/Screens/Gameplay/Components/TeamScore.cs index 3fa06c16b4..8b3786fa1f 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/TeamScore.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/TeamScore.cs @@ -17,7 +17,7 @@ using osuTK.Graphics; namespace osu.Game.Tournament.Screens.Gameplay.Components { - public class TeamScore : CompositeDrawable + public partial class TeamScore : CompositeDrawable { private readonly Bindable currentTeamScore = new Bindable(); private readonly StarCounter counter; @@ -41,7 +41,7 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components private void scoreChanged(ValueChangedEvent score) => counter.Current = score.NewValue ?? 0; - public class TeamScoreStarCounter : StarCounter + public partial class TeamScoreStarCounter : StarCounter { public TeamScoreStarCounter(int count) : base(count) @@ -50,7 +50,7 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components public override Star CreateStar() => new LightSquare(); - public class LightSquare : Star + public partial class LightSquare : Star { private readonly Box box; diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/TeamScoreDisplay.cs b/osu.Game.Tournament/Screens/Gameplay/Components/TeamScoreDisplay.cs index 0fa5884603..57fe1c7312 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/TeamScoreDisplay.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/TeamScoreDisplay.cs @@ -13,7 +13,7 @@ using osuTK.Input; namespace osu.Game.Tournament.Screens.Gameplay.Components { - public class TeamScoreDisplay : CompositeDrawable + public partial class TeamScoreDisplay : CompositeDrawable { private readonly TeamColour teamColour; diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/TournamentMatchScoreDisplay.cs b/osu.Game.Tournament/Screens/Gameplay/Components/TournamentMatchScoreDisplay.cs index 7454d22aa2..bd1f3a2dd0 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/TournamentMatchScoreDisplay.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/TournamentMatchScoreDisplay.cs @@ -18,7 +18,7 @@ using osuTK; namespace osu.Game.Tournament.Screens.Gameplay.Components { // TODO: Update to derive from osu-side class? - public class TournamentMatchScoreDisplay : CompositeDrawable + public partial class TournamentMatchScoreDisplay : CompositeDrawable { private const float bar_height = 18; @@ -128,7 +128,7 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components score2Text.X = Math.Max(5 + score2Text.DrawWidth / 2, score2Bar.DrawWidth); } - private class MatchScoreCounter : CommaSeparatedScoreCounter + private partial class MatchScoreCounter : CommaSeparatedScoreCounter { private OsuSpriteText displayedSpriteText; diff --git a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs index 8a23ee65da..f2a2e97bcc 100644 --- a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs +++ b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs @@ -21,7 +21,7 @@ using osuTK.Graphics; namespace osu.Game.Tournament.Screens.Gameplay { - public class GameplayScreen : BeatmapInfoScreen + public partial class GameplayScreen : BeatmapInfoScreen { private readonly BindableBool warmup = new BindableBool(); @@ -232,7 +232,7 @@ namespace osu.Game.Tournament.Screens.Gameplay } } - private class ChromaArea : CompositeDrawable + private partial class ChromaArea : CompositeDrawable { [Resolved] private LadderInfo ladder { get; set; } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs index c005e11efe..2b66df1a31 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs @@ -24,7 +24,7 @@ using osuTK.Input; namespace osu.Game.Tournament.Screens.Ladder.Components { - public class DrawableMatchTeam : DrawableTournamentTeam, IHasContextMenu + public partial class DrawableMatchTeam : DrawableTournamentTeam, IHasContextMenu { private readonly TournamentMatch match; private readonly bool losers; diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentMatch.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentMatch.cs index ed8b789387..33e383482f 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentMatch.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentMatch.cs @@ -19,7 +19,7 @@ using osuTK.Input; namespace osu.Game.Tournament.Screens.Ladder.Components { - public class DrawableTournamentMatch : CompositeDrawable + public partial class DrawableTournamentMatch : CompositeDrawable { public readonly TournamentMatch Match; private readonly bool editor; diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentRound.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentRound.cs index 466b9ed482..4b2a29247b 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentRound.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentRound.cs @@ -12,7 +12,7 @@ using osu.Game.Tournament.Models; namespace osu.Game.Tournament.Screens.Ladder.Components { - public class DrawableTournamentRound : CompositeDrawable + public partial class DrawableTournamentRound : CompositeDrawable { [UsedImplicitly] private readonly Bindable name; diff --git a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs index 1fdf616e34..5aea551c00 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Collections.Specialized; +using System.Diagnostics; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -18,10 +19,8 @@ using osu.Game.Tournament.Models; namespace osu.Game.Tournament.Screens.Ladder.Components { - public class LadderEditorSettings : PlayerSettingsGroup + public partial class LadderEditorSettings : PlayerSettingsGroup { - private const int padding = 10; - private SettingsDropdown roundDropdown; private PlayerCheckbox losersCheckbox; private DateTextBox dateTimeBox; @@ -89,7 +88,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { } - private class SettingsRoundDropdown : SettingsDropdown + private partial class SettingsRoundDropdown : SettingsDropdown { public SettingsRoundDropdown(BindableList rounds) { @@ -103,10 +102,14 @@ namespace osu.Game.Tournament.Screens.Ladder.Components switch (args.Action) { case NotifyCollectionChangedAction.Add: + Debug.Assert(args.NewItems != null); + args.NewItems.Cast().ForEach(add); break; case NotifyCollectionChangedAction.Remove: + Debug.Assert(args.OldItems != null); + args.OldItems.Cast().ForEach(i => Control.RemoveDropdownItem(i)); break; } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs b/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs index c5f8c3bb51..c79dbc26be 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs @@ -10,7 +10,7 @@ using osuTK; namespace osu.Game.Tournament.Screens.Ladder.Components { - public class ProgressionPath : Path + public partial class ProgressionPath : Path { public DrawableTournamentMatch Source { get; } public DrawableTournamentMatch Destination { get; } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/SettingsTeamDropdown.cs b/osu.Game.Tournament/Screens/Ladder/Components/SettingsTeamDropdown.cs index 74424783c6..f7a42e4f50 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/SettingsTeamDropdown.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/SettingsTeamDropdown.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Collections.Specialized; +using System.Diagnostics; using System.Linq; using osu.Framework.Bindables; using osu.Framework.Extensions.IEnumerableExtensions; @@ -13,7 +14,7 @@ using osu.Game.Tournament.Models; namespace osu.Game.Tournament.Screens.Ladder.Components { - public class SettingsTeamDropdown : SettingsDropdown + public partial class SettingsTeamDropdown : SettingsDropdown { public SettingsTeamDropdown(BindableList teams) { @@ -25,10 +26,14 @@ namespace osu.Game.Tournament.Screens.Ladder.Components switch (args.Action) { case NotifyCollectionChangedAction.Add: + Debug.Assert(args.NewItems != null); + args.NewItems.Cast().ForEach(add); break; case NotifyCollectionChangedAction.Remove: + Debug.Assert(args.OldItems != null); + args.OldItems.Cast().ForEach(i => Control.RemoveDropdownItem(i)); break; } diff --git a/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs b/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs index 6fae44de35..10d58612f4 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs @@ -12,7 +12,7 @@ using osuTK; namespace osu.Game.Tournament.Screens.Ladder { - public class LadderDragContainer : Container + public partial class LadderDragContainer : Container { protected override bool OnDragStart(DragStartEvent e) => true; diff --git a/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs b/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs index 7ad7e76a1f..176c06c0e5 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs @@ -4,6 +4,7 @@ #nullable disable using System.Collections.Specialized; +using System.Diagnostics; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Caching; @@ -19,7 +20,7 @@ using osuTK.Graphics; namespace osu.Game.Tournament.Screens.Ladder { - public class LadderScreen : TournamentScreen + public partial class LadderScreen : TournamentScreen { protected Container MatchesContainer; private Container paths; @@ -81,11 +82,15 @@ namespace osu.Game.Tournament.Screens.Ladder switch (args.Action) { case NotifyCollectionChangedAction.Add: + Debug.Assert(args.NewItems != null); + foreach (var p in args.NewItems.Cast()) addMatch(p); break; case NotifyCollectionChangedAction.Remove: + Debug.Assert(args.OldItems != null); + foreach (var p in args.OldItems.Cast()) { foreach (var d in MatchesContainer.Where(d => d.Match == p)) @@ -153,7 +158,7 @@ namespace osu.Game.Tournament.Screens.Ladder foreach (var round in LadderInfo.Rounds) { - var topMatch = MatchesContainer.Where(p => !p.Match.Losers.Value && p.Match.Round.Value == round).OrderBy(p => p.Y).FirstOrDefault(); + var topMatch = MatchesContainer.Where(p => !p.Match.Losers.Value && p.Match.Round.Value == round).MinBy(p => p.Y); if (topMatch == null) continue; @@ -167,7 +172,7 @@ namespace osu.Game.Tournament.Screens.Ladder foreach (var round in LadderInfo.Rounds) { - var topMatch = MatchesContainer.Where(p => p.Match.Losers.Value && p.Match.Round.Value == round).OrderBy(p => p.Y).FirstOrDefault(); + var topMatch = MatchesContainer.Where(p => p.Match.Losers.Value && p.Match.Round.Value == round).MinBy(p => p.Y); if (topMatch == null) continue; diff --git a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs index decd723814..f0e34d78c3 100644 --- a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs +++ b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs @@ -22,7 +22,7 @@ using osuTK.Input; namespace osu.Game.Tournament.Screens.MapPool { - public class MapPoolScreen : TournamentMatchScreen + public partial class MapPoolScreen : TournamentMatchScreen { private readonly FillFlowContainer> mapFlows; diff --git a/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs b/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs index 0827cbae69..8d5547c749 100644 --- a/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs +++ b/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs @@ -19,7 +19,7 @@ using osuTK.Graphics; namespace osu.Game.Tournament.Screens.Schedule { - public class ScheduleScreen : TournamentScreen + public partial class ScheduleScreen : TournamentScreen { private readonly Bindable currentMatch = new Bindable(); private Container mainContainer; @@ -209,7 +209,7 @@ namespace osu.Game.Tournament.Screens.Schedule } } - public class ScheduleMatch : DrawableTournamentMatch + public partial class ScheduleMatch : DrawableTournamentMatch { public ScheduleMatch(TournamentMatch match, bool showTimestamp = true) : base(match) @@ -249,7 +249,7 @@ namespace osu.Game.Tournament.Screens.Schedule } } - public class ScheduleMatchDate : DrawableDate + public partial class ScheduleMatchDate : DrawableDate { public ScheduleMatchDate(DateTimeOffset date, float textSize = OsuFont.DEFAULT_FONT_SIZE, bool italic = true) : base(date, textSize, italic) @@ -261,7 +261,7 @@ namespace osu.Game.Tournament.Screens.Schedule : $"Starting {base.Format()}"; } - public class ScheduleContainer : Container + public partial class ScheduleContainer : Container { protected override Container Content => content; diff --git a/osu.Game.Tournament/Screens/Setup/ActionableInfo.cs b/osu.Game.Tournament/Screens/Setup/ActionableInfo.cs index a9ac21284e..e3fe2170ba 100644 --- a/osu.Game.Tournament/Screens/Setup/ActionableInfo.cs +++ b/osu.Game.Tournament/Screens/Setup/ActionableInfo.cs @@ -13,7 +13,7 @@ using osuTK.Graphics; namespace osu.Game.Tournament.Screens.Setup { - internal class ActionableInfo : LabelledDrawable + internal partial class ActionableInfo : LabelledDrawable { protected OsuButton Button; @@ -61,7 +61,7 @@ namespace osu.Game.Tournament.Screens.Setup Spacing = new Vector2(10, 0), Children = new Drawable[] { - Button = new TriangleButton + Button = new RoundedButton { Size = new Vector2(100, 40), Action = () => Action?.Invoke() diff --git a/osu.Game.Tournament/Screens/Setup/ResolutionSelector.cs b/osu.Game.Tournament/Screens/Setup/ResolutionSelector.cs index a387341d66..e6ab6f143a 100644 --- a/osu.Game.Tournament/Screens/Setup/ResolutionSelector.cs +++ b/osu.Game.Tournament/Screens/Setup/ResolutionSelector.cs @@ -9,7 +9,7 @@ using osu.Game.Graphics.UserInterface; namespace osu.Game.Tournament.Screens.Setup { - internal class ResolutionSelector : ActionableInfo + internal partial class ResolutionSelector : ActionableInfo { private const int minimum_window_height = 480; private const int maximum_window_height = 2160; diff --git a/osu.Game.Tournament/Screens/Setup/SetupScreen.cs b/osu.Game.Tournament/Screens/Setup/SetupScreen.cs index ff781dec80..b86513eb49 100644 --- a/osu.Game.Tournament/Screens/Setup/SetupScreen.cs +++ b/osu.Game.Tournament/Screens/Setup/SetupScreen.cs @@ -21,7 +21,7 @@ using osuTK; namespace osu.Game.Tournament.Screens.Setup { - public class SetupScreen : TournamentScreen + public partial class SetupScreen : TournamentScreen { private FillFlowContainer fillFlow; diff --git a/osu.Game.Tournament/Screens/Setup/StablePathSelectScreen.cs b/osu.Game.Tournament/Screens/Setup/StablePathSelectScreen.cs index fac488fcf5..463b012b77 100644 --- a/osu.Game.Tournament/Screens/Setup/StablePathSelectScreen.cs +++ b/osu.Game.Tournament/Screens/Setup/StablePathSelectScreen.cs @@ -21,7 +21,7 @@ using osuTK; namespace osu.Game.Tournament.Screens.Setup { - public class StablePathSelectScreen : TournamentScreen + public partial class StablePathSelectScreen : TournamentScreen { [Resolved(canBeNull: true)] private TournamentSceneManager sceneManager { get; set; } @@ -93,7 +93,7 @@ namespace osu.Game.Tournament.Screens.Setup Spacing = new Vector2(20), Children = new Drawable[] { - new TriangleButton + new RoundedButton { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -101,7 +101,7 @@ namespace osu.Game.Tournament.Screens.Setup Text = "Select stable path", Action = ChangePath }, - new TriangleButton + new RoundedButton { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game.Tournament/Screens/Setup/TournamentSwitcher.cs b/osu.Game.Tournament/Screens/Setup/TournamentSwitcher.cs index 447d6f44ce..7a8b03a7aa 100644 --- a/osu.Game.Tournament/Screens/Setup/TournamentSwitcher.cs +++ b/osu.Game.Tournament/Screens/Setup/TournamentSwitcher.cs @@ -6,11 +6,12 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Graphics.UserInterface; +using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Tournament.IO; namespace osu.Game.Tournament.Screens.Setup { - internal class TournamentSwitcher : ActionableInfo + internal partial class TournamentSwitcher : ActionableInfo { private OsuDropdown dropdown; private OsuButton folderButton; @@ -37,7 +38,7 @@ namespace osu.Game.Tournament.Screens.Setup { var drawable = base.CreateComponent(); - FlowContainer.Insert(-1, folderButton = new TriangleButton + FlowContainer.Insert(-1, folderButton = new RoundedButton { Text = "Open folder", Width = 100 diff --git a/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs b/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs index a7a175ceba..35d63f4fcf 100644 --- a/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs +++ b/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs @@ -14,7 +14,7 @@ using osuTK.Graphics; namespace osu.Game.Tournament.Screens.Showcase { - public class ShowcaseScreen : BeatmapInfoScreen + public partial class ShowcaseScreen : BeatmapInfoScreen { [BackgroundDependencyLoader] private void load() diff --git a/osu.Game.Tournament/Screens/Showcase/TournamentLogo.cs b/osu.Game.Tournament/Screens/Showcase/TournamentLogo.cs index 07a632ec72..d04059118f 100644 --- a/osu.Game.Tournament/Screens/Showcase/TournamentLogo.cs +++ b/osu.Game.Tournament/Screens/Showcase/TournamentLogo.cs @@ -11,7 +11,7 @@ using osu.Framework.Graphics.Textures; namespace osu.Game.Tournament.Screens.Showcase { - public class TournamentLogo : CompositeDrawable + public partial class TournamentLogo : CompositeDrawable { public TournamentLogo() { diff --git a/osu.Game.Tournament/Screens/TeamIntro/SeedingScreen.cs b/osu.Game.Tournament/Screens/TeamIntro/SeedingScreen.cs index ba75b6a2ed..b07a0a65dd 100644 --- a/osu.Game.Tournament/Screens/TeamIntro/SeedingScreen.cs +++ b/osu.Game.Tournament/Screens/TeamIntro/SeedingScreen.cs @@ -20,7 +20,7 @@ using osuTK; namespace osu.Game.Tournament.Screens.TeamIntro { - public class SeedingScreen : TournamentMatchScreen + public partial class SeedingScreen : TournamentMatchScreen { private Container mainContainer; @@ -116,7 +116,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro }; }); - private class RightInfo : CompositeDrawable + private partial class RightInfo : CompositeDrawable { public RightInfo(TournamentTeam team) { @@ -148,7 +148,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro } } - private class BeatmapScoreRow : CompositeDrawable + private partial class BeatmapScoreRow : CompositeDrawable { public BeatmapScoreRow(SeedingBeatmap beatmap) { @@ -190,7 +190,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro } } - private class ModRow : CompositeDrawable + private partial class ModRow : CompositeDrawable { private readonly string mods; private readonly int seeding; @@ -254,7 +254,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro } } - private class LeftInfo : CompositeDrawable + private partial class LeftInfo : CompositeDrawable { public LeftInfo(TournamentTeam team) { @@ -286,7 +286,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro fill.Add(new RowDisplay(p.Username, p.Rank?.ToString("\\##,0") ?? "-")); } - internal class RowDisplay : CompositeDrawable + internal partial class RowDisplay : CompositeDrawable { public RowDisplay(string left, string right) { @@ -313,7 +313,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro } } - private class TeamDisplay : DrawableTournamentTeam + private partial class TeamDisplay : DrawableTournamentTeam { public TeamDisplay(TournamentTeam team) : base(team) diff --git a/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs b/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs index 08c9a7a897..950a63808c 100644 --- a/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs +++ b/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs @@ -13,7 +13,7 @@ using osuTK; namespace osu.Game.Tournament.Screens.TeamIntro { - public class TeamIntroScreen : TournamentMatchScreen + public partial class TeamIntroScreen : TournamentMatchScreen { private Container mainContainer; diff --git a/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs b/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs index ac54ff58f5..9206de1dc2 100644 --- a/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs +++ b/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs @@ -14,7 +14,7 @@ using osuTK; namespace osu.Game.Tournament.Screens.TeamWin { - public class TeamWinScreen : TournamentMatchScreen + public partial class TeamWinScreen : TournamentMatchScreen { private Container mainContainer; diff --git a/osu.Game.Tournament/Screens/TournamentMatchScreen.cs b/osu.Game.Tournament/Screens/TournamentMatchScreen.cs index 585cdd09c1..58444d0c1b 100644 --- a/osu.Game.Tournament/Screens/TournamentMatchScreen.cs +++ b/osu.Game.Tournament/Screens/TournamentMatchScreen.cs @@ -8,7 +8,7 @@ using osu.Game.Tournament.Models; namespace osu.Game.Tournament.Screens { - public abstract class TournamentMatchScreen : TournamentScreen + public abstract partial class TournamentMatchScreen : TournamentScreen { protected readonly Bindable CurrentMatch = new Bindable(); private WarningBox noMatchWarning; diff --git a/osu.Game.Tournament/Screens/TournamentScreen.cs b/osu.Game.Tournament/Screens/TournamentScreen.cs index b4641fa45d..02903a637c 100644 --- a/osu.Game.Tournament/Screens/TournamentScreen.cs +++ b/osu.Game.Tournament/Screens/TournamentScreen.cs @@ -10,7 +10,7 @@ using osu.Game.Tournament.Models; namespace osu.Game.Tournament.Screens { - public abstract class TournamentScreen : CompositeDrawable + public abstract partial class TournamentScreen : CompositeDrawable { public const double FADE_DELAY = 200; diff --git a/osu.Game.Tournament/TournamentGame.cs b/osu.Game.Tournament/TournamentGame.cs index 7d67bfa759..beef1e197d 100644 --- a/osu.Game.Tournament/TournamentGame.cs +++ b/osu.Game.Tournament/TournamentGame.cs @@ -23,7 +23,7 @@ using osuTK.Graphics; namespace osu.Game.Tournament { [Cached] - public class TournamentGame : TournamentGameBase + public partial class TournamentGame : TournamentGameBase { public static ColourInfo GetTeamColour(TeamColour teamColour) => teamColour == TeamColour.Red ? COLOUR_RED : COLOUR_BLUE; diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 98ba3ca60f..08f21cb556 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -27,7 +27,7 @@ using osuTK.Input; namespace osu.Game.Tournament { [Cached(typeof(TournamentGameBase))] - public class TournamentGameBase : OsuGameBase + public partial class TournamentGameBase : OsuGameBase { public const string BRACKET_FILENAME = @"bracket.json"; private LadderInfo ladder; @@ -335,7 +335,7 @@ namespace osu.Game.Tournament protected override UserInputManager CreateUserInputManager() => new TournamentInputManager(); - private class TournamentInputManager : UserInputManager + private partial class TournamentInputManager : UserInputManager { protected override MouseButtonEventManager CreateButtonEventManagerFor(MouseButton button) { diff --git a/osu.Game.Tournament/TournamentSceneManager.cs b/osu.Game.Tournament/TournamentSceneManager.cs index a12dbb4740..abfe69b97b 100644 --- a/osu.Game.Tournament/TournamentSceneManager.cs +++ b/osu.Game.Tournament/TournamentSceneManager.cs @@ -33,7 +33,7 @@ using osuTK.Input; namespace osu.Game.Tournament { [Cached] - public class TournamentSceneManager : CompositeDrawable + public partial class TournamentSceneManager : CompositeDrawable { private Container screens; private TourneyVideo video; @@ -224,7 +224,7 @@ namespace osu.Game.Tournament s.IsSelected = screenType == s.Type; } - private class Separator : CompositeDrawable + private partial class Separator : CompositeDrawable { public Separator() { @@ -233,7 +233,7 @@ namespace osu.Game.Tournament } } - private class ScreenButton : TourneyButton + private partial class ScreenButton : TourneyButton { public readonly Type Type; diff --git a/osu.Game.Tournament/TournamentSpriteText.cs b/osu.Game.Tournament/TournamentSpriteText.cs index 166a8dfaf0..7ecb31ff15 100644 --- a/osu.Game.Tournament/TournamentSpriteText.cs +++ b/osu.Game.Tournament/TournamentSpriteText.cs @@ -8,7 +8,7 @@ using osu.Game.Graphics.Sprites; namespace osu.Game.Tournament { - public class TournamentSpriteText : OsuSpriteText + public partial class TournamentSpriteText : OsuSpriteText { public TournamentSpriteText() { diff --git a/osu.Game.Tournament/TourneyButton.cs b/osu.Game.Tournament/TourneyButton.cs index f1b14df783..558bd476c3 100644 --- a/osu.Game.Tournament/TourneyButton.cs +++ b/osu.Game.Tournament/TourneyButton.cs @@ -8,7 +8,7 @@ using osu.Game.Graphics.UserInterface; namespace osu.Game.Tournament { - public class TourneyButton : OsuButton + public partial class TourneyButton : OsuButton { public new Box Background => base.Background; diff --git a/osu.Game.Tournament/WarningBox.cs b/osu.Game.Tournament/WarningBox.cs index 123e78113a..4a196446f6 100644 --- a/osu.Game.Tournament/WarningBox.cs +++ b/osu.Game.Tournament/WarningBox.cs @@ -11,7 +11,7 @@ using osuTK.Graphics; namespace osu.Game.Tournament { - internal class WarningBox : Container + internal partial class WarningBox : Container { public WarningBox(string text) { diff --git a/osu.Game.Tournament/osu.Game.Tournament.csproj b/osu.Game.Tournament/osu.Game.Tournament.csproj index b049542bb0..ab67e490cd 100644 --- a/osu.Game.Tournament/osu.Game.Tournament.csproj +++ b/osu.Game.Tournament/osu.Game.Tournament.csproj @@ -1,6 +1,6 @@  - netstandard2.1 + net6.0 Library true tools for tournaments. @@ -11,4 +11,4 @@ - \ No newline at end of file + diff --git a/osu.Game/Audio/Effects/AudioFilter.cs b/osu.Game/Audio/Effects/AudioFilter.cs index 9446967173..682ca4ca7b 100644 --- a/osu.Game/Audio/Effects/AudioFilter.cs +++ b/osu.Game/Audio/Effects/AudioFilter.cs @@ -8,7 +8,7 @@ using osu.Framework.Graphics; namespace osu.Game.Audio.Effects { - public class AudioFilter : Component, ITransformableFilter + public partial class AudioFilter : Component, ITransformableFilter { /// /// The maximum cutoff frequency that can be used with a low-pass filter. diff --git a/osu.Game/Audio/PreviewTrack.cs b/osu.Game/Audio/PreviewTrack.cs index 2409ca6eb6..2c63c16274 100644 --- a/osu.Game/Audio/PreviewTrack.cs +++ b/osu.Game/Audio/PreviewTrack.cs @@ -10,7 +10,7 @@ using osu.Framework.Threading; namespace osu.Game.Audio { [LongRunningLoad] - public abstract class PreviewTrack : Component + public abstract partial class PreviewTrack : Component { /// /// Invoked when this has stopped playing. @@ -109,6 +109,8 @@ namespace osu.Game.Audio protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); + + Stop(); Track?.Dispose(); } } diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index b8662b6a4b..1d710e6395 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -12,7 +12,7 @@ using osu.Game.Beatmaps; namespace osu.Game.Audio { - public class PreviewTrackManager : Component + public partial class PreviewTrackManager : Component { private readonly IAdjustableAudioComponent mainTrackAdjustments; @@ -85,7 +85,7 @@ namespace osu.Game.Audio protected virtual TrackManagerPreviewTrack CreatePreviewTrack(IBeatmapSetInfo beatmapSetInfo, ITrackStore trackStore) => new TrackManagerPreviewTrack(beatmapSetInfo, trackStore); - public class TrackManagerPreviewTrack : PreviewTrack + public partial class TrackManagerPreviewTrack : PreviewTrack { [Resolved] public IPreviewTrackOwner? Owner { get; private set; } diff --git a/osu.Game/Audio/SampleInfo.cs b/osu.Game/Audio/SampleInfo.cs index 19c78f34b2..0191f96825 100644 --- a/osu.Game/Audio/SampleInfo.cs +++ b/osu.Game/Audio/SampleInfo.cs @@ -35,7 +35,7 @@ namespace osu.Game.Audio public bool Equals(SampleInfo? other) => other != null && sampleNames.SequenceEqual(other.sampleNames); - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj is SampleInfo other && Equals(other); } } diff --git a/osu.Game/BackgroundBeatmapProcessor.cs b/osu.Game/BackgroundBeatmapProcessor.cs index ea5904a8d3..b8c89d8822 100644 --- a/osu.Game/BackgroundBeatmapProcessor.cs +++ b/osu.Game/BackgroundBeatmapProcessor.cs @@ -20,7 +20,7 @@ using osu.Game.Screens.Play; namespace osu.Game { - public class BackgroundBeatmapProcessor : Component + public partial class BackgroundBeatmapProcessor : Component { [Resolved] private RulesetStore rulesetStore { get; set; } = null!; diff --git a/osu.Game/Beatmaps/Beatmap.cs b/osu.Game/Beatmaps/Beatmap.cs index 2d02fb6200..416d655cc3 100644 --- a/osu.Game/Beatmaps/Beatmap.cs +++ b/osu.Game/Beatmaps/Beatmap.cs @@ -81,9 +81,14 @@ namespace osu.Game.Beatmaps public double GetMostCommonBeatLength() { + double lastTime; + // The last playable time in the beatmap - the last timing point extends to this time. // Note: This is more accurate and may present different results because osu-stable didn't have the ability to calculate slider durations in this context. - double lastTime = HitObjects.LastOrDefault()?.GetEndTime() ?? ControlPointInfo.TimingPoints.LastOrDefault()?.Time ?? 0; + if (!HitObjects.Any()) + lastTime = ControlPointInfo.TimingPoints.LastOrDefault()?.Time ?? 0; + else + lastTime = this.GetLastObjectTime(); var mostCommon = // Construct a set of (beatLength, duration) tuples for each individual timing point. diff --git a/osu.Game/Beatmaps/BeatmapDifficultyCache.cs b/osu.Game/Beatmaps/BeatmapDifficultyCache.cs index bf7b980e75..871faf5906 100644 --- a/osu.Game/Beatmaps/BeatmapDifficultyCache.cs +++ b/osu.Game/Beatmaps/BeatmapDifficultyCache.cs @@ -26,7 +26,7 @@ namespace osu.Game.Beatmaps /// A component which performs and acts as a central cache for difficulty calculations of beatmap/ruleset/mod combinations. /// Currently not persisted between game sessions. /// - public class BeatmapDifficultyCache : MemoryCachingComponent + public partial class BeatmapDifficultyCache : MemoryCachingComponent { // Too many simultaneous updates can lead to stutters. One thread seems to work fine for song select display purposes. private readonly ThreadedTaskScheduler updateScheduler = new ThreadedTaskScheduler(1, nameof(BeatmapDifficultyCache)); diff --git a/osu.Game/Beatmaps/BeatmapImporter.cs b/osu.Game/Beatmaps/BeatmapImporter.cs index bcb1d7f961..4752a88199 100644 --- a/osu.Game/Beatmaps/BeatmapImporter.cs +++ b/osu.Game/Beatmaps/BeatmapImporter.cs @@ -44,7 +44,7 @@ namespace osu.Game.Beatmaps public override async Task?> ImportAsUpdate(ProgressNotification notification, ImportTask importTask, BeatmapSetInfo original) { - var imported = await Import(notification, importTask); + var imported = await Import(notification, new[] { importTask }).ConfigureAwait(true); if (!imported.Any()) return null; @@ -203,10 +203,10 @@ namespace osu.Game.Beatmaps } } - protected override void PostImport(BeatmapSetInfo model, Realm realm, bool batchImport) + protected override void PostImport(BeatmapSetInfo model, Realm realm, ImportParameters parameters) { - base.PostImport(model, realm, batchImport); - ProcessBeatmap?.Invoke((model, batchImport)); + base.PostImport(model, realm, parameters); + ProcessBeatmap?.Invoke((model, parameters.Batch)); } private void validateOnlineIds(BeatmapSetInfo beatmapSet, Realm realm) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 965cc43815..34637501fa 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -44,6 +44,16 @@ namespace osu.Game.Beatmaps public Action<(BeatmapSetInfo beatmapSet, bool isBatch)>? ProcessBeatmap { private get; set; } + public override bool PauseImports + { + get => base.PauseImports; + set + { + base.PauseImports = value; + beatmapImporter.PauseImports = value; + } + } + public BeatmapManager(Storage storage, RealmAccess realm, IAPIProvider? api, AudioManager audioManager, IResourceStore gameResources, GameHost? host = null, WorkingBeatmap? defaultBeatmap = null, BeatmapDifficultyCache? difficultyCache = null, bool performOnlineLookups = false) : base(storage, realm) @@ -126,14 +136,12 @@ namespace osu.Game.Beatmaps /// The ruleset with which the new difficulty should be created. public virtual WorkingBeatmap CreateNewDifficulty(BeatmapSetInfo targetBeatmapSet, WorkingBeatmap referenceWorkingBeatmap, RulesetInfo rulesetInfo) { - var playableBeatmap = referenceWorkingBeatmap.GetPlayableBeatmap(rulesetInfo); - - var newBeatmapInfo = new BeatmapInfo(rulesetInfo, new BeatmapDifficulty(), playableBeatmap.Metadata.DeepClone()) + var newBeatmapInfo = new BeatmapInfo(rulesetInfo, new BeatmapDifficulty(), referenceWorkingBeatmap.Metadata.DeepClone()) { DifficultyName = NamingUtils.GetNextBestName(targetBeatmapSet.Beatmaps.Select(b => b.DifficultyName), "New Difficulty") }; var newBeatmap = new Beatmap { BeatmapInfo = newBeatmapInfo }; - foreach (var timingPoint in playableBeatmap.ControlPointInfo.TimingPoints) + foreach (var timingPoint in referenceWorkingBeatmap.Beatmap.ControlPointInfo.TimingPoints) newBeatmap.ControlPointInfo.Add(timingPoint.Time, timingPoint.DeepClone()); return addDifficultyToSet(targetBeatmapSet, newBeatmap, referenceWorkingBeatmap.Skin); @@ -456,15 +464,16 @@ namespace osu.Game.Beatmaps public Task Import(params string[] paths) => beatmapImporter.Import(paths); - public Task Import(params ImportTask[] tasks) => beatmapImporter.Import(tasks); + public Task Import(ImportTask[] tasks, ImportParameters parameters = default) => beatmapImporter.Import(tasks, parameters); - public Task>> Import(ProgressNotification notification, params ImportTask[] tasks) => beatmapImporter.Import(notification, tasks); + public Task>> Import(ProgressNotification notification, ImportTask[] tasks, ImportParameters parameters = default) => + beatmapImporter.Import(notification, tasks, parameters); - public Task?> Import(ImportTask task, bool batchImport = false, CancellationToken cancellationToken = default) => - beatmapImporter.Import(task, batchImport, cancellationToken); + public Task?> Import(ImportTask task, ImportParameters parameters = default, CancellationToken cancellationToken = default) => + beatmapImporter.Import(task, parameters, cancellationToken); public Live? Import(BeatmapSetInfo item, ArchiveReader? archive = null, CancellationToken cancellationToken = default) => - beatmapImporter.ImportModel(item, archive, false, cancellationToken); + beatmapImporter.ImportModel(item, archive, default, cancellationToken); public IEnumerable HandledExtensions => beatmapImporter.HandledExtensions; diff --git a/osu.Game/Beatmaps/BeatmapOnlineChangeIngest.cs b/osu.Game/Beatmaps/BeatmapOnlineChangeIngest.cs index 5d0765641b..98aefd75d3 100644 --- a/osu.Game/Beatmaps/BeatmapOnlineChangeIngest.cs +++ b/osu.Game/Beatmaps/BeatmapOnlineChangeIngest.cs @@ -11,7 +11,7 @@ namespace osu.Game.Beatmaps /// /// Ingests any changes that happen externally to the client, reprocessing as required. /// - public class BeatmapOnlineChangeIngest : Component + public partial class BeatmapOnlineChangeIngest : Component { private readonly BeatmapUpdater beatmapUpdater; private readonly RealmAccess realm; diff --git a/osu.Game/Beatmaps/BeatmapSetOnlineNomination.cs b/osu.Game/Beatmaps/BeatmapSetOnlineNomination.cs new file mode 100644 index 0000000000..f6de414628 --- /dev/null +++ b/osu.Game/Beatmaps/BeatmapSetOnlineNomination.cs @@ -0,0 +1,22 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using Newtonsoft.Json; + +namespace osu.Game.Beatmaps +{ + public struct BeatmapSetOnlineNomination + { + [JsonProperty(@"beatmapset_id")] + public int BeatmapsetId { get; set; } + + [JsonProperty(@"reset")] + public bool Reset { get; set; } + + [JsonProperty(@"rulesets")] + public string[]? Rulesets { get; set; } + + [JsonProperty(@"user_id")] + public int UserId { get; set; } + } +} diff --git a/osu.Game/Beatmaps/BeatmapStatisticIcon.cs b/osu.Game/Beatmaps/BeatmapStatisticIcon.cs index 8002910b52..ca07e5f365 100644 --- a/osu.Game/Beatmaps/BeatmapStatisticIcon.cs +++ b/osu.Game/Beatmaps/BeatmapStatisticIcon.cs @@ -13,7 +13,7 @@ namespace osu.Game.Beatmaps /// /// A default implementation of an icon used to represent beatmap statistics. /// - public class BeatmapStatisticIcon : Sprite + public partial class BeatmapStatisticIcon : Sprite { private readonly BeatmapStatisticsIconType iconType; diff --git a/osu.Game/Beatmaps/BeatmapUpdaterMetadataLookup.cs b/osu.Game/Beatmaps/BeatmapUpdaterMetadataLookup.cs index 2fd1d06b7b..71d40b1a48 100644 --- a/osu.Game/Beatmaps/BeatmapUpdaterMetadataLookup.cs +++ b/osu.Game/Beatmaps/BeatmapUpdaterMetadataLookup.cs @@ -178,7 +178,7 @@ namespace osu.Game.Beatmaps { try { - await cacheDownloadRequest.PerformAsync(); + await cacheDownloadRequest.PerformAsync().ConfigureAwait(false); } catch { diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs index 0a09e6e7e6..f46e4af332 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs @@ -16,7 +16,7 @@ namespace osu.Game.Beatmaps.ControlPoints public void AttachGroup(ControlPointGroup pointGroup) => Time = pointGroup.Time; - public int CompareTo(ControlPoint other) => Time.CompareTo(other.Time); + public int CompareTo(ControlPoint? other) => Time.CompareTo(other?.Time); public virtual Color4 GetRepresentingColour(OsuColour colours) => colours.Yellow; @@ -32,7 +32,7 @@ namespace osu.Game.Beatmaps.ControlPoints /// public ControlPoint DeepClone() { - var copy = (ControlPoint)Activator.CreateInstance(GetType()); + var copy = (ControlPoint)Activator.CreateInstance(GetType())!; copy.CopyFrom(this); diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointGroup.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointGroup.cs index db479f0e5b..1f34f3777d 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPointGroup.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPointGroup.cs @@ -26,7 +26,7 @@ namespace osu.Game.Beatmaps.ControlPoints Time = time; } - public int CompareTo(ControlPointGroup other) => Time.CompareTo(other.Time); + public int CompareTo(ControlPointGroup? other) => Time.CompareTo(other?.Time); public void Add(ControlPoint point) { diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs index 422e306450..29b7191ecf 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs @@ -70,14 +70,14 @@ namespace osu.Game.Beatmaps.ControlPoints /// [JsonIgnore] public double BPMMaximum => - 60000 / (TimingPoints.OrderBy(c => c.BeatLength).FirstOrDefault() ?? TimingControlPoint.DEFAULT).BeatLength; + 60000 / (TimingPoints.MinBy(c => c.BeatLength) ?? TimingControlPoint.DEFAULT).BeatLength; /// /// Finds the minimum BPM represented by any timing control point. /// [JsonIgnore] public double BPMMinimum => - 60000 / (TimingPoints.OrderByDescending(c => c.BeatLength).FirstOrDefault() ?? TimingControlPoint.DEFAULT).BeatLength; + 60000 / (TimingPoints.MaxBy(c => c.BeatLength) ?? TimingControlPoint.DEFAULT).BeatLength; /// /// Remove all s and return to a pristine state. @@ -211,8 +211,7 @@ namespace osu.Game.Beatmaps.ControlPoints public static T BinarySearch(IReadOnlyList list, double time) where T : class, IControlPoint { - if (list == null) - throw new ArgumentNullException(nameof(list)); + ArgumentNullException.ThrowIfNull(list); if (list.Count == 0) return null; @@ -300,7 +299,7 @@ namespace osu.Game.Beatmaps.ControlPoints public ControlPointInfo DeepClone() { - var controlPointInfo = (ControlPointInfo)Activator.CreateInstance(GetType()); + var controlPointInfo = (ControlPointInfo)Activator.CreateInstance(GetType())!; foreach (var point in AllControlPoints) controlPointInfo.Add(point.Time, point.DeepClone()); diff --git a/osu.Game/Beatmaps/DifficultyRecommender.cs b/osu.Game/Beatmaps/DifficultyRecommender.cs index ed2d6cd3a8..ec00756fd9 100644 --- a/osu.Game/Beatmaps/DifficultyRecommender.cs +++ b/osu.Game/Beatmaps/DifficultyRecommender.cs @@ -19,7 +19,7 @@ namespace osu.Game.Beatmaps /// A class which will recommend the most suitable difficulty for the local user from a beatmap set. /// This requires the user to be logged in, as it sources from the user's online profile. /// - public class DifficultyRecommender : Component + public partial class DifficultyRecommender : Component { [Resolved] private IAPIProvider api { get; set; } @@ -51,11 +51,11 @@ namespace osu.Game.Beatmaps if (!recommendedDifficultyMapping.TryGetValue(r, out double recommendation)) continue; - BeatmapInfo beatmapInfo = beatmaps.Where(b => b.Ruleset.ShortName.Equals(r)).OrderBy(b => + BeatmapInfo beatmapInfo = beatmaps.Where(b => b.Ruleset.ShortName.Equals(r, StringComparison.Ordinal)).MinBy(b => { double difference = b.StarRating - recommendation; return difference >= 0 ? difference * 2 : difference * -1; // prefer easier over harder - }).FirstOrDefault(); + }); if (beatmapInfo != null) return beatmapInfo; @@ -90,7 +90,7 @@ namespace osu.Game.Beatmaps return recommendedDifficultyMapping .OrderByDescending(pair => pair.Value) .Select(pair => pair.Key) - .Where(r => !r.Equals(ruleset.Value.ShortName)) + .Where(r => !r.Equals(ruleset.Value.ShortName, StringComparison.Ordinal)) .Prepend(ruleset.Value.ShortName); } } diff --git a/osu.Game/Beatmaps/Drawables/BeatmapBackgroundSprite.cs b/osu.Game/Beatmaps/Drawables/BeatmapBackgroundSprite.cs index 4ba16839f5..767504fcb1 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapBackgroundSprite.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapBackgroundSprite.cs @@ -9,14 +9,13 @@ using osu.Framework.Graphics.Sprites; namespace osu.Game.Beatmaps.Drawables { - public class BeatmapBackgroundSprite : Sprite + public partial class BeatmapBackgroundSprite : Sprite { private readonly IWorkingBeatmap working; public BeatmapBackgroundSprite(IWorkingBeatmap working) { - if (working == null) - throw new ArgumentNullException(nameof(working)); + ArgumentNullException.ThrowIfNull(working); this.working = working; } diff --git a/osu.Game/Beatmaps/Drawables/BeatmapDownloadButton.cs b/osu.Game/Beatmaps/Drawables/BeatmapDownloadButton.cs index 4dd3a56244..cf27023a9c 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapDownloadButton.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapDownloadButton.cs @@ -18,7 +18,7 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Beatmaps.Drawables { - public class BeatmapDownloadButton : CompositeDrawable + public partial class BeatmapDownloadButton : CompositeDrawable { protected bool DownloadEnabled => button.Enabled.Value; diff --git a/osu.Game/Beatmaps/Drawables/BeatmapSetOnlineStatusPill.cs b/osu.Game/Beatmaps/Drawables/BeatmapSetOnlineStatusPill.cs index 23d90ab76e..c353b9e904 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapSetOnlineStatusPill.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapSetOnlineStatusPill.cs @@ -17,7 +17,7 @@ using osuTK.Graphics; namespace osu.Game.Beatmaps.Drawables { - public class BeatmapSetOnlineStatusPill : CircularContainer, IHasTooltip + public partial class BeatmapSetOnlineStatusPill : CircularContainer, IHasTooltip { private BeatmapOnlineStatus status; diff --git a/osu.Game/Beatmaps/Drawables/BundledBeatmapDownloader.cs b/osu.Game/Beatmaps/Drawables/BundledBeatmapDownloader.cs index 053ac8fc17..21ab1b78ea 100644 --- a/osu.Game/Beatmaps/Drawables/BundledBeatmapDownloader.cs +++ b/osu.Game/Beatmaps/Drawables/BundledBeatmapDownloader.cs @@ -21,7 +21,7 @@ using osu.Game.Utils; namespace osu.Game.Beatmaps.Drawables { - public class BundledBeatmapDownloader : CompositeDrawable + public partial class BundledBeatmapDownloader : CompositeDrawable { private readonly bool shouldPostNotifications; diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs index b9e0a4e6cb..94b2956b4e 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs @@ -5,16 +5,19 @@ using System; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osu.Game.Online; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays; +using osu.Game.Localisation; namespace osu.Game.Beatmaps.Drawables.Cards { - public abstract class BeatmapCard : OsuClickableContainer + public abstract partial class BeatmapCard : OsuClickableContainer, IHasContextMenu { public const float TRANSITION_DURATION = 400; public const float CORNER_RADIUS = 10; @@ -96,5 +99,10 @@ namespace osu.Game.Beatmaps.Drawables.Cards throw new ArgumentOutOfRangeException(nameof(size), size, @"Unsupported card size"); } } + + public MenuItem[] ContextMenuItems => new MenuItem[] + { + new OsuMenuItem(ContextMenuStrings.ViewBeatmap, MenuItemType.Highlighted, Action), + }; } } diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardContent.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardContent.cs index bfec391b1d..7deb5f768c 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardContent.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardContent.cs @@ -14,7 +14,7 @@ using osuTK; namespace osu.Game.Beatmaps.Drawables.Cards { - public class BeatmapCardContent : CompositeDrawable + public partial class BeatmapCardContent : CompositeDrawable { public Drawable MainContent { @@ -138,9 +138,18 @@ namespace osu.Game.Beatmaps.Drawables.Cards // This avoids depth issues where a hovered (scaled) card to the right of another card would be beneath the card to the left. this.ScaleTo(Expanded.Value ? 1.03f : 1, 500, Easing.OutQuint); - background.FadeTo(Expanded.Value ? 1 : 0, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); - dropdownContent.FadeTo(Expanded.Value ? 1 : 0, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); - borderContainer.FadeTo(Expanded.Value ? 1 : 0, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); + if (Expanded.Value) + { + background.FadeIn(BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); + dropdownContent.FadeIn(BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); + borderContainer.FadeIn(BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); + } + else + { + background.FadeOut(BeatmapCard.TRANSITION_DURATION / 3f, Easing.OutQuint); + dropdownContent.FadeOut(BeatmapCard.TRANSITION_DURATION / 3f, Easing.OutQuint); + borderContainer.FadeOut(BeatmapCard.TRANSITION_DURATION / 3f, Easing.OutQuint); + } content.TweenEdgeEffectTo(new EdgeEffectParameters { diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardContentBackground.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardContentBackground.cs index 64a28c5394..deb56bb281 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardContentBackground.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardContentBackground.cs @@ -11,7 +11,7 @@ using osu.Game.Overlays; namespace osu.Game.Beatmaps.Drawables.Cards { - public class BeatmapCardContentBackground : CompositeDrawable + public partial class BeatmapCardContentBackground : CompositeDrawable { public BindableBool Dimmed { get; } = new BindableBool(); diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardDifficultyList.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardDifficultyList.cs index 9489116530..84445dc14c 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardDifficultyList.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardDifficultyList.cs @@ -16,7 +16,7 @@ using osuTK; namespace osu.Game.Beatmaps.Drawables.Cards { - public class BeatmapCardDifficultyList : CompositeDrawable + public partial class BeatmapCardDifficultyList : CompositeDrawable { public BeatmapCardDifficultyList(IBeatmapSetInfo beatmapSetInfo) { @@ -53,7 +53,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards } } - private class BeatmapCardDifficultyRow : CompositeDrawable + private partial class BeatmapCardDifficultyRow : CompositeDrawable { private readonly IBeatmapInfo beatmapInfo; diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardDownloadProgressBar.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardDownloadProgressBar.cs index d55622d7aa..3737715a7d 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardDownloadProgressBar.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardDownloadProgressBar.cs @@ -14,7 +14,7 @@ using osu.Game.Overlays; namespace osu.Game.Beatmaps.Drawables.Cards { - public class BeatmapCardDownloadProgressBar : CompositeDrawable + public partial class BeatmapCardDownloadProgressBar : CompositeDrawable { public IBindable State => state; private readonly Bindable state = new Bindable(); diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs index 646c990564..5c6f0c4ee1 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs @@ -17,7 +17,7 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Beatmaps.Drawables.Cards { - public class BeatmapCardExtra : BeatmapCard + public partial class BeatmapCardExtra : BeatmapCard { protected override Drawable IdleContent => idleBottomContent; protected override Drawable DownloadInProgressContent => downloadProgressBar; diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtraInfoRow.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtraInfoRow.cs index 7ba677e5dc..3a1b8f7e86 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtraInfoRow.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtraInfoRow.cs @@ -10,7 +10,7 @@ using osuTK; namespace osu.Game.Beatmaps.Drawables.Cards { - public class BeatmapCardExtraInfoRow : CompositeDrawable + public partial class BeatmapCardExtraInfoRow : CompositeDrawable { [Resolved(CanBeNull = true)] private BeatmapCardContent? content { get; set; } diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardNormal.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardNormal.cs index addc88700c..720d892495 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardNormal.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardNormal.cs @@ -18,7 +18,7 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Beatmaps.Drawables.Cards { - public class BeatmapCardNormal : BeatmapCard + public partial class BeatmapCardNormal : BeatmapCard { protected override Drawable IdleContent => idleBottomContent; protected override Drawable DownloadInProgressContent => downloadProgressBar; diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardThumbnail.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardThumbnail.cs index 55d3f0b969..c99d1f0c76 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardThumbnail.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardThumbnail.cs @@ -11,13 +11,13 @@ using osu.Game.Beatmaps.Drawables.Cards.Buttons; using osu.Game.Graphics; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays; -using osu.Game.Screens.Ranking.Expanded.Accuracy; +using osu.Framework.Graphics.UserInterface; using osuTK; using osuTK.Graphics; namespace osu.Game.Beatmaps.Drawables.Cards { - public class BeatmapCardThumbnail : Container + public partial class BeatmapCardThumbnail : Container { public BindableBool Dimmed { get; } = new BindableBool(); @@ -30,7 +30,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards private readonly UpdateableOnlineBeatmapSetCover cover; private readonly Container foreground; private readonly PlayButton playButton; - private readonly SmoothCircularProgress progress; + private readonly CircularProgress progress; private readonly Container content; protected override Container Content => content; @@ -53,7 +53,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards { RelativeSizeAxes = Axes.Both }, - progress = new SmoothCircularProgress + progress = new CircularProgress { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game/Beatmaps/Drawables/Cards/Buttons/BeatmapCardIconButton.cs b/osu.Game/Beatmaps/Drawables/Cards/Buttons/BeatmapCardIconButton.cs index af1a8eb06a..ee45d56b6e 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/Buttons/BeatmapCardIconButton.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/Buttons/BeatmapCardIconButton.cs @@ -17,7 +17,7 @@ using osuTK.Graphics; namespace osu.Game.Beatmaps.Drawables.Cards.Buttons { - public abstract class BeatmapCardIconButton : OsuClickableContainer + public abstract partial class BeatmapCardIconButton : OsuClickableContainer { private Colour4 idleColour; diff --git a/osu.Game/Beatmaps/Drawables/Cards/Buttons/DownloadButton.cs b/osu.Game/Beatmaps/Drawables/Cards/Buttons/DownloadButton.cs index 1b15b2498c..7f23b46150 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/Buttons/DownloadButton.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/Buttons/DownloadButton.cs @@ -15,7 +15,7 @@ using osuTK; namespace osu.Game.Beatmaps.Drawables.Cards.Buttons { - public class DownloadButton : BeatmapCardIconButton + public partial class DownloadButton : BeatmapCardIconButton { public Bindable State { get; } = new Bindable(); diff --git a/osu.Game/Beatmaps/Drawables/Cards/Buttons/FavouriteButton.cs b/osu.Game/Beatmaps/Drawables/Cards/Buttons/FavouriteButton.cs index bc0fcb92bb..f698185863 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/Buttons/FavouriteButton.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/Buttons/FavouriteButton.cs @@ -15,7 +15,7 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Beatmaps.Drawables.Cards.Buttons { - public class FavouriteButton : BeatmapCardIconButton, IHasCurrentValue + public partial class FavouriteButton : BeatmapCardIconButton, IHasCurrentValue { private readonly BindableWithCurrent current; diff --git a/osu.Game/Beatmaps/Drawables/Cards/Buttons/GoToBeatmapButton.cs b/osu.Game/Beatmaps/Drawables/Cards/Buttons/GoToBeatmapButton.cs index 127c5bd903..3df94bf233 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/Buttons/GoToBeatmapButton.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/Buttons/GoToBeatmapButton.cs @@ -10,7 +10,7 @@ using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Beatmaps.Drawables.Cards.Buttons { - public class GoToBeatmapButton : BeatmapCardIconButton + public partial class GoToBeatmapButton : BeatmapCardIconButton { public IBindable State => state; private readonly Bindable state = new Bindable(); diff --git a/osu.Game/Beatmaps/Drawables/Cards/Buttons/PlayButton.cs b/osu.Game/Beatmaps/Drawables/Cards/Buttons/PlayButton.cs index c5436182a4..f808fd21b7 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/Buttons/PlayButton.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/Buttons/PlayButton.cs @@ -16,7 +16,7 @@ using osuTK; namespace osu.Game.Beatmaps.Drawables.Cards.Buttons { - public class PlayButton : OsuHoverContainer + public partial class PlayButton : OsuHoverContainer { public IBindable Progress => progress; private readonly BindableDouble progress = new BindableDouble(); diff --git a/osu.Game/Beatmaps/Drawables/Cards/CollapsibleButtonContainer.cs b/osu.Game/Beatmaps/Drawables/Cards/CollapsibleButtonContainer.cs index 9b200d62aa..fe2ee8c7cc 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/CollapsibleButtonContainer.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/CollapsibleButtonContainer.cs @@ -14,7 +14,7 @@ using osu.Game.Overlays; namespace osu.Game.Beatmaps.Drawables.Cards { - public class CollapsibleButtonContainer : Container + public partial class CollapsibleButtonContainer : Container { public Bindable ShowDetails = new Bindable(); public Bindable FavouriteState = new Bindable(); diff --git a/osu.Game/Beatmaps/Drawables/Cards/ExpandedContentScrollContainer.cs b/osu.Game/Beatmaps/Drawables/Cards/ExpandedContentScrollContainer.cs index c0ed6ac1a9..9a2a37a09a 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/ExpandedContentScrollContainer.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/ExpandedContentScrollContainer.cs @@ -11,7 +11,7 @@ using osu.Game.Graphics.Containers; namespace osu.Game.Beatmaps.Drawables.Cards { - public class ExpandedContentScrollContainer : OsuScrollContainer + public partial class ExpandedContentScrollContainer : OsuScrollContainer { public const float HEIGHT = 200; @@ -61,7 +61,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards protected override bool OnClick(ClickEvent e) => true; - private class ExpandedContentScrollbar : OsuScrollbar + private partial class ExpandedContentScrollbar : OsuScrollbar { public ExpandedContentScrollbar(Direction scrollDir) : base(scrollDir) diff --git a/osu.Game/Beatmaps/Drawables/Cards/HoverHandlingContainer.cs b/osu.Game/Beatmaps/Drawables/Cards/HoverHandlingContainer.cs index 7d70f3c4cd..91cd498b81 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/HoverHandlingContainer.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/HoverHandlingContainer.cs @@ -7,7 +7,7 @@ using osu.Framework.Input.Events; namespace osu.Game.Beatmaps.Drawables.Cards { - public class HoverHandlingContainer : Container + public partial class HoverHandlingContainer : Container { public Func? Hovered { get; set; } public Action? Unhovered { get; set; } diff --git a/osu.Game/Beatmaps/Drawables/Cards/IconPill.cs b/osu.Game/Beatmaps/Drawables/Cards/IconPill.cs index aad71610a5..3cabbba98d 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/IconPill.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/IconPill.cs @@ -14,7 +14,7 @@ using osuTK.Graphics; namespace osu.Game.Beatmaps.Drawables.Cards { - public abstract class IconPill : CircularContainer, IHasTooltip + public abstract partial class IconPill : CircularContainer, IHasTooltip { public Vector2 IconSize { diff --git a/osu.Game/Beatmaps/Drawables/Cards/Statistics/BeatmapCardDateStatistic.cs b/osu.Game/Beatmaps/Drawables/Cards/Statistics/BeatmapCardDateStatistic.cs index f6fc3070aa..2948e89e60 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/Statistics/BeatmapCardDateStatistic.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/Statistics/BeatmapCardDateStatistic.cs @@ -9,7 +9,7 @@ using osu.Game.Graphics; namespace osu.Game.Beatmaps.Drawables.Cards.Statistics { - public class BeatmapCardDateStatistic : BeatmapCardStatistic + public partial class BeatmapCardDateStatistic : BeatmapCardStatistic { private readonly DateTimeOffset dateTime; diff --git a/osu.Game/Beatmaps/Drawables/Cards/Statistics/BeatmapCardStatistic.cs b/osu.Game/Beatmaps/Drawables/Cards/Statistics/BeatmapCardStatistic.cs index 89a4687500..10de2b9128 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/Statistics/BeatmapCardStatistic.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/Statistics/BeatmapCardStatistic.cs @@ -19,7 +19,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards.Statistics /// /// A single statistic shown on a beatmap card. /// - public abstract class BeatmapCardStatistic : CompositeDrawable, IHasTooltip, IHasCustomTooltip + public abstract partial class BeatmapCardStatistic : CompositeDrawable, IHasTooltip, IHasCustomTooltip { protected IconUsage Icon { diff --git a/osu.Game/Beatmaps/Drawables/Cards/Statistics/FavouritesStatistic.cs b/osu.Game/Beatmaps/Drawables/Cards/Statistics/FavouritesStatistic.cs index cef1f630ed..439e6acd22 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/Statistics/FavouritesStatistic.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/Statistics/FavouritesStatistic.cs @@ -15,7 +15,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards.Statistics /// /// Shows the number of favourites that a beatmap set has received. /// - public class FavouritesStatistic : BeatmapCardStatistic, IHasCurrentValue + public partial class FavouritesStatistic : BeatmapCardStatistic, IHasCurrentValue { private readonly BindableWithCurrent current; diff --git a/osu.Game/Beatmaps/Drawables/Cards/Statistics/HypesStatistic.cs b/osu.Game/Beatmaps/Drawables/Cards/Statistics/HypesStatistic.cs index 26b90ba0c0..840763b58e 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/Statistics/HypesStatistic.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/Statistics/HypesStatistic.cs @@ -10,7 +10,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards.Statistics /// /// Shows the number of current hypes that a map has received, as well as the number of hypes required for nomination. /// - public class HypesStatistic : BeatmapCardStatistic + public partial class HypesStatistic : BeatmapCardStatistic { private HypesStatistic(BeatmapSetHypeStatus hypeStatus) { diff --git a/osu.Game/Beatmaps/Drawables/Cards/Statistics/NominationsStatistic.cs b/osu.Game/Beatmaps/Drawables/Cards/Statistics/NominationsStatistic.cs index 4f3605c138..083f1a353b 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/Statistics/NominationsStatistic.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/Statistics/NominationsStatistic.cs @@ -10,7 +10,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards.Statistics /// /// Shows the number of current nominations that a map has received, as well as the number of nominations required for qualification. /// - public class NominationsStatistic : BeatmapCardStatistic + public partial class NominationsStatistic : BeatmapCardStatistic { private NominationsStatistic(BeatmapSetNominationStatus nominationStatus) { diff --git a/osu.Game/Beatmaps/Drawables/Cards/Statistics/PlayCountStatistic.cs b/osu.Game/Beatmaps/Drawables/Cards/Statistics/PlayCountStatistic.cs index f66d51de5d..45ab6ddb40 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/Statistics/PlayCountStatistic.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/Statistics/PlayCountStatistic.cs @@ -13,7 +13,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards.Statistics /// /// Shows the number of times the given beatmap set has been played. /// - public class PlayCountStatistic : BeatmapCardStatistic + public partial class PlayCountStatistic : BeatmapCardStatistic { public PlayCountStatistic(IBeatmapSetOnlineInfo onlineInfo) { diff --git a/osu.Game/Beatmaps/Drawables/Cards/StoryboardIconPill.cs b/osu.Game/Beatmaps/Drawables/Cards/StoryboardIconPill.cs index dcb2c3c760..6de16da2b1 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/StoryboardIconPill.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/StoryboardIconPill.cs @@ -9,7 +9,7 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Beatmaps.Drawables.Cards { - public class StoryboardIconPill : IconPill + public partial class StoryboardIconPill : IconPill { public StoryboardIconPill() : base(FontAwesome.Solid.Image) diff --git a/osu.Game/Beatmaps/Drawables/Cards/VideoIconPill.cs b/osu.Game/Beatmaps/Drawables/Cards/VideoIconPill.cs index 9ca1e5c4c4..63b5e95b12 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/VideoIconPill.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/VideoIconPill.cs @@ -9,7 +9,7 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Beatmaps.Drawables.Cards { - public class VideoIconPill : IconPill + public partial class VideoIconPill : IconPill { public VideoIconPill() : base(FontAwesome.Solid.Film) diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs index 679e9c3665..1665ec52fa 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs @@ -19,7 +19,7 @@ using osuTK.Graphics; namespace osu.Game.Beatmaps.Drawables { - public class DifficultyIcon : CompositeDrawable, IHasCustomTooltip, IHasCurrentValue + public partial class DifficultyIcon : CompositeDrawable, IHasCustomTooltip, IHasCurrentValue { /// /// Size of this difficulty icon. diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs b/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs index 4732de6e79..3fa24bcc3e 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs @@ -15,7 +15,7 @@ using osuTK; namespace osu.Game.Beatmaps.Drawables { - internal class DifficultyIconTooltip : VisibilityContainer, ITooltip + internal partial class DifficultyIconTooltip : VisibilityContainer, ITooltip { private OsuSpriteText difficultyName; private StarRatingDisplay starRating; diff --git a/osu.Game/Beatmaps/Drawables/DifficultySpectrumDisplay.cs b/osu.Game/Beatmaps/Drawables/DifficultySpectrumDisplay.cs index 22ca0a9037..efce0f80f1 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultySpectrumDisplay.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultySpectrumDisplay.cs @@ -18,7 +18,7 @@ using osuTK; namespace osu.Game.Beatmaps.Drawables { - public class DifficultySpectrumDisplay : CompositeDrawable + public partial class DifficultySpectrumDisplay : CompositeDrawable { private Vector2 dotSize = new Vector2(4, 8); @@ -83,7 +83,7 @@ namespace osu.Game.Beatmaps.Drawables } } - private class RulesetDifficultyGroup : FillFlowContainer + private partial class RulesetDifficultyGroup : FillFlowContainer { private readonly int rulesetId; private readonly IEnumerable beatmapInfos; @@ -143,7 +143,7 @@ namespace osu.Game.Beatmaps.Drawables } } - private class DifficultyDot : CircularContainer + private partial class DifficultyDot : CircularContainer { private readonly double starDifficulty; diff --git a/osu.Game/Beatmaps/Drawables/DownloadProgressBar.cs b/osu.Game/Beatmaps/Drawables/DownloadProgressBar.cs index 50bd7ad48e..9877b628db 100644 --- a/osu.Game/Beatmaps/Drawables/DownloadProgressBar.cs +++ b/osu.Game/Beatmaps/Drawables/DownloadProgressBar.cs @@ -14,7 +14,7 @@ using osuTK.Graphics; namespace osu.Game.Beatmaps.Drawables { - public class DownloadProgressBar : CompositeDrawable + public partial class DownloadProgressBar : CompositeDrawable { private readonly ProgressBar progressBar; private readonly BeatmapDownloadTracker downloadTracker; diff --git a/osu.Game/Beatmaps/Drawables/OnlineBeatmapSetCover.cs b/osu.Game/Beatmaps/Drawables/OnlineBeatmapSetCover.cs index 063990c89c..fc7c14e734 100644 --- a/osu.Game/Beatmaps/Drawables/OnlineBeatmapSetCover.cs +++ b/osu.Game/Beatmaps/Drawables/OnlineBeatmapSetCover.cs @@ -11,15 +11,14 @@ using osu.Framework.Graphics.Textures; namespace osu.Game.Beatmaps.Drawables { [LongRunningLoad] - public class OnlineBeatmapSetCover : Sprite + public partial class OnlineBeatmapSetCover : Sprite { private readonly IBeatmapSetOnlineInfo set; private readonly BeatmapSetCoverType type; public OnlineBeatmapSetCover(IBeatmapSetOnlineInfo set, BeatmapSetCoverType type = BeatmapSetCoverType.Cover) { - if (set == null) - throw new ArgumentNullException(nameof(set)); + ArgumentNullException.ThrowIfNull(set); this.set = set; this.type = type; diff --git a/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs b/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs index 9585f1bdb5..36fff1dc3c 100644 --- a/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs +++ b/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs @@ -23,7 +23,7 @@ namespace osu.Game.Beatmaps.Drawables /// /// A pill that displays the star rating of a beatmap. /// - public class StarRatingDisplay : CompositeDrawable, IHasCurrentValue + public partial class StarRatingDisplay : CompositeDrawable, IHasCurrentValue { private readonly bool animated; private readonly Box background; diff --git a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs index f37771a74d..2cd9785048 100644 --- a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs +++ b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs @@ -14,7 +14,7 @@ namespace osu.Game.Beatmaps.Drawables /// /// Display a beatmap background from a local source, but fallback to online source if not available. /// - public class UpdateableBeatmapBackgroundSprite : ModelBackedDrawable + public partial class UpdateableBeatmapBackgroundSprite : ModelBackedDrawable { public readonly Bindable Beatmap = new Bindable(); diff --git a/osu.Game/Beatmaps/Drawables/UpdateableOnlineBeatmapSetCover.cs b/osu.Game/Beatmaps/Drawables/UpdateableOnlineBeatmapSetCover.cs index 236bb63e24..93b0dd5c15 100644 --- a/osu.Game/Beatmaps/Drawables/UpdateableOnlineBeatmapSetCover.cs +++ b/osu.Game/Beatmaps/Drawables/UpdateableOnlineBeatmapSetCover.cs @@ -11,7 +11,7 @@ using osu.Game.Graphics; namespace osu.Game.Beatmaps.Drawables { - public class UpdateableOnlineBeatmapSetCover : ModelBackedDrawable + public partial class UpdateableOnlineBeatmapSetCover : ModelBackedDrawable { private readonly BeatmapSetCoverType coverType; diff --git a/osu.Game/Beatmaps/Formats/Decoder.cs b/osu.Game/Beatmaps/Formats/Decoder.cs index ca1bcc97fd..4f0f11d053 100644 --- a/osu.Game/Beatmaps/Formats/Decoder.cs +++ b/osu.Game/Beatmaps/Formats/Decoder.cs @@ -57,8 +57,7 @@ namespace osu.Game.Beatmaps.Formats public static Decoder GetDecoder(LineBufferedReader stream) where T : new() { - if (stream == null) - throw new ArgumentNullException(nameof(stream)); + ArgumentNullException.ThrowIfNull(stream); if (!decoders.TryGetValue(typeof(T), out var typedDecoders)) throw new IOException(@"Unknown decoder type"); diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 5f0a2a0824..9c710b690e 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -160,7 +160,7 @@ namespace osu.Game.Beatmaps.Formats break; case @"SampleSet": - defaultSampleBank = (LegacySampleBank)Enum.Parse(typeof(LegacySampleBank), pair.Value); + defaultSampleBank = Enum.Parse(pair.Value); break; case @"SampleVolume": @@ -218,7 +218,7 @@ namespace osu.Game.Beatmaps.Formats break; case @"Countdown": - beatmap.BeatmapInfo.Countdown = (CountdownType)Enum.Parse(typeof(CountdownType), pair.Value); + beatmap.BeatmapInfo.Countdown = Enum.Parse(pair.Value); break; case @"CountdownOffset": diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs index 03c63ff4f2..7e058d755e 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs @@ -300,7 +300,7 @@ namespace osu.Game.Beatmaps.Formats { var comboColour = colours[i]; - writer.Write(FormattableString.Invariant($"Combo{i}: ")); + writer.Write(FormattableString.Invariant($"Combo{1 + i}: ")); writer.Write(FormattableString.Invariant($"{(byte)(comboColour.R * byte.MaxValue)},")); writer.Write(FormattableString.Invariant($"{(byte)(comboColour.G * byte.MaxValue)},")); writer.Write(FormattableString.Invariant($"{(byte)(comboColour.B * byte.MaxValue)},")); diff --git a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs index a4e15f790a..704756e3dd 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs @@ -132,13 +132,7 @@ namespace osu.Game.Beatmaps.Formats protected KeyValuePair SplitKeyVal(string line, char separator = ':', bool shouldTrim = true) { - string[] split = line.Split(separator, 2); - - if (shouldTrim) - { - for (int i = 0; i < split.Length; i++) - split[i] = split[i].Trim(); - } + string[] split = line.Split(separator, 2, shouldTrim ? StringSplitOptions.TrimEntries : StringSplitOptions.None); return new KeyValuePair ( diff --git a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs index 2b4f377ab6..44dbb3cc9f 100644 --- a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs @@ -301,11 +301,11 @@ namespace osu.Game.Beatmaps.Formats } } - private string parseLayer(string value) => Enum.Parse(typeof(LegacyStoryLayer), value).ToString(); + private string parseLayer(string value) => Enum.Parse(value).ToString(); private Anchor parseOrigin(string value) { - var origin = (LegacyOrigins)Enum.Parse(typeof(LegacyOrigins), value); + var origin = Enum.Parse(value); switch (origin) { @@ -343,8 +343,8 @@ namespace osu.Game.Beatmaps.Formats private AnimationLoopType parseAnimationLoopType(string value) { - var parsed = (AnimationLoopType)Enum.Parse(typeof(AnimationLoopType), value); - return Enum.IsDefined(typeof(AnimationLoopType), parsed) ? parsed : AnimationLoopType.LoopForever; + var parsed = Enum.Parse(value); + return Enum.IsDefined(parsed) ? parsed : AnimationLoopType.LoopForever; } private void handleVariables(string line) diff --git a/osu.Game/Beatmaps/FramedBeatmapClock.cs b/osu.Game/Beatmaps/FramedBeatmapClock.cs index c7050cc50f..080b0ce7ec 100644 --- a/osu.Game/Beatmaps/FramedBeatmapClock.cs +++ b/osu.Game/Beatmaps/FramedBeatmapClock.cs @@ -24,7 +24,7 @@ namespace osu.Game.Beatmaps /// - Exposes track length. /// - Allows changing the source to a new track (for cases like editor track updating). /// - public class FramedBeatmapClock : Component, IFrameBasedClock, IAdjustableClock, ISourceChangeableClock + public partial class FramedBeatmapClock : Component, IFrameBasedClock, IAdjustableClock, ISourceChangeableClock { private readonly bool applyOffsets; diff --git a/osu.Game/Beatmaps/IBeatmap.cs b/osu.Game/Beatmaps/IBeatmap.cs index 0e892b6581..f6771f7adf 100644 --- a/osu.Game/Beatmaps/IBeatmap.cs +++ b/osu.Game/Beatmaps/IBeatmap.cs @@ -4,6 +4,7 @@ #nullable disable using System.Collections.Generic; +using System.Linq; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.Timing; using osu.Game.Rulesets.Objects; @@ -102,5 +103,16 @@ namespace osu.Game.Beatmaps addCombo(nested, ref combo); } } + + /// + /// Find the absolute end time of the latest in a beatmap. Will throw if beatmap contains no objects. + /// + /// + /// This correctly accounts for rulesets which have concurrent hitobjects which may have durations, causing the .Last() object + /// to not necessarily have the latest end time. + /// + /// It's not super efficient so calls should be kept to a minimum. + /// + public static double GetLastObjectTime(this IBeatmap beatmap) => beatmap.HitObjects.Max(h => h.GetEndTime()); } } diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 393c4ba892..ab790617bb 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -34,8 +34,6 @@ namespace osu.Game.Beatmaps // TODO: remove once the fallback lookup is not required (and access via `working.BeatmapInfo.Metadata` directly). public BeatmapMetadata Metadata => BeatmapInfo.Metadata; - public Waveform Waveform => waveform.Value; - public Storyboard Storyboard => storyboard.Value; public Texture Background => GetBackground(); // Texture uses ref counting, so we want to return a new instance every usage. @@ -48,10 +46,11 @@ namespace osu.Game.Beatmaps private readonly object beatmapFetchLock = new object(); - private readonly Lazy waveform; private readonly Lazy storyboard; private readonly Lazy skin; + private Track track; // track is not Lazy as we allow transferring and loading multiple times. + private Waveform waveform; // waveform is also not Lazy as the track may change. protected WorkingBeatmap(BeatmapInfo beatmapInfo, AudioManager audioManager) { @@ -60,7 +59,6 @@ namespace osu.Game.Beatmaps BeatmapInfo = beatmapInfo; BeatmapSetInfo = beatmapInfo.BeatmapSet ?? new BeatmapSetInfo(); - waveform = new Lazy(GetWaveform); storyboard = new Lazy(GetStoryboard); skin = new Lazy(GetSkin); } @@ -108,7 +106,16 @@ namespace osu.Game.Beatmaps public virtual bool TrackLoaded => track != null; - public Track LoadTrack() => track = GetBeatmapTrack() ?? GetVirtualTrack(1000); + public Track LoadTrack() + { + track = GetBeatmapTrack() ?? GetVirtualTrack(1000); + + // the track may have changed, recycle the current waveform. + waveform?.Dispose(); + waveform = null; + + return track; + } public void PrepareTrackForPreview(bool looping, double offsetFromPreviewPoint = 0) { @@ -171,6 +178,12 @@ namespace osu.Game.Beatmaps #endregion + #region Waveform + + public Waveform Waveform => waveform ??= GetWaveform(); + + #endregion + #region Beatmap public virtual bool BeatmapLoaded => beatmapLoadTask?.IsCompleted ?? false; diff --git a/osu.Game/Beatmaps/WorkingBeatmapCache.cs b/osu.Game/Beatmaps/WorkingBeatmapCache.cs index adb5f8c433..e6f96330e7 100644 --- a/osu.Game/Beatmaps/WorkingBeatmapCache.cs +++ b/osu.Game/Beatmaps/WorkingBeatmapCache.cs @@ -141,6 +141,9 @@ namespace osu.Game.Beatmaps try { string fileStorePath = BeatmapSetInfo.GetPathForFile(BeatmapInfo.Path); + + // TODO: check validity of file + var stream = GetStream(fileStorePath); if (stream == null) diff --git a/osu.Game/Collections/CollectionDropdown.cs b/osu.Game/Collections/CollectionDropdown.cs index 71341f51a4..19fa3a3d66 100644 --- a/osu.Game/Collections/CollectionDropdown.cs +++ b/osu.Game/Collections/CollectionDropdown.cs @@ -6,6 +6,7 @@ using System.Diagnostics; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.UserInterface; @@ -23,7 +24,7 @@ namespace osu.Game.Collections /// /// A dropdown to select the collection to be used to filter results. /// - public class CollectionDropdown : OsuDropdown + public partial class CollectionDropdown : OsuDropdown { /// /// Whether to show the "manage collections..." menu item in the dropdown. @@ -100,7 +101,7 @@ namespace osu.Game.Collections private void selectionChanged(ValueChangedEvent filter) { // May be null during .Clear(). - if (filter.NewValue == null) + if (filter.NewValue.IsNull()) return; // Never select the manage collection filter - rollback to the previous filter. @@ -112,7 +113,7 @@ namespace osu.Game.Collections return; } - var newCollection = filter.NewValue?.Collection; + var newCollection = filter.NewValue.Collection; // This dropdown be weird. // We only care about filtering if the actual collection has changed. @@ -139,7 +140,7 @@ namespace osu.Game.Collections protected virtual CollectionDropdownMenu CreateCollectionMenu() => new CollectionDropdownMenu(); - public class CollectionDropdownHeader : OsuDropdownHeader + public partial class CollectionDropdownHeader : OsuDropdownHeader { public CollectionDropdownHeader() { @@ -149,7 +150,7 @@ namespace osu.Game.Collections } } - protected class CollectionDropdownMenu : OsuDropdownMenu + protected partial class CollectionDropdownMenu : OsuDropdownMenu { public CollectionDropdownMenu() { @@ -163,7 +164,7 @@ namespace osu.Game.Collections }; } - protected class CollectionDropdownDrawableMenuItem : OsuDropdownMenu.DrawableOsuDropdownMenuItem + protected partial class CollectionDropdownDrawableMenuItem : OsuDropdownMenu.DrawableOsuDropdownMenuItem { private IconButton addOrRemoveButton = null!; diff --git a/osu.Game/Collections/DeleteCollectionDialog.cs b/osu.Game/Collections/DeleteCollectionDialog.cs index bf187265c1..4b23f661f9 100644 --- a/osu.Game/Collections/DeleteCollectionDialog.cs +++ b/osu.Game/Collections/DeleteCollectionDialog.cs @@ -8,7 +8,7 @@ using osu.Game.Overlays.Dialog; namespace osu.Game.Collections { - public class DeleteCollectionDialog : DeleteConfirmationDialog + public partial class DeleteCollectionDialog : DeleteConfirmationDialog { public DeleteCollectionDialog(Live collection, Action deleteAction) { diff --git a/osu.Game/Collections/DrawableCollectionList.cs b/osu.Game/Collections/DrawableCollectionList.cs index 0f4362fff3..0fdf196c4a 100644 --- a/osu.Game/Collections/DrawableCollectionList.cs +++ b/osu.Game/Collections/DrawableCollectionList.cs @@ -18,7 +18,7 @@ namespace osu.Game.Collections /// /// Visualises a list of s. /// - public class DrawableCollectionList : OsuRearrangeableListContainer> + public partial class DrawableCollectionList : OsuRearrangeableListContainer> { protected override ScrollContainer CreateScrollContainer() => scroll = new Scroll(); @@ -68,7 +68,7 @@ namespace osu.Game.Collections /// /// Use to transfer the placeholder into the main list. /// - private class Scroll : OsuScrollContainer + private partial class Scroll : OsuScrollContainer { /// /// The currently-displayed placeholder item. @@ -132,7 +132,7 @@ namespace osu.Game.Collections /// /// The flow of . Disables layout easing unless a drag is in progress. /// - private class Flow : FillFlowContainer>> + private partial class Flow : FillFlowContainer>> { public readonly IBindable DragActive = new Bindable(); diff --git a/osu.Game/Collections/DrawableCollectionListItem.cs b/osu.Game/Collections/DrawableCollectionListItem.cs index d1e40f6262..23156b1ad5 100644 --- a/osu.Game/Collections/DrawableCollectionListItem.cs +++ b/osu.Game/Collections/DrawableCollectionListItem.cs @@ -23,7 +23,7 @@ namespace osu.Game.Collections /// /// Visualises a inside a . /// - public class DrawableCollectionListItem : OsuRearrangeableListItem> + public partial class DrawableCollectionListItem : OsuRearrangeableListItem> { private const float item_height = 35; private const float button_width = item_height * 0.75f; @@ -44,7 +44,7 @@ namespace osu.Game.Collections /// /// The main content of the . /// - private class ItemContent : CircularContainer + private partial class ItemContent : CircularContainer { private readonly Live collection; @@ -113,7 +113,7 @@ namespace osu.Game.Collections } } - private class ItemTextBox : OsuTextBox + private partial class ItemTextBox : OsuTextBox { protected override float LeftRightPadding => item_height / 2; @@ -125,7 +125,7 @@ namespace osu.Game.Collections } } - public class DeleteButton : CompositeDrawable + public partial class DeleteButton : CompositeDrawable { public Func IsTextBoxHovered = null!; diff --git a/osu.Game/Collections/ManageCollectionsDialog.cs b/osu.Game/Collections/ManageCollectionsDialog.cs index 13737dbd78..36142cf26f 100644 --- a/osu.Game/Collections/ManageCollectionsDialog.cs +++ b/osu.Game/Collections/ManageCollectionsDialog.cs @@ -16,7 +16,7 @@ using osuTK; namespace osu.Game.Collections { - public class ManageCollectionsDialog : OsuFocusedOverlayContainer + public partial class ManageCollectionsDialog : OsuFocusedOverlayContainer { private const double enter_duration = 500; private const double exit_duration = 200; diff --git a/osu.Game/Configuration/SessionStatics.cs b/osu.Game/Configuration/SessionStatics.cs index 12a30a0c84..276563e163 100644 --- a/osu.Game/Configuration/SessionStatics.cs +++ b/osu.Game/Configuration/SessionStatics.cs @@ -19,6 +19,7 @@ namespace osu.Game.Configuration SetDefault(Static.LoginOverlayDisplayed, false); SetDefault(Static.MutedAudioNotificationShownOnce, false); SetDefault(Static.LowBatteryNotificationShownOnce, false); + SetDefault(Static.FeaturedArtistDisclaimerShownOnce, false); SetDefault(Static.LastHoverSoundPlaybackTime, (double?)null); SetDefault(Static.SeasonalBackgrounds, null); } @@ -42,6 +43,7 @@ namespace osu.Game.Configuration LoginOverlayDisplayed, MutedAudioNotificationShownOnce, LowBatteryNotificationShownOnce, + FeaturedArtistDisclaimerShownOnce, /// /// Info about seasonal backgrounds available fetched from API - see . @@ -53,6 +55,6 @@ namespace osu.Game.Configuration /// The last playback time in milliseconds of a hover sample (from ). /// Used to debounce hover sounds game-wide to avoid volume saturation, especially in scrolling views with many UI controls like . /// - LastHoverSoundPlaybackTime + LastHoverSoundPlaybackTime, } } diff --git a/osu.Game/Configuration/SettingSourceAttribute.cs b/osu.Game/Configuration/SettingSourceAttribute.cs index 630b65ae82..1e425c88a6 100644 --- a/osu.Game/Configuration/SettingSourceAttribute.cs +++ b/osu.Game/Configuration/SettingSourceAttribute.cs @@ -91,15 +91,15 @@ namespace osu.Game.Configuration OrderPosition = orderPosition; } - public int CompareTo(SettingSourceAttribute other) + public int CompareTo(SettingSourceAttribute? other) { - if (OrderPosition == other.OrderPosition) + if (OrderPosition == other?.OrderPosition) return 0; // unordered items come last (are greater than any ordered items). if (OrderPosition == null) return 1; - if (other.OrderPosition == null) + if (other?.OrderPosition == null) return -1; // ordered items are sorted by the order value. @@ -107,13 +107,13 @@ namespace osu.Game.Configuration } } - public static class SettingSourceExtensions + public static partial class SettingSourceExtensions { public static IEnumerable CreateSettingsControls(this object obj) { foreach (var (attr, property) in obj.GetOrderedSettingsSourceProperties()) { - object value = property.GetValue(obj); + object value = property.GetValue(obj)!; if (attr.SettingControlType != null) { @@ -121,7 +121,7 @@ namespace osu.Game.Configuration if (controlType.EnumerateBaseTypes().All(t => !t.IsGenericType || t.GetGenericTypeDefinition() != typeof(SettingsItem<>))) throw new InvalidOperationException($"{nameof(SettingSourceAttribute)} had an unsupported custom control type ({controlType.ReadableName()})"); - var control = (Drawable)Activator.CreateInstance(controlType); + var control = (Drawable)Activator.CreateInstance(controlType)!; controlType.GetProperty(nameof(SettingsItem.SettingSourceObject))?.SetValue(control, obj); controlType.GetProperty(nameof(SettingsItem.LabelText))?.SetValue(control, attr.Label); controlType.GetProperty(nameof(SettingsItem.TooltipText))?.SetValue(control, attr.Description); @@ -188,7 +188,7 @@ namespace osu.Game.Configuration case IBindable bindable: var dropdownType = typeof(ModSettingsEnumDropdown<>).MakeGenericType(bindable.GetType().GetGenericArguments()[0]); - var dropdown = (Drawable)Activator.CreateInstance(dropdownType); + var dropdown = (Drawable)Activator.CreateInstance(dropdownType)!; dropdownType.GetProperty(nameof(SettingsDropdown.LabelText))?.SetValue(dropdown, attr.Label); dropdownType.GetProperty(nameof(SettingsDropdown.TooltipText))?.SetValue(dropdown, attr.Description); @@ -231,7 +231,7 @@ namespace osu.Game.Configuration // An unknown (e.g. enum) generic type. var valueMethod = u.GetType().GetProperty(nameof(IBindable.Value)); Debug.Assert(valueMethod != null); - return valueMethod.GetValue(u); + return valueMethod.GetValue(u)!; default: // fall back for non-bindable cases. @@ -267,12 +267,12 @@ namespace osu.Game.Configuration .OrderBy(attr => attr.Item1) .ToArray(); - private class ModSettingsEnumDropdown : SettingsEnumDropdown + private partial class ModSettingsEnumDropdown : SettingsEnumDropdown where T : struct, Enum { protected override OsuDropdown CreateDropdown() => new ModDropdownControl(); - private class ModDropdownControl : DropdownControl + private partial class ModDropdownControl : DropdownControl { // Set menu's max height low enough to workaround nested scroll issues (see https://github.com/ppy/osu-framework/issues/4536). protected override DropdownMenu CreateMenu() => base.CreateMenu().With(m => m.MaxHeight = 100); diff --git a/osu.Game/Database/BeatmapLookupCache.cs b/osu.Game/Database/BeatmapLookupCache.cs index 53cb7d72fc..d9bf0138dc 100644 --- a/osu.Game/Database/BeatmapLookupCache.cs +++ b/osu.Game/Database/BeatmapLookupCache.cs @@ -13,7 +13,7 @@ using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Database { - public class BeatmapLookupCache : OnlineLookupCache + public partial class BeatmapLookupCache : OnlineLookupCache { /// /// Perform an API lookup on the specified beatmap, populating a model. diff --git a/osu.Game/Database/ICanAcceptFiles.cs b/osu.Game/Database/ICanAcceptFiles.cs index 3ce343249b..da970a29d4 100644 --- a/osu.Game/Database/ICanAcceptFiles.cs +++ b/osu.Game/Database/ICanAcceptFiles.cs @@ -31,7 +31,8 @@ namespace osu.Game.Database /// This will post notifications tracking progress. /// /// The import tasks from which the files should be imported. - Task Import(params ImportTask[] tasks); + /// Parameters to further configure the import process. + Task Import(ImportTask[] tasks, ImportParameters parameters = default); /// /// An array of accepted file extensions (in the standard format of ".abc"). diff --git a/osu.Game/Database/IModelImporter.cs b/osu.Game/Database/IModelImporter.cs index 4085f122d0..dcbbad0d35 100644 --- a/osu.Game/Database/IModelImporter.cs +++ b/osu.Game/Database/IModelImporter.cs @@ -20,8 +20,9 @@ namespace osu.Game.Database /// /// The notification to update. /// The import tasks. + /// Parameters to further configure the import process. /// The imported models. - Task>> Import(ProgressNotification notification, params ImportTask[] tasks); + Task>> Import(ProgressNotification notification, ImportTask[] tasks, ImportParameters parameters = default); /// /// Process a single import as an update for an existing model. diff --git a/osu.Game/Database/ImportParameters.cs b/osu.Game/Database/ImportParameters.cs new file mode 100644 index 0000000000..83ca0ac694 --- /dev/null +++ b/osu.Game/Database/ImportParameters.cs @@ -0,0 +1,25 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Database +{ + public struct ImportParameters + { + /// + /// Whether this import is part of a larger batch. + /// + /// + /// May skip intensive pre-import checks in favour of faster processing. + /// + /// More specifically, imports will be skipped before they begin, given an existing model matches on hash and filenames. Should generally only be used for large batch imports, as it may defy user expectations when updating an existing model. + /// + /// Will also change scheduling behaviour to run at a lower priority. + /// + public bool Batch { get; set; } + + /// + /// Whether this import should use hard links rather than file copy operations if available. + /// + public bool PreferHardLinks { get; set; } + } +} diff --git a/osu.Game/Database/ImportProgressNotification.cs b/osu.Game/Database/ImportProgressNotification.cs index aaee3e117f..762918f376 100644 --- a/osu.Game/Database/ImportProgressNotification.cs +++ b/osu.Game/Database/ImportProgressNotification.cs @@ -5,7 +5,7 @@ using osu.Game.Overlays.Notifications; namespace osu.Game.Database { - public class ImportProgressNotification : ProgressNotification + public partial class ImportProgressNotification : ProgressNotification { public ImportProgressNotification() { diff --git a/osu.Game/Database/LegacyExporter.cs b/osu.Game/Database/LegacyExporter.cs index 16d7441dde..09d6913dd9 100644 --- a/osu.Game/Database/LegacyExporter.cs +++ b/osu.Game/Database/LegacyExporter.cs @@ -3,9 +3,11 @@ #nullable disable +using System.Collections.Generic; using System.IO; using osu.Framework.Platform; using osu.Game.Extensions; +using osu.Game.Utils; using SharpCompress.Archives.Zip; namespace osu.Game.Database @@ -31,14 +33,19 @@ namespace osu.Game.Database UserFileStorage = storage.GetStorageForDirectory(@"files"); } + protected virtual string GetFilename(TModel item) => item.GetDisplayString(); + /// /// Exports an item to a legacy (.zip based) package. /// /// The item to export. public void Export(TModel item) { - string filename = $"{item.GetDisplayString().GetValidFilename()}{FileExtension}"; + string itemFilename = GetFilename(item).GetValidFilename(); + IEnumerable existingExports = exportStorage.GetFiles("", $"{itemFilename}*{FileExtension}"); + + string filename = NamingUtils.GetNextBestFilename(existingExports, $"{itemFilename}{FileExtension}"); using (var stream = exportStorage.CreateFileSafely(filename)) ExportModelTo(item, stream); diff --git a/osu.Game/Database/LegacyImportManager.cs b/osu.Game/Database/LegacyImportManager.cs index 78ebd8750e..20738f859e 100644 --- a/osu.Game/Database/LegacyImportManager.cs +++ b/osu.Game/Database/LegacyImportManager.cs @@ -22,7 +22,7 @@ namespace osu.Game.Database /// /// Handles migration of legacy user data from osu-stable. /// - public class LegacyImportManager : Component + public partial class LegacyImportManager : Component { [Resolved] private SkinManager skins { get; set; } = null!; @@ -42,8 +42,8 @@ namespace osu.Game.Database [Resolved] private RealmAccess realmAccess { get; set; } = null!; - [Resolved(canBeNull: true)] // canBeNull required while we remain on mono for mobile platforms. - private DesktopGameHost? desktopGameHost { get; set; } + [Resolved] + private GameHost gameHost { get; set; } = null!; [Resolved] private INotificationOverlay? notifications { get; set; } @@ -52,7 +52,20 @@ namespace osu.Game.Database public bool SupportsImportFromStable => RuntimeInfo.IsDesktop; - public void UpdateStorage(string stablePath) => cachedStorage = new StableStorage(stablePath, desktopGameHost); + public void UpdateStorage(string stablePath) => cachedStorage = new StableStorage(stablePath, gameHost as DesktopGameHost); + + public bool CheckSongsFolderHardLinkAvailability() + { + var stableStorage = GetCurrentStableStorage(); + + if (stableStorage == null || gameHost is not DesktopGameHost desktopGameHost) + return false; + + string testExistingPath = stableStorage.GetSongStorage().GetFullPath(string.Empty); + string testDestinationPath = desktopGameHost.Storage.GetFullPath(string.Empty); + + return HardLinkHelper.CheckAvailability(testDestinationPath, testExistingPath); + } public virtual async Task GetImportCount(StableContent content, CancellationToken cancellationToken) { @@ -66,16 +79,16 @@ namespace osu.Game.Database switch (content) { case StableContent.Beatmaps: - return await new LegacyBeatmapImporter(beatmaps).GetAvailableCount(stableStorage); + return await new LegacyBeatmapImporter(beatmaps).GetAvailableCount(stableStorage).ConfigureAwait(false); case StableContent.Skins: - return await new LegacySkinImporter(skins).GetAvailableCount(stableStorage); + return await new LegacySkinImporter(skins).GetAvailableCount(stableStorage).ConfigureAwait(false); case StableContent.Collections: - return await new LegacyCollectionImporter(realmAccess).GetAvailableCount(stableStorage); + return await new LegacyCollectionImporter(realmAccess).GetAvailableCount(stableStorage).ConfigureAwait(false); case StableContent.Scores: - return await new LegacyScoreImporter(scores).GetAvailableCount(stableStorage); + return await new LegacyScoreImporter(scores).GetAvailableCount(stableStorage).ConfigureAwait(false); default: throw new ArgumentException($"Only one {nameof(StableContent)} flag should be specified."); diff --git a/osu.Game/Database/LegacyModelImporter.cs b/osu.Game/Database/LegacyModelImporter.cs index df354a856e..29386a1103 100644 --- a/osu.Game/Database/LegacyModelImporter.cs +++ b/osu.Game/Database/LegacyModelImporter.cs @@ -57,7 +57,12 @@ namespace osu.Game.Database return Task.CompletedTask; } - return Task.Run(async () => await Importer.Import(GetStableImportPaths(storage).ToArray()).ConfigureAwait(false)); + return Task.Run(async () => + { + var tasks = GetStableImportPaths(storage).Select(p => new ImportTask(p)).ToArray(); + + await Importer.Import(tasks, new ImportParameters { Batch = true, PreferHardLinks = true }).ConfigureAwait(false); + }); } /// diff --git a/osu.Game/Database/LegacyScoreExporter.cs b/osu.Game/Database/LegacyScoreExporter.cs index 6fa02b957d..01f9afdc86 100644 --- a/osu.Game/Database/LegacyScoreExporter.cs +++ b/osu.Game/Database/LegacyScoreExporter.cs @@ -20,6 +20,14 @@ namespace osu.Game.Database { } + protected override string GetFilename(ScoreInfo score) + { + string scoreString = score.GetDisplayString(); + string filename = $"{scoreString} ({score.Date.LocalDateTime:yyyy-MM-dd_HH-mm})"; + + return filename; + } + public override void ExportModelTo(ScoreInfo model, Stream outputStream) { var file = model.Files.SingleOrDefault(); diff --git a/osu.Game/Database/Live.cs b/osu.Game/Database/Live.cs index 3bb11c3a50..2df6f3f508 100644 --- a/osu.Game/Database/Live.cs +++ b/osu.Game/Database/Live.cs @@ -61,6 +61,6 @@ namespace osu.Game.Database public override int GetHashCode() => HashCode.Combine(ID); - public override string ToString() => PerformRead(i => i.ToString()); + public override string? ToString() => PerformRead(i => i.ToString()); } } diff --git a/osu.Game/Database/MemoryCachingComponent.cs b/osu.Game/Database/MemoryCachingComponent.cs index 571a9ccc7c..5d1a381f09 100644 --- a/osu.Game/Database/MemoryCachingComponent.cs +++ b/osu.Game/Database/MemoryCachingComponent.cs @@ -18,7 +18,7 @@ namespace osu.Game.Database /// A component which performs lookups (or calculations) and caches the results. /// Currently not persisted between game sessions. /// - public abstract class MemoryCachingComponent : Component + public abstract partial class MemoryCachingComponent : Component { private readonly ConcurrentDictionary cache = new ConcurrentDictionary(); diff --git a/osu.Game/Database/ModelDownloader.cs b/osu.Game/Database/ModelDownloader.cs index 6cba8fe819..8aece748a8 100644 --- a/osu.Game/Database/ModelDownloader.cs +++ b/osu.Game/Database/ModelDownloader.cs @@ -14,7 +14,7 @@ using osu.Game.Overlays.Notifications; namespace osu.Game.Database { - public abstract class ModelDownloader : IModelDownloader + public abstract partial class ModelDownloader : IModelDownloader where TModel : class, IHasGuidPrimaryKey, ISoftDelete, IEquatable, T where T : class { @@ -71,9 +71,9 @@ namespace osu.Game.Database bool importSuccessful; if (originalModel != null) - importSuccessful = (await importer.ImportAsUpdate(notification, new ImportTask(filename), originalModel)) != null; + importSuccessful = (await importer.ImportAsUpdate(notification, new ImportTask(filename), originalModel).ConfigureAwait(false)) != null; else - importSuccessful = (await importer.Import(notification, new ImportTask(filename))).Any(); + importSuccessful = (await importer.Import(notification, new[] { new ImportTask(filename) }).ConfigureAwait(false)).Any(); // for now a failed import will be marked as a failed download for simplicity. if (!importSuccessful) @@ -124,7 +124,7 @@ namespace osu.Game.Database private bool canDownload(T model) => GetExistingDownload(model) == null && api != null; - private class DownloadNotification : ProgressNotification + private partial class DownloadNotification : ProgressNotification { public override bool IsImportant => false; @@ -134,7 +134,7 @@ namespace osu.Game.Database Text = CompletionText }; - private class SilencedProgressCompletionNotification : ProgressCompletionNotification + private partial class SilencedProgressCompletionNotification : ProgressCompletionNotification { public override bool IsImportant => false; } diff --git a/osu.Game/Database/ModelManager.cs b/osu.Game/Database/ModelManager.cs index 5c106aa493..7d1dc5239a 100644 --- a/osu.Game/Database/ModelManager.cs +++ b/osu.Game/Database/ModelManager.cs @@ -18,6 +18,11 @@ namespace osu.Game.Database public class ModelManager : IModelManager, IModelFileManager where TModel : RealmObject, IHasRealmFiles, IHasGuidPrimaryKey, ISoftDelete { + /// + /// Temporarily pause imports to avoid performance overheads affecting gameplay scenarios. + /// + public virtual bool PauseImports { get; set; } + protected RealmAccess Realm { get; } private readonly RealmFileStore realmFileStore; diff --git a/osu.Game/Database/OnlineLookupCache.cs b/osu.Game/Database/OnlineLookupCache.cs index 317c37bbfb..d9b37e2f29 100644 --- a/osu.Game/Database/OnlineLookupCache.cs +++ b/osu.Game/Database/OnlineLookupCache.cs @@ -15,7 +15,7 @@ using osu.Game.Online.API; namespace osu.Game.Database { - public abstract class OnlineLookupCache : MemoryCachingComponent + public abstract partial class OnlineLookupCache : MemoryCachingComponent where TLookup : IEquatable where TValue : class, IHasOnlineID where TRequest : APIRequest diff --git a/osu.Game/Database/RealmAccess.cs b/osu.Game/Database/RealmAccess.cs index 1a938c12e5..177c671bca 100644 --- a/osu.Game/Database/RealmAccess.cs +++ b/osu.Game/Database/RealmAccess.cs @@ -481,7 +481,7 @@ namespace osu.Game.Database // server, which we don't use. May want to report upstream or revisit in the future. using (var realm = getRealmInstance()) // ReSharper disable once AccessToDisposedClosure (WriteAsync should be marked as [InstantHandle]). - await realm.WriteAsync(() => action(realm)); + await realm.WriteAsync(() => action(realm)).ConfigureAwait(false); pendingAsyncWrites.Signal(); }); @@ -558,7 +558,7 @@ namespace osu.Game.Database return new InvokeOnDisposal(() => model.PropertyChanged -= onPropertyChanged); - void onPropertyChanged(object sender, PropertyChangedEventArgs args) + void onPropertyChanged(object? sender, PropertyChangedEventArgs args) { if (args.PropertyName == propertyName) onChanged(propLookupCompiled(model)); diff --git a/osu.Game/Database/RealmArchiveModelImporter.cs b/osu.Game/Database/RealmArchiveModelImporter.cs index 0286815569..db8861c281 100644 --- a/osu.Game/Database/RealmArchiveModelImporter.cs +++ b/osu.Game/Database/RealmArchiveModelImporter.cs @@ -56,6 +56,11 @@ namespace osu.Game.Database /// private static readonly ThreadedTaskScheduler import_scheduler_batch = new ThreadedTaskScheduler(import_queue_request_concurrency, nameof(RealmArchiveModelImporter)); + /// + /// Temporarily pause imports to avoid performance overheads affecting gameplay scenarios. + /// + public bool PauseImports { get; set; } + public abstract IEnumerable HandledExtensions { get; } protected readonly RealmFileStore Files; @@ -81,16 +86,16 @@ namespace osu.Game.Database public Task Import(params string[] paths) => Import(paths.Select(p => new ImportTask(p)).ToArray()); - public Task Import(params ImportTask[] tasks) + public Task Import(ImportTask[] tasks, ImportParameters parameters = default) { var notification = new ProgressNotification { State = ProgressNotificationState.Active }; PostNotification?.Invoke(notification); - return Import(notification, tasks); + return Import(notification, tasks, parameters); } - public async Task>> Import(ProgressNotification notification, params ImportTask[] tasks) + public async Task>> Import(ProgressNotification notification, ImportTask[] tasks, ImportParameters parameters = default) { if (tasks.Length == 0) { @@ -106,7 +111,7 @@ namespace osu.Game.Database var imported = new List>(); - bool isBatchImport = tasks.Length >= minimum_items_considered_batch_import; + parameters.Batch |= tasks.Length >= minimum_items_considered_batch_import; await Task.WhenAll(tasks.Select(async task => { @@ -115,7 +120,7 @@ namespace osu.Game.Database try { - var model = await Import(task, isBatchImport, notification.CancellationToken).ConfigureAwait(false); + var model = await Import(task, parameters, notification.CancellationToken).ConfigureAwait(false); lock (imported) { @@ -149,9 +154,12 @@ namespace osu.Game.Database } else { - notification.CompletionText = imported.Count == 1 - ? $"Imported {imported.First().GetDisplayString()}!" - : $"Imported {imported.Count} {HumanisedModelName}s!"; + if (tasks.Length > imported.Count) + notification.CompletionText = $"Imported {imported.Count} of {tasks.Length} {HumanisedModelName}s."; + else if (imported.Count > 1) + notification.CompletionText = $"Imported {imported.Count} {HumanisedModelName}s!"; + else + notification.CompletionText = $"Imported {imported.First().GetDisplayString()}!"; if (imported.Count > 0 && PresentImport != null) { @@ -176,16 +184,16 @@ namespace osu.Game.Database /// Note that this bypasses the UI flow and should only be used for special cases or testing. /// /// The containing data about the to import. - /// Whether this import is part of a larger batch. + /// Parameters to further configure the import process. /// An optional cancellation token. /// The imported model, if successful. - public async Task?> Import(ImportTask task, bool batchImport = false, CancellationToken cancellationToken = default) + public async Task?> Import(ImportTask task, ImportParameters parameters = default, CancellationToken cancellationToken = default) { cancellationToken.ThrowIfCancellationRequested(); Live? import; using (ArchiveReader reader = task.GetReader()) - import = await importFromArchive(reader, batchImport, cancellationToken).ConfigureAwait(false); + import = await importFromArchive(reader, parameters, cancellationToken).ConfigureAwait(false); // We may or may not want to delete the file depending on where it is stored. // e.g. reconstructing/repairing database with items from default storage. @@ -211,9 +219,9 @@ namespace osu.Game.Database /// This method also handled queueing the import task on a relevant import thread pool. /// /// The archive to be imported. - /// Whether this import is part of a larger batch. + /// Parameters to further configure the import process. /// An optional cancellation token. - private async Task?> importFromArchive(ArchiveReader archive, bool batchImport = false, CancellationToken cancellationToken = default) + private async Task?> importFromArchive(ArchiveReader archive, ImportParameters parameters = default, CancellationToken cancellationToken = default) { cancellationToken.ThrowIfCancellationRequested(); @@ -236,10 +244,10 @@ namespace osu.Game.Database return null; } - var scheduledImport = Task.Factory.StartNew(() => ImportModel(model, archive, batchImport, cancellationToken), + var scheduledImport = Task.Factory.StartNew(() => ImportModel(model, archive, parameters, cancellationToken), cancellationToken, TaskCreationOptions.HideScheduler, - batchImport ? import_scheduler_batch : import_scheduler); + parameters.Batch ? import_scheduler_batch : import_scheduler); return await scheduledImport.ConfigureAwait(false); } @@ -249,15 +257,15 @@ namespace osu.Game.Database /// /// The model to be imported. /// An optional archive to use for model population. - /// If true, imports will be skipped before they begin, given an existing model matches on hash and filenames. Should generally only be used for large batch imports, as it may defy user expectations when updating an existing model. + /// Parameters to further configure the import process. /// An optional cancellation token. - public virtual Live? ImportModel(TModel item, ArchiveReader? archive = null, bool batchImport = false, CancellationToken cancellationToken = default) => Realm.Run(realm => + public virtual Live? ImportModel(TModel item, ArchiveReader? archive = null, ImportParameters parameters = default, CancellationToken cancellationToken = default) => Realm.Run(realm => { - cancellationToken.ThrowIfCancellationRequested(); + pauseIfNecessary(cancellationToken); TModel? existing; - if (batchImport && archive != null) + if (parameters.Batch && archive != null) { // this is a fast bail condition to improve large import performance. item.Hash = computeHashFast(archive); @@ -303,7 +311,7 @@ namespace osu.Game.Database foreach (var filenames in getShortenedFilenames(archive)) { using (Stream s = archive.GetStream(filenames.original)) - files.Add(new RealmNamedFileUsage(Files.Add(s, realm, false), filenames.shortened)); + files.Add(new RealmNamedFileUsage(Files.Add(s, realm, false, parameters.PreferHardLinks), filenames.shortened)); } } @@ -358,7 +366,7 @@ namespace osu.Game.Database // import to store realm.Add(item); - PostImport(item, realm, batchImport); + PostImport(item, realm, parameters); transaction.Commit(); } @@ -493,8 +501,8 @@ namespace osu.Game.Database /// /// The model prepared for import. /// The current realm context. - /// Whether the import was part of a batch. - protected virtual void PostImport(TModel model, Realm realm, bool batchImport) + /// Parameters to further configure the import process. + protected virtual void PostImport(TModel model, Realm realm, ImportParameters parameters) { } @@ -551,6 +559,23 @@ namespace osu.Game.Database /// Whether to perform deletion. protected virtual bool ShouldDeleteArchive(string path) => false; + private void pauseIfNecessary(CancellationToken cancellationToken) + { + if (!PauseImports) + return; + + Logger.Log($@"{GetType().Name} is being paused."); + + while (PauseImports) + { + cancellationToken.ThrowIfCancellationRequested(); + Thread.Sleep(500); + } + + cancellationToken.ThrowIfCancellationRequested(); + Logger.Log($@"{GetType().Name} is being resumed."); + } + private IEnumerable getIDs(IEnumerable files) { foreach (var f in files.OrderBy(f => f.Filename)) diff --git a/osu.Game/Database/RealmFileStore.cs b/osu.Game/Database/RealmFileStore.cs index 036b15ea17..f75d3be725 100644 --- a/osu.Game/Database/RealmFileStore.cs +++ b/osu.Game/Database/RealmFileStore.cs @@ -10,6 +10,7 @@ using osu.Framework.Logging; using osu.Framework.Platform; using osu.Framework.Testing; using osu.Game.Extensions; +using osu.Game.IO; using osu.Game.Models; using Realms; @@ -41,7 +42,8 @@ namespace osu.Game.Database /// The file data stream. /// The realm instance to add to. Should already be in a transaction. /// Whether the should immediately be added to the underlying realm. If false is provided here, the instance must be manually added. - public RealmFile Add(Stream data, Realm realm, bool addToRealm = true) + /// Whether this import should use hard links rather than file copy operations if available. + public RealmFile Add(Stream data, Realm realm, bool addToRealm = true, bool preferHardLinks = false) { string hash = data.ComputeSHA2Hash(); @@ -50,7 +52,7 @@ namespace osu.Game.Database var file = existing ?? new RealmFile { Hash = hash }; if (!checkFileExistsAndMatchesHash(file)) - copyToStore(file, data); + copyToStore(file, data, preferHardLinks); if (addToRealm && !file.IsManaged) realm.Add(file); @@ -58,8 +60,15 @@ namespace osu.Game.Database return file; } - private void copyToStore(RealmFile file, Stream data) + private void copyToStore(RealmFile file, Stream data, bool preferHardLinks) { + if (data is FileStream fs && preferHardLinks) + { + // attempt to do a fast hard link rather than copy. + if (HardLinkHelper.TryCreateHardLink(Storage.GetFullPath(file.GetStoragePath(), true), fs.Name)) + return; + } + data.Seek(0, SeekOrigin.Begin); using (var output = Storage.CreateFileSafely(file.GetStoragePath())) diff --git a/osu.Game/Database/TooManyDownloadsNotification.cs b/osu.Game/Database/TooManyDownloadsNotification.cs index 14012e1d34..92e9a73026 100644 --- a/osu.Game/Database/TooManyDownloadsNotification.cs +++ b/osu.Game/Database/TooManyDownloadsNotification.cs @@ -9,7 +9,7 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Database { - public class TooManyDownloadsNotification : SimpleNotification + public partial class TooManyDownloadsNotification : SimpleNotification { public TooManyDownloadsNotification() { diff --git a/osu.Game/Database/UserLookupCache.cs b/osu.Game/Database/UserLookupCache.cs index 87f08d36ae..b1609fbf7b 100644 --- a/osu.Game/Database/UserLookupCache.cs +++ b/osu.Game/Database/UserLookupCache.cs @@ -13,7 +13,7 @@ using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Database { - public class UserLookupCache : OnlineLookupCache + public partial class UserLookupCache : OnlineLookupCache { /// /// Perform an API lookup on the specified user, populating a model. diff --git a/osu.Game/Extensions/DrawableExtensions.cs b/osu.Game/Extensions/DrawableExtensions.cs index 35f2d61437..65b9e46764 100644 --- a/osu.Game/Extensions/DrawableExtensions.cs +++ b/osu.Game/Extensions/DrawableExtensions.cs @@ -66,10 +66,10 @@ namespace osu.Game.Extensions foreach (var (_, property) in component.GetSettingsSourceProperties()) { - if (!info.Settings.TryGetValue(property.Name.ToSnakeCase(), out object settingValue)) + if (!info.Settings.TryGetValue(property.Name.ToSnakeCase(), out object? settingValue)) continue; - skinnable.CopyAdjustedSetting((IBindable)property.GetValue(component), settingValue); + skinnable.CopyAdjustedSetting(((IBindable)property.GetValue(component)!), settingValue); } } diff --git a/osu.Game/Extensions/TaskExtensions.cs b/osu.Game/Extensions/TaskExtensions.cs index b4a0c02e35..43abb59042 100644 --- a/osu.Game/Extensions/TaskExtensions.cs +++ b/osu.Game/Extensions/TaskExtensions.cs @@ -37,7 +37,7 @@ namespace osu.Game.Extensions if (cancellationToken.IsCancellationRequested) { - tcs.SetCanceled(); + tcs.SetCanceled(cancellationToken); } else { diff --git a/osu.Game/Graphics/Backgrounds/Background.cs b/osu.Game/Graphics/Backgrounds/Background.cs index 0899c0706d..bc2ad81fef 100644 --- a/osu.Game/Graphics/Backgrounds/Background.cs +++ b/osu.Game/Graphics/Backgrounds/Background.cs @@ -18,7 +18,7 @@ namespace osu.Game.Graphics.Backgrounds /// /// A background which offers blurring via a on demand. /// - public class Background : CompositeDrawable, IEquatable + public partial class Background : CompositeDrawable, IEquatable { public readonly Sprite Sprite; diff --git a/osu.Game/Graphics/Backgrounds/BeatmapBackground.cs b/osu.Game/Graphics/Backgrounds/BeatmapBackground.cs index 543bfe2bac..b79eb4927f 100644 --- a/osu.Game/Graphics/Backgrounds/BeatmapBackground.cs +++ b/osu.Game/Graphics/Backgrounds/BeatmapBackground.cs @@ -9,7 +9,7 @@ using osu.Game.Beatmaps; namespace osu.Game.Graphics.Backgrounds { - public class BeatmapBackground : Background + public partial class BeatmapBackground : Background { public readonly WorkingBeatmap Beatmap; diff --git a/osu.Game/Graphics/Backgrounds/BeatmapBackgroundWithStoryboard.cs b/osu.Game/Graphics/Backgrounds/BeatmapBackgroundWithStoryboard.cs index 0dcfa4e9aa..9c0d109ce4 100644 --- a/osu.Game/Graphics/Backgrounds/BeatmapBackgroundWithStoryboard.cs +++ b/osu.Game/Graphics/Backgrounds/BeatmapBackgroundWithStoryboard.cs @@ -14,7 +14,7 @@ using osu.Game.Storyboards.Drawables; namespace osu.Game.Graphics.Backgrounds { - public class BeatmapBackgroundWithStoryboard : BeatmapBackground + public partial class BeatmapBackgroundWithStoryboard : BeatmapBackground { private readonly InterpolatingFramedClock storyboardClock; diff --git a/osu.Game/Graphics/Backgrounds/SeasonalBackgroundLoader.cs b/osu.Game/Graphics/Backgrounds/SeasonalBackgroundLoader.cs index 9d873762bf..6f6febb646 100644 --- a/osu.Game/Graphics/Backgrounds/SeasonalBackgroundLoader.cs +++ b/osu.Game/Graphics/Backgrounds/SeasonalBackgroundLoader.cs @@ -17,7 +17,7 @@ using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Graphics.Backgrounds { - public class SeasonalBackgroundLoader : Component + public partial class SeasonalBackgroundLoader : Component { /// /// Fired when background should be changed due to receiving backgrounds from API @@ -97,7 +97,7 @@ namespace osu.Game.Graphics.Backgrounds } [LongRunningLoad] - public class SeasonalBackground : Background + public partial class SeasonalBackground : Background { private readonly string url; private const string fallback_texture_name = @"Backgrounds/bg1"; diff --git a/osu.Game/Graphics/Backgrounds/SkinBackground.cs b/osu.Game/Graphics/Backgrounds/SkinBackground.cs index e4bf3b94c5..e30bb961a0 100644 --- a/osu.Game/Graphics/Backgrounds/SkinBackground.cs +++ b/osu.Game/Graphics/Backgrounds/SkinBackground.cs @@ -8,7 +8,7 @@ using osu.Game.Skinning; namespace osu.Game.Graphics.Backgrounds { - internal class SkinBackground : Background + internal partial class SkinBackground : Background { private readonly Skin skin; diff --git a/osu.Game/Graphics/Backgrounds/Triangles.cs b/osu.Game/Graphics/Backgrounds/Triangles.cs index 09d137011c..94397f7ffb 100644 --- a/osu.Game/Graphics/Backgrounds/Triangles.cs +++ b/osu.Game/Graphics/Backgrounds/Triangles.cs @@ -21,7 +21,7 @@ using osu.Framework.Bindables; namespace osu.Game.Graphics.Backgrounds { - public class Triangles : Drawable + public partial class Triangles : Drawable { private const float triangle_size = 100; private const float base_velocity = 50; diff --git a/osu.Game/Graphics/Backgrounds/TrianglesV2.cs b/osu.Game/Graphics/Backgrounds/TrianglesV2.cs index 5fc32ff704..d543f082b4 100644 --- a/osu.Game/Graphics/Backgrounds/TrianglesV2.cs +++ b/osu.Game/Graphics/Backgrounds/TrianglesV2.cs @@ -11,40 +11,22 @@ using osu.Framework.Allocation; using System.Collections.Generic; using osu.Framework.Graphics.Rendering; using osu.Framework.Graphics.Rendering.Vertices; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp; -using osuTK.Graphics; +using osu.Framework.Graphics.Colour; using osu.Framework.Bindables; using osu.Framework.Graphics; namespace osu.Game.Graphics.Backgrounds { - public class TrianglesV2 : Drawable + public partial class TrianglesV2 : Drawable { private const float triangle_size = 100; private const float base_velocity = 50; - private const int texture_height = 128; /// /// sqrt(3) / 2 /// private const float equilateral_triangle_ratio = 0.866f; - private readonly Bindable colourTop = new Bindable(Color4.White); - private readonly Bindable colourBottom = new Bindable(Color4.Black); - - public Color4 ColourTop - { - get => colourTop.Value; - set => colourTop.Value = value; - } - - public Color4 ColourBottom - { - get => colourBottom.Value; - set => colourBottom.Value = value; - } - public float Thickness { get; set; } = 0.02f; // No need for invalidation since it's happening in Update() /// @@ -70,9 +52,6 @@ namespace osu.Game.Graphics.Backgrounds private readonly List parts = new List(); - [Resolved] - private IRenderer renderer { get; set; } = null!; - private Random? stableRandom; private IShader shader = null!; @@ -89,42 +68,19 @@ namespace osu.Game.Graphics.Backgrounds } [BackgroundDependencyLoader] - private void load(ShaderManager shaders) + private void load(ShaderManager shaders, IRenderer renderer) { shader = shaders.Load(VertexShaderDescriptor.TEXTURE_2, "TriangleBorder"); + texture = renderer.WhitePixel; } protected override void LoadComplete() { base.LoadComplete(); - colourTop.BindValueChanged(_ => updateTexture()); - colourBottom.BindValueChanged(_ => updateTexture(), true); - spawnRatio.BindValueChanged(_ => Reset(), true); } - private void updateTexture() - { - var image = new Image(texture_height, 1); - - texture = renderer.CreateTexture(1, texture_height, true); - - for (int i = 0; i < texture_height; i++) - { - float ratio = (float)i / texture_height; - - image[i, 0] = new Rgba32( - colourBottom.Value.R * ratio + colourTop.Value.R * (1f - ratio), - colourBottom.Value.G * ratio + colourTop.Value.G * (1f - ratio), - colourBottom.Value.B * ratio + colourTop.Value.B * (1f - ratio) - ); - } - - texture.SetData(new TextureUpload(image)); - Invalidate(Invalidation.DrawNode); - } - protected override void Update() { base.Update(); @@ -172,7 +128,7 @@ namespace osu.Game.Graphics.Backgrounds // Limited by the maximum size of QuadVertexBuffer for safety. const int max_triangles = ushort.MaxValue / (IRenderer.VERTICES_PER_QUAD + 2); - AimCount = (int)Math.Min(max_triangles, DrawWidth * DrawHeight * 0.0005f * SpawnRatio); + AimCount = (int)Math.Clamp(DrawWidth * 0.02f * SpawnRatio, 1, max_triangles); int currentCount = parts.Count; @@ -227,8 +183,12 @@ namespace osu.Game.Graphics.Backgrounds private Texture texture = null!; private readonly List parts = new List(); + + private readonly Vector2 triangleSize = new Vector2(1f, equilateral_triangle_ratio) * triangle_size; + private Vector2 size; private float thickness; + private float texelSize; private IVertexBatch? vertexBatch; @@ -246,6 +206,15 @@ namespace osu.Game.Graphics.Backgrounds size = Source.DrawSize; thickness = Source.Thickness; + Quad triangleQuad = new Quad( + Vector2Extensions.Transform(Vector2.Zero, DrawInfo.Matrix), + Vector2Extensions.Transform(new Vector2(triangle_size, 0f), DrawInfo.Matrix), + Vector2Extensions.Transform(new Vector2(0f, triangleSize.Y), DrawInfo.Matrix), + Vector2Extensions.Transform(triangleSize, DrawInfo.Matrix) + ); + + texelSize = 1.5f / triangleQuad.Height; + parts.Clear(); parts.AddRange(Source.parts); } @@ -254,7 +223,7 @@ namespace osu.Game.Graphics.Backgrounds { base.Draw(renderer); - if (Source.AimCount == 0) + if (Source.AimCount == 0 || thickness == 0) return; if (vertexBatch == null || vertexBatch.Size != Source.AimCount) @@ -265,36 +234,44 @@ namespace osu.Game.Graphics.Backgrounds shader.Bind(); shader.GetUniform("thickness").UpdateValue(ref thickness); + shader.GetUniform("texelSize").UpdateValue(ref texelSize); + + float relativeHeight = triangleSize.Y / size.Y; + float relativeWidth = triangleSize.X / size.X; foreach (TriangleParticle particle in parts) { - var offset = triangle_size * new Vector2(0.5f, equilateral_triangle_ratio); - - Vector2 topLeft = particle.Position * size + new Vector2(-offset.X, 0f); - Vector2 topRight = particle.Position * size + new Vector2(offset.X, 0); - Vector2 bottomLeft = particle.Position * size + new Vector2(-offset.X, offset.Y); - Vector2 bottomRight = particle.Position * size + new Vector2(offset.X, offset.Y); + Vector2 topLeft = particle.Position - new Vector2(relativeWidth * 0.5f, 0f); + Vector2 topRight = topLeft + new Vector2(relativeWidth, 0f); + Vector2 bottomLeft = topLeft + new Vector2(0f, relativeHeight); + Vector2 bottomRight = bottomLeft + new Vector2(relativeWidth, 0f); var drawQuad = new Quad( - Vector2Extensions.Transform(topLeft, DrawInfo.Matrix), - Vector2Extensions.Transform(topRight, DrawInfo.Matrix), - Vector2Extensions.Transform(bottomLeft, DrawInfo.Matrix), - Vector2Extensions.Transform(bottomRight, DrawInfo.Matrix) + Vector2Extensions.Transform(topLeft * size, DrawInfo.Matrix), + Vector2Extensions.Transform(topRight * size, DrawInfo.Matrix), + Vector2Extensions.Transform(bottomLeft * size, DrawInfo.Matrix), + Vector2Extensions.Transform(bottomRight * size, DrawInfo.Matrix) ); - var tRect = new Quad( - topLeft.X / size.X, - topLeft.Y / size.Y * texture_height, - (topRight.X - topLeft.X) / size.X, - (bottomRight.Y - topRight.Y) / size.Y * texture_height - ).AABBFloat; + ColourInfo colourInfo = triangleColourInfo(DrawColourInfo.Colour, new Quad(topLeft, topRight, bottomLeft, bottomRight)); - renderer.DrawQuad(texture, drawQuad, DrawColourInfo.Colour, tRect, vertexBatch.AddAction, textureCoords: tRect); + renderer.DrawQuad(texture, drawQuad, colourInfo, vertexAction: vertexBatch.AddAction); } shader.Unbind(); } + private static ColourInfo triangleColourInfo(ColourInfo source, Quad quad) + { + return new ColourInfo + { + TopLeft = source.Interpolate(quad.TopLeft), + TopRight = source.Interpolate(quad.TopRight), + BottomLeft = source.Interpolate(quad.BottomLeft), + BottomRight = source.Interpolate(quad.BottomRight) + }; + } + protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); diff --git a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs index 00fea601c6..724005a0cc 100644 --- a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs +++ b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs @@ -22,7 +22,7 @@ namespace osu.Game.Graphics.Containers /// /// This container will also trigger beat events when the beat matching clock is paused at 's BPM. /// - public class BeatSyncedContainer : Container + public partial class BeatSyncedContainer : Container { private int lastBeat; diff --git a/osu.Game/Graphics/Containers/ConstrainedIconContainer.cs b/osu.Game/Graphics/Containers/ConstrainedIconContainer.cs index f34a856707..55160e14af 100644 --- a/osu.Game/Graphics/Containers/ConstrainedIconContainer.cs +++ b/osu.Game/Graphics/Containers/ConstrainedIconContainer.cs @@ -14,7 +14,7 @@ namespace osu.Game.Graphics.Containers /// /// Display an icon that is forced to scale to the size of this container. /// - public class ConstrainedIconContainer : CompositeDrawable + public partial class ConstrainedIconContainer : CompositeDrawable { public Drawable Icon { diff --git a/osu.Game/Graphics/Containers/ExpandingButtonContainer.cs b/osu.Game/Graphics/Containers/ExpandingButtonContainer.cs index f66afb27c4..a06af61125 100644 --- a/osu.Game/Graphics/Containers/ExpandingButtonContainer.cs +++ b/osu.Game/Graphics/Containers/ExpandingButtonContainer.cs @@ -11,7 +11,7 @@ namespace osu.Game.Graphics.Containers /// /// Mostly used for buttons with explanatory labels, in which the label would display after a "long hover". /// - public class ExpandingButtonContainer : ExpandingContainer + public partial class ExpandingButtonContainer : ExpandingContainer { protected ExpandingButtonContainer(float contractedWidth, float expandedWidth) : base(contractedWidth, expandedWidth) diff --git a/osu.Game/Graphics/Containers/ExpandingContainer.cs b/osu.Game/Graphics/Containers/ExpandingContainer.cs index debc068220..60b9e6a167 100644 --- a/osu.Game/Graphics/Containers/ExpandingContainer.cs +++ b/osu.Game/Graphics/Containers/ExpandingContainer.cs @@ -14,7 +14,7 @@ namespace osu.Game.Graphics.Containers /// /// Represents a with the ability to expand/contract on hover. /// - public class ExpandingContainer : Container, IExpandingContainer + public partial class ExpandingContainer : Container, IExpandingContainer { private readonly float contractedWidth; private readonly float expandedWidth; diff --git a/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs b/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs index 7d38478b81..cbe327bac7 100644 --- a/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs +++ b/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs @@ -22,7 +22,7 @@ namespace osu.Game.Graphics.Containers /// The is exposed as a transforming bindable which smoothly tracks the progress of a hold operation. /// It can be used for animating and displaying progress directly. /// - public abstract class HoldToConfirmContainer : Container + public abstract partial class HoldToConfirmContainer : Container { public const double DANGEROUS_HOLD_ACTIVATION_DELAY = 500; diff --git a/osu.Game/Graphics/Containers/LinkFlowContainer.cs b/osu.Game/Graphics/Containers/LinkFlowContainer.cs index bf96695fd3..2d27ce906b 100644 --- a/osu.Game/Graphics/Containers/LinkFlowContainer.cs +++ b/osu.Game/Graphics/Containers/LinkFlowContainer.cs @@ -18,7 +18,7 @@ using osu.Game.Users; namespace osu.Game.Graphics.Containers { - public class LinkFlowContainer : OsuTextFlowContainer + public partial class LinkFlowContainer : OsuTextFlowContainer { public LinkFlowContainer(Action defaultCreationParameters = null) : base(defaultCreationParameters) diff --git a/osu.Game/Graphics/Containers/LogoTrackingContainer.cs b/osu.Game/Graphics/Containers/LogoTrackingContainer.cs index bf8d70a200..984d60d35e 100644 --- a/osu.Game/Graphics/Containers/LogoTrackingContainer.cs +++ b/osu.Game/Graphics/Containers/LogoTrackingContainer.cs @@ -15,7 +15,7 @@ namespace osu.Game.Graphics.Containers /// /// A container that handles tracking of an through different layout scenarios. /// - public class LogoTrackingContainer : Container + public partial class LogoTrackingContainer : Container { public Facade LogoFacade => facade; @@ -36,8 +36,7 @@ namespace osu.Game.Graphics.Containers /// The easing type of the initial transform. public void StartTracking(OsuLogo logo, double duration = 0, Easing easing = Easing.None) { - if (logo == null) - throw new ArgumentNullException(nameof(logo)); + ArgumentNullException.ThrowIfNull(logo); if (logo.IsTracking && Logo == null) throw new InvalidOperationException($"Cannot track an instance of {typeof(OsuLogo)} to multiple {typeof(LogoTrackingContainer)}s"); @@ -131,7 +130,7 @@ namespace osu.Game.Graphics.Containers base.Dispose(isDisposing); } - private class InternalFacade : Facade + private partial class InternalFacade : Facade { public new void SetSize(Vector2 size) { @@ -142,7 +141,7 @@ namespace osu.Game.Graphics.Containers /// /// A dummy object used to denote another object's location. /// - public abstract class Facade : Drawable + public abstract partial class Facade : Drawable { public override Vector2 Size { diff --git a/osu.Game/Graphics/Containers/Markdown/Extensions/BlockAttributeExtension.cs b/osu.Game/Graphics/Containers/Markdown/Extensions/BlockAttributeExtension.cs new file mode 100644 index 0000000000..caed4b26b9 --- /dev/null +++ b/osu.Game/Graphics/Containers/Markdown/Extensions/BlockAttributeExtension.cs @@ -0,0 +1,34 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using Markdig; +using Markdig.Extensions.GenericAttributes; +using Markdig.Renderers; +using Markdig.Syntax; + +namespace osu.Game.Graphics.Containers.Markdown.Extensions +{ + /// + /// A variant of + /// which only handles generic attributes in the current markdown and ignores inline generic attributes. + /// + /// + /// For rationale, see implementation of . + /// + public class BlockAttributeExtension : IMarkdownExtension + { + private readonly GenericAttributesExtension genericAttributesExtension = new GenericAttributesExtension(); + + public void Setup(MarkdownPipelineBuilder pipeline) + { + genericAttributesExtension.Setup(pipeline); + + // GenericAttributesExtension registers a GenericAttributesParser in pipeline.InlineParsers. + // this conflicts with the CustomContainerExtension, leading to some custom containers (e.g. flags) not displaying. + // as a workaround, remove the inline parser here before it can do damage. + pipeline.InlineParsers.RemoveAll(parser => parser is GenericAttributesParser); + } + + public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer) => genericAttributesExtension.Setup(pipeline, renderer); + } +} diff --git a/osu.Game/Graphics/Containers/Markdown/Extensions/OsuMarkdownExtensions.cs b/osu.Game/Graphics/Containers/Markdown/Extensions/OsuMarkdownExtensions.cs new file mode 100644 index 0000000000..10542abe71 --- /dev/null +++ b/osu.Game/Graphics/Containers/Markdown/Extensions/OsuMarkdownExtensions.cs @@ -0,0 +1,21 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using Markdig; + +namespace osu.Game.Graphics.Containers.Markdown.Extensions +{ + public static class OsuMarkdownExtensions + { + /// + /// Uses the block attributes extension. + /// + /// The pipeline. + /// The modified pipeline. + public static MarkdownPipelineBuilder UseBlockAttributes(this MarkdownPipelineBuilder pipeline) + { + pipeline.Extensions.AddIfNotAlready(); + return pipeline; + } + } +} diff --git a/osu.Game/Graphics/Containers/Markdown/Footnotes/OsuMarkdownFootnote.cs b/osu.Game/Graphics/Containers/Markdown/Footnotes/OsuMarkdownFootnote.cs new file mode 100644 index 0000000000..e92d866eed --- /dev/null +++ b/osu.Game/Graphics/Containers/Markdown/Footnotes/OsuMarkdownFootnote.cs @@ -0,0 +1,30 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using Markdig.Extensions.Footnotes; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers.Markdown; +using osu.Framework.Graphics.Containers.Markdown.Footnotes; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Localisation; + +namespace osu.Game.Graphics.Containers.Markdown.Footnotes +{ + public partial class OsuMarkdownFootnote : MarkdownFootnote + { + public OsuMarkdownFootnote(Footnote footnote) + : base(footnote) + { + } + + public override SpriteText CreateOrderMarker(int order) => CreateSpriteText().With(marker => + { + marker.Text = LocalisableString.Format("{0}.", order); + }); + + public override MarkdownTextFlowContainer CreateTextFlow() => base.CreateTextFlow().With(textFlow => + { + textFlow.Margin = new MarginPadding { Left = 30 }; + }); + } +} diff --git a/osu.Game/Graphics/Containers/Markdown/Footnotes/OsuMarkdownFootnoteBacklink.cs b/osu.Game/Graphics/Containers/Markdown/Footnotes/OsuMarkdownFootnoteBacklink.cs new file mode 100644 index 0000000000..22c02ea720 --- /dev/null +++ b/osu.Game/Graphics/Containers/Markdown/Footnotes/OsuMarkdownFootnoteBacklink.cs @@ -0,0 +1,62 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using System.Linq; +using Markdig.Extensions.Footnotes; +using osu.Framework.Allocation; +using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers.Markdown; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Testing; +using osu.Game.Overlays; +using osuTK; + +namespace osu.Game.Graphics.Containers.Markdown.Footnotes +{ + public partial class OsuMarkdownFootnoteBacklink : OsuHoverContainer + { + private readonly FootnoteLink backlink; + + private SpriteIcon spriteIcon = null!; + + [Resolved] + private IMarkdownTextComponent parentTextComponent { get; set; } = null!; + + protected override IEnumerable EffectTargets => spriteIcon.Yield(); + + public OsuMarkdownFootnoteBacklink(FootnoteLink backlink) + { + this.backlink = backlink; + } + + [BackgroundDependencyLoader(true)] + private void load(OverlayColourProvider colourProvider, OsuMarkdownContainer markdownContainer, OverlayScrollContainer? scrollContainer) + { + float fontSize = parentTextComponent.CreateSpriteText().Font.Size; + Size = new Vector2(fontSize); + + IdleColour = colourProvider.Light2; + HoverColour = colourProvider.Light1; + + Add(spriteIcon = new SpriteIcon + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Margin = new MarginPadding { Left = 5 }, + Size = new Vector2(fontSize / 2), + Icon = FontAwesome.Solid.ArrowUp, + }); + + if (scrollContainer != null) + { + Action = () => + { + var footnoteLink = markdownContainer.ChildrenOfType().Single(footnoteLink => footnoteLink.FootnoteLink.Index == backlink.Index); + scrollContainer.ScrollIntoView(footnoteLink); + }; + } + } + } +} diff --git a/osu.Game/Graphics/Containers/Markdown/Footnotes/OsuMarkdownFootnoteLink.cs b/osu.Game/Graphics/Containers/Markdown/Footnotes/OsuMarkdownFootnoteLink.cs new file mode 100644 index 0000000000..c9bd408e9e --- /dev/null +++ b/osu.Game/Graphics/Containers/Markdown/Footnotes/OsuMarkdownFootnoteLink.cs @@ -0,0 +1,80 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using System.Linq; +using Markdig.Extensions.Footnotes; +using osu.Framework.Allocation; +using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers.Markdown; +using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Localisation; +using osu.Framework.Testing; +using osu.Game.Overlays; + +namespace osu.Game.Graphics.Containers.Markdown.Footnotes +{ + public partial class OsuMarkdownFootnoteLink : OsuHoverContainer, IHasCustomTooltip + { + public readonly FootnoteLink FootnoteLink; + + private SpriteText spriteText = null!; + + [Resolved] + private IMarkdownTextComponent parentTextComponent { get; set; } = null!; + + [Resolved] + private OverlayColourProvider colourProvider { get; set; } = null!; + + [Resolved] + private OsuMarkdownContainer markdownContainer { get; set; } = null!; + + protected override IEnumerable EffectTargets => spriteText.Yield(); + + public OsuMarkdownFootnoteLink(FootnoteLink footnoteLink) + { + FootnoteLink = footnoteLink; + + AutoSizeAxes = Axes.Both; + } + + [BackgroundDependencyLoader(true)] + private void load(OsuMarkdownContainer markdownContainer, OverlayScrollContainer? scrollContainer) + { + IdleColour = colourProvider.Light2; + HoverColour = colourProvider.Light1; + + spriteText = parentTextComponent.CreateSpriteText(); + + Add(spriteText.With(t => + { + float baseSize = t.Font.Size; + t.Font = t.Font.With(size: baseSize * 0.58f); + t.Margin = new MarginPadding { Bottom = 0.33f * baseSize }; + t.Text = LocalisableString.Format("[{0}]", FootnoteLink.Index); + })); + + if (scrollContainer != null) + { + Action = () => + { + var footnote = markdownContainer.ChildrenOfType().Single(footnote => footnote.Footnote.Label == FootnoteLink.Footnote.Label); + scrollContainer.ScrollIntoView(footnote); + }; + } + } + + public object TooltipContent + { + get + { + var span = FootnoteLink.Footnote.LastChild.Span; + return markdownContainer.Text.Substring(span.Start, span.Length); + } + } + + public ITooltip GetCustomTooltip() => new OsuMarkdownFootnoteTooltip(colourProvider); + } +} diff --git a/osu.Game/Graphics/Containers/Markdown/Footnotes/OsuMarkdownFootnoteTooltip.cs b/osu.Game/Graphics/Containers/Markdown/Footnotes/OsuMarkdownFootnoteTooltip.cs new file mode 100644 index 0000000000..af64913212 --- /dev/null +++ b/osu.Game/Graphics/Containers/Markdown/Footnotes/OsuMarkdownFootnoteTooltip.cs @@ -0,0 +1,76 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using Markdig.Extensions.Footnotes; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Containers.Markdown; +using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.Shapes; +using osu.Game.Overlays; +using osuTK; + +namespace osu.Game.Graphics.Containers.Markdown.Footnotes +{ + public partial class OsuMarkdownFootnoteTooltip : CompositeDrawable, ITooltip + { + private readonly FootnoteMarkdownContainer markdownContainer; + + [Cached] + private OverlayColourProvider colourProvider; + + public OsuMarkdownFootnoteTooltip(OverlayColourProvider colourProvider) + { + this.colourProvider = colourProvider; + + Masking = true; + Width = 200; + AutoSizeAxes = Axes.Y; + CornerRadius = 4; + + InternalChildren = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colourProvider.Background6 + }, + markdownContainer = new FootnoteMarkdownContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + DocumentMargin = new MarginPadding(), + DocumentPadding = new MarginPadding { Horizontal = 10, Vertical = 5 } + } + }; + } + + public void Move(Vector2 pos) => Position = pos; + + public void SetContent(object content) => markdownContainer.SetContent((string)content); + + private partial class FootnoteMarkdownContainer : OsuMarkdownContainer + { + private string? lastFootnote; + + public void SetContent(string footnote) + { + if (footnote == lastFootnote) + return; + + lastFootnote = Text = footnote; + } + + public override MarkdownTextFlowContainer CreateTextFlow() => new FootnoteMarkdownTextFlowContainer(); + } + + private partial class FootnoteMarkdownTextFlowContainer : OsuMarkdownTextFlowContainer + { + protected override void AddFootnoteBacklink(FootnoteLink footnoteBacklink) + { + // we don't want footnote backlinks to show up in tooltips. + } + } + } +} diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs index 3855ed6d4e..5b1780a068 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs @@ -4,41 +4,25 @@ #nullable disable using Markdig; -using Markdig.Extensions.AutoLinks; -using Markdig.Extensions.CustomContainers; -using Markdig.Extensions.EmphasisExtras; using Markdig.Extensions.Footnotes; using Markdig.Extensions.Tables; using Markdig.Extensions.Yaml; using Markdig.Syntax; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers.Markdown; +using osu.Framework.Graphics.Containers.Markdown.Footnotes; using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics.Containers.Markdown.Footnotes; using osu.Game.Graphics.Sprites; +using osuTK; namespace osu.Game.Graphics.Containers.Markdown { - public class OsuMarkdownContainer : MarkdownContainer + [Cached] + public partial class OsuMarkdownContainer : MarkdownContainer { - /// - /// Allows this markdown container to parse and link footnotes. - /// - /// - protected virtual bool Footnotes => false; - - /// - /// Allows this markdown container to make URL text clickable. - /// - /// - protected virtual bool Autolinks => false; - - /// - /// Allows this markdown container to parse custom containers (used for flags and infoboxes). - /// - /// - protected virtual bool CustomContainers => false; - public OsuMarkdownContainer() { LineSpacing = 21; @@ -99,25 +83,17 @@ namespace osu.Game.Graphics.Containers.Markdown return new OsuMarkdownUnorderedListItem(level); } - // reference: https://github.com/ppy/osu-web/blob/05488a96b25b5a09f2d97c54c06dd2bae59d1dc8/app/Libraries/Markdown/OsuMarkdown.php#L301 - protected override MarkdownPipeline CreateBuilder() - { - var pipeline = new MarkdownPipelineBuilder() - .UseAutoIdentifiers() - .UsePipeTables() - .UseEmphasisExtras(EmphasisExtraOptions.Strikethrough) - .UseYamlFrontMatter(); + protected override MarkdownFootnoteGroup CreateFootnoteGroup(FootnoteGroup footnoteGroup) => base.CreateFootnoteGroup(footnoteGroup).With(g => g.Spacing = new Vector2(5)); - if (Footnotes) - pipeline = pipeline.UseFootnotes(); + protected override MarkdownFootnote CreateFootnote(Footnote footnote) => new OsuMarkdownFootnote(footnote); - if (Autolinks) - pipeline = pipeline.UseAutoLinks(); + protected sealed override MarkdownPipeline CreateBuilder() + => Options.BuildPipeline(); - if (CustomContainers) - pipeline.UseCustomContainers(); - - return pipeline.Build(); - } + /// + /// Creates a instance which is used to determine + /// which CommonMark/Markdig extensions should be enabled for this . + /// + protected virtual OsuMarkdownContainerOptions Options => new OsuMarkdownContainerOptions(); } } diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainerOptions.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainerOptions.cs new file mode 100644 index 0000000000..1648ffbf90 --- /dev/null +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainerOptions.cs @@ -0,0 +1,71 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using Markdig; +using Markdig.Extensions.AutoLinks; +using Markdig.Extensions.CustomContainers; +using Markdig.Extensions.EmphasisExtras; +using Markdig.Extensions.Footnotes; +using osu.Game.Graphics.Containers.Markdown.Extensions; + +namespace osu.Game.Graphics.Containers.Markdown +{ + /// + /// Groups options of customising the set of available extensions to instances. + /// + public class OsuMarkdownContainerOptions + { + /// + /// Allows the to parse and link footnotes. + /// + /// + public bool Footnotes { get; init; } + + /// + /// Allows the container to make URL text clickable. + /// + /// + public bool Autolinks { get; init; } + + /// + /// Allows the to parse custom containers (used for flags and infoboxes). + /// + /// + public bool CustomContainers { get; init; } + + /// + /// Allows the to parse custom attributes in block elements (used e.g. for custom anchor names in the wiki). + /// + /// + public bool BlockAttributes { get; init; } + + /// + /// Returns a prepared according to the options specified by the current instance. + /// + /// + /// Compare: https://github.com/ppy/osu-web/blob/05488a96b25b5a09f2d97c54c06dd2bae59d1dc8/app/Libraries/Markdown/OsuMarkdown.php#L301 + /// + public MarkdownPipeline BuildPipeline() + { + var pipeline = new MarkdownPipelineBuilder() + .UseAutoIdentifiers() + .UsePipeTables() + .UseEmphasisExtras(EmphasisExtraOptions.Strikethrough) + .UseYamlFrontMatter(); + + if (Footnotes) + pipeline = pipeline.UseFootnotes(); + + if (Autolinks) + pipeline = pipeline.UseAutoLinks(); + + if (CustomContainers) + pipeline = pipeline.UseCustomContainers(); + + if (BlockAttributes) + pipeline = pipeline.UseBlockAttributes(); + + return pipeline.Build(); + } + } +} diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownFencedCodeBlock.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownFencedCodeBlock.cs index fc7401046f..b5bbe3e2cc 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownFencedCodeBlock.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownFencedCodeBlock.cs @@ -12,7 +12,7 @@ using osu.Game.Overlays; namespace osu.Game.Graphics.Containers.Markdown { - public class OsuMarkdownFencedCodeBlock : MarkdownFencedCodeBlock + public partial class OsuMarkdownFencedCodeBlock : MarkdownFencedCodeBlock { // TODO : change to monospace font for this component public OsuMarkdownFencedCodeBlock(FencedCodeBlock fencedCodeBlock) @@ -24,7 +24,7 @@ namespace osu.Game.Graphics.Containers.Markdown public override MarkdownTextFlowContainer CreateTextFlow() => new CodeBlockTextFlowContainer(); - private class CodeBlockBackground : Box + private partial class CodeBlockBackground : Box { [BackgroundDependencyLoader] private void load(OverlayColourProvider colourProvider) @@ -34,7 +34,7 @@ namespace osu.Game.Graphics.Containers.Markdown } } - private class CodeBlockTextFlowContainer : OsuMarkdownTextFlowContainer + private partial class CodeBlockTextFlowContainer : OsuMarkdownTextFlowContainer { [BackgroundDependencyLoader] private void load(OverlayColourProvider colourProvider) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownHeading.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownHeading.cs index 0c70952222..800a0e1fc3 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownHeading.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownHeading.cs @@ -10,7 +10,7 @@ using osu.Framework.Graphics.Sprites; namespace osu.Game.Graphics.Containers.Markdown { - public class OsuMarkdownHeading : MarkdownHeading + public partial class OsuMarkdownHeading : MarkdownHeading { private readonly int level; @@ -66,7 +66,7 @@ namespace osu.Game.Graphics.Containers.Markdown } } - private class HeadingTextFlowContainer : OsuMarkdownTextFlowContainer + private partial class HeadingTextFlowContainer : OsuMarkdownTextFlowContainer { public float FontSize; public FontWeight FontWeight; diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownImage.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownImage.cs index 9ad501fdff..8ccac158eb 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownImage.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownImage.cs @@ -10,7 +10,7 @@ using osu.Framework.Localisation; namespace osu.Game.Graphics.Containers.Markdown { - public class OsuMarkdownImage : MarkdownImage, IHasTooltip + public partial class OsuMarkdownImage : MarkdownImage, IHasTooltip { public LocalisableString TooltipText { get; } diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownLinkText.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownLinkText.cs index 3a16eb0a0f..0049feca02 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownLinkText.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownLinkText.cs @@ -14,7 +14,7 @@ using osu.Game.Overlays; namespace osu.Game.Graphics.Containers.Markdown { - public class OsuMarkdownLinkText : MarkdownLinkText + public partial class OsuMarkdownLinkText : MarkdownLinkText { [Resolved(canBeNull: true)] private ILinkHandler linkHandler { get; set; } @@ -54,7 +54,7 @@ namespace osu.Game.Graphics.Containers.Markdown protected override void OnLinkPressed() => linkHandler?.HandleLink(Url); - private class OsuMarkdownLinkCompiler : DrawableLinkCompiler + private partial class OsuMarkdownLinkCompiler : DrawableLinkCompiler { public OsuMarkdownLinkCompiler(IEnumerable parts) : base(parts) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs index 153c4f9f93..2d38e44d32 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs @@ -12,7 +12,7 @@ using osuTK; namespace osu.Game.Graphics.Containers.Markdown { - public abstract class OsuMarkdownListItem : CompositeDrawable + public abstract partial class OsuMarkdownListItem : CompositeDrawable { [Resolved] private IMarkdownTextComponent parentTextComponent { get; set; } diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownOrderedListItem.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownOrderedListItem.cs index 116a8e2872..6eac9378ae 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownOrderedListItem.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownOrderedListItem.cs @@ -8,7 +8,7 @@ using osu.Framework.Graphics.Sprites; namespace osu.Game.Graphics.Containers.Markdown { - public class OsuMarkdownOrderedListItem : OsuMarkdownListItem + public partial class OsuMarkdownOrderedListItem : OsuMarkdownListItem { private const float left_padding = 30; diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownQuoteBlock.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownQuoteBlock.cs index 3ef67df7a9..447085a48c 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownQuoteBlock.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownQuoteBlock.cs @@ -12,7 +12,7 @@ using osu.Game.Overlays; namespace osu.Game.Graphics.Containers.Markdown { - public class OsuMarkdownQuoteBlock : MarkdownQuoteBlock + public partial class OsuMarkdownQuoteBlock : MarkdownQuoteBlock { public OsuMarkdownQuoteBlock(QuoteBlock quoteBlock) : base(quoteBlock) @@ -30,7 +30,7 @@ namespace osu.Game.Graphics.Containers.Markdown }); } - private class QuoteBackground : Box + private partial class QuoteBackground : Box { [BackgroundDependencyLoader] private void load(OverlayColourProvider colourProvider) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownSeparator.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownSeparator.cs index abbc10a7e2..343a1d1015 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownSeparator.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownSeparator.cs @@ -11,11 +11,11 @@ using osu.Game.Overlays; namespace osu.Game.Graphics.Containers.Markdown { - public class OsuMarkdownSeparator : MarkdownSeparator + public partial class OsuMarkdownSeparator : MarkdownSeparator { protected override Drawable CreateSeparator() => new Separator(); - private class Separator : Box + private partial class Separator : Box { [BackgroundDependencyLoader] private void load(OverlayColourProvider colourProvider) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTable.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTable.cs index ee851045f9..c9c1098e05 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTable.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTable.cs @@ -8,7 +8,7 @@ using osu.Framework.Graphics.Containers.Markdown; namespace osu.Game.Graphics.Containers.Markdown { - public class OsuMarkdownTable : MarkdownTable + public partial class OsuMarkdownTable : MarkdownTable { public OsuMarkdownTable(Table table) : base(table) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTableCell.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTableCell.cs index 3863beb133..dbf15a2546 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTableCell.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTableCell.cs @@ -13,7 +13,7 @@ using osu.Game.Overlays; namespace osu.Game.Graphics.Containers.Markdown { - public class OsuMarkdownTableCell : MarkdownTableCell + public partial class OsuMarkdownTableCell : MarkdownTableCell { private readonly bool isHeading; @@ -45,7 +45,7 @@ namespace osu.Game.Graphics.Containers.Markdown return new TableBodyBorder(); } - private class TableHeadBorder : Box + private partial class TableHeadBorder : Box { [BackgroundDependencyLoader] private void load(OverlayColourProvider colourProvider) @@ -58,7 +58,7 @@ namespace osu.Game.Graphics.Containers.Markdown } } - private class TableBodyBorder : Box + private partial class TableBodyBorder : Box { [BackgroundDependencyLoader] private void load(OverlayColourProvider colourProvider) @@ -69,7 +69,7 @@ namespace osu.Game.Graphics.Containers.Markdown } } - private class TableCellTextFlowContainer : OsuMarkdownTextFlowContainer + private partial class TableCellTextFlowContainer : OsuMarkdownTextFlowContainer { public FontWeight Weight { get; set; } diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTextFlowContainer.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTextFlowContainer.cs index 9d7b47281f..5f5b9acf56 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTextFlowContainer.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTextFlowContainer.cs @@ -6,6 +6,7 @@ using System; using System.Linq; using Markdig.Extensions.CustomContainers; +using Markdig.Extensions.Footnotes; using Markdig.Syntax.Inlines; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -13,6 +14,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers.Markdown; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics.Containers.Markdown.Footnotes; using osu.Game.Overlays; using osu.Game.Users; using osu.Game.Users.Drawables; @@ -20,7 +22,7 @@ using osuTK; namespace osu.Game.Graphics.Containers.Markdown { - public class OsuMarkdownTextFlowContainer : MarkdownTextFlowContainer + public partial class OsuMarkdownTextFlowContainer : MarkdownTextFlowContainer { protected override void AddLinkText(string text, LinkInline linkInline) => AddDrawable(new OsuMarkdownLinkText(text, linkInline)); @@ -36,6 +38,10 @@ namespace osu.Game.Graphics.Containers.Markdown Text = codeInline.Content }); + protected override void AddFootnoteLink(FootnoteLink footnoteLink) => AddDrawable(new OsuMarkdownFootnoteLink(footnoteLink)); + + protected override void AddFootnoteBacklink(FootnoteLink footnoteBacklink) => AddDrawable(new OsuMarkdownFootnoteBacklink(footnoteBacklink)); + protected override SpriteText CreateEmphasisedSpriteText(bool bold, bool italic) => CreateSpriteText().With(t => t.Font = t.Font.With(weight: bold ? FontWeight.Bold : FontWeight.Regular, italics: italic)); @@ -64,7 +70,7 @@ namespace osu.Game.Graphics.Containers.Markdown AddDrawable(new DrawableFlag(countryCode) { Size = new Vector2(20, 15) }); } - private class OsuMarkdownInlineCode : Container + private partial class OsuMarkdownInlineCode : Container { [Resolved] private IMarkdownTextComponent parentTextComponent { get; set; } diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownUnorderedListItem.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownUnorderedListItem.cs index f8e8571557..64e98511c2 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownUnorderedListItem.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownUnorderedListItem.cs @@ -8,7 +8,7 @@ using osu.Framework.Graphics.Sprites; namespace osu.Game.Graphics.Containers.Markdown { - public class OsuMarkdownUnorderedListItem : OsuMarkdownListItem + public partial class OsuMarkdownUnorderedListItem : OsuMarkdownListItem { private const float left_padding = 20; diff --git a/osu.Game/Graphics/Containers/OsuClickableContainer.cs b/osu.Game/Graphics/Containers/OsuClickableContainer.cs index 03a1cfcc13..ce50dbdc39 100644 --- a/osu.Game/Graphics/Containers/OsuClickableContainer.cs +++ b/osu.Game/Graphics/Containers/OsuClickableContainer.cs @@ -1,23 +1,29 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - +using System; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Localisation; using osu.Game.Graphics.UserInterface; +using osuTK; namespace osu.Game.Graphics.Containers { - public class OsuClickableContainer : ClickableContainer, IHasTooltip + public partial class OsuClickableContainer : ClickableContainer, IHasTooltip { private readonly HoverSampleSet sampleSet; private readonly Container content = new Container { RelativeSizeAxes = Axes.Both }; + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => + // base call is checked for cases when `OsuClickableContainer` has masking applied to it directly (ie. externally in object initialisation). + base.ReceivePositionalInputAt(screenSpacePos) + // Implementations often apply masking / edge rounding at a content level, so it's imperative to check that as well. + && Content.ReceivePositionalInputAt(screenSpacePos); + protected override Container Content => content; protected virtual HoverSounds CreateHoverSounds(HoverSampleSet sampleSet) => new HoverClickSounds(sampleSet) { Enabled = { BindTarget = Enabled } }; @@ -38,11 +44,11 @@ namespace osu.Game.Graphics.Containers content.AutoSizeAxes = AutoSizeAxes; } - InternalChildren = new Drawable[] - { - content, - CreateHoverSounds(sampleSet) - }; + AddInternal(content); + Add(CreateHoverSounds(sampleSet)); } + + protected override void ClearInternal(bool disposeChildren = true) => + throw new InvalidOperationException($"Clearing {nameof(InternalChildren)} will cause critical failure. Use {nameof(Clear)} instead."); } } diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index e8a0c0cd25..07b5b53e0e 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -18,15 +18,13 @@ using osu.Game.Overlays; namespace osu.Game.Graphics.Containers { [Cached(typeof(IPreviewTrackOwner))] - public abstract class OsuFocusedOverlayContainer : FocusedOverlayContainer, IPreviewTrackOwner, IKeyBindingHandler + public abstract partial class OsuFocusedOverlayContainer : FocusedOverlayContainer, IPreviewTrackOwner, IKeyBindingHandler { private Sample samplePopIn; private Sample samplePopOut; protected virtual string PopInSampleName => "UI/overlay-pop-in"; protected virtual string PopOutSampleName => "UI/overlay-pop-out"; - protected override bool BlockScrollInput => false; - protected override bool BlockNonPositionalInput => true; /// @@ -90,6 +88,15 @@ namespace osu.Game.Graphics.Containers base.OnMouseUp(e); } + protected override bool OnScroll(ScrollEvent e) + { + // allow for controlling volume when alt is held. + // mostly for compatibility with osu-stable. + if (e.AltPressed) return false; + + return true; + } + public virtual bool OnPressed(KeyBindingPressEvent e) { if (e.Repeat) diff --git a/osu.Game/Graphics/Containers/OsuHoverContainer.cs b/osu.Game/Graphics/Containers/OsuHoverContainer.cs index 93205e0d03..b4b80f7574 100644 --- a/osu.Game/Graphics/Containers/OsuHoverContainer.cs +++ b/osu.Game/Graphics/Containers/OsuHoverContainer.cs @@ -13,7 +13,7 @@ using osu.Game.Graphics.UserInterface; namespace osu.Game.Graphics.Containers { - public class OsuHoverContainer : OsuClickableContainer + public partial class OsuHoverContainer : OsuClickableContainer { protected const float FADE_DURATION = 500; diff --git a/osu.Game/Graphics/Containers/OsuRearrangeableListContainer.cs b/osu.Game/Graphics/Containers/OsuRearrangeableListContainer.cs index b604ae73eb..fcc48d80ea 100644 --- a/osu.Game/Graphics/Containers/OsuRearrangeableListContainer.cs +++ b/osu.Game/Graphics/Containers/OsuRearrangeableListContainer.cs @@ -14,7 +14,7 @@ using osu.Framework.Utils; namespace osu.Game.Graphics.Containers { - public abstract class OsuRearrangeableListContainer : RearrangeableListContainer + public abstract partial class OsuRearrangeableListContainer : RearrangeableListContainer { /// /// Whether any item is currently being dragged. Used to hide other items' drag handles. diff --git a/osu.Game/Graphics/Containers/OsuRearrangeableListItem.cs b/osu.Game/Graphics/Containers/OsuRearrangeableListItem.cs index e6183ea837..39a3edb82c 100644 --- a/osu.Game/Graphics/Containers/OsuRearrangeableListItem.cs +++ b/osu.Game/Graphics/Containers/OsuRearrangeableListItem.cs @@ -15,7 +15,7 @@ using osuTK.Graphics; namespace osu.Game.Graphics.Containers { - public abstract class OsuRearrangeableListItem : RearrangeableListItem + public abstract partial class OsuRearrangeableListItem : RearrangeableListItem { public const float FADE_DURATION = 100; @@ -129,7 +129,7 @@ namespace osu.Game.Graphics.Containers protected abstract Drawable CreateContent(); - public class PlaylistItemHandle : SpriteIcon + public partial class PlaylistItemHandle : SpriteIcon { public bool HandlingDrag { get; private set; } private bool isHovering; diff --git a/osu.Game/Graphics/Containers/OsuScrollContainer.cs b/osu.Game/Graphics/Containers/OsuScrollContainer.cs index 7e5d5e53d3..e39fd45a16 100644 --- a/osu.Game/Graphics/Containers/OsuScrollContainer.cs +++ b/osu.Game/Graphics/Containers/OsuScrollContainer.cs @@ -14,7 +14,7 @@ using osuTK.Input; namespace osu.Game.Graphics.Containers { - public class OsuScrollContainer : OsuScrollContainer + public partial class OsuScrollContainer : OsuScrollContainer { public OsuScrollContainer() { @@ -26,7 +26,7 @@ namespace osu.Game.Graphics.Containers } } - public class OsuScrollContainer : ScrollContainer where T : Drawable + public partial class OsuScrollContainer : ScrollContainer where T : Drawable { public const float SCROLL_BAR_HEIGHT = 10; public const float SCROLL_BAR_PADDING = 3; @@ -131,7 +131,7 @@ namespace osu.Game.Graphics.Containers protected override ScrollbarContainer CreateScrollbar(Direction direction) => new OsuScrollbar(direction); - protected class OsuScrollbar : ScrollbarContainer + protected partial class OsuScrollbar : ScrollbarContainer { private Color4 hoverColour; private Color4 defaultColour; diff --git a/osu.Game/Graphics/Containers/OsuTextFlowContainer.cs b/osu.Game/Graphics/Containers/OsuTextFlowContainer.cs index 5cdccee01d..d3bbc2e80b 100644 --- a/osu.Game/Graphics/Containers/OsuTextFlowContainer.cs +++ b/osu.Game/Graphics/Containers/OsuTextFlowContainer.cs @@ -12,7 +12,7 @@ using osu.Game.Graphics.Sprites; namespace osu.Game.Graphics.Containers { - public class OsuTextFlowContainer : TextFlowContainer + public partial class OsuTextFlowContainer : TextFlowContainer { public OsuTextFlowContainer(Action defaultCreationParameters = null) : base(defaultCreationParameters) diff --git a/osu.Game/Graphics/Containers/ParallaxContainer.cs b/osu.Game/Graphics/Containers/ParallaxContainer.cs index f70abc16dd..3893413f61 100644 --- a/osu.Game/Graphics/Containers/ParallaxContainer.cs +++ b/osu.Game/Graphics/Containers/ParallaxContainer.cs @@ -15,7 +15,7 @@ using osu.Framework.Utils; namespace osu.Game.Graphics.Containers { - public class ParallaxContainer : Container, IRequireHighFrequencyMousePosition + public partial class ParallaxContainer : Container, IRequireHighFrequencyMousePosition { public const float DEFAULT_PARALLAX_AMOUNT = 0.02f; diff --git a/osu.Game/Graphics/Containers/ReverseChildIDFillFlowContainer.cs b/osu.Game/Graphics/Containers/ReverseChildIDFillFlowContainer.cs index db265d6d64..e37d23fe97 100644 --- a/osu.Game/Graphics/Containers/ReverseChildIDFillFlowContainer.cs +++ b/osu.Game/Graphics/Containers/ReverseChildIDFillFlowContainer.cs @@ -8,7 +8,7 @@ using osu.Framework.Graphics.Containers; namespace osu.Game.Graphics.Containers { - public class ReverseChildIDFillFlowContainer : FillFlowContainer where T : Drawable + public partial class ReverseChildIDFillFlowContainer : FillFlowContainer where T : Drawable { protected override int Compare(Drawable x, Drawable y) => CompareReverseChildID(x, y); } diff --git a/osu.Game/Graphics/Containers/ScalingContainer.cs b/osu.Game/Graphics/Containers/ScalingContainer.cs index 11e57d4be3..fb5c3e3b60 100644 --- a/osu.Game/Graphics/Containers/ScalingContainer.cs +++ b/osu.Game/Graphics/Containers/ScalingContainer.cs @@ -21,7 +21,7 @@ namespace osu.Game.Graphics.Containers /// /// Handles user-defined scaling, allowing application at multiple levels defined by . /// - public class ScalingContainer : Container + public partial class ScalingContainer : Container { internal const float TRANSITION_DURATION = 500; @@ -82,7 +82,7 @@ namespace osu.Game.Graphics.Containers }; } - public class ScalingDrawSizePreservingFillContainer : DrawSizePreservingFillContainer + public partial class ScalingDrawSizePreservingFillContainer : DrawSizePreservingFillContainer { private readonly bool applyUIScale; private Bindable uiScale; @@ -211,7 +211,7 @@ namespace osu.Game.Graphics.Containers .OnComplete(_ => { sizableContainer.Masking = requiresMasking; }); } - private class ScalingBackgroundScreen : BackgroundScreenDefault + private partial class ScalingBackgroundScreen : BackgroundScreenDefault { protected override bool AllowStoryboardBackground => false; @@ -221,7 +221,7 @@ namespace osu.Game.Graphics.Containers } } - private class SizeableAlwaysInputContainer : Container + private partial class SizeableAlwaysInputContainer : Container { [Resolved] private GameHost host { get; set; } diff --git a/osu.Game/Graphics/Containers/SectionsContainer.cs b/osu.Game/Graphics/Containers/SectionsContainer.cs index 97e9ff88b5..8dd6eac7bb 100644 --- a/osu.Game/Graphics/Containers/SectionsContainer.cs +++ b/osu.Game/Graphics/Containers/SectionsContainer.cs @@ -20,7 +20,7 @@ namespace osu.Game.Graphics.Containers /// A container that can scroll to each section inside it. /// [Cached] - public class SectionsContainer : Container + public partial class SectionsContainer : Container where T : Drawable { public Bindable SelectedSection { get; } = new Bindable(); @@ -240,7 +240,9 @@ namespace osu.Game.Graphics.Containers headerBackgroundContainer.Height = expandableHeaderSize + fixedHeaderSize; headerBackgroundContainer.Y = ExpandableHeader?.Y ?? 0; - float smallestSectionHeight = Children.Count > 0 ? Children.Min(d => d.Height) : 0; + var flowChildren = scrollContentContainer.FlowingChildren.OfType(); + + float smallestSectionHeight = flowChildren.Any() ? flowChildren.Min(d => d.Height) : 0; // scroll offset is our fixed header height if we have it plus 10% of content height // plus 5% to fix floating point errors and to not have a section instantly unselect when scrolling upwards @@ -249,7 +251,7 @@ namespace osu.Game.Graphics.Containers float scrollCentre = fixedHeaderSize + scrollContainer.DisplayableContent * scroll_y_centre + selectionLenienceAboveSection; - var presentChildren = Children.Where(c => c.IsPresent); + var presentChildren = flowChildren.Where(c => c.IsPresent); if (lastClickedSection != null) SelectedSection.Value = lastClickedSection; diff --git a/osu.Game/Graphics/Containers/SelectionCycleFillFlowContainer.cs b/osu.Game/Graphics/Containers/SelectionCycleFillFlowContainer.cs index 2667b8b8e0..62544c6111 100644 --- a/osu.Game/Graphics/Containers/SelectionCycleFillFlowContainer.cs +++ b/osu.Game/Graphics/Containers/SelectionCycleFillFlowContainer.cs @@ -16,7 +16,7 @@ namespace osu.Game.Graphics.Containers /// A FillFlowContainer that provides functionality to cycle selection between children /// The selection wraps around when overflowing past the first or last child. /// - public class SelectionCycleFillFlowContainer : FillFlowContainer where T : Drawable, IStateful + public partial class SelectionCycleFillFlowContainer : FillFlowContainer where T : Drawable, IStateful { public T Selected => (selectedIndex >= 0 && selectedIndex < Count) ? this[selectedIndex.Value] : null; diff --git a/osu.Game/Graphics/Containers/ShakeContainer.cs b/osu.Game/Graphics/Containers/ShakeContainer.cs index 7b6fc22cc0..9a1ddac40d 100644 --- a/osu.Game/Graphics/Containers/ShakeContainer.cs +++ b/osu.Game/Graphics/Containers/ShakeContainer.cs @@ -11,7 +11,7 @@ namespace osu.Game.Graphics.Containers /// /// A container that adds the ability to shake its contents. /// - public class ShakeContainer : Container + public partial class ShakeContainer : Container { /// /// The length of a single shake. diff --git a/osu.Game/Graphics/Containers/UprightAspectMaintainingContainer.cs b/osu.Game/Graphics/Containers/UprightAspectMaintainingContainer.cs index 300b5bd4b4..38ab6deb97 100644 --- a/osu.Game/Graphics/Containers/UprightAspectMaintainingContainer.cs +++ b/osu.Game/Graphics/Containers/UprightAspectMaintainingContainer.cs @@ -12,7 +12,7 @@ namespace osu.Game.Graphics.Containers /// /// A container that reverts any rotation (and optionally scale) applied by its direct parent. /// - public class UprightAspectMaintainingContainer : Container + public partial class UprightAspectMaintainingContainer : Container { /// /// Controls how much this container scales compared to its parent (default is 1.0f). diff --git a/osu.Game/Graphics/Containers/UserDimContainer.cs b/osu.Game/Graphics/Containers/UserDimContainer.cs index 0b20159190..25830c9d54 100644 --- a/osu.Game/Graphics/Containers/UserDimContainer.cs +++ b/osu.Game/Graphics/Containers/UserDimContainer.cs @@ -14,7 +14,7 @@ namespace osu.Game.Graphics.Containers /// /// A container that applies user-configured visual settings to its contents. /// - public abstract class UserDimContainer : Container + public abstract partial class UserDimContainer : Container { /// /// Amount of lightening to apply to current dim level during break times. diff --git a/osu.Game/Graphics/Containers/UserTrackingScrollContainer.cs b/osu.Game/Graphics/Containers/UserTrackingScrollContainer.cs index 2bb9d7261d..715677aec1 100644 --- a/osu.Game/Graphics/Containers/UserTrackingScrollContainer.cs +++ b/osu.Game/Graphics/Containers/UserTrackingScrollContainer.cs @@ -7,7 +7,7 @@ using osu.Framework.Graphics; namespace osu.Game.Graphics.Containers { - public class UserTrackingScrollContainer : UserTrackingScrollContainer + public partial class UserTrackingScrollContainer : UserTrackingScrollContainer { public UserTrackingScrollContainer() { @@ -19,7 +19,7 @@ namespace osu.Game.Graphics.Containers } } - public class UserTrackingScrollContainer : OsuScrollContainer + public partial class UserTrackingScrollContainer : OsuScrollContainer where T : Drawable { /// diff --git a/osu.Game/Graphics/Containers/WaveContainer.cs b/osu.Game/Graphics/Containers/WaveContainer.cs index ba85ef0aab..952ef3f182 100644 --- a/osu.Game/Graphics/Containers/WaveContainer.cs +++ b/osu.Game/Graphics/Containers/WaveContainer.cs @@ -13,7 +13,7 @@ using osuTK.Graphics; namespace osu.Game.Graphics.Containers { - public class WaveContainer : VisibilityContainer + public partial class WaveContainer : VisibilityContainer { public const float APPEAR_DURATION = 800; public const float DISAPPEAR_DURATION = 500; @@ -131,7 +131,7 @@ namespace osu.Game.Graphics.Containers wavesContainer.Height = Math.Max(0, DrawHeight - (contentContainer.DrawHeight - contentContainer.Y * DrawHeight)); } - private class Wave : VisibilityContainer + private partial class Wave : VisibilityContainer { public float FinalPosition; diff --git a/osu.Game/Graphics/Cursor/GlobalCursorDisplay.cs b/osu.Game/Graphics/Cursor/GlobalCursorDisplay.cs index f5429723be..85a2d68e55 100644 --- a/osu.Game/Graphics/Cursor/GlobalCursorDisplay.cs +++ b/osu.Game/Graphics/Cursor/GlobalCursorDisplay.cs @@ -16,7 +16,7 @@ namespace osu.Game.Graphics.Cursor /// A container which provides the main . /// Also handles cases where a more localised cursor is provided by another component (via ). /// - public class GlobalCursorDisplay : Container, IProvideCursor + public partial class GlobalCursorDisplay : Container, IProvideCursor { /// /// Control whether any cursor should be displayed. diff --git a/osu.Game/Graphics/Cursor/MenuCursorContainer.cs b/osu.Game/Graphics/Cursor/MenuCursorContainer.cs index adc0f81daf..8cf47006ab 100644 --- a/osu.Game/Graphics/Cursor/MenuCursorContainer.cs +++ b/osu.Game/Graphics/Cursor/MenuCursorContainer.cs @@ -18,7 +18,7 @@ using osuTK; namespace osu.Game.Graphics.Cursor { - public class MenuCursorContainer : CursorContainer + public partial class MenuCursorContainer : CursorContainer { private readonly IBindable screenshotCursorVisibility = new Bindable(true); public override bool IsPresent => screenshotCursorVisibility.Value && base.IsPresent; @@ -234,14 +234,14 @@ namespace osu.Game.Graphics.Cursor SampleChannel channel = tapSample.GetChannel(); // Scale to [-0.75, 0.75] so that the sample isn't fully panned left or right (sounds weird) - channel.Balance.Value = ((activeCursor.X / DrawWidth) * 2 - 1) * 0.75; + channel.Balance.Value = ((activeCursor.X / DrawWidth) * 2 - 1) * OsuGameBase.SFX_STEREO_STRENGTH; channel.Frequency.Value = baseFrequency - (random_range / 2f) + RNG.NextDouble(random_range); channel.Volume.Value = baseFrequency; channel.Play(); } - public class Cursor : Container + public partial class Cursor : Container { private Container cursorContainer = null!; private Bindable cursorScale = null!; @@ -284,7 +284,7 @@ namespace osu.Game.Graphics.Cursor } } - private class MouseInputDetector : Component + private partial class MouseInputDetector : Component { /// /// Whether the last input applied to the game is sourced from mouse. diff --git a/osu.Game/Graphics/Cursor/OsuContextMenuContainer.cs b/osu.Game/Graphics/Cursor/OsuContextMenuContainer.cs index fbaefe24b0..27700e71d9 100644 --- a/osu.Game/Graphics/Cursor/OsuContextMenuContainer.cs +++ b/osu.Game/Graphics/Cursor/OsuContextMenuContainer.cs @@ -10,7 +10,7 @@ using osu.Game.Graphics.UserInterface; namespace osu.Game.Graphics.Cursor { - public class OsuContextMenuContainer : ContextMenuContainer + public partial class OsuContextMenuContainer : ContextMenuContainer { [Cached] private OsuContextMenuSamples samples = new OsuContextMenuSamples(); diff --git a/osu.Game/Graphics/Cursor/OsuTooltipContainer.cs b/osu.Game/Graphics/Cursor/OsuTooltipContainer.cs index 8bf4dfcd24..dc75d626b9 100644 --- a/osu.Game/Graphics/Cursor/OsuTooltipContainer.cs +++ b/osu.Game/Graphics/Cursor/OsuTooltipContainer.cs @@ -16,7 +16,7 @@ using osu.Game.Graphics.Sprites; namespace osu.Game.Graphics.Cursor { - public class OsuTooltipContainer : TooltipContainer + public partial class OsuTooltipContainer : TooltipContainer { protected override ITooltip CreateTooltip() => new OsuTooltip(); @@ -27,7 +27,7 @@ namespace osu.Game.Graphics.Cursor protected override double AppearDelay => (1 - CurrentTooltip.Alpha) * base.AppearDelay; // reduce appear delay if the tooltip is already partly visible. - public class OsuTooltip : Tooltip + public partial class OsuTooltip : Tooltip { private readonly Box background; private readonly OsuSpriteText text; diff --git a/osu.Game/Graphics/DateTooltip.cs b/osu.Game/Graphics/DateTooltip.cs index 77bf78b213..c62f53f1d4 100644 --- a/osu.Game/Graphics/DateTooltip.cs +++ b/osu.Game/Graphics/DateTooltip.cs @@ -9,12 +9,13 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; +using osu.Framework.Localisation; using osu.Game.Graphics.Sprites; using osuTK; namespace osu.Game.Graphics { - public class DateTooltip : VisibilityContainer, ITooltip + public partial class DateTooltip : VisibilityContainer, ITooltip { private readonly OsuSpriteText dateText, timeText; private readonly Box background; @@ -69,8 +70,8 @@ namespace osu.Game.Graphics { DateTimeOffset localDate = date.ToLocalTime(); - dateText.Text = $"{localDate:d MMMM yyyy} "; - timeText.Text = $"{localDate:HH:mm:ss \"UTC\"z}"; + dateText.Text = LocalisableString.Interpolate($"{localDate:d MMMM yyyy} "); + timeText.Text = LocalisableString.Interpolate($"{localDate:HH:mm:ss \"UTC\"z}"); } public void Move(Vector2 pos) => Position = pos; diff --git a/osu.Game/Graphics/DrawableDate.cs b/osu.Game/Graphics/DrawableDate.cs index 0008d0fcaa..553b27acb1 100644 --- a/osu.Game/Graphics/DrawableDate.cs +++ b/osu.Game/Graphics/DrawableDate.cs @@ -12,7 +12,7 @@ using osu.Game.Utils; namespace osu.Game.Graphics { - public class DrawableDate : OsuSpriteText, IHasCustomTooltip + public partial class DrawableDate : OsuSpriteText, IHasCustomTooltip { private DateTimeOffset date; diff --git a/osu.Game/Graphics/ErrorTextFlowContainer.cs b/osu.Game/Graphics/ErrorTextFlowContainer.cs index 0d47245e8c..65a90534e5 100644 --- a/osu.Game/Graphics/ErrorTextFlowContainer.cs +++ b/osu.Game/Graphics/ErrorTextFlowContainer.cs @@ -10,7 +10,7 @@ using osuTK.Graphics; namespace osu.Game.Graphics { - public class ErrorTextFlowContainer : OsuTextFlowContainer + public partial class ErrorTextFlowContainer : OsuTextFlowContainer { private readonly List errorTextParts = new List(); diff --git a/osu.Game/Graphics/InputBlockingContainer.cs b/osu.Game/Graphics/InputBlockingContainer.cs index 66caa57c1a..f652dc8850 100644 --- a/osu.Game/Graphics/InputBlockingContainer.cs +++ b/osu.Game/Graphics/InputBlockingContainer.cs @@ -9,7 +9,7 @@ namespace osu.Game.Graphics /// /// A simple container which blocks input events from travelling through it. /// - public class InputBlockingContainer : Container + public partial class InputBlockingContainer : Container { protected override bool OnHover(HoverEvent e) => true; diff --git a/osu.Game/Graphics/OsuColour.cs b/osu.Game/Graphics/OsuColour.cs index 91161d5c71..c5659aaf57 100644 --- a/osu.Game/Graphics/OsuColour.cs +++ b/osu.Game/Graphics/OsuColour.cs @@ -22,38 +22,8 @@ namespace osu.Game.Graphics public static Color4 Gray(byte amt) => new Color4(amt, amt, amt, 255); /// - /// Retrieves the colour for a . + /// Retrieves the colour for a given point in the star range. /// - /// - /// Sourced from the @diff-{rating} variables in https://github.com/ppy/osu-web/blob/71fbab8936d79a7929d13854f5e854b4f383b236/resources/assets/less/variables.less. - /// - public Color4 ForDifficultyRating(DifficultyRating difficulty, bool useLighterColour = false) - { - switch (difficulty) - { - case DifficultyRating.Easy: - return Color4Extensions.FromHex("4ebfff"); - - case DifficultyRating.Normal: - return Color4Extensions.FromHex("66ff91"); - - case DifficultyRating.Hard: - return Color4Extensions.FromHex("f7e85d"); - - case DifficultyRating.Insane: - return Color4Extensions.FromHex("ff7e68"); - - case DifficultyRating.Expert: - return Color4Extensions.FromHex("fe3c71"); - - case DifficultyRating.ExpertPlus: - return Color4Extensions.FromHex("6662dd"); - - default: - throw new ArgumentOutOfRangeException(nameof(difficulty)); - } - } - public Color4 ForStarDifficulty(double starDifficulty) => ColourUtils.SampleFromLinearGradient(new[] { (0.1f, Color4Extensions.FromHex("aaaaaa")), diff --git a/osu.Game/Graphics/ParticleExplosion.cs b/osu.Game/Graphics/ParticleExplosion.cs index a902c8426f..56e1568441 100644 --- a/osu.Game/Graphics/ParticleExplosion.cs +++ b/osu.Game/Graphics/ParticleExplosion.cs @@ -18,7 +18,7 @@ namespace osu.Game.Graphics /// /// An explosion of textured particles based on how osu-stable randomises the explosion pattern. /// - public class ParticleExplosion : Sprite + public partial class ParticleExplosion : Sprite { private readonly int particleCount; private readonly double duration; diff --git a/osu.Game/Graphics/ParticleSpewer.cs b/osu.Game/Graphics/ParticleSpewer.cs index 41a7d82e74..8519cf0c59 100644 --- a/osu.Game/Graphics/ParticleSpewer.cs +++ b/osu.Game/Graphics/ParticleSpewer.cs @@ -16,7 +16,7 @@ using osuTK; namespace osu.Game.Graphics { - public abstract class ParticleSpewer : Sprite + public abstract partial class ParticleSpewer : Sprite { private readonly FallingParticle[] particles; private int currentIndex; diff --git a/osu.Game/Graphics/ScreenshotManager.cs b/osu.Game/Graphics/ScreenshotManager.cs index 2cc9e63c87..d799e82bc9 100644 --- a/osu.Game/Graphics/ScreenshotManager.cs +++ b/osu.Game/Graphics/ScreenshotManager.cs @@ -4,6 +4,7 @@ #nullable disable using System; +using System.IO; using System.Threading; using System.Threading.Tasks; using osu.Framework.Allocation; @@ -25,7 +26,7 @@ using SixLabors.ImageSharp.Formats.Jpeg; namespace osu.Game.Graphics { - public class ScreenshotManager : Component, IKeyBindingHandler, IHandleGlobalKeyboardInput + public partial class ScreenshotManager : Component, IKeyBindingHandler, IHandleGlobalKeyboardInput { private readonly BindableBool cursorVisibility = new BindableBool(true); @@ -117,11 +118,11 @@ namespace osu.Game.Graphics host.GetClipboard()?.SetImage(image); - string filename = getFilename(); + (string filename, var stream) = getWritableStream(); if (filename == null) return; - using (var stream = storage.CreateFileSafely(filename)) + using (stream) { switch (screenshotFormat.Value) { @@ -142,7 +143,7 @@ namespace osu.Game.Graphics notificationOverlay.Post(new SimpleNotification { - Text = $"{filename} saved!", + Text = $"Screenshot {filename} saved!", Activated = () => { storage.PresentFileExternally(filename); @@ -152,23 +153,28 @@ namespace osu.Game.Graphics } }); - private string getFilename() + private static readonly object filename_reservation_lock = new object(); + + private (string filename, Stream stream) getWritableStream() { - var dt = DateTime.Now; - string fileExt = screenshotFormat.ToString().ToLowerInvariant(); - - string withoutIndex = $"osu_{dt:yyyy-MM-dd_HH-mm-ss}.{fileExt}"; - if (!storage.Exists(withoutIndex)) - return withoutIndex; - - for (ulong i = 1; i < ulong.MaxValue; i++) + lock (filename_reservation_lock) { - string indexedName = $"osu_{dt:yyyy-MM-dd_HH-mm-ss}-{i}.{fileExt}"; - if (!storage.Exists(indexedName)) - return indexedName; - } + var dt = DateTime.Now; + string fileExt = screenshotFormat.ToString().ToLowerInvariant(); - return null; + string withoutIndex = $"osu_{dt:yyyy-MM-dd_HH-mm-ss}.{fileExt}"; + if (!storage.Exists(withoutIndex)) + return (withoutIndex, storage.GetStream(withoutIndex, FileAccess.Write, FileMode.Create)); + + for (ulong i = 1; i < ulong.MaxValue; i++) + { + string indexedName = $"osu_{dt:yyyy-MM-dd_HH-mm-ss}-{i}.{fileExt}"; + if (!storage.Exists(indexedName)) + return (indexedName, storage.GetStream(indexedName, FileAccess.Write, FileMode.Create)); + } + + return (null, null); + } } } } diff --git a/osu.Game/Graphics/Sprites/GlowingSpriteText.cs b/osu.Game/Graphics/Sprites/GlowingSpriteText.cs index dca6b7158b..ae594ddfe2 100644 --- a/osu.Game/Graphics/Sprites/GlowingSpriteText.cs +++ b/osu.Game/Graphics/Sprites/GlowingSpriteText.cs @@ -13,7 +13,7 @@ using osuTK; namespace osu.Game.Graphics.Sprites { - public class GlowingSpriteText : Container, IHasText + public partial class GlowingSpriteText : Container, IHasText { private readonly OsuSpriteText spriteText, blurredText; diff --git a/osu.Game/Graphics/Sprites/LogoAnimation.cs b/osu.Game/Graphics/Sprites/LogoAnimation.cs index 097de4dfcb..e177cc604b 100644 --- a/osu.Game/Graphics/Sprites/LogoAnimation.cs +++ b/osu.Game/Graphics/Sprites/LogoAnimation.cs @@ -11,7 +11,7 @@ using osu.Framework.Graphics.Sprites; namespace osu.Game.Graphics.Sprites { - public class LogoAnimation : Sprite + public partial class LogoAnimation : Sprite { [BackgroundDependencyLoader] private void load(ShaderManager shaders) diff --git a/osu.Game/Graphics/Sprites/OsuSpriteText.cs b/osu.Game/Graphics/Sprites/OsuSpriteText.cs index a46ed27b9b..e149e0abfb 100644 --- a/osu.Game/Graphics/Sprites/OsuSpriteText.cs +++ b/osu.Game/Graphics/Sprites/OsuSpriteText.cs @@ -7,7 +7,7 @@ using osu.Framework.Graphics.Sprites; namespace osu.Game.Graphics.Sprites { - public class OsuSpriteText : SpriteText + public partial class OsuSpriteText : SpriteText { public OsuSpriteText() { diff --git a/osu.Game/Graphics/Sprites/SizePreservingSpriteText.cs b/osu.Game/Graphics/Sprites/SizePreservingSpriteText.cs index baffe106ed..458dac2b91 100644 --- a/osu.Game/Graphics/Sprites/SizePreservingSpriteText.cs +++ b/osu.Game/Graphics/Sprites/SizePreservingSpriteText.cs @@ -15,7 +15,7 @@ namespace osu.Game.Graphics.Sprites /// /// A wrapped version of which will expand in size based on text content, but never shrink back down. /// - public class SizePreservingSpriteText : CompositeDrawable + public partial class SizePreservingSpriteText : CompositeDrawable { private readonly OsuSpriteText text = new OsuSpriteText(); diff --git a/osu.Game/Graphics/UserInterface/BackButton.cs b/osu.Game/Graphics/UserInterface/BackButton.cs index d2ed71dfc6..cd9a357ea4 100644 --- a/osu.Game/Graphics/UserInterface/BackButton.cs +++ b/osu.Game/Graphics/UserInterface/BackButton.cs @@ -13,7 +13,7 @@ using osu.Game.Input.Bindings; namespace osu.Game.Graphics.UserInterface { - public class BackButton : VisibilityContainer + public partial class BackButton : VisibilityContainer { public Action Action; @@ -60,7 +60,7 @@ namespace osu.Game.Graphics.UserInterface button.FadeOut(400, Easing.OutQuint); } - public class Receptor : Drawable, IKeyBindingHandler + public partial class Receptor : Drawable, IKeyBindingHandler { public Action OnBackPressed; diff --git a/osu.Game/Graphics/UserInterface/Bar.cs b/osu.Game/Graphics/UserInterface/Bar.cs index e9a20761b3..53217e2120 100644 --- a/osu.Game/Graphics/UserInterface/Bar.cs +++ b/osu.Game/Graphics/UserInterface/Bar.cs @@ -12,7 +12,7 @@ using osu.Framework.Graphics.Shapes; namespace osu.Game.Graphics.UserInterface { - public class Bar : Container, IHasAccentColour + public partial class Bar : Container, IHasAccentColour { private readonly Box background; private readonly Box bar; diff --git a/osu.Game/Graphics/UserInterface/BarGraph.cs b/osu.Game/Graphics/UserInterface/BarGraph.cs index 3f356c0225..c394e58d87 100644 --- a/osu.Game/Graphics/UserInterface/BarGraph.cs +++ b/osu.Game/Graphics/UserInterface/BarGraph.cs @@ -17,7 +17,7 @@ using System; namespace osu.Game.Graphics.UserInterface { - public class BarGraph : Drawable + public partial class BarGraph : Drawable { private const int resize_duration = 250; private const Easing easing = Easing.InOutCubic; diff --git a/osu.Game/Graphics/UserInterface/BasicSearchTextBox.cs b/osu.Game/Graphics/UserInterface/BasicSearchTextBox.cs index e0efa1d81c..c4e03133dc 100644 --- a/osu.Game/Graphics/UserInterface/BasicSearchTextBox.cs +++ b/osu.Game/Graphics/UserInterface/BasicSearchTextBox.cs @@ -9,7 +9,7 @@ using osuTK; namespace osu.Game.Graphics.UserInterface { - public class BasicSearchTextBox : SearchTextBox + public partial class BasicSearchTextBox : SearchTextBox { public BasicSearchTextBox() { diff --git a/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs b/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs index b6ae4d6dc5..fc0770d896 100644 --- a/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs +++ b/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs @@ -14,7 +14,7 @@ using osu.Framework.Graphics.Sprites; namespace osu.Game.Graphics.UserInterface { - public class BreadcrumbControl : OsuTabControl + public partial class BreadcrumbControl : OsuTabControl { private const float padding = 10; @@ -44,7 +44,7 @@ namespace osu.Game.Graphics.UserInterface }; } - public class BreadcrumbTabItem : OsuTabItem, IStateful + public partial class BreadcrumbTabItem : OsuTabItem, IStateful { protected virtual float ChevronSize => 10; @@ -52,8 +52,8 @@ namespace osu.Game.Graphics.UserInterface public readonly SpriteIcon Chevron; - //don't allow clicking between transitions and don't make the chevron clickable - public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => Alpha == 1f && Text.ReceivePositionalInputAt(screenSpacePos); + //don't allow clicking between transitions + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => Alpha == 1f && base.ReceivePositionalInputAt(screenSpacePos); public override bool HandleNonPositionalInput => State == Visibility.Visible; public override bool HandlePositionalInput => State == Visibility.Visible; @@ -95,7 +95,7 @@ namespace osu.Game.Graphics.UserInterface { Text.Font = Text.Font.With(size: 18); Text.Margin = new MarginPadding { Vertical = 8 }; - Padding = new MarginPadding { Right = padding + ChevronSize }; + Margin = new MarginPadding { Right = padding + ChevronSize }; Add(Chevron = new SpriteIcon { Anchor = Anchor.CentreRight, diff --git a/osu.Game/Graphics/UserInterface/CommaSeparatedScoreCounter.cs b/osu.Game/Graphics/UserInterface/CommaSeparatedScoreCounter.cs index bec78c68d3..ba76a17fc6 100644 --- a/osu.Game/Graphics/UserInterface/CommaSeparatedScoreCounter.cs +++ b/osu.Game/Graphics/UserInterface/CommaSeparatedScoreCounter.cs @@ -10,7 +10,7 @@ using osu.Game.Graphics.Sprites; namespace osu.Game.Graphics.UserInterface { - public abstract class CommaSeparatedScoreCounter : RollingCounter + public abstract partial class CommaSeparatedScoreCounter : RollingCounter { protected override double RollingDuration => 1000; protected override Easing RollingEasing => Easing.Out; diff --git a/osu.Game/Graphics/UserInterface/DangerousTriangleButton.cs b/osu.Game/Graphics/UserInterface/DangerousRoundedButton.cs similarity index 71% rename from osu.Game/Graphics/UserInterface/DangerousTriangleButton.cs rename to osu.Game/Graphics/UserInterface/DangerousRoundedButton.cs index 1414979531..5855a66ae1 100644 --- a/osu.Game/Graphics/UserInterface/DangerousTriangleButton.cs +++ b/osu.Game/Graphics/UserInterface/DangerousRoundedButton.cs @@ -4,17 +4,16 @@ #nullable disable using osu.Framework.Allocation; +using osu.Game.Graphics.UserInterfaceV2; namespace osu.Game.Graphics.UserInterface { - public class DangerousTriangleButton : TriangleButton + public partial class DangerousRoundedButton : RoundedButton { [BackgroundDependencyLoader] private void load(OsuColour colours) { BackgroundColour = colours.PinkDark; - Triangles.ColourDark = colours.PinkDarker; - Triangles.ColourLight = colours.Pink; } } } diff --git a/osu.Game/Graphics/UserInterface/DialogButton.cs b/osu.Game/Graphics/UserInterface/DialogButton.cs index 52ad5c6b80..670778b07b 100644 --- a/osu.Game/Graphics/UserInterface/DialogButton.cs +++ b/osu.Game/Graphics/UserInterface/DialogButton.cs @@ -22,7 +22,7 @@ using osuTK.Graphics; namespace osu.Game.Graphics.UserInterface { - public class DialogButton : OsuClickableContainer, IStateful + public partial class DialogButton : OsuClickableContainer, IStateful { private const float idle_width = 0.8f; private const float hover_width = 0.9f; diff --git a/osu.Game/Graphics/UserInterface/DownloadButton.cs b/osu.Game/Graphics/UserInterface/DownloadButton.cs index dfbe6bd44d..73783e718c 100644 --- a/osu.Game/Graphics/UserInterface/DownloadButton.cs +++ b/osu.Game/Graphics/UserInterface/DownloadButton.cs @@ -12,7 +12,7 @@ using osuTK; namespace osu.Game.Graphics.UserInterface { - public class DownloadButton : GrayButton + public partial class DownloadButton : GrayButton { [Resolved] private OsuColour colours { get; set; } diff --git a/osu.Game/Graphics/UserInterface/DrawableOsuMenuItem.cs b/osu.Game/Graphics/UserInterface/DrawableOsuMenuItem.cs index 6c8eeed391..ad02e3b2ab 100644 --- a/osu.Game/Graphics/UserInterface/DrawableOsuMenuItem.cs +++ b/osu.Game/Graphics/UserInterface/DrawableOsuMenuItem.cs @@ -16,7 +16,7 @@ using osuTK.Graphics; namespace osu.Game.Graphics.UserInterface { - public class DrawableOsuMenuItem : Menu.DrawableMenuItem + public partial class DrawableOsuMenuItem : Menu.DrawableMenuItem { public const int MARGIN_HORIZONTAL = 17; public const int MARGIN_VERTICAL = 4; @@ -95,7 +95,7 @@ namespace osu.Game.Graphics.UserInterface protected sealed override Drawable CreateContent() => text = CreateTextContainer(); protected virtual TextContainer CreateTextContainer() => new TextContainer(); - protected class TextContainer : Container, IHasText + protected partial class TextContainer : Container, IHasText { public LocalisableString Text { diff --git a/osu.Game/Graphics/UserInterface/DrawableStatefulMenuItem.cs b/osu.Game/Graphics/UserInterface/DrawableStatefulMenuItem.cs index 5a7cf0d73e..ec3a5744f8 100644 --- a/osu.Game/Graphics/UserInterface/DrawableStatefulMenuItem.cs +++ b/osu.Game/Graphics/UserInterface/DrawableStatefulMenuItem.cs @@ -10,7 +10,7 @@ using osuTK; namespace osu.Game.Graphics.UserInterface { - public class DrawableStatefulMenuItem : DrawableOsuMenuItem + public partial class DrawableStatefulMenuItem : DrawableOsuMenuItem { protected new StatefulMenuItem Item => (StatefulMenuItem)base.Item; @@ -21,7 +21,7 @@ namespace osu.Game.Graphics.UserInterface protected override TextContainer CreateTextContainer() => new ToggleTextContainer(Item); - private class ToggleTextContainer : TextContainer + private partial class ToggleTextContainer : TextContainer { private readonly StatefulMenuItem menuItem; private readonly Bindable state; diff --git a/osu.Game/Graphics/UserInterface/ExpandableSlider.cs b/osu.Game/Graphics/UserInterface/ExpandableSlider.cs index 92b0059157..9669fe89a5 100644 --- a/osu.Game/Graphics/UserInterface/ExpandableSlider.cs +++ b/osu.Game/Graphics/UserInterface/ExpandableSlider.cs @@ -19,7 +19,7 @@ namespace osu.Game.Graphics.UserInterface /// /// An implementation for the UI slider bar control. /// - public class ExpandableSlider : CompositeDrawable, IExpandable, IHasCurrentValue + public partial class ExpandableSlider : CompositeDrawable, IExpandable, IHasCurrentValue where T : struct, IEquatable, IComparable, IConvertible where TSlider : OsuSliderBar, new() { @@ -130,7 +130,7 @@ namespace osu.Game.Graphics.UserInterface /// /// An implementation for the UI slider bar control. /// - public class ExpandableSlider : ExpandableSlider> + public partial class ExpandableSlider : ExpandableSlider> where T : struct, IEquatable, IComparable, IConvertible { } diff --git a/osu.Game/Graphics/UserInterface/ExpandingBar.cs b/osu.Game/Graphics/UserInterface/ExpandingBar.cs index b2ffb4da7d..6d7c41ee7c 100644 --- a/osu.Game/Graphics/UserInterface/ExpandingBar.cs +++ b/osu.Game/Graphics/UserInterface/ExpandingBar.cs @@ -13,7 +13,7 @@ namespace osu.Game.Graphics.UserInterface /// A rounded bar which can be expanded or collapsed. /// Generally used for tabs or breadcrumbs. /// - public class ExpandingBar : Circle + public partial class ExpandingBar : Circle { private bool expanded = true; diff --git a/osu.Game/Graphics/UserInterface/ExternalLinkButton.cs b/osu.Game/Graphics/UserInterface/ExternalLinkButton.cs index e51dbeed14..4eccb37613 100644 --- a/osu.Game/Graphics/UserInterface/ExternalLinkButton.cs +++ b/osu.Game/Graphics/UserInterface/ExternalLinkButton.cs @@ -18,7 +18,7 @@ using osuTK.Graphics; namespace osu.Game.Graphics.UserInterface { - public class ExternalLinkButton : CompositeDrawable, IHasTooltip, IHasContextMenu + public partial class ExternalLinkButton : CompositeDrawable, IHasTooltip, IHasContextMenu { public string? Link { get; set; } @@ -82,7 +82,7 @@ namespace osu.Game.Graphics.UserInterface if (Link != null) { - items.Add(new OsuMenuItem("Open", MenuItemType.Standard, () => host.OpenUrlExternally(Link))); + items.Add(new OsuMenuItem("Open", MenuItemType.Highlighted, () => host.OpenUrlExternally(Link))); items.Add(new OsuMenuItem("Copy URL", MenuItemType.Standard, copyUrl)); } diff --git a/osu.Game/Graphics/UserInterface/FPSCounter.cs b/osu.Game/Graphics/UserInterface/FPSCounter.cs index e9fb6a046a..9dbeba6449 100644 --- a/osu.Game/Graphics/UserInterface/FPSCounter.cs +++ b/osu.Game/Graphics/UserInterface/FPSCounter.cs @@ -19,7 +19,7 @@ using osuTK; namespace osu.Game.Graphics.UserInterface { - public class FPSCounter : VisibilityContainer, IHasCustomTooltip + public partial class FPSCounter : VisibilityContainer, IHasCustomTooltip { private OsuSpriteText counterUpdateFrameTime = null!; private OsuSpriteText counterDrawFPS = null!; diff --git a/osu.Game/Graphics/UserInterface/FPSCounterTooltip.cs b/osu.Game/Graphics/UserInterface/FPSCounterTooltip.cs index bf53bff9b4..17e7be1d8b 100644 --- a/osu.Game/Graphics/UserInterface/FPSCounterTooltip.cs +++ b/osu.Game/Graphics/UserInterface/FPSCounterTooltip.cs @@ -13,7 +13,7 @@ using osuTK; namespace osu.Game.Graphics.UserInterface { - public class FPSCounterTooltip : CompositeDrawable, ITooltip + public partial class FPSCounterTooltip : CompositeDrawable, ITooltip { private OsuTextFlowContainer textFlow = null!; diff --git a/osu.Game/Graphics/UserInterface/FocusedTextBox.cs b/osu.Game/Graphics/UserInterface/FocusedTextBox.cs index 0c18fd36fc..338f32f321 100644 --- a/osu.Game/Graphics/UserInterface/FocusedTextBox.cs +++ b/osu.Game/Graphics/UserInterface/FocusedTextBox.cs @@ -15,7 +15,7 @@ namespace osu.Game.Graphics.UserInterface /// /// A textbox which holds focus eagerly. /// - public class FocusedTextBox : OsuTextBox, IKeyBindingHandler + public partial class FocusedTextBox : OsuTextBox, IKeyBindingHandler { private bool focus; diff --git a/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs b/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs index e16f1ee897..7e29053035 100644 --- a/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs +++ b/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs @@ -13,7 +13,7 @@ using osu.Framework.Graphics.Colour; namespace osu.Game.Graphics.UserInterface { - public abstract class GradientLineTabControl : PageTabControl + public abstract partial class GradientLineTabControl : PageTabControl { protected Color4 LineColour { @@ -46,7 +46,7 @@ namespace osu.Game.Graphics.UserInterface Spacing = new Vector2(20, 0), }; - private class GradientLine : GridContainer + private partial class GradientLine : GridContainer { public GradientLine() { diff --git a/osu.Game/Graphics/UserInterface/GrayButton.cs b/osu.Game/Graphics/UserInterface/GrayButton.cs index d95032bce6..3df234e97d 100644 --- a/osu.Game/Graphics/UserInterface/GrayButton.cs +++ b/osu.Game/Graphics/UserInterface/GrayButton.cs @@ -11,7 +11,7 @@ using osuTK; namespace osu.Game.Graphics.UserInterface { - public class GrayButton : OsuAnimatedButton + public partial class GrayButton : OsuAnimatedButton { protected SpriteIcon Icon { get; private set; } protected Box Background { get; private set; } diff --git a/osu.Game/Graphics/UserInterface/HistoryTextBox.cs b/osu.Game/Graphics/UserInterface/HistoryTextBox.cs index 0958e1832e..b6dc1fcc9b 100644 --- a/osu.Game/Graphics/UserInterface/HistoryTextBox.cs +++ b/osu.Game/Graphics/UserInterface/HistoryTextBox.cs @@ -13,7 +13,7 @@ namespace osu.Game.Graphics.UserInterface /// The history of committed text can be navigated using up/down arrows. /// This resembles the operation of command-line terminals. /// - public class HistoryTextBox : FocusedTextBox + public partial class HistoryTextBox : FocusedTextBox { private readonly LimitedCapacityQueue messageHistory; @@ -45,6 +45,9 @@ namespace osu.Game.Graphics.UserInterface protected override bool OnKeyDown(KeyDownEvent e) { + if (e.ControlPressed || e.AltPressed || e.SuperPressed || e.ShiftPressed) + return false; + switch (e.Key) { case Key.Up: diff --git a/osu.Game/Graphics/UserInterface/HoverClickSounds.cs b/osu.Game/Graphics/UserInterface/HoverClickSounds.cs index 99cec7411c..ed1838abd0 100644 --- a/osu.Game/Graphics/UserInterface/HoverClickSounds.cs +++ b/osu.Game/Graphics/UserInterface/HoverClickSounds.cs @@ -19,7 +19,7 @@ namespace osu.Game.Graphics.UserInterface /// Adds hover and click sounds to a drawable. /// Does not draw anything. /// - public class HoverClickSounds : HoverSounds + public partial class HoverClickSounds : HoverSounds { public Bindable Enabled = new Bindable(true); diff --git a/osu.Game/Graphics/UserInterface/HoverSampleDebounceComponent.cs b/osu.Game/Graphics/UserInterface/HoverSampleDebounceComponent.cs index 20715309a2..53f1c06a67 100644 --- a/osu.Game/Graphics/UserInterface/HoverSampleDebounceComponent.cs +++ b/osu.Game/Graphics/UserInterface/HoverSampleDebounceComponent.cs @@ -14,7 +14,7 @@ namespace osu.Game.Graphics.UserInterface /// /// Handles debouncing hover sounds at a global level to ensure the effects are not overwhelming. /// - public abstract class HoverSampleDebounceComponent : CompositeDrawable + public abstract partial class HoverSampleDebounceComponent : CompositeDrawable { private Bindable lastPlaybackTime; diff --git a/osu.Game/Graphics/UserInterface/HoverSounds.cs b/osu.Game/Graphics/UserInterface/HoverSounds.cs index dd03e83ab1..012594b404 100644 --- a/osu.Game/Graphics/UserInterface/HoverSounds.cs +++ b/osu.Game/Graphics/UserInterface/HoverSounds.cs @@ -16,7 +16,7 @@ namespace osu.Game.Graphics.UserInterface /// Adds hover sounds to a drawable. /// Does not draw anything. /// - public class HoverSounds : HoverSampleDebounceComponent + public partial class HoverSounds : HoverSampleDebounceComponent { private Sample sampleHover; diff --git a/osu.Game/Graphics/UserInterface/IconButton.cs b/osu.Game/Graphics/UserInterface/IconButton.cs index e0b5999c4d..47f06715b5 100644 --- a/osu.Game/Graphics/UserInterface/IconButton.cs +++ b/osu.Game/Graphics/UserInterface/IconButton.cs @@ -11,7 +11,7 @@ using osu.Framework.Input.Events; namespace osu.Game.Graphics.UserInterface { - public class IconButton : OsuAnimatedButton + public partial class IconButton : OsuAnimatedButton { public const float DEFAULT_BUTTON_SIZE = 30; diff --git a/osu.Game/Graphics/UserInterface/LineGraph.cs b/osu.Game/Graphics/UserInterface/LineGraph.cs index fe634390a2..18c022818f 100644 --- a/osu.Game/Graphics/UserInterface/LineGraph.cs +++ b/osu.Game/Graphics/UserInterface/LineGraph.cs @@ -15,7 +15,7 @@ using osuTK.Graphics; namespace osu.Game.Graphics.UserInterface { - public class LineGraph : Container + public partial class LineGraph : Container { /// /// Manually set the max value, otherwise will be used. diff --git a/osu.Game/Graphics/UserInterface/LoadingButton.cs b/osu.Game/Graphics/UserInterface/LoadingButton.cs index 44067bac8b..8a841ffc94 100644 --- a/osu.Game/Graphics/UserInterface/LoadingButton.cs +++ b/osu.Game/Graphics/UserInterface/LoadingButton.cs @@ -12,7 +12,7 @@ using osuTK; namespace osu.Game.Graphics.UserInterface { - public abstract class LoadingButton : OsuHoverContainer + public abstract partial class LoadingButton : OsuHoverContainer { private bool isLoading; diff --git a/osu.Game/Graphics/UserInterface/LoadingLayer.cs b/osu.Game/Graphics/UserInterface/LoadingLayer.cs index 9f6177c226..9059b61a33 100644 --- a/osu.Game/Graphics/UserInterface/LoadingLayer.cs +++ b/osu.Game/Graphics/UserInterface/LoadingLayer.cs @@ -18,7 +18,7 @@ namespace osu.Game.Graphics.UserInterface /// Also optionally dims target elements. /// Useful for disabling all elements in a form and showing we are waiting on a response, for instance. /// - public class LoadingLayer : LoadingSpinner + public partial class LoadingLayer : LoadingSpinner { private readonly bool blockInput; diff --git a/osu.Game/Graphics/UserInterface/LoadingSpinner.cs b/osu.Game/Graphics/UserInterface/LoadingSpinner.cs index 864dd0a65e..0ea44dfe49 100644 --- a/osu.Game/Graphics/UserInterface/LoadingSpinner.cs +++ b/osu.Game/Graphics/UserInterface/LoadingSpinner.cs @@ -15,7 +15,7 @@ namespace osu.Game.Graphics.UserInterface /// /// A loading spinner. /// - public class LoadingSpinner : VisibilityContainer + public partial class LoadingSpinner : VisibilityContainer { private readonly SpriteIcon spinner; diff --git a/osu.Game/Graphics/UserInterface/Nub.cs b/osu.Game/Graphics/UserInterface/Nub.cs index db3a41e303..7921dcf593 100644 --- a/osu.Game/Graphics/UserInterface/Nub.cs +++ b/osu.Game/Graphics/UserInterface/Nub.cs @@ -19,7 +19,7 @@ using osu.Game.Overlays; namespace osu.Game.Graphics.UserInterface { - public class Nub : Container, IHasCurrentValue, IHasAccentColour + public partial class Nub : Container, IHasCurrentValue, IHasAccentColour { public const float HEIGHT = 15; @@ -114,8 +114,7 @@ namespace osu.Game.Graphics.UserInterface get => current; set { - if (value == null) - throw new ArgumentNullException(nameof(value)); + ArgumentNullException.ThrowIfNull(value); current.UnbindBindings(); current.BindTo(value); diff --git a/osu.Game/Graphics/UserInterface/OsuAnimatedButton.cs b/osu.Game/Graphics/UserInterface/OsuAnimatedButton.cs index f720678a93..5ef590d253 100644 --- a/osu.Game/Graphics/UserInterface/OsuAnimatedButton.cs +++ b/osu.Game/Graphics/UserInterface/OsuAnimatedButton.cs @@ -18,7 +18,7 @@ namespace osu.Game.Graphics.UserInterface /// /// Highlight on hover, bounce on click. /// - public class OsuAnimatedButton : OsuClickableContainer + public partial class OsuAnimatedButton : OsuClickableContainer { /// /// The colour that should be flashed when the is clicked. diff --git a/osu.Game/Graphics/UserInterface/OsuButton.cs b/osu.Game/Graphics/UserInterface/OsuButton.cs index dae5de2d65..805dfcaa95 100644 --- a/osu.Game/Graphics/UserInterface/OsuButton.cs +++ b/osu.Game/Graphics/UserInterface/OsuButton.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -13,6 +11,7 @@ using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; using osu.Framework.Localisation; using osu.Game.Graphics.Sprites; +using osuTK; using osuTK.Graphics; namespace osu.Game.Graphics.UserInterface @@ -20,16 +19,12 @@ namespace osu.Game.Graphics.UserInterface /// /// A button with added default sound effects. /// - public class OsuButton : Button + public abstract partial class OsuButton : Button { public LocalisableString Text { - get => SpriteText?.Text ?? default; - set - { - if (SpriteText != null) - SpriteText.Text = value; - } + get => SpriteText.Text; + set => SpriteText.Text = value; } private Color4? backgroundColour; @@ -37,7 +32,7 @@ namespace osu.Game.Graphics.UserInterface /// /// Sets a custom background colour to this button, replacing the provided default. /// - public Color4 BackgroundColour + public virtual Color4 BackgroundColour { get => backgroundColour ?? defaultBackgroundColour; set @@ -66,13 +61,19 @@ namespace osu.Game.Graphics.UserInterface protected override Container Content { get; } + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => + // base call is checked for cases when `OsuClickableContainer` has masking applied to it directly (ie. externally in object initialisation). + base.ReceivePositionalInputAt(screenSpacePos) + // Implementations often apply masking / edge rounding at a content level, so it's imperative to check that as well. + && Content.ReceivePositionalInputAt(screenSpacePos); + protected Box Hover; protected Box Background; protected SpriteText SpriteText; private readonly Box flashLayer; - public OsuButton(HoverSampleSet? hoverSounds = HoverSampleSet.Button) + protected OsuButton(HoverSampleSet? hoverSounds = HoverSampleSet.Button) { Height = 40; @@ -90,6 +91,7 @@ namespace osu.Game.Graphics.UserInterface Anchor = Anchor.Centre, Origin = Anchor.Centre, RelativeSizeAxes = Axes.Both, + Depth = float.MaxValue, }, Hover = new Box { @@ -114,7 +116,7 @@ namespace osu.Game.Graphics.UserInterface }); if (hoverSounds.HasValue) - AddInternal(new HoverClickSounds(hoverSounds.Value) { Enabled = { BindTarget = Enabled } }); + Add(new HoverClickSounds(hoverSounds.Value) { Enabled = { BindTarget = Enabled } }); } [BackgroundDependencyLoader] @@ -141,13 +143,15 @@ namespace osu.Game.Graphics.UserInterface return base.OnClick(e); } + protected virtual float HoverLayerFinalAlpha => 0.1f; + protected override bool OnHover(HoverEvent e) { if (Enabled.Value) { Hover.FadeTo(0.2f, 40, Easing.OutQuint) .Then() - .FadeTo(0.1f, 800, Easing.OutQuint); + .FadeTo(HoverLayerFinalAlpha, 800, Easing.OutQuint); } return base.OnHover(e); diff --git a/osu.Game/Graphics/UserInterface/OsuCheckbox.cs b/osu.Game/Graphics/UserInterface/OsuCheckbox.cs index 8772c1e2d9..160105af1a 100644 --- a/osu.Game/Graphics/UserInterface/OsuCheckbox.cs +++ b/osu.Game/Graphics/UserInterface/OsuCheckbox.cs @@ -15,7 +15,7 @@ using osu.Game.Graphics.Containers; namespace osu.Game.Graphics.UserInterface { - public class OsuCheckbox : Checkbox + public partial class OsuCheckbox : Checkbox { /// /// Whether to play sounds when the state changes as a result of user interaction. diff --git a/osu.Game/Graphics/UserInterface/OsuContextMenu.cs b/osu.Game/Graphics/UserInterface/OsuContextMenu.cs index cc5ce8f46d..1b5f7cc4b5 100644 --- a/osu.Game/Graphics/UserInterface/OsuContextMenu.cs +++ b/osu.Game/Graphics/UserInterface/OsuContextMenu.cs @@ -12,7 +12,7 @@ using osu.Framework.Graphics.UserInterface; namespace osu.Game.Graphics.UserInterface { - public class OsuContextMenu : OsuMenu + public partial class OsuContextMenu : OsuMenu { private const int fade_duration = 250; diff --git a/osu.Game/Graphics/UserInterface/OsuContextMenuSamples.cs b/osu.Game/Graphics/UserInterface/OsuContextMenuSamples.cs index c329974e28..6d7543c472 100644 --- a/osu.Game/Graphics/UserInterface/OsuContextMenuSamples.cs +++ b/osu.Game/Graphics/UserInterface/OsuContextMenuSamples.cs @@ -11,7 +11,7 @@ using osu.Framework.Graphics; namespace osu.Game.Graphics.UserInterface { - public class OsuContextMenuSamples : Component + public partial class OsuContextMenuSamples : Component { private Sample sampleClick; private Sample sampleOpen; diff --git a/osu.Game/Graphics/UserInterface/OsuDropdown.cs b/osu.Game/Graphics/UserInterface/OsuDropdown.cs index ce2a690e92..3230bb0569 100644 --- a/osu.Game/Graphics/UserInterface/OsuDropdown.cs +++ b/osu.Game/Graphics/UserInterface/OsuDropdown.cs @@ -22,7 +22,7 @@ using osuTK.Graphics; namespace osu.Game.Graphics.UserInterface { - public class OsuDropdown : Dropdown + public partial class OsuDropdown : Dropdown { private const float corner_radius = 5; @@ -32,7 +32,7 @@ namespace osu.Game.Graphics.UserInterface #region OsuDropdownMenu - protected class OsuDropdownMenu : DropdownMenu, IKeyBindingHandler + protected partial class OsuDropdownMenu : DropdownMenu, IKeyBindingHandler { public override bool HandleNonPositionalInput => State == MenuState.Open; @@ -135,7 +135,7 @@ namespace osu.Game.Graphics.UserInterface #region DrawableOsuDropdownMenuItem - public class DrawableOsuDropdownMenuItem : DrawableDropdownMenuItem + public partial class DrawableOsuDropdownMenuItem : DrawableDropdownMenuItem { // IsHovered is used public override bool HandlePositionalInput => true; @@ -203,7 +203,7 @@ namespace osu.Game.Graphics.UserInterface protected override Drawable CreateContent() => new Content(); - protected new class Content : CompositeDrawable, IHasText + protected new partial class Content : CompositeDrawable, IHasText { public LocalisableString Text { @@ -297,7 +297,7 @@ namespace osu.Game.Graphics.UserInterface #endregion - public class OsuDropdownHeader : DropdownHeader + public partial class OsuDropdownHeader : DropdownHeader { protected readonly SpriteText Text; diff --git a/osu.Game/Graphics/UserInterface/OsuEnumDropdown.cs b/osu.Game/Graphics/UserInterface/OsuEnumDropdown.cs index 3d4a8cf359..dc089e3410 100644 --- a/osu.Game/Graphics/UserInterface/OsuEnumDropdown.cs +++ b/osu.Game/Graphics/UserInterface/OsuEnumDropdown.cs @@ -7,12 +7,12 @@ using System; namespace osu.Game.Graphics.UserInterface { - public class OsuEnumDropdown : OsuDropdown + public partial class OsuEnumDropdown : OsuDropdown where T : struct, Enum { public OsuEnumDropdown() { - Items = (T[])Enum.GetValues(typeof(T)); + Items = Enum.GetValues(); } } } diff --git a/osu.Game/Graphics/UserInterface/OsuMenu.cs b/osu.Game/Graphics/UserInterface/OsuMenu.cs index a11bffd05d..73d57af793 100644 --- a/osu.Game/Graphics/UserInterface/OsuMenu.cs +++ b/osu.Game/Graphics/UserInterface/OsuMenu.cs @@ -16,7 +16,7 @@ using osuTK; namespace osu.Game.Graphics.UserInterface { - public class OsuMenu : Menu + public partial class OsuMenu : Menu { private Sample sampleOpen; private Sample sampleClose; diff --git a/osu.Game/Graphics/UserInterface/OsuMenuItem.cs b/osu.Game/Graphics/UserInterface/OsuMenuItem.cs index 9d65d6b8b9..20461de08f 100644 --- a/osu.Game/Graphics/UserInterface/OsuMenuItem.cs +++ b/osu.Game/Graphics/UserInterface/OsuMenuItem.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using osu.Framework.Graphics.UserInterface; using osu.Framework.Localisation; @@ -13,12 +11,12 @@ namespace osu.Game.Graphics.UserInterface { public readonly MenuItemType Type; - public OsuMenuItem(string text, MenuItemType type = MenuItemType.Standard) + public OsuMenuItem(LocalisableString text, MenuItemType type = MenuItemType.Standard) : this(text, type, null) { } - public OsuMenuItem(LocalisableString text, MenuItemType type, Action action) + public OsuMenuItem(LocalisableString text, MenuItemType type, Action? action) : base(text, action) { Type = type; diff --git a/osu.Game/Graphics/UserInterface/OsuNumberBox.cs b/osu.Game/Graphics/UserInterface/OsuNumberBox.cs index 93d47792c8..f6a3abdaae 100644 --- a/osu.Game/Graphics/UserInterface/OsuNumberBox.cs +++ b/osu.Game/Graphics/UserInterface/OsuNumberBox.cs @@ -7,7 +7,7 @@ using osu.Framework.Extensions; namespace osu.Game.Graphics.UserInterface { - public class OsuNumberBox : OsuTextBox + public partial class OsuNumberBox : OsuTextBox { protected override bool AllowIme => false; diff --git a/osu.Game/Graphics/UserInterface/OsuPasswordTextBox.cs b/osu.Game/Graphics/UserInterface/OsuPasswordTextBox.cs index 305b1b6687..63c98d7838 100644 --- a/osu.Game/Graphics/UserInterface/OsuPasswordTextBox.cs +++ b/osu.Game/Graphics/UserInterface/OsuPasswordTextBox.cs @@ -19,7 +19,7 @@ using osu.Framework.Platform; namespace osu.Game.Graphics.UserInterface { - public class OsuPasswordTextBox : OsuTextBox, ISuppressKeyEventLogging + public partial class OsuPasswordTextBox : OsuTextBox, ISuppressKeyEventLogging { protected override Drawable GetDrawableCharacter(char c) => new FallingDownContainer { @@ -73,7 +73,7 @@ namespace osu.Game.Graphics.UserInterface private void updateCapsWarning(bool visible) => warning.FadeTo(visible ? 1 : 0, 250, Easing.OutQuint); - public class PasswordMaskChar : Container + public partial class PasswordMaskChar : Container { private readonly CircularContainer circle; @@ -110,7 +110,7 @@ namespace osu.Game.Graphics.UserInterface } } - private class CapsWarning : SpriteIcon, IHasTooltip + private partial class CapsWarning : SpriteIcon, IHasTooltip { public LocalisableString TooltipText => "caps lock is active"; diff --git a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs index 4d3f4be8f6..6d6a591673 100644 --- a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs @@ -25,7 +25,7 @@ using osu.Game.Utils; namespace osu.Game.Graphics.UserInterface { - public class OsuSliderBar : SliderBar, IHasTooltip, IHasAccentColour + public partial class OsuSliderBar : SliderBar, IHasTooltip, IHasAccentColour where T : struct, IEquatable, IComparable, IConvertible { /// diff --git a/osu.Game/Graphics/UserInterface/OsuTabControl.cs b/osu.Game/Graphics/UserInterface/OsuTabControl.cs index 3cfe401bb9..05309760e7 100644 --- a/osu.Game/Graphics/UserInterface/OsuTabControl.cs +++ b/osu.Game/Graphics/UserInterface/OsuTabControl.cs @@ -22,7 +22,7 @@ using osu.Game.Graphics.Sprites; namespace osu.Game.Graphics.UserInterface { - public class OsuTabControl : TabControl + public partial class OsuTabControl : TabControl { private Color4 accentColour; @@ -98,7 +98,7 @@ namespace osu.Game.Graphics.UserInterface strip.Width = Interpolation.ValueAt(Math.Clamp(Clock.ElapsedFrameTime, 0, 1000), strip.Width, StripWidth, 0, 500, Easing.OutQuint); } - public class OsuTabItem : TabItem, IHasAccentColour + public partial class OsuTabItem : TabItem, IHasAccentColour { protected readonly SpriteText Text; protected readonly Box Bar; diff --git a/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs b/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs index 6e6296c24b..fa58ae27f2 100644 --- a/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs +++ b/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs @@ -22,7 +22,7 @@ namespace osu.Game.Graphics.UserInterface /// /// A Checkbox styled to be placed in line with an /// - public class OsuTabControlCheckbox : Checkbox + public partial class OsuTabControlCheckbox : Checkbox { private readonly Box box; private readonly SpriteText text; diff --git a/osu.Game/Graphics/UserInterface/OsuTabDropdown.cs b/osu.Game/Graphics/UserInterface/OsuTabDropdown.cs index d9d9a21401..01d072b6d7 100644 --- a/osu.Game/Graphics/UserInterface/OsuTabDropdown.cs +++ b/osu.Game/Graphics/UserInterface/OsuTabDropdown.cs @@ -13,7 +13,7 @@ using osu.Framework.Input.Events; namespace osu.Game.Graphics.UserInterface { - public class OsuTabDropdown : OsuDropdown, IHasAccentColour + public partial class OsuTabDropdown : OsuDropdown, IHasAccentColour { private Color4 accentColour; @@ -60,7 +60,7 @@ namespace osu.Game.Graphics.UserInterface tabDropdownHeader.AccentColour = accentColour; } - private class OsuTabDropdownMenu : OsuDropdownMenu + private partial class OsuTabDropdownMenu : OsuDropdownMenu { public OsuTabDropdownMenu() { @@ -73,7 +73,7 @@ namespace osu.Game.Graphics.UserInterface protected override DrawableDropdownMenuItem CreateDrawableDropdownMenuItem(MenuItem item) => new DrawableOsuTabDropdownMenuItem(item); - private class DrawableOsuTabDropdownMenuItem : DrawableOsuDropdownMenuItem + private partial class DrawableOsuTabDropdownMenuItem : DrawableOsuDropdownMenuItem { public DrawableOsuTabDropdownMenuItem(MenuItem item) : base(item) @@ -83,7 +83,7 @@ namespace osu.Game.Graphics.UserInterface } } - protected class OsuTabDropdownHeader : OsuDropdownHeader, IHasAccentColour + protected partial class OsuTabDropdownHeader : OsuDropdownHeader, IHasAccentColour { private Color4 accentColour; diff --git a/osu.Game/Graphics/UserInterface/OsuTextBox.cs b/osu.Game/Graphics/UserInterface/OsuTextBox.cs index 18977638f3..a65204e6b3 100644 --- a/osu.Game/Graphics/UserInterface/OsuTextBox.cs +++ b/osu.Game/Graphics/UserInterface/OsuTextBox.cs @@ -24,7 +24,7 @@ using osuTK; namespace osu.Game.Graphics.UserInterface { - public class OsuTextBox : BasicTextBox + public partial class OsuTextBox : BasicTextBox { /// /// Whether to allow playing a different samples based on the type of character. @@ -277,7 +277,7 @@ namespace osu.Game.Graphics.UserInterface { var samples = sampleMap[feedbackSampleType]; - if (samples == null || samples.Length == 0) + if (samples.Length == 0) return null; return samples[RNG.Next(0, samples.Length)]?.GetChannel(); @@ -302,7 +302,7 @@ namespace osu.Game.Graphics.UserInterface sampleLastPlaybackTime = Time.Current; }); - private class OsuCaret : Caret + private partial class OsuCaret : Caret { private const float caret_move_time = 60; @@ -349,7 +349,7 @@ namespace osu.Game.Graphics.UserInterface } } - private class CaretBeatSyncedContainer : BeatSyncedContainer + private partial class CaretBeatSyncedContainer : BeatSyncedContainer { private bool hasSelection; diff --git a/osu.Game/Graphics/UserInterface/PageSelector/PageEllipsis.cs b/osu.Game/Graphics/UserInterface/PageSelector/PageEllipsis.cs index b750abcd2b..068e477d79 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector/PageEllipsis.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector/PageEllipsis.cs @@ -11,7 +11,7 @@ using osu.Game.Overlays; namespace osu.Game.Graphics.UserInterface.PageSelector { - internal class PageEllipsis : CompositeDrawable + internal partial class PageEllipsis : CompositeDrawable { [BackgroundDependencyLoader] private void load(OverlayColourProvider colourProvider) diff --git a/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs b/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs index 7c5d38b91b..63f35d5f89 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs @@ -11,7 +11,7 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Graphics.UserInterface.PageSelector { - public class PageSelector : CompositeDrawable + public partial class PageSelector : CompositeDrawable { public readonly BindableInt CurrentPage = new BindableInt { MinValue = 0, }; diff --git a/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorButton.cs b/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorButton.cs index adeae4fc8d..9388f045d3 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorButton.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorButton.cs @@ -14,7 +14,7 @@ using osu.Game.Overlays; namespace osu.Game.Graphics.UserInterface.PageSelector { - public abstract class PageSelectorButton : OsuClickableContainer + public abstract partial class PageSelectorButton : OsuClickableContainer { protected const int DURATION = 200; diff --git a/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorPageButton.cs b/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorPageButton.cs index 7696087195..3e5d1fac6d 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorPageButton.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorPageButton.cs @@ -10,7 +10,7 @@ using osu.Game.Graphics.Sprites; namespace osu.Game.Graphics.UserInterface.PageSelector { - public class PageSelectorPageButton : PageSelectorButton + public partial class PageSelectorPageButton : PageSelectorButton { private readonly BindableBool selected = new BindableBool(); diff --git a/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorPrevNextButton.cs b/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorPrevNextButton.cs index a96cc892d4..e5e0dab2f0 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorPrevNextButton.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorPrevNextButton.cs @@ -14,7 +14,7 @@ using osuTK; namespace osu.Game.Graphics.UserInterface.PageSelector { - public class PageSelectorPrevNextButton : PageSelectorButton + public partial class PageSelectorPrevNextButton : PageSelectorButton { private readonly bool rightAligned; private readonly LocalisableString text; diff --git a/osu.Game/Graphics/UserInterface/PageTabControl.cs b/osu.Game/Graphics/UserInterface/PageTabControl.cs index 13654fac85..2fe8acfbd5 100644 --- a/osu.Game/Graphics/UserInterface/PageTabControl.cs +++ b/osu.Game/Graphics/UserInterface/PageTabControl.cs @@ -18,7 +18,7 @@ using osu.Game.Graphics.Sprites; namespace osu.Game.Graphics.UserInterface { - public class PageTabControl : OsuTabControl + public partial class PageTabControl : OsuTabControl { protected override TabItem CreateTabItem(T value) => new PageTabItem(value); @@ -33,7 +33,7 @@ namespace osu.Game.Graphics.UserInterface AccentColour = colours.Yellow; } - public class PageTabItem : TabItem, IHasAccentColour + public partial class PageTabItem : TabItem, IHasAccentColour { private const float transition_duration = 100; diff --git a/osu.Game/Graphics/UserInterface/PercentageCounter.cs b/osu.Game/Graphics/UserInterface/PercentageCounter.cs index e5b0f0cbee..de93d9b2b4 100644 --- a/osu.Game/Graphics/UserInterface/PercentageCounter.cs +++ b/osu.Game/Graphics/UserInterface/PercentageCounter.cs @@ -14,7 +14,7 @@ namespace osu.Game.Graphics.UserInterface /// /// Used as an accuracy counter. Represented visually as a percentage. /// - public class PercentageCounter : RollingCounter + public partial class PercentageCounter : RollingCounter { protected override double RollingDuration => 750; diff --git a/osu.Game/Graphics/UserInterface/ProgressBar.cs b/osu.Game/Graphics/UserInterface/ProgressBar.cs index 774704223b..8f383c76db 100644 --- a/osu.Game/Graphics/UserInterface/ProgressBar.cs +++ b/osu.Game/Graphics/UserInterface/ProgressBar.cs @@ -11,7 +11,7 @@ using osuTK.Graphics; namespace osu.Game.Graphics.UserInterface { - public class ProgressBar : SliderBar + public partial class ProgressBar : SliderBar { public Action OnSeek; diff --git a/osu.Game/Graphics/UserInterface/RangeSlider.cs b/osu.Game/Graphics/UserInterface/RangeSlider.cs new file mode 100644 index 0000000000..4e23b06c2b --- /dev/null +++ b/osu.Game/Graphics/UserInterface/RangeSlider.cs @@ -0,0 +1,212 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Input.Events; +using osu.Framework.Localisation; +using osu.Game.Graphics.Sprites; +using osu.Game.Overlays; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Graphics.UserInterface +{ + public partial class RangeSlider : CompositeDrawable + { + /// + /// The lower limiting value + /// + public Bindable LowerBound + { + get => lowerBound.Current; + set => lowerBound.Current = value; + } + + /// + /// The upper limiting value + /// + public Bindable UpperBound + { + get => upperBound.Current; + set => upperBound.Current = value; + } + + /// + /// Text that describes this RangeSlider's functionality + /// + public string Label + { + set => label.Text = value; + } + + public float NubWidth + { + set => lowerBound.NubWidth = upperBound.NubWidth = value; + } + + /// + /// Minimum difference between the lower bound and higher bound + /// + public float MinRange + { + set => minRange = value; + } + + /// + /// lower bound display for when it is set to its default value + /// + public string DefaultStringLowerBound + { + set => lowerBound.DefaultString = value; + } + + /// + /// upper bound display for when it is set to its default value + /// + public string DefaultStringUpperBound + { + set => upperBound.DefaultString = value; + } + + public LocalisableString DefaultTooltipLowerBound + { + set => lowerBound.DefaultTooltip = value; + } + + public LocalisableString DefaultTooltipUpperBound + { + set => upperBound.DefaultTooltip = value; + } + + public string TooltipSuffix + { + set => upperBound.TooltipSuffix = lowerBound.TooltipSuffix = value; + } + + private float minRange = 0.1f; + + private readonly OsuSpriteText label; + + private readonly LowerBoundSlider lowerBound; + private readonly UpperBoundSlider upperBound; + + public RangeSlider() + { + const float vertical_offset = 13; + + InternalChildren = new Drawable[] + { + label = new OsuSpriteText + { + Font = OsuFont.GetFont(size: 14), + }, + upperBound = new UpperBoundSlider + { + KeyboardStep = 0.1f, + RelativeSizeAxes = Axes.X, + Y = vertical_offset, + }, + lowerBound = new LowerBoundSlider + { + KeyboardStep = 0.1f, + RelativeSizeAxes = Axes.X, + Y = vertical_offset, + } + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + lowerBound.Current.ValueChanged += min => upperBound.Current.Value = Math.Max(min.NewValue + minRange, upperBound.Current.Value); + upperBound.Current.ValueChanged += max => lowerBound.Current.Value = Math.Min(max.NewValue - minRange, lowerBound.Current.Value); + } + + private partial class LowerBoundSlider : BoundSlider + { + protected override void LoadComplete() + { + base.LoadComplete(); + + LeftBox.Height = 6; // hide any colour bleeding from overlap + + AccentColour = BackgroundColour; + BackgroundColour = Color4.Transparent; + } + + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => + base.ReceivePositionalInputAt(screenSpacePos) + && screenSpacePos.X <= Nub.ScreenSpaceDrawQuad.TopRight.X; + } + + private partial class UpperBoundSlider : BoundSlider + { + protected override void LoadComplete() + { + base.LoadComplete(); + + RightBox.Height = 6; // just to match the left bar height really + } + + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => + base.ReceivePositionalInputAt(screenSpacePos) + && screenSpacePos.X >= Nub.ScreenSpaceDrawQuad.TopLeft.X; + } + + protected partial class BoundSlider : OsuSliderBar + { + public string? DefaultString; + public LocalisableString? DefaultTooltip; + public string? TooltipSuffix; + public float NubWidth { get; set; } = Nub.HEIGHT; + + public override LocalisableString TooltipText => + (Current.IsDefault ? DefaultTooltip : Current.Value.ToString($@"0.## {TooltipSuffix}")) ?? Current.Value.ToString($@"0.## {TooltipSuffix}"); + + protected override bool OnHover(HoverEvent e) + { + base.OnHover(e); + return true; // Make sure only one nub shows hover effect at once. + } + + protected override void LoadComplete() + { + base.LoadComplete(); + Nub.Width = NubWidth; + RangePadding = Nub.Width / 2; + + OsuSpriteText currentDisplay; + + Nub.Add(currentDisplay = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Y = -0.5f, + Colour = Color4.White, + Font = OsuFont.Torus.With(size: 10), + }); + + Current.BindValueChanged(current => + { + currentDisplay.Text = (current.NewValue != Current.Default ? current.NewValue.ToString("N1") : DefaultString) ?? current.NewValue.ToString("N1"); + }, true); + } + + [BackgroundDependencyLoader(true)] + private void load(OverlayColourProvider? colourProvider) + { + if (colourProvider == null) return; + + AccentColour = colourProvider.Background2; + Nub.AccentColour = colourProvider.Background2; + Nub.GlowingAccentColour = colourProvider.Background1; + Nub.GlowColour = colourProvider.Background2; + } + } + } +} diff --git a/osu.Game/Graphics/UserInterface/RollingCounter.cs b/osu.Game/Graphics/UserInterface/RollingCounter.cs index 2f8c8414e2..b80c0e3b58 100644 --- a/osu.Game/Graphics/UserInterface/RollingCounter.cs +++ b/osu.Game/Graphics/UserInterface/RollingCounter.cs @@ -16,7 +16,7 @@ using osu.Framework.Localisation; namespace osu.Game.Graphics.UserInterface { - public abstract class RollingCounter : Container, IHasCurrentValue + public abstract partial class RollingCounter : Container, IHasCurrentValue where T : struct, IEquatable { private readonly BindableWithCurrent current = new BindableWithCurrent(); diff --git a/osu.Game/Graphics/UserInterface/ScoreCounter.cs b/osu.Game/Graphics/UserInterface/ScoreCounter.cs index 2efe27c842..255b2149f0 100644 --- a/osu.Game/Graphics/UserInterface/ScoreCounter.cs +++ b/osu.Game/Graphics/UserInterface/ScoreCounter.cs @@ -11,7 +11,7 @@ using osu.Game.Graphics.Sprites; namespace osu.Game.Graphics.UserInterface { - public abstract class ScoreCounter : RollingCounter + public abstract partial class ScoreCounter : RollingCounter { protected override double RollingDuration => 1000; protected override Easing RollingEasing => Easing.Out; diff --git a/osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs b/osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs index edd705ca00..65dce422d6 100644 --- a/osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs +++ b/osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs @@ -13,7 +13,7 @@ namespace osu.Game.Graphics.UserInterface /// /// A which follows the active screen (and allows navigation) in a stack. /// - public class ScreenBreadcrumbControl : BreadcrumbControl + public partial class ScreenBreadcrumbControl : BreadcrumbControl { public ScreenBreadcrumbControl(ScreenStack stack) { diff --git a/osu.Game/Graphics/UserInterface/SearchTextBox.cs b/osu.Game/Graphics/UserInterface/SearchTextBox.cs index 2c2597f149..2d09a239bb 100644 --- a/osu.Game/Graphics/UserInterface/SearchTextBox.cs +++ b/osu.Game/Graphics/UserInterface/SearchTextBox.cs @@ -10,7 +10,7 @@ using osuTK.Input; namespace osu.Game.Graphics.UserInterface { - public class SearchTextBox : FocusedTextBox + public partial class SearchTextBox : FocusedTextBox { protected virtual bool AllowCommit => false; diff --git a/osu.Game/Graphics/UserInterface/SeekLimitedSearchTextBox.cs b/osu.Game/Graphics/UserInterface/SeekLimitedSearchTextBox.cs index f64f455f6b..a85cd36808 100644 --- a/osu.Game/Graphics/UserInterface/SeekLimitedSearchTextBox.cs +++ b/osu.Game/Graphics/UserInterface/SeekLimitedSearchTextBox.cs @@ -8,7 +8,7 @@ namespace osu.Game.Graphics.UserInterface /// /// A which does not handle left/right arrow keys for seeking. /// - public class SeekLimitedSearchTextBox : BasicSearchTextBox + public partial class SeekLimitedSearchTextBox : BasicSearchTextBox { public override bool HandleLeftRightArrows => false; } diff --git a/osu.Game/Graphics/UserInterface/SegmentedGraph.cs b/osu.Game/Graphics/UserInterface/SegmentedGraph.cs new file mode 100644 index 0000000000..8ccba710b8 --- /dev/null +++ b/osu.Game/Graphics/UserInterface/SegmentedGraph.cs @@ -0,0 +1,337 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Primitives; +using osu.Framework.Graphics.Rendering; +using osu.Framework.Graphics.Shaders; +using osu.Framework.Graphics.Textures; +using osuTK; + +namespace osu.Game.Graphics.UserInterface +{ + public partial class SegmentedGraph : Drawable + where T : struct, IComparable, IConvertible, IEquatable + { + private bool graphNeedsUpdate; + + private T[]? values; + private int[] tiers = Array.Empty(); + private readonly SegmentManager segments; + + private int tierCount; + + public SegmentedGraph(int tierCount = 1) + { + this.tierCount = tierCount; + tierColours = new[] + { + new Colour4(0, 0, 0, 0) + }; + segments = new SegmentManager(tierCount); + } + + public T[] Values + { + get => values ?? Array.Empty(); + set + { + if (value == values) return; + + values = value; + graphNeedsUpdate = true; + } + } + + private Colour4[] tierColours; + + public Colour4[] TierColours + { + get => tierColours; + set + { + if (value.Length == 0 || value == tierColours) + return; + + tierCount = value.Length; + tierColours = value; + + graphNeedsUpdate = true; + } + } + + private Texture texture = null!; + private IShader shader = null!; + + [BackgroundDependencyLoader] + private void load(IRenderer renderer, ShaderManager shaders) + { + texture = renderer.WhitePixel; + shader = shaders.Load(VertexShaderDescriptor.TEXTURE_2, FragmentShaderDescriptor.TEXTURE); + } + + protected override void Update() + { + base.Update(); + + if (graphNeedsUpdate) + { + recalculateTiers(values); + recalculateSegments(); + Invalidate(Invalidation.DrawNode); + graphNeedsUpdate = false; + } + } + + private void recalculateTiers(T[]? arr) + { + if (arr == null || arr.Length == 0) + { + tiers = Array.Empty(); + return; + } + + float[] floatValues = arr.Select(v => Convert.ToSingle(v)).ToArray(); + + // Shift values to eliminate negative ones + float min = floatValues.Min(); + + if (min < 0) + { + for (int i = 0; i < floatValues.Length; i++) + floatValues[i] += Math.Abs(min); + } + + // Normalize values + float max = floatValues.Max(); + + for (int i = 0; i < floatValues.Length; i++) + floatValues[i] /= max; + + // Deduce tiers from values + tiers = floatValues.Select(v => (int)Math.Floor(v * tierCount)).ToArray(); + } + + private void recalculateSegments() + { + segments.Clear(); + + if (tiers.Length == 0) + { + segments.Add(0, 0, 1); + return; + } + + for (int i = 0; i < tiers.Length; i++) + { + for (int tier = 0; tier < tierCount; tier++) + { + if (tier < 0) + continue; + + // One tier covers itself and all tiers above it. + // By layering multiple transparent boxes, higher tiers will be brighter. + // If using opaque colors, higher tiers will be on front, covering lower tiers. + if (tiers[i] >= tier) + { + if (!segments.IsTierStarted(tier)) + segments.StartSegment(tier, i * 1f / tiers.Length); + } + else + { + if (segments.IsTierStarted(tier)) + segments.EndSegment(tier, i * 1f / tiers.Length); + } + } + } + + segments.EndAllPendingSegments(); + segments.Sort(); + } + + private Colour4 getTierColour(int tier) => tier >= 0 ? tierColours[tier] : new Colour4(0, 0, 0, 0); + + protected override DrawNode CreateDrawNode() => new SegmentedGraphDrawNode(this); + + protected struct SegmentInfo + { + /// + /// The tier this segment is at. + /// + public int Tier; + + /// + /// The progress at which this segment starts. + /// + /// + /// The value is a normalized float (from 0 to 1). + /// + public float Start; + + /// + /// The progress at which this segment ends. + /// + /// + /// The value is a normalized float (from 0 to 1). + /// + public float End; + + /// + /// The length of this segment. + /// + /// + /// The value is a normalized float (from 0 to 1). + /// + public float Length => End - Start; + + public override string ToString() + { + return $"({Tier}, {Start * 100}%, {End * 100}%)"; + } + } + + private class SegmentedGraphDrawNode : DrawNode + { + public new SegmentedGraph Source => (SegmentedGraph)base.Source; + + private Texture texture = null!; + private IShader shader = null!; + private readonly List segments = new List(); + private Vector2 drawSize; + + public SegmentedGraphDrawNode(SegmentedGraph source) + : base(source) + { + } + + public override void ApplyState() + { + base.ApplyState(); + + texture = Source.texture; + shader = Source.shader; + drawSize = Source.DrawSize; + segments.Clear(); + segments.AddRange(Source.segments.Where(s => s.Length * drawSize.X > 1)); + } + + public override void Draw(IRenderer renderer) + { + base.Draw(renderer); + + shader.Bind(); + + foreach (SegmentInfo segment in segments) + { + Vector2 topLeft = new Vector2(segment.Start * drawSize.X, 0); + Vector2 topRight = new Vector2(segment.End * drawSize.X, 0); + Vector2 bottomLeft = new Vector2(segment.Start * drawSize.X, drawSize.Y); + Vector2 bottomRight = new Vector2(segment.End * drawSize.X, drawSize.Y); + + renderer.DrawQuad( + texture, + new Quad( + Vector2Extensions.Transform(topLeft, DrawInfo.Matrix), + Vector2Extensions.Transform(topRight, DrawInfo.Matrix), + Vector2Extensions.Transform(bottomLeft, DrawInfo.Matrix), + Vector2Extensions.Transform(bottomRight, DrawInfo.Matrix)), + Source.getTierColour(segment.Tier)); + } + + shader.Unbind(); + } + } + + protected class SegmentManager : IEnumerable + { + private readonly List segments = new List(); + + private readonly SegmentInfo?[] pendingSegments; + + public SegmentManager(int tierCount) + { + pendingSegments = new SegmentInfo?[tierCount]; + } + + public void StartSegment(int tier, float start) + { + if (pendingSegments[tier] != null) + throw new InvalidOperationException($"Another {nameof(SegmentInfo)} of tier {tier.ToString()} has already been started."); + + pendingSegments[tier] = new SegmentInfo + { + Tier = tier, + Start = Math.Clamp(start, 0, 1) + }; + } + + public void EndSegment(int tier, float end) + { + SegmentInfo? pendingSegment = pendingSegments[tier]; + if (pendingSegment == null) + throw new InvalidOperationException($"Cannot end {nameof(SegmentInfo)} of tier {tier.ToString()} that has not been started."); + + SegmentInfo segment = pendingSegment.Value; + segment.End = Math.Clamp(end, 0, 1); + segments.Add(segment); + pendingSegments[tier] = null; + } + + public void EndAllPendingSegments() + { + foreach (SegmentInfo? pendingSegment in pendingSegments) + { + if (pendingSegment == null) + continue; + + SegmentInfo finalizedSegment = pendingSegment.Value; + finalizedSegment.End = 1; + segments.Add(finalizedSegment); + } + } + + public void Sort() => + segments.Sort((a, b) => + a.Tier != b.Tier + ? a.Tier.CompareTo(b.Tier) + : a.Start.CompareTo(b.Start)); + + public void Add(SegmentInfo segment) => segments.Add(segment); + + public void Clear() + { + segments.Clear(); + + for (int i = 0; i < pendingSegments.Length; i++) + pendingSegments[i] = null; + } + + public int Count => segments.Count; + + public void Add(int tier, float start, float end) + { + SegmentInfo segment = new SegmentInfo + { + Tier = tier, + Start = Math.Clamp(start, 0, 1), + End = Math.Clamp(end, 0, 1) + }; + + if (segment.Start > segment.End) + throw new InvalidOperationException("Segment start cannot be after segment end."); + + Add(segment); + } + + public bool IsTierStarted(int tier) => tier >= 0 && pendingSegments[tier].HasValue; + + public IEnumerator GetEnumerator() => segments.GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + } + } +} diff --git a/osu.Game/Graphics/UserInterface/ShearedButton.cs b/osu.Game/Graphics/UserInterface/ShearedButton.cs index e406e273e6..f1afacb2f4 100644 --- a/osu.Game/Graphics/UserInterface/ShearedButton.cs +++ b/osu.Game/Graphics/UserInterface/ShearedButton.cs @@ -15,7 +15,7 @@ using osuTK; namespace osu.Game.Graphics.UserInterface { - public class ShearedButton : OsuClickableContainer + public partial class ShearedButton : OsuClickableContainer { public LocalisableString Text { diff --git a/osu.Game/Graphics/UserInterface/ShearedOverlayHeader.cs b/osu.Game/Graphics/UserInterface/ShearedOverlayHeader.cs index deb2374e88..99eb439f75 100644 --- a/osu.Game/Graphics/UserInterface/ShearedOverlayHeader.cs +++ b/osu.Game/Graphics/UserInterface/ShearedOverlayHeader.cs @@ -17,7 +17,7 @@ using osuTK; namespace osu.Game.Graphics.UserInterface { - public class ShearedOverlayHeader : CompositeDrawable + public partial class ShearedOverlayHeader : CompositeDrawable { public const float HEIGHT = main_area_height + 2 * corner_radius; diff --git a/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs b/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs index d7e027b3f9..7bd083f9d5 100644 --- a/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs +++ b/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs @@ -18,7 +18,7 @@ using osuTK; namespace osu.Game.Graphics.UserInterface { - public class ShearedSearchTextBox : CompositeDrawable, IHasCurrentValue + public partial class ShearedSearchTextBox : CompositeDrawable, IHasCurrentValue { private const float corner_radius = 7; @@ -95,7 +95,7 @@ namespace osu.Game.Graphics.UserInterface public override bool HandleNonPositionalInput => textBox.HandleNonPositionalInput; - private class InnerSearchTextBox : SearchTextBox + private partial class InnerSearchTextBox : SearchTextBox { [BackgroundDependencyLoader] private void load(OverlayColourProvider colourProvider) @@ -112,7 +112,7 @@ namespace osu.Game.Graphics.UserInterface protected override SpriteText CreatePlaceholder() => new SearchPlaceholder(); - internal class SearchPlaceholder : SpriteText + internal partial class SearchPlaceholder : SpriteText { public override void Show() { diff --git a/osu.Game/Graphics/UserInterface/ShearedToggleButton.cs b/osu.Game/Graphics/UserInterface/ShearedToggleButton.cs index 9ef09d799e..d5e0abe9d8 100644 --- a/osu.Game/Graphics/UserInterface/ShearedToggleButton.cs +++ b/osu.Game/Graphics/UserInterface/ShearedToggleButton.cs @@ -8,7 +8,7 @@ using osu.Framework.Bindables; namespace osu.Game.Graphics.UserInterface { - public class ShearedToggleButton : ShearedButton + public partial class ShearedToggleButton : ShearedButton { private Sample? sampleClick; private Sample? sampleOff; diff --git a/osu.Game/Graphics/UserInterface/ShowMoreButton.cs b/osu.Game/Graphics/UserInterface/ShowMoreButton.cs index ed64a31412..3afb7e701f 100644 --- a/osu.Game/Graphics/UserInterface/ShowMoreButton.cs +++ b/osu.Game/Graphics/UserInterface/ShowMoreButton.cs @@ -19,7 +19,7 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Graphics.UserInterface { - public class ShowMoreButton : LoadingButton + public partial class ShowMoreButton : LoadingButton { private const int duration = 200; @@ -115,7 +115,7 @@ namespace osu.Game.Graphics.UserInterface rightIcon.SetHoveredState(false); } - public class ChevronIcon : SpriteIcon + public partial class ChevronIcon : SpriteIcon { [Resolved] private OverlayColourProvider colourProvider { get; set; } diff --git a/osu.Game/Graphics/UserInterface/SlimEnumDropdown.cs b/osu.Game/Graphics/UserInterface/SlimEnumDropdown.cs index 534fcf76e5..e3f5bc65e6 100644 --- a/osu.Game/Graphics/UserInterface/SlimEnumDropdown.cs +++ b/osu.Game/Graphics/UserInterface/SlimEnumDropdown.cs @@ -9,12 +9,12 @@ using osu.Framework.Graphics.UserInterface; namespace osu.Game.Graphics.UserInterface { - public class SlimEnumDropdown : OsuEnumDropdown + public partial class SlimEnumDropdown : OsuEnumDropdown where T : struct, Enum { protected override DropdownHeader CreateHeader() => new SlimDropdownHeader(); - private class SlimDropdownHeader : OsuDropdownHeader + private partial class SlimDropdownHeader : OsuDropdownHeader { public SlimDropdownHeader() { diff --git a/osu.Game/Graphics/UserInterface/StarCounter.cs b/osu.Game/Graphics/UserInterface/StarCounter.cs index d9274bf2cb..d7d088d798 100644 --- a/osu.Game/Graphics/UserInterface/StarCounter.cs +++ b/osu.Game/Graphics/UserInterface/StarCounter.cs @@ -13,7 +13,7 @@ using osu.Framework.Graphics.Sprites; namespace osu.Game.Graphics.UserInterface { - public class StarCounter : Container + public partial class StarCounter : Container { private readonly FillFlowContainer stars; @@ -120,7 +120,7 @@ namespace osu.Game.Graphics.UserInterface } } - public class DefaultStar : Star + public partial class DefaultStar : Star { private const double scaling_duration = 1000; @@ -156,7 +156,7 @@ namespace osu.Game.Graphics.UserInterface } } - public abstract class Star : CompositeDrawable + public abstract partial class Star : CompositeDrawable { public abstract void DisplayAt(float scale); } diff --git a/osu.Game/Graphics/UserInterface/StatefulMenuItem.cs b/osu.Game/Graphics/UserInterface/StatefulMenuItem.cs index 17266e876c..85efd75a60 100644 --- a/osu.Game/Graphics/UserInterface/StatefulMenuItem.cs +++ b/osu.Game/Graphics/UserInterface/StatefulMenuItem.cs @@ -1,11 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using osu.Framework.Bindables; using osu.Framework.Graphics.Sprites; +using osu.Framework.Localisation; namespace osu.Game.Graphics.UserInterface { @@ -25,7 +24,7 @@ namespace osu.Game.Graphics.UserInterface /// The text to display. /// A function that mutates a state to another state after this is pressed. /// The type of action which this performs. - protected StatefulMenuItem(string text, Func changeStateFunc, MenuItemType type = MenuItemType.Standard) + protected StatefulMenuItem(LocalisableString text, Func changeStateFunc, MenuItemType type = MenuItemType.Standard) : this(text, changeStateFunc, type, null) { } @@ -37,7 +36,7 @@ namespace osu.Game.Graphics.UserInterface /// A function that mutates a state to another state after this is pressed. /// The type of action which this performs. /// A delegate to be invoked when this is pressed. - protected StatefulMenuItem(string text, Func changeStateFunc, MenuItemType type, Action action) + protected StatefulMenuItem(LocalisableString text, Func? changeStateFunc, MenuItemType type, Action? action) : base(text, type) { Action.Value = () => @@ -69,7 +68,7 @@ namespace osu.Game.Graphics.UserInterface /// The text to display. /// A function that mutates a state to another state after this is pressed. /// The type of action which this performs. - protected StatefulMenuItem(string text, Func changeStateFunc, MenuItemType type = MenuItemType.Standard) + protected StatefulMenuItem(LocalisableString text, Func? changeStateFunc, MenuItemType type = MenuItemType.Standard) : this(text, changeStateFunc, type, null) { } @@ -81,7 +80,7 @@ namespace osu.Game.Graphics.UserInterface /// A function that mutates a state to another state after this is pressed. /// The type of action which this performs. /// A delegate to be invoked when this is pressed. - protected StatefulMenuItem(string text, Func changeStateFunc, MenuItemType type, Action action) + protected StatefulMenuItem(LocalisableString text, Func? changeStateFunc, MenuItemType type, Action? action) : base(text, o => changeStateFunc?.Invoke((T)o) ?? o, type, o => action?.Invoke((T)o)) { base.State.BindValueChanged(state => diff --git a/osu.Game/Graphics/UserInterface/TimeSlider.cs b/osu.Game/Graphics/UserInterface/TimeSlider.cs index d45c6614aa..46f0821033 100644 --- a/osu.Game/Graphics/UserInterface/TimeSlider.cs +++ b/osu.Game/Graphics/UserInterface/TimeSlider.cs @@ -10,7 +10,7 @@ namespace osu.Game.Graphics.UserInterface /// /// A slider bar which displays a millisecond time value. /// - public class TimeSlider : OsuSliderBar + public partial class TimeSlider : OsuSliderBar { public override LocalisableString TooltipText => $"{Current.Value:N0} ms"; } diff --git a/osu.Game/Graphics/UserInterface/ToggleMenuItem.cs b/osu.Game/Graphics/UserInterface/ToggleMenuItem.cs index 6787e17113..51e1248bc1 100644 --- a/osu.Game/Graphics/UserInterface/ToggleMenuItem.cs +++ b/osu.Game/Graphics/UserInterface/ToggleMenuItem.cs @@ -1,10 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using osu.Framework.Graphics.Sprites; +using osu.Framework.Localisation; namespace osu.Game.Graphics.UserInterface { @@ -18,7 +17,7 @@ namespace osu.Game.Graphics.UserInterface /// /// The text to display. /// The type of action which this performs. - public ToggleMenuItem(string text, MenuItemType type = MenuItemType.Standard) + public ToggleMenuItem(LocalisableString text, MenuItemType type = MenuItemType.Standard) : this(text, type, null) { } @@ -29,7 +28,7 @@ namespace osu.Game.Graphics.UserInterface /// The text to display. /// The type of action which this performs. /// A delegate to be invoked when this is pressed. - public ToggleMenuItem(string text, MenuItemType type, Action action) + public ToggleMenuItem(LocalisableString text, MenuItemType type, Action? action) : base(text, value => !value, type, action) { } diff --git a/osu.Game/Graphics/UserInterface/TriangleButton.cs b/osu.Game/Graphics/UserInterface/TriangleButton.cs deleted file mode 100644 index 60d1824e5a..0000000000 --- a/osu.Game/Graphics/UserInterface/TriangleButton.cs +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -#nullable disable - -using System.Collections.Generic; -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Localisation; -using osu.Game.Graphics.Backgrounds; - -namespace osu.Game.Graphics.UserInterface -{ - /// - /// A button with moving triangles in the background. - /// - public class TriangleButton : OsuButton, IFilterable - { - protected Triangles Triangles { get; private set; } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - Add(Triangles = new Triangles - { - RelativeSizeAxes = Axes.Both, - ColourDark = colours.BlueDarker, - ColourLight = colours.Blue, - }); - } - - public virtual IEnumerable FilterTerms => new[] { Text }; - - public bool MatchingFilter - { - set => this.FadeTo(value ? 1 : 0); - } - - public bool FilteringActive { get; set; } - } -} diff --git a/osu.Game/Graphics/UserInterface/TwoLayerButton.cs b/osu.Game/Graphics/UserInterface/TwoLayerButton.cs index 1b8848f3d5..aa542b8f49 100644 --- a/osu.Game/Graphics/UserInterface/TwoLayerButton.cs +++ b/osu.Game/Graphics/UserInterface/TwoLayerButton.cs @@ -22,7 +22,7 @@ using osu.Game.Screens.Select; namespace osu.Game.Graphics.UserInterface { - public class TwoLayerButton : OsuClickableContainer + public partial class TwoLayerButton : OsuClickableContainer { private readonly BouncingIcon bouncingIcon; @@ -207,7 +207,7 @@ namespace osu.Game.Graphics.UserInterface return base.OnClick(e); } - private class BouncingIcon : BeatSyncedContainer + private partial class BouncingIcon : BeatSyncedContainer { private const double beat_in_time = 60; diff --git a/osu.Game/Graphics/UserInterfaceV2/ColourDisplay.cs b/osu.Game/Graphics/UserInterfaceV2/ColourDisplay.cs index 93852f19c4..9ddbf84c39 100644 --- a/osu.Game/Graphics/UserInterfaceV2/ColourDisplay.cs +++ b/osu.Game/Graphics/UserInterfaceV2/ColourDisplay.cs @@ -24,7 +24,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 /// /// A component which displays a colour along with related description text. /// - public class ColourDisplay : CompositeDrawable, IHasCurrentValue + public partial class ColourDisplay : CompositeDrawable, IHasCurrentValue { /// /// Invoked when the user has requested the colour corresponding to this @@ -86,7 +86,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 }; } - private class ColourCircle : OsuClickableContainer, IHasPopover, IHasContextMenu + private partial class ColourCircle : OsuClickableContainer, IHasPopover, IHasContextMenu { public Bindable Current { get; } = new Bindable(); diff --git a/osu.Game/Graphics/UserInterfaceV2/ColourPalette.cs b/osu.Game/Graphics/UserInterfaceV2/ColourPalette.cs index f61d6db8b1..f554887510 100644 --- a/osu.Game/Graphics/UserInterfaceV2/ColourPalette.cs +++ b/osu.Game/Graphics/UserInterfaceV2/ColourPalette.cs @@ -23,7 +23,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 /// /// A component which displays a collection of colours in individual s. /// - public class ColourPalette : CompositeDrawable + public partial class ColourPalette : CompositeDrawable { public BindableList Colours { get; } = new BindableList(); @@ -119,7 +119,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 } } - internal class AddColourButton : CompositeDrawable + internal partial class AddColourButton : CompositeDrawable { public Action Action { diff --git a/osu.Game/Graphics/UserInterfaceV2/LabelledColourPalette.cs b/osu.Game/Graphics/UserInterfaceV2/LabelledColourPalette.cs index b144f8f696..721d8990ba 100644 --- a/osu.Game/Graphics/UserInterfaceV2/LabelledColourPalette.cs +++ b/osu.Game/Graphics/UserInterfaceV2/LabelledColourPalette.cs @@ -9,7 +9,7 @@ using osu.Framework.Localisation; namespace osu.Game.Graphics.UserInterfaceV2 { - public class LabelledColourPalette : LabelledDrawable + public partial class LabelledColourPalette : LabelledDrawable { public LabelledColourPalette() : base(true) diff --git a/osu.Game/Graphics/UserInterfaceV2/LabelledComponent.cs b/osu.Game/Graphics/UserInterfaceV2/LabelledComponent.cs index 977ef5d7bc..8fd9a62ad7 100644 --- a/osu.Game/Graphics/UserInterfaceV2/LabelledComponent.cs +++ b/osu.Game/Graphics/UserInterfaceV2/LabelledComponent.cs @@ -9,7 +9,7 @@ using osu.Framework.Graphics.UserInterface; namespace osu.Game.Graphics.UserInterfaceV2 { - public abstract class LabelledComponent : LabelledDrawable, IHasCurrentValue + public abstract partial class LabelledComponent : LabelledDrawable, IHasCurrentValue where TDrawable : Drawable, IHasCurrentValue { protected LabelledComponent(bool padded) diff --git a/osu.Game/Graphics/UserInterfaceV2/LabelledDrawable.cs b/osu.Game/Graphics/UserInterfaceV2/LabelledDrawable.cs index 8c98a3e0a7..9b7087ce6d 100644 --- a/osu.Game/Graphics/UserInterfaceV2/LabelledDrawable.cs +++ b/osu.Game/Graphics/UserInterfaceV2/LabelledDrawable.cs @@ -13,7 +13,7 @@ using osuTK; namespace osu.Game.Graphics.UserInterfaceV2 { - public abstract class LabelledDrawable : CompositeDrawable + public abstract partial class LabelledDrawable : CompositeDrawable where T : Drawable { private float? fixedLabelWidth; diff --git a/osu.Game/Graphics/UserInterfaceV2/LabelledDropdown.cs b/osu.Game/Graphics/UserInterfaceV2/LabelledDropdown.cs index bfb009658d..0e2ea362da 100644 --- a/osu.Game/Graphics/UserInterfaceV2/LabelledDropdown.cs +++ b/osu.Game/Graphics/UserInterfaceV2/LabelledDropdown.cs @@ -9,7 +9,7 @@ using osu.Game.Graphics.UserInterface; namespace osu.Game.Graphics.UserInterfaceV2 { - public class LabelledDropdown : LabelledComponent, TItem> + public partial class LabelledDropdown : LabelledComponent, TItem> { public LabelledDropdown() : base(true) diff --git a/osu.Game/Graphics/UserInterfaceV2/LabelledEnumDropdown.cs b/osu.Game/Graphics/UserInterfaceV2/LabelledEnumDropdown.cs index 594f132154..3ca460be90 100644 --- a/osu.Game/Graphics/UserInterfaceV2/LabelledEnumDropdown.cs +++ b/osu.Game/Graphics/UserInterfaceV2/LabelledEnumDropdown.cs @@ -8,7 +8,7 @@ using osu.Game.Graphics.UserInterface; namespace osu.Game.Graphics.UserInterfaceV2 { - public class LabelledEnumDropdown : LabelledDropdown + public partial class LabelledEnumDropdown : LabelledDropdown where TEnum : struct, Enum { protected override OsuDropdown CreateDropdown() => new OsuEnumDropdown(); diff --git a/osu.Game/Graphics/UserInterfaceV2/LabelledNumberBox.cs b/osu.Game/Graphics/UserInterfaceV2/LabelledNumberBox.cs index cb032698ef..2643db0547 100644 --- a/osu.Game/Graphics/UserInterfaceV2/LabelledNumberBox.cs +++ b/osu.Game/Graphics/UserInterfaceV2/LabelledNumberBox.cs @@ -7,7 +7,7 @@ using osu.Game.Graphics.UserInterface; namespace osu.Game.Graphics.UserInterfaceV2 { - public class LabelledNumberBox : LabelledTextBox + public partial class LabelledNumberBox : LabelledTextBox { protected override OsuTextBox CreateTextBox() => new OsuNumberBox(); } diff --git a/osu.Game/Graphics/UserInterfaceV2/LabelledSliderBar.cs b/osu.Game/Graphics/UserInterfaceV2/LabelledSliderBar.cs index 50b6834f01..00f4ef1a30 100644 --- a/osu.Game/Graphics/UserInterfaceV2/LabelledSliderBar.cs +++ b/osu.Game/Graphics/UserInterfaceV2/LabelledSliderBar.cs @@ -9,7 +9,7 @@ using osu.Game.Overlays.Settings; namespace osu.Game.Graphics.UserInterfaceV2 { - public class LabelledSliderBar : LabelledComponent, TNumber> + public partial class LabelledSliderBar : LabelledComponent, TNumber> where TNumber : struct, IEquatable, IComparable, IConvertible { public LabelledSliderBar() diff --git a/osu.Game/Graphics/UserInterfaceV2/LabelledSwitchButton.cs b/osu.Game/Graphics/UserInterfaceV2/LabelledSwitchButton.cs index 99a1a98d5b..3c27829de3 100644 --- a/osu.Game/Graphics/UserInterfaceV2/LabelledSwitchButton.cs +++ b/osu.Game/Graphics/UserInterfaceV2/LabelledSwitchButton.cs @@ -5,7 +5,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 { - public class LabelledSwitchButton : LabelledComponent + public partial class LabelledSwitchButton : LabelledComponent { public LabelledSwitchButton() : base(true) diff --git a/osu.Game/Graphics/UserInterfaceV2/LabelledTextBox.cs b/osu.Game/Graphics/UserInterfaceV2/LabelledTextBox.cs index 97bc845766..454be02d0b 100644 --- a/osu.Game/Graphics/UserInterfaceV2/LabelledTextBox.cs +++ b/osu.Game/Graphics/UserInterfaceV2/LabelledTextBox.cs @@ -13,7 +13,7 @@ using osu.Game.Graphics.UserInterface; namespace osu.Game.Graphics.UserInterfaceV2 { - public class LabelledTextBox : LabelledComponent + public partial class LabelledTextBox : LabelledComponent { public event TextBox.OnCommitHandler OnCommit; diff --git a/osu.Game/Graphics/UserInterfaceV2/OsuColourPicker.cs b/osu.Game/Graphics/UserInterfaceV2/OsuColourPicker.cs index f4ae2f0fd7..fed17eaf20 100644 --- a/osu.Game/Graphics/UserInterfaceV2/OsuColourPicker.cs +++ b/osu.Game/Graphics/UserInterfaceV2/OsuColourPicker.cs @@ -7,7 +7,7 @@ using osu.Framework.Graphics.UserInterface; namespace osu.Game.Graphics.UserInterfaceV2 { - public class OsuColourPicker : ColourPicker + public partial class OsuColourPicker : ColourPicker { public OsuColourPicker() { diff --git a/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelector.cs b/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelector.cs index 0e348108aa..21f926ba42 100644 --- a/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelector.cs +++ b/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelector.cs @@ -12,7 +12,7 @@ using osu.Game.Graphics.Containers; namespace osu.Game.Graphics.UserInterfaceV2 { - public class OsuDirectorySelector : DirectorySelector + public partial class OsuDirectorySelector : DirectorySelector { public const float ITEM_HEIGHT = 20; diff --git a/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelectorBreadcrumbDisplay.cs b/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelectorBreadcrumbDisplay.cs index 08a569269e..0917b9db97 100644 --- a/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelectorBreadcrumbDisplay.cs +++ b/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelectorBreadcrumbDisplay.cs @@ -13,7 +13,7 @@ using osuTK; namespace osu.Game.Graphics.UserInterfaceV2 { - internal class OsuDirectorySelectorBreadcrumbDisplay : DirectorySelectorBreadcrumbDisplay + internal partial class OsuDirectorySelectorBreadcrumbDisplay : DirectorySelectorBreadcrumbDisplay { protected override Drawable CreateCaption() => new OsuSpriteText { @@ -30,7 +30,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 Padding = new MarginPadding(15); } - private class OsuBreadcrumbDisplayComputer : OsuBreadcrumbDisplayDirectory + private partial class OsuBreadcrumbDisplayComputer : OsuBreadcrumbDisplayDirectory { protected override IconUsage? Icon => null; @@ -40,7 +40,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 } } - private class OsuBreadcrumbDisplayDirectory : OsuDirectorySelectorDirectory + private partial class OsuBreadcrumbDisplayDirectory : OsuDirectorySelectorDirectory { public OsuBreadcrumbDisplayDirectory(DirectoryInfo directory, string displayName = null) : base(directory, displayName) diff --git a/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelectorDirectory.cs b/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelectorDirectory.cs index 1896d7ee4d..932017b03e 100644 --- a/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelectorDirectory.cs +++ b/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelectorDirectory.cs @@ -16,7 +16,7 @@ using osu.Game.Overlays; namespace osu.Game.Graphics.UserInterfaceV2 { - internal class OsuDirectorySelectorDirectory : DirectorySelectorDirectory + internal partial class OsuDirectorySelectorDirectory : DirectorySelectorDirectory { public OsuDirectorySelectorDirectory(DirectoryInfo directory, string displayName = null) : base(directory, displayName) @@ -45,7 +45,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 ? FontAwesome.Solid.Database : FontAwesome.Regular.Folder; - internal class Background : CompositeDrawable + internal partial class Background : CompositeDrawable { [BackgroundDependencyLoader(true)] private void load(OverlayColourProvider overlayColourProvider, OsuColour colours) diff --git a/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelectorHiddenToggle.cs b/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelectorHiddenToggle.cs index 7aaf12ca34..7665ed507f 100644 --- a/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelectorHiddenToggle.cs +++ b/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelectorHiddenToggle.cs @@ -10,7 +10,7 @@ using osuTK.Graphics; namespace osu.Game.Graphics.UserInterfaceV2 { - internal class OsuDirectorySelectorHiddenToggle : OsuCheckbox + internal partial class OsuDirectorySelectorHiddenToggle : OsuCheckbox { public OsuDirectorySelectorHiddenToggle() { diff --git a/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelectorParentDirectory.cs b/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelectorParentDirectory.cs index 7d2b28e803..beaeb86243 100644 --- a/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelectorParentDirectory.cs +++ b/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelectorParentDirectory.cs @@ -8,7 +8,7 @@ using osu.Framework.Graphics.Sprites; namespace osu.Game.Graphics.UserInterfaceV2 { - internal class OsuDirectorySelectorParentDirectory : OsuDirectorySelectorDirectory + internal partial class OsuDirectorySelectorParentDirectory : OsuDirectorySelectorDirectory { protected override IconUsage? Icon => FontAwesome.Solid.Folder; diff --git a/osu.Game/Graphics/UserInterfaceV2/OsuFileSelector.cs b/osu.Game/Graphics/UserInterfaceV2/OsuFileSelector.cs index 70af68d595..37e15c6127 100644 --- a/osu.Game/Graphics/UserInterfaceV2/OsuFileSelector.cs +++ b/osu.Game/Graphics/UserInterfaceV2/OsuFileSelector.cs @@ -16,7 +16,7 @@ using osu.Game.Graphics.UserInterface; namespace osu.Game.Graphics.UserInterfaceV2 { - public class OsuFileSelector : FileSelector + public partial class OsuFileSelector : FileSelector { public OsuFileSelector(string initialPath = null, string[] validFileExtensions = null) : base(initialPath, validFileExtensions) @@ -43,7 +43,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 protected override void NotifySelectionError() => this.FlashColour(Colour4.Red, 300); - protected class OsuDirectoryListingFile : DirectoryListingFile + protected partial class OsuDirectoryListingFile : DirectoryListingFile { public OsuDirectoryListingFile(FileInfo file) : base(file) diff --git a/osu.Game/Graphics/UserInterfaceV2/OsuHSVColourPicker.cs b/osu.Game/Graphics/UserInterfaceV2/OsuHSVColourPicker.cs index 1a8fa435cb..ff51f3aa92 100644 --- a/osu.Game/Graphics/UserInterfaceV2/OsuHSVColourPicker.cs +++ b/osu.Game/Graphics/UserInterfaceV2/OsuHSVColourPicker.cs @@ -16,7 +16,7 @@ using osuTK; namespace osu.Game.Graphics.UserInterfaceV2 { - public class OsuHSVColourPicker : HSVColourPicker + public partial class OsuHSVColourPicker : HSVColourPicker { private const float spacing = 10; private const float corner_radius = 10; @@ -42,7 +42,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 Colour = Colour4.Black.Opacity(0.3f) }; - private class OsuHueSelector : HueSelector + private partial class OsuHueSelector : HueSelector { public OsuHueSelector() { @@ -52,7 +52,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 protected override Drawable CreateSliderNub() => new SliderNub(this); - private class SliderNub : CompositeDrawable + private partial class SliderNub : CompositeDrawable { private readonly Bindable hue; private readonly Box fill; @@ -85,7 +85,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 } } - private class OsuSaturationValueSelector : SaturationValueSelector + private partial class OsuSaturationValueSelector : SaturationValueSelector { public OsuSaturationValueSelector() { @@ -95,7 +95,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 protected override Marker CreateMarker() => new OsuMarker(); - private class OsuMarker : Marker + private partial class OsuMarker : Marker { private readonly Box previewBox; diff --git a/osu.Game/Graphics/UserInterfaceV2/OsuHexColourPicker.cs b/osu.Game/Graphics/UserInterfaceV2/OsuHexColourPicker.cs index 12313791f0..9aa650d88d 100644 --- a/osu.Game/Graphics/UserInterfaceV2/OsuHexColourPicker.cs +++ b/osu.Game/Graphics/UserInterfaceV2/OsuHexColourPicker.cs @@ -14,7 +14,7 @@ using osu.Game.Overlays; namespace osu.Game.Graphics.UserInterfaceV2 { - public class OsuHexColourPicker : HexColourPicker + public partial class OsuHexColourPicker : HexColourPicker { public OsuHexColourPicker() { @@ -31,7 +31,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 protected override TextBox CreateHexCodeTextBox() => new OsuTextBox(); protected override ColourPreview CreateColourPreview() => new OsuColourPreview(); - private class OsuColourPreview : ColourPreview + private partial class OsuColourPreview : ColourPreview { private readonly Box preview; diff --git a/osu.Game/Graphics/UserInterfaceV2/OsuPopover.cs b/osu.Game/Graphics/UserInterfaceV2/OsuPopover.cs index e468e14f45..e66e48373c 100644 --- a/osu.Game/Graphics/UserInterfaceV2/OsuPopover.cs +++ b/osu.Game/Graphics/UserInterfaceV2/OsuPopover.cs @@ -17,7 +17,7 @@ using osuTK; namespace osu.Game.Graphics.UserInterfaceV2 { - public class OsuPopover : Popover, IKeyBindingHandler + public partial class OsuPopover : Popover, IKeyBindingHandler { private const float fade_duration = 250; private const double scale_duration = 500; diff --git a/osu.Game/Graphics/UserInterfaceV2/RoundedButton.cs b/osu.Game/Graphics/UserInterfaceV2/RoundedButton.cs index 4477633da1..6aded3fe32 100644 --- a/osu.Game/Graphics/UserInterfaceV2/RoundedButton.cs +++ b/osu.Game/Graphics/UserInterfaceV2/RoundedButton.cs @@ -1,19 +1,30 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Collections.Generic; +using System.Diagnostics; using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; +using osu.Framework.Input.Events; using osu.Framework.Localisation; +using osu.Game.Graphics.Backgrounds; using osu.Game.Graphics.UserInterface; +using osu.Game.Overlays; +using osuTK.Graphics; namespace osu.Game.Graphics.UserInterfaceV2 { - public class RoundedButton : OsuButton, IFilterable + public partial class RoundedButton : OsuButton, IFilterable { + protected TrianglesV2? Triangles { get; private set; } + + protected override float HoverLayerFinalAlpha => 0; + + private Color4? triangleGradientSecondColour; + public override float Height { get => base.Height; @@ -26,19 +37,64 @@ namespace osu.Game.Graphics.UserInterfaceV2 } } - [BackgroundDependencyLoader(true)] - private void load(OsuColour colours) + public override Color4 BackgroundColour { - // According to flyte, buttons are supposed to have explicit colours for now. - // Not sure this is the correct direction, but we haven't decided on an `OverlayColourProvider` stand-in yet. - // This is a better default. See `SettingsButton` for an override which uses `OverlayColourProvider`. - DefaultBackgroundColour = colours.Blue3; + get => base.BackgroundColour; + set + { + base.BackgroundColour = value; + triangleGradientSecondColour = BackgroundColour.Lighten(0.2f); + updateColours(); + } + } + + [BackgroundDependencyLoader(true)] + private void load(OverlayColourProvider? overlayColourProvider, OsuColour colours) + { + // Many buttons have local colours, but this provides a sane default for all other cases. + DefaultBackgroundColour = overlayColourProvider?.Colour3 ?? colours.Blue3; + triangleGradientSecondColour ??= overlayColourProvider?.Colour1 ?? colours.Blue3.Lighten(0.2f); } protected override void LoadComplete() { base.LoadComplete(); + updateCornerRadius(); + + Add(Triangles = new TrianglesV2 + { + Thickness = 0.02f, + SpawnRatio = 0.6f, + RelativeSizeAxes = Axes.Both, + Depth = float.MaxValue, + }); + + updateColours(); + } + + private void updateColours() + { + if (Triangles == null) + return; + + Debug.Assert(triangleGradientSecondColour != null); + + Triangles.Colour = ColourInfo.GradientVertical(triangleGradientSecondColour.Value, BackgroundColour); + } + + protected override bool OnHover(HoverEvent e) + { + Debug.Assert(triangleGradientSecondColour != null); + + Background.FadeColour(triangleGradientSecondColour.Value, 300, Easing.OutQuint); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + Background.FadeColour(BackgroundColour, 300, Easing.OutQuint); + base.OnHoverLost(e); } private void updateCornerRadius() => Content.CornerRadius = DrawHeight / 2; diff --git a/osu.Game/Graphics/UserInterfaceV2/SwitchButton.cs b/osu.Game/Graphics/UserInterfaceV2/SwitchButton.cs index b5c1c0a854..cf569a73ca 100644 --- a/osu.Game/Graphics/UserInterfaceV2/SwitchButton.cs +++ b/osu.Game/Graphics/UserInterfaceV2/SwitchButton.cs @@ -18,7 +18,7 @@ using osuTK.Graphics; namespace osu.Game.Graphics.UserInterfaceV2 { - public class SwitchButton : Checkbox + public partial class SwitchButton : Checkbox { private const float border_thickness = 4.5f; private const float padding = 1.25f; @@ -128,7 +128,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 circularContainer.TransformBorderTo((Current.Value ? enabledColour : disabledColour).Lighten(IsHovered ? 0.3f : 0)); } - private class CircularBorderContainer : CircularContainer + private partial class CircularBorderContainer : CircularContainer { public void TransformBorderTo(ColourInfo colour) => this.TransformTo(nameof(BorderColour), colour, 250, Easing.OutQuint); diff --git a/osu.Game/IO/FileAbstraction/StreamFileAbstraction.cs b/osu.Game/IO/FileAbstraction/StreamFileAbstraction.cs index 8e6c3e5f3d..d47f936eb3 100644 --- a/osu.Game/IO/FileAbstraction/StreamFileAbstraction.cs +++ b/osu.Game/IO/FileAbstraction/StreamFileAbstraction.cs @@ -23,8 +23,7 @@ namespace osu.Game.IO.FileAbstraction public void CloseStream(Stream stream) { - if (stream == null) - throw new ArgumentNullException(nameof(stream)); + ArgumentNullException.ThrowIfNull(stream); stream.Close(); } diff --git a/osu.Game/IO/HardLinkHelper.cs b/osu.Game/IO/HardLinkHelper.cs new file mode 100644 index 0000000000..619bfdad6e --- /dev/null +++ b/osu.Game/IO/HardLinkHelper.cs @@ -0,0 +1,190 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.IO; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.ComTypes; +using Microsoft.Win32.SafeHandles; +using osu.Framework; + +namespace osu.Game.IO +{ + internal static class HardLinkHelper + { + public static bool CheckAvailability(string testDestinationPath, string testSourcePath) + { + // For simplicity, only support desktop operating systems for now. + if (!RuntimeInfo.IsDesktop) + return false; + + const string test_filename = "_hard_link_test"; + + testDestinationPath = Path.Combine(testDestinationPath, test_filename); + testSourcePath = Path.Combine(testSourcePath, test_filename); + + cleanupFiles(); + + try + { + File.WriteAllText(testSourcePath, string.Empty); + + // Test availability by creating an arbitrary hard link between the source and destination paths. + return TryCreateHardLink(testDestinationPath, testSourcePath); + } + catch + { + return false; + } + finally + { + cleanupFiles(); + } + + void cleanupFiles() + { + try + { + File.Delete(testDestinationPath); + File.Delete(testSourcePath); + } + catch + { + } + } + } + + /// + /// Attempts to create a hard link from to , + /// using platform-specific native methods. + /// + /// + /// Hard links are only available on desktop platforms. + /// + /// Whether the hard link was successfully created. + public static bool TryCreateHardLink(string destinationPath, string sourcePath) + { + switch (RuntimeInfo.OS) + { + case RuntimeInfo.Platform.Windows: + return CreateHardLink(destinationPath, sourcePath, IntPtr.Zero); + + case RuntimeInfo.Platform.Linux: + case RuntimeInfo.Platform.macOS: + return link(sourcePath, destinationPath) == 0; + + default: + return false; + } + } + + // For future use (to detect if a file is a hard link with other references existing on disk). + public static int GetFileLinkCount(string filePath) + { + int result = 0; + + switch (RuntimeInfo.OS) + { + case RuntimeInfo.Platform.Windows: + SafeFileHandle handle = CreateFile(filePath, FileAccess.Read, FileShare.Read, IntPtr.Zero, FileMode.Open, FileAttributes.Archive, IntPtr.Zero); + + ByHandleFileInformation fileInfo; + + if (GetFileInformationByHandle(handle, out fileInfo)) + result = (int)fileInfo.NumberOfLinks; + CloseHandle(handle); + break; + + case RuntimeInfo.Platform.Linux: + case RuntimeInfo.Platform.macOS: + if (stat(filePath, out var statbuf) == 0) + result = (int)statbuf.st_nlink; + + break; + } + + return result; + } + + #region Windows native methods + + [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] + public static extern bool CreateHardLink(string lpFileName, string lpExistingFileName, IntPtr lpSecurityAttributes); + + [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] + private static extern SafeFileHandle CreateFile( + string lpFileName, + [MarshalAs(UnmanagedType.U4)] FileAccess dwDesiredAccess, + [MarshalAs(UnmanagedType.U4)] FileShare dwShareMode, + IntPtr lpSecurityAttributes, + [MarshalAs(UnmanagedType.U4)] FileMode dwCreationDisposition, + [MarshalAs(UnmanagedType.U4)] FileAttributes dwFlagsAndAttributes, + IntPtr hTemplateFile); + + [DllImport("kernel32.dll", SetLastError = true)] + private static extern bool GetFileInformationByHandle(SafeFileHandle handle, out ByHandleFileInformation lpFileInformation); + + [DllImport("kernel32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool CloseHandle(SafeHandle hObject); + + [StructLayout(LayoutKind.Sequential)] + private struct ByHandleFileInformation + { + public readonly uint FileAttributes; + public readonly FILETIME CreationTime; + public readonly FILETIME LastAccessTime; + public readonly FILETIME LastWriteTime; + public readonly uint VolumeSerialNumber; + public readonly uint FileSizeHigh; + public readonly uint FileSizeLow; + public readonly uint NumberOfLinks; + public readonly uint FileIndexHigh; + public readonly uint FileIndexLow; + } + + #endregion + + #region Linux native methods + +#pragma warning disable IDE1006 // Naming rule violation + + [DllImport("libc", SetLastError = true)] + public static extern int link(string oldpath, string newpath); + + [DllImport("libc", SetLastError = true)] + private static extern int stat(string pathname, out struct_stat statbuf); + + // ReSharper disable once InconsistentNaming + // Struct layout is likely non-portable across unices. Tread with caution. + [StructLayout(LayoutKind.Sequential)] + private struct struct_stat + { + public readonly long st_dev; + public readonly long st_ino; + public readonly long st_nlink; + public readonly int st_mode; + public readonly int st_uid; + public readonly int st_gid; + public readonly long st_rdev; + public readonly long st_size; + public readonly long st_blksize; + public readonly long st_blocks; + public readonly timespec st_atim; + public readonly timespec st_mtim; + public readonly timespec st_ctim; + } + + // ReSharper disable once InconsistentNaming + [StructLayout(LayoutKind.Sequential)] + private struct timespec + { + public readonly long tv_sec; + public readonly long tv_nsec; + } + +#pragma warning restore IDE1006 + + #endregion + } +} diff --git a/osu.Game/IO/Serialization/Converters/TypedListConverter.cs b/osu.Game/IO/Serialization/Converters/TypedListConverter.cs index 176e4e240d..de25d3e30e 100644 --- a/osu.Game/IO/Serialization/Converters/TypedListConverter.cs +++ b/osu.Game/IO/Serialization/Converters/TypedListConverter.cs @@ -63,7 +63,7 @@ namespace osu.Game.IO.Serialization.Converters throw new JsonException("Expected $type token."); string typeName = lookupTable[(int)tok["$type"]]; - var instance = (T)Activator.CreateInstance(Type.GetType(typeName).AsNonNull()); + var instance = (T)Activator.CreateInstance(Type.GetType(typeName).AsNonNull())!; serializer.Populate(itemReader, instance); list.Add(instance); diff --git a/osu.Game/Input/Bindings/DatabasedKeyBindingContainer.cs b/osu.Game/Input/Bindings/DatabasedKeyBindingContainer.cs index 4f079ab435..fab0be6cf0 100644 --- a/osu.Game/Input/Bindings/DatabasedKeyBindingContainer.cs +++ b/osu.Game/Input/Bindings/DatabasedKeyBindingContainer.cs @@ -18,7 +18,7 @@ namespace osu.Game.Input.Bindings /// A KeyBindingInputManager with a database backing for custom overrides. /// /// The type of the custom action. - public class DatabasedKeyBindingContainer : KeyBindingContainer + public partial class DatabasedKeyBindingContainer : KeyBindingContainer where T : struct { private readonly RulesetInfo ruleset; diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs index ebdc446ec8..07cef50dec 100644 --- a/osu.Game/Input/Bindings/GlobalActionContainer.cs +++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs @@ -11,7 +11,7 @@ using osu.Game.Localisation; namespace osu.Game.Input.Bindings { - public class GlobalActionContainer : DatabasedKeyBindingContainer, IHandleGlobalKeyboardInput + public partial class GlobalActionContainer : DatabasedKeyBindingContainer, IHandleGlobalKeyboardInput { private readonly Drawable? handler; diff --git a/osu.Game/Input/ConfineMouseTracker.cs b/osu.Game/Input/ConfineMouseTracker.cs index 7e8ace5693..de8660dbce 100644 --- a/osu.Game/Input/ConfineMouseTracker.cs +++ b/osu.Game/Input/ConfineMouseTracker.cs @@ -18,7 +18,7 @@ namespace osu.Game.Input /// If is true, we should also confine the mouse cursor if it has been /// requested with . /// - public class ConfineMouseTracker : Component + public partial class ConfineMouseTracker : Component { private Bindable frameworkConfineMode; private Bindable frameworkWindowMode; diff --git a/osu.Game/Input/GameIdleTracker.cs b/osu.Game/Input/GameIdleTracker.cs index d82cc25851..560ec1bc1e 100644 --- a/osu.Game/Input/GameIdleTracker.cs +++ b/osu.Game/Input/GameIdleTracker.cs @@ -7,7 +7,7 @@ using osu.Framework.Input; namespace osu.Game.Input { - public class GameIdleTracker : IdleTracker + public partial class GameIdleTracker : IdleTracker { private InputManager inputManager; diff --git a/osu.Game/Input/IdleTracker.cs b/osu.Game/Input/IdleTracker.cs index 45036b3e41..54157c9e3d 100644 --- a/osu.Game/Input/IdleTracker.cs +++ b/osu.Game/Input/IdleTracker.cs @@ -17,7 +17,7 @@ namespace osu.Game.Input /// /// Track whether the end-user is in an idle state, based on their last interaction with the game. /// - public class IdleTracker : Component, IKeyBindingHandler, IKeyBindingHandler, IHandleGlobalKeyboardInput + public partial class IdleTracker : Component, IKeyBindingHandler, IKeyBindingHandler, IHandleGlobalKeyboardInput { private readonly double timeToIdle; diff --git a/osu.Game/Input/OsuUserInputManager.cs b/osu.Game/Input/OsuUserInputManager.cs index 7a9002a004..ab43497156 100644 --- a/osu.Game/Input/OsuUserInputManager.cs +++ b/osu.Game/Input/OsuUserInputManager.cs @@ -8,7 +8,7 @@ using osuTK.Input; namespace osu.Game.Input { - public class OsuUserInputManager : UserInputManager + public partial class OsuUserInputManager : UserInputManager { internal OsuUserInputManager() { diff --git a/osu.Game/Localisation/BeatmapOverlayStrings.cs b/osu.Game/Localisation/BeatmapOverlayStrings.cs new file mode 100644 index 0000000000..fc818f7596 --- /dev/null +++ b/osu.Game/Localisation/BeatmapOverlayStrings.cs @@ -0,0 +1,33 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Localisation; + +namespace osu.Game.Localisation +{ + public static class BeatmapOverlayStrings + { + private const string prefix = @"osu.Game.Resources.Localisation.BeatmapOverlayStrings"; + + /// + /// "User content disclaimer" + /// + public static LocalisableString UserContentDisclaimerHeader => new TranslatableString(getKey(@"user_content_disclaimer"), @"User content disclaimer"); + + /// + /// "By turning off the "Featured Artist" filter, all user-uploaded content will be displayed. + /// + /// This includes content that may not be correctly licensed for osu! usage. Browse at your own risk." + /// + public static LocalisableString UserContentDisclaimerDescription => new TranslatableString(getKey(@"by_turning_off_the_featured"), @"By turning off the ""Featured Artist"" filter, all user-uploaded content will be displayed. + +This includes content that may not be correctly licensed for osu! usage. Browse at your own risk."); + + /// + /// "I understand" + /// + public static LocalisableString UserContentConfirmButtonText => new TranslatableString(getKey(@"understood"), @"I understand"); + + private static string getKey(string key) => $@"{prefix}:{key}"; + } +} diff --git a/osu.Game/Localisation/CommonStrings.cs b/osu.Game/Localisation/CommonStrings.cs index 385ebd0593..fed7b6cab7 100644 --- a/osu.Game/Localisation/CommonStrings.cs +++ b/osu.Game/Localisation/CommonStrings.cs @@ -104,6 +104,61 @@ namespace osu.Game.Localisation /// public static LocalisableString Description => new TranslatableString(getKey(@"description"), @"Description"); + /// + /// "File" + /// + public static LocalisableString MenuBarFile => new TranslatableString(getKey(@"menu_bar_file"), @"File"); + + /// + /// "Edit" + /// + public static LocalisableString MenuBarEdit => new TranslatableString(getKey(@"menu_bar_edit"), @"Edit"); + + /// + /// "View" + /// + public static LocalisableString MenuBarView => new TranslatableString(getKey(@"menu_bar_view"), @"View"); + + /// + /// "Undo" + /// + public static LocalisableString Undo => new TranslatableString(getKey(@"undo"), @"Undo"); + + /// + /// "Redo" + /// + public static LocalisableString Redo => new TranslatableString(getKey(@"redo"), @"Redo"); + + /// + /// "Cut" + /// + public static LocalisableString Cut => new TranslatableString(getKey(@"cut"), @"Cut"); + + /// + /// "Copy" + /// + public static LocalisableString Copy => new TranslatableString(getKey(@"copy"), @"Copy"); + + /// + /// "Paste" + /// + public static LocalisableString Paste => new TranslatableString(getKey(@"paste"), @"Paste"); + + /// + /// "Clone" + /// + public static LocalisableString Clone => new TranslatableString(getKey(@"clone"), @"Clone"); + + /// + /// "Exit" + /// + public static LocalisableString Exit => new TranslatableString(getKey(@"exit"), @"Exit"); + + /// + /// "Revert to default" + /// + public static LocalisableString RevertToDefault => new TranslatableString(getKey(@"revert_to_default"), @"Revert to default"); + private static string getKey(string key) => $@"{prefix}:{key}"; } } diff --git a/osu.Game/Localisation/ContextMenuStrings.cs b/osu.Game/Localisation/ContextMenuStrings.cs new file mode 100644 index 0000000000..8bc213016b --- /dev/null +++ b/osu.Game/Localisation/ContextMenuStrings.cs @@ -0,0 +1,24 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Localisation; + +namespace osu.Game.Localisation +{ + public static class ContextMenuStrings + { + private const string prefix = @"osu.Game.Resources.Localisation.ContextMenu"; + + /// + /// "View profile" + /// + public static LocalisableString ViewProfile => new TranslatableString(getKey(@"view_profile"), @"View profile"); + + /// + /// "View beatmap" + /// + public static LocalisableString ViewBeatmap => new TranslatableString(getKey(@"view_beatmap"), @"View beatmap"); + + private static string getKey(string key) => $@"{prefix}:{key}"; + } +} diff --git a/osu.Game/Localisation/EditorDialogsStrings.cs b/osu.Game/Localisation/EditorDialogsStrings.cs new file mode 100644 index 0000000000..fc4c2b7f2a --- /dev/null +++ b/osu.Game/Localisation/EditorDialogsStrings.cs @@ -0,0 +1,54 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Localisation; + +namespace osu.Game.Localisation +{ + public static class EditorDialogsStrings + { + private const string prefix = @"osu.Game.Resources.Localisation.EditorDialogs"; + + /// + /// "Would you like to create a blank difficulty?" + /// + public static LocalisableString NewDifficultyDialogHeader => new TranslatableString(getKey(@"new_difficulty_dialog_header"), @"Would you like to create a blank difficulty?"); + + /// + /// "Yeah, let's start from scratch!" + /// + public static LocalisableString CreateNew => new TranslatableString(getKey(@"create_new"), @"Yeah, let's start from scratch!"); + + /// + /// "No, create an exact copy of this difficulty" + /// + public static LocalisableString CreateCopy => new TranslatableString(getKey(@"create_copy"), @"No, create an exact copy of this difficulty"); + + /// + /// "I changed my mind, I want to keep editing this difficulty" + /// + public static LocalisableString KeepEditing => new TranslatableString(getKey(@"keep_editing"), @"I changed my mind, I want to keep editing this difficulty"); + + /// + /// "Did you want to save your changes?" + /// + public static LocalisableString SaveDialogHeader => new TranslatableString(getKey(@"save_dialog_header"), @"Did you want to save your changes?"); + + /// + /// "Save my masterpiece!" + /// + public static LocalisableString Save => new TranslatableString(getKey(@"save"), @"Save my masterpiece!"); + + /// + /// "Forget all changes" + /// + public static LocalisableString ForgetAllChanges => new TranslatableString(getKey(@"forget_all_changes"), @"Forget all changes"); + + /// + /// "Oops, continue editing" + /// + public static LocalisableString ContinueEditing => new TranslatableString(getKey(@"continue_editing"), @"Oops, continue editing"); + + private static string getKey(string key) => $@"{prefix}:{key}"; + } +} diff --git a/osu.Game/Localisation/EditorSetupStrings.cs b/osu.Game/Localisation/EditorSetupStrings.cs index 0431b9cf76..4ddacf2c5b 100644 --- a/osu.Game/Localisation/EditorSetupStrings.cs +++ b/osu.Game/Localisation/EditorSetupStrings.cs @@ -42,7 +42,8 @@ namespace osu.Game.Localisation /// /// "If enabled, an "Are you ready? 3, 2, 1, GO!" countdown will be inserted at the beginning of the beatmap, assuming there is enough time to do so." /// - public static LocalisableString CountdownDescription => new TranslatableString(getKey(@"countdown_description"), @"If enabled, an ""Are you ready? 3, 2, 1, GO!"" countdown will be inserted at the beginning of the beatmap, assuming there is enough time to do so."); + public static LocalisableString CountdownDescription => new TranslatableString(getKey(@"countdown_description"), + @"If enabled, an ""Are you ready? 3, 2, 1, GO!"" countdown will be inserted at the beginning of the beatmap, assuming there is enough time to do so."); /// /// "Countdown speed" @@ -52,7 +53,8 @@ namespace osu.Game.Localisation /// /// "If the countdown sounds off-time, use this to make it appear one or more beats early." /// - public static LocalisableString CountdownOffsetDescription => new TranslatableString(getKey(@"countdown_offset_description"), @"If the countdown sounds off-time, use this to make it appear one or more beats early."); + public static LocalisableString CountdownOffsetDescription => + new TranslatableString(getKey(@"countdown_offset_description"), @"If the countdown sounds off-time, use this to make it appear one or more beats early."); /// /// "Countdown offset" @@ -67,7 +69,8 @@ namespace osu.Game.Localisation /// /// "Allows storyboards to use the full screen space, rather than be confined to a 4:3 area." /// - public static LocalisableString WidescreenSupportDescription => new TranslatableString(getKey(@"widescreen_support_description"), @"Allows storyboards to use the full screen space, rather than be confined to a 4:3 area."); + public static LocalisableString WidescreenSupportDescription => + new TranslatableString(getKey(@"widescreen_support_description"), @"Allows storyboards to use the full screen space, rather than be confined to a 4:3 area."); /// /// "Epilepsy warning" @@ -77,7 +80,8 @@ namespace osu.Game.Localisation /// /// "Recommended if the storyboard or video contain scenes with rapidly flashing colours." /// - public static LocalisableString EpilepsyWarningDescription => new TranslatableString(getKey(@"epilepsy_warning_description"), @"Recommended if the storyboard or video contain scenes with rapidly flashing colours."); + public static LocalisableString EpilepsyWarningDescription => + new TranslatableString(getKey(@"epilepsy_warning_description"), @"Recommended if the storyboard or video contain scenes with rapidly flashing colours."); /// /// "Letterbox during breaks" @@ -87,7 +91,8 @@ namespace osu.Game.Localisation /// /// "Adds horizontal letterboxing to give a cinematic look during breaks." /// - public static LocalisableString LetterboxDuringBreaksDescription => new TranslatableString(getKey(@"letterbox_during_breaks_description"), @"Adds horizontal letterboxing to give a cinematic look during breaks."); + public static LocalisableString LetterboxDuringBreaksDescription => + new TranslatableString(getKey(@"letterbox_during_breaks_description"), @"Adds horizontal letterboxing to give a cinematic look during breaks."); /// /// "Samples match playback rate" @@ -97,7 +102,8 @@ namespace osu.Game.Localisation /// /// "When enabled, all samples will speed up or slow down when rate-changing mods are enabled." /// - public static LocalisableString SamplesMatchPlaybackRateDescription => new TranslatableString(getKey(@"samples_match_playback_rate_description"), @"When enabled, all samples will speed up or slow down when rate-changing mods are enabled."); + public static LocalisableString SamplesMatchPlaybackRateDescription => new TranslatableString(getKey(@"samples_match_playback_rate_description"), + @"When enabled, all samples will speed up or slow down when rate-changing mods are enabled."); /// /// "The size of all hit objects" @@ -117,7 +123,8 @@ namespace osu.Game.Localisation /// /// "The harshness of hit windows and difficulty of special objects (ie. spinners)" /// - public static LocalisableString OverallDifficultyDescription => new TranslatableString(getKey(@"overall_difficulty_description"), @"The harshness of hit windows and difficulty of special objects (ie. spinners)"); + public static LocalisableString OverallDifficultyDescription => + new TranslatableString(getKey(@"overall_difficulty_description"), @"The harshness of hit windows and difficulty of special objects (ie. spinners)"); /// /// "Metadata" @@ -199,6 +206,11 @@ namespace osu.Game.Localisation /// public static LocalisableString DifficultyHeader => new TranslatableString(getKey(@"difficulty_header"), @"Difficulty"); + /// + /// "Drag image here to set beatmap background!" + /// + public static LocalisableString DragToSetBackground => new TranslatableString(getKey(@"drag_to_set_background"), @"Drag image here to set beatmap background!"); + private static string getKey(string key) => $@"{prefix}:{key}"; } } diff --git a/osu.Game/Localisation/EditorStrings.cs b/osu.Game/Localisation/EditorStrings.cs new file mode 100644 index 0000000000..96c08aa6f8 --- /dev/null +++ b/osu.Game/Localisation/EditorStrings.cs @@ -0,0 +1,99 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Localisation; + +namespace osu.Game.Localisation +{ + public static class EditorStrings + { + private const string prefix = @"osu.Game.Resources.Localisation.Editor"; + + /// + /// "Waveform opacity" + /// + public static LocalisableString WaveformOpacity => new TranslatableString(getKey(@"waveform_opacity"), @"Waveform opacity"); + + /// + /// "Show hit markers" + /// + public static LocalisableString ShowHitMarkers => new TranslatableString(getKey(@"show_hit_markers"), @"Show hit markers"); + + /// + /// "Timing" + /// + public static LocalisableString Timing => new TranslatableString(getKey(@"timing"), @"Timing"); + + /// + /// "Set preview point to current time" + /// + public static LocalisableString SetPreviewPointToCurrent => new TranslatableString(getKey(@"set_preview_point_to_current"), @"Set preview point to current time"); + + /// + /// "Export package" + /// + public static LocalisableString ExportPackage => new TranslatableString(getKey(@"export_package"), @"Export package"); + + /// + /// "Create new difficulty" + /// + public static LocalisableString CreateNewDifficulty => new TranslatableString(getKey(@"create_new_difficulty"), @"Create new difficulty"); + + /// + /// "Change difficulty" + /// + public static LocalisableString ChangeDifficulty => new TranslatableString(getKey(@"change_difficulty"), @"Change difficulty"); + + /// + /// "Delete difficulty" + /// + public static LocalisableString DeleteDifficulty => new TranslatableString(getKey(@"delete_difficulty"), @"Delete difficulty"); + + /// + /// "setup" + /// + public static LocalisableString SetupScreen => new TranslatableString(getKey(@"setup_screen"), @"setup"); + + /// + /// "compose" + /// + public static LocalisableString ComposeScreen => new TranslatableString(getKey(@"compose_screen"), @"compose"); + + /// + /// "design" + /// + public static LocalisableString DesignScreen => new TranslatableString(getKey(@"design_screen"), @"design"); + + /// + /// "timing" + /// + public static LocalisableString TimingScreen => new TranslatableString(getKey(@"timing_screen"), @"timing"); + + /// + /// "verify" + /// + public static LocalisableString VerifyScreen => new TranslatableString(getKey(@"verify_screen"), @"verify"); + + /// + /// "Playback speed" + /// + public static LocalisableString PlaybackSpeed => new TranslatableString(getKey(@"playback_speed"), @"Playback speed"); + + /// + /// "Test!" + /// + public static LocalisableString TestBeatmap => new TranslatableString(getKey(@"test_beatmap"), @"Test!"); + + /// + /// "Waveform" + /// + public static LocalisableString TimelineWaveform => new TranslatableString(getKey(@"timeline_waveform"), @"Waveform"); + + /// + /// "Ticks" + /// + public static LocalisableString TimelineTicks => new TranslatableString(getKey(@"timeline_ticks"), @"Ticks"); + + private static string getKey(string key) => $@"{prefix}:{key}"; + } +} diff --git a/osu.Game/Localisation/FirstRunOverlayImportFromStableScreenStrings.cs b/osu.Game/Localisation/FirstRunOverlayImportFromStableScreenStrings.cs index deac7d8628..f0620245c3 100644 --- a/osu.Game/Localisation/FirstRunOverlayImportFromStableScreenStrings.cs +++ b/osu.Game/Localisation/FirstRunOverlayImportFromStableScreenStrings.cs @@ -15,10 +15,10 @@ namespace osu.Game.Localisation public static LocalisableString Header => new TranslatableString(getKey(@"header"), @"Import"); /// - /// "If you have an installation of a previous osu! version, you can choose to migrate your existing content. Note that this will create a copy, and not affect your existing installation." + /// "If you have an installation of a previous osu! version, you can choose to migrate your existing content. Note that this will not affect your existing installation's files in any way." /// public static LocalisableString Description => new TranslatableString(getKey(@"description"), - @"If you have an installation of a previous osu! version, you can choose to migrate your existing content. Note that this will create a copy, and not affect your existing installation."); + @"If you have an installation of a previous osu! version, you can choose to migrate your existing content. Note that this will not affect your existing installation's files in any way."); /// /// "previous osu! install" diff --git a/osu.Game/Localisation/GeneralSettingsStrings.cs b/osu.Game/Localisation/GeneralSettingsStrings.cs index 3278b20983..a525af508b 100644 --- a/osu.Game/Localisation/GeneralSettingsStrings.cs +++ b/osu.Game/Localisation/GeneralSettingsStrings.cs @@ -64,6 +64,16 @@ namespace osu.Game.Localisation /// public static LocalisableString RunSetupWizard => new TranslatableString(getKey(@"run_setup_wizard"), @"Run setup wizard"); + /// + /// "Learn more about lazer" + /// + public static LocalisableString LearnMoreAboutLazer => new TranslatableString(getKey(@"learn_more_about_lazer"), @"Learn more about lazer"); + + /// + /// "Check out the feature comparison and FAQ" + /// + public static LocalisableString LearnMoreAboutLazerTooltip => new TranslatableString(getKey(@"check_out_the_feature_comparison"), @"Check out the feature comparison and FAQ"); + /// /// "You are running the latest release ({0})" /// diff --git a/osu.Game/Localisation/MaintenanceSettingsStrings.cs b/osu.Game/Localisation/MaintenanceSettingsStrings.cs index 8aa0adf7a0..469f565f1e 100644 --- a/osu.Game/Localisation/MaintenanceSettingsStrings.cs +++ b/osu.Game/Localisation/MaintenanceSettingsStrings.cs @@ -54,11 +54,6 @@ namespace osu.Game.Localisation /// public static LocalisableString RestartAndReOpenRequiredForCompletion => new TranslatableString(getKey(@"restart_and_re_open_required_for_completion"), @"To complete this operation, osu! will close. Please open it again to use the new data location."); - /// - /// "Import beatmaps from stable" - /// - public static LocalisableString ImportBeatmapsFromStable => new TranslatableString(getKey(@"import_beatmaps_from_stable"), @"Import beatmaps from stable"); - /// /// "Delete ALL beatmaps" /// @@ -69,31 +64,16 @@ namespace osu.Game.Localisation /// public static LocalisableString DeleteAllBeatmapVideos => new TranslatableString(getKey(@"delete_all_beatmap_videos"), @"Delete ALL beatmap videos"); - /// - /// "Import scores from stable" - /// - public static LocalisableString ImportScoresFromStable => new TranslatableString(getKey(@"import_scores_from_stable"), @"Import scores from stable"); - /// /// "Delete ALL scores" /// public static LocalisableString DeleteAllScores => new TranslatableString(getKey(@"delete_all_scores"), @"Delete ALL scores"); - /// - /// "Import skins from stable" - /// - public static LocalisableString ImportSkinsFromStable => new TranslatableString(getKey(@"import_skins_from_stable"), @"Import skins from stable"); - /// /// "Delete ALL skins" /// public static LocalisableString DeleteAllSkins => new TranslatableString(getKey(@"delete_all_skins"), @"Delete ALL skins"); - /// - /// "Import collections from stable" - /// - public static LocalisableString ImportCollectionsFromStable => new TranslatableString(getKey(@"import_collections_from_stable"), @"Import collections from stable"); - /// /// "Delete ALL collections" /// diff --git a/osu.Game/Localisation/NotificationsStrings.cs b/osu.Game/Localisation/NotificationsStrings.cs index 382e0d81f4..6a9793b20c 100644 --- a/osu.Game/Localisation/NotificationsStrings.cs +++ b/osu.Game/Localisation/NotificationsStrings.cs @@ -15,10 +15,52 @@ namespace osu.Game.Localisation public static LocalisableString HeaderTitle => new TranslatableString(getKey(@"header_title"), @"notifications"); /// - /// "waiting for 'ya" + /// "waiting for 'ya" /// public static LocalisableString HeaderDescription => new TranslatableString(getKey(@"header_description"), @"waiting for 'ya"); - private static string getKey(string key) => $"{prefix}:{key}"; + /// + /// "Running Tasks" + /// + public static LocalisableString RunningTasks => new TranslatableString(getKey(@"running_tasks"), @"Running Tasks"); + + /// + /// "Clear All" + /// + public static LocalisableString ClearAll => new TranslatableString(getKey(@"clear_all"), @"Clear All"); + + /// + /// "Cancel All" + /// + public static LocalisableString CancelAll => new TranslatableString(getKey(@"cancel_all"), @"Cancel All"); + + /// + /// "Your battery level is low! Charge your device to prevent interruptions during gameplay." + /// + public static LocalisableString BatteryLow => new TranslatableString(getKey(@"battery_low"), @"Your battery level is low! Charge your device to prevent interruptions during gameplay."); + + /// + /// "Your game volume is too low to hear anything! Click here to restore it." + /// + public static LocalisableString GameVolumeTooLow => new TranslatableString(getKey(@"game_volume_too_low"), @"Your game volume is too low to hear anything! Click here to restore it."); + + /// + /// "The current ruleset doesn't have an autoplay mod available!" + /// + public static LocalisableString NoAutoplayMod => new TranslatableString(getKey(@"no_autoplay_mod"), @"The current ruleset doesn't have an autoplay mod available!"); + + /// + /// "osu! doesn't seem to be able to play audio correctly.\n\nPlease try changing your audio device to a working setting." + /// + public static LocalisableString AudioPlaybackIssue => new TranslatableString(getKey(@"audio_playback_issue"), + @"osu! doesn't seem to be able to play audio correctly.\n\nPlease try changing your audio device to a working setting."); + + /// + /// "The score overlay is currently disabled. You can toggle this by pressing {0}." + /// + public static LocalisableString ScoreOverlayDisabled(LocalisableString arg0) => new TranslatableString(getKey(@"score_overlay_disabled"), + @"The score overlay is currently disabled. You can toggle this by pressing {0}.", arg0); + + private static string getKey(string key) => $@"{prefix}:{key}"; } } diff --git a/osu.Game/Localisation/RulesetSettingsStrings.cs b/osu.Game/Localisation/RulesetSettingsStrings.cs index bc4be56c80..1b0df6ecf6 100644 --- a/osu.Game/Localisation/RulesetSettingsStrings.cs +++ b/osu.Game/Localisation/RulesetSettingsStrings.cs @@ -14,6 +14,26 @@ namespace osu.Game.Localisation /// public static LocalisableString Rulesets => new TranslatableString(getKey(@"rulesets"), @"Rulesets"); + /// + /// "Snaking in sliders" + /// + public static LocalisableString SnakingInSliders => new TranslatableString(getKey(@"snaking_in_sliders"), @"Snaking in sliders"); + + /// + /// "Snaking out sliders" + /// + public static LocalisableString SnakingOutSliders => new TranslatableString(getKey(@"snaking_out_sliders"), @"Snaking out sliders"); + + /// + /// "Cursor trail" + /// + public static LocalisableString CursorTrail => new TranslatableString(getKey(@"cursor_trail"), @"Cursor trail"); + + /// + /// "Playfield border style" + /// + public static LocalisableString PlayfieldBorderStyle => new TranslatableString(getKey(@"playfield_border_style"), @"Playfield border style"); + /// /// "None" /// @@ -29,6 +49,36 @@ namespace osu.Game.Localisation /// public static LocalisableString BorderFull => new TranslatableString(getKey(@"full_borders"), @"Full"); + /// + /// "Scrolling direction" + /// + public static LocalisableString ScrollingDirection => new TranslatableString(getKey(@"scrolling_direction"), @"Scrolling direction"); + + /// + /// "Up" + /// + public static LocalisableString ScrollingDirectionUp => new TranslatableString(getKey(@"scrolling_up"), @"Up"); + + /// + /// "Down" + /// + public static LocalisableString ScrollingDirectionDown => new TranslatableString(getKey(@"scrolling_down"), @"Down"); + + /// + /// "Scroll speed" + /// + public static LocalisableString ScrollSpeed => new TranslatableString(getKey(@"scroll_speed"), @"Scroll speed"); + + /// + /// "Timing-based note colouring" + /// + public static LocalisableString TimingBasedColouring => new TranslatableString(getKey(@"Timing_based_colouring"), @"Timing-based note colouring"); + + /// + /// "{0}ms (speed {1})" + /// + public static LocalisableString ScrollSpeedTooltip(double arg0, int arg1) => new TranslatableString(getKey(@"ruleset"), @"{0}ms (speed {1})", arg0, arg1); + private static string getKey(string key) => $@"{prefix}:{key}"; } } diff --git a/osu.Game/Localisation/SkinEditorStrings.cs b/osu.Game/Localisation/SkinEditorStrings.cs new file mode 100644 index 0000000000..b2e5f3aeb6 --- /dev/null +++ b/osu.Game/Localisation/SkinEditorStrings.cs @@ -0,0 +1,44 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Localisation; + +namespace osu.Game.Localisation +{ + public static class SkinEditorStrings + { + private const string prefix = @"osu.Game.Resources.Localisation.SkinEditor"; + + /// + /// "Skin editor" + /// + public static LocalisableString SkinEditor => new TranslatableString(getKey(@"skin_editor"), @"Skin editor"); + + /// + /// "Components" + /// + public static LocalisableString Components => new TranslatableString(getKey(@"components"), @"Components"); + + /// + /// "Scene library" + /// + public static LocalisableString SceneLibrary => new TranslatableString(getKey(@"scene_library"), @"Scene library"); + + /// + /// "Song Select" + /// + public static LocalisableString SongSelect => new TranslatableString(getKey(@"song_select"), @"Song Select"); + + /// + /// "Gameplay" + /// + public static LocalisableString Gameplay => new TranslatableString(getKey(@"gameplay"), @"Gameplay"); + + /// + /// "Settings ({0})" + /// + public static LocalisableString Settings(string arg0) => new TranslatableString(getKey(@"settings"), @"Settings ({0})", arg0); + + private static string getKey(string key) => $@"{prefix}:{key}"; + } +} diff --git a/osu.Game/Models/RealmUser.cs b/osu.Game/Models/RealmUser.cs index e20ffc0808..6997f04f44 100644 --- a/osu.Game/Models/RealmUser.cs +++ b/osu.Game/Models/RealmUser.cs @@ -27,7 +27,7 @@ namespace osu.Game.Models public bool IsBot => false; - public bool Equals(RealmUser other) + public bool Equals(RealmUser? other) { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index 65f78e1fd7..94bb77d6ec 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -26,7 +26,7 @@ using osu.Game.Users; namespace osu.Game.Online.API { - public class APIAccess : Component, IAPIProvider + public partial class APIAccess : Component, IAPIProvider { private readonly OsuConfigManager config; @@ -259,7 +259,11 @@ namespace osu.Game.Online.API var friendsReq = new GetFriendsRequest(); friendsReq.Failure += _ => state.Value = APIState.Failing; - friendsReq.Success += res => friends.AddRange(res); + friendsReq.Success += res => + { + friends.Clear(); + friends.AddRange(res); + }; if (!handleRequest(friendsReq)) { @@ -325,12 +329,35 @@ namespace osu.Game.Online.API { try { - return JObject.Parse(req.GetResponseString().AsNonNull()).SelectToken("form_error", true).AsNonNull().ToObject(); + return JObject.Parse(req.GetResponseString().AsNonNull()).SelectToken(@"form_error", true).AsNonNull().ToObject(); } catch { - // if we couldn't deserialize the error message let's throw the original exception outwards. - e.Rethrow(); + try + { + // attempt to parse a non-form error message + var response = JObject.Parse(req.GetResponseString().AsNonNull()); + + string redirect = (string)response.SelectToken(@"url", true); + string message = (string)response.SelectToken(@"error", false); + + if (!string.IsNullOrEmpty(redirect)) + { + return new RegistrationRequest.RegistrationRequestErrors + { + Redirect = redirect, + Message = message, + }; + } + + // if we couldn't deserialize the error message let's throw the original exception outwards. + e.Rethrow(); + } + catch + { + // if we couldn't deserialize the error message let's throw the original exception outwards. + e.Rethrow(); + } } } diff --git a/osu.Game/Online/API/APIMod.cs b/osu.Game/Online/API/APIMod.cs index 176f10975d..45128375ab 100644 --- a/osu.Game/Online/API/APIMod.cs +++ b/osu.Game/Online/API/APIMod.cs @@ -39,7 +39,7 @@ namespace osu.Game.Online.API foreach (var (_, property) in mod.GetSettingsSourceProperties()) { - var bindable = (IBindable)property.GetValue(mod); + var bindable = (IBindable)property.GetValue(mod)!; if (!bindable.IsDefault) Settings.Add(property.Name.ToSnakeCase(), bindable.GetUnderlyingSettingValue()); @@ -60,16 +60,16 @@ namespace osu.Game.Online.API { foreach (var (_, property) in resultMod.GetSettingsSourceProperties()) { - if (!Settings.TryGetValue(property.Name.ToSnakeCase(), out object settingValue)) + if (!Settings.TryGetValue(property.Name.ToSnakeCase(), out object? settingValue)) continue; try { - resultMod.CopyAdjustedSetting((IBindable)property.GetValue(resultMod), settingValue); + resultMod.CopyAdjustedSetting((IBindable)property.GetValue(resultMod)!, settingValue); } catch (Exception ex) { - Logger.Log($"Failed to copy mod setting value '{settingValue ?? "null"}' to \"{property.Name}\": {ex.Message}"); + Logger.Log($"Failed to copy mod setting value '{settingValue}' to \"{property.Name}\": {ex.Message}"); } } } @@ -79,7 +79,7 @@ namespace osu.Game.Online.API public bool ShouldSerializeSettings() => Settings.Count > 0; - public bool Equals(APIMod other) + public bool Equals(APIMod? other) { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; diff --git a/osu.Game/Online/API/DummyAPIAccess.cs b/osu.Game/Online/API/DummyAPIAccess.cs index 609efd8ab6..abe2755654 100644 --- a/osu.Game/Online/API/DummyAPIAccess.cs +++ b/osu.Game/Online/API/DummyAPIAccess.cs @@ -15,7 +15,7 @@ using osu.Game.Users; namespace osu.Game.Online.API { - public class DummyAPIAccess : Component, IAPIProvider + public partial class DummyAPIAccess : Component, IAPIProvider { public const int DUMMY_USER_ID = 1001; diff --git a/osu.Game/Online/API/RegistrationRequest.cs b/osu.Game/Online/API/RegistrationRequest.cs index 6dc867481a..78633f70b7 100644 --- a/osu.Game/Online/API/RegistrationRequest.cs +++ b/osu.Game/Online/API/RegistrationRequest.cs @@ -1,17 +1,16 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - +using System; using Newtonsoft.Json; namespace osu.Game.Online.API { public class RegistrationRequest : OsuWebRequest { - internal string Username; - internal string Email; - internal string Password; + internal string Username = string.Empty; + internal string Email = string.Empty; + internal string Password = string.Empty; protected override void PrePerform() { @@ -24,18 +23,28 @@ namespace osu.Game.Online.API public class RegistrationRequestErrors { - public UserErrors User; + /// + /// An optional error message. + /// + public string? Message; + + /// + /// An optional URL which the user should be directed towards to complete registration. + /// + public string? Redirect; + + public UserErrors? User; public class UserErrors { [JsonProperty("username")] - public string[] Username; + public string[] Username = Array.Empty(); [JsonProperty("user_email")] - public string[] Email; + public string[] Email = Array.Empty(); [JsonProperty("password")] - public string[] Password; + public string[] Password = Array.Empty(); } } } diff --git a/osu.Game/Online/API/Requests/GetScoresRequest.cs b/osu.Game/Online/API/Requests/GetScoresRequest.cs index 7d1d26b75d..f2a2daccb5 100644 --- a/osu.Game/Online/API/Requests/GetScoresRequest.cs +++ b/osu.Game/Online/API/Requests/GetScoresRequest.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using osu.Game.Beatmaps; using osu.Game.Rulesets; @@ -11,10 +9,11 @@ using osu.Game.Online.API.Requests.Responses; using osu.Game.Rulesets.Mods; using System.Text; using System.Collections.Generic; +using System.Linq; namespace osu.Game.Online.API.Requests { - public class GetScoresRequest : APIRequest + public class GetScoresRequest : APIRequest, IEquatable { public const int MAX_SCORES_PER_REQUEST = 50; @@ -23,7 +22,7 @@ namespace osu.Game.Online.API.Requests private readonly IRulesetInfo ruleset; private readonly IEnumerable mods; - public GetScoresRequest(IBeatmapInfo beatmapInfo, IRulesetInfo ruleset, BeatmapLeaderboardScope scope = BeatmapLeaderboardScope.Global, IEnumerable mods = null) + public GetScoresRequest(IBeatmapInfo beatmapInfo, IRulesetInfo ruleset, BeatmapLeaderboardScope scope = BeatmapLeaderboardScope.Global, IEnumerable? mods = null) { if (beatmapInfo.OnlineID <= 0) throw new InvalidOperationException($"Cannot lookup a beatmap's scores without having a populated {nameof(IBeatmapInfo.OnlineID)}."); @@ -51,5 +50,16 @@ namespace osu.Game.Online.API.Requests return query.ToString(); } + + public bool Equals(GetScoresRequest? other) + { + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + + return beatmapInfo.Equals(other.beatmapInfo) + && scope == other.scope + && ruleset.Equals(other.ruleset) + && mods.SequenceEqual(other.mods); + } } } diff --git a/osu.Game/Online/API/Requests/GetUpdatesRequest.cs b/osu.Game/Online/API/Requests/GetUpdatesRequest.cs index ce2689d262..529c579996 100644 --- a/osu.Game/Online/API/Requests/GetUpdatesRequest.cs +++ b/osu.Game/Online/API/Requests/GetUpdatesRequest.cs @@ -25,6 +25,7 @@ namespace osu.Game.Online.API.Requests var req = base.CreateWebRequest(); if (channel != null) req.AddParameter(@"channel", channel.Id.ToString()); req.AddParameter(@"since", since.ToString()); + req.AddParameter(@"includes[]", "presence"); return req; } diff --git a/osu.Game/Online/API/Requests/GetUpdatesResponse.cs b/osu.Game/Online/API/Requests/GetUpdatesResponse.cs index 61f6a8664d..7e030ce922 100644 --- a/osu.Game/Online/API/Requests/GetUpdatesResponse.cs +++ b/osu.Game/Online/API/Requests/GetUpdatesResponse.cs @@ -16,5 +16,7 @@ namespace osu.Game.Online.API.Requests [JsonProperty] public List Messages; + + // TODO: Handle Silences here (will need to add to includes[] in the request). } } diff --git a/osu.Game/Online/API/Requests/GetUserBeatmapsRequest.cs b/osu.Game/Online/API/Requests/GetUserBeatmapsRequest.cs index d723786f23..e4134980b1 100644 --- a/osu.Game/Online/API/Requests/GetUserBeatmapsRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserBeatmapsRequest.cs @@ -32,6 +32,7 @@ namespace osu.Game.Online.API.Requests Loved, Pending, Guest, - Graveyard + Graveyard, + Nominated, } } diff --git a/osu.Game/Online/API/Requests/GetUsersRequest.cs b/osu.Game/Online/API/Requests/GetUsersRequest.cs index bbaf241384..b57bb215aa 100644 --- a/osu.Game/Online/API/Requests/GetUsersRequest.cs +++ b/osu.Game/Online/API/Requests/GetUsersRequest.cs @@ -9,7 +9,7 @@ namespace osu.Game.Online.API.Requests { public class GetUsersRequest : APIRequest { - private readonly int[] userIds; + public readonly int[] UserIds; private const int max_ids_per_request = 50; @@ -18,9 +18,9 @@ namespace osu.Game.Online.API.Requests if (userIds.Length > max_ids_per_request) throw new ArgumentException($"{nameof(GetUsersRequest)} calls only support up to {max_ids_per_request} IDs at once"); - this.userIds = userIds; + UserIds = userIds; } - protected override string Target => "users/?ids[]=" + string.Join("&ids[]=", userIds); + protected override string Target => "users/?ids[]=" + string.Join("&ids[]=", UserIds); } } diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs index 8a77801c3a..7d6740ee46 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs @@ -63,6 +63,9 @@ namespace osu.Game.Online.API.Requests.Responses set => Length = TimeSpan.FromSeconds(value).TotalMilliseconds; } + [JsonProperty(@"convert")] + public bool Convert { get; set; } + [JsonProperty(@"count_circles")] public int CircleCount { get; set; } @@ -143,7 +146,7 @@ namespace osu.Game.Online.API.Requests.Responses public bool Equals(IRulesetInfo? other) => other is APIRuleset r && this.MatchesOnlineID(r); - public int CompareTo(IRulesetInfo other) + public int CompareTo(IRulesetInfo? other) { if (!(other is APIRuleset ruleset)) throw new ArgumentException($@"Object is not of type {nameof(APIRuleset)}.", nameof(other)); diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs index 717a1de6b5..d98715a42d 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs @@ -111,6 +111,12 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty(@"language")] public BeatmapSetOnlineLanguage Language { get; set; } + [JsonProperty(@"current_nominations")] + public BeatmapSetOnlineNomination[]? CurrentNominations { get; set; } + + [JsonProperty(@"related_users")] + public APIUser[]? RelatedUsers { get; set; } + public string Source { get; set; } = string.Empty; [JsonProperty(@"tags")] @@ -119,6 +125,9 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty(@"beatmaps")] public APIBeatmap[] Beatmaps { get; set; } = Array.Empty(); + [JsonProperty(@"converts")] + public APIBeatmap[]? Converts { get; set; } + private BeatmapMetadata metadata => new BeatmapMetadata { Title = Title, diff --git a/osu.Game/Online/API/Requests/Responses/APIRecentActivity.cs b/osu.Game/Online/API/Requests/Responses/APIRecentActivity.cs index 2def18926f..c6a8a85407 100644 --- a/osu.Game/Online/API/Requests/Responses/APIRecentActivity.cs +++ b/osu.Game/Online/API/Requests/Responses/APIRecentActivity.cs @@ -21,7 +21,7 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty] private string type { - set => Type = (RecentActivityType)Enum.Parse(typeof(RecentActivityType), value.ToPascalCase()); + set => Type = Enum.Parse(value.ToPascalCase()); } public RecentActivityType Type; @@ -29,7 +29,7 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty] private string scoreRank { - set => ScoreRank = (ScoreRank)Enum.Parse(typeof(ScoreRank), value); + set => ScoreRank = Enum.Parse(value); } public ScoreRank ScoreRank; diff --git a/osu.Game/Online/API/Requests/Responses/APIUser.cs b/osu.Game/Online/API/Requests/Responses/APIUser.cs index d3ddcffaf5..0e62b03f1a 100644 --- a/osu.Game/Online/API/Requests/Responses/APIUser.cs +++ b/osu.Game/Online/API/Requests/Responses/APIUser.cs @@ -164,6 +164,9 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty(@"guest_beatmapset_count")] public int GuestBeatmapsetCount; + [JsonProperty(@"nominated_beatmapset_count")] + public int NominatedBeatmapsetCount; + [JsonProperty(@"scores_best_count")] public int ScoresBestCount; @@ -182,7 +185,7 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty(@"playstyle")] private string[] playStyle { - set => PlayStyles = value?.Select(str => Enum.Parse(typeof(APIPlayStyle), str, true)).Cast().ToArray(); + set => PlayStyles = value?.Select(str => Enum.Parse(str, true)).ToArray(); } public APIPlayStyle[] PlayStyles; @@ -252,6 +255,9 @@ namespace osu.Game.Online.API.Requests.Responses [CanBeNull] public Dictionary RulesetsStatistics { get; set; } + [JsonProperty("groups")] + public APIUserGroup[] Groups; + public override string ToString() => Username; /// diff --git a/osu.Game/Online/API/Requests/Responses/APIUserGroup.cs b/osu.Game/Online/API/Requests/Responses/APIUserGroup.cs new file mode 100644 index 0000000000..89631d3d7a --- /dev/null +++ b/osu.Game/Online/API/Requests/Responses/APIUserGroup.cs @@ -0,0 +1,37 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using Newtonsoft.Json; + +namespace osu.Game.Online.API.Requests.Responses +{ + public class APIUserGroup + { + [JsonProperty(@"colour")] + public string? Colour { get; set; } + + [JsonProperty(@"has_listing")] + public bool HasListings { get; set; } + + [JsonProperty(@"has_playmodes")] + public bool HasPlaymodes { get; set; } + + [JsonProperty(@"id")] + public int Id { get; set; } + + [JsonProperty(@"identifier")] + public string Identifier { get; set; } = null!; + + [JsonProperty(@"is_probationary")] + public bool IsProbationary { get; set; } + + [JsonProperty(@"name")] + public string Name { get; set; } = null!; + + [JsonProperty(@"short_name")] + public string ShortName { get; set; } = null!; + + [JsonProperty(@"playmodes")] + public string[]? Playmodes { get; set; } + } +} diff --git a/osu.Game/Online/BeatmapDownloadTracker.cs b/osu.Game/Online/BeatmapDownloadTracker.cs index 19708cc07d..144c4445a3 100644 --- a/osu.Game/Online/BeatmapDownloadTracker.cs +++ b/osu.Game/Online/BeatmapDownloadTracker.cs @@ -10,7 +10,7 @@ using osu.Game.Online.API; namespace osu.Game.Online { - public class BeatmapDownloadTracker : DownloadTracker + public partial class BeatmapDownloadTracker : DownloadTracker { [Resolved(CanBeNull = true)] protected BeatmapModelDownloader? Downloader { get; private set; } diff --git a/osu.Game/Online/Chat/Channel.cs b/osu.Game/Online/Chat/Channel.cs index 24b384b1d4..761e8aba8d 100644 --- a/osu.Game/Online/Chat/Channel.cs +++ b/osu.Game/Online/Chat/Channel.cs @@ -98,6 +98,11 @@ namespace osu.Game.Online.Chat /// public Bindable HighlightedMessage = new Bindable(); + /// + /// The current text box message while in this . + /// + public Bindable TextBoxMessage = new Bindable(string.Empty); + [JsonConstructor] public Channel() { diff --git a/osu.Game/Online/Chat/ChannelManager.cs b/osu.Game/Online/Chat/ChannelManager.cs index 25a53360f0..7ab678775f 100644 --- a/osu.Game/Online/Chat/ChannelManager.cs +++ b/osu.Game/Online/Chat/ChannelManager.cs @@ -24,7 +24,7 @@ namespace osu.Game.Online.Chat /// /// Manages everything channel related /// - public class ChannelManager : CompositeComponent, IChannelPostTarget + public partial class ChannelManager : CompositeComponent, IChannelPostTarget { /// /// The channels the player joins on startup @@ -64,6 +64,11 @@ namespace osu.Game.Online.Chat /// public IBindableList AvailableChannels => availableChannels; + /// + /// Whether the client responsible for channel notifications is connected. + /// + public bool NotificationsConnected => connector.IsConnected.Value; + private readonly IAPIProvider api; private readonly NotificationsClientConnector connector; @@ -71,7 +76,6 @@ namespace osu.Game.Online.Chat private UserLookupCache users { get; set; } private readonly IBindable apiState = new Bindable(); - private bool channelsInitialised; private ScheduledDelegate scheduledAck; private long? lastSilenceMessageId; @@ -95,15 +99,7 @@ namespace osu.Game.Online.Chat connector.NewMessages += msgs => Schedule(() => addMessages(msgs)); - connector.PresenceReceived += () => Schedule(() => - { - if (!channelsInitialised) - { - channelsInitialised = true; - // we want this to run after the first presence so we can see if the user is in any channels already. - initializeChannels(); - } - }); + connector.PresenceReceived += () => Schedule(initializeChannels); connector.Start(); @@ -118,8 +114,7 @@ namespace osu.Game.Online.Chat /// public void OpenChannel(string name) { - if (name == null) - throw new ArgumentNullException(nameof(name)); + ArgumentNullException.ThrowIfNull(name); CurrentChannel.Value = AvailableChannels.FirstOrDefault(c => c.Name == name) ?? throw new ChannelNotFoundException(name); } @@ -130,8 +125,7 @@ namespace osu.Game.Online.Chat /// The user the private channel is opened with. public void OpenPrivateChannel(APIUser user) { - if (user == null) - throw new ArgumentNullException(nameof(user)); + ArgumentNullException.ThrowIfNull(user); if (user.Id == api.LocalUser.Value.Id) return; @@ -337,6 +331,11 @@ namespace osu.Game.Online.Chat private void initializeChannels() { + // This request is self-retrying until it succeeds. + // To avoid requests piling up when not logged in (ie. API is unavailable) exit early. + if (!api.IsLoggedIn) + return; + var req = new ListChannelsRequest(); bool joinDefaults = JoinedChannels.Count == 0; @@ -352,10 +351,11 @@ namespace osu.Game.Online.Chat joinChannel(ch); } }; + req.Failure += error => { Logger.Error(error, "Fetching channel list failed"); - initializeChannels(); + Scheduler.AddDelayed(initializeChannels, 60000); }; api.Queue(req); @@ -529,6 +529,10 @@ namespace osu.Game.Online.Chat { Logger.Log($"Joined public channel {channel}"); joinChannel(channel, fetchInitialMessages); + + // Required after joining public channels to mark the user as online in them. + // Todo: Temporary workaround for https://github.com/ppy/osu-web/issues/9602 + SendAck(); }; req.Failure += e => { diff --git a/osu.Game/Online/Chat/DrawableLinkCompiler.cs b/osu.Game/Online/Chat/DrawableLinkCompiler.cs index 44e66c1a69..ee53c00668 100644 --- a/osu.Game/Online/Chat/DrawableLinkCompiler.cs +++ b/osu.Game/Online/Chat/DrawableLinkCompiler.cs @@ -20,7 +20,7 @@ namespace osu.Game.Online.Chat /// /// An invisible drawable that brings multiple pieces together to form a consumable clickable link. /// - public class DrawableLinkCompiler : OsuHoverContainer + public partial class DrawableLinkCompiler : OsuHoverContainer { /// /// Each word part of a chat link (split for word-wrap support). @@ -52,7 +52,7 @@ namespace osu.Game.Online.Chat protected override IEnumerable EffectTargets => Parts; - private class LinkHoverSounds : HoverClickSounds + private partial class LinkHoverSounds : HoverClickSounds { private readonly List parts; diff --git a/osu.Game/Online/Chat/ExternalLinkOpener.cs b/osu.Game/Online/Chat/ExternalLinkOpener.cs index 587159179f..201212c648 100644 --- a/osu.Game/Online/Chat/ExternalLinkOpener.cs +++ b/osu.Game/Online/Chat/ExternalLinkOpener.cs @@ -13,7 +13,7 @@ using osu.Game.Overlays.Dialog; namespace osu.Game.Online.Chat { - public class ExternalLinkOpener : Component + public partial class ExternalLinkOpener : Component { [Resolved] private GameHost host { get; set; } = null!; @@ -37,7 +37,7 @@ namespace osu.Game.Online.Chat host.OpenUrlExternally(url); } - public class ExternalLinkDialog : PopupDialog + public partial class ExternalLinkDialog : PopupDialog { public ExternalLinkDialog(string url, Action openExternalLinkAction, Action copyExternalLinkAction) { diff --git a/osu.Game/Online/Chat/InfoMessage.cs b/osu.Game/Online/Chat/InfoMessage.cs index d98c67de34..2ade99dcb2 100644 --- a/osu.Game/Online/Chat/InfoMessage.cs +++ b/osu.Game/Online/Chat/InfoMessage.cs @@ -1,9 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - -using System; using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Online.Chat @@ -13,7 +10,6 @@ namespace osu.Game.Online.Chat public InfoMessage(string message) : base(null) { - Timestamp = DateTimeOffset.Now; Content = message; Sender = APIUser.SYSTEM_USER; diff --git a/osu.Game/Online/Chat/LocalEchoMessage.cs b/osu.Game/Online/Chat/LocalEchoMessage.cs index b226fe6cad..8a39515575 100644 --- a/osu.Game/Online/Chat/LocalEchoMessage.cs +++ b/osu.Game/Online/Chat/LocalEchoMessage.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - namespace osu.Game.Online.Chat { public class LocalEchoMessage : LocalMessage diff --git a/osu.Game/Online/Chat/LocalMessage.cs b/osu.Game/Online/Chat/LocalMessage.cs index 5736f5cabf..57caca2287 100644 --- a/osu.Game/Online/Chat/LocalMessage.cs +++ b/osu.Game/Online/Chat/LocalMessage.cs @@ -1,7 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable +using System; namespace osu.Game.Online.Chat { @@ -13,6 +13,7 @@ namespace osu.Game.Online.Chat protected LocalMessage(long? id) : base(id) { + Timestamp = DateTimeOffset.Now; } } } diff --git a/osu.Game/Online/Chat/Message.cs b/osu.Game/Online/Chat/Message.cs index 9f6f9c8d6b..8ea3ca0fc7 100644 --- a/osu.Game/Online/Chat/Message.cs +++ b/osu.Game/Online/Chat/Message.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; +using System.Threading; using Newtonsoft.Json; using osu.Game.Online.API.Requests.Responses; @@ -59,19 +60,28 @@ namespace osu.Game.Online.Chat /// The s' and s are according to public List Links; + private static long constructionOrderStatic; + private readonly long constructionOrder; + public Message(long? id) { Id = id; + + constructionOrder = Interlocked.Increment(ref constructionOrderStatic); } public int CompareTo(Message other) { - if (!Id.HasValue) - return other.Id.HasValue ? 1 : Timestamp.CompareTo(other.Timestamp); - if (!other.Id.HasValue) - return -1; + if (Id.HasValue && other.Id.HasValue) + return Id.Value.CompareTo(other.Id.Value); - return Id.Value.CompareTo(other.Id.Value); + int timestampComparison = Timestamp.CompareTo(other.Timestamp); + + if (timestampComparison != 0) + return timestampComparison; + + // Timestamp might not be accurate enough to make a stable sorting decision. + return constructionOrder.CompareTo(other.constructionOrder); } public virtual bool Equals(Message other) @@ -85,6 +95,6 @@ namespace osu.Game.Online.Chat // ReSharper disable once ImpureMethodCallOnReadonlyValueField public override int GetHashCode() => Id.GetHashCode(); - public override string ToString() => $"[{ChannelId}] ({Id}) {Sender}: {Content}"; + public override string ToString() => $"({(Id?.ToString() ?? "null")}) {Timestamp} {Sender}: {Content}"; } } diff --git a/osu.Game/Online/Chat/MessageFormatter.cs b/osu.Game/Online/Chat/MessageFormatter.cs index 7a040d9446..523185a7cb 100644 --- a/osu.Game/Online/Chat/MessageFormatter.cs +++ b/osu.Game/Online/Chat/MessageFormatter.cs @@ -71,7 +71,7 @@ namespace osu.Game.Online.Chat { int index = m.Index - captureOffset; - string? displayText = string.Format(display, + string displayText = string.Format(display, m.Groups[0], m.Groups["text"].Value, m.Groups["url"].Value).Trim(); @@ -109,7 +109,7 @@ namespace osu.Game.Online.Chat foreach (Match m in regex.Matches(result.Text, startIndex)) { int index = m.Index; - string? linkText = m.Groups["link"].Value; + string linkText = m.Groups["link"].Value; int indexLength = linkText.Length; var details = GetLinkDetails(linkText); @@ -125,7 +125,7 @@ namespace osu.Game.Online.Chat public static LinkDetails GetLinkDetails(string url) { - string[]? args = url.Split('/', StringSplitOptions.RemoveEmptyEntries); + string[] args = url.Split('/', StringSplitOptions.RemoveEmptyEntries); args[0] = args[0].TrimEnd(':'); switch (args[0]) @@ -341,6 +341,8 @@ namespace osu.Game.Online.Chat OpenWiki, Custom, OpenChangelog, + FilterBeatmapSetGenre, + FilterBeatmapSetLanguage, } public class Link : IComparable @@ -362,6 +364,6 @@ namespace osu.Game.Online.Chat public bool Overlaps(Link otherLink) => Index < otherLink.Index + otherLink.Length && otherLink.Index < Index + Length; - public int CompareTo(Link otherLink) => Index > otherLink.Index ? 1 : -1; + public int CompareTo(Link? otherLink) => Index > otherLink?.Index ? 1 : -1; } } diff --git a/osu.Game/Online/Chat/MessageNotifier.cs b/osu.Game/Online/Chat/MessageNotifier.cs index 22c2b4690e..9b2ad666b2 100644 --- a/osu.Game/Online/Chat/MessageNotifier.cs +++ b/osu.Game/Online/Chat/MessageNotifier.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Collections.Specialized; +using System.Diagnostics; using System.Linq; using System.Text.RegularExpressions; using osu.Framework.Allocation; @@ -23,7 +24,7 @@ namespace osu.Game.Online.Chat /// /// Component that handles creating and posting notifications for incoming messages. /// - public class MessageNotifier : Component + public partial class MessageNotifier : Component { [Resolved] private INotificationOverlay notifications { get; set; } @@ -61,12 +62,16 @@ namespace osu.Game.Online.Chat switch (e.Action) { case NotifyCollectionChangedAction.Add: + Debug.Assert(e.NewItems != null); + foreach (var channel in e.NewItems.Cast()) channel.NewMessagesArrived += checkNewMessages; break; case NotifyCollectionChangedAction.Remove: + Debug.Assert(e.OldItems != null); + foreach (var channel in e.OldItems.Cast()) channel.NewMessagesArrived -= checkNewMessages; @@ -138,7 +143,7 @@ namespace osu.Game.Online.Chat return Regex.IsMatch(message, $@"(^|\W)({fullName}|{underscoreName})($|\W)", RegexOptions.IgnoreCase); } - public class PrivateMessageNotification : HighlightMessageNotification + public partial class PrivateMessageNotification : HighlightMessageNotification { public PrivateMessageNotification(Message message, Channel channel) : base(message, channel) @@ -148,7 +153,7 @@ namespace osu.Game.Online.Chat } } - public class MentionNotification : HighlightMessageNotification + public partial class MentionNotification : HighlightMessageNotification { public MentionNotification(Message message, Channel channel) : base(message, channel) @@ -158,7 +163,7 @@ namespace osu.Game.Online.Chat } } - public abstract class HighlightMessageNotification : SimpleNotification + public abstract partial class HighlightMessageNotification : SimpleNotification { protected HighlightMessageNotification(Message message, Channel channel) { diff --git a/osu.Game/Online/Chat/NowPlayingCommand.cs b/osu.Game/Online/Chat/NowPlayingCommand.cs index 6a25ceb919..9902704883 100644 --- a/osu.Game/Online/Chat/NowPlayingCommand.cs +++ b/osu.Game/Online/Chat/NowPlayingCommand.cs @@ -1,35 +1,48 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - +using System.Collections.Generic; +using System.Linq; +using System.Text; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Localisation; using osu.Game.Beatmaps; using osu.Game.Online.API; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Mods; using osu.Game.Users; namespace osu.Game.Online.Chat { - public class NowPlayingCommand : Component + public partial class NowPlayingCommand : Component { [Resolved] - private IChannelPostTarget channelManager { get; set; } + private IChannelPostTarget channelManager { get; set; } = null!; [Resolved] - private IAPIProvider api { get; set; } + private IAPIProvider api { get; set; } = null!; [Resolved] - private Bindable currentBeatmap { get; set; } + private Bindable currentBeatmap { get; set; } = null!; - private readonly Channel target; + [Resolved] + private Bindable> selectedMods { get; set; } = null!; + + [Resolved] + private IBindable currentRuleset { get; set; } = null!; + + [Resolved] + private LocalisationManager localisation { get; set; } = null!; + + private readonly Channel? target; /// /// Creates a new to post the currently-playing beatmap to a parenting . /// /// The target channel to post to. If null, the currently-selected channel will be posted to. - public NowPlayingCommand(Channel target = null) + public NowPlayingCommand(Channel target) { this.target = target; } @@ -59,10 +72,55 @@ namespace osu.Game.Online.Chat break; } - string beatmapString = beatmapInfo.OnlineID > 0 ? $"[{api.WebsiteRootUrl}/b/{beatmapInfo.OnlineID} {beatmapInfo}]" : beatmapInfo.ToString(); + string[] pieces = + { + "is", + verb, + getBeatmapPart(), + getRulesetPart(), + getModPart(), + }; - channelManager.PostMessage($"is {verb} {beatmapString}", true, target); + channelManager.PostMessage(string.Join(' ', pieces.Where(p => !string.IsNullOrEmpty(p))), true, target); Expire(); + + string getBeatmapPart() + { + string beatmapInfoString = localisation.GetLocalisedBindableString(beatmapInfo.GetDisplayTitleRomanisable()).Value; + + return beatmapInfo.OnlineID > 0 ? $"[{api.WebsiteRootUrl}/b/{beatmapInfo.OnlineID} {beatmapInfoString}]" : beatmapInfoString; + } + + string getRulesetPart() + { + if (api.Activity.Value is not UserActivity.InGame) return string.Empty; + + return $"<{currentRuleset.Value.Name}>"; + } + + string getModPart() + { + if (api.Activity.Value is not UserActivity.InGame) return string.Empty; + + if (selectedMods.Value.Count == 0) + { + return string.Empty; + } + + StringBuilder modsString = new StringBuilder(); + + foreach (var mod in selectedMods.Value.Where(mod => mod.Type == ModType.DifficultyIncrease)) + { + modsString.Append($"+{mod.Acronym} "); + } + + foreach (var mod in selectedMods.Value.Where(mod => mod.Type != ModType.DifficultyIncrease)) + { + modsString.Append($"-{mod.Acronym} "); + } + + return modsString.ToString().Trim(); + } } } } diff --git a/osu.Game/Online/Chat/StandAloneChatDisplay.cs b/osu.Game/Online/Chat/StandAloneChatDisplay.cs index de68dd231f..0a5434822b 100644 --- a/osu.Game/Online/Chat/StandAloneChatDisplay.cs +++ b/osu.Game/Online/Chat/StandAloneChatDisplay.cs @@ -23,7 +23,7 @@ namespace osu.Game.Online.Chat /// /// Display a chat channel in an insolated region. /// - public class StandAloneChatDisplay : CompositeDrawable + public partial class StandAloneChatDisplay : CompositeDrawable { public readonly Bindable Channel = new Bindable(); @@ -111,8 +111,13 @@ namespace osu.Game.Online.Chat { drawableChannel?.Expire(); + if (e.OldValue != null) + TextBox?.Current.UnbindFrom(e.OldValue.TextBoxMessage); + if (e.NewValue == null) return; + TextBox?.Current.BindTo(e.NewValue.TextBoxMessage); + drawableChannel = CreateDrawableChannel(e.NewValue); drawableChannel.CreateChatLineAction = CreateMessage; drawableChannel.Padding = new MarginPadding { Bottom = postingTextBox ? text_box_height : 0 }; @@ -120,7 +125,7 @@ namespace osu.Game.Online.Chat AddInternal(drawableChannel); } - public class ChatTextBox : HistoryTextBox + public partial class ChatTextBox : HistoryTextBox { protected override bool OnKeyDown(KeyDownEvent e) { @@ -156,7 +161,7 @@ namespace osu.Game.Online.Chat public Action FocusLost; } - public class StandAloneDrawableChannel : DrawableChannel + public partial class StandAloneDrawableChannel : DrawableChannel { public Func CreateChatLineAction; @@ -170,7 +175,7 @@ namespace osu.Game.Online.Chat protected override DaySeparator CreateDaySeparator(DateTimeOffset time) => new StandAloneDaySeparator(time); } - protected class StandAloneDaySeparator : DaySeparator + protected partial class StandAloneDaySeparator : DaySeparator { protected override float TextSize => 14; protected override float LineHeight => 1; @@ -190,9 +195,9 @@ namespace osu.Game.Online.Chat } } - protected class StandAloneMessage : ChatLine + protected partial class StandAloneMessage : ChatLine { - protected override float TextSize => 15; + protected override float FontSize => 15; protected override float Spacing => 5; protected override float UsernameWidth => 75; diff --git a/osu.Game/Online/DownloadTracker.cs b/osu.Game/Online/DownloadTracker.cs index 85af9abb33..27a765ca20 100644 --- a/osu.Game/Online/DownloadTracker.cs +++ b/osu.Game/Online/DownloadTracker.cs @@ -6,7 +6,7 @@ using osu.Framework.Graphics; namespace osu.Game.Online { - public abstract class DownloadTracker : Component + public abstract partial class DownloadTracker : Component where T : class { public readonly T TrackedItem; diff --git a/osu.Game/Online/HubClientConnector.cs b/osu.Game/Online/HubClientConnector.cs index ca6d2932f7..8fd79bd703 100644 --- a/osu.Game/Online/HubClientConnector.cs +++ b/osu.Game/Online/HubClientConnector.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Net; +using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.SignalR.Client; @@ -59,17 +60,21 @@ namespace osu.Game.Online var builder = new HubConnectionBuilder() .WithUrl(endpoint, options => { - // Use HttpClient.DefaultProxy once on net6 everywhere. - // The credential setter can also be removed at this point. - options.Proxy = WebRequest.DefaultWebProxy; - if (options.Proxy != null) - options.Proxy.Credentials = CredentialCache.DefaultCredentials; + // Configuring proxies is not supported on iOS, see https://github.com/xamarin/xamarin-macios/issues/14632. + if (RuntimeInfo.OS != RuntimeInfo.Platform.iOS) + { + // Use HttpClient.DefaultProxy once on net6 everywhere. + // The credential setter can also be removed at this point. + options.Proxy = WebRequest.DefaultWebProxy; + if (options.Proxy != null) + options.Proxy.Credentials = CredentialCache.DefaultCredentials; + } options.Headers.Add("Authorization", $"Bearer {api.AccessToken}"); options.Headers.Add("OsuVersionHash", versionHash); }); - if (RuntimeInfo.SupportsJIT && preferMessagePack) + if (RuntimeFeature.IsDynamicCodeCompiled && preferMessagePack) { builder.AddMessagePackProtocol(options => { diff --git a/osu.Game/Online/Leaderboards/DrawableRank.cs b/osu.Game/Online/Leaderboards/DrawableRank.cs index 35bdc4e31f..5a65c15444 100644 --- a/osu.Game/Online/Leaderboards/DrawableRank.cs +++ b/osu.Game/Online/Leaderboards/DrawableRank.cs @@ -18,7 +18,7 @@ using osuTK.Graphics; namespace osu.Game.Online.Leaderboards { - public class DrawableRank : CompositeDrawable + public partial class DrawableRank : CompositeDrawable { private readonly ScoreRank rank; diff --git a/osu.Game/Online/Leaderboards/Leaderboard.cs b/osu.Game/Online/Leaderboards/Leaderboard.cs index 69b4e5b209..93aa0b95a7 100644 --- a/osu.Game/Online/Leaderboards/Leaderboard.cs +++ b/osu.Game/Online/Leaderboards/Leaderboard.cs @@ -31,7 +31,7 @@ namespace osu.Game.Online.Leaderboards /// /// The scope of the leaderboard (ie. global or local). /// The score model class. - public abstract class Leaderboard : CompositeDrawable + public abstract partial class Leaderboard : CompositeDrawable { /// /// The currently displayed scores. diff --git a/osu.Game/Online/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs index a7b6bd044d..e20b28ee0c 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs @@ -37,7 +37,7 @@ using osu.Game.Utils; namespace osu.Game.Online.Leaderboards { - public class LeaderboardScore : OsuClickableContainer, IHasContextMenu, IHasCustomTooltip + public partial class LeaderboardScore : OsuClickableContainer, IHasContextMenu, IHasCustomTooltip { public const float HEIGHT = 60; @@ -310,7 +310,7 @@ namespace osu.Game.Online.Leaderboards base.OnHoverLost(e); } - private class ScoreComponentLabel : Container, IHasTooltip + private partial class ScoreComponentLabel : Container, IHasTooltip { private const float icon_size = 20; private readonly FillFlowContainer content; @@ -372,7 +372,7 @@ namespace osu.Game.Online.Leaderboards } } - private class RankLabel : Container, IHasTooltip + private partial class RankLabel : Container, IHasTooltip { public RankLabel(int? rank) { @@ -391,7 +391,7 @@ namespace osu.Game.Online.Leaderboards public LocalisableString TooltipText { get; } } - private class DateLabel : DrawableDate + private partial class DateLabel : DrawableDate { public DateLabel(DateTimeOffset date) : base(date) diff --git a/osu.Game/Online/Leaderboards/LeaderboardScoreTooltip.cs b/osu.Game/Online/Leaderboards/LeaderboardScoreTooltip.cs index f51f57c031..0b2e401f57 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScoreTooltip.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScoreTooltip.cs @@ -20,7 +20,7 @@ using osu.Game.Configuration; namespace osu.Game.Online.Leaderboards { - public class LeaderboardScoreTooltip : VisibilityContainer, ITooltip + public partial class LeaderboardScoreTooltip : VisibilityContainer, ITooltip { private OsuSpriteText timestampLabel = null!; private FillFlowContainer topScoreStatistics = null!; @@ -136,9 +136,8 @@ namespace osu.Game.Online.Leaderboards { if (displayedScore != null) { - timestampLabel.Text = prefer24HourTime.Value - ? $"Played on {displayedScore.Date.ToLocalTime():d MMMM yyyy HH:mm}" - : $"Played on {displayedScore.Date.ToLocalTime():d MMMM yyyy h:mm tt}"; + timestampLabel.Text = LocalisableString.Format("Played on {0}", + displayedScore.Date.ToLocalTime().ToLocalisableString(prefer24HourTime.Value ? @"d MMMM yyyy HH:mm" : @"d MMMM yyyy h:mm tt")); } } @@ -147,7 +146,7 @@ namespace osu.Game.Online.Leaderboards public void Move(Vector2 pos) => Position = pos; - private class HitResultCell : CompositeDrawable + private partial class HitResultCell : CompositeDrawable { private readonly LocalisableString displayName; private readonly HitResult result; @@ -189,7 +188,7 @@ namespace osu.Game.Online.Leaderboards } } - private class ModCell : CompositeDrawable + private partial class ModCell : CompositeDrawable { private readonly Mod mod; diff --git a/osu.Game/Online/Leaderboards/UpdateableRank.cs b/osu.Game/Online/Leaderboards/UpdateableRank.cs index e640fe8494..46cfe8ec65 100644 --- a/osu.Game/Online/Leaderboards/UpdateableRank.cs +++ b/osu.Game/Online/Leaderboards/UpdateableRank.cs @@ -9,7 +9,7 @@ using osu.Game.Scoring; namespace osu.Game.Online.Leaderboards { - public class UpdateableRank : ModelBackedDrawable + public partial class UpdateableRank : ModelBackedDrawable { public ScoreRank? Rank { diff --git a/osu.Game/Online/Leaderboards/UserTopScoreContainer.cs b/osu.Game/Online/Leaderboards/UserTopScoreContainer.cs index 391e8804f0..af59da2fb8 100644 --- a/osu.Game/Online/Leaderboards/UserTopScoreContainer.cs +++ b/osu.Game/Online/Leaderboards/UserTopScoreContainer.cs @@ -12,7 +12,7 @@ using osuTK; namespace osu.Game.Online.Leaderboards { - public class UserTopScoreContainer : VisibilityContainer + public partial class UserTopScoreContainer : VisibilityContainer { private const int duration = 500; diff --git a/osu.Game/Online/Metadata/MetadataClient.cs b/osu.Game/Online/Metadata/MetadataClient.cs index 60867da2d7..d4e7540fe7 100644 --- a/osu.Game/Online/Metadata/MetadataClient.cs +++ b/osu.Game/Online/Metadata/MetadataClient.cs @@ -8,7 +8,7 @@ using osu.Framework.Graphics; namespace osu.Game.Online.Metadata { - public abstract class MetadataClient : Component, IMetadataClient, IMetadataServer + public abstract partial class MetadataClient : Component, IMetadataClient, IMetadataServer { public abstract Task BeatmapSetsUpdated(BeatmapUpdates updates); diff --git a/osu.Game/Online/Metadata/OnlineMetadataClient.cs b/osu.Game/Online/Metadata/OnlineMetadataClient.cs index 06d24a82f3..57311419f7 100644 --- a/osu.Game/Online/Metadata/OnlineMetadataClient.cs +++ b/osu.Game/Online/Metadata/OnlineMetadataClient.cs @@ -13,7 +13,7 @@ using osu.Game.Online.API; namespace osu.Game.Online.Metadata { - public class OnlineMetadataClient : MetadataClient + public partial class OnlineMetadataClient : MetadataClient { private readonly string endpoint; @@ -68,7 +68,7 @@ namespace osu.Game.Online.Metadata while (true) { Logger.Log($"Requesting catch-up from {lastQueueId.Value}"); - var catchUpChanges = await GetChangesSince(lastQueueId.Value); + var catchUpChanges = await GetChangesSince(lastQueueId.Value).ConfigureAwait(true); lastQueueId.Value = catchUpChanges.LastProcessedQueueID; @@ -78,7 +78,7 @@ namespace osu.Game.Online.Metadata break; } - await ProcessChanges(catchUpChanges.BeatmapSetIDs); + await ProcessChanges(catchUpChanges.BeatmapSetIDs).ConfigureAwait(true); } } catch (Exception e) @@ -101,7 +101,7 @@ namespace osu.Game.Online.Metadata if (!catchingUp) lastQueueId.Value = updates.LastProcessedQueueID; - await ProcessChanges(updates.BeatmapSetIDs); + await ProcessChanges(updates.BeatmapSetIDs).ConfigureAwait(false); } public override Task GetChangesSince(int queueId) diff --git a/osu.Game/Online/Multiplayer/MultiplayerClient.cs b/osu.Game/Online/Multiplayer/MultiplayerClient.cs index b39781ebc2..2be7327234 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerClient.cs @@ -26,7 +26,7 @@ using osu.Game.Utils; namespace osu.Game.Online.Multiplayer { - public abstract class MultiplayerClient : Component, IMultiplayerClient, IMultiplayerRoomServer + public abstract partial class MultiplayerClient : Component, IMultiplayerClient, IMultiplayerRoomServer { public Action? PostNotification { protected get; set; } @@ -822,7 +822,7 @@ namespace osu.Game.Online.Multiplayer { if (cancellationToken.IsCancellationRequested) { - tcs.SetCanceled(); + tcs.SetCanceled(cancellationToken); return; } diff --git a/osu.Game/Online/Multiplayer/MultiplayerRoomUser.cs b/osu.Game/Online/Multiplayer/MultiplayerRoomUser.cs index 681a839b89..d70a2797c4 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerRoomUser.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerRoomUser.cs @@ -54,10 +54,10 @@ namespace osu.Game.Online.Multiplayer return UserID == other.UserID; } - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != GetType()) return false; + if (obj?.GetType() != GetType()) return false; return Equals((MultiplayerRoomUser)obj); } diff --git a/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs b/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs index 190d150502..8ff0ce4065 100644 --- a/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs @@ -18,7 +18,7 @@ namespace osu.Game.Online.Multiplayer /// /// A with online connectivity. /// - public class OnlineMultiplayerClient : MultiplayerClient + public partial class OnlineMultiplayerClient : MultiplayerClient { private readonly string endpoint; @@ -80,7 +80,7 @@ namespace osu.Game.Online.Multiplayer try { - return await connection.InvokeAsync(nameof(IMultiplayerServer.JoinRoomWithPassword), roomId, password ?? string.Empty); + return await connection.InvokeAsync(nameof(IMultiplayerServer.JoinRoomWithPassword), roomId, password ?? string.Empty).ConfigureAwait(false); } catch (HubException exception) { @@ -88,8 +88,8 @@ namespace osu.Game.Online.Multiplayer { Debug.Assert(connector != null); - await connector.Reconnect(); - return await JoinRoom(roomId, password); + await connector.Reconnect().ConfigureAwait(false); + return await JoinRoom(roomId, password).ConfigureAwait(false); } throw; diff --git a/osu.Game/Online/Multiplayer/ServerShutdownNotification.cs b/osu.Game/Online/Multiplayer/ServerShutdownNotification.cs index c114741be8..1de18e44a7 100644 --- a/osu.Game/Online/Multiplayer/ServerShutdownNotification.cs +++ b/osu.Game/Online/Multiplayer/ServerShutdownNotification.cs @@ -10,7 +10,7 @@ using osu.Game.Utils; namespace osu.Game.Online.Multiplayer { - public class ServerShutdownNotification : SimpleNotification + public partial class ServerShutdownNotification : SimpleNotification { private readonly DateTimeOffset endDate; private ScheduledDelegate? updateDelegate; diff --git a/osu.Game/Online/Notifications/NotificationsClient.cs b/osu.Game/Online/Notifications/NotificationsClient.cs index 6198707111..5762e0e588 100644 --- a/osu.Game/Online/Notifications/NotificationsClient.cs +++ b/osu.Game/Online/Notifications/NotificationsClient.cs @@ -33,11 +33,11 @@ namespace osu.Game.Online.Notifications public override Task ConnectAsync(CancellationToken cancellationToken) { - API.Queue(CreateFetchMessagesRequest(0)); + API.Queue(CreateInitialFetchRequest(0)); return Task.CompletedTask; } - protected APIRequest CreateFetchMessagesRequest(long? lastMessageId = null) + protected APIRequest CreateInitialFetchRequest(long? lastMessageId = null) { var fetchReq = new GetUpdatesRequest(lastMessageId ?? this.lastMessageId); @@ -67,8 +67,11 @@ namespace osu.Game.Online.Notifications protected void HandleChannelParted(Channel channel) => ChannelParted?.Invoke(channel); - protected void HandleMessages(List messages) + protected void HandleMessages(List? messages) { + if (messages == null) + return; + NewMessages?.Invoke(messages); lastMessageId = Math.Max(lastMessageId, messages.LastOrDefault()?.Id ?? 0); } diff --git a/osu.Game/Online/Notifications/NotificationsClientConnector.cs b/osu.Game/Online/Notifications/NotificationsClientConnector.cs index d2c2e6673c..34ce186cb8 100644 --- a/osu.Game/Online/Notifications/NotificationsClientConnector.cs +++ b/osu.Game/Online/Notifications/NotificationsClientConnector.cs @@ -27,7 +27,7 @@ namespace osu.Game.Online.Notifications protected sealed override async Task BuildConnectionAsync(CancellationToken cancellationToken) { - var client = await BuildNotificationClientAsync(cancellationToken); + var client = await BuildNotificationClientAsync(cancellationToken).ConfigureAwait(false); client.ChannelJoined = c => ChannelJoined?.Invoke(c); client.ChannelParted = c => ChannelParted?.Invoke(c); diff --git a/osu.Game/Online/Notifications/WebSocket/WebSocketNotificationsClient.cs b/osu.Game/Online/Notifications/WebSocket/WebSocketNotificationsClient.cs index d8d78297e3..73e5dcec6f 100644 --- a/osu.Game/Online/Notifications/WebSocket/WebSocketNotificationsClient.cs +++ b/osu.Game/Online/Notifications/WebSocket/WebSocketNotificationsClient.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Concurrent; using System.Diagnostics; +using System.Net; using System.Net.WebSockets; using System.Text; using System.Threading; @@ -36,11 +37,11 @@ namespace osu.Game.Online.Notifications.WebSocket public override async Task ConnectAsync(CancellationToken cancellationToken) { await socket.ConnectAsync(new Uri(endpoint), cancellationToken).ConfigureAwait(false); - await sendMessage(new StartChatRequest(), CancellationToken.None); + await sendMessage(new StartChatRequest(), CancellationToken.None).ConfigureAwait(false); runReadLoop(cancellationToken); - await base.ConnectAsync(cancellationToken); + await base.ConnectAsync(cancellationToken).ConfigureAwait(false); } private void runReadLoop(CancellationToken cancellationToken) => Task.Run(async () => @@ -52,7 +53,7 @@ namespace osu.Game.Online.Notifications.WebSocket { try { - WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, cancellationToken); + WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, cancellationToken).ConfigureAwait(false); switch (result.MessageType) { @@ -72,7 +73,7 @@ namespace osu.Game.Online.Notifications.WebSocket break; } - await onMessageReceivedAsync(message); + await onMessageReceivedAsync(message).ConfigureAwait(false); } break; @@ -81,12 +82,12 @@ namespace osu.Game.Online.Notifications.WebSocket throw new NotImplementedException("Binary message type not supported."); case WebSocketMessageType.Close: - throw new Exception("Connection closed by remote host."); + throw new WebException("Connection closed by remote host."); } } catch (Exception ex) { - await InvokeClosed(ex); + await InvokeClosed(ex).ConfigureAwait(false); return; } } @@ -109,7 +110,7 @@ namespace osu.Game.Online.Notifications.WebSocket if (socket.State != WebSocketState.Open) return; - await socket.SendAsync(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(message)), WebSocketMessageType.Text, true, cancellationToken); + await socket.SendAsync(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(message)), WebSocketMessageType.Text, true, cancellationToken).ConfigureAwait(false); } private async Task onMessageReceivedAsync(SocketMessage message) @@ -141,7 +142,7 @@ namespace osu.Game.Online.Notifications.WebSocket Debug.Assert(messageData != null); foreach (var msg in messageData.Messages) - HandleChannelJoined(await getChannel(msg.ChannelId)); + HandleChannelJoined(await getChannel(msg.ChannelId).ConfigureAwait(false)); HandleMessages(messageData.Messages); break; @@ -150,7 +151,7 @@ namespace osu.Game.Online.Notifications.WebSocket private async Task getChannel(long channelId) { - if (channelsMap.TryGetValue(channelId, out Channel channel)) + if (channelsMap.TryGetValue(channelId, out Channel? channel)) return channel; var tsc = new TaskCompletionSource(); @@ -166,13 +167,13 @@ namespace osu.Game.Online.Notifications.WebSocket API.Queue(req); - return await tsc.Task; + return await tsc.Task.ConfigureAwait(false); } public override async ValueTask DisposeAsync() { - await base.DisposeAsync(); - await closeAsync(); + await base.DisposeAsync().ConfigureAwait(false); + await closeAsync().ConfigureAwait(false); socket.Dispose(); } } diff --git a/osu.Game/Online/Notifications/WebSocket/WebSocketNotificationsClientConnector.cs b/osu.Game/Online/Notifications/WebSocket/WebSocketNotificationsClientConnector.cs index 21335a3b59..f50369a06c 100644 --- a/osu.Game/Online/Notifications/WebSocket/WebSocketNotificationsClientConnector.cs +++ b/osu.Game/Online/Notifications/WebSocket/WebSocketNotificationsClientConnector.cs @@ -32,7 +32,7 @@ namespace osu.Game.Online.Notifications.WebSocket req.Failure += ex => tcs.SetException(ex); api.Queue(req); - string endpoint = await tcs.Task; + string endpoint = await tcs.Task.ConfigureAwait(false); ClientWebSocket socket = new ClientWebSocket(); socket.Options.SetRequestHeader(@"Authorization", @$"Bearer {api.AccessToken}"); diff --git a/osu.Game/Online/OnlineViewContainer.cs b/osu.Game/Online/OnlineViewContainer.cs index 7af1ac9d5d..46f64fbb61 100644 --- a/osu.Game/Online/OnlineViewContainer.cs +++ b/osu.Game/Online/OnlineViewContainer.cs @@ -17,7 +17,7 @@ namespace osu.Game.Online /// A for displaying online content which require a local user to be logged in. /// Shows its children only when the local user is logged in and supports displaying a placeholder if not. /// - public class OnlineViewContainer : Container + public partial class OnlineViewContainer : Container { protected LoadingSpinner LoadingSpinner { get; private set; } diff --git a/osu.Game/Online/PersistentEndpointClientConnector.cs b/osu.Game/Online/PersistentEndpointClientConnector.cs index be76644745..e33924047d 100644 --- a/osu.Game/Online/PersistentEndpointClientConnector.cs +++ b/osu.Game/Online/PersistentEndpointClientConnector.cs @@ -65,11 +65,11 @@ namespace osu.Game.Online { case APIState.Failing: case APIState.Offline: - await disconnect(true); + await disconnect(true).ConfigureAwait(true); break; case APIState.Online: - await connect(); + await connect().ConfigureAwait(true); break; } } @@ -147,10 +147,10 @@ namespace osu.Game.Online { bool hasBeenCancelled = cancellationToken.IsCancellationRequested; - await disconnect(true); + await disconnect(true).ConfigureAwait(false); if (ex != null) - await handleErrorAndDelay(ex, cancellationToken).ConfigureAwait(false); + await handleErrorAndDelay(ex, CancellationToken.None).ConfigureAwait(false); else Logger.Log($"{ClientName} disconnected", LoggingTarget.Network); diff --git a/osu.Game/Online/Placeholders/ClickablePlaceholder.cs b/osu.Game/Online/Placeholders/ClickablePlaceholder.cs index 7f9e16399e..9bef1d4b7a 100644 --- a/osu.Game/Online/Placeholders/ClickablePlaceholder.cs +++ b/osu.Game/Online/Placeholders/ClickablePlaceholder.cs @@ -11,7 +11,7 @@ using osu.Game.Graphics.UserInterface; namespace osu.Game.Online.Placeholders { - public class ClickablePlaceholder : Placeholder + public partial class ClickablePlaceholder : Placeholder { public Action Action; diff --git a/osu.Game/Online/Placeholders/LoginPlaceholder.cs b/osu.Game/Online/Placeholders/LoginPlaceholder.cs index 6a4065208e..de7ac6e936 100644 --- a/osu.Game/Online/Placeholders/LoginPlaceholder.cs +++ b/osu.Game/Online/Placeholders/LoginPlaceholder.cs @@ -10,7 +10,7 @@ using osu.Game.Overlays; namespace osu.Game.Online.Placeholders { - public sealed class LoginPlaceholder : ClickablePlaceholder + public sealed partial class LoginPlaceholder : ClickablePlaceholder { [Resolved(CanBeNull = true)] private LoginOverlay login { get; set; } diff --git a/osu.Game/Online/Placeholders/MessagePlaceholder.cs b/osu.Game/Online/Placeholders/MessagePlaceholder.cs index 451a4cba85..07a111a10f 100644 --- a/osu.Game/Online/Placeholders/MessagePlaceholder.cs +++ b/osu.Game/Online/Placeholders/MessagePlaceholder.cs @@ -9,7 +9,7 @@ using osu.Framework.Localisation; namespace osu.Game.Online.Placeholders { - public class MessagePlaceholder : Placeholder + public partial class MessagePlaceholder : Placeholder { private readonly LocalisableString message; diff --git a/osu.Game/Online/Placeholders/Placeholder.cs b/osu.Game/Online/Placeholders/Placeholder.cs index 3a05ce1365..37669fb899 100644 --- a/osu.Game/Online/Placeholders/Placeholder.cs +++ b/osu.Game/Online/Placeholders/Placeholder.cs @@ -9,7 +9,7 @@ using osu.Game.Graphics.Containers; namespace osu.Game.Online.Placeholders { - public abstract class Placeholder : OsuTextFlowContainer, IEquatable + public abstract partial class Placeholder : OsuTextFlowContainer, IEquatable { protected const float TEXT_SIZE = 22; diff --git a/osu.Game/Online/PollingComponent.cs b/osu.Game/Online/PollingComponent.cs index fcea650e2d..a44308c726 100644 --- a/osu.Game/Online/PollingComponent.cs +++ b/osu.Game/Online/PollingComponent.cs @@ -16,7 +16,7 @@ namespace osu.Game.Online /// /// A component which requires a constant polling process. /// - public abstract class PollingComponent : CompositeComponent + public abstract partial class PollingComponent : CompositeComponent { private double? lastTimePolled; diff --git a/osu.Game/Online/ProductionEndpointConfiguration.cs b/osu.Game/Online/ProductionEndpointConfiguration.cs index 316452280d..003ec50afd 100644 --- a/osu.Game/Online/ProductionEndpointConfiguration.cs +++ b/osu.Game/Online/ProductionEndpointConfiguration.cs @@ -9,7 +9,8 @@ namespace osu.Game.Online { public ProductionEndpointConfiguration() { - WebsiteRootUrl = APIEndpointUrl = @"https://osu.ppy.sh"; + WebsiteRootUrl = @"https://osu.ppy.sh"; + APIEndpointUrl = @"https://lazer.ppy.sh"; APIClientSecret = @"FGc9GAtyHzeQDshWP5Ah7dega8hJACAJpQtw6OXk"; APIClientID = "5"; SpectatorEndpointUrl = "https://spectator.ppy.sh/spectator"; diff --git a/osu.Game/Online/Rooms/APICreatedRoom.cs b/osu.Game/Online/Rooms/APICreatedRoom.cs index ca1179efeb..254a338a60 100644 --- a/osu.Game/Online/Rooms/APICreatedRoom.cs +++ b/osu.Game/Online/Rooms/APICreatedRoom.cs @@ -7,7 +7,7 @@ using Newtonsoft.Json; namespace osu.Game.Online.Rooms { - public class APICreatedRoom : Room + public partial class APICreatedRoom : Room { [JsonProperty("error")] public string Error { get; set; } diff --git a/osu.Game/Online/Rooms/OnlinePlayBeatmapAvailabilityTracker.cs b/osu.Game/Online/Rooms/OnlinePlayBeatmapAvailabilityTracker.cs index 7f8f9703e4..1d496cc636 100644 --- a/osu.Game/Online/Rooms/OnlinePlayBeatmapAvailabilityTracker.cs +++ b/osu.Game/Online/Rooms/OnlinePlayBeatmapAvailabilityTracker.cs @@ -27,7 +27,7 @@ namespace osu.Game.Online.Rooms /// This differs from a regular download tracking composite as this accounts for the /// databased beatmap set's checksum, to disallow from playing with an altered version of the beatmap. /// - public class OnlinePlayBeatmapAvailabilityTracker : CompositeComponent + public partial class OnlinePlayBeatmapAvailabilityTracker : CompositeComponent { public readonly IBindable SelectedItem = new Bindable(); diff --git a/osu.Game/Online/Rooms/Room.cs b/osu.Game/Online/Rooms/Room.cs index adfd4c226a..8f346c4057 100644 --- a/osu.Game/Online/Rooms/Room.cs +++ b/osu.Game/Online/Rooms/Room.cs @@ -16,7 +16,7 @@ using osu.Game.Online.Rooms.RoomStatuses; namespace osu.Game.Online.Rooms { [JsonObject(MemberSerialization.OptIn)] - public class Room + public partial class Room : IDependencyInjectionCandidate { [Cached] [JsonProperty("id")] diff --git a/osu.Game/Online/ScoreDownloadTracker.cs b/osu.Game/Online/ScoreDownloadTracker.cs index 680bb16264..4ddcb40368 100644 --- a/osu.Game/Online/ScoreDownloadTracker.cs +++ b/osu.Game/Online/ScoreDownloadTracker.cs @@ -11,7 +11,7 @@ using osu.Game.Scoring; namespace osu.Game.Online { - public class ScoreDownloadTracker : DownloadTracker + public partial class ScoreDownloadTracker : DownloadTracker { [Resolved(CanBeNull = true)] protected ScoreModelDownloader? Downloader { get; private set; } diff --git a/osu.Game/Online/SignalRDerivedTypeWorkaroundJsonConverter.cs b/osu.Game/Online/SignalRDerivedTypeWorkaroundJsonConverter.cs index a999cb47f8..86708bee82 100644 --- a/osu.Game/Online/SignalRDerivedTypeWorkaroundJsonConverter.cs +++ b/osu.Game/Online/SignalRDerivedTypeWorkaroundJsonConverter.cs @@ -33,7 +33,8 @@ namespace osu.Game.Online object? instance = Activator.CreateInstance(resolvedType); - jsonSerializer.Populate(obj["$value"]!.CreateReader(), instance); + if (instance != null) + jsonSerializer.Populate(obj["$value"]!.CreateReader(), instance); return instance; } diff --git a/osu.Game/Online/Solo/SoloStatisticsUpdate.cs b/osu.Game/Online/Solo/SoloStatisticsUpdate.cs new file mode 100644 index 0000000000..cb9dac97c7 --- /dev/null +++ b/osu.Game/Online/Solo/SoloStatisticsUpdate.cs @@ -0,0 +1,42 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Scoring; +using osu.Game.Users; + +namespace osu.Game.Online.Solo +{ + /// + /// Contains data about the change in a user's profile statistics after completing a score. + /// + public class SoloStatisticsUpdate + { + /// + /// The score set by the user that triggered the update. + /// + public ScoreInfo Score { get; } + + /// + /// The user's profile statistics prior to the score being set. + /// + public UserStatistics Before { get; } + + /// + /// The user's profile statistics after the score was set. + /// + public UserStatistics After { get; } + + /// + /// Creates a new . + /// + /// The score set by the user that triggered the update. + /// The user's profile statistics prior to the score being set. + /// The user's profile statistics after the score was set. + public SoloStatisticsUpdate(ScoreInfo score, UserStatistics before, UserStatistics after) + { + Score = score; + Before = before; + After = after; + } + } +} diff --git a/osu.Game/Online/Solo/SoloStatisticsWatcher.cs b/osu.Game/Online/Solo/SoloStatisticsWatcher.cs new file mode 100644 index 0000000000..46449fea73 --- /dev/null +++ b/osu.Game/Online/Solo/SoloStatisticsWatcher.cs @@ -0,0 +1,162 @@ +// Copyright (c) ppy Pty Ltd . 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.Extensions.ObjectExtensions; +using osu.Framework.Graphics; +using osu.Game.Extensions; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests; +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Online.Spectator; +using osu.Game.Scoring; +using osu.Game.Users; + +namespace osu.Game.Online.Solo +{ + /// + /// A persistent component that binds to the spectator server and API in order to deliver updates about the logged in user's gameplay statistics. + /// + public partial class SoloStatisticsWatcher : Component + { + [Resolved] + private SpectatorClient spectatorClient { get; set; } = null!; + + [Resolved] + private IAPIProvider api { get; set; } = null!; + + private readonly Dictionary callbacks = new Dictionary(); + private long? lastProcessedScoreId; + + private Dictionary? latestStatistics; + + protected override void LoadComplete() + { + base.LoadComplete(); + + api.LocalUser.BindValueChanged(user => onUserChanged(user.NewValue), true); + spectatorClient.OnUserScoreProcessed += userScoreProcessed; + } + + /// + /// Registers for a user statistics update after the given has been processed server-side. + /// + /// The score to listen for the statistics update for. + /// The callback to be invoked once the statistics update has been prepared. + /// An representing the subscription. Disposing it is equivalent to unsubscribing from future notifications. + public IDisposable RegisterForStatisticsUpdateAfter(ScoreInfo score, Action onUpdateReady) + { + Schedule(() => + { + if (!api.IsLoggedIn) + return; + + if (!score.Ruleset.IsLegacyRuleset() || score.OnlineID <= 0) + return; + + var callback = new StatisticsUpdateCallback(score, onUpdateReady); + + if (lastProcessedScoreId == score.OnlineID) + { + requestStatisticsUpdate(api.LocalUser.Value.Id, callback); + return; + } + + callbacks.Add(score.OnlineID, callback); + }); + + return new InvokeOnDisposal(() => Schedule(() => callbacks.Remove(score.OnlineID))); + } + + private void onUserChanged(APIUser? localUser) => Schedule(() => + { + callbacks.Clear(); + lastProcessedScoreId = null; + latestStatistics = null; + + if (localUser == null || localUser.OnlineID <= 1) + return; + + var userRequest = new GetUsersRequest(new[] { localUser.OnlineID }); + userRequest.Success += initialiseUserStatistics; + api.Queue(userRequest); + }); + + private void initialiseUserStatistics(GetUsersResponse response) => Schedule(() => + { + var user = response.Users.SingleOrDefault(); + + // possible if the user is restricted or similar. + if (user == null) + return; + + latestStatistics = new Dictionary(); + + if (user.RulesetsStatistics != null) + { + foreach (var rulesetStats in user.RulesetsStatistics) + latestStatistics.Add(rulesetStats.Key, rulesetStats.Value); + } + }); + + private void userScoreProcessed(int userId, long scoreId) + { + if (userId != api.LocalUser.Value?.OnlineID) + return; + + lastProcessedScoreId = scoreId; + + if (!callbacks.TryGetValue(scoreId, out var callback)) + return; + + requestStatisticsUpdate(userId, callback); + callbacks.Remove(scoreId); + } + + private void requestStatisticsUpdate(int userId, StatisticsUpdateCallback callback) + { + var request = new GetUserRequest(userId, callback.Score.Ruleset); + request.Success += user => Schedule(() => dispatchStatisticsUpdate(callback, user.Statistics)); + api.Queue(request); + } + + private void dispatchStatisticsUpdate(StatisticsUpdateCallback callback, UserStatistics updatedStatistics) + { + string rulesetName = callback.Score.Ruleset.ShortName; + + if (latestStatistics == null) + return; + + latestStatistics.TryGetValue(rulesetName, out UserStatistics? latestRulesetStatistics); + latestRulesetStatistics ??= new UserStatistics(); + + var update = new SoloStatisticsUpdate(callback.Score, latestRulesetStatistics, updatedStatistics); + callback.OnUpdateReady.Invoke(update); + + latestStatistics[rulesetName] = updatedStatistics; + } + + protected override void Dispose(bool isDisposing) + { + if (spectatorClient.IsNotNull()) + spectatorClient.OnUserScoreProcessed -= userScoreProcessed; + + base.Dispose(isDisposing); + } + + private class StatisticsUpdateCallback + { + public ScoreInfo Score { get; } + public Action OnUpdateReady { get; } + + public StatisticsUpdateCallback(ScoreInfo score, Action onUpdateReady) + { + Score = score; + OnUpdateReady = onUpdateReady; + } + } + } +} diff --git a/osu.Game/Online/Spectator/ISpectatorClient.cs b/osu.Game/Online/Spectator/ISpectatorClient.cs index ccba280001..605ebc4ef0 100644 --- a/osu.Game/Online/Spectator/ISpectatorClient.cs +++ b/osu.Game/Online/Spectator/ISpectatorClient.cs @@ -32,5 +32,12 @@ namespace osu.Game.Online.Spectator /// The user. /// The frame data. Task UserSentFrames(int userId, FrameDataBundle data); + + /// + /// Signals that a user's submitted score was fully processed. + /// + /// The ID of the user who achieved the score. + /// The ID of the score. + Task UserScoreProcessed(int userId, long scoreId); } } diff --git a/osu.Game/Online/Spectator/ISpectatorServer.cs b/osu.Game/Online/Spectator/ISpectatorServer.cs index 25785f60a4..fa9d04792a 100644 --- a/osu.Game/Online/Spectator/ISpectatorServer.cs +++ b/osu.Game/Online/Spectator/ISpectatorServer.cs @@ -15,8 +15,9 @@ namespace osu.Game.Online.Spectator /// /// Signal the start of a new play session. /// + /// The score submission token. /// The state of gameplay. - Task BeginPlaySession(SpectatorState state); + Task BeginPlaySession(long? scoreToken, SpectatorState state); /// /// Send a bundle of frame data for the current play session. diff --git a/osu.Game/Online/Spectator/OnlineSpectatorClient.cs b/osu.Game/Online/Spectator/OnlineSpectatorClient.cs index 48d5c0bea9..3118e05053 100644 --- a/osu.Game/Online/Spectator/OnlineSpectatorClient.cs +++ b/osu.Game/Online/Spectator/OnlineSpectatorClient.cs @@ -12,7 +12,7 @@ using osu.Game.Online.Multiplayer; namespace osu.Game.Online.Spectator { - public class OnlineSpectatorClient : SpectatorClient + public partial class OnlineSpectatorClient : SpectatorClient { private readonly string endpoint; @@ -41,13 +41,14 @@ namespace osu.Game.Online.Spectator connection.On(nameof(ISpectatorClient.UserBeganPlaying), ((ISpectatorClient)this).UserBeganPlaying); connection.On(nameof(ISpectatorClient.UserSentFrames), ((ISpectatorClient)this).UserSentFrames); connection.On(nameof(ISpectatorClient.UserFinishedPlaying), ((ISpectatorClient)this).UserFinishedPlaying); + connection.On(nameof(ISpectatorClient.UserScoreProcessed), ((ISpectatorClient)this).UserScoreProcessed); }; IsConnected.BindTo(connector.IsConnected); } } - protected override async Task BeginPlayingInternal(SpectatorState state) + protected override async Task BeginPlayingInternal(long? scoreToken, SpectatorState state) { if (!IsConnected.Value) return; @@ -56,7 +57,7 @@ namespace osu.Game.Online.Spectator try { - await connection.InvokeAsync(nameof(ISpectatorServer.BeginPlaySession), state); + await connection.InvokeAsync(nameof(ISpectatorServer.BeginPlaySession), scoreToken, state).ConfigureAwait(false); } catch (Exception exception) { @@ -64,8 +65,8 @@ namespace osu.Game.Online.Spectator { Debug.Assert(connector != null); - await connector.Reconnect(); - await BeginPlayingInternal(state); + await connector.Reconnect().ConfigureAwait(false); + await BeginPlayingInternal(scoreToken, state).ConfigureAwait(false); } // Exceptions can occur if, for instance, the locally played beatmap doesn't have a server-side counterpart. diff --git a/osu.Game/Online/Spectator/SpectatorClient.cs b/osu.Game/Online/Spectator/SpectatorClient.cs index 592bae80ba..55ec75f4ce 100644 --- a/osu.Game/Online/Spectator/SpectatorClient.cs +++ b/osu.Game/Online/Spectator/SpectatorClient.cs @@ -21,7 +21,7 @@ using osu.Game.Screens.Play; namespace osu.Game.Online.Spectator { - public abstract class SpectatorClient : Component, ISpectatorClient + public abstract partial class SpectatorClient : Component, ISpectatorClient { /// /// The maximum milliseconds between frame bundle sends. @@ -47,7 +47,7 @@ namespace osu.Game.Online.Spectator /// /// Whether the local user is playing. /// - protected bool IsPlaying { get; private set; } + protected internal bool IsPlaying { get; private set; } /// /// Called whenever new frames arrive from the server. @@ -64,6 +64,11 @@ namespace osu.Game.Online.Spectator /// public virtual event Action? OnUserFinishedPlaying; + /// + /// Called whenever a user-submitted score has been fully processed. + /// + public virtual event Action? OnUserScoreProcessed; + /// /// A dictionary containing all users currently being watched, with the number of watching components for each user. /// @@ -76,6 +81,7 @@ namespace osu.Game.Online.Spectator private IBeatmap? currentBeatmap; private Score? currentScore; + private long? currentScoreToken; private readonly Queue pendingFrameBundles = new Queue(); @@ -108,7 +114,7 @@ namespace osu.Game.Online.Spectator // re-send state in case it wasn't received if (IsPlaying) // TODO: this is likely sent out of order after a reconnect scenario. needs further consideration. - BeginPlayingInternal(currentState); + BeginPlayingInternal(currentScoreToken, currentState); } else { @@ -159,7 +165,14 @@ namespace osu.Game.Online.Spectator return Task.CompletedTask; } - public void BeginPlaying(GameplayState state, Score score) + Task ISpectatorClient.UserScoreProcessed(int userId, long scoreId) + { + Schedule(() => OnUserScoreProcessed?.Invoke(userId, scoreId)); + + return Task.CompletedTask; + } + + public void BeginPlaying(long? scoreToken, GameplayState state, Score score) { // This schedule is only here to match the one below in `EndPlaying`. Schedule(() => @@ -174,12 +187,13 @@ namespace osu.Game.Online.Spectator currentState.RulesetID = score.ScoreInfo.RulesetID; currentState.Mods = score.ScoreInfo.Mods.Select(m => new APIMod(m)).ToArray(); currentState.State = SpectatedUserState.Playing; - currentState.MaximumScoringValues = state.ScoreProcessor.MaximumScoringValues; + currentState.MaximumStatistics = state.ScoreProcessor.MaximumStatistics; currentBeatmap = state.Beatmap; currentScore = score; + currentScoreToken = scoreToken; - BeginPlayingInternal(currentState); + BeginPlayingInternal(currentScoreToken, currentState); }); } @@ -264,7 +278,7 @@ namespace osu.Game.Online.Spectator }); } - protected abstract Task BeginPlayingInternal(SpectatorState state); + protected abstract Task BeginPlayingInternal(long? scoreToken, SpectatorState state); protected abstract Task SendFramesInternal(FrameDataBundle bundle); diff --git a/osu.Game/Online/Spectator/SpectatorScoreProcessor.cs b/osu.Game/Online/Spectator/SpectatorScoreProcessor.cs index 573c504add..1c505ea107 100644 --- a/osu.Game/Online/Spectator/SpectatorScoreProcessor.cs +++ b/osu.Game/Online/Spectator/SpectatorScoreProcessor.cs @@ -21,7 +21,7 @@ namespace osu.Game.Online.Spectator /// A wrapper over a for spectated users. /// This should be used when a local "playable" beatmap is unavailable or expensive to generate for the spectated user. /// - public class SpectatorScoreProcessor : Component + public partial class SpectatorScoreProcessor : Component { /// /// The current total score. @@ -152,12 +152,12 @@ namespace osu.Game.Online.Spectator scoreInfo.MaxCombo = frame.Header.MaxCombo; scoreInfo.Statistics = frame.Header.Statistics; + scoreInfo.MaximumStatistics = spectatorState.MaximumStatistics; Accuracy.Value = frame.Header.Accuracy; Combo.Value = frame.Header.Combo; - scoreProcessor.ExtractScoringValues(frame.Header, out var currentScoringValues, out _); - TotalScore.Value = scoreProcessor.ComputeScore(Mode.Value, currentScoringValues, spectatorState.MaximumScoringValues); + TotalScore.Value = scoreProcessor.ComputeScore(Mode.Value, scoreInfo); } protected override void Dispose(bool isDisposing) @@ -184,7 +184,7 @@ namespace osu.Game.Online.Spectator Header = header; } - public int CompareTo(TimedFrame other) => Time.CompareTo(other.Time); + public int CompareTo(TimedFrame? other) => Time.CompareTo(other?.Time); } } } diff --git a/osu.Game/Online/Spectator/SpectatorState.cs b/osu.Game/Online/Spectator/SpectatorState.cs index 766b274e63..91df05bf96 100644 --- a/osu.Game/Online/Spectator/SpectatorState.cs +++ b/osu.Game/Online/Spectator/SpectatorState.cs @@ -9,7 +9,7 @@ using System.Diagnostics.CodeAnalysis; using System.Linq; using MessagePack; using osu.Game.Online.API; -using osu.Game.Scoring; +using osu.Game.Rulesets.Scoring; namespace osu.Game.Online.Spectator { @@ -31,7 +31,7 @@ namespace osu.Game.Online.Spectator public SpectatedUserState State { get; set; } [Key(4)] - public ScoringValues MaximumScoringValues { get; set; } + public Dictionary MaximumStatistics { get; set; } = new Dictionary(); public bool Equals(SpectatorState other) { diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index a93c187e53..4113c9be8f 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -16,6 +16,7 @@ using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Bindables; using osu.Framework.Configuration; +using osu.Framework.Extensions; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Extensions.TypeExtensions; using osu.Framework.Graphics; @@ -45,6 +46,7 @@ using osu.Game.Online; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Chat; using osu.Game.Overlays; +using osu.Game.Overlays.BeatmapListing; using osu.Game.Overlays.Music; using osu.Game.Overlays.Notifications; using osu.Game.Overlays.Toolbar; @@ -71,7 +73,7 @@ namespace osu.Game /// for initial components that are generally retrieved via DI. /// [Cached(typeof(OsuGame))] - public class OsuGame : OsuGameBase, IKeyBindingHandler, ILocalUserPlayInfo, IPerformFromScreenRunner, IOverlayManager, ILinkHandler + public partial class OsuGame : OsuGameBase, IKeyBindingHandler, ILocalUserPlayInfo, IPerformFromScreenRunner, IOverlayManager, ILinkHandler { /// /// The amount of global offset to apply when a left/right anchored overlay is displayed (ie. settings or notifications). @@ -305,6 +307,13 @@ namespace osu.Game // Transfer any runtime changes back to configuration file. SkinManager.CurrentSkinInfo.ValueChanged += skin => configSkin.Value = skin.NewValue.ID.ToString(); + LocalUserPlaying.BindValueChanged(p => + { + BeatmapManager.PauseImports = p.NewValue; + SkinManager.PauseImports = p.NewValue; + ScoreManager.PauseImports = p.NewValue; + }, true); + IsActive.BindValueChanged(active => updateActiveState(active.NewValue), true); Audio.AddAdjustment(AdjustableProperty.Volume, inactiveVolumeFade); @@ -332,7 +341,7 @@ namespace osu.Game /// The link to load. public void HandleLink(LinkDetails link) => Schedule(() => { - string argString = link.Argument.ToString(); + string argString = link.Argument.ToString() ?? string.Empty; switch (link.Action) { @@ -352,7 +361,18 @@ namespace osu.Game break; case LinkAction.SearchBeatmapSet: - SearchBeatmapSet(argString); + if (link.Argument is RomanisableString romanisable) + SearchBeatmapSet(romanisable.GetPreferred(Localisation.CurrentParameters.Value.PreferOriginalScript)); + else + SearchBeatmapSet(argString); + break; + + case LinkAction.FilterBeatmapSetGenre: + FilterBeatmapSetGenre((SearchGenre)link.Argument); + break; + + case LinkAction.FilterBeatmapSetLanguage: + FilterBeatmapSetLanguage((SearchLanguage)link.Argument); break; case LinkAction.OpenEditorTimestamp: @@ -406,6 +426,16 @@ namespace osu.Game if (url.StartsWith('/')) url = $"{API.APIEndpointUrl}{url}"; + if (!url.CheckIsValidUrl()) + { + Notifications.Post(new SimpleErrorNotification + { + Text = $"The URL {url} has an unsupported or dangerous protocol and will not be opened.", + }); + + return; + } + externalLinkOpener.OpenUrlExternally(url, bypassExternalUrlWarning); }); @@ -449,6 +479,10 @@ namespace osu.Game /// The query to search for. public void SearchBeatmapSet(string query) => waitForReady(() => beatmapListing, _ => beatmapListing.ShowWithSearch(query)); + public void FilterBeatmapSetGenre(SearchGenre genre) => waitForReady(() => beatmapListing, _ => beatmapListing.ShowWithGenreFilter(genre)); + + public void FilterBeatmapSetLanguage(SearchLanguage language) => waitForReady(() => beatmapListing, _ => beatmapListing.ShowWithLanguageFilter(language)); + /// /// Show a wiki's page as an overlay /// @@ -520,11 +554,29 @@ namespace osu.Game } else { - Logger.Log($"Completing {nameof(PresentBeatmap)} with beatmap {beatmap} ruleset {selection.Ruleset}"); - Ruleset.Value = selection.Ruleset; - Beatmap.Value = BeatmapManager.GetWorkingBeatmap(selection); + // Don't change the local ruleset if the user is on another ruleset and is showing converted beatmaps at song select. + // Eventually we probably want to check whether conversion is actually possible for the current ruleset. + bool requiresRulesetSwitch = !selection.Ruleset.Equals(Ruleset.Value) + && (selection.Ruleset.OnlineID > 0 || !LocalConfig.Get(OsuSetting.ShowConvertedBeatmaps)); + + if (requiresRulesetSwitch) + { + Ruleset.Value = selection.Ruleset; + Beatmap.Value = BeatmapManager.GetWorkingBeatmap(selection); + + Logger.Log($"Completing {nameof(PresentBeatmap)} with beatmap {beatmap} ruleset {selection.Ruleset}"); + } + else + { + Beatmap.Value = BeatmapManager.GetWorkingBeatmap(selection); + + Logger.Log($"Completing {nameof(PresentBeatmap)} with beatmap {beatmap} (maintaining ruleset)"); + } } - }, validScreens: new[] { typeof(SongSelect), typeof(IHandlePresentBeatmap) }); + }, validScreens: new[] + { + typeof(SongSelect), typeof(IHandlePresentBeatmap) + }); } /// @@ -598,14 +650,14 @@ namespace osu.Game }, validScreens: validScreens); } - public override Task Import(params ImportTask[] imports) + public override Task Import(ImportTask[] imports, ImportParameters parameters = default) { // encapsulate task as we don't want to begin the import process until in a ready state. // ReSharper disable once AsyncVoidLambda // TODO: This is bad because `new Task` doesn't have a Func override. // Only used for android imports and a bit of a mess. Probably needs rethinking overall. - var importTask = new Task(async () => await base.Import(imports).ConfigureAwait(false)); + var importTask = new Task(async () => await base.Import(imports, parameters).ConfigureAwait(false)); waitForReady(() => this, _ => importTask.Start()); @@ -694,7 +746,7 @@ namespace osu.Game { base.LoadComplete(); - var languages = Enum.GetValues(typeof(Language)).OfType(); + var languages = Enum.GetValues(); var mappings = languages.Select(language => { @@ -881,9 +933,9 @@ namespace osu.Game loadComponentSingleFile(dashboard = new DashboardOverlay(), overlayContent.Add, true); loadComponentSingleFile(news = new NewsOverlay(), overlayContent.Add, true); var rankingsOverlay = loadComponentSingleFile(new RankingsOverlay(), overlayContent.Add, true); - loadComponentSingleFile(channelManager = new ChannelManager(API), AddInternal, true); + loadComponentSingleFile(channelManager = new ChannelManager(API), Add, true); loadComponentSingleFile(chatOverlay = new ChatOverlay(), overlayContent.Add, true); - loadComponentSingleFile(new MessageNotifier(), AddInternal, true); + loadComponentSingleFile(new MessageNotifier(), Add, true); loadComponentSingleFile(Settings = new SettingsOverlay(), leftFloatingOverlayContent.Add, true); loadComponentSingleFile(changelogOverlay = new ChangelogOverlay(), overlayContent.Add, true); loadComponentSingleFile(userProfile = new UserProfileOverlay(), overlayContent.Add, true); @@ -1011,7 +1063,7 @@ namespace osu.Game Logger.NewEntry += entry => { - if (entry.Level < LogLevel.Important || entry.Target > LoggingTarget.Database) return; + if (entry.Level < LogLevel.Important || entry.Target > LoggingTarget.Database || entry.Target == null) return; const int short_term_display_limit = 3; @@ -1025,7 +1077,7 @@ namespace osu.Game } else if (recentLogCount == short_term_display_limit) { - string logFile = $@"{entry.Target.ToString().ToLowerInvariant()}.log"; + string logFile = $@"{entry.Target.Value.ToString().ToLowerInvariant()}.log"; Schedule(() => Notifications.Post(new SimpleNotification { diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 1d5f5a75e5..b27be37591 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -46,6 +46,7 @@ using osu.Game.Online.API; using osu.Game.Online.Chat; using osu.Game.Online.Metadata; using osu.Game.Online.Multiplayer; +using osu.Game.Online.Solo; using osu.Game.Online.Spectator; using osu.Game.Overlays; using osu.Game.Overlays.Settings; @@ -83,6 +84,8 @@ namespace osu.Game public const int SAMPLE_CONCURRENCY = 6; + public const double SFX_STEREO_STRENGTH = 0.75; + /// /// Length of debounce (in milliseconds) for commonly occuring sample playbacks that could stack. /// @@ -186,11 +189,12 @@ namespace osu.Game private RulesetConfigCache rulesetConfigCache; - private SpectatorClient spectatorClient; + protected SpectatorClient SpectatorClient { get; private set; } protected MultiplayerClient MultiplayerClient { get; private set; } private MetadataClient metadataClient; + private SoloStatisticsWatcher soloStatisticsWatcher; private RealmAccess realm; @@ -292,27 +296,28 @@ namespace osu.Game dependencies.Cache(ScoreDownloader = new ScoreModelDownloader(ScoreManager, API)); // Add after all the above cache operations as it depends on them. - AddInternal(difficultyCache); + base.Content.Add(difficultyCache); // TODO: OsuGame or OsuGameBase? dependencies.CacheAs(beatmapUpdater = new BeatmapUpdater(BeatmapManager, difficultyCache, API, Storage)); - dependencies.CacheAs(spectatorClient = new OnlineSpectatorClient(endpoints)); + dependencies.CacheAs(SpectatorClient = new OnlineSpectatorClient(endpoints)); dependencies.CacheAs(MultiplayerClient = new OnlineMultiplayerClient(endpoints)); dependencies.CacheAs(metadataClient = new OnlineMetadataClient(endpoints)); + dependencies.CacheAs(soloStatisticsWatcher = new SoloStatisticsWatcher()); - AddInternal(new BeatmapOnlineChangeIngest(beatmapUpdater, realm, metadataClient)); + base.Content.Add(new BeatmapOnlineChangeIngest(beatmapUpdater, realm, metadataClient)); BeatmapManager.ProcessBeatmap = args => beatmapUpdater.Process(args.beatmapSet, !args.isBatch); dependencies.Cache(userCache = new UserLookupCache()); - AddInternal(userCache); + base.Content.Add(userCache); dependencies.Cache(beatmapCache = new BeatmapLookupCache()); - AddInternal(beatmapCache); + base.Content.Add(beatmapCache); var scorePerformanceManager = new ScorePerformanceCache(); dependencies.Cache(scorePerformanceManager); - AddInternal(scorePerformanceManager); + base.Content.Add(scorePerformanceManager); dependencies.CacheAs(rulesetConfigCache = new RulesetConfigCache(realm, RulesetStore)); @@ -339,13 +344,24 @@ namespace osu.Game // add api components to hierarchy. if (API is APIAccess apiAccess) - AddInternal(apiAccess); + base.Content.Add(apiAccess); - AddInternal(spectatorClient); - AddInternal(MultiplayerClient); - AddInternal(metadataClient); + base.Content.Add(SpectatorClient); + base.Content.Add(MultiplayerClient); + base.Content.Add(metadataClient); + base.Content.Add(soloStatisticsWatcher); - AddInternal(rulesetConfigCache); + base.Content.Add(rulesetConfigCache); + + PreviewTrackManager previewTrackManager; + dependencies.Cache(previewTrackManager = new PreviewTrackManager(BeatmapManager.BeatmapTrackStore)); + base.Content.Add(previewTrackManager); + + base.Content.Add(MusicController = new MusicController()); + dependencies.CacheAs(MusicController); + + MusicController.TrackChanged += onTrackChanged; + base.Content.Add(beatmapClock); GlobalActionContainer globalBindings; @@ -372,16 +388,6 @@ namespace osu.Game dependencies.Cache(globalBindings); - PreviewTrackManager previewTrackManager; - dependencies.Cache(previewTrackManager = new PreviewTrackManager(BeatmapManager.BeatmapTrackStore)); - Add(previewTrackManager); - - AddInternal(MusicController = new MusicController()); - dependencies.CacheAs(MusicController); - - MusicController.TrackChanged += onTrackChanged; - AddInternal(beatmapClock); - Ruleset.BindValueChanged(onRulesetChanged); Beatmap.BindValueChanged(onBeatmapChanged); } @@ -601,7 +607,7 @@ namespace osu.Game try { - foreach (ModType type in Enum.GetValues(typeof(ModType))) + foreach (ModType type in Enum.GetValues()) { dict[type] = instance.GetModsFor(type) // Rulesets should never return null mods, but let's be defensive just in case. diff --git a/osu.Game/OsuGameBase_Importing.cs b/osu.Game/OsuGameBase_Importing.cs index e34e48f21d..cf65460bab 100644 --- a/osu.Game/OsuGameBase_Importing.cs +++ b/osu.Game/OsuGameBase_Importing.cs @@ -44,13 +44,13 @@ namespace osu.Game } } - public virtual async Task Import(params ImportTask[] tasks) + public virtual async Task Import(ImportTask[] tasks, ImportParameters parameters = default) { var tasksPerExtension = tasks.GroupBy(t => Path.GetExtension(t.Path).ToLowerInvariant()); await Task.WhenAll(tasksPerExtension.Select(taskGroup => { var importer = fileImporters.FirstOrDefault(i => i.HandledExtensions.Contains(taskGroup.Key)); - return importer?.Import(taskGroup.ToArray()) ?? Task.CompletedTask; + return importer?.Import(taskGroup.ToArray(), parameters) ?? Task.CompletedTask; })).ConfigureAwait(false); } diff --git a/osu.Game/Overlays/AccountCreation/AccountCreationBackground.cs b/osu.Game/Overlays/AccountCreation/AccountCreationBackground.cs index 2b372c18eb..0042b9f8f6 100644 --- a/osu.Game/Overlays/AccountCreation/AccountCreationBackground.cs +++ b/osu.Game/Overlays/AccountCreation/AccountCreationBackground.cs @@ -10,7 +10,7 @@ using osu.Framework.Graphics.Textures; namespace osu.Game.Overlays.AccountCreation { - public class AccountCreationBackground : Sprite + public partial class AccountCreationBackground : Sprite { public AccountCreationBackground() { diff --git a/osu.Game/Overlays/AccountCreation/AccountCreationScreen.cs b/osu.Game/Overlays/AccountCreation/AccountCreationScreen.cs index 299a41f45b..a7dd53f511 100644 --- a/osu.Game/Overlays/AccountCreation/AccountCreationScreen.cs +++ b/osu.Game/Overlays/AccountCreation/AccountCreationScreen.cs @@ -8,7 +8,7 @@ using osu.Framework.Screens; namespace osu.Game.Overlays.AccountCreation { - public abstract class AccountCreationScreen : Screen + public abstract partial class AccountCreationScreen : Screen { public override void OnEntering(ScreenTransitionEvent e) { diff --git a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs index 2120f351a2..2e20f83e9e 100644 --- a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs +++ b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs @@ -25,7 +25,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.AccountCreation { - public class ScreenEntry : AccountCreationScreen + public partial class ScreenEntry : AccountCreationScreen { private ErrorTextFlowContainer usernameDescription; private ErrorTextFlowContainer emailAddressDescription; @@ -47,6 +47,9 @@ namespace osu.Game.Overlays.AccountCreation [Resolved] private GameHost host { get; set; } + [Resolved] + private OsuGame game { get; set; } + [BackgroundDependencyLoader] private void load() { @@ -194,9 +197,20 @@ namespace osu.Game.Overlays.AccountCreation { if (errors != null) { - usernameDescription.AddErrors(errors.User.Username); - emailAddressDescription.AddErrors(errors.User.Email); - passwordDescription.AddErrors(errors.User.Password); + if (errors.User != null) + { + usernameDescription.AddErrors(errors.User.Username); + emailAddressDescription.AddErrors(errors.User.Email); + passwordDescription.AddErrors(errors.User.Password); + } + + if (!string.IsNullOrEmpty(errors.Redirect)) + { + if (!string.IsNullOrEmpty(errors.Message)) + passwordDescription.AddErrors(new[] { errors.Message }); + + game.OpenUrlExternally($"{errors.Redirect}?username={usernameTextBox.Text}&email={emailTextBox.Text}"); + } } else { diff --git a/osu.Game/Overlays/AccountCreation/ScreenWarning.cs b/osu.Game/Overlays/AccountCreation/ScreenWarning.cs index f8070788c2..a833a871f9 100644 --- a/osu.Game/Overlays/AccountCreation/ScreenWarning.cs +++ b/osu.Game/Overlays/AccountCreation/ScreenWarning.cs @@ -20,7 +20,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.AccountCreation { - public class ScreenWarning : AccountCreationScreen + public partial class ScreenWarning : AccountCreationScreen { private OsuTextFlowContainer multiAccountExplanationText; private LinkFlowContainer furtherAssistance; diff --git a/osu.Game/Overlays/AccountCreation/ScreenWelcome.cs b/osu.Game/Overlays/AccountCreation/ScreenWelcome.cs index 1936ad533a..4becb225f8 100644 --- a/osu.Game/Overlays/AccountCreation/ScreenWelcome.cs +++ b/osu.Game/Overlays/AccountCreation/ScreenWelcome.cs @@ -15,7 +15,7 @@ using osuTK; namespace osu.Game.Overlays.AccountCreation { - public class ScreenWelcome : AccountCreationScreen + public partial class ScreenWelcome : AccountCreationScreen { [BackgroundDependencyLoader] private void load() diff --git a/osu.Game/Overlays/AccountCreationOverlay.cs b/osu.Game/Overlays/AccountCreationOverlay.cs index c51ed07c38..6f79316670 100644 --- a/osu.Game/Overlays/AccountCreationOverlay.cs +++ b/osu.Game/Overlays/AccountCreationOverlay.cs @@ -20,7 +20,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays { - public class AccountCreationOverlay : OsuFocusedOverlayContainer + public partial class AccountCreationOverlay : OsuFocusedOverlayContainer { private const float transition_time = 400; diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapListingCardSizeTabControl.cs b/osu.Game/Overlays/BeatmapListing/BeatmapListingCardSizeTabControl.cs index 13da9d335c..feb0c27ee7 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapListingCardSizeTabControl.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapListingCardSizeTabControl.cs @@ -17,7 +17,7 @@ using osuTK; namespace osu.Game.Overlays.BeatmapListing { - public class BeatmapListingCardSizeTabControl : OsuTabControl + public partial class BeatmapListingCardSizeTabControl : OsuTabControl { public BeatmapListingCardSizeTabControl() { @@ -35,7 +35,7 @@ namespace osu.Game.Overlays.BeatmapListing protected override TabItem CreateTabItem(BeatmapCardSize value) => new TabItem(value); - private class TabItem : TabItem + private partial class TabItem : TabItem { private Box background; private SpriteIcon icon; diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapListingFilterControl.cs b/osu.Game/Overlays/BeatmapListing/BeatmapListingFilterControl.cs index ff9a46ed4f..37a29b1c50 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapListingFilterControl.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapListingFilterControl.cs @@ -26,7 +26,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.BeatmapListing { - public class BeatmapListingFilterControl : CompositeDrawable + public partial class BeatmapListingFilterControl : CompositeDrawable { /// /// Fired when a search finishes. @@ -145,6 +145,12 @@ namespace osu.Game.Overlays.BeatmapListing public void Search(string query) => Schedule(() => searchControl.Query.Value = query); + public void FilterGenre(SearchGenre genre) + => Schedule(() => searchControl.Genre.Value = genre); + + public void FilterLanguage(SearchLanguage language) + => Schedule(() => searchControl.Language.Value = language); + protected override void LoadComplete() { base.LoadComplete(); diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapListingHeader.cs b/osu.Game/Overlays/BeatmapListing/BeatmapListingHeader.cs index ccab810612..76b6dec65b 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapListingHeader.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapListingHeader.cs @@ -8,11 +8,11 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.BeatmapListing { - public class BeatmapListingHeader : OverlayHeader + public partial class BeatmapListingHeader : OverlayHeader { protected override OverlayTitle CreateTitle() => new BeatmapListingTitle(); - private class BeatmapListingTitle : OverlayTitle + private partial class BeatmapListingTitle : OverlayTitle { public BeatmapListingTitle() { diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchControl.cs b/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchControl.cs index 86cf3b5588..23de1cf76d 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchControl.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchControl.cs @@ -24,7 +24,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.BeatmapListing { - public class BeatmapListingSearchControl : CompositeDrawable + public partial class BeatmapListingSearchControl : CompositeDrawable { /// /// Any time the text box receives key events (even while masked). @@ -146,6 +146,7 @@ namespace osu.Game.Overlays.BeatmapListing } }); + generalFilter.Current.Add(SearchGeneral.FeaturedArtists); categoryFilter.Current.Value = SearchCategory.Leaderboard; } @@ -165,7 +166,7 @@ namespace osu.Game.Overlays.BeatmapListing public void TakeFocus() => textBox.TakeFocus(); - private class BeatmapSearchTextBox : BasicSearchTextBox + private partial class BeatmapSearchTextBox : BasicSearchTextBox { /// /// Any time the text box receives key events (even while masked). @@ -198,7 +199,7 @@ namespace osu.Game.Overlays.BeatmapListing } } - private class TopSearchBeatmapSetCover : UpdateableOnlineBeatmapSetCover + private partial class TopSearchBeatmapSetCover : UpdateableOnlineBeatmapSetCover { protected override bool TransformImmediately => true; } diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapListingSortTabControl.cs b/osu.Game/Overlays/BeatmapListing/BeatmapListingSortTabControl.cs index bc1f30dcaf..34e0408db6 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapListingSortTabControl.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapListingSortTabControl.cs @@ -13,7 +13,7 @@ using osu.Framework.Input.Events; namespace osu.Game.Overlays.BeatmapListing { - public class BeatmapListingSortTabControl : OverlaySortTabControl + public partial class BeatmapListingSortTabControl : OverlaySortTabControl { public readonly Bindable SortDirection = new Bindable(Overlays.SortDirection.Descending); @@ -72,7 +72,7 @@ namespace osu.Game.Overlays.BeatmapListing SortDirection = { BindTarget = SortDirection }, }; - private class BeatmapSortTabControl : SortTabControl + private partial class BeatmapSortTabControl : SortTabControl { protected override bool AddEnumEntriesAutomatically => false; @@ -84,7 +84,7 @@ namespace osu.Game.Overlays.BeatmapListing }; } - private class BeatmapSortTabItem : SortTabItem + private partial class BeatmapSortTabItem : SortTabItem { public readonly Bindable SortDirection = new Bindable(); @@ -100,7 +100,7 @@ namespace osu.Game.Overlays.BeatmapListing }; } - private class BeatmapTabButton : TabButton + private partial class BeatmapTabButton : TabButton { public readonly Bindable SortDirection = new Bindable(); diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapSearchFilterRow.cs b/osu.Game/Overlays/BeatmapListing/BeatmapSearchFilterRow.cs index 8ae39aeaca..3ab0e47a6c 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapSearchFilterRow.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapSearchFilterRow.cs @@ -18,7 +18,7 @@ using osu.Framework.Localisation; namespace osu.Game.Overlays.BeatmapListing { - public class BeatmapSearchFilterRow : CompositeDrawable, IHasCurrentValue + public partial class BeatmapSearchFilterRow : CompositeDrawable, IHasCurrentValue { private readonly BindableWithCurrent current = new BindableWithCurrent(); @@ -69,7 +69,7 @@ namespace osu.Game.Overlays.BeatmapListing [NotNull] protected virtual Drawable CreateFilter() => new BeatmapSearchFilter(); - protected class BeatmapSearchFilter : TabControl + protected partial class BeatmapSearchFilter : TabControl { public BeatmapSearchFilter() { @@ -98,7 +98,7 @@ namespace osu.Game.Overlays.BeatmapListing protected override TabItem CreateTabItem(T value) => new FilterTabItem(value); - private class FilterDropdown : OsuTabDropdown + private partial class FilterDropdown : OsuTabDropdown { protected override DropdownHeader CreateHeader() => new FilterHeader { @@ -106,7 +106,7 @@ namespace osu.Game.Overlays.BeatmapListing Origin = Anchor.TopRight }; - private class FilterHeader : OsuTabDropdownHeader + private partial class FilterHeader : OsuTabDropdownHeader { public FilterHeader() { diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapSearchGeneralFilterRow.cs b/osu.Game/Overlays/BeatmapListing/BeatmapSearchGeneralFilterRow.cs index c01aa9a1c4..a4a914db55 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapSearchGeneralFilterRow.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapSearchGeneralFilterRow.cs @@ -3,14 +3,22 @@ #nullable disable +using System; using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Input.Events; +using osu.Game.Configuration; using osu.Game.Graphics; +using osu.Game.Localisation; +using osu.Game.Overlays.Dialog; using osu.Game.Resources.Localisation.Web; using osuTK.Graphics; +using CommonStrings = osu.Game.Resources.Localisation.Web.CommonStrings; namespace osu.Game.Overlays.BeatmapListing { - public class BeatmapSearchGeneralFilterRow : BeatmapSearchMultipleSelectionFilterRow + public partial class BeatmapSearchGeneralFilterRow : BeatmapSearchMultipleSelectionFilterRow { public BeatmapSearchGeneralFilterRow() : base(BeatmapsStrings.ListingSearchFiltersGeneral) @@ -19,7 +27,7 @@ namespace osu.Game.Overlays.BeatmapListing protected override MultipleSelectionFilter CreateMultipleSelectionFilter() => new GeneralFilter(); - private class GeneralFilter : MultipleSelectionFilter + private partial class GeneralFilter : MultipleSelectionFilter { protected override MultipleSelectionFilterTabItem CreateTabItem(SearchGeneral value) { @@ -30,8 +38,10 @@ namespace osu.Game.Overlays.BeatmapListing } } - private class FeaturedArtistsTabItem : MultipleSelectionFilterTabItem + private partial class FeaturedArtistsTabItem : MultipleSelectionFilterTabItem { + private Bindable disclaimerShown; + public FeaturedArtistsTabItem() : base(SearchGeneral.FeaturedArtists) { @@ -40,7 +50,60 @@ namespace osu.Game.Overlays.BeatmapListing [Resolved] private OsuColour colours { get; set; } + [Resolved] + private SessionStatics sessionStatics { get; set; } + + [Resolved(canBeNull: true)] + private IDialogOverlay dialogOverlay { get; set; } + protected override Color4 GetStateColour() => colours.Orange1; + + protected override void LoadComplete() + { + base.LoadComplete(); + + disclaimerShown = sessionStatics.GetBindable(Static.FeaturedArtistDisclaimerShownOnce); + } + + protected override bool OnClick(ClickEvent e) + { + if (!disclaimerShown.Value && dialogOverlay != null) + { + dialogOverlay.Push(new FeaturedArtistConfirmDialog(() => + { + disclaimerShown.Value = true; + base.OnClick(e); + })); + + return true; + } + + return base.OnClick(e); + } + } + } + + internal partial class FeaturedArtistConfirmDialog : PopupDialog + { + public FeaturedArtistConfirmDialog(Action confirm) + { + HeaderText = BeatmapOverlayStrings.UserContentDisclaimerHeader; + BodyText = BeatmapOverlayStrings.UserContentDisclaimerDescription; + + Icon = FontAwesome.Solid.ExclamationTriangle; + + Buttons = new PopupDialogButton[] + { + new PopupDialogDangerousButton + { + Text = BeatmapOverlayStrings.UserContentConfirmButtonText, + Action = confirm + }, + new PopupDialogCancelButton + { + Text = CommonStrings.ButtonsCancel, + }, + }; } } } diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapSearchMultipleSelectionFilterRow.cs b/osu.Game/Overlays/BeatmapListing/BeatmapSearchMultipleSelectionFilterRow.cs index cca75e9548..abd2643a41 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapSearchMultipleSelectionFilterRow.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapSearchMultipleSelectionFilterRow.cs @@ -5,19 +5,22 @@ using System; using System.Collections.Generic; +using System.Collections.Specialized; using System.Linq; using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; using osu.Framework.Localisation; using osuTK; namespace osu.Game.Overlays.BeatmapListing { - public class BeatmapSearchMultipleSelectionFilterRow : BeatmapSearchFilterRow> + public partial class BeatmapSearchMultipleSelectionFilterRow : BeatmapSearchFilterRow> + where T : Enum { public new readonly BindableList Current = new BindableList(); @@ -31,7 +34,7 @@ namespace osu.Game.Overlays.BeatmapListing [BackgroundDependencyLoader] private void load() { - Current.BindTo(filter.Current); + filter.Current.BindTo(Current); } protected sealed override Drawable CreateFilter() => filter = CreateMultipleSelectionFilter(); @@ -42,7 +45,7 @@ namespace osu.Game.Overlays.BeatmapListing [NotNull] protected virtual MultipleSelectionFilter CreateMultipleSelectionFilter() => new MultipleSelectionFilter(); - protected class MultipleSelectionFilter : FillFlowContainer + protected partial class MultipleSelectionFilter : FillFlowContainer { public readonly BindableList Current = new BindableList(); @@ -64,6 +67,14 @@ namespace osu.Game.Overlays.BeatmapListing foreach (var item in Children) item.Active.BindValueChanged(active => toggleItem(item.Value, active.NewValue)); + + Current.BindCollectionChanged(currentChanged, true); + } + + private void currentChanged(object sender, NotifyCollectionChangedEventArgs e) + { + foreach (var c in Children) + c.Active.Value = Current.Contains(c.Value); } /// @@ -79,17 +90,41 @@ namespace osu.Game.Overlays.BeatmapListing private void toggleItem(T value, bool active) { if (active) - Current.Add(value); + { + if (!Current.Contains(value)) + Current.Add(value); + } else Current.Remove(value); } } - protected class MultipleSelectionFilterTabItem : FilterTabItem + protected partial class MultipleSelectionFilterTabItem : FilterTabItem { + private readonly Box selectedUnderline; + + protected override bool HighlightOnHoverWhenActive => true; + public MultipleSelectionFilterTabItem(T value) : base(value) { + // This doesn't match any actual design, but should make it easier for the user to understand + // that filters are applied until we settle on a final design. + AddInternal(selectedUnderline = new Box + { + Depth = float.MaxValue, + RelativeSizeAxes = Axes.X, + Height = 1.5f, + Anchor = Anchor.BottomLeft, + Origin = Anchor.CentreLeft, + }); + } + + protected override void UpdateState() + { + base.UpdateState(); + selectedUnderline.FadeTo(Active.Value ? 1 : 0, 200, Easing.OutQuint); + selectedUnderline.FadeColour(IsHovered ? ColourProvider.Content2 : GetStateColour(), 200, Easing.OutQuint); } protected override bool OnClick(ClickEvent e) diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapSearchRulesetFilterRow.cs b/osu.Game/Overlays/BeatmapListing/BeatmapSearchRulesetFilterRow.cs index 526c14511e..96626d0ac6 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapSearchRulesetFilterRow.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapSearchRulesetFilterRow.cs @@ -6,12 +6,13 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; +using osu.Game.Extensions; using osu.Game.Resources.Localisation.Web; using osu.Game.Rulesets; namespace osu.Game.Overlays.BeatmapListing { - public class BeatmapSearchRulesetFilterRow : BeatmapSearchFilterRow + public partial class BeatmapSearchRulesetFilterRow : BeatmapSearchFilterRow { public BeatmapSearchRulesetFilterRow() : base(BeatmapsStrings.ListingSearchFiltersMode) @@ -20,7 +21,7 @@ namespace osu.Game.Overlays.BeatmapListing protected override Drawable CreateFilter() => new RulesetFilter(); - private class RulesetFilter : BeatmapSearchFilter + private partial class RulesetFilter : BeatmapSearchFilter { [BackgroundDependencyLoader] private void load(RulesetStore rulesets) @@ -28,11 +29,17 @@ namespace osu.Game.Overlays.BeatmapListing AddTabItem(new RulesetFilterTabItemAny()); foreach (var r in rulesets.AvailableRulesets) + { + // Don't display non-legacy rulesets + if (!r.IsLegacyRuleset()) + continue; + AddItem(r); + } } } - private class RulesetFilterTabItemAny : FilterTabItem + private partial class RulesetFilterTabItemAny : FilterTabItem { protected override LocalisableString LabelFor(RulesetInfo info) => BeatmapsStrings.ModeAny; diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapSearchScoreFilterRow.cs b/osu.Game/Overlays/BeatmapListing/BeatmapSearchScoreFilterRow.cs index 09b44be6c9..031833a107 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapSearchScoreFilterRow.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapSearchScoreFilterRow.cs @@ -12,7 +12,7 @@ using osu.Game.Scoring; namespace osu.Game.Overlays.BeatmapListing { - public class BeatmapSearchScoreFilterRow : BeatmapSearchMultipleSelectionFilterRow + public partial class BeatmapSearchScoreFilterRow : BeatmapSearchMultipleSelectionFilterRow { public BeatmapSearchScoreFilterRow() : base(BeatmapsStrings.ListingSearchFiltersRank) @@ -21,14 +21,14 @@ namespace osu.Game.Overlays.BeatmapListing protected override MultipleSelectionFilter CreateMultipleSelectionFilter() => new RankFilter(); - private class RankFilter : MultipleSelectionFilter + private partial class RankFilter : MultipleSelectionFilter { protected override MultipleSelectionFilterTabItem CreateTabItem(ScoreRank value) => new RankItem(value); protected override IEnumerable GetValues() => base.GetValues().Where(r => r > ScoreRank.F).Reverse(); } - private class RankItem : MultipleSelectionFilterTabItem + private partial class RankItem : MultipleSelectionFilterTabItem { public RankItem(ScoreRank value) : base(value) diff --git a/osu.Game/Overlays/BeatmapListing/FilterTabItem.cs b/osu.Game/Overlays/BeatmapListing/FilterTabItem.cs index cc131ffc27..c33d5056fa 100644 --- a/osu.Game/Overlays/BeatmapListing/FilterTabItem.cs +++ b/osu.Game/Overlays/BeatmapListing/FilterTabItem.cs @@ -17,10 +17,10 @@ using osuTK.Graphics; namespace osu.Game.Overlays.BeatmapListing { - public class FilterTabItem : TabItem + public partial class FilterTabItem : TabItem { [Resolved] - private OverlayColourProvider colourProvider { get; set; } + protected OverlayColourProvider ColourProvider { get; private set; } private OsuSpriteText text; @@ -52,38 +52,42 @@ namespace osu.Game.Overlays.BeatmapListing { base.LoadComplete(); - updateState(); + UpdateState(); FinishTransforms(true); } protected override bool OnHover(HoverEvent e) { base.OnHover(e); - updateState(); + UpdateState(); return true; } protected override void OnHoverLost(HoverLostEvent e) { base.OnHoverLost(e); - updateState(); + UpdateState(); } - protected override void OnActivated() => updateState(); + protected override void OnActivated() => UpdateState(); - protected override void OnDeactivated() => updateState(); + protected override void OnDeactivated() => UpdateState(); /// /// Returns the label text to be used for the supplied . /// protected virtual LocalisableString LabelFor(T value) => (value as Enum)?.GetLocalisableDescription() ?? value.ToString(); - private void updateState() + protected virtual bool HighlightOnHoverWhenActive => false; + + protected virtual void UpdateState() { - text.FadeColour(IsHovered ? colourProvider.Light1 : GetStateColour(), 200, Easing.OutQuint); - text.Font = text.Font.With(weight: Active.Value ? FontWeight.SemiBold : FontWeight.Regular); + bool highlightHover = IsHovered && (!Active.Value || HighlightOnHoverWhenActive); + + text.FadeColour(highlightHover ? ColourProvider.Content2 : GetStateColour(), 200, Easing.OutQuint); + text.Font = text.Font.With(weight: Active.Value ? FontWeight.Bold : FontWeight.Regular); } - protected virtual Color4 GetStateColour() => Active.Value ? colourProvider.Content1 : colourProvider.Light2; + protected virtual Color4 GetStateColour() => Active.Value ? ColourProvider.Content1 : ColourProvider.Light2; } } diff --git a/osu.Game/Overlays/BeatmapListingOverlay.cs b/osu.Game/Overlays/BeatmapListingOverlay.cs index 2d9583b864..73961487ed 100644 --- a/osu.Game/Overlays/BeatmapListingOverlay.cs +++ b/osu.Game/Overlays/BeatmapListingOverlay.cs @@ -31,7 +31,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays { - public class BeatmapListingOverlay : OnlineOverlay + public partial class BeatmapListingOverlay : OnlineOverlay { [Resolved] private PreviewTrackManager previewTrackManager { get; set; } @@ -110,6 +110,18 @@ namespace osu.Game.Overlays ScrollFlow.ScrollToStart(); } + public void ShowWithGenreFilter(SearchGenre genre) + { + ShowWithSearch(string.Empty); + filterControl.FilterGenre(genre); + } + + public void ShowWithLanguageFilter(SearchLanguage language) + { + ShowWithSearch(string.Empty); + filterControl.FilterLanguage(language); + } + protected override BeatmapListingHeader CreateHeader() => new BeatmapListingHeader(); protected override Color4 BackgroundColour => ColourProvider.Background6; @@ -248,7 +260,7 @@ namespace osu.Game.Overlays base.Dispose(isDisposing); } - public class NotFoundDrawable : CompositeDrawable + public partial class NotFoundDrawable : CompositeDrawable { public NotFoundDrawable() { @@ -292,7 +304,7 @@ namespace osu.Game.Overlays // TODO: localisation requires Text/LinkFlowContainer support for localising strings with links inside // (https://github.com/ppy/osu-framework/issues/4530) - public class SupporterRequiredDrawable : CompositeDrawable + public partial class SupporterRequiredDrawable : CompositeDrawable { private LinkFlowContainer supporterRequiredText; diff --git a/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs b/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs index 2341997626..1d01495188 100644 --- a/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs +++ b/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs @@ -21,7 +21,7 @@ using APIUser = osu.Game.Online.API.Requests.Responses.APIUser; namespace osu.Game.Overlays.BeatmapSet { - public class AuthorInfo : Container + public partial class AuthorInfo : Container { private const float height = 50; @@ -105,7 +105,7 @@ namespace osu.Game.Overlays.BeatmapSet } } - private class Field : FillFlowContainer + private partial class Field : FillFlowContainer { public Field(string first, string second, FontUsage secondFont) { diff --git a/osu.Game/Overlays/BeatmapSet/BasicStats.cs b/osu.Game/Overlays/BeatmapSet/BasicStats.cs index a8bbb9fe1c..4a9a3d8089 100644 --- a/osu.Game/Overlays/BeatmapSet/BasicStats.cs +++ b/osu.Game/Overlays/BeatmapSet/BasicStats.cs @@ -22,7 +22,7 @@ using osuTK; namespace osu.Game.Overlays.BeatmapSet { - public class BasicStats : Container + public partial class BasicStats : Container { private readonly Statistic length, bpm, circleCount, sliderCount; @@ -117,7 +117,7 @@ namespace osu.Game.Overlays.BeatmapSet updateDisplay(); } - private class Statistic : Container, IHasTooltip + private partial class Statistic : Container, IHasTooltip { private readonly OsuSpriteText value; diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapAvailability.cs b/osu.Game/Overlays/BeatmapSet/BeatmapAvailability.cs index d893ef80d8..d18e1c93c9 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapAvailability.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapAvailability.cs @@ -15,7 +15,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.BeatmapSet { - public class BeatmapAvailability : Container + public partial class BeatmapAvailability : Container { private APIBeatmapSet beatmapSet; diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapBadge.cs b/osu.Game/Overlays/BeatmapSet/BeatmapBadge.cs index 52fed99431..feb27aaa60 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapBadge.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapBadge.cs @@ -12,7 +12,7 @@ using osu.Game.Graphics.Sprites; namespace osu.Game.Overlays.BeatmapSet { - public abstract class BeatmapBadge : CompositeDrawable + public abstract partial class BeatmapBadge : CompositeDrawable { /// /// The text displayed on the badge's label. diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs index b27d9b3f1e..585e0dd1a2 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Linq; using osu.Framework; @@ -27,7 +25,7 @@ using osuTK; namespace osu.Game.Overlays.BeatmapSet { - public class BeatmapPicker : Container + public partial class BeatmapPicker : Container { private const float tile_icon_padding = 7; private const float tile_spacing = 2; @@ -38,10 +36,10 @@ namespace osu.Game.Overlays.BeatmapSet public readonly DifficultiesContainer Difficulties; - public readonly Bindable Beatmap = new Bindable(); - private APIBeatmapSet beatmapSet; + public readonly Bindable Beatmap = new Bindable(); + private APIBeatmapSet? beatmapSet; - public APIBeatmapSet BeatmapSet + public APIBeatmapSet? BeatmapSet { get => beatmapSet; set @@ -142,7 +140,7 @@ namespace osu.Game.Overlays.BeatmapSet } [Resolved] - private IBindable ruleset { get; set; } + private IBindable ruleset { get; set; } = null!; [BackgroundDependencyLoader] private void load(OsuColour colours) @@ -168,10 +166,11 @@ namespace osu.Game.Overlays.BeatmapSet if (BeatmapSet != null) { - Difficulties.ChildrenEnumerable = BeatmapSet.Beatmaps + Difficulties.ChildrenEnumerable = BeatmapSet.Beatmaps.Concat(BeatmapSet.Converts ?? Array.Empty()) .Where(b => b.Ruleset.MatchesOnlineID(ruleset.Value)) - .OrderBy(b => b.StarRating) - .Select(b => new DifficultySelectorButton(b) + .OrderBy(b => !b.Convert) + .ThenBy(b => b.StarRating) + .Select(b => new DifficultySelectorButton(b, b.Convert ? new RulesetInfo { OnlineID = 0 } : null) { State = DifficultySelectorState.NotSelected, OnHovered = beatmap => @@ -199,9 +198,9 @@ namespace osu.Game.Overlays.BeatmapSet updateDifficultyButtons(); } - private void showBeatmap(IBeatmapInfo beatmapInfo) + private void showBeatmap(IBeatmapInfo? beatmapInfo) { - version.Text = beatmapInfo?.DifficultyName; + version.Text = beatmapInfo?.DifficultyName ?? string.Empty; } private void updateDifficultyButtons() @@ -209,9 +208,9 @@ namespace osu.Game.Overlays.BeatmapSet Difficulties.Children.ToList().ForEach(diff => diff.State = diff.Beatmap == Beatmap.Value ? DifficultySelectorState.Selected : DifficultySelectorState.NotSelected); } - public class DifficultiesContainer : FillFlowContainer + public partial class DifficultiesContainer : FillFlowContainer { - public Action OnLostHover; + public Action? OnLostHover; protected override void OnHoverLost(HoverLostEvent e) { @@ -220,7 +219,7 @@ namespace osu.Game.Overlays.BeatmapSet } } - public class DifficultySelectorButton : OsuClickableContainer, IStateful + public partial class DifficultySelectorButton : OsuClickableContainer, IStateful { private const float transition_duration = 100; private const float size = 54; @@ -232,9 +231,9 @@ namespace osu.Game.Overlays.BeatmapSet public readonly APIBeatmap Beatmap; - public Action OnHovered; - public Action OnClicked; - public event Action StateChanged; + public Action? OnHovered; + public Action? OnClicked; + public event Action? StateChanged; private DifficultySelectorState state; @@ -255,7 +254,7 @@ namespace osu.Game.Overlays.BeatmapSet } } - public DifficultySelectorButton(APIBeatmap beatmapInfo) + public DifficultySelectorButton(APIBeatmap beatmapInfo, IRulesetInfo? ruleset) { Beatmap = beatmapInfo; Size = new Vector2(size); @@ -274,7 +273,7 @@ namespace osu.Game.Overlays.BeatmapSet Alpha = 0.5f } }, - icon = new DifficultyIcon(beatmapInfo) + icon = new DifficultyIcon(beatmapInfo, ruleset) { ShowTooltip = false, Current = { Value = new StarDifficulty(beatmapInfo.StarRating, 0) }, @@ -325,7 +324,7 @@ namespace osu.Game.Overlays.BeatmapSet } } - private class Statistic : FillFlowContainer + private partial class Statistic : FillFlowContainer { private readonly OsuSpriteText text; diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs b/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs index 0f5eb18c4e..9291988367 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs @@ -11,7 +11,7 @@ using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Overlays.BeatmapSet { - public class BeatmapRulesetSelector : OverlayRulesetSelector + public partial class BeatmapRulesetSelector : OverlayRulesetSelector { private readonly Bindable beatmapSet = new Bindable(); diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapRulesetTabItem.cs b/osu.Game/Overlays/BeatmapSet/BeatmapRulesetTabItem.cs index e9acca5bcd..76e2f256b0 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapRulesetTabItem.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapRulesetTabItem.cs @@ -17,7 +17,7 @@ using osu.Game.Rulesets; namespace osu.Game.Overlays.BeatmapSet { - public class BeatmapRulesetTabItem : OverlayRulesetTabItem + public partial class BeatmapRulesetTabItem : OverlayRulesetTabItem { public readonly Bindable BeatmapSet = new Bindable(); @@ -68,11 +68,12 @@ namespace osu.Game.Overlays.BeatmapSet BeatmapSet.BindValueChanged(setInfo => { int beatmapsCount = setInfo.NewValue?.Beatmaps.Count(b => b.Ruleset.MatchesOnlineID(Value)) ?? 0; + int osuBeatmaps = setInfo.NewValue?.Beatmaps.Count(b => b.Ruleset.OnlineID == 0) ?? 0; count.Text = beatmapsCount.ToString(); countContainer.FadeTo(beatmapsCount > 0 ? 1 : 0); - Enabled.Value = beatmapsCount > 0; + Enabled.Value = beatmapsCount > 0 || osuBeatmaps > 0; }, true); } } diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapSetHeader.cs b/osu.Game/Overlays/BeatmapSet/BeatmapSetHeader.cs index 02da7812d1..858742648c 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapSetHeader.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapSetHeader.cs @@ -8,6 +8,7 @@ using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Effects; +using osu.Framework.Localisation; using osu.Game.Online.API.Requests.Responses; using osu.Game.Resources.Localisation.Web; using osu.Game.Rulesets; @@ -16,7 +17,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.BeatmapSet { - public class BeatmapSetHeader : OverlayHeader + public partial class BeatmapSetHeader : TabControlOverlayHeader { public readonly Bindable BeatmapSet = new Bindable(); @@ -46,14 +47,14 @@ namespace osu.Game.Overlays.BeatmapSet BeatmapSet = { BindTarget = BeatmapSet } }; - protected override Drawable CreateTitleContent() => RulesetSelector = new BeatmapRulesetSelector + protected override Drawable CreateTabControlContent() => RulesetSelector = new BeatmapRulesetSelector { Current = ruleset }; protected override OverlayTitle CreateTitle() => new BeatmapHeaderTitle(); - private class BeatmapHeaderTitle : OverlayTitle + private partial class BeatmapHeaderTitle : OverlayTitle { public BeatmapHeaderTitle() { @@ -62,4 +63,10 @@ namespace osu.Game.Overlays.BeatmapSet } } } + + public enum BeatmapSetTabs + { + [LocalisableDescription(typeof(LayoutStrings), nameof(LayoutStrings.HeaderBeatmapsetsShow))] + Info, + } } diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapSetHeaderContent.cs b/osu.Game/Overlays/BeatmapSet/BeatmapSetHeaderContent.cs index 9e14122ae4..26e6b1f158 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapSetHeaderContent.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapSetHeaderContent.cs @@ -3,30 +3,33 @@ #nullable disable +using System; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; -using osu.Game.Graphics.Cursor; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osu.Game.Online; using osu.Game.Online.API; using osu.Game.Online.API.Requests.Responses; +using osu.Game.Online.Chat; using osu.Game.Overlays.BeatmapSet.Buttons; using osuTK; +using osuTK.Graphics; namespace osu.Game.Overlays.BeatmapSet { - public class BeatmapSetHeaderContent : CompositeDrawable + public partial class BeatmapSetHeaderContent : CompositeDrawable { public readonly Bindable BeatmapSet = new Bindable(); @@ -41,12 +44,10 @@ namespace osu.Game.Overlays.BeatmapSet private readonly UpdateableOnlineBeatmapSetCover cover; private readonly Box coverGradient; - private readonly OsuSpriteText title, artist; + private readonly LinkFlowContainer title, artist; private readonly AuthorInfo author; - private readonly ExplicitContentBeatmapBadge explicitContent; - private readonly SpotlightBeatmapBadge spotlight; - private readonly FeaturedArtistBeatmapBadge featuredArtist; + private ExternalLinkButton externalLink; private readonly FillFlowContainer downloadButtonsContainer; private readonly BeatmapAvailability beatmapAvailability; @@ -65,8 +66,6 @@ namespace osu.Game.Overlays.BeatmapSet public BeatmapSetHeaderContent() { - ExternalLinkButton externalLink; - RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; InternalChild = new Container @@ -91,118 +90,74 @@ namespace osu.Game.Overlays.BeatmapSet }, }, }, - new OsuContextMenuContainer + new Container { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Child = new Container + Padding = new MarginPadding { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Padding = new MarginPadding + Vertical = BeatmapSetOverlay.Y_PADDING, + Left = BeatmapSetOverlay.X_PADDING, + Right = BeatmapSetOverlay.X_PADDING + BeatmapSetOverlay.RIGHT_WIDTH, + }, + Children = new Drawable[] + { + fadeContent = new FillFlowContainer { - Vertical = BeatmapSetOverlay.Y_PADDING, - Left = BeatmapSetOverlay.X_PADDING, - Right = BeatmapSetOverlay.X_PADDING + BeatmapSetOverlay.RIGHT_WIDTH, - }, - Children = new Drawable[] - { - fadeContent = new FillFlowContainer + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Children = new Drawable[] { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Children = new Drawable[] + new Container { - new Container + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Child = Picker = new BeatmapPicker(), + }, + title = new MetadataFlowContainer(s => + { + s.Font = OsuFont.GetFont(size: 30, weight: FontWeight.SemiBold, italics: true); + }) + { + Margin = new MarginPadding { Top = 15 }, + }, + artist = new MetadataFlowContainer(s => + { + s.Font = OsuFont.GetFont(size: 20, weight: FontWeight.Medium, italics: true); + }) + { + Margin = new MarginPadding { Bottom = 20 }, + }, + new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Child = author = new AuthorInfo(), + }, + beatmapAvailability = new BeatmapAvailability(), + new Container + { + RelativeSizeAxes = Axes.X, + Height = buttons_height, + Margin = new MarginPadding { Top = 10 }, + Children = new Drawable[] { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Child = Picker = new BeatmapPicker(), - }, - new FillFlowContainer - { - Direction = FillDirection.Horizontal, - AutoSizeAxes = Axes.Both, - Margin = new MarginPadding { Top = 15 }, - Children = new Drawable[] + favouriteButton = new FavouriteButton { - title = new OsuSpriteText - { - Font = OsuFont.GetFont(size: 30, weight: FontWeight.SemiBold, italics: true) - }, - externalLink = new ExternalLinkButton - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Margin = new MarginPadding { Left = 5, Bottom = 4 }, // To better lineup with the font - }, - explicitContent = new ExplicitContentBeatmapBadge - { - Alpha = 0f, - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Margin = new MarginPadding { Left = 10, Bottom = 4 }, - }, - spotlight = new SpotlightBeatmapBadge - { - Alpha = 0f, - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Margin = new MarginPadding { Left = 10, Bottom = 4 }, - } - } - }, - new FillFlowContainer - { - Direction = FillDirection.Horizontal, - AutoSizeAxes = Axes.Both, - Margin = new MarginPadding { Bottom = 20 }, - Children = new Drawable[] - { - artist = new OsuSpriteText - { - Font = OsuFont.GetFont(size: 20, weight: FontWeight.Medium, italics: true), - }, - featuredArtist = new FeaturedArtistBeatmapBadge - { - Alpha = 0f, - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Margin = new MarginPadding { Left = 10 } - } - } - }, - new Container - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Child = author = new AuthorInfo(), - }, - beatmapAvailability = new BeatmapAvailability(), - new Container - { - RelativeSizeAxes = Axes.X, - Height = buttons_height, - Margin = new MarginPadding { Top = 10 }, - Children = new Drawable[] - { - favouriteButton = new FavouriteButton - { - BeatmapSet = { BindTarget = BeatmapSet } - }, - downloadButtonsContainer = new FillFlowContainer - { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Left = buttons_height + buttons_spacing }, - Spacing = new Vector2(buttons_spacing), - }, + BeatmapSet = { BindTarget = BeatmapSet } }, - }, + downloadButtonsContainer = new FillFlowContainer + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Left = buttons_height + buttons_spacing }, + Spacing = new Vector2(buttons_spacing), + }, + } }, }, - } - }, + }, + } }, loading = new LoadingSpinner { @@ -237,12 +192,17 @@ namespace osu.Game.Overlays.BeatmapSet Picker.Beatmap.ValueChanged += b => { Details.BeatmapInfo = b.NewValue; - externalLink.Link = $@"{api.WebsiteRootUrl}/beatmapsets/{BeatmapSet.Value?.OnlineID}#{b.NewValue?.Ruleset.ShortName}/{b.NewValue?.OnlineID}"; + updateExternalLink(); onlineStatusPill.Status = b.NewValue?.Status ?? BeatmapOnlineStatus.None; }; } + private void updateExternalLink() + { + if (externalLink != null) externalLink.Link = $@"{api.WebsiteRootUrl}/beatmapsets/{BeatmapSet.Value?.OnlineID}#{Picker.Beatmap.Value?.Ruleset.ShortName}/{Picker.Beatmap.Value?.OnlineID}"; + } + [BackgroundDependencyLoader] private void load(OverlayColourProvider colourProvider) { @@ -275,12 +235,38 @@ namespace osu.Game.Overlays.BeatmapSet loading.Hide(); - title.Text = new RomanisableString(setInfo.NewValue.TitleUnicode, setInfo.NewValue.Title); - artist.Text = new RomanisableString(setInfo.NewValue.ArtistUnicode, setInfo.NewValue.Artist); + var titleText = new RomanisableString(setInfo.NewValue.TitleUnicode, setInfo.NewValue.Title); + var artistText = new RomanisableString(setInfo.NewValue.ArtistUnicode, setInfo.NewValue.Artist); - explicitContent.Alpha = setInfo.NewValue.HasExplicitContent ? 1 : 0; - spotlight.Alpha = setInfo.NewValue.FeaturedInSpotlight ? 1 : 0; - featuredArtist.Alpha = setInfo.NewValue.TrackId != null ? 1 : 0; + title.Clear(); + artist.Clear(); + + title.AddLink(titleText, LinkAction.SearchBeatmapSet, titleText); + + title.AddArbitraryDrawable(Empty().With(d => d.Width = 5)); + title.AddArbitraryDrawable(externalLink = new ExternalLinkButton()); + + if (setInfo.NewValue.HasExplicitContent) + { + title.AddArbitraryDrawable(Empty().With(d => d.Width = 10)); + title.AddArbitraryDrawable(new ExplicitContentBeatmapBadge()); + } + + if (setInfo.NewValue.FeaturedInSpotlight) + { + title.AddArbitraryDrawable(Empty().With(d => d.Width = 10)); + title.AddArbitraryDrawable(new SpotlightBeatmapBadge()); + } + + artist.AddLink(artistText, LinkAction.SearchBeatmapSet, artistText); + + if (setInfo.NewValue.TrackId != null) + { + artist.AddArbitraryDrawable(Empty().With(d => d.Width = 10)); + artist.AddArbitraryDrawable(new FeaturedArtistBeatmapBadge()); + } + + updateExternalLink(); onlineStatusPill.FadeIn(500, Easing.OutQuint); @@ -327,5 +313,32 @@ namespace osu.Game.Overlays.BeatmapSet break; } } + + public partial class MetadataFlowContainer : LinkFlowContainer + { + public MetadataFlowContainer(Action defaultCreationParameters = null) + : base(defaultCreationParameters) + { + TextAnchor = Anchor.CentreLeft; + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + } + + protected override DrawableLinkCompiler CreateLinkCompiler(ITextPart textPart) => new MetadataLinkCompiler(textPart); + + public partial class MetadataLinkCompiler : DrawableLinkCompiler + { + public MetadataLinkCompiler(ITextPart part) + : base(part) + { + } + + [BackgroundDependencyLoader] + private void load() + { + IdleColour = Color4.White; + } + } + } } } diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapSetLayoutSection.cs b/osu.Game/Overlays/BeatmapSet/BeatmapSetLayoutSection.cs index 797b6716e7..305a3661a7 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapSetLayoutSection.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapSetLayoutSection.cs @@ -12,7 +12,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.BeatmapSet { - public class BeatmapSetLayoutSection : Container + public partial class BeatmapSetLayoutSection : Container { public BeatmapSetLayoutSection() { diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs index f7c8aa44ad..cbdb2ea190 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs @@ -21,7 +21,7 @@ using APIUser = osu.Game.Online.API.Requests.Responses.APIUser; namespace osu.Game.Overlays.BeatmapSet.Buttons { - public class FavouriteButton : HeaderButton, IHasTooltip + public partial class FavouriteButton : HeaderButton, IHasTooltip { public readonly Bindable BeatmapSet = new Bindable(); diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/HeaderButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/HeaderButton.cs index 25d11bd6d7..6e4386bb48 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/HeaderButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/HeaderButton.cs @@ -1,16 +1,14 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; -using osu.Game.Graphics.UserInterface; +using osu.Game.Graphics.UserInterfaceV2; namespace osu.Game.Overlays.BeatmapSet.Buttons { - public class HeaderButton : TriangleButton + public partial class HeaderButton : RoundedButton { public HeaderButton() { @@ -22,9 +20,6 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons private void load() { BackgroundColour = Color4Extensions.FromHex(@"094c5f"); - Triangles.ColourLight = Color4Extensions.FromHex(@"0f7c9b"); - Triangles.ColourDark = Color4Extensions.FromHex(@"094c5f"); - Triangles.TriangleScale = 1.5f; } } } diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/HeaderDownloadButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/HeaderDownloadButton.cs index c2de96f245..d8dcf2b51b 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/HeaderDownloadButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/HeaderDownloadButton.cs @@ -26,7 +26,7 @@ using CommonStrings = osu.Game.Localisation.CommonStrings; namespace osu.Game.Overlays.BeatmapSet.Buttons { - public class HeaderDownloadButton : CompositeDrawable, IHasTooltip + public partial class HeaderDownloadButton : CompositeDrawable, IHasTooltip { private const int text_size = 12; diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/PlayButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/PlayButton.cs index 0ce55ce549..c43be33290 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/PlayButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/PlayButton.cs @@ -18,7 +18,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.BeatmapSet.Buttons { - public class PlayButton : Container + public partial class PlayButton : Container { public IBindable Playing => playing; diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs index 8fc8927c4b..b3b8b80a0d 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs @@ -17,7 +17,7 @@ using osuTK; namespace osu.Game.Overlays.BeatmapSet.Buttons { - public class PreviewButton : OsuClickableContainer + public partial class PreviewButton : OsuClickableContainer { private readonly Box background, progress; private readonly PlayButton playButton; diff --git a/osu.Game/Overlays/BeatmapSet/Details.cs b/osu.Game/Overlays/BeatmapSet/Details.cs index 6db54db811..cf78f605aa 100644 --- a/osu.Game/Overlays/BeatmapSet/Details.cs +++ b/osu.Game/Overlays/BeatmapSet/Details.cs @@ -15,7 +15,7 @@ using osuTK; namespace osu.Game.Overlays.BeatmapSet { - public class Details : FillFlowContainer + public partial class Details : FillFlowContainer { protected readonly UserRatings Ratings; @@ -107,7 +107,7 @@ namespace osu.Game.Overlays.BeatmapSet updateDisplay(); } - private class DetailBox : Container + private partial class DetailBox : Container { private readonly Container content; private readonly Box background; diff --git a/osu.Game/Overlays/BeatmapSet/ExplicitContentBeatmapBadge.cs b/osu.Game/Overlays/BeatmapSet/ExplicitContentBeatmapBadge.cs index 18dcfc0385..f666961784 100644 --- a/osu.Game/Overlays/BeatmapSet/ExplicitContentBeatmapBadge.cs +++ b/osu.Game/Overlays/BeatmapSet/ExplicitContentBeatmapBadge.cs @@ -7,7 +7,7 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.BeatmapSet { - public class ExplicitContentBeatmapBadge : BeatmapBadge + public partial class ExplicitContentBeatmapBadge : BeatmapBadge { [BackgroundDependencyLoader] private void load(OsuColour colours) diff --git a/osu.Game/Overlays/BeatmapSet/FeaturedArtistBeatmapBadge.cs b/osu.Game/Overlays/BeatmapSet/FeaturedArtistBeatmapBadge.cs index a0ee0a18ec..6090ec6fae 100644 --- a/osu.Game/Overlays/BeatmapSet/FeaturedArtistBeatmapBadge.cs +++ b/osu.Game/Overlays/BeatmapSet/FeaturedArtistBeatmapBadge.cs @@ -7,7 +7,7 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.BeatmapSet { - public class FeaturedArtistBeatmapBadge : BeatmapBadge + public partial class FeaturedArtistBeatmapBadge : BeatmapBadge { [BackgroundDependencyLoader] private void load(OsuColour colours) diff --git a/osu.Game/Overlays/BeatmapSet/Info.cs b/osu.Game/Overlays/BeatmapSet/Info.cs index 08423f2aa7..58739eb471 100644 --- a/osu.Game/Overlays/BeatmapSet/Info.cs +++ b/osu.Game/Overlays/BeatmapSet/Info.cs @@ -3,18 +3,21 @@ #nullable disable +using System; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Online.API.Requests.Responses; +using osu.Game.Overlays.BeatmapListing; namespace osu.Game.Overlays.BeatmapSet { - public class Info : Container + public partial class Info : Container { private const float metadata_width = 175; private const float spacing = 20; @@ -34,7 +37,10 @@ namespace osu.Game.Overlays.BeatmapSet public Info() { - MetadataSection source, tags, genre, language; + MetadataSectionNominators nominators; + MetadataSection source, tags; + MetadataSectionGenre genre; + MetadataSectionLanguage language; OsuSpriteText notRankedPlaceholder; RelativeSizeAxes = Axes.X; @@ -59,7 +65,7 @@ namespace osu.Game.Overlays.BeatmapSet Child = new Container { RelativeSizeAxes = Axes.Both, - Child = new MetadataSection(MetadataType.Description), + Child = new MetadataSectionDescription(), }, }, new Container @@ -76,12 +82,13 @@ namespace osu.Game.Overlays.BeatmapSet RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Direction = FillDirection.Full, - Children = new[] + Children = new Drawable[] { - source = new MetadataSection(MetadataType.Source), - genre = new MetadataSection(MetadataType.Genre) { Width = 0.5f }, - language = new MetadataSection(MetadataType.Language) { Width = 0.5f }, - tags = new MetadataSection(MetadataType.Tags), + nominators = new MetadataSectionNominators(), + source = new MetadataSectionSource(), + genre = new MetadataSectionGenre { Width = 0.5f }, + language = new MetadataSectionLanguage { Width = 0.5f }, + tags = new MetadataSectionTags(), }, }, }, @@ -118,10 +125,11 @@ namespace osu.Game.Overlays.BeatmapSet BeatmapSet.ValueChanged += b => { - source.Text = b.NewValue?.Source ?? string.Empty; - tags.Text = b.NewValue?.Tags ?? string.Empty; - genre.Text = b.NewValue?.Genre.Name ?? string.Empty; - language.Text = b.NewValue?.Language.Name ?? string.Empty; + nominators.Metadata = (b.NewValue?.CurrentNominations ?? Array.Empty(), b.NewValue?.RelatedUsers ?? Array.Empty()); + source.Metadata = b.NewValue?.Source ?? string.Empty; + tags.Metadata = b.NewValue?.Tags ?? string.Empty; + genre.Metadata = b.NewValue?.Genre ?? new BeatmapSetOnlineGenre { Id = (int)SearchGenre.Unspecified }; + language.Metadata = b.NewValue?.Language ?? new BeatmapSetOnlineLanguage { Id = (int)SearchLanguage.Unspecified }; bool setHasLeaderboard = b.NewValue?.Status > 0; successRate.Alpha = setHasLeaderboard ? 1 : 0; notRankedPlaceholder.Alpha = setHasLeaderboard ? 0 : 1; diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index 8311368da3..9c8f810607 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -20,7 +20,7 @@ using osu.Framework.Extensions.IEnumerableExtensions; namespace osu.Game.Overlays.BeatmapSet { - public class LeaderboardModSelector : CompositeDrawable + public partial class LeaderboardModSelector : CompositeDrawable { public readonly BindableList SelectedMods = new BindableList(); public readonly Bindable Ruleset = new Bindable(); @@ -107,7 +107,7 @@ namespace osu.Game.Overlays.BeatmapSet public void DeselectAll() => modsContainer.ForEach(mod => mod.Selected.Value = false); - private class ModButton : ModIcon + private partial class ModButton : ModIcon { private const int duration = 200; diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs index db7d04f597..476a252c7b 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs @@ -13,7 +13,7 @@ using osu.Framework.Graphics; namespace osu.Game.Overlays.BeatmapSet { - public class LeaderboardScopeSelector : GradientLineTabControl + public partial class LeaderboardScopeSelector : GradientLineTabControl { protected override bool AddEnumEntriesAutomatically => false; @@ -33,7 +33,7 @@ namespace osu.Game.Overlays.BeatmapSet LineColour = colourProvider.Background1; } - private class ScopeSelectorTabItem : PageTabItem + private partial class ScopeSelectorTabItem : PageTabItem { public ScopeSelectorTabItem(BeatmapLeaderboardScope value) : base(value) diff --git a/osu.Game/Overlays/BeatmapSet/MetadataSection.cs b/osu.Game/Overlays/BeatmapSet/MetadataSection.cs index 317b369d8f..d32d8e83fb 100644 --- a/osu.Game/Overlays/BeatmapSet/MetadataSection.cs +++ b/osu.Game/Overlays/BeatmapSet/MetadataSection.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using osu.Framework.Extensions; using osu.Framework.Extensions.Color4Extensions; @@ -11,26 +9,45 @@ using osu.Framework.Graphics.Containers; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; -using osu.Game.Online.Chat; using osuTK; using osuTK.Graphics; namespace osu.Game.Overlays.BeatmapSet { - public class MetadataSection : Container + public abstract partial class MetadataSection : MetadataSection + { + public override string Metadata + { + set + { + if (string.IsNullOrEmpty(value)) + { + this.FadeOut(TRANSITION_DURATION); + return; + } + + base.Metadata = value; + } + } + + protected MetadataSection(MetadataType type, Action? searchAction = null) + : base(type, searchAction) + { + } + } + + public abstract partial class MetadataSection : Container { private readonly FillFlowContainer textContainer; - private readonly MetadataType type; - private TextFlowContainer textFlow; + private TextFlowContainer? textFlow; - private readonly Action searchAction; + protected readonly Action? SearchAction; - private const float transition_duration = 250; + protected const float TRANSITION_DURATION = 250; - public MetadataSection(MetadataType type, Action searchAction = null) + protected MetadataSection(MetadataType type, Action? searchAction = null) { - this.type = type; - this.searchAction = searchAction; + SearchAction = searchAction; Alpha = 0; @@ -53,7 +70,7 @@ namespace osu.Game.Overlays.BeatmapSet AutoSizeAxes = Axes.Y, Child = new OsuSpriteText { - Text = this.type.GetLocalisableDescription(), + Text = type.GetLocalisableDescription(), Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 14), }, }, @@ -61,23 +78,23 @@ namespace osu.Game.Overlays.BeatmapSet }; } - public string Text + public virtual T Metadata { set { - if (string.IsNullOrEmpty(value)) + if (value == null) { - this.FadeOut(transition_duration); + this.FadeOut(TRANSITION_DURATION); return; } - this.FadeIn(transition_duration); + this.FadeIn(TRANSITION_DURATION); - setTextAsync(value); + setTextFlowAsync(value); } } - private void setTextAsync(string text) + private void setTextFlowAsync(T metadata) { LoadComponentAsync(new LinkFlowContainer(s => s.Font = s.Font.With(size: 14)) { @@ -88,44 +105,15 @@ namespace osu.Game.Overlays.BeatmapSet { textFlow?.Expire(); - switch (type) - { - case MetadataType.Tags: - string[] tags = text.Split(" "); - - for (int i = 0; i <= tags.Length - 1; i++) - { - string tag = tags[i]; - - if (searchAction != null) - loaded.AddLink(tag, () => searchAction(tag)); - else - loaded.AddLink(tag, LinkAction.SearchBeatmapSet, tag); - - if (i != tags.Length - 1) - loaded.AddText(" "); - } - - break; - - case MetadataType.Source: - if (searchAction != null) - loaded.AddLink(text, () => searchAction(text)); - else - loaded.AddLink(text, LinkAction.SearchBeatmapSet, text); - - break; - - default: - loaded.AddText(text); - break; - } + AddMetadata(metadata, loaded); textContainer.Add(textFlow = loaded); // fade in if we haven't yet. - textContainer.FadeIn(transition_duration); + textContainer.FadeIn(TRANSITION_DURATION); }); } + + protected abstract void AddMetadata(T metadata, LinkFlowContainer loaded); } } diff --git a/osu.Game/Overlays/BeatmapSet/MetadataSectionDescription.cs b/osu.Game/Overlays/BeatmapSet/MetadataSectionDescription.cs new file mode 100644 index 0000000000..e6837951c9 --- /dev/null +++ b/osu.Game/Overlays/BeatmapSet/MetadataSectionDescription.cs @@ -0,0 +1,21 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Game.Graphics.Containers; + +namespace osu.Game.Overlays.BeatmapSet +{ + public partial class MetadataSectionDescription : MetadataSection + { + public MetadataSectionDescription(Action? searchAction = null) + : base(MetadataType.Description, searchAction) + { + } + + protected override void AddMetadata(string metadata, LinkFlowContainer loaded) + { + loaded.AddText(metadata); + } + } +} diff --git a/osu.Game/Overlays/BeatmapSet/MetadataSectionGenre.cs b/osu.Game/Overlays/BeatmapSet/MetadataSectionGenre.cs new file mode 100644 index 0000000000..d41115f2b8 --- /dev/null +++ b/osu.Game/Overlays/BeatmapSet/MetadataSectionGenre.cs @@ -0,0 +1,30 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Framework.Extensions; +using osu.Game.Beatmaps; +using osu.Game.Graphics.Containers; +using osu.Game.Online.Chat; +using osu.Game.Overlays.BeatmapListing; + +namespace osu.Game.Overlays.BeatmapSet +{ + public partial class MetadataSectionGenre : MetadataSection + { + public MetadataSectionGenre(Action? searchAction = null) + : base(MetadataType.Genre, searchAction) + { + } + + protected override void AddMetadata(BeatmapSetOnlineGenre metadata, LinkFlowContainer loaded) + { + var genre = (SearchGenre)metadata.Id; + + if (Enum.IsDefined(genre)) + loaded.AddLink(genre.GetLocalisableDescription(), LinkAction.FilterBeatmapSetGenre, genre); + else + loaded.AddText(metadata.Name); + } + } +} diff --git a/osu.Game/Overlays/BeatmapSet/MetadataSectionLanguage.cs b/osu.Game/Overlays/BeatmapSet/MetadataSectionLanguage.cs new file mode 100644 index 0000000000..e831b1eaca --- /dev/null +++ b/osu.Game/Overlays/BeatmapSet/MetadataSectionLanguage.cs @@ -0,0 +1,30 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Framework.Extensions; +using osu.Game.Beatmaps; +using osu.Game.Graphics.Containers; +using osu.Game.Online.Chat; +using osu.Game.Overlays.BeatmapListing; + +namespace osu.Game.Overlays.BeatmapSet +{ + public partial class MetadataSectionLanguage : MetadataSection + { + public MetadataSectionLanguage(Action? searchAction = null) + : base(MetadataType.Language, searchAction) + { + } + + protected override void AddMetadata(BeatmapSetOnlineLanguage metadata, LinkFlowContainer loaded) + { + var language = (SearchLanguage)metadata.Id; + + if (Enum.IsDefined(language)) + loaded.AddLink(language.GetLocalisableDescription(), LinkAction.FilterBeatmapSetLanguage, language); + else + loaded.AddText(metadata.Name); + } + } +} diff --git a/osu.Game/Overlays/BeatmapSet/MetadataSectionNominators.cs b/osu.Game/Overlays/BeatmapSet/MetadataSectionNominators.cs new file mode 100644 index 0000000000..76dbda3d5e --- /dev/null +++ b/osu.Game/Overlays/BeatmapSet/MetadataSectionNominators.cs @@ -0,0 +1,63 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Linq; +using osu.Framework.Graphics; +using osu.Game.Beatmaps; +using osu.Game.Graphics.Containers; +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Resources.Localisation.Web; + +namespace osu.Game.Overlays.BeatmapSet +{ + public partial class MetadataSectionNominators : MetadataSection<(BeatmapSetOnlineNomination[] CurrentNominations, APIUser[] RelatedUsers)> + { + public override (BeatmapSetOnlineNomination[] CurrentNominations, APIUser[] RelatedUsers) Metadata + { + set + { + if (value.CurrentNominations.Length == 0) + { + this.FadeOut(TRANSITION_DURATION); + return; + } + + base.Metadata = value; + } + } + + public MetadataSectionNominators(Action<(BeatmapSetOnlineNomination[] CurrentNominations, APIUser[] RelatedUsers)>? searchAction = null) + : base(MetadataType.Nominators, searchAction) + { + } + + protected override void AddMetadata((BeatmapSetOnlineNomination[] CurrentNominations, APIUser[] RelatedUsers) metadata, LinkFlowContainer loaded) + { + int[] nominatorIds = metadata.CurrentNominations.Select(n => n.UserId).ToArray(); + + int nominatorsFound = 0; + + foreach (int nominatorId in nominatorIds) + { + foreach (var user in metadata.RelatedUsers) + { + if (nominatorId != user.OnlineID) continue; + + nominatorsFound++; + + loaded.AddUserLink(new APIUser + { + Username = user.Username, + Id = nominatorId, + }); + + if (nominatorsFound < nominatorIds.Length) + loaded.AddText(CommonStrings.ArrayAndWordsConnector); + + break; + } + } + } + } +} diff --git a/osu.Game/Overlays/BeatmapSet/MetadataSectionSource.cs b/osu.Game/Overlays/BeatmapSet/MetadataSectionSource.cs new file mode 100644 index 0000000000..544dc0dfe4 --- /dev/null +++ b/osu.Game/Overlays/BeatmapSet/MetadataSectionSource.cs @@ -0,0 +1,25 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Game.Graphics.Containers; +using osu.Game.Online.Chat; + +namespace osu.Game.Overlays.BeatmapSet +{ + public partial class MetadataSectionSource : MetadataSection + { + public MetadataSectionSource(Action? searchAction = null) + : base(MetadataType.Source, searchAction) + { + } + + protected override void AddMetadata(string metadata, LinkFlowContainer loaded) + { + if (SearchAction != null) + loaded.AddLink(metadata, () => SearchAction(metadata)); + else + loaded.AddLink(metadata, LinkAction.SearchBeatmapSet, metadata); + } + } +} diff --git a/osu.Game/Overlays/BeatmapSet/MetadataSectionTags.cs b/osu.Game/Overlays/BeatmapSet/MetadataSectionTags.cs new file mode 100644 index 0000000000..fc16ba19d8 --- /dev/null +++ b/osu.Game/Overlays/BeatmapSet/MetadataSectionTags.cs @@ -0,0 +1,35 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Game.Graphics.Containers; +using osu.Game.Online.Chat; + +namespace osu.Game.Overlays.BeatmapSet +{ + public partial class MetadataSectionTags : MetadataSection + { + public MetadataSectionTags(Action? searchAction = null) + : base(MetadataType.Tags, searchAction) + { + } + + protected override void AddMetadata(string metadata, LinkFlowContainer loaded) + { + string[] tags = metadata.Split(" "); + + for (int i = 0; i <= tags.Length - 1; i++) + { + string tag = tags[i]; + + if (SearchAction != null) + loaded.AddLink(tag, () => SearchAction(tag)); + else + loaded.AddLink(tag, LinkAction.SearchBeatmapSet, tag); + + if (i != tags.Length - 1) + loaded.AddText(" "); + } + } + } +} diff --git a/osu.Game/Overlays/BeatmapSet/MetadataType.cs b/osu.Game/Overlays/BeatmapSet/MetadataType.cs index 924e020641..dc96ce99e9 100644 --- a/osu.Game/Overlays/BeatmapSet/MetadataType.cs +++ b/osu.Game/Overlays/BeatmapSet/MetadataType.cs @@ -23,6 +23,9 @@ namespace osu.Game.Overlays.BeatmapSet Genre, [LocalisableDescription(typeof(BeatmapsetsStrings), nameof(BeatmapsetsStrings.ShowInfoLanguage))] - Language + Language, + + [LocalisableDescription(typeof(BeatmapsetsStrings), nameof(BeatmapsetsStrings.ShowInfoNominators))] + Nominators, } } diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs index 06bf9e1d50..01e4416156 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs @@ -15,7 +15,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.BeatmapSet.Scores { - public class DrawableTopScore : CompositeDrawable + public partial class DrawableTopScore : CompositeDrawable { private readonly Box background; @@ -89,7 +89,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores background.Colour = colourProvider.Background4; } - private class AutoSizingGrid : GridContainer + private partial class AutoSizingGrid : GridContainer { public AutoSizingGrid() { diff --git a/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs b/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs index 47690bab1f..f7703af27d 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs @@ -12,7 +12,7 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.BeatmapSet.Scores { - public class NoScoresPlaceholder : Container + public partial class NoScoresPlaceholder : Container { private readonly SpriteText text; diff --git a/osu.Game/Overlays/BeatmapSet/Scores/NotSupporterPlaceholder.cs b/osu.Game/Overlays/BeatmapSet/Scores/NotSupporterPlaceholder.cs index b83b4d6b26..04ab3ec72f 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/NotSupporterPlaceholder.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/NotSupporterPlaceholder.cs @@ -13,7 +13,7 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.BeatmapSet.Scores { - public class NotSupporterPlaceholder : Container + public partial class NotSupporterPlaceholder : Container { public NotSupporterPlaceholder() { diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs index 11aefd435d..425f40258e 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs @@ -28,7 +28,7 @@ using osu.Game.Scoring.Drawables; namespace osu.Game.Overlays.BeatmapSet.Scores { - public class ScoreTable : TableContainer + public partial class ScoreTable : TableContainer { private const float horizontal_inset = 20; private const float row_height = 22; @@ -95,8 +95,8 @@ namespace osu.Game.Overlays.BeatmapSet.Scores new TableColumn(BeatmapsetsStrings.ShowScoreboardHeadersScore, Anchor.CentreLeft, new Dimension(GridSizeMode.AutoSize)), new TableColumn(BeatmapsetsStrings.ShowScoreboardHeadersAccuracy, Anchor.CentreLeft, new Dimension(GridSizeMode.Absolute, minSize: 60, maxSize: 70)), new TableColumn("", Anchor.CentreLeft, new Dimension(GridSizeMode.Absolute, 25)), // flag - new TableColumn(BeatmapsetsStrings.ShowScoreboardHeadersPlayer, Anchor.CentreLeft, new Dimension(GridSizeMode.Distributed, minSize: 125)), - new TableColumn(BeatmapsetsStrings.ShowScoreboardHeadersCombo, Anchor.CentreLeft, new Dimension(GridSizeMode.Distributed, minSize: 70, maxSize: 120)) + new TableColumn(BeatmapsetsStrings.ShowScoreboardHeadersPlayer, Anchor.CentreLeft, new Dimension(minSize: 125)), + new TableColumn(BeatmapsetsStrings.ShowScoreboardHeadersCombo, Anchor.CentreLeft, new Dimension(minSize: 70, maxSize: 120)) }; // All statistics across all scores, unordered. @@ -116,7 +116,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores var displayName = ruleset.GetDisplayNameForHitResult(result); - columns.Add(new TableColumn(displayName, Anchor.CentreLeft, new Dimension(GridSizeMode.Distributed, minSize: 35, maxSize: 60))); + columns.Add(new TableColumn(displayName, Anchor.CentreLeft, new Dimension(minSize: 35, maxSize: 60))); statisticResultTypes.Add((result, displayName)); } @@ -207,7 +207,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores protected override Drawable CreateHeader(int index, TableColumn column) => new HeaderText(column?.Header ?? default); - private class HeaderText : OsuSpriteText + private partial class HeaderText : OsuSpriteText { public HeaderText(LocalisableString text) { @@ -222,7 +222,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores } } - private class StatisticText : OsuSpriteText, IHasTooltip + private partial class StatisticText : OsuSpriteText, IHasTooltip { private readonly double? count; private readonly double? maxCount; diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRowBackground.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRowBackground.cs index c17bb70bc2..130dfd45e7 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRowBackground.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRowBackground.cs @@ -14,7 +14,7 @@ using osu.Game.Scoring; namespace osu.Game.Overlays.BeatmapSet.Scores { - public class ScoreTableRowBackground : CompositeDrawable + public partial class ScoreTableRowBackground : CompositeDrawable { private const int fade_duration = 100; diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreboardTime.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreboardTime.cs index 72aa221432..04cbf171f6 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreboardTime.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreboardTime.cs @@ -9,7 +9,7 @@ using osu.Game.Graphics; namespace osu.Game.Overlays.BeatmapSet.Scores { - public class ScoreboardTime : DrawableDate + public partial class ScoreboardTime : DrawableDate { public ScoreboardTime(DateTimeOffset date, float textSize = OsuFont.DEFAULT_FONT_SIZE, bool italic = true) : base(date, textSize, italic) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 53818bbee3..9eb04d9cc5 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -24,7 +24,7 @@ using APIUser = osu.Game.Online.API.Requests.Responses.APIUser; namespace osu.Game.Overlays.BeatmapSet.Scores { - public class ScoresContainer : BeatmapSetLayoutSection + public partial class ScoresContainer : BeatmapSetLayoutSection { private const int spacing = 15; diff --git a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs index 653bfd6d2c..e030b1e34f 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs @@ -27,7 +27,7 @@ using osuTK; namespace osu.Game.Overlays.BeatmapSet.Scores { - public class TopScoreStatisticsSection : CompositeDrawable + public partial class TopScoreStatisticsSection : CompositeDrawable { private const float margin = 10; private const float top_columns_min_width = 64; @@ -143,7 +143,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Text = stat.MaxCount == null ? stat.Count.ToLocalisableString(@"N0") : (LocalisableString)$"{stat.Count}/{stat.MaxCount}" }; - private class InfoColumn : CompositeDrawable + private partial class InfoColumn : CompositeDrawable { private readonly Box separator; private readonly OsuSpriteText text; @@ -204,7 +204,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores } } - private class TextColumn : InfoColumn, IHasCurrentValue + private partial class TextColumn : InfoColumn, IHasCurrentValue { private readonly OsuTextFlowContainer text; @@ -249,7 +249,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores } } - private class ModsInfoColumn : InfoColumn + private partial class ModsInfoColumn : InfoColumn { private readonly FillFlowContainer modsContainer; diff --git a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs index 2eaa03a05d..afaed85250 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs @@ -22,7 +22,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.BeatmapSet.Scores { - public class TopScoreUserSection : CompositeDrawable + public partial class TopScoreUserSection : CompositeDrawable { private readonly SpriteText rankText; private readonly UpdateableRank rank; diff --git a/osu.Game/Overlays/BeatmapSet/SpotlightBeatmapBadge.cs b/osu.Game/Overlays/BeatmapSet/SpotlightBeatmapBadge.cs index 44b3acea5f..00534ff700 100644 --- a/osu.Game/Overlays/BeatmapSet/SpotlightBeatmapBadge.cs +++ b/osu.Game/Overlays/BeatmapSet/SpotlightBeatmapBadge.cs @@ -7,7 +7,7 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.BeatmapSet { - public class SpotlightBeatmapBadge : BeatmapBadge + public partial class SpotlightBeatmapBadge : BeatmapBadge { [BackgroundDependencyLoader] private void load(OsuColour colours) diff --git a/osu.Game/Overlays/BeatmapSet/SuccessRate.cs b/osu.Game/Overlays/BeatmapSet/SuccessRate.cs index cbcef9fcec..48732ac586 100644 --- a/osu.Game/Overlays/BeatmapSet/SuccessRate.cs +++ b/osu.Game/Overlays/BeatmapSet/SuccessRate.cs @@ -18,7 +18,7 @@ using osu.Game.Screens.Select.Details; namespace osu.Game.Overlays.BeatmapSet { - public class SuccessRate : Container + public partial class SuccessRate : Container { protected readonly FailRetryGraph Graph; @@ -127,7 +127,7 @@ namespace osu.Game.Overlays.BeatmapSet Graph.Padding = new MarginPadding { Top = header.DrawHeight }; } - private class SuccessRatePercentage : OsuSpriteText, IHasTooltip + private partial class SuccessRatePercentage : OsuSpriteText, IHasTooltip { public LocalisableString TooltipText { get; set; } } diff --git a/osu.Game/Overlays/BeatmapSetOverlay.cs b/osu.Game/Overlays/BeatmapSetOverlay.cs index 207dc91ca5..237ce22767 100644 --- a/osu.Game/Overlays/BeatmapSetOverlay.cs +++ b/osu.Game/Overlays/BeatmapSetOverlay.cs @@ -10,6 +10,7 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.BeatmapSet; @@ -22,7 +23,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays { - public class BeatmapSetOverlay : OnlineOverlay + public partial class BeatmapSetOverlay : OnlineOverlay { public const float X_PADDING = 40; public const float Y_PADDING = 25; @@ -30,6 +31,13 @@ namespace osu.Game.Overlays private readonly Bindable beatmapSet = new Bindable(); + [Resolved] + private IAPIProvider api { get; set; } + + private IBindable apiUser; + + private (BeatmapSetLookupType type, int id)? lastLookup; + /// /// Isolates the beatmap set overlay from the game-wide selected mods bindable /// to avoid affecting the beatmap details section (i.e. ). @@ -72,6 +80,17 @@ namespace osu.Game.Overlays }; } + [BackgroundDependencyLoader] + private void load() + { + apiUser = api.LocalUser.GetBoundCopy(); + apiUser.BindValueChanged(_ => Schedule(() => + { + if (api.IsLoggedIn) + performFetch(); + })); + } + protected override BeatmapSetHeader CreateHeader() => new BeatmapSetHeader(); protected override Color4 BackgroundColour => ColourProvider.Background6; @@ -84,27 +103,20 @@ namespace osu.Game.Overlays public void FetchAndShowBeatmap(int beatmapId) { + lastLookup = (BeatmapSetLookupType.BeatmapId, beatmapId); beatmapSet.Value = null; - var req = new GetBeatmapSetRequest(beatmapId, BeatmapSetLookupType.BeatmapId); - req.Success += res => - { - beatmapSet.Value = res; - Header.HeaderContent.Picker.Beatmap.Value = Header.BeatmapSet.Value.Beatmaps.First(b => b.OnlineID == beatmapId); - }; - API.Queue(req); - + performFetch(); Show(); } public void FetchAndShowBeatmapSet(int beatmapSetId) { + lastLookup = (BeatmapSetLookupType.SetId, beatmapSetId); + beatmapSet.Value = null; - var req = new GetBeatmapSetRequest(beatmapSetId); - req.Success += res => beatmapSet.Value = res; - API.Queue(req); - + performFetch(); Show(); } @@ -118,7 +130,25 @@ namespace osu.Game.Overlays Show(); } - private class CommentsSection : BeatmapSetLayoutSection + private void performFetch() + { + if (!api.IsLoggedIn) + return; + + if (lastLookup == null) + return; + + var req = new GetBeatmapSetRequest(lastLookup.Value.id, lastLookup.Value.type); + req.Success += res => + { + beatmapSet.Value = res; + if (lastLookup.Value.type == BeatmapSetLookupType.BeatmapId) + Header.HeaderContent.Picker.Beatmap.Value = Header.BeatmapSet.Value.Beatmaps.First(b => b.OnlineID == lastLookup.Value.id); + }; + API.Queue(req); + } + + private partial class CommentsSection : BeatmapSetLayoutSection { public readonly Bindable BeatmapSet = new Bindable(); diff --git a/osu.Game/Overlays/BreadcrumbControlOverlayHeader.cs b/osu.Game/Overlays/BreadcrumbControlOverlayHeader.cs index 5b83f0e62e..e730496b5c 100644 --- a/osu.Game/Overlays/BreadcrumbControlOverlayHeader.cs +++ b/osu.Game/Overlays/BreadcrumbControlOverlayHeader.cs @@ -11,11 +11,11 @@ using osu.Game.Graphics.UserInterface; namespace osu.Game.Overlays { - public abstract class BreadcrumbControlOverlayHeader : TabControlOverlayHeader + public abstract partial class BreadcrumbControlOverlayHeader : TabControlOverlayHeader { protected override OsuTabControl CreateTabControl() => new OverlayHeaderBreadcrumbControl(); - public class OverlayHeaderBreadcrumbControl : BreadcrumbControl + public partial class OverlayHeaderBreadcrumbControl : BreadcrumbControl { public OverlayHeaderBreadcrumbControl() { @@ -34,7 +34,7 @@ namespace osu.Game.Overlays AccentColour = AccentColour, }; - private class ControlTabItem : BreadcrumbTabItem + private partial class ControlTabItem : BreadcrumbTabItem { protected override float ChevronSize => 8; diff --git a/osu.Game/Overlays/Changelog/ChangelogBuild.cs b/osu.Game/Overlays/Changelog/ChangelogBuild.cs index 575f1a398a..96d5203d14 100644 --- a/osu.Game/Overlays/Changelog/ChangelogBuild.cs +++ b/osu.Game/Overlays/Changelog/ChangelogBuild.cs @@ -16,7 +16,7 @@ using osu.Framework.Allocation; namespace osu.Game.Overlays.Changelog { - public class ChangelogBuild : FillFlowContainer + public partial class ChangelogBuild : FillFlowContainer { public const float HORIZONTAL_PADDING = 70; @@ -68,11 +68,15 @@ namespace osu.Game.Overlays.Changelog Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, + Direction = FillDirection.Vertical, Margin = new MarginPadding { Top = 20 }, - Children = new Drawable[] + Child = new FillFlowContainer { - new OsuHoverContainer + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Child = new OsuHoverContainer { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game/Overlays/Changelog/ChangelogContent.cs b/osu.Game/Overlays/Changelog/ChangelogContent.cs index e04133f2e4..51ef4ddf94 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContent.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContent.cs @@ -8,7 +8,7 @@ using System; namespace osu.Game.Overlays.Changelog { - public class ChangelogContent : FillFlowContainer + public partial class ChangelogContent : FillFlowContainer { public Action? BuildSelected; diff --git a/osu.Game/Overlays/Changelog/ChangelogEntry.cs b/osu.Game/Overlays/Changelog/ChangelogEntry.cs index 4d034007b1..ab671d9c86 100644 --- a/osu.Game/Overlays/Changelog/ChangelogEntry.cs +++ b/osu.Game/Overlays/Changelog/ChangelogEntry.cs @@ -21,7 +21,7 @@ using APIUser = osu.Game.Online.API.Requests.Responses.APIUser; namespace osu.Game.Overlays.Changelog { - public class ChangelogEntry : FillFlowContainer + public partial class ChangelogEntry : FillFlowContainer { private readonly APIChangelogEntry entry; diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs index 6ce6b82c8f..54ada24987 100644 --- a/osu.Game/Overlays/Changelog/ChangelogHeader.cs +++ b/osu.Game/Overlays/Changelog/ChangelogHeader.cs @@ -18,7 +18,7 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Changelog { - public class ChangelogHeader : BreadcrumbControlOverlayHeader + public partial class ChangelogHeader : BreadcrumbControlOverlayHeader { public readonly Bindable Build = new Bindable(); @@ -117,7 +117,7 @@ namespace osu.Game.Overlays.Changelog currentStream.Value = Streams.Items.FirstOrDefault(s => s.Name == Build.Value.UpdateStream.Name); } - private class ChangelogHeaderTitle : OverlayTitle + private partial class ChangelogHeaderTitle : OverlayTitle { public ChangelogHeaderTitle() { diff --git a/osu.Game/Overlays/Changelog/ChangelogListing.cs b/osu.Game/Overlays/Changelog/ChangelogListing.cs index e848f26587..d7c9ff67fe 100644 --- a/osu.Game/Overlays/Changelog/ChangelogListing.cs +++ b/osu.Game/Overlays/Changelog/ChangelogListing.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; using osu.Framework.Allocation; +using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -15,7 +16,7 @@ using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Overlays.Changelog { - public class ChangelogListing : ChangelogContent + public partial class ChangelogListing : ChangelogContent { private readonly List entries; @@ -51,7 +52,7 @@ namespace osu.Game.Overlays.Changelog Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Margin = new MarginPadding { Top = 20 }, - Text = build.CreatedAt.Date.ToString("dd MMMM yyyy"), + Text = build.CreatedAt.Date.ToLocalisableString("dd MMMM yyyy"), Font = OsuFont.GetFont(weight: FontWeight.Regular, size: 24), }); diff --git a/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs b/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs index e4f240f0e7..13a19de22a 100644 --- a/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs +++ b/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs @@ -4,10 +4,10 @@ #nullable disable using System; -using System.Linq; using System.Threading; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -24,7 +24,7 @@ using osuTK; namespace osu.Game.Overlays.Changelog { - public class ChangelogSingleBuild : ChangelogContent + public partial class ChangelogSingleBuild : ChangelogContent { private APIChangelogBuild build; @@ -91,7 +91,7 @@ namespace osu.Game.Overlays.Changelog } } - public class ChangelogBuildWithNavigation : ChangelogBuild + public partial class ChangelogBuildWithNavigation : ChangelogBuild { public ChangelogBuildWithNavigation(APIChangelogBuild build) : base(build) @@ -104,27 +104,29 @@ namespace osu.Game.Overlays.Changelog { var fill = base.CreateHeader(); - foreach (var existing in fill.Children.OfType()) + var nestedFill = (FillFlowContainer)fill.Child; + + var buildDisplay = (OsuHoverContainer)nestedFill.Child; + + buildDisplay.Scale = new Vector2(1.25f); + buildDisplay.Action = null; + + fill.Add(date = new OsuSpriteText { - existing.Scale = new Vector2(1.25f); - existing.Action = null; + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Text = Build.CreatedAt.Date.ToLocalisableString("dd MMMM yyyy"), + Font = OsuFont.GetFont(weight: FontWeight.Regular, size: 14), + Margin = new MarginPadding { Top = 5 }, + Scale = new Vector2(1.25f), + }); - existing.Add(date = new OsuSpriteText - { - Text = Build.CreatedAt.Date.ToString("dd MMMM yyyy"), - Font = OsuFont.GetFont(weight: FontWeight.Regular, size: 14), - Anchor = Anchor.BottomCentre, - Origin = Anchor.TopCentre, - Margin = new MarginPadding { Top = 5 }, - }); - } - - fill.Insert(-1, new NavigationIconButton(Build.Versions?.Previous) + nestedFill.Insert(-1, new NavigationIconButton(Build.Versions?.Previous) { Icon = FontAwesome.Solid.ChevronLeft, SelectBuild = b => SelectBuild(b) }); - fill.Insert(1, new NavigationIconButton(Build.Versions?.Next) + nestedFill.Insert(1, new NavigationIconButton(Build.Versions?.Next) { Icon = FontAwesome.Solid.ChevronRight, SelectBuild = b => SelectBuild(b) @@ -140,7 +142,7 @@ namespace osu.Game.Overlays.Changelog } } - private class NavigationIconButton : IconButton + private partial class NavigationIconButton : IconButton { public Action SelectBuild; diff --git a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs index d84ed3c807..04526eb7ba 100644 --- a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs +++ b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs @@ -22,7 +22,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Changelog { - public class ChangelogSupporterPromo : CompositeDrawable + public partial class ChangelogSupporterPromo : CompositeDrawable { private const float image_container_width = 164; private const float heart_size = 75; @@ -160,7 +160,7 @@ namespace osu.Game.Overlays.Changelog supportLinkText.AddText(" today!"); } - private class SupporterPromoLinkFlowContainer : LinkFlowContainer + private partial class SupporterPromoLinkFlowContainer : LinkFlowContainer { public SupporterPromoLinkFlowContainer(Action defaultCreationParameters) : base(defaultCreationParameters) @@ -169,7 +169,7 @@ namespace osu.Game.Overlays.Changelog protected override DrawableLinkCompiler CreateLinkCompiler(ITextPart textPart) => new SupporterPromoLinkCompiler(textPart); - private class SupporterPromoLinkCompiler : DrawableLinkCompiler + private partial class SupporterPromoLinkCompiler : DrawableLinkCompiler { public SupporterPromoLinkCompiler(ITextPart part) : base(part) diff --git a/osu.Game/Overlays/Changelog/ChangelogUpdateStreamControl.cs b/osu.Game/Overlays/Changelog/ChangelogUpdateStreamControl.cs index 1db2d2f172..155cbc7d65 100644 --- a/osu.Game/Overlays/Changelog/ChangelogUpdateStreamControl.cs +++ b/osu.Game/Overlays/Changelog/ChangelogUpdateStreamControl.cs @@ -7,7 +7,7 @@ using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Overlays.Changelog { - public class ChangelogUpdateStreamControl : OverlayStreamControl + public partial class ChangelogUpdateStreamControl : OverlayStreamControl { public ChangelogUpdateStreamControl() { diff --git a/osu.Game/Overlays/Changelog/ChangelogUpdateStreamItem.cs b/osu.Game/Overlays/Changelog/ChangelogUpdateStreamItem.cs index 974b283ccf..08ea373fb1 100644 --- a/osu.Game/Overlays/Changelog/ChangelogUpdateStreamItem.cs +++ b/osu.Game/Overlays/Changelog/ChangelogUpdateStreamItem.cs @@ -11,7 +11,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Changelog { - public class ChangelogUpdateStreamItem : OverlayStreamItem + public partial class ChangelogUpdateStreamItem : OverlayStreamItem { public ChangelogUpdateStreamItem(APIUpdateStream stream) : base(stream) diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index 7e0d5e9432..671d649dcf 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -20,7 +20,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays { - public class ChangelogOverlay : OnlineOverlay + public partial class ChangelogOverlay : OnlineOverlay { public override bool IsPresent => base.IsPresent || Scheduler.HasPendingTasks; @@ -70,7 +70,7 @@ namespace osu.Game.Overlays /// are specified, the header will instantly display them. public void ShowBuild([NotNull] APIChangelogBuild build) { - if (build == null) throw new ArgumentNullException(nameof(build)); + ArgumentNullException.ThrowIfNull(build); Current.Value = build; Show(); @@ -78,8 +78,8 @@ namespace osu.Game.Overlays public void ShowBuild([NotNull] string updateStream, [NotNull] string version) { - if (updateStream == null) throw new ArgumentNullException(nameof(updateStream)); - if (version == null) throw new ArgumentNullException(nameof(version)); + ArgumentNullException.ThrowIfNull(updateStream); + ArgumentNullException.ThrowIfNull(version); performAfterFetch(() => { diff --git a/osu.Game/Overlays/Chat/ChannelList/ChannelList.cs b/osu.Game/Overlays/Chat/ChannelList/ChannelList.cs index d9f962ca97..e6fe97f3c6 100644 --- a/osu.Game/Overlays/Chat/ChannelList/ChannelList.cs +++ b/osu.Game/Overlays/Chat/ChannelList/ChannelList.cs @@ -19,7 +19,7 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Chat.ChannelList { - public class ChannelList : Container + public partial class ChannelList : Container { public Action? OnRequestSelect; public Action? OnRequestLeave; @@ -140,7 +140,7 @@ namespace osu.Game.Overlays.Chat.ChannelList announceChannelGroup.Show(); } - private class ChannelGroup : FillFlowContainer + private partial class ChannelGroup : FillFlowContainer { public readonly FillFlowContainer ItemFlow; diff --git a/osu.Game/Overlays/Chat/ChannelList/ChannelListItem.cs b/osu.Game/Overlays/Chat/ChannelList/ChannelListItem.cs index c18e9e11fa..57b6f6268c 100644 --- a/osu.Game/Overlays/Chat/ChannelList/ChannelListItem.cs +++ b/osu.Game/Overlays/Chat/ChannelList/ChannelListItem.cs @@ -19,7 +19,7 @@ using osuTK; namespace osu.Game.Overlays.Chat.ChannelList { - public class ChannelListItem : OsuClickableContainer + public partial class ChannelListItem : OsuClickableContainer { public event Action? OnRequestSelect; public event Action? OnRequestLeave; diff --git a/osu.Game/Overlays/Chat/ChannelList/ChannelListItemCloseButton.cs b/osu.Game/Overlays/Chat/ChannelList/ChannelListItemCloseButton.cs index 46d70b2d67..204b9aab19 100644 --- a/osu.Game/Overlays/Chat/ChannelList/ChannelListItemCloseButton.cs +++ b/osu.Game/Overlays/Chat/ChannelList/ChannelListItemCloseButton.cs @@ -12,7 +12,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Chat.ChannelList { - public class ChannelListItemCloseButton : OsuClickableContainer + public partial class ChannelListItemCloseButton : OsuClickableContainer { private SpriteIcon icon = null!; diff --git a/osu.Game/Overlays/Chat/ChannelList/ChannelListItemMentionPill.cs b/osu.Game/Overlays/Chat/ChannelList/ChannelListItemMentionPill.cs index 2ead841f58..bbd042cfc9 100644 --- a/osu.Game/Overlays/Chat/ChannelList/ChannelListItemMentionPill.cs +++ b/osu.Game/Overlays/Chat/ChannelList/ChannelListItemMentionPill.cs @@ -13,7 +13,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Chat.ChannelList { - public class ChannelListItemMentionPill : CircularContainer + public partial class ChannelListItemMentionPill : CircularContainer { public readonly BindableInt Mentions = new BindableInt(); diff --git a/osu.Game/Overlays/Chat/ChannelScrollContainer.cs b/osu.Game/Overlays/Chat/ChannelScrollContainer.cs index dee7730e2c..090f7835ae 100644 --- a/osu.Game/Overlays/Chat/ChannelScrollContainer.cs +++ b/osu.Game/Overlays/Chat/ChannelScrollContainer.cs @@ -11,7 +11,7 @@ namespace osu.Game.Overlays.Chat /// /// An with functionality to automatically scroll whenever the maximum scrollable distance increases. /// - public class ChannelScrollContainer : OsuScrollContainer + public partial class ChannelScrollContainer : OsuScrollContainer { /// /// The chat will be automatically scrolled to end if and only if diff --git a/osu.Game/Overlays/Chat/ChatLine.cs b/osu.Game/Overlays/Chat/ChatLine.cs index a991103fac..70c3bf181c 100644 --- a/osu.Game/Overlays/Chat/ChatLine.cs +++ b/osu.Game/Overlays/Chat/ChatLine.cs @@ -1,33 +1,28 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using System.Linq; using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Cursor; -using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.UserInterface; using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; -using osu.Game.Online.API; -using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Chat; -using osuTK; -using osuTK.Graphics; +using osu.Framework.Graphics.Sprites; namespace osu.Game.Overlays.Chat { - public class ChatLine : CompositeDrawable + public partial class ChatLine : CompositeDrawable { + private Message message = null!; + public Message Message { get => message; @@ -44,49 +39,35 @@ namespace osu.Game.Overlays.Chat } } - public LinkFlowContainer ContentFlow { get; private set; } = null!; + public IReadOnlyCollection DrawableContentFlow => drawableContentFlow; - protected virtual float TextSize => 20; + protected virtual float FontSize => 20; protected virtual float Spacing => 15; protected virtual float UsernameWidth => 130; - private Color4 usernameColour; - - private OsuSpriteText timestamp = null!; - - private Message message = null!; - - private OsuSpriteText username = null!; - - private Container? highlight; - - private readonly Bindable prefer24HourTime = new Bindable(); - - private bool senderHasColour => !string.IsNullOrEmpty(message.Sender.Colour); - - private bool messageHasColour => Message.IsAction && senderHasColour; - [Resolved] private ChannelManager? chatManager { get; set; } [Resolved] - private OsuColour colours { get; set; } = null!; + private OverlayColourProvider? colourProvider { get; set; } + + private readonly OsuSpriteText drawableTimestamp; + + private readonly DrawableUsername drawableUsername; + + private readonly LinkFlowContainer drawableContentFlow; + + private readonly Bindable prefer24HourTime = new Bindable(); + + private Container? highlight; public ChatLine(Message message) { Message = message; RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; - } - - [BackgroundDependencyLoader] - private void load(OverlayColourProvider? colourProvider, OsuConfigManager configManager) - { - usernameColour = senderHasColour - ? Color4Extensions.FromHex(message.Sender.Colour) - : username_colours[message.Sender.Id % username_colours.Length]; InternalChild = new GridContainer { @@ -103,30 +84,24 @@ namespace osu.Game.Overlays.Chat { new Drawable[] { - timestamp = new OsuSpriteText + drawableTimestamp = new OsuSpriteText { Shadow = false, Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - Font = OsuFont.GetFont(size: TextSize * 0.75f, weight: FontWeight.SemiBold, fixedWidth: true), - Colour = colourProvider?.Background1 ?? Colour4.White, + Font = OsuFont.GetFont(size: FontSize * 0.75f, weight: FontWeight.SemiBold, fixedWidth: true), AlwaysPresent = true, }, - new MessageSender(message.Sender) + drawableUsername = new DrawableUsername(message.Sender) { Width = UsernameWidth, + FontSize = FontSize, AutoSizeAxes = Axes.Y, Origin = Anchor.TopRight, Anchor = Anchor.TopRight, - Child = createUsername(), Margin = new MarginPadding { Horizontal = Spacing }, }, - ContentFlow = new LinkFlowContainer(t => - { - t.Shadow = false; - t.Font = t.Font.With(size: TextSize, italics: Message.IsAction); - t.Colour = messageHasColour ? Color4Extensions.FromHex(message.Sender.Colour) : colourProvider?.Content1 ?? Colour4.White; - }) + drawableContentFlow = new LinkFlowContainer(styleMessageContent) { AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, @@ -134,18 +109,23 @@ namespace osu.Game.Overlays.Chat }, } }; + } + [BackgroundDependencyLoader] + private void load(OsuConfigManager configManager) + { configManager.BindWith(OsuSetting.Prefer24HourTime, prefer24HourTime); + prefer24HourTime.BindValueChanged(_ => updateTimestamp()); } protected override void LoadComplete() { base.LoadComplete(); + drawableTimestamp.Colour = colourProvider?.Background1 ?? Colour4.White; + updateMessageContent(); FinishTransforms(true); - - prefer24HourTime.BindValueChanged(_ => updateTimestamp()); } /// @@ -160,7 +140,7 @@ namespace osu.Game.Overlays.Chat CornerRadius = 2f, Masking = true, RelativeSizeAxes = Axes.Both, - Colour = usernameColour.Darken(1f), + Colour = drawableUsername.AccentColour.Darken(1f), Depth = float.MaxValue, Child = new Box { RelativeSizeAxes = Axes.Both } }); @@ -170,166 +150,33 @@ namespace osu.Game.Overlays.Chat highlight.Expire(); } + private void styleMessageContent(SpriteText text) + { + text.Shadow = false; + text.Font = text.Font.With(size: FontSize, italics: Message.IsAction); + + bool messageHasColour = Message.IsAction && !string.IsNullOrEmpty(message.Sender.Colour); + text.Colour = messageHasColour ? Color4Extensions.FromHex(message.Sender.Colour) : colourProvider?.Content1 ?? Colour4.White; + } + private void updateMessageContent() { this.FadeTo(message is LocalEchoMessage ? 0.4f : 1.0f, 500, Easing.OutQuint); - timestamp.FadeTo(message is LocalEchoMessage ? 0 : 1, 500, Easing.OutQuint); + drawableTimestamp.FadeTo(message is LocalEchoMessage ? 0 : 1, 500, Easing.OutQuint); updateTimestamp(); - username.Text = $@"{message.Sender.Username}"; + drawableUsername.Text = $@"{message.Sender.Username}"; // remove non-existent channels from the link list message.Links.RemoveAll(link => link.Action == LinkAction.OpenChannel && chatManager?.AvailableChannels.Any(c => c.Name == link.Argument.ToString()) != true); - ContentFlow.Clear(); - ContentFlow.AddLinks(message.DisplayContent, message.Links); + drawableContentFlow.Clear(); + drawableContentFlow.AddLinks(message.DisplayContent, message.Links); } private void updateTimestamp() { - timestamp.Text = prefer24HourTime.Value - ? $@"{message.Timestamp.LocalDateTime:HH:mm:ss}" - : $@"{message.Timestamp.LocalDateTime:hh:mm:ss tt}"; + drawableTimestamp.Text = message.Timestamp.LocalDateTime.ToLocalisableString(prefer24HourTime.Value ? @"HH:mm:ss" : @"hh:mm:ss tt"); } - - private Drawable createUsername() - { - username = new OsuSpriteText - { - Shadow = false, - Colour = senderHasColour ? colours.ChatBlue : usernameColour, - Truncate = true, - EllipsisString = "…", - Font = OsuFont.GetFont(size: TextSize, weight: FontWeight.Bold, italics: true), - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - MaxWidth = UsernameWidth, - }; - - if (!senderHasColour) - return username; - - // Background effect - return new Container - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - AutoSizeAxes = Axes.Both, - Masking = true, - CornerRadius = 4, - EdgeEffect = new EdgeEffectParameters - { - Roundness = 1, - Radius = 1, - Colour = Color4.Black.Opacity(0.3f), - Offset = new Vector2(0, 1), - Type = EdgeEffectType.Shadow, - }, - Child = new Container - { - AutoSizeAxes = Axes.Both, - Masking = true, - CornerRadius = 4, - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = usernameColour, - }, - new Container - { - AutoSizeAxes = Axes.Both, - Padding = new MarginPadding { Left = 4, Right = 4, Bottom = 1, Top = -2 }, - Child = username - } - } - } - }; - } - - private class MessageSender : OsuClickableContainer, IHasContextMenu - { - private readonly APIUser sender; - - private Action startChatAction = null!; - - [Resolved] - private IAPIProvider api { get; set; } = null!; - - public MessageSender(APIUser sender) - { - this.sender = sender; - } - - [BackgroundDependencyLoader] - private void load(UserProfileOverlay? profile, ChannelManager? chatManager, ChatOverlay? chatOverlay) - { - Action = () => profile?.ShowUser(sender); - startChatAction = () => - { - chatManager?.OpenPrivateChannel(sender); - chatOverlay?.Show(); - }; - } - - public MenuItem[] ContextMenuItems - { - get - { - if (sender.Equals(APIUser.SYSTEM_USER)) - return Array.Empty(); - - List items = new List - { - new OsuMenuItem("View Profile", MenuItemType.Highlighted, Action) - }; - - if (!sender.Equals(api.LocalUser.Value)) - items.Add(new OsuMenuItem("Start Chat", MenuItemType.Standard, startChatAction)); - - return items.ToArray(); - } - } - } - - private static readonly Color4[] username_colours = - { - Color4Extensions.FromHex("588c7e"), - Color4Extensions.FromHex("b2a367"), - Color4Extensions.FromHex("c98f65"), - Color4Extensions.FromHex("bc5151"), - Color4Extensions.FromHex("5c8bd6"), - Color4Extensions.FromHex("7f6ab7"), - Color4Extensions.FromHex("a368ad"), - Color4Extensions.FromHex("aa6880"), - - Color4Extensions.FromHex("6fad9b"), - Color4Extensions.FromHex("f2e394"), - Color4Extensions.FromHex("f2ae72"), - Color4Extensions.FromHex("f98f8a"), - Color4Extensions.FromHex("7daef4"), - Color4Extensions.FromHex("a691f2"), - Color4Extensions.FromHex("c894d3"), - Color4Extensions.FromHex("d895b0"), - - Color4Extensions.FromHex("53c4a1"), - Color4Extensions.FromHex("eace5c"), - Color4Extensions.FromHex("ea8c47"), - Color4Extensions.FromHex("fc4f4f"), - Color4Extensions.FromHex("3d94ea"), - Color4Extensions.FromHex("7760ea"), - Color4Extensions.FromHex("af52c6"), - Color4Extensions.FromHex("e25696"), - - Color4Extensions.FromHex("677c66"), - Color4Extensions.FromHex("9b8732"), - Color4Extensions.FromHex("8c5129"), - Color4Extensions.FromHex("8c3030"), - Color4Extensions.FromHex("1f5d91"), - Color4Extensions.FromHex("4335a5"), - Color4Extensions.FromHex("812a96"), - Color4Extensions.FromHex("992861"), - }; } } diff --git a/osu.Game/Overlays/Chat/ChatOverlayTopBar.cs b/osu.Game/Overlays/Chat/ChatOverlayTopBar.cs index ad9ae412da..0410174dc1 100644 --- a/osu.Game/Overlays/Chat/ChatOverlayTopBar.cs +++ b/osu.Game/Overlays/Chat/ChatOverlayTopBar.cs @@ -17,7 +17,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Chat { - public class ChatOverlayTopBar : Container + public partial class ChatOverlayTopBar : Container { private Box background = null!; diff --git a/osu.Game/Overlays/Chat/ChatTextBar.cs b/osu.Game/Overlays/Chat/ChatTextBar.cs index 73314c2e44..682c96a695 100644 --- a/osu.Game/Overlays/Chat/ChatTextBar.cs +++ b/osu.Game/Overlays/Chat/ChatTextBar.cs @@ -17,7 +17,7 @@ using osuTK; namespace osu.Game.Overlays.Chat { - public class ChatTextBar : Container + public partial class ChatTextBar : Container { public readonly BindableBool ShowSearch = new BindableBool(); @@ -128,9 +128,8 @@ namespace osu.Game.Overlays.Chat chattingTextContainer.FadeTo(showSearch ? 0 : 1); searchIconContainer.FadeTo(showSearch ? 1 : 0); - // Clear search terms if any exist when switching back to chat mode - if (!showSearch) - OnSearchTermsChanged?.Invoke(string.Empty); + if (showSearch) + OnSearchTermsChanged?.Invoke(chatTextBox.Current.Value); }, true); currentChannel.BindValueChanged(change => @@ -151,6 +150,12 @@ namespace osu.Game.Overlays.Chat chattingText.Text = ChatStrings.TalkingIn(newChannel.Name); break; } + + if (change.OldValue != null) + chatTextBox.Current.UnbindFrom(change.OldValue.TextBoxMessage); + + if (newChannel != null) + chatTextBox.Current.BindTo(newChannel.TextBoxMessage); }, true); } diff --git a/osu.Game/Overlays/Chat/ChatTextBox.cs b/osu.Game/Overlays/Chat/ChatTextBox.cs index f0bdbce08d..7cd005698e 100644 --- a/osu.Game/Overlays/Chat/ChatTextBox.cs +++ b/osu.Game/Overlays/Chat/ChatTextBox.cs @@ -7,7 +7,7 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Chat { - public class ChatTextBox : HistoryTextBox + public partial class ChatTextBox : HistoryTextBox { public readonly BindableBool ShowSearch = new BindableBool(); @@ -24,7 +24,6 @@ namespace osu.Game.Overlays.Chat bool showSearch = change.NewValue; PlaceholderText = showSearch ? HomeStrings.SearchPlaceholder : ChatStrings.InputPlaceholder; - Text = string.Empty; }, true); } diff --git a/osu.Game/Overlays/Chat/DaySeparator.cs b/osu.Game/Overlays/Chat/DaySeparator.cs index d68f325738..e737b787ba 100644 --- a/osu.Game/Overlays/Chat/DaySeparator.cs +++ b/osu.Game/Overlays/Chat/DaySeparator.cs @@ -12,7 +12,7 @@ using osu.Game.Graphics.Sprites; namespace osu.Game.Overlays.Chat { - public class DaySeparator : Container + public partial class DaySeparator : Container { protected virtual float TextSize => 15; diff --git a/osu.Game/Overlays/Chat/DrawableChannel.cs b/osu.Game/Overlays/Chat/DrawableChannel.cs index 65876fd7c5..aa17df4907 100644 --- a/osu.Game/Overlays/Chat/DrawableChannel.cs +++ b/osu.Game/Overlays/Chat/DrawableChannel.cs @@ -17,7 +17,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Chat { - public class DrawableChannel : Container + public partial class DrawableChannel : Container { public readonly Channel Channel; protected FillFlowContainer ChatLineFlow; diff --git a/osu.Game/Overlays/Chat/DrawableUsername.cs b/osu.Game/Overlays/Chat/DrawableUsername.cs new file mode 100644 index 0000000000..8cd16047f3 --- /dev/null +++ b/osu.Game/Overlays/Chat/DrawableUsername.cs @@ -0,0 +1,227 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.Effects; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Input.Events; +using osu.Framework.Localisation; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osu.Game.Localisation; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Online.Chat; +using osu.Game.Resources.Localisation.Web; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Overlays.Chat +{ + public partial class DrawableUsername : OsuClickableContainer, IHasContextMenu + { + public Color4 AccentColour { get; } + + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => + colouredDrawable.ReceivePositionalInputAt(screenSpacePos); + + public float FontSize + { + set => drawableText.Font = OsuFont.GetFont(size: value, weight: FontWeight.Bold, italics: true); + } + + public LocalisableString Text + { + set => drawableText.Text = value; + } + + public override float Width + { + get => base.Width; + set => base.Width = drawableText.MaxWidth = value; + } + + [Resolved] + private IAPIProvider api { get; set; } = null!; + + [Resolved] + private OsuColour colours { get; set; } = null!; + + [Resolved(canBeNull: true)] + private ChannelManager? chatManager { get; set; } + + [Resolved(canBeNull: true)] + private ChatOverlay? chatOverlay { get; set; } + + [Resolved(canBeNull: true)] + private UserProfileOverlay? profileOverlay { get; set; } + + private readonly APIUser user; + private readonly OsuSpriteText drawableText; + + private readonly Drawable colouredDrawable; + + public DrawableUsername(APIUser user) + { + this.user = user; + + Action = openUserProfile; + + drawableText = new OsuSpriteText + { + Shadow = false, + Truncate = true, + EllipsisString = "…", + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + }; + + if (string.IsNullOrWhiteSpace(user.Colour)) + { + AccentColour = default_colours[user.Id % default_colours.Length]; + + Add(colouredDrawable = drawableText); + } + else + { + AccentColour = Color4Extensions.FromHex(user.Colour); + + Add(new Container + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + AutoSizeAxes = Axes.Both, + Masking = true, + CornerRadius = 4, + EdgeEffect = new EdgeEffectParameters + { + Roundness = 1, + Radius = 1, + Colour = Color4.Black.Opacity(0.3f), + Offset = new Vector2(0, 1), + Type = EdgeEffectType.Shadow, + }, + Child = new Container + { + AutoSizeAxes = Axes.Both, + Masking = true, + CornerRadius = 4, + Children = new[] + { + colouredDrawable = new Box + { + RelativeSizeAxes = Axes.Both, + }, + new Container + { + AutoSizeAxes = Axes.Both, + Padding = new MarginPadding { Left = 4, Right = 4, Bottom = 1, Top = -2 }, + Child = drawableText, + } + } + } + }); + } + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + drawableText.Colour = colours.ChatBlue; + colouredDrawable.Colour = AccentColour; + } + + public MenuItem[] ContextMenuItems + { + get + { + if (user.Equals(APIUser.SYSTEM_USER)) + return Array.Empty(); + + List items = new List + { + new OsuMenuItem(ContextMenuStrings.ViewProfile, MenuItemType.Highlighted, openUserProfile) + }; + + if (!user.Equals(api.LocalUser.Value)) + items.Add(new OsuMenuItem(UsersStrings.CardSendMessage, MenuItemType.Standard, openUserChannel)); + + return items.ToArray(); + } + } + + private void openUserChannel() + { + chatManager?.OpenPrivateChannel(user); + chatOverlay?.Show(); + } + + private void openUserProfile() + { + profileOverlay?.ShowUser(user); + } + + protected override bool OnHover(HoverEvent e) + { + colouredDrawable.FadeColour(AccentColour.Lighten(0.6f), 30, Easing.OutQuint); + + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + base.OnHoverLost(e); + + colouredDrawable.FadeColour(AccentColour, 800, Easing.OutQuint); + } + + private static readonly Color4[] default_colours = + { + Color4Extensions.FromHex("588c7e"), + Color4Extensions.FromHex("b2a367"), + Color4Extensions.FromHex("c98f65"), + Color4Extensions.FromHex("bc5151"), + Color4Extensions.FromHex("5c8bd6"), + Color4Extensions.FromHex("7f6ab7"), + Color4Extensions.FromHex("a368ad"), + Color4Extensions.FromHex("aa6880"), + + Color4Extensions.FromHex("6fad9b"), + Color4Extensions.FromHex("f2e394"), + Color4Extensions.FromHex("f2ae72"), + Color4Extensions.FromHex("f98f8a"), + Color4Extensions.FromHex("7daef4"), + Color4Extensions.FromHex("a691f2"), + Color4Extensions.FromHex("c894d3"), + Color4Extensions.FromHex("d895b0"), + + Color4Extensions.FromHex("53c4a1"), + Color4Extensions.FromHex("eace5c"), + Color4Extensions.FromHex("ea8c47"), + Color4Extensions.FromHex("fc4f4f"), + Color4Extensions.FromHex("3d94ea"), + Color4Extensions.FromHex("7760ea"), + Color4Extensions.FromHex("af52c6"), + Color4Extensions.FromHex("e25696"), + + Color4Extensions.FromHex("677c66"), + Color4Extensions.FromHex("9b8732"), + Color4Extensions.FromHex("8c5129"), + Color4Extensions.FromHex("8c3030"), + Color4Extensions.FromHex("1f5d91"), + Color4Extensions.FromHex("4335a5"), + Color4Extensions.FromHex("812a96"), + Color4Extensions.FromHex("992861"), + }; + } +} diff --git a/osu.Game/Overlays/Chat/Listing/ChannelListing.cs b/osu.Game/Overlays/Chat/Listing/ChannelListing.cs index 44255eb754..809ea2f11d 100644 --- a/osu.Game/Overlays/Chat/Listing/ChannelListing.cs +++ b/osu.Game/Overlays/Chat/Listing/ChannelListing.cs @@ -13,7 +13,7 @@ using osu.Game.Online.Chat; namespace osu.Game.Overlays.Chat.Listing { - public class ChannelListing : VisibilityContainer + public partial class ChannelListing : VisibilityContainer { public event Action? OnRequestJoin; public event Action? OnRequestLeave; diff --git a/osu.Game/Overlays/Chat/Listing/ChannelListingItem.cs b/osu.Game/Overlays/Chat/Listing/ChannelListingItem.cs index ffeab3b380..9c85c73ee4 100644 --- a/osu.Game/Overlays/Chat/Listing/ChannelListingItem.cs +++ b/osu.Game/Overlays/Chat/Listing/ChannelListingItem.cs @@ -22,7 +22,7 @@ using osuTK; namespace osu.Game.Overlays.Chat.Listing { - public class ChannelListingItem : OsuClickableContainer, IFilterable + public partial class ChannelListingItem : OsuClickableContainer, IFilterable { public event Action? OnRequestJoin; public event Action? OnRequestLeave; @@ -38,7 +38,7 @@ namespace osu.Game.Overlays.Chat.Listing private Box hoverBox = null!; private SpriteIcon checkbox = null!; private OsuSpriteText channelText = null!; - private OsuSpriteText topicText = null!; + private OsuTextFlowContainer topicText = null!; private IBindable channelJoined = null!; [Resolved] @@ -65,8 +65,8 @@ namespace osu.Game.Overlays.Chat.Listing Masking = true; CornerRadius = 5; - RelativeSizeAxes = Axes.X; - Height = 20 + (vertical_margin * 2); + RelativeSizeAxes = Content.RelativeSizeAxes = Axes.X; + AutoSizeAxes = Content.AutoSizeAxes = Axes.Y; Children = new Drawable[] { @@ -79,14 +79,19 @@ namespace osu.Game.Overlays.Chat.Listing }, new GridContainer { - RelativeSizeAxes = Axes.Both, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, ColumnDimensions = new[] { new Dimension(GridSizeMode.Absolute, 40), new Dimension(GridSizeMode.Absolute, 200), - new Dimension(GridSizeMode.Absolute, 400), + new Dimension(maxSize: 400), new Dimension(GridSizeMode.AutoSize), - new Dimension(), + new Dimension(GridSizeMode.Absolute, 50), // enough for any 5 digit user count + }, + RowDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize, minSize: 20 + (vertical_margin * 2)), }, Content = new[] { @@ -108,12 +113,13 @@ namespace osu.Game.Overlays.Chat.Listing Font = OsuFont.Torus.With(size: text_size, weight: FontWeight.SemiBold), Margin = new MarginPadding { Bottom = 2 }, }, - topicText = new OsuSpriteText + topicText = new OsuTextFlowContainer(t => t.Font = OsuFont.Torus.With(size: text_size)) { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, Text = Channel.Topic, - Font = OsuFont.Torus.With(size: text_size), Margin = new MarginPadding { Bottom = 2 }, }, new SpriteIcon diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index c491c0c695..c539cdc5ec 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -26,7 +26,7 @@ using osu.Game.Overlays.Chat.Listing; namespace osu.Game.Overlays { - public class ChatOverlay : OsuFocusedOverlayContainer, INamedOverlayComponent, IKeyBindingHandler + public partial class ChatOverlay : OsuFocusedOverlayContainer, INamedOverlayComponent, IKeyBindingHandler { public string IconTexture => "Icons/Hexacons/messaging"; public LocalisableString Title => ChatStrings.HeaderTitle; @@ -64,7 +64,7 @@ namespace osu.Game.Overlays private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Pink); [Cached] - private readonly Bindable currentChannel = new Bindable(); + private readonly Bindable currentChannel = new Bindable(); private readonly IBindableList availableChannels = new BindableList(); private readonly IBindableList joinedChannels = new BindableList(); @@ -293,7 +293,7 @@ namespace osu.Game.Overlays base.OnFocus(e); } - private void currentChannelChanged(ValueChangedEvent channel) + private void currentChannelChanged(ValueChangedEvent channel) { Channel? newChannel = channel.NewValue; @@ -352,11 +352,13 @@ namespace osu.Game.Overlays protected virtual DrawableChannel CreateDrawableChannel(Channel newChannel) => new DrawableChannel(newChannel); - private void joinedChannelsChanged(object sender, NotifyCollectionChangedEventArgs args) + private void joinedChannelsChanged(object? sender, NotifyCollectionChangedEventArgs args) { switch (args.Action) { case NotifyCollectionChangedAction.Add: + Debug.Assert(args.NewItems != null); + IEnumerable newChannels = args.NewItems.OfType().Where(isChatChannel); foreach (var channel in newChannels) @@ -365,6 +367,8 @@ namespace osu.Game.Overlays break; case NotifyCollectionChangedAction.Remove: + Debug.Assert(args.OldItems != null); + IEnumerable leftChannels = args.OldItems.OfType().Where(isChatChannel); foreach (var channel in leftChannels) @@ -384,7 +388,7 @@ namespace osu.Game.Overlays } } - private void availableChannelsChanged(object sender, NotifyCollectionChangedEventArgs args) + private void availableChannelsChanged(object? sender, NotifyCollectionChangedEventArgs args) => channelListing.UpdateAvailableChannels(channelManager.AvailableChannels); private void handleChatMessage(string message) @@ -402,7 +406,7 @@ namespace osu.Game.Overlays { List overlayChannels = channelList.Channels.ToList(); - if (overlayChannels.Count < 2) + if (overlayChannels.Count < 2 || currentChannel.Value == null) return; int currentIndex = overlayChannels.IndexOf(currentChannel.Value); diff --git a/osu.Game/Overlays/Comments/Buttons/ChevronButton.cs b/osu.Game/Overlays/Comments/Buttons/ChevronButton.cs index 46a455cbb3..88e7d00476 100644 --- a/osu.Game/Overlays/Comments/Buttons/ChevronButton.cs +++ b/osu.Game/Overlays/Comments/Buttons/ChevronButton.cs @@ -12,7 +12,7 @@ using osu.Framework.Allocation; namespace osu.Game.Overlays.Comments.Buttons { - public class ChevronButton : OsuHoverContainer + public partial class ChevronButton : OsuHoverContainer { public readonly BindableBool Expanded = new BindableBool(true); diff --git a/osu.Game/Overlays/Comments/Buttons/CommentRepliesButton.cs b/osu.Game/Overlays/Comments/Buttons/CommentRepliesButton.cs index d24a0cd27b..d9576f5b72 100644 --- a/osu.Game/Overlays/Comments/Buttons/CommentRepliesButton.cs +++ b/osu.Game/Overlays/Comments/Buttons/CommentRepliesButton.cs @@ -17,7 +17,7 @@ using static osu.Game.Graphics.UserInterface.ShowMoreButton; namespace osu.Game.Overlays.Comments.Buttons { - public abstract class CommentRepliesButton : CompositeDrawable + public abstract partial class CommentRepliesButton : CompositeDrawable { protected LocalisableString Text { diff --git a/osu.Game/Overlays/Comments/Buttons/LoadRepliesButton.cs b/osu.Game/Overlays/Comments/Buttons/LoadRepliesButton.cs index 42aca2f4a3..65d8685403 100644 --- a/osu.Game/Overlays/Comments/Buttons/LoadRepliesButton.cs +++ b/osu.Game/Overlays/Comments/Buttons/LoadRepliesButton.cs @@ -9,7 +9,7 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Comments.Buttons { - public class LoadRepliesButton : LoadingButton + public partial class LoadRepliesButton : LoadingButton { private ButtonContent content; @@ -24,7 +24,7 @@ namespace osu.Game.Overlays.Comments.Buttons protected override void OnLoadFinished() => content.ToggleTextVisibility(true); - private class ButtonContent : CommentRepliesButton + private partial class ButtonContent : CommentRepliesButton { public ButtonContent() { diff --git a/osu.Game/Overlays/Comments/Buttons/ShowMoreRepliesButton.cs b/osu.Game/Overlays/Comments/Buttons/ShowMoreRepliesButton.cs index 6f3841d52e..0aedbe4c53 100644 --- a/osu.Game/Overlays/Comments/Buttons/ShowMoreRepliesButton.cs +++ b/osu.Game/Overlays/Comments/Buttons/ShowMoreRepliesButton.cs @@ -15,7 +15,7 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Comments.Buttons { - public class ShowMoreRepliesButton : LoadingButton + public partial class ShowMoreRepliesButton : LoadingButton { protected override IEnumerable EffectTargets => new[] { text }; diff --git a/osu.Game/Overlays/Comments/Buttons/ShowRepliesButton.cs b/osu.Game/Overlays/Comments/Buttons/ShowRepliesButton.cs index 845a630d97..aa9b2df7e4 100644 --- a/osu.Game/Overlays/Comments/Buttons/ShowRepliesButton.cs +++ b/osu.Game/Overlays/Comments/Buttons/ShowRepliesButton.cs @@ -9,7 +9,7 @@ using osu.Framework.Input.Events; namespace osu.Game.Overlays.Comments.Buttons { - public class ShowRepliesButton : CommentRepliesButton + public partial class ShowRepliesButton : CommentRepliesButton { public readonly BindableBool Expanded = new BindableBool(true); diff --git a/osu.Game/Overlays/Comments/CancellableCommentEditor.cs b/osu.Game/Overlays/Comments/CancellableCommentEditor.cs index 7ba6de86b7..02abc5b6cf 100644 --- a/osu.Game/Overlays/Comments/CancellableCommentEditor.cs +++ b/osu.Game/Overlays/Comments/CancellableCommentEditor.cs @@ -1,76 +1,24 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; -using System.Collections.Generic; using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Game.Graphics; -using osu.Game.Graphics.Containers; -using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Comments { - public abstract class CancellableCommentEditor : CommentEditor + public abstract partial class CancellableCommentEditor : CommentEditor { - public Action OnCancel; + public Action? OnCancel; [BackgroundDependencyLoader] private void load() { - ButtonsContainer.Add(new CancelButton + ButtonsContainer.Add(new EditorButton { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - Action = () => OnCancel?.Invoke() + Action = () => OnCancel?.Invoke(), + Text = CommonStrings.ButtonsCancel, }); } - - private class CancelButton : OsuHoverContainer - { - protected override IEnumerable EffectTargets => new[] { background }; - - private readonly Box background; - - public CancelButton() - : base(HoverSampleSet.Button) - { - AutoSizeAxes = Axes.Both; - Child = new CircularContainer - { - Masking = true, - Height = 25, - AutoSizeAxes = Axes.X, - Children = new Drawable[] - { - background = new Box - { - RelativeSizeAxes = Axes.Both - }, - new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold), - Margin = new MarginPadding { Horizontal = 20 }, - Text = CommonStrings.ButtonsCancel - } - } - }; - } - - [BackgroundDependencyLoader] - private void load(OverlayColourProvider colourProvider) - { - IdleColour = colourProvider.Light4; - HoverColour = colourProvider.Light3; - } - } } } diff --git a/osu.Game/Overlays/Comments/CommentEditor.cs b/osu.Game/Overlays/Comments/CommentEditor.cs index e2a7e78356..769263b3fc 100644 --- a/osu.Game/Overlays/Comments/CommentEditor.cs +++ b/osu.Game/Overlays/Comments/CommentEditor.cs @@ -1,49 +1,53 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; -using osu.Framework.Graphics.Containers; +using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -using osu.Framework.Graphics.UserInterface; -using osu.Framework.Graphics.Sprites; -using osuTK.Graphics; using osu.Game.Graphics.UserInterface; -using System.Collections.Generic; -using System; +using osu.Game.Graphics.UserInterfaceV2; using osuTK; -using osu.Framework.Bindables; +using osuTK.Graphics; namespace osu.Game.Overlays.Comments { - public abstract class CommentEditor : CompositeDrawable + public abstract partial class CommentEditor : CompositeDrawable { private const int side_padding = 8; - public Action OnCommit; + protected abstract LocalisableString FooterText { get; } - public bool IsLoading + protected abstract LocalisableString CommitButtonText { get; } + + protected abstract LocalisableString TextBoxPlaceholder { get; } + + protected FillFlowContainer ButtonsContainer { get; private set; } = null!; + + protected readonly Bindable Current = new Bindable(string.Empty); + + private RoundedButton commitButton = null!; + private LoadingSpinner loadingSpinner = null!; + + protected bool ShowLoadingSpinner { - get => commitButton.IsLoading; - set => commitButton.IsLoading = value; + set + { + if (value) + loadingSpinner.Show(); + else + loadingSpinner.Hide(); + + updateCommitButtonState(); + } } - protected abstract string FooterText { get; } - - protected abstract string CommitButtonText { get; } - - protected abstract string TextBoxPlaceholder { get; } - - protected FillFlowContainer ButtonsContainer { get; private set; } - - protected readonly Bindable Current = new Bindable(); - - private CommitButton commitButton; - [BackgroundDependencyLoader] private void load(OverlayColourProvider colourProvider) { @@ -79,7 +83,7 @@ namespace osu.Game.Overlays.Comments }, new Container { - Name = "Footer", + Name = @"Footer", RelativeSizeAxes = Axes.X, Height = 35, Padding = new MarginPadding { Horizontal = side_padding }, @@ -92,54 +96,64 @@ namespace osu.Game.Overlays.Comments Font = OsuFont.GetFont(size: 12, weight: FontWeight.SemiBold), Text = FooterText }, - ButtonsContainer = new FillFlowContainer + new FillFlowContainer { - Name = "Buttons", Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, Spacing = new Vector2(5, 0), - Child = commitButton = new CommitButton(CommitButtonText) + Children = new Drawable[] { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - Action = () => + ButtonsContainer = new FillFlowContainer { - OnCommit?.Invoke(Current.Value); - Current.Value = string.Empty; - } + Name = @"Buttons", + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(5, 0), + Child = commitButton = new EditorButton + { + Text = CommitButtonText, + Action = () => OnCommit(Current.Value) + } + }, + loadingSpinner = new LoadingSpinner + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + Size = new Vector2(18), + }, } - } + }, } } } } }); - textBox.OnCommit += (_, _) => - { - if (commitButton.IsBlocked.Value) - return; - - commitButton.TriggerClick(); - }; + textBox.OnCommit += (_, _) => commitButton.TriggerClick(); } protected override void LoadComplete() { base.LoadComplete(); - - Current.BindValueChanged(text => commitButton.IsBlocked.Value = string.IsNullOrEmpty(text.NewValue), true); + Current.BindValueChanged(_ => updateCommitButtonState(), true); } - private class EditorTextBox : BasicTextBox + protected abstract void OnCommit(string text); + + private void updateCommitButtonState() => + commitButton.Enabled.Value = loadingSpinner.State.Value == Visibility.Hidden && !string.IsNullOrEmpty(Current.Value); + + private partial class EditorTextBox : BasicTextBox { protected override float LeftRightPadding => side_padding; protected override Color4 SelectionColour => Color4.Gray; - private OsuSpriteText placeholder; + private OsuSpriteText placeholder = null!; public EditorTextBox() { @@ -163,88 +177,26 @@ namespace osu.Game.Overlays.Comments protected override Drawable GetDrawableCharacter(char c) => new FallingDownContainer { AutoSizeAxes = Axes.Both, - Child = new OsuSpriteText { Text = c.ToString(), Font = OsuFont.GetFont(size: CalculatedTextSize) }, + Child = new OsuSpriteText { Text = c.ToString(), Font = OsuFont.GetFont(size: CalculatedTextSize) } }; } - private class CommitButton : LoadingButton + protected partial class EditorButton : RoundedButton { - private const int duration = 200; - - public readonly BindableBool IsBlocked = new BindableBool(); - - public override bool PropagatePositionalInputSubTree => !IsBlocked.Value && base.PropagatePositionalInputSubTree; - - protected override IEnumerable EffectTargets => new[] { background }; - - private readonly string text; - - [Resolved] - private OverlayColourProvider colourProvider { get; set; } - - private OsuSpriteText drawableText; - private Box background; - private Box blockedBackground; - - public CommitButton(string text) + public EditorButton() { - this.text = text; - - AutoSizeAxes = Axes.Both; - LoadingAnimationSize = new Vector2(10); + Width = 80; + Height = 25; + Anchor = Anchor.CentreRight; + Origin = Anchor.CentreRight; } - [BackgroundDependencyLoader] - private void load() + protected override SpriteText CreateText() { - IdleColour = colourProvider.Light4; - HoverColour = colourProvider.Light3; - blockedBackground.Colour = colourProvider.Background5; + var t = base.CreateText(); + t.Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 12); + return t; } - - protected override void LoadComplete() - { - base.LoadComplete(); - IsBlocked.BindValueChanged(onBlockedStateChanged, true); - } - - private void onBlockedStateChanged(ValueChangedEvent isBlocked) - { - drawableText.FadeColour(isBlocked.NewValue ? colourProvider.Foreground1 : Color4.White, duration, Easing.OutQuint); - background.FadeTo(isBlocked.NewValue ? 0 : 1, duration, Easing.OutQuint); - } - - protected override Drawable CreateContent() => new CircularContainer - { - Masking = true, - Height = 25, - AutoSizeAxes = Axes.X, - Children = new Drawable[] - { - blockedBackground = new Box - { - RelativeSizeAxes = Axes.Both - }, - background = new Box - { - RelativeSizeAxes = Axes.Both, - Alpha = 0 - }, - drawableText = new OsuSpriteText - { - AlwaysPresent = true, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold), - Margin = new MarginPadding { Horizontal = 20 }, - Text = text, - } - } - }; - - protected override void OnLoadStarted() => drawableText.FadeOut(duration, Easing.OutQuint); - - protected override void OnLoadFinished() => drawableText.FadeIn(duration, Easing.OutQuint); } } } diff --git a/osu.Game/Overlays/Comments/CommentMarkdownContainer.cs b/osu.Game/Overlays/Comments/CommentMarkdownContainer.cs index b32b1c74c4..9cc20caa05 100644 --- a/osu.Game/Overlays/Comments/CommentMarkdownContainer.cs +++ b/osu.Game/Overlays/Comments/CommentMarkdownContainer.cs @@ -9,13 +9,16 @@ using osu.Game.Graphics.Containers.Markdown; namespace osu.Game.Overlays.Comments { - public class CommentMarkdownContainer : OsuMarkdownContainer + public partial class CommentMarkdownContainer : OsuMarkdownContainer { - protected override bool Autolinks => true; + protected override OsuMarkdownContainerOptions Options => new OsuMarkdownContainerOptions + { + Autolinks = true + }; protected override MarkdownHeading CreateHeading(HeadingBlock headingBlock) => new CommentMarkdownHeading(headingBlock); - private class CommentMarkdownHeading : OsuMarkdownHeading + private partial class CommentMarkdownHeading : OsuMarkdownHeading { public CommentMarkdownHeading(HeadingBlock headingBlock) : base(headingBlock) diff --git a/osu.Game/Overlays/Comments/CommentReportButton.cs b/osu.Game/Overlays/Comments/CommentReportButton.cs index 4f5c5c6dcf..ba5319094b 100644 --- a/osu.Game/Overlays/Comments/CommentReportButton.cs +++ b/osu.Game/Overlays/Comments/CommentReportButton.cs @@ -3,6 +3,7 @@ using osu.Framework.Allocation; using osu.Framework.Extensions; +using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; @@ -18,7 +19,7 @@ using osuTK; namespace osu.Game.Overlays.Comments { - public class CommentReportButton : CompositeDrawable, IHasPopover + public partial class CommentReportButton : CompositeDrawable, IHasPopover { private readonly Comment comment; @@ -53,7 +54,7 @@ namespace osu.Game.Overlays.Comments } }; - link.AddLink(UsersStrings.ReportButtonText, this.ShowPopover); + link.AddLink(ReportStrings.CommentButton.ToLower(), this.ShowPopover); } private void report(CommentReportReason reason, string comments) diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index 4a836e0e62..7bd2d6a5e6 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -23,7 +23,7 @@ using APIUser = osu.Game.Online.API.Requests.Responses.APIUser; namespace osu.Game.Overlays.Comments { - public class CommentsContainer : CompositeDrawable + public partial class CommentsContainer : CompositeDrawable { private readonly Bindable type = new Bindable(); private readonly BindableLong id = new BindableLong(); @@ -317,7 +317,7 @@ namespace osu.Game.Overlays.Comments base.Dispose(isDisposing); } - private class NoCommentsPlaceholder : CompositeDrawable + private partial class NoCommentsPlaceholder : CompositeDrawable { [BackgroundDependencyLoader] private void load() diff --git a/osu.Game/Overlays/Comments/CommentsHeader.cs b/osu.Game/Overlays/Comments/CommentsHeader.cs index 5684841c37..e6d44e618b 100644 --- a/osu.Game/Overlays/Comments/CommentsHeader.cs +++ b/osu.Game/Overlays/Comments/CommentsHeader.cs @@ -20,7 +20,7 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Comments { - public class CommentsHeader : CompositeDrawable + public partial class CommentsHeader : CompositeDrawable { public readonly Bindable Sort = new Bindable(); public readonly BindableBool ShowDeleted = new BindableBool(); @@ -67,7 +67,7 @@ namespace osu.Game.Overlays.Comments background.Colour = colourProvider.Background4; } - private class ShowDeletedButton : HeaderButton + private partial class ShowDeletedButton : HeaderButton { public readonly BindableBool Checked = new BindableBool(); diff --git a/osu.Game/Overlays/Comments/CommentsShowMoreButton.cs b/osu.Game/Overlays/Comments/CommentsShowMoreButton.cs index 84d1f67486..1770fcb269 100644 --- a/osu.Game/Overlays/Comments/CommentsShowMoreButton.cs +++ b/osu.Game/Overlays/Comments/CommentsShowMoreButton.cs @@ -11,7 +11,7 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Comments { - public class CommentsShowMoreButton : ShowMoreButton + public partial class CommentsShowMoreButton : ShowMoreButton { public readonly BindableInt Current = new BindableInt(); diff --git a/osu.Game/Overlays/Comments/DeletedCommentsCounter.cs b/osu.Game/Overlays/Comments/DeletedCommentsCounter.cs index 2c7ed4f5b3..6adb388185 100644 --- a/osu.Game/Overlays/Comments/DeletedCommentsCounter.cs +++ b/osu.Game/Overlays/Comments/DeletedCommentsCounter.cs @@ -14,7 +14,7 @@ using osu.Game.Graphics.Sprites; namespace osu.Game.Overlays.Comments { - public class DeletedCommentsCounter : CompositeDrawable + public partial class DeletedCommentsCounter : CompositeDrawable { public readonly BindableBool ShowDeleted = new BindableBool(); diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index aa08de798c..834abd5e9f 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -19,6 +19,8 @@ using System; using osu.Framework.Graphics.Shapes; using osu.Framework.Extensions.IEnumerableExtensions; using System.Collections.Specialized; +using System.Diagnostics; +using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Localisation; using osu.Framework.Platform; using osu.Game.Graphics.UserInterface; @@ -32,7 +34,7 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Comments { [Cached] - public class DrawableComment : CompositeDrawable + public partial class DrawableComment : CompositeDrawable { private const int avatar_size = 40; @@ -331,11 +333,11 @@ namespace osu.Game.Overlays.Comments if (WasDeleted) makeDeleted(); - actionsContainer.AddLink("Copy link", copyUrl); + actionsContainer.AddLink(CommonStrings.ButtonsPermalink, copyUrl); actionsContainer.AddArbitraryDrawable(Empty().With(d => d.Width = 10)); if (Comment.UserId.HasValue && Comment.UserId.Value == api.LocalUser.Value.Id) - actionsContainer.AddLink("Delete", deleteComment); + actionsContainer.AddLink(CommonStrings.ButtonsDelete.ToLower(), deleteComment); else actionsContainer.AddArbitraryDrawable(new CommentReportButton(Comment)); @@ -359,6 +361,8 @@ namespace osu.Game.Overlays.Comments switch (args.Action) { case NotifyCollectionChangedAction.Add: + Debug.Assert(args.NewItems != null); + onRepliesAdded(args.NewItems.Cast()); break; @@ -497,7 +501,7 @@ namespace osu.Game.Overlays.Comments }; } - private class PinnedCommentNotice : FillFlowContainer + private partial class PinnedCommentNotice : FillFlowContainer { public PinnedCommentNotice() { @@ -524,7 +528,7 @@ namespace osu.Game.Overlays.Comments } } - private class ParentUsername : FillFlowContainer, IHasTooltip + private partial class ParentUsername : FillFlowContainer, IHasTooltip { public LocalisableString TooltipText => getParentMessage(); @@ -553,12 +557,12 @@ namespace osu.Game.Overlays.Comments }; } - private string getParentMessage() + private LocalisableString getParentMessage() { if (parentComment == null) return string.Empty; - return parentComment.HasMessage ? parentComment.Message : parentComment.IsDeleted ? "deleted" : string.Empty; + return parentComment.HasMessage ? parentComment.Message : parentComment.IsDeleted ? CommentsStrings.Deleted : string.Empty; } } } diff --git a/osu.Game/Overlays/Comments/HeaderButton.cs b/osu.Game/Overlays/Comments/HeaderButton.cs index 186b892c4d..de99cd6cc8 100644 --- a/osu.Game/Overlays/Comments/HeaderButton.cs +++ b/osu.Game/Overlays/Comments/HeaderButton.cs @@ -11,7 +11,7 @@ using osu.Framework.Input.Events; namespace osu.Game.Overlays.Comments { - public class HeaderButton : Container + public partial class HeaderButton : Container { private const int transition_duration = 200; diff --git a/osu.Game/Overlays/Comments/ReportCommentPopover.cs b/osu.Game/Overlays/Comments/ReportCommentPopover.cs index 39fd52aa2a..f3b2a2f97c 100644 --- a/osu.Game/Overlays/Comments/ReportCommentPopover.cs +++ b/osu.Game/Overlays/Comments/ReportCommentPopover.cs @@ -18,7 +18,7 @@ using osuTK; namespace osu.Game.Overlays.Comments { - public class ReportCommentPopover : OsuPopover + public partial class ReportCommentPopover : OsuPopover { public Action? Action; diff --git a/osu.Game/Overlays/Comments/TotalCommentsCounter.cs b/osu.Game/Overlays/Comments/TotalCommentsCounter.cs index 218d8383f6..38928f6f3d 100644 --- a/osu.Game/Overlays/Comments/TotalCommentsCounter.cs +++ b/osu.Game/Overlays/Comments/TotalCommentsCounter.cs @@ -15,7 +15,7 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Comments { - public class TotalCommentsCounter : CompositeDrawable + public partial class TotalCommentsCounter : CompositeDrawable { public readonly BindableInt Current = new BindableInt(); diff --git a/osu.Game/Overlays/Comments/VotePill.cs b/osu.Game/Overlays/Comments/VotePill.cs index 7a4b83cc48..6cfa5cb9e8 100644 --- a/osu.Game/Overlays/Comments/VotePill.cs +++ b/osu.Game/Overlays/Comments/VotePill.cs @@ -24,7 +24,7 @@ using System.Linq; namespace osu.Game.Overlays.Comments { - public class VotePill : LoadingButton, IHasAccentColour + public partial class VotePill : LoadingButton, IHasAccentColour { private const int duration = 200; diff --git a/osu.Game/Overlays/Dashboard/CurrentlyPlayingDisplay.cs b/osu.Game/Overlays/Dashboard/CurrentlyPlayingDisplay.cs index aae4932c22..1540aa8fbb 100644 --- a/osu.Game/Overlays/Dashboard/CurrentlyPlayingDisplay.cs +++ b/osu.Game/Overlays/Dashboard/CurrentlyPlayingDisplay.cs @@ -30,7 +30,7 @@ using osuTK; namespace osu.Game.Overlays.Dashboard { - internal class CurrentlyPlayingDisplay : CompositeDrawable + internal partial class CurrentlyPlayingDisplay : CompositeDrawable { private const float search_textbox_height = 40; private const float padding = 10; @@ -153,7 +153,7 @@ namespace osu.Game.Overlays.Dashboard panel.Origin = Anchor.TopCentre; }); - public class PlayingUserPanel : CompositeDrawable, IFilterable + public partial class PlayingUserPanel : CompositeDrawable, IFilterable { public readonly APIUser User; @@ -203,7 +203,7 @@ namespace osu.Game.Overlays.Dashboard Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, }, - new PurpleTriangleButton + new PurpleRoundedButton { RelativeSizeAxes = Axes.X, Text = "Spectate", diff --git a/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs b/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs index 370181a0cb..5cbeb8f306 100644 --- a/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs +++ b/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs @@ -10,11 +10,11 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Dashboard { - public class DashboardOverlayHeader : TabControlOverlayHeader + public partial class DashboardOverlayHeader : TabControlOverlayHeader { protected override OverlayTitle CreateTitle() => new DashboardTitle(); - private class DashboardTitle : OverlayTitle + private partial class DashboardTitle : OverlayTitle { public DashboardTitle() { diff --git a/osu.Game/Overlays/Dashboard/Friends/FriendDisplay.cs b/osu.Game/Overlays/Dashboard/Friends/FriendDisplay.cs index bfd356193d..73fab6d62b 100644 --- a/osu.Game/Overlays/Dashboard/Friends/FriendDisplay.cs +++ b/osu.Game/Overlays/Dashboard/Friends/FriendDisplay.cs @@ -19,7 +19,7 @@ using osuTK; namespace osu.Game.Overlays.Dashboard.Friends { - public class FriendDisplay : CompositeDrawable + public partial class FriendDisplay : CompositeDrawable { private List users = new List(); diff --git a/osu.Game/Overlays/Dashboard/Friends/FriendOnlineStreamControl.cs b/osu.Game/Overlays/Dashboard/Friends/FriendOnlineStreamControl.cs index fc6158e747..9f429c23d8 100644 --- a/osu.Game/Overlays/Dashboard/Friends/FriendOnlineStreamControl.cs +++ b/osu.Game/Overlays/Dashboard/Friends/FriendOnlineStreamControl.cs @@ -9,7 +9,7 @@ using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Overlays.Dashboard.Friends { - public class FriendOnlineStreamControl : OverlayStreamControl + public partial class FriendOnlineStreamControl : OverlayStreamControl { protected override OverlayStreamItem CreateStreamItem(FriendStream value) => new FriendsOnlineStatusItem(value); diff --git a/osu.Game/Overlays/Dashboard/Friends/FriendsOnlineStatusItem.cs b/osu.Game/Overlays/Dashboard/Friends/FriendsOnlineStatusItem.cs index 7e2ec3f442..785eef38ad 100644 --- a/osu.Game/Overlays/Dashboard/Friends/FriendsOnlineStatusItem.cs +++ b/osu.Game/Overlays/Dashboard/Friends/FriendsOnlineStatusItem.cs @@ -11,7 +11,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Dashboard.Friends { - public class FriendsOnlineStatusItem : OverlayStreamItem + public partial class FriendsOnlineStatusItem : OverlayStreamItem { public FriendsOnlineStatusItem(FriendStream value) : base(value) diff --git a/osu.Game/Overlays/Dashboard/Friends/UserListToolbar.cs b/osu.Game/Overlays/Dashboard/Friends/UserListToolbar.cs index 25ddb9e704..db8510325c 100644 --- a/osu.Game/Overlays/Dashboard/Friends/UserListToolbar.cs +++ b/osu.Game/Overlays/Dashboard/Friends/UserListToolbar.cs @@ -10,7 +10,7 @@ using osu.Framework.Bindables; namespace osu.Game.Overlays.Dashboard.Friends { - public class UserListToolbar : CompositeDrawable + public partial class UserListToolbar : CompositeDrawable { public Bindable SortCriteria => sortControl.Current; diff --git a/osu.Game/Overlays/Dashboard/Friends/UserSortTabControl.cs b/osu.Game/Overlays/Dashboard/Friends/UserSortTabControl.cs index 466e36c1a9..886ed08af2 100644 --- a/osu.Game/Overlays/Dashboard/Friends/UserSortTabControl.cs +++ b/osu.Game/Overlays/Dashboard/Friends/UserSortTabControl.cs @@ -9,7 +9,7 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Dashboard.Friends { - public class UserSortTabControl : OverlaySortTabControl + public partial class UserSortTabControl : OverlaySortTabControl { } diff --git a/osu.Game/Overlays/Dashboard/Home/DashboardBeatmapListing.cs b/osu.Game/Overlays/Dashboard/Home/DashboardBeatmapListing.cs index e9c7af3339..0282ba8785 100644 --- a/osu.Game/Overlays/Dashboard/Home/DashboardBeatmapListing.cs +++ b/osu.Game/Overlays/Dashboard/Home/DashboardBeatmapListing.cs @@ -12,7 +12,7 @@ using osuTK; namespace osu.Game.Overlays.Dashboard.Home { - public class DashboardBeatmapListing : CompositeDrawable + public partial class DashboardBeatmapListing : CompositeDrawable { private readonly List newBeatmaps; private readonly List popularBeatmaps; diff --git a/osu.Game/Overlays/Dashboard/Home/DashboardBeatmapPanel.cs b/osu.Game/Overlays/Dashboard/Home/DashboardBeatmapPanel.cs index 1e4ba2ef05..792d6cc785 100644 --- a/osu.Game/Overlays/Dashboard/Home/DashboardBeatmapPanel.cs +++ b/osu.Game/Overlays/Dashboard/Home/DashboardBeatmapPanel.cs @@ -18,7 +18,7 @@ using osuTK; namespace osu.Game.Overlays.Dashboard.Home { - public abstract class DashboardBeatmapPanel : OsuClickableContainer + public abstract partial class DashboardBeatmapPanel : OsuClickableContainer { [Resolved] protected OverlayColourProvider ColourProvider { get; private set; } diff --git a/osu.Game/Overlays/Dashboard/Home/DashboardNewBeatmapPanel.cs b/osu.Game/Overlays/Dashboard/Home/DashboardNewBeatmapPanel.cs index 258fd56dd7..fef33bdf5a 100644 --- a/osu.Game/Overlays/Dashboard/Home/DashboardNewBeatmapPanel.cs +++ b/osu.Game/Overlays/Dashboard/Home/DashboardNewBeatmapPanel.cs @@ -10,7 +10,7 @@ using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Overlays.Dashboard.Home { - public class DashboardNewBeatmapPanel : DashboardBeatmapPanel + public partial class DashboardNewBeatmapPanel : DashboardBeatmapPanel { public DashboardNewBeatmapPanel(APIBeatmapSet beatmapSet) : base(beatmapSet) diff --git a/osu.Game/Overlays/Dashboard/Home/DashboardPopularBeatmapPanel.cs b/osu.Game/Overlays/Dashboard/Home/DashboardPopularBeatmapPanel.cs index 743bd5440f..54d95c994b 100644 --- a/osu.Game/Overlays/Dashboard/Home/DashboardPopularBeatmapPanel.cs +++ b/osu.Game/Overlays/Dashboard/Home/DashboardPopularBeatmapPanel.cs @@ -13,7 +13,7 @@ using osuTK; namespace osu.Game.Overlays.Dashboard.Home { - public class DashboardPopularBeatmapPanel : DashboardBeatmapPanel + public partial class DashboardPopularBeatmapPanel : DashboardBeatmapPanel { public DashboardPopularBeatmapPanel(APIBeatmapSet beatmapSet) : base(beatmapSet) diff --git a/osu.Game/Overlays/Dashboard/Home/DrawableBeatmapList.cs b/osu.Game/Overlays/Dashboard/Home/DrawableBeatmapList.cs index 8f140facef..af36f71dd2 100644 --- a/osu.Game/Overlays/Dashboard/Home/DrawableBeatmapList.cs +++ b/osu.Game/Overlays/Dashboard/Home/DrawableBeatmapList.cs @@ -16,7 +16,7 @@ using osuTK; namespace osu.Game.Overlays.Dashboard.Home { - public abstract class DrawableBeatmapList : CompositeDrawable + public abstract partial class DrawableBeatmapList : CompositeDrawable { private readonly List beatmapSets; diff --git a/osu.Game/Overlays/Dashboard/Home/DrawableNewBeatmapList.cs b/osu.Game/Overlays/Dashboard/Home/DrawableNewBeatmapList.cs index c6917b41fb..8a60d8568c 100644 --- a/osu.Game/Overlays/Dashboard/Home/DrawableNewBeatmapList.cs +++ b/osu.Game/Overlays/Dashboard/Home/DrawableNewBeatmapList.cs @@ -10,7 +10,7 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Dashboard.Home { - public class DrawableNewBeatmapList : DrawableBeatmapList + public partial class DrawableNewBeatmapList : DrawableBeatmapList { public DrawableNewBeatmapList(List beatmapSets) : base(beatmapSets) diff --git a/osu.Game/Overlays/Dashboard/Home/DrawablePopularBeatmapList.cs b/osu.Game/Overlays/Dashboard/Home/DrawablePopularBeatmapList.cs index 9ff12623e0..aab99d0ed3 100644 --- a/osu.Game/Overlays/Dashboard/Home/DrawablePopularBeatmapList.cs +++ b/osu.Game/Overlays/Dashboard/Home/DrawablePopularBeatmapList.cs @@ -10,7 +10,7 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Dashboard.Home { - public class DrawablePopularBeatmapList : DrawableBeatmapList + public partial class DrawablePopularBeatmapList : DrawableBeatmapList { public DrawablePopularBeatmapList(List beatmapSets) : base(beatmapSets) diff --git a/osu.Game/Overlays/Dashboard/Home/HomePanel.cs b/osu.Game/Overlays/Dashboard/Home/HomePanel.cs index 099e16cd55..8023c093aa 100644 --- a/osu.Game/Overlays/Dashboard/Home/HomePanel.cs +++ b/osu.Game/Overlays/Dashboard/Home/HomePanel.cs @@ -14,7 +14,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Dashboard.Home { - public class HomePanel : Container + public partial class HomePanel : Container { protected override Container Content => content; diff --git a/osu.Game/Overlays/Dashboard/Home/News/FeaturedNewsItemPanel.cs b/osu.Game/Overlays/Dashboard/Home/News/FeaturedNewsItemPanel.cs index 1d904526fd..dabe65964a 100644 --- a/osu.Game/Overlays/Dashboard/Home/News/FeaturedNewsItemPanel.cs +++ b/osu.Game/Overlays/Dashboard/Home/News/FeaturedNewsItemPanel.cs @@ -5,6 +5,7 @@ using System; using osu.Framework.Allocation; +using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; @@ -20,7 +21,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Dashboard.Home.News { - public class FeaturedNewsItemPanel : HomePanel + public partial class FeaturedNewsItemPanel : HomePanel { private readonly APINewsPost post; @@ -104,7 +105,7 @@ namespace osu.Game.Overlays.Dashboard.Home.News }; } - private class ClickableNewsBackground : OsuHoverContainer + private partial class ClickableNewsBackground : OsuHoverContainer { private readonly APINewsPost post; @@ -137,7 +138,7 @@ namespace osu.Game.Overlays.Dashboard.Home.News } } - private class Date : CompositeDrawable, IHasCustomTooltip + private partial class Date : CompositeDrawable, IHasCustomTooltip { private readonly DateTimeOffset date; @@ -167,7 +168,7 @@ namespace osu.Game.Overlays.Dashboard.Home.News Origin = Anchor.TopRight, Font = OsuFont.GetFont(weight: FontWeight.Bold), // using Bold since there is no 800 weight alternative Colour = colourProvider.Light1, - Text = $"{date:dd}" + Text = date.ToLocalisableString(@"dd") }, new TextFlowContainer(f => { @@ -178,7 +179,7 @@ namespace osu.Game.Overlays.Dashboard.Home.News Anchor = Anchor.TopRight, Origin = Anchor.TopRight, AutoSizeAxes = Axes.Both, - Text = $"{date:MMM yyyy}" + Text = date.ToLocalisableString(@"MMM yyyy") } } }; diff --git a/osu.Game/Overlays/Dashboard/Home/News/NewsGroupItem.cs b/osu.Game/Overlays/Dashboard/Home/News/NewsGroupItem.cs index 9b66e5524b..9b27d1a193 100644 --- a/osu.Game/Overlays/Dashboard/Home/News/NewsGroupItem.cs +++ b/osu.Game/Overlays/Dashboard/Home/News/NewsGroupItem.cs @@ -5,6 +5,7 @@ using System; using osu.Framework.Allocation; +using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; @@ -14,7 +15,7 @@ using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Overlays.Dashboard.Home.News { - public class NewsGroupItem : CompositeDrawable + public partial class NewsGroupItem : CompositeDrawable { private readonly APINewsPost post; @@ -69,7 +70,7 @@ namespace osu.Game.Overlays.Dashboard.Home.News }; } - private class Date : CompositeDrawable, IHasCustomTooltip + private partial class Date : CompositeDrawable, IHasCustomTooltip { private readonly DateTimeOffset date; @@ -98,12 +99,12 @@ namespace osu.Game.Overlays.Dashboard.Home.News Margin = new MarginPadding { Vertical = 5 } }; - textFlow.AddText($"{date:dd}", t => + textFlow.AddText(date.ToLocalisableString(@"dd"), t => { t.Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold); }); - textFlow.AddText($"{date: MMM}", t => + textFlow.AddText(date.ToLocalisableString(@" MMM"), t => { t.Font = OsuFont.GetFont(size: 14, weight: FontWeight.Regular); }); diff --git a/osu.Game/Overlays/Dashboard/Home/News/NewsItemGroupPanel.cs b/osu.Game/Overlays/Dashboard/Home/News/NewsItemGroupPanel.cs index 4456a292a5..fa59f38690 100644 --- a/osu.Game/Overlays/Dashboard/Home/News/NewsItemGroupPanel.cs +++ b/osu.Game/Overlays/Dashboard/Home/News/NewsItemGroupPanel.cs @@ -12,7 +12,7 @@ using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Overlays.Dashboard.Home.News { - public class NewsItemGroupPanel : HomePanel + public partial class NewsItemGroupPanel : HomePanel { private readonly List posts; diff --git a/osu.Game/Overlays/Dashboard/Home/News/NewsTitleLink.cs b/osu.Game/Overlays/Dashboard/Home/News/NewsTitleLink.cs index e384c3e6e5..1960e0372e 100644 --- a/osu.Game/Overlays/Dashboard/Home/News/NewsTitleLink.cs +++ b/osu.Game/Overlays/Dashboard/Home/News/NewsTitleLink.cs @@ -13,7 +13,7 @@ using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Overlays.Dashboard.Home.News { - public class NewsTitleLink : OsuHoverContainer + public partial class NewsTitleLink : OsuHoverContainer { private readonly APINewsPost post; diff --git a/osu.Game/Overlays/Dashboard/Home/News/ShowMoreNewsPanel.cs b/osu.Game/Overlays/Dashboard/Home/News/ShowMoreNewsPanel.cs index 9b1d77a8c2..3e61dd1938 100644 --- a/osu.Game/Overlays/Dashboard/Home/News/ShowMoreNewsPanel.cs +++ b/osu.Game/Overlays/Dashboard/Home/News/ShowMoreNewsPanel.cs @@ -13,7 +13,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Dashboard.Home.News { - public class ShowMoreNewsPanel : OsuHoverContainer + public partial class ShowMoreNewsPanel : OsuHoverContainer { protected override IEnumerable EffectTargets => new[] { text }; diff --git a/osu.Game/Overlays/DashboardOverlay.cs b/osu.Game/Overlays/DashboardOverlay.cs index d919022dbb..527ac1689b 100644 --- a/osu.Game/Overlays/DashboardOverlay.cs +++ b/osu.Game/Overlays/DashboardOverlay.cs @@ -9,7 +9,7 @@ using osu.Game.Overlays.Dashboard.Friends; namespace osu.Game.Overlays { - public class DashboardOverlay : TabbableOnlineOverlay + public partial class DashboardOverlay : TabbableOnlineOverlay { public DashboardOverlay() : base(OverlayColourScheme.Purple) diff --git a/osu.Game/Overlays/Dialog/ConfirmDialog.cs b/osu.Game/Overlays/Dialog/ConfirmDialog.cs index c17080f602..f1caac8b5d 100644 --- a/osu.Game/Overlays/Dialog/ConfirmDialog.cs +++ b/osu.Game/Overlays/Dialog/ConfirmDialog.cs @@ -13,7 +13,7 @@ namespace osu.Game.Overlays.Dialog /// /// A dialog which confirms a user action. /// - public class ConfirmDialog : PopupDialog + public partial class ConfirmDialog : PopupDialog { /// /// Construct a new confirmation dialog. diff --git a/osu.Game/Overlays/Dialog/DeleteConfirmationDialog.cs b/osu.Game/Overlays/Dialog/DeleteConfirmationDialog.cs index fd26dd7e8e..ddb59c4c9e 100644 --- a/osu.Game/Overlays/Dialog/DeleteConfirmationDialog.cs +++ b/osu.Game/Overlays/Dialog/DeleteConfirmationDialog.cs @@ -12,7 +12,7 @@ namespace osu.Game.Overlays.Dialog /// Differs from in that the confirmation button is a "dangerous" one /// (requires the confirm button to be held). /// - public abstract class DeleteConfirmationDialog : PopupDialog + public abstract partial class DeleteConfirmationDialog : PopupDialog { /// /// The action which performs the deletion. diff --git a/osu.Game/Overlays/Dialog/PopupDialog.cs b/osu.Game/Overlays/Dialog/PopupDialog.cs index 864120cc49..f5a7e9e43d 100644 --- a/osu.Game/Overlays/Dialog/PopupDialog.cs +++ b/osu.Game/Overlays/Dialog/PopupDialog.cs @@ -21,7 +21,7 @@ using osuTK.Input; namespace osu.Game.Overlays.Dialog { - public abstract class PopupDialog : VisibilityContainer + public abstract partial class PopupDialog : VisibilityContainer { public const float ENTER_DURATION = 500; public const float EXIT_DURATION = 200; @@ -198,6 +198,7 @@ namespace osu.Game.Overlays.Dialog TextAnchor = Anchor.TopCentre, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, + Padding = new MarginPadding(5), }, }, }, diff --git a/osu.Game/Overlays/Dialog/PopupDialogButton.cs b/osu.Game/Overlays/Dialog/PopupDialogButton.cs index e1cc31da82..91a19add21 100644 --- a/osu.Game/Overlays/Dialog/PopupDialogButton.cs +++ b/osu.Game/Overlays/Dialog/PopupDialogButton.cs @@ -8,7 +8,7 @@ using osu.Game.Graphics.UserInterface; namespace osu.Game.Overlays.Dialog { - public class PopupDialogButton : DialogButton + public partial class PopupDialogButton : DialogButton { public PopupDialogButton(HoverSampleSet sampleSet = HoverSampleSet.Button) : base(sampleSet) diff --git a/osu.Game/Overlays/Dialog/PopupDialogCancelButton.cs b/osu.Game/Overlays/Dialog/PopupDialogCancelButton.cs index f23a40b7ab..f4289c66f1 100644 --- a/osu.Game/Overlays/Dialog/PopupDialogCancelButton.cs +++ b/osu.Game/Overlays/Dialog/PopupDialogCancelButton.cs @@ -9,7 +9,7 @@ using osu.Game.Graphics.UserInterface; namespace osu.Game.Overlays.Dialog { - public class PopupDialogCancelButton : PopupDialogButton + public partial class PopupDialogCancelButton : PopupDialogButton { [BackgroundDependencyLoader] private void load(OsuColour colours) diff --git a/osu.Game/Overlays/Dialog/PopupDialogDangerousButton.cs b/osu.Game/Overlays/Dialog/PopupDialogDangerousButton.cs index bd7cb4ed33..6b3716ac8d 100644 --- a/osu.Game/Overlays/Dialog/PopupDialogDangerousButton.cs +++ b/osu.Game/Overlays/Dialog/PopupDialogDangerousButton.cs @@ -16,7 +16,7 @@ using osu.Game.Graphics.Containers; namespace osu.Game.Overlays.Dialog { - public class PopupDialogDangerousButton : PopupDialogButton + public partial class PopupDialogDangerousButton : PopupDialogButton { private Box progressBox; private DangerousConfirmContainer confirmContainer; @@ -46,7 +46,7 @@ namespace osu.Game.Overlays.Dialog confirmContainer.Progress.BindValueChanged(progress => progressBox.Width = (float)progress.NewValue, true); } - private class DangerousConfirmContainer : HoldToConfirmContainer + private partial class DangerousConfirmContainer : HoldToConfirmContainer { public DangerousConfirmContainer() : base(isDangerousAction: true) diff --git a/osu.Game/Overlays/Dialog/PopupDialogOkButton.cs b/osu.Game/Overlays/Dialog/PopupDialogOkButton.cs index 3496627c89..eb4a0f0709 100644 --- a/osu.Game/Overlays/Dialog/PopupDialogOkButton.cs +++ b/osu.Game/Overlays/Dialog/PopupDialogOkButton.cs @@ -9,7 +9,7 @@ using osu.Game.Graphics.UserInterface; namespace osu.Game.Overlays.Dialog { - public class PopupDialogOkButton : PopupDialogButton + public partial class PopupDialogOkButton : PopupDialogButton { [BackgroundDependencyLoader] private void load(OsuColour colours) diff --git a/osu.Game/Overlays/DialogOverlay.cs b/osu.Game/Overlays/DialogOverlay.cs index ba8083e535..098a5d0a33 100644 --- a/osu.Game/Overlays/DialogOverlay.cs +++ b/osu.Game/Overlays/DialogOverlay.cs @@ -16,7 +16,7 @@ using osu.Game.Audio.Effects; namespace osu.Game.Overlays { - public class DialogOverlay : OsuFocusedOverlayContainer, IDialogOverlay + public partial class DialogOverlay : OsuFocusedOverlayContainer, IDialogOverlay { private readonly Container dialogContainer; diff --git a/osu.Game/Overlays/FirstRunSetup/FirstRunSetupScreen.cs b/osu.Game/Overlays/FirstRunSetup/FirstRunSetupScreen.cs index cef1f1c869..76921718f2 100644 --- a/osu.Game/Overlays/FirstRunSetup/FirstRunSetupScreen.cs +++ b/osu.Game/Overlays/FirstRunSetup/FirstRunSetupScreen.cs @@ -15,7 +15,7 @@ using osuTK; namespace osu.Game.Overlays.FirstRunSetup { - public abstract class FirstRunSetupScreen : Screen + public abstract partial class FirstRunSetupScreen : Screen { private const float offset = 100; diff --git a/osu.Game/Overlays/FirstRunSetup/ProgressRoundedButton.cs b/osu.Game/Overlays/FirstRunSetup/ProgressRoundedButton.cs index 95ebb256c4..a1e61e66f8 100644 --- a/osu.Game/Overlays/FirstRunSetup/ProgressRoundedButton.cs +++ b/osu.Game/Overlays/FirstRunSetup/ProgressRoundedButton.cs @@ -13,7 +13,7 @@ using osuTK; namespace osu.Game.Overlays.FirstRunSetup { - public class ProgressRoundedButton : RoundedButton + public partial class ProgressRoundedButton : RoundedButton { public new Action? Action; @@ -81,7 +81,7 @@ namespace osu.Game.Overlays.FirstRunSetup loading.Hide(); tick.FadeIn(500, Easing.OutQuint); - Background.FadeColour(colours.Green, 500, Easing.OutQuint); + this.TransformTo(nameof(BackgroundColour), colours.Green, 500, Easing.OutQuint); progressBar.FillColour = colours.Green; this.TransformBindableTo(progressBar.Current, 1, 500, Easing.OutQuint); diff --git a/osu.Game/Overlays/FirstRunSetup/ScreenBeatmaps.cs b/osu.Game/Overlays/FirstRunSetup/ScreenBeatmaps.cs index 4963de7251..75bc8fd3a8 100644 --- a/osu.Game/Overlays/FirstRunSetup/ScreenBeatmaps.cs +++ b/osu.Game/Overlays/FirstRunSetup/ScreenBeatmaps.cs @@ -20,7 +20,7 @@ using Realms; namespace osu.Game.Overlays.FirstRunSetup { [LocalisableDescription(typeof(FirstRunSetupBeatmapScreenStrings), nameof(FirstRunSetupBeatmapScreenStrings.Header))] - public class ScreenBeatmaps : FirstRunSetupScreen + public partial class ScreenBeatmaps : FirstRunSetupScreen { private ProgressRoundedButton downloadBundledButton = null!; private ProgressRoundedButton downloadTutorialButton = null!; diff --git a/osu.Game/Overlays/FirstRunSetup/ScreenBehaviour.cs b/osu.Game/Overlays/FirstRunSetup/ScreenBehaviour.cs index 9573b4859f..95af8ec0f3 100644 --- a/osu.Game/Overlays/FirstRunSetup/ScreenBehaviour.cs +++ b/osu.Game/Overlays/FirstRunSetup/ScreenBehaviour.cs @@ -19,7 +19,7 @@ using osu.Game.Overlays.Settings.Sections; namespace osu.Game.Overlays.FirstRunSetup { [LocalisableDescription(typeof(FirstRunSetupOverlayStrings), nameof(FirstRunSetupOverlayStrings.Behaviour))] - public class ScreenBehaviour : FirstRunSetupScreen + public partial class ScreenBehaviour : FirstRunSetupScreen { private SearchContainer searchContainer; diff --git a/osu.Game/Overlays/FirstRunSetup/ScreenImportFromStable.cs b/osu.Game/Overlays/FirstRunSetup/ScreenImportFromStable.cs index 43d68653ad..23f3b3e1af 100644 --- a/osu.Game/Overlays/FirstRunSetup/ScreenImportFromStable.cs +++ b/osu.Game/Overlays/FirstRunSetup/ScreenImportFromStable.cs @@ -7,6 +7,7 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; +using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions; @@ -14,19 +15,23 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.UserInterface; using osu.Framework.Localisation; +using osu.Framework.Logging; +using osu.Framework.Screens; using osu.Game.Database; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Localisation; +using osu.Game.Online.Chat; using osu.Game.Overlays.Settings; +using osu.Game.Overlays.Settings.Sections.Maintenance; using osu.Game.Screens.Edit.Setup; using osuTK; namespace osu.Game.Overlays.FirstRunSetup { [LocalisableDescription(typeof(FirstRunOverlayImportFromStableScreenStrings), nameof(FirstRunOverlayImportFromStableScreenStrings.Header))] - public class ScreenImportFromStable : FirstRunSetupScreen + public partial class ScreenImportFromStable : FirstRunSetupScreen { private static readonly Vector2 button_size = new Vector2(400, 50); @@ -39,6 +44,8 @@ namespace osu.Game.Overlays.FirstRunSetup private StableLocatorLabelledTextBox stableLocatorTextBox = null!; + private LinkFlowContainer copyInformation = null!; + private IEnumerable contentCheckboxes => Content.Children.OfType(); [BackgroundDependencyLoader(permitNulls: true)] @@ -46,7 +53,7 @@ namespace osu.Game.Overlays.FirstRunSetup { Content.Children = new Drawable[] { - new OsuTextFlowContainer(cp => cp.Font = OsuFont.Default.With(size: CONTENT_FONT_SIZE)) + new LinkFlowContainer(cp => cp.Font = OsuFont.Default.With(size: CONTENT_FONT_SIZE)) { Colour = OverlayColourProvider.Content1, Text = FirstRunOverlayImportFromStableScreenStrings.Description, @@ -62,6 +69,12 @@ namespace osu.Game.Overlays.FirstRunSetup new ImportCheckbox(CommonStrings.Scores, StableContent.Scores), new ImportCheckbox(CommonStrings.Skins, StableContent.Skins), new ImportCheckbox(CommonStrings.Collections, StableContent.Collections), + copyInformation = new LinkFlowContainer(cp => cp.Font = OsuFont.Default.With(size: CONTENT_FONT_SIZE)) + { + Colour = OverlayColourProvider.Content1, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y + }, importButton = new ProgressRoundedButton { Size = button_size, @@ -83,6 +96,9 @@ namespace osu.Game.Overlays.FirstRunSetup stableLocatorTextBox.Current.BindValueChanged(_ => updateStablePath(), true); } + [Resolved(canBeNull: true)] + private OsuGame? game { get; set; } + private void updateStablePath() { var storage = legacyImportManager.GetCurrentStableStorage(); @@ -105,6 +121,29 @@ namespace osu.Game.Overlays.FirstRunSetup toggleInteraction(true); stableLocatorTextBox.Current.Value = storage.GetFullPath(string.Empty); importButton.Enabled.Value = true; + + bool available = legacyImportManager.CheckSongsFolderHardLinkAvailability(); + Logger.Log($"Hard link support for beatmaps is {available}"); + + if (available) + { + copyInformation.Text = + "Data migration will use \"hard links\". No extra disk space will be used, and you can delete either data folder at any point without affecting the other installation. "; + + copyInformation.AddLink("Learn more about how \"hard links\" work", LinkAction.OpenWiki, @"Client/Release_stream/Lazer/File_storage#via-hard-links"); + } + else if (!RuntimeInfo.IsDesktop) + copyInformation.Text = "Lightweight linking of files is not supported on your operating system yet, so a copy of all files will be made during import."; + else + { + copyInformation.Text = RuntimeInfo.OS == RuntimeInfo.Platform.Windows + ? "A second copy of all files will be made during import. To avoid this, please make sure the lazer data folder is on the same drive as your previous osu! install (and the file system is NTFS). " + : "A second copy of all files will be made during import. To avoid this, please make sure the lazer data folder is on the same drive as your previous osu! install (and the file system supports hard links). "; + copyInformation.AddLink(GeneralSettingsStrings.ChangeFolderLocation, () => + { + game?.PerformFromScreen(menu => menu.Push(new MigrationSelectScreen())); + }); + } } private void runImport() @@ -139,7 +178,19 @@ namespace osu.Game.Overlays.FirstRunSetup c.Current.Disabled = !allow; } - private class ImportCheckbox : SettingsCheckbox + public override void OnSuspending(ScreenTransitionEvent e) + { + stableLocatorTextBox.HidePopover(); + base.OnSuspending(e); + } + + public override bool OnExiting(ScreenExitEvent e) + { + stableLocatorTextBox.HidePopover(); + return base.OnExiting(e); + } + + private partial class ImportCheckbox : SettingsCheckbox { public readonly StableContent StableContent; @@ -181,14 +232,14 @@ namespace osu.Game.Overlays.FirstRunSetup } } - internal class StableLocatorLabelledTextBox : LabelledTextBoxWithPopover, ICanAcceptFiles + internal partial class StableLocatorLabelledTextBox : LabelledTextBoxWithPopover, ICanAcceptFiles { [Resolved] private LegacyImportManager legacyImportManager { get; set; } = null!; public IEnumerable HandledExtensions { get; } = new[] { string.Empty }; - private readonly Bindable currentDirectory = new Bindable(); + private readonly Bindable currentDirectory = new Bindable(); [Resolved(canBeNull: true)] // Can't really be null but required to handle potential of disposal before DI completes. private OsuGameBase? game { get; set; } @@ -206,7 +257,7 @@ namespace osu.Game.Overlays.FirstRunSetup currentDirectory.Value = new DirectoryInfo(fullPath); } - private void onDirectorySelected(ValueChangedEvent directory) + private void onDirectorySelected(ValueChangedEvent directory) { if (directory.NewValue == null) { @@ -235,7 +286,7 @@ namespace osu.Game.Overlays.FirstRunSetup return Task.CompletedTask; } - Task ICanAcceptFiles.Import(params ImportTask[] tasks) => throw new NotImplementedException(); + Task ICanAcceptFiles.Import(ImportTask[] tasks, ImportParameters parameters) => throw new NotImplementedException(); protected override void Dispose(bool isDisposing) { @@ -245,9 +296,9 @@ namespace osu.Game.Overlays.FirstRunSetup public override Popover GetPopover() => new DirectoryChooserPopover(currentDirectory); - private class DirectoryChooserPopover : OsuPopover + private partial class DirectoryChooserPopover : OsuPopover { - public DirectoryChooserPopover(Bindable currentDirectory) + public DirectoryChooserPopover(Bindable currentDirectory) { Child = new Container { diff --git a/osu.Game/Overlays/FirstRunSetup/ScreenUIScale.cs b/osu.Game/Overlays/FirstRunSetup/ScreenUIScale.cs index 0d4496a6a3..1bcb1bcdf4 100644 --- a/osu.Game/Overlays/FirstRunSetup/ScreenUIScale.cs +++ b/osu.Game/Overlays/FirstRunSetup/ScreenUIScale.cs @@ -13,7 +13,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Textures; using osu.Framework.Localisation; -using osu.Framework.Screens; using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Graphics; @@ -32,7 +31,7 @@ using osuTK; namespace osu.Game.Overlays.FirstRunSetup { [LocalisableDescription(typeof(GraphicsSettingsStrings), nameof(GraphicsSettingsStrings.UIScaling))] - public class ScreenUIScale : FirstRunSetupScreen + public partial class ScreenUIScale : FirstRunSetupScreen { [BackgroundDependencyLoader] private void load(OsuConfigManager config) @@ -58,7 +57,7 @@ namespace osu.Game.Overlays.FirstRunSetup Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, RelativeSizeAxes = Axes.None, - Size = new Vector2(screen_width, screen_width / 16f * 9 / 2), + Size = new Vector2(screen_width, screen_width / 16f * 9), Children = new Drawable[] { new GridContainer @@ -68,7 +67,6 @@ namespace osu.Game.Overlays.FirstRunSetup { new Drawable[] { - new SampleScreenContainer(new PinnedMainMenu()), new SampleScreenContainer(new NestedSongSelect()), }, // TODO: add more screens here in the future (gameplay / results) @@ -80,7 +78,7 @@ namespace osu.Game.Overlays.FirstRunSetup }; } - private class InverseScalingDrawSizePreservingFillContainer : ScalingContainer.ScalingDrawSizePreservingFillContainer + private partial class InverseScalingDrawSizePreservingFillContainer : ScalingContainer.ScalingDrawSizePreservingFillContainer { private Vector2 initialSize; @@ -102,30 +100,19 @@ namespace osu.Game.Overlays.FirstRunSetup } } - private class NestedSongSelect : PlaySongSelect + private partial class NestedSongSelect : PlaySongSelect { protected override bool ControlGlobalMusic => false; public override bool? AllowTrackAdjustments => false; } - private class PinnedMainMenu : MainMenu - { - public override void OnEntering(ScreenTransitionEvent e) - { - base.OnEntering(e); - - Buttons.ReturnToTopOnIdle = false; - Buttons.State = ButtonSystemState.TopLevel; - } - } - - private class UIScaleSlider : OsuSliderBar + private partial class UIScaleSlider : OsuSliderBar { public override LocalisableString TooltipText => base.TooltipText + "x"; } - private class SampleScreenContainer : CompositeDrawable + private partial class SampleScreenContainer : CompositeDrawable { private readonly OsuScreen screen; @@ -233,7 +220,7 @@ namespace osu.Game.Overlays.FirstRunSetup return parentDependencies.Get(type, info); } - public void Inject(T instance) where T : class + public void Inject(T instance) where T : class, IDependencyInjectionCandidate { parentDependencies.Inject(instance); } diff --git a/osu.Game/Overlays/FirstRunSetup/ScreenWelcome.cs b/osu.Game/Overlays/FirstRunSetup/ScreenWelcome.cs index 3113e11346..b8d802ad4b 100644 --- a/osu.Game/Overlays/FirstRunSetup/ScreenWelcome.cs +++ b/osu.Game/Overlays/FirstRunSetup/ScreenWelcome.cs @@ -24,7 +24,7 @@ using osuTK; namespace osu.Game.Overlays.FirstRunSetup { [LocalisableDescription(typeof(FirstRunSetupOverlayStrings), nameof(FirstRunSetupOverlayStrings.WelcomeTitle))] - public class ScreenWelcome : FirstRunSetupScreen + public partial class ScreenWelcome : FirstRunSetupScreen { [BackgroundDependencyLoader] private void load(FrameworkConfigManager frameworkConfig) @@ -66,7 +66,7 @@ namespace osu.Game.Overlays.FirstRunSetup }; } - private class LanguageSelectionFlow : FillFlowContainer + private partial class LanguageSelectionFlow : FillFlowContainer { private Bindable frameworkLocale = null!; private IBindable localisationParameters = null!; @@ -79,26 +79,28 @@ namespace osu.Game.Overlays.FirstRunSetup Direction = FillDirection.Full; Spacing = new Vector2(5); - ChildrenEnumerable = Enum.GetValues(typeof(Language)) - .Cast() + ChildrenEnumerable = Enum.GetValues() .Select(l => new LanguageButton(l) { Action = () => frameworkLocale.Value = l.ToCultureCode() }); frameworkLocale = frameworkConfig.GetBindable(FrameworkSetting.Locale); + frameworkLocale.BindValueChanged(_ => onLanguageChange()); localisationParameters = localisation.CurrentParameters.GetBoundCopy(); - localisationParameters.BindValueChanged(p => - { - var language = LanguageExtensions.GetLanguageFor(frameworkLocale.Value, p.NewValue); + localisationParameters.BindValueChanged(_ => onLanguageChange(), true); + } - // Changing language may cause a short period of blocking the UI thread while the new glyphs are loaded. - // Scheduling ensures the button animation plays smoothly after any blocking operation completes. - // Note that a delay is required (the alternative would be a double-schedule; delay feels better). - updateSelectedDelegate?.Cancel(); - updateSelectedDelegate = Scheduler.AddDelayed(() => updateSelectedStates(language), 50); - }, true); + private void onLanguageChange() + { + var language = LanguageExtensions.GetLanguageFor(frameworkLocale.Value, localisationParameters.Value); + + // Changing language may cause a short period of blocking the UI thread while the new glyphs are loaded. + // Scheduling ensures the button animation plays smoothly after any blocking operation completes. + // Note that a delay is required (the alternative would be a double-schedule; delay feels better). + updateSelectedDelegate?.Cancel(); + updateSelectedDelegate = Scheduler.AddDelayed(() => updateSelectedStates(language), 50); } private void updateSelectedStates(Language language) @@ -107,7 +109,7 @@ namespace osu.Game.Overlays.FirstRunSetup c.Selected = c.Language == language; } - private class LanguageButton : OsuClickableContainer + private partial class LanguageButton : OsuClickableContainer { public readonly Language Language; @@ -147,7 +149,7 @@ namespace osu.Game.Overlays.FirstRunSetup [BackgroundDependencyLoader] private void load() { - InternalChildren = new Drawable[] + AddRange(new Drawable[] { backgroundBox = new Box { @@ -162,7 +164,7 @@ namespace osu.Game.Overlays.FirstRunSetup Colour = colourProvider.Light1, Text = Language.GetDescription(), } - }; + }); } protected override void LoadComplete() diff --git a/osu.Game/Overlays/FirstRunSetupOverlay.cs b/osu.Game/Overlays/FirstRunSetupOverlay.cs index 8c9ca7e35b..f2fdaefbb4 100644 --- a/osu.Game/Overlays/FirstRunSetupOverlay.cs +++ b/osu.Game/Overlays/FirstRunSetupOverlay.cs @@ -31,7 +31,7 @@ using osu.Game.Screens.Menu; namespace osu.Game.Overlays { [Cached] - public class FirstRunSetupOverlay : ShearedOverlayContainer + public partial class FirstRunSetupOverlay : ShearedOverlayContainer { [Resolved] private IPerformFromScreenRunner performer { get; set; } = null!; @@ -301,7 +301,7 @@ namespace osu.Game.Overlays if (currentStepIndex < steps.Count) { - var nextScreen = (Screen)Activator.CreateInstance(steps[currentStepIndex.Value]); + var nextScreen = (Screen)Activator.CreateInstance(steps[currentStepIndex.Value])!; loadingShowDelegate = Scheduler.AddDelayed(() => loading.Show(), 200); nextScreen.OnLoadComplete += _ => diff --git a/osu.Game/Overlays/FullscreenOverlay.cs b/osu.Game/Overlays/FullscreenOverlay.cs index 63a9ebc750..2cc8354e50 100644 --- a/osu.Game/Overlays/FullscreenOverlay.cs +++ b/osu.Game/Overlays/FullscreenOverlay.cs @@ -17,7 +17,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays { - public abstract class FullscreenOverlay : WaveOverlayContainer, INamedOverlayComponent + public abstract partial class FullscreenOverlay : WaveOverlayContainer, INamedOverlayComponent where T : OverlayHeader { public virtual string IconTexture => Header.Title.IconTexture ?? string.Empty; diff --git a/osu.Game/Overlays/HoldToConfirmOverlay.cs b/osu.Game/Overlays/HoldToConfirmOverlay.cs index dd03206eab..ac8b4ad0a8 100644 --- a/osu.Game/Overlays/HoldToConfirmOverlay.cs +++ b/osu.Game/Overlays/HoldToConfirmOverlay.cs @@ -17,7 +17,7 @@ namespace osu.Game.Overlays /// An overlay which will display a black screen that dims over a period before confirming an exit action. /// Action is BYO (derived class will need to call and from a user event). /// - public abstract class HoldToConfirmOverlay : HoldToConfirmContainer + public abstract partial class HoldToConfirmOverlay : HoldToConfirmContainer { private Box overlay; diff --git a/osu.Game/Overlays/Login/LoginForm.cs b/osu.Game/Overlays/Login/LoginForm.cs index 0042f4607d..af145c418c 100644 --- a/osu.Game/Overlays/Login/LoginForm.cs +++ b/osu.Game/Overlays/Login/LoginForm.cs @@ -19,7 +19,7 @@ using osuTK; namespace osu.Game.Overlays.Login { - public class LoginForm : FillFlowContainer + public partial class LoginForm : FillFlowContainer { private TextBox username = null!; private TextBox password = null!; diff --git a/osu.Game/Overlays/Login/LoginPanel.cs b/osu.Game/Overlays/Login/LoginPanel.cs index 32a7fca1a6..44f2f3273a 100644 --- a/osu.Game/Overlays/Login/LoginPanel.cs +++ b/osu.Game/Overlays/Login/LoginPanel.cs @@ -22,7 +22,7 @@ using Container = osu.Framework.Graphics.Containers.Container; namespace osu.Game.Overlays.Login { - public class LoginPanel : FillFlowContainer + public partial class LoginPanel : FillFlowContainer { private bool bounding = true; private LoginForm form; diff --git a/osu.Game/Overlays/Login/UserDropdown.cs b/osu.Game/Overlays/Login/UserDropdown.cs index 73ccfb3443..0bdfa82517 100644 --- a/osu.Game/Overlays/Login/UserDropdown.cs +++ b/osu.Game/Overlays/Login/UserDropdown.cs @@ -7,16 +7,16 @@ using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Effects; -using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; +using osu.Game.Users.Drawables; using osuTK; using osuTK.Graphics; namespace osu.Game.Overlays.Login { - public class UserDropdown : OsuEnumDropdown + public partial class UserDropdown : OsuEnumDropdown { protected override DropdownHeader CreateHeader() => new UserDropdownHeader(); @@ -31,7 +31,7 @@ namespace osu.Game.Overlays.Login } } - protected class UserDropdownMenu : OsuDropdownMenu + protected partial class UserDropdownMenu : OsuDropdownMenu { public UserDropdownMenu() { @@ -58,7 +58,7 @@ namespace osu.Game.Overlays.Login protected override DrawableDropdownMenuItem CreateDrawableDropdownMenuItem(MenuItem item) => new DrawableUserDropdownMenuItem(item); - private class DrawableUserDropdownMenuItem : DrawableOsuDropdownMenuItem + private partial class DrawableUserDropdownMenuItem : DrawableOsuDropdownMenuItem { public DrawableUserDropdownMenuItem(MenuItem item) : base(item) @@ -74,11 +74,11 @@ namespace osu.Game.Overlays.Login } } - private class UserDropdownHeader : OsuDropdownHeader + private partial class UserDropdownHeader : OsuDropdownHeader { public const float LABEL_LEFT_MARGIN = 20; - private readonly SpriteIcon statusIcon; + private readonly StatusIcon statusIcon; public Color4 StatusColour { @@ -101,11 +101,10 @@ namespace osu.Game.Overlays.Login Icon.Size = new Vector2(14); Icon.Margin = new MarginPadding(0); - Foreground.Add(statusIcon = new SpriteIcon + Foreground.Add(statusIcon = new StatusIcon { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - Icon = FontAwesome.Regular.Circle, Size = new Vector2(14), }); diff --git a/osu.Game/Overlays/LoginOverlay.cs b/osu.Game/Overlays/LoginOverlay.cs index 2362b2ad88..536811dfcf 100644 --- a/osu.Game/Overlays/LoginOverlay.cs +++ b/osu.Game/Overlays/LoginOverlay.cs @@ -15,7 +15,7 @@ using osu.Game.Overlays.Login; namespace osu.Game.Overlays { - public class LoginOverlay : OsuFocusedOverlayContainer + public partial class LoginOverlay : OsuFocusedOverlayContainer { private LoginPanel panel; diff --git a/osu.Game/Overlays/MedalOverlay.cs b/osu.Game/Overlays/MedalOverlay.cs index 9b856014f9..bd895fe6bf 100644 --- a/osu.Game/Overlays/MedalOverlay.cs +++ b/osu.Game/Overlays/MedalOverlay.cs @@ -27,7 +27,7 @@ using osu.Framework.Utils; namespace osu.Game.Overlays { - public class MedalOverlay : FocusedOverlayContainer + public partial class MedalOverlay : FocusedOverlayContainer { public const float DISC_SIZE = 400; @@ -266,7 +266,7 @@ namespace osu.Game.Overlays Expire(); } - private class BackgroundStrip : Container + private partial class BackgroundStrip : Container { public BackgroundStrip(float start, float end) { @@ -286,7 +286,7 @@ namespace osu.Game.Overlays } } - private class MedalParticle : CircularContainer + private partial class MedalParticle : CircularContainer { private readonly float direction; diff --git a/osu.Game/Overlays/MedalSplash/DrawableMedal.cs b/osu.Game/Overlays/MedalSplash/DrawableMedal.cs index 1c007c913e..a25147b69f 100644 --- a/osu.Game/Overlays/MedalSplash/DrawableMedal.cs +++ b/osu.Game/Overlays/MedalSplash/DrawableMedal.cs @@ -19,7 +19,7 @@ using osu.Game.Users; namespace osu.Game.Overlays.MedalSplash { [LongRunningLoad] - public class DrawableMedal : Container, IStateful + public partial class DrawableMedal : Container, IStateful { private const float scale_when_unlocked = 0.76f; private const float scale_when_full = 0.6f; diff --git a/osu.Game/Overlays/Mods/AddPresetButton.cs b/osu.Game/Overlays/Mods/AddPresetButton.cs index 1242088cf5..731079d1d9 100644 --- a/osu.Game/Overlays/Mods/AddPresetButton.cs +++ b/osu.Game/Overlays/Mods/AddPresetButton.cs @@ -16,7 +16,7 @@ using osuTK; namespace osu.Game.Overlays.Mods { - public class AddPresetButton : ShearedToggleButton, IHasPopover + public partial class AddPresetButton : ShearedToggleButton, IHasPopover { [Resolved] private OsuColour colours { get; set; } = null!; diff --git a/osu.Game/Overlays/Mods/AddPresetPopover.cs b/osu.Game/Overlays/Mods/AddPresetPopover.cs index 8188c98e46..33d72ff383 100644 --- a/osu.Game/Overlays/Mods/AddPresetPopover.cs +++ b/osu.Game/Overlays/Mods/AddPresetPopover.cs @@ -20,7 +20,7 @@ using osuTK; namespace osu.Game.Overlays.Mods { - internal class AddPresetPopover : OsuPopover + internal partial class AddPresetPopover : OsuPopover { private readonly AddPresetButton button; diff --git a/osu.Game/Overlays/Mods/DeleteModPresetDialog.cs b/osu.Game/Overlays/Mods/DeleteModPresetDialog.cs index b3a19e35ce..800ebe8b4e 100644 --- a/osu.Game/Overlays/Mods/DeleteModPresetDialog.cs +++ b/osu.Game/Overlays/Mods/DeleteModPresetDialog.cs @@ -7,7 +7,7 @@ using osu.Game.Rulesets.Mods; namespace osu.Game.Overlays.Mods { - public class DeleteModPresetDialog : DeleteConfirmationDialog + public partial class DeleteModPresetDialog : DeleteConfirmationDialog { public DeleteModPresetDialog(Live modPreset) { diff --git a/osu.Game/Overlays/Mods/DeselectAllModsButton.cs b/osu.Game/Overlays/Mods/DeselectAllModsButton.cs index 61fca9e091..3e5a3b12d1 100644 --- a/osu.Game/Overlays/Mods/DeselectAllModsButton.cs +++ b/osu.Game/Overlays/Mods/DeselectAllModsButton.cs @@ -15,7 +15,7 @@ using osu.Game.Rulesets.Mods; namespace osu.Game.Overlays.Mods { - public class DeselectAllModsButton : ShearedButton, IKeyBindingHandler + public partial class DeselectAllModsButton : ShearedButton, IKeyBindingHandler { private readonly Bindable> selectedMods = new Bindable>(); diff --git a/osu.Game/Overlays/Mods/DifficultyMultiplierDisplay.cs b/osu.Game/Overlays/Mods/DifficultyMultiplierDisplay.cs index f582a010c6..ee4f932326 100644 --- a/osu.Game/Overlays/Mods/DifficultyMultiplierDisplay.cs +++ b/osu.Game/Overlays/Mods/DifficultyMultiplierDisplay.cs @@ -11,7 +11,7 @@ using osu.Game.Localisation; namespace osu.Game.Overlays.Mods { - public sealed class DifficultyMultiplierDisplay : ModsEffectDisplay + public sealed partial class DifficultyMultiplierDisplay : ModsEffectDisplay { protected override LocalisableString Label => DifficultyMultiplierDisplayStrings.DifficultyMultiplier; diff --git a/osu.Game/Overlays/Mods/IncompatibilityDisplayingModPanel.cs b/osu.Game/Overlays/Mods/IncompatibilityDisplayingModPanel.cs index 8cedd6b374..93279b6e1c 100644 --- a/osu.Game/Overlays/Mods/IncompatibilityDisplayingModPanel.cs +++ b/osu.Game/Overlays/Mods/IncompatibilityDisplayingModPanel.cs @@ -14,7 +14,7 @@ using osu.Game.Utils; namespace osu.Game.Overlays.Mods { - public class IncompatibilityDisplayingModPanel : ModPanel, IHasCustomTooltip + public partial class IncompatibilityDisplayingModPanel : ModPanel, IHasCustomTooltip { private readonly BindableBool incompatible = new BindableBool(); diff --git a/osu.Game/Overlays/Mods/IncompatibilityDisplayingTooltip.cs b/osu.Game/Overlays/Mods/IncompatibilityDisplayingTooltip.cs index 3f44e82d50..1723634774 100644 --- a/osu.Game/Overlays/Mods/IncompatibilityDisplayingTooltip.cs +++ b/osu.Game/Overlays/Mods/IncompatibilityDisplayingTooltip.cs @@ -17,7 +17,7 @@ using osuTK; namespace osu.Game.Overlays.Mods { - internal class IncompatibilityDisplayingTooltip : ModButtonTooltip + internal partial class IncompatibilityDisplayingTooltip : ModButtonTooltip { private readonly OsuSpriteText incompatibleText; diff --git a/osu.Game/Overlays/Mods/ModButtonTooltip.cs b/osu.Game/Overlays/Mods/ModButtonTooltip.cs index e19f24103f..52b27f1e00 100644 --- a/osu.Game/Overlays/Mods/ModButtonTooltip.cs +++ b/osu.Game/Overlays/Mods/ModButtonTooltip.cs @@ -15,7 +15,7 @@ using osuTK; namespace osu.Game.Overlays.Mods { - public class ModButtonTooltip : VisibilityContainer, ITooltip + public partial class ModButtonTooltip : VisibilityContainer, ITooltip { private readonly OsuSpriteText descriptionText; private readonly Box background; diff --git a/osu.Game/Overlays/Mods/ModColumn.cs b/osu.Game/Overlays/Mods/ModColumn.cs index b9f7114f74..5d9f616e5f 100644 --- a/osu.Game/Overlays/Mods/ModColumn.cs +++ b/osu.Game/Overlays/Mods/ModColumn.cs @@ -25,7 +25,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Mods { - public class ModColumn : ModSelectColumn + public partial class ModColumn : ModSelectColumn { public readonly ModType ModType; @@ -219,7 +219,7 @@ namespace osu.Game.Overlays.Mods dequeuedAction(); } - private class ToggleAllCheckbox : OsuCheckbox + private partial class ToggleAllCheckbox : OsuCheckbox { private Color4 accentColour; diff --git a/osu.Game/Overlays/Mods/ModPanel.cs b/osu.Game/Overlays/Mods/ModPanel.cs index 7bdb9511ac..b5fee9d116 100644 --- a/osu.Game/Overlays/Mods/ModPanel.cs +++ b/osu.Game/Overlays/Mods/ModPanel.cs @@ -11,7 +11,7 @@ using osuTK; namespace osu.Game.Overlays.Mods { - public class ModPanel : ModSelectPanel + public partial class ModPanel : ModSelectPanel { public Mod Mod => modState.Mod; public override BindableBool Active => modState.Active; diff --git a/osu.Game/Overlays/Mods/ModPresetColumn.cs b/osu.Game/Overlays/Mods/ModPresetColumn.cs index 176c527a10..bf5e576277 100644 --- a/osu.Game/Overlays/Mods/ModPresetColumn.cs +++ b/osu.Game/Overlays/Mods/ModPresetColumn.cs @@ -18,7 +18,7 @@ using Realms; namespace osu.Game.Overlays.Mods { - public class ModPresetColumn : ModSelectColumn + public partial class ModPresetColumn : ModSelectColumn { [Resolved] private RealmAccess realm { get; set; } = null!; diff --git a/osu.Game/Overlays/Mods/ModPresetPanel.cs b/osu.Game/Overlays/Mods/ModPresetPanel.cs index b314a19142..6e12e34124 100644 --- a/osu.Game/Overlays/Mods/ModPresetPanel.cs +++ b/osu.Game/Overlays/Mods/ModPresetPanel.cs @@ -17,7 +17,7 @@ using osu.Game.Rulesets.Mods; namespace osu.Game.Overlays.Mods { - public class ModPresetPanel : ModSelectPanel, IHasCustomTooltip, IHasContextMenu + public partial class ModPresetPanel : ModSelectPanel, IHasCustomTooltip, IHasContextMenu { public readonly Live Preset; diff --git a/osu.Game/Overlays/Mods/ModPresetTooltip.cs b/osu.Game/Overlays/Mods/ModPresetTooltip.cs index 97d118fbfd..ff4f00da69 100644 --- a/osu.Game/Overlays/Mods/ModPresetTooltip.cs +++ b/osu.Game/Overlays/Mods/ModPresetTooltip.cs @@ -15,7 +15,7 @@ using osuTK; namespace osu.Game.Overlays.Mods { - public class ModPresetTooltip : VisibilityContainer, ITooltip + public partial class ModPresetTooltip : VisibilityContainer, ITooltip { protected override Container Content { get; } @@ -62,7 +62,7 @@ namespace osu.Game.Overlays.Mods public void Move(Vector2 pos) => Position = pos; - private class ModPresetRow : FillFlowContainer + private partial class ModPresetRow : FillFlowContainer { public ModPresetRow(Mod mod) { diff --git a/osu.Game/Overlays/Mods/ModSelectColumn.cs b/osu.Game/Overlays/Mods/ModSelectColumn.cs index d5dc079628..e5154fd631 100644 --- a/osu.Game/Overlays/Mods/ModSelectColumn.cs +++ b/osu.Game/Overlays/Mods/ModSelectColumn.cs @@ -15,7 +15,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Mods { - public abstract class ModSelectColumn : CompositeDrawable, IHasAccentColour + public abstract partial class ModSelectColumn : CompositeDrawable, IHasAccentColour { public readonly Container TopLevelContent; diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index ccc075b190..16602db4be 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -28,7 +28,7 @@ using osuTK; namespace osu.Game.Overlays.Mods { - public abstract class ModSelectOverlay : ShearedOverlayContainer, ISamplePlaybackDisabler + public abstract partial class ModSelectOverlay : ShearedOverlayContainer, ISamplePlaybackDisabler { public const int BUTTON_WIDTH = 200; @@ -612,7 +612,7 @@ namespace osu.Game.Overlays.Mods /// Manages horizontal scrolling of mod columns, along with the "active" states of each column based on visibility. /// [Cached] - internal class ColumnScrollContainer : OsuScrollContainer + internal partial class ColumnScrollContainer : OsuScrollContainer { public ColumnScrollContainer() : base(Direction.Horizontal) @@ -653,7 +653,7 @@ namespace osu.Game.Overlays.Mods /// /// Manages layout of mod columns. /// - internal class ColumnFlowContainer : FillFlowContainer + internal partial class ColumnFlowContainer : FillFlowContainer { public IEnumerable Columns => Children.Select(dimWrapper => dimWrapper.Column); @@ -669,7 +669,7 @@ namespace osu.Game.Overlays.Mods /// /// Encapsulates a column and provides dim and input blocking based on an externally managed "active" state. /// - internal class ColumnDimContainer : Container + internal partial class ColumnDimContainer : Container { public ModSelectColumn Column { get; } @@ -759,7 +759,7 @@ namespace osu.Game.Overlays.Mods /// /// A container which blocks and handles input, managing the "return from customisation" state change. /// - private class ClickToReturnContainer : Container + private partial class ClickToReturnContainer : Container { public BindableBool HandleMouse { get; } = new BindableBool(); diff --git a/osu.Game/Overlays/Mods/ModSelectPanel.cs b/osu.Game/Overlays/Mods/ModSelectPanel.cs index 27abface0c..81285833bd 100644 --- a/osu.Game/Overlays/Mods/ModSelectPanel.cs +++ b/osu.Game/Overlays/Mods/ModSelectPanel.cs @@ -24,7 +24,7 @@ using osuTK.Input; namespace osu.Game.Overlays.Mods { - public abstract class ModSelectPanel : OsuClickableContainer, IHasAccentColour + public abstract partial class ModSelectPanel : OsuClickableContainer, IHasAccentColour { public abstract BindableBool Active { get; } diff --git a/osu.Game/Overlays/Mods/ModSettingsArea.cs b/osu.Game/Overlays/Mods/ModSettingsArea.cs index 0932c2c832..f11fef1299 100644 --- a/osu.Game/Overlays/Mods/ModSettingsArea.cs +++ b/osu.Game/Overlays/Mods/ModSettingsArea.cs @@ -22,7 +22,7 @@ using osuTK; namespace osu.Game.Overlays.Mods { - public class ModSettingsArea : CompositeDrawable + public partial class ModSettingsArea : CompositeDrawable { public Bindable> SelectedMods { get; } = new Bindable>(Array.Empty()); @@ -110,7 +110,7 @@ namespace osu.Game.Overlays.Mods protected override bool OnMouseDown(MouseDownEvent e) => true; protected override bool OnHover(HoverEvent e) => true; - private class ModSettingsColumn : CompositeDrawable + private partial class ModSettingsColumn : CompositeDrawable { public ModSettingsColumn(Mod mod, IEnumerable settingsControls) { diff --git a/osu.Game/Overlays/Mods/ModsEffectDisplay.cs b/osu.Game/Overlays/Mods/ModsEffectDisplay.cs index eed3181e49..3f31736ee1 100644 --- a/osu.Game/Overlays/Mods/ModsEffectDisplay.cs +++ b/osu.Game/Overlays/Mods/ModsEffectDisplay.cs @@ -21,7 +21,7 @@ namespace osu.Game.Overlays.Mods /// /// Base class for displays of mods effects. /// - public abstract class ModsEffectDisplay : Container, IHasCurrentValue + public abstract partial class ModsEffectDisplay : Container, IHasCurrentValue { public const float HEIGHT = 42; private const float transition_duration = 200; @@ -201,7 +201,7 @@ namespace osu.Game.Overlays.Mods DifficultyIncrease } - private class EffectCounter : RollingCounter + private partial class EffectCounter : RollingCounter { private readonly string? format; diff --git a/osu.Game/Overlays/Mods/SelectAllModsButton.cs b/osu.Game/Overlays/Mods/SelectAllModsButton.cs index fc24e99c7e..f4b8025227 100644 --- a/osu.Game/Overlays/Mods/SelectAllModsButton.cs +++ b/osu.Game/Overlays/Mods/SelectAllModsButton.cs @@ -16,7 +16,7 @@ using osu.Game.Screens.OnlinePlay; namespace osu.Game.Overlays.Mods { - public class SelectAllModsButton : ShearedButton, IKeyBindingHandler + public partial class SelectAllModsButton : ShearedButton, IKeyBindingHandler { private readonly Bindable> selectedMods = new Bindable>(); private readonly Bindable>> availableMods = new Bindable>>(); diff --git a/osu.Game/Overlays/Mods/ShearedOverlayContainer.cs b/osu.Game/Overlays/Mods/ShearedOverlayContainer.cs index 2585e44e05..7f7b09a62c 100644 --- a/osu.Game/Overlays/Mods/ShearedOverlayContainer.cs +++ b/osu.Game/Overlays/Mods/ShearedOverlayContainer.cs @@ -18,7 +18,7 @@ namespace osu.Game.Overlays.Mods /// A sheared overlay which provides a header and footer and basic animations. /// Exposes , and as valid targets for content. /// - public abstract class ShearedOverlayContainer : OsuFocusedOverlayContainer + public abstract partial class ShearedOverlayContainer : OsuFocusedOverlayContainer { protected const float PADDING = 14; diff --git a/osu.Game/Overlays/Mods/UserModSelectOverlay.cs b/osu.Game/Overlays/Mods/UserModSelectOverlay.cs index 1090306c5b..49469b99f3 100644 --- a/osu.Game/Overlays/Mods/UserModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/UserModSelectOverlay.cs @@ -8,7 +8,7 @@ using osu.Game.Utils; namespace osu.Game.Overlays.Mods { - public class UserModSelectOverlay : ModSelectOverlay + public partial class UserModSelectOverlay : ModSelectOverlay { public UserModSelectOverlay(OverlayColourScheme colourScheme = OverlayColourScheme.Green) : base(colourScheme) @@ -38,7 +38,7 @@ namespace osu.Game.Overlays.Mods return modsAfterRemoval.ToList(); } - private class UserModColumn : ModColumn + private partial class UserModColumn : ModColumn { public UserModColumn(ModType modType, bool allowIncompatibleSelection) : base(modType, allowIncompatibleSelection) diff --git a/osu.Game/Overlays/Music/FilterControl.cs b/osu.Game/Overlays/Music/FilterControl.cs index ffa50c3a35..a61702645a 100644 --- a/osu.Game/Overlays/Music/FilterControl.cs +++ b/osu.Game/Overlays/Music/FilterControl.cs @@ -13,7 +13,7 @@ using osu.Framework.Allocation; namespace osu.Game.Overlays.Music { - public class FilterControl : Container + public partial class FilterControl : Container { public Action FilterChanged; @@ -58,7 +58,7 @@ namespace osu.Game.Overlays.Music Collection = collectionDropdown.Current.Value?.Collection }; - public class FilterTextBox : BasicSearchTextBox + public partial class FilterTextBox : BasicSearchTextBox { protected override bool AllowCommit => true; diff --git a/osu.Game/Overlays/Music/MusicKeyBindingHandler.cs b/osu.Game/Overlays/Music/MusicKeyBindingHandler.cs index 8df465e075..827caf0467 100644 --- a/osu.Game/Overlays/Music/MusicKeyBindingHandler.cs +++ b/osu.Game/Overlays/Music/MusicKeyBindingHandler.cs @@ -21,7 +21,7 @@ namespace osu.Game.Overlays.Music /// /// Handles s related to music playback, and displays s via the global accordingly. /// - public class MusicKeyBindingHandler : Component, IKeyBindingHandler + public partial class MusicKeyBindingHandler : Component, IKeyBindingHandler { [Resolved] private IBindable beatmap { get; set; } @@ -89,7 +89,7 @@ namespace osu.Game.Overlays.Music { } - private class MusicActionToast : Toast + private partial class MusicActionToast : Toast { private readonly GlobalAction action; diff --git a/osu.Game/Overlays/Music/NowPlayingCollectionDropdown.cs b/osu.Game/Overlays/Music/NowPlayingCollectionDropdown.cs index 635a2e5044..ae59fbb35e 100644 --- a/osu.Game/Overlays/Music/NowPlayingCollectionDropdown.cs +++ b/osu.Game/Overlays/Music/NowPlayingCollectionDropdown.cs @@ -17,7 +17,7 @@ namespace osu.Game.Overlays.Music /// /// A for use in the . /// - public class NowPlayingCollectionDropdown : CollectionDropdown + public partial class NowPlayingCollectionDropdown : CollectionDropdown { protected override bool ShowManageCollectionsItem => false; @@ -25,7 +25,7 @@ namespace osu.Game.Overlays.Music protected override CollectionDropdownMenu CreateCollectionMenu() => new CollectionsMenu(); - private class CollectionsMenu : CollectionDropdownMenu + private partial class CollectionsMenu : CollectionDropdownMenu { public CollectionsMenu() { @@ -42,7 +42,7 @@ namespace osu.Game.Overlays.Music } } - private class CollectionsHeader : CollectionDropdownHeader + private partial class CollectionsHeader : CollectionDropdownHeader { [BackgroundDependencyLoader] private void load(OsuColour colours) diff --git a/osu.Game/Overlays/Music/Playlist.cs b/osu.Game/Overlays/Music/Playlist.cs index b48257a61a..ab51ca7e1d 100644 --- a/osu.Game/Overlays/Music/Playlist.cs +++ b/osu.Game/Overlays/Music/Playlist.cs @@ -13,7 +13,7 @@ using osuTK; namespace osu.Game.Overlays.Music { - public class Playlist : OsuRearrangeableListContainer> + public partial class Playlist : OsuRearrangeableListContainer> { public Action>? RequestSelection; diff --git a/osu.Game/Overlays/Music/PlaylistItem.cs b/osu.Game/Overlays/Music/PlaylistItem.cs index b30ae095b1..00c5ce8002 100644 --- a/osu.Game/Overlays/Music/PlaylistItem.cs +++ b/osu.Game/Overlays/Music/PlaylistItem.cs @@ -20,7 +20,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Music { - public class PlaylistItem : OsuRearrangeableListItem>, IFilterable + public partial class PlaylistItem : OsuRearrangeableListItem>, IFilterable { public readonly Bindable> SelectedSet = new Bindable>(); diff --git a/osu.Game/Overlays/Music/PlaylistOverlay.cs b/osu.Game/Overlays/Music/PlaylistOverlay.cs index 63f1aa248c..43b9024303 100644 --- a/osu.Game/Overlays/Music/PlaylistOverlay.cs +++ b/osu.Game/Overlays/Music/PlaylistOverlay.cs @@ -22,7 +22,7 @@ using Realms; namespace osu.Game.Overlays.Music { - public class PlaylistOverlay : VisibilityContainer + public partial class PlaylistOverlay : VisibilityContainer { private const float transition_duration = 600; public const float PLAYLIST_HEIGHT = 510; diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 793b7e294f..1ad5a8c08b 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -25,7 +25,7 @@ namespace osu.Game.Overlays /// /// Handles playback of the global music track. /// - public class MusicController : CompositeDrawable + public partial class MusicController : CompositeDrawable { [Resolved] private BeatmapManager beatmaps { get; set; } diff --git a/osu.Game/Overlays/News/Displays/ArticleListing.cs b/osu.Game/Overlays/News/Displays/ArticleListing.cs index 8465ebf07c..b6ce16ae7d 100644 --- a/osu.Game/Overlays/News/Displays/ArticleListing.cs +++ b/osu.Game/Overlays/News/Displays/ArticleListing.cs @@ -19,7 +19,7 @@ namespace osu.Game.Overlays.News.Displays /// /// Lists articles in a vertical flow for a specified year. /// - public class ArticleListing : CompositeDrawable + public partial class ArticleListing : CompositeDrawable { private readonly Action fetchMorePosts; diff --git a/osu.Game/Overlays/News/NewsCard.cs b/osu.Game/Overlays/News/NewsCard.cs index c8e0b0c7ef..e0be5cc4a9 100644 --- a/osu.Game/Overlays/News/NewsCard.cs +++ b/osu.Game/Overlays/News/NewsCard.cs @@ -21,7 +21,7 @@ using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Overlays.News { - public class NewsCard : OsuHoverContainer + public partial class NewsCard : OsuHoverContainer { protected override IEnumerable EffectTargets => new[] { background }; @@ -121,7 +121,7 @@ namespace osu.Game.Overlays.News main.AddText(post.Author, t => t.Font = OsuFont.GetFont(size: 12, weight: FontWeight.SemiBold)); } - private class DateContainer : CircularContainer, IHasCustomTooltip + private partial class DateContainer : CircularContainer, IHasCustomTooltip { private readonly DateTimeOffset date; diff --git a/osu.Game/Overlays/News/NewsHeader.cs b/osu.Game/Overlays/News/NewsHeader.cs index d204dfcf2e..44e2f6a8cb 100644 --- a/osu.Game/Overlays/News/NewsHeader.cs +++ b/osu.Game/Overlays/News/NewsHeader.cs @@ -12,7 +12,7 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.News { - public class NewsHeader : BreadcrumbControlOverlayHeader + public partial class NewsHeader : BreadcrumbControlOverlayHeader { public static LocalisableString FrontPageString => NewsStrings.IndexTitleInfo; @@ -62,7 +62,7 @@ namespace osu.Game.Overlays.News protected override OverlayTitle CreateTitle() => new NewsHeaderTitle(); - private class NewsHeaderTitle : OverlayTitle + private partial class NewsHeaderTitle : OverlayTitle { public NewsHeaderTitle() { diff --git a/osu.Game/Overlays/News/NewsPostBackground.cs b/osu.Game/Overlays/News/NewsPostBackground.cs index b77623842c..05f8a639fa 100644 --- a/osu.Game/Overlays/News/NewsPostBackground.cs +++ b/osu.Game/Overlays/News/NewsPostBackground.cs @@ -11,7 +11,7 @@ using osu.Framework.Graphics.Textures; namespace osu.Game.Overlays.News { [LongRunningLoad] - public class NewsPostBackground : Sprite + public partial class NewsPostBackground : Sprite { private readonly string sourceUrl; diff --git a/osu.Game/Overlays/News/Sidebar/MonthSection.cs b/osu.Game/Overlays/News/Sidebar/MonthSection.cs index 894f8d5667..30d29048ba 100644 --- a/osu.Game/Overlays/News/Sidebar/MonthSection.cs +++ b/osu.Game/Overlays/News/Sidebar/MonthSection.cs @@ -19,11 +19,12 @@ using osu.Framework.Graphics.Sprites; using System.Diagnostics; using osu.Framework.Audio; using osu.Framework.Audio.Sample; +using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Platform; namespace osu.Game.Overlays.News.Sidebar { - public class MonthSection : CompositeDrawable + public partial class MonthSection : CompositeDrawable { public int Year { get; private set; } public int Month { get; private set; } @@ -79,7 +80,7 @@ namespace osu.Game.Overlays.News.Sidebar sampleClose = audio.Samples.Get(@"UI/dropdown-close"); } - private class DropdownHeader : OsuClickableContainer + private partial class DropdownHeader : OsuClickableContainer { public readonly BindableBool Expanded = new BindableBool(); @@ -99,7 +100,7 @@ namespace osu.Game.Overlays.News.Sidebar Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold), - Text = date.ToString("MMM yyyy") + Text = date.ToLocalisableString(@"MMM yyyy") }, icon = new SpriteIcon { @@ -122,7 +123,7 @@ namespace osu.Game.Overlays.News.Sidebar } } - private class PostButton : OsuHoverContainer + private partial class PostButton : OsuHoverContainer { protected override IEnumerable EffectTargets => new[] { text }; @@ -154,7 +155,7 @@ namespace osu.Game.Overlays.News.Sidebar } } - private class PostsContainer : Container + private partial class PostsContainer : Container { public readonly BindableBool Expanded = new BindableBool(); diff --git a/osu.Game/Overlays/News/Sidebar/NewsSidebar.cs b/osu.Game/Overlays/News/Sidebar/NewsSidebar.cs index 884e15c03b..939e5367b7 100644 --- a/osu.Game/Overlays/News/Sidebar/NewsSidebar.cs +++ b/osu.Game/Overlays/News/Sidebar/NewsSidebar.cs @@ -13,7 +13,7 @@ using System.Linq; namespace osu.Game.Overlays.News.Sidebar { - public class NewsSidebar : OverlaySidebar + public partial class NewsSidebar : OverlaySidebar { [Cached] public readonly Bindable Metadata = new Bindable(); diff --git a/osu.Game/Overlays/News/Sidebar/YearsPanel.cs b/osu.Game/Overlays/News/Sidebar/YearsPanel.cs index 915ed1817c..524ffbf63d 100644 --- a/osu.Game/Overlays/News/Sidebar/YearsPanel.cs +++ b/osu.Game/Overlays/News/Sidebar/YearsPanel.cs @@ -17,7 +17,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.News.Sidebar { - public class YearsPanel : CompositeDrawable + public partial class YearsPanel : CompositeDrawable { private readonly Bindable metadata = new Bindable(); @@ -79,7 +79,7 @@ namespace osu.Game.Overlays.News.Sidebar Show(); } - public class YearButton : OsuHoverContainer + public partial class YearButton : OsuHoverContainer { public int Year { get; } diff --git a/osu.Game/Overlays/NewsOverlay.cs b/osu.Game/Overlays/NewsOverlay.cs index 87b7ebbe89..cb9d940a05 100644 --- a/osu.Game/Overlays/NewsOverlay.cs +++ b/osu.Game/Overlays/NewsOverlay.cs @@ -15,7 +15,7 @@ using osu.Game.Overlays.News.Sidebar; namespace osu.Game.Overlays { - public class NewsOverlay : OnlineOverlay + public partial class NewsOverlay : OnlineOverlay { private readonly Bindable article = new Bindable(); diff --git a/osu.Game/Overlays/NotificationOverlay.cs b/osu.Game/Overlays/NotificationOverlay.cs index 36548c893c..71a4c58afd 100644 --- a/osu.Game/Overlays/NotificationOverlay.cs +++ b/osu.Game/Overlays/NotificationOverlay.cs @@ -20,7 +20,7 @@ using NotificationsStrings = osu.Game.Localisation.NotificationsStrings; namespace osu.Game.Overlays { - public class NotificationOverlay : OsuFocusedOverlayContainer, INamedOverlayComponent, INotificationOverlay + public partial class NotificationOverlay : OsuFocusedOverlayContainer, INamedOverlayComponent, INotificationOverlay { public string IconTexture => "Icons/Hexacons/notification"; public LocalisableString Title => NotificationsStrings.HeaderTitle; @@ -92,8 +92,8 @@ namespace osu.Game.Overlays RelativeSizeAxes = Axes.X, Children = new[] { - new NotificationSection(AccountsStrings.NotificationsTitle, new[] { typeof(SimpleNotification) }, "Clear All"), - new NotificationSection(@"Running Tasks", new[] { typeof(ProgressNotification) }, @"Cancel All"), + new NotificationSection(AccountsStrings.NotificationsTitle, new[] { typeof(SimpleNotification) }, NotificationsStrings.ClearAll), + new NotificationSection(NotificationsStrings.RunningTasks, new[] { typeof(ProgressNotification) }, NotificationsStrings.CancelAll), } } } diff --git a/osu.Game/Overlays/NotificationOverlayToastTray.cs b/osu.Game/Overlays/NotificationOverlayToastTray.cs index 329379de4a..7a793ee092 100644 --- a/osu.Game/Overlays/NotificationOverlayToastTray.cs +++ b/osu.Game/Overlays/NotificationOverlayToastTray.cs @@ -22,7 +22,7 @@ namespace osu.Game.Overlays /// /// A tray which attaches to the left of to show temporary toasts. /// - public class NotificationOverlayToastTray : CompositeDrawable + public partial class NotificationOverlayToastTray : CompositeDrawable { public override bool IsPresent => toastContentBackground.Height > 0 || toastFlow.Count > 0; diff --git a/osu.Game/Overlays/Notifications/Notification.cs b/osu.Game/Overlays/Notifications/Notification.cs index 8be9d2072b..77d3317b1f 100644 --- a/osu.Game/Overlays/Notifications/Notification.cs +++ b/osu.Game/Overlays/Notifications/Notification.cs @@ -23,7 +23,7 @@ using osuTK.Input; namespace osu.Game.Overlays.Notifications { - public abstract class Notification : Container + public abstract partial class Notification : Container { /// /// Notification was closed, either by user or otherwise. @@ -269,7 +269,7 @@ namespace osu.Game.Overlays.Notifications }); } - private class DragContainer : Container + private partial class DragContainer : Container { private Vector2 velocity; private Vector2 lastPosition; @@ -381,7 +381,7 @@ namespace osu.Game.Overlays.Notifications } } - internal class CloseButton : OsuClickableContainer + internal partial class CloseButton : OsuClickableContainer { private SpriteIcon icon = null!; private Box background = null!; @@ -436,7 +436,7 @@ namespace osu.Game.Overlays.Notifications } } - public class NotificationLight : Container + public partial class NotificationLight : Container { private bool pulsate; private Container pulsateLayer = null!; diff --git a/osu.Game/Overlays/Notifications/NotificationSection.cs b/osu.Game/Overlays/Notifications/NotificationSection.cs index 16105f913f..de4c72e473 100644 --- a/osu.Game/Overlays/Notifications/NotificationSection.cs +++ b/osu.Game/Overlays/Notifications/NotificationSection.cs @@ -17,7 +17,7 @@ using osuTK; namespace osu.Game.Overlays.Notifications { - public class NotificationSection : AlwaysUpdateFillFlowContainer + public partial class NotificationSection : AlwaysUpdateFillFlowContainer { private OsuSpriteText countDrawable = null!; @@ -33,15 +33,15 @@ namespace osu.Game.Overlays.Notifications public IEnumerable AcceptedNotificationTypes { get; } - private readonly string clearButtonText; + private readonly LocalisableString clearButtonText; private readonly LocalisableString titleText; - public NotificationSection(LocalisableString title, IEnumerable acceptedNotificationTypes, string clearButtonText) + public NotificationSection(LocalisableString title, IEnumerable acceptedNotificationTypes, LocalisableString clearButtonText) { AcceptedNotificationTypes = acceptedNotificationTypes.ToArray(); - this.clearButtonText = clearButtonText.ToUpperInvariant(); + this.clearButtonText = clearButtonText.ToUpper(); titleText = title; } @@ -135,7 +135,7 @@ namespace osu.Game.Overlays.Notifications return count; } - private class ClearAllButton : OsuClickableContainer + private partial class ClearAllButton : OsuClickableContainer { private readonly OsuSpriteText text; @@ -162,7 +162,7 @@ namespace osu.Game.Overlays.Notifications } } - public class AlwaysUpdateFillFlowContainer : FillFlowContainer + public partial class AlwaysUpdateFillFlowContainer : FillFlowContainer where T : Drawable { // this is required to ensure correct layout and scheduling on children. diff --git a/osu.Game/Overlays/Notifications/ProgressCompletionNotification.cs b/osu.Game/Overlays/Notifications/ProgressCompletionNotification.cs index 3cbdf7edf7..46972d4b5e 100644 --- a/osu.Game/Overlays/Notifications/ProgressCompletionNotification.cs +++ b/osu.Game/Overlays/Notifications/ProgressCompletionNotification.cs @@ -8,7 +8,7 @@ using osu.Framework.Graphics.Sprites; namespace osu.Game.Overlays.Notifications { - public class ProgressCompletionNotification : SimpleNotification + public partial class ProgressCompletionNotification : SimpleNotification { public ProgressCompletionNotification() { diff --git a/osu.Game/Overlays/Notifications/ProgressNotification.cs b/osu.Game/Overlays/Notifications/ProgressNotification.cs index 9812feb4a1..5cce0f8c5b 100644 --- a/osu.Game/Overlays/Notifications/ProgressNotification.cs +++ b/osu.Game/Overlays/Notifications/ProgressNotification.cs @@ -19,7 +19,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Notifications { - public class ProgressNotification : Notification, IHasCompletionTarget + public partial class ProgressNotification : Notification, IHasCompletionTarget { private const float loading_spinner_size = 22; @@ -255,7 +255,7 @@ namespace osu.Game.Overlays.Notifications } } - private class ProgressBar : Container + private partial class ProgressBar : Container { private readonly Box box; diff --git a/osu.Game/Overlays/Notifications/SimpleErrorNotification.cs b/osu.Game/Overlays/Notifications/SimpleErrorNotification.cs index ffefcb033f..7d0d07fc1b 100644 --- a/osu.Game/Overlays/Notifications/SimpleErrorNotification.cs +++ b/osu.Game/Overlays/Notifications/SimpleErrorNotification.cs @@ -7,7 +7,7 @@ using osu.Framework.Graphics.Sprites; namespace osu.Game.Overlays.Notifications { - public class SimpleErrorNotification : SimpleNotification + public partial class SimpleErrorNotification : SimpleNotification { public override string PopInSampleName => "UI/error-notification-pop-in"; diff --git a/osu.Game/Overlays/Notifications/SimpleNotification.cs b/osu.Game/Overlays/Notifications/SimpleNotification.cs index f3bb6a0578..109b31ff71 100644 --- a/osu.Game/Overlays/Notifications/SimpleNotification.cs +++ b/osu.Game/Overlays/Notifications/SimpleNotification.cs @@ -14,7 +14,7 @@ using osuTK; namespace osu.Game.Overlays.Notifications { - public class SimpleNotification : Notification + public partial class SimpleNotification : Notification { private LocalisableString text; diff --git a/osu.Game/Overlays/NowPlayingOverlay.cs b/osu.Game/Overlays/NowPlayingOverlay.cs index 949f1e7b96..66fb3571ba 100644 --- a/osu.Game/Overlays/NowPlayingOverlay.cs +++ b/osu.Game/Overlays/NowPlayingOverlay.cs @@ -28,7 +28,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays { - public class NowPlayingOverlay : OsuFocusedOverlayContainer, INamedOverlayComponent + public partial class NowPlayingOverlay : OsuFocusedOverlayContainer, INamedOverlayComponent { public string IconTexture => "Icons/Hexacons/music"; public LocalisableString Title => NowPlayingStrings.HeaderTitle; @@ -356,7 +356,7 @@ namespace osu.Game.Overlays musicController.TrackChanged -= trackChanged; } - private class MusicIconButton : IconButton + private partial class MusicIconButton : IconButton { public MusicIconButton() { @@ -380,7 +380,7 @@ namespace osu.Game.Overlays } } - private class Background : BufferedContainer + private partial class Background : BufferedContainer { private readonly Sprite sprite; private readonly WorkingBeatmap beatmap; @@ -419,7 +419,7 @@ namespace osu.Game.Overlays } } - private class DragContainer : Container + private partial class DragContainer : Container { protected override bool OnDragStart(DragStartEvent e) { @@ -443,7 +443,7 @@ namespace osu.Game.Overlays } } - private class HoverableProgressBar : ProgressBar + private partial class HoverableProgressBar : ProgressBar { public HoverableProgressBar() : base(true) diff --git a/osu.Game/Overlays/OSD/CopyUrlToast.cs b/osu.Game/Overlays/OSD/CopyUrlToast.cs index ea835a1c5e..ce5a5f56c4 100644 --- a/osu.Game/Overlays/OSD/CopyUrlToast.cs +++ b/osu.Game/Overlays/OSD/CopyUrlToast.cs @@ -5,7 +5,7 @@ using osu.Game.Localisation; namespace osu.Game.Overlays.OSD { - public class CopyUrlToast : Toast + public partial class CopyUrlToast : Toast { public CopyUrlToast() : base(UserInterfaceStrings.GeneralHeader, ToastStrings.UrlCopied, "") diff --git a/osu.Game/Overlays/OSD/Toast.cs b/osu.Game/Overlays/OSD/Toast.cs index a9fab0a23d..ff8696c04f 100644 --- a/osu.Game/Overlays/OSD/Toast.cs +++ b/osu.Game/Overlays/OSD/Toast.cs @@ -16,7 +16,7 @@ using osu.Game.Localisation; namespace osu.Game.Overlays.OSD { - public abstract class Toast : Container + public abstract partial class Toast : Container { private const int toast_minimum_width = 240; diff --git a/osu.Game/Overlays/OSD/TrackedSettingToast.cs b/osu.Game/Overlays/OSD/TrackedSettingToast.cs index 3bed5e7e4c..1aa6de423e 100644 --- a/osu.Game/Overlays/OSD/TrackedSettingToast.cs +++ b/osu.Game/Overlays/OSD/TrackedSettingToast.cs @@ -21,7 +21,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.OSD { - public class TrackedSettingToast : Toast + public partial class TrackedSettingToast : Toast { private const int lights_bottom_margin = 40; @@ -129,7 +129,7 @@ namespace osu.Game.Overlays.OSD sampleChange = audio.Samples.Get("UI/osd-change"); } - private class OptionLight : Container + private partial class OptionLight : Container { private Color4 glowingColour, idleColour; diff --git a/osu.Game/Overlays/OnScreenDisplay.cs b/osu.Game/Overlays/OnScreenDisplay.cs index f2836885ce..4f2dba7b2c 100644 --- a/osu.Game/Overlays/OnScreenDisplay.cs +++ b/osu.Game/Overlays/OnScreenDisplay.cs @@ -20,7 +20,7 @@ namespace osu.Game.Overlays /// An on-screen display which automatically tracks and displays toast notifications for . /// Can also display custom content via /// - public class OnScreenDisplay : Container + public partial class OnScreenDisplay : Container { private readonly Container box; @@ -58,7 +58,7 @@ namespace osu.Game.Overlays /// If is already being tracked from the same . public void BeginTracking(object source, ITrackableConfigManager configManager) { - if (configManager == null) throw new ArgumentNullException(nameof(configManager)); + ArgumentNullException.ThrowIfNull(configManager); if (trackedConfigManagers.ContainsKey((source, configManager))) throw new InvalidOperationException($"{nameof(configManager)} is already registered."); @@ -82,7 +82,7 @@ namespace osu.Game.Overlays /// If is not being tracked from the same . public void StopTracking(object source, ITrackableConfigManager configManager) { - if (configManager == null) throw new ArgumentNullException(nameof(configManager)); + ArgumentNullException.ThrowIfNull(configManager); if (!trackedConfigManagers.TryGetValue((source, configManager), out var existing)) return; diff --git a/osu.Game/Overlays/OnlineOverlay.cs b/osu.Game/Overlays/OnlineOverlay.cs index 24bc7a73e0..4fdf7cb2b6 100644 --- a/osu.Game/Overlays/OnlineOverlay.cs +++ b/osu.Game/Overlays/OnlineOverlay.cs @@ -7,12 +7,13 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; +using osu.Game.Graphics.Cursor; using osu.Game.Graphics.UserInterface; using osu.Game.Online; namespace osu.Game.Overlays { - public abstract class OnlineOverlay : FullscreenOverlay + public abstract partial class OnlineOverlay : FullscreenOverlay where T : OverlayHeader { protected override Container Content => content; @@ -38,20 +39,30 @@ namespace osu.Game.Overlays { RelativeSizeAxes = Axes.Both, ScrollbarVisible = false, - Child = new FillFlowContainer + Child = new OsuContextMenuContainer { - AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, - Direction = FillDirection.Vertical, - Children = new Drawable[] + AutoSizeAxes = Axes.Y, + Child = new PopoverContainer { - Header.With(h => h.Depth = float.MinValue), - content = new PopoverContainer + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Child = new FillFlowContainer { RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + Header.With(h => h.Depth = float.MinValue), + content = new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y + } + } } - } + }, } }, Loading = new LoadingLayer(true) diff --git a/osu.Game/Overlays/OverlayHeader.cs b/osu.Game/Overlays/OverlayHeader.cs index ed8e3849d4..f28d40c429 100644 --- a/osu.Game/Overlays/OverlayHeader.cs +++ b/osu.Game/Overlays/OverlayHeader.cs @@ -12,7 +12,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays { - public abstract class OverlayHeader : Container + public abstract partial class OverlayHeader : Container { public OverlayTitle Title { get; } @@ -75,19 +75,11 @@ namespace osu.Game.Overlays { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Children = new[] + Child = Title = CreateTitle().With(title => { - Title = CreateTitle().With(title => - { - title.Anchor = Anchor.CentreLeft; - title.Origin = Anchor.CentreLeft; - }), - CreateTitleContent().With(content => - { - content.Anchor = Anchor.CentreRight; - content.Origin = Anchor.CentreRight; - }) - } + title.Anchor = Anchor.CentreLeft; + title.Origin = Anchor.CentreLeft; + }), } } }, @@ -112,12 +104,6 @@ namespace osu.Game.Overlays [NotNull] protected virtual Drawable CreateBackground() => Empty(); - /// - /// Creates a on the opposite side of the . Used mostly to create . - /// - [NotNull] - protected virtual Drawable CreateTitleContent() => Empty(); - protected abstract OverlayTitle CreateTitle(); } } diff --git a/osu.Game/Overlays/OverlayHeaderBackground.cs b/osu.Game/Overlays/OverlayHeaderBackground.cs index 540b28d9b2..a089001385 100644 --- a/osu.Game/Overlays/OverlayHeaderBackground.cs +++ b/osu.Game/Overlays/OverlayHeaderBackground.cs @@ -11,7 +11,7 @@ using osu.Framework.Graphics.Textures; namespace osu.Game.Overlays { - public class OverlayHeaderBackground : CompositeDrawable + public partial class OverlayHeaderBackground : CompositeDrawable { public OverlayHeaderBackground(string textureName) { @@ -21,7 +21,7 @@ namespace osu.Game.Overlays InternalChild = new DelayedLoadWrapper(() => new Background(textureName)); } - private class Background : Sprite + private partial class Background : Sprite { private readonly string textureName; diff --git a/osu.Game/Overlays/OverlayPanelDisplayStyleControl.cs b/osu.Game/Overlays/OverlayPanelDisplayStyleControl.cs index 14a99cd5bb..d7d6bd4a2a 100644 --- a/osu.Game/Overlays/OverlayPanelDisplayStyleControl.cs +++ b/osu.Game/Overlays/OverlayPanelDisplayStyleControl.cs @@ -19,7 +19,7 @@ using osu.Framework.Extensions; namespace osu.Game.Overlays { - public class OverlayPanelDisplayStyleControl : OsuTabControl + public partial class OverlayPanelDisplayStyleControl : OsuTabControl { protected override Dropdown CreateDropdown() => null; @@ -51,7 +51,7 @@ namespace osu.Game.Overlays Direction = FillDirection.Horizontal }; - private class PanelDisplayTabItem : TabItem, IHasTooltip + private partial class PanelDisplayTabItem : TabItem, IHasTooltip { public IconUsage Icon { diff --git a/osu.Game/Overlays/OverlayRulesetSelector.cs b/osu.Game/Overlays/OverlayRulesetSelector.cs index a0efb197c2..9205a14d9f 100644 --- a/osu.Game/Overlays/OverlayRulesetSelector.cs +++ b/osu.Game/Overlays/OverlayRulesetSelector.cs @@ -11,8 +11,11 @@ using osuTK; namespace osu.Game.Overlays { - public class OverlayRulesetSelector : RulesetSelector + public partial class OverlayRulesetSelector : RulesetSelector { + // Since this component is used in online overlays and currently web-side doesn't support non-legacy rulesets, let's disable them for now. + protected override bool LegacyOnly => true; + public OverlayRulesetSelector() { AutoSizeAxes = Axes.Both; diff --git a/osu.Game/Overlays/OverlayRulesetTabItem.cs b/osu.Game/Overlays/OverlayRulesetTabItem.cs index ba0b81a514..d5c70a46d0 100644 --- a/osu.Game/Overlays/OverlayRulesetTabItem.cs +++ b/osu.Game/Overlays/OverlayRulesetTabItem.cs @@ -18,7 +18,7 @@ using osu.Game.Graphics.Containers; namespace osu.Game.Overlays { - public class OverlayRulesetTabItem : TabItem, IHasTooltip + public partial class OverlayRulesetTabItem : TabItem, IHasTooltip { private Color4 accentColour; diff --git a/osu.Game/Overlays/OverlayScrollContainer.cs b/osu.Game/Overlays/OverlayScrollContainer.cs index 95b27665f4..5bd7f014a9 100644 --- a/osu.Game/Overlays/OverlayScrollContainer.cs +++ b/osu.Game/Overlays/OverlayScrollContainer.cs @@ -23,7 +23,7 @@ namespace osu.Game.Overlays /// /// which provides . Mostly used in . /// - public class OverlayScrollContainer : UserTrackingScrollContainer + public partial class OverlayScrollContainer : UserTrackingScrollContainer { /// /// Scroll position at which the will be shown. @@ -62,7 +62,7 @@ namespace osu.Game.Overlays Button.State = Visibility.Hidden; } - public class ScrollToTopButton : OsuHoverContainer + public partial class ScrollToTopButton : OsuHoverContainer { private const int fade_duration = 500; diff --git a/osu.Game/Overlays/OverlaySidebar.cs b/osu.Game/Overlays/OverlaySidebar.cs index 62f3e1af13..87ce1b7e8c 100644 --- a/osu.Game/Overlays/OverlaySidebar.cs +++ b/osu.Game/Overlays/OverlaySidebar.cs @@ -12,7 +12,7 @@ using osu.Game.Graphics.Containers; namespace osu.Game.Overlays { - public abstract class OverlaySidebar : CompositeDrawable + public abstract partial class OverlaySidebar : CompositeDrawable { private readonly Box sidebarBackground; private readonly Box scrollbarBackground; diff --git a/osu.Game/Overlays/OverlaySortTabControl.cs b/osu.Game/Overlays/OverlaySortTabControl.cs index befb011353..8af2ab3823 100644 --- a/osu.Game/Overlays/OverlaySortTabControl.cs +++ b/osu.Game/Overlays/OverlaySortTabControl.cs @@ -24,7 +24,7 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays { - public class OverlaySortTabControl : CompositeDrawable, IHasCurrentValue + public partial class OverlaySortTabControl : CompositeDrawable, IHasCurrentValue { public TabControl TabControl { get; } @@ -74,7 +74,7 @@ namespace osu.Game.Overlays [NotNull] protected virtual SortTabControl CreateControl() => new SortTabControl(); - protected class SortTabControl : OsuTabControl + protected partial class SortTabControl : OsuTabControl { protected override Dropdown CreateDropdown() => null; @@ -93,7 +93,7 @@ namespace osu.Game.Overlays } } - protected class SortTabItem : TabItem + protected partial class SortTabItem : TabItem { public SortTabItem(T value) : base(value) @@ -117,7 +117,7 @@ namespace osu.Game.Overlays } } - protected class TabButton : HeaderButton + protected partial class TabButton : HeaderButton { public readonly BindableBool Active = new BindableBool(); diff --git a/osu.Game/Overlays/OverlayStreamControl.cs b/osu.Game/Overlays/OverlayStreamControl.cs index 1bd244176e..84de384fb5 100644 --- a/osu.Game/Overlays/OverlayStreamControl.cs +++ b/osu.Game/Overlays/OverlayStreamControl.cs @@ -12,7 +12,7 @@ using JetBrains.Annotations; namespace osu.Game.Overlays { - public abstract class OverlayStreamControl : TabControl + public abstract partial class OverlayStreamControl : TabControl { protected OverlayStreamControl() { diff --git a/osu.Game/Overlays/OverlayStreamItem.cs b/osu.Game/Overlays/OverlayStreamItem.cs index 3e09956480..9b18e5cccf 100644 --- a/osu.Game/Overlays/OverlayStreamItem.cs +++ b/osu.Game/Overlays/OverlayStreamItem.cs @@ -18,7 +18,7 @@ using osu.Framework.Localisation; namespace osu.Game.Overlays { - public abstract class OverlayStreamItem : TabItem + public abstract partial class OverlayStreamItem : TabItem { public readonly Bindable SelectedItem = new Bindable(); diff --git a/osu.Game/Overlays/OverlayTabControl.cs b/osu.Game/Overlays/OverlayTabControl.cs index 35e073a3a1..884e31868f 100644 --- a/osu.Game/Overlays/OverlayTabControl.cs +++ b/osu.Game/Overlays/OverlayTabControl.cs @@ -16,7 +16,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays { - public abstract class OverlayTabControl : OsuTabControl + public abstract partial class OverlayTabControl : OsuTabControl { private readonly Box bar; @@ -58,7 +58,7 @@ namespace osu.Game.Overlays protected override TabItem CreateTabItem(T value) => new OverlayTabItem(value); - protected class OverlayTabItem : TabItem, IHasAccentColour + protected partial class OverlayTabItem : TabItem, IHasAccentColour { protected readonly ExpandingBar Bar; protected readonly OsuSpriteText Text; diff --git a/osu.Game/Overlays/OverlayTitle.cs b/osu.Game/Overlays/OverlayTitle.cs index f2c42034a3..1d207e5f7d 100644 --- a/osu.Game/Overlays/OverlayTitle.cs +++ b/osu.Game/Overlays/OverlayTitle.cs @@ -15,7 +15,7 @@ using osuTK; namespace osu.Game.Overlays { - public abstract class OverlayTitle : CompositeDrawable, INamedOverlayComponent + public abstract partial class OverlayTitle : CompositeDrawable, INamedOverlayComponent { public const float ICON_SIZE = 30; @@ -69,7 +69,7 @@ namespace osu.Game.Overlays }; } - private class OverlayTitleIcon : Sprite + private partial class OverlayTitleIcon : Sprite { private readonly string textureName; diff --git a/osu.Game/Overlays/OverlayView.cs b/osu.Game/Overlays/OverlayView.cs index 80df0c695f..e919641b9b 100644 --- a/osu.Game/Overlays/OverlayView.cs +++ b/osu.Game/Overlays/OverlayView.cs @@ -18,7 +18,7 @@ namespace osu.Game.Overlays /// Automatically performs a data fetch on load. /// /// The type of the API response. - public abstract class OverlayView : CompositeDrawable + public abstract partial class OverlayView : CompositeDrawable where T : class { [Resolved] diff --git a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs index dcc8b19021..1e80257a57 100644 --- a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using Humanizer; using osu.Framework.Allocation; @@ -23,17 +21,17 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Profile.Header { - public class BottomHeaderContainer : CompositeDrawable + public partial class BottomHeaderContainer : CompositeDrawable { - public readonly Bindable User = new Bindable(); + public readonly Bindable User = new Bindable(); - private LinkFlowContainer topLinkContainer; - private LinkFlowContainer bottomLinkContainer; + private LinkFlowContainer topLinkContainer = null!; + private LinkFlowContainer bottomLinkContainer = null!; private Color4 iconColour; [Resolved] - private IAPIProvider api { get; set; } + private IAPIProvider api { get; set; } = null!; public BottomHeaderContainer() { @@ -75,10 +73,10 @@ namespace osu.Game.Overlays.Profile.Header } }; - User.BindValueChanged(user => updateDisplay(user.NewValue)); + User.BindValueChanged(user => updateDisplay(user.NewValue?.User)); } - private void updateDisplay(APIUser user) + private void updateDisplay(APIUser? user) { topLinkContainer.Clear(); bottomLinkContainer.Clear(); @@ -164,7 +162,7 @@ namespace osu.Game.Overlays.Profile.Header private void addSpacer(OsuTextFlowContainer textFlow) => textFlow.AddArbitraryDrawable(new Container { Width = 15 }); - private bool tryAddInfo(IconUsage icon, string content, string link = null) + private bool tryAddInfo(IconUsage icon, string content, string? link = null) { if (string.IsNullOrEmpty(content)) return false; diff --git a/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs index b07817de46..0dab4d582d 100644 --- a/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs @@ -1,29 +1,22 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Localisation; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.Profile.Header.Components; -using osu.Game.Resources.Localisation.Web; using osuTK; namespace osu.Game.Overlays.Profile.Header { - public class CentreHeaderContainer : CompositeDrawable + public partial class CentreHeaderContainer : CompositeDrawable { - public readonly BindableBool DetailsVisible = new BindableBool(true); - public readonly Bindable User = new Bindable(); + public readonly Bindable User = new Bindable(); - private OverlinedInfoContainer hiddenDetailGlobal; - private OverlinedInfoContainer hiddenDetailCountry; + private LevelBadge levelBadge = null!; public CentreHeaderContainer() { @@ -33,15 +26,12 @@ namespace osu.Game.Overlays.Profile.Header [BackgroundDependencyLoader] private void load(OverlayColourProvider colourProvider) { - Container hiddenDetailContainer; - Container expandedDetailContainer; - InternalChildren = new Drawable[] { new Box { RelativeSizeAxes = Axes.Both, - Colour = colourProvider.Background4 + Colour = colourProvider.Background3 }, new FillFlowContainer { @@ -68,20 +58,6 @@ namespace osu.Game.Overlays.Profile.Header } }, new Container - { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - RelativeSizeAxes = Axes.Y, - Padding = new MarginPadding { Vertical = 10 }, - Width = UserProfileOverlay.CONTENT_X_MARGIN, - Child = new ExpandDetailsButton - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - DetailsVisible = { BindTarget = DetailsVisible } - }, - }, - new Container { Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, @@ -89,14 +65,13 @@ namespace osu.Game.Overlays.Profile.Header Margin = new MarginPadding { Right = UserProfileOverlay.CONTENT_X_MARGIN }, Children = new Drawable[] { - new LevelBadge + levelBadge = new LevelBadge { Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, - Size = new Vector2(40), - User = { BindTarget = User } + Size = new Vector2(40) }, - expandedDetailContainer = new Container + new Container { Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, @@ -109,47 +84,21 @@ namespace osu.Game.Overlays.Profile.Header User = { BindTarget = User } } }, - hiddenDetailContainer = new FillFlowContainer - { - Direction = FillDirection.Horizontal, - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - Width = 200, - AutoSizeAxes = Axes.Y, - Alpha = 0, - Spacing = new Vector2(10, 0), - Margin = new MarginPadding { Right = 50 }, - Children = new[] - { - hiddenDetailGlobal = new OverlinedInfoContainer - { - Title = UsersStrings.ShowRankGlobalSimple, - LineColour = colourProvider.Highlight1 - }, - hiddenDetailCountry = new OverlinedInfoContainer - { - Title = UsersStrings.ShowRankCountrySimple, - LineColour = colourProvider.Highlight1 - }, - } - } } } }; - - DetailsVisible.BindValueChanged(visible => - { - hiddenDetailContainer.FadeTo(visible.NewValue ? 0 : 1, 200, Easing.OutQuint); - expandedDetailContainer.FadeTo(visible.NewValue ? 1 : 0, 200, Easing.OutQuint); - }); - - User.BindValueChanged(user => updateDisplay(user.NewValue)); } - private void updateDisplay(APIUser user) + protected override void LoadComplete() { - hiddenDetailGlobal.Content = user?.Statistics?.GlobalRank?.ToLocalisableString("\\##,##0") ?? (LocalisableString)"-"; - hiddenDetailCountry.Content = user?.Statistics?.CountryRank?.ToLocalisableString("\\##,##0") ?? (LocalisableString)"-"; + base.LoadComplete(); + + User.BindValueChanged(user => updateDisplay(user.NewValue?.User), true); + } + + private void updateDisplay(APIUser? user) + { + levelBadge.LevelInfo.Value = user?.Statistics?.Level; } } } diff --git a/osu.Game/Overlays/Profile/Header/Components/DrawableBadge.cs b/osu.Game/Overlays/Profile/Header/Components/DrawableBadge.cs index 2ee80a7494..5f100bc882 100644 --- a/osu.Game/Overlays/Profile/Header/Components/DrawableBadge.cs +++ b/osu.Game/Overlays/Profile/Header/Components/DrawableBadge.cs @@ -14,7 +14,7 @@ using osuTK; namespace osu.Game.Overlays.Profile.Header.Components { [LongRunningLoad] - public class DrawableBadge : OsuClickableContainer + public partial class DrawableBadge : OsuClickableContainer { public static readonly Vector2 DRAWABLE_BADGE_SIZE = new Vector2(86, 40); diff --git a/osu.Game/Overlays/Profile/Header/Components/ExpandDetailsButton.cs b/osu.Game/Overlays/Profile/Header/Components/ExpandDetailsButton.cs index 62b228c285..e7a83c95d8 100644 --- a/osu.Game/Overlays/Profile/Header/Components/ExpandDetailsButton.cs +++ b/osu.Game/Overlays/Profile/Header/Components/ExpandDetailsButton.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; @@ -17,15 +15,15 @@ using osuTK; namespace osu.Game.Overlays.Profile.Header.Components { - public class ExpandDetailsButton : ProfileHeaderButton + public partial class ExpandDetailsButton : ProfileHeaderButton { public readonly BindableBool DetailsVisible = new BindableBool(); public override LocalisableString TooltipText => DetailsVisible.Value ? CommonStrings.ButtonsCollapse : CommonStrings.ButtonsExpand; - private SpriteIcon icon; - private Sample sampleOpen; - private Sample sampleClose; + private SpriteIcon icon = null!; + private Sample? sampleOpen; + private Sample? sampleClose; protected override HoverSounds CreateHoverSounds(HoverSampleSet sampleSet) => new HoverClickSounds(); diff --git a/osu.Game/Overlays/Profile/Header/Components/FollowersButton.cs b/osu.Game/Overlays/Profile/Header/Components/FollowersButton.cs index 6fbfff1dd7..844efa5cf0 100644 --- a/osu.Game/Overlays/Profile/Header/Components/FollowersButton.cs +++ b/osu.Game/Overlays/Profile/Header/Components/FollowersButton.cs @@ -1,20 +1,17 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; -using osu.Game.Online.API.Requests.Responses; using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Profile.Header.Components { - public class FollowersButton : ProfileHeaderStatisticsButton + public partial class FollowersButton : ProfileHeaderStatisticsButton { - public readonly Bindable User = new Bindable(); + public readonly Bindable User = new Bindable(); public override LocalisableString TooltipText => FriendsStrings.ButtonsDisabled; @@ -24,7 +21,7 @@ namespace osu.Game.Overlays.Profile.Header.Components private void load() { // todo: when friending/unfriending is implemented, the APIAccess.Friends list should be updated accordingly. - User.BindValueChanged(user => SetValue(user.NewValue?.FollowerCount ?? 0), true); + User.BindValueChanged(user => SetValue(user.NewValue?.User.FollowerCount ?? 0), true); } } } diff --git a/osu.Game/Overlays/Profile/Header/Components/GroupBadge.cs b/osu.Game/Overlays/Profile/Header/Components/GroupBadge.cs new file mode 100644 index 0000000000..e62f1cebf0 --- /dev/null +++ b/osu.Game/Overlays/Profile/Header/Components/GroupBadge.cs @@ -0,0 +1,84 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Localisation; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Rulesets; +using osuTK; + +namespace osu.Game.Overlays.Profile.Header.Components +{ + public partial class GroupBadge : Container, IHasTooltip + { + public LocalisableString TooltipText { get; } + + public int TextSize { get; set; } = 12; + + private readonly APIUserGroup group; + + public GroupBadge(APIUserGroup group) + { + this.group = group; + + AutoSizeAxes = Axes.Both; + Masking = true; + CornerRadius = 8; + + TooltipText = group.Name; + } + + [BackgroundDependencyLoader] + private void load(OverlayColourProvider? colourProvider, RulesetStore rulesets) + { + FillFlowContainer innerContainer; + + AddRangeInternal(new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colourProvider?.Background6 ?? Colour4.Black + }, + innerContainer = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Padding = new MarginPadding { Vertical = 2, Horizontal = 10 }, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(5), + Children = new[] + { + new OsuSpriteText + { + Text = group.ShortName, + Colour = Color4Extensions.FromHex(group.Colour ?? Colour4.White.ToHex()), + Shadow = false, + Font = OsuFont.GetFont(size: TextSize, weight: FontWeight.Bold, italics: true) + } + } + } + }); + + if (group.Playmodes?.Length > 0) + { + innerContainer.AddRange(group.Playmodes.Select(p => + (rulesets.GetRuleset(p)?.CreateInstance().CreateIcon() ?? new SpriteIcon { Icon = FontAwesome.Regular.QuestionCircle }).With(icon => + { + icon.Size = new Vector2(TextSize - 1); + })).ToList() + ); + } + } + } +} diff --git a/osu.Game/Overlays/Profile/Header/Components/GroupBadgeFlow.cs b/osu.Game/Overlays/Profile/Header/Components/GroupBadgeFlow.cs new file mode 100644 index 0000000000..33b3de94db --- /dev/null +++ b/osu.Game/Overlays/Profile/Header/Components/GroupBadgeFlow.cs @@ -0,0 +1,32 @@ +// Copyright (c) ppy Pty Ltd . 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.Framework.Graphics.Containers; +using osu.Game.Online.API.Requests.Responses; +using osuTK; + +namespace osu.Game.Overlays.Profile.Header.Components +{ + public partial class GroupBadgeFlow : FillFlowContainer + { + public readonly Bindable User = new Bindable(); + + public GroupBadgeFlow() + { + AutoSizeAxes = Axes.Both; + Direction = FillDirection.Horizontal; + Spacing = new Vector2(2); + + User.BindValueChanged(user => + { + Clear(true); + + if (user.NewValue?.Groups != null) + AddRange(user.NewValue.Groups.Select(g => new GroupBadge(g))); + }); + } + } +} diff --git a/osu.Game/Overlays/Profile/Header/Components/LevelBadge.cs b/osu.Game/Overlays/Profile/Header/Components/LevelBadge.cs index fdf7478834..00bb8cbc75 100644 --- a/osu.Game/Overlays/Profile/Header/Components/LevelBadge.cs +++ b/osu.Game/Overlays/Profile/Header/Components/LevelBadge.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -13,18 +11,18 @@ using osu.Framework.Graphics.Textures; using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -using osu.Game.Online.API.Requests.Responses; using osu.Game.Resources.Localisation.Web; +using osu.Game.Users; namespace osu.Game.Overlays.Profile.Header.Components { - public class LevelBadge : CompositeDrawable, IHasTooltip + public partial class LevelBadge : CompositeDrawable, IHasTooltip { - public readonly Bindable User = new Bindable(); + public readonly Bindable LevelInfo = new Bindable(); public LocalisableString TooltipText { get; private set; } - private OsuSpriteText levelText; + private OsuSpriteText levelText = null!; public LevelBadge() { @@ -49,14 +47,20 @@ namespace osu.Game.Overlays.Profile.Header.Components Font = OsuFont.GetFont(size: 20) } }; - - User.BindValueChanged(user => updateLevel(user.NewValue)); } - private void updateLevel(APIUser user) + protected override void LoadComplete() { - levelText.Text = user?.Statistics?.Level.Current.ToString() ?? "0"; - TooltipText = UsersStrings.ShowStatsLevel(user?.Statistics?.Level.Current.ToString()); + base.LoadComplete(); + + LevelInfo.BindValueChanged(level => updateLevel(level.NewValue), true); + } + + private void updateLevel(UserStatistics.LevelInfo? levelInfo) + { + string level = levelInfo?.Current.ToString() ?? "0"; + levelText.Text = level; + TooltipText = UsersStrings.ShowStatsLevel(level); } } } diff --git a/osu.Game/Overlays/Profile/Header/Components/LevelProgressBar.cs b/osu.Game/Overlays/Profile/Header/Components/LevelProgressBar.cs index 1ba391431f..919ccb0dd4 100644 --- a/osu.Game/Overlays/Profile/Header/Components/LevelProgressBar.cs +++ b/osu.Game/Overlays/Profile/Header/Components/LevelProgressBar.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.LocalisationExtensions; @@ -19,14 +17,14 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Profile.Header.Components { - public class LevelProgressBar : CompositeDrawable, IHasTooltip + public partial class LevelProgressBar : CompositeDrawable, IHasTooltip { - public readonly Bindable User = new Bindable(); + public readonly Bindable User = new Bindable(); public LocalisableString TooltipText { get; } - private Bar levelProgressBar; - private OsuSpriteText levelProgressText; + private Bar levelProgressBar = null!; + private OsuSpriteText levelProgressText = null!; public LevelProgressBar() { @@ -58,10 +56,10 @@ namespace osu.Game.Overlays.Profile.Header.Components } }; - User.BindValueChanged(user => updateProgress(user.NewValue)); + User.BindValueChanged(user => updateProgress(user.NewValue?.User)); } - private void updateProgress(APIUser user) + private void updateProgress(APIUser? user) { levelProgressBar.Length = user?.Statistics?.Level.Progress / 100f ?? 0; levelProgressText.Text = user?.Statistics?.Level.Progress.ToLocalisableString("0'%'") ?? default; diff --git a/osu.Game/Overlays/Profile/Header/Components/MappingSubscribersButton.cs b/osu.Game/Overlays/Profile/Header/Components/MappingSubscribersButton.cs index 7bfc78cb2d..d509ec0f81 100644 --- a/osu.Game/Overlays/Profile/Header/Components/MappingSubscribersButton.cs +++ b/osu.Game/Overlays/Profile/Header/Components/MappingSubscribersButton.cs @@ -1,20 +1,17 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; -using osu.Game.Online.API.Requests.Responses; using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Profile.Header.Components { - public class MappingSubscribersButton : ProfileHeaderStatisticsButton + public partial class MappingSubscribersButton : ProfileHeaderStatisticsButton { - public readonly Bindable User = new Bindable(); + public readonly Bindable User = new Bindable(); public override LocalisableString TooltipText => FollowsStrings.MappingFollowers; @@ -23,7 +20,7 @@ namespace osu.Game.Overlays.Profile.Header.Components [BackgroundDependencyLoader] private void load() { - User.BindValueChanged(user => SetValue(user.NewValue?.MappingFollowerCount ?? 0), true); + User.BindValueChanged(user => SetValue(user.NewValue?.User.MappingFollowerCount ?? 0), true); } } } diff --git a/osu.Game/Overlays/Profile/Header/Components/MessageUserButton.cs b/osu.Game/Overlays/Profile/Header/Components/MessageUserButton.cs index 46cb811846..5f934e3916 100644 --- a/osu.Game/Overlays/Profile/Header/Components/MessageUserButton.cs +++ b/osu.Game/Overlays/Profile/Header/Components/MessageUserButton.cs @@ -1,38 +1,35 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; using osu.Game.Online.API; -using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Chat; using osu.Game.Resources.Localisation.Web; using osuTK; namespace osu.Game.Overlays.Profile.Header.Components { - public class MessageUserButton : ProfileHeaderButton + public partial class MessageUserButton : ProfileHeaderButton { - public readonly Bindable User = new Bindable(); + public readonly Bindable User = new Bindable(); public override LocalisableString TooltipText => UsersStrings.CardSendMessage; - [Resolved(CanBeNull = true)] - private ChannelManager channelManager { get; set; } - - [Resolved(CanBeNull = true)] - private UserProfileOverlay userOverlay { get; set; } - - [Resolved(CanBeNull = true)] - private ChatOverlay chatOverlay { get; set; } + [Resolved] + private ChannelManager? channelManager { get; set; } [Resolved] - private IAPIProvider apiProvider { get; set; } + private UserProfileOverlay? userOverlay { get; set; } + + [Resolved] + private ChatOverlay? chatOverlay { get; set; } + + [Resolved] + private IAPIProvider apiProvider { get; set; } = null!; public MessageUserButton() { @@ -51,12 +48,16 @@ namespace osu.Game.Overlays.Profile.Header.Components { if (!Content.IsPresent) return; - channelManager?.OpenPrivateChannel(User.Value); + channelManager?.OpenPrivateChannel(User.Value?.User); userOverlay?.Hide(); chatOverlay?.Show(); }; - User.ValueChanged += e => Content.Alpha = !e.NewValue.PMFriendsOnly && apiProvider.LocalUser.Value.Id != e.NewValue.Id ? 1 : 0; + User.ValueChanged += e => + { + var user = e.NewValue?.User; + Content.Alpha = user != null && !user.PMFriendsOnly && apiProvider.LocalUser.Value.Id != user.Id ? 1 : 0; + }; } } } diff --git a/osu.Game/Overlays/Profile/Header/Components/PreviousUsernames.cs b/osu.Game/Overlays/Profile/Header/Components/PreviousUsernames.cs index 808c814928..b722fe92e0 100644 --- a/osu.Game/Overlays/Profile/Header/Components/PreviousUsernames.cs +++ b/osu.Game/Overlays/Profile/Header/Components/PreviousUsernames.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Linq; using osu.Framework.Allocation; @@ -20,14 +18,14 @@ using osuTK; namespace osu.Game.Overlays.Profile.Header.Components { - public class PreviousUsernames : CompositeDrawable + public partial class PreviousUsernames : CompositeDrawable { private const int duration = 200; private const int margin = 10; private const int width = 310; private const int move_offset = 15; - public readonly Bindable User = new Bindable(); + public readonly Bindable User = new Bindable(); private readonly TextFlowContainer text; private readonly Box background; @@ -109,11 +107,11 @@ namespace osu.Game.Overlays.Profile.Header.Components User.BindValueChanged(onUserChanged, true); } - private void onUserChanged(ValueChangedEvent user) + private void onUserChanged(ValueChangedEvent user) { text.Text = string.Empty; - string[] usernames = user.NewValue?.PreviousUsernames; + string[]? usernames = user.NewValue?.PreviousUsernames; if (usernames?.Any() ?? false) { @@ -147,9 +145,9 @@ namespace osu.Game.Overlays.Profile.Header.Components this.MoveToY(0, duration, Easing.OutQuint); } - private class HoverIconContainer : Container + private partial class HoverIconContainer : Container { - public Action ActivateHover; + public Action? ActivateHover; public HoverIconContainer() { diff --git a/osu.Game/Overlays/Profile/Header/Components/ProfileHeaderButton.cs b/osu.Game/Overlays/Profile/Header/Components/ProfileHeaderButton.cs index 5bdf9c19e1..414ca4d077 100644 --- a/osu.Game/Overlays/Profile/Header/Components/ProfileHeaderButton.cs +++ b/osu.Game/Overlays/Profile/Header/Components/ProfileHeaderButton.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -12,7 +10,7 @@ using osu.Game.Graphics.Containers; namespace osu.Game.Overlays.Profile.Header.Components { - public abstract class ProfileHeaderButton : OsuHoverContainer + public abstract partial class ProfileHeaderButton : OsuHoverContainer { private readonly Box background; private readonly Container content; diff --git a/osu.Game/Overlays/Profile/Header/Components/ProfileHeaderStatisticsButton.cs b/osu.Game/Overlays/Profile/Header/Components/ProfileHeaderStatisticsButton.cs index 3b3251fc4e..32c5ebee2c 100644 --- a/osu.Game/Overlays/Profile/Header/Components/ProfileHeaderStatisticsButton.cs +++ b/osu.Game/Overlays/Profile/Header/Components/ProfileHeaderStatisticsButton.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -13,7 +11,7 @@ using osuTK; namespace osu.Game.Overlays.Profile.Header.Components { - public abstract class ProfileHeaderStatisticsButton : ProfileHeaderButton + public abstract partial class ProfileHeaderStatisticsButton : ProfileHeaderButton { private readonly OsuSpriteText drawableText; diff --git a/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetSelector.cs b/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetSelector.cs index 3a47570cf7..9f306ee20b 100644 --- a/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetSelector.cs +++ b/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetSelector.cs @@ -1,23 +1,39 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - +using System.Linq; +using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics.UserInterface; -using osu.Game.Online.API.Requests.Responses; +using osu.Game.Extensions; using osu.Game.Rulesets; namespace osu.Game.Overlays.Profile.Header.Components { - public class ProfileRulesetSelector : OverlayRulesetSelector + public partial class ProfileRulesetSelector : OverlayRulesetSelector { - public readonly Bindable User = new Bindable(); + [Resolved] + private UserProfileOverlay? profileOverlay { get; set; } + + public readonly Bindable User = new Bindable(); protected override void LoadComplete() { base.LoadComplete(); - User.BindValueChanged(u => SetDefaultRuleset(Rulesets.GetRuleset(u.NewValue?.PlayMode ?? "osu")), true); + + User.BindValueChanged(user => updateState(user.NewValue), true); + Current.BindValueChanged(ruleset => + { + if (User.Value != null && !ruleset.NewValue.Equals(User.Value.Ruleset)) + profileOverlay?.ShowUser(User.Value.User, ruleset.NewValue); + }); + } + + private void updateState(UserProfileData? user) + { + Current.Value = Items.SingleOrDefault(ruleset => user?.Ruleset.MatchesOnlineID(ruleset) == true); + SetDefaultRuleset(Rulesets.GetRuleset(user?.User.PlayMode ?? @"osu").AsNonNull()); } public void SetDefaultRuleset(RulesetInfo ruleset) diff --git a/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetTabItem.cs b/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetTabItem.cs index d75fe1ae84..9caa7dd1bc 100644 --- a/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetTabItem.cs +++ b/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetTabItem.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Sprites; @@ -14,7 +12,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Profile.Header.Components { - public class ProfileRulesetTabItem : OverlayRulesetTabItem + public partial class ProfileRulesetTabItem : OverlayRulesetTabItem { private bool isDefault; @@ -50,7 +48,7 @@ namespace osu.Game.Overlays.Profile.Header.Components Add(icon = new DefaultRulesetIcon { Alpha = 0 }); } - public class DefaultRulesetIcon : SpriteIcon, IHasTooltip + public partial class DefaultRulesetIcon : SpriteIcon, IHasTooltip { public LocalisableString TooltipText => UsersStrings.ShowEditDefaultPlaymodeIsDefaultTooltip; diff --git a/osu.Game/Overlays/Profile/Header/Components/OverlinedInfoContainer.cs b/osu.Game/Overlays/Profile/Header/Components/ProfileValueDisplay.cs similarity index 64% rename from osu.Game/Overlays/Profile/Header/Components/OverlinedInfoContainer.cs rename to osu.Game/Overlays/Profile/Header/Components/ProfileValueDisplay.cs index 7ac472ee00..4b1a0409a3 100644 --- a/osu.Game/Overlays/Profile/Header/Components/OverlinedInfoContainer.cs +++ b/osu.Game/Overlays/Profile/Header/Components/ProfileValueDisplay.cs @@ -1,21 +1,17 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -using osuTK.Graphics; namespace osu.Game.Overlays.Profile.Header.Components { - public class OverlinedInfoContainer : CompositeDrawable + public partial class ProfileValueDisplay : CompositeDrawable { - private readonly Circle line; private readonly OsuSpriteText title; private readonly OsuSpriteText content; @@ -29,12 +25,7 @@ namespace osu.Game.Overlays.Profile.Header.Components set => content.Text = value; } - public Color4 LineColour - { - set => line.Colour = value; - } - - public OverlinedInfoContainer(bool big = false, int minimumWidth = 60) + public ProfileValueDisplay(bool big = false, int minimumWidth = 60) { AutoSizeAxes = Axes.Both; InternalChild = new FillFlowContainer @@ -43,19 +34,13 @@ namespace osu.Game.Overlays.Profile.Header.Components AutoSizeAxes = Axes.Both, Children = new Drawable[] { - line = new Circle - { - RelativeSizeAxes = Axes.X, - Height = 2, - Margin = new MarginPadding { Bottom = 2 } - }, title = new OsuSpriteText { - Font = OsuFont.GetFont(size: big ? 14 : 12, weight: FontWeight.Bold) + Font = OsuFont.GetFont(size: 12) }, content = new OsuSpriteText { - Font = OsuFont.GetFont(size: big ? 40 : 18, weight: FontWeight.Light) + Font = OsuFont.GetFont(size: big ? 30 : 20, weight: FontWeight.Light) }, new Container // Add a minimum size to the FillFlowContainer { @@ -64,5 +49,12 @@ namespace osu.Game.Overlays.Profile.Header.Components } }; } + + [BackgroundDependencyLoader] + private void load(OverlayColourProvider colourProvider) + { + title.Colour = colourProvider.Content1; + content.Colour = colourProvider.Content2; + } } } diff --git a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs index 85fb5c4e5c..fe1069eea1 100644 --- a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs +++ b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; @@ -17,11 +15,11 @@ using osu.Game.Users; namespace osu.Game.Overlays.Profile.Header.Components { - public class RankGraph : UserGraph + public partial class RankGraph : UserGraph { private const int ranked_days = 88; - public readonly Bindable Statistics = new Bindable(); + public readonly Bindable Statistics = new Bindable(); private readonly OsuSpriteText placeholder; @@ -42,11 +40,11 @@ namespace osu.Game.Overlays.Profile.Header.Components Statistics.BindValueChanged(statistics => updateStatistics(statistics.NewValue), true); } - private void updateStatistics(UserStatistics statistics) + private void updateStatistics(UserStatistics? statistics) { // checking both IsRanked and RankHistory is required. // see https://github.com/ppy/osu-web/blob/154ceafba0f35a1dd935df53ec98ae2ea5615f9f/resources/assets/lib/profile-page/rank-chart.tsx#L46 - int[] userRanks = statistics?.IsRanked == true ? statistics.RankHistory?.Data : null; + int[]? userRanks = statistics?.IsRanked == true ? statistics.RankHistory?.Data : null; Data = userRanks?.Select((x, index) => new KeyValuePair(index, x)).Where(x => x.Value != 0).ToArray(); } diff --git a/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs b/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs index a05d8ba152..92e2017659 100644 --- a/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs +++ b/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -17,7 +15,7 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Profile.Header.Components { - public class SupporterIcon : OsuClickableContainer + public partial class SupporterIcon : OsuClickableContainer { private readonly Box background; private readonly FillFlowContainer iconContainer; @@ -82,10 +80,10 @@ namespace osu.Game.Overlays.Profile.Header.Components } [Resolved] - private OsuColour colours { get; set; } + private OsuColour colours { get; set; } = null!; - [BackgroundDependencyLoader(true)] - private void load(OsuGame game) + [BackgroundDependencyLoader] + private void load(OsuGame? game) { background.Colour = colours.Pink; diff --git a/osu.Game/Overlays/Profile/Header/Components/OverlinedTotalPlayTime.cs b/osu.Game/Overlays/Profile/Header/Components/TotalPlayTime.cs similarity index 66% rename from osu.Game/Overlays/Profile/Header/Components/OverlinedTotalPlayTime.cs rename to osu.Game/Overlays/Profile/Header/Components/TotalPlayTime.cs index 9e5a0f5962..08ca59d89b 100644 --- a/osu.Game/Overlays/Profile/Header/Components/OverlinedTotalPlayTime.cs +++ b/osu.Game/Overlays/Profile/Header/Components/TotalPlayTime.cs @@ -1,28 +1,25 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Localisation; -using osu.Game.Online.API.Requests.Responses; using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Profile.Header.Components { - public class OverlinedTotalPlayTime : CompositeDrawable, IHasTooltip + public partial class TotalPlayTime : CompositeDrawable, IHasTooltip { - public readonly Bindable User = new Bindable(); + public readonly Bindable User = new Bindable(); public LocalisableString TooltipText { get; set; } - private OverlinedInfoContainer info; + private ProfileValueDisplay info = null!; - public OverlinedTotalPlayTime() + public TotalPlayTime() { AutoSizeAxes = Axes.Both; @@ -30,21 +27,21 @@ namespace osu.Game.Overlays.Profile.Header.Components } [BackgroundDependencyLoader] - private void load(OverlayColourProvider colourProvider) + private void load() { - InternalChild = info = new OverlinedInfoContainer + InternalChild = info = new ProfileValueDisplay(minimumWidth: 140) { Title = UsersStrings.ShowStatsPlayTime, - LineColour = colourProvider.Highlight1, }; User.BindValueChanged(updateTime, true); } - private void updateTime(ValueChangedEvent user) + private void updateTime(ValueChangedEvent user) { - TooltipText = (user.NewValue?.Statistics?.PlayTime ?? 0) / 3600 + " hours"; - info.Content = formatTime(user.NewValue?.Statistics?.PlayTime); + int? playTime = user.NewValue?.User.Statistics?.PlayTime; + TooltipText = (playTime ?? 0) / 3600 + " hours"; + info.Content = formatTime(playTime); } private string formatTime(int? secondsNull) diff --git a/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs index d65691f531..890e6c4e04 100644 --- a/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -13,7 +11,6 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Leaderboards; using osu.Game.Overlays.Profile.Header.Components; using osu.Game.Resources.Localisation.Web; @@ -22,44 +19,19 @@ using osuTK; namespace osu.Game.Overlays.Profile.Header { - public class DetailHeaderContainer : CompositeDrawable + public partial class DetailHeaderContainer : CompositeDrawable { private readonly Dictionary scoreRankInfos = new Dictionary(); - private OverlinedInfoContainer medalInfo; - private OverlinedInfoContainer ppInfo; - private OverlinedInfoContainer detailGlobalRank; - private OverlinedInfoContainer detailCountryRank; - private FillFlowContainer fillFlow; - private RankGraph rankGraph; + private ProfileValueDisplay medalInfo = null!; + private ProfileValueDisplay ppInfo = null!; + private ProfileValueDisplay detailGlobalRank = null!; + private ProfileValueDisplay detailCountryRank = null!; + private RankGraph rankGraph = null!; - public readonly Bindable User = new Bindable(); - - private bool expanded = true; - - public bool Expanded - { - set - { - if (expanded == value) return; - - expanded = value; - - if (fillFlow == null) return; - - fillFlow.ClearTransforms(); - - if (expanded) - fillFlow.AutoSizeAxes = Axes.Y; - else - { - fillFlow.AutoSizeAxes = Axes.None; - fillFlow.ResizeHeightTo(0, 200, Easing.OutQuint); - } - } - } + public readonly Bindable User = new Bindable(); [BackgroundDependencyLoader] - private void load(OverlayColourProvider colourProvider, OsuColour colours) + private void load(OverlayColourProvider colourProvider) { AutoSizeAxes = Axes.Y; @@ -72,18 +44,48 @@ namespace osu.Game.Overlays.Profile.Header RelativeSizeAxes = Axes.Both, Colour = colourProvider.Background5, }, - fillFlow = new FillFlowContainer + new FillFlowContainer { RelativeSizeAxes = Axes.X, - AutoSizeAxes = expanded ? Axes.Y : Axes.None, + AutoSizeAxes = Axes.Y, AutoSizeDuration = 200, AutoSizeEasing = Easing.OutQuint, Masking = true, Padding = new MarginPadding { Horizontal = UserProfileOverlay.CONTENT_X_MARGIN, Vertical = 10 }, Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 20), + Spacing = new Vector2(0, 15), Children = new Drawable[] { + new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(20), + Children = new Drawable[] + { + detailGlobalRank = new ProfileValueDisplay(true) + { + Title = UsersStrings.ShowRankGlobalSimple, + }, + detailCountryRank = new ProfileValueDisplay(true) + { + Title = UsersStrings.ShowRankCountrySimple, + }, + } + }, + new Container + { + RelativeSizeAxes = Axes.X, + Height = 60, + Children = new Drawable[] + { + rankGraph = new RankGraph + { + RelativeSizeAxes = Axes.Both, + }, + } + }, new Container { RelativeSizeAxes = Axes.X, @@ -99,19 +101,17 @@ namespace osu.Game.Overlays.Profile.Header Spacing = new Vector2(10, 0), Children = new Drawable[] { - new OverlinedTotalPlayTime - { - User = { BindTarget = User } - }, - medalInfo = new OverlinedInfoContainer + medalInfo = new ProfileValueDisplay { Title = UsersStrings.ShowStatsMedals, - LineColour = colours.GreenLight, }, - ppInfo = new OverlinedInfoContainer + ppInfo = new ProfileValueDisplay { Title = "pp", - LineColour = colours.Red, + }, + new TotalPlayTime + { + User = { BindTarget = User } }, } }, @@ -133,48 +133,15 @@ namespace osu.Game.Overlays.Profile.Header } } }, - new Container - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Padding = new MarginPadding { Right = 130 }, - Children = new Drawable[] - { - rankGraph = new RankGraph - { - RelativeSizeAxes = Axes.Both, - }, - new FillFlowContainer - { - AutoSizeAxes = Axes.Y, - Width = 130, - Anchor = Anchor.TopRight, - Direction = FillDirection.Vertical, - Padding = new MarginPadding { Horizontal = 10 }, - Spacing = new Vector2(0, 20), - Children = new Drawable[] - { - detailGlobalRank = new OverlinedInfoContainer(true, 110) - { - Title = UsersStrings.ShowRankGlobalSimple, - LineColour = colourProvider.Highlight1, - }, - detailCountryRank = new OverlinedInfoContainer(false, 110) - { - Title = UsersStrings.ShowRankCountrySimple, - LineColour = colourProvider.Highlight1, - }, - } - } - } - }, } }, }; } - private void updateDisplay(APIUser user) + private void updateDisplay(UserProfileData? data) { + var user = data?.User; + medalInfo.Content = user?.Achievements?.Length.ToString() ?? "0"; ppInfo.Content = user?.Statistics?.PP?.ToLocalisableString("#,##0") ?? (LocalisableString)"0"; @@ -187,7 +154,7 @@ namespace osu.Game.Overlays.Profile.Header rankGraph.Statistics.Value = user?.Statistics; } - private class ScoreRankInfo : CompositeDrawable + private partial class ScoreRankInfo : CompositeDrawable { private readonly OsuSpriteText rankCount; @@ -202,14 +169,14 @@ namespace osu.Game.Overlays.Profile.Header InternalChild = new FillFlowContainer { AutoSizeAxes = Axes.Y, - Width = 56, + Width = 44, Direction = FillDirection.Vertical, Children = new Drawable[] { new DrawableRank(rank) { RelativeSizeAxes = Axes.X, - Height = 30, + Height = 22, }, rankCount = new OsuSpriteText { diff --git a/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs index deb675df1d..be160a6948 100644 --- a/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs @@ -1,12 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Threading; using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; @@ -14,22 +11,21 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.Profile.Header.Components; using osuTK; -using osuTK.Graphics; namespace osu.Game.Overlays.Profile.Header { - public class MedalHeaderContainer : CompositeDrawable + public partial class MedalHeaderContainer : CompositeDrawable { - private FillFlowContainer badgeFlowContainer; + private FillFlowContainer badgeFlowContainer = null!; - public readonly Bindable User = new Bindable(); + public readonly Bindable User = new Bindable(); [BackgroundDependencyLoader] private void load(OverlayColourProvider colourProvider) { Alpha = 0; AutoSizeAxes = Axes.Y; - User.ValueChanged += e => updateDisplay(e.NewValue); + User.ValueChanged += e => updateDisplay(e.NewValue?.User); InternalChildren = new Drawable[] { @@ -45,37 +41,30 @@ namespace osu.Game.Overlays.Profile.Header Child = new Box { RelativeSizeAxes = Axes.Both, - Colour = new ColourInfo - { - TopLeft = Color4.Black.Opacity(0.2f), - TopRight = Color4.Black.Opacity(0.2f), - BottomLeft = Color4.Black.Opacity(0), - BottomRight = Color4.Black.Opacity(0) - } - }, + Colour = ColourInfo.GradientVertical(Colour4.Black.Opacity(0.2f), Colour4.Black.Opacity(0)) + } }, badgeFlowContainer = new FillFlowContainer { Direction = FillDirection.Full, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Margin = new MarginPadding { Top = 5 }, Spacing = new Vector2(10, 10), - Padding = new MarginPadding { Horizontal = UserProfileOverlay.CONTENT_X_MARGIN, Vertical = 10 }, + Padding = new MarginPadding { Horizontal = UserProfileOverlay.CONTENT_X_MARGIN, Top = 10 }, } }; } - private CancellationTokenSource cancellationTokenSource; + private CancellationTokenSource? cancellationTokenSource; - private void updateDisplay(APIUser user) + private void updateDisplay(APIUser? user) { cancellationTokenSource?.Cancel(); cancellationTokenSource = new CancellationTokenSource(); badgeFlowContainer.Clear(); - var badges = user.Badges; + var badges = user?.Badges; if (badges?.Length > 0) { diff --git a/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs index 67a6df3228..e04a8ad9ad 100644 --- a/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions; @@ -17,7 +15,6 @@ using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Cursor; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; -using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.Profile.Header.Components; using osu.Game.Resources.Localisation.Web; using osu.Game.Users.Drawables; @@ -25,23 +22,24 @@ using osuTK; namespace osu.Game.Overlays.Profile.Header { - public class TopHeaderContainer : CompositeDrawable + public partial class TopHeaderContainer : CompositeDrawable { private const float avatar_size = 110; - public readonly Bindable User = new Bindable(); + public readonly Bindable User = new Bindable(); [Resolved] - private IAPIProvider api { get; set; } + private IAPIProvider api { get; set; } = null!; - private SupporterIcon supporterTag; - private UpdateableAvatar avatar; - private OsuSpriteText usernameText; - private ExternalLinkButton openUserExternally; - private OsuSpriteText titleText; - private UpdateableFlag userFlag; - private OsuSpriteText userCountryText; - private FillFlowContainer userStats; + private SupporterIcon supporterTag = null!; + private UpdateableAvatar avatar = null!; + private OsuSpriteText usernameText = null!; + private ExternalLinkButton openUserExternally = null!; + private OsuSpriteText titleText = null!; + private UpdateableFlag userFlag = null!; + private OsuSpriteText userCountryText = null!; + private FillFlowContainer userStats = null!; + private GroupBadgeFlow groupBadgeFlow = null!; [BackgroundDependencyLoader] private void load(OverlayColourProvider colourProvider) @@ -53,7 +51,7 @@ namespace osu.Game.Overlays.Profile.Header new Box { RelativeSizeAxes = Axes.Both, - Colour = colourProvider.Background5, + Colour = colourProvider.Background4, }, new FillFlowContainer { @@ -92,6 +90,7 @@ namespace osu.Game.Overlays.Profile.Header { AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, + Spacing = new Vector2(5), Children = new Drawable[] { usernameText = new OsuSpriteText @@ -100,10 +99,14 @@ namespace osu.Game.Overlays.Profile.Header }, openUserExternally = new ExternalLinkButton { - Margin = new MarginPadding { Left = 5 }, Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, }, + groupBadgeFlow = new GroupBadgeFlow + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + } } }, titleText = new OsuSpriteText @@ -176,8 +179,10 @@ namespace osu.Game.Overlays.Profile.Header User.BindValueChanged(user => updateUser(user.NewValue)); } - private void updateUser(APIUser user) + private void updateUser(UserProfileData? data) { + var user = data?.User; + avatar.User = user; usernameText.Text = user?.Username ?? string.Empty; openUserExternally.Link = $@"{api.WebsiteRootUrl}/users/{user?.Id ?? 0}"; @@ -186,6 +191,7 @@ namespace osu.Game.Overlays.Profile.Header supporterTag.SupportLevel = user?.SupportLevel ?? 0; titleText.Text = user?.Title ?? string.Empty; titleText.Colour = Color4Extensions.FromHex(user?.Colour ?? "fff"); + groupBadgeFlow.User.Value = user; userStats.Clear(); @@ -201,7 +207,7 @@ namespace osu.Game.Overlays.Profile.Header } } - private class UserStatsLine : Container + private partial class UserStatsLine : Container { public UserStatsLine(LocalisableString left, LocalisableString right) { diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 1eca6a81cf..c559a1c102 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Diagnostics; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; @@ -11,18 +9,18 @@ using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Localisation; -using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.Profile.Header; +using osu.Game.Overlays.Profile.Header.Components; using osu.Game.Resources.Localisation.Web; using osu.Game.Users; namespace osu.Game.Overlays.Profile { - public class ProfileHeader : TabControlOverlayHeader + public partial class ProfileHeader : TabControlOverlayHeader { - private UserCoverBackground coverContainer; + private UserCoverBackground coverContainer = null!; - public Bindable User = new Bindable(); + public Bindable User = new Bindable(); private CentreHeaderContainer centreHeaderContainer; private DetailHeaderContainer detailHeaderContainer; @@ -41,8 +39,6 @@ namespace osu.Game.Overlays.Profile // Haphazardly guaranteed by OverlayHeader constructor (see CreateBackground / CreateContent). Debug.Assert(centreHeaderContainer != null); Debug.Assert(detailHeaderContainer != null); - - centreHeaderContainer.DetailsVisible.BindValueChanged(visible => detailHeaderContainer.Expanded = visible.NewValue, true); } protected override Drawable CreateBackground() => @@ -77,7 +73,7 @@ namespace osu.Game.Overlays.Profile RelativeSizeAxes = Axes.X, User = { BindTarget = User }, }, - centreHeaderContainer = new CentreHeaderContainer + new MedalHeaderContainer { RelativeSizeAxes = Axes.X, User = { BindTarget = User }, @@ -87,7 +83,7 @@ namespace osu.Game.Overlays.Profile RelativeSizeAxes = Axes.X, User = { BindTarget = User }, }, - new MedalHeaderContainer + centreHeaderContainer = new CentreHeaderContainer { RelativeSizeAxes = Axes.X, User = { BindTarget = User }, @@ -102,9 +98,14 @@ namespace osu.Game.Overlays.Profile protected override OverlayTitle CreateTitle() => new ProfileHeaderTitle(); - private void updateDisplay(APIUser user) => coverContainer.User = user; + protected override Drawable CreateTabControlContent() => new ProfileRulesetSelector + { + User = { BindTarget = User } + }; - private class ProfileHeaderTitle : OverlayTitle + private void updateDisplay(UserProfileData? user) => coverContainer.User = user?.User; + + private partial class ProfileHeaderTitle : OverlayTitle { public ProfileHeaderTitle() { @@ -113,7 +114,7 @@ namespace osu.Game.Overlays.Profile } } - private class ProfileCoverBackground : UserCoverBackground + private partial class ProfileCoverBackground : UserCoverBackground { protected override double LoadDelay => 0; } diff --git a/osu.Game/Overlays/Profile/ProfileSection.cs b/osu.Game/Overlays/Profile/ProfileSection.cs index 67738943e8..03917b75a4 100644 --- a/osu.Game/Overlays/Profile/ProfileSection.cs +++ b/osu.Game/Overlays/Profile/ProfileSection.cs @@ -1,25 +1,21 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; -using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Localisation; using osu.Game.Graphics; -using osu.Game.Graphics.Backgrounds; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; -using osu.Game.Online.API.Requests.Responses; +using osuTK; namespace osu.Game.Overlays.Profile { - public abstract class ProfileSection : Container + public abstract partial class ProfileSection : Container { public abstract LocalisableString Title { get; } @@ -31,24 +27,31 @@ namespace osu.Game.Overlays.Profile protected override Container Content => content; - public readonly Bindable User = new Bindable(); + public readonly Bindable User = new Bindable(); + + private const float outer_gutter_width = 10; protected ProfileSection() { AutoSizeAxes = Axes.Y; RelativeSizeAxes = Axes.X; + Masking = true; + CornerRadius = 10; + EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Shadow, + Offset = new Vector2(0, 1), + Radius = 3, + Colour = Colour4.Black.Opacity(0.25f) + }; + InternalChildren = new Drawable[] { background = new Box { RelativeSizeAxes = Axes.Both, }, - new SectionTriangles - { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - }, new FillFlowContainer { Direction = FillDirection.Vertical, @@ -61,8 +64,8 @@ namespace osu.Game.Overlays.Profile AutoSizeAxes = Axes.Both, Margin = new MarginPadding { - Horizontal = UserProfileOverlay.CONTENT_X_MARGIN, - Top = 15, + Horizontal = UserProfileOverlay.CONTENT_X_MARGIN - outer_gutter_width, + Top = 20, Bottom = 20, }, Children = new Drawable[] @@ -70,7 +73,7 @@ namespace osu.Game.Overlays.Profile new OsuSpriteText { Text = Title, - Font = OsuFont.GetFont(size: 20, weight: FontWeight.Bold), + Font = OsuFont.GetFont(size: 16, weight: FontWeight.Bold), }, underscore = new Box { @@ -91,7 +94,7 @@ namespace osu.Game.Overlays.Profile RelativeSizeAxes = Axes.X, Padding = new MarginPadding { - Horizontal = UserProfileOverlay.CONTENT_X_MARGIN, + Horizontal = UserProfileOverlay.CONTENT_X_MARGIN - outer_gutter_width, Bottom = 20 } }, @@ -103,43 +106,8 @@ namespace osu.Game.Overlays.Profile [BackgroundDependencyLoader] private void load(OverlayColourProvider colourProvider) { - background.Colour = colourProvider.Background5; + background.Colour = colourProvider.Background4; underscore.Colour = colourProvider.Highlight1; } - - private class SectionTriangles : Container - { - private readonly Triangles triangles; - private readonly Box foreground; - - public SectionTriangles() - { - RelativeSizeAxes = Axes.X; - Height = 100; - Masking = true; - Children = new Drawable[] - { - triangles = new Triangles - { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - RelativeSizeAxes = Axes.Both, - TriangleScale = 3, - }, - foreground = new Box - { - RelativeSizeAxes = Axes.Both, - } - }; - } - - [BackgroundDependencyLoader] - private void load(OverlayColourProvider colourProvider) - { - triangles.ColourLight = colourProvider.Background4; - triangles.ColourDark = colourProvider.Background5.Darken(0.2f); - foreground.Colour = ColourInfo.GradientVertical(colourProvider.Background5, colourProvider.Background5.Opacity(0)); - } - } } } diff --git a/osu.Game/Overlays/Profile/Sections/AboutSection.cs b/osu.Game/Overlays/Profile/Sections/AboutSection.cs index 2b6ce732a2..69a8b23412 100644 --- a/osu.Game/Overlays/Profile/Sections/AboutSection.cs +++ b/osu.Game/Overlays/Profile/Sections/AboutSection.cs @@ -1,14 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Profile.Sections { - public class AboutSection : ProfileSection + public partial class AboutSection : ProfileSection { public override LocalisableString Title => UsersStrings.ShowExtraMeTitle; diff --git a/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs b/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs index 5d36537c3e..499c572eac 100644 --- a/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -14,7 +12,7 @@ namespace osu.Game.Overlays.Profile.Sections /// /// Display artist/title/mapper information, commonly used as the left portion of a profile or score display row. /// - public abstract class BeatmapMetadataContainer : OsuHoverContainer + public abstract partial class BeatmapMetadataContainer : OsuHoverContainer { private readonly IBeatmapInfo beatmapInfo; @@ -25,8 +23,8 @@ namespace osu.Game.Overlays.Profile.Sections AutoSizeAxes = Axes.Both; } - [BackgroundDependencyLoader(true)] - private void load(BeatmapSetOverlay beatmapSetOverlay) + [BackgroundDependencyLoader] + private void load(BeatmapSetOverlay? beatmapSetOverlay) { Action = () => { diff --git a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs index aaaed5ad0a..b237a0ee05 100644 --- a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -17,14 +15,14 @@ using APIUser = osu.Game.Online.API.Requests.Responses.APIUser; namespace osu.Game.Overlays.Profile.Sections.Beatmaps { - public class PaginatedBeatmapContainer : PaginatedProfileSubsection + public partial class PaginatedBeatmapContainer : PaginatedProfileSubsection { private const float panel_padding = 10f; private readonly BeatmapSetType type; protected override int InitialItemsCount => type == BeatmapSetType.Graveyard ? 2 : 6; - public PaginatedBeatmapContainer(BeatmapSetType type, Bindable user, LocalisableString headerText) + public PaginatedBeatmapContainer(BeatmapSetType type, Bindable user, LocalisableString headerText) : base(user, headerText) { this.type = type; @@ -58,15 +56,18 @@ namespace osu.Game.Overlays.Profile.Sections.Beatmaps case BeatmapSetType.Guest: return user.GuestBeatmapsetCount; + case BeatmapSetType.Nominated: + return user.NominatedBeatmapsetCount; + default: return 0; } } - protected override APIRequest> CreateRequest(PaginationParameters pagination) => - new GetUserBeatmapsRequest(User.Value.Id, type, pagination); + protected override APIRequest> CreateRequest(UserProfileData user, PaginationParameters pagination) => + new GetUserBeatmapsRequest(user.User.Id, type, pagination); - protected override Drawable CreateDrawableItem(APIBeatmapSet model) => model.OnlineID > 0 + protected override Drawable? CreateDrawableItem(APIBeatmapSet model) => model.OnlineID > 0 ? new BeatmapCardNormal(model) { Anchor = Anchor.TopCentre, diff --git a/osu.Game/Overlays/Profile/Sections/BeatmapsSection.cs b/osu.Game/Overlays/Profile/Sections/BeatmapsSection.cs index e3cff5da05..3b304a79ef 100644 --- a/osu.Game/Overlays/Profile/Sections/BeatmapsSection.cs +++ b/osu.Game/Overlays/Profile/Sections/BeatmapsSection.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Localisation; using osu.Game.Online.API.Requests; using osu.Game.Overlays.Profile.Sections.Beatmaps; @@ -10,7 +8,7 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Profile.Sections { - public class BeatmapsSection : ProfileSection + public partial class BeatmapsSection : ProfileSection { public override LocalisableString Title => UsersStrings.ShowExtraBeatmapsTitle; @@ -25,7 +23,8 @@ namespace osu.Game.Overlays.Profile.Sections new PaginatedBeatmapContainer(BeatmapSetType.Loved, User, UsersStrings.ShowExtraBeatmapsLovedTitle), new PaginatedBeatmapContainer(BeatmapSetType.Guest, User, UsersStrings.ShowExtraBeatmapsGuestTitle), new PaginatedBeatmapContainer(BeatmapSetType.Pending, User, UsersStrings.ShowExtraBeatmapsPendingTitle), - new PaginatedBeatmapContainer(BeatmapSetType.Graveyard, User, UsersStrings.ShowExtraBeatmapsGraveyardTitle) + new PaginatedBeatmapContainer(BeatmapSetType.Graveyard, User, UsersStrings.ShowExtraBeatmapsGraveyardTitle), + new PaginatedBeatmapContainer(BeatmapSetType.Nominated, User, UsersStrings.ShowExtraBeatmapsNominatedTitle), }; } } diff --git a/osu.Game/Overlays/Profile/Sections/CounterPill.cs b/osu.Game/Overlays/Profile/Sections/CounterPill.cs index e9b55f62ef..74cd4b218b 100644 --- a/osu.Game/Overlays/Profile/Sections/CounterPill.cs +++ b/osu.Game/Overlays/Profile/Sections/CounterPill.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; @@ -14,11 +12,11 @@ using osu.Framework.Extensions.LocalisationExtensions; namespace osu.Game.Overlays.Profile.Sections { - public class CounterPill : CircularContainer + public partial class CounterPill : CircularContainer { public readonly BindableInt Current = new BindableInt(); - private OsuSpriteText counter; + private OsuSpriteText counter = null!; [BackgroundDependencyLoader] private void load(OverlayColourProvider colourProvider) diff --git a/osu.Game/Overlays/Profile/Sections/Historical/ChartProfileSubsection.cs b/osu.Game/Overlays/Profile/Sections/Historical/ChartProfileSubsection.cs index f0819c4474..583006031c 100644 --- a/osu.Game/Overlays/Profile/Sections/Historical/ChartProfileSubsection.cs +++ b/osu.Game/Overlays/Profile/Sections/Historical/ChartProfileSubsection.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Collections.Generic; using System.Linq; using osu.Framework.Bindables; @@ -13,16 +11,16 @@ using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Overlays.Profile.Sections.Historical { - public abstract class ChartProfileSubsection : ProfileSubsection + public abstract partial class ChartProfileSubsection : ProfileSubsection { - private ProfileLineChart chart; + private ProfileLineChart chart = null!; /// /// Text describing the value being plotted on the graph, which will be displayed as a prefix to the value in the history graph tooltip. /// protected abstract LocalisableString GraphCounterName { get; } - protected ChartProfileSubsection(Bindable user, LocalisableString headerText) + protected ChartProfileSubsection(Bindable user, LocalisableString headerText) : base(user, headerText) { } @@ -46,9 +44,9 @@ namespace osu.Game.Overlays.Profile.Sections.Historical User.BindValueChanged(onUserChanged, true); } - private void onUserChanged(ValueChangedEvent e) + private void onUserChanged(ValueChangedEvent e) { - var values = GetValues(e.NewValue); + var values = GetValues(e.NewValue?.User); if (values == null || values.Length <= 1) { @@ -86,6 +84,6 @@ namespace osu.Game.Overlays.Profile.Sections.Historical return filledHistoryEntries.ToArray(); } - protected abstract APIUserHistoryCount[] GetValues(APIUser user); + protected abstract APIUserHistoryCount[]? GetValues(APIUser? user); } } diff --git a/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedBeatmap.cs b/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedBeatmap.cs index 70ab95b848..8a05341783 100644 --- a/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedBeatmap.cs +++ b/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedBeatmap.cs @@ -1,9 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - -using System.Diagnostics; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -21,7 +18,7 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Profile.Sections.Historical { - public class DrawableMostPlayedBeatmap : CompositeDrawable + public partial class DrawableMostPlayedBeatmap : CompositeDrawable { private const int cover_width = 100; private const int corner_radius = 6; @@ -110,17 +107,17 @@ namespace osu.Game.Overlays.Profile.Sections.Historical }); } - private class MostPlayedBeatmapContainer : ProfileItemContainer + private partial class MostPlayedBeatmapContainer : ProfileItemContainer { [BackgroundDependencyLoader] private void load(OverlayColourProvider colourProvider) { - IdleColour = colourProvider.Background4; - HoverColour = colourProvider.Background3; + IdleColour = colourProvider.Background3; + HoverColour = colourProvider.Background2; } } - private class MostPlayedBeatmapMetadataContainer : BeatmapMetadataContainer + private partial class MostPlayedBeatmapMetadataContainer : BeatmapMetadataContainer { public MostPlayedBeatmapMetadataContainer(IBeatmapInfo beatmapInfo) : base(beatmapInfo) @@ -131,8 +128,6 @@ namespace osu.Game.Overlays.Profile.Sections.Historical { var metadata = beatmapInfo.Metadata; - Debug.Assert(metadata != null); - return new Drawable[] { new OsuSpriteText @@ -159,7 +154,7 @@ namespace osu.Game.Overlays.Profile.Sections.Historical } } - private class PlayCountText : CompositeDrawable, IHasTooltip + private partial class PlayCountText : CompositeDrawable, IHasTooltip { public LocalisableString TooltipText => UsersStrings.ShowExtraHistoricalMostPlayedCount; diff --git a/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs index 34c9892f06..9708062202 100644 --- a/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -16,9 +14,9 @@ using APIUser = osu.Game.Online.API.Requests.Responses.APIUser; namespace osu.Game.Overlays.Profile.Sections.Historical { - public class PaginatedMostPlayedBeatmapContainer : PaginatedProfileSubsection + public partial class PaginatedMostPlayedBeatmapContainer : PaginatedProfileSubsection { - public PaginatedMostPlayedBeatmapContainer(Bindable user) + public PaginatedMostPlayedBeatmapContainer(Bindable user) : base(user, UsersStrings.ShowExtraHistoricalMostPlayedTitle) { } @@ -31,8 +29,8 @@ namespace osu.Game.Overlays.Profile.Sections.Historical protected override int GetCount(APIUser user) => user.BeatmapPlayCountsCount; - protected override APIRequest> CreateRequest(PaginationParameters pagination) => - new GetUserMostPlayedBeatmapsRequest(User.Value.Id, pagination); + protected override APIRequest> CreateRequest(UserProfileData user, PaginationParameters pagination) => + new GetUserMostPlayedBeatmapsRequest(user.User.Id, pagination); protected override Drawable CreateDrawableItem(APIUserMostPlayedBeatmap mostPlayed) => new DrawableMostPlayedBeatmap(mostPlayed); diff --git a/osu.Game/Overlays/Profile/Sections/Historical/PlayHistorySubsection.cs b/osu.Game/Overlays/Profile/Sections/Historical/PlayHistorySubsection.cs index 73e39a2440..f472ded182 100644 --- a/osu.Game/Overlays/Profile/Sections/Historical/PlayHistorySubsection.cs +++ b/osu.Game/Overlays/Profile/Sections/Historical/PlayHistorySubsection.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Bindables; using osu.Framework.Localisation; using osu.Game.Online.API.Requests.Responses; @@ -10,15 +8,15 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Profile.Sections.Historical { - public class PlayHistorySubsection : ChartProfileSubsection + public partial class PlayHistorySubsection : ChartProfileSubsection { protected override LocalisableString GraphCounterName => UsersStrings.ShowExtraHistoricalMonthlyPlaycountsCountLabel; - public PlayHistorySubsection(Bindable user) + public PlayHistorySubsection(Bindable user) : base(user, UsersStrings.ShowExtraHistoricalMonthlyPlaycountsTitle) { } - protected override APIUserHistoryCount[] GetValues(APIUser user) => user?.MonthlyPlayCounts; + protected override APIUserHistoryCount[]? GetValues(APIUser? user) => user?.MonthlyPlayCounts; } } diff --git a/osu.Game/Overlays/Profile/Sections/Historical/ProfileLineChart.cs b/osu.Game/Overlays/Profile/Sections/Historical/ProfileLineChart.cs index 78a28a39d2..5711bfc046 100644 --- a/osu.Game/Overlays/Profile/Sections/Historical/ProfileLineChart.cs +++ b/osu.Game/Overlays/Profile/Sections/Historical/ProfileLineChart.cs @@ -1,11 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; -using JetBrains.Annotations; using System; using System.Linq; using osu.Game.Graphics.Sprites; @@ -20,11 +17,10 @@ using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Overlays.Profile.Sections.Historical { - public class ProfileLineChart : CompositeDrawable + public partial class ProfileLineChart : CompositeDrawable { - private APIUserHistoryCount[] values; + private APIUserHistoryCount[] values = Array.Empty(); - [NotNull] public APIUserHistoryCount[] Values { get => values; @@ -242,7 +238,7 @@ namespace osu.Game.Overlays.Profile.Sections.Historical return Math.Max((long)(tickMultiplier * tickBase), 1); } - private class TickText : OsuSpriteText + private partial class TickText : OsuSpriteText { [BackgroundDependencyLoader] private void load(OverlayColourProvider colourProvider) @@ -251,7 +247,7 @@ namespace osu.Game.Overlays.Profile.Sections.Historical } } - private class TickLine : Box + private partial class TickLine : Box { [BackgroundDependencyLoader] private void load(OverlayColourProvider colourProvider) diff --git a/osu.Game/Overlays/Profile/Sections/Historical/ReplaysSubsection.cs b/osu.Game/Overlays/Profile/Sections/Historical/ReplaysSubsection.cs index 89e8f51338..225eaa8c7e 100644 --- a/osu.Game/Overlays/Profile/Sections/Historical/ReplaysSubsection.cs +++ b/osu.Game/Overlays/Profile/Sections/Historical/ReplaysSubsection.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Bindables; using osu.Framework.Localisation; using osu.Game.Online.API.Requests.Responses; @@ -10,15 +8,15 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Profile.Sections.Historical { - public class ReplaysSubsection : ChartProfileSubsection + public partial class ReplaysSubsection : ChartProfileSubsection { protected override LocalisableString GraphCounterName => UsersStrings.ShowExtraHistoricalReplaysWatchedCountsCountLabel; - public ReplaysSubsection(Bindable user) + public ReplaysSubsection(Bindable user) : base(user, UsersStrings.ShowExtraHistoricalReplaysWatchedCountsTitle) { } - protected override APIUserHistoryCount[] GetValues(APIUser user) => user?.ReplaysWatchedCounts; + protected override APIUserHistoryCount[]? GetValues(APIUser? user) => user?.ReplaysWatchedCounts; } } diff --git a/osu.Game/Overlays/Profile/Sections/Historical/UserHistoryGraph.cs b/osu.Game/Overlays/Profile/Sections/Historical/UserHistoryGraph.cs index 48d75a4953..310607e757 100644 --- a/osu.Game/Overlays/Profile/Sections/Historical/UserHistoryGraph.cs +++ b/osu.Game/Overlays/Profile/Sections/Historical/UserHistoryGraph.cs @@ -1,24 +1,20 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; -using JetBrains.Annotations; using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Localisation; using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Overlays.Profile.Sections.Historical { - public class UserHistoryGraph : UserGraph + public partial class UserHistoryGraph : UserGraph { private readonly LocalisableString tooltipCounterName; - [CanBeNull] - public APIUserHistoryCount[] Values + public APIUserHistoryCount[]? Values { set => Data = value?.Select(v => new KeyValuePair(v.Date, v.Count)).ToArray(); } diff --git a/osu.Game/Overlays/Profile/Sections/HistoricalSection.cs b/osu.Game/Overlays/Profile/Sections/HistoricalSection.cs index f1e1c44734..19f7a32d4d 100644 --- a/osu.Game/Overlays/Profile/Sections/HistoricalSection.cs +++ b/osu.Game/Overlays/Profile/Sections/HistoricalSection.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Online.API.Requests; @@ -12,7 +10,7 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Profile.Sections { - public class HistoricalSection : ProfileSection + public partial class HistoricalSection : ProfileSection { public override LocalisableString Title => UsersStrings.ShowExtraHistoricalTitle; diff --git a/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs b/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs index 44f1af4b72..161d5b6f64 100644 --- a/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs +++ b/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -15,13 +13,10 @@ using osuTK; namespace osu.Game.Overlays.Profile.Sections.Kudosu { - public class DrawableKudosuHistoryItem : CompositeDrawable + public partial class DrawableKudosuHistoryItem : CompositeDrawable { private const int height = 25; - [Resolved] - private OsuColour colours { get; set; } - private readonly APIKudosuHistory historyItem; private readonly LinkFlowContainer linkFlowContainer; private readonly DrawableDate date; @@ -50,9 +45,9 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu } [BackgroundDependencyLoader] - private void load() + private void load(OverlayColourProvider colourProvider) { - date.Colour = colours.GreySeaFoamLighter; + date.Colour = colourProvider.Foreground1; var formattedSource = MessageFormatter.FormatText(getString(historyItem)); linkFlowContainer.AddLinks(formattedSource.Text, formattedSource.Links); } diff --git a/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs b/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs index bb9d48c473..d2f01ef9f7 100644 --- a/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs +++ b/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Bindables; using osuTK; using osu.Framework.Graphics; @@ -16,15 +14,15 @@ using osu.Framework.Allocation; using osu.Framework.Extensions.LocalisationExtensions; using osu.Game.Resources.Localisation.Web; using osu.Framework.Localisation; -using osu.Game.Online.API.Requests.Responses; +using osu.Game.Online.Chat; namespace osu.Game.Overlays.Profile.Sections.Kudosu { - public class KudosuInfo : Container + public partial class KudosuInfo : Container { - private readonly Bindable user = new Bindable(); + private readonly Bindable user = new Bindable(); - public KudosuInfo(Bindable user) + public KudosuInfo(Bindable user) { this.user.BindTo(user); CountSection total; @@ -34,23 +32,23 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu CornerRadius = 3; Child = total = new CountTotal(); - this.user.ValueChanged += u => total.Count = u.NewValue?.Kudosu.Total ?? 0; + this.user.ValueChanged += u => total.Count = u.NewValue?.User.Kudosu.Total ?? 0; } protected override bool OnClick(ClickEvent e) => true; - private class CountTotal : CountSection + private partial class CountTotal : CountSection { public CountTotal() : base(UsersStrings.ShowExtraKudosuTotal) { DescriptionText.AddText("Based on how much of a contribution the user has made to beatmap moderation. See "); - DescriptionText.AddLink("this page", "https://osu.ppy.sh/wiki/Kudosu"); + DescriptionText.AddLink("this page", LinkAction.OpenWiki, @"Modding/Kudosu"); DescriptionText.AddText(" for more information."); } } - private class CountSection : Container + private partial class CountSection : Container { private readonly OsuSpriteText valueText; protected readonly LinkFlowContainer DescriptionText; diff --git a/osu.Game/Overlays/Profile/Sections/Kudosu/PaginatedKudosuHistoryContainer.cs b/osu.Game/Overlays/Profile/Sections/Kudosu/PaginatedKudosuHistoryContainer.cs index 34e6866d25..79d31c6ed1 100644 --- a/osu.Game/Overlays/Profile/Sections/Kudosu/PaginatedKudosuHistoryContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Kudosu/PaginatedKudosuHistoryContainer.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Graphics; using osu.Game.Online.API.Requests; using osu.Framework.Bindables; @@ -10,19 +8,18 @@ using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.API; using System.Collections.Generic; using osu.Game.Resources.Localisation.Web; -using APIUser = osu.Game.Online.API.Requests.Responses.APIUser; namespace osu.Game.Overlays.Profile.Sections.Kudosu { - public class PaginatedKudosuHistoryContainer : PaginatedProfileSubsection + public partial class PaginatedKudosuHistoryContainer : PaginatedProfileSubsection { - public PaginatedKudosuHistoryContainer(Bindable user) + public PaginatedKudosuHistoryContainer(Bindable user) : base(user, missingText: UsersStrings.ShowExtraKudosuEntryEmpty) { } - protected override APIRequest> CreateRequest(PaginationParameters pagination) - => new GetUserKudosuHistoryRequest(User.Value.Id, pagination); + protected override APIRequest> CreateRequest(UserProfileData user, PaginationParameters pagination) + => new GetUserKudosuHistoryRequest(user.User.Id, pagination); protected override Drawable CreateDrawableItem(APIKudosuHistory item) => new DrawableKudosuHistoryItem(item); } diff --git a/osu.Game/Overlays/Profile/Sections/KudosuSection.cs b/osu.Game/Overlays/Profile/Sections/KudosuSection.cs index 517b4d92cf..482a853c44 100644 --- a/osu.Game/Overlays/Profile/Sections/KudosuSection.cs +++ b/osu.Game/Overlays/Profile/Sections/KudosuSection.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Graphics; using osu.Game.Overlays.Profile.Sections.Kudosu; using osu.Framework.Localisation; @@ -10,7 +8,7 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Profile.Sections { - public class KudosuSection : ProfileSection + public partial class KudosuSection : ProfileSection { public override LocalisableString Title => UsersStrings.ShowExtraKudosuTitle; diff --git a/osu.Game/Overlays/Profile/Sections/MedalsSection.cs b/osu.Game/Overlays/Profile/Sections/MedalsSection.cs index a458bc4873..42f241d662 100644 --- a/osu.Game/Overlays/Profile/Sections/MedalsSection.cs +++ b/osu.Game/Overlays/Profile/Sections/MedalsSection.cs @@ -1,14 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Profile.Sections { - public class MedalsSection : ProfileSection + public partial class MedalsSection : ProfileSection { public override LocalisableString Title => UsersStrings.ShowExtraMedalsTitle; diff --git a/osu.Game/Overlays/Profile/Sections/PaginatedProfileSubsection.cs b/osu.Game/Overlays/Profile/Sections/PaginatedProfileSubsection.cs index 8ed1dc3676..1c94048758 100644 --- a/osu.Game/Overlays/Profile/Sections/PaginatedProfileSubsection.cs +++ b/osu.Game/Overlays/Profile/Sections/PaginatedProfileSubsection.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Collections.Generic; using System.Linq; using System.Threading; @@ -22,7 +20,7 @@ using osuTK; namespace osu.Game.Overlays.Profile.Sections { - public abstract class PaginatedProfileSubsection : ProfileSubsection + public abstract partial class PaginatedProfileSubsection : ProfileSubsection { /// /// The number of items displayed per page. @@ -35,20 +33,20 @@ namespace osu.Game.Overlays.Profile.Sections protected virtual int InitialItemsCount => 5; [Resolved] - private IAPIProvider api { get; set; } + private IAPIProvider api { get; set; } = null!; protected PaginationParameters? CurrentPage { get; private set; } - protected ReverseChildIDFillFlowContainer ItemsContainer { get; private set; } + protected ReverseChildIDFillFlowContainer ItemsContainer { get; private set; } = null!; - private APIRequest> retrievalRequest; - private CancellationTokenSource loadCancellation; + private APIRequest>? retrievalRequest; + private CancellationTokenSource? loadCancellation; - private ShowMoreButton moreButton; - private OsuSpriteText missing; + private ShowMoreButton moreButton = null!; + private OsuSpriteText missing = null!; private readonly LocalisableString? missingText; - protected PaginatedProfileSubsection(Bindable user, LocalisableString? headerText = null, LocalisableString? missingText = null) + protected PaginatedProfileSubsection(Bindable user, LocalisableString? headerText = null, LocalisableString? missingText = null) : base(user, headerText, CounterVisibilityState.AlwaysVisible) { this.missingText = missingText; @@ -94,7 +92,7 @@ namespace osu.Game.Overlays.Profile.Sections User.BindValueChanged(onUserChanged, true); } - private void onUserChanged(ValueChangedEvent e) + private void onUserChanged(ValueChangedEvent e) { loadCancellation?.Cancel(); retrievalRequest?.Cancel(); @@ -102,26 +100,29 @@ namespace osu.Game.Overlays.Profile.Sections CurrentPage = null; ItemsContainer.Clear(); - if (e.NewValue != null) + if (e.NewValue?.User != null) { showMore(); - SetCount(GetCount(e.NewValue)); + SetCount(GetCount(e.NewValue.User)); } } private void showMore() { + if (User.Value == null) + return; + loadCancellation = new CancellationTokenSource(); CurrentPage = CurrentPage?.TakeNext(ItemsPerPage) ?? new PaginationParameters(InitialItemsCount); - retrievalRequest = CreateRequest(CurrentPage.Value); - retrievalRequest.Success += UpdateItems; + retrievalRequest = CreateRequest(User.Value, CurrentPage.Value); + retrievalRequest.Success += items => UpdateItems(items, loadCancellation); api.Queue(retrievalRequest); } - protected virtual void UpdateItems(List items) => Schedule(() => + protected virtual void UpdateItems(List items, CancellationTokenSource cancellationTokenSource) => Schedule(() => { OnItemsReceived(items); @@ -136,7 +137,7 @@ namespace osu.Game.Overlays.Profile.Sections return; } - LoadComponentsAsync(items.Select(CreateDrawableItem).Where(d => d != null), drawables => + LoadComponentsAsync(items.Select(CreateDrawableItem).Where(d => d != null).Cast(), drawables => { missing.Hide(); @@ -144,7 +145,7 @@ namespace osu.Game.Overlays.Profile.Sections moreButton.IsLoading = false; ItemsContainer.AddRange(drawables); - }, loadCancellation.Token); + }, cancellationTokenSource.Token); }); protected virtual int GetCount(APIUser user) => 0; @@ -153,9 +154,9 @@ namespace osu.Game.Overlays.Profile.Sections { } - protected abstract APIRequest> CreateRequest(PaginationParameters pagination); + protected abstract APIRequest> CreateRequest(UserProfileData user, PaginationParameters pagination); - protected abstract Drawable CreateDrawableItem(TModel model); + protected abstract Drawable? CreateDrawableItem(TModel model); protected override void Dispose(bool isDisposing) { diff --git a/osu.Game/Overlays/Profile/Sections/ProfileItemContainer.cs b/osu.Game/Overlays/Profile/Sections/ProfileItemContainer.cs index 392e35ac05..5e1b650bd3 100644 --- a/osu.Game/Overlays/Profile/Sections/ProfileItemContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/ProfileItemContainer.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -12,7 +10,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Profile.Sections { - public class ProfileItemContainer : Container + public partial class ProfileItemContainer : Container { private const int hover_duration = 200; @@ -67,8 +65,8 @@ namespace osu.Game.Overlays.Profile.Sections [BackgroundDependencyLoader] private void load(OverlayColourProvider colourProvider) { - IdleColour = colourProvider.Background3; - HoverColour = colourProvider.Background2; + IdleColour = colourProvider.Background2; + HoverColour = colourProvider.Background1; } protected override bool OnHover(HoverEvent e) diff --git a/osu.Game/Overlays/Profile/Sections/ProfileSubsection.cs b/osu.Game/Overlays/Profile/Sections/ProfileSubsection.cs index 8e43519a17..35d3ac1579 100644 --- a/osu.Game/Overlays/Profile/Sections/ProfileSubsection.cs +++ b/osu.Game/Overlays/Profile/Sections/ProfileSubsection.cs @@ -1,28 +1,24 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using JetBrains.Annotations; using osu.Framework.Localisation; -using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Overlays.Profile.Sections { - public abstract class ProfileSubsection : FillFlowContainer + public abstract partial class ProfileSubsection : FillFlowContainer { - protected readonly Bindable User = new Bindable(); + protected readonly Bindable User = new Bindable(); private readonly LocalisableString headerText; private readonly CounterVisibilityState counterVisibilityState; - private ProfileSubsectionHeader header; + private ProfileSubsectionHeader header = null!; - protected ProfileSubsection(Bindable user, LocalisableString? headerText = null, CounterVisibilityState counterVisibilityState = CounterVisibilityState.AlwaysHidden) + protected ProfileSubsection(Bindable user, LocalisableString? headerText = null, CounterVisibilityState counterVisibilityState = CounterVisibilityState.AlwaysHidden) { this.headerText = headerText ?? string.Empty; this.counterVisibilityState = counterVisibilityState; @@ -46,7 +42,6 @@ namespace osu.Game.Overlays.Profile.Sections }; } - [NotNull] protected abstract Drawable CreateContent(); protected void SetCount(int value) => header.Current.Value = value; diff --git a/osu.Game/Overlays/Profile/Sections/ProfileSubsectionHeader.cs b/osu.Game/Overlays/Profile/Sections/ProfileSubsectionHeader.cs index f2770d81cd..fa21535d02 100644 --- a/osu.Game/Overlays/Profile/Sections/ProfileSubsectionHeader.cs +++ b/osu.Game/Overlays/Profile/Sections/ProfileSubsectionHeader.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; @@ -17,7 +15,7 @@ using osu.Framework.Localisation; namespace osu.Game.Overlays.Profile.Sections { - public class ProfileSubsectionHeader : CompositeDrawable, IHasCurrentValue + public partial class ProfileSubsectionHeader : CompositeDrawable, IHasCurrentValue { private readonly BindableWithCurrent current = new BindableWithCurrent(); @@ -30,7 +28,7 @@ namespace osu.Game.Overlays.Profile.Sections private readonly LocalisableString text; private readonly CounterVisibilityState counterState; - private CounterPill counterPill; + private CounterPill counterPill = null!; public ProfileSubsectionHeader(LocalisableString text, CounterVisibilityState counterState) { diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs index fda2db7acc..529e78a7cf 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs @@ -1,13 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; -using System.Diagnostics; using System.Linq; -using JetBrains.Annotations; using osu.Framework.Allocation; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -25,7 +22,7 @@ using osuTK; namespace osu.Game.Overlays.Profile.Sections.Ranks { - public class DrawableProfileScore : CompositeDrawable + public partial class DrawableProfileScore : CompositeDrawable { private const int height = 40; private const int performance_width = 100; @@ -35,10 +32,10 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks protected readonly SoloScoreInfo Score; [Resolved] - private OsuColour colours { get; set; } + private OsuColour colours { get; set; } = null!; [Resolved] - private OverlayColourProvider colourProvider { get; set; } + private OverlayColourProvider colourProvider { get; set; } = null!; public DrawableProfileScore(SoloScoreInfo score) { @@ -85,7 +82,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks Spacing = new Vector2(0, 2), Children = new Drawable[] { - new ScoreBeatmapMetadataContainer(Score.Beatmap), + new ScoreBeatmapMetadataContainer(Score.Beatmap.AsNonNull()), new FillFlowContainer { AutoSizeAxes = Axes.Both, @@ -95,7 +92,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks { new OsuSpriteText { - Text = $"{Score.Beatmap?.DifficultyName}", + Text = $"{Score.Beatmap.AsNonNull().DifficultyName}", Font = OsuFont.GetFont(size: 12, weight: FontWeight.Regular), Colour = colours.Yellow }, @@ -163,7 +160,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks Origin = Anchor.TopRight, RelativeSizeAxes = Axes.Both, Height = 0.5f, - Colour = colourProvider.Background4, + Colour = colourProvider.Background3, Shear = new Vector2(-performance_background_shear, 0), EdgeSmoothness = new Vector2(2, 0), }, @@ -175,7 +172,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks RelativePositionAxes = Axes.Y, Height = -0.5f, Position = new Vector2(0, 1), - Colour = colourProvider.Background4, + Colour = colourProvider.Background3, Shear = new Vector2(performance_background_shear, 0), EdgeSmoothness = new Vector2(2, 0), }, @@ -200,7 +197,6 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks }); } - [NotNull] protected virtual Drawable CreateRightContent() => CreateDrawableAccuracy(); protected Drawable CreateDrawableAccuracy() => new Container @@ -258,7 +254,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks }; } - private class ScoreBeatmapMetadataContainer : BeatmapMetadataContainer + private partial class ScoreBeatmapMetadataContainer : BeatmapMetadataContainer { public ScoreBeatmapMetadataContainer(IBeatmapInfo beatmapInfo) : base(beatmapInfo) @@ -269,8 +265,6 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks { var metadata = beatmapInfo.Metadata; - Debug.Assert(metadata != null); - return new Drawable[] { new OsuSpriteText diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileWeightedScore.cs b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileWeightedScore.cs index 8c46f10ba2..6cfe34ec6f 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileWeightedScore.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileWeightedScore.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -14,7 +12,7 @@ using osuTK; namespace osu.Game.Overlays.Profile.Sections.Ranks { - public class DrawableProfileWeightedScore : DrawableProfileScore + public partial class DrawableProfileWeightedScore : DrawableProfileScore { private readonly double weight; diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs index 2564692c87..c85d16a17c 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Graphics.Containers; using osu.Game.Online.API.Requests; using System; @@ -17,11 +15,11 @@ using APIUser = osu.Game.Online.API.Requests.Responses.APIUser; namespace osu.Game.Overlays.Profile.Sections.Ranks { - public class PaginatedScoreContainer : PaginatedProfileSubsection + public partial class PaginatedScoreContainer : PaginatedProfileSubsection { private readonly ScoreType type; - public PaginatedScoreContainer(ScoreType type, Bindable user, LocalisableString headerText) + public PaginatedScoreContainer(ScoreType type, Bindable user, LocalisableString headerText) : base(user, headerText) { this.type = type; @@ -62,8 +60,8 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks base.OnItemsReceived(items); } - protected override APIRequest> CreateRequest(PaginationParameters pagination) => - new GetUserScoresRequest(User.Value.Id, type, pagination); + protected override APIRequest> CreateRequest(UserProfileData user, PaginationParameters pagination) => + new GetUserScoresRequest(user.User.Id, type, pagination, user.Ruleset); private int drawableItemIndex; diff --git a/osu.Game/Overlays/Profile/Sections/RanksSection.cs b/osu.Game/Overlays/Profile/Sections/RanksSection.cs index 581b6e1139..ce831b30a8 100644 --- a/osu.Game/Overlays/Profile/Sections/RanksSection.cs +++ b/osu.Game/Overlays/Profile/Sections/RanksSection.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Game.Overlays.Profile.Sections.Ranks; using osu.Game.Online.API.Requests; using osu.Framework.Localisation; @@ -10,7 +8,7 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Profile.Sections { - public class RanksSection : ProfileSection + public partial class RanksSection : ProfileSection { public override LocalisableString Title => UsersStrings.ShowExtraTopRanksTitle; diff --git a/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs b/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs index 6b71ae73e3..0479ab7c16 100644 --- a/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs +++ b/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs @@ -1,10 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; @@ -19,19 +18,19 @@ using osu.Game.Rulesets; namespace osu.Game.Overlays.Profile.Sections.Recent { - public class DrawableRecentActivity : CompositeDrawable + public partial class DrawableRecentActivity : CompositeDrawable { private const int font_size = 14; [Resolved] - private IAPIProvider api { get; set; } + private IAPIProvider api { get; set; } = null!; [Resolved] - private IRulesetStore rulesets { get; set; } + private IRulesetStore rulesets { get; set; } = null!; private readonly APIRecentActivity activity; - private LinkFlowContainer content; + private LinkFlowContainer content = null!; public DrawableRecentActivity(APIRecentActivity activity) { @@ -216,15 +215,15 @@ namespace osu.Game.Overlays.Profile.Sections.Recent rulesets.AvailableRulesets.FirstOrDefault(r => r.ShortName == activity.Mode)?.Name ?? activity.Mode; private void addUserLink() - => content.AddLink(activity.User?.Username, LinkAction.OpenUserProfile, getLinkArgument(activity.User?.Url), creationParameters: t => t.Font = getLinkFont(FontWeight.Bold)); + => content.AddLink(activity.User.AsNonNull().Username, LinkAction.OpenUserProfile, getLinkArgument(activity.User.AsNonNull().Url), creationParameters: t => t.Font = getLinkFont(FontWeight.Bold)); private void addBeatmapLink() - => content.AddLink(activity.Beatmap?.Title, LinkAction.OpenBeatmap, getLinkArgument(activity.Beatmap?.Url), creationParameters: t => t.Font = getLinkFont()); + => content.AddLink(activity.Beatmap.AsNonNull().Title, LinkAction.OpenBeatmap, getLinkArgument(activity.Beatmap.AsNonNull().Url), creationParameters: t => t.Font = getLinkFont()); private void addBeatmapsetLink() - => content.AddLink(activity.Beatmapset?.Title, LinkAction.OpenBeatmapSet, getLinkArgument(activity.Beatmapset?.Url), creationParameters: t => t.Font = getLinkFont()); + => content.AddLink(activity.Beatmapset.AsNonNull().Title, LinkAction.OpenBeatmapSet, getLinkArgument(activity.Beatmapset.AsNonNull().Url), creationParameters: t => t.Font = getLinkFont()); - private string getLinkArgument(string url) => MessageFormatter.GetLinkDetails($"{api.APIEndpointUrl}{url}").Argument.ToString(); + private string getLinkArgument(string url) => MessageFormatter.GetLinkDetails($"{api.WebsiteRootUrl}{url}").Argument.ToString().AsNonNull(); private FontUsage getLinkFont(FontWeight fontWeight = FontWeight.Regular) => OsuFont.GetFont(size: font_size, weight: fontWeight, italics: true); diff --git a/osu.Game/Overlays/Profile/Sections/Recent/MedalIcon.cs b/osu.Game/Overlays/Profile/Sections/Recent/MedalIcon.cs index e3072f3420..6cb439ab33 100644 --- a/osu.Game/Overlays/Profile/Sections/Recent/MedalIcon.cs +++ b/osu.Game/Overlays/Profile/Sections/Recent/MedalIcon.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; @@ -12,7 +10,7 @@ using osu.Framework.Graphics.Textures; namespace osu.Game.Overlays.Profile.Sections.Recent { [LongRunningLoad] - public class MedalIcon : Container + public partial class MedalIcon : Container { private readonly string slug; private readonly Sprite sprite; diff --git a/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs b/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs index 2878e0e940..37a004f10c 100644 --- a/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Graphics; using osu.Game.Online.API.Requests; using osu.Framework.Bindables; @@ -12,13 +10,12 @@ using System.Collections.Generic; using osuTK; using osu.Framework.Allocation; using osu.Game.Resources.Localisation.Web; -using APIUser = osu.Game.Online.API.Requests.Responses.APIUser; namespace osu.Game.Overlays.Profile.Sections.Recent { - public class PaginatedRecentActivityContainer : PaginatedProfileSubsection + public partial class PaginatedRecentActivityContainer : PaginatedProfileSubsection { - public PaginatedRecentActivityContainer(Bindable user) + public PaginatedRecentActivityContainer(Bindable user) : base(user, missingText: EventsStrings.Empty) { } @@ -29,8 +26,8 @@ namespace osu.Game.Overlays.Profile.Sections.Recent ItemsContainer.Spacing = new Vector2(0, 8); } - protected override APIRequest> CreateRequest(PaginationParameters pagination) => - new GetUserRecentActivitiesRequest(User.Value.Id, pagination); + protected override APIRequest> CreateRequest(UserProfileData user, PaginationParameters pagination) => + new GetUserRecentActivitiesRequest(user.User.Id, pagination); protected override Drawable CreateDrawableItem(APIRecentActivity model) => new DrawableRecentActivity(model); } diff --git a/osu.Game/Overlays/Profile/Sections/Recent/RecentActivityIcon.cs b/osu.Game/Overlays/Profile/Sections/Recent/RecentActivityIcon.cs index c55eedd1ed..8c40c6c7a5 100644 --- a/osu.Game/Overlays/Profile/Sections/Recent/RecentActivityIcon.cs +++ b/osu.Game/Overlays/Profile/Sections/Recent/RecentActivityIcon.cs @@ -13,7 +13,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Profile.Sections.Recent { - public class RecentActivityIcon : Container + public partial class RecentActivityIcon : Container { private readonly SpriteIcon icon; private readonly APIRecentActivity activity; diff --git a/osu.Game/Overlays/Profile/Sections/RecentSection.cs b/osu.Game/Overlays/Profile/Sections/RecentSection.cs index c20594f974..e29dc7f635 100644 --- a/osu.Game/Overlays/Profile/Sections/RecentSection.cs +++ b/osu.Game/Overlays/Profile/Sections/RecentSection.cs @@ -1,15 +1,13 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Localisation; using osu.Game.Overlays.Profile.Sections.Recent; using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Profile.Sections { - public class RecentSection : ProfileSection + public partial class RecentSection : ProfileSection { public override LocalisableString Title => UsersStrings.ShowExtraRecentActivityTitle; diff --git a/osu.Game/Overlays/Profile/UserGraph.cs b/osu.Game/Overlays/Profile/UserGraph.cs index a8a4de68ff..63cdbea5a4 100644 --- a/osu.Game/Overlays/Profile/UserGraph.cs +++ b/osu.Game/Overlays/Profile/UserGraph.cs @@ -1,12 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; -using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -26,12 +23,12 @@ namespace osu.Game.Overlays.Profile /// /// Type of data to be used for X-axis of the graph. /// Type of data to be used for Y-axis of the graph. - public abstract class UserGraph : Container, IHasCustomTooltip + public abstract partial class UserGraph : Container, IHasCustomTooltip { protected const float FADE_DURATION = 150; private readonly UserLineGraph graph; - private KeyValuePair[] data; + private KeyValuePair[]? data; private int hoveredIndex = -1; protected UserGraph() @@ -83,8 +80,7 @@ namespace osu.Game.Overlays.Profile /// /// Set of values which will be used to create a graph. /// - [CanBeNull] - protected KeyValuePair[] Data + protected KeyValuePair[]? Data { set { @@ -120,9 +116,9 @@ namespace osu.Game.Overlays.Profile protected virtual void ShowGraph() => graph.FadeIn(FADE_DURATION, Easing.Out); protected virtual void HideGraph() => graph.FadeOut(FADE_DURATION, Easing.Out); - public ITooltip GetCustomTooltip() => new UserGraphTooltip(); + public ITooltip GetCustomTooltip() => new UserGraphTooltip(); - public UserGraphTooltipContent TooltipContent + public UserGraphTooltipContent? TooltipContent { get { @@ -136,14 +132,14 @@ namespace osu.Game.Overlays.Profile protected abstract UserGraphTooltipContent GetTooltipContent(TKey key, TValue value); - protected class UserLineGraph : LineGraph + protected partial class UserLineGraph : LineGraph { private readonly CircularContainer movingBall; private readonly Container bar; private readonly Box ballBg; private readonly Box line; - public Action OnBallMove; + public Action? OnBallMove; public UserLineGraph() { @@ -191,7 +187,7 @@ namespace osu.Game.Overlays.Profile Vector2 position = calculateBallPosition(index); movingBall.MoveToY(position.Y, duration, Easing.OutQuint); bar.MoveToX(position.X, duration, Easing.OutQuint); - OnBallMove.Invoke(index); + OnBallMove?.Invoke(index); } public void ShowBar() => bar.FadeIn(FADE_DURATION); @@ -207,7 +203,7 @@ namespace osu.Game.Overlays.Profile } } - private class UserGraphTooltip : VisibilityContainer, ITooltip + private partial class UserGraphTooltip : VisibilityContainer, ITooltip { protected readonly OsuSpriteText Label, Counter, BottomText; private readonly Box background; @@ -267,8 +263,11 @@ namespace osu.Game.Overlays.Profile background.Colour = colours.Gray1; } - public void SetContent(UserGraphTooltipContent content) + public void SetContent(UserGraphTooltipContent? content) { + if (content == null) + return; + Label.Text = content.Name; Counter.Text = content.Count; BottomText.Text = content.Time; diff --git a/osu.Game/Overlays/Profile/UserProfileData.cs b/osu.Game/Overlays/Profile/UserProfileData.cs new file mode 100644 index 0000000000..79518516e4 --- /dev/null +++ b/osu.Game/Overlays/Profile/UserProfileData.cs @@ -0,0 +1,30 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Rulesets; + +namespace osu.Game.Overlays.Profile +{ + /// + /// Contains data about a profile presented on the . + /// + public class UserProfileData + { + /// + /// The user whose profile is being presented. + /// + public APIUser User { get; } + + /// + /// The ruleset that the user profile is being shown with. + /// + public RulesetInfo Ruleset { get; } + + public UserProfileData(APIUser user, RulesetInfo ruleset) + { + User = user; + Ruleset = ruleset; + } + } +} diff --git a/osu.Game/Overlays/Rankings/CountryFilter.cs b/osu.Game/Overlays/Rankings/CountryFilter.cs index 9376bafdff..e27fa7c7bd 100644 --- a/osu.Game/Overlays/Rankings/CountryFilter.cs +++ b/osu.Game/Overlays/Rankings/CountryFilter.cs @@ -16,7 +16,7 @@ using osuTK; namespace osu.Game.Overlays.Rankings { - public class CountryFilter : CompositeDrawable, IHasCurrentValue + public partial class CountryFilter : CompositeDrawable, IHasCurrentValue { private const int duration = 200; private const int height = 70; diff --git a/osu.Game/Overlays/Rankings/CountryPill.cs b/osu.Game/Overlays/Rankings/CountryPill.cs index ee4c4f08af..5efa9d12f0 100644 --- a/osu.Game/Overlays/Rankings/CountryPill.cs +++ b/osu.Game/Overlays/Rankings/CountryPill.cs @@ -22,7 +22,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Rankings { - public class CountryPill : CompositeDrawable, IHasCurrentValue + public partial class CountryPill : CompositeDrawable, IHasCurrentValue { private const int duration = 200; @@ -140,7 +140,7 @@ namespace osu.Game.Overlays.Rankings countryName.Text = country.NewValue.GetDescription(); } - private class CloseButton : OsuHoverContainer + private partial class CloseButton : OsuHoverContainer { private readonly SpriteIcon icon; diff --git a/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs b/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs index 936545bd49..44f278a237 100644 --- a/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs +++ b/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs @@ -12,7 +12,7 @@ using osu.Game.Users; namespace osu.Game.Overlays.Rankings { - public class RankingsOverlayHeader : TabControlOverlayHeader + public partial class RankingsOverlayHeader : TabControlOverlayHeader { public Bindable Ruleset => rulesetSelector.Current; @@ -23,13 +23,13 @@ namespace osu.Game.Overlays.Rankings protected override OverlayTitle CreateTitle() => new RankingsTitle(); - protected override Drawable CreateTitleContent() => rulesetSelector = new OverlayRulesetSelector(); + protected override Drawable CreateTabControlContent() => rulesetSelector = new OverlayRulesetSelector(); protected override Drawable CreateContent() => countryFilter = new CountryFilter(); protected override Drawable CreateBackground() => new OverlayHeaderBackground("Headers/rankings"); - private class RankingsTitle : OverlayTitle + private partial class RankingsTitle : OverlayTitle { public RankingsTitle() { diff --git a/osu.Game/Overlays/Rankings/RankingsSortTabControl.cs b/osu.Game/Overlays/Rankings/RankingsSortTabControl.cs index 905c0fae65..9e73c3adb0 100644 --- a/osu.Game/Overlays/Rankings/RankingsSortTabControl.cs +++ b/osu.Game/Overlays/Rankings/RankingsSortTabControl.cs @@ -9,7 +9,7 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Rankings { - public class RankingsSortTabControl : OverlaySortTabControl + public partial class RankingsSortTabControl : OverlaySortTabControl { public RankingsSortTabControl() { diff --git a/osu.Game/Overlays/Rankings/SpotlightSelector.cs b/osu.Game/Overlays/Rankings/SpotlightSelector.cs index 234b91de66..31273e3b01 100644 --- a/osu.Game/Overlays/Rankings/SpotlightSelector.cs +++ b/osu.Game/Overlays/Rankings/SpotlightSelector.cs @@ -24,7 +24,7 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Rankings { - public class SpotlightSelector : CompositeDrawable, IHasCurrentValue + public partial class SpotlightSelector : CompositeDrawable, IHasCurrentValue { private readonly BindableWithCurrent current = new BindableWithCurrent(); public readonly Bindable Sort = new Bindable(); @@ -133,7 +133,7 @@ namespace osu.Game.Overlays.Rankings private LocalisableString dateToString(DateTimeOffset date) => date.ToLocalisableString(@"yyyy-MM-dd"); - private class InfoColumn : FillFlowContainer + private partial class InfoColumn : FillFlowContainer { public LocalisableString Value { @@ -175,7 +175,7 @@ namespace osu.Game.Overlays.Rankings } } - private class SpotlightsDropdown : OsuDropdown + private partial class SpotlightsDropdown : OsuDropdown { private OsuDropdownMenu menu; @@ -192,7 +192,7 @@ namespace osu.Game.Overlays.Rankings Padding = new MarginPadding { Vertical = 20 }; } - private class SpotlightsDropdownHeader : OsuDropdownHeader + private partial class SpotlightsDropdownHeader : OsuDropdownHeader { public SpotlightsDropdownHeader() { diff --git a/osu.Game/Overlays/Rankings/SpotlightsLayout.cs b/osu.Game/Overlays/Rankings/SpotlightsLayout.cs index c23b9711dd..8a1b929753 100644 --- a/osu.Game/Overlays/Rankings/SpotlightsLayout.cs +++ b/osu.Game/Overlays/Rankings/SpotlightsLayout.cs @@ -21,7 +21,7 @@ using osuTK; namespace osu.Game.Overlays.Rankings { - public class SpotlightsLayout : CompositeDrawable + public partial class SpotlightsLayout : CompositeDrawable { public readonly Bindable Ruleset = new Bindable(); diff --git a/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs b/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs index a6f0c7a123..3be5cc994c 100644 --- a/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs @@ -17,7 +17,7 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Rankings.Tables { - public class CountriesTable : RankingsTable + public partial class CountriesTable : RankingsTable { public CountriesTable(int page, IReadOnlyList rankings) : base(page, rankings) @@ -66,7 +66,7 @@ namespace osu.Game.Overlays.Rankings.Tables } }; - private class CountryName : LinkFlowContainer + private partial class CountryName : LinkFlowContainer { [Resolved(canBeNull: true)] private RankingsOverlay rankings { get; set; } diff --git a/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs b/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs index a77546d83f..19ed3afdca 100644 --- a/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs @@ -12,7 +12,7 @@ using osu.Game.Users; namespace osu.Game.Overlays.Rankings.Tables { - public class PerformanceTable : UserBasedTable + public partial class PerformanceTable : UserBasedTable { public PerformanceTable(int page, IReadOnlyList rankings) : base(page, rankings) diff --git a/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs b/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs index 073bf86a7a..affd9a2c44 100644 --- a/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs @@ -20,7 +20,7 @@ using osu.Framework.Localisation; namespace osu.Game.Overlays.Rankings.Tables { - public abstract class RankingsTable : TableContainer + public abstract partial class RankingsTable : TableContainer { protected const int TEXT_SIZE = 12; private const float horizontal_inset = 20; @@ -119,7 +119,7 @@ namespace osu.Game.Overlays.Rankings.Tables public virtual HeaderText CreateHeaderText() => new HeaderText(Header, Highlighted); } - protected class HeaderText : OsuSpriteText + protected partial class HeaderText : OsuSpriteText { private readonly bool isHighlighted; @@ -140,7 +140,7 @@ namespace osu.Game.Overlays.Rankings.Tables } } - protected class RowText : OsuSpriteText + protected partial class RowText : OsuSpriteText { public RowText() { @@ -149,7 +149,7 @@ namespace osu.Game.Overlays.Rankings.Tables } } - protected class ColouredRowText : RowText + protected partial class ColouredRowText : RowText { [BackgroundDependencyLoader] private void load(OverlayColourProvider colourProvider) diff --git a/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs b/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs index 71c78baf3c..0da3fba8cc 100644 --- a/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs @@ -12,7 +12,7 @@ using osu.Game.Users; namespace osu.Game.Overlays.Rankings.Tables { - public class ScoresTable : UserBasedTable + public partial class ScoresTable : UserBasedTable { public ScoresTable(int page, IReadOnlyList rankings) : base(page, rankings) diff --git a/osu.Game/Overlays/Rankings/Tables/TableRowBackground.cs b/osu.Game/Overlays/Rankings/Tables/TableRowBackground.cs index fd9f6da749..54ec45f4ff 100644 --- a/osu.Game/Overlays/Rankings/Tables/TableRowBackground.cs +++ b/osu.Game/Overlays/Rankings/Tables/TableRowBackground.cs @@ -12,7 +12,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Rankings.Tables { - public class TableRowBackground : CompositeDrawable + public partial class TableRowBackground : CompositeDrawable { private const int fade_duration = 100; diff --git a/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs b/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs index 48185e6083..4d25065578 100644 --- a/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs @@ -17,7 +17,7 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Rankings.Tables { - public abstract class UserBasedTable : RankingsTable + public abstract partial class UserBasedTable : RankingsTable { protected UserBasedTable(int page, IReadOnlyList rankings) : base(page, rankings) @@ -98,7 +98,7 @@ namespace osu.Game.Overlays.Rankings.Tables public override HeaderText CreateHeaderText() => new GradeHeaderText(Header, Highlighted); } - private class GradeHeaderText : HeaderText + private partial class GradeHeaderText : HeaderText { public GradeHeaderText(LocalisableString text, bool isHighlighted) : base(text, isHighlighted) diff --git a/osu.Game/Overlays/RankingsOverlay.cs b/osu.Game/Overlays/RankingsOverlay.cs index 586b883604..f25bf80b6a 100644 --- a/osu.Game/Overlays/RankingsOverlay.cs +++ b/osu.Game/Overlays/RankingsOverlay.cs @@ -15,7 +15,7 @@ using osu.Game.Overlays.Rankings.Tables; namespace osu.Game.Overlays { - public class RankingsOverlay : TabbableOnlineOverlay + public partial class RankingsOverlay : TabbableOnlineOverlay { protected Bindable Country => Header.Country; diff --git a/osu.Game/Overlays/RestoreDefaultValueButton.cs b/osu.Game/Overlays/RestoreDefaultValueButton.cs index a5da696f58..97c66fdf02 100644 --- a/osu.Game/Overlays/RestoreDefaultValueButton.cs +++ b/osu.Game/Overlays/RestoreDefaultValueButton.cs @@ -6,19 +6,23 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; -using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; +using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; using osu.Framework.Localisation; using osu.Game.Graphics; +using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osuTK; +using osu.Game.Localisation; namespace osu.Game.Overlays { - public class RestoreDefaultValueButton : OsuButton, IHasTooltip, IHasCurrentValue + public partial class RestoreDefaultValueButton : OsuClickableContainer, IHasCurrentValue { public override bool IsPresent => base.IsPresent || Scheduler.HasPendingTasks; @@ -51,15 +55,32 @@ namespace osu.Game.Overlays private const float size = 4; + private CircularContainer circle = null!; + private Box background = null!; + + public RestoreDefaultValueButton() + : base(HoverSampleSet.Button) + { + } + [BackgroundDependencyLoader] private void load(OsuColour colour) { - BackgroundColour = colour.Lime1; + // size intentionally much larger than actual drawn content, so that the button is easier to click. Size = new Vector2(3 * size); - Content.RelativeSizeAxes = Axes.None; - Content.Size = new Vector2(size); - Content.CornerRadius = size / 2; + Add(circle = new CircularContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(size), + Masking = true, + Child = background = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colour.Lime1 + } + }); Alpha = 0f; @@ -77,7 +98,7 @@ namespace osu.Game.Overlays FinishTransforms(true); } - public LocalisableString TooltipText => "revert to default"; + public override LocalisableString TooltipText => CommonStrings.RevertToDefault.ToLower(); protected override bool OnHover(HoverEvent e) { @@ -104,8 +125,8 @@ namespace osu.Game.Overlays if (!Current.Disabled) { this.FadeTo(Current.IsDefault ? 0 : 1, fade_duration, Easing.OutQuint); - Background.FadeColour(IsHovered ? colours.Lime0 : colours.Lime1, fade_duration, Easing.OutQuint); - Content.TweenEdgeEffectTo(new EdgeEffectParameters + background.FadeColour(IsHovered ? colours.Lime0 : colours.Lime1, fade_duration, Easing.OutQuint); + circle.TweenEdgeEffectTo(new EdgeEffectParameters { Colour = (IsHovered ? colours.Lime1 : colours.Lime3).Opacity(0.4f), Radius = IsHovered ? 8 : 4, @@ -114,8 +135,8 @@ namespace osu.Game.Overlays } else { - Background.FadeColour(colours.Lime3, fade_duration, Easing.OutQuint); - Content.TweenEdgeEffectTo(new EdgeEffectParameters + background.FadeColour(colours.Lime3, fade_duration, Easing.OutQuint); + circle.TweenEdgeEffectTo(new EdgeEffectParameters { Colour = colours.Lime3.Opacity(0.1f), Radius = 2, diff --git a/osu.Game/Overlays/Settings/DangerousSettingsButton.cs b/osu.Game/Overlays/Settings/DangerousSettingsButton.cs index bf7c9ccf2b..248b4d339a 100644 --- a/osu.Game/Overlays/Settings/DangerousSettingsButton.cs +++ b/osu.Game/Overlays/Settings/DangerousSettingsButton.cs @@ -11,7 +11,7 @@ namespace osu.Game.Overlays.Settings /// /// A with pink colours to mark dangerous/destructive actions. /// - public class DangerousSettingsButton : SettingsButton + public partial class DangerousSettingsButton : SettingsButton { [BackgroundDependencyLoader] private void load(OsuColour colours) diff --git a/osu.Game/Overlays/Settings/OutlinedTextBox.cs b/osu.Game/Overlays/Settings/OutlinedTextBox.cs index de7fe75060..56b662ecf0 100644 --- a/osu.Game/Overlays/Settings/OutlinedTextBox.cs +++ b/osu.Game/Overlays/Settings/OutlinedTextBox.cs @@ -12,7 +12,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Settings { - public class OutlinedTextBox : OsuTextBox + public partial class OutlinedTextBox : OsuTextBox { private const float border_thickness = 3; diff --git a/osu.Game/Overlays/Settings/RulesetSettingsSubsection.cs b/osu.Game/Overlays/Settings/RulesetSettingsSubsection.cs index 76e75a5b3c..1bc2c08352 100644 --- a/osu.Game/Overlays/Settings/RulesetSettingsSubsection.cs +++ b/osu.Game/Overlays/Settings/RulesetSettingsSubsection.cs @@ -14,7 +14,7 @@ namespace osu.Game.Overlays.Settings /// A which provides subclasses with the /// from the 's . /// - public abstract class RulesetSettingsSubsection : SettingsSubsection + public abstract partial class RulesetSettingsSubsection : SettingsSubsection { private readonly Ruleset ruleset; diff --git a/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs index 9b53d62272..a71f2a6d29 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs @@ -14,7 +14,7 @@ using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Audio { - public class AudioDevicesSettings : SettingsSubsection + public partial class AudioDevicesSettings : SettingsSubsection { protected override LocalisableString Header => AudioSettingsStrings.AudioDevicesHeader; @@ -77,11 +77,11 @@ namespace osu.Game.Overlays.Settings.Sections.Audio } } - private class AudioDeviceSettingsDropdown : SettingsDropdown + private partial class AudioDeviceSettingsDropdown : SettingsDropdown { protected override OsuDropdown CreateDropdown() => new AudioDeviceDropdownControl(); - private class AudioDeviceDropdownControl : DropdownControl + private partial class AudioDeviceDropdownControl : DropdownControl { protected override LocalisableString GenerateItemText(string item) => string.IsNullOrEmpty(item) ? CommonStrings.Default : base.GenerateItemText(item); diff --git a/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs index d25e9490b7..1755c12f94 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs @@ -14,7 +14,7 @@ using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Audio { - public class OffsetSettings : SettingsSubsection + public partial class OffsetSettings : SettingsSubsection { protected override LocalisableString Header => AudioSettingsStrings.OffsetHeader; diff --git a/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs index 8f188f04d9..a83707b5f6 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs @@ -13,7 +13,7 @@ using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Audio { - public class VolumeSettings : SettingsSubsection + public partial class VolumeSettings : SettingsSubsection { protected override LocalisableString Header => AudioSettingsStrings.VolumeHeader; @@ -54,7 +54,7 @@ namespace osu.Game.Overlays.Settings.Sections.Audio }; } - private class VolumeAdjustSlider : SettingsSlider + private partial class VolumeAdjustSlider : SettingsSlider { protected override Drawable CreateControl() { diff --git a/osu.Game/Overlays/Settings/Sections/AudioSection.cs b/osu.Game/Overlays/Settings/Sections/AudioSection.cs index 70c74cd77c..542d5bc8fd 100644 --- a/osu.Game/Overlays/Settings/Sections/AudioSection.cs +++ b/osu.Game/Overlays/Settings/Sections/AudioSection.cs @@ -13,7 +13,7 @@ using osu.Game.Overlays.Settings.Sections.Audio; namespace osu.Game.Overlays.Settings.Sections { - public class AudioSection : SettingsSection + public partial class AudioSection : SettingsSection { public override LocalisableString Header => AudioSettingsStrings.AudioSectionHeader; diff --git a/osu.Game/Overlays/Settings/Sections/DebugSection.cs b/osu.Game/Overlays/Settings/Sections/DebugSection.cs index a02e28d33a..509410fbb1 100644 --- a/osu.Game/Overlays/Settings/Sections/DebugSection.cs +++ b/osu.Game/Overlays/Settings/Sections/DebugSection.cs @@ -3,6 +3,7 @@ #nullable disable +using osu.Framework.Development; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; @@ -11,7 +12,7 @@ using osu.Game.Overlays.Settings.Sections.DebugSettings; namespace osu.Game.Overlays.Settings.Sections { - public class DebugSection : SettingsSection + public partial class DebugSection : SettingsSection { public override LocalisableString Header => DebugSettingsStrings.DebugSectionHeader; @@ -22,11 +23,12 @@ namespace osu.Game.Overlays.Settings.Sections public DebugSection() { - Children = new Drawable[] - { - new GeneralSettings(), - new MemorySettings(), - }; + Add(new GeneralSettings()); + + if (DebugUtils.IsDebugBuild) + Add(new BatchImportSettings()); + + Add(new MemorySettings()); } } } diff --git a/osu.Game/Overlays/Settings/Sections/DebugSettings/BatchImportSettings.cs b/osu.Game/Overlays/Settings/Sections/DebugSettings/BatchImportSettings.cs new file mode 100644 index 0000000000..1c17356313 --- /dev/null +++ b/osu.Game/Overlays/Settings/Sections/DebugSettings/BatchImportSettings.cs @@ -0,0 +1,66 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Localisation; +using osu.Game.Database; + +namespace osu.Game.Overlays.Settings.Sections.DebugSettings +{ + public partial class BatchImportSettings : SettingsSubsection + { + protected override LocalisableString Header => @"Batch Import"; + + private SettingsButton importBeatmapsButton = null!; + private SettingsButton importCollectionsButton = null!; + private SettingsButton importScoresButton = null!; + private SettingsButton importSkinsButton = null!; + + [BackgroundDependencyLoader] + private void load(LegacyImportManager? legacyImportManager) + { + if (legacyImportManager?.SupportsImportFromStable != true) + return; + + AddRange(new[] + { + importBeatmapsButton = new SettingsButton + { + Text = @"Import beatmaps from stable", + Action = () => + { + importBeatmapsButton.Enabled.Value = false; + legacyImportManager.ImportFromStableAsync(StableContent.Beatmaps).ContinueWith(_ => Schedule(() => importBeatmapsButton.Enabled.Value = true)); + } + }, + importSkinsButton = new SettingsButton + { + Text = @"Import skins from stable", + Action = () => + { + importSkinsButton.Enabled.Value = false; + legacyImportManager.ImportFromStableAsync(StableContent.Skins).ContinueWith(_ => Schedule(() => importSkinsButton.Enabled.Value = true)); + } + }, + importCollectionsButton = new SettingsButton + { + Text = @"Import collections from stable", + Action = () => + { + importCollectionsButton.Enabled.Value = false; + legacyImportManager.ImportFromStableAsync(StableContent.Collections).ContinueWith(_ => Schedule(() => importCollectionsButton.Enabled.Value = true)); + } + }, + importScoresButton = new SettingsButton + { + Text = @"Import scores from stable", + Action = () => + { + importScoresButton.Enabled.Value = false; + legacyImportManager.ImportFromStableAsync(StableContent.Scores).ContinueWith(_ => Schedule(() => importScoresButton.Enabled.Value = true)); + } + }, + }); + } + } +} diff --git a/osu.Game/Overlays/Settings/Sections/DebugSettings/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/DebugSettings/GeneralSettings.cs index e79d27ad2a..6c2bfedba0 100644 --- a/osu.Game/Overlays/Settings/Sections/DebugSettings/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/DebugSettings/GeneralSettings.cs @@ -15,7 +15,7 @@ using osu.Game.Screens.Utility; namespace osu.Game.Overlays.Settings.Sections.DebugSettings { - public class GeneralSettings : SettingsSubsection + public partial class GeneralSettings : SettingsSubsection { protected override LocalisableString Header => DebugSettingsStrings.GeneralHeader; diff --git a/osu.Game/Overlays/Settings/Sections/DebugSettings/MemorySettings.cs b/osu.Game/Overlays/Settings/Sections/DebugSettings/MemorySettings.cs index 3afb060e49..bf0a48d2c2 100644 --- a/osu.Game/Overlays/Settings/Sections/DebugSettings/MemorySettings.cs +++ b/osu.Game/Overlays/Settings/Sections/DebugSettings/MemorySettings.cs @@ -16,7 +16,7 @@ using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.DebugSettings { - public class MemorySettings : SettingsSubsection + public partial class MemorySettings : SettingsSubsection { protected override LocalisableString Header => DebugSettingsStrings.MemoryHeader; diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/AudioSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/AudioSettings.cs index d369c4470b..00eb6fa62c 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/AudioSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/AudioSettings.cs @@ -11,7 +11,7 @@ using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Gameplay { - public class AudioSettings : SettingsSubsection + public partial class AudioSettings : SettingsSubsection { protected override LocalisableString Header => GameplaySettingsStrings.AudioHeader; diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/BackgroundSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/BackgroundSettings.cs index cc224a4f7f..09e5f3e163 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/BackgroundSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/BackgroundSettings.cs @@ -11,7 +11,7 @@ using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Gameplay { - public class BackgroundSettings : SettingsSubsection + public partial class BackgroundSettings : SettingsSubsection { protected override LocalisableString Header => GameplaySettingsStrings.BackgroundHeader; diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/BeatmapSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/BeatmapSettings.cs index 14ff6ac2b5..da5fc519e6 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/BeatmapSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/BeatmapSettings.cs @@ -12,7 +12,7 @@ using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Gameplay { - public class BeatmapSettings : SettingsSubsection + public partial class BeatmapSettings : SettingsSubsection { protected override LocalisableString Header => GameplaySettingsStrings.BeatmapHeader; @@ -32,11 +32,13 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay }, new SettingsCheckbox { + Keywords = new[] { "combo", "override" }, LabelText = SkinSettingsStrings.BeatmapColours, Current = config.GetBindable(OsuSetting.BeatmapColours) }, new SettingsCheckbox { + Keywords = new[] { "samples", "override" }, LabelText = SkinSettingsStrings.BeatmapHitsounds, Current = config.GetBindable(OsuSetting.BeatmapHitsounds) }, diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs index c16ee39191..96d458a942 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs @@ -12,7 +12,7 @@ using osu.Game.Rulesets.Scoring; namespace osu.Game.Overlays.Settings.Sections.Gameplay { - public class GeneralSettings : SettingsSubsection + public partial class GeneralSettings : SettingsSubsection { protected override LocalisableString Header => GameplaySettingsStrings.GeneralHeader; diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/HUDSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/HUDSettings.cs index 88a27840d8..c67c14bb43 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/HUDSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/HUDSettings.cs @@ -11,7 +11,7 @@ using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Gameplay { - public class HUDSettings : SettingsSubsection + public partial class HUDSettings : SettingsSubsection { protected override LocalisableString Header => GameplaySettingsStrings.HUDHeader; diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/InputSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/InputSettings.cs index ac59a6c0ed..4d027cf8cb 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/InputSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/InputSettings.cs @@ -12,7 +12,7 @@ using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Gameplay { - public class InputSettings : SettingsSubsection + public partial class InputSettings : SettingsSubsection { protected override LocalisableString Header => GameplaySettingsStrings.InputHeader; diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs index 53f7f52212..f6b3c12487 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs @@ -12,7 +12,7 @@ using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Gameplay { - public class ModsSettings : SettingsSubsection + public partial class ModsSettings : SettingsSubsection { protected override LocalisableString Header => GameplaySettingsStrings.ModsHeader; @@ -27,6 +27,7 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay { LabelText = GameplaySettingsStrings.IncreaseFirstObjectVisibility, Current = config.GetBindable(OsuSetting.IncreaseFirstObjectVisibility), + Keywords = new[] { @"approach", @"circle", @"hidden" }, }, }; } diff --git a/osu.Game/Overlays/Settings/Sections/GameplaySection.cs b/osu.Game/Overlays/Settings/Sections/GameplaySection.cs index 48e76bfeb7..ae6145752b 100644 --- a/osu.Game/Overlays/Settings/Sections/GameplaySection.cs +++ b/osu.Game/Overlays/Settings/Sections/GameplaySection.cs @@ -11,7 +11,7 @@ using osu.Game.Overlays.Settings.Sections.Gameplay; namespace osu.Game.Overlays.Settings.Sections { - public class GameplaySection : SettingsSection + public partial class GameplaySection : SettingsSection { public override LocalisableString Header => GameplaySettingsStrings.GameplaySectionHeader; diff --git a/osu.Game/Overlays/Settings/Sections/General/LanguageSettings.cs b/osu.Game/Overlays/Settings/Sections/General/LanguageSettings.cs index b7e3bd90b0..982cbec376 100644 --- a/osu.Game/Overlays/Settings/Sections/General/LanguageSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/LanguageSettings.cs @@ -12,7 +12,7 @@ using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.General { - public class LanguageSettings : SettingsSubsection + public partial class LanguageSettings : SettingsSubsection { private SettingsDropdown languageSelection = null!; private Bindable frameworkLocale = null!; @@ -44,10 +44,13 @@ namespace osu.Game.Overlays.Settings.Sections.General }, }; - localisationParameters.BindValueChanged(p - => languageSelection.Current.Value = LanguageExtensions.GetLanguageFor(frameworkLocale.Value, p.NewValue), true); + frameworkLocale.BindValueChanged(_ => updateSelection()); + localisationParameters.BindValueChanged(_ => updateSelection(), true); languageSelection.Current.BindValueChanged(val => frameworkLocale.Value = val.NewValue.ToCultureCode()); } + + private void updateSelection() => + languageSelection.Current.Value = LanguageExtensions.GetLanguageFor(frameworkLocale.Value, localisationParameters.Value); } } diff --git a/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs b/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs index d97cf699e5..55be06c765 100644 --- a/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs @@ -19,7 +19,7 @@ using osu.Game.Updater; namespace osu.Game.Overlays.Settings.Sections.General { - public class UpdateSettings : SettingsSubsection + public partial class UpdateSettings : SettingsSubsection { [Resolved(CanBeNull = true)] private UpdateManager updateManager { get; set; } diff --git a/osu.Game/Overlays/Settings/Sections/GeneralSection.cs b/osu.Game/Overlays/Settings/Sections/GeneralSection.cs index 59cbd8cd5a..d4fd78f0c8 100644 --- a/osu.Game/Overlays/Settings/Sections/GeneralSection.cs +++ b/osu.Game/Overlays/Settings/Sections/GeneralSection.cs @@ -1,21 +1,23 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; +using osu.Game.Graphics; using osu.Game.Localisation; using osu.Game.Overlays.Settings.Sections.General; namespace osu.Game.Overlays.Settings.Sections { - public class GeneralSection : SettingsSection + public partial class GeneralSection : SettingsSection { [Resolved(CanBeNull = true)] - private FirstRunSetupOverlay firstRunSetupOverlay { get; set; } + private FirstRunSetupOverlay? firstRunSetupOverlay { get; set; } + + [Resolved(CanBeNull = true)] + private OsuGame? game { get; set; } public override LocalisableString Header => GeneralSettingsStrings.GeneralSectionHeader; @@ -24,15 +26,24 @@ namespace osu.Game.Overlays.Settings.Sections Icon = FontAwesome.Solid.Cog }; - public GeneralSection() + [BackgroundDependencyLoader] + private void load(OsuColour colours) { Children = new Drawable[] { new SettingsButton { Text = GeneralSettingsStrings.RunSetupWizard, + TooltipText = FirstRunSetupOverlayStrings.FirstRunSetupDescription, Action = () => firstRunSetupOverlay?.Show(), }, + new SettingsButton + { + Text = GeneralSettingsStrings.LearnMoreAboutLazer, + TooltipText = GeneralSettingsStrings.LearnMoreAboutLazerTooltip, + BackgroundColour = colours.YellowDark, + Action = () => game?.ShowWiki(@"Help_centre/Upgrading_to_lazer") + }, new LanguageSettings(), new UpdateSettings(), }; diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 7f0bded806..bad06732d0 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -25,7 +25,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Settings.Sections.Graphics { - public class LayoutSettings : SettingsSubsection + public partial class LayoutSettings : SettingsSubsection { protected override LocalisableString Header => GraphicsSettingsStrings.LayoutHeader; @@ -177,13 +177,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics updateScreenModeWarning(); }, true); - windowModes.BindCollectionChanged((_, _) => - { - if (windowModes.Count > 1) - windowModeDropdown.Show(); - else - windowModeDropdown.Hide(); - }, true); + windowModes.BindCollectionChanged((_, _) => updateDisplaySettingsVisibility()); currentDisplay.BindValueChanged(display => Schedule(() => { @@ -219,7 +213,11 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics scalingSettings.ResizeHeightTo(0, transition_duration, Easing.OutQuint); scalingSettings.AutoSizeAxes = scalingMode.Value != ScalingMode.Off ? Axes.Y : Axes.None; - scalingSettings.ForEach(s => s.TransferValueOnCommit = scalingMode.Value == ScalingMode.Everything); + scalingSettings.ForEach(s => + { + s.TransferValueOnCommit = scalingMode.Value == ScalingMode.Everything; + s.CanBeShown.Value = scalingMode.Value != ScalingMode.Off; + }); } } @@ -234,20 +232,10 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics private void updateDisplaySettingsVisibility() { - if (resolutions.Count > 1 && windowModeDropdown.Current.Value == WindowMode.Fullscreen) - resolutionDropdown.Show(); - else - resolutionDropdown.Hide(); - - if (displayDropdown.Items.Count() > 1) - displayDropdown.Show(); - else - displayDropdown.Hide(); - - if (host.Window?.SafeAreaPadding.Value.Total != Vector2.Zero) - safeAreaConsiderationsCheckbox.Show(); - else - safeAreaConsiderationsCheckbox.Hide(); + windowModeDropdown.CanBeShown.Value = windowModes.Count > 1; + resolutionDropdown.CanBeShown.Value = resolutions.Count > 1 && windowModeDropdown.Current.Value == WindowMode.Fullscreen; + displayDropdown.CanBeShown.Value = displayDropdown.Items.Count() > 1; + safeAreaConsiderationsCheckbox.CanBeShown.Value = host.Window?.SafeAreaPadding.Value.Total != Vector2.Zero; } private void updateScreenModeWarning() @@ -324,7 +312,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics base.Dispose(isDisposing); } - private class ScalingPreview : ScalingContainer + private partial class ScalingPreview : ScalingContainer { public ScalingPreview() { @@ -337,16 +325,16 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics } } - private class UIScaleSlider : OsuSliderBar + private partial class UIScaleSlider : OsuSliderBar { public override LocalisableString TooltipText => base.TooltipText + "x"; } - private class DisplaySettingsDropdown : SettingsDropdown + private partial class DisplaySettingsDropdown : SettingsDropdown { protected override OsuDropdown CreateDropdown() => new DisplaySettingsDropdownControl(); - private class DisplaySettingsDropdownControl : DropdownControl + private partial class DisplaySettingsDropdownControl : DropdownControl { protected override LocalisableString GenerateItemText(Display item) { @@ -355,11 +343,11 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics } } - private class ResolutionSettingsDropdown : SettingsDropdown + private partial class ResolutionSettingsDropdown : SettingsDropdown { protected override OsuDropdown CreateDropdown() => new ResolutionDropdownControl(); - private class ResolutionDropdownControl : DropdownControl + private partial class ResolutionDropdownControl : DropdownControl { protected override LocalisableString GenerateItemText(Size item) { diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs index 2e15172e46..a5fdfdc105 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs @@ -13,7 +13,7 @@ using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Graphics { - public class RendererSettings : SettingsSubsection + public partial class RendererSettings : SettingsSubsection { protected override LocalisableString Header => GraphicsSettingsStrings.RendererHeader; @@ -27,7 +27,8 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics new SettingsEnumDropdown { LabelText = GraphicsSettingsStrings.FrameLimiter, - Current = config.GetBindable(FrameworkSetting.FrameSync) + Current = config.GetBindable(FrameworkSetting.FrameSync), + Keywords = new[] { @"fps" }, }, new SettingsEnumDropdown { diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/ScreenshotSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/ScreenshotSettings.cs index 7f88cc23d2..8054b27de5 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/ScreenshotSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/ScreenshotSettings.cs @@ -11,7 +11,7 @@ using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Graphics { - public class ScreenshotSettings : SettingsSubsection + public partial class ScreenshotSettings : SettingsSubsection { protected override LocalisableString Header => GraphicsSettingsStrings.Screenshots; diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/VideoSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/VideoSettings.cs index 56d0a6421b..2e0bbe3c16 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/VideoSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/VideoSettings.cs @@ -13,7 +13,7 @@ using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Graphics { - public class VideoSettings : SettingsSubsection + public partial class VideoSettings : SettingsSubsection { protected override LocalisableString Header => GraphicsSettingsStrings.VideoHeader; diff --git a/osu.Game/Overlays/Settings/Sections/GraphicsSection.cs b/osu.Game/Overlays/Settings/Sections/GraphicsSection.cs index e094e0e051..323cdaf14d 100644 --- a/osu.Game/Overlays/Settings/Sections/GraphicsSection.cs +++ b/osu.Game/Overlays/Settings/Sections/GraphicsSection.cs @@ -11,7 +11,7 @@ using osu.Game.Overlays.Settings.Sections.Graphics; namespace osu.Game.Overlays.Settings.Sections { - public class GraphicsSection : SettingsSection + public partial class GraphicsSection : SettingsSection { public override LocalisableString Header => GraphicsSettingsStrings.GraphicsSectionHeader; diff --git a/osu.Game/Overlays/Settings/Sections/Input/BindingSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/BindingSettings.cs index 2f4840a384..dbd7949206 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/BindingSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/BindingSettings.cs @@ -11,7 +11,7 @@ using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Input { - public class BindingSettings : SettingsSubsection + public partial class BindingSettings : SettingsSubsection { protected override LocalisableString Header => BindingSettingsStrings.ShortcutAndGameplayBindings; diff --git a/osu.Game/Overlays/Settings/Sections/Input/GlobalKeyBindingsSection.cs b/osu.Game/Overlays/Settings/Sections/Input/GlobalKeyBindingsSection.cs index 7ab10a3c3a..862bbbede0 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/GlobalKeyBindingsSection.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/GlobalKeyBindingsSection.cs @@ -9,7 +9,7 @@ using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Input { - public class GlobalKeyBindingsSection : SettingsSection + public partial class GlobalKeyBindingsSection : SettingsSection { public override Drawable CreateIcon() => new SpriteIcon { @@ -28,7 +28,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input Add(new EditorKeyBindingsSubsection(manager)); } - private class DefaultBindingsSubsection : KeyBindingsSubsection + private partial class DefaultBindingsSubsection : KeyBindingsSubsection { protected override LocalisableString Header => string.Empty; @@ -39,7 +39,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input } } - private class OverlayBindingsSubsection : KeyBindingsSubsection + private partial class OverlayBindingsSubsection : KeyBindingsSubsection { protected override LocalisableString Header => InputSettingsStrings.OverlaysSection; @@ -50,7 +50,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input } } - private class SongSelectKeyBindingSubsection : KeyBindingsSubsection + private partial class SongSelectKeyBindingSubsection : KeyBindingsSubsection { protected override LocalisableString Header => InputSettingsStrings.SongSelectSection; @@ -61,7 +61,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input } } - private class InGameKeyBindingsSubsection : KeyBindingsSubsection + private partial class InGameKeyBindingsSubsection : KeyBindingsSubsection { protected override LocalisableString Header => InputSettingsStrings.InGameSection; @@ -72,7 +72,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input } } - private class AudioControlKeyBindingsSubsection : KeyBindingsSubsection + private partial class AudioControlKeyBindingsSubsection : KeyBindingsSubsection { protected override LocalisableString Header => InputSettingsStrings.AudioSection; @@ -83,7 +83,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input } } - private class EditorKeyBindingsSubsection : KeyBindingsSubsection + private partial class EditorKeyBindingsSubsection : KeyBindingsSubsection { protected override LocalisableString Header => InputSettingsStrings.EditorSection; diff --git a/osu.Game/Overlays/Settings/Sections/Input/JoystickSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/JoystickSettings.cs index 34be846595..8455c09633 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/JoystickSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/JoystickSettings.cs @@ -12,7 +12,7 @@ using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Input { - public class JoystickSettings : SettingsSubsection + public partial class JoystickSettings : SettingsSubsection { protected override LocalisableString Header => JoystickSettingsStrings.JoystickGamepad; diff --git a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingPanel.cs b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingPanel.cs index 0830241f2b..30429c84f0 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingPanel.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingPanel.cs @@ -11,7 +11,7 @@ using osu.Game.Rulesets; namespace osu.Game.Overlays.Settings.Sections.Input { - public class KeyBindingPanel : SettingsSubPanel + public partial class KeyBindingPanel : SettingsSubPanel { protected override Drawable CreateHeader() => new SettingsHeader(InputSettingsStrings.KeyBindingPanelHeader, InputSettingsStrings.KeyBindingPanelDescription); diff --git a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingRow.cs b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingRow.cs index 25ab8cfad2..b04e514ec2 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingRow.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingRow.cs @@ -22,6 +22,7 @@ using osu.Game.Database; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Input; using osu.Game.Input.Bindings; using osu.Game.Resources.Localisation.Web; @@ -31,7 +32,7 @@ using osuTK.Input; namespace osu.Game.Overlays.Settings.Sections.Input { - public class KeyBindingRow : Container, IFilterable + public partial class KeyBindingRow : Container, IFilterable { /// /// Invoked when the binding of this row is updated with a change being written. @@ -446,7 +447,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input isDefault.Value = bindings.Select(b => b.KeyCombination).SequenceEqual(Defaults); } - private class CancelButton : TriangleButton + private partial class CancelButton : RoundedButton { public CancelButton() { @@ -455,7 +456,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input } } - public class ClearButton : DangerousTriangleButton + public partial class ClearButton : DangerousRoundedButton { public ClearButton() { @@ -464,7 +465,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input } } - public class KeyButton : Container + public partial class KeyButton : Container { public readonly RealmKeyBinding KeyBinding; diff --git a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingsSubsection.cs b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingsSubsection.cs index 98d569948f..d6d4abfa92 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingsSubsection.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingsSubsection.cs @@ -17,7 +17,7 @@ using osuTK; namespace osu.Game.Overlays.Settings.Sections.Input { - public abstract class KeyBindingsSubsection : SettingsSubsection + public abstract partial class KeyBindingsSubsection : SettingsSubsection { /// /// After a successful binding, automatically select the next binding row to make quickly @@ -77,7 +77,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input } } - public class ResetButton : DangerousSettingsButton + public partial class ResetButton : DangerousSettingsButton { [BackgroundDependencyLoader] private void load() diff --git a/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs index b815239c9f..5a6338dc09 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs @@ -17,7 +17,7 @@ using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Input { - public class MouseSettings : SettingsSubsection + public partial class MouseSettings : SettingsSubsection { private readonly MouseHandler mouseHandler; @@ -126,7 +126,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input }, true); } - public class SensitivitySetting : SettingsSlider + public partial class SensitivitySetting : SettingsSlider { public SensitivitySetting() { @@ -135,7 +135,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input } } - public class SensitivitySlider : OsuSliderBar + public partial class SensitivitySlider : OsuSliderBar { public override LocalisableString TooltipText => Current.Disabled ? MouseSettingsStrings.EnableHighPrecisionForSensitivityAdjust : $"{base.TooltipText}x"; } diff --git a/osu.Game/Overlays/Settings/Sections/Input/RotationPresetButtons.cs b/osu.Game/Overlays/Settings/Sections/Input/RotationPresetButtons.cs index 2172dc175e..a66e44f8cb 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/RotationPresetButtons.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/RotationPresetButtons.cs @@ -15,7 +15,7 @@ using osu.Game.Graphics.UserInterfaceV2; namespace osu.Game.Overlays.Settings.Sections.Input { - internal class RotationPresetButtons : CompositeDrawable + internal partial class RotationPresetButtons : CompositeDrawable { public new MarginPadding Padding { @@ -86,7 +86,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input }, true); } - public class RotationButton : RoundedButton + public partial class RotationButton : RoundedButton { [Resolved] private OsuColour colours { get; set; } diff --git a/osu.Game/Overlays/Settings/Sections/Input/RulesetBindingsSection.cs b/osu.Game/Overlays/Settings/Sections/Input/RulesetBindingsSection.cs index 6f3127a377..19f0d0f7d1 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/RulesetBindingsSection.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/RulesetBindingsSection.cs @@ -3,7 +3,6 @@ #nullable disable -using System.Diagnostics; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; @@ -12,7 +11,7 @@ using osu.Game.Rulesets; namespace osu.Game.Overlays.Settings.Sections.Input { - public class RulesetBindingsSection : SettingsSection + public partial class RulesetBindingsSection : SettingsSection { public override Drawable CreateIcon() => ruleset?.CreateInstance().CreateIcon() ?? new SpriteIcon { @@ -29,8 +28,6 @@ namespace osu.Game.Overlays.Settings.Sections.Input var r = ruleset.CreateInstance(); - Debug.Assert(r != null); - foreach (int variant in r.AvailableVariants) Add(new VariantBindingsSubsection(ruleset, variant)); } diff --git a/osu.Game/Overlays/Settings/Sections/Input/TabletAreaSelection.cs b/osu.Game/Overlays/Settings/Sections/Input/TabletAreaSelection.cs index 708cd5900a..6f7faf535b 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/TabletAreaSelection.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/TabletAreaSelection.cs @@ -20,7 +20,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Settings.Sections.Input { - public class TabletAreaSelection : CompositeDrawable + public partial class TabletAreaSelection : CompositeDrawable { public bool IsWithinBounds { get; private set; } diff --git a/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs index b6efa00cdb..951cf3802f 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs @@ -21,7 +21,7 @@ using osu.Game.Online.Chat; namespace osu.Game.Overlays.Settings.Sections.Input { - public class TabletSettings : SettingsSubsection + public partial class TabletSettings : SettingsSubsection { public TabletAreaSelection AreaSelection { get; private set; } @@ -143,6 +143,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input areaOffset.SetDefault(); areaSize.SetDefault(); }, + CanBeShown = { BindTarget = enabled } }, new SettingsButton { @@ -150,25 +151,29 @@ namespace osu.Game.Overlays.Settings.Sections.Input Action = () => { forceAspectRatio((float)host.Window.ClientSize.Width / host.Window.ClientSize.Height); - } + }, + CanBeShown = { BindTarget = enabled } }, new SettingsSlider { TransferValueOnCommit = true, LabelText = TabletSettingsStrings.XOffset, - Current = offsetX + Current = offsetX, + CanBeShown = { BindTarget = enabled } }, new SettingsSlider { TransferValueOnCommit = true, LabelText = TabletSettingsStrings.YOffset, - Current = offsetY + Current = offsetY, + CanBeShown = { BindTarget = enabled } }, new SettingsSlider { TransferValueOnCommit = true, LabelText = TabletSettingsStrings.Rotation, - Current = rotation + Current = rotation, + CanBeShown = { BindTarget = enabled } }, new RotationPresetButtons(tabletHandler) { @@ -181,24 +186,28 @@ namespace osu.Game.Overlays.Settings.Sections.Input { TransferValueOnCommit = true, LabelText = TabletSettingsStrings.AspectRatio, - Current = aspectRatio + Current = aspectRatio, + CanBeShown = { BindTarget = enabled } }, new SettingsCheckbox { LabelText = TabletSettingsStrings.LockAspectRatio, - Current = aspectLock + Current = aspectLock, + CanBeShown = { BindTarget = enabled } }, new SettingsSlider { TransferValueOnCommit = true, LabelText = CommonStrings.Width, - Current = sizeX + Current = sizeX, + CanBeShown = { BindTarget = enabled } }, new SettingsSlider { TransferValueOnCommit = true, LabelText = CommonStrings.Height, - Current = sizeY + Current = sizeY, + CanBeShown = { BindTarget = enabled } }, } }, diff --git a/osu.Game/Overlays/Settings/Sections/Input/VariantBindingsSubsection.cs b/osu.Game/Overlays/Settings/Sections/Input/VariantBindingsSubsection.cs index a6f6c28463..d00de7f549 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/VariantBindingsSubsection.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/VariantBindingsSubsection.cs @@ -6,7 +6,7 @@ using osu.Game.Rulesets; namespace osu.Game.Overlays.Settings.Sections.Input { - public class VariantBindingsSubsection : KeyBindingsSubsection + public partial class VariantBindingsSubsection : KeyBindingsSubsection { protected override bool AutoAdvanceTarget => true; diff --git a/osu.Game/Overlays/Settings/Sections/InputSection.cs b/osu.Game/Overlays/Settings/Sections/InputSection.cs index 4d75537f6b..0647068da7 100644 --- a/osu.Game/Overlays/Settings/Sections/InputSection.cs +++ b/osu.Game/Overlays/Settings/Sections/InputSection.cs @@ -14,7 +14,7 @@ using osu.Game.Overlays.Settings.Sections.Input; namespace osu.Game.Overlays.Settings.Sections { - public class InputSection : SettingsSection + public partial class InputSection : SettingsSection { private readonly KeyBindingPanel keyConfig; @@ -47,7 +47,7 @@ namespace osu.Game.Overlays.Settings.Sections } } - public class HandlerSection : SettingsSubsection + public partial class HandlerSection : SettingsSubsection { private readonly InputHandler handler; diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/BeatmapSettings.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/BeatmapSettings.cs index beae5a6aad..4b1836ed86 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/BeatmapSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/BeatmapSettings.cs @@ -6,37 +6,22 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Beatmaps; -using osu.Game.Database; using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Maintenance { - public class BeatmapSettings : SettingsSubsection + public partial class BeatmapSettings : SettingsSubsection { protected override LocalisableString Header => CommonStrings.Beatmaps; - private SettingsButton importBeatmapsButton = null!; private SettingsButton deleteBeatmapsButton = null!; private SettingsButton deleteBeatmapVideosButton = null!; private SettingsButton restoreButton = null!; private SettingsButton undeleteButton = null!; [BackgroundDependencyLoader] - private void load(BeatmapManager beatmaps, LegacyImportManager? legacyImportManager, IDialogOverlay? dialogOverlay) + private void load(BeatmapManager beatmaps, IDialogOverlay? dialogOverlay) { - if (legacyImportManager?.SupportsImportFromStable == true) - { - Add(importBeatmapsButton = new SettingsButton - { - Text = MaintenanceSettingsStrings.ImportBeatmapsFromStable, - Action = () => - { - importBeatmapsButton.Enabled.Value = false; - legacyImportManager.ImportFromStableAsync(StableContent.Beatmaps).ContinueWith(_ => Schedule(() => importBeatmapsButton.Enabled.Value = true)); - } - }); - } - Add(deleteBeatmapsButton = new DangerousSettingsButton { Text = MaintenanceSettingsStrings.DeleteAllBeatmaps, diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/CollectionsSettings.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/CollectionsSettings.cs index 17fef37e40..09acc22c25 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/CollectionsSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/CollectionsSettings.cs @@ -10,12 +10,10 @@ using osu.Game.Overlays.Notifications; namespace osu.Game.Overlays.Settings.Sections.Maintenance { - public class CollectionsSettings : SettingsSubsection + public partial class CollectionsSettings : SettingsSubsection { protected override LocalisableString Header => CommonStrings.Collections; - private SettingsButton importCollectionsButton = null!; - [Resolved] private RealmAccess realm { get; set; } = null!; @@ -23,21 +21,8 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance private INotificationOverlay? notificationOverlay { get; set; } [BackgroundDependencyLoader] - private void load(LegacyImportManager? legacyImportManager, IDialogOverlay? dialogOverlay) + private void load(IDialogOverlay? dialogOverlay) { - if (legacyImportManager?.SupportsImportFromStable == true) - { - Add(importCollectionsButton = new SettingsButton - { - Text = MaintenanceSettingsStrings.ImportCollectionsFromStable, - Action = () => - { - importCollectionsButton.Enabled.Value = false; - legacyImportManager.ImportFromStableAsync(StableContent.Collections).ContinueWith(_ => Schedule(() => importCollectionsButton.Enabled.Value = true)); - } - }); - } - Add(new DangerousSettingsButton { Text = MaintenanceSettingsStrings.DeleteAllCollections, diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/DirectorySelectScreen.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/DirectorySelectScreen.cs index 1c9a758c6f..e87ca32bf6 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/DirectorySelectScreen.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/DirectorySelectScreen.cs @@ -13,16 +13,15 @@ using osuTK; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Localisation; -using osu.Game.Graphics.UserInterface; using osu.Framework.Screens; using osu.Game.Graphics.Containers; using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Maintenance { - public abstract class DirectorySelectScreen : OsuScreen + public abstract partial class DirectorySelectScreen : OsuScreen { - private TriangleButton selectionButton; + private RoundedButton selectionButton; private OsuDirectorySelector directorySelector; @@ -101,7 +100,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance }, new Drawable[] { - selectionButton = new TriangleButton + selectionButton = new RoundedButton { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/MassDeleteConfirmationDialog.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/MassDeleteConfirmationDialog.cs index 19e6f83dac..948d646e3d 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/MassDeleteConfirmationDialog.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/MassDeleteConfirmationDialog.cs @@ -6,7 +6,7 @@ using osu.Game.Overlays.Dialog; namespace osu.Game.Overlays.Settings.Sections.Maintenance { - public class MassDeleteConfirmationDialog : DeleteConfirmationDialog + public partial class MassDeleteConfirmationDialog : DeleteConfirmationDialog { public MassDeleteConfirmationDialog(Action deleteAction) { diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/MassVideoDeleteConfirmationDialog.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/MassVideoDeleteConfirmationDialog.cs index fc8c9d497b..6312e09b3e 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/MassVideoDeleteConfirmationDialog.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/MassVideoDeleteConfirmationDialog.cs @@ -5,7 +5,7 @@ using System; namespace osu.Game.Overlays.Settings.Sections.Maintenance { - public class MassVideoDeleteConfirmationDialog : MassDeleteConfirmationDialog + public partial class MassVideoDeleteConfirmationDialog : MassDeleteConfirmationDialog { public MassVideoDeleteConfirmationDialog(Action deleteAction) : base(deleteAction) diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/MigrationRunScreen.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/MigrationRunScreen.cs index 158e1a8aa0..5b24460ac2 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/MigrationRunScreen.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/MigrationRunScreen.cs @@ -22,7 +22,7 @@ using osuTK; namespace osu.Game.Overlays.Settings.Sections.Maintenance { - public class MigrationRunScreen : OsuScreen + public partial class MigrationRunScreen : OsuScreen { private readonly DirectoryInfo destination; diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/MigrationSelectScreen.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/MigrationSelectScreen.cs index 5de33fdd55..80bf292057 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/MigrationSelectScreen.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/MigrationSelectScreen.cs @@ -17,7 +17,7 @@ using osu.Game.Overlays.Dialog; namespace osu.Game.Overlays.Settings.Sections.Maintenance { - public class MigrationSelectScreen : DirectorySelectScreen + public partial class MigrationSelectScreen : DirectorySelectScreen { [Resolved] private Storage storage { get; set; } diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/ModPresetSettings.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/ModPresetSettings.cs index 51f6e1bf60..ba45d9c896 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/ModPresetSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/ModPresetSettings.cs @@ -14,7 +14,7 @@ using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Maintenance { - public class ModPresetSettings : SettingsSubsection + public partial class ModPresetSettings : SettingsSubsection { protected override LocalisableString Header => CommonStrings.ModPresets; diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/ScoreSettings.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/ScoreSettings.cs index eb2d3171ea..c6f4f1e1a5 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/ScoreSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/ScoreSettings.cs @@ -4,35 +4,20 @@ using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Localisation; -using osu.Game.Database; using osu.Game.Localisation; using osu.Game.Scoring; namespace osu.Game.Overlays.Settings.Sections.Maintenance { - public class ScoreSettings : SettingsSubsection + public partial class ScoreSettings : SettingsSubsection { protected override LocalisableString Header => CommonStrings.Scores; - private SettingsButton importScoresButton = null!; private SettingsButton deleteScoresButton = null!; [BackgroundDependencyLoader] - private void load(ScoreManager scores, LegacyImportManager? legacyImportManager, IDialogOverlay? dialogOverlay) + private void load(ScoreManager scores, IDialogOverlay? dialogOverlay) { - if (legacyImportManager?.SupportsImportFromStable == true) - { - Add(importScoresButton = new SettingsButton - { - Text = MaintenanceSettingsStrings.ImportScoresFromStable, - Action = () => - { - importScoresButton.Enabled.Value = false; - legacyImportManager.ImportFromStableAsync(StableContent.Scores).ContinueWith(_ => Schedule(() => importScoresButton.Enabled.Value = true)); - } - }); - } - Add(deleteScoresButton = new DangerousSettingsButton { Text = MaintenanceSettingsStrings.DeleteAllScores, diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/SkinSettings.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/SkinSettings.cs index 93c65513b7..c3ac49af6d 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/SkinSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/SkinSettings.cs @@ -4,35 +4,20 @@ using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Localisation; -using osu.Game.Database; using osu.Game.Localisation; using osu.Game.Skinning; namespace osu.Game.Overlays.Settings.Sections.Maintenance { - public class SkinSettings : SettingsSubsection + public partial class SkinSettings : SettingsSubsection { protected override LocalisableString Header => CommonStrings.Skins; - private SettingsButton importSkinsButton = null!; private SettingsButton deleteSkinsButton = null!; [BackgroundDependencyLoader] - private void load(SkinManager skins, LegacyImportManager? legacyImportManager, IDialogOverlay? dialogOverlay) + private void load(SkinManager skins, IDialogOverlay? dialogOverlay) { - if (legacyImportManager?.SupportsImportFromStable == true) - { - Add(importSkinsButton = new SettingsButton - { - Text = MaintenanceSettingsStrings.ImportSkinsFromStable, - Action = () => - { - importSkinsButton.Enabled.Value = false; - legacyImportManager.ImportFromStableAsync(StableContent.Skins).ContinueWith(_ => Schedule(() => importSkinsButton.Enabled.Value = true)); - } - }); - } - Add(deleteSkinsButton = new DangerousSettingsButton { Text = MaintenanceSettingsStrings.DeleteAllSkins, diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/StableDirectoryLocationDialog.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/StableDirectoryLocationDialog.cs index 8aff4520b5..633bf8c5a5 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/StableDirectoryLocationDialog.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/StableDirectoryLocationDialog.cs @@ -12,7 +12,7 @@ using osu.Game.Screens; namespace osu.Game.Overlays.Settings.Sections.Maintenance { - public class StableDirectoryLocationDialog : PopupDialog + public partial class StableDirectoryLocationDialog : PopupDialog { [Resolved] private IPerformFromScreenRunner performer { get; set; } diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/StableDirectorySelectScreen.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/StableDirectorySelectScreen.cs index 047d589689..048f3ee683 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/StableDirectorySelectScreen.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/StableDirectorySelectScreen.cs @@ -11,7 +11,7 @@ using osu.Framework.Screens; namespace osu.Game.Overlays.Settings.Sections.Maintenance { - public class StableDirectorySelectScreen : DirectorySelectScreen + public partial class StableDirectorySelectScreen : DirectorySelectScreen { private readonly TaskCompletionSource taskCompletionSource; diff --git a/osu.Game/Overlays/Settings/Sections/MaintenanceSection.cs b/osu.Game/Overlays/Settings/Sections/MaintenanceSection.cs index 4be6d1653b..bb0a952164 100644 --- a/osu.Game/Overlays/Settings/Sections/MaintenanceSection.cs +++ b/osu.Game/Overlays/Settings/Sections/MaintenanceSection.cs @@ -9,7 +9,7 @@ using osu.Game.Overlays.Settings.Sections.Maintenance; namespace osu.Game.Overlays.Settings.Sections { - public class MaintenanceSection : SettingsSection + public partial class MaintenanceSection : SettingsSection { public override LocalisableString Header => MaintenanceSettingsStrings.MaintenanceSectionHeader; diff --git a/osu.Game/Overlays/Settings/Sections/Online/AlertsAndPrivacySettings.cs b/osu.Game/Overlays/Settings/Sections/Online/AlertsAndPrivacySettings.cs index 529f1b5ee4..dc6743c042 100644 --- a/osu.Game/Overlays/Settings/Sections/Online/AlertsAndPrivacySettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Online/AlertsAndPrivacySettings.cs @@ -11,7 +11,7 @@ using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Online { - public class AlertsAndPrivacySettings : SettingsSubsection + public partial class AlertsAndPrivacySettings : SettingsSubsection { protected override LocalisableString Header => OnlineSettingsStrings.AlertsAndPrivacyHeader; diff --git a/osu.Game/Overlays/Settings/Sections/Online/IntegrationSettings.cs b/osu.Game/Overlays/Settings/Sections/Online/IntegrationSettings.cs index 17228d6359..33748d0f5e 100644 --- a/osu.Game/Overlays/Settings/Sections/Online/IntegrationSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Online/IntegrationSettings.cs @@ -11,7 +11,7 @@ using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Online { - public class IntegrationSettings : SettingsSubsection + public partial class IntegrationSettings : SettingsSubsection { protected override LocalisableString Header => OnlineSettingsStrings.IntegrationsHeader; diff --git a/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs b/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs index ba707e2145..d0707a434a 100644 --- a/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs @@ -11,7 +11,7 @@ using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Online { - public class WebSettings : SettingsSubsection + public partial class WebSettings : SettingsSubsection { protected override LocalisableString Header => OnlineSettingsStrings.WebHeader; diff --git a/osu.Game/Overlays/Settings/Sections/OnlineSection.cs b/osu.Game/Overlays/Settings/Sections/OnlineSection.cs index feb281f1b8..775c6f9839 100644 --- a/osu.Game/Overlays/Settings/Sections/OnlineSection.cs +++ b/osu.Game/Overlays/Settings/Sections/OnlineSection.cs @@ -11,7 +11,7 @@ using osu.Game.Overlays.Settings.Sections.Online; namespace osu.Game.Overlays.Settings.Sections { - public class OnlineSection : SettingsSection + public partial class OnlineSection : SettingsSection { public override LocalisableString Header => OnlineSettingsStrings.OnlineSectionHeader; diff --git a/osu.Game/Overlays/Settings/Sections/RulesetSection.cs b/osu.Game/Overlays/Settings/Sections/RulesetSection.cs index 6f0b3c27a0..aaad1ec4e2 100644 --- a/osu.Game/Overlays/Settings/Sections/RulesetSection.cs +++ b/osu.Game/Overlays/Settings/Sections/RulesetSection.cs @@ -12,7 +12,7 @@ using osu.Game.Rulesets; namespace osu.Game.Overlays.Settings.Sections { - public class RulesetSection : SettingsSection + public partial class RulesetSection : SettingsSection { public override LocalisableString Header => RulesetSettingsStrings.Rulesets; diff --git a/osu.Game/Overlays/Settings/Sections/SizeSlider.cs b/osu.Game/Overlays/Settings/Sections/SizeSlider.cs index 28b4cd6418..26d6147bb7 100644 --- a/osu.Game/Overlays/Settings/Sections/SizeSlider.cs +++ b/osu.Game/Overlays/Settings/Sections/SizeSlider.cs @@ -13,7 +13,7 @@ namespace osu.Game.Overlays.Settings.Sections /// /// A slider intended to show a "size" multiplier number, where 1x is 1.0. /// - public class SizeSlider : OsuSliderBar + public partial class SizeSlider : OsuSliderBar where T : struct, IEquatable, IComparable, IConvertible, IFormattable { public override LocalisableString TooltipText => Current.Value.ToString(@"0.##x", NumberFormatInfo.CurrentInfo); diff --git a/osu.Game/Overlays/Settings/Sections/SkinSection.cs b/osu.Game/Overlays/Settings/Sections/SkinSection.cs index f602b73065..f75656cc99 100644 --- a/osu.Game/Overlays/Settings/Sections/SkinSection.cs +++ b/osu.Game/Overlays/Settings/Sections/SkinSection.cs @@ -24,7 +24,7 @@ using Realms; namespace osu.Game.Overlays.Settings.Sections { - public class SkinSection : SettingsSection + public partial class SkinSection : SettingsSection { private SkinSettingsDropdown skinDropdown; @@ -105,6 +105,7 @@ namespace osu.Game.Overlays.Settings.Sections dropdownItems.Clear(); dropdownItems.Add(sender.Single(s => s.ID == SkinInfo.ARGON_SKIN).ToLive(realm)); + dropdownItems.Add(sender.Single(s => s.ID == SkinInfo.ARGON_PRO_SKIN).ToLive(realm)); dropdownItems.Add(sender.Single(s => s.ID == SkinInfo.TRIANGLES_SKIN).ToLive(realm)); dropdownItems.Add(sender.Single(s => s.ID == SkinInfo.CLASSIC_SKIN).ToLive(realm)); @@ -123,17 +124,17 @@ namespace osu.Game.Overlays.Settings.Sections realmSubscription?.Dispose(); } - private class SkinSettingsDropdown : SettingsDropdown> + private partial class SkinSettingsDropdown : SettingsDropdown> { protected override OsuDropdown> CreateDropdown() => new SkinDropdownControl(); - private class SkinDropdownControl : DropdownControl + private partial class SkinDropdownControl : DropdownControl { protected override LocalisableString GenerateItemText(Live item) => item.ToString(); } } - public class ExportSkinButton : SettingsButton + public partial class ExportSkinButton : SettingsButton { [Resolved] private SkinManager skins { get; set; } @@ -171,7 +172,7 @@ namespace osu.Game.Overlays.Settings.Sections } } - public class DeleteSkinButton : DangerousSettingsButton + public partial class DeleteSkinButton : DangerousSettingsButton { [Resolved] private SkinManager skins { get; set; } diff --git a/osu.Game/Overlays/Settings/Sections/UserInterface/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/UserInterface/GeneralSettings.cs index 85cfdb33d5..2e8d005401 100644 --- a/osu.Game/Overlays/Settings/Sections/UserInterface/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/UserInterface/GeneralSettings.cs @@ -12,7 +12,7 @@ using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.UserInterface { - public class GeneralSettings : SettingsSubsection + public partial class GeneralSettings : SettingsSubsection { protected override LocalisableString Header => UserInterfaceStrings.GeneralHeader; diff --git a/osu.Game/Overlays/Settings/Sections/UserInterface/MainMenuSettings.cs b/osu.Game/Overlays/Settings/Sections/UserInterface/MainMenuSettings.cs index 7ca45bb6b8..4577fadb01 100644 --- a/osu.Game/Overlays/Settings/Sections/UserInterface/MainMenuSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/UserInterface/MainMenuSettings.cs @@ -14,7 +14,7 @@ using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Overlays.Settings.Sections.UserInterface { - public class MainMenuSettings : SettingsSubsection + public partial class MainMenuSettings : SettingsSubsection { protected override LocalisableString Header => UserInterfaceStrings.MainMenuHeader; diff --git a/osu.Game/Overlays/Settings/Sections/UserInterface/SongSelectSettings.cs b/osu.Game/Overlays/Settings/Sections/UserInterface/SongSelectSettings.cs index 708bee6fbd..8b5e0b75b7 100644 --- a/osu.Game/Overlays/Settings/Sections/UserInterface/SongSelectSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/UserInterface/SongSelectSettings.cs @@ -12,7 +12,7 @@ using osu.Game.Overlays.Mods.Input; namespace osu.Game.Overlays.Settings.Sections.UserInterface { - public class SongSelectSettings : SettingsSubsection + public partial class SongSelectSettings : SettingsSubsection { protected override LocalisableString Header => UserInterfaceStrings.SongSelectHeader; diff --git a/osu.Game/Overlays/Settings/Sections/UserInterfaceSection.cs b/osu.Game/Overlays/Settings/Sections/UserInterfaceSection.cs index b2711af612..0926574a54 100644 --- a/osu.Game/Overlays/Settings/Sections/UserInterfaceSection.cs +++ b/osu.Game/Overlays/Settings/Sections/UserInterfaceSection.cs @@ -11,7 +11,7 @@ using osu.Game.Overlays.Settings.Sections.UserInterface; namespace osu.Game.Overlays.Settings.Sections { - public class UserInterfaceSection : SettingsSection + public partial class UserInterfaceSection : SettingsSection { public override LocalisableString Header => UserInterfaceStrings.UserInterfaceSectionHeader; diff --git a/osu.Game/Overlays/Settings/SettingsButton.cs b/osu.Game/Overlays/Settings/SettingsButton.cs index 5f2a416f58..5091ddc2d0 100644 --- a/osu.Game/Overlays/Settings/SettingsButton.cs +++ b/osu.Game/Overlays/Settings/SettingsButton.cs @@ -1,21 +1,18 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Collections.Generic; using System.Linq; -using JetBrains.Annotations; -using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Localisation; -using osu.Game.Graphics; using osu.Game.Graphics.UserInterfaceV2; namespace osu.Game.Overlays.Settings { - public class SettingsButton : RoundedButton, IHasTooltip + public partial class SettingsButton : RoundedButton, IHasTooltip, IConditionalFilterable { public SettingsButton() { @@ -23,14 +20,11 @@ namespace osu.Game.Overlays.Settings Padding = new MarginPadding { Left = SettingsPanel.CONTENT_MARGINS, Right = SettingsPanel.CONTENT_MARGINS }; } - [BackgroundDependencyLoader(true)] - private void load([CanBeNull] OverlayColourProvider overlayColourProvider, OsuColour colours) - { - DefaultBackgroundColour = overlayColourProvider?.Highlight1 ?? colours.Blue3; - } - public LocalisableString TooltipText { get; set; } + public BindableBool CanBeShown { get; } = new BindableBool(true); + IBindable IConditionalFilterable.CanBeShown => CanBeShown; + public override IEnumerable FilterTerms { get diff --git a/osu.Game/Overlays/Settings/SettingsCheckbox.cs b/osu.Game/Overlays/Settings/SettingsCheckbox.cs index efe7fb6d9e..a413bcf220 100644 --- a/osu.Game/Overlays/Settings/SettingsCheckbox.cs +++ b/osu.Game/Overlays/Settings/SettingsCheckbox.cs @@ -9,7 +9,7 @@ using osu.Game.Graphics.UserInterface; namespace osu.Game.Overlays.Settings { - public class SettingsCheckbox : SettingsItem + public partial class SettingsCheckbox : SettingsItem { private LocalisableString labelText; diff --git a/osu.Game/Overlays/Settings/SettingsDropdown.cs b/osu.Game/Overlays/Settings/SettingsDropdown.cs index 347ef03b42..5798d02e03 100644 --- a/osu.Game/Overlays/Settings/SettingsDropdown.cs +++ b/osu.Game/Overlays/Settings/SettingsDropdown.cs @@ -12,7 +12,7 @@ using osu.Game.Graphics.UserInterface; namespace osu.Game.Overlays.Settings { - public class SettingsDropdown : SettingsItem + public partial class SettingsDropdown : SettingsItem { protected new OsuDropdown Control => (OsuDropdown)base.Control; @@ -34,7 +34,7 @@ namespace osu.Game.Overlays.Settings protected virtual OsuDropdown CreateDropdown() => new DropdownControl(); - protected class DropdownControl : OsuDropdown + protected partial class DropdownControl : OsuDropdown { public DropdownControl() { diff --git a/osu.Game/Overlays/Settings/SettingsEnumDropdown.cs b/osu.Game/Overlays/Settings/SettingsEnumDropdown.cs index 9408e4a9ce..62dd4f2905 100644 --- a/osu.Game/Overlays/Settings/SettingsEnumDropdown.cs +++ b/osu.Game/Overlays/Settings/SettingsEnumDropdown.cs @@ -9,12 +9,12 @@ using osu.Game.Graphics.UserInterface; namespace osu.Game.Overlays.Settings { - public class SettingsEnumDropdown : SettingsDropdown + public partial class SettingsEnumDropdown : SettingsDropdown where T : struct, Enum { protected override OsuDropdown CreateDropdown() => new DropdownControl(); - protected new class DropdownControl : OsuEnumDropdown + protected new partial class DropdownControl : OsuEnumDropdown { public DropdownControl() { diff --git a/osu.Game/Overlays/Settings/SettingsFooter.cs b/osu.Game/Overlays/Settings/SettingsFooter.cs index db0dc8fd5e..62933ed556 100644 --- a/osu.Game/Overlays/Settings/SettingsFooter.cs +++ b/osu.Game/Overlays/Settings/SettingsFooter.cs @@ -18,7 +18,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Settings { - public class SettingsFooter : FillFlowContainer + public partial class SettingsFooter : FillFlowContainer { [BackgroundDependencyLoader] private void load(OsuGameBase game, RulesetStore rulesets) @@ -78,7 +78,7 @@ namespace osu.Game.Overlays.Settings } } - private class BuildDisplay : OsuAnimatedButton + private partial class BuildDisplay : OsuAnimatedButton { private readonly string version; private readonly bool isDebug; diff --git a/osu.Game/Overlays/Settings/SettingsHeader.cs b/osu.Game/Overlays/Settings/SettingsHeader.cs index 56360fc4a1..f2b84c4ba9 100644 --- a/osu.Game/Overlays/Settings/SettingsHeader.cs +++ b/osu.Game/Overlays/Settings/SettingsHeader.cs @@ -12,7 +12,7 @@ using osu.Game.Graphics.Containers; namespace osu.Game.Overlays.Settings { - public class SettingsHeader : Container + public partial class SettingsHeader : Container { private readonly LocalisableString heading; private readonly LocalisableString subheading; diff --git a/osu.Game/Overlays/Settings/SettingsItem.cs b/osu.Game/Overlays/Settings/SettingsItem.cs index c34964fa96..5f4bb9d57f 100644 --- a/osu.Game/Overlays/Settings/SettingsItem.cs +++ b/osu.Game/Overlays/Settings/SettingsItem.cs @@ -22,7 +22,7 @@ using osuTK; namespace osu.Game.Overlays.Settings { - public abstract class SettingsItem : Container, IFilterable, ISettingsItem, IHasCurrentValue, IHasTooltip + public abstract partial class SettingsItem : Container, IConditionalFilterable, ISettingsItem, IHasCurrentValue, IHasTooltip { protected abstract Drawable CreateControl(); @@ -144,6 +144,9 @@ namespace osu.Game.Overlays.Settings public bool FilteringActive { get; set; } + public BindableBool CanBeShown { get; } = new BindableBool(true); + IBindable IConditionalFilterable.CanBeShown => CanBeShown; + public event Action SettingChanged; private T classicDefault; diff --git a/osu.Game/Overlays/Settings/SettingsNumberBox.cs b/osu.Game/Overlays/Settings/SettingsNumberBox.cs index 4f98954289..97b8f6de60 100644 --- a/osu.Game/Overlays/Settings/SettingsNumberBox.cs +++ b/osu.Game/Overlays/Settings/SettingsNumberBox.cs @@ -11,14 +11,14 @@ using osu.Framework.Graphics.UserInterface; namespace osu.Game.Overlays.Settings { - public class SettingsNumberBox : SettingsItem + public partial class SettingsNumberBox : SettingsItem { protected override Drawable CreateControl() => new NumberControl { RelativeSizeAxes = Axes.X, }; - private sealed class NumberControl : CompositeDrawable, IHasCurrentValue + private sealed partial class NumberControl : CompositeDrawable, IHasCurrentValue { private readonly BindableWithCurrent current = new BindableWithCurrent(); @@ -68,7 +68,7 @@ namespace osu.Game.Overlays.Settings } } - private class OutlinedNumberBox : OutlinedTextBox + private partial class OutlinedNumberBox : OutlinedTextBox { protected override bool AllowIme => false; diff --git a/osu.Game/Overlays/Settings/SettingsSection.cs b/osu.Game/Overlays/Settings/SettingsSection.cs index dfdc850ed8..9602e4373f 100644 --- a/osu.Game/Overlays/Settings/SettingsSection.cs +++ b/osu.Game/Overlays/Settings/SettingsSection.cs @@ -5,7 +5,6 @@ using System.Collections.Generic; using System.Diagnostics; -using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -19,7 +18,7 @@ using osuTK; namespace osu.Game.Overlays.Settings { - public abstract class SettingsSection : Container, IHasFilterableChildren + public abstract partial class SettingsSection : Container, IFilterable { protected FillFlowContainer FlowContent; protected override Container Content => FlowContent; @@ -33,7 +32,6 @@ namespace osu.Game.Overlays.Settings public abstract Drawable CreateIcon(); public abstract LocalisableString Header { get; } - public IEnumerable FilterableChildren => Children.OfType(); public virtual IEnumerable FilterTerms => new[] { Header }; public const int ITEM_SPACING = 14; diff --git a/osu.Game/Overlays/Settings/SettingsSidebar.cs b/osu.Game/Overlays/Settings/SettingsSidebar.cs index ca6bcae6e4..36411e01cc 100644 --- a/osu.Game/Overlays/Settings/SettingsSidebar.cs +++ b/osu.Game/Overlays/Settings/SettingsSidebar.cs @@ -10,7 +10,7 @@ using osu.Game.Graphics.Containers; namespace osu.Game.Overlays.Settings { - public class SettingsSidebar : ExpandingButtonContainer + public partial class SettingsSidebar : ExpandingButtonContainer { public const float DEFAULT_WIDTH = 70; public const int EXPANDED_WIDTH = 200; diff --git a/osu.Game/Overlays/Settings/SettingsSlider.cs b/osu.Game/Overlays/Settings/SettingsSlider.cs index 43f007f201..babac8ec69 100644 --- a/osu.Game/Overlays/Settings/SettingsSlider.cs +++ b/osu.Game/Overlays/Settings/SettingsSlider.cs @@ -10,12 +10,12 @@ using osu.Game.Graphics.UserInterface; namespace osu.Game.Overlays.Settings { - public class SettingsSlider : SettingsSlider> + public partial class SettingsSlider : SettingsSlider> where T : struct, IEquatable, IComparable, IConvertible { } - public class SettingsSlider : SettingsItem + public partial class SettingsSlider : SettingsItem where TValue : struct, IEquatable, IComparable, IConvertible where TSlider : OsuSliderBar, new() { diff --git a/osu.Game/Overlays/Settings/SettingsSubsection.cs b/osu.Game/Overlays/Settings/SettingsSubsection.cs index 72788c55cd..784f20a6e8 100644 --- a/osu.Game/Overlays/Settings/SettingsSubsection.cs +++ b/osu.Game/Overlays/Settings/SettingsSubsection.cs @@ -8,7 +8,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics.Sprites; using System.Collections.Generic; -using System.Linq; using osu.Framework.Allocation; using osu.Framework.Localisation; using osu.Framework.Testing; @@ -17,7 +16,7 @@ using osu.Game.Graphics; namespace osu.Game.Overlays.Settings { [ExcludeFromDynamicCompile] - public abstract class SettingsSubsection : FillFlowContainer, IHasFilterableChildren + public abstract partial class SettingsSubsection : FillFlowContainer, IFilterable { protected override Container Content => FlowContent; @@ -25,8 +24,6 @@ namespace osu.Game.Overlays.Settings protected abstract LocalisableString Header { get; } - public IEnumerable FilterableChildren => Children.OfType(); - public virtual IEnumerable FilterTerms => new[] { Header }; public bool MatchingFilter diff --git a/osu.Game/Overlays/Settings/SettingsTextBox.cs b/osu.Game/Overlays/Settings/SettingsTextBox.cs index 4d0f4253eb..3f9fa06384 100644 --- a/osu.Game/Overlays/Settings/SettingsTextBox.cs +++ b/osu.Game/Overlays/Settings/SettingsTextBox.cs @@ -9,7 +9,7 @@ using osu.Framework.Graphics; namespace osu.Game.Overlays.Settings { - public class SettingsTextBox : SettingsItem + public partial class SettingsTextBox : SettingsItem { protected override Drawable CreateControl() => new OutlinedTextBox { diff --git a/osu.Game/Overlays/Settings/SidebarButton.cs b/osu.Game/Overlays/Settings/SidebarButton.cs index 2c4832c68a..aec0509394 100644 --- a/osu.Game/Overlays/Settings/SidebarButton.cs +++ b/osu.Game/Overlays/Settings/SidebarButton.cs @@ -9,7 +9,7 @@ using osu.Game.Graphics.UserInterface; namespace osu.Game.Overlays.Settings { - public abstract class SidebarButton : OsuButton + public abstract partial class SidebarButton : OsuButton { protected const double FADE_DURATION = 500; diff --git a/osu.Game/Overlays/Settings/SidebarIconButton.cs b/osu.Game/Overlays/Settings/SidebarIconButton.cs index b32337eb2e..4e5b361460 100644 --- a/osu.Game/Overlays/Settings/SidebarIconButton.cs +++ b/osu.Game/Overlays/Settings/SidebarIconButton.cs @@ -15,7 +15,7 @@ using osu.Game.Graphics.Containers; namespace osu.Game.Overlays.Settings { - public class SidebarIconButton : SidebarButton + public partial class SidebarIconButton : SidebarButton { private const float selection_indicator_height_active = 18; private const float selection_indicator_height_inactive = 4; diff --git a/osu.Game/Overlays/SettingsOverlay.cs b/osu.Game/Overlays/SettingsOverlay.cs index b28ac4ab8b..291281124c 100644 --- a/osu.Game/Overlays/SettingsOverlay.cs +++ b/osu.Game/Overlays/SettingsOverlay.cs @@ -17,7 +17,7 @@ using osu.Game.Localisation; namespace osu.Game.Overlays { - public class SettingsOverlay : SettingsPanel, INamedOverlayComponent + public partial class SettingsOverlay : SettingsPanel, INamedOverlayComponent { public string IconTexture => "Icons/Hexacons/settings"; public LocalisableString Title => SettingsStrings.HeaderTitle; diff --git a/osu.Game/Overlays/SettingsPanel.cs b/osu.Game/Overlays/SettingsPanel.cs index eb457032ea..aefaccdb5d 100644 --- a/osu.Game/Overlays/SettingsPanel.cs +++ b/osu.Game/Overlays/SettingsPanel.cs @@ -23,7 +23,7 @@ using osu.Game.Overlays.Settings; namespace osu.Game.Overlays { [Cached] - public abstract class SettingsPanel : OsuFocusedOverlayContainer + public abstract partial class SettingsPanel : OsuFocusedOverlayContainer { public const float CONTENT_MARGINS = 20; @@ -273,13 +273,13 @@ namespace osu.Game.Overlays } } - private class NonMaskedContent : Container + private partial class NonMaskedContent : Container { // masking breaks the pan-out transform with nested sub-settings panels. protected override bool ComputeIsMaskedAway(RectangleF maskingBounds) => false; } - public class SettingsSectionsContainer : SectionsContainer + public partial class SettingsSectionsContainer : SectionsContainer { public SearchContainer SearchContainer; diff --git a/osu.Game/Overlays/SettingsSubPanel.cs b/osu.Game/Overlays/SettingsSubPanel.cs index 4548cdfb5d..5890d1c8fa 100644 --- a/osu.Game/Overlays/SettingsSubPanel.cs +++ b/osu.Game/Overlays/SettingsSubPanel.cs @@ -14,7 +14,7 @@ using osuTK; namespace osu.Game.Overlays { - public abstract class SettingsSubPanel : SettingsPanel + public abstract partial class SettingsSubPanel : SettingsPanel { protected SettingsSubPanel() : base(true) @@ -34,7 +34,7 @@ namespace osu.Game.Overlays protected override bool DimMainContent => false; // dimming is handled by main overlay - public class BackButton : SidebarButton + public partial class BackButton : SidebarButton { private Container content; diff --git a/osu.Game/Overlays/SettingsToolboxGroup.cs b/osu.Game/Overlays/SettingsToolboxGroup.cs index 6dd9e2a56d..86964e7ed4 100644 --- a/osu.Game/Overlays/SettingsToolboxGroup.cs +++ b/osu.Game/Overlays/SettingsToolboxGroup.cs @@ -20,7 +20,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays { - public class SettingsToolboxGroup : Container, IExpandable + public partial class SettingsToolboxGroup : Container, IExpandable { private readonly string title; public const int CONTAINER_WIDTH = 270; @@ -126,7 +126,8 @@ namespace osu.Game.Overlays { base.LoadComplete(); - Expanded.BindValueChanged(updateExpandedState, true); + Expanded.BindValueChanged(_ => updateExpandedState(true)); + updateExpandedState(false); this.Delay(600).Schedule(updateFadeState); } @@ -161,21 +162,25 @@ namespace osu.Game.Overlays return base.OnInvalidate(invalidation, source); } - private void updateExpandedState(ValueChangedEvent expanded) + private void updateExpandedState(bool animate) { // clearing transforms is necessary to avoid a previous height transform // potentially continuing to get processed while content has changed to autosize. content.ClearTransforms(); - if (expanded.NewValue) + if (Expanded.Value) + { content.AutoSizeAxes = Axes.Y; + content.AutoSizeDuration = animate ? transition_duration : 0; + content.AutoSizeEasing = Easing.OutQuint; + } else { content.AutoSizeAxes = Axes.None; - content.ResizeHeightTo(0, transition_duration, Easing.OutQuint); + content.ResizeHeightTo(0, animate ? transition_duration : 0, Easing.OutQuint); } - headerContent.FadeColour(expanded.NewValue ? Color4.White : OsuColour.Gray(0.5f), 200, Easing.OutQuint); + headerContent.FadeColour(Expanded.Value ? Color4.White : OsuColour.Gray(0.5f), 200, Easing.OutQuint); } private void updateFadeState() diff --git a/osu.Game/Overlays/TabControlOverlayHeader.cs b/osu.Game/Overlays/TabControlOverlayHeader.cs index caec4aeed0..2b87535708 100644 --- a/osu.Game/Overlays/TabControlOverlayHeader.cs +++ b/osu.Game/Overlays/TabControlOverlayHeader.cs @@ -21,12 +21,12 @@ namespace osu.Game.Overlays /// An overlay header which contains a . /// /// The type of item to be represented by tabs. - public abstract class TabControlOverlayHeader : OverlayHeader, IHasCurrentValue + public abstract partial class TabControlOverlayHeader : OverlayHeader, IHasCurrentValue { - protected OsuTabControl TabControl; + protected OsuTabControl TabControl { get; } + protected Container TabControlContainer { get; } private readonly Box controlBackground; - private readonly Container tabControlContainer; private readonly BindableWithCurrent current = new BindableWithCurrent(); public Bindable Current @@ -41,7 +41,7 @@ namespace osu.Game.Overlays set { base.ContentSidePadding = value; - tabControlContainer.Padding = new MarginPadding { Horizontal = value }; + TabControlContainer.Padding = new MarginPadding { Horizontal = value }; } } @@ -57,15 +57,23 @@ namespace osu.Game.Overlays { RelativeSizeAxes = Axes.Both, }, - tabControlContainer = new Container + TabControlContainer = new Container { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Padding = new MarginPadding { Horizontal = ContentSidePadding }, - Child = TabControl = CreateTabControl().With(control => + Children = new[] { - control.Current = Current; - }) + TabControl = CreateTabControl().With(control => + { + control.Current = Current; + }), + CreateTabControlContent().With(content => + { + content.Anchor = Anchor.CentreRight; + content.Origin = Anchor.CentreRight; + }), + } } } }); @@ -80,7 +88,13 @@ namespace osu.Game.Overlays [NotNull] protected virtual OsuTabControl CreateTabControl() => new OverlayHeaderTabControl(); - public class OverlayHeaderTabControl : OverlayTabControl + /// + /// Creates a on the opposite side of the . Used mostly to create . + /// + [NotNull] + protected virtual Drawable CreateTabControlContent() => Empty(); + + public partial class OverlayHeaderTabControl : OverlayTabControl { private const float bar_height = 1; @@ -103,7 +117,7 @@ namespace osu.Game.Overlays Direction = FillDirection.Horizontal, }; - private class OverlayHeaderTabItem : OverlayTabItem + private partial class OverlayHeaderTabItem : OverlayTabItem { public OverlayHeaderTabItem(T value) : base(value) diff --git a/osu.Game/Overlays/TabbableOnlineOverlay.cs b/osu.Game/Overlays/TabbableOnlineOverlay.cs index a99be4cc18..d92dd4ae54 100644 --- a/osu.Game/Overlays/TabbableOnlineOverlay.cs +++ b/osu.Game/Overlays/TabbableOnlineOverlay.cs @@ -12,7 +12,7 @@ using osu.Game.Online.API; namespace osu.Game.Overlays { - public abstract class TabbableOnlineOverlay : OnlineOverlay + public abstract partial class TabbableOnlineOverlay : OnlineOverlay where THeader : TabControlOverlayHeader { private readonly IBindable apiState = new Bindable(); diff --git a/osu.Game/Overlays/Toolbar/AnalogClockDisplay.cs b/osu.Game/Overlays/Toolbar/AnalogClockDisplay.cs index 477991f599..a5ed0d65bd 100644 --- a/osu.Game/Overlays/Toolbar/AnalogClockDisplay.cs +++ b/osu.Game/Overlays/Toolbar/AnalogClockDisplay.cs @@ -14,7 +14,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Toolbar { - public class AnalogClockDisplay : ClockDisplay + public partial class AnalogClockDisplay : ClockDisplay { private const float hand_thickness = 2.4f; @@ -76,7 +76,7 @@ namespace osu.Game.Overlays.Toolbar hand.RotateTo(rotation, duration, Easing.OutElastic); } - private class CentreCircle : CompositeDrawable + private partial class CentreCircle : CompositeDrawable { [BackgroundDependencyLoader] private void load(OsuColour colours) @@ -101,7 +101,7 @@ namespace osu.Game.Overlays.Toolbar } } - private class SecondHand : CompositeDrawable + private partial class SecondHand : CompositeDrawable { [BackgroundDependencyLoader] private void load(OsuColour colours) @@ -126,7 +126,7 @@ namespace osu.Game.Overlays.Toolbar } } - private class LargeHand : CompositeDrawable + private partial class LargeHand : CompositeDrawable { public LargeHand(float length) { diff --git a/osu.Game/Overlays/Toolbar/ClockDisplay.cs b/osu.Game/Overlays/Toolbar/ClockDisplay.cs index 0711341445..088631f8d6 100644 --- a/osu.Game/Overlays/Toolbar/ClockDisplay.cs +++ b/osu.Game/Overlays/Toolbar/ClockDisplay.cs @@ -8,7 +8,7 @@ using osu.Framework.Graphics.Containers; namespace osu.Game.Overlays.Toolbar { - public abstract class ClockDisplay : CompositeDrawable + public abstract partial class ClockDisplay : CompositeDrawable { private int? lastSecond; diff --git a/osu.Game/Overlays/Toolbar/DigitalClockDisplay.cs b/osu.Game/Overlays/Toolbar/DigitalClockDisplay.cs index 5592590fd9..ada2f6ff86 100644 --- a/osu.Game/Overlays/Toolbar/DigitalClockDisplay.cs +++ b/osu.Game/Overlays/Toolbar/DigitalClockDisplay.cs @@ -5,13 +5,14 @@ using System; using osu.Framework.Allocation; +using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; namespace osu.Game.Overlays.Toolbar { - public class DigitalClockDisplay : ClockDisplay + public partial class DigitalClockDisplay : ClockDisplay { private OsuSpriteText realTime; private OsuSpriteText gameTime; @@ -69,7 +70,7 @@ namespace osu.Game.Overlays.Toolbar protected override void UpdateDisplay(DateTimeOffset now) { - realTime.Text = use24HourDisplay ? $"{now:HH:mm:ss}" : $"{now:h:mm:ss tt}"; + realTime.Text = now.ToLocalisableString(use24HourDisplay ? @"HH:mm:ss" : @"h:mm:ss tt"); gameTime.Text = $"running {new TimeSpan(TimeSpan.TicksPerSecond * (int)(Clock.CurrentTime / 1000)):c}"; } diff --git a/osu.Game/Overlays/Toolbar/Toolbar.cs b/osu.Game/Overlays/Toolbar/Toolbar.cs index 9d0f43c45a..f21ef0ee98 100644 --- a/osu.Game/Overlays/Toolbar/Toolbar.cs +++ b/osu.Game/Overlays/Toolbar/Toolbar.cs @@ -21,7 +21,7 @@ using osu.Game.Input.Bindings; namespace osu.Game.Overlays.Toolbar { - public class Toolbar : OverlayContainer, IKeyBindingHandler + public partial class Toolbar : OverlayContainer, IKeyBindingHandler { public const float HEIGHT = 40; public const float TOOLTIP_HEIGHT = 30; @@ -65,9 +65,12 @@ namespace osu.Game.Overlays.Toolbar [BackgroundDependencyLoader(true)] private void load(OsuGame osuGame) { + ToolbarBackground background; + HoverInterceptor interceptor; + Children = new Drawable[] { - new ToolbarBackground(), + background = new ToolbarBackground(), new GridContainer { RelativeSizeAxes = Axes.Both, @@ -180,9 +183,15 @@ namespace osu.Game.Overlays.Toolbar }, }, } + }, + interceptor = new HoverInterceptor + { + RelativeSizeAxes = Axes.Both } }; + ((IBindable)background.ShowGradient).BindTo(interceptor.ReceivedHover); + if (osuGame != null) OverlayActivationMode.BindTo(osuGame.OverlayActivationMode); } @@ -194,8 +203,10 @@ namespace osu.Game.Overlays.Toolbar rulesetSelector.Current.BindTo(ruleset); } - public class ToolbarBackground : Container + public partial class ToolbarBackground : Container { + public Bindable ShowGradient { get; } = new BindableBool(); + private readonly Box gradientBackground; public ToolbarBackground() @@ -220,15 +231,43 @@ namespace osu.Game.Overlays.Toolbar }; } + protected override void LoadComplete() + { + base.LoadComplete(); + + ShowGradient.BindValueChanged(_ => updateState(), true); + } + + private void updateState() + { + if (ShowGradient.Value) + gradientBackground.FadeIn(transition_time, Easing.OutQuint); + else + gradientBackground.FadeOut(transition_time, Easing.OutQuint); + } + } + + /// + /// Whenever the mouse cursor is within the bounds of the toolbar, we want the background gradient to show, for toolbar button descriptions to be legible. + /// Unfortunately we also need to ensure that the toolbar buttons handle hover, to prevent the possibility of multiple descriptions being shown + /// due to hover events passing through multiple buttons. + /// This drawable is a workaround, that when placed front-most in the toolbar, allows to see whether hover events have been propagated through it without handling them. + /// + private partial class HoverInterceptor : Drawable + { + public IBindable ReceivedHover => receivedHover; + private readonly Bindable receivedHover = new BindableBool(); + protected override bool OnHover(HoverEvent e) { - gradientBackground.FadeIn(transition_time, Easing.OutQuint); - return true; + receivedHover.Value = true; + return base.OnHover(e); } protected override void OnHoverLost(HoverLostEvent e) { - gradientBackground.FadeOut(transition_time, Easing.OutQuint); + receivedHover.Value = false; + base.OnHoverLost(e); } } diff --git a/osu.Game/Overlays/Toolbar/ToolbarBeatmapListingButton.cs b/osu.Game/Overlays/Toolbar/ToolbarBeatmapListingButton.cs index a2de186488..efcb011293 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarBeatmapListingButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarBeatmapListingButton.cs @@ -9,7 +9,7 @@ using osu.Game.Input.Bindings; namespace osu.Game.Overlays.Toolbar { - public class ToolbarBeatmapListingButton : ToolbarOverlayToggleButton + public partial class ToolbarBeatmapListingButton : ToolbarOverlayToggleButton { protected override Anchor TooltipAnchor => Anchor.TopRight; diff --git a/osu.Game/Overlays/Toolbar/ToolbarButton.cs b/osu.Game/Overlays/Toolbar/ToolbarButton.cs index 96d4da1112..4193e52584 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarButton.cs @@ -28,7 +28,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Toolbar { - public abstract class ToolbarButton : OsuClickableContainer, IKeyBindingHandler + public abstract partial class ToolbarButton : OsuClickableContainer, IKeyBindingHandler { protected GlobalAction? Hotkey { get; set; } @@ -179,7 +179,7 @@ namespace osu.Game.Overlays.Toolbar HoverBackground.FadeIn(200); tooltipContainer.FadeIn(100); - return base.OnHover(e); + return true; } protected override void OnHoverLost(HoverLostEvent e) @@ -219,7 +219,7 @@ namespace osu.Game.Overlays.Toolbar } } - public class OpaqueBackground : Container + public partial class OpaqueBackground : Container { public OpaqueBackground() { diff --git a/osu.Game/Overlays/Toolbar/ToolbarChangelogButton.cs b/osu.Game/Overlays/Toolbar/ToolbarChangelogButton.cs index 5ce6387196..30e32d831c 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarChangelogButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarChangelogButton.cs @@ -8,7 +8,7 @@ using osu.Framework.Graphics; namespace osu.Game.Overlays.Toolbar { - public class ToolbarChangelogButton : ToolbarOverlayToggleButton + public partial class ToolbarChangelogButton : ToolbarOverlayToggleButton { protected override Anchor TooltipAnchor => Anchor.TopRight; diff --git a/osu.Game/Overlays/Toolbar/ToolbarChatButton.cs b/osu.Game/Overlays/Toolbar/ToolbarChatButton.cs index 86f87deabd..7bb94067ab 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarChatButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarChatButton.cs @@ -9,7 +9,7 @@ using osu.Game.Input.Bindings; namespace osu.Game.Overlays.Toolbar { - public class ToolbarChatButton : ToolbarOverlayToggleButton + public partial class ToolbarChatButton : ToolbarOverlayToggleButton { protected override Anchor TooltipAnchor => Anchor.TopRight; diff --git a/osu.Game/Overlays/Toolbar/ToolbarClock.cs b/osu.Game/Overlays/Toolbar/ToolbarClock.cs index 3fd37d9a62..f1310d8535 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarClock.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarClock.cs @@ -19,7 +19,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Toolbar { - public class ToolbarClock : OsuClickableContainer + public partial class ToolbarClock : OsuClickableContainer { private Bindable clockDisplayMode; private Bindable prefer24HourTime; diff --git a/osu.Game/Overlays/Toolbar/ToolbarHomeButton.cs b/osu.Game/Overlays/Toolbar/ToolbarHomeButton.cs index f170ec84ac..5a1fe40fbf 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarHomeButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarHomeButton.cs @@ -8,7 +8,7 @@ using osu.Game.Input.Bindings; namespace osu.Game.Overlays.Toolbar { - public class ToolbarHomeButton : ToolbarButton + public partial class ToolbarHomeButton : ToolbarButton { public ToolbarHomeButton() { diff --git a/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs b/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs index bd56c60582..69597c6b46 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs @@ -19,7 +19,7 @@ using osuTK.Input; namespace osu.Game.Overlays.Toolbar { - public class ToolbarMusicButton : ToolbarOverlayToggleButton + public partial class ToolbarMusicButton : ToolbarOverlayToggleButton { private Circle volumeBar; diff --git a/osu.Game/Overlays/Toolbar/ToolbarNewsButton.cs b/osu.Game/Overlays/Toolbar/ToolbarNewsButton.cs index 286cfa20f0..bdcf6c3fec 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarNewsButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarNewsButton.cs @@ -8,7 +8,7 @@ using osu.Framework.Graphics; namespace osu.Game.Overlays.Toolbar { - public class ToolbarNewsButton : ToolbarOverlayToggleButton + public partial class ToolbarNewsButton : ToolbarOverlayToggleButton { protected override Anchor TooltipAnchor => Anchor.TopRight; diff --git a/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs b/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs index 265eb044e0..3dfec2cba0 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs @@ -16,7 +16,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Toolbar { - public class ToolbarNotificationButton : ToolbarOverlayToggleButton + public partial class ToolbarNotificationButton : ToolbarOverlayToggleButton { protected override Anchor TooltipAnchor => Anchor.TopRight; @@ -58,7 +58,7 @@ namespace osu.Game.Overlays.Toolbar }; } - private class CountCircle : CompositeDrawable + private partial class CountCircle : CompositeDrawable { private readonly OsuSpriteText countText; private readonly Circle circle; diff --git a/osu.Game/Overlays/Toolbar/ToolbarOverlayToggleButton.cs b/osu.Game/Overlays/Toolbar/ToolbarOverlayToggleButton.cs index 03c365e49e..7bd48174db 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarOverlayToggleButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarOverlayToggleButton.cs @@ -12,7 +12,7 @@ using osu.Game.Graphics; namespace osu.Game.Overlays.Toolbar { - public class ToolbarOverlayToggleButton : ToolbarButton + public partial class ToolbarOverlayToggleButton : ToolbarButton { private readonly Box stateBackground; diff --git a/osu.Game/Overlays/Toolbar/ToolbarRankingsButton.cs b/osu.Game/Overlays/Toolbar/ToolbarRankingsButton.cs index 1bda6da419..ddbf4889b6 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarRankingsButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarRankingsButton.cs @@ -8,7 +8,7 @@ using osu.Framework.Graphics; namespace osu.Game.Overlays.Toolbar { - public class ToolbarRankingsButton : ToolbarOverlayToggleButton + public partial class ToolbarRankingsButton : ToolbarOverlayToggleButton { protected override Anchor TooltipAnchor => Anchor.TopRight; diff --git a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs index 1ca492f81a..715076b368 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs @@ -21,7 +21,7 @@ using osu.Framework.Audio.Sample; namespace osu.Game.Overlays.Toolbar { - public class ToolbarRulesetSelector : RulesetSelector + public partial class ToolbarRulesetSelector : RulesetSelector { protected Drawable ModeButtonLine { get; private set; } diff --git a/osu.Game/Overlays/Toolbar/ToolbarRulesetTabButton.cs b/osu.Game/Overlays/Toolbar/ToolbarRulesetTabButton.cs index 31c6802fda..8f9930e910 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarRulesetTabButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarRulesetTabButton.cs @@ -12,7 +12,7 @@ using osu.Framework.Input.Events; namespace osu.Game.Overlays.Toolbar { - public class ToolbarRulesetTabButton : TabItem + public partial class ToolbarRulesetTabButton : TabItem { private readonly RulesetButton ruleset; @@ -37,7 +37,7 @@ namespace osu.Game.Overlays.Toolbar protected override void OnDeactivated() => ruleset.Active = false; - private class RulesetButton : ToolbarButton + private partial class RulesetButton : ToolbarButton { public bool Active { diff --git a/osu.Game/Overlays/Toolbar/ToolbarSettingsButton.cs b/osu.Game/Overlays/Toolbar/ToolbarSettingsButton.cs index c3d48bc60e..6ebf2a4c02 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarSettingsButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarSettingsButton.cs @@ -8,7 +8,7 @@ using osu.Game.Input.Bindings; namespace osu.Game.Overlays.Toolbar { - public class ToolbarSettingsButton : ToolbarOverlayToggleButton + public partial class ToolbarSettingsButton : ToolbarOverlayToggleButton { public ToolbarSettingsButton() { diff --git a/osu.Game/Overlays/Toolbar/ToolbarSocialButton.cs b/osu.Game/Overlays/Toolbar/ToolbarSocialButton.cs index f8ee39d56e..a8a88813d2 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarSocialButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarSocialButton.cs @@ -9,7 +9,7 @@ using osu.Game.Input.Bindings; namespace osu.Game.Overlays.Toolbar { - public class ToolbarSocialButton : ToolbarOverlayToggleButton + public partial class ToolbarSocialButton : ToolbarOverlayToggleButton { protected override Anchor TooltipAnchor => Anchor.TopRight; diff --git a/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs b/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs index 4ebd19a1f7..028decea1e 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs @@ -20,7 +20,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Toolbar { - public class ToolbarUserButton : ToolbarOverlayToggleButton + public partial class ToolbarUserButton : ToolbarOverlayToggleButton { private UpdateableAvatar avatar = null!; diff --git a/osu.Game/Overlays/Toolbar/ToolbarWikiButton.cs b/osu.Game/Overlays/Toolbar/ToolbarWikiButton.cs index 5511902fa8..49e6be7978 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarWikiButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarWikiButton.cs @@ -8,7 +8,7 @@ using osu.Framework.Graphics; namespace osu.Game.Overlays.Toolbar { - public class ToolbarWikiButton : ToolbarOverlayToggleButton + public partial class ToolbarWikiButton : ToolbarOverlayToggleButton { protected override Anchor TooltipAnchor => Anchor.TopRight; diff --git a/osu.Game/Overlays/UserProfileOverlay.cs b/osu.Game/Overlays/UserProfileOverlay.cs index c0ca63bbd9..8849c674dc 100644 --- a/osu.Game/Overlays/UserProfileOverlay.cs +++ b/osu.Game/Overlays/UserProfileOverlay.cs @@ -1,54 +1,76 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; +using System.Diagnostics; using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; +using osu.Game.Extensions; +using osu.Game.Graphics; using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osu.Game.Online; using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.Profile; using osu.Game.Overlays.Profile.Sections; +using osu.Game.Rulesets; using osu.Game.Users; using osuTK; using osuTK.Graphics; namespace osu.Game.Overlays { - public class UserProfileOverlay : FullscreenOverlay + public partial class UserProfileOverlay : FullscreenOverlay { - private ProfileSection lastSection; - private ProfileSection[] sections; - private GetUserRequest userReq; - private ProfileSectionsContainer sectionsContainer; - private ProfileSectionTabControl tabs; + protected override Container Content => onlineViewContainer; - public const float CONTENT_X_MARGIN = 70; + private readonly OnlineViewContainer onlineViewContainer; + private readonly LoadingLayer loadingLayer; + + private ProfileSection? lastSection; + private ProfileSection[]? sections; + private GetUserRequest? userReq; + private ProfileSectionsContainer? sectionsContainer; + private ProfileSectionTabControl? tabs; + + [Resolved] + private RulesetStore rulesets { get; set; } = null!; + + public const float CONTENT_X_MARGIN = 50; public UserProfileOverlay() : base(OverlayColourScheme.Pink) { + base.Content.AddRange(new Drawable[] + { + onlineViewContainer = new OnlineViewContainer($"Sign in to view the {Header.Title.Title}") + { + RelativeSizeAxes = Axes.Both + }, + loadingLayer = new LoadingLayer(true) + }); } protected override ProfileHeader CreateHeader() => new ProfileHeader(); - protected override Color4 BackgroundColour => ColourProvider.Background6; + protected override Color4 BackgroundColour => ColourProvider.Background5; - public void ShowUser(IUser user) + public void ShowUser(IUser user, IRulesetInfo? ruleset = null) { if (user.OnlineID == APIUser.SYSTEM_USER_ID) return; Show(); - if (user.OnlineID == Header?.User.Value?.Id) + if (user.OnlineID == Header.User.Value?.User.Id && ruleset?.MatchesOnlineID(Header.User.Value?.Ruleset) == true) return; if (sectionsContainer != null) @@ -117,23 +139,20 @@ namespace osu.Game.Overlays sectionsContainer.ScrollToTop(); - // Check arbitrarily whether this user has already been populated. - // This is only generally used by tests, but should be quite safe unless we want to force a refresh on loading a previous user in the future. - if (user is APIUser apiUser && apiUser.JoinDate != default) - { - userReq = null; - userLoadComplete(apiUser); - return; - } - - userReq = user.OnlineID > 1 ? new GetUserRequest(user.OnlineID) : new GetUserRequest(user.Username); - userReq.Success += userLoadComplete; + userReq = user.OnlineID > 1 ? new GetUserRequest(user.OnlineID, ruleset) : new GetUserRequest(user.Username, ruleset); + userReq.Success += u => userLoadComplete(u, ruleset); API.Queue(userReq); + loadingLayer.Show(); } - private void userLoadComplete(APIUser user) + private void userLoadComplete(APIUser user, IRulesetInfo? ruleset) { - Header.User.Value = user; + Debug.Assert(sections != null && sectionsContainer != null && tabs != null); + + var actualRuleset = rulesets.GetRuleset(ruleset?.ShortName ?? user.PlayMode).AsNonNull(); + + var userProfile = new UserProfileData(user, actualRuleset); + Header.User.Value = userProfile; if (user.ProfileOrder != null) { @@ -143,60 +162,88 @@ namespace osu.Game.Overlays if (sec != null) { - sec.User.Value = user; + sec.User.Value = userProfile; sectionsContainer.Add(sec); tabs.AddItem(sec); } } } + + loadingLayer.Hide(); } - private class ProfileSectionTabControl : OverlayTabControl + private partial class ProfileSectionTabControl : OsuTabControl { - private const float bar_height = 2; - public ProfileSectionTabControl() { - TabContainer.RelativeSizeAxes &= ~Axes.X; - TabContainer.AutoSizeAxes |= Axes.X; - TabContainer.Anchor |= Anchor.x1; - TabContainer.Origin |= Anchor.x1; - - Height = 36 + bar_height; - BarHeight = bar_height; + Height = 40; + Padding = new MarginPadding { Horizontal = CONTENT_X_MARGIN }; + TabContainer.Spacing = new Vector2(20); } - protected override TabItem CreateTabItem(ProfileSection value) => new ProfileSectionTabItem(value) - { - AccentColour = AccentColour, - }; - - [BackgroundDependencyLoader] - private void load(OverlayColourProvider colourProvider) - { - AccentColour = colourProvider.Highlight1; - } + protected override TabItem CreateTabItem(ProfileSection value) => new ProfileSectionTabItem(value); protected override bool OnClick(ClickEvent e) => true; protected override bool OnHover(HoverEvent e) => true; - private class ProfileSectionTabItem : OverlayTabItem + private partial class ProfileSectionTabItem : TabItem { + private OsuSpriteText text = null!; + + [Resolved] + private OverlayColourProvider colourProvider { get; set; } = null!; + public ProfileSectionTabItem(ProfileSection value) : base(value) { - Text.Text = value.Title; - Text.Font = Text.Font.With(size: 16); - Text.Margin = new MarginPadding { Bottom = 10 + bar_height }; - Bar.ExpandedSize = 10; - Bar.Margin = new MarginPadding { Bottom = bar_height }; + } + + [BackgroundDependencyLoader] + private void load() + { + AutoSizeAxes = Axes.Both; + Anchor = Anchor.CentreLeft; + Origin = Anchor.CentreLeft; + + InternalChild = text = new OsuSpriteText + { + Text = Value.Title + }; + + updateState(); + } + + protected override void OnActivated() => updateState(); + + protected override void OnDeactivated() => updateState(); + + protected override bool OnHover(HoverEvent e) + { + updateState(); + return true; + } + + protected override void OnHoverLost(HoverLostEvent e) => updateState(); + + private void updateState() + { + text.Font = OsuFont.Default.With(size: 14, weight: Active.Value ? FontWeight.SemiBold : FontWeight.Regular); + + Colour4 textColour; + + if (IsHovered) + textColour = colourProvider.Light1; + else + textColour = Active.Value ? colourProvider.Content1 : colourProvider.Light2; + + text.FadeColour(textColour, 300, Easing.OutQuint); } } } - private class ProfileSectionsContainer : SectionsContainer + private partial class ProfileSectionsContainer : SectionsContainer { public ProfileSectionsContainer() { @@ -205,12 +252,16 @@ namespace osu.Game.Overlays protected override UserTrackingScrollContainer CreateScrollContainer() => new OverlayScrollContainer(); - protected override FlowContainer CreateScrollContentContainer() => new FillFlowContainer + // Reverse child ID is required so expanding beatmap panels can appear above sections below them. + // This can also be done by setting Depth when adding new sections above if using ReverseChildID turns out to have any issues. + protected override FlowContainer CreateScrollContentContainer() => new ReverseChildIDFillFlowContainer { Direction = FillDirection.Vertical, AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, - Spacing = new Vector2(0, 20), + Spacing = new Vector2(0, 10), + Padding = new MarginPadding { Horizontal = 10 }, + Margin = new MarginPadding { Bottom = 10 }, }; } } diff --git a/osu.Game/Overlays/VersionManager.cs b/osu.Game/Overlays/VersionManager.cs index a1cfdf4594..0e74cada29 100644 --- a/osu.Game/Overlays/VersionManager.cs +++ b/osu.Game/Overlays/VersionManager.cs @@ -16,7 +16,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays { - public class VersionManager : VisibilityContainer + public partial class VersionManager : VisibilityContainer { [BackgroundDependencyLoader] private void load(OsuColour colours, TextureStore textures, OsuGameBase game) diff --git a/osu.Game/Overlays/Volume/MuteButton.cs b/osu.Game/Overlays/Volume/MuteButton.cs index 744b2bafbd..c83ad4ac0d 100644 --- a/osu.Game/Overlays/Volume/MuteButton.cs +++ b/osu.Game/Overlays/Volume/MuteButton.cs @@ -19,7 +19,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Volume { - public class MuteButton : OsuButton, IHasCurrentValue + public partial class MuteButton : OsuButton, IHasCurrentValue { private readonly Bindable current = new Bindable(); @@ -28,8 +28,7 @@ namespace osu.Game.Overlays.Volume get => current; set { - if (value == null) - throw new ArgumentNullException(nameof(value)); + ArgumentNullException.ThrowIfNull(value); current.UnbindBindings(); current.BindTo(value); @@ -89,5 +88,13 @@ namespace osu.Game.Overlays.Volume { Content.TransformTo, ColourInfo>("BorderColour", unhoveredColour, 500, Easing.OutQuint); } + + protected override bool OnMouseDown(MouseDownEvent e) + { + base.OnMouseDown(e); + + // Block mouse down to avoid dismissing overlays sitting behind the mute button + return true; + } } } diff --git a/osu.Game/Overlays/Volume/VolumeControlReceptor.cs b/osu.Game/Overlays/Volume/VolumeControlReceptor.cs index 624be0b25c..4ddbc9dd48 100644 --- a/osu.Game/Overlays/Volume/VolumeControlReceptor.cs +++ b/osu.Game/Overlays/Volume/VolumeControlReceptor.cs @@ -12,7 +12,7 @@ using osu.Game.Input.Bindings; namespace osu.Game.Overlays.Volume { - public class VolumeControlReceptor : Container, IScrollBindingHandler, IHandleGlobalKeyboardInput + public partial class VolumeControlReceptor : Container, IScrollBindingHandler, IHandleGlobalKeyboardInput { public Func ActionRequested; public Func ScrollActionRequested; diff --git a/osu.Game/Overlays/Volume/VolumeMeter.cs b/osu.Game/Overlays/Volume/VolumeMeter.cs index e01890ddc2..d366f0bddb 100644 --- a/osu.Game/Overlays/Volume/VolumeMeter.cs +++ b/osu.Game/Overlays/Volume/VolumeMeter.cs @@ -29,7 +29,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Volume { - public class VolumeMeter : Container, IStateful + public partial class VolumeMeter : Container, IStateful { private CircularProgress volumeCircle; private CircularProgress volumeCircleGlow; diff --git a/osu.Game/Overlays/VolumeOverlay.cs b/osu.Game/Overlays/VolumeOverlay.cs index 4cedd87eac..5470c70400 100644 --- a/osu.Game/Overlays/VolumeOverlay.cs +++ b/osu.Game/Overlays/VolumeOverlay.cs @@ -23,7 +23,7 @@ using osuTK.Input; namespace osu.Game.Overlays { - public class VolumeOverlay : VisibilityContainer + public partial class VolumeOverlay : VisibilityContainer { private const float offset = 10; diff --git a/osu.Game/Overlays/WaveOverlayContainer.cs b/osu.Game/Overlays/WaveOverlayContainer.cs index faf2cca8cf..d25f6a9ae5 100644 --- a/osu.Game/Overlays/WaveOverlayContainer.cs +++ b/osu.Game/Overlays/WaveOverlayContainer.cs @@ -9,7 +9,7 @@ using osu.Game.Graphics.Containers; namespace osu.Game.Overlays { - public abstract class WaveOverlayContainer : OsuFocusedOverlayContainer + public abstract partial class WaveOverlayContainer : OsuFocusedOverlayContainer { protected readonly WaveContainer Waves; diff --git a/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownContainer.cs b/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownContainer.cs index 15c455416c..7c36caa62f 100644 --- a/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownContainer.cs +++ b/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownContainer.cs @@ -14,10 +14,14 @@ using osu.Game.Graphics.Containers.Markdown; namespace osu.Game.Overlays.Wiki.Markdown { - public class WikiMarkdownContainer : OsuMarkdownContainer + public partial class WikiMarkdownContainer : OsuMarkdownContainer { - protected override bool Footnotes => true; - protected override bool CustomContainers => true; + protected override OsuMarkdownContainerOptions Options => new OsuMarkdownContainerOptions + { + Footnotes = true, + CustomContainers = true, + BlockAttributes = true + }; public string CurrentPath { @@ -53,7 +57,7 @@ namespace osu.Game.Overlays.Wiki.Markdown public override MarkdownTextFlowContainer CreateTextFlow() => new WikiMarkdownTextFlowContainer(); - private class WikiMarkdownTextFlowContainer : OsuMarkdownTextFlowContainer + private partial class WikiMarkdownTextFlowContainer : OsuMarkdownTextFlowContainer { protected override void AddImage(LinkInline linkInline) => AddDrawable(new WikiMarkdownImage(linkInline)); } diff --git a/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImage.cs b/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImage.cs index 1c7a08930b..71c2df538d 100644 --- a/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImage.cs +++ b/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImage.cs @@ -8,7 +8,7 @@ using osu.Game.Graphics.Containers.Markdown; namespace osu.Game.Overlays.Wiki.Markdown { - public class WikiMarkdownImage : OsuMarkdownImage + public partial class WikiMarkdownImage : OsuMarkdownImage { public WikiMarkdownImage(LinkInline linkInline) : base(linkInline) diff --git a/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs b/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs index 5ce3f179a4..641c6242b6 100644 --- a/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs +++ b/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs @@ -13,7 +13,7 @@ using osuTK; namespace osu.Game.Overlays.Wiki.Markdown { - public class WikiMarkdownImageBlock : FillFlowContainer + public partial class WikiMarkdownImageBlock : FillFlowContainer { [Resolved] private IMarkdownTextFlowComponent parentFlowComponent { get; set; } @@ -49,7 +49,7 @@ namespace osu.Game.Overlays.Wiki.Markdown textFlow.AddText(linkInline.Title); } - private class BlockMarkdownImage : WikiMarkdownImage + private partial class BlockMarkdownImage : WikiMarkdownImage { public BlockMarkdownImage(LinkInline linkInline) : base(linkInline) @@ -60,7 +60,7 @@ namespace osu.Game.Overlays.Wiki.Markdown protected override ImageContainer CreateImageContainer(string url) => new BlockImageContainer(url); - private class BlockImageContainer : ImageContainer + private partial class BlockImageContainer : ImageContainer { public BlockImageContainer(string url) : base(url) @@ -71,7 +71,7 @@ namespace osu.Game.Overlays.Wiki.Markdown protected override Sprite CreateImageSprite() => new ImageSprite(); - private class ImageSprite : Sprite + private partial class ImageSprite : Sprite { public ImageSprite() { diff --git a/osu.Game/Overlays/Wiki/Markdown/WikiNoticeContainer.cs b/osu.Game/Overlays/Wiki/Markdown/WikiNoticeContainer.cs index 64d7e20d9b..5f8bee7558 100644 --- a/osu.Game/Overlays/Wiki/Markdown/WikiNoticeContainer.cs +++ b/osu.Game/Overlays/Wiki/Markdown/WikiNoticeContainer.cs @@ -15,7 +15,7 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Wiki.Markdown { - public class WikiNoticeContainer : FillFlowContainer + public partial class WikiNoticeContainer : FillFlowContainer { private readonly bool isOutdated; private readonly bool needsCleanup; @@ -62,7 +62,7 @@ namespace osu.Game.Overlays.Wiki.Markdown } } - private class NoticeBox : Container + private partial class NoticeBox : Container { [Resolved] private IMarkdownTextFlowComponent parentFlowComponent { get; set; } diff --git a/osu.Game/Overlays/Wiki/WikiArticlePage.cs b/osu.Game/Overlays/Wiki/WikiArticlePage.cs index f4ba0a4d8d..6c1dbe3181 100644 --- a/osu.Game/Overlays/Wiki/WikiArticlePage.cs +++ b/osu.Game/Overlays/Wiki/WikiArticlePage.cs @@ -12,7 +12,7 @@ using osu.Game.Overlays.Wiki.Markdown; namespace osu.Game.Overlays.Wiki { - public class WikiArticlePage : CompositeDrawable + public partial class WikiArticlePage : CompositeDrawable { public Container SidebarContainer { get; } @@ -65,7 +65,7 @@ namespace osu.Game.Overlays.Wiki }; } - private class ArticleMarkdownContainer : WikiMarkdownContainer + private partial class ArticleMarkdownContainer : WikiMarkdownContainer { public Action OnAddHeading; diff --git a/osu.Game/Overlays/Wiki/WikiHeader.cs b/osu.Game/Overlays/Wiki/WikiHeader.cs index fc8df03892..9317813fc4 100644 --- a/osu.Game/Overlays/Wiki/WikiHeader.cs +++ b/osu.Game/Overlays/Wiki/WikiHeader.cs @@ -14,7 +14,7 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Wiki { - public class WikiHeader : BreadcrumbControlOverlayHeader + public partial class WikiHeader : BreadcrumbControlOverlayHeader { private const string index_path = "Main_Page"; @@ -75,7 +75,7 @@ namespace osu.Game.Overlays.Wiki protected override OverlayTitle CreateTitle() => new WikiHeaderTitle(); - private class WikiHeaderTitle : OverlayTitle + private partial class WikiHeaderTitle : OverlayTitle { public WikiHeaderTitle() { diff --git a/osu.Game/Overlays/Wiki/WikiMainPage.cs b/osu.Game/Overlays/Wiki/WikiMainPage.cs index 67e4bdf2e5..457309ae44 100644 --- a/osu.Game/Overlays/Wiki/WikiMainPage.cs +++ b/osu.Game/Overlays/Wiki/WikiMainPage.cs @@ -15,7 +15,7 @@ using osu.Game.Graphics.Containers; namespace osu.Game.Overlays.Wiki { - public class WikiMainPage : FillFlowContainer + public partial class WikiMainPage : FillFlowContainer { public string Markdown; diff --git a/osu.Game/Overlays/Wiki/WikiPanelContainer.cs b/osu.Game/Overlays/Wiki/WikiPanelContainer.cs index 552770f098..ef31e9cfdd 100644 --- a/osu.Game/Overlays/Wiki/WikiPanelContainer.cs +++ b/osu.Game/Overlays/Wiki/WikiPanelContainer.cs @@ -22,7 +22,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Wiki { - public class WikiPanelContainer : Container + public partial class WikiPanelContainer : Container { private WikiPanelMarkdownContainer panelContainer; @@ -78,7 +78,7 @@ namespace osu.Game.Overlays.Wiki Height = Math.Max(panelContainer.Height, Parent.DrawHeight); } - private class WikiPanelMarkdownContainer : WikiMarkdownContainer + private partial class WikiPanelMarkdownContainer : WikiMarkdownContainer { private readonly bool isFullWidth; @@ -104,7 +104,7 @@ namespace osu.Game.Overlays.Wiki }; } - private class WikiPanelHeading : OsuMarkdownHeading + private partial class WikiPanelHeading : OsuMarkdownHeading { public bool IsFullWidth; diff --git a/osu.Game/Overlays/Wiki/WikiSidebar.cs b/osu.Game/Overlays/Wiki/WikiSidebar.cs index 78ce9c8a24..4c8fe83703 100644 --- a/osu.Game/Overlays/Wiki/WikiSidebar.cs +++ b/osu.Game/Overlays/Wiki/WikiSidebar.cs @@ -15,7 +15,7 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Wiki { - public class WikiSidebar : OverlaySidebar + public partial class WikiSidebar : OverlaySidebar { private WikiTableOfContents tableOfContents; diff --git a/osu.Game/Overlays/Wiki/WikiTableOfContents.cs b/osu.Game/Overlays/Wiki/WikiTableOfContents.cs index d60d728aca..5566233c39 100644 --- a/osu.Game/Overlays/Wiki/WikiTableOfContents.cs +++ b/osu.Game/Overlays/Wiki/WikiTableOfContents.cs @@ -13,7 +13,7 @@ using osu.Game.Graphics.Containers; namespace osu.Game.Overlays.Wiki { - public class WikiTableOfContents : CompositeDrawable + public partial class WikiTableOfContents : CompositeDrawable { private readonly FillFlowContainer content; @@ -54,7 +54,7 @@ namespace osu.Game.Overlays.Wiki content.Add(lastMainTitle = entry.With(d => d.Margin = new MarginPadding { Bottom = 5 })); } - private class TableOfContentsEntry : OsuHoverContainer + private partial class TableOfContentsEntry : OsuHoverContainer { private readonly MarkdownHeading target; diff --git a/osu.Game/Overlays/WikiOverlay.cs b/osu.Game/Overlays/WikiOverlay.cs index 148d2977c7..88dc2cd7a4 100644 --- a/osu.Game/Overlays/WikiOverlay.cs +++ b/osu.Game/Overlays/WikiOverlay.cs @@ -17,10 +17,12 @@ using osu.Game.Overlays.Wiki; namespace osu.Game.Overlays { - public class WikiOverlay : OnlineOverlay + public partial class WikiOverlay : OnlineOverlay { private const string index_path = @"main_page"; + public string CurrentPath => path.Value; + private readonly Bindable path = new Bindable(index_path); private readonly Bindable wikiData = new Bindable(); @@ -105,6 +107,9 @@ namespace osu.Game.Overlays if (e.NewValue == wikiData.Value?.Path) return; + if (e.NewValue == "error") + return; + cancellationToken?.Cancel(); request?.Cancel(); @@ -118,7 +123,11 @@ namespace osu.Game.Overlays Loading.Show(); request.Success += response => Schedule(() => onSuccess(response)); - request.Failure += _ => Schedule(onFail); + request.Failure += ex => + { + if (ex is not OperationCanceledException) + Schedule(onFail, request.Path); + }; api.PerformAsync(request); } @@ -146,10 +155,11 @@ namespace osu.Game.Overlays } } - private void onFail() + private void onFail(string originalPath) { + path.Value = "error"; LoadDisplay(articlePage = new WikiArticlePage($@"{api.WebsiteRootUrl}/wiki/", - $"Something went wrong when trying to fetch page \"{path.Value}\".\n\n[Return to the main page](Main_Page).")); + $"Something went wrong when trying to fetch page \"{originalPath}\".\n\n[Return to the main page](Main_Page).")); } private void showParentPage() diff --git a/osu.Game/PerformFromMenuRunner.cs b/osu.Game/PerformFromMenuRunner.cs index 158350b43d..21beadf366 100644 --- a/osu.Game/PerformFromMenuRunner.cs +++ b/osu.Game/PerformFromMenuRunner.cs @@ -18,7 +18,7 @@ using osu.Game.Screens.Menu; namespace osu.Game { - internal class PerformFromMenuRunner : Component + internal partial class PerformFromMenuRunner : Component { private readonly Action finalAction; private readonly Type[] validScreens; diff --git a/osu.Game/Performance/HighPerformanceSession.cs b/osu.Game/Performance/HighPerformanceSession.cs index dd5de03077..c113e7a342 100644 --- a/osu.Game/Performance/HighPerformanceSession.cs +++ b/osu.Game/Performance/HighPerformanceSession.cs @@ -10,7 +10,7 @@ using osu.Game.Screens.Play; namespace osu.Game.Performance { - public class HighPerformanceSession : Component + public partial class HighPerformanceSession : Component { private readonly IBindable localUserPlaying = new Bindable(); diff --git a/osu.Game/Rulesets/Configuration/RulesetConfigManager.cs b/osu.Game/Rulesets/Configuration/RulesetConfigManager.cs index 4ff4f66665..0eea1ff215 100644 --- a/osu.Game/Rulesets/Configuration/RulesetConfigManager.cs +++ b/osu.Game/Rulesets/Configuration/RulesetConfigManager.cs @@ -5,9 +5,11 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using osu.Framework.Bindables; using osu.Framework.Configuration; +using osu.Framework.Extensions; using osu.Game.Configuration; using osu.Game.Database; @@ -67,7 +69,7 @@ namespace osu.Game.Rulesets.Configuration { var setting = r.All().First(s => s.RulesetName == rulesetName && s.Variant == variant && s.Key == c.ToString()); - setting.Value = ConfigStore[c].ToString(); + setting.Value = ConfigStore[c].ToString(CultureInfo.InvariantCulture); } }); @@ -89,7 +91,7 @@ namespace osu.Game.Rulesets.Configuration setting = new RealmRulesetSetting { Key = lookup.ToString(), - Value = bindable.Value.ToString(), + Value = bindable.ToString(CultureInfo.InvariantCulture), RulesetName = rulesetName, Variant = variant, }; diff --git a/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs b/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs index b0a2694a0a..0df481737e 100644 --- a/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs @@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Edit /// Represents a for rulesets with the concept of distances between objects. /// /// The base type of supported objects. - public abstract class DistancedHitObjectComposer : HitObjectComposer, IDistanceSnapProvider, IScrollBindingHandler + public abstract partial class DistancedHitObjectComposer : HitObjectComposer, IDistanceSnapProvider, IScrollBindingHandler where TObject : HitObject { private const float adjust_step = 0.1f; @@ -297,7 +297,7 @@ namespace osu.Game.Rulesets.Edit return DurationToDistance(referenceObject, snappedEndTime - startTime); } - private class DistanceSpacingToast : Toast + private partial class DistanceSpacingToast : Toast { private readonly ValueChangedEvent change; diff --git a/osu.Game/Rulesets/Edit/DrawableEditorRulesetWrapper.cs b/osu.Game/Rulesets/Edit/DrawableEditorRulesetWrapper.cs index 9588a092a8..20ee409937 100644 --- a/osu.Game/Rulesets/Edit/DrawableEditorRulesetWrapper.cs +++ b/osu.Game/Rulesets/Edit/DrawableEditorRulesetWrapper.cs @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Edit /// /// A wrapper for a . Handles adding visual representations of s to the underlying . /// - internal class DrawableEditorRulesetWrapper : CompositeDrawable + internal partial class DrawableEditorRulesetWrapper : CompositeDrawable where TObject : HitObject { public Playfield Playfield => drawableRuleset.Playfield; diff --git a/osu.Game/Rulesets/Edit/EditorToolboxGroup.cs b/osu.Game/Rulesets/Edit/EditorToolboxGroup.cs index 7dcc90b16d..312ba62b61 100644 --- a/osu.Game/Rulesets/Edit/EditorToolboxGroup.cs +++ b/osu.Game/Rulesets/Edit/EditorToolboxGroup.cs @@ -8,7 +8,7 @@ using osu.Game.Overlays; namespace osu.Game.Rulesets.Edit { - public class EditorToolboxGroup : SettingsToolboxGroup + public partial class EditorToolboxGroup : SettingsToolboxGroup { public EditorToolboxGroup(string title) : base(title) diff --git a/osu.Game/Rulesets/Edit/ExpandableButton.cs b/osu.Game/Rulesets/Edit/ExpandableButton.cs index a66600bd58..a708f76845 100644 --- a/osu.Game/Rulesets/Edit/ExpandableButton.cs +++ b/osu.Game/Rulesets/Edit/ExpandableButton.cs @@ -11,7 +11,7 @@ using osu.Game.Graphics.UserInterfaceV2; namespace osu.Game.Rulesets.Edit { - internal class ExpandableButton : RoundedButton, IExpandable + internal partial class ExpandableButton : RoundedButton, IExpandable { private float actualHeight; @@ -86,6 +86,7 @@ namespace osu.Game.Rulesets.Edit SpriteText.Font = OsuFont.GetFont(weight: FontWeight.Bold); base.Height = actualHeight; Background.Show(); + Triangles?.Show(); } else { @@ -94,6 +95,7 @@ namespace osu.Game.Rulesets.Edit SpriteText.Font = OsuFont.GetFont(weight: FontWeight.Regular); base.Height = actualHeight / 2; Background.Hide(); + Triangles?.Hide(); } }, true); } diff --git a/osu.Game/Rulesets/Edit/ExpandingToolboxContainer.cs b/osu.Game/Rulesets/Edit/ExpandingToolboxContainer.cs index 26dd5dfa55..7bf10f6beb 100644 --- a/osu.Game/Rulesets/Edit/ExpandingToolboxContainer.cs +++ b/osu.Game/Rulesets/Edit/ExpandingToolboxContainer.cs @@ -10,7 +10,7 @@ using osuTK; namespace osu.Game.Rulesets.Edit { - public class ExpandingToolboxContainer : ExpandingContainer + public partial class ExpandingToolboxContainer : ExpandingContainer { protected override double HoverExpansionDelay => 250; diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 520fcb0290..b5b7400f64 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -40,13 +40,11 @@ namespace osu.Game.Rulesets.Edit /// Responsible for providing snapping and generally gluing components together. /// /// The base type of supported objects. - public abstract class HitObjectComposer : HitObjectComposer, IPlacementHandler + public abstract partial class HitObjectComposer : HitObjectComposer, IPlacementHandler where TObject : HitObject { protected IRulesetConfigManager Config { get; private set; } - protected readonly Ruleset Ruleset; - // Provides `Playfield` private DependencyContainer dependencies; @@ -74,8 +72,8 @@ namespace osu.Game.Rulesets.Edit private IBindable hasTiming; protected HitObjectComposer(Ruleset ruleset) + : base(ruleset) { - Ruleset = ruleset; } protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) => @@ -417,10 +415,13 @@ namespace osu.Game.Rulesets.Edit /// Generally used to access certain methods without requiring a generic type for . /// [Cached] - public abstract class HitObjectComposer : CompositeDrawable, IPositionSnapProvider + public abstract partial class HitObjectComposer : CompositeDrawable, IPositionSnapProvider { - protected HitObjectComposer() + public readonly Ruleset Ruleset; + + protected HitObjectComposer(Ruleset ruleset) { + Ruleset = ruleset; RelativeSizeAxes = Axes.Both; } diff --git a/osu.Game/Rulesets/Edit/HitObjectSelectionBlueprint.cs b/osu.Game/Rulesets/Edit/HitObjectSelectionBlueprint.cs index 408fbfc04f..93b889792b 100644 --- a/osu.Game/Rulesets/Edit/HitObjectSelectionBlueprint.cs +++ b/osu.Game/Rulesets/Edit/HitObjectSelectionBlueprint.cs @@ -14,7 +14,7 @@ using osuTK; namespace osu.Game.Rulesets.Edit { - public abstract class HitObjectSelectionBlueprint : SelectionBlueprint + public abstract partial class HitObjectSelectionBlueprint : SelectionBlueprint { /// /// The which this applies to. @@ -51,7 +51,7 @@ namespace osu.Game.Rulesets.Edit public override Quad SelectionQuad => DrawableObject.ScreenSpaceDrawQuad; } - public abstract class HitObjectSelectionBlueprint : HitObjectSelectionBlueprint + public abstract partial class HitObjectSelectionBlueprint : HitObjectSelectionBlueprint where T : HitObject { public T HitObject => (T)Item; diff --git a/osu.Game/Rulesets/Edit/IBeatSnapProvider.cs b/osu.Game/Rulesets/Edit/IBeatSnapProvider.cs index dbad407b75..5e45cefe8c 100644 --- a/osu.Game/Rulesets/Edit/IBeatSnapProvider.cs +++ b/osu.Game/Rulesets/Edit/IBeatSnapProvider.cs @@ -1,14 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - namespace osu.Game.Rulesets.Edit { public interface IBeatSnapProvider { /// - /// Snaps a duration to the closest beat of a timing point applicable at the reference time. + /// Snaps a duration to the closest beat of a timing point applicable at the reference time, factoring in the current . /// /// The time to snap. /// An optional reference point to use for timing point lookup. @@ -16,10 +14,10 @@ namespace osu.Game.Rulesets.Edit double SnapTime(double time, double? referenceTime = null); /// - /// Get the most appropriate beat length at a given time. + /// Get the most appropriate beat length at a given time, pre-divided by . /// /// A reference time used for lookup. - /// The most appropriate beat length. + /// The most appropriate beat length, divided by . double GetBeatLengthAtTime(double referenceTime); /// diff --git a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs index c8196b6865..dd8dd93d66 100644 --- a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs +++ b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs @@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Edit /// /// A blueprint which governs the creation of a new to actualisation. /// - public abstract class PlacementBlueprint : CompositeDrawable + public abstract partial class PlacementBlueprint : CompositeDrawable { /// /// Whether the is currently mid-placement, but has not necessarily finished being placed. diff --git a/osu.Game/Rulesets/Edit/SelectionBlueprint.cs b/osu.Game/Rulesets/Edit/SelectionBlueprint.cs index fc24b55d21..4e0e45e0f5 100644 --- a/osu.Game/Rulesets/Edit/SelectionBlueprint.cs +++ b/osu.Game/Rulesets/Edit/SelectionBlueprint.cs @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Edit /// /// A blueprint placed above a displaying item adding editing functionality. /// - public abstract class SelectionBlueprint : CompositeDrawable, IStateful + public abstract partial class SelectionBlueprint : CompositeDrawable, IStateful { public readonly T Item; diff --git a/osu.Game/Rulesets/Judgements/DefaultJudgementPiece.cs b/osu.Game/Rulesets/Judgements/DefaultJudgementPiece.cs index c2b27d4ce8..d5f586dc35 100644 --- a/osu.Game/Rulesets/Judgements/DefaultJudgementPiece.cs +++ b/osu.Game/Rulesets/Judgements/DefaultJudgementPiece.cs @@ -1,12 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - -using osu.Framework.Allocation; -using osu.Framework.Extensions; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; @@ -15,40 +10,25 @@ using osuTK; namespace osu.Game.Rulesets.Judgements { - public class DefaultJudgementPiece : CompositeDrawable, IAnimatableJudgement + public partial class DefaultJudgementPiece : JudgementPiece, IAnimatableJudgement { - protected readonly HitResult Result; - - protected SpriteText JudgementText { get; private set; } - - [Resolved] - private OsuColour colours { get; set; } - public DefaultJudgementPiece(HitResult result) - { - Result = result; - Origin = Anchor.Centre; - } - - [BackgroundDependencyLoader] - private void load() + : base(result) { AutoSizeAxes = Axes.Both; - InternalChildren = new Drawable[] - { - JudgementText = new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Text = Result.GetDescription().ToUpperInvariant(), - Colour = colours.ForHitResult(Result), - Font = OsuFont.Numeric.With(size: 20), - Scale = new Vector2(0.85f, 1), - } - }; + Origin = Anchor.Centre; } + protected override SpriteText CreateJudgementText() => + new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = OsuFont.Numeric.With(size: 20), + Scale = new Vector2(0.85f, 1), + }; + /// /// Plays the default animation for this judgement piece. /// @@ -75,6 +55,6 @@ namespace osu.Game.Rulesets.Judgements this.FadeOutFromOne(800); } - public Drawable GetAboveHitObjectsProxiedContent() => null; + public Drawable? GetAboveHitObjectsProxiedContent() => null; } } diff --git a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs index 48955c729f..15434fcc04 100644 --- a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs +++ b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs @@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Judgements /// /// A drawable object which visualises the hit result of a . /// - public class DrawableJudgement : PoolableDrawable + public partial class DrawableJudgement : PoolableDrawable { private const float judgement_size = 128; diff --git a/osu.Game/Rulesets/Judgements/JudgementPiece.cs b/osu.Game/Rulesets/Judgements/JudgementPiece.cs new file mode 100644 index 0000000000..03f211c318 --- /dev/null +++ b/osu.Game/Rulesets/Judgements/JudgementPiece.cs @@ -0,0 +1,38 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Extensions; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics; +using osu.Game.Rulesets.Scoring; + +namespace osu.Game.Rulesets.Judgements +{ + public abstract partial class JudgementPiece : CompositeDrawable + { + protected readonly HitResult Result; + + protected SpriteText JudgementText { get; private set; } = null!; + + [Resolved] + private OsuColour colours { get; set; } = null!; + + protected JudgementPiece(HitResult result) + { + Result = result; + } + + [BackgroundDependencyLoader] + private void load() + { + AddInternal(JudgementText = CreateJudgementText()); + + JudgementText.Colour = colours.ForHitResult(Result); + JudgementText.Text = Result.GetDescription().ToUpperInvariant(); + } + + protected abstract SpriteText CreateJudgementText(); + } +} diff --git a/osu.Game/Rulesets/Mods/DifficultyAdjustSettingsControl.cs b/osu.Game/Rulesets/Mods/DifficultyAdjustSettingsControl.cs index 599e81f2b8..38ced4c9e7 100644 --- a/osu.Game/Rulesets/Mods/DifficultyAdjustSettingsControl.cs +++ b/osu.Game/Rulesets/Mods/DifficultyAdjustSettingsControl.cs @@ -15,7 +15,7 @@ using osu.Game.Overlays.Settings; namespace osu.Game.Rulesets.Mods { - public class DifficultyAdjustSettingsControl : SettingsItem + public partial class DifficultyAdjustSettingsControl : SettingsItem { [Resolved] private IBindable beatmap { get; set; } @@ -88,7 +88,7 @@ namespace osu.Game.Rulesets.Mods isInternalChange = false; } - private class SliderControl : CompositeDrawable, IHasCurrentValue + private partial class SliderControl : CompositeDrawable, IHasCurrentValue { // This is required as SettingsItem relies heavily on this bindable for internal use. // The actual update flow is done via the bindable provided in the constructor. @@ -126,8 +126,7 @@ namespace osu.Game.Rulesets.Mods get => this; set { - if (value == null) - throw new ArgumentNullException(nameof(value)); + ArgumentNullException.ThrowIfNull(value); if (currentBound != null) UnbindFrom(currentBound); BindTo(currentBound = value); diff --git a/osu.Game/Rulesets/Mods/DifficultyBindable.cs b/osu.Game/Rulesets/Mods/DifficultyBindable.cs index 34e9fe40a3..c21ce756c9 100644 --- a/osu.Game/Rulesets/Mods/DifficultyBindable.cs +++ b/osu.Game/Rulesets/Mods/DifficultyBindable.cs @@ -99,21 +99,37 @@ namespace osu.Game.Rulesets.Mods CurrentNumber.MaxValue = ExtendedLimits.Value && extendedMaxValue != null ? extendedMaxValue.Value : maxValue; } + public override void CopyTo(Bindable them) + { + if (!(them is DifficultyBindable otherDifficultyBindable)) + throw new InvalidOperationException($"Cannot copy to a non-{nameof(DifficultyBindable)}."); + + base.CopyTo(them); + + otherDifficultyBindable.ReadCurrentFromDifficulty = ReadCurrentFromDifficulty; + + // the following max value copies are only safe as long as these values are effectively constants. + otherDifficultyBindable.MaxValue = maxValue; + otherDifficultyBindable.ExtendedMaxValue = extendedMaxValue; + } + public override void BindTo(Bindable them) { if (!(them is DifficultyBindable otherDifficultyBindable)) throw new InvalidOperationException($"Cannot bind to a non-{nameof(DifficultyBindable)}."); - ReadCurrentFromDifficulty = otherDifficultyBindable.ReadCurrentFromDifficulty; - - // the following max value copies are only safe as long as these values are effectively constants. - MaxValue = otherDifficultyBindable.maxValue; - ExtendedMaxValue = otherDifficultyBindable.extendedMaxValue; + // ensure that MaxValue and ExtendedMaxValue are copied across first before continuing. + // not doing so may cause the value of CurrentNumber to be truncated to 10. + otherDifficultyBindable.CopyTo(this); + // set up mutual binding for ExtendedLimits to correctly set the upper bound of CurrentNumber. ExtendedLimits.BindTarget = otherDifficultyBindable.ExtendedLimits; - // the actual values need to be copied after the max value constraints. + // set up mutual binding for CurrentNumber. this must happen after all of the above. CurrentNumber.BindTarget = otherDifficultyBindable.CurrentNumber; + + // finish up the binding by setting up weak references via the base call. + // unfortunately this will call `.CopyTo()` again, but fixing that is problematic and messy. base.BindTo(them); } diff --git a/osu.Game/Rulesets/Mods/IMod.cs b/osu.Game/Rulesets/Mods/IMod.cs index 1f9e26c9d7..05b2510e53 100644 --- a/osu.Game/Rulesets/Mods/IMod.cs +++ b/osu.Game/Rulesets/Mods/IMod.cs @@ -55,6 +55,6 @@ namespace osu.Game.Rulesets.Mods /// /// Create a fresh instance based on this mod. /// - Mod CreateInstance() => (Mod)Activator.CreateInstance(GetType()); + Mod CreateInstance() => (Mod)Activator.CreateInstance(GetType())!; } } diff --git a/osu.Game/Rulesets/Mods/MetronomeBeat.cs b/osu.Game/Rulesets/Mods/MetronomeBeat.cs index 149af1e30a..265970ea46 100644 --- a/osu.Game/Rulesets/Mods/MetronomeBeat.cs +++ b/osu.Game/Rulesets/Mods/MetronomeBeat.cs @@ -11,7 +11,7 @@ using osu.Game.Skinning; namespace osu.Game.Rulesets.Mods { - public class MetronomeBeat : BeatSyncedContainer, IAdjustableAudioComponent + public partial class MetronomeBeat : BeatSyncedContainer, IAdjustableAudioComponent { private readonly double firstHitTime; diff --git a/osu.Game/Rulesets/Mods/Mod.cs b/osu.Game/Rulesets/Mods/Mod.cs index 98df540de4..04d55bc5fe 100644 --- a/osu.Game/Rulesets/Mods/Mod.cs +++ b/osu.Game/Rulesets/Mods/Mod.cs @@ -70,7 +70,7 @@ namespace osu.Game.Rulesets.Mods foreach ((SettingSourceAttribute attr, PropertyInfo property) in this.GetOrderedSettingsSourceProperties()) { - var bindable = (IBindable)property.GetValue(this); + var bindable = (IBindable)property.GetValue(this)!; if (!bindable.IsDefault) tooltipTexts.Add($"{attr.Label} {bindable}"); @@ -134,7 +134,7 @@ namespace osu.Game.Rulesets.Mods /// public virtual Mod DeepClone() { - var result = (Mod)Activator.CreateInstance(GetType()); + var result = (Mod)Activator.CreateInstance(GetType())!; result.CopyFrom(this); return result; } @@ -150,8 +150,8 @@ namespace osu.Game.Rulesets.Mods foreach (var (_, prop) in this.GetSettingsSourceProperties()) { - var targetBindable = (IBindable)prop.GetValue(this); - var sourceBindable = (IBindable)prop.GetValue(source); + var targetBindable = (IBindable)prop.GetValue(this)!; + var sourceBindable = (IBindable)prop.GetValue(source)!; CopyAdjustedSetting(targetBindable, sourceBindable); } @@ -183,9 +183,9 @@ namespace osu.Game.Rulesets.Mods } } - public bool Equals(IMod other) => other is Mod them && Equals(them); + public bool Equals(IMod? other) => other is Mod them && Equals(them); - public bool Equals(Mod other) + public bool Equals(Mod? other) { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; @@ -209,16 +209,16 @@ namespace osu.Game.Rulesets.Mods /// /// Reset all custom settings for this mod back to their defaults. /// - public virtual void ResetSettingsToDefaults() => CopyFrom((Mod)Activator.CreateInstance(GetType())); + public virtual void ResetSettingsToDefaults() => CopyFrom((Mod)Activator.CreateInstance(GetType())!); private class ModSettingsEqualityComparer : IEqualityComparer { public static ModSettingsEqualityComparer Default { get; } = new ModSettingsEqualityComparer(); - public bool Equals(IBindable x, IBindable y) + public bool Equals(IBindable? x, IBindable? y) { - object xValue = x.GetUnderlyingSettingValue(); - object yValue = y.GetUnderlyingSettingValue(); + object? xValue = x?.GetUnderlyingSettingValue(); + object? yValue = y?.GetUnderlyingSettingValue(); return EqualityComparer.Default.Equals(xValue, yValue); } diff --git a/osu.Game/Rulesets/Mods/ModFlashlight.cs b/osu.Game/Rulesets/Mods/ModFlashlight.cs index d58a901154..45fa55c7f2 100644 --- a/osu.Game/Rulesets/Mods/ModFlashlight.cs +++ b/osu.Game/Rulesets/Mods/ModFlashlight.cs @@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Mods public abstract float DefaultFlashlightSize { get; } } - public abstract class ModFlashlight : ModFlashlight, IApplicableToDrawableRuleset, IApplicableToScoreProcessor + public abstract partial class ModFlashlight : ModFlashlight, IApplicableToDrawableRuleset, IApplicableToScoreProcessor where T : HitObject { public const double FLASHLIGHT_FADE_DURATION = 800; @@ -87,7 +87,7 @@ namespace osu.Game.Rulesets.Mods protected abstract Flashlight CreateFlashlight(); - public abstract class Flashlight : Drawable + public abstract partial class Flashlight : Drawable { public readonly BindableInt Combo = new BindableInt(); diff --git a/osu.Game/Rulesets/Mods/ModMuted.cs b/osu.Game/Rulesets/Mods/ModMuted.cs index 05ecd37000..59c4cfa85b 100644 --- a/osu.Game/Rulesets/Mods/ModMuted.cs +++ b/osu.Game/Rulesets/Mods/ModMuted.cs @@ -35,6 +35,9 @@ namespace osu.Game.Rulesets.Mods private readonly BindableNumber currentCombo = new BindableInt(); + [SettingSource("Start muted", "Increase volume as combo builds.")] + public BindableBool InverseMuting { get; } = new BindableBool(); + [SettingSource("Enable metronome", "Add a metronome beat to help you keep track of the rhythm.")] public BindableBool EnableMetronome { get; } = new BindableBool(true); @@ -45,9 +48,6 @@ namespace osu.Game.Rulesets.Mods MaxValue = 500, }; - [SettingSource("Start muted", "Increase volume as combo builds.")] - public BindableBool InverseMuting { get; } = new BindableBool(); - [SettingSource("Mute hit sounds", "Hit sounds are also muted alongside the track.")] public BindableBool AffectsHitSounds { get; } = new BindableBool(true); @@ -94,7 +94,7 @@ namespace osu.Game.Rulesets.Mods public ScoreRank AdjustRank(ScoreRank rank, double accuracy) => rank; } - public class MuteComboSlider : OsuSliderBar + public partial class MuteComboSlider : OsuSliderBar { public override LocalisableString TooltipText => Current.Value == 0 ? "always muted" : base.TooltipText; } diff --git a/osu.Game/Rulesets/Mods/ModNightcore.cs b/osu.Game/Rulesets/Mods/ModNightcore.cs index 099bf386f3..9b1f7d5cf7 100644 --- a/osu.Game/Rulesets/Mods/ModNightcore.cs +++ b/osu.Game/Rulesets/Mods/ModNightcore.cs @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Mods public override LocalisableString Description => "Uguuuuuuuu..."; } - public abstract class ModNightcore : ModNightcore, IApplicableToDrawableRuleset + public abstract partial class ModNightcore : ModNightcore, IApplicableToDrawableRuleset where TObject : HitObject { private readonly BindableNumber tempoAdjust = new BindableDouble(1); @@ -54,7 +54,7 @@ namespace osu.Game.Rulesets.Mods drawableRuleset.Overlays.Add(new NightcoreBeatContainer()); } - public class NightcoreBeatContainer : BeatSyncedContainer + public partial class NightcoreBeatContainer : BeatSyncedContainer { private PausableSkinnableSound? hatSample; private PausableSkinnableSound? clapSample; diff --git a/osu.Game/Rulesets/Mods/ModNoScope.cs b/osu.Game/Rulesets/Mods/ModNoScope.cs index 36fbb88943..cfac44066e 100644 --- a/osu.Game/Rulesets/Mods/ModNoScope.cs +++ b/osu.Game/Rulesets/Mods/ModNoScope.cs @@ -62,7 +62,7 @@ namespace osu.Game.Rulesets.Mods } } - public class HiddenComboSlider : OsuSliderBar + public partial class HiddenComboSlider : OsuSliderBar { public override LocalisableString TooltipText => Current.Value == 0 ? "always hidden" : base.TooltipText; } diff --git a/osu.Game/Rulesets/Mods/ModTimeRamp.cs b/osu.Game/Rulesets/Mods/ModTimeRamp.cs index c4cb41fb6a..7285315c3b 100644 --- a/osu.Game/Rulesets/Mods/ModTimeRamp.cs +++ b/osu.Game/Rulesets/Mods/ModTimeRamp.cs @@ -7,7 +7,6 @@ using osu.Framework.Audio; using osu.Framework.Bindables; using osu.Game.Beatmaps; using osu.Game.Configuration; -using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Mods @@ -71,7 +70,7 @@ namespace osu.Game.Rulesets.Mods SpeedChange.SetDefault(); double firstObjectStart = beatmap.HitObjects.FirstOrDefault()?.StartTime ?? 0; - double lastObjectEnd = beatmap.HitObjects.LastOrDefault()?.GetEndTime() ?? 0; + double lastObjectEnd = beatmap.HitObjects.Any() ? beatmap.GetLastObjectTime() : 0; beginRampTime = firstObjectStart; finalRateTime = firstObjectStart + FINAL_RATE_PROGRESS * (lastObjectEnd - firstObjectStart); diff --git a/osu.Game/Rulesets/Objects/BarLineGenerator.cs b/osu.Game/Rulesets/Objects/BarLineGenerator.cs index 5c76c43f20..af32c7def3 100644 --- a/osu.Game/Rulesets/Objects/BarLineGenerator.cs +++ b/osu.Game/Rulesets/Objects/BarLineGenerator.cs @@ -27,11 +27,8 @@ namespace osu.Game.Rulesets.Objects if (beatmap.HitObjects.Count == 0) return; - HitObject firstObject = beatmap.HitObjects.First(); - HitObject lastObject = beatmap.HitObjects.Last(); - - double firstHitTime = firstObject.StartTime; - double lastHitTime = 1 + lastObject.GetEndTime(); + double firstHitTime = beatmap.HitObjects.First().StartTime; + double lastHitTime = 1 + beatmap.GetLastObjectTime(); var timingPoints = beatmap.ControlPointInfo.TimingPoints; diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 60792445cd..be5a7f71e7 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -30,7 +30,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Objects.Drawables { [Cached(typeof(DrawableHitObject))] - public abstract class DrawableHitObject : PoolableDrawableWithLifetime + public abstract partial class DrawableHitObject : PoolableDrawableWithLifetime { /// /// Invoked after this 's applied has had its defaults applied. @@ -199,7 +199,7 @@ namespace osu.Game.Rulesets.Objects.Drawables comboColourBrightness.BindValueChanged(_ => UpdateComboColour()); // Apply transforms - updateState(State.Value, true); + updateStateFromResult(); } /// @@ -208,8 +208,7 @@ namespace osu.Game.Rulesets.Objects.Drawables /// public void Apply([NotNull] HitObject hitObject) { - if (hitObject == null) - throw new ArgumentNullException($"Cannot apply a null {nameof(HitObject)}."); + ArgumentNullException.ThrowIfNull(hitObject); Apply(new SyntheticHitObjectEntry(hitObject)); } @@ -266,12 +265,7 @@ namespace osu.Game.Rulesets.Objects.Drawables // If not loaded, the state update happens in LoadComplete(). if (IsLoaded) { - if (Result.IsHit) - updateState(ArmedState.Hit, true); - else if (Result.HasResult) - updateState(ArmedState.Miss, true); - else - updateState(ArmedState.Idle, true); + updateStateFromResult(); // Combo colour may have been applied via a bindable flow while no object entry was attached. // Update here to ensure we're in a good state. @@ -279,6 +273,16 @@ namespace osu.Game.Rulesets.Objects.Drawables } } + private void updateStateFromResult() + { + if (Result.IsHit) + updateState(ArmedState.Hit, true); + else if (Result.HasResult) + updateState(ArmedState.Miss, true); + else + updateState(ArmedState.Idle, true); + } + protected sealed override void OnFree(HitObjectLifetimeEntry entry) { StartTimeBindable.UnbindFrom(HitObject.StartTimeBindable); @@ -745,7 +749,7 @@ namespace osu.Game.Rulesets.Objects.Drawables } } - public abstract class DrawableHitObject : DrawableHitObject + public abstract partial class DrawableHitObject : DrawableHitObject where TObject : HitObject { public new TObject HitObject => (TObject)base.HitObject; diff --git a/osu.Game/Rulesets/Objects/Pooling/PoolableDrawableWithLifetime.cs b/osu.Game/Rulesets/Objects/Pooling/PoolableDrawableWithLifetime.cs index 8dc588da9e..a06f810cfe 100644 --- a/osu.Game/Rulesets/Objects/Pooling/PoolableDrawableWithLifetime.cs +++ b/osu.Game/Rulesets/Objects/Pooling/PoolableDrawableWithLifetime.cs @@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.Objects.Pooling /// A that is controlled by to implement drawable pooling and replay rewinding. /// /// The type storing state and controlling this drawable. - public abstract class PoolableDrawableWithLifetime : PoolableDrawable where TEntry : LifetimeEntry + public abstract partial class PoolableDrawableWithLifetime : PoolableDrawable where TEntry : LifetimeEntry { private TEntry? entry; diff --git a/osu.Game/Rulesets/Objects/Pooling/PooledDrawableWithLifetimeContainer.cs b/osu.Game/Rulesets/Objects/Pooling/PooledDrawableWithLifetimeContainer.cs index d5b4390ce8..3b45acc7bb 100644 --- a/osu.Game/Rulesets/Objects/Pooling/PooledDrawableWithLifetimeContainer.cs +++ b/osu.Game/Rulesets/Objects/Pooling/PooledDrawableWithLifetimeContainer.cs @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Objects.Pooling /// /// The type of entries managed by this container. /// The type of drawables corresponding to the entries. - public abstract class PooledDrawableWithLifetimeContainer : CompositeDrawable + public abstract partial class PooledDrawableWithLifetimeContainer : CompositeDrawable where TEntry : LifetimeEntry where TDrawable : Drawable { diff --git a/osu.Game/Rulesets/Objects/SliderPath.cs b/osu.Game/Rulesets/Objects/SliderPath.cs index ddc121eb5b..13cc6361cf 100644 --- a/osu.Game/Rulesets/Objects/SliderPath.cs +++ b/osu.Game/Rulesets/Objects/SliderPath.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; using System.Collections.Specialized; +using System.Diagnostics; using System.Linq; using Newtonsoft.Json; using osu.Framework.Bindables; @@ -41,6 +42,7 @@ namespace osu.Game.Rulesets.Objects private readonly List calculatedPath = new List(); private readonly List cumulativeLength = new List(); + private readonly List segmentEnds = new List(); private readonly Cached pathCache = new Cached(); private double calculatedLength; @@ -57,12 +59,16 @@ namespace osu.Game.Rulesets.Objects switch (args.Action) { case NotifyCollectionChangedAction.Add: + Debug.Assert(args.NewItems != null); + foreach (var c in args.NewItems.Cast()) c.Changed += invalidate; break; case NotifyCollectionChangedAction.Reset: case NotifyCollectionChangedAction.Remove: + Debug.Assert(args.OldItems != null); + foreach (var c in args.OldItems.Cast()) c.Changed -= invalidate; break; @@ -191,6 +197,16 @@ namespace osu.Game.Rulesets.Objects return pointsInCurrentSegment; } + /// + /// Returns the progress values at which segments of the path end. + /// + public IEnumerable GetSegmentEnds() + { + ensureValid(); + + return segmentEnds.Select(i => cumulativeLength[i] / calculatedLength); + } + private void invalidate() { pathCache.Invalidate(); @@ -211,6 +227,7 @@ namespace osu.Game.Rulesets.Objects private void calculatePath() { calculatedPath.Clear(); + segmentEnds.Clear(); if (ControlPoints.Count == 0) return; @@ -236,6 +253,9 @@ namespace osu.Game.Rulesets.Objects calculatedPath.Add(t); } + // Remember the index of the segment end + segmentEnds.Add(calculatedPath.Count - 1); + // Start the new segment at the current vertex start = i; } @@ -301,6 +321,10 @@ namespace osu.Game.Rulesets.Objects { cumulativeLength.RemoveAt(cumulativeLength.Count - 1); calculatedPath.RemoveAt(pathEndIndex--); + + // Shorten the last segment to the expected distance + if (segmentEnds.Count > 0) + segmentEnds[^1]--; } } diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index a446210c8a..fcf7a78090 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -85,10 +85,12 @@ namespace osu.Game.Rulesets /// This comes with considerable allocation overhead. If only accessing for reference purposes (ie. not changing bindables / settings) /// use instead. /// - public IEnumerable CreateAllMods() => Enum.GetValues(typeof(ModType)).Cast() + public IEnumerable CreateAllMods() => Enum.GetValues() // Confine all mods of each mod type into a single IEnumerable .SelectMany(GetModsFor) // Filter out all null mods + // This is to handle old rulesets which were doing mods bad. Can be removed at some point we are sure nulls will not appear here. + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract .Where(mod => mod != null) // Resolve MultiMods as their .Mods property .SelectMany(mod => (mod as MultiMod)?.Mods ?? new[] { mod }); diff --git a/osu.Game/Rulesets/RulesetConfigCache.cs b/osu.Game/Rulesets/RulesetConfigCache.cs index ab44e86048..79dff37280 100644 --- a/osu.Game/Rulesets/RulesetConfigCache.cs +++ b/osu.Game/Rulesets/RulesetConfigCache.cs @@ -11,7 +11,7 @@ using osu.Game.Rulesets.Configuration; namespace osu.Game.Rulesets { - public class RulesetConfigCache : Component, IRulesetConfigCache + public partial class RulesetConfigCache : Component, IRulesetConfigCache { private readonly RealmAccess realm; private readonly RulesetStore rulesets; diff --git a/osu.Game/Rulesets/RulesetInfo.cs b/osu.Game/Rulesets/RulesetInfo.cs index 91954320a4..6a4e0f0b48 100644 --- a/osu.Game/Rulesets/RulesetInfo.cs +++ b/osu.Game/Rulesets/RulesetInfo.cs @@ -53,21 +53,21 @@ namespace osu.Game.Rulesets public bool Equals(IRulesetInfo? other) => other is RulesetInfo r && Equals(r); - public int CompareTo(RulesetInfo other) + public int CompareTo(RulesetInfo? other) { - if (OnlineID >= 0 && other.OnlineID >= 0) + if (OnlineID >= 0 && other?.OnlineID >= 0) return OnlineID.CompareTo(other.OnlineID); // Official rulesets are always given precedence for the time being. if (OnlineID >= 0) return -1; - if (other.OnlineID >= 0) + if (other?.OnlineID >= 0) return 1; - return string.Compare(ShortName, other.ShortName, StringComparison.Ordinal); + return string.Compare(ShortName, other?.ShortName, StringComparison.Ordinal); } - public int CompareTo(IRulesetInfo other) + public int CompareTo(IRulesetInfo? other) { if (!(other is RulesetInfo ruleset)) throw new ArgumentException($@"Object is not of type {nameof(RulesetInfo)}.", nameof(other)); diff --git a/osu.Game/Rulesets/RulesetSelector.cs b/osu.Game/Rulesets/RulesetSelector.cs index 701e60eec9..ba10033a98 100644 --- a/osu.Game/Rulesets/RulesetSelector.cs +++ b/osu.Game/Rulesets/RulesetSelector.cs @@ -6,21 +6,27 @@ using osu.Framework.Graphics.UserInterface; using osu.Framework.Allocation; using osu.Framework.Logging; +using osu.Game.Extensions; namespace osu.Game.Rulesets { - public abstract class RulesetSelector : TabControl + public abstract partial class RulesetSelector : TabControl { [Resolved] protected RulesetStore Rulesets { get; private set; } protected override Dropdown CreateDropdown() => null; + protected virtual bool LegacyOnly => false; + [BackgroundDependencyLoader] private void load() { foreach (var ruleset in Rulesets.AvailableRulesets) { + if (!ruleset.IsLegacyRuleset() && LegacyOnly) + continue; + try { AddItem(ruleset); diff --git a/osu.Game/Rulesets/RulesetStore.cs b/osu.Game/Rulesets/RulesetStore.cs index e2b8cd2c4e..881b09bd1b 100644 --- a/osu.Game/Rulesets/RulesetStore.cs +++ b/osu.Game/Rulesets/RulesetStore.cs @@ -75,10 +75,7 @@ namespace osu.Game.Rulesets return false; return args.Name.Contains(name, StringComparison.Ordinal); - }) - // Pick the greatest assembly version. - .OrderByDescending(a => a.GetName().Version) - .FirstOrDefault(); + }).MaxBy(a => a.GetName().Version); if (domainAssembly != null) return domainAssembly; @@ -114,7 +111,10 @@ namespace osu.Game.Rulesets { try { - string[] files = Directory.GetFiles(RuntimeInfo.StartupDirectory, @$"{ruleset_library_prefix}.*.dll"); + // On net6-android (Debug), StartupDirectory can be different from where assemblies are placed. + // Search sub-directories too. + + string[] files = Directory.GetFiles(RuntimeInfo.StartupDirectory, @$"{ruleset_library_prefix}.*.dll", SearchOption.AllDirectories); foreach (string file in files.Where(f => !Path.GetFileName(f).Contains("Tests"))) loadRulesetFromFile(file); @@ -127,7 +127,7 @@ namespace osu.Game.Rulesets private void loadRulesetFromFile(string file) { - string? filename = Path.GetFileNameWithoutExtension(file); + string filename = Path.GetFileNameWithoutExtension(file); if (LoadedAssemblies.Values.Any(t => Path.GetFileNameWithoutExtension(t.Assembly.Location) == filename)) return; @@ -158,7 +158,7 @@ namespace osu.Game.Rulesets } catch (Exception e) { - LogFailedLoad(assembly.GetName().Name.Split('.').Last(), e); + LogFailedLoad(assembly.GetName().Name!.Split('.').Last(), e); } } diff --git a/osu.Game/Rulesets/Scoring/AccumulatingHealthProcessor.cs b/osu.Game/Rulesets/Scoring/AccumulatingHealthProcessor.cs index c6b9d227af..af6e825b06 100644 --- a/osu.Game/Rulesets/Scoring/AccumulatingHealthProcessor.cs +++ b/osu.Game/Rulesets/Scoring/AccumulatingHealthProcessor.cs @@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Scoring /// A that accumulates health and causes a fail if the final health /// is less than a value required to pass the beatmap. /// - public class AccumulatingHealthProcessor : HealthProcessor + public partial class AccumulatingHealthProcessor : HealthProcessor { protected override bool DefaultFailCondition => JudgedHits == MaxHits && Health.Value < requiredHealth; diff --git a/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs b/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs index 65af161393..592dcbfeb8 100644 --- a/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs +++ b/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Scoring /// At HP=5, the minimum health reached for a perfect play is 70%.
/// At HP=10, the minimum health reached for a perfect play is 30%. /// - public class DrainingHealthProcessor : HealthProcessor + public partial class DrainingHealthProcessor : HealthProcessor { /// /// A reasonable allowable error for the minimum health offset from . A 1% error is unnoticeable. @@ -65,7 +65,7 @@ namespace osu.Game.Rulesets.Scoring public DrainingHealthProcessor(double drainStartTime, double drainLenience = 0) { this.drainStartTime = drainStartTime; - this.drainLenience = drainLenience; + this.drainLenience = Math.Clamp(drainLenience, 0, 1); } protected override void Update() @@ -79,7 +79,8 @@ namespace osu.Game.Rulesets.Scoring double lastGameplayTime = Math.Clamp(Time.Current - Time.Elapsed, drainStartTime, gameplayEndTime); double currentGameplayTime = Math.Clamp(Time.Current, drainStartTime, gameplayEndTime); - Health.Value -= drainRate * (currentGameplayTime - lastGameplayTime); + if (drainLenience < 1) + Health.Value -= drainRate * (currentGameplayTime - lastGameplayTime); } public override void ApplyBeatmap(IBeatmap beatmap) diff --git a/osu.Game/Rulesets/Scoring/HealthProcessor.cs b/osu.Game/Rulesets/Scoring/HealthProcessor.cs index 0a1e6b729f..b70ddd5e24 100644 --- a/osu.Game/Rulesets/Scoring/HealthProcessor.cs +++ b/osu.Game/Rulesets/Scoring/HealthProcessor.cs @@ -8,7 +8,7 @@ using osu.Game.Rulesets.Judgements; namespace osu.Game.Rulesets.Scoring { - public abstract class HealthProcessor : JudgementProcessor + public abstract partial class HealthProcessor : JudgementProcessor { /// /// Invoked when the is in a failed state. @@ -80,7 +80,7 @@ namespace osu.Game.Rulesets.Scoring { foreach (var condition in FailConditions.GetInvocationList()) { - bool conditionResult = (bool)condition.Method.Invoke(condition.Target, new object[] { this, result }); + bool conditionResult = (bool)condition.Method.Invoke(condition.Target, new object[] { this, result })!; if (conditionResult) return true; } diff --git a/osu.Game/Rulesets/Scoring/HitResult.cs b/osu.Game/Rulesets/Scoring/HitResult.cs index 96e13e5861..83ed98768c 100644 --- a/osu.Game/Rulesets/Scoring/HitResult.cs +++ b/osu.Game/Rulesets/Scoring/HitResult.cs @@ -264,7 +264,7 @@ namespace osu.Game.Rulesets.Scoring /// /// An array of all scorable s. /// - public static readonly HitResult[] ALL_TYPES = ((HitResult[])Enum.GetValues(typeof(HitResult))).Except(new[] { HitResult.LegacyComboIncrease }).ToArray(); + public static readonly HitResult[] ALL_TYPES = Enum.GetValues().Except(new[] { HitResult.LegacyComboIncrease }).ToArray(); /// /// Whether a is valid within a given range. diff --git a/osu.Game/Rulesets/Scoring/JudgementProcessor.cs b/osu.Game/Rulesets/Scoring/JudgementProcessor.cs index bc8f2c22f3..09b5f0a6bc 100644 --- a/osu.Game/Rulesets/Scoring/JudgementProcessor.cs +++ b/osu.Game/Rulesets/Scoring/JudgementProcessor.cs @@ -13,7 +13,7 @@ using osu.Game.Rulesets.Replays; namespace osu.Game.Rulesets.Scoring { - public abstract class JudgementProcessor : Component + public abstract partial class JudgementProcessor : Component { /// /// Invoked when a new judgement has occurred. This occurs after the judgement has been processed by this . diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 899d149cbc..ff0d91c0dd 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -10,7 +10,6 @@ using osu.Framework.Bindables; using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Extensions; -using osu.Game.Online.Spectator; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; @@ -21,7 +20,7 @@ using osu.Game.Localisation; namespace osu.Game.Rulesets.Scoring { - public class ScoreProcessor : JudgementProcessor + public partial class ScoreProcessor : JudgementProcessor { private const double max_score = 1000000; @@ -40,6 +39,18 @@ namespace osu.Game.Rulesets.Scoring /// public readonly BindableDouble Accuracy = new BindableDouble(1) { MinValue = 0, MaxValue = 1 }; + /// + /// The minimum achievable accuracy for the whole beatmap at this stage of gameplay. + /// Assumes that all objects that have not been judged yet will receive the minimum hit result. + /// + public readonly BindableDouble MinimumAccuracy = new BindableDouble { MinValue = 0, MaxValue = 1 }; + + /// + /// The maximum achievable accuracy for the whole beatmap at this stage of gameplay. + /// Assumes that all objects that have not been judged yet will receive the maximum hit result. + /// + public readonly BindableDouble MaximumAccuracy = new BindableDouble(1) { MinValue = 0, MaxValue = 1 }; + /// /// The current combo. /// @@ -90,17 +101,14 @@ namespace osu.Game.Rulesets.Scoring private readonly double accuracyPortion; private readonly double comboPortion; - /// - /// Scoring values for a perfect play. - /// - public ScoringValues MaximumScoringValues + public Dictionary MaximumStatistics { get { if (!beatmapApplied) - throw new InvalidOperationException($"Cannot access maximum scoring values before calling {nameof(ApplyBeatmap)}."); + throw new InvalidOperationException($"Cannot access maximum statistics before calling {nameof(ApplyBeatmap)}."); - return maximumScoringValues; + return new Dictionary(maximumResultCounts); } } @@ -268,7 +276,11 @@ namespace osu.Game.Rulesets.Scoring private void updateScore() { Accuracy.Value = currentMaximumScoringValues.BaseScore > 0 ? (double)currentScoringValues.BaseScore / currentMaximumScoringValues.BaseScore : 1; - TotalScore.Value = ComputeScore(Mode.Value, currentScoringValues, maximumScoringValues); + MinimumAccuracy.Value = maximumScoringValues.BaseScore > 0 ? (double)currentScoringValues.BaseScore / maximumScoringValues.BaseScore : 0; + MaximumAccuracy.Value = maximumScoringValues.BaseScore > 0 + ? (double)(currentScoringValues.BaseScore + (maximumScoringValues.BaseScore - currentMaximumScoringValues.BaseScore)) / maximumScoringValues.BaseScore + : 1; + TotalScore.Value = computeScore(Mode.Value, currentScoringValues, maximumScoringValues); } /// @@ -285,7 +297,7 @@ namespace osu.Game.Rulesets.Scoring // We only extract scoring values from the score's statistics. This is because accuracy is always relative to the point of pass or fail rather than relative to the whole beatmap. extractScoringValues(scoreInfo.Statistics, out var current, out var maximum); - return maximum.BaseScore > 0 ? current.BaseScore / maximum.BaseScore : 1; + return maximum.BaseScore > 0 ? (double)current.BaseScore / maximum.BaseScore : 1; } /// @@ -303,9 +315,9 @@ namespace osu.Game.Rulesets.Scoring if (!ruleset.RulesetInfo.Equals(scoreInfo.Ruleset)) throw new ArgumentException($"Unexpected score ruleset. Expected \"{ruleset.RulesetInfo.ShortName}\" but was \"{scoreInfo.Ruleset.ShortName}\"."); - ExtractScoringValues(scoreInfo, out var current, out var maximum); + extractScoringValues(scoreInfo, out var current, out var maximum); - return ComputeScore(mode, current, maximum); + return computeScore(mode, current, maximum); } /// @@ -316,7 +328,7 @@ namespace osu.Game.Rulesets.Scoring /// The maximum scoring values. /// The total score computed from the given scoring values. [Pure] - public long ComputeScore(ScoringMode mode, ScoringValues current, ScoringValues maximum) + private long computeScore(ScoringMode mode, ScoringValues current, ScoringValues maximum) { double accuracyRatio = maximum.BaseScore > 0 ? (double)current.BaseScore / maximum.BaseScore : 1; double comboRatio = maximum.MaxCombo > 0 ? (double)current.MaxCombo / maximum.MaxCombo : 1; @@ -411,6 +423,8 @@ namespace osu.Game.Rulesets.Scoring score.Accuracy = Accuracy.Value; score.Rank = Rank.Value; score.HitEvents = hitEvents; + score.Statistics.Clear(); + score.MaximumStatistics.Clear(); foreach (var result in HitResultExtensions.ALL_TYPES) score.Statistics[result] = scoreResultCounts.GetValueOrDefault(result); @@ -474,14 +488,14 @@ namespace osu.Game.Rulesets.Scoring /// Consumers are expected to more accurately fill in the above values through external means. /// /// Ensure to fill in the maximum for use in - /// . + /// . /// /// /// The score to extract scoring values from. /// The "current" scoring values, representing the hit statistics as they appear. /// The "maximum" scoring values, representing the hit statistics as if the maximum hit result was attained each time. [Pure] - internal void ExtractScoringValues(ScoreInfo scoreInfo, out ScoringValues current, out ScoringValues maximum) + private void extractScoringValues(ScoreInfo scoreInfo, out ScoringValues current, out ScoringValues maximum) { extractScoringValues(scoreInfo.Statistics, out current, out maximum); current.MaxCombo = scoreInfo.MaxCombo; @@ -490,31 +504,6 @@ namespace osu.Game.Rulesets.Scoring extractScoringValues(scoreInfo.MaximumStatistics, out _, out maximum); } - /// - /// Applies a best-effort extraction of hit statistics into . - /// - /// - /// This method is useful in a variety of situations, with a few drawbacks that need to be considered: - /// - /// The maximum will always be 0. - /// The current and maximum will always be the same value. - /// - /// Consumers are expected to more accurately fill in the above values through external means. - /// - /// Ensure to fill in the maximum for use in - /// . - /// - /// - /// The replay frame header to extract scoring values from. - /// The "current" scoring values, representing the hit statistics as they appear. - /// The "maximum" scoring values, representing the hit statistics as if the maximum hit result was attained each time. - [Pure] - internal void ExtractScoringValues(FrameHeader header, out ScoringValues current, out ScoringValues maximum) - { - extractScoringValues(header.Statistics, out current, out maximum); - current.MaxCombo = header.MaxCombo; - } - /// /// Applies a best-effort extraction of hit statistics into . /// @@ -563,7 +552,7 @@ namespace osu.Game.Rulesets.Scoring break; default: - maxResult = maxBasicResult ??= ruleset.GetHitResults().OrderByDescending(kvp => Judgement.ToNumericResult(kvp.result)).First().result; + maxResult = maxBasicResult ??= ruleset.GetHitResults().MaxBy(kvp => Judgement.ToNumericResult(kvp.result)).result; break; } @@ -589,6 +578,32 @@ namespace osu.Game.Rulesets.Scoring base.Dispose(isDisposing); hitEvents.Clear(); } + + /// + /// Stores the required scoring data that fulfils the minimum requirements for a to calculate score. + /// + private struct ScoringValues + { + /// + /// The sum of all "basic" scoring values. See: and . + /// + public long BaseScore; + + /// + /// The sum of all "bonus" scoring values. See: and . + /// + public long BonusScore; + + /// + /// The highest achieved combo. + /// + public int MaxCombo; + + /// + /// The count of "basic" s. See: . + /// + public int CountBasicHitObjects; + } } public enum ScoringMode diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index dd3a950264..71b452c309 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -39,7 +39,7 @@ namespace osu.Game.Rulesets.UI /// Displays an interactive ruleset gameplay instance. /// /// The type of HitObject contained by this DrawableRuleset. - public abstract class DrawableRuleset : DrawableRuleset, IProvideCursor, ICanAttachHUDPieces + public abstract partial class DrawableRuleset : DrawableRuleset, IProvideCursor, ICanAttachHUDPieces where TObject : HitObject { public override event Action NewResult; @@ -414,7 +414,7 @@ namespace osu.Game.Rulesets.UI /// /// [Cached(typeof(DrawableRuleset))] - public abstract class DrawableRuleset : CompositeDrawable + public abstract partial class DrawableRuleset : CompositeDrawable { /// /// Invoked when a has been applied by a . diff --git a/osu.Game/Rulesets/UI/DrawableRulesetDependenciesProvidingContainer.cs b/osu.Game/Rulesets/UI/DrawableRulesetDependenciesProvidingContainer.cs new file mode 100644 index 0000000000..6c213497dd --- /dev/null +++ b/osu.Game/Rulesets/UI/DrawableRulesetDependenciesProvidingContainer.cs @@ -0,0 +1,36 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Extensions.ObjectExtensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; + +namespace osu.Game.Rulesets.UI +{ + public partial class DrawableRulesetDependenciesProvidingContainer : Container + { + private readonly Ruleset ruleset; + + private DrawableRulesetDependencies rulesetDependencies = null!; + + public DrawableRulesetDependenciesProvidingContainer(Ruleset ruleset) + { + this.ruleset = ruleset; + RelativeSizeAxes = Axes.Both; + } + + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) + { + return rulesetDependencies = new DrawableRulesetDependencies(ruleset, base.CreateChildDependencies(parent)); + } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + if (rulesetDependencies.IsNotNull()) + rulesetDependencies.Dispose(); + } + } +} diff --git a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs index 3b35fba122..4bb145973d 100644 --- a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs +++ b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs @@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.UI /// [Cached(typeof(IGameplayClock))] [Cached(typeof(IFrameStableClock))] - public sealed class FrameStabilityContainer : Container, IHasReplayHandler, IFrameStableClock + public sealed partial class FrameStabilityContainer : Container, IHasReplayHandler, IFrameStableClock { public ReplayInputHandler? ReplayInputHandler { get; set; } diff --git a/osu.Game/Rulesets/UI/GameplayCursorContainer.cs b/osu.Game/Rulesets/UI/GameplayCursorContainer.cs index 3149b7f890..cbce397d1e 100644 --- a/osu.Game/Rulesets/UI/GameplayCursorContainer.cs +++ b/osu.Game/Rulesets/UI/GameplayCursorContainer.cs @@ -8,7 +8,7 @@ using osu.Framework.Graphics.Cursor; namespace osu.Game.Rulesets.UI { - public class GameplayCursorContainer : CursorContainer + public partial class GameplayCursorContainer : CursorContainer { /// /// Because Show/Hide are executed by a parent, is updated immediately even if the cursor diff --git a/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs b/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs index fd8fcfddab..d2244df3b8 100644 --- a/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs +++ b/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs @@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.UI /// /// A component which can trigger the most appropriate hit sound for a given point in time, based on the state of a /// - public class GameplaySampleTriggerSource : CompositeDrawable + public partial class GameplaySampleTriggerSource : CompositeDrawable { /// /// The number of concurrent samples allowed to be played concurrently so that it feels better when spam-pressing a key. @@ -79,9 +79,7 @@ namespace osu.Game.Rulesets.UI // We need to use lifetime entries to find the next object (we can't just use `hitObjectContainer.Objects` due to pooling - it may even be empty). // If required, we can make this lookup more efficient by adding support to get next-future-entry in LifetimeEntryManager. fallbackObject = hitObjectContainer.Entries - .Where(e => e.Result?.HasResult != true) - .OrderBy(e => e.HitObject.StartTime) - .FirstOrDefault(); + .Where(e => e.Result?.HasResult != true).MinBy(e => e.HitObject.StartTime); // In the case there are no unjudged objects, the last hit object should be used instead. fallbackObject ??= hitObjectContainer.Entries.LastOrDefault(); diff --git a/osu.Game/Rulesets/UI/HitObjectContainer.cs b/osu.Game/Rulesets/UI/HitObjectContainer.cs index bbced9e58c..7cbf49aa31 100644 --- a/osu.Game/Rulesets/UI/HitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/HitObjectContainer.cs @@ -17,7 +17,7 @@ using osu.Game.Rulesets.Objects.Pooling; namespace osu.Game.Rulesets.UI { - public class HitObjectContainer : PooledDrawableWithLifetimeContainer, IHitObjectContainer + public partial class HitObjectContainer : PooledDrawableWithLifetimeContainer, IHitObjectContainer { public IEnumerable Objects => InternalChildren.Cast().OrderBy(h => h.HitObject.StartTime); diff --git a/osu.Game/Rulesets/UI/JudgementContainer.cs b/osu.Game/Rulesets/UI/JudgementContainer.cs index 471a62cab3..7181e80206 100644 --- a/osu.Game/Rulesets/UI/JudgementContainer.cs +++ b/osu.Game/Rulesets/UI/JudgementContainer.cs @@ -9,12 +9,12 @@ using osu.Game.Rulesets.Judgements; namespace osu.Game.Rulesets.UI { - public class JudgementContainer : Container + public partial class JudgementContainer : Container where T : DrawableJudgement { public override void Add(T judgement) { - if (judgement == null) throw new ArgumentNullException(nameof(judgement)); + ArgumentNullException.ThrowIfNull(judgement); // remove any existing judgements for the judged object. // this can be the case when rewinding. diff --git a/osu.Game/Rulesets/UI/ModIcon.cs b/osu.Game/Rulesets/UI/ModIcon.cs index b1f355a789..bf212ad72f 100644 --- a/osu.Game/Rulesets/UI/ModIcon.cs +++ b/osu.Game/Rulesets/UI/ModIcon.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.UI /// /// Display the specified mod at a fixed size. /// - public class ModIcon : Container, IHasTooltip + public partial class ModIcon : Container, IHasTooltip { public readonly BindableBool Selected = new BindableBool(); diff --git a/osu.Game/Rulesets/UI/ModSwitchSmall.cs b/osu.Game/Rulesets/UI/ModSwitchSmall.cs index 1b777f3e88..b6058c16ce 100644 --- a/osu.Game/Rulesets/UI/ModSwitchSmall.cs +++ b/osu.Game/Rulesets/UI/ModSwitchSmall.cs @@ -15,7 +15,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.UI { - public class ModSwitchSmall : CompositeDrawable + public partial class ModSwitchSmall : CompositeDrawable { public BindableBool Active { get; } = new BindableBool(); diff --git a/osu.Game/Rulesets/UI/ModSwitchTiny.cs b/osu.Game/Rulesets/UI/ModSwitchTiny.cs index 1bb0fe535f..a5cf75bd07 100644 --- a/osu.Game/Rulesets/UI/ModSwitchTiny.cs +++ b/osu.Game/Rulesets/UI/ModSwitchTiny.cs @@ -16,7 +16,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.UI { - public class ModSwitchTiny : CompositeDrawable + public partial class ModSwitchTiny : CompositeDrawable { public BindableBool Active { get; } = new BindableBool(); diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index e59e45722a..a7881678f1 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.UI { [Cached(typeof(IPooledHitObjectProvider))] [Cached(typeof(IPooledSampleProvider))] - public abstract class Playfield : CompositeDrawable, IPooledHitObjectProvider, IPooledSampleProvider + public abstract partial class Playfield : CompositeDrawable, IPooledHitObjectProvider, IPooledSampleProvider { /// /// Invoked when a is judged. @@ -93,7 +93,8 @@ namespace osu.Game.Rulesets.UI public readonly BindableBool DisplayJudgements = new BindableBool(true); [Resolved(CanBeNull = true)] - private IReadOnlyList mods { get; set; } + [CanBeNull] + protected IReadOnlyList Mods { get; private set; } private readonly HitObjectEntryManager entryManager = new HitObjectEntryManager(); @@ -243,9 +244,9 @@ namespace osu.Game.Rulesets.UI { base.Update(); - if (!IsNested && mods != null) + if (!IsNested && Mods != null) { - foreach (var mod in mods) + foreach (var mod in Mods) { if (mod is IUpdatableByPlayfield updatable) updatable.Update(this); @@ -374,9 +375,9 @@ namespace osu.Game.Rulesets.UI // If this is the first time this DHO is being used, then apply the DHO mods. // This is done before Apply() so that the state is updated once when the hitobject is applied. - if (mods != null) + if (Mods != null) { - foreach (var m in mods.OfType()) + foreach (var m in Mods.OfType()) m.ApplyToDrawableHitObject(dho); } } @@ -427,7 +428,7 @@ namespace osu.Game.Rulesets.UI return pool; } - private class DrawableSamplePool : DrawablePool + private partial class DrawableSamplePool : DrawablePool { private readonly ISampleInfo sampleInfo; diff --git a/osu.Game/Rulesets/UI/PlayfieldAdjustmentContainer.cs b/osu.Game/Rulesets/UI/PlayfieldAdjustmentContainer.cs index d0e79281a7..0f440adef8 100644 --- a/osu.Game/Rulesets/UI/PlayfieldAdjustmentContainer.cs +++ b/osu.Game/Rulesets/UI/PlayfieldAdjustmentContainer.cs @@ -11,7 +11,7 @@ namespace osu.Game.Rulesets.UI /// /// A container which handles sizing of the and any other components that need to match their size. /// - public class PlayfieldAdjustmentContainer : Container + public partial class PlayfieldAdjustmentContainer : Container { public PlayfieldAdjustmentContainer() { diff --git a/osu.Game/Rulesets/UI/PlayfieldBorder.cs b/osu.Game/Rulesets/UI/PlayfieldBorder.cs index a129760ef3..211a87de84 100644 --- a/osu.Game/Rulesets/UI/PlayfieldBorder.cs +++ b/osu.Game/Rulesets/UI/PlayfieldBorder.cs @@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.UI /// /// Provides a border around the playfield. /// - public class PlayfieldBorder : CompositeDrawable + public partial class PlayfieldBorder : CompositeDrawable { public Bindable PlayfieldBorderStyle { get; } = new Bindable(); @@ -108,7 +108,7 @@ namespace osu.Game.Rulesets.UI } } - private class Line : Box + private partial class Line : Box { private readonly Direction direction; diff --git a/osu.Game/Rulesets/UI/ReplayRecorder.cs b/osu.Game/Rulesets/UI/ReplayRecorder.cs index 79da56fc8a..28e25c72e1 100644 --- a/osu.Game/Rulesets/UI/ReplayRecorder.cs +++ b/osu.Game/Rulesets/UI/ReplayRecorder.cs @@ -18,7 +18,7 @@ using osuTK; namespace osu.Game.Rulesets.UI { - public abstract class ReplayRecorder : ReplayRecorder, IKeyBindingHandler + public abstract partial class ReplayRecorder : ReplayRecorder, IKeyBindingHandler where T : struct { private readonly Score target; @@ -94,7 +94,7 @@ namespace osu.Game.Rulesets.UI protected abstract ReplayFrame HandleFrame(Vector2 mousePosition, List actions, ReplayFrame previousFrame); } - public abstract class ReplayRecorder : Component + public abstract partial class ReplayRecorder : Component { public Func ScreenSpaceToGamefield; } diff --git a/osu.Game/Rulesets/UI/RulesetInputManager.cs b/osu.Game/Rulesets/UI/RulesetInputManager.cs index 64ac021204..a5e442b7de 100644 --- a/osu.Game/Rulesets/UI/RulesetInputManager.cs +++ b/osu.Game/Rulesets/UI/RulesetInputManager.cs @@ -25,7 +25,7 @@ using static osu.Game.Input.Handlers.ReplayInputHandler; namespace osu.Game.Rulesets.UI { - public abstract class RulesetInputManager : PassThroughInputManager, ICanAttachHUDPieces, IHasReplayHandler, IHasRecordingHandler + public abstract partial class RulesetInputManager : PassThroughInputManager, ICanAttachHUDPieces, IHasReplayHandler, IHasRecordingHandler where T : struct { public readonly KeyBindingContainer KeyBindingContainer; @@ -169,7 +169,7 @@ namespace osu.Game.Rulesets.UI .Select(action => new KeyCounterAction(action))); } - private class ActionReceptor : KeyCounterDisplay.Receptor, IKeyBindingHandler + private partial class ActionReceptor : KeyCounterDisplay.Receptor, IKeyBindingHandler { public ActionReceptor(KeyCounterDisplay target) : base(target) @@ -196,7 +196,7 @@ namespace osu.Game.Rulesets.UI KeyBindingContainer.Add(listener); } - private class ActionListener : Component, IKeyBindingHandler + private partial class ActionListener : Component, IKeyBindingHandler { private readonly ClicksPerSecondCalculator calculator; @@ -221,7 +221,7 @@ namespace osu.Game.Rulesets.UI protected virtual KeyBindingContainer CreateKeyBindingContainer(RulesetInfo ruleset, int variant, SimultaneousBindingMode unique) => new RulesetKeyBindingContainer(ruleset, variant, unique); - public class RulesetKeyBindingContainer : DatabasedKeyBindingContainer + public partial class RulesetKeyBindingContainer : DatabasedKeyBindingContainer { protected override bool HandleRepeats => false; diff --git a/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs b/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs index 2cb57966e7..4c7564b791 100644 --- a/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs +++ b/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs @@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.UI.Scrolling /// A type of that supports a . /// s inside this will scroll within the playfield. /// - public abstract class DrawableScrollingRuleset : DrawableRuleset, IDrawableScrollingRuleset, IKeyBindingHandler + public abstract partial class DrawableScrollingRuleset : DrawableRuleset, IDrawableScrollingRuleset, IKeyBindingHandler where TObject : HitObject { /// @@ -114,7 +114,7 @@ namespace osu.Game.Rulesets.UI.Scrolling break; } - double lastObjectTime = Objects.LastOrDefault()?.GetEndTime() ?? double.MaxValue; + double lastObjectTime = Beatmap.HitObjects.Any() ? Beatmap.GetLastObjectTime() : double.MaxValue; double baseBeatLength = TimingControlPoint.DEFAULT_BEAT_LENGTH; if (RelativeScaleBeatLengths) diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs index 424fc7c44c..3559a1521c 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs @@ -17,7 +17,7 @@ using osuTK; namespace osu.Game.Rulesets.UI.Scrolling { - public class ScrollingHitObjectContainer : HitObjectContainer + public partial class ScrollingHitObjectContainer : HitObjectContainer { private readonly IBindable timeRange = new BindableDouble(); private readonly IBindable direction = new Bindable(); diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs index 34e5b7f9de..7d141113df 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs @@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.UI.Scrolling /// /// A type of specialized towards scrolling s. /// - public abstract class ScrollingPlayfield : Playfield + public abstract partial class ScrollingPlayfield : Playfield { protected readonly IBindable Direction = new Bindable(); diff --git a/osu.Game/Scoring/Drawables/UnprocessedPerformancePointsPlaceholder.cs b/osu.Game/Scoring/Drawables/UnprocessedPerformancePointsPlaceholder.cs index 6087ca9eb9..99eb7e964d 100644 --- a/osu.Game/Scoring/Drawables/UnprocessedPerformancePointsPlaceholder.cs +++ b/osu.Game/Scoring/Drawables/UnprocessedPerformancePointsPlaceholder.cs @@ -13,7 +13,7 @@ namespace osu.Game.Scoring.Drawables /// /// A placeholder used in PP columns for scores with unprocessed PP value. /// - public class UnprocessedPerformancePointsPlaceholder : SpriteIcon, IHasTooltip + public partial class UnprocessedPerformancePointsPlaceholder : SpriteIcon, IHasTooltip { public LocalisableString TooltipText => ScoresStrings.StatusProcessing; diff --git a/osu.Game/Scoring/Legacy/LegacyReplaySoloScoreInfo.cs b/osu.Game/Scoring/Legacy/LegacyReplaySoloScoreInfo.cs new file mode 100644 index 0000000000..f2e8cf141b --- /dev/null +++ b/osu.Game/Scoring/Legacy/LegacyReplaySoloScoreInfo.cs @@ -0,0 +1,38 @@ +// Copyright (c) ppy Pty Ltd . 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 Newtonsoft.Json; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Rulesets.Scoring; + +namespace osu.Game.Scoring.Legacy +{ + /// + /// A minified version of retrofit onto the end of legacy replay files (.osr), + /// containing the minimum data required to support storage of non-legacy replays. + /// + [Serializable] + [JsonObject(MemberSerialization.OptIn)] + public class LegacyReplaySoloScoreInfo + { + [JsonProperty("mods")] + public APIMod[] Mods { get; set; } = Array.Empty(); + + [JsonProperty("statistics")] + public Dictionary Statistics { get; set; } = new Dictionary(); + + [JsonProperty("maximum_statistics")] + public Dictionary MaximumStatistics { get; set; } = new Dictionary(); + + public static LegacyReplaySoloScoreInfo FromScore(ScoreInfo score) => new LegacyReplaySoloScoreInfo + { + Mods = score.APIMods, + Statistics = score.Statistics.Where(kvp => kvp.Value != 0).ToDictionary(kvp => kvp.Key, kvp => kvp.Value), + MaximumStatistics = score.MaximumStatistics.Where(kvp => kvp.Value != 0).ToDictionary(kvp => kvp.Key, kvp => kvp.Value), + }; + } +} diff --git a/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs b/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs index f64e730c06..6f0b0c62f8 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs @@ -4,8 +4,10 @@ #nullable disable using System; +using System.Diagnostics; using System.IO; using System.Linq; +using Newtonsoft.Json; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Formats; using osu.Game.Beatmaps.Legacy; @@ -44,10 +46,12 @@ namespace osu.Game.Scoring.Legacy score.ScoreInfo = scoreInfo; int version = sr.ReadInt32(); + string beatmapHash = sr.ReadString(); + + workingBeatmap = GetBeatmap(beatmapHash); - workingBeatmap = GetBeatmap(sr.ReadString()); if (workingBeatmap is DummyWorkingBeatmap) - throw new BeatmapNotFoundException(); + throw new BeatmapNotFoundException(beatmapHash); scoreInfo.User = new APIUser { Username = sr.ReadString() }; @@ -91,31 +95,26 @@ namespace osu.Game.Scoring.Legacy else if (version >= 20121008) scoreInfo.OnlineID = sr.ReadInt32(); + byte[] compressedScoreInfo = null; + + if (version >= 30000001) + compressedScoreInfo = sr.ReadByteArray(); + if (compressedReplay?.Length > 0) + readCompressedData(compressedReplay, reader => readLegacyReplay(score.Replay, reader)); + + if (compressedScoreInfo?.Length > 0) { - using (var replayInStream = new MemoryStream(compressedReplay)) + readCompressedData(compressedScoreInfo, reader => { - byte[] properties = new byte[5]; - if (replayInStream.Read(properties, 0, 5) != 5) - throw new IOException("input .lzma is too short"); + LegacyReplaySoloScoreInfo readScore = JsonConvert.DeserializeObject(reader.ReadToEnd()); - long outSize = 0; + Debug.Assert(readScore != null); - for (int i = 0; i < 8; i++) - { - int v = replayInStream.ReadByte(); - if (v < 0) - throw new IOException("Can't Read 1"); - - outSize |= (long)(byte)v << (8 * i); - } - - long compressedSize = replayInStream.Length - replayInStream.Position; - - using (var lzma = new LzmaStream(properties, replayInStream, compressedSize, outSize)) - using (var reader = new StreamReader(lzma)) - readLegacyReplay(score.Replay, reader); - } + score.ScoreInfo.Statistics = readScore.Statistics; + score.ScoreInfo.MaximumStatistics = readScore.MaximumStatistics; + score.ScoreInfo.Mods = readScore.Mods.Select(m => m.ToMod(currentRuleset)).ToArray(); + }); } } @@ -128,6 +127,33 @@ namespace osu.Game.Scoring.Legacy return score; } + private void readCompressedData(byte[] data, Action readFunc) + { + using (var replayInStream = new MemoryStream(data)) + { + byte[] properties = new byte[5]; + if (replayInStream.Read(properties, 0, 5) != 5) + throw new IOException("input .lzma is too short"); + + long outSize = 0; + + for (int i = 0; i < 8; i++) + { + int v = replayInStream.ReadByte(); + if (v < 0) + throw new IOException("Can't Read 1"); + + outSize |= (long)(byte)v << (8 * i); + } + + long compressedSize = replayInStream.Length - replayInStream.Position; + + using (var lzma = new LzmaStream(properties, replayInStream, compressedSize, outSize)) + using (var reader = new StreamReader(lzma)) + readFunc(reader); + } + } + /// /// Populates the accuracy of a given from its contained statistics. /// @@ -310,9 +336,11 @@ namespace osu.Game.Scoring.Legacy public class BeatmapNotFoundException : Exception { - public BeatmapNotFoundException() - : base("No corresponding beatmap for the score could be found.") + public string Hash { get; } + + public BeatmapNotFoundException(string hash) { + Hash = hash; } } } diff --git a/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs b/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs index 750bb50be3..a78ae24da2 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs @@ -11,6 +11,7 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.Formats; using osu.Game.Extensions; using osu.Game.IO.Legacy; +using osu.Game.IO.Serialization; using osu.Game.Replays.Legacy; using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Replays.Types; @@ -24,7 +25,12 @@ namespace osu.Game.Scoring.Legacy /// Database version in stable-compatible YYYYMMDD format. /// Should be incremented if any changes are made to the format/usage. /// - public const int LATEST_VERSION = FIRST_LAZER_VERSION; + /// + /// + /// 30000001: Appends to the end of scores. + /// + /// + public const int LATEST_VERSION = 30000001; /// /// The first stable-compatible YYYYMMDD format version given to lazer usage of replays. @@ -52,9 +58,9 @@ namespace osu.Game.Scoring.Legacy throw new ArgumentException(@"Only scores in the osu, taiko, catch, or mania rulesets can be encoded to the legacy score format.", nameof(score)); } - public void Encode(Stream stream) + public void Encode(Stream stream, bool leaveOpen = false) { - using (SerializationWriter sw = new SerializationWriter(stream)) + using (SerializationWriter sw = new SerializationWriter(stream, leaveOpen)) { sw.Write((byte)(score.ScoreInfo.Ruleset.OnlineID)); sw.Write(LATEST_VERSION); @@ -77,6 +83,7 @@ namespace osu.Game.Scoring.Legacy sw.WriteByteArray(createReplayData()); sw.Write((long)0); writeModSpecificData(score.ScoreInfo, sw); + sw.WriteByteArray(createScoreInfoData()); } } @@ -84,9 +91,13 @@ namespace osu.Game.Scoring.Legacy { } - private byte[] createReplayData() + private byte[] createReplayData() => compress(replayStringContent); + + private byte[] createScoreInfoData() => compress(LegacyReplaySoloScoreInfo.FromScore(score.ScoreInfo).Serialize()); + + private byte[] compress(string data) { - byte[] content = new ASCIIEncoding().GetBytes(replayStringContent); + byte[] content = new ASCIIEncoding().GetBytes(data); using (var outStream = new MemoryStream()) { diff --git a/osu.Game/Scoring/ScoreImporter.cs b/osu.Game/Scoring/ScoreImporter.cs index 5c8e21014c..f69c1b9385 100644 --- a/osu.Game/Scoring/ScoreImporter.cs +++ b/osu.Game/Scoring/ScoreImporter.cs @@ -44,7 +44,9 @@ namespace osu.Game.Scoring protected override ScoreInfo? CreateModel(ArchiveReader archive) { - using (var stream = archive.GetStream(archive.Filenames.First(f => f.EndsWith(".osr", StringComparison.OrdinalIgnoreCase)))) + string name = archive.Filenames.First(f => f.EndsWith(".osr", StringComparison.OrdinalIgnoreCase)); + + using (var stream = archive.GetStream(name)) { try { @@ -52,7 +54,7 @@ namespace osu.Game.Scoring } catch (LegacyScoreDecoder.BeatmapNotFoundException e) { - Logger.Log(e.Message, LoggingTarget.Information, LogLevel.Error); + Logger.Log($@"Score '{name}' failed to import: no corresponding beatmap with the hash '{e.Hash}' could be found.", LoggingTarget.Database); return null; } } @@ -71,8 +73,8 @@ namespace osu.Game.Scoring // These properties are known to be non-null, but these final checks ensure a null hasn't come from somewhere (or the refetch has failed). // Under no circumstance do we want these to be written to realm as null. - if (model.BeatmapInfo == null) throw new ArgumentNullException(nameof(model.BeatmapInfo)); - if (model.Ruleset == null) throw new ArgumentNullException(nameof(model.Ruleset)); + ArgumentNullException.ThrowIfNull(model.BeatmapInfo); + ArgumentNullException.ThrowIfNull(model.Ruleset); PopulateMaximumStatistics(model); @@ -101,8 +103,7 @@ namespace osu.Game.Scoring // Populate the maximum statistics. HitResult maxBasicResult = rulesetInstance.GetHitResults() .Select(h => h.result) - .Where(h => h.IsBasic()) - .OrderByDescending(Judgement.ToNumericResult).First(); + .Where(h => h.IsBasic()).MaxBy(Judgement.ToNumericResult); foreach ((HitResult result, int count) in score.Statistics) { @@ -145,9 +146,9 @@ namespace osu.Game.Scoring #pragma warning restore CS0618 } - protected override void PostImport(ScoreInfo model, Realm realm, bool batchImport) + protected override void PostImport(ScoreInfo model, Realm realm, ImportParameters parameters) { - base.PostImport(model, realm, batchImport); + base.PostImport(model, realm, parameters); var userRequest = new GetUserRequest(model.RealmUser.Username); diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index a9ced62c95..1009474d89 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -317,7 +317,7 @@ namespace osu.Game.Scoring #endregion - public bool Equals(ScoreInfo other) => other.ID == ID; + public bool Equals(ScoreInfo? other) => other?.ID == ID; public override string ToString() => this.GetDisplayTitle(); } diff --git a/osu.Game/Scoring/ScoreManager.cs b/osu.Game/Scoring/ScoreManager.cs index b2944ad219..3217c79768 100644 --- a/osu.Game/Scoring/ScoreManager.cs +++ b/osu.Game/Scoring/ScoreManager.cs @@ -28,6 +28,16 @@ namespace osu.Game.Scoring private readonly OsuConfigManager configManager; private readonly ScoreImporter scoreImporter; + public override bool PauseImports + { + get => base.PauseImports; + set + { + base.PauseImports = value; + scoreImporter.PauseImports = value; + } + } + public ScoreManager(RulesetStore rulesets, Func beatmaps, Storage storage, RealmAccess realm, IAPIProvider api, OsuConfigManager configManager = null) : base(storage, realm) @@ -169,18 +179,18 @@ namespace osu.Game.Scoring public Task Import(params string[] paths) => scoreImporter.Import(paths); - public Task Import(params ImportTask[] tasks) => scoreImporter.Import(tasks); + public Task Import(ImportTask[] imports, ImportParameters parameters = default) => scoreImporter.Import(imports, parameters); public override bool IsAvailableLocally(ScoreInfo model) => Realm.Run(realm => realm.All().Any(s => s.OnlineID == model.OnlineID)); public IEnumerable HandledExtensions => scoreImporter.HandledExtensions; - public Task>> Import(ProgressNotification notification, params ImportTask[] tasks) => scoreImporter.Import(notification, tasks); + public Task>> Import(ProgressNotification notification, ImportTask[] tasks, ImportParameters parameters = default) => scoreImporter.Import(notification, tasks); public Task> ImportAsUpdate(ProgressNotification notification, ImportTask task, ScoreInfo original) => scoreImporter.ImportAsUpdate(notification, task, original); - public Live Import(ScoreInfo item, ArchiveReader archive = null, bool batchImport = false, CancellationToken cancellationToken = default) => - scoreImporter.ImportModel(item, archive, batchImport, cancellationToken); + public Live Import(ScoreInfo item, ArchiveReader archive = null, ImportParameters parameters = default, CancellationToken cancellationToken = default) => + scoreImporter.ImportModel(item, archive, parameters, cancellationToken); /// /// Populates the for a given . diff --git a/osu.Game/Scoring/ScoreModelDownloader.cs b/osu.Game/Scoring/ScoreModelDownloader.cs index 514b7a57de..c5434e8faf 100644 --- a/osu.Game/Scoring/ScoreModelDownloader.cs +++ b/osu.Game/Scoring/ScoreModelDownloader.cs @@ -17,7 +17,7 @@ namespace osu.Game.Scoring protected override ArchiveDownloadRequest CreateDownloadRequest(IScoreInfo score, bool minimiseDownload) => new DownloadReplayRequest(score); - public override ArchiveDownloadRequest GetExistingDownload(IScoreInfo model) + public override ArchiveDownloadRequest? GetExistingDownload(IScoreInfo model) => CurrentDownloads.Find(r => r.Model.MatchesOnlineID(model)); } } diff --git a/osu.Game/Scoring/ScorePerformanceCache.cs b/osu.Game/Scoring/ScorePerformanceCache.cs index f51fb41497..17a0c0ea6a 100644 --- a/osu.Game/Scoring/ScorePerformanceCache.cs +++ b/osu.Game/Scoring/ScorePerformanceCache.cs @@ -18,7 +18,7 @@ namespace osu.Game.Scoring /// A component which performs and acts as a central cache for performance calculations of locally databased scores. /// Currently not persisted between game sessions. /// - public class ScorePerformanceCache : MemoryCachingComponent + public partial class ScorePerformanceCache : MemoryCachingComponent { [Resolved] private BeatmapDifficultyCache difficultyCache { get; set; } diff --git a/osu.Game/Scoring/ScoringValues.cs b/osu.Game/Scoring/ScoringValues.cs deleted file mode 100644 index 471067c9db..0000000000 --- a/osu.Game/Scoring/ScoringValues.cs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -#nullable disable - -using MessagePack; -using osu.Game.Rulesets.Judgements; -using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Scoring; - -namespace osu.Game.Scoring -{ - /// - /// Stores the required scoring data that fulfils the minimum requirements for a to calculate score. - /// - [MessagePackObject] - public struct ScoringValues - { - /// - /// The sum of all "basic" scoring values. See: and . - /// - [Key(0)] - public long BaseScore; - - /// - /// The sum of all "bonus" scoring values. See: and . - /// - [Key(1)] - public long BonusScore; - - /// - /// The highest achieved combo. - /// - [Key(2)] - public int MaxCombo; - - /// - /// The count of "basic" s. See: . - /// - [Key(3)] - public int CountBasicHitObjects; - } -} diff --git a/osu.Game/Screens/BackgroundScreen.cs b/osu.Game/Screens/BackgroundScreen.cs index 8e1fd63040..a7502f22d5 100644 --- a/osu.Game/Screens/BackgroundScreen.cs +++ b/osu.Game/Screens/BackgroundScreen.cs @@ -11,7 +11,7 @@ using osuTK; namespace osu.Game.Screens { - public abstract class BackgroundScreen : Screen, IEquatable + public abstract partial class BackgroundScreen : Screen, IEquatable { protected const float TRANSITION_LENGTH = 500; private const float x_movement_amount = 50; diff --git a/osu.Game/Screens/BackgroundScreenStack.cs b/osu.Game/Screens/BackgroundScreenStack.cs index bafd1ff348..ca0dad83c8 100644 --- a/osu.Game/Screens/BackgroundScreenStack.cs +++ b/osu.Game/Screens/BackgroundScreenStack.cs @@ -9,7 +9,7 @@ using osu.Framework.Screens; namespace osu.Game.Screens { - public class BackgroundScreenStack : ScreenStack + public partial class BackgroundScreenStack : ScreenStack { public BackgroundScreenStack() : base(false) diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs index 4d84a8194d..312fd496a1 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs @@ -17,7 +17,7 @@ using osuTK; namespace osu.Game.Screens.Backgrounds { - public class BackgroundScreenBeatmap : BackgroundScreen + public partial class BackgroundScreenBeatmap : BackgroundScreen { /// /// The amount of blur to apply when full user blur is requested. @@ -99,6 +99,18 @@ namespace osu.Game.Screens.Backgrounds } } + /// + /// Reloads beatmap's background. + /// + public void RefreshBackground() + { + Schedule(() => + { + cancellationSource?.Cancel(); + LoadComponentAsync(new BeatmapBackground(beatmap), switchBackground, (cancellationSource = new CancellationTokenSource()).Token); + }); + } + private void switchBackground(BeatmapBackground b) { float newDepth = 0; @@ -122,7 +134,7 @@ namespace osu.Game.Screens.Backgrounds return base.Equals(other) && beatmap == otherBeatmapBackground.Beatmap; } - public class DimmableBackground : UserDimContainer + public partial class DimmableBackground : UserDimContainer { /// /// The amount of blur to be applied to the background in addition to user-specified blur. diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenBlack.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenBlack.cs index 4b0f262ab1..09778c5cdf 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenBlack.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenBlack.cs @@ -10,7 +10,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.Backgrounds { - public class BackgroundScreenBlack : BackgroundScreen + public partial class BackgroundScreenBlack : BackgroundScreen { public BackgroundScreenBlack() { diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenCustom.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenCustom.cs index 3dd72685e9..3c8ed6fe76 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenCustom.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenCustom.cs @@ -7,7 +7,7 @@ using osu.Game.Graphics.Backgrounds; namespace osu.Game.Screens.Backgrounds { - public class BackgroundScreenCustom : BackgroundScreen + public partial class BackgroundScreenCustom : BackgroundScreen { private readonly string textureName; diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs index 44b6fcce4a..0d9b39f099 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs @@ -19,7 +19,7 @@ using osu.Game.Skinning; namespace osu.Game.Screens.Backgrounds { - public class BackgroundScreenDefault : BackgroundScreen + public partial class BackgroundScreenDefault : BackgroundScreen { private Background background; diff --git a/osu.Game/Screens/Edit/BackgroundDimMenuItem.cs b/osu.Game/Screens/Edit/BackgroundDimMenuItem.cs index b5a33f06e7..2a1159eb27 100644 --- a/osu.Game/Screens/Edit/BackgroundDimMenuItem.cs +++ b/osu.Game/Screens/Edit/BackgroundDimMenuItem.cs @@ -5,17 +5,18 @@ using System.Collections.Generic; using osu.Framework.Bindables; using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics.UserInterface; +using osu.Game.Localisation; namespace osu.Game.Screens.Edit { internal class BackgroundDimMenuItem : MenuItem { - private readonly Bindable backgroudDim; + private readonly Bindable backgroundDim; private readonly Dictionary menuItemLookup = new Dictionary(); - public BackgroundDimMenuItem(Bindable backgroudDim) - : base("Background dim") + public BackgroundDimMenuItem(Bindable backgroundDim) + : base(GameplaySettingsStrings.BackgroundDim) { Items = new[] { @@ -25,8 +26,8 @@ namespace osu.Game.Screens.Edit createMenuItem(0.75f), }; - this.backgroudDim = backgroudDim; - backgroudDim.BindValueChanged(dim => + this.backgroundDim = backgroundDim; + backgroundDim.BindValueChanged(dim => { foreach (var kvp in menuItemLookup) kvp.Value.State.Value = kvp.Key == dim.NewValue ? TernaryState.True : TernaryState.False; @@ -40,6 +41,6 @@ namespace osu.Game.Screens.Edit return item; } - private void updateOpacity(float dim) => backgroudDim.Value = dim; + private void updateOpacity(float dim) => backgroundDim.Value = dim; } } diff --git a/osu.Game/Screens/Edit/BottomBar.cs b/osu.Game/Screens/Edit/BottomBar.cs index 444911cf2d..b8fed4b935 100644 --- a/osu.Game/Screens/Edit/BottomBar.cs +++ b/osu.Game/Screens/Edit/BottomBar.cs @@ -17,7 +17,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.Edit { - internal class BottomBar : CompositeDrawable + internal partial class BottomBar : CompositeDrawable { public TestGameplayButton TestGameplayButton { get; private set; } diff --git a/osu.Game/Screens/Edit/Components/BottomBarContainer.cs b/osu.Game/Screens/Edit/Components/BottomBarContainer.cs index 482a0bbe5f..0ba1ab9258 100644 --- a/osu.Game/Screens/Edit/Components/BottomBarContainer.cs +++ b/osu.Game/Screens/Edit/Components/BottomBarContainer.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Audio.Track; using osu.Framework.Bindables; @@ -14,7 +12,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.Edit.Components { - public class BottomBarContainer : Container + public partial class BottomBarContainer : Container { private const float contents_padding = 15; diff --git a/osu.Game/Screens/Edit/Components/EditorSidebar.cs b/osu.Game/Screens/Edit/Components/EditorSidebar.cs index da15512cdc..9a8c5115dd 100644 --- a/osu.Game/Screens/Edit/Components/EditorSidebar.cs +++ b/osu.Game/Screens/Edit/Components/EditorSidebar.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -16,7 +14,7 @@ namespace osu.Game.Screens.Edit.Components /// A sidebar area that can be attached to the left or right edge of the screen. /// Houses scrolling sectionised content. /// - internal class EditorSidebar : Container + internal partial class EditorSidebar : Container { public const float WIDTH = 250; diff --git a/osu.Game/Screens/Edit/Components/EditorSidebarSection.cs b/osu.Game/Screens/Edit/Components/EditorSidebarSection.cs index 6782b2f357..279793c0a1 100644 --- a/osu.Game/Screens/Edit/Components/EditorSidebarSection.cs +++ b/osu.Game/Screens/Edit/Components/EditorSidebarSection.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -15,7 +13,7 @@ using osuTK; namespace osu.Game.Screens.Edit.Components { - public class EditorSidebarSection : Container + public partial class EditorSidebarSection : Container { protected override Container Content { get; } @@ -41,7 +39,7 @@ namespace osu.Game.Screens.Edit.Components }; } - public class SectionHeader : CompositeDrawable + public partial class SectionHeader : CompositeDrawable { private readonly LocalisableString text; diff --git a/osu.Game/Screens/Edit/Components/Menus/EditorMenuBar.cs b/osu.Game/Screens/Edit/Components/Menus/EditorMenuBar.cs index 20b8bba6da..a911b4e1d8 100644 --- a/osu.Game/Screens/Edit/Components/Menus/EditorMenuBar.cs +++ b/osu.Game/Screens/Edit/Components/Menus/EditorMenuBar.cs @@ -12,7 +12,7 @@ using osuTK; namespace osu.Game.Screens.Edit.Components.Menus { - public class EditorMenuBar : OsuMenu + public partial class EditorMenuBar : OsuMenu { public EditorMenuBar() : base(Direction.Horizontal, true) @@ -33,7 +33,7 @@ namespace osu.Game.Screens.Edit.Components.Menus protected override DrawableMenuItem CreateDrawableMenuItem(MenuItem item) => new DrawableEditorBarMenuItem(item); - private class DrawableEditorBarMenuItem : DrawableOsuMenuItem + private partial class DrawableEditorBarMenuItem : DrawableOsuMenuItem { public DrawableEditorBarMenuItem(MenuItem item) : base(item) @@ -75,7 +75,7 @@ namespace osu.Game.Screens.Edit.Components.Menus protected override DrawableOsuMenuItem.TextContainer CreateTextContainer() => new TextContainer(); - private new class TextContainer : DrawableOsuMenuItem.TextContainer + private new partial class TextContainer : DrawableOsuMenuItem.TextContainer { public TextContainer() { @@ -85,7 +85,7 @@ namespace osu.Game.Screens.Edit.Components.Menus } } - private class SubMenu : OsuMenu + private partial class SubMenu : OsuMenu { public SubMenu() : base(Direction.Vertical) @@ -118,7 +118,7 @@ namespace osu.Game.Screens.Edit.Components.Menus } } - private class EditorStatefulMenuItem : DrawableStatefulMenuItem + private partial class EditorStatefulMenuItem : DrawableStatefulMenuItem { public EditorStatefulMenuItem(StatefulMenuItem item) : base(item) @@ -135,7 +135,7 @@ namespace osu.Game.Screens.Edit.Components.Menus } } - private class EditorMenuItem : DrawableOsuMenuItem + private partial class EditorMenuItem : DrawableOsuMenuItem { public EditorMenuItem(MenuItem item) : base(item) @@ -152,7 +152,7 @@ namespace osu.Game.Screens.Edit.Components.Menus } } - private class DrawableSpacer : DrawableOsuMenuItem + private partial class DrawableSpacer : DrawableOsuMenuItem { public DrawableSpacer(MenuItem item) : base(item) diff --git a/osu.Game/Screens/Edit/Components/Menus/EditorMenuItem.cs b/osu.Game/Screens/Edit/Components/Menus/EditorMenuItem.cs index 0a2c073dcd..368fe40977 100644 --- a/osu.Game/Screens/Edit/Components/Menus/EditorMenuItem.cs +++ b/osu.Game/Screens/Edit/Components/Menus/EditorMenuItem.cs @@ -2,21 +2,20 @@ // See the LICENCE file in the repository root for full licence text. using System; +using osu.Framework.Localisation; using osu.Game.Graphics.UserInterface; namespace osu.Game.Screens.Edit.Components.Menus { public class EditorMenuItem : OsuMenuItem { - private const int min_text_length = 40; - - public EditorMenuItem(string text, MenuItemType type = MenuItemType.Standard) - : base(text.PadRight(min_text_length), type) + public EditorMenuItem(LocalisableString text, MenuItemType type = MenuItemType.Standard) + : base(text, type) { } - public EditorMenuItem(string text, MenuItemType type, Action action) - : base(text.PadRight(min_text_length), type, action) + public EditorMenuItem(LocalisableString text, MenuItemType type, Action action) + : base(text, type, action) { } } diff --git a/osu.Game/Screens/Edit/Components/Menus/EditorScreenSwitcherControl.cs b/osu.Game/Screens/Edit/Components/Menus/EditorScreenSwitcherControl.cs index 0bba5a79ab..1f6d61d0ad 100644 --- a/osu.Game/Screens/Edit/Components/Menus/EditorScreenSwitcherControl.cs +++ b/osu.Game/Screens/Edit/Components/Menus/EditorScreenSwitcherControl.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; @@ -14,7 +12,7 @@ using osuTK; namespace osu.Game.Screens.Edit.Components.Menus { - public class EditorScreenSwitcherControl : OsuTabControl + public partial class EditorScreenSwitcherControl : OsuTabControl { public EditorScreenSwitcherControl() { @@ -38,11 +36,11 @@ namespace osu.Game.Screens.Edit.Components.Menus }); } - protected override Dropdown CreateDropdown() => null; + protected override Dropdown CreateDropdown() => null!; protected override TabItem CreateTabItem(EditorScreenMode value) => new TabItem(value); - private class TabItem : OsuTabItem + private partial class TabItem : OsuTabItem { private const float transition_length = 250; @@ -58,11 +56,6 @@ namespace osu.Game.Screens.Edit.Components.Menus Bar.Expire(); } - [BackgroundDependencyLoader] - private void load(OverlayColourProvider colourProvider) - { - } - protected override void OnActivated() { base.OnActivated(); diff --git a/osu.Game/Screens/Edit/Components/PlaybackControl.cs b/osu.Game/Screens/Edit/Components/PlaybackControl.cs index 30316cb12c..72c299f443 100644 --- a/osu.Game/Screens/Edit/Components/PlaybackControl.cs +++ b/osu.Game/Screens/Edit/Components/PlaybackControl.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Linq; using osuTK; using osuTK.Graphics; @@ -18,17 +16,18 @@ using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osu.Game.Localisation; using osu.Game.Overlays; using osuTK.Input; namespace osu.Game.Screens.Edit.Components { - public class PlaybackControl : BottomBarContainer + public partial class PlaybackControl : BottomBarContainer { - private IconButton playButton; + private IconButton playButton = null!; [Resolved] - private EditorClock editorClock { get; set; } + private EditorClock editorClock { get; set; } = null!; private readonly BindableNumber freqAdjust = new BindableDouble(1); @@ -49,7 +48,7 @@ namespace osu.Game.Screens.Edit.Components new OsuSpriteText { Origin = Anchor.BottomLeft, - Text = "Playback speed", + Text = EditorStrings.PlaybackSpeed, RelativePositionAxes = Axes.Y, Y = 0.5f, Padding = new MarginPadding { Left = 45 } @@ -102,13 +101,13 @@ namespace osu.Game.Screens.Edit.Components playButton.Icon = editorClock.IsRunning ? FontAwesome.Regular.PauseCircle : FontAwesome.Regular.PlayCircle; } - private class PlaybackTabControl : OsuTabControl + private partial class PlaybackTabControl : OsuTabControl { private static readonly double[] tempo_values = { 0.25, 0.5, 0.75, 1 }; protected override TabItem CreateTabItem(double value) => new PlaybackTabItem(value); - protected override Dropdown CreateDropdown() => null; + protected override Dropdown CreateDropdown() => null!; public PlaybackTabControl() { @@ -120,7 +119,7 @@ namespace osu.Game.Screens.Edit.Components Current.Value = tempo_values.Last(); } - public class PlaybackTabItem : TabItem + public partial class PlaybackTabItem : TabItem { private const float fade_duration = 200; diff --git a/osu.Game/Screens/Edit/Components/RadioButtons/EditorRadioButton.cs b/osu.Game/Screens/Edit/Components/RadioButtons/EditorRadioButton.cs index 071bb9fdcb..65f3e41c13 100644 --- a/osu.Game/Screens/Edit/Components/RadioButtons/EditorRadioButton.cs +++ b/osu.Game/Screens/Edit/Components/RadioButtons/EditorRadioButton.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; @@ -19,12 +17,12 @@ using osuTK.Graphics; namespace osu.Game.Screens.Edit.Components.RadioButtons { - public class EditorRadioButton : OsuButton, IHasTooltip + public partial class EditorRadioButton : OsuButton, IHasTooltip { /// /// Invoked when this has been selected. /// - public Action Selected; + public Action? Selected; public readonly RadioButton Button; @@ -33,10 +31,10 @@ namespace osu.Game.Screens.Edit.Components.RadioButtons private Color4 selectedBackgroundColour; private Color4 selectedIconColour; - private Drawable icon; + private Drawable icon = null!; - [Resolved(canBeNull: true)] - private EditorBeatmap editorBeatmap { get; set; } + [Resolved] + private EditorBeatmap? editorBeatmap { get; set; } public EditorRadioButton(RadioButton button) { diff --git a/osu.Game/Screens/Edit/Components/RadioButtons/EditorRadioButtonCollection.cs b/osu.Game/Screens/Edit/Components/RadioButtons/EditorRadioButtonCollection.cs index b8d1cca061..4391729adc 100644 --- a/osu.Game/Screens/Edit/Components/RadioButtons/EditorRadioButtonCollection.cs +++ b/osu.Game/Screens/Edit/Components/RadioButtons/EditorRadioButtonCollection.cs @@ -1,8 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - +using System; using System.Collections.Generic; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; @@ -11,9 +10,9 @@ using osuTK; namespace osu.Game.Screens.Edit.Components.RadioButtons { - public class EditorRadioButtonCollection : CompositeDrawable + public partial class EditorRadioButtonCollection : CompositeDrawable { - private IReadOnlyList items; + private IReadOnlyList items = Array.Empty(); public IReadOnlyList Items { @@ -45,7 +44,7 @@ namespace osu.Game.Screens.Edit.Components.RadioButtons }; } - private RadioButton currentlySelected; + private RadioButton? currentlySelected; private void addButton(RadioButton button) { diff --git a/osu.Game/Screens/Edit/Components/RadioButtons/RadioButton.cs b/osu.Game/Screens/Edit/Components/RadioButtons/RadioButton.cs index 03745ce19d..9dcd29bf83 100644 --- a/osu.Game/Screens/Edit/Components/RadioButtons/RadioButton.cs +++ b/osu.Game/Screens/Edit/Components/RadioButtons/RadioButton.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -24,11 +22,11 @@ namespace osu.Game.Screens.Edit.Components.RadioButtons /// /// A function which creates a drawable icon to represent this item. If null, a sane default should be used. /// - public readonly Func CreateIcon; + public readonly Func? CreateIcon; - private readonly Action action; + private readonly Action? action; - public RadioButton(string label, Action action, Func createIcon = null) + public RadioButton(string label, Action? action, Func? createIcon = null) { Label = label; CreateIcon = createIcon; diff --git a/osu.Game/Screens/Edit/Components/TernaryButtons/DrawableTernaryButton.cs b/osu.Game/Screens/Edit/Components/TernaryButtons/DrawableTernaryButton.cs index 1fb5c0285d..873551db77 100644 --- a/osu.Game/Screens/Edit/Components/TernaryButtons/DrawableTernaryButton.cs +++ b/osu.Game/Screens/Edit/Components/TernaryButtons/DrawableTernaryButton.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -16,14 +14,14 @@ using osuTK.Graphics; namespace osu.Game.Screens.Edit.Components.TernaryButtons { - internal class DrawableTernaryButton : OsuButton + internal partial class DrawableTernaryButton : OsuButton { private Color4 defaultBackgroundColour; private Color4 defaultIconColour; private Color4 selectedBackgroundColour; private Color4 selectedIconColour; - private Drawable icon; + private Drawable icon = null!; public readonly TernaryButton Button; diff --git a/osu.Game/Screens/Edit/Components/TernaryButtons/TernaryButton.cs b/osu.Game/Screens/Edit/Components/TernaryButtons/TernaryButton.cs index 8eb781c947..0ff2aa83b5 100644 --- a/osu.Game/Screens/Edit/Components/TernaryButtons/TernaryButton.cs +++ b/osu.Game/Screens/Edit/Components/TernaryButtons/TernaryButton.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -19,9 +17,9 @@ namespace osu.Game.Screens.Edit.Components.TernaryButtons /// /// A function which creates a drawable icon to represent this item. If null, a sane default should be used. /// - public readonly Func CreateIcon; + public readonly Func? CreateIcon; - public TernaryButton(Bindable bindable, string description, Func createIcon = null) + public TernaryButton(Bindable bindable, string description, Func? createIcon = null) { Bindable = bindable; Description = description; diff --git a/osu.Game/Screens/Edit/Components/TimeInfoContainer.cs b/osu.Game/Screens/Edit/Components/TimeInfoContainer.cs index 7051dd226c..9c51258f17 100644 --- a/osu.Game/Screens/Edit/Components/TimeInfoContainer.cs +++ b/osu.Game/Screens/Edit/Components/TimeInfoContainer.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Graphics; using osu.Game.Graphics.Sprites; using osu.Framework.Allocation; @@ -13,16 +11,16 @@ using osuTK; namespace osu.Game.Screens.Edit.Components { - public class TimeInfoContainer : BottomBarContainer + public partial class TimeInfoContainer : BottomBarContainer { - private OsuSpriteText trackTimer; - private OsuSpriteText bpm; + private OsuSpriteText trackTimer = null!; + private OsuSpriteText bpm = null!; [Resolved] - private EditorBeatmap editorBeatmap { get; set; } + private EditorBeatmap editorBeatmap { get; set; } = null!; [Resolved] - private EditorClock editorClock { get; set; } + private EditorClock editorClock { get; set; } = null!; [BackgroundDependencyLoader] private void load(OsuColour colours, OverlayColourProvider colourProvider) diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BookmarkPart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BookmarkPart.cs index 058aa83b97..3102bf7c06 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BookmarkPart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BookmarkPart.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Game.Graphics; using osu.Game.Screens.Edit.Components.Timelines.Summary.Visualisations; @@ -12,7 +10,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts /// /// The part of the timeline that displays bookmarks. /// - public class BookmarkPart : TimelinePart + public partial class BookmarkPart : TimelinePart { protected override void LoadBeatmap(EditorBeatmap beatmap) { @@ -21,7 +19,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts Add(new BookmarkVisualisation(bookmark)); } - private class BookmarkVisualisation : PointVisualisation + private partial class BookmarkVisualisation : PointVisualisation { public BookmarkVisualisation(double startTime) : base(startTime) diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BreakPart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BreakPart.cs index 4dbec880dc..e502dd951b 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BreakPart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BreakPart.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Game.Beatmaps.Timing; using osu.Game.Graphics; @@ -13,7 +11,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts /// /// The part of the timeline that displays breaks in the song. /// - public class BreakPart : TimelinePart + public partial class BreakPart : TimelinePart { protected override void LoadBeatmap(EditorBeatmap beatmap) { @@ -22,7 +20,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts Add(new BreakVisualisation(breakPeriod)); } - private class BreakVisualisation : DurationVisualisation + private partial class BreakVisualisation : DurationVisualisation { public BreakVisualisation(BreakPeriod breakPeriod) : base(breakPeriod.StartTime, breakPeriod.EndTime) diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointPart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointPart.cs index 54ef5a2bd7..6f53f710ba 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointPart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointPart.cs @@ -1,10 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Collections.Specialized; +using System.Diagnostics; using System.Linq; using osu.Framework.Bindables; using osu.Game.Beatmaps.ControlPoints; @@ -14,7 +13,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts /// /// The part of the timeline that displays the control points. /// - public class ControlPointPart : TimelinePart + public partial class ControlPointPart : TimelinePart { private readonly IBindableList controlPointGroups = new BindableList(); @@ -33,6 +32,8 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts break; case NotifyCollectionChangedAction.Add: + Debug.Assert(args.NewItems != null); + foreach (var group in args.NewItems.OfType()) { // as an optimisation, don't add a visualisation if there are already groups with the same types in close proximity. @@ -47,6 +48,8 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts break; case NotifyCollectionChangedAction.Remove: + Debug.Assert(args.OldItems != null); + foreach (var group in args.OldItems.OfType()) { var matching = Children.SingleOrDefault(gv => ReferenceEquals(gv.Group, group)); diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointVisualisation.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointVisualisation.cs index 89c0309222..12620963e1 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointVisualisation.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointVisualisation.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Beatmaps.ControlPoints; @@ -11,7 +9,7 @@ using osu.Game.Screens.Edit.Components.Timelines.Summary.Visualisations; namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts { - public class ControlPointVisualisation : PointVisualisation, IControlPointVisualisation + public partial class ControlPointVisualisation : PointVisualisation, IControlPointVisualisation { protected readonly ControlPoint Point; diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/EffectPointVisualisation.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/EffectPointVisualisation.cs index b61fcf4482..d92beba38a 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/EffectPointVisualisation.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/EffectPointVisualisation.cs @@ -13,7 +13,7 @@ using osu.Game.Screens.Edit.Components.Timelines.Summary.Visualisations; namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts { - public class EffectPointVisualisation : CompositeDrawable, IControlPointVisualisation + public partial class EffectPointVisualisation : CompositeDrawable, IControlPointVisualisation { private readonly EffectControlPoint effect; private Bindable kiai = null!; diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/GroupVisualisation.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/GroupVisualisation.cs index e058cae191..b39365277f 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/GroupVisualisation.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/GroupVisualisation.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Linq; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -11,7 +9,7 @@ using osu.Game.Beatmaps.ControlPoints; namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts { - public class GroupVisualisation : CompositeDrawable + public partial class GroupVisualisation : CompositeDrawable { public readonly ControlPointGroup Group; diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/IControlPointVisualisation.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/IControlPointVisualisation.cs index b9e2a969a5..c81f1828f7 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/IControlPointVisualisation.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/IControlPointVisualisation.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Game.Beatmaps.ControlPoints; namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs index c00ebb32bc..d42c02e03d 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -18,12 +16,12 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts /// /// The part of the timeline that displays the current position of the song. /// - public class MarkerPart : TimelinePart + public partial class MarkerPart : TimelinePart { - private Drawable marker; + private Drawable marker = null!; [Resolved] - private EditorClock editorClock { get; set; } + private EditorClock editorClock { get; set; } = null!; [BackgroundDependencyLoader] private void load() @@ -44,7 +42,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts return true; } - private ScheduledDelegate scheduledSeek; + private ScheduledDelegate? scheduledSeek; /// /// Seeks the to the time closest to a position on the screen relative to the . @@ -71,7 +69,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts // block base call so we don't clear our marker (can be reused on beatmap change). } - private class MarkerVisualisation : CompositeDrawable + private partial class MarkerVisualisation : CompositeDrawable { public MarkerVisualisation() { diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/PreviewTimePart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/PreviewTimePart.cs new file mode 100644 index 0000000000..c63bb7ac24 --- /dev/null +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/PreviewTimePart.cs @@ -0,0 +1,41 @@ +// Copyright (c) ppy Pty Ltd . 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.Game.Graphics; +using osu.Game.Screens.Edit.Components.Timelines.Summary.Visualisations; + +namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts +{ + public partial class PreviewTimePart : TimelinePart + { + private readonly BindableInt previewTime = new BindableInt(); + + protected override void LoadBeatmap(EditorBeatmap beatmap) + { + base.LoadBeatmap(beatmap); + + previewTime.UnbindAll(); + previewTime.BindTo(beatmap.PreviewTime); + previewTime.BindValueChanged(t => + { + Clear(); + + if (t.NewValue >= 0) + Add(new PreviewTimeVisualisation(t.NewValue)); + }, true); + } + + private partial class PreviewTimeVisualisation : PointVisualisation + { + public PreviewTimeVisualisation(double time) + : base(time) + { + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) => Colour = colours.Green1; + } + } +} diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs index bb5b4a6cea..ee7e759ebc 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using osu.Framework.Allocation; using osu.Framework.Audio.Track; @@ -14,19 +12,19 @@ using osu.Game.Beatmaps; namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts { - public class TimelinePart : TimelinePart + public partial class TimelinePart : TimelinePart { } /// /// Represents a part of the summary timeline.. /// - public class TimelinePart : Container where T : Drawable + public partial class TimelinePart : Container where T : Drawable { private readonly IBindable beatmap = new Bindable(); [Resolved] - protected EditorBeatmap EditorBeatmap { get; private set; } + protected EditorBeatmap EditorBeatmap { get; private set; } = null!; protected readonly IBindable Track = new Bindable(); @@ -34,7 +32,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts protected override Container Content => content; - public TimelinePart(Container content = null) + public TimelinePart(Container? content = null) { AddInternal(this.content = content ?? new Container { RelativeSizeAxes = Axes.Both }); diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/SummaryTimeline.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/SummaryTimeline.cs index afaedee0a9..6199cefb57 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/SummaryTimeline.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/SummaryTimeline.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -16,7 +14,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary /// /// The timeline that sits at the bottom of the editor. /// - public class SummaryTimeline : BottomBarContainer + public partial class SummaryTimeline : BottomBarContainer { [BackgroundDependencyLoader] private void load(OverlayColourProvider colourProvider) @@ -41,6 +39,13 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary RelativeSizeAxes = Axes.Both, Height = 0.35f }, + new PreviewTimePart + { + Anchor = Anchor.Centre, + Origin = Anchor.TopCentre, + RelativeSizeAxes = Axes.Both, + Height = 0.35f + }, new Container { Name = "centre line", diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/TestGameplayButton.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/TestGameplayButton.cs index d38596b9be..169e72fe3f 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/TestGameplayButton.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/TestGameplayButton.cs @@ -1,19 +1,18 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osu.Game.Localisation; using osu.Game.Overlays; namespace osu.Game.Screens.Edit.Components.Timelines.Summary { - public class TestGameplayButton : OsuButton + public partial class TestGameplayButton : OsuButton { protected override SpriteText CreateText() => new OsuSpriteText { @@ -32,7 +31,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary Content.CornerRadius = 0; - Text = "Test!"; + Text = EditorStrings.TestBeatmap; } } } diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/DurationVisualisation.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/DurationVisualisation.cs index 88e40cb305..bfb50a05ea 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/DurationVisualisation.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/DurationVisualisation.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; @@ -11,7 +9,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Visualisations /// /// Represents a spanning point on a timeline part. /// - public class DurationVisualisation : Circle + public partial class DurationVisualisation : Circle { protected DurationVisualisation(double startTime, double endTime) { diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/PointVisualisation.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/PointVisualisation.cs index b8e55c8db8..3f0c125ada 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/PointVisualisation.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/PointVisualisation.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; @@ -11,7 +9,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Visualisations /// /// Represents a singular point on a timeline part. /// - public class PointVisualisation : Circle + public partial class PointVisualisation : Circle { public const float MAX_WIDTH = 4; diff --git a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs index 6dca799549..9f422d5aa9 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs @@ -29,7 +29,7 @@ using osuTK.Input; namespace osu.Game.Screens.Edit.Compose.Components { - public class BeatDivisorControl : CompositeDrawable + public partial class BeatDivisorControl : CompositeDrawable { private readonly BindableBeatDivisor beatDivisor = new BindableBeatDivisor(); @@ -220,7 +220,7 @@ namespace osu.Game.Screens.Edit.Compose.Components return base.OnKeyDown(e); } - internal class DivisorDisplay : OsuAnimatedButton, IHasPopover + internal partial class DivisorDisplay : OsuAnimatedButton, IHasPopover { public BindableBeatDivisor BeatDivisor { get; } = new BindableBeatDivisor(); @@ -270,7 +270,7 @@ namespace osu.Game.Screens.Edit.Compose.Components }; } - internal class CustomDivisorPopover : OsuPopover + internal partial class CustomDivisorPopover : OsuPopover { public BindableBeatDivisor BeatDivisor { get; } = new BindableBeatDivisor(); @@ -328,7 +328,7 @@ namespace osu.Game.Screens.Edit.Compose.Components } } - private class DivisorTypeText : OsuSpriteText + private partial class DivisorTypeText : OsuSpriteText { public BindableBeatDivisor BeatDivisor { get; } = new BindableBeatDivisor(); @@ -347,7 +347,7 @@ namespace osu.Game.Screens.Edit.Compose.Components } } - internal class ChevronButton : IconButton + internal partial class ChevronButton : IconButton { public ChevronButton() { @@ -370,7 +370,7 @@ namespace osu.Game.Screens.Edit.Compose.Components } } - private class TickSliderBar : SliderBar + private partial class TickSliderBar : SliderBar { private Marker marker; @@ -479,13 +479,13 @@ namespace osu.Game.Screens.Edit.Compose.Components // copied from SliderBar so we can do custom spacing logic. float xPosition = (ToLocalSpace(screenSpaceMousePosition).X - RangePadding) / UsableWidth; - CurrentNumber.Value = beatDivisor.ValidDivisors.Value.Presets.OrderBy(d => Math.Abs(getMappedPosition(d) - xPosition)).First(); + CurrentNumber.Value = beatDivisor.ValidDivisors.Value.Presets.MinBy(d => Math.Abs(getMappedPosition(d) - xPosition)); OnUserChange(Current.Value); } private float getMappedPosition(float divisor) => MathF.Pow((divisor - 1) / (beatDivisor.ValidDivisors.Value.Presets.Last() - 1), 0.90f); - private class Tick : Circle + private partial class Tick : Circle { public Tick(int divisor) { @@ -494,7 +494,7 @@ namespace osu.Game.Screens.Edit.Compose.Components } } - private class Marker : CompositeDrawable + private partial class Marker : CompositeDrawable { [Resolved] private OverlayColourProvider colourProvider { get; set; } diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 43ad270c16..77892f21e6 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -26,7 +26,7 @@ namespace osu.Game.Screens.Edit.Compose.Components /// A container which provides a "blueprint" display of items. /// Includes selection and manipulation support via a . /// - public abstract class BlueprintContainer : CompositeDrawable, IKeyBindingHandler + public abstract partial class BlueprintContainer : CompositeDrawable, IKeyBindingHandler where T : class { protected DragBox DragBox { get; private set; } @@ -58,6 +58,8 @@ namespace osu.Game.Screens.Edit.Compose.Components switch (args.Action) { case NotifyCollectionChangedAction.Add: + Debug.Assert(args.NewItems != null); + foreach (object o in args.NewItems) { if (blueprintMap.TryGetValue((T)o, out var blueprint)) @@ -67,6 +69,8 @@ namespace osu.Game.Screens.Edit.Compose.Components break; case NotifyCollectionChangedAction.Remove: + Debug.Assert(args.OldItems != null); + foreach (object o in args.OldItems) { if (blueprintMap.TryGetValue((T)o, out var blueprint)) diff --git a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs index 6e54e98740..d6e4e1f030 100644 --- a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs @@ -16,7 +16,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.Edit.Compose.Components { - public abstract class CircularDistanceSnapGrid : DistanceSnapGrid + public abstract partial class CircularDistanceSnapGrid : DistanceSnapGrid { protected CircularDistanceSnapGrid(HitObject referenceObject, Vector2 startPosition, double startTime, double? endTime = null) : base(referenceObject, startPosition, startTime, endTime) @@ -117,7 +117,7 @@ namespace osu.Game.Screens.Edit.Compose.Components return (snappedPosition, snappedTime); } - private class Ring : CircularProgress + private partial class Ring : CircularProgress { [Resolved] private IDistanceSnapProvider snapProvider { get; set; } diff --git a/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs index ec07da43a0..836fceea22 100644 --- a/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs @@ -20,6 +20,7 @@ using osu.Game.Rulesets.Edit.Tools; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.UI; using osu.Game.Screens.Edit.Components.TernaryButtons; using osuTK; using osuTK.Input; @@ -29,13 +30,13 @@ namespace osu.Game.Screens.Edit.Compose.Components /// /// A blueprint container generally displayed as an overlay to a ruleset's playfield. /// - public class ComposeBlueprintContainer : EditorBlueprintContainer + public partial class ComposeBlueprintContainer : EditorBlueprintContainer { private readonly Container placementBlueprintContainer; protected new EditorSelectionHandler SelectionHandler => (EditorSelectionHandler)base.SelectionHandler; - private PlacementBlueprint currentPlacement; + public PlacementBlueprint CurrentPlacement { get; private set; } /// /// Positional input must be received outside the container's bounds, @@ -57,7 +58,10 @@ namespace osu.Game.Screens.Edit.Compose.Components { TernaryStates = CreateTernaryButtons().ToArray(); - AddInternal(placementBlueprintContainer); + AddInternal(new DrawableRulesetDependenciesProvidingContainer(Composer.Ruleset) + { + Child = placementBlueprintContainer + }); } protected override void LoadComplete() @@ -133,13 +137,13 @@ namespace osu.Game.Screens.Edit.Compose.Components private void updatePlacementNewCombo() { - if (currentPlacement?.HitObject is IHasComboInformation c) + if (CurrentPlacement?.HitObject is IHasComboInformation c) c.NewCombo = NewCombo.Value == TernaryState.True; } private void updatePlacementSamples() { - if (currentPlacement == null) return; + if (CurrentPlacement == null) return; foreach (var kvp in SelectionHandler.SelectionSampleStates) sampleChanged(kvp.Key, kvp.Value.Value); @@ -147,9 +151,9 @@ namespace osu.Game.Screens.Edit.Compose.Components private void sampleChanged(string sampleName, TernaryState state) { - if (currentPlacement == null) return; + if (CurrentPlacement == null) return; - var samples = currentPlacement.HitObject.Samples; + var samples = CurrentPlacement.HitObject.Samples; var existingSample = samples.FirstOrDefault(s => s.Name == sampleName); @@ -221,7 +225,7 @@ namespace osu.Game.Screens.Edit.Compose.Components // if no time was found from positional snapping, we should still quantize to the beat. snapResult.Time ??= Beatmap.SnapTime(EditorClock.CurrentTime, null); - currentPlacement.UpdateTimeAndPosition(snapResult); + CurrentPlacement.UpdateTimeAndPosition(snapResult); } #endregion @@ -230,9 +234,9 @@ namespace osu.Game.Screens.Edit.Compose.Components { base.Update(); - if (currentPlacement != null) + if (CurrentPlacement != null) { - switch (currentPlacement.PlacementActive) + switch (CurrentPlacement.PlacementActive) { case PlacementBlueprint.PlacementState.Waiting: if (!Composer.CursorInPlacementArea) @@ -248,7 +252,7 @@ namespace osu.Game.Screens.Edit.Compose.Components if (Composer.CursorInPlacementArea) ensurePlacementCreated(); - if (currentPlacement != null) + if (CurrentPlacement != null) updatePlacementPosition(); } @@ -277,13 +281,13 @@ namespace osu.Game.Screens.Edit.Compose.Components private void ensurePlacementCreated() { - if (currentPlacement != null) return; + if (CurrentPlacement != null) return; var blueprint = CurrentTool?.CreatePlacementBlueprint(); if (blueprint != null) { - placementBlueprintContainer.Child = currentPlacement = blueprint; + placementBlueprintContainer.Child = CurrentPlacement = blueprint; // Fixes a 1-frame position discrepancy due to the first mouse move event happening in the next frame updatePlacementPosition(); @@ -296,11 +300,11 @@ namespace osu.Game.Screens.Edit.Compose.Components private void removePlacement() { - if (currentPlacement == null) return; + if (CurrentPlacement == null) return; - currentPlacement.EndPlacement(false); - currentPlacement.Expire(); - currentPlacement = null; + CurrentPlacement.EndPlacement(false); + CurrentPlacement.Expire(); + CurrentPlacement = null; } private HitObjectCompositionTool currentTool; diff --git a/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs index c179e7f0c2..6092ebc08f 100644 --- a/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs @@ -21,7 +21,7 @@ namespace osu.Game.Screens.Edit.Compose.Components /// /// A grid which takes user input and returns a quantized ("snapped") position and time. /// - public abstract class DistanceSnapGrid : CompositeDrawable + public abstract partial class DistanceSnapGrid : CompositeDrawable { /// /// The spacing between each tick of the beat snapping grid. diff --git a/osu.Game/Screens/Edit/Compose/Components/DragBox.cs b/osu.Game/Screens/Edit/Compose/Components/DragBox.cs index 905d47533a..4d1f81228e 100644 --- a/osu.Game/Screens/Edit/Compose/Components/DragBox.cs +++ b/osu.Game/Screens/Edit/Compose/Components/DragBox.cs @@ -18,7 +18,7 @@ namespace osu.Game.Screens.Edit.Compose.Components /// /// A box that displays the drag selection and provides selection events for users to handle. /// - public class DragBox : CompositeDrawable, IStateful + public partial class DragBox : CompositeDrawable, IStateful { public Drawable Box { get; private set; } @@ -71,7 +71,7 @@ namespace osu.Game.Screens.Edit.Compose.Components public event Action StateChanged; - public class BoxWithBorders : CompositeDrawable + public partial class BoxWithBorders : CompositeDrawable { private readonly LayoutValue cache = new LayoutValue(Invalidation.RequiredParentSizeToFit); diff --git a/osu.Game/Screens/Edit/Compose/Components/EditorBlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/EditorBlueprintContainer.cs index 7423b368b4..65797a968d 100644 --- a/osu.Game/Screens/Edit/Compose/Components/EditorBlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/EditorBlueprintContainer.cs @@ -16,7 +16,7 @@ using osu.Game.Rulesets.Objects.Drawables; namespace osu.Game.Screens.Edit.Compose.Components { - public class EditorBlueprintContainer : BlueprintContainer + public partial class EditorBlueprintContainer : BlueprintContainer { [Resolved] protected EditorClock EditorClock { get; private set; } diff --git a/osu.Game/Screens/Edit/Compose/Components/EditorSelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/EditorSelectionHandler.cs index 0bdfc5b0a0..357cc940f2 100644 --- a/osu.Game/Screens/Edit/Compose/Components/EditorSelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/EditorSelectionHandler.cs @@ -18,7 +18,7 @@ using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Screens.Edit.Compose.Components { - public class EditorSelectionHandler : SelectionHandler + public partial class EditorSelectionHandler : SelectionHandler { [Resolved] protected EditorBeatmap EditorBeatmap { get; private set; } diff --git a/osu.Game/Screens/Edit/Compose/Components/HitObjectOrderedSelectionContainer.cs b/osu.Game/Screens/Edit/Compose/Components/HitObjectOrderedSelectionContainer.cs index 18bb6284b8..849a526556 100644 --- a/osu.Game/Screens/Edit/Compose/Components/HitObjectOrderedSelectionContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/HitObjectOrderedSelectionContainer.cs @@ -15,7 +15,7 @@ namespace osu.Game.Screens.Edit.Compose.Components /// /// A container for ordered by their start times. /// - public sealed class HitObjectOrderedSelectionContainer : Container> + public sealed partial class HitObjectOrderedSelectionContainer : Container> { [Resolved] private EditorBeatmap editorBeatmap { get; set; } diff --git a/osu.Game/Screens/Edit/Compose/Components/RectangularPositionSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/RectangularPositionSnapGrid.cs index 64fb2ccaba..06b73c8af4 100644 --- a/osu.Game/Screens/Edit/Compose/Components/RectangularPositionSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/RectangularPositionSnapGrid.cs @@ -15,7 +15,7 @@ using osuTK; namespace osu.Game.Screens.Edit.Compose.Components { - public class RectangularPositionSnapGrid : CompositeDrawable + public partial class RectangularPositionSnapGrid : CompositeDrawable { /// /// The position of the origin of this in local coordinates. diff --git a/osu.Game/Screens/Edit/Compose/Components/ScrollingDragBox.cs b/osu.Game/Screens/Edit/Compose/Components/ScrollingDragBox.cs index 58bfaf56ff..599e64760d 100644 --- a/osu.Game/Screens/Edit/Compose/Components/ScrollingDragBox.cs +++ b/osu.Game/Screens/Edit/Compose/Components/ScrollingDragBox.cs @@ -11,7 +11,7 @@ namespace osu.Game.Screens.Edit.Compose.Components /// /// A that scrolls along with the scrolling playfield. /// - public class ScrollingDragBox : DragBox + public partial class ScrollingDragBox : DragBox { public double MinTime { get; private set; } diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs index 2c4c220ad0..17790547ed 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs @@ -18,7 +18,7 @@ using osuTK.Input; namespace osu.Game.Screens.Edit.Compose.Components { [Cached] - public class SelectionBox : CompositeDrawable + public partial class SelectionBox : CompositeDrawable { public const float BORDER_RADIUS = 3; diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxButton.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxButton.cs index 3d6dacc95e..832d8b65e5 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxButton.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxButton.cs @@ -15,7 +15,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.Edit.Compose.Components { - public sealed class SelectionBoxButton : SelectionBoxControl, IHasTooltip + public sealed partial class SelectionBoxButton : SelectionBoxControl, IHasTooltip { private SpriteIcon icon; diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs index c4675685f6..35c67a1c67 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs @@ -17,7 +17,7 @@ namespace osu.Game.Screens.Edit.Compose.Components /// Represents the base appearance for UI controls of the , /// such as scale handles, rotation handles, buttons, etc... /// - public abstract class SelectionBoxControl : CompositeDrawable + public abstract partial class SelectionBoxControl : CompositeDrawable { public const double TRANSFORM_DURATION = 100; diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandle.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandle.cs index 308d0cc893..757ff655f5 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandle.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandle.cs @@ -8,7 +8,7 @@ using osu.Framework.Input.Events; namespace osu.Game.Screens.Edit.Compose.Components { - public abstract class SelectionBoxDragHandle : SelectionBoxControl + public abstract partial class SelectionBoxDragHandle : SelectionBoxControl { protected override bool OnDragStart(DragStartEvent e) { diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandleContainer.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandleContainer.cs index 5c7debf57e..5c87271493 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandleContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandleContainer.cs @@ -15,7 +15,7 @@ namespace osu.Game.Screens.Edit.Compose.Components /// /// Represents a display composite containing and managing the visibility state of the selection box's drag handles. /// - public class SelectionBoxDragHandleContainer : CompositeDrawable + public partial class SelectionBoxDragHandleContainer : CompositeDrawable { private Container scaleHandles; private Container rotationHandles; diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs index 761cd118bf..0f702e1c49 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs @@ -18,7 +18,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.Edit.Compose.Components { - public class SelectionBoxRotationHandle : SelectionBoxDragHandle, IHasTooltip + public partial class SelectionBoxRotationHandle : SelectionBoxDragHandle, IHasTooltip { public Action HandleRotate { get; set; } diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxScaleHandle.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxScaleHandle.cs index bd1e2f4649..7943065c82 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxScaleHandle.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxScaleHandle.cs @@ -11,7 +11,7 @@ using osuTK; namespace osu.Game.Screens.Edit.Compose.Components { - public class SelectionBoxScaleHandle : SelectionBoxDragHandle + public partial class SelectionBoxScaleHandle : SelectionBoxDragHandle { public Action HandleScale { get; set; } diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index 269c19f846..a0ac99fec2 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -30,7 +30,7 @@ namespace osu.Game.Screens.Edit.Compose.Components /// /// A component which outlines items and handles movement of selections. /// - public abstract class SelectionHandler : CompositeDrawable, IKeyBindingHandler, IKeyBindingHandler, IHasContextMenu + public abstract partial class SelectionHandler : CompositeDrawable, IKeyBindingHandler, IKeyBindingHandler, IHasContextMenu { /// /// The currently selected blueprints. diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/CentreMarker.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/CentreMarker.cs index 6c545f8f78..44daf70577 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/CentreMarker.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/CentreMarker.cs @@ -12,7 +12,7 @@ using osuTK; namespace osu.Game.Screens.Edit.Compose.Components.Timeline { - public class CentreMarker : CompositeDrawable + public partial class CentreMarker : CompositeDrawable { private const float triangle_width = 15; private const float triangle_height = 10; diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs index b028f67ba1..d3cdd461ea 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs @@ -22,7 +22,7 @@ using osuTK; namespace osu.Game.Screens.Edit.Compose.Components.Timeline { - public class DifficultyPointPiece : HitObjectPointPiece, IHasPopover + public partial class DifficultyPointPiece : HitObjectPointPiece, IHasPopover { public readonly HitObject HitObject; @@ -51,7 +51,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline public Popover GetPopover() => new DifficultyEditPopover(HitObject); - public class DifficultyEditPopover : OsuPopover + public partial class DifficultyEditPopover : OsuPopover { private readonly HitObject hitObject; diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/HitObjectPointPiece.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/HitObjectPointPiece.cs index 1091afe226..5b0a5729c8 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/HitObjectPointPiece.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/HitObjectPointPiece.cs @@ -14,7 +14,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.Edit.Compose.Components.Timeline { - public class HitObjectPointPiece : CircularContainer + public partial class HitObjectPointPiece : CircularContainer { private readonly ControlPoint point; diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/SamplePointPiece.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/SamplePointPiece.cs index 648ffd9609..314137a565 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/SamplePointPiece.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/SamplePointPiece.cs @@ -20,7 +20,7 @@ using osuTK; namespace osu.Game.Screens.Edit.Compose.Components.Timeline { - public class SamplePointPiece : HitObjectPointPiece, IHasPopover + public partial class SamplePointPiece : HitObjectPointPiece, IHasPopover { public readonly HitObject HitObject; @@ -55,7 +55,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline public Popover GetPopover() => new SampleEditPopover(HitObject); - public class SampleEditPopover : OsuPopover + public partial class SampleEditPopover : OsuPopover { private readonly HitObject hitObject; diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs index 8befda82e8..75de15fe56 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs @@ -5,6 +5,7 @@ using System; using osu.Framework.Allocation; +using osu.Framework.Audio.Track; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -22,7 +23,7 @@ using osuTK.Input; namespace osu.Game.Screens.Edit.Compose.Components.Timeline { [Cached] - public class Timeline : ZoomableScrollContainer, IPositionSnapProvider + public partial class Timeline : ZoomableScrollContainer, IPositionSnapProvider { private const float timeline_height = 72; private const float timeline_expanded_height = 94; @@ -35,8 +36,6 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline public readonly Bindable TicksVisible = new Bindable(); - public readonly IBindable Beatmap = new Bindable(); - [Resolved] private EditorClock editorClock { get; set; } @@ -92,6 +91,8 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline private double trackLengthForZoom; + private readonly IBindable track = new Bindable(); + [BackgroundDependencyLoader] private void load(IBindable beatmap, OsuColour colours, OsuConfigManager config) { @@ -139,11 +140,8 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline waveformOpacity = config.GetBindable(OsuSetting.EditorWaveformOpacity); - Beatmap.BindTo(beatmap); - Beatmap.BindValueChanged(b => - { - waveform.Waveform = b.NewValue.Waveform; - }, true); + track.BindTo(editorClock.Track); + track.BindValueChanged(_ => waveform.Waveform = beatmap.Value.Waveform, true); Zoom = (float)(defaultTimelineZoom * editorBeatmap.BeatmapInfo.TimelineZoom); } diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs index 58d378154a..0b83258f8b 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs @@ -9,12 +9,14 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osu.Game.Localisation; using osu.Game.Overlays; +using osu.Game.Resources.Localisation.Web; using osuTK; namespace osu.Game.Screens.Edit.Compose.Components.Timeline { - public class TimelineArea : CompositeDrawable + public partial class TimelineArea : CompositeDrawable { public Timeline Timeline; @@ -75,17 +77,17 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline { waveformCheckbox = new OsuCheckbox { - LabelText = "Waveform", + LabelText = EditorStrings.TimelineWaveform, Current = { Value = true }, }, ticksCheckbox = new OsuCheckbox { - LabelText = "Ticks", + LabelText = EditorStrings.TimelineTicks, Current = { Value = true }, }, controlPointsCheckbox = new OsuCheckbox { - LabelText = "BPM", + LabelText = BeatmapsetsStrings.ShowStatsBpm, Current = { Value = true }, }, } diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineBlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineBlueprintContainer.cs index b79c2675c8..f93fb0679f 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineBlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineBlueprintContainer.cs @@ -24,7 +24,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.Edit.Compose.Components.Timeline { - internal class TimelineBlueprintContainer : EditorBlueprintContainer + internal partial class TimelineBlueprintContainer : EditorBlueprintContainer { [Resolved(CanBeNull = true)] private Timeline timeline { get; set; } @@ -198,7 +198,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline timeline.ScrollBy((float)((mouseX - timelineQuad.TopLeft.X) / 10 * Clock.ElapsedFrameTime)); } - private class SelectableAreaBackground : CompositeDrawable + private partial class SelectableAreaBackground : CompositeDrawable { [Resolved] private OsuColour colours { get; set; } @@ -246,7 +246,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline } } - protected class TimelineSelectionBlueprintContainer : Container> + protected partial class TimelineSelectionBlueprintContainer : Container> { protected override Container> Content { get; } diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineButton.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineButton.cs index 0832dc02a9..c94de0fe67 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineButton.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineButton.cs @@ -10,7 +10,7 @@ using osu.Game.Screens.Edit.Timing; namespace osu.Game.Screens.Edit.Compose.Components.Timeline { - public class TimelineButton : IconButton + public partial class TimelineButton : IconButton { [BackgroundDependencyLoader] private void load(OverlayColourProvider colourProvider) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointDisplay.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointDisplay.cs index cfc71256e8..29983c9cbf 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointDisplay.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointDisplay.cs @@ -4,6 +4,7 @@ #nullable disable using System.Collections.Specialized; +using System.Diagnostics; using System.Linq; using osu.Framework.Bindables; using osu.Game.Beatmaps.ControlPoints; @@ -14,7 +15,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline /// /// The part of the timeline that displays the control points. /// - public class TimelineControlPointDisplay : TimelinePart + public partial class TimelineControlPointDisplay : TimelinePart { private readonly IBindableList controlPointGroups = new BindableList(); @@ -33,11 +34,15 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline break; case NotifyCollectionChangedAction.Add: + Debug.Assert(args.NewItems != null); + foreach (var group in args.NewItems.OfType()) Add(new TimelineControlPointGroup(group)); break; case NotifyCollectionChangedAction.Remove: + Debug.Assert(args.OldItems != null); + foreach (var group in args.OldItems.OfType()) { var matching = Children.SingleOrDefault(gv => ReferenceEquals(gv.Group, group)); diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointGroup.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointGroup.cs index 10355045be..257cc9e635 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointGroup.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointGroup.cs @@ -10,7 +10,7 @@ using osu.Game.Beatmaps.ControlPoints; namespace osu.Game.Screens.Edit.Compose.Components.Timeline { - public class TimelineControlPointGroup : CompositeDrawable + public partial class TimelineControlPointGroup : CompositeDrawable { public readonly ControlPointGroup Group; diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineDragBox.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineDragBox.cs index 65d9293b7e..a1dfd0718b 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineDragBox.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineDragBox.cs @@ -11,7 +11,7 @@ using osu.Framework.Input.Events; namespace osu.Game.Screens.Edit.Compose.Components.Timeline { - public class TimelineDragBox : DragBox + public partial class TimelineDragBox : DragBox { public double MinTime { get; private set; } diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs index 20ef128ee9..4e5087c004 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs @@ -18,6 +18,7 @@ using osu.Framework.Utils; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; +using osu.Game.Overlays; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; @@ -27,7 +28,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.Edit.Compose.Components.Timeline { - public class TimelineHitObjectBlueprint : SelectionBlueprint + public partial class TimelineHitObjectBlueprint : SelectionBlueprint { private const float circle_size = 38; @@ -54,6 +55,9 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline [Resolved] private ISkinSource skin { get; set; } = null!; + [Resolved] + private OverlayColourProvider colourProvider { get; set; } = null!; + public TimelineHitObjectBlueprint(HitObject item) : base(item) { @@ -165,7 +169,8 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline break; default: - return; + colour = colourProvider.Highlight1; + break; } if (IsSelected) @@ -262,7 +267,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline public override Vector2 ScreenSpaceSelectionPoint => ScreenSpaceDrawQuad.TopLeft; - private class Tick : Circle + private partial class Tick : Circle { public Tick() { @@ -273,7 +278,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline } } - public class DragArea : Circle + public partial class DragArea : Circle { private readonly HitObject? hitObject; @@ -286,7 +291,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline [Resolved] private Timeline timeline { get; set; } = null!; - [Resolved(CanBeNull = true)] + [Resolved] private IEditorChangeHandler? changeHandler { get; set; } private ScheduledDelegate? dragOperation; @@ -419,9 +424,9 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline break; case IHasDuration endTimeHitObject: - double snappedTime = Math.Max(hitObject.StartTime, beatSnapProvider.SnapTime(time)); + double snappedTime = Math.Max(hitObject.StartTime + beatSnapProvider.GetBeatLengthAtTime(hitObject.StartTime), beatSnapProvider.SnapTime(time)); - if (endTimeHitObject.EndTime == snappedTime || Precision.AlmostEquals(snappedTime, hitObject.StartTime, beatmap.GetBeatLengthAtTime(snappedTime))) + if (endTimeHitObject.EndTime == snappedTime) return; endTimeHitObject.Duration = snappedTime - hitObject.StartTime; @@ -444,7 +449,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline } } - public class Border : ExtendableCircle + public partial class Border : ExtendableCircle { [BackgroundDependencyLoader] private void load(OsuColour colours) @@ -460,7 +465,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline /// /// A circle with externalised end caps so it can take up the full width of a relative width area. /// - public class ExtendableCircle : CompositeDrawable + public partial class ExtendableCircle : CompositeDrawable { protected readonly Circle Content; diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineSelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineSelectionHandler.cs index d91b95888b..0a5a0e99ac 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineSelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineSelectionHandler.cs @@ -16,7 +16,7 @@ using osuTK.Input; namespace osu.Game.Screens.Edit.Compose.Components.Timeline { - internal class TimelineSelectionHandler : EditorSelectionHandler + internal partial class TimelineSelectionHandler : EditorSelectionHandler { // for now we always allow movement. snapping is provided by the Timeline's "distance" snap implementation public override bool HandleMovement(MoveSelectionEvent moveEvent) => true; diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs index c1c9b2493b..6a0688e19c 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs @@ -18,7 +18,7 @@ using osuTK; namespace osu.Game.Screens.Edit.Compose.Components.Timeline { - public class TimelineTickDisplay : TimelinePart + public partial class TimelineTickDisplay : TimelinePart { [Resolved] private EditorBeatmap beatmap { get; set; } diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimingPointPiece.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimingPointPiece.cs index cf62707839..4191864e5c 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimingPointPiece.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimingPointPiece.cs @@ -9,7 +9,7 @@ using osu.Game.Beatmaps.ControlPoints; namespace osu.Game.Screens.Edit.Compose.Components.Timeline { - public class TimingPointPiece : TopPointPiece + public partial class TimingPointPiece : TopPointPiece { private readonly BindableNumber beatLength; diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TopPointPiece.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TopPointPiece.cs index 28ae77c931..69fb001a66 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TopPointPiece.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TopPointPiece.cs @@ -13,7 +13,7 @@ using osu.Game.Graphics.Sprites; namespace osu.Game.Screens.Edit.Compose.Components.Timeline { - public class TopPointPiece : CompositeDrawable + public partial class TopPointPiece : CompositeDrawable { private readonly ControlPoint point; diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs index 839b2b5bad..951f4129d4 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs @@ -17,7 +17,7 @@ using osuTK; namespace osu.Game.Screens.Edit.Compose.Components.Timeline { - public class ZoomableScrollContainer : OsuScrollContainer + public partial class ZoomableScrollContainer : OsuScrollContainer { /// /// The time to zoom into/out of a point. @@ -99,9 +99,11 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline minZoom = minimum; maxZoom = maximum; - CurrentZoom = zoomTarget = initial; - isZoomSetUp = true; + CurrentZoom = zoomTarget = initial; + zoomedContentWidthCache.Invalidate(); + + isZoomSetUp = true; zoomedContent.Show(); } diff --git a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs index d3c330c6d7..dc026f7eac 100644 --- a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs +++ b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs @@ -20,7 +20,7 @@ using osu.Game.Screens.Edit.Compose.Components.Timeline; namespace osu.Game.Screens.Edit.Compose { - public class ComposeScreen : EditorScreenWithTimeline, IGameplaySettings + public partial class ComposeScreen : EditorScreenWithTimeline, IGameplaySettings { [Resolved] private GameHost host { get; set; } @@ -152,7 +152,7 @@ namespace osu.Game.Screens.Edit.Compose if (composer == null) return string.Empty; - double displayTime = EditorBeatmap.SelectedHitObjects.OrderBy(h => h.StartTime).FirstOrDefault()?.StartTime ?? clock.CurrentTime; + double displayTime = EditorBeatmap.SelectedHitObjects.MinBy(h => h.StartTime)?.StartTime ?? clock.CurrentTime; string selectionAsString = composer.ConvertSelectionToString(); return !string.IsNullOrEmpty(selectionAsString) diff --git a/osu.Game/Screens/Edit/CreateNewDifficultyDialog.cs b/osu.Game/Screens/Edit/CreateNewDifficultyDialog.cs index 36c4e397a7..811da5236e 100644 --- a/osu.Game/Screens/Edit/CreateNewDifficultyDialog.cs +++ b/osu.Game/Screens/Edit/CreateNewDifficultyDialog.cs @@ -1,14 +1,13 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Graphics.Sprites; using osu.Game.Overlays.Dialog; +using osu.Game.Localisation; namespace osu.Game.Screens.Edit { - public class CreateNewDifficultyDialog : PopupDialog + public partial class CreateNewDifficultyDialog : PopupDialog { /// /// Delegate used to create new difficulties. @@ -20,7 +19,7 @@ namespace osu.Game.Screens.Edit public CreateNewDifficultyDialog(CreateNewDifficulty createNewDifficulty) { - HeaderText = "Would you like to create a blank difficulty?"; + HeaderText = EditorDialogsStrings.NewDifficultyDialogHeader; Icon = FontAwesome.Regular.Clone; @@ -28,17 +27,17 @@ namespace osu.Game.Screens.Edit { new PopupDialogOkButton { - Text = "Yeah, let's start from scratch!", + Text = EditorDialogsStrings.CreateNew, Action = () => createNewDifficulty.Invoke(false) }, new PopupDialogCancelButton { - Text = "No, create an exact copy of this difficulty", + Text = EditorDialogsStrings.CreateCopy, Action = () => createNewDifficulty.Invoke(true) }, new PopupDialogCancelButton { - Text = "I changed my mind, I want to keep editing this difficulty", + Text = EditorDialogsStrings.KeepEditing, Action = () => { } } }; diff --git a/osu.Game/Screens/Edit/DeleteDifficultyConfirmationDialog.cs b/osu.Game/Screens/Edit/DeleteDifficultyConfirmationDialog.cs index 594042b426..68a0ef4250 100644 --- a/osu.Game/Screens/Edit/DeleteDifficultyConfirmationDialog.cs +++ b/osu.Game/Screens/Edit/DeleteDifficultyConfirmationDialog.cs @@ -7,7 +7,7 @@ using osu.Game.Overlays.Dialog; namespace osu.Game.Screens.Edit { - public class DeleteDifficultyConfirmationDialog : DeleteConfirmationDialog + public partial class DeleteDifficultyConfirmationDialog : DeleteConfirmationDialog { public DeleteDifficultyConfirmationDialog(BeatmapInfo beatmapInfo, Action deleteAction) { diff --git a/osu.Game/Screens/Edit/Design/DesignScreen.cs b/osu.Game/Screens/Edit/Design/DesignScreen.cs index 546a07f17d..c36afcdb6d 100644 --- a/osu.Game/Screens/Edit/Design/DesignScreen.cs +++ b/osu.Game/Screens/Edit/Design/DesignScreen.cs @@ -1,11 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - namespace osu.Game.Screens.Edit.Design { - public class DesignScreen : EditorScreen + public partial class DesignScreen : EditorScreen { public DesignScreen() : base(EditorScreenMode.Design) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index e40910e5c6..74ea933255 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -40,7 +40,6 @@ using osu.Game.Overlays.Notifications; using osu.Game.Overlays.OSD; using osu.Game.Rulesets; using osu.Game.Rulesets.Edit; -using osu.Game.Rulesets.Objects; using osu.Game.Screens.Edit.Components.Menus; using osu.Game.Screens.Edit.Compose; using osu.Game.Screens.Edit.Compose.Components.Timeline; @@ -52,13 +51,13 @@ using osu.Game.Screens.Edit.Verify; using osu.Game.Screens.Play; using osu.Game.Users; using osuTK.Input; -using CommonStrings = osu.Game.Resources.Localisation.Web.CommonStrings; +using WebCommonStrings = osu.Game.Resources.Localisation.Web.CommonStrings; namespace osu.Game.Screens.Edit { [Cached(typeof(IBeatSnapProvider))] [Cached] - public class Editor : ScreenWithBeatmapBackground, IKeyBindingHandler, IKeyBindingHandler, IBeatSnapProvider, ISamplePlaybackDisabler, IBeatSyncProvider + public partial class Editor : ScreenWithBeatmapBackground, IKeyBindingHandler, IKeyBindingHandler, IBeatSnapProvider, ISamplePlaybackDisabler, IBeatSyncProvider { public override float BackgroundParallaxAmount => 0.1f; @@ -295,34 +294,41 @@ namespace osu.Game.Screens.Edit RelativeSizeAxes = Axes.Both, Items = new[] { - new MenuItem("File") + new MenuItem(CommonStrings.MenuBarFile) { Items = createFileMenuItems() }, - new MenuItem(CommonStrings.ButtonsEdit) + new MenuItem(CommonStrings.MenuBarEdit) { Items = new[] { - undoMenuItem = new EditorMenuItem("Undo", MenuItemType.Standard, Undo), - redoMenuItem = new EditorMenuItem("Redo", MenuItemType.Standard, Redo), + undoMenuItem = new EditorMenuItem(CommonStrings.Undo, MenuItemType.Standard, Undo), + redoMenuItem = new EditorMenuItem(CommonStrings.Redo, MenuItemType.Standard, Redo), new EditorMenuItemSpacer(), - cutMenuItem = new EditorMenuItem("Cut", MenuItemType.Standard, Cut), - copyMenuItem = new EditorMenuItem("Copy", MenuItemType.Standard, Copy), - pasteMenuItem = new EditorMenuItem("Paste", MenuItemType.Standard, Paste), - cloneMenuItem = new EditorMenuItem("Clone", MenuItemType.Standard, Clone), + cutMenuItem = new EditorMenuItem(CommonStrings.Cut, MenuItemType.Standard, Cut), + copyMenuItem = new EditorMenuItem(CommonStrings.Copy, MenuItemType.Standard, Copy), + pasteMenuItem = new EditorMenuItem(CommonStrings.Paste, MenuItemType.Standard, Paste), + cloneMenuItem = new EditorMenuItem(CommonStrings.Clone, MenuItemType.Standard, Clone), } }, - new MenuItem("View") + new MenuItem(CommonStrings.MenuBarView) { Items = new MenuItem[] { new WaveformOpacityMenuItem(config.GetBindable(OsuSetting.EditorWaveformOpacity)), new BackgroundDimMenuItem(editorBackgroundDim), - new ToggleMenuItem("Show hit markers") + new ToggleMenuItem(EditorStrings.ShowHitMarkers) { State = { BindTarget = editorHitMarkers }, } } + }, + new MenuItem(EditorStrings.Timing) + { + Items = new MenuItem[] + { + new EditorMenuItem(EditorStrings.SetPreviewPointToCurrent, MenuItemType.Standard, SetPreviewPointToCurrentTime) + } } } }, @@ -338,7 +344,6 @@ namespace osu.Game.Screens.Edit bottomBar = new BottomBar(), } }); - changeHandler?.CanUndo.BindValueChanged(v => undoMenuItem.Action.Disabled = !v.NewValue, true); changeHandler?.CanRedo.BindValueChanged(v => redoMenuItem.Action.Disabled = !v.NewValue, true); @@ -538,12 +543,14 @@ namespace osu.Game.Screens.Edit // Seek to last object time, or track end if already there. // Note that in osu-stable subsequent presses when at track end won't return to last object. // This has intentionally been changed to make it more useful. - double? lastObjectTime = editorBeatmap.HitObjects.LastOrDefault()?.GetEndTime(); - - if (lastObjectTime == null || clock.CurrentTime == lastObjectTime) + if (!editorBeatmap.HitObjects.Any()) + { clock.Seek(clock.TrackLength); - else - clock.Seek(lastObjectTime.Value); + return true; + } + + double lastObjectTime = editorBeatmap.GetLastObjectTime(); + clock.Seek(clock.CurrentTime == lastObjectTime ? clock.TrackLength : lastObjectTime); return true; } @@ -708,7 +715,7 @@ namespace osu.Game.Screens.Edit if (!(refetchedBeatmap is DummyWorkingBeatmap)) { - Logger.Log("Editor providing re-fetched beatmap post edit session"); + Logger.Log(@"Editor providing re-fetched beatmap post edit session"); Beatmap.Value = refetchedBeatmap; } } @@ -800,6 +807,11 @@ namespace osu.Game.Screens.Edit protected void Redo() => changeHandler?.RestoreState(1); + protected void SetPreviewPointToCurrentTime() + { + editorBeatmap.PreviewTime.Value = (int)clock.CurrentTime; + } + private void resetTrack(bool seekToStart = false) { Beatmap.Value.Track.Stop(); @@ -939,15 +951,15 @@ namespace osu.Game.Screens.Edit private List createFileMenuItems() => new List { - new EditorMenuItem("Save", MenuItemType.Standard, () => Save()), - new EditorMenuItem("Export package", MenuItemType.Standard, exportBeatmap) { Action = { Disabled = !RuntimeInfo.IsDesktop } }, + new EditorMenuItem(WebCommonStrings.ButtonsSave, MenuItemType.Standard, () => Save()), + new EditorMenuItem(EditorStrings.ExportPackage, MenuItemType.Standard, exportBeatmap) { Action = { Disabled = !RuntimeInfo.IsDesktop } }, new EditorMenuItemSpacer(), createDifficultyCreationMenu(), createDifficultySwitchMenu(), new EditorMenuItemSpacer(), - new EditorMenuItem("Delete difficulty", MenuItemType.Standard, deleteDifficulty) { Action = { Disabled = Beatmap.Value.BeatmapSetInfo.Beatmaps.Count < 2 } }, + new EditorMenuItem(EditorStrings.DeleteDifficulty, MenuItemType.Standard, deleteDifficulty) { Action = { Disabled = Beatmap.Value.BeatmapSetInfo.Beatmaps.Count < 2 } }, new EditorMenuItemSpacer(), - new EditorMenuItem("Exit", MenuItemType.Standard, this.Exit) + new EditorMenuItem(CommonStrings.Exit, MenuItemType.Standard, this.Exit) }; private void exportBeatmap() @@ -996,7 +1008,7 @@ namespace osu.Game.Screens.Edit foreach (var ruleset in rulesets.AvailableRulesets) rulesetItems.Add(new EditorMenuItem(ruleset.Name, MenuItemType.Standard, () => CreateNewDifficulty(ruleset))); - return new EditorMenuItem("Create new difficulty") { Items = rulesetItems }; + return new EditorMenuItem(EditorStrings.CreateNewDifficulty) { Items = rulesetItems }; } protected void CreateNewDifficulty(RulesetInfo rulesetInfo) @@ -1032,7 +1044,7 @@ namespace osu.Game.Screens.Edit } } - return new EditorMenuItem("Change difficulty") { Items = difficultyItems }; + return new EditorMenuItem(EditorStrings.ChangeDifficulty) { Items = difficultyItems }; } protected void SwitchToDifficulty(BeatmapInfo nextBeatmap) => loader?.ScheduleSwitchToExistingDifficulty(nextBeatmap, GetState(nextBeatmap.Ruleset)); @@ -1053,7 +1065,7 @@ namespace osu.Game.Screens.Edit IClock IBeatSyncProvider.Clock => clock; ChannelAmplitudes IHasAmplitudes.CurrentAmplitudes => Beatmap.Value.TrackLoaded ? Beatmap.Value.Track.CurrentAmplitudes : ChannelAmplitudes.Empty; - private class BeatmapEditorToast : Toast + private partial class BeatmapEditorToast : Toast { public BeatmapEditorToast(LocalisableString value, string beatmapDisplayName) : base(InputSettingsStrings.EditorSection, value, beatmapDisplayName) diff --git a/osu.Game/Screens/Edit/EditorBeatmap.cs b/osu.Game/Screens/Edit/EditorBeatmap.cs index 839535b99f..dc1fda13f4 100644 --- a/osu.Game/Screens/Edit/EditorBeatmap.cs +++ b/osu.Game/Screens/Edit/EditorBeatmap.cs @@ -20,7 +20,7 @@ using osu.Game.Skinning; namespace osu.Game.Screens.Edit { - public class EditorBeatmap : TransactionalCommitComponent, IBeatmap, IBeatSnapProvider + public partial class EditorBeatmap : TransactionalCommitComponent, IBeatmap, IBeatSnapProvider { /// /// Will become true when a new update is queued, and false when all updates have been applied. @@ -86,6 +86,8 @@ namespace osu.Game.Screens.Edit [Resolved] private EditorClock editorClock { get; set; } + public BindableInt PreviewTime { get; } + private readonly IBeatmapProcessor beatmapProcessor; private readonly Dictionary> startTimeBindables = new Dictionary>(); @@ -107,6 +109,14 @@ namespace osu.Game.Screens.Edit foreach (var obj in HitObjects) trackStartTime(obj); + + PreviewTime = new BindableInt(BeatmapInfo.Metadata.PreviewTime); + PreviewTime.BindValueChanged(s => + { + BeginChange(); + BeatmapInfo.Metadata.PreviewTime = s.NewValue; + EndChange(); + }); } /// @@ -304,7 +314,7 @@ namespace osu.Game.Screens.Edit /// The index of the to remove. public void RemoveAt(int index) { - var hitObject = (HitObject)mutableHitObjects[index]; + HitObject hitObject = (HitObject)mutableHitObjects[index]!; mutableHitObjects.RemoveAt(index); diff --git a/osu.Game/Screens/Edit/EditorChangeHandler.cs b/osu.Game/Screens/Edit/EditorChangeHandler.cs index 1a93f3f101..964b86cad3 100644 --- a/osu.Game/Screens/Edit/EditorChangeHandler.cs +++ b/osu.Game/Screens/Edit/EditorChangeHandler.cs @@ -18,7 +18,7 @@ namespace osu.Game.Screens.Edit /// /// Tracks changes to the . /// - public class EditorChangeHandler : TransactionalCommitComponent, IEditorChangeHandler + public partial class EditorChangeHandler : TransactionalCommitComponent, IEditorChangeHandler { public readonly Bindable CanUndo = new Bindable(); public readonly Bindable CanRedo = new Bindable(); diff --git a/osu.Game/Screens/Edit/EditorClock.cs b/osu.Game/Screens/Edit/EditorClock.cs index f83874e4a0..e5e88a04d9 100644 --- a/osu.Game/Screens/Edit/EditorClock.cs +++ b/osu.Game/Screens/Edit/EditorClock.cs @@ -21,7 +21,7 @@ namespace osu.Game.Screens.Edit /// /// A decoupled clock which adds editor-specific functionality, such as snapping to a user-defined beat divisor. /// - public class EditorClock : CompositeComponent, IFrameBasedClock, IAdjustableClock, ISourceChangeableClock + public partial class EditorClock : CompositeComponent, IFrameBasedClock, IAdjustableClock, ISourceChangeableClock { public IBindable Track => track; diff --git a/osu.Game/Screens/Edit/EditorLoader.cs b/osu.Game/Screens/Edit/EditorLoader.cs index d6af990b52..f665b7c511 100644 --- a/osu.Game/Screens/Edit/EditorLoader.cs +++ b/osu.Game/Screens/Edit/EditorLoader.cs @@ -25,7 +25,7 @@ namespace osu.Game.Screens.Edit /// Transition screen for the editor. /// Used to avoid backing out to main menu/song select when switching difficulties from within the editor. /// - public class EditorLoader : ScreenWithBeatmapBackground + public partial class EditorLoader : ScreenWithBeatmapBackground { /// /// The stored state from the last editor opened. diff --git a/osu.Game/Screens/Edit/EditorRoundedScreenSettings.cs b/osu.Game/Screens/Edit/EditorRoundedScreenSettings.cs index 013971960b..1c083b4fab 100644 --- a/osu.Game/Screens/Edit/EditorRoundedScreenSettings.cs +++ b/osu.Game/Screens/Edit/EditorRoundedScreenSettings.cs @@ -14,7 +14,7 @@ using osuTK; namespace osu.Game.Screens.Edit { - public abstract class EditorRoundedScreenSettings : CompositeDrawable + public abstract partial class EditorRoundedScreenSettings : CompositeDrawable { [BackgroundDependencyLoader] private void load(OverlayColourProvider colours) diff --git a/osu.Game/Screens/Edit/EditorRoundedScreenSettingsSection.cs b/osu.Game/Screens/Edit/EditorRoundedScreenSettingsSection.cs index be1545cac8..751b6f61d1 100644 --- a/osu.Game/Screens/Edit/EditorRoundedScreenSettingsSection.cs +++ b/osu.Game/Screens/Edit/EditorRoundedScreenSettingsSection.cs @@ -12,7 +12,7 @@ using osuTK; namespace osu.Game.Screens.Edit { - public abstract class EditorRoundedScreenSettingsSection : CompositeDrawable + public abstract partial class EditorRoundedScreenSettingsSection : CompositeDrawable { private const int header_height = 50; diff --git a/osu.Game/Screens/Edit/EditorScreen.cs b/osu.Game/Screens/Edit/EditorScreen.cs index 92709484ff..069a5490bb 100644 --- a/osu.Game/Screens/Edit/EditorScreen.cs +++ b/osu.Game/Screens/Edit/EditorScreen.cs @@ -14,7 +14,7 @@ namespace osu.Game.Screens.Edit /// /// TODO: eventually make this inherit Screen and add a local screen stack inside the Editor. /// - public abstract class EditorScreen : VisibilityContainer + public abstract partial class EditorScreen : VisibilityContainer { [Resolved] protected EditorBeatmap EditorBeatmap { get; private set; } diff --git a/osu.Game/Screens/Edit/EditorScreenMode.cs b/osu.Game/Screens/Edit/EditorScreenMode.cs index 81fcf23cdf..f787fee1e0 100644 --- a/osu.Game/Screens/Edit/EditorScreenMode.cs +++ b/osu.Game/Screens/Edit/EditorScreenMode.cs @@ -1,27 +1,26 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - -using System.ComponentModel; +using osu.Framework.Localisation; +using osu.Game.Localisation; namespace osu.Game.Screens.Edit { public enum EditorScreenMode { - [Description("setup")] + [LocalisableDescription(typeof(EditorStrings), nameof(EditorStrings.SetupScreen))] SongSetup, - [Description("compose")] + [LocalisableDescription(typeof(EditorStrings), nameof(EditorStrings.ComposeScreen))] Compose, - [Description("design")] + [LocalisableDescription(typeof(EditorStrings), nameof(EditorStrings.DesignScreen))] Design, - [Description("timing")] + [LocalisableDescription(typeof(EditorStrings), nameof(EditorStrings.TimingScreen))] Timing, - [Description("verify")] + [LocalisableDescription(typeof(EditorStrings), nameof(EditorStrings.VerifyScreen))] Verify, } } diff --git a/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs b/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs index b3aafb9730..84cfac8f65 100644 --- a/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs +++ b/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs @@ -15,7 +15,7 @@ using osu.Game.Screens.Edit.Compose.Components.Timeline; namespace osu.Game.Screens.Edit { - public abstract class EditorScreenWithTimeline : EditorScreen + public abstract partial class EditorScreenWithTimeline : EditorScreen { private const float padding = 10; diff --git a/osu.Game/Screens/Edit/EditorSkinProvidingContainer.cs b/osu.Game/Screens/Edit/EditorSkinProvidingContainer.cs index d4387a0263..814b5dc18e 100644 --- a/osu.Game/Screens/Edit/EditorSkinProvidingContainer.cs +++ b/osu.Game/Screens/Edit/EditorSkinProvidingContainer.cs @@ -9,7 +9,7 @@ namespace osu.Game.Screens.Edit /// A that fires when users have made a change to the beatmap skin /// of the map being edited. /// - public class EditorSkinProvidingContainer : RulesetSkinProvidingContainer + public partial class EditorSkinProvidingContainer : RulesetSkinProvidingContainer { private readonly EditorBeatmapSkin? beatmapSkin; diff --git a/osu.Game/Screens/Edit/EditorTable.cs b/osu.Game/Screens/Edit/EditorTable.cs index a290cce708..b79d71b42b 100644 --- a/osu.Game/Screens/Edit/EditorTable.cs +++ b/osu.Game/Screens/Edit/EditorTable.cs @@ -1,8 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - +using System; using osu.Framework.Allocation; using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; @@ -18,8 +17,10 @@ using osuTK.Graphics; namespace osu.Game.Screens.Edit { - public abstract class EditorTable : TableContainer + public abstract partial class EditorTable : TableContainer { + public event Action? OnRowSelected; + private const float horizontal_inset = 20; protected const float ROW_HEIGHT = 25; @@ -45,9 +46,20 @@ namespace osu.Game.Screens.Edit }); } - protected override Drawable CreateHeader(int index, TableColumn column) => new HeaderText(column?.Header ?? default); + protected void SetSelectedRow(object? item) + { + foreach (var b in BackgroundFlow) + { + b.Selected = ReferenceEquals(b.Item, item); - private class HeaderText : OsuSpriteText + if (b.Selected) + OnRowSelected?.Invoke(b); + } + } + + protected override Drawable CreateHeader(int index, TableColumn? column) => new HeaderText(column?.Header ?? default); + + private partial class HeaderText : OsuSpriteText { public HeaderText(LocalisableString text) { @@ -56,7 +68,7 @@ namespace osu.Game.Screens.Edit } } - public class RowBackground : OsuClickableContainer + public partial class RowBackground : OsuClickableContainer { public readonly object Item; @@ -84,11 +96,6 @@ namespace osu.Game.Screens.Edit Alpha = 0, }, }; - - // todo delete - Action = () => - { - }; } private Color4 colourHover; diff --git a/osu.Game/Screens/Edit/GameplayTest/EditorPlayer.cs b/osu.Game/Screens/Edit/GameplayTest/EditorPlayer.cs index ad09618279..e7db1c105b 100644 --- a/osu.Game/Screens/Edit/GameplayTest/EditorPlayer.cs +++ b/osu.Game/Screens/Edit/GameplayTest/EditorPlayer.cs @@ -10,7 +10,7 @@ using osu.Game.Screens.Play; namespace osu.Game.Screens.Edit.GameplayTest { - public class EditorPlayer : Player + public partial class EditorPlayer : Player { private readonly Editor editor; private readonly EditorState editorState; diff --git a/osu.Game/Screens/Edit/GameplayTest/EditorPlayerLoader.cs b/osu.Game/Screens/Edit/GameplayTest/EditorPlayerLoader.cs index d3260f1e7d..a74d97cdc7 100644 --- a/osu.Game/Screens/Edit/GameplayTest/EditorPlayerLoader.cs +++ b/osu.Game/Screens/Edit/GameplayTest/EditorPlayerLoader.cs @@ -11,7 +11,7 @@ using osu.Game.Screens.Play; namespace osu.Game.Screens.Edit.GameplayTest { - public class EditorPlayerLoader : PlayerLoader + public partial class EditorPlayerLoader : PlayerLoader { [Resolved] private OsuLogo osuLogo { get; set; } diff --git a/osu.Game/Screens/Edit/GameplayTest/SaveBeforeGameplayTestDialog.cs b/osu.Game/Screens/Edit/GameplayTest/SaveBeforeGameplayTestDialog.cs index 37e1c99d98..5a5572b508 100644 --- a/osu.Game/Screens/Edit/GameplayTest/SaveBeforeGameplayTestDialog.cs +++ b/osu.Game/Screens/Edit/GameplayTest/SaveBeforeGameplayTestDialog.cs @@ -9,7 +9,7 @@ using osu.Game.Overlays.Dialog; namespace osu.Game.Screens.Edit.GameplayTest { - public class SaveBeforeGameplayTestDialog : PopupDialog + public partial class SaveBeforeGameplayTestDialog : PopupDialog { public SaveBeforeGameplayTestDialog(Action saveAndPreview) { diff --git a/osu.Game/Screens/Edit/PromptForSaveDialog.cs b/osu.Game/Screens/Edit/PromptForSaveDialog.cs index 59a697d91c..7d78465e6c 100644 --- a/osu.Game/Screens/Edit/PromptForSaveDialog.cs +++ b/osu.Game/Screens/Edit/PromptForSaveDialog.cs @@ -1,19 +1,18 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using osu.Framework.Graphics.Sprites; using osu.Game.Overlays.Dialog; +using osu.Game.Localisation; namespace osu.Game.Screens.Edit { - public class PromptForSaveDialog : PopupDialog + public partial class PromptForSaveDialog : PopupDialog { public PromptForSaveDialog(Action exit, Action saveAndExit, Action cancel) { - HeaderText = "Did you want to save your changes?"; + HeaderText = EditorDialogsStrings.SaveDialogHeader; Icon = FontAwesome.Regular.Save; @@ -21,17 +20,17 @@ namespace osu.Game.Screens.Edit { new PopupDialogOkButton { - Text = @"Save my masterpiece!", + Text = EditorDialogsStrings.Save, Action = saveAndExit }, new PopupDialogDangerousButton { - Text = @"Forget all changes", + Text = EditorDialogsStrings.ForgetAllChanges, Action = exit }, new PopupDialogCancelButton { - Text = @"Oops, continue editing", + Text = EditorDialogsStrings.ContinueEditing, Action = cancel }, }; diff --git a/osu.Game/Screens/Edit/Setup/ColoursSection.cs b/osu.Game/Screens/Edit/Setup/ColoursSection.cs index e3fcdedd1b..8cd5c0f779 100644 --- a/osu.Game/Screens/Edit/Setup/ColoursSection.cs +++ b/osu.Game/Screens/Edit/Setup/ColoursSection.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; @@ -11,11 +9,11 @@ using osu.Game.Localisation; namespace osu.Game.Screens.Edit.Setup { - internal class ColoursSection : SetupSection + internal partial class ColoursSection : SetupSection { public override LocalisableString Title => EditorSetupStrings.ColoursHeader; - private LabelledColourPalette comboColours; + private LabelledColourPalette comboColours = null!; [BackgroundDependencyLoader] private void load() diff --git a/osu.Game/Screens/Edit/Setup/DesignSection.cs b/osu.Game/Screens/Edit/Setup/DesignSection.cs index cc3e9b91ab..b05a073146 100644 --- a/osu.Game/Screens/Edit/Setup/DesignSection.cs +++ b/osu.Game/Screens/Edit/Setup/DesignSection.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Globalization; using System.Linq; @@ -17,18 +15,18 @@ using osu.Game.Localisation; namespace osu.Game.Screens.Edit.Setup { - internal class DesignSection : SetupSection + internal partial class DesignSection : SetupSection { - protected LabelledSwitchButton EnableCountdown; + protected LabelledSwitchButton EnableCountdown = null!; - protected FillFlowContainer CountdownSettings; - protected LabelledEnumDropdown CountdownSpeed; - protected LabelledNumberBox CountdownOffset; + protected FillFlowContainer CountdownSettings = null!; + protected LabelledEnumDropdown CountdownSpeed = null!; + protected LabelledNumberBox CountdownOffset = null!; - private LabelledSwitchButton widescreenSupport; - private LabelledSwitchButton epilepsyWarning; - private LabelledSwitchButton letterboxDuringBreaks; - private LabelledSwitchButton samplesMatchPlaybackRate; + private LabelledSwitchButton widescreenSupport = null!; + private LabelledSwitchButton epilepsyWarning = null!; + private LabelledSwitchButton letterboxDuringBreaks = null!; + private LabelledSwitchButton samplesMatchPlaybackRate = null!; public override LocalisableString Title => EditorSetupStrings.DesignHeader; @@ -55,7 +53,7 @@ namespace osu.Game.Screens.Edit.Setup { Label = EditorSetupStrings.CountdownSpeed, Current = { Value = Beatmap.BeatmapInfo.Countdown != CountdownType.None ? Beatmap.BeatmapInfo.Countdown : CountdownType.Normal }, - Items = Enum.GetValues(typeof(CountdownType)).Cast().Where(type => type != CountdownType.None) + Items = Enum.GetValues().Where(type => type != CountdownType.None) }, CountdownOffset = new LabelledNumberBox { diff --git a/osu.Game/Screens/Edit/Setup/DifficultySection.cs b/osu.Game/Screens/Edit/Setup/DifficultySection.cs index 01e31bd688..7026bde681 100644 --- a/osu.Game/Screens/Edit/Setup/DifficultySection.cs +++ b/osu.Game/Screens/Edit/Setup/DifficultySection.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -15,12 +13,12 @@ using osu.Game.Localisation; namespace osu.Game.Screens.Edit.Setup { - internal class DifficultySection : SetupSection + internal partial class DifficultySection : SetupSection { - private LabelledSliderBar circleSizeSlider; - private LabelledSliderBar healthDrainSlider; - private LabelledSliderBar approachRateSlider; - private LabelledSliderBar overallDifficultySlider; + private LabelledSliderBar circleSizeSlider = null!; + private LabelledSliderBar healthDrainSlider = null!; + private LabelledSliderBar approachRateSlider = null!; + private LabelledSliderBar overallDifficultySlider = null!; public override LocalisableString Title => EditorSetupStrings.DifficultyHeader; diff --git a/osu.Game/Screens/Edit/Setup/LabelledFileChooser.cs b/osu.Game/Screens/Edit/Setup/LabelledFileChooser.cs index efc8b6978e..d14357e875 100644 --- a/osu.Game/Screens/Edit/Setup/LabelledFileChooser.cs +++ b/osu.Game/Screens/Edit/Setup/LabelledFileChooser.cs @@ -26,7 +26,7 @@ namespace osu.Game.Screens.Edit.Setup /// A labelled drawable displaying file chooser on click, with placeholder text support. /// todo: this should probably not use PopoverTextBox just to display placeholder text, but is the best way for now. /// - internal class LabelledFileChooser : LabelledDrawable, IHasCurrentValue, ICanAcceptFiles, IHasPopover + internal partial class LabelledFileChooser : LabelledDrawable, IHasCurrentValue, ICanAcceptFiles, IHasPopover { private readonly string[] handledExtensions; @@ -91,7 +91,7 @@ namespace osu.Game.Screens.Edit.Setup return Task.CompletedTask; } - Task ICanAcceptFiles.Import(params ImportTask[] tasks) => throw new NotImplementedException(); + Task ICanAcceptFiles.Import(ImportTask[] tasks, ImportParameters parameters) => throw new NotImplementedException(); protected override void Dispose(bool isDisposing) { @@ -112,7 +112,7 @@ namespace osu.Game.Screens.Edit.Setup public Popover GetPopover() => new FileChooserPopover(handledExtensions, Current, initialChooserPath); - private class FileChooserPopover : OsuPopover + private partial class FileChooserPopover : OsuPopover { public FileChooserPopover(string[] handledExtensions, Bindable currentFile, string? chooserPath) { diff --git a/osu.Game/Screens/Edit/Setup/LabelledRomanisedTextBox.cs b/osu.Game/Screens/Edit/Setup/LabelledRomanisedTextBox.cs index a9cf5357c8..85c697bf14 100644 --- a/osu.Game/Screens/Edit/Setup/LabelledRomanisedTextBox.cs +++ b/osu.Game/Screens/Edit/Setup/LabelledRomanisedTextBox.cs @@ -1,19 +1,17 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Game.Beatmaps; using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterfaceV2; namespace osu.Game.Screens.Edit.Setup { - internal class LabelledRomanisedTextBox : LabelledTextBox + internal partial class LabelledRomanisedTextBox : LabelledTextBox { protected override OsuTextBox CreateTextBox() => new RomanisedTextBox(); - private class RomanisedTextBox : OsuTextBox + private partial class RomanisedTextBox : OsuTextBox { protected override bool AllowIme => false; diff --git a/osu.Game/Screens/Edit/Setup/LabelledTextBoxWithPopover.cs b/osu.Game/Screens/Edit/Setup/LabelledTextBoxWithPopover.cs index 0eb74df575..79288e2977 100644 --- a/osu.Game/Screens/Edit/Setup/LabelledTextBoxWithPopover.cs +++ b/osu.Game/Screens/Edit/Setup/LabelledTextBoxWithPopover.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using osu.Framework.Extensions; using osu.Framework.Graphics; @@ -14,7 +12,7 @@ using osu.Game.Graphics.UserInterfaceV2; namespace osu.Game.Screens.Edit.Setup { - internal abstract class LabelledTextBoxWithPopover : LabelledTextBox, IHasPopover + internal abstract partial class LabelledTextBoxWithPopover : LabelledTextBox, IHasPopover { public abstract Popover GetPopover(); @@ -28,9 +26,9 @@ namespace osu.Game.Screens.Edit.Setup OnFocused = this.ShowPopover }; - internal class PopoverTextBox : OsuTextBox + internal partial class PopoverTextBox : OsuTextBox { - public Action OnFocused; + public Action? OnFocused; protected override bool OnDragStart(DragStartEvent e) { diff --git a/osu.Game/Screens/Edit/Setup/MetadataSection.cs b/osu.Game/Screens/Edit/Setup/MetadataSection.cs index 1da7a87f83..752f590308 100644 --- a/osu.Game/Screens/Edit/Setup/MetadataSection.cs +++ b/osu.Game/Screens/Edit/Setup/MetadataSection.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics.UserInterface; @@ -14,18 +12,18 @@ using osu.Game.Localisation; namespace osu.Game.Screens.Edit.Setup { - public class MetadataSection : SetupSection + public partial class MetadataSection : SetupSection { - protected LabelledTextBox ArtistTextBox; - protected LabelledTextBox RomanisedArtistTextBox; + protected LabelledTextBox ArtistTextBox = null!; + protected LabelledTextBox RomanisedArtistTextBox = null!; - protected LabelledTextBox TitleTextBox; - protected LabelledTextBox RomanisedTitleTextBox; + protected LabelledTextBox TitleTextBox = null!; + protected LabelledTextBox RomanisedTitleTextBox = null!; - private LabelledTextBox creatorTextBox; - private LabelledTextBox difficultyTextBox; - private LabelledTextBox sourceTextBox; - private LabelledTextBox tagsTextBox; + private LabelledTextBox creatorTextBox = null!; + private LabelledTextBox difficultyTextBox = null!; + private LabelledTextBox sourceTextBox = null!; + private LabelledTextBox tagsTextBox = null!; public override LocalisableString Title => EditorSetupStrings.MetadataHeader; diff --git a/osu.Game/Screens/Edit/Setup/ResourcesSection.cs b/osu.Game/Screens/Edit/Setup/ResourcesSection.cs index cbaa2d8b42..8c84ad90ba 100644 --- a/osu.Game/Screens/Edit/Setup/ResourcesSection.cs +++ b/osu.Game/Screens/Edit/Setup/ResourcesSection.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.IO; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -14,27 +12,30 @@ using osu.Game.Localisation; namespace osu.Game.Screens.Edit.Setup { - internal class ResourcesSection : SetupSection + internal partial class ResourcesSection : SetupSection { - private LabelledFileChooser audioTrackChooser; - private LabelledFileChooser backgroundChooser; + private LabelledFileChooser audioTrackChooser = null!; + private LabelledFileChooser backgroundChooser = null!; public override LocalisableString Title => EditorSetupStrings.ResourcesHeader; [Resolved] - private MusicController music { get; set; } + private MusicController music { get; set; } = null!; [Resolved] - private BeatmapManager beatmaps { get; set; } + private BeatmapManager beatmaps { get; set; } = null!; [Resolved] - private IBindable working { get; set; } + private IBindable working { get; set; } = null!; [Resolved] - private EditorBeatmap editorBeatmap { get; set; } + private EditorBeatmap editorBeatmap { get; set; } = null!; [Resolved] - private SetupScreenHeader header { get; set; } + private Editor? editor { get; set; } + + [Resolved] + private SetupScreenHeader header { get; set; } = null!; [BackgroundDependencyLoader] private void load() @@ -93,6 +94,8 @@ namespace osu.Game.Screens.Edit.Setup working.Value.Metadata.BackgroundFile = destination.Name; header.Background.UpdateBackground(); + editor?.ApplyToBackground(bg => bg.RefreshBackground()); + return true; } @@ -125,17 +128,17 @@ namespace osu.Game.Screens.Edit.Setup return true; } - private void backgroundChanged(ValueChangedEvent file) + private void backgroundChanged(ValueChangedEvent file) { - if (!ChangeBackgroundImage(file.NewValue)) + if (file.NewValue == null || !ChangeBackgroundImage(file.NewValue)) backgroundChooser.Current.Value = file.OldValue; updatePlaceholderText(); } - private void audioTrackChanged(ValueChangedEvent file) + private void audioTrackChanged(ValueChangedEvent file) { - if (!ChangeAudioTrack(file.NewValue)) + if (file.NewValue == null || !ChangeAudioTrack(file.NewValue)) audioTrackChooser.Current.Value = file.OldValue; updatePlaceholderText(); diff --git a/osu.Game/Screens/Edit/Setup/RulesetSetupSection.cs b/osu.Game/Screens/Edit/Setup/RulesetSetupSection.cs index d6664e860b..af59868f29 100644 --- a/osu.Game/Screens/Edit/Setup/RulesetSetupSection.cs +++ b/osu.Game/Screens/Edit/Setup/RulesetSetupSection.cs @@ -1,15 +1,13 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Localisation; using osu.Game.Rulesets; using osu.Game.Localisation; namespace osu.Game.Screens.Edit.Setup { - public abstract class RulesetSetupSection : SetupSection + public abstract partial class RulesetSetupSection : SetupSection { public sealed override LocalisableString Title => EditorSetupStrings.RulesetHeader(rulesetInfo.Name); diff --git a/osu.Game/Screens/Edit/Setup/SetupScreen.cs b/osu.Game/Screens/Edit/Setup/SetupScreen.cs index 036202a503..ab4299a2f0 100644 --- a/osu.Game/Screens/Edit/Setup/SetupScreen.cs +++ b/osu.Game/Screens/Edit/Setup/SetupScreen.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -12,7 +10,7 @@ using osu.Game.Overlays; namespace osu.Game.Screens.Edit.Setup { - public class SetupScreen : EditorScreen + public partial class SetupScreen : EditorScreen { [Cached] private SectionsContainer sections { get; } = new SetupScreenSectionsContainer(); @@ -55,7 +53,7 @@ namespace osu.Game.Screens.Edit.Setup })); } - private class SetupScreenSectionsContainer : SectionsContainer + private partial class SetupScreenSectionsContainer : SectionsContainer { protected override UserTrackingScrollContainer CreateScrollContainer() { diff --git a/osu.Game/Screens/Edit/Setup/SetupScreenHeader.cs b/osu.Game/Screens/Edit/Setup/SetupScreenHeader.cs index 9486b3728b..1d66830adf 100644 --- a/osu.Game/Screens/Edit/Setup/SetupScreenHeader.cs +++ b/osu.Game/Screens/Edit/Setup/SetupScreenHeader.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; @@ -16,14 +14,14 @@ using osu.Game.Localisation; namespace osu.Game.Screens.Edit.Setup { - internal class SetupScreenHeader : OverlayHeader + internal partial class SetupScreenHeader : OverlayHeader { - public SetupScreenHeaderBackground Background { get; private set; } + public SetupScreenHeaderBackground Background { get; private set; } = null!; [Resolved] - private SectionsContainer sections { get; set; } + private SectionsContainer sections { get; set; } = null!; - private SetupScreenTabControl tabControl; + private SetupScreenTabControl tabControl = null!; protected override OverlayTitle CreateTitle() => new SetupScreenTitle(); @@ -75,7 +73,7 @@ namespace osu.Game.Screens.Edit.Setup }); } - private class SetupScreenTitle : OverlayTitle + private partial class SetupScreenTitle : OverlayTitle { public SetupScreenTitle() { @@ -85,7 +83,7 @@ namespace osu.Game.Screens.Edit.Setup } } - internal class SetupScreenTabControl : OverlayTabControl + internal partial class SetupScreenTabControl : OverlayTabControl { private readonly Box background; @@ -111,7 +109,7 @@ namespace osu.Game.Screens.Edit.Setup AccentColour = AccentColour }; - private class SetupScreenTabItem : OverlayTabItem + private partial class SetupScreenTabItem : OverlayTabItem { public SetupScreenTabItem(SetupSection value) : base(value) diff --git a/osu.Game/Screens/Edit/Setup/SetupScreenHeaderBackground.cs b/osu.Game/Screens/Edit/Setup/SetupScreenHeaderBackground.cs index 5680d75f4e..033e5361bb 100644 --- a/osu.Game/Screens/Edit/Setup/SetupScreenHeaderBackground.cs +++ b/osu.Game/Screens/Edit/Setup/SetupScreenHeaderBackground.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -12,16 +10,17 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; using osu.Game.Graphics.Containers; +using osu.Game.Localisation; namespace osu.Game.Screens.Edit.Setup { - public class SetupScreenHeaderBackground : CompositeDrawable + public partial class SetupScreenHeaderBackground : CompositeDrawable { [Resolved] - private OsuColour colours { get; set; } + private OsuColour colours { get; set; } = null!; [Resolved] - private IBindable working { get; set; } + private IBindable working { get; set; } = null!; private readonly Container content; @@ -63,7 +62,7 @@ namespace osu.Game.Screens.Edit.Setup }, new OsuTextFlowContainer(t => t.Font = OsuFont.Default.With(size: 24)) { - Text = "Drag image here to set beatmap background!", + Text = EditorSetupStrings.DragToSetBackground, Anchor = Anchor.Centre, Origin = Anchor.Centre, AutoSizeAxes = Axes.Both diff --git a/osu.Game/Screens/Edit/Setup/SetupSection.cs b/osu.Game/Screens/Edit/Setup/SetupSection.cs index 727a94a590..5f676798f1 100644 --- a/osu.Game/Screens/Edit/Setup/SetupSection.cs +++ b/osu.Game/Screens/Edit/Setup/SetupSection.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -14,9 +12,9 @@ using osuTK; namespace osu.Game.Screens.Edit.Setup { - public abstract class SetupSection : Container + public abstract partial class SetupSection : Container { - private FillFlowContainer flow; + private FillFlowContainer flow = null!; /// /// Used to align some of the child s together to achieve a grid-like look. @@ -24,10 +22,10 @@ namespace osu.Game.Screens.Edit.Setup protected const float LABEL_WIDTH = 160; [Resolved] - protected OsuColour Colours { get; private set; } + protected OsuColour Colours { get; private set; } = null!; [Resolved] - protected EditorBeatmap Beatmap { get; private set; } + protected EditorBeatmap Beatmap { get; private set; } = null!; protected override Container Content => flow; diff --git a/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs b/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs index 1f95156aba..b76723378f 100644 --- a/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs +++ b/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs @@ -1,14 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Collections.Generic; using osu.Framework.Graphics; namespace osu.Game.Screens.Edit.Timing { - public class ControlPointSettings : EditorRoundedScreenSettings + public partial class ControlPointSettings : EditorRoundedScreenSettings { protected override IReadOnlyList CreateSections() => new Drawable[] { diff --git a/osu.Game/Screens/Edit/Timing/ControlPointTable.cs b/osu.Game/Screens/Edit/Timing/ControlPointTable.cs index b51da2c53d..08b2ce8562 100644 --- a/osu.Game/Screens/Edit/Timing/ControlPointTable.cs +++ b/osu.Game/Screens/Edit/Timing/ControlPointTable.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; @@ -20,13 +18,13 @@ using osuTK; namespace osu.Game.Screens.Edit.Timing { - public class ControlPointTable : EditorTable + public partial class ControlPointTable : EditorTable { [Resolved] - private Bindable selectedGroup { get; set; } + private Bindable selectedGroup { get; set; } = null!; [Resolved] - private EditorClock clock { get; set; } + private EditorClock clock { get; set; } = null!; public const float TIMING_COLUMN_WIDTH = 230; @@ -37,7 +35,7 @@ namespace osu.Game.Screens.Edit.Timing Content = null; BackgroundFlow.Clear(); - if (value?.Any() != true) + if (!value.Any()) return; foreach (var group in value) @@ -63,19 +61,10 @@ namespace osu.Game.Screens.Edit.Timing { base.LoadComplete(); - selectedGroup.BindValueChanged(_ => - { - // TODO: This should scroll the selected row into view. - updateSelectedGroup(); - }, true); + selectedGroup.BindValueChanged(_ => updateSelectedGroup(), true); } - private void updateSelectedGroup() - { - // TODO: This should scroll the selected row into view. - foreach (var b in BackgroundFlow) - b.Selected = ReferenceEquals(b.Item, selectedGroup?.Value); - } + private void updateSelectedGroup() => SetSelectedRow(selectedGroup.Value); private TableColumn[] createHeaders() { @@ -92,33 +81,39 @@ namespace osu.Game.Screens.Edit.Timing { return new Drawable[] { - new FillFlowContainer - { - RelativeSizeAxes = Axes.Y, - Width = TIMING_COLUMN_WIDTH, - Spacing = new Vector2(5), - Children = new Drawable[] - { - new OsuSpriteText - { - Text = group.Time.ToEditorFormattedString(), - Font = OsuFont.GetFont(size: TEXT_SIZE, weight: FontWeight.Bold), - Width = 70, - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - }, - new ControlGroupAttributes(group, c => c is TimingControlPoint) - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - } - } - }, - new ControlGroupAttributes(group, c => !(c is TimingControlPoint)) + new ControlGroupTiming(group), + new ControlGroupAttributes(group, c => c is not TimingControlPoint) }; } - private class ControlGroupAttributes : CompositeDrawable + private partial class ControlGroupTiming : FillFlowContainer + { + public ControlGroupTiming(ControlPointGroup group) + { + Name = @"ControlGroupTiming"; + RelativeSizeAxes = Axes.Y; + Width = TIMING_COLUMN_WIDTH; + Spacing = new Vector2(5); + Children = new Drawable[] + { + new OsuSpriteText + { + Text = group.Time.ToEditorFormattedString(), + Font = OsuFont.GetFont(size: TEXT_SIZE, weight: FontWeight.Bold), + Width = 70, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + }, + new ControlGroupAttributes(group, c => c is TimingControlPoint) + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + } + }; + } + } + + private partial class ControlGroupAttributes : CompositeDrawable { private readonly Func matchFunction; @@ -132,6 +127,7 @@ namespace osu.Game.Screens.Edit.Timing AutoSizeAxes = Axes.X; RelativeSizeAxes = Axes.Y; + Name = @"ControlGroupAttributes"; InternalChild = fill = new FillFlowContainer { @@ -161,7 +157,6 @@ namespace osu.Game.Screens.Edit.Timing fill.ChildrenEnumerable = controlPoints .Where(matchFunction) .Select(createAttribute) - .Where(c => c != null) // arbitrary ordering to make timing points first. // probably want to explicitly define order in the future. .OrderByDescending(c => c.GetType().Name); @@ -184,7 +179,7 @@ namespace osu.Game.Screens.Edit.Timing return new SampleRowAttribute(sample); } - return null; + throw new ArgumentOutOfRangeException(nameof(controlPoint), $"Control point type {controlPoint.GetType()} is not supported"); } } } diff --git a/osu.Game/Screens/Edit/Timing/EffectSection.cs b/osu.Game/Screens/Edit/Timing/EffectSection.cs index 9be663bb26..051ac97366 100644 --- a/osu.Game/Screens/Edit/Timing/EffectSection.cs +++ b/osu.Game/Screens/Edit/Timing/EffectSection.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -13,12 +11,12 @@ using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Screens.Edit.Timing { - internal class EffectSection : Section + internal partial class EffectSection : Section { - private LabelledSwitchButton kiai; - private LabelledSwitchButton omitBarLine; + private LabelledSwitchButton kiai = null!; + private LabelledSwitchButton omitBarLine = null!; - private SliderWithTextBoxInput scrollSpeedSlider; + private SliderWithTextBoxInput scrollSpeedSlider = null!; [BackgroundDependencyLoader] private void load() @@ -55,7 +53,7 @@ namespace osu.Game.Screens.Edit.Timing private bool isRebinding; - protected override void OnControlPointChanged(ValueChangedEvent point) + protected override void OnControlPointChanged(ValueChangedEvent point) { if (point.NewValue != null) { diff --git a/osu.Game/Screens/Edit/Timing/GroupSection.cs b/osu.Game/Screens/Edit/Timing/GroupSection.cs index e78cd18024..487a871881 100644 --- a/osu.Game/Screens/Edit/Timing/GroupSection.cs +++ b/osu.Game/Screens/Edit/Timing/GroupSection.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -15,23 +13,23 @@ using osuTK; namespace osu.Game.Screens.Edit.Timing { - internal class GroupSection : CompositeDrawable + internal partial class GroupSection : CompositeDrawable { - private LabelledTextBox textBox; + private LabelledTextBox textBox = null!; - private OsuButton button; + private OsuButton button = null!; [Resolved] - protected Bindable SelectedGroup { get; private set; } + protected Bindable SelectedGroup { get; private set; } = null!; [Resolved] - protected EditorBeatmap Beatmap { get; private set; } + protected EditorBeatmap Beatmap { get; private set; } = null!; [Resolved] - private EditorClock clock { get; set; } + private EditorClock clock { get; set; } = null!; - [Resolved(canBeNull: true)] - private IEditorChangeHandler changeHandler { get; set; } + [Resolved] + private IEditorChangeHandler? changeHandler { get; set; } [BackgroundDependencyLoader] private void load() diff --git a/osu.Game/Screens/Edit/Timing/IndeterminateSliderWithTextBoxInput.cs b/osu.Game/Screens/Edit/Timing/IndeterminateSliderWithTextBoxInput.cs index ea6c6f31e4..eabe9b9f64 100644 --- a/osu.Game/Screens/Edit/Timing/IndeterminateSliderWithTextBoxInput.cs +++ b/osu.Game/Screens/Edit/Timing/IndeterminateSliderWithTextBoxInput.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Globalization; using osu.Framework.Bindables; @@ -23,7 +21,7 @@ namespace osu.Game.Screens.Edit.Timing /// where multiple objects with multiple different property values are selected /// by providing an "indeterminate state". /// - public class IndeterminateSliderWithTextBoxInput : CompositeDrawable, IHasCurrentValue + public partial class IndeterminateSliderWithTextBoxInput : CompositeDrawable, IHasCurrentValue where T : struct, IEquatable, IComparable, IConvertible { /// @@ -94,7 +92,20 @@ namespace osu.Game.Screens.Edit.Timing try { - slider.Current.Parse(t.Text); + switch (slider.Current) + { + case Bindable bindableInt: + bindableInt.Value = int.Parse(t.Text); + break; + + case Bindable bindableDouble: + bindableDouble.Value = double.Parse(t.Text); + break; + + default: + slider.Current.Parse(t.Text); + break; + } } catch { diff --git a/osu.Game/Screens/Edit/Timing/LabelledTimeSignature.cs b/osu.Game/Screens/Edit/Timing/LabelledTimeSignature.cs index 998e49a6ab..d0e1737f78 100644 --- a/osu.Game/Screens/Edit/Timing/LabelledTimeSignature.cs +++ b/osu.Game/Screens/Edit/Timing/LabelledTimeSignature.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -16,7 +14,7 @@ using osu.Game.Graphics.UserInterfaceV2; namespace osu.Game.Screens.Edit.Timing { - public class LabelledTimeSignature : LabelledComponent + public partial class LabelledTimeSignature : LabelledComponent { public LabelledTimeSignature() : base(false) @@ -25,7 +23,7 @@ namespace osu.Game.Screens.Edit.Timing protected override TimeSignatureBox CreateComponent() => new TimeSignatureBox(); - public class TimeSignatureBox : CompositeDrawable, IHasCurrentValue + public partial class TimeSignatureBox : CompositeDrawable, IHasCurrentValue { private readonly BindableWithCurrent current = new BindableWithCurrent(TimeSignature.SimpleQuadruple); @@ -35,7 +33,7 @@ namespace osu.Game.Screens.Edit.Timing set => current.Current = value; } - private OsuNumberBox numeratorBox; + private OsuNumberBox numeratorBox = null!; [BackgroundDependencyLoader] private void load() diff --git a/osu.Game/Screens/Edit/Timing/MetronomeDisplay.cs b/osu.Game/Screens/Edit/Timing/MetronomeDisplay.cs index 3895959982..f4a39405a1 100644 --- a/osu.Game/Screens/Edit/Timing/MetronomeDisplay.cs +++ b/osu.Game/Screens/Edit/Timing/MetronomeDisplay.cs @@ -1,10 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; -using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; @@ -26,26 +23,25 @@ using osuTK; namespace osu.Game.Screens.Edit.Timing { - public class MetronomeDisplay : BeatSyncedContainer + public partial class MetronomeDisplay : BeatSyncedContainer { - private Container swing; + private Container swing = null!; - private OsuSpriteText bpmText; + private OsuSpriteText bpmText = null!; - private Drawable weight; - private Drawable stick; + private Drawable weight = null!; + private Drawable stick = null!; - private IAdjustableClock metronomeClock; + private IAdjustableClock metronomeClock = null!; - private Sample sampleTick; - private Sample sampleTickDownbeat; - private Sample sampleLatch; + private Sample? sampleTick; + private Sample? sampleTickDownbeat; + private Sample? sampleLatch; - [CanBeNull] - private ScheduledDelegate tickPlaybackDelegate; + private ScheduledDelegate? tickPlaybackDelegate; [Resolved] - private OverlayColourProvider overlayColourProvider { get; set; } + private OverlayColourProvider overlayColourProvider { get; set; } = null!; public bool EnableClicking { get; set; } = true; @@ -225,13 +221,13 @@ namespace osu.Game.Screens.Edit.Timing private double beatLength; - private TimingControlPoint timingPoint; + private TimingControlPoint timingPoint = null!; private bool isSwinging; private readonly BindableInt interpolatedBpm = new BindableInt(); - private ScheduledDelegate latchDelegate; + private ScheduledDelegate? latchDelegate; protected override void LoadComplete() { diff --git a/osu.Game/Screens/Edit/Timing/RepeatingButtonBehaviour.cs b/osu.Game/Screens/Edit/Timing/RepeatingButtonBehaviour.cs index cd3ced53da..0437118f81 100644 --- a/osu.Game/Screens/Edit/Timing/RepeatingButtonBehaviour.cs +++ b/osu.Game/Screens/Edit/Timing/RepeatingButtonBehaviour.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using osu.Framework.Allocation; using osu.Framework.Audio; @@ -16,17 +14,17 @@ namespace osu.Game.Screens.Edit.Timing /// /// Represents a component that provides the behaviour of triggering button clicks repeatedly while holding with mouse. /// - public class RepeatingButtonBehaviour : Component + public partial class RepeatingButtonBehaviour : Component { private const double initial_delay = 300; private const double minimum_delay = 80; private readonly Drawable button; - private Sample sample; + private Sample? sample; - public Action RepeatBegan; - public Action RepeatEnded; + public Action? RepeatBegan; + public Action? RepeatEnded; /// /// An additive modifier for the frequency of the sample played on next actuation. @@ -61,7 +59,7 @@ namespace osu.Game.Screens.Edit.Timing base.OnMouseUp(e); } - private ScheduledDelegate adjustDelegate; + private ScheduledDelegate? adjustDelegate; private double adjustDelay = initial_delay; private void beginRepeat() diff --git a/osu.Game/Screens/Edit/Timing/RowAttribute.cs b/osu.Game/Screens/Edit/Timing/RowAttribute.cs index e73a343583..71407701db 100644 --- a/osu.Game/Screens/Edit/Timing/RowAttribute.cs +++ b/osu.Game/Screens/Edit/Timing/RowAttribute.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -15,15 +13,15 @@ using osuTK; namespace osu.Game.Screens.Edit.Timing { - public class RowAttribute : CompositeDrawable + public partial class RowAttribute : CompositeDrawable { protected readonly ControlPoint Point; private readonly string label; - protected Drawable Background { get; private set; } + protected Drawable Background { get; private set; } = null!; - protected FillFlowContainer Content { get; private set; } + protected FillFlowContainer Content { get; private set; } = null!; public RowAttribute(ControlPoint point, string label) { diff --git a/osu.Game/Screens/Edit/Timing/RowAttributes/AttributeProgressBar.cs b/osu.Game/Screens/Edit/Timing/RowAttributes/AttributeProgressBar.cs index a8d2172f58..4cae774078 100644 --- a/osu.Game/Screens/Edit/Timing/RowAttributes/AttributeProgressBar.cs +++ b/osu.Game/Screens/Edit/Timing/RowAttributes/AttributeProgressBar.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Beatmaps.ControlPoints; @@ -13,7 +11,7 @@ using osuTK; namespace osu.Game.Screens.Edit.Timing.RowAttributes { - public class AttributeProgressBar : ProgressBar + public partial class AttributeProgressBar : ProgressBar { private readonly ControlPoint controlPoint; diff --git a/osu.Game/Screens/Edit/Timing/RowAttributes/AttributeText.cs b/osu.Game/Screens/Edit/Timing/RowAttributes/AttributeText.cs index d65ef1799a..d735c93523 100644 --- a/osu.Game/Screens/Edit/Timing/RowAttributes/AttributeText.cs +++ b/osu.Game/Screens/Edit/Timing/RowAttributes/AttributeText.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Beatmaps.ControlPoints; @@ -11,7 +9,7 @@ using osu.Game.Graphics.Sprites; namespace osu.Game.Screens.Edit.Timing.RowAttributes { - public class AttributeText : OsuSpriteText + public partial class AttributeText : OsuSpriteText { private readonly ControlPoint controlPoint; diff --git a/osu.Game/Screens/Edit/Timing/RowAttributes/DifficultyRowAttribute.cs b/osu.Game/Screens/Edit/Timing/RowAttributes/DifficultyRowAttribute.cs index 17f8b01d07..43f3739503 100644 --- a/osu.Game/Screens/Edit/Timing/RowAttributes/DifficultyRowAttribute.cs +++ b/osu.Game/Screens/Edit/Timing/RowAttributes/DifficultyRowAttribute.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -11,11 +9,11 @@ using osu.Game.Graphics.Sprites; namespace osu.Game.Screens.Edit.Timing.RowAttributes { - public class DifficultyRowAttribute : RowAttribute + public partial class DifficultyRowAttribute : RowAttribute { private readonly BindableNumber speedMultiplier; - private OsuSpriteText text; + private OsuSpriteText text = null!; public DifficultyRowAttribute(DifficultyControlPoint difficulty) : base(difficulty, "difficulty") diff --git a/osu.Game/Screens/Edit/Timing/RowAttributes/EffectRowAttribute.cs b/osu.Game/Screens/Edit/Timing/RowAttributes/EffectRowAttribute.cs index ef682dd3ad..3b068699ca 100644 --- a/osu.Game/Screens/Edit/Timing/RowAttributes/EffectRowAttribute.cs +++ b/osu.Game/Screens/Edit/Timing/RowAttributes/EffectRowAttribute.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -10,15 +8,15 @@ using osu.Game.Beatmaps.ControlPoints; namespace osu.Game.Screens.Edit.Timing.RowAttributes { - public class EffectRowAttribute : RowAttribute + public partial class EffectRowAttribute : RowAttribute { private readonly Bindable kiaiMode; private readonly Bindable omitBarLine; private readonly BindableNumber scrollSpeed; - private AttributeText kiaiModeBubble; - private AttributeText omitBarLineBubble; - private AttributeText text; + private AttributeText kiaiModeBubble = null!; + private AttributeText omitBarLineBubble = null!; + private AttributeText text = null!; public EffectRowAttribute(EffectControlPoint effect) : base(effect, "effect") diff --git a/osu.Game/Screens/Edit/Timing/RowAttributes/SampleRowAttribute.cs b/osu.Game/Screens/Edit/Timing/RowAttributes/SampleRowAttribute.cs index e06f6b7bfb..e86a991521 100644 --- a/osu.Game/Screens/Edit/Timing/RowAttributes/SampleRowAttribute.cs +++ b/osu.Game/Screens/Edit/Timing/RowAttributes/SampleRowAttribute.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -11,10 +9,10 @@ using osu.Game.Graphics.Sprites; namespace osu.Game.Screens.Edit.Timing.RowAttributes { - public class SampleRowAttribute : RowAttribute + public partial class SampleRowAttribute : RowAttribute { - private AttributeText sampleText; - private OsuSpriteText volumeText; + private AttributeText sampleText = null!; + private OsuSpriteText volumeText = null!; private readonly Bindable sampleBank; private readonly BindableNumber volume; diff --git a/osu.Game/Screens/Edit/Timing/RowAttributes/TimingRowAttribute.cs b/osu.Game/Screens/Edit/Timing/RowAttributes/TimingRowAttribute.cs index 0b498650d4..a6d3816bd4 100644 --- a/osu.Game/Screens/Edit/Timing/RowAttributes/TimingRowAttribute.cs +++ b/osu.Game/Screens/Edit/Timing/RowAttributes/TimingRowAttribute.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions; @@ -13,11 +11,11 @@ using osu.Game.Overlays; namespace osu.Game.Screens.Edit.Timing.RowAttributes { - public class TimingRowAttribute : RowAttribute + public partial class TimingRowAttribute : RowAttribute { private readonly BindableNumber beatLength; private readonly Bindable timeSignature; - private OsuSpriteText text; + private OsuSpriteText text = null!; public TimingRowAttribute(TimingControlPoint timing) : base(timing, "timing") diff --git a/osu.Game/Screens/Edit/Timing/Section.cs b/osu.Game/Screens/Edit/Timing/Section.cs index 02789c0cbf..ba3874dcee 100644 --- a/osu.Game/Screens/Edit/Timing/Section.cs +++ b/osu.Game/Screens/Edit/Timing/Section.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -16,26 +14,26 @@ using osuTK; namespace osu.Game.Screens.Edit.Timing { - internal abstract class Section : CompositeDrawable + internal abstract partial class Section : CompositeDrawable where T : ControlPoint { - private OsuCheckbox checkbox; - private Container content; + private OsuCheckbox checkbox = null!; + private Container content = null!; - protected FillFlowContainer Flow { get; private set; } + protected FillFlowContainer Flow { get; private set; } = null!; - protected Bindable ControlPoint { get; } = new Bindable(); + protected Bindable ControlPoint { get; } = new Bindable(); private const float header_height = 50; [Resolved] - protected EditorBeatmap Beatmap { get; private set; } + protected EditorBeatmap Beatmap { get; private set; } = null!; [Resolved] - protected Bindable SelectedGroup { get; private set; } + protected Bindable SelectedGroup { get; private set; } = null!; - [Resolved(canBeNull: true)] - protected IEditorChangeHandler ChangeHandler { get; private set; } + [Resolved] + protected IEditorChangeHandler? ChangeHandler { get; private set; } [BackgroundDependencyLoader] private void load(OverlayColourProvider colours) @@ -128,7 +126,7 @@ namespace osu.Game.Screens.Edit.Timing ControlPoint.BindValueChanged(OnControlPointChanged, true); } - protected abstract void OnControlPointChanged(ValueChangedEvent point); + protected abstract void OnControlPointChanged(ValueChangedEvent point); protected abstract T CreatePoint(); } diff --git a/osu.Game/Screens/Edit/Timing/SliderWithTextBoxInput.cs b/osu.Game/Screens/Edit/Timing/SliderWithTextBoxInput.cs index 4dcb5ad2ba..1bf0e5299d 100644 --- a/osu.Game/Screens/Edit/Timing/SliderWithTextBoxInput.cs +++ b/osu.Game/Screens/Edit/Timing/SliderWithTextBoxInput.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Globalization; using osu.Framework.Bindables; @@ -17,7 +15,7 @@ using osuTK; namespace osu.Game.Screens.Edit.Timing { - public class SliderWithTextBoxInput : CompositeDrawable, IHasCurrentValue + public partial class SliderWithTextBoxInput : CompositeDrawable, IHasCurrentValue where T : struct, IEquatable, IComparable, IConvertible { private readonly SettingsSlider slider; @@ -58,7 +56,20 @@ namespace osu.Game.Screens.Edit.Timing try { - slider.Current.Parse(t.Text); + switch (slider.Current) + { + case Bindable bindableInt: + bindableInt.Value = int.Parse(t.Text); + break; + + case Bindable bindableDouble: + bindableDouble.Value = double.Parse(t.Text); + break; + + default: + slider.Current.Parse(t.Text); + break; + } } catch { diff --git a/osu.Game/Screens/Edit/Timing/TapButton.cs b/osu.Game/Screens/Edit/Timing/TapButton.cs index 2944eea4fe..f28c6ccf0a 100644 --- a/osu.Game/Screens/Edit/Timing/TapButton.cs +++ b/osu.Game/Screens/Edit/Timing/TapButton.cs @@ -28,7 +28,7 @@ using osuTK.Input; namespace osu.Game.Screens.Edit.Timing { - internal class TapButton : CircularContainer, IKeyBindingHandler + internal partial class TapButton : CircularContainer, IKeyBindingHandler { public const float SIZE = 140; @@ -37,10 +37,10 @@ namespace osu.Game.Screens.Edit.Timing [Resolved] private OverlayColourProvider colourProvider { get; set; } = null!; - [Resolved(canBeNull: true)] + [Resolved] private Bindable? selectedGroup { get; set; } - [Resolved(canBeNull: true)] + [Resolved] private IBeatSyncProvider? beatSyncSource { get; set; } private Circle hoverLayer = null!; @@ -343,7 +343,7 @@ namespace osu.Game.Screens.Edit.Timing IsHandlingTapping.Value = false; } - private class Light : CompositeDrawable + private partial class Light : CompositeDrawable { public Drawable Glow { get; private set; } = null!; diff --git a/osu.Game/Screens/Edit/Timing/TapTimingControl.cs b/osu.Game/Screens/Edit/Timing/TapTimingControl.cs index 3b26e335d9..bb7a3b8be3 100644 --- a/osu.Game/Screens/Edit/Timing/TapTimingControl.cs +++ b/osu.Game/Screens/Edit/Timing/TapTimingControl.cs @@ -18,7 +18,7 @@ using osuTK; namespace osu.Game.Screens.Edit.Timing { - public class TapTimingControl : CompositeDrawable + public partial class TapTimingControl : CompositeDrawable { [Resolved] private EditorClock editorClock { get; set; } = null!; @@ -88,7 +88,7 @@ namespace osu.Game.Screens.Edit.Timing Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, }, - new WaveformComparisonDisplay(), + new WaveformComparisonDisplay() } }, } @@ -233,7 +233,7 @@ namespace osu.Game.Screens.Edit.Timing timing.BeatLength = 60000 / (timing.BPM + adjust); } - private class InlineButton : OsuButton + private partial class InlineButton : OsuButton { private readonly IconUsage icon; private readonly Anchor anchor; diff --git a/osu.Game/Screens/Edit/Timing/TimingAdjustButton.cs b/osu.Game/Screens/Edit/Timing/TimingAdjustButton.cs index 16dea328da..fac168c70c 100644 --- a/osu.Game/Screens/Edit/Timing/TimingAdjustButton.cs +++ b/osu.Game/Screens/Edit/Timing/TimingAdjustButton.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Linq; using osu.Framework.Allocation; @@ -20,9 +18,9 @@ namespace osu.Game.Screens.Edit.Timing /// /// A button with variable constant output based on hold position and length. /// - public class TimingAdjustButton : CompositeDrawable + public partial class TimingAdjustButton : CompositeDrawable { - public Action Action; + public Action? Action; private readonly double adjustAmount; @@ -44,10 +42,10 @@ namespace osu.Game.Screens.Edit.Timing private readonly RepeatingButtonBehaviour repeatBehaviour; [Resolved] - private OverlayColourProvider colourProvider { get; set; } + private OverlayColourProvider colourProvider { get; set; } = null!; [Resolved] - private EditorBeatmap editorBeatmap { get; set; } + private EditorBeatmap editorBeatmap { get; set; } = null!; public TimingAdjustButton(double adjustAmount) { @@ -104,7 +102,7 @@ namespace osu.Game.Screens.Edit.Timing if (hoveredBox == null) return false; - Action(adjustAmount * hoveredBox.Multiplier); + Action?.Invoke(adjustAmount * hoveredBox.Multiplier); hoveredBox.Flash(); @@ -112,13 +110,16 @@ namespace osu.Game.Screens.Edit.Timing return true; } - private class IncrementBox : CompositeDrawable + private partial class IncrementBox : CompositeDrawable { public readonly float Multiplier; private readonly Box box; private readonly OsuSpriteText text; + [Resolved] + private OverlayColourProvider colourProvider { get; set; } = null!; + public IncrementBox(int index, double amount) { Multiplier = Math.Sign(index) * convertMultiplier(index); @@ -156,9 +157,6 @@ namespace osu.Game.Screens.Edit.Timing }; } - [Resolved] - private OverlayColourProvider colourProvider { get; set; } - protected override void LoadComplete() { base.LoadComplete(); diff --git a/osu.Game/Screens/Edit/Timing/TimingScreen.cs b/osu.Game/Screens/Edit/Timing/TimingScreen.cs index fd218209d4..2450909929 100644 --- a/osu.Game/Screens/Edit/Timing/TimingScreen.cs +++ b/osu.Game/Screens/Edit/Timing/TimingScreen.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Linq; using osu.Framework.Allocation; @@ -20,7 +18,7 @@ using osuTK; namespace osu.Game.Screens.Edit.Timing { - public class TimingScreen : EditorScreenWithTimeline + public partial class TimingScreen : EditorScreenWithTimeline { [Cached] public readonly Bindable SelectedGroup = new Bindable(); @@ -48,26 +46,26 @@ namespace osu.Game.Screens.Edit.Timing } }; - public class ControlPointList : CompositeDrawable + public partial class ControlPointList : CompositeDrawable { - private OsuButton deleteButton; - private ControlPointTable table; + private OsuButton deleteButton = null!; + private ControlPointTable table = null!; + private OsuScrollContainer scroll = null!; + private RoundedButton addButton = null!; private readonly IBindableList controlPointGroups = new BindableList(); - private RoundedButton addButton; + [Resolved] + private EditorClock clock { get; set; } = null!; [Resolved] - private EditorClock clock { get; set; } + protected EditorBeatmap Beatmap { get; private set; } = null!; [Resolved] - protected EditorBeatmap Beatmap { get; private set; } + private Bindable selectedGroup { get; set; } = null!; [Resolved] - private Bindable selectedGroup { get; set; } - - [Resolved(canBeNull: true)] - private IEditorChangeHandler changeHandler { get; set; } + private IEditorChangeHandler? changeHandler { get; set; } [BackgroundDependencyLoader] private void load(OverlayColourProvider colours) @@ -88,7 +86,7 @@ namespace osu.Game.Screens.Edit.Timing RelativeSizeAxes = Axes.Y, Width = ControlPointTable.TIMING_COLUMN_WIDTH + margins, }, - new OsuScrollContainer + scroll = new OsuScrollContainer { RelativeSizeAxes = Axes.Both, Child = table = new ControlPointTable(), @@ -142,6 +140,8 @@ namespace osu.Game.Screens.Edit.Timing table.ControlGroups = controlPointGroups; changeHandler?.SaveState(); }, true); + + table.OnRowSelected += drawable => scroll.ScrollIntoView(drawable); } protected override bool OnClick(ClickEvent e) @@ -159,7 +159,7 @@ namespace osu.Game.Screens.Edit.Timing addButton.Enabled.Value = clock.CurrentTimeAccurate != selectedGroup.Value?.Time; } - private Type trackedType; + private Type? trackedType; /// /// Given the user has selected a control point group, we want to track any group which is diff --git a/osu.Game/Screens/Edit/Timing/TimingSection.cs b/osu.Game/Screens/Edit/Timing/TimingSection.cs index 9b86969db1..d2d524ccbe 100644 --- a/osu.Game/Screens/Edit/Timing/TimingSection.cs +++ b/osu.Game/Screens/Edit/Timing/TimingSection.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -11,10 +9,10 @@ using osu.Game.Graphics.UserInterfaceV2; namespace osu.Game.Screens.Edit.Timing { - internal class TimingSection : Section + internal partial class TimingSection : Section { - private LabelledTimeSignature timeSignature; - private BPMTextBox bpmTextEntry; + private LabelledTimeSignature timeSignature = null!; + private BPMTextBox bpmTextEntry = null!; [BackgroundDependencyLoader] private void load() @@ -45,7 +43,7 @@ namespace osu.Game.Screens.Edit.Timing private bool isRebinding; - protected override void OnControlPointChanged(ValueChangedEvent point) + protected override void OnControlPointChanged(ValueChangedEvent point) { if (point.NewValue != null) { @@ -69,7 +67,7 @@ namespace osu.Game.Screens.Edit.Timing }; } - private class BPMTextBox : LabelledTextBox + private partial class BPMTextBox : LabelledTextBox { private readonly BindableNumber beatLengthBindable = new TimingControlPoint().BeatLengthBindable; diff --git a/osu.Game/Screens/Edit/Timing/WaveformComparisonDisplay.cs b/osu.Game/Screens/Edit/Timing/WaveformComparisonDisplay.cs index 2956a28547..3b3acea935 100644 --- a/osu.Game/Screens/Edit/Timing/WaveformComparisonDisplay.cs +++ b/osu.Game/Screens/Edit/Timing/WaveformComparisonDisplay.cs @@ -4,6 +4,7 @@ using System; using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Audio.Track; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Audio; @@ -21,7 +22,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.Edit.Timing { - internal class WaveformComparisonDisplay : CompositeDrawable + internal partial class WaveformComparisonDisplay : CompositeDrawable { private const int total_waveforms = 8; @@ -150,7 +151,7 @@ namespace osu.Game.Screens.Edit.Timing if (!displayLocked.Value) { float trackLength = (float)beatmap.Value.Track.Length; - int totalBeatsAvailable = (int)(trackLength / timingPoint.BeatLength); + int totalBeatsAvailable = (int)((trackLength - timingPoint.Time) / timingPoint.BeatLength); Scheduler.AddOnce(showFromBeat, (int)(e.MousePosition.X / DrawWidth * totalBeatsAvailable)); } @@ -222,7 +223,7 @@ namespace osu.Game.Screens.Edit.Timing } } - internal class LockedOverlay : CompositeDrawable + internal partial class LockedOverlay : CompositeDrawable { private OsuSpriteText text = null!; @@ -285,7 +286,7 @@ namespace osu.Game.Screens.Edit.Timing } } - internal class WaveformRow : CompositeDrawable + internal partial class WaveformRow : CompositeDrawable { private readonly bool isMainRow; private OsuSpriteText beatIndexText = null!; @@ -294,13 +295,18 @@ namespace osu.Game.Screens.Edit.Timing [Resolved] private OverlayColourProvider colourProvider { get; set; } = null!; + [Resolved] + private IBindable beatmap { get; set; } = null!; + + private readonly IBindable track = new Bindable(); + public WaveformRow(bool isMainRow) { this.isMainRow = isMainRow; } [BackgroundDependencyLoader] - private void load(IBindable beatmap) + private void load(EditorClock clock) { InternalChildren = new Drawable[] { @@ -330,6 +336,13 @@ namespace osu.Game.Screens.Edit.Timing Colour = colourProvider.Content2 } }; + + track.BindTo(clock.Track); + } + + protected override void LoadComplete() + { + track.ValueChanged += _ => waveformGraph.Waveform = beatmap.Value.Waveform; } public int BeatIndex { set => beatIndexText.Text = value.ToString(); } diff --git a/osu.Game/Screens/Edit/TransactionalCommitComponent.cs b/osu.Game/Screens/Edit/TransactionalCommitComponent.cs index 78d052702a..55c9cf86c3 100644 --- a/osu.Game/Screens/Edit/TransactionalCommitComponent.cs +++ b/osu.Game/Screens/Edit/TransactionalCommitComponent.cs @@ -11,7 +11,7 @@ namespace osu.Game.Screens.Edit /// /// A component that tracks a batch change, only applying after all active changes are completed. /// - public abstract class TransactionalCommitComponent : Component + public abstract partial class TransactionalCommitComponent : Component { /// /// Fires whenever a transaction begins. Will not fire on nested transactions. diff --git a/osu.Game/Screens/Edit/Verify/InterpretationSection.cs b/osu.Game/Screens/Edit/Verify/InterpretationSection.cs index 276c2a3ea9..5b6eea098c 100644 --- a/osu.Game/Screens/Edit/Verify/InterpretationSection.cs +++ b/osu.Game/Screens/Edit/Verify/InterpretationSection.cs @@ -10,7 +10,7 @@ using osu.Game.Overlays.Settings; namespace osu.Game.Screens.Edit.Verify { - internal class InterpretationSection : EditorRoundedScreenSettingsSection + internal partial class InterpretationSection : EditorRoundedScreenSettingsSection { protected override string HeaderText => "Interpretation"; diff --git a/osu.Game/Screens/Edit/Verify/IssueList.cs b/osu.Game/Screens/Edit/Verify/IssueList.cs index bffda4ec41..907949aee8 100644 --- a/osu.Game/Screens/Edit/Verify/IssueList.cs +++ b/osu.Game/Screens/Edit/Verify/IssueList.cs @@ -21,7 +21,7 @@ using osuTK; namespace osu.Game.Screens.Edit.Verify { [Cached] - public class IssueList : CompositeDrawable + public partial class IssueList : CompositeDrawable { private IssueTable table; diff --git a/osu.Game/Screens/Edit/Verify/IssueSettings.cs b/osu.Game/Screens/Edit/Verify/IssueSettings.cs index 70065f6f0d..e8275c3684 100644 --- a/osu.Game/Screens/Edit/Verify/IssueSettings.cs +++ b/osu.Game/Screens/Edit/Verify/IssueSettings.cs @@ -8,7 +8,7 @@ using osu.Framework.Graphics; namespace osu.Game.Screens.Edit.Verify { - public class IssueSettings : EditorRoundedScreenSettings + public partial class IssueSettings : EditorRoundedScreenSettings { protected override IReadOnlyList CreateSections() => new Drawable[] { diff --git a/osu.Game/Screens/Edit/Verify/IssueTable.cs b/osu.Game/Screens/Edit/Verify/IssueTable.cs index f1a76dcbf5..ba5f98a772 100644 --- a/osu.Game/Screens/Edit/Verify/IssueTable.cs +++ b/osu.Game/Screens/Edit/Verify/IssueTable.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; @@ -18,21 +16,21 @@ using osu.Game.Rulesets.Edit.Checks.Components; namespace osu.Game.Screens.Edit.Verify { - public class IssueTable : EditorTable + public partial class IssueTable : EditorTable { - [Resolved] - private VerifyScreen verify { get; set; } - - private Bindable selectedIssue; + private Bindable selectedIssue = null!; [Resolved] - private EditorClock clock { get; set; } + private VerifyScreen verify { get; set; } = null!; [Resolved] - private EditorBeatmap editorBeatmap { get; set; } + private EditorClock clock { get; set; } = null!; [Resolved] - private Editor editor { get; set; } + private EditorBeatmap editorBeatmap { get; set; } = null!; + + [Resolved] + private Editor editor { get; set; } = null!; public IEnumerable Issues { @@ -41,7 +39,7 @@ namespace osu.Game.Screens.Edit.Verify Content = null; BackgroundFlow.Clear(); - if (value == null) + if (!value.Any()) return; foreach (var issue in value) @@ -79,7 +77,7 @@ namespace osu.Game.Screens.Edit.Verify selectedIssue = verify.SelectedIssue.GetBoundCopy(); selectedIssue.BindValueChanged(issue => { - foreach (var b in BackgroundFlow) b.Selected = b.Item == issue.NewValue; + SetSelectedRow(issue.NewValue); }, true); } diff --git a/osu.Game/Screens/Edit/Verify/VerifyScreen.cs b/osu.Game/Screens/Edit/Verify/VerifyScreen.cs index 3030018138..b17cf3379e 100644 --- a/osu.Game/Screens/Edit/Verify/VerifyScreen.cs +++ b/osu.Game/Screens/Edit/Verify/VerifyScreen.cs @@ -13,7 +13,7 @@ using osu.Game.Rulesets.Edit.Checks.Components; namespace osu.Game.Screens.Edit.Verify { [Cached] - public class VerifyScreen : EditorScreen + public partial class VerifyScreen : EditorScreen { public readonly Bindable SelectedIssue = new Bindable(); diff --git a/osu.Game/Screens/Edit/Verify/VisibilitySection.cs b/osu.Game/Screens/Edit/Verify/VisibilitySection.cs index fbf6982984..e2e2e518ae 100644 --- a/osu.Game/Screens/Edit/Verify/VisibilitySection.cs +++ b/osu.Game/Screens/Edit/Verify/VisibilitySection.cs @@ -11,7 +11,7 @@ using osu.Game.Rulesets.Edit.Checks.Components; namespace osu.Game.Screens.Edit.Verify { - internal class VisibilitySection : EditorRoundedScreenSettingsSection + internal partial class VisibilitySection : EditorRoundedScreenSettingsSection { private readonly IssueType[] configurableIssueTypes = { diff --git a/osu.Game/Screens/Edit/WaveformOpacityMenuItem.cs b/osu.Game/Screens/Edit/WaveformOpacityMenuItem.cs index 3d3f67e70e..5b1d7142e4 100644 --- a/osu.Game/Screens/Edit/WaveformOpacityMenuItem.cs +++ b/osu.Game/Screens/Edit/WaveformOpacityMenuItem.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using osu.Framework.Bindables; using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics.UserInterface; +using osu.Game.Localisation; namespace osu.Game.Screens.Edit { @@ -17,7 +18,7 @@ namespace osu.Game.Screens.Edit private readonly Dictionary menuItemLookup = new Dictionary(); public WaveformOpacityMenuItem(Bindable waveformOpacity) - : base("Waveform opacity") + : base(EditorStrings.WaveformOpacity) { Items = new[] { diff --git a/osu.Game/Screens/Import/FileImportScreen.cs b/osu.Game/Screens/Import/FileImportScreen.cs index e3d8de2dfd..6b7a269d12 100644 --- a/osu.Game/Screens/Import/FileImportScreen.cs +++ b/osu.Game/Screens/Import/FileImportScreen.cs @@ -14,13 +14,12 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Screens; using osu.Game.Graphics; using osu.Game.Graphics.Containers; -using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterfaceV2; using osuTK; namespace osu.Game.Screens.Import { - public class FileImportScreen : OsuScreen + public partial class FileImportScreen : OsuScreen { public override bool HideOverlaysOnEnter => true; @@ -28,7 +27,7 @@ namespace osu.Game.Screens.Import private Container contentContainer; private TextFlowContainer currentFileText; - private TriangleButton importButton; + private RoundedButton importButton; private const float duration = 300; private const float button_height = 50; @@ -100,7 +99,7 @@ namespace osu.Game.Screens.Import } }, }, - importButton = new TriangleButton + importButton = new RoundedButton { Text = "Import", Anchor = Anchor.BottomCentre, diff --git a/osu.Game/Screens/Loader.cs b/osu.Game/Screens/Loader.cs index ac22fdce71..b70c1f7ddf 100644 --- a/osu.Game/Screens/Loader.cs +++ b/osu.Game/Screens/Loader.cs @@ -19,7 +19,7 @@ using IntroSequence = osu.Game.Configuration.IntroSequence; namespace osu.Game.Screens { - public class Loader : StartupScreen + public partial class Loader : StartupScreen { private bool showDisclaimer; @@ -116,7 +116,7 @@ namespace osu.Game.Screens /// /// Compiles a set of shaders before continuing. Attempts to draw some frames between compilation by limiting to one compile per draw frame. /// - public class ShaderPrecompiler : Drawable + public partial class ShaderPrecompiler : Drawable { private readonly List loadTargets = new List(); diff --git a/osu.Game/Screens/Menu/ButtonArea.cs b/osu.Game/Screens/Menu/ButtonArea.cs index bf6e0cee83..69ba68442f 100644 --- a/osu.Game/Screens/Menu/ButtonArea.cs +++ b/osu.Game/Screens/Menu/ButtonArea.cs @@ -13,7 +13,7 @@ using osuTK; namespace osu.Game.Screens.Menu { - public class ButtonArea : Container, IStateful + public partial class ButtonArea : Container, IStateful { public FlowContainerWithOrigin Flow; @@ -90,7 +90,7 @@ namespace osu.Game.Screens.Menu public event Action StateChanged; - private class ButtonAreaBackground : Box, IStateful + private partial class ButtonAreaBackground : Box, IStateful { private ButtonAreaBackgroundState state; diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index 04bffda81b..2ead18c3d6 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -34,7 +34,7 @@ using osuTK.Input; namespace osu.Game.Screens.Menu { - public class ButtonSystem : Container, IStateful, IKeyBindingHandler + public partial class ButtonSystem : Container, IStateful, IKeyBindingHandler { public event Action StateChanged; diff --git a/osu.Game/Screens/Menu/ConfirmDiscardChangesDialog.cs b/osu.Game/Screens/Menu/ConfirmDiscardChangesDialog.cs index 450c559450..0cd3e9ce71 100644 --- a/osu.Game/Screens/Menu/ConfirmDiscardChangesDialog.cs +++ b/osu.Game/Screens/Menu/ConfirmDiscardChangesDialog.cs @@ -7,7 +7,7 @@ using osu.Game.Overlays.Dialog; namespace osu.Game.Screens.Menu { - public class ConfirmDiscardChangesDialog : PopupDialog + public partial class ConfirmDiscardChangesDialog : PopupDialog { /// /// Construct a new discard changes confirmation dialog. diff --git a/osu.Game/Screens/Menu/ConfirmExitDialog.cs b/osu.Game/Screens/Menu/ConfirmExitDialog.cs index 20fa889986..4906232d21 100644 --- a/osu.Game/Screens/Menu/ConfirmExitDialog.cs +++ b/osu.Game/Screens/Menu/ConfirmExitDialog.cs @@ -7,7 +7,7 @@ using osu.Game.Overlays.Dialog; namespace osu.Game.Screens.Menu { - public class ConfirmExitDialog : PopupDialog + public partial class ConfirmExitDialog : PopupDialog { /// /// Construct a new exit confirmation dialog. diff --git a/osu.Game/Screens/Menu/Disclaimer.cs b/osu.Game/Screens/Menu/Disclaimer.cs index a81658a4b6..539d58d2d7 100644 --- a/osu.Game/Screens/Menu/Disclaimer.cs +++ b/osu.Game/Screens/Menu/Disclaimer.cs @@ -22,7 +22,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.Menu { - public class Disclaimer : StartupScreen + public partial class Disclaimer : StartupScreen { private SpriteIcon icon; private Color4 iconColour; @@ -239,7 +239,7 @@ namespace osu.Game.Screens.Menu "New features are coming online every update. Make sure to stay up-to-date!", "If you find the UI too large or small, try adjusting UI scale in settings!", "Try adjusting the \"Screen Scaling\" mode to change your gameplay or UI area, even in fullscreen!", - "What used to be \"osu!direct\" is available to all users just like on the website. You can access it anywhere using Ctrl-D!", + "What used to be \"osu!direct\" is available to all users just like on the website. You can access it anywhere using Ctrl-B!", "Seeking in replays is available by dragging on the difficulty bar at the bottom of the screen!", "Multithreading support means that even with low \"FPS\" your input and judgements will be accurate!", "Try scrolling down in the mod select panel to find a bunch of new fun mods!", diff --git a/osu.Game/Screens/Menu/ExitConfirmOverlay.cs b/osu.Game/Screens/Menu/ExitConfirmOverlay.cs index f82a6c9736..bc2f6ea00f 100644 --- a/osu.Game/Screens/Menu/ExitConfirmOverlay.cs +++ b/osu.Game/Screens/Menu/ExitConfirmOverlay.cs @@ -10,7 +10,7 @@ using osu.Game.Overlays; namespace osu.Game.Screens.Menu { - public class ExitConfirmOverlay : HoldToConfirmOverlay, IKeyBindingHandler + public partial class ExitConfirmOverlay : HoldToConfirmOverlay, IKeyBindingHandler { protected override bool AllowMultipleFires => true; diff --git a/osu.Game/Screens/Menu/FlowContainerWithOrigin.cs b/osu.Game/Screens/Menu/FlowContainerWithOrigin.cs index 24a365ffd1..e36cc4a152 100644 --- a/osu.Game/Screens/Menu/FlowContainerWithOrigin.cs +++ b/osu.Game/Screens/Menu/FlowContainerWithOrigin.cs @@ -12,7 +12,7 @@ namespace osu.Game.Screens.Menu /// /// A flow container with an origin based on one of its contained drawables. /// - public class FlowContainerWithOrigin : FillFlowContainer + public partial class FlowContainerWithOrigin : FillFlowContainer { /// /// A target drawable which this flowcontainer should be centered around. diff --git a/osu.Game/Screens/Menu/IntroCircles.cs b/osu.Game/Screens/Menu/IntroCircles.cs index 7a4bdb231f..57a3fd9c38 100644 --- a/osu.Game/Screens/Menu/IntroCircles.cs +++ b/osu.Game/Screens/Menu/IntroCircles.cs @@ -13,7 +13,7 @@ using osu.Framework.Graphics; namespace osu.Game.Screens.Menu { - public class IntroCircles : IntroScreen + public partial class IntroCircles : IntroScreen { protected override string BeatmapHash => "3c8b1fcc9434dbb29e2fb613d3b9eada9d7bb6c125ceb32396c3b53437280c83"; diff --git a/osu.Game/Screens/Menu/IntroScreen.cs b/osu.Game/Screens/Menu/IntroScreen.cs index dcead4a3a8..de7732dd5e 100644 --- a/osu.Game/Screens/Menu/IntroScreen.cs +++ b/osu.Game/Screens/Menu/IntroScreen.cs @@ -20,6 +20,7 @@ using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Database; +using osu.Game.Localisation; using osu.Game.Online.API; using osu.Game.Overlays; using osu.Game.Overlays.Notifications; @@ -32,7 +33,7 @@ using Realms; namespace osu.Game.Screens.Menu { - public abstract class IntroScreen : StartupScreen + public abstract partial class IntroScreen : StartupScreen { /// /// Whether we have loaded the menu previously. @@ -201,7 +202,7 @@ namespace osu.Game.Screens.Menu { notifications.Post(new SimpleErrorNotification { - Text = "osu! doesn't seem to be able to play audio correctly.\n\nPlease try changing your audio device to a working setting." + Text = NotificationsStrings.AudioPlaybackIssue }); } }, 5000); diff --git a/osu.Game/Screens/Menu/IntroSequence.cs b/osu.Game/Screens/Menu/IntroSequence.cs index bc5aa83503..722f884ac5 100644 --- a/osu.Game/Screens/Menu/IntroSequence.cs +++ b/osu.Game/Screens/Menu/IntroSequence.cs @@ -16,7 +16,7 @@ using osu.Game.Graphics.Sprites; namespace osu.Game.Screens.Menu { - public class IntroSequence : Container + public partial class IntroSequence : Container { private const float logo_size = 460; //todo: this should probably be 480 @@ -266,7 +266,7 @@ namespace osu.Game.Screens.Menu } } - private class Ring : Container + private partial class Ring : Container { public readonly Circle Foreground; diff --git a/osu.Game/Screens/Menu/IntroTriangles.cs b/osu.Game/Screens/Menu/IntroTriangles.cs index 4ec877b85a..a9c86b10c4 100644 --- a/osu.Game/Screens/Menu/IntroTriangles.cs +++ b/osu.Game/Screens/Menu/IntroTriangles.cs @@ -25,7 +25,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.Menu { - public class IntroTriangles : IntroScreen + public partial class IntroTriangles : IntroScreen { protected override string BeatmapHash => "a1556d0801b3a6b175dda32ef546f0ec812b400499f575c44fccbe9c67f9b1e5"; @@ -107,7 +107,7 @@ namespace osu.Game.Screens.Menu intro.Expire(); } - private class TrianglesIntroSequence : CompositeDrawable + private partial class TrianglesIntroSequence : CompositeDrawable { private readonly OsuLogo logo; private readonly Action showBackgroundAction; @@ -269,7 +269,7 @@ namespace osu.Game.Screens.Menu } } - private class GameWideFlash : Box + private partial class GameWideFlash : Box { private const double flash_length = 1000; @@ -287,7 +287,7 @@ namespace osu.Game.Screens.Menu } } - private class LazerLogo : CompositeDrawable + private partial class LazerLogo : CompositeDrawable { private LogoAnimation highlight, background; @@ -327,7 +327,7 @@ namespace osu.Game.Screens.Menu } } - private class RulesetFlow : FillFlowContainer + private partial class RulesetFlow : FillFlowContainer { [BackgroundDependencyLoader] private void load(RulesetStore rulesets) @@ -357,7 +357,7 @@ namespace osu.Game.Screens.Menu } } - private class GlitchingTriangles : CompositeDrawable + private partial class GlitchingTriangles : CompositeDrawable { public GlitchingTriangles() { @@ -391,7 +391,7 @@ namespace osu.Game.Screens.Menu /// /// Represents a sprite that is drawn in a triangle shape, instead of a rectangle shape. /// - public class OutlineTriangle : BufferedContainer + public partial class OutlineTriangle : BufferedContainer { public OutlineTriangle(bool outlineOnly, float size) : base(cachedFrameBuffer: true) diff --git a/osu.Game/Screens/Menu/IntroWelcome.cs b/osu.Game/Screens/Menu/IntroWelcome.cs index 5ae2158172..da44161507 100644 --- a/osu.Game/Screens/Menu/IntroWelcome.cs +++ b/osu.Game/Screens/Menu/IntroWelcome.cs @@ -21,7 +21,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.Menu { - public class IntroWelcome : IntroScreen + public partial class IntroWelcome : IntroScreen { protected override string BeatmapHash => "64e00d7022195959bfa3109d09c2e2276c8f12f486b91fcf6175583e973b48f2"; protected override string BeatmapFile => "welcome.osz"; @@ -103,7 +103,7 @@ namespace osu.Game.Screens.Menu } } - private class WelcomeIntroSequence : Container + private partial class WelcomeIntroSequence : Container { private Drawable welcomeText; private Container scaleContainer; diff --git a/osu.Game/Screens/Menu/LogoVisualisation.cs b/osu.Game/Screens/Menu/LogoVisualisation.cs index 4a20d7cb2b..5000a97b3d 100644 --- a/osu.Game/Screens/Menu/LogoVisualisation.cs +++ b/osu.Game/Screens/Menu/LogoVisualisation.cs @@ -24,7 +24,7 @@ namespace osu.Game.Screens.Menu /// /// A visualiser that reacts to music coming from beatmaps. /// - public class LogoVisualisation : Drawable + public partial class LogoVisualisation : Drawable { /// /// The number of bars to jump each update iteration. @@ -147,7 +147,7 @@ namespace osu.Game.Screens.Menu private void addAmplitudesFromSource(IHasAmplitudes source) { - if (source == null) throw new ArgumentNullException(nameof(source)); + ArgumentNullException.ThrowIfNull(source); var amplitudes = source.CurrentAmplitudes.FrequencyAmplitudes.Span; diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 0071ada05a..69b8596474 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -32,7 +32,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.Menu { - public class MainMenu : OsuScreen, IHandlePresentBeatmap, IKeyBindingHandler + public partial class MainMenu : OsuScreen, IHandlePresentBeatmap, IKeyBindingHandler { public const float FADE_IN_DURATION = 300; diff --git a/osu.Game/Screens/Menu/MainMenuButton.cs b/osu.Game/Screens/Menu/MainMenuButton.cs index f2b57b185e..cd3795711e 100644 --- a/osu.Game/Screens/Menu/MainMenuButton.cs +++ b/osu.Game/Screens/Menu/MainMenuButton.cs @@ -30,7 +30,7 @@ namespace osu.Game.Screens.Menu /// Button designed specifically for the osu!next main menu. /// In order to correctly flow, we have to use a negative margin on the parent container (due to the parallelogram shape). /// - public class MainMenuButton : BeatSyncedContainer, IStateful + public partial class MainMenuButton : BeatSyncedContainer, IStateful { public event Action StateChanged; diff --git a/osu.Game/Screens/Menu/MenuLogoVisualisation.cs b/osu.Game/Screens/Menu/MenuLogoVisualisation.cs index 4324f02c84..f4e992be9a 100644 --- a/osu.Game/Screens/Menu/MenuLogoVisualisation.cs +++ b/osu.Game/Screens/Menu/MenuLogoVisualisation.cs @@ -12,7 +12,7 @@ using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Screens.Menu { - internal class MenuLogoVisualisation : LogoVisualisation + internal partial class MenuLogoVisualisation : LogoVisualisation { private IBindable user; private Bindable skin; diff --git a/osu.Game/Screens/Menu/MenuSideFlashes.cs b/osu.Game/Screens/Menu/MenuSideFlashes.cs index 5214d87ee9..533c39826c 100644 --- a/osu.Game/Screens/Menu/MenuSideFlashes.cs +++ b/osu.Game/Screens/Menu/MenuSideFlashes.cs @@ -22,7 +22,7 @@ using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Screens.Menu { - public class MenuSideFlashes : BeatSyncedContainer + public partial class MenuSideFlashes : BeatSyncedContainer { private readonly IBindable beatmap = new Bindable(); diff --git a/osu.Game/Screens/Menu/OsuLogo.cs b/osu.Game/Screens/Menu/OsuLogo.cs index 3efd74d2c8..9430a1cda8 100644 --- a/osu.Game/Screens/Menu/OsuLogo.cs +++ b/osu.Game/Screens/Menu/OsuLogo.cs @@ -29,7 +29,7 @@ namespace osu.Game.Screens.Menu /// /// osu! logo and its attachments (pulsing, visualiser etc.) /// - public class OsuLogo : BeatSyncedContainer + public partial class OsuLogo : BeatSyncedContainer { public readonly Color4 OsuPink = Color4Extensions.FromHex(@"e967a1"); @@ -282,7 +282,7 @@ namespace osu.Game.Screens.Menu if (beatIndex < 0) return; - if (IsHovered) + if (Action != null && IsHovered) { this.Delay(early_activation).Schedule(() => { @@ -361,11 +361,11 @@ namespace osu.Game.Screens.Menu } } - public override bool HandlePositionalInput => base.HandlePositionalInput && Action != null && Alpha > 0.2f; + public override bool HandlePositionalInput => base.HandlePositionalInput && Alpha > 0.2f; protected override bool OnMouseDown(MouseDownEvent e) { - if (e.Button != MouseButton.Left) return false; + if (e.Button != MouseButton.Left) return true; logoBounceContainer.ScaleTo(0.9f, 1000, Easing.Out); return true; @@ -380,18 +380,21 @@ namespace osu.Game.Screens.Menu protected override bool OnClick(ClickEvent e) { - if (Action?.Invoke() ?? true) - sampleClick.Play(); - flashLayer.ClearTransforms(); flashLayer.Alpha = 0.4f; flashLayer.FadeOut(1500, Easing.OutExpo); + + if (Action?.Invoke() == true) + sampleClick.Play(); + return true; } protected override bool OnHover(HoverEvent e) { - logoHoverContainer.ScaleTo(1.1f, 500, Easing.OutElastic); + if (Action != null) + logoHoverContainer.ScaleTo(1.1f, 500, Easing.OutElastic); + return true; } diff --git a/osu.Game/Screens/Menu/SongTicker.cs b/osu.Game/Screens/Menu/SongTicker.cs index 6574c9a696..bac7e15461 100644 --- a/osu.Game/Screens/Menu/SongTicker.cs +++ b/osu.Game/Screens/Menu/SongTicker.cs @@ -15,7 +15,7 @@ using osu.Game.Beatmaps; namespace osu.Game.Screens.Menu { - public class SongTicker : Container + public partial class SongTicker : Container { private const int fade_duration = 800; diff --git a/osu.Game/Screens/Menu/StorageErrorDialog.cs b/osu.Game/Screens/Menu/StorageErrorDialog.cs index 28ef413179..ba05ad8b76 100644 --- a/osu.Game/Screens/Menu/StorageErrorDialog.cs +++ b/osu.Game/Screens/Menu/StorageErrorDialog.cs @@ -12,7 +12,7 @@ using osu.Game.Overlays.Dialog; namespace osu.Game.Screens.Menu { - public class StorageErrorDialog : PopupDialog + public partial class StorageErrorDialog : PopupDialog { [Resolved] private IDialogOverlay dialogOverlay { get; set; } diff --git a/osu.Game/Screens/OnlinePlay/Components/BeatmapTitle.cs b/osu.Game/Screens/OnlinePlay/Components/BeatmapTitle.cs index 39a887f820..ebcc08360e 100644 --- a/osu.Game/Screens/OnlinePlay/Components/BeatmapTitle.cs +++ b/osu.Game/Screens/OnlinePlay/Components/BeatmapTitle.cs @@ -13,7 +13,7 @@ using osu.Game.Online.Chat; namespace osu.Game.Screens.OnlinePlay.Components { - public class BeatmapTitle : OnlinePlayComposite + public partial class BeatmapTitle : OnlinePlayComposite { private readonly LinkFlowContainer textFlow; diff --git a/osu.Game/Screens/OnlinePlay/Components/DisableableTabControl.cs b/osu.Game/Screens/OnlinePlay/Components/DisableableTabControl.cs index 22839ab4d4..3f7f38f3bc 100644 --- a/osu.Game/Screens/OnlinePlay/Components/DisableableTabControl.cs +++ b/osu.Game/Screens/OnlinePlay/Components/DisableableTabControl.cs @@ -9,7 +9,7 @@ using osu.Framework.Input.Events; namespace osu.Game.Screens.OnlinePlay.Components { - public abstract class DisableableTabControl : TabControl + public abstract partial class DisableableTabControl : TabControl { public readonly BindableBool Enabled = new BindableBool(true); @@ -20,7 +20,7 @@ namespace osu.Game.Screens.OnlinePlay.Components base.AddTabItem(tab, addToDropdown); } - protected abstract class DisableableTabItem : TabItem + protected abstract partial class DisableableTabItem : TabItem { protected DisableableTabItem(T value) : base(value) diff --git a/osu.Game/Screens/OnlinePlay/Components/DrawableGameType.cs b/osu.Game/Screens/OnlinePlay/Components/DrawableGameType.cs index c97e52c247..77e461ce41 100644 --- a/osu.Game/Screens/OnlinePlay/Components/DrawableGameType.cs +++ b/osu.Game/Screens/OnlinePlay/Components/DrawableGameType.cs @@ -19,7 +19,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.OnlinePlay.Components { - public class DrawableGameType : CircularContainer, IHasTooltip + public partial class DrawableGameType : CircularContainer, IHasTooltip { private readonly MatchType type; @@ -132,7 +132,7 @@ namespace osu.Game.Screens.OnlinePlay.Components } } - private class VersusRow : FillFlowContainer + private partial class VersusRow : FillFlowContainer { public VersusRow(Color4 first, Color4 second, float size) { diff --git a/osu.Game/Screens/OnlinePlay/Components/ListingPollingComponent.cs b/osu.Game/Screens/OnlinePlay/Components/ListingPollingComponent.cs index 1ea84b60b9..c296e2a86b 100644 --- a/osu.Game/Screens/OnlinePlay/Components/ListingPollingComponent.cs +++ b/osu.Game/Screens/OnlinePlay/Components/ListingPollingComponent.cs @@ -15,7 +15,7 @@ namespace osu.Game.Screens.OnlinePlay.Components /// /// A that polls for the lounge listing. /// - public class ListingPollingComponent : RoomPollingComponent + public partial class ListingPollingComponent : RoomPollingComponent { public IBindable InitialRoomsReceived => initialRoomsReceived; private readonly Bindable initialRoomsReceived = new Bindable(); diff --git a/osu.Game/Screens/OnlinePlay/Components/MatchBeatmapDetailArea.cs b/osu.Game/Screens/OnlinePlay/Components/MatchBeatmapDetailArea.cs index 9a48769405..dec91d8a37 100644 --- a/osu.Game/Screens/OnlinePlay/Components/MatchBeatmapDetailArea.cs +++ b/osu.Game/Screens/OnlinePlay/Components/MatchBeatmapDetailArea.cs @@ -9,7 +9,7 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Graphics.UserInterface; +using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Online.Rooms; using osu.Game.Screens.OnlinePlay.Playlists; using osu.Game.Screens.Select; @@ -17,7 +17,7 @@ using osuTK; namespace osu.Game.Screens.OnlinePlay.Components { - public class MatchBeatmapDetailArea : BeatmapDetailArea + public partial class MatchBeatmapDetailArea : BeatmapDetailArea { public Action CreateNewItem; @@ -54,7 +54,7 @@ namespace osu.Game.Screens.OnlinePlay.Components }, new Drawable[] { - new TriangleButton + new RoundedButton { Text = "Add new playlist entry", RelativeSizeAxes = Axes.Both, diff --git a/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundScreen.cs b/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundScreen.cs index 8c65649cc6..014473dfee 100644 --- a/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundScreen.cs @@ -15,7 +15,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.OnlinePlay.Components { - public abstract class OnlinePlayBackgroundScreen : BackgroundScreen + public abstract partial class OnlinePlayBackgroundScreen : BackgroundScreen { private CancellationTokenSource? cancellationSource; private PlaylistItemBackground? background; diff --git a/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundSprite.cs b/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundSprite.cs index fe89eaf591..0d4cd30090 100644 --- a/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundSprite.cs +++ b/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundSprite.cs @@ -10,7 +10,7 @@ using osu.Game.Online.Rooms; namespace osu.Game.Screens.OnlinePlay.Components { - public class OnlinePlayBackgroundSprite : OnlinePlayComposite + public partial class OnlinePlayBackgroundSprite : OnlinePlayComposite { protected readonly BeatmapSetCoverType BeatmapSetCoverType; private UpdateableBeatmapBackgroundSprite sprite; diff --git a/osu.Game/Screens/OnlinePlay/Components/OverlinedHeader.cs b/osu.Game/Screens/OnlinePlay/Components/OverlinedHeader.cs index b953136fdd..0e2ce6703f 100644 --- a/osu.Game/Screens/OnlinePlay/Components/OverlinedHeader.cs +++ b/osu.Game/Screens/OnlinePlay/Components/OverlinedHeader.cs @@ -18,7 +18,7 @@ namespace osu.Game.Screens.OnlinePlay.Components /// /// A header used in the multiplayer interface which shows text / details beneath a line. /// - public class OverlinedHeader : OnlinePlayComposite + public partial class OverlinedHeader : OnlinePlayComposite { private bool showLine = true; diff --git a/osu.Game/Screens/OnlinePlay/Components/OverlinedPlaylistHeader.cs b/osu.Game/Screens/OnlinePlay/Components/OverlinedPlaylistHeader.cs index a268d4d917..f8dcd7b75d 100644 --- a/osu.Game/Screens/OnlinePlay/Components/OverlinedPlaylistHeader.cs +++ b/osu.Game/Screens/OnlinePlay/Components/OverlinedPlaylistHeader.cs @@ -7,7 +7,7 @@ using osu.Game.Online.Rooms; namespace osu.Game.Screens.OnlinePlay.Components { - public class OverlinedPlaylistHeader : OverlinedHeader + public partial class OverlinedPlaylistHeader : OverlinedHeader { public OverlinedPlaylistHeader() : base("Playlist") diff --git a/osu.Game/Screens/OnlinePlay/Components/ParticipantCountDisplay.cs b/osu.Game/Screens/OnlinePlay/Components/ParticipantCountDisplay.cs index 71b33bf247..9f7e700ab3 100644 --- a/osu.Game/Screens/OnlinePlay/Components/ParticipantCountDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Components/ParticipantCountDisplay.cs @@ -11,7 +11,7 @@ using osu.Game.Graphics.Sprites; namespace osu.Game.Screens.OnlinePlay.Components { - public class ParticipantCountDisplay : OnlinePlayComposite + public partial class ParticipantCountDisplay : OnlinePlayComposite { private const float text_size = 30; private const float transition_duration = 100; diff --git a/osu.Game/Screens/OnlinePlay/Components/ParticipantsDisplay.cs b/osu.Game/Screens/OnlinePlay/Components/ParticipantsDisplay.cs index c66ae8b6d5..4fdf41d0f7 100644 --- a/osu.Game/Screens/OnlinePlay/Components/ParticipantsDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Components/ParticipantsDisplay.cs @@ -10,7 +10,7 @@ using osu.Game.Graphics.Containers; namespace osu.Game.Screens.OnlinePlay.Components { - public class ParticipantsDisplay : OnlinePlayComposite + public partial class ParticipantsDisplay : OnlinePlayComposite { public Bindable Details = new Bindable(); diff --git a/osu.Game/Screens/OnlinePlay/Components/ParticipantsList.cs b/osu.Game/Screens/OnlinePlay/Components/ParticipantsList.cs index 2f38321e13..00f0889cc8 100644 --- a/osu.Game/Screens/OnlinePlay/Components/ParticipantsList.cs +++ b/osu.Game/Screens/OnlinePlay/Components/ParticipantsList.cs @@ -15,7 +15,7 @@ using osuTK; namespace osu.Game.Screens.OnlinePlay.Components { - public class ParticipantsList : OnlinePlayComposite + public partial class ParticipantsList : OnlinePlayComposite { public const float TILE_SIZE = 35; @@ -92,7 +92,7 @@ namespace osu.Game.Screens.OnlinePlay.Components }); } - private class UserTile : CompositeDrawable + private partial class UserTile : CompositeDrawable { public APIUser User { diff --git a/osu.Game/Screens/OnlinePlay/Components/PlaylistItemBackground.cs b/osu.Game/Screens/OnlinePlay/Components/PlaylistItemBackground.cs index d882b3d97f..997ba6b639 100644 --- a/osu.Game/Screens/OnlinePlay/Components/PlaylistItemBackground.cs +++ b/osu.Game/Screens/OnlinePlay/Components/PlaylistItemBackground.cs @@ -9,7 +9,7 @@ using osu.Game.Online.Rooms; namespace osu.Game.Screens.OnlinePlay.Components { - public class PlaylistItemBackground : Background + public partial class PlaylistItemBackground : Background { public readonly IBeatmapInfo? Beatmap; diff --git a/osu.Game/Screens/OnlinePlay/Components/ReadyButton.cs b/osu.Game/Screens/OnlinePlay/Components/ReadyButton.cs index 0871fc9a72..772c8c4278 100644 --- a/osu.Game/Screens/OnlinePlay/Components/ReadyButton.cs +++ b/osu.Game/Screens/OnlinePlay/Components/ReadyButton.cs @@ -7,13 +7,13 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics.Cursor; using osu.Framework.Localisation; -using osu.Game.Graphics.UserInterface; +using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Online; using osu.Game.Online.Rooms; namespace osu.Game.Screens.OnlinePlay.Components { - public abstract class ReadyButton : TriangleButton, IHasTooltip + public abstract partial class ReadyButton : RoundedButton, IHasTooltip { public new readonly BindableBool Enabled = new BindableBool(); diff --git a/osu.Game/Screens/OnlinePlay/Components/RoomLocalUserInfo.cs b/osu.Game/Screens/OnlinePlay/Components/RoomLocalUserInfo.cs index cc517ca080..0c3b53266c 100644 --- a/osu.Game/Screens/OnlinePlay/Components/RoomLocalUserInfo.cs +++ b/osu.Game/Screens/OnlinePlay/Components/RoomLocalUserInfo.cs @@ -12,7 +12,7 @@ using osu.Game.Graphics.Sprites; namespace osu.Game.Screens.OnlinePlay.Components { - public class RoomLocalUserInfo : OnlinePlayComposite + public partial class RoomLocalUserInfo : OnlinePlayComposite { private OsuSpriteText attemptDisplay; diff --git a/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs b/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs index 35dc251e4d..539d5b74b3 100644 --- a/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs +++ b/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs @@ -17,7 +17,7 @@ using osu.Game.Online.Rooms; namespace osu.Game.Screens.OnlinePlay.Components { - public class RoomManager : Component, IRoomManager + public partial class RoomManager : Component, IRoomManager { public event Action RoomsUpdated; diff --git a/osu.Game/Screens/OnlinePlay/Components/RoomPollingComponent.cs b/osu.Game/Screens/OnlinePlay/Components/RoomPollingComponent.cs index 039e1d92b7..395a77b9e6 100644 --- a/osu.Game/Screens/OnlinePlay/Components/RoomPollingComponent.cs +++ b/osu.Game/Screens/OnlinePlay/Components/RoomPollingComponent.cs @@ -9,7 +9,7 @@ using osu.Game.Online.API; namespace osu.Game.Screens.OnlinePlay.Components { - public abstract class RoomPollingComponent : PollingComponent + public abstract partial class RoomPollingComponent : PollingComponent { [Resolved] protected IAPIProvider API { get; private set; } diff --git a/osu.Game/Screens/OnlinePlay/Components/SelectionPollingComponent.cs b/osu.Game/Screens/OnlinePlay/Components/SelectionPollingComponent.cs index 3b8ba739d9..780ee29e41 100644 --- a/osu.Game/Screens/OnlinePlay/Components/SelectionPollingComponent.cs +++ b/osu.Game/Screens/OnlinePlay/Components/SelectionPollingComponent.cs @@ -11,7 +11,7 @@ namespace osu.Game.Screens.OnlinePlay.Components /// /// A that polls for the currently-selected room. /// - public class SelectionPollingComponent : RoomPollingComponent + public partial class SelectionPollingComponent : RoomPollingComponent { private readonly Room room; diff --git a/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs b/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs index b6ef080e44..93c8faf0b0 100644 --- a/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs @@ -17,7 +17,7 @@ using osuTK; namespace osu.Game.Screens.OnlinePlay.Components { - public class StarRatingRangeDisplay : OnlinePlayComposite + public partial class StarRatingRangeDisplay : OnlinePlayComposite { [Resolved] private OsuColour colours { get; set; } diff --git a/osu.Game/Screens/OnlinePlay/Components/StatusColouredContainer.cs b/osu.Game/Screens/OnlinePlay/Components/StatusColouredContainer.cs index 6122e7ec5e..ed39021a73 100644 --- a/osu.Game/Screens/OnlinePlay/Components/StatusColouredContainer.cs +++ b/osu.Game/Screens/OnlinePlay/Components/StatusColouredContainer.cs @@ -12,7 +12,7 @@ using osu.Game.Online.Rooms; namespace osu.Game.Screens.OnlinePlay.Components { - public class StatusColouredContainer : Container + public partial class StatusColouredContainer : Container { private readonly double transitionDuration; diff --git a/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylist.cs b/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylist.cs index ed554ebd34..8abdec9ade 100644 --- a/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylist.cs +++ b/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylist.cs @@ -20,7 +20,7 @@ namespace osu.Game.Screens.OnlinePlay /// /// A scrollable list which displays the s in a . /// - public class DrawableRoomPlaylist : OsuRearrangeableListContainer, IKeyBindingHandler + public partial class DrawableRoomPlaylist : OsuRearrangeableListContainer, IKeyBindingHandler { /// /// The currently-selected item. Selection is visually represented with a border. @@ -156,6 +156,8 @@ namespace osu.Game.Screens.OnlinePlay protected override FillFlowContainer> CreateListFillFlowContainer() => new FillFlowContainer> { + LayoutDuration = 200, + LayoutEasing = Easing.OutQuint, Spacing = new Vector2(0, 2) }; diff --git a/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs b/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs index bda616d5c3..3fab0fc180 100644 --- a/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs +++ b/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs @@ -42,7 +42,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.OnlinePlay { - public class DrawableRoomPlaylistItem : OsuRearrangeableListItem, IHasContextMenu + public partial class DrawableRoomPlaylistItem : OsuRearrangeableListItem, IHasContextMenu { public const float HEIGHT = 50; @@ -512,7 +512,7 @@ namespace osu.Game.Screens.OnlinePlay } } - public class PlaylistEditButton : GrayButton + public partial class PlaylistEditButton : GrayButton { public PlaylistEditButton() : base(FontAwesome.Solid.Edit) @@ -520,7 +520,7 @@ namespace osu.Game.Screens.OnlinePlay } } - public class PlaylistRemoveButton : GrayButton + public partial class PlaylistRemoveButton : GrayButton { public PlaylistRemoveButton() : base(FontAwesome.Solid.MinusSquare) @@ -528,7 +528,7 @@ namespace osu.Game.Screens.OnlinePlay } } - private sealed class PlaylistDownloadButton : BeatmapDownloadButton + private sealed partial class PlaylistDownloadButton : BeatmapDownloadButton { private readonly IBeatmapInfo beatmap; @@ -586,7 +586,7 @@ namespace osu.Game.Screens.OnlinePlay } // For now, this is the same implementation as in PanelBackground, but supports a beatmap info rather than a working beatmap - private class PanelBackground : Container // todo: should be a buffered container (https://github.com/ppy/osu-framework/issues/3222) + private partial class PanelBackground : Container // todo: should be a buffered container (https://github.com/ppy/osu-framework/issues/3222) { public readonly Bindable Beatmap = new Bindable(); @@ -641,7 +641,7 @@ namespace osu.Game.Screens.OnlinePlay } } - private class OwnerAvatar : UpdateableAvatar, IHasTooltip + private partial class OwnerAvatar : UpdateableAvatar, IHasTooltip { public OwnerAvatar() { @@ -654,7 +654,7 @@ namespace osu.Game.Screens.OnlinePlay public LocalisableString TooltipText => User == null ? string.Empty : $"queued by {User.Username}"; - private class TooltipArea : Component, IHasTooltip + private partial class TooltipArea : Component, IHasTooltip { private readonly OwnerAvatar avatar; diff --git a/osu.Game/Screens/OnlinePlay/FooterButtonFreeMods.cs b/osu.Game/Screens/OnlinePlay/FooterButtonFreeMods.cs index 9e589b362b..98f3df525d 100644 --- a/osu.Game/Screens/OnlinePlay/FooterButtonFreeMods.cs +++ b/osu.Game/Screens/OnlinePlay/FooterButtonFreeMods.cs @@ -17,7 +17,7 @@ using osuTK; namespace osu.Game.Screens.OnlinePlay { - public class FooterButtonFreeMods : FooterButton, IHasCurrentValue> + public partial class FooterButtonFreeMods : FooterButton, IHasCurrentValue> { public Bindable> Current { diff --git a/osu.Game/Screens/OnlinePlay/FreeModSelectOverlay.cs b/osu.Game/Screens/OnlinePlay/FreeModSelectOverlay.cs index 0f02692eda..6313d907a5 100644 --- a/osu.Game/Screens/OnlinePlay/FreeModSelectOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/FreeModSelectOverlay.cs @@ -14,7 +14,7 @@ using osu.Game.Rulesets.Mods; namespace osu.Game.Screens.OnlinePlay { - public class FreeModSelectOverlay : ModSelectOverlay + public partial class FreeModSelectOverlay : ModSelectOverlay { protected override bool ShowTotalMultiplier => false; diff --git a/osu.Game/Screens/OnlinePlay/Header.cs b/osu.Game/Screens/OnlinePlay/Header.cs index a9e9f046e2..4c4851c3ac 100644 --- a/osu.Game/Screens/OnlinePlay/Header.cs +++ b/osu.Game/Screens/OnlinePlay/Header.cs @@ -16,7 +16,7 @@ using osuTK; namespace osu.Game.Screens.OnlinePlay { - public class Header : Container + public partial class Header : Container { public const float HEIGHT = 80; @@ -44,7 +44,7 @@ namespace osu.Game.Screens.OnlinePlay private void updateSubScreenTitle() => title.Screen = stack.CurrentScreen as IOnlinePlaySubScreen; - private class MultiHeaderTitle : CompositeDrawable + private partial class MultiHeaderTitle : CompositeDrawable { private const float spacing = 6; diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs index 7e39a52c0a..8c85a8235c 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs @@ -29,7 +29,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.OnlinePlay.Lounge.Components { - public class DrawableRoom : CompositeDrawable + public partial class DrawableRoom : CompositeDrawable { protected const float CORNER_RADIUS = 10; private const float height = 100; @@ -311,7 +311,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components return pills; } - private class RoomNameText : OsuSpriteText + private partial class RoomNameText : OsuSpriteText { [Resolved(typeof(Room), nameof(Online.Rooms.Room.Name))] private Bindable name { get; set; } @@ -328,7 +328,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components } } - private class RoomStatusText : OnlinePlayComposite + private partial class RoomStatusText : OnlinePlayComposite { [Resolved] private OsuColour colours { get; set; } @@ -434,7 +434,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components } } - public class PasswordProtectedIcon : CompositeDrawable + public partial class PasswordProtectedIcon : CompositeDrawable { [BackgroundDependencyLoader] private void load(OsuColour colours) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoomParticipantsList.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoomParticipantsList.cs index 9e2bd41fd0..c31633eefc 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoomParticipantsList.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoomParticipantsList.cs @@ -4,6 +4,7 @@ #nullable disable using System.Collections.Specialized; +using System.Diagnostics; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -21,7 +22,7 @@ using osuTK; namespace osu.Game.Screens.OnlinePlay.Lounge.Components { - public class DrawableRoomParticipantsList : OnlinePlayComposite + public partial class DrawableRoomParticipantsList : OnlinePlayComposite { private const float avatar_size = 36; @@ -197,11 +198,15 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components switch (e.Action) { case NotifyCollectionChangedAction.Add: + Debug.Assert(e.NewItems != null); + foreach (var added in e.NewItems.OfType()) addUser(added); break; case NotifyCollectionChangedAction.Remove: + Debug.Assert(e.OldItems != null); + foreach (var removed in e.OldItems.OfType()) removeUser(removed); break; @@ -270,7 +275,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components } } - private class CircularAvatar : CompositeDrawable + private partial class CircularAvatar : CompositeDrawable { public APIUser User { @@ -302,7 +307,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components } } - public class HiddenUserCount : CompositeDrawable + public partial class HiddenUserCount : CompositeDrawable { public int Count { diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/EndDateInfo.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/EndDateInfo.cs index d951b42854..c25dd6f158 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/EndDateInfo.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/EndDateInfo.cs @@ -11,7 +11,7 @@ using osu.Game.Graphics; namespace osu.Game.Screens.OnlinePlay.Lounge.Components { - public class EndDateInfo : OnlinePlayComposite + public partial class EndDateInfo : OnlinePlayComposite { public EndDateInfo() { @@ -30,7 +30,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components }; } - private class EndDatePart : DrawableDate + private partial class EndDatePart : DrawableDate { public readonly IBindable EndDate = new Bindable(); diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/MatchTypePill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/MatchTypePill.cs index b2e527766a..f96d547747 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/MatchTypePill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/MatchTypePill.cs @@ -13,7 +13,7 @@ using osu.Game.Online.Rooms; namespace osu.Game.Screens.OnlinePlay.Lounge.Components { - public class MatchTypePill : OnlinePlayComposite + public partial class MatchTypePill : OnlinePlayComposite { private OsuTextFlowContainer textFlow; diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/PillContainer.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/PillContainer.cs index b17873b1c8..263261143d 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/PillContainer.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/PillContainer.cs @@ -13,7 +13,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components /// /// Displays contents in a "pill". /// - public class PillContainer : Container + public partial class PillContainer : Container { private const float padding = 8; diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs index 474463d5f1..81ba48d135 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs @@ -16,7 +16,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components /// /// A pill that displays the playlist item count. /// - public class PlaylistCountPill : OnlinePlayComposite + public partial class PlaylistCountPill : OnlinePlayComposite { private OsuTextFlowContainer count; diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/QueueModePill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/QueueModePill.cs index 85177ee32c..0175418a96 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/QueueModePill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/QueueModePill.cs @@ -13,7 +13,7 @@ using osu.Game.Online.Multiplayer; namespace osu.Game.Screens.OnlinePlay.Lounge.Components { - public class QueueModePill : OnlinePlayComposite + public partial class QueueModePill : OnlinePlayComposite { private OsuTextFlowContainer textFlow; diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RankRangePill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RankRangePill.cs index fa531a0d14..adfc44fbd4 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RankRangePill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RankRangePill.cs @@ -15,7 +15,7 @@ using osuTK; namespace osu.Game.Screens.OnlinePlay.Lounge.Components { - public class RankRangePill : MultiplayerRoomComposite + public partial class RankRangePill : MultiplayerRoomComposite { private OsuTextFlowContainer rankFlow; diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomSpecialCategoryPill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomSpecialCategoryPill.cs index 0f9bfb22e8..5d67a18d1f 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomSpecialCategoryPill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomSpecialCategoryPill.cs @@ -13,7 +13,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.OnlinePlay.Lounge.Components { - public class RoomSpecialCategoryPill : OnlinePlayComposite + public partial class RoomSpecialCategoryPill : OnlinePlayComposite { private SpriteText text; private PillContainer pill; diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs index f37ec9d9d4..201314851e 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs @@ -18,7 +18,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components /// /// A pill that displays the room's current status. /// - public class RoomStatusPill : OnlinePlayComposite + public partial class RoomStatusPill : OnlinePlayComposite { [Resolved] private OsuColour colours { get; set; } diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs index e6b1942506..ac6403bb34 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; using System.Collections.Specialized; +using System.Diagnostics; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -21,7 +22,7 @@ using osuTK; namespace osu.Game.Screens.OnlinePlay.Lounge.Components { - public class RoomsContainer : CompositeDrawable, IKeyBindingHandler + public partial class RoomsContainer : CompositeDrawable, IKeyBindingHandler { public readonly Bindable SelectedRoom = new Bindable(); public readonly Bindable Filter = new Bindable(); @@ -117,10 +118,14 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components switch (args.Action) { case NotifyCollectionChangedAction.Add: + Debug.Assert(args.NewItems != null); + addRooms(args.NewItems.Cast()); break; case NotifyCollectionChangedAction.Remove: + Debug.Assert(args.OldItems != null); + removeRooms(args.OldItems.Cast()); break; } diff --git a/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs index 8a2aeb9e5e..70e4b2a589 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs @@ -34,7 +34,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge /// /// A with lounge-specific interactions such as selection and hover sounds. /// - public class DrawableLoungeRoom : DrawableRoom, IFilterable, IHasContextMenu, IHasPopover, IKeyBindingHandler + public partial class DrawableLoungeRoom : DrawableRoom, IFilterable, IHasContextMenu, IHasPopover, IKeyBindingHandler { private const float transition_duration = 60; private const float selection_border_width = 4; @@ -180,7 +180,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge return true; } - public class PasswordEntryPopover : OsuPopover + public partial class PasswordEntryPopover : OsuPopover { private readonly Room room; @@ -197,7 +197,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge } private OsuPasswordTextBox passwordTextBox; - private TriangleButton joinButton; + private RoundedButton joinButton; private OsuSpriteText errorText; private Sample sampleJoinFail; @@ -226,7 +226,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge Width = 200, PlaceholderText = "password", }, - joinButton = new TriangleButton + joinButton = new RoundedButton { Width = 80, Text = "Join Room", diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeBackgroundScreen.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeBackgroundScreen.cs index 58ccb24f7a..b31c351b82 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/LoungeBackgroundScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeBackgroundScreen.cs @@ -5,13 +5,12 @@ using osu.Framework.Bindables; using osu.Framework.Screens; using osu.Game.Online.Rooms; using osu.Game.Screens.OnlinePlay.Components; -using PlaylistItem = osu.Game.Online.Rooms.PlaylistItem; namespace osu.Game.Screens.OnlinePlay.Lounge { - public class LoungeBackgroundScreen : OnlinePlayBackgroundScreen + public partial class LoungeBackgroundScreen : OnlinePlayBackgroundScreen { - public readonly Bindable SelectedRoom = new Bindable(); + public readonly Bindable SelectedRoom = new Bindable(); private readonly BindableList playlist = new BindableList(); public LoungeBackgroundScreen() @@ -20,7 +19,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge playlist.BindCollectionChanged((_, _) => PlaylistItem = playlist.GetCurrentItem()); } - private void onSelectedRoomChanged(ValueChangedEvent room) + private void onSelectedRoomChanged(ValueChangedEvent room) { if (room.OldValue != null) playlist.UnbindFrom(room.OldValue.Playlist); diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs index 09bc496da5..fc4a5357c6 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs @@ -35,7 +35,7 @@ using osuTK; namespace osu.Game.Screens.OnlinePlay.Lounge { [Cached] - public abstract class LoungeSubScreen : OnlinePlaySubScreen + public abstract partial class LoungeSubScreen : OnlinePlaySubScreen { public override string Title => "Lounge"; diff --git a/osu.Game/Screens/OnlinePlay/Match/Components/CreateRoomButton.cs b/osu.Game/Screens/OnlinePlay/Match/Components/CreateRoomButton.cs index 3d0c181d9d..0251dba6ce 100644 --- a/osu.Game/Screens/OnlinePlay/Match/Components/CreateRoomButton.cs +++ b/osu.Game/Screens/OnlinePlay/Match/Components/CreateRoomButton.cs @@ -10,13 +10,12 @@ using osu.Framework.Input.Events; namespace osu.Game.Screens.OnlinePlay.Match.Components { - public abstract class CreateRoomButton : PurpleTriangleButton, IKeyBindingHandler + public abstract partial class CreateRoomButton : PurpleRoundedButton, IKeyBindingHandler { [BackgroundDependencyLoader] private void load() { SpriteText.Font = SpriteText.Font.With(size: 14); - Triangles.TriangleScale = 1.5f; } public bool OnPressed(KeyBindingPressEvent e) diff --git a/osu.Game/Screens/OnlinePlay/Match/Components/MatchChatDisplay.cs b/osu.Game/Screens/OnlinePlay/Match/Components/MatchChatDisplay.cs index 880bba895a..55d39407b0 100644 --- a/osu.Game/Screens/OnlinePlay/Match/Components/MatchChatDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Match/Components/MatchChatDisplay.cs @@ -10,7 +10,7 @@ using osu.Game.Online.Rooms; namespace osu.Game.Screens.OnlinePlay.Match.Components { - public class MatchChatDisplay : StandAloneChatDisplay + public partial class MatchChatDisplay : StandAloneChatDisplay { private readonly IBindable channelId = new Bindable(); diff --git a/osu.Game/Screens/OnlinePlay/Match/Components/MatchLeaderboard.cs b/osu.Game/Screens/OnlinePlay/Match/Components/MatchLeaderboard.cs index ee5ee576d8..4627cd4072 100644 --- a/osu.Game/Screens/OnlinePlay/Match/Components/MatchLeaderboard.cs +++ b/osu.Game/Screens/OnlinePlay/Match/Components/MatchLeaderboard.cs @@ -11,7 +11,7 @@ using osu.Game.Online.Rooms; namespace osu.Game.Screens.OnlinePlay.Match.Components { - public class MatchLeaderboard : Leaderboard + public partial class MatchLeaderboard : Leaderboard { [Resolved(typeof(Room), nameof(Room.RoomID))] private Bindable roomId { get; set; } = null!; diff --git a/osu.Game/Screens/OnlinePlay/Match/Components/MatchLeaderboardScore.cs b/osu.Game/Screens/OnlinePlay/Match/Components/MatchLeaderboardScore.cs index 5bd8f9e066..fabebc3859 100644 --- a/osu.Game/Screens/OnlinePlay/Match/Components/MatchLeaderboardScore.cs +++ b/osu.Game/Screens/OnlinePlay/Match/Components/MatchLeaderboardScore.cs @@ -13,7 +13,7 @@ using osu.Game.Scoring; namespace osu.Game.Screens.OnlinePlay.Match.Components { - public class MatchLeaderboardScore : LeaderboardScore + public partial class MatchLeaderboardScore : LeaderboardScore { private readonly APIUserScoreAggregate score; diff --git a/osu.Game/Screens/OnlinePlay/Match/Components/MatchTypePicker.cs b/osu.Game/Screens/OnlinePlay/Match/Components/MatchTypePicker.cs index 91477879c6..995fce085e 100644 --- a/osu.Game/Screens/OnlinePlay/Match/Components/MatchTypePicker.cs +++ b/osu.Game/Screens/OnlinePlay/Match/Components/MatchTypePicker.cs @@ -17,7 +17,7 @@ using osuTK; namespace osu.Game.Screens.OnlinePlay.Match.Components { - public class MatchTypePicker : DisableableTabControl + public partial class MatchTypePicker : DisableableTabControl { private const float height = 40; private const float selection_width = 3; @@ -35,7 +35,7 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components AddItem(MatchType.TeamVersus); } - private class GameTypePickerItem : DisableableTabItem + private partial class GameTypePickerItem : DisableableTabItem { private const float transition_duration = 200; diff --git a/osu.Game/Screens/OnlinePlay/Match/Components/PurpleTriangleButton.cs b/osu.Game/Screens/OnlinePlay/Match/Components/PurpleRoundedButton.cs similarity index 63% rename from osu.Game/Screens/OnlinePlay/Match/Components/PurpleTriangleButton.cs rename to osu.Game/Screens/OnlinePlay/Match/Components/PurpleRoundedButton.cs index 5c751f238f..80469e8171 100644 --- a/osu.Game/Screens/OnlinePlay/Match/Components/PurpleTriangleButton.cs +++ b/osu.Game/Screens/OnlinePlay/Match/Components/PurpleRoundedButton.cs @@ -1,22 +1,18 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; -using osu.Game.Graphics.UserInterface; +using osu.Game.Graphics.UserInterfaceV2; namespace osu.Game.Screens.OnlinePlay.Match.Components { - public class PurpleTriangleButton : TriangleButton + public partial class PurpleRoundedButton : RoundedButton { [BackgroundDependencyLoader] private void load() { BackgroundColour = Color4Extensions.FromHex(@"593790"); - Triangles.ColourLight = Color4Extensions.FromHex(@"7247b6"); - Triangles.ColourDark = Color4Extensions.FromHex(@"593790"); } } } diff --git a/osu.Game/Screens/OnlinePlay/Match/Components/RoomAvailabilityPicker.cs b/osu.Game/Screens/OnlinePlay/Match/Components/RoomAvailabilityPicker.cs index 408742d8e1..85fac9228b 100644 --- a/osu.Game/Screens/OnlinePlay/Match/Components/RoomAvailabilityPicker.cs +++ b/osu.Game/Screens/OnlinePlay/Match/Components/RoomAvailabilityPicker.cs @@ -19,7 +19,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.OnlinePlay.Match.Components { - public class RoomAvailabilityPicker : DisableableTabControl + public partial class RoomAvailabilityPicker : DisableableTabControl { protected override TabItem CreateTabItem(RoomAvailability value) => new RoomAvailabilityPickerItem(value); protected override Dropdown CreateDropdown() => null; @@ -36,7 +36,7 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components AddItem(RoomAvailability.InviteOnly); } - private class RoomAvailabilityPickerItem : DisableableTabItem + private partial class RoomAvailabilityPickerItem : DisableableTabItem { private const float transition_duration = 200; diff --git a/osu.Game/Screens/OnlinePlay/Match/Components/RoomSettingsOverlay.cs b/osu.Game/Screens/OnlinePlay/Match/Components/RoomSettingsOverlay.cs index 71447b15e2..4d4fe4ea56 100644 --- a/osu.Game/Screens/OnlinePlay/Match/Components/RoomSettingsOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Match/Components/RoomSettingsOverlay.cs @@ -18,7 +18,7 @@ using osuTK; namespace osu.Game.Screens.OnlinePlay.Match.Components { - public abstract class RoomSettingsOverlay : FocusedOverlayContainer, IKeyBindingHandler + public abstract partial class RoomSettingsOverlay : FocusedOverlayContainer, IKeyBindingHandler { protected const float TRANSITION_DURATION = 350; protected const float FIELD_PADDING = 25; @@ -101,7 +101,7 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components /// use expanded overhanging content (like an 's dropdown), /// then the overhanging content will be correctly Z-ordered. /// - protected class SectionContainer : ReverseChildIDFillFlowContainer
+ protected partial class SectionContainer : ReverseChildIDFillFlowContainer
{ public SectionContainer() { @@ -113,7 +113,7 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components } } - protected class Section : Container + protected partial class Section : Container { private readonly Container content; diff --git a/osu.Game/Screens/OnlinePlay/Match/DrawableMatchRoom.cs b/osu.Game/Screens/OnlinePlay/Match/DrawableMatchRoom.cs index 7c444b9bbd..3bda93c909 100644 --- a/osu.Game/Screens/OnlinePlay/Match/DrawableMatchRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Match/DrawableMatchRoom.cs @@ -19,7 +19,7 @@ using osuTK; namespace osu.Game.Screens.OnlinePlay.Match { - public class DrawableMatchRoom : DrawableRoom + public partial class DrawableMatchRoom : DrawableRoom { public readonly IBindable SelectedItem = new Bindable(); public Action OnEdit; @@ -48,7 +48,7 @@ namespace osu.Game.Screens.OnlinePlay.Match { if (allowEdit) { - ButtonsContainer.Add(editButton = new PurpleTriangleButton + ButtonsContainer.Add(editButton = new PurpleRoundedButton { RelativeSizeAxes = Axes.Y, Size = new Vector2(100, 1), @@ -70,7 +70,7 @@ namespace osu.Game.Screens.OnlinePlay.Match protected override Drawable CreateBackground() => background = new BackgroundSprite(); - private class BackgroundSprite : UpdateableBeatmapBackgroundSprite + private partial class BackgroundSprite : UpdateableBeatmapBackgroundSprite { protected override double LoadDelay => 0; } diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomBackgroundScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomBackgroundScreen.cs index 74c37b865c..c9e51d376c 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomBackgroundScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomBackgroundScreen.cs @@ -9,7 +9,7 @@ using osu.Game.Screens.OnlinePlay.Components; namespace osu.Game.Screens.OnlinePlay.Match { - public class RoomBackgroundScreen : OnlinePlayBackgroundScreen + public partial class RoomBackgroundScreen : OnlinePlayBackgroundScreen { public readonly Bindable SelectedItem = new Bindable(); diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs index 00c819e5e4..6b68024393 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs @@ -35,7 +35,7 @@ using osu.Game.Screens.OnlinePlay.Multiplayer; namespace osu.Game.Screens.OnlinePlay.Match { [Cached(typeof(IPreviewTrackOwner))] - public abstract class RoomSubScreen : OnlinePlaySubScreen, IPreviewTrackOwner + public abstract partial class RoomSubScreen : OnlinePlaySubScreen, IPreviewTrackOwner { [Cached(typeof(IBindable))] public readonly Bindable SelectedItem = new Bindable(); @@ -517,7 +517,7 @@ namespace osu.Game.Screens.OnlinePlay.Match /// The room to change the settings of. protected abstract RoomSettingsOverlay CreateRoomSettingsOverlay(Room room); - public class UserModSelectButton : PurpleTriangleButton, IKeyBindingHandler + public partial class UserModSelectButton : PurpleRoundedButton, IKeyBindingHandler { public bool OnPressed(KeyBindingPressEvent e) { diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/CreateMultiplayerMatchButton.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/CreateMultiplayerMatchButton.cs index fd535f979d..7975597beb 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/CreateMultiplayerMatchButton.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/CreateMultiplayerMatchButton.cs @@ -10,7 +10,7 @@ using osu.Game.Screens.OnlinePlay.Match.Components; namespace osu.Game.Screens.OnlinePlay.Multiplayer { - public class CreateMultiplayerMatchButton : CreateRoomButton + public partial class CreateMultiplayerMatchButton : CreateRoomButton { private IBindable isConnected; private IBindable operationInProgress; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs index 270f15a98d..d003110039 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs @@ -16,7 +16,7 @@ using osu.Game.Screens.Play; namespace osu.Game.Screens.OnlinePlay.Multiplayer { - public class GameplayChatDisplay : MatchChatDisplay, IKeyBindingHandler + public partial class GameplayChatDisplay : MatchChatDisplay, IKeyBindingHandler { [Resolved(CanBeNull = true)] [CanBeNull] diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayMatchScoreDisplay.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayMatchScoreDisplay.cs index c7fb6a82d5..8c08390c73 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayMatchScoreDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayMatchScoreDisplay.cs @@ -10,7 +10,7 @@ using osuTK; namespace osu.Game.Screens.OnlinePlay.Multiplayer { - public class GameplayMatchScoreDisplay : MatchScoreDisplay + public partial class GameplayMatchScoreDisplay : MatchScoreDisplay { public Bindable Expanded = new Bindable(); diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MatchStartControl.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MatchStartControl.cs index f048ae59cd..44e18dd2bb 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MatchStartControl.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MatchStartControl.cs @@ -20,7 +20,7 @@ using osuTK; namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match { - public class MatchStartControl : MultiplayerRoomComposite + public partial class MatchStartControl : MultiplayerRoomComposite { [Resolved] private OngoingOperationTracker ongoingOperationTracker { get; set; } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerCountdownButton.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerCountdownButton.cs index cd94b47d9e..6dc343f00a 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerCountdownButton.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerCountdownButton.cs @@ -22,7 +22,7 @@ using osuTK; namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match { - public class MultiplayerCountdownButton : IconButton, IHasPopover + public partial class MultiplayerCountdownButton : IconButton, IHasPopover { private static readonly TimeSpan[] available_delays = { @@ -109,7 +109,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match foreach (var duration in available_delays) { - flow.Add(new OsuButton + flow.Add(new RoundedButton { RelativeSizeAxes = Axes.X, Text = $"Start match in {duration.Humanize()}", @@ -124,7 +124,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match if (multiplayerClient.Room?.ActiveCountdowns.Any(c => c is MatchStartCountdown) == true && multiplayerClient.IsHost) { - flow.Add(new OsuButton + flow.Add(new RoundedButton { RelativeSizeAxes = Axes.X, Text = "Stop countdown", diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchFooter.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchFooter.cs index c28bd4892a..fcb6480b58 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchFooter.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchFooter.cs @@ -8,7 +8,7 @@ using osu.Framework.Graphics.Containers; namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match { - public class MultiplayerMatchFooter : CompositeDrawable + public partial class MultiplayerMatchFooter : CompositeDrawable { private const float ready_button_width = 600; private const float spectate_button_width = 200; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs index bbdfed0a00..207b9c378b 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs @@ -16,6 +16,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Online.Multiplayer; using osu.Game.Online.Rooms; using osu.Game.Overlays; @@ -25,7 +26,7 @@ using Container = osu.Framework.Graphics.Containers.Container; namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match { - public class MultiplayerMatchSettingsOverlay : RoomSettingsOverlay + public partial class MultiplayerMatchSettingsOverlay : RoomSettingsOverlay { private MatchSettings settings = null!; @@ -50,7 +51,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match SettingsApplied = Hide }; - protected class MatchSettings : OnlinePlayComposite + protected partial class MatchSettings : OnlinePlayComposite { private const float disabled_alpha = 0.2f; @@ -64,7 +65,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match public OsuEnumDropdown QueueModeDropdown = null!; public OsuTextBox PasswordTextBox = null!; public OsuCheckbox AutoSkipCheckbox = null!; - public TriangleButton ApplyButton = null!; + public RoundedButton ApplyButton = null!; public OsuSpriteText ErrorText = null!; @@ -274,7 +275,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match RelativeSizeAxes = Axes.X, Height = DrawableRoomPlaylistItem.HEIGHT }, - new PurpleTriangleButton + new RoundedButton { RelativeSizeAxes = Axes.X, Height = 40, @@ -460,7 +461,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match }); } - public class CreateOrUpdateButton : TriangleButton + public partial class CreateOrUpdateButton : RoundedButton { [Resolved(typeof(Room), nameof(Room.RoomID))] private Bindable roomId { get; set; } = null!; @@ -474,9 +475,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match [BackgroundDependencyLoader] private void load(OsuColour colours) { - BackgroundColour = colours.Yellow; - Triangles.ColourLight = colours.YellowLight; - Triangles.ColourDark = colours.YellowDark; + BackgroundColour = colours.YellowDark; } } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerReadyButton.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerReadyButton.cs index b4ff34cbc2..1be573bdb8 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerReadyButton.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerReadyButton.cs @@ -12,16 +12,13 @@ using osu.Framework.Audio.Sample; using osu.Framework.Localisation; using osu.Framework.Threading; using osu.Game.Graphics; -using osu.Game.Graphics.Backgrounds; using osu.Game.Online.Multiplayer; using osu.Game.Screens.OnlinePlay.Components; namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match { - public class MultiplayerReadyButton : ReadyButton + public partial class MultiplayerReadyButton : ReadyButton { - public new Triangles Triangles => base.Triangles; - [Resolved] private MultiplayerClient multiplayerClient { get; set; } @@ -212,15 +209,11 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match void setYellow() { BackgroundColour = colours.YellowDark; - Triangles.ColourDark = colours.YellowDark; - Triangles.ColourLight = colours.Yellow; } void setGreen() { BackgroundColour = colours.Green; - Triangles.ColourDark = colours.Green; - Triangles.ColourLight = colours.GreenLight; } } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerSpectateButton.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerSpectateButton.cs index b55a7d0731..1d308ed39c 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerSpectateButton.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerSpectateButton.cs @@ -7,14 +7,13 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Graphics; -using osu.Game.Graphics.Backgrounds; -using osu.Game.Graphics.UserInterface; +using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Online.Multiplayer; using osuTK; namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match { - public class MultiplayerSpectateButton : MultiplayerRoomComposite + public partial class MultiplayerSpectateButton : MultiplayerRoomComposite { [Resolved] private OngoingOperationTracker ongoingOperationTracker { get; set; } @@ -24,11 +23,11 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match private IBindable operationInProgress; - private readonly ButtonWithTrianglesExposed button; + private readonly RoundedButton button; public MultiplayerSpectateButton() { - InternalChild = button = new ButtonWithTrianglesExposed + InternalChild = button = new RoundedButton { RelativeSizeAxes = Axes.Both, Size = Vector2.One, @@ -67,15 +66,11 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match default: button.Text = "Spectate"; button.BackgroundColour = colours.BlueDark; - button.Triangles.ColourDark = colours.BlueDarker; - button.Triangles.ColourLight = colours.Blue; break; case MultiplayerUserState.Spectating: button.Text = "Stop spectating"; button.BackgroundColour = colours.Gray4; - button.Triangles.ColourDark = colours.Gray5; - button.Triangles.ColourLight = colours.Gray6; break; } @@ -83,10 +78,5 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match && Client.Room.State != MultiplayerRoomState.Closed && !operationInProgress.Value; } - - private class ButtonWithTrianglesExposed : TriangleButton - { - public new Triangles Triangles => base.Triangles; - } } } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerHistoryList.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerHistoryList.cs index 3def73accb..a19f61787b 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerHistoryList.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerHistoryList.cs @@ -15,7 +15,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match.Playlist /// /// A historically-ordered list of s. /// - public class MultiplayerHistoryList : DrawableRoomPlaylist + public partial class MultiplayerHistoryList : DrawableRoomPlaylist { public MultiplayerHistoryList() { @@ -27,7 +27,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match.Playlist Spacing = new Vector2(0, 2) }; - private class HistoryFillFlowContainer : FillFlowContainer> + private partial class HistoryFillFlowContainer : FillFlowContainer> { public override IEnumerable FlowingChildren => base.FlowingChildren.OfType>().OrderByDescending(item => item.Model.PlayedAt); } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerPlaylist.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerPlaylist.cs index bc96bd61d7..2d08d8ecf6 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerPlaylist.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerPlaylist.cs @@ -17,7 +17,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match.Playlist /// /// The multiplayer playlist, containing lists to show the items from a in both gameplay-order and historical-order. /// - public class MultiplayerPlaylist : MultiplayerRoomComposite + public partial class MultiplayerPlaylist : MultiplayerRoomComposite { public readonly Bindable DisplayMode = new Bindable(); diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerPlaylistTabControl.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerPlaylistTabControl.cs index f7abc91227..a5589c48b9 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerPlaylistTabControl.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerPlaylistTabControl.cs @@ -10,7 +10,7 @@ using osu.Game.Online.Rooms; namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match.Playlist { - public class MultiplayerPlaylistTabControl : OsuTabControl + public partial class MultiplayerPlaylistTabControl : OsuTabControl { public readonly IBindableList QueueItems = new BindableList(); @@ -22,7 +22,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match.Playlist return base.CreateTabItem(value); } - private class QueueTabItem : OsuTabItem + private partial class QueueTabItem : OsuTabItem { public readonly IBindableList QueueItems = new BindableList(); diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerQueueList.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerQueueList.cs index ba6b482729..77d82c4347 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerQueueList.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerQueueList.cs @@ -19,7 +19,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match.Playlist /// /// A gameplay-ordered list of s. /// - public class MultiplayerQueueList : DrawableRoomPlaylist + public partial class MultiplayerQueueList : DrawableRoomPlaylist { public MultiplayerQueueList() { @@ -33,7 +33,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match.Playlist protected override DrawableRoomPlaylistItem CreateDrawablePlaylistItem(PlaylistItem item) => new QueuePlaylistItem(item); - private class QueueFillFlowContainer : FillFlowContainer> + private partial class QueueFillFlowContainer : FillFlowContainer> { [Resolved(typeof(Room), nameof(Room.Playlist))] private BindableList roomPlaylist { get; set; } @@ -47,7 +47,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match.Playlist public override IEnumerable FlowingChildren => base.FlowingChildren.OfType>().OrderBy(item => item.Model.PlaylistOrder); } - private class QueuePlaylistItem : DrawableRoomPlaylistItem + private partial class QueuePlaylistItem : DrawableRoomPlaylistItem { [Resolved] private IAPIProvider api { get; set; } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Multiplayer.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Multiplayer.cs index 03a2f00c0d..164d1c9a4b 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Multiplayer.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Multiplayer.cs @@ -13,7 +13,7 @@ using osu.Game.Screens.OnlinePlay.Lounge; namespace osu.Game.Screens.OnlinePlay.Multiplayer { - public class Multiplayer : OnlinePlayScreen + public partial class Multiplayer : OnlinePlayScreen { [Resolved] private MultiplayerClient client { get; set; } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs index 8206d4b64d..dd4f35cdd4 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs @@ -23,7 +23,7 @@ using osu.Game.Screens.OnlinePlay.Match; namespace osu.Game.Screens.OnlinePlay.Multiplayer { - public class MultiplayerLoungeSubScreen : LoungeSubScreen + public partial class MultiplayerLoungeSubScreen : LoungeSubScreen { [Resolved] private IAPIProvider api { get; set; } @@ -90,7 +90,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer base.OpenNewRoom(room); } - private class MultiplayerListingPollingComponent : ListingPollingComponent + private partial class MultiplayerListingPollingComponent : ListingPollingComponent { [Resolved] private MultiplayerClient client { get; set; } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSongSelect.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSongSelect.cs index 3fe236bd7a..873a1b0d50 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSongSelect.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSongSelect.cs @@ -16,7 +16,7 @@ using osu.Game.Screens.Select; namespace osu.Game.Screens.OnlinePlay.Multiplayer { - public class MultiplayerMatchSongSelect : OnlinePlaySongSelect + public partial class MultiplayerMatchSongSelect : OnlinePlaySongSelect { [Resolved] private MultiplayerClient client { get; set; } = null!; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs index db752f2b42..a36c7e801e 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs @@ -38,7 +38,7 @@ using ParticipantsList = osu.Game.Screens.OnlinePlay.Multiplayer.Participants.Pa namespace osu.Game.Screens.OnlinePlay.Multiplayer { [Cached] - public class MultiplayerMatchSubScreen : RoomSubScreen, IHandlePresentBeatmap + public partial class MultiplayerMatchSubScreen : RoomSubScreen, IHandlePresentBeatmap { public override string Title { get; } @@ -430,7 +430,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer modSettingChangeTracker?.Dispose(); } - public class AddItemButton : PurpleTriangleButton + public partial class AddItemButton : PurpleRoundedButton { } } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs index a2c43898f7..7b448e4b5c 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs @@ -22,7 +22,7 @@ using osu.Game.Users; namespace osu.Game.Screens.OnlinePlay.Multiplayer { - public class MultiplayerPlayer : RoomSubmittingPlayer + public partial class MultiplayerPlayer : RoomSubmittingPlayer { protected override bool PauseOnFocusLost => false; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayerLoader.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayerLoader.cs index f79af664d8..f682508319 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayerLoader.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayerLoader.cs @@ -13,7 +13,7 @@ using osu.Game.Screens.Play; namespace osu.Game.Screens.OnlinePlay.Multiplayer { - public class MultiplayerPlayerLoader : PlayerLoader + public partial class MultiplayerPlayerLoader : PlayerLoader { public bool GameplayPassed => player?.GameplayState.HasPassed == true; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerResultsScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerResultsScreen.cs index d98b837883..de19d3a0e9 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerResultsScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerResultsScreen.cs @@ -9,7 +9,7 @@ using osu.Game.Screens.OnlinePlay.Playlists; namespace osu.Game.Screens.OnlinePlay.Multiplayer { - public class MultiplayerResultsScreen : PlaylistsResultsScreen + public partial class MultiplayerResultsScreen : PlaylistsResultsScreen { public MultiplayerResultsScreen(ScoreInfo score, long roomId, PlaylistItem playlistItem) : base(score, roomId, playlistItem, false, false) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomComposite.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomComposite.cs index 5a297f18db..ee5c84bf40 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomComposite.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomComposite.cs @@ -10,7 +10,7 @@ using osu.Game.Online.Rooms; namespace osu.Game.Screens.OnlinePlay.Multiplayer { - public abstract class MultiplayerRoomComposite : OnlinePlayComposite + public abstract partial class MultiplayerRoomComposite : OnlinePlayComposite { [CanBeNull] protected MultiplayerRoom Room => Client.Room; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs index 7e83d72c77..5f51ccc8d4 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs @@ -15,7 +15,7 @@ using osu.Game.Screens.OnlinePlay.Components; namespace osu.Game.Screens.OnlinePlay.Multiplayer { - public class MultiplayerRoomManager : RoomManager + public partial class MultiplayerRoomManager : RoomManager { [Resolved] private MultiplayerClient multiplayerClient { get; set; } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomSounds.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomSounds.cs index 1aafcea20c..90595bc33b 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomSounds.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomSounds.cs @@ -12,7 +12,7 @@ using osu.Game.Online.Multiplayer; namespace osu.Game.Screens.OnlinePlay.Multiplayer { - public class MultiplayerRoomSounds : MultiplayerRoomComposite + public partial class MultiplayerRoomSounds : MultiplayerRoomComposite { private Sample hostChangedSample; private Sample userJoinedSample; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerTeamResultsScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerTeamResultsScreen.cs index 6fbed03e44..a8c513603c 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerTeamResultsScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerTeamResultsScreen.cs @@ -24,7 +24,7 @@ using osuTK; namespace osu.Game.Screens.OnlinePlay.Multiplayer { - public class MultiplayerTeamResultsScreen : MultiplayerResultsScreen + public partial class MultiplayerTeamResultsScreen : MultiplayerResultsScreen { private readonly SortedDictionary teamScores; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs index 3ef2f033b0..c79c210e30 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs @@ -30,7 +30,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants { - public class ParticipantPanel : MultiplayerRoomComposite, IHasContextMenu + public partial class ParticipantPanel : MultiplayerRoomComposite, IHasContextMenu { public readonly MultiplayerRoomUser User; @@ -250,7 +250,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants } } - public class KickButton : IconButton + public partial class KickButton : IconButton { public KickButton() { diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantsList.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantsList.cs index 7c93c6084e..6a7a3758c3 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantsList.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantsList.cs @@ -13,7 +13,7 @@ using osuTK; namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants { - public class ParticipantsList : MultiplayerRoomComposite + public partial class ParticipantsList : MultiplayerRoomComposite { private FillFlowContainer panels; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantsListHeader.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantsListHeader.cs index b0acda03df..7f4e3360e4 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantsListHeader.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantsListHeader.cs @@ -10,7 +10,7 @@ using osu.Game.Screens.OnlinePlay.Components; namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants { - public class ParticipantsListHeader : OverlinedHeader + public partial class ParticipantsListHeader : OverlinedHeader { [Resolved] private MultiplayerClient client { get; set; } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/StateDisplay.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/StateDisplay.cs index ecef7509d9..bfdc0c02ac 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/StateDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/StateDisplay.cs @@ -18,7 +18,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants { - public class StateDisplay : CompositeDrawable + public partial class StateDisplay : CompositeDrawable { private const double fade_time = 50; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/TeamDisplay.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/TeamDisplay.cs index 5500d96eea..fe57ad26a5 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/TeamDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/TeamDisplay.cs @@ -20,7 +20,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants { - internal class TeamDisplay : MultiplayerRoomComposite + internal partial class TeamDisplay : MultiplayerRoomComposite { private readonly MultiplayerRoomUser user; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorLeaderboard.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorLeaderboard.cs index 4e9ab07e4c..ed92b719fc 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorLeaderboard.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorLeaderboard.cs @@ -8,7 +8,7 @@ using osu.Game.Screens.Play.HUD; namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate { - public class MultiSpectatorLeaderboard : MultiplayerGameplayLeaderboard + public partial class MultiSpectatorLeaderboard : MultiplayerGameplayLeaderboard { public MultiSpectatorLeaderboard(MultiplayerRoomUser[] users) : base(users) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs index 6e939c3916..930bea4497 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs @@ -7,13 +7,14 @@ using osu.Framework.Audio; using osu.Game.Beatmaps; using osu.Game.Scoring; using osu.Game.Screens.Play; +using osu.Game.Screens.Ranking; namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate { /// /// A single spectated player within a . /// - public class MultiSpectatorPlayer : SpectatorPlayer + public partial class MultiSpectatorPlayer : SpectatorPlayer { /// /// All adjustments applied to the clock of this which come from mods. @@ -70,5 +71,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate clockAdjustmentsFromMods.BindAdjustments(gameplayClockContainer.AdjustmentsFromMods); return gameplayClockContainer; } + + protected override ResultsScreen CreateResults(ScoreInfo score) => new MultiSpectatorResultsScreen(score); } } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayerLoader.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayerLoader.cs index 36a6487289..eb55b0d18a 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayerLoader.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayerLoader.cs @@ -15,7 +15,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate /// /// Used to load a single in a . /// - public class MultiSpectatorPlayerLoader : SpectatorPlayerLoader + public partial class MultiSpectatorPlayerLoader : SpectatorPlayerLoader { public MultiSpectatorPlayerLoader([NotNull] Score score, [NotNull] Func createPlayer) : base(score, createPlayer) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorResultsScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorResultsScreen.cs new file mode 100644 index 0000000000..fe3f02466d --- /dev/null +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorResultsScreen.cs @@ -0,0 +1,25 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +#nullable disable + +using System; +using System.Collections.Generic; +using osu.Game.Online.API; +using osu.Game.Scoring; +using osu.Game.Screens.Play; + +namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate +{ + public partial class MultiSpectatorResultsScreen : SpectatorResultsScreen + { + public MultiSpectatorResultsScreen(ScoreInfo score) + : base(score) + { + } + + protected override APIRequest FetchScores(Action> scoresCallback) => null; + + protected override APIRequest FetchNextPage(int direction, Action> scoresCallback) => null; + } +} diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs index 1fd04d35f8..2d2aa0f1d5 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs @@ -23,7 +23,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate /// /// A that spectates multiple users in a match. /// - public class MultiSpectatorScreen : SpectatorScreen + public partial class MultiSpectatorScreen : SpectatorScreen { // Isolates beatmap/ruleset to this screen. public override bool DisallowExternalBeatmapRulesetChanges => true; @@ -34,7 +34,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate /// /// Whether all spectating players have finished loading. /// - public bool AllPlayersLoaded => instances.All(p => p?.PlayerLoaded == true); + public bool AllPlayersLoaded => instances.All(p => p.PlayerLoaded); protected override UserActivity InitialActivity => new UserActivity.SpectatingMultiplayerGame(Beatmap.Value.BeatmapInfo, Ruleset.Value); @@ -171,9 +171,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate if (!isCandidateAudioSource(currentAudioSource?.SpectatorPlayerClock)) { - currentAudioSource = instances.Where(i => isCandidateAudioSource(i.SpectatorPlayerClock)) - .OrderBy(i => Math.Abs(i.SpectatorPlayerClock.CurrentTime - syncManager.CurrentMasterTime)) - .FirstOrDefault(); + currentAudioSource = instances.Where(i => isCandidateAudioSource(i.SpectatorPlayerClock)).MinBy(i => Math.Abs(i.SpectatorPlayerClock.CurrentTime - syncManager.CurrentMasterTime)); // Only bind adjustments if there's actually a valid source, else just use the previous ones to ensure no sudden changes to audio. if (currentAudioSource != null) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/PlayerArea.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/PlayerArea.cs index 96f134568d..dc4a2df9d8 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/PlayerArea.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/PlayerArea.cs @@ -20,7 +20,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate /// /// Provides an area for and manages the hierarchy of a spectated player within a . /// - public class PlayerArea : CompositeDrawable + public partial class PlayerArea : CompositeDrawable { /// /// Raised after is called on . @@ -131,7 +131,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate /// /// Isolates each player instance from the game-wide ruleset/beatmap/mods (to allow for different players having different settings). /// - private class PlayerIsolationContainer : Container + private partial class PlayerIsolationContainer : Container { [Cached] private readonly Bindable ruleset = new Bindable(); diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/PlayerGrid_Cell.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/PlayerGrid_Cell.cs index ee213f7be1..4a8b8f49e1 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/PlayerGrid_Cell.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/PlayerGrid_Cell.cs @@ -17,7 +17,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate /// /// A cell of the grid. Contains the content and tracks to the linked facade. /// - private class Cell : CompositeDrawable + private partial class Cell : CompositeDrawable { /// /// The index of the original facade of this cell. diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/PlayerGrid_Facade.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/PlayerGrid_Facade.cs index f7b8d48d0a..2f4ed35392 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/PlayerGrid_Facade.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/PlayerGrid_Facade.cs @@ -12,7 +12,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate /// /// A facade of the grid which is used as a dummy object to store the required position/size of cells. /// - private class Facade : Drawable + private partial class Facade : Drawable { public Facade() { diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/SpectatorSyncManager.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/SpectatorSyncManager.cs index 8d087aa25c..615c0d7c2b 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/SpectatorSyncManager.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/SpectatorSyncManager.cs @@ -13,7 +13,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate /// /// Manages the synchronisation between one or more s in relation to a master clock. /// - public class SpectatorSyncManager : Component + public partial class SpectatorSyncManager : Component { /// /// The offset from the master clock to which player clocks should remain within to be considered in-sync. diff --git a/osu.Game/Screens/OnlinePlay/OngoingOperationTracker.cs b/osu.Game/Screens/OnlinePlay/OngoingOperationTracker.cs index c87cf32c73..7f73d6655f 100644 --- a/osu.Game/Screens/OnlinePlay/OngoingOperationTracker.cs +++ b/osu.Game/Screens/OnlinePlay/OngoingOperationTracker.cs @@ -13,7 +13,7 @@ namespace osu.Game.Screens.OnlinePlay /// Utility class to track ongoing online operations' progress. /// Can be used to disable interactivity while waiting for a response from online sources. /// - public class OngoingOperationTracker : Component + public partial class OngoingOperationTracker : Component { /// /// Whether there is an online operation in progress. diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlayComposite.cs b/osu.Game/Screens/OnlinePlay/OnlinePlayComposite.cs index 50ad3228e5..ff536a65c4 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlayComposite.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlayComposite.cs @@ -17,7 +17,7 @@ namespace osu.Game.Screens.OnlinePlay /// /// A that exposes bindables for properties. /// - public class OnlinePlayComposite : CompositeDrawable + public partial class OnlinePlayComposite : CompositeDrawable { [Resolved(typeof(Room))] protected Bindable RoomID { get; private set; } diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs index 7e5d90bd4f..3d80248306 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs @@ -21,7 +21,7 @@ using osu.Game.Users; namespace osu.Game.Screens.OnlinePlay { [Cached] - public abstract class OnlinePlayScreen : OsuScreen, IHasSubScreenStack + public abstract partial class OnlinePlayScreen : OsuScreen, IHasSubScreenStack { [Cached] protected readonly OverlayColourProvider ColourProvider = new OverlayColourProvider(OverlayColourScheme.Plum); @@ -148,9 +148,14 @@ namespace osu.Game.Screens.OnlinePlay public override bool OnExiting(ScreenExitEvent e) { - var subScreen = screenStack.CurrentScreen as Drawable; - if (subScreen?.IsLoaded == true && screenStack.CurrentScreen.OnExiting(e)) - return true; + while (screenStack.CurrentScreen != null && screenStack.CurrentScreen is not LoungeSubScreen) + { + var subScreen = (Screen)screenStack.CurrentScreen; + if (subScreen.IsLoaded && subScreen.OnExiting(e)) + return true; + + subScreen.Exit(); + } RoomManager.PartRoom(); @@ -217,7 +222,7 @@ namespace osu.Game.Screens.OnlinePlay protected abstract LoungeSubScreen CreateLounge(); - private class MultiplayerWaveContainer : WaveContainer + private partial class MultiplayerWaveContainer : WaveContainer { protected override bool StartHidden => true; diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlaySongSelect.cs b/osu.Game/Screens/OnlinePlay/OnlinePlaySongSelect.cs index ea20270c1e..b9d8912170 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlaySongSelect.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlaySongSelect.cs @@ -24,7 +24,7 @@ using osu.Game.Utils; namespace osu.Game.Screens.OnlinePlay { - public abstract class OnlinePlaySongSelect : SongSelect, IOnlinePlaySubScreen + public abstract partial class OnlinePlaySongSelect : SongSelect, IOnlinePlaySubScreen { public string ShortTitle => "song selection"; diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreen.cs b/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreen.cs index 5c0a158c97..c7b32131cf 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreen.cs @@ -9,7 +9,7 @@ using osu.Framework.Screens; namespace osu.Game.Screens.OnlinePlay { - public abstract class OnlinePlaySubScreen : OsuScreen, IOnlinePlaySubScreen + public abstract partial class OnlinePlaySubScreen : OsuScreen, IOnlinePlaySubScreen { public override bool DisallowExternalBeatmapRulesetChanges => false; diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreenStack.cs b/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreenStack.cs index ae6988f0d6..7ecb7d954e 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreenStack.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreenStack.cs @@ -7,7 +7,7 @@ using osu.Framework.Screens; namespace osu.Game.Screens.OnlinePlay { - public class OnlinePlaySubScreenStack : OsuScreenStack + public partial class OnlinePlaySubScreenStack : OsuScreenStack { protected override void ScreenChanged(IScreen prev, IScreen next) { diff --git a/osu.Game/Screens/OnlinePlay/Playlists/CreatePlaylistsRoomButton.cs b/osu.Game/Screens/OnlinePlay/Playlists/CreatePlaylistsRoomButton.cs index 8cdae954ce..9507169e0f 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/CreatePlaylistsRoomButton.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/CreatePlaylistsRoomButton.cs @@ -8,7 +8,7 @@ using osu.Game.Screens.OnlinePlay.Match.Components; namespace osu.Game.Screens.OnlinePlay.Playlists { - public class CreatePlaylistsRoomButton : CreateRoomButton + public partial class CreatePlaylistsRoomButton : CreateRoomButton { [BackgroundDependencyLoader] private void load() diff --git a/osu.Game/Screens/OnlinePlay/Playlists/Playlists.cs b/osu.Game/Screens/OnlinePlay/Playlists/Playlists.cs index b84079b955..f9324840dc 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/Playlists.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/Playlists.cs @@ -7,7 +7,7 @@ using osu.Game.Screens.OnlinePlay.Lounge; namespace osu.Game.Screens.OnlinePlay.Playlists { - public class Playlists : OnlinePlayScreen + public partial class Playlists : OnlinePlayScreen { protected override string ScreenTitle => "Playlists"; diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsLoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsLoungeSubScreen.cs index 0827e2031d..e1d747c3b0 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsLoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsLoungeSubScreen.cs @@ -19,7 +19,7 @@ using osu.Game.Screens.OnlinePlay.Match; namespace osu.Game.Screens.OnlinePlay.Playlists { - public class PlaylistsLoungeSubScreen : LoungeSubScreen + public partial class PlaylistsLoungeSubScreen : LoungeSubScreen { [Resolved] private IAPIProvider api { get; set; } diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsPlayer.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsPlayer.cs index 2444729118..0c25a32259 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsPlayer.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsPlayer.cs @@ -21,7 +21,7 @@ using osu.Game.Users; namespace osu.Game.Screens.OnlinePlay.Playlists { - public class PlaylistsPlayer : RoomSubmittingPlayer + public partial class PlaylistsPlayer : RoomSubmittingPlayer { public Action Exited; diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsReadyButton.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsReadyButton.cs index b8ab514721..91a3edbea3 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsReadyButton.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsReadyButton.cs @@ -15,7 +15,7 @@ using osu.Game.Screens.OnlinePlay.Components; namespace osu.Game.Screens.OnlinePlay.Playlists { - public class PlaylistsReadyButton : ReadyButton + public partial class PlaylistsReadyButton : ReadyButton { [Resolved(typeof(Room), nameof(Room.EndDate))] private Bindable endDate { get; set; } @@ -38,8 +38,6 @@ namespace osu.Game.Screens.OnlinePlay.Playlists private void load(OsuColour colours) { BackgroundColour = colours.Green; - Triangles.ColourDark = colours.Green; - Triangles.ColourLight = colours.GreenLight; } private bool hasRemainingAttempts = true; diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsResultsScreen.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsResultsScreen.cs index 27193d3cb6..d40d43cd54 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsResultsScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsResultsScreen.cs @@ -20,7 +20,7 @@ using osu.Game.Screens.Ranking; namespace osu.Game.Screens.OnlinePlay.Playlists { - public class PlaylistsResultsScreen : ResultsScreen + public partial class PlaylistsResultsScreen : ResultsScreen { private readonly long roomId; private readonly PlaylistItem playlistItem; @@ -235,7 +235,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists } } - private class PanelListLoadingSpinner : LoadingSpinner + private partial class PanelListLoadingSpinner : LoadingSpinner { private readonly ScorePanelList list; diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomFooter.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomFooter.cs index b1b400713f..5161de5f64 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomFooter.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomFooter.cs @@ -10,7 +10,7 @@ using osuTK; namespace osu.Game.Screens.OnlinePlay.Playlists { - public class PlaylistsRoomFooter : CompositeDrawable + public partial class PlaylistsRoomFooter : CompositeDrawable { public Action OnStart; diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSettingsOverlay.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSettingsOverlay.cs index cd52981528..e93f56c2e2 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSettingsOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSettingsOverlay.cs @@ -16,6 +16,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Online.API; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Rooms; @@ -25,7 +26,7 @@ using osuTK; namespace osu.Game.Screens.OnlinePlay.Playlists { - public class PlaylistsRoomSettingsOverlay : RoomSettingsOverlay + public partial class PlaylistsRoomSettingsOverlay : RoomSettingsOverlay { public Action? EditPlaylist; @@ -49,7 +50,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists EditPlaylist = () => EditPlaylist?.Invoke() }; - protected class MatchSettings : OnlinePlayComposite + protected partial class MatchSettings : OnlinePlayComposite { private const float disabled_alpha = 0.2f; @@ -58,7 +59,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists public OsuTextBox NameField = null!, MaxParticipantsField = null!, MaxAttemptsField = null!; public OsuDropdown DurationField = null!; public RoomAvailabilityPicker AvailabilityPicker = null!; - public TriangleButton ApplyButton = null!; + public RoundedButton ApplyButton = null!; public bool IsLoading => loadingLayer.State.Value == Visibility.Visible; @@ -68,7 +69,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists private DrawableRoomPlaylist playlist = null!; private OsuSpriteText playlistLength = null!; - private PurpleTriangleButton editPlaylistButton = null!; + private PurpleRoundedButton editPlaylistButton = null!; [Resolved] private IRoomManager? manager { get; set; } @@ -222,7 +223,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists }, new Drawable[] { - editPlaylistButton = new PurpleTriangleButton + editPlaylistButton = new PurpleRoundedButton { RelativeSizeAxes = Axes.X, Height = 40, @@ -348,7 +349,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists public void SelectBeatmap() => editPlaylistButton.TriggerClick(); - private void onPlaylistChanged(object sender, NotifyCollectionChangedEventArgs e) => + private void onPlaylistChanged(object? sender, NotifyCollectionChangedEventArgs e) => playlistLength.Text = $"Length: {Playlist.GetTotalDuration()}"; private bool hasValidSettings => RoomID.Value == null && NameField.Text.Length > 0 && Playlist.Count > 0; @@ -414,7 +415,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists } } - public class CreateRoomButton : TriangleButton + public partial class CreateRoomButton : RoundedButton { public CreateRoomButton() { @@ -424,13 +425,11 @@ namespace osu.Game.Screens.OnlinePlay.Playlists [BackgroundDependencyLoader] private void load(OsuColour colours) { - BackgroundColour = colours.Yellow; - Triangles.ColourLight = colours.YellowLight; - Triangles.ColourDark = colours.YellowDark; + BackgroundColour = colours.YellowDark; } } - private class DurationDropdown : OsuDropdown + private partial class DurationDropdown : OsuDropdown { public DurationDropdown() { diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSettingsPlaylist.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSettingsPlaylist.cs index 80f38d0cd8..736f09584b 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSettingsPlaylist.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSettingsPlaylist.cs @@ -11,7 +11,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists /// /// A which is displayed during the setup stage of a playlists room. /// - public class PlaylistsRoomSettingsPlaylist : DrawableRoomPlaylist + public partial class PlaylistsRoomSettingsPlaylist : DrawableRoomPlaylist { public PlaylistsRoomSettingsPlaylist() { @@ -24,7 +24,8 @@ namespace osu.Game.Screens.OnlinePlay.Playlists Items.Remove(item); - SelectedItem.Value = nextItem ?? Items.LastOrDefault(); + if (AllowSelection && SelectedItem.Value == item) + SelectedItem.Value = nextItem ?? Items.LastOrDefault(); }; } } diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs index 228ecd4bf3..cf5a8e1985 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs @@ -25,7 +25,7 @@ using osuTK; namespace osu.Game.Screens.OnlinePlay.Playlists { - public class PlaylistsRoomSubScreen : RoomSubScreen + public partial class PlaylistsRoomSubScreen : RoomSubScreen { public override string Title { get; } diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsSongSelect.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsSongSelect.cs index e3f7b5dfc4..cedea4af70 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsSongSelect.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsSongSelect.cs @@ -10,7 +10,7 @@ using osu.Game.Screens.Select; namespace osu.Game.Screens.OnlinePlay.Playlists { - public class PlaylistsSongSelect : OnlinePlaySongSelect + public partial class PlaylistsSongSelect : OnlinePlaySongSelect { public PlaylistsSongSelect(Room room) : base(room) diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index 6be13bbda3..bc4cc2b00f 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -21,7 +21,7 @@ using osu.Game.Users; namespace osu.Game.Screens { - public abstract class OsuScreen : Screen, IOsuScreen, IHasDescription + public abstract partial class OsuScreen : Screen, IOsuScreen, IHasDescription { /// /// The amount of negative padding that should be applied to game background content which touches both the left and right sides of the screen. diff --git a/osu.Game/Screens/OsuScreenStack.cs b/osu.Game/Screens/OsuScreenStack.cs index 49f1255ec7..dffbbdbc55 100644 --- a/osu.Game/Screens/OsuScreenStack.cs +++ b/osu.Game/Screens/OsuScreenStack.cs @@ -10,7 +10,7 @@ using osu.Game.Graphics.Containers; namespace osu.Game.Screens { - public class OsuScreenStack : ScreenStack + public partial class OsuScreenStack : ScreenStack { [Cached] private BackgroundScreenStack backgroundScreenStack; diff --git a/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs b/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs index 0e56cafaaa..06509b6465 100644 --- a/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs +++ b/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs @@ -26,7 +26,7 @@ namespace osu.Game.Screens.Play /// /// Displays beatmap metadata inside /// - public class BeatmapMetadataDisplay : Container + public partial class BeatmapMetadataDisplay : Container { private readonly IWorkingBeatmap beatmap; private readonly Bindable> mods; @@ -212,7 +212,7 @@ namespace osu.Game.Screens.Play }; } - private class MetadataLineLabel : OsuSpriteText + private partial class MetadataLineLabel : OsuSpriteText { public MetadataLineLabel(LocalisableString text) { @@ -224,7 +224,7 @@ namespace osu.Game.Screens.Play } } - private class MetadataLineInfo : OsuSpriteText + private partial class MetadataLineInfo : OsuSpriteText { public MetadataLineInfo(string text) { diff --git a/osu.Game/Screens/Play/Break/BlurredIcon.cs b/osu.Game/Screens/Play/Break/BlurredIcon.cs index 97eafa01fa..cd38390324 100644 --- a/osu.Game/Screens/Play/Break/BlurredIcon.cs +++ b/osu.Game/Screens/Play/Break/BlurredIcon.cs @@ -12,7 +12,7 @@ using osuTK; namespace osu.Game.Screens.Play.Break { - public class BlurredIcon : BufferedContainer + public partial class BlurredIcon : BufferedContainer { private readonly SpriteIcon icon; diff --git a/osu.Game/Screens/Play/Break/BreakArrows.cs b/osu.Game/Screens/Play/Break/BreakArrows.cs index f2feda4d76..f0f1e8cc3d 100644 --- a/osu.Game/Screens/Play/Break/BreakArrows.cs +++ b/osu.Game/Screens/Play/Break/BreakArrows.cs @@ -11,7 +11,7 @@ using osuTK; namespace osu.Game.Screens.Play.Break { - public class BreakArrows : CompositeDrawable + public partial class BreakArrows : CompositeDrawable { private const int glow_icon_size = 60; private const int glow_icon_blur_sigma = 10; diff --git a/osu.Game/Screens/Play/Break/BreakInfo.cs b/osu.Game/Screens/Play/Break/BreakInfo.cs index 5aed8b7df1..f99c1d1817 100644 --- a/osu.Game/Screens/Play/Break/BreakInfo.cs +++ b/osu.Game/Screens/Play/Break/BreakInfo.cs @@ -13,7 +13,7 @@ using osuTK; namespace osu.Game.Screens.Play.Break { - public class BreakInfo : Container + public partial class BreakInfo : Container { public PercentageBreakInfoLine AccuracyDisplay; diff --git a/osu.Game/Screens/Play/Break/BreakInfoLine.cs b/osu.Game/Screens/Play/Break/BreakInfoLine.cs index 690d7c7e63..7261155c94 100644 --- a/osu.Game/Screens/Play/Break/BreakInfoLine.cs +++ b/osu.Game/Screens/Play/Break/BreakInfoLine.cs @@ -16,7 +16,7 @@ using osu.Game.Utils; namespace osu.Game.Screens.Play.Break { - public class BreakInfoLine : Container + public partial class BreakInfoLine : Container where T : struct { private const int margin = 2; @@ -82,7 +82,7 @@ namespace osu.Game.Screens.Play.Break } } - public class PercentageBreakInfoLine : BreakInfoLine + public partial class PercentageBreakInfoLine : BreakInfoLine { public PercentageBreakInfoLine(LocalisableString name, string prefix = "") : base(name, prefix) diff --git a/osu.Game/Screens/Play/Break/GlowIcon.cs b/osu.Game/Screens/Play/Break/GlowIcon.cs index 9222e8f890..595c4dd494 100644 --- a/osu.Game/Screens/Play/Break/GlowIcon.cs +++ b/osu.Game/Screens/Play/Break/GlowIcon.cs @@ -12,7 +12,7 @@ using osuTK; namespace osu.Game.Screens.Play.Break { - public class GlowIcon : Container + public partial class GlowIcon : Container { private readonly SpriteIcon spriteIcon; private readonly BlurredIcon blurredIcon; diff --git a/osu.Game/Screens/Play/Break/LetterboxOverlay.cs b/osu.Game/Screens/Play/Break/LetterboxOverlay.cs index 3eb58da469..92b432831d 100644 --- a/osu.Game/Screens/Play/Break/LetterboxOverlay.cs +++ b/osu.Game/Screens/Play/Break/LetterboxOverlay.cs @@ -11,7 +11,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.Play.Break { - public class LetterboxOverlay : CompositeDrawable + public partial class LetterboxOverlay : CompositeDrawable { private const int height = 350; diff --git a/osu.Game/Screens/Play/Break/RemainingTimeCounter.cs b/osu.Game/Screens/Play/Break/RemainingTimeCounter.cs index 4b84f7c69e..da83f8c29f 100644 --- a/osu.Game/Screens/Play/Break/RemainingTimeCounter.cs +++ b/osu.Game/Screens/Play/Break/RemainingTimeCounter.cs @@ -11,7 +11,7 @@ using osu.Game.Graphics.Sprites; namespace osu.Game.Screens.Play.Break { - public class RemainingTimeCounter : Counter + public partial class RemainingTimeCounter : Counter { private readonly OsuSpriteText counter; diff --git a/osu.Game/Screens/Play/BreakOverlay.cs b/osu.Game/Screens/Play/BreakOverlay.cs index 492c9c27ff..4927800059 100644 --- a/osu.Game/Screens/Play/BreakOverlay.cs +++ b/osu.Game/Screens/Play/BreakOverlay.cs @@ -14,7 +14,7 @@ using osu.Game.Screens.Play.Break; namespace osu.Game.Screens.Play { - public class BreakOverlay : Container + public partial class BreakOverlay : Container { /// /// The duration of the break overlay fading. diff --git a/osu.Game/Screens/Play/BreakTracker.cs b/osu.Game/Screens/Play/BreakTracker.cs index 8679db01a0..20ef1dc4bf 100644 --- a/osu.Game/Screens/Play/BreakTracker.cs +++ b/osu.Game/Screens/Play/BreakTracker.cs @@ -13,7 +13,7 @@ using osu.Game.Utils; namespace osu.Game.Screens.Play { - public class BreakTracker : Component + public partial class BreakTracker : Component { private readonly ScoreProcessor scoreProcessor; private readonly double gameplayStartTime; diff --git a/osu.Game/Screens/Play/ComboEffects.cs b/osu.Game/Screens/Play/ComboEffects.cs index 442b061af7..09c94a8f1d 100644 --- a/osu.Game/Screens/Play/ComboEffects.cs +++ b/osu.Game/Screens/Play/ComboEffects.cs @@ -13,7 +13,7 @@ using osu.Game.Skinning; namespace osu.Game.Screens.Play { - public class ComboEffects : CompositeDrawable + public partial class ComboEffects : CompositeDrawable { private readonly ScoreProcessor processor; diff --git a/osu.Game/Screens/Play/DimmableStoryboard.cs b/osu.Game/Screens/Play/DimmableStoryboard.cs index ae43d3d70d..40cc0f66ad 100644 --- a/osu.Game/Screens/Play/DimmableStoryboard.cs +++ b/osu.Game/Screens/Play/DimmableStoryboard.cs @@ -17,7 +17,7 @@ namespace osu.Game.Screens.Play /// /// A container that handles loading, as well as applies user-specified visual settings to it. /// - public class DimmableStoryboard : UserDimContainer + public partial class DimmableStoryboard : UserDimContainer { public Container OverlayLayerContainer { get; private set; } diff --git a/osu.Game/Screens/Play/EpilepsyWarning.cs b/osu.Game/Screens/Play/EpilepsyWarning.cs index 4f87853158..6316bbdb4e 100644 --- a/osu.Game/Screens/Play/EpilepsyWarning.cs +++ b/osu.Game/Screens/Play/EpilepsyWarning.cs @@ -14,7 +14,7 @@ using osuTK; namespace osu.Game.Screens.Play { - public class EpilepsyWarning : VisibilityContainer + public partial class EpilepsyWarning : VisibilityContainer { public const double FADE_DURATION = 250; diff --git a/osu.Game/Screens/Play/FailAnimation.cs b/osu.Game/Screens/Play/FailAnimation.cs index a4b4bf4d2b..3f21f811c1 100644 --- a/osu.Game/Screens/Play/FailAnimation.cs +++ b/osu.Game/Screens/Play/FailAnimation.cs @@ -15,11 +15,13 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Utils; +using osu.Game.Audio; using osu.Game.Audio.Effects; using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Skinning; using osuTK; using osuTK.Graphics; @@ -29,7 +31,7 @@ namespace osu.Game.Screens.Play /// Manage the animation to be applied when a player fails. /// Single use and automatically disposed after use. /// - public class FailAnimation : Container + public partial class FailAnimation : Container { public Action? OnComplete; @@ -48,7 +50,7 @@ namespace osu.Game.Screens.Play private const float duration = 2500; - private Sample? failSample; + private ISample? failSample; [Resolved] private OsuConfigManager config { get; set; } = null!; @@ -73,10 +75,10 @@ namespace osu.Game.Screens.Play } [BackgroundDependencyLoader] - private void load(AudioManager audio, IBindable beatmap) + private void load(AudioManager audio, ISkinSource skin, IBindable beatmap) { track = beatmap.Value.Track; - failSample = audio.Samples.Get(@"Gameplay/failsound"); + failSample = skin.GetSample(new SampleInfo(@"Gameplay/failsound")); AddRangeInternal(new Drawable[] { diff --git a/osu.Game/Screens/Play/FailOverlay.cs b/osu.Game/Screens/Play/FailOverlay.cs index 2af5102369..4fbc937b59 100644 --- a/osu.Game/Screens/Play/FailOverlay.cs +++ b/osu.Game/Screens/Play/FailOverlay.cs @@ -18,7 +18,7 @@ using osu.Framework.Graphics.Shapes; namespace osu.Game.Screens.Play { - public class FailOverlay : GameplayMenuOverlay + public partial class FailOverlay : GameplayMenuOverlay { public Func> SaveReplay; diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index 35b79fd628..c42f607908 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -17,7 +17,7 @@ namespace osu.Game.Screens.Play /// Encapsulates gameplay timing logic and provides a via DI for gameplay components to use. /// [Cached(typeof(IGameplayClock))] - public class GameplayClockContainer : Container, IAdjustableClock, IGameplayClock + public partial class GameplayClockContainer : Container, IAdjustableClock, IGameplayClock { /// /// Whether gameplay is paused. diff --git a/osu.Game/Screens/Play/GameplayMenuOverlay.cs b/osu.Game/Screens/Play/GameplayMenuOverlay.cs index c2652e9212..c681ef8f96 100644 --- a/osu.Game/Screens/Play/GameplayMenuOverlay.cs +++ b/osu.Game/Screens/Play/GameplayMenuOverlay.cs @@ -25,7 +25,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.Play { - public abstract class GameplayMenuOverlay : OverlayContainer, IKeyBindingHandler + public abstract partial class GameplayMenuOverlay : OverlayContainer, IKeyBindingHandler { protected const int TRANSITION_DURATION = 200; @@ -248,7 +248,7 @@ namespace osu.Game.Screens.Play }; } - private class Button : DialogButton + private partial class Button : DialogButton { // required to ensure keyboard navigation always starts from an extremity (unless the cursor is moved) protected override bool OnHover(HoverEvent e) => true; diff --git a/osu.Game/Screens/Play/HUD/BPMCounter.cs b/osu.Game/Screens/Play/HUD/BPMCounter.cs new file mode 100644 index 0000000000..c07b203341 --- /dev/null +++ b/osu.Game/Screens/Play/HUD/BPMCounter.cs @@ -0,0 +1,98 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Localisation; +using osu.Game.Beatmaps; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osu.Game.Skinning; +using osuTK; + +namespace osu.Game.Screens.Play.HUD +{ + public partial class BPMCounter : RollingCounter, ISkinnableDrawable + { + protected override double RollingDuration => 750; + + [Resolved] + private IBindable beatmap { get; set; } = null!; + + [Resolved] + private IGameplayClock gameplayClock { get; set; } = null!; + + [BackgroundDependencyLoader] + private void load(OsuColour colour) + { + Colour = colour.BlueLighter; + Current.Value = DisplayedCount = 0; + } + + protected override void Update() + { + base.Update(); + + //We don't want it going to 0 when we pause. so we block the updates + if (gameplayClock.IsPaused.Value) return; + + // We want to check Rate every update to cover windup/down + Current.Value = beatmap.Value.Beatmap.ControlPointInfo.TimingPointAt(gameplayClock.CurrentTime).BPM * gameplayClock.Rate; + } + + protected override OsuSpriteText CreateSpriteText() + => base.CreateSpriteText().With(s => s.Font = s.Font.With(size: 20f, fixedWidth: true)); + + protected override LocalisableString FormatCount(double count) + { + return $@"{count:0}"; + } + + protected override IHasText CreateText() => new TextComponent(); + + private partial class TextComponent : CompositeDrawable, IHasText + { + public LocalisableString Text + { + get => text.Text; + set => text.Text = value; + } + + private readonly OsuSpriteText text; + + public TextComponent() + { + AutoSizeAxes = Axes.Both; + + InternalChild = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Spacing = new Vector2(2), + Children = new Drawable[] + { + text = new OsuSpriteText + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Font = OsuFont.Numeric.With(size: 16, fixedWidth: true) + }, + new OsuSpriteText + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Font = OsuFont.Numeric.With(size: 8), + Text = @"BPM", + Padding = new MarginPadding { Bottom = 2f }, // align baseline better + } + } + }; + } + } + + public bool UsesFixedAnchor { get; set; } + } +} diff --git a/osu.Game/Screens/Play/HUD/ClicksPerSecond/ClicksPerSecondCalculator.cs b/osu.Game/Screens/Play/HUD/ClicksPerSecond/ClicksPerSecondCalculator.cs index 04774b974f..bf1f508d7b 100644 --- a/osu.Game/Screens/Play/HUD/ClicksPerSecond/ClicksPerSecondCalculator.cs +++ b/osu.Game/Screens/Play/HUD/ClicksPerSecond/ClicksPerSecondCalculator.cs @@ -8,7 +8,7 @@ using osu.Game.Rulesets.UI; namespace osu.Game.Screens.Play.HUD.ClicksPerSecond { - public class ClicksPerSecondCalculator : Component + public partial class ClicksPerSecondCalculator : Component { private readonly List timestamps = new List(); diff --git a/osu.Game/Screens/Play/HUD/ClicksPerSecond/ClicksPerSecondCounter.cs b/osu.Game/Screens/Play/HUD/ClicksPerSecond/ClicksPerSecondCounter.cs index 243d8ed1e8..cb72bb5f6f 100644 --- a/osu.Game/Screens/Play/HUD/ClicksPerSecond/ClicksPerSecondCounter.cs +++ b/osu.Game/Screens/Play/HUD/ClicksPerSecond/ClicksPerSecondCounter.cs @@ -14,7 +14,7 @@ using osuTK; namespace osu.Game.Screens.Play.HUD.ClicksPerSecond { - public class ClicksPerSecondCounter : RollingCounter, ISkinnableDrawable + public partial class ClicksPerSecondCounter : RollingCounter, ISkinnableDrawable { [Resolved] private ClicksPerSecondCalculator calculator { get; set; } = null!; @@ -43,7 +43,7 @@ namespace osu.Game.Screens.Play.HUD.ClicksPerSecond protected override IHasText CreateText() => new TextComponent(); - private class TextComponent : CompositeDrawable, IHasText + private partial class TextComponent : CompositeDrawable, IHasText { public LocalisableString Text { diff --git a/osu.Game/Screens/Play/HUD/ComboCounter.cs b/osu.Game/Screens/Play/HUD/ComboCounter.cs index 4179d41646..afccbc4ef0 100644 --- a/osu.Game/Screens/Play/HUD/ComboCounter.cs +++ b/osu.Game/Screens/Play/HUD/ComboCounter.cs @@ -7,7 +7,7 @@ using osu.Game.Skinning; namespace osu.Game.Screens.Play.HUD { - public abstract class ComboCounter : RollingCounter, ISkinnableDrawable + public abstract partial class ComboCounter : RollingCounter, ISkinnableDrawable { public bool UsesFixedAnchor { get; set; } diff --git a/osu.Game/Screens/Play/HUD/DefaultAccuracyCounter.cs b/osu.Game/Screens/Play/HUD/DefaultAccuracyCounter.cs index 018720510c..1a082e58b7 100644 --- a/osu.Game/Screens/Play/HUD/DefaultAccuracyCounter.cs +++ b/osu.Game/Screens/Play/HUD/DefaultAccuracyCounter.cs @@ -9,7 +9,7 @@ using osu.Game.Skinning; namespace osu.Game.Screens.Play.HUD { - public class DefaultAccuracyCounter : GameplayAccuracyCounter, ISkinnableDrawable + public partial class DefaultAccuracyCounter : GameplayAccuracyCounter, ISkinnableDrawable { public bool UsesFixedAnchor { get; set; } diff --git a/osu.Game/Screens/Play/HUD/DefaultComboCounter.cs b/osu.Game/Screens/Play/HUD/DefaultComboCounter.cs index 0c9c363280..1377055c30 100644 --- a/osu.Game/Screens/Play/HUD/DefaultComboCounter.cs +++ b/osu.Game/Screens/Play/HUD/DefaultComboCounter.cs @@ -10,7 +10,7 @@ using osu.Game.Rulesets.Scoring; namespace osu.Game.Screens.Play.HUD { - public class DefaultComboCounter : ComboCounter + public partial class DefaultComboCounter : ComboCounter { [BackgroundDependencyLoader] private void load(OsuColour colours, ScoreProcessor scoreProcessor) diff --git a/osu.Game/Screens/Play/HUD/DefaultHealthDisplay.cs b/osu.Game/Screens/Play/HUD/DefaultHealthDisplay.cs index 37e1d2fb84..76027f9e5d 100644 --- a/osu.Game/Screens/Play/HUD/DefaultHealthDisplay.cs +++ b/osu.Game/Screens/Play/HUD/DefaultHealthDisplay.cs @@ -19,7 +19,7 @@ using osu.Game.Skinning; namespace osu.Game.Screens.Play.HUD { - public class DefaultHealthDisplay : HealthDisplay, IHasAccentColour, ISkinnableDrawable + public partial class DefaultHealthDisplay : HealthDisplay, IHasAccentColour, ISkinnableDrawable { /// /// The base opacity of the glow. diff --git a/osu.Game/Screens/Play/HUD/DefaultScoreCounter.cs b/osu.Game/Screens/Play/HUD/DefaultScoreCounter.cs index 4450ad53d8..f116617271 100644 --- a/osu.Game/Screens/Play/HUD/DefaultScoreCounter.cs +++ b/osu.Game/Screens/Play/HUD/DefaultScoreCounter.cs @@ -10,7 +10,7 @@ using osu.Game.Skinning; namespace osu.Game.Screens.Play.HUD { - public class DefaultScoreCounter : GameplayScoreCounter, ISkinnableDrawable + public partial class DefaultScoreCounter : GameplayScoreCounter, ISkinnableDrawable { public DefaultScoreCounter() { diff --git a/osu.Game/Screens/Play/HUD/DefaultSongProgress.cs b/osu.Game/Screens/Play/HUD/DefaultSongProgress.cs index 45d0cf8462..53866312a0 100644 --- a/osu.Game/Screens/Play/HUD/DefaultSongProgress.cs +++ b/osu.Game/Screens/Play/HUD/DefaultSongProgress.cs @@ -13,7 +13,7 @@ using osuTK; namespace osu.Game.Screens.Play.HUD { - public class DefaultSongProgress : SongProgress + public partial class DefaultSongProgress : SongProgress { private const float bottom_bar_height = 5; private const float graph_height = SquareGraph.Column.WIDTH * 6; diff --git a/osu.Game/Screens/Play/HUD/FailingLayer.cs b/osu.Game/Screens/Play/HUD/FailingLayer.cs index 10c1d418ee..67e7ae8f3f 100644 --- a/osu.Game/Screens/Play/HUD/FailingLayer.cs +++ b/osu.Game/Screens/Play/HUD/FailingLayer.cs @@ -22,7 +22,7 @@ namespace osu.Game.Screens.Play.HUD /// /// An overlay layer on top of the playfield which fades to red when the current player health falls below a certain threshold defined by . /// - public class FailingLayer : HealthDisplay + public partial class FailingLayer : HealthDisplay { /// /// Whether the current player health should be shown on screen. diff --git a/osu.Game/Screens/Play/HUD/GameplayAccuracyCounter.cs b/osu.Game/Screens/Play/HUD/GameplayAccuracyCounter.cs index afb6749436..ca7fef8f73 100644 --- a/osu.Game/Screens/Play/HUD/GameplayAccuracyCounter.cs +++ b/osu.Game/Screens/Play/HUD/GameplayAccuracyCounter.cs @@ -1,20 +1,64 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - +using System.ComponentModel; using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Game.Configuration; using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets.Scoring; namespace osu.Game.Screens.Play.HUD { - public abstract class GameplayAccuracyCounter : PercentageCounter + public abstract partial class GameplayAccuracyCounter : PercentageCounter { - [BackgroundDependencyLoader] - private void load(ScoreProcessor scoreProcessor) + [SettingSource("Accuracy display mode", "Which accuracy mode should be displayed.")] + public Bindable AccuracyDisplay { get; } = new Bindable(); + + [Resolved] + private ScoreProcessor scoreProcessor { get; set; } = null!; + + protected override void LoadComplete() { - Current.BindTo(scoreProcessor.Accuracy); + base.LoadComplete(); + + AccuracyDisplay.BindValueChanged(mod => + { + Current.UnbindBindings(); + + switch (mod.NewValue) + { + case AccuracyDisplayMode.Standard: + Current.BindTo(scoreProcessor.Accuracy); + break; + + case AccuracyDisplayMode.MinimumAchievable: + Current.BindTo(scoreProcessor.MinimumAccuracy); + break; + + case AccuracyDisplayMode.MaximumAchievable: + Current.BindTo(scoreProcessor.MaximumAccuracy); + break; + } + }, true); + + // if the accuracy counter is using the "minimum achievable" mode, + // then its initial value is 0%, rather than the 100% that the base PercentageCounter assumes. + // to counteract this, manually finish transforms on DisplayedCount once after the initial callback above + // to stop it from rolling down from 100% to 0%. + FinishTransforms(targetMember: nameof(DisplayedCount)); + } + + public enum AccuracyDisplayMode + { + [Description("Standard")] + Standard, + + [Description("Maximum achievable")] + MaximumAchievable, + + [Description("Minimum achievable")] + MinimumAchievable } } } diff --git a/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs b/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs index 47b67fba00..d990af32e7 100644 --- a/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs +++ b/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs @@ -16,7 +16,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.Play.HUD { - public abstract class GameplayLeaderboard : CompositeDrawable + public abstract partial class GameplayLeaderboard : CompositeDrawable { private readonly Cached sorting = new Cached(); @@ -171,15 +171,15 @@ namespace osu.Game.Screens.Play.HUD for (int i = 0; i < Flow.Count; i++) { Flow.SetLayoutPosition(orderedByScore[i], i); - orderedByScore[i].ScorePosition = CheckValidScorePosition(i + 1) ? i + 1 : null; + orderedByScore[i].ScorePosition = CheckValidScorePosition(orderedByScore[i], i + 1) ? i + 1 : null; } sorting.Validate(); } - protected virtual bool CheckValidScorePosition(int i) => true; + protected virtual bool CheckValidScorePosition(GameplayLeaderboardScore score, int position) => true; - private class InputDisabledScrollContainer : OsuScrollContainer + private partial class InputDisabledScrollContainer : OsuScrollContainer { public InputDisabledScrollContainer() { diff --git a/osu.Game/Screens/Play/HUD/GameplayLeaderboardScore.cs b/osu.Game/Screens/Play/HUD/GameplayLeaderboardScore.cs index 0d03d8d090..07b80feb3e 100644 --- a/osu.Game/Screens/Play/HUD/GameplayLeaderboardScore.cs +++ b/osu.Game/Screens/Play/HUD/GameplayLeaderboardScore.cs @@ -21,7 +21,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.Play.HUD { - public class GameplayLeaderboardScore : CompositeDrawable, ILeaderboardScore + public partial class GameplayLeaderboardScore : CompositeDrawable, ILeaderboardScore { public const float EXTENDED_WIDTH = regular_width + top_player_left_width_extension; diff --git a/osu.Game/Screens/Play/HUD/GameplayScoreCounter.cs b/osu.Game/Screens/Play/HUD/GameplayScoreCounter.cs index 7a6292ccbf..a11cccd97c 100644 --- a/osu.Game/Screens/Play/HUD/GameplayScoreCounter.cs +++ b/osu.Game/Screens/Play/HUD/GameplayScoreCounter.cs @@ -12,7 +12,7 @@ using osu.Game.Rulesets.Scoring; namespace osu.Game.Screens.Play.HUD { - public abstract class GameplayScoreCounter : ScoreCounter + public abstract partial class GameplayScoreCounter : ScoreCounter { private Bindable scoreDisplayMode; diff --git a/osu.Game/Screens/Play/HUD/HealthDisplay.cs b/osu.Game/Screens/Play/HUD/HealthDisplay.cs index 569b37aea5..7a73eb1657 100644 --- a/osu.Game/Screens/Play/HUD/HealthDisplay.cs +++ b/osu.Game/Screens/Play/HUD/HealthDisplay.cs @@ -17,7 +17,7 @@ namespace osu.Game.Screens.Play.HUD /// A container for components displaying the current player health. /// Gets bound automatically to the when inserted to hierarchy. /// - public abstract class HealthDisplay : CompositeDrawable + public abstract partial class HealthDisplay : CompositeDrawable { private readonly Bindable showHealthBar = new Bindable(true); diff --git a/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs b/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs index c9f1571dfe..0337f66bd9 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs @@ -23,7 +23,7 @@ using osuTK; namespace osu.Game.Screens.Play.HUD.HitErrorMeters { [Cached] - public class BarHitErrorMeter : HitErrorMeter + public partial class BarHitErrorMeter : HitErrorMeter { [SettingSource("Judgement line thickness", "How thick the individual lines should be.")] public BindableNumber JudgementLineThickness { get; } = new BindableNumber(4) @@ -33,6 +33,9 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters Precision = 0.1f, }; + [SettingSource("Show colour bars")] + public Bindable ColourBarVisibility { get; } = new Bindable(true); + [SettingSource("Show moving average arrow", "Whether an arrow should move beneath the bar showing the average error.")] public Bindable ShowMovingAverage { get; } = new BindableBool(true); @@ -108,6 +111,7 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters Origin = Anchor.TopCentre, Width = bar_width, RelativeSizeAxes = Axes.Y, + Alpha = 0, Height = 0.5f, Scale = new Vector2(1, -1), }, @@ -115,6 +119,7 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters { Anchor = Anchor.Centre, Origin = Anchor.TopCentre, + Alpha = 0, Width = bar_width, RelativeSizeAxes = Axes.Y, Height = 0.5f, @@ -178,6 +183,11 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters CentreMarkerStyle.BindValueChanged(style => recreateCentreMarker(style.NewValue), true); LabelStyle.BindValueChanged(style => recreateLabels(style.NewValue), true); + ColourBarVisibility.BindValueChanged(visible => + { + colourBarsEarly.FadeTo(visible.NewValue ? 1 : 0, 500, Easing.OutQuint); + colourBarsLate.FadeTo(visible.NewValue ? 1 : 0, 500, Easing.OutQuint); + }, true); // delay the appearance animations for only the initial appearance. using (arrowContainer.BeginDelayedSequence(450)) @@ -422,7 +432,7 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters private float getRelativeJudgementPosition(double value) => Math.Clamp((float)((value / maxHitWindow) + 1) / 2, 0, 1); - internal class JudgementLine : PoolableDrawable + internal partial class JudgementLine : PoolableDrawable { public readonly BindableNumber JudgementLineThickness = new BindableFloat(); diff --git a/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs b/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs index 86ba85168f..ec5dc5f52f 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs @@ -18,7 +18,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.Play.HUD.HitErrorMeters { [Cached] - public class ColourHitErrorMeter : HitErrorMeter + public partial class ColourHitErrorMeter : HitErrorMeter { private const int animation_duration = 200; private const int drawable_judgement_size = 8; @@ -63,7 +63,7 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters public override void Clear() => judgementsFlow.Clear(); - private class JudgementFlow : FillFlowContainer + private partial class JudgementFlow : FillFlowContainer { public override IEnumerable FlowingChildren => base.FlowingChildren.Reverse(); @@ -122,7 +122,7 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters } } - public class HitErrorShape : PoolableDrawable + public partial class HitErrorShape : PoolableDrawable { public bool IsRemoved { get; private set; } diff --git a/osu.Game/Screens/Play/HUD/HitErrorMeters/HitErrorMeter.cs b/osu.Game/Screens/Play/HUD/HitErrorMeters/HitErrorMeter.cs index dda17c25e6..191f63e97d 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorMeters/HitErrorMeter.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorMeters/HitErrorMeter.cs @@ -14,7 +14,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.Play.HUD.HitErrorMeters { - public abstract class HitErrorMeter : CompositeDrawable, ISkinnableDrawable + public abstract partial class HitErrorMeter : CompositeDrawable, ISkinnableDrawable { protected HitWindows HitWindows { get; private set; } diff --git a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs index 39a8f1e783..f902e0903d 100644 --- a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs +++ b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs @@ -25,7 +25,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.Play.HUD { - public class HoldForMenuButton : FillFlowContainer + public partial class HoldForMenuButton : FillFlowContainer { public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true; @@ -102,7 +102,7 @@ namespace osu.Game.Screens.Play.HUD } } - private class HoldButton : HoldToConfirmContainer, IKeyBindingHandler + private partial class HoldButton : HoldToConfirmContainer, IKeyBindingHandler { private SpriteIcon icon; private CircularProgress circularProgress; diff --git a/osu.Game/Screens/Play/HUD/LongestComboCounter.cs b/osu.Game/Screens/Play/HUD/LongestComboCounter.cs index 0e7af69af2..fdc3768aab 100644 --- a/osu.Game/Screens/Play/HUD/LongestComboCounter.cs +++ b/osu.Game/Screens/Play/HUD/LongestComboCounter.cs @@ -13,7 +13,7 @@ using osuTK; namespace osu.Game.Screens.Play.HUD { - public class LongestComboCounter : ComboCounter + public partial class LongestComboCounter : ComboCounter { [BackgroundDependencyLoader] private void load(OsuColour colours, ScoreProcessor scoreProcessor) @@ -24,7 +24,7 @@ namespace osu.Game.Screens.Play.HUD protected override IHasText CreateText() => new TextComponent(); - private class TextComponent : CompositeDrawable, IHasText + private partial class TextComponent : CompositeDrawable, IHasText { public LocalisableString Text { diff --git a/osu.Game/Screens/Play/HUD/MatchScoreDisplay.cs b/osu.Game/Screens/Play/HUD/MatchScoreDisplay.cs index 00dc586448..58bf4eea4b 100644 --- a/osu.Game/Screens/Play/HUD/MatchScoreDisplay.cs +++ b/osu.Game/Screens/Play/HUD/MatchScoreDisplay.cs @@ -16,7 +16,7 @@ using osuTK; namespace osu.Game.Screens.Play.HUD { - public class MatchScoreDisplay : CompositeDrawable + public partial class MatchScoreDisplay : CompositeDrawable { private const float bar_height = 18; private const float font_size = 50; @@ -148,7 +148,7 @@ namespace osu.Game.Screens.Play.HUD Score2Text.X = Math.Max(5 + Score2Text.DrawWidth / 2, score2Bar.DrawWidth); } - protected class MatchScoreCounter : CommaSeparatedScoreCounter + protected partial class MatchScoreCounter : CommaSeparatedScoreCounter { private OsuSpriteText displayedSpriteText; diff --git a/osu.Game/Screens/Play/HUD/ModDisplay.cs b/osu.Game/Screens/Play/HUD/ModDisplay.cs index 0badc063ce..8b2b8f9464 100644 --- a/osu.Game/Screens/Play/HUD/ModDisplay.cs +++ b/osu.Game/Screens/Play/HUD/ModDisplay.cs @@ -20,7 +20,7 @@ namespace osu.Game.Screens.Play.HUD /// /// Displays a single-line horizontal auto-sized flow of mods. For cases where wrapping is required, use instead. /// - public class ModDisplay : CompositeDrawable, IHasCurrentValue> + public partial class ModDisplay : CompositeDrawable, IHasCurrentValue> { private const int fade_duration = 1000; @@ -33,8 +33,7 @@ namespace osu.Game.Screens.Play.HUD get => current.Current; set { - if (value == null) - throw new ArgumentNullException(nameof(value)); + ArgumentNullException.ThrowIfNull(value); current.Current = value; } diff --git a/osu.Game/Screens/Play/HUD/ModFlowDisplay.cs b/osu.Game/Screens/Play/HUD/ModFlowDisplay.cs index 86fece84fa..38027c64ac 100644 --- a/osu.Game/Screens/Play/HUD/ModFlowDisplay.cs +++ b/osu.Game/Screens/Play/HUD/ModFlowDisplay.cs @@ -19,7 +19,7 @@ namespace osu.Game.Screens.Play.HUD /// /// A horizontally wrapping display of mods. For cases where wrapping is not required, use instead. /// - public class ModFlowDisplay : ReverseChildIDFillFlowContainer, IHasCurrentValue> + public partial class ModFlowDisplay : ReverseChildIDFillFlowContainer, IHasCurrentValue> { private const int fade_duration = 1000; @@ -30,8 +30,7 @@ namespace osu.Game.Screens.Play.HUD get => current.Current; set { - if (value == null) - throw new ArgumentNullException(nameof(value)); + ArgumentNullException.ThrowIfNull(value); current.Current = value; } diff --git a/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs b/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs index 4ac92056ef..620f3718c2 100644 --- a/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs +++ b/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Collections.Specialized; +using System.Diagnostics; using System.Linq; using System.Threading; using osu.Framework.Allocation; @@ -25,7 +26,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.Play.HUD { [LongRunningLoad] - public class MultiplayerGameplayLeaderboard : GameplayLeaderboard + public partial class MultiplayerGameplayLeaderboard : GameplayLeaderboard { protected readonly Dictionary UserScores = new Dictionary(); @@ -153,11 +154,13 @@ namespace osu.Game.Screens.Play.HUD } } - private void playingUsersChanged(object sender, NotifyCollectionChangedEventArgs e) + private void playingUsersChanged(object? sender, NotifyCollectionChangedEventArgs e) { switch (e.Action) { case NotifyCollectionChangedAction.Remove: + Debug.Assert(e.OldItems != null); + foreach (int userId in e.OldItems.OfType()) { spectatorClient.StopWatchingUser(userId); diff --git a/osu.Game/Screens/Play/HUD/PerformancePointsCounter.cs b/osu.Game/Screens/Play/HUD/PerformancePointsCounter.cs index 97a120f9bd..15484f2965 100644 --- a/osu.Game/Screens/Play/HUD/PerformancePointsCounter.cs +++ b/osu.Game/Screens/Play/HUD/PerformancePointsCounter.cs @@ -35,7 +35,7 @@ using osuTK; namespace osu.Game.Screens.Play.HUD { - public class PerformancePointsCounter : RollingCounter, ISkinnableDrawable + public partial class PerformancePointsCounter : RollingCounter, ISkinnableDrawable { public bool UsesFixedAnchor { get; set; } @@ -171,7 +171,7 @@ namespace osu.Game.Screens.Play.HUD loadCancellationSource?.Cancel(); } - private class TextComponent : CompositeDrawable, IHasText + private partial class TextComponent : CompositeDrawable, IHasText { public LocalisableString Text { diff --git a/osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs b/osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs index 019ba53a5e..45b2c1b13c 100644 --- a/osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs +++ b/osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs @@ -12,7 +12,7 @@ using osuTK.Input; namespace osu.Game.Screens.Play.HUD { - public class PlayerSettingsOverlay : VisibilityContainer + public partial class PlayerSettingsOverlay : VisibilityContainer { private const int fade_duration = 200; diff --git a/osu.Game/Screens/Play/HUD/SkinnableInfo.cs b/osu.Game/Screens/Play/HUD/SkinnableInfo.cs index 6d63776dbb..da759b4329 100644 --- a/osu.Game/Screens/Play/HUD/SkinnableInfo.cs +++ b/osu.Game/Screens/Play/HUD/SkinnableInfo.cs @@ -67,7 +67,7 @@ namespace osu.Game.Screens.Play.HUD foreach (var (_, property) in component.GetSettingsSourceProperties()) { - var bindable = (IBindable)property.GetValue(component); + var bindable = (IBindable)property.GetValue(component)!; if (!bindable.IsDefault) Settings.Add(property.Name.ToSnakeCase(), bindable.GetUnderlyingSettingValue()); @@ -88,7 +88,7 @@ namespace osu.Game.Screens.Play.HUD { try { - Drawable d = (Drawable)Activator.CreateInstance(Type); + Drawable d = (Drawable)Activator.CreateInstance(Type)!; d.ApplySkinnableInfo(this); return d; } diff --git a/osu.Game/Screens/Play/HUD/SoloGameplayLeaderboard.cs b/osu.Game/Screens/Play/HUD/SoloGameplayLeaderboard.cs index 0df3200adb..9f92880919 100644 --- a/osu.Game/Screens/Play/HUD/SoloGameplayLeaderboard.cs +++ b/osu.Game/Screens/Play/HUD/SoloGameplayLeaderboard.cs @@ -15,7 +15,7 @@ using osu.Game.Users; namespace osu.Game.Screens.Play.HUD { - public class SoloGameplayLeaderboard : GameplayLeaderboard + public partial class SoloGameplayLeaderboard : GameplayLeaderboard { private const int duration = 100; @@ -100,16 +100,16 @@ namespace osu.Game.Screens.Play.HUD local.DisplayOrder.Value = long.MaxValue; } - protected override bool CheckValidScorePosition(int i) + protected override bool CheckValidScorePosition(GameplayLeaderboardScore score, int position) { // change displayed position to '-' when there are 50 already submitted scores and tracked score is last - if (scoreSource.Value != PlayBeatmapDetailArea.TabType.Local) + if (score.Tracked && scoreSource.Value != PlayBeatmapDetailArea.TabType.Local) { - if (i == Flow.Count && Flow.Count > GetScoresRequest.MAX_SCORES_PER_REQUEST) + if (position == Flow.Count && Flow.Count > GetScoresRequest.MAX_SCORES_PER_REQUEST) return false; } - return base.CheckValidScorePosition(i); + return base.CheckValidScorePosition(score, position); } private void updateVisibility() => diff --git a/osu.Game/Screens/Play/HUD/SongProgress.cs b/osu.Game/Screens/Play/HUD/SongProgress.cs index 0b6494bd8a..4504745eb9 100644 --- a/osu.Game/Screens/Play/HUD/SongProgress.cs +++ b/osu.Game/Screens/Play/HUD/SongProgress.cs @@ -12,7 +12,7 @@ using osu.Game.Skinning; namespace osu.Game.Screens.Play.HUD { - public abstract class SongProgress : OverlayContainer, ISkinnableDrawable + public abstract partial class SongProgress : OverlayContainer, ISkinnableDrawable { // Some implementations of this element allow seeking during gameplay playback. // Set a sane default of never handling input to override the behaviour provided by OverlayContainer. diff --git a/osu.Game/Screens/Play/HUD/SongProgressBar.cs b/osu.Game/Screens/Play/HUD/SongProgressBar.cs index db4e200724..28059d4911 100644 --- a/osu.Game/Screens/Play/HUD/SongProgressBar.cs +++ b/osu.Game/Screens/Play/HUD/SongProgressBar.cs @@ -15,7 +15,7 @@ using osu.Framework.Threading; namespace osu.Game.Screens.Play.HUD { - public class SongProgressBar : SliderBar + public partial class SongProgressBar : SliderBar { public Action OnSeek; diff --git a/osu.Game/Screens/Play/HUD/SongProgressGraph.cs b/osu.Game/Screens/Play/HUD/SongProgressGraph.cs index f234b45922..f69a1eccd6 100644 --- a/osu.Game/Screens/Play/HUD/SongProgressGraph.cs +++ b/osu.Game/Screens/Play/HUD/SongProgressGraph.cs @@ -10,7 +10,7 @@ using osu.Game.Rulesets.Objects; namespace osu.Game.Screens.Play.HUD { - public class SongProgressGraph : SquareGraph + public partial class SongProgressGraph : SquareGraph { private IEnumerable objects; diff --git a/osu.Game/Screens/Play/HUD/SongProgressInfo.cs b/osu.Game/Screens/Play/HUD/SongProgressInfo.cs index d0eb8f8ca1..fb5f5cc916 100644 --- a/osu.Game/Screens/Play/HUD/SongProgressInfo.cs +++ b/osu.Game/Screens/Play/HUD/SongProgressInfo.cs @@ -13,7 +13,7 @@ using System; namespace osu.Game.Screens.Play.HUD { - public class SongProgressInfo : Container + public partial class SongProgressInfo : Container { private SizePreservingSpriteText timeCurrent; private SizePreservingSpriteText timeLeft; diff --git a/osu.Game/Screens/Play/HUD/UnstableRateCounter.cs b/osu.Game/Screens/Play/HUD/UnstableRateCounter.cs index 0ba88c549e..f450ae799e 100644 --- a/osu.Game/Screens/Play/HUD/UnstableRateCounter.cs +++ b/osu.Game/Screens/Play/HUD/UnstableRateCounter.cs @@ -20,7 +20,7 @@ using osuTK; namespace osu.Game.Screens.Play.HUD { - public class UnstableRateCounter : RollingCounter, ISkinnableDrawable + public partial class UnstableRateCounter : RollingCounter, ISkinnableDrawable { public bool UsesFixedAnchor { get; set; } @@ -83,7 +83,7 @@ namespace osu.Game.Screens.Play.HUD scoreProcessor.JudgementReverted -= updateDisplay; } - private class TextComponent : CompositeDrawable, IHasText + private partial class TextComponent : CompositeDrawable, IHasText { public LocalisableString Text { diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index fa38eeb9aa..076d43c077 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -24,11 +24,12 @@ using osu.Game.Screens.Play.HUD; using osu.Game.Screens.Play.HUD.ClicksPerSecond; using osu.Game.Skinning; using osuTK; +using osu.Game.Localisation; namespace osu.Game.Screens.Play { [Cached] - public class HUDOverlay : Container, IKeyBindingHandler + public partial class HUDOverlay : Container, IKeyBindingHandler { public const float FADE_DURATION = 300; @@ -172,7 +173,7 @@ namespace osu.Game.Screens.Play notificationOverlay?.Post(new SimpleNotification { - Text = $"The score overlay is currently disabled. You can toggle this by pressing {config.LookupKeyBindings(GlobalAction.ToggleInGameInterface)}." + Text = NotificationsStrings.ScoreOverlayDisabled(config.LookupKeyBindings(GlobalAction.ToggleInGameInterface)) }); } @@ -383,7 +384,7 @@ namespace osu.Game.Screens.Play } } - private class MainComponentsContainer : SkinnableTargetContainer + private partial class MainComponentsContainer : SkinnableTargetContainer { private Bindable scoringMode; diff --git a/osu.Game/Screens/Play/HotkeyExitOverlay.cs b/osu.Game/Screens/Play/HotkeyExitOverlay.cs index 07595a43c4..4c1265c699 100644 --- a/osu.Game/Screens/Play/HotkeyExitOverlay.cs +++ b/osu.Game/Screens/Play/HotkeyExitOverlay.cs @@ -10,7 +10,7 @@ using osu.Game.Overlays; namespace osu.Game.Screens.Play { - public class HotkeyExitOverlay : HoldToConfirmOverlay, IKeyBindingHandler + public partial class HotkeyExitOverlay : HoldToConfirmOverlay, IKeyBindingHandler { public bool OnPressed(KeyBindingPressEvent e) { diff --git a/osu.Game/Screens/Play/HotkeyRetryOverlay.cs b/osu.Game/Screens/Play/HotkeyRetryOverlay.cs index 94c0f0a89d..582b5a1691 100644 --- a/osu.Game/Screens/Play/HotkeyRetryOverlay.cs +++ b/osu.Game/Screens/Play/HotkeyRetryOverlay.cs @@ -10,7 +10,7 @@ using osu.Game.Overlays; namespace osu.Game.Screens.Play { - public class HotkeyRetryOverlay : HoldToConfirmOverlay, IKeyBindingHandler + public partial class HotkeyRetryOverlay : HoldToConfirmOverlay, IKeyBindingHandler { public bool OnPressed(KeyBindingPressEvent e) { diff --git a/osu.Game/Screens/Play/KeyCounter.cs b/osu.Game/Screens/Play/KeyCounter.cs index 1e5ada5295..4405542b3b 100644 --- a/osu.Game/Screens/Play/KeyCounter.cs +++ b/osu.Game/Screens/Play/KeyCounter.cs @@ -15,7 +15,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.Play { - public abstract class KeyCounter : Container + public abstract partial class KeyCounter : Container { private Sprite buttonSprite; private Sprite glowSprite; diff --git a/osu.Game/Screens/Play/KeyCounterAction.cs b/osu.Game/Screens/Play/KeyCounterAction.cs index f636796436..900d9bcd0e 100644 --- a/osu.Game/Screens/Play/KeyCounterAction.cs +++ b/osu.Game/Screens/Play/KeyCounterAction.cs @@ -7,7 +7,7 @@ using System.Collections.Generic; namespace osu.Game.Screens.Play { - public class KeyCounterAction : KeyCounter + public partial class KeyCounterAction : KeyCounter where T : struct { public T Action { get; } diff --git a/osu.Game/Screens/Play/KeyCounterDisplay.cs b/osu.Game/Screens/Play/KeyCounterDisplay.cs index 1b726b0f7b..bb50d4a539 100644 --- a/osu.Game/Screens/Play/KeyCounterDisplay.cs +++ b/osu.Game/Screens/Play/KeyCounterDisplay.cs @@ -16,7 +16,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.Play { - public class KeyCounterDisplay : Container + public partial class KeyCounterDisplay : Container { private const int duration = 100; private const double key_fade_time = 80; @@ -54,7 +54,7 @@ namespace osu.Game.Screens.Play public override void Add(KeyCounter key) { - if (key == null) throw new ArgumentNullException(nameof(key)); + ArgumentNullException.ThrowIfNull(key); base.Add(key); key.IsCounting = IsCounting; @@ -141,7 +141,7 @@ namespace osu.Game.Screens.Play this.receptor = receptor; } - public class Receptor : Drawable + public partial class Receptor : Drawable { protected readonly KeyCounterDisplay Target; diff --git a/osu.Game/Screens/Play/KeyCounterKeyboard.cs b/osu.Game/Screens/Play/KeyCounterKeyboard.cs index 1005de4ea4..c5c8b7eeae 100644 --- a/osu.Game/Screens/Play/KeyCounterKeyboard.cs +++ b/osu.Game/Screens/Play/KeyCounterKeyboard.cs @@ -8,7 +8,7 @@ using osuTK.Input; namespace osu.Game.Screens.Play { - public class KeyCounterKeyboard : KeyCounter + public partial class KeyCounterKeyboard : KeyCounter { public Key Key { get; } diff --git a/osu.Game/Screens/Play/KeyCounterMouse.cs b/osu.Game/Screens/Play/KeyCounterMouse.cs index 0dc2830665..cf9c7c029f 100644 --- a/osu.Game/Screens/Play/KeyCounterMouse.cs +++ b/osu.Game/Screens/Play/KeyCounterMouse.cs @@ -9,7 +9,7 @@ using osuTK; namespace osu.Game.Screens.Play { - public class KeyCounterMouse : KeyCounter + public partial class KeyCounterMouse : KeyCounter { public MouseButton Button { get; } diff --git a/osu.Game/Screens/Play/MasterGameplayClockContainer.cs b/osu.Game/Screens/Play/MasterGameplayClockContainer.cs index c3c351ac36..489a4ef8b3 100644 --- a/osu.Game/Screens/Play/MasterGameplayClockContainer.cs +++ b/osu.Game/Screens/Play/MasterGameplayClockContainer.cs @@ -25,7 +25,7 @@ namespace osu.Game.Screens.Play /// /// This is intended to be used as a single controller for gameplay, or as a reference source for other s. /// - public class MasterGameplayClockContainer : GameplayClockContainer, IBeatSyncProvider + public partial class MasterGameplayClockContainer : GameplayClockContainer, IBeatSyncProvider { /// /// Duration before gameplay start time required before skip button displays. diff --git a/osu.Game/Screens/Play/PauseOverlay.cs b/osu.Game/Screens/Play/PauseOverlay.cs index cb98fefcfe..28044653e6 100644 --- a/osu.Game/Screens/Play/PauseOverlay.cs +++ b/osu.Game/Screens/Play/PauseOverlay.cs @@ -15,7 +15,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.Play { - public class PauseOverlay : GameplayMenuOverlay + public partial class PauseOverlay : GameplayMenuOverlay { public Action OnResume; diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 7048f83c09..05133fba35 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -44,7 +44,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.Play { [Cached] - public abstract class Player : ScreenWithBeatmapBackground, ISamplePlaybackDisabler, ILocalUserPlayInfo + public abstract partial class Player : ScreenWithBeatmapBackground, ISamplePlaybackDisabler, ILocalUserPlayInfo { /// /// The delay upon completion of the beatmap before displaying the results screen. @@ -1159,7 +1159,10 @@ namespace osu.Game.Screens.Play /// /// The to be displayed in the results screen. /// The . - protected virtual ResultsScreen CreateResults(ScoreInfo score) => new SoloResultsScreen(score, true); + protected virtual ResultsScreen CreateResults(ScoreInfo score) => new SoloResultsScreen(score, true) + { + ShowUserStatistics = true + }; private void fadeOut(bool instant = false) { diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 4ff5083107..d9062da8aa 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -20,6 +20,7 @@ using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Input; +using osu.Game.Localisation; using osu.Game.Overlays; using osu.Game.Overlays.Notifications; using osu.Game.Screens.Menu; @@ -31,7 +32,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.Play { - public class PlayerLoader : ScreenWithBeatmapBackground + public partial class PlayerLoader : ScreenWithBeatmapBackground { protected const float BACKGROUND_BLUR = 15; @@ -130,16 +131,16 @@ namespace osu.Game.Screens.Play private bool quickRestart; - [Resolved(CanBeNull = true)] + [Resolved] private INotificationOverlay? notificationOverlay { get; set; } - [Resolved(CanBeNull = true)] + [Resolved] private VolumeOverlay? volumeOverlay { get; set; } [Resolved] private AudioManager audioManager { get; set; } = null!; - [Resolved(CanBeNull = true)] + [Resolved] private BatteryInfo? batteryInfo { get; set; } public PlayerLoader(Func createPlayer) @@ -544,13 +545,13 @@ namespace osu.Game.Screens.Play } } - private class MutedNotification : SimpleNotification + private partial class MutedNotification : SimpleNotification { public override bool IsImportant => true; public MutedNotification() { - Text = "Your game volume is too low to hear anything! Click here to restore it."; + Text = NotificationsStrings.GameVolumeTooLow; } [BackgroundDependencyLoader] @@ -599,13 +600,13 @@ namespace osu.Game.Screens.Play } } - private class BatteryWarningNotification : SimpleNotification + private partial class BatteryWarningNotification : SimpleNotification { public override bool IsImportant => true; public BatteryWarningNotification() { - Text = "Your battery level is low! Charge your device to prevent interruptions during gameplay."; + Text = NotificationsStrings.BatteryLow; } [BackgroundDependencyLoader] diff --git a/osu.Game/Screens/Play/PlayerSettings/AudioSettings.cs b/osu.Game/Screens/Play/PlayerSettings/AudioSettings.cs index 606b5c198c..010d8115fa 100644 --- a/osu.Game/Screens/Play/PlayerSettings/AudioSettings.cs +++ b/osu.Game/Screens/Play/PlayerSettings/AudioSettings.cs @@ -12,7 +12,7 @@ using osu.Game.Scoring; namespace osu.Game.Screens.Play.PlayerSettings { - public class AudioSettings : PlayerSettingsGroup + public partial class AudioSettings : PlayerSettingsGroup { public Bindable ReferenceScore { get; } = new Bindable(); diff --git a/osu.Game/Screens/Play/PlayerSettings/BeatmapOffsetControl.cs b/osu.Game/Screens/Play/PlayerSettings/BeatmapOffsetControl.cs index 537f4d811a..9492614b66 100644 --- a/osu.Game/Screens/Play/PlayerSettings/BeatmapOffsetControl.cs +++ b/osu.Game/Screens/Play/PlayerSettings/BeatmapOffsetControl.cs @@ -25,9 +25,9 @@ using osuTK; namespace osu.Game.Screens.Play.PlayerSettings { - public class BeatmapOffsetControl : CompositeDrawable + public partial class BeatmapOffsetControl : CompositeDrawable { - public Bindable ReferenceScore { get; } = new Bindable(); + public Bindable ReferenceScore { get; } = new Bindable(); public BindableDouble Current { get; } = new BindableDouble { @@ -87,11 +87,11 @@ namespace osu.Game.Screens.Play.PlayerSettings }; } - public class OffsetSliderBar : PlayerSliderBar + public partial class OffsetSliderBar : PlayerSliderBar { protected override Drawable CreateControl() => new CustomSliderBar(); - protected class CustomSliderBar : SliderBar + protected partial class CustomSliderBar : SliderBar { public override LocalisableString TooltipText => Current.Value == 0 @@ -176,7 +176,7 @@ namespace osu.Game.Screens.Play.PlayerSettings } } - private void scoreChanged(ValueChangedEvent score) + private void scoreChanged(ValueChangedEvent score) { referenceScoreContainer.Clear(); diff --git a/osu.Game/Screens/Play/PlayerSettings/DiscussionSettings.cs b/osu.Game/Screens/Play/PlayerSettings/DiscussionSettings.cs index afbd5caef3..7c76936621 100644 --- a/osu.Game/Screens/Play/PlayerSettings/DiscussionSettings.cs +++ b/osu.Game/Screens/Play/PlayerSettings/DiscussionSettings.cs @@ -10,7 +10,7 @@ using osu.Game.Graphics.UserInterface; namespace osu.Game.Screens.Play.PlayerSettings { - public class DiscussionSettings : PlayerSettingsGroup + public partial class DiscussionSettings : PlayerSettingsGroup { public DiscussionSettings() : base("discussions") diff --git a/osu.Game/Screens/Play/PlayerSettings/InputSettings.cs b/osu.Game/Screens/Play/PlayerSettings/InputSettings.cs index 04cf79873c..13e5b66a70 100644 --- a/osu.Game/Screens/Play/PlayerSettings/InputSettings.cs +++ b/osu.Game/Screens/Play/PlayerSettings/InputSettings.cs @@ -10,7 +10,7 @@ using osu.Game.Localisation; namespace osu.Game.Screens.Play.PlayerSettings { - public class InputSettings : PlayerSettingsGroup + public partial class InputSettings : PlayerSettingsGroup { private readonly PlayerCheckbox mouseButtonsCheckbox; diff --git a/osu.Game/Screens/Play/PlayerSettings/PlaybackSettings.cs b/osu.Game/Screens/Play/PlayerSettings/PlaybackSettings.cs index 14e3123028..cb6fcb2413 100644 --- a/osu.Game/Screens/Play/PlayerSettings/PlaybackSettings.cs +++ b/osu.Game/Screens/Play/PlayerSettings/PlaybackSettings.cs @@ -11,7 +11,7 @@ using osu.Game.Graphics.Sprites; namespace osu.Game.Screens.Play.PlayerSettings { - public class PlaybackSettings : PlayerSettingsGroup + public partial class PlaybackSettings : PlayerSettingsGroup { private const int padding = 10; diff --git a/osu.Game/Screens/Play/PlayerSettings/PlayerCheckbox.cs b/osu.Game/Screens/Play/PlayerSettings/PlayerCheckbox.cs index cea03d2155..49c9cbf385 100644 --- a/osu.Game/Screens/Play/PlayerSettings/PlayerCheckbox.cs +++ b/osu.Game/Screens/Play/PlayerSettings/PlayerCheckbox.cs @@ -9,11 +9,11 @@ using osu.Game.Overlays.Settings; namespace osu.Game.Screens.Play.PlayerSettings { - public class PlayerCheckbox : SettingsCheckbox + public partial class PlayerCheckbox : SettingsCheckbox { protected override Drawable CreateControl() => new PlayerCheckboxControl(); - public class PlayerCheckboxControl : OsuCheckbox + public partial class PlayerCheckboxControl : OsuCheckbox { [BackgroundDependencyLoader] private void load(OsuColour colours) diff --git a/osu.Game/Screens/Play/PlayerSettings/PlayerSettingsGroup.cs b/osu.Game/Screens/Play/PlayerSettings/PlayerSettingsGroup.cs index 55cf69b0f2..ea4d983343 100644 --- a/osu.Game/Screens/Play/PlayerSettings/PlayerSettingsGroup.cs +++ b/osu.Game/Screens/Play/PlayerSettings/PlayerSettingsGroup.cs @@ -8,7 +8,7 @@ using osu.Game.Overlays; namespace osu.Game.Screens.Play.PlayerSettings { - public class PlayerSettingsGroup : SettingsToolboxGroup + public partial class PlayerSettingsGroup : SettingsToolboxGroup { public PlayerSettingsGroup(string title) : base(title) diff --git a/osu.Game/Screens/Play/PlayerSettings/PlayerSliderBar.cs b/osu.Game/Screens/Play/PlayerSettings/PlayerSliderBar.cs index 063056e83e..45d4995753 100644 --- a/osu.Game/Screens/Play/PlayerSettings/PlayerSliderBar.cs +++ b/osu.Game/Screens/Play/PlayerSettings/PlayerSliderBar.cs @@ -12,14 +12,14 @@ using osu.Game.Overlays.Settings; namespace osu.Game.Screens.Play.PlayerSettings { - public class PlayerSliderBar : SettingsSlider + public partial class PlayerSliderBar : SettingsSlider where T : struct, IEquatable, IComparable, IConvertible { public OsuSliderBar Bar => (OsuSliderBar)Control; protected override Drawable CreateControl() => new SliderBar(); - protected class SliderBar : OsuSliderBar + protected partial class SliderBar : OsuSliderBar { public SliderBar() { diff --git a/osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs b/osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs index 6a7eabc6a2..ff857ddb12 100644 --- a/osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs +++ b/osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs @@ -8,7 +8,7 @@ using osu.Game.Localisation; namespace osu.Game.Screens.Play.PlayerSettings { - public class VisualSettings : PlayerSettingsGroup + public partial class VisualSettings : PlayerSettingsGroup { private readonly PlayerSliderBar dimSliderBar; private readonly PlayerSliderBar blurSliderBar; diff --git a/osu.Game/Screens/Play/ReplayPlayer.cs b/osu.Game/Screens/Play/ReplayPlayer.cs index 5382e283e0..c5ef6b1585 100644 --- a/osu.Game/Screens/Play/ReplayPlayer.cs +++ b/osu.Game/Screens/Play/ReplayPlayer.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; using osu.Framework.Bindables; using osu.Framework.Input.Bindings; @@ -13,14 +12,13 @@ using osu.Framework.Input.Events; using osu.Game.Beatmaps; using osu.Game.Input.Bindings; using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.Objects; using osu.Game.Scoring; using osu.Game.Screens.Play.HUD; using osu.Game.Screens.Ranking; namespace osu.Game.Screens.Play { - public class ReplayPlayer : Player, IKeyBindingHandler + public partial class ReplayPlayer : Player, IKeyBindingHandler { private readonly Func, Score> createScore; @@ -94,7 +92,7 @@ namespace osu.Game.Screens.Play void keyboardSeek(int direction) { - double target = Math.Clamp(GameplayClockContainer.CurrentTime + direction * keyboard_seek_amount, 0, GameplayState.Beatmap.HitObjects.Last().GetEndTime()); + double target = Math.Clamp(GameplayClockContainer.CurrentTime + direction * keyboard_seek_amount, 0, GameplayState.Beatmap.GetLastObjectTime()); Seek(target); } diff --git a/osu.Game/Screens/Play/ReplayPlayerLoader.cs b/osu.Game/Screens/Play/ReplayPlayerLoader.cs index a961f90d00..1c9d694325 100644 --- a/osu.Game/Screens/Play/ReplayPlayerLoader.cs +++ b/osu.Game/Screens/Play/ReplayPlayerLoader.cs @@ -9,7 +9,7 @@ using osu.Game.Scoring; namespace osu.Game.Screens.Play { - public class ReplayPlayerLoader : PlayerLoader + public partial class ReplayPlayerLoader : PlayerLoader { public readonly ScoreInfo Score; diff --git a/osu.Game/Screens/Play/ResumeOverlay.cs b/osu.Game/Screens/Play/ResumeOverlay.cs index 7ed95c4ce3..fae406bd6b 100644 --- a/osu.Game/Screens/Play/ResumeOverlay.cs +++ b/osu.Game/Screens/Play/ResumeOverlay.cs @@ -19,7 +19,7 @@ namespace osu.Game.Screens.Play /// /// An overlay which can be used to require further user actions before gameplay is resumed. /// - public abstract class ResumeOverlay : VisibilityContainer + public abstract partial class ResumeOverlay : VisibilityContainer { public CursorContainer GameplayCursor { get; set; } diff --git a/osu.Game/Screens/Play/RoomSubmittingPlayer.cs b/osu.Game/Screens/Play/RoomSubmittingPlayer.cs index 3eb659664a..e21daa737e 100644 --- a/osu.Game/Screens/Play/RoomSubmittingPlayer.cs +++ b/osu.Game/Screens/Play/RoomSubmittingPlayer.cs @@ -13,7 +13,7 @@ namespace osu.Game.Screens.Play /// /// A player instance which submits to a room backing. This is generally used by playlists and multiplayer. /// - public abstract class RoomSubmittingPlayer : SubmittingPlayer + public abstract partial class RoomSubmittingPlayer : SubmittingPlayer { protected readonly PlaylistItem PlaylistItem; protected readonly Room Room; diff --git a/osu.Game/Screens/Play/SaveFailedScoreButton.cs b/osu.Game/Screens/Play/SaveFailedScoreButton.cs index 7358ff3de4..20d2130e76 100644 --- a/osu.Game/Screens/Play/SaveFailedScoreButton.cs +++ b/osu.Game/Screens/Play/SaveFailedScoreButton.cs @@ -16,7 +16,7 @@ using osuTK; namespace osu.Game.Screens.Play { - public class SaveFailedScoreButton : CompositeDrawable + public partial class SaveFailedScoreButton : CompositeDrawable { private readonly Bindable state = new Bindable(); diff --git a/osu.Game/Screens/Play/ScreenSuspensionHandler.cs b/osu.Game/Screens/Play/ScreenSuspensionHandler.cs index cc1254975c..85948ea3f7 100644 --- a/osu.Game/Screens/Play/ScreenSuspensionHandler.cs +++ b/osu.Game/Screens/Play/ScreenSuspensionHandler.cs @@ -15,7 +15,7 @@ namespace osu.Game.Screens.Play /// /// Ensures screen is not suspended / dimmed while gameplay is active. /// - public class ScreenSuspensionHandler : Component + public partial class ScreenSuspensionHandler : Component { private readonly GameplayClockContainer gameplayClockContainer; private IBindable isPaused; diff --git a/osu.Game/Screens/Play/ScreenWithBeatmapBackground.cs b/osu.Game/Screens/Play/ScreenWithBeatmapBackground.cs index 7152fb7473..d6c8a0ad6a 100644 --- a/osu.Game/Screens/Play/ScreenWithBeatmapBackground.cs +++ b/osu.Game/Screens/Play/ScreenWithBeatmapBackground.cs @@ -8,7 +8,7 @@ using osu.Game.Screens.Backgrounds; namespace osu.Game.Screens.Play { - public abstract class ScreenWithBeatmapBackground : OsuScreen + public abstract partial class ScreenWithBeatmapBackground : OsuScreen { protected override BackgroundScreen CreateBackground() => new BackgroundScreenBeatmap(Beatmap.Value); diff --git a/osu.Game/Screens/Play/SkipOverlay.cs b/osu.Game/Screens/Play/SkipOverlay.cs index 99fe659bf3..7d69f0ca18 100644 --- a/osu.Game/Screens/Play/SkipOverlay.cs +++ b/osu.Game/Screens/Play/SkipOverlay.cs @@ -25,7 +25,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.Play { - public class SkipOverlay : CompositeDrawable, IKeyBindingHandler + public partial class SkipOverlay : CompositeDrawable, IKeyBindingHandler { /// /// The total number of successful skips performed by this overlay. @@ -209,7 +209,7 @@ namespace osu.Game.Screens.Play { } - public class FadeContainer : Container, IStateful + public partial class FadeContainer : Container, IStateful { public event Action StateChanged; @@ -287,14 +287,14 @@ namespace osu.Game.Screens.Play public override void Show() => State = Visibility.Visible; } - private class ButtonContainer : VisibilityContainer + private partial class ButtonContainer : VisibilityContainer { protected override void PopIn() => this.FadeIn(fade_time); protected override void PopOut() => this.FadeOut(fade_time); } - private class Button : OsuClickableContainer + private partial class Button : OsuClickableContainer { private Color4 colourNormal; private Color4 colourHover; diff --git a/osu.Game/Screens/Play/SoloPlayer.cs b/osu.Game/Screens/Play/SoloPlayer.cs index ee19391b89..dafdf00136 100644 --- a/osu.Game/Screens/Play/SoloPlayer.cs +++ b/osu.Game/Screens/Play/SoloPlayer.cs @@ -17,7 +17,7 @@ using osu.Game.Screens.Play.HUD; namespace osu.Game.Screens.Play { - public class SoloPlayer : SubmittingPlayer + public partial class SoloPlayer : SubmittingPlayer { public SoloPlayer() : this(null) diff --git a/osu.Game/Screens/Play/SoloSpectator.cs b/osu.Game/Screens/Play/SoloSpectator.cs index 9ef05c3a05..a5c84e97ab 100644 --- a/osu.Game/Screens/Play/SoloSpectator.cs +++ b/osu.Game/Screens/Play/SoloSpectator.cs @@ -18,7 +18,7 @@ using osu.Game.Beatmaps.Drawables.Cards; using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; +using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; @@ -33,7 +33,7 @@ using osuTK; namespace osu.Game.Screens.Play { [Cached(typeof(IPreviewTrackOwner))] - public class SoloSpectator : SpectatorScreen, IPreviewTrackOwner + public partial class SoloSpectator : SpectatorScreen, IPreviewTrackOwner { [NotNull] private readonly APIUser targetUser; @@ -54,7 +54,7 @@ namespace osu.Game.Screens.Play private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple); private Container beatmapPanelContainer; - private TriangleButton watchButton; + private RoundedButton watchButton; private SettingsCheckbox automaticDownload; /// @@ -147,7 +147,7 @@ namespace osu.Game.Screens.Play Anchor = Anchor.Centre, Origin = Anchor.Centre, }, - watchButton = new PurpleTriangleButton + watchButton = new PurpleRoundedButton { Text = "Start Watching", Width = 250, diff --git a/osu.Game/Screens/Play/SoloSpectatorPlayer.cs b/osu.Game/Screens/Play/SoloSpectatorPlayer.cs index 5aa310750b..240fbcf662 100644 --- a/osu.Game/Screens/Play/SoloSpectatorPlayer.cs +++ b/osu.Game/Screens/Play/SoloSpectatorPlayer.cs @@ -10,7 +10,7 @@ using osu.Game.Scoring; namespace osu.Game.Screens.Play { - public class SoloSpectatorPlayer : SpectatorPlayer + public partial class SoloSpectatorPlayer : SpectatorPlayer { private readonly Score score; diff --git a/osu.Game/Screens/Play/SpectatorPlayer.cs b/osu.Game/Screens/Play/SpectatorPlayer.cs index 68cc21fc1c..30a5ac3741 100644 --- a/osu.Game/Screens/Play/SpectatorPlayer.cs +++ b/osu.Game/Screens/Play/SpectatorPlayer.cs @@ -18,7 +18,7 @@ using osu.Game.Screens.Ranking; namespace osu.Game.Screens.Play { - public abstract class SpectatorPlayer : Player + public abstract partial class SpectatorPlayer : Player { [Resolved] protected SpectatorClient SpectatorClient { get; private set; } diff --git a/osu.Game/Screens/Play/SpectatorPlayerLoader.cs b/osu.Game/Screens/Play/SpectatorPlayerLoader.cs index 6b664a4f96..3830443ce8 100644 --- a/osu.Game/Screens/Play/SpectatorPlayerLoader.cs +++ b/osu.Game/Screens/Play/SpectatorPlayerLoader.cs @@ -9,7 +9,7 @@ using osu.Game.Scoring; namespace osu.Game.Screens.Play { - public class SpectatorPlayerLoader : PlayerLoader + public partial class SpectatorPlayerLoader : PlayerLoader { public readonly ScoreInfo Score; diff --git a/osu.Game/Screens/Play/SpectatorResultsScreen.cs b/osu.Game/Screens/Play/SpectatorResultsScreen.cs index 3d320bd294..b54dbb387a 100644 --- a/osu.Game/Screens/Play/SpectatorResultsScreen.cs +++ b/osu.Game/Screens/Play/SpectatorResultsScreen.cs @@ -11,7 +11,7 @@ using osu.Game.Screens.Ranking; namespace osu.Game.Screens.Play { - public class SpectatorResultsScreen : SoloResultsScreen + public partial class SpectatorResultsScreen : SoloResultsScreen { public SpectatorResultsScreen(ScoreInfo score) : base(score, false) diff --git a/osu.Game/Screens/Play/SquareGraph.cs b/osu.Game/Screens/Play/SquareGraph.cs index 9ac673ae52..57b7c84e89 100644 --- a/osu.Game/Screens/Play/SquareGraph.cs +++ b/osu.Game/Screens/Play/SquareGraph.cs @@ -19,7 +19,7 @@ using osu.Framework.Threading; namespace osu.Game.Screens.Play { - public class SquareGraph : Container + public partial class SquareGraph : Container { private BufferedContainer columns; @@ -176,7 +176,7 @@ namespace osu.Game.Screens.Play calculatedValues = newValues.ToArray(); } - public class Column : Container, IStateful + public partial class Column : Container, IStateful { protected readonly Color4 EmptyColour = Color4.White.Opacity(20); public Color4 LitColour = Color4.LightBlue; diff --git a/osu.Game/Screens/Play/SubmittingPlayer.cs b/osu.Game/Screens/Play/SubmittingPlayer.cs index fb296d7988..5fa6508a31 100644 --- a/osu.Game/Screens/Play/SubmittingPlayer.cs +++ b/osu.Game/Screens/Play/SubmittingPlayer.cs @@ -13,6 +13,7 @@ using osu.Framework.Screens; using osu.Game.Beatmaps; using osu.Game.Database; using osu.Game.Online.API; +using osu.Game.Online.Multiplayer; using osu.Game.Online.Rooms; using osu.Game.Online.Spectator; using osu.Game.Rulesets.Scoring; @@ -23,7 +24,7 @@ namespace osu.Game.Screens.Play /// /// A player instance which supports submitting scores to an online store. /// - public abstract class SubmittingPlayer : Player + public abstract partial class SubmittingPlayer : Player { /// /// The token to be used for the current submission. This is fetched via a request created by . @@ -130,6 +131,7 @@ namespace osu.Game.Screens.Play score.ScoreInfo.Date = DateTimeOffset.Now; await submitScore(score).ConfigureAwait(false); + spectatorClient.EndPlaying(GameplayState); } [Resolved] @@ -148,7 +150,7 @@ namespace osu.Game.Screens.Play realmBeatmap.LastPlayed = DateTimeOffset.Now; }); - spectatorClient.BeginPlaying(GameplayState, Score); + spectatorClient.BeginPlaying(token, GameplayState, Score); } public override bool OnExiting(ScreenExitEvent e) @@ -157,8 +159,11 @@ namespace osu.Game.Screens.Play if (LoadedBeatmapSuccessfully) { - submitScore(Score.DeepClone()); - spectatorClient.EndPlaying(GameplayState); + Task.Run(async () => + { + await submitScore(Score.DeepClone()).ConfigureAwait(false); + spectatorClient.EndPlaying(GameplayState); + }).FireAndForget(); } return exiting; diff --git a/osu.Game/Screens/Ranking/AspectContainer.cs b/osu.Game/Screens/Ranking/AspectContainer.cs index 1c93d08474..9ec2a15044 100644 --- a/osu.Game/Screens/Ranking/AspectContainer.cs +++ b/osu.Game/Screens/Ranking/AspectContainer.cs @@ -8,7 +8,7 @@ using osu.Framework.Graphics.Containers; namespace osu.Game.Screens.Ranking { - public class AspectContainer : Container + public partial class AspectContainer : Container { protected override void Update() { diff --git a/osu.Game/Screens/Ranking/Contracted/ContractedPanelMiddleContent.cs b/osu.Game/Screens/Ranking/Contracted/ContractedPanelMiddleContent.cs index 3e67868f34..402322c611 100644 --- a/osu.Game/Screens/Ranking/Contracted/ContractedPanelMiddleContent.cs +++ b/osu.Game/Screens/Ranking/Contracted/ContractedPanelMiddleContent.cs @@ -31,7 +31,7 @@ namespace osu.Game.Screens.Ranking.Contracted /// /// The content that appears in the middle of a contracted . /// - public class ContractedPanelMiddleContent : CompositeDrawable + public partial class ContractedPanelMiddleContent : CompositeDrawable { private readonly ScoreInfo score; diff --git a/osu.Game/Screens/Ranking/Contracted/ContractedPanelTopContent.cs b/osu.Game/Screens/Ranking/Contracted/ContractedPanelTopContent.cs index 74b2f4ef93..93bc7c41e1 100644 --- a/osu.Game/Screens/Ranking/Contracted/ContractedPanelTopContent.cs +++ b/osu.Game/Screens/Ranking/Contracted/ContractedPanelTopContent.cs @@ -12,7 +12,7 @@ using osu.Game.Graphics.Sprites; namespace osu.Game.Screens.Ranking.Contracted { - public class ContractedPanelTopContent : CompositeDrawable + public partial class ContractedPanelTopContent : CompositeDrawable { public readonly Bindable ScorePosition = new Bindable(); diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs index a1879c5c9b..8e04bb68fb 100644 --- a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs +++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs @@ -12,6 +12,7 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.UserInterface; using osu.Framework.Utils; using osu.Game.Audio; using osu.Game.Graphics; @@ -25,7 +26,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy /// /// The component that displays the player's accuracy on the results screen. /// - public class AccuracyCircle : CompositeDrawable + public partial class AccuracyCircle : CompositeDrawable { /// /// Duration for the transforms causing this component to appear. @@ -79,8 +80,8 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy private readonly ScoreInfo score; - private SmoothCircularProgress accuracyCircle; - private SmoothCircularProgress innerMask; + private CircularProgress accuracyCircle; + private CircularProgress innerMask; private Container badges; private RankText rankText; @@ -109,7 +110,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy { InternalChildren = new Drawable[] { - new SmoothCircularProgress + new CircularProgress { Name = "Background circle", Anchor = Anchor.Centre, @@ -120,7 +121,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy InnerRadius = accuracy_circle_radius + 0.01f, // Extends a little bit into the circle Current = { Value = 1 }, }, - accuracyCircle = new SmoothCircularProgress + accuracyCircle = new CircularProgress { Name = "Accuracy circle", Anchor = Anchor.Centre, @@ -139,42 +140,42 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy Padding = new MarginPadding(2), Children = new Drawable[] { - new SmoothCircularProgress + new CircularProgress { RelativeSizeAxes = Axes.Both, Colour = OsuColour.ForRank(ScoreRank.X), InnerRadius = RANK_CIRCLE_RADIUS, Current = { Value = 1 } }, - new SmoothCircularProgress + new CircularProgress { RelativeSizeAxes = Axes.Both, Colour = OsuColour.ForRank(ScoreRank.S), InnerRadius = RANK_CIRCLE_RADIUS, Current = { Value = 1 - virtual_ss_percentage } }, - new SmoothCircularProgress + new CircularProgress { RelativeSizeAxes = Axes.Both, Colour = OsuColour.ForRank(ScoreRank.A), InnerRadius = RANK_CIRCLE_RADIUS, Current = { Value = 0.95f } }, - new SmoothCircularProgress + new CircularProgress { RelativeSizeAxes = Axes.Both, Colour = OsuColour.ForRank(ScoreRank.B), InnerRadius = RANK_CIRCLE_RADIUS, Current = { Value = 0.9f } }, - new SmoothCircularProgress + new CircularProgress { RelativeSizeAxes = Axes.Both, Colour = OsuColour.ForRank(ScoreRank.C), InnerRadius = RANK_CIRCLE_RADIUS, Current = { Value = 0.8f } }, - new SmoothCircularProgress + new CircularProgress { RelativeSizeAxes = Axes.Both, Colour = OsuColour.ForRank(ScoreRank.D), @@ -195,14 +196,14 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy Blending = new BlendingParameters { Source = BlendingType.DstColor, - Destination = BlendingType.OneMinusSrcAlpha, + Destination = BlendingType.OneMinusSrcColor, SourceAlpha = BlendingType.One, DestinationAlpha = BlendingType.SrcAlpha }, - Child = innerMask = new SmoothCircularProgress + Child = innerMask = new CircularProgress { RelativeSizeAxes = Axes.Both, - InnerRadius = RANK_CIRCLE_RADIUS - 0.01f, + InnerRadius = RANK_CIRCLE_RADIUS - 0.02f, } } } diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/RankBadge.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/RankBadge.cs index 80415dbbc2..5432b4cbeb 100644 --- a/osu.Game/Screens/Ranking/Expanded/Accuracy/RankBadge.cs +++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/RankBadge.cs @@ -20,7 +20,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy /// /// Contains a that is positioned around the . /// - public class RankBadge : CompositeDrawable + public partial class RankBadge : CompositeDrawable { /// /// The accuracy value corresponding to the displayed by this badge. diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/RankNotch.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/RankNotch.cs index 573833932f..7e73767318 100644 --- a/osu.Game/Screens/Ranking/Expanded/Accuracy/RankNotch.cs +++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/RankNotch.cs @@ -15,7 +15,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy /// /// A solid "notch" of the that appears at the ends of the rank circles to add separation. /// - public class RankNotch : CompositeDrawable + public partial class RankNotch : CompositeDrawable { private readonly float position; diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/RankText.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/RankText.cs index 2d9c1f9d07..b7adcb032f 100644 --- a/osu.Game/Screens/Ranking/Expanded/Accuracy/RankText.cs +++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/RankText.cs @@ -19,7 +19,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy /// /// The text that appears in the middle of the displaying the user's rank. /// - public class RankText : CompositeDrawable + public partial class RankText : CompositeDrawable { private readonly ScoreRank rank; diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/SmoothCircularProgress.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/SmoothCircularProgress.cs deleted file mode 100644 index b4f41e0f39..0000000000 --- a/osu.Game/Screens/Ranking/Expanded/Accuracy/SmoothCircularProgress.cs +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -#nullable disable - -using osu.Framework.Bindables; -using osu.Framework.Extensions.Color4Extensions; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Transforms; -using osu.Framework.Graphics.UserInterface; -using osu.Game.Graphics; -using osuTK; - -namespace osu.Game.Screens.Ranking.Expanded.Accuracy -{ - /// - /// Contains a with smoothened edges. - /// - public class SmoothCircularProgress : CompositeDrawable - { - public Bindable Current - { - get => progress.Current; - set => progress.Current = value; - } - - public float InnerRadius - { - get => progress.InnerRadius; - set - { - progress.InnerRadius = value; - innerSmoothingContainer.Size = new Vector2(1 - value); - smoothingWedge.Height = value / 2; - } - } - - private readonly CircularProgress progress; - private readonly Container innerSmoothingContainer; - private readonly Drawable smoothingWedge; - - public SmoothCircularProgress() - { - Container smoothingWedgeContainer; - - InternalChild = new BufferedContainer - { - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - progress = new CircularProgress { RelativeSizeAxes = Axes.Both }, - smoothingWedgeContainer = new Container - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Child = smoothingWedge = new Box - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - RelativeSizeAxes = Axes.Y, - Width = 1f, - EdgeSmoothness = new Vector2(2, 0), - } - }, - new Container - { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding(-1), - Child = new CircularContainer - { - RelativeSizeAxes = Axes.Both, - BorderThickness = 2, - Masking = true, - BorderColour = OsuColour.Gray(0.5f).Opacity(0.75f), - Blending = new BlendingParameters - { - AlphaEquation = BlendingEquation.ReverseSubtract, - }, - Child = new Box - { - RelativeSizeAxes = Axes.Both, - Alpha = 0, - AlwaysPresent = true - } - } - }, - innerSmoothingContainer = new Container - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Size = Vector2.Zero, - Padding = new MarginPadding(-1), - Child = new CircularContainer - { - RelativeSizeAxes = Axes.Both, - BorderThickness = 2, - BorderColour = OsuColour.Gray(0.5f).Opacity(0.75f), - Masking = true, - Blending = new BlendingParameters - { - AlphaEquation = BlendingEquation.ReverseSubtract, - }, - Child = new Box - { - RelativeSizeAxes = Axes.Both, - Alpha = 0, - AlwaysPresent = true - } - } - }, - } - }; - - Current.BindValueChanged(c => - { - smoothingWedgeContainer.Alpha = c.NewValue > 0 ? 1 : 0; - smoothingWedgeContainer.Rotation = (float)(360 * c.NewValue); - }, true); - } - - public TransformSequence FillTo(double newValue, double duration = 0, Easing easing = Easing.None) - => progress.FillTo(newValue, duration, easing); - } -} diff --git a/osu.Game/Screens/Ranking/Expanded/ExpandedPanelMiddleContent.cs b/osu.Game/Screens/Ranking/Expanded/ExpandedPanelMiddleContent.cs index 829ba83696..f23b469f5c 100644 --- a/osu.Game/Screens/Ranking/Expanded/ExpandedPanelMiddleContent.cs +++ b/osu.Game/Screens/Ranking/Expanded/ExpandedPanelMiddleContent.cs @@ -9,6 +9,7 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions; +using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Localisation; @@ -31,7 +32,7 @@ namespace osu.Game.Screens.Ranking.Expanded /// /// The content that appears in the middle section of the . /// - public class ExpandedPanelMiddleContent : CompositeDrawable + public partial class ExpandedPanelMiddleContent : CompositeDrawable { private const float padding = 10; @@ -280,7 +281,7 @@ namespace osu.Game.Screens.Ranking.Expanded }); } - public class PlayedOnText : OsuSpriteText + public partial class PlayedOnText : OsuSpriteText { private readonly DateTimeOffset time; private readonly Bindable prefer24HourTime = new Bindable(); @@ -309,7 +310,8 @@ namespace osu.Game.Screens.Ranking.Expanded private void updateDisplay() { - Text = prefer24HourTime.Value ? $"Played on {time.ToLocalTime():d MMMM yyyy HH:mm}" : $"Played on {time.ToLocalTime():d MMMM yyyy h:mm tt}"; + Text = LocalisableString.Format("Played on {0}", + time.ToLocalTime().ToLocalisableString(prefer24HourTime.Value ? @"d MMMM yyyy HH:mm" : @"d MMMM yyyy h:mm tt")); } } } diff --git a/osu.Game/Screens/Ranking/Expanded/ExpandedPanelTopContent.cs b/osu.Game/Screens/Ranking/Expanded/ExpandedPanelTopContent.cs index 2708090855..c834d541eb 100644 --- a/osu.Game/Screens/Ranking/Expanded/ExpandedPanelTopContent.cs +++ b/osu.Game/Screens/Ranking/Expanded/ExpandedPanelTopContent.cs @@ -19,7 +19,7 @@ namespace osu.Game.Screens.Ranking.Expanded /// /// The content that appears in the middle section of the . /// - public class ExpandedPanelTopContent : CompositeDrawable + public partial class ExpandedPanelTopContent : CompositeDrawable { private readonly APIUser user; diff --git a/osu.Game/Screens/Ranking/Expanded/Statistics/AccuracyStatistic.cs b/osu.Game/Screens/Ranking/Expanded/Statistics/AccuracyStatistic.cs index 824156598c..4b8c057235 100644 --- a/osu.Game/Screens/Ranking/Expanded/Statistics/AccuracyStatistic.cs +++ b/osu.Game/Screens/Ranking/Expanded/Statistics/AccuracyStatistic.cs @@ -18,7 +18,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Statistics /// /// A to display the player's accuracy. /// - public class AccuracyStatistic : StatisticDisplay + public partial class AccuracyStatistic : StatisticDisplay { private readonly double accuracy; @@ -42,7 +42,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Statistics protected override Drawable CreateContent() => counter = new Counter(); - private class Counter : RollingCounter + private partial class Counter : RollingCounter { protected override double RollingDuration => AccuracyCircle.ACCURACY_TRANSFORM_DURATION; diff --git a/osu.Game/Screens/Ranking/Expanded/Statistics/ComboStatistic.cs b/osu.Game/Screens/Ranking/Expanded/Statistics/ComboStatistic.cs index 3505786b64..6290cee6da 100644 --- a/osu.Game/Screens/Ranking/Expanded/Statistics/ComboStatistic.cs +++ b/osu.Game/Screens/Ranking/Expanded/Statistics/ComboStatistic.cs @@ -18,7 +18,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Statistics /// /// A to display the player's combo. /// - public class ComboStatistic : CounterStatistic + public partial class ComboStatistic : CounterStatistic { private readonly bool isPerfect; diff --git a/osu.Game/Screens/Ranking/Expanded/Statistics/CounterStatistic.cs b/osu.Game/Screens/Ranking/Expanded/Statistics/CounterStatistic.cs index 17a12a76a5..8528dac83b 100644 --- a/osu.Game/Screens/Ranking/Expanded/Statistics/CounterStatistic.cs +++ b/osu.Game/Screens/Ranking/Expanded/Statistics/CounterStatistic.cs @@ -16,7 +16,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Statistics /// /// A to display general numeric values. /// - public class CounterStatistic : StatisticDisplay + public partial class CounterStatistic : StatisticDisplay { private readonly int count; private readonly int? maxCount; diff --git a/osu.Game/Screens/Ranking/Expanded/Statistics/HitResultStatistic.cs b/osu.Game/Screens/Ranking/Expanded/Statistics/HitResultStatistic.cs index c23a5e668d..863c450617 100644 --- a/osu.Game/Screens/Ranking/Expanded/Statistics/HitResultStatistic.cs +++ b/osu.Game/Screens/Ranking/Expanded/Statistics/HitResultStatistic.cs @@ -10,7 +10,7 @@ using osu.Game.Scoring; namespace osu.Game.Screens.Ranking.Expanded.Statistics { - public class HitResultStatistic : CounterStatistic + public partial class HitResultStatistic : CounterStatistic { public readonly HitResult Result; diff --git a/osu.Game/Screens/Ranking/Expanded/Statistics/PerformanceStatistic.cs b/osu.Game/Screens/Ranking/Expanded/Statistics/PerformanceStatistic.cs index 332215e15d..22509b2cea 100644 --- a/osu.Game/Screens/Ranking/Expanded/Statistics/PerformanceStatistic.cs +++ b/osu.Game/Screens/Ranking/Expanded/Statistics/PerformanceStatistic.cs @@ -15,7 +15,7 @@ using osu.Game.Scoring; namespace osu.Game.Screens.Ranking.Expanded.Statistics { - public class PerformanceStatistic : StatisticDisplay + public partial class PerformanceStatistic : StatisticDisplay { private readonly ScoreInfo score; diff --git a/osu.Game/Screens/Ranking/Expanded/Statistics/StatisticCounter.cs b/osu.Game/Screens/Ranking/Expanded/Statistics/StatisticCounter.cs index 36d6d6fa7c..ecadc9eed6 100644 --- a/osu.Game/Screens/Ranking/Expanded/Statistics/StatisticCounter.cs +++ b/osu.Game/Screens/Ranking/Expanded/Statistics/StatisticCounter.cs @@ -12,7 +12,7 @@ using osuTK; namespace osu.Game.Screens.Ranking.Expanded.Statistics { - public class StatisticCounter : RollingCounter + public partial class StatisticCounter : RollingCounter { protected override double RollingDuration => AccuracyCircle.ACCURACY_TRANSFORM_DURATION; diff --git a/osu.Game/Screens/Ranking/Expanded/Statistics/StatisticDisplay.cs b/osu.Game/Screens/Ranking/Expanded/Statistics/StatisticDisplay.cs index 0d8dcda895..686b6c7d47 100644 --- a/osu.Game/Screens/Ranking/Expanded/Statistics/StatisticDisplay.cs +++ b/osu.Game/Screens/Ranking/Expanded/Statistics/StatisticDisplay.cs @@ -19,7 +19,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Statistics /// /// A statistic from the score to be displayed in the . /// - public abstract class StatisticDisplay : CompositeDrawable + public abstract partial class StatisticDisplay : CompositeDrawable { protected SpriteText HeaderText { get; private set; } diff --git a/osu.Game/Screens/Ranking/Expanded/TotalScoreCounter.cs b/osu.Game/Screens/Ranking/Expanded/TotalScoreCounter.cs index c7286a1838..b017a3a63d 100644 --- a/osu.Game/Screens/Ranking/Expanded/TotalScoreCounter.cs +++ b/osu.Game/Screens/Ranking/Expanded/TotalScoreCounter.cs @@ -20,7 +20,7 @@ namespace osu.Game.Screens.Ranking.Expanded /// /// A counter for the player's total score to be displayed in the . /// - public class TotalScoreCounter : RollingCounter + public partial class TotalScoreCounter : RollingCounter { protected override double RollingDuration => AccuracyCircle.ACCURACY_TRANSFORM_DURATION; diff --git a/osu.Game/Screens/Ranking/ReplayDownloadButton.cs b/osu.Game/Screens/Ranking/ReplayDownloadButton.cs index 7081a0156e..5c5cb61b79 100644 --- a/osu.Game/Screens/Ranking/ReplayDownloadButton.cs +++ b/osu.Game/Screens/Ranking/ReplayDownloadButton.cs @@ -15,7 +15,7 @@ using osuTK; namespace osu.Game.Screens.Ranking { - public class ReplayDownloadButton : CompositeDrawable + public partial class ReplayDownloadButton : CompositeDrawable { public readonly Bindable Score = new Bindable(); diff --git a/osu.Game/Screens/Ranking/ResultsScreen.cs b/osu.Game/Screens/Ranking/ResultsScreen.cs index 486df8653f..78239e0dbe 100644 --- a/osu.Game/Screens/Ranking/ResultsScreen.cs +++ b/osu.Game/Screens/Ranking/ResultsScreen.cs @@ -29,7 +29,7 @@ using osuTK; namespace osu.Game.Screens.Ranking { - public abstract class ResultsScreen : ScreenWithBeatmapBackground, IKeyBindingHandler + public abstract partial class ResultsScreen : ScreenWithBeatmapBackground, IKeyBindingHandler { protected const float BACKGROUND_BLUR = 20; private static readonly float screen_height = 768 - TwoLayerButton.SIZE_EXTENDED.Y; @@ -96,11 +96,11 @@ namespace osu.Game.Screens.Ranking RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - statisticsPanel = new StatisticsPanel + statisticsPanel = CreateStatisticsPanel().With(panel => { - RelativeSizeAxes = Axes.Both, - Score = { BindTarget = SelectedScore } - }, + panel.RelativeSizeAxes = Axes.Both; + panel.Score.BindTarget = SelectedScore; + }), ScorePanelList = new ScorePanelList { RelativeSizeAxes = Axes.Both, @@ -231,6 +231,11 @@ namespace osu.Game.Screens.Ranking /// An responsible for the fetch operation. This will be queued and performed automatically. protected virtual APIRequest FetchNextPage(int direction, Action> scoresCallback) => null; + /// + /// Creates the to be used to display extended information about scores. + /// + protected virtual StatisticsPanel CreateStatisticsPanel() => new StatisticsPanel(); + private void fetchScoresCallback(IEnumerable scores) => Schedule(() => { foreach (var s in scores) @@ -357,7 +362,7 @@ namespace osu.Game.Screens.Ranking { } - protected class VerticalScrollContainer : OsuScrollContainer + protected partial class VerticalScrollContainer : OsuScrollContainer { protected override Container Content => content; diff --git a/osu.Game/Screens/Ranking/RetryButton.cs b/osu.Game/Screens/Ranking/RetryButton.cs index c56f364ae8..c7d2416e29 100644 --- a/osu.Game/Screens/Ranking/RetryButton.cs +++ b/osu.Game/Screens/Ranking/RetryButton.cs @@ -14,7 +14,7 @@ using osuTK; namespace osu.Game.Screens.Ranking { - public class RetryButton : OsuAnimatedButton + public partial class RetryButton : OsuAnimatedButton { private readonly Box background; diff --git a/osu.Game/Screens/Ranking/ScorePanel.cs b/osu.Game/Screens/Ranking/ScorePanel.cs index cb777de144..1d332d6b27 100644 --- a/osu.Game/Screens/Ranking/ScorePanel.cs +++ b/osu.Game/Screens/Ranking/ScorePanel.cs @@ -25,7 +25,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.Ranking { - public class ScorePanel : CompositeDrawable, IStateful + public partial class ScorePanel : CompositeDrawable, IStateful { /// /// Width of the panel when contracted. @@ -225,7 +225,7 @@ namespace osu.Game.Screens.Ranking protected override void Update() { base.Update(); - audioContent.Balance.Value = (ScreenSpaceDrawQuad.Centre.X / game.ScreenSpaceDrawQuad.Width) * 2 - 1; + audioContent.Balance.Value = ((ScreenSpaceDrawQuad.Centre.X / game.ScreenSpaceDrawQuad.Width) * 2 - 1) * OsuGameBase.SFX_STEREO_STRENGTH; } private void playAppearSample() diff --git a/osu.Game/Screens/Ranking/ScorePanelList.cs b/osu.Game/Screens/Ranking/ScorePanelList.cs index 46f9efd126..29dec42083 100644 --- a/osu.Game/Screens/Ranking/ScorePanelList.cs +++ b/osu.Game/Screens/Ranking/ScorePanelList.cs @@ -21,7 +21,7 @@ using osuTK.Input; namespace osu.Game.Screens.Ranking { - public class ScorePanelList : CompositeDrawable + public partial class ScorePanelList : CompositeDrawable { /// /// Normal spacing between all panels. @@ -322,7 +322,7 @@ namespace osu.Game.Screens.Ranking loadCancellationSource?.Cancel(); } - private class Flow : FillFlowContainer + private partial class Flow : FillFlowContainer { public override IEnumerable FlowingChildren => applySorting(AliveInternalChildren); @@ -339,7 +339,7 @@ namespace osu.Game.Screens.Ranking .ThenBy(s => s.Panel.Score.OnlineID); } - private class Scroll : OsuScrollContainer + private partial class Scroll : OsuScrollContainer { public new float Target => base.Target; diff --git a/osu.Game/Screens/Ranking/ScorePanelTrackingContainer.cs b/osu.Game/Screens/Ranking/ScorePanelTrackingContainer.cs index b4d6d481ef..ec153cbd63 100644 --- a/osu.Game/Screens/Ranking/ScorePanelTrackingContainer.cs +++ b/osu.Game/Screens/Ranking/ScorePanelTrackingContainer.cs @@ -11,7 +11,7 @@ namespace osu.Game.Screens.Ranking /// /// A which tracks the size of a , to which the can be added or removed. /// - public class ScorePanelTrackingContainer : CompositeDrawable + public partial class ScorePanelTrackingContainer : CompositeDrawable { /// /// The that created this . diff --git a/osu.Game/Screens/Ranking/SoloResultsScreen.cs b/osu.Game/Screens/Ranking/SoloResultsScreen.cs index 4312c9528f..c8920a734d 100644 --- a/osu.Game/Screens/Ranking/SoloResultsScreen.cs +++ b/osu.Game/Screens/Ranking/SoloResultsScreen.cs @@ -1,33 +1,67 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Game.Beatmaps; using osu.Game.Online.API; using osu.Game.Online.API.Requests; +using osu.Game.Online.Solo; using osu.Game.Rulesets; using osu.Game.Scoring; +using osu.Game.Screens.Ranking.Statistics; namespace osu.Game.Screens.Ranking { - public class SoloResultsScreen : ResultsScreen + public partial class SoloResultsScreen : ResultsScreen { - private GetScoresRequest getScoreRequest; + /// + /// Whether the user's personal statistics should be shown on the extended statistics panel + /// after clicking the score panel associated with the being presented. + /// + public bool ShowUserStatistics { get; init; } + + private GetScoresRequest? getScoreRequest; [Resolved] - private RulesetStore rulesets { get; set; } + private RulesetStore rulesets { get; set; } = null!; + + [Resolved] + private SoloStatisticsWatcher soloStatisticsWatcher { get; set; } = null!; + + private IDisposable? statisticsSubscription; + private readonly Bindable statisticsUpdate = new Bindable(); public SoloResultsScreen(ScoreInfo score, bool allowRetry) : base(score, allowRetry) { } - protected override APIRequest FetchScores(Action> scoresCallback) + protected override void LoadComplete() + { + base.LoadComplete(); + + if (ShowUserStatistics) + statisticsSubscription = soloStatisticsWatcher.RegisterForStatisticsUpdateAfter(Score, update => statisticsUpdate.Value = update); + } + + protected override StatisticsPanel CreateStatisticsPanel() + { + if (ShowUserStatistics) + { + return new SoloStatisticsPanel(Score) + { + StatisticsUpdate = { BindTarget = statisticsUpdate } + }; + } + + return base.CreateStatisticsPanel(); + } + + protected override APIRequest? FetchScores(Action>? scoresCallback) { if (Score.BeatmapInfo.OnlineID <= 0 || Score.BeatmapInfo.Status <= BeatmapOnlineStatus.Pending) return null; @@ -42,6 +76,7 @@ namespace osu.Game.Screens.Ranking base.Dispose(isDisposing); getScoreRequest?.Cancel(); + statisticsSubscription?.Dispose(); } } } diff --git a/osu.Game/Screens/Ranking/Statistics/AverageHitError.cs b/osu.Game/Screens/Ranking/Statistics/AverageHitError.cs index a0a9c1c1e2..bb9905d29c 100644 --- a/osu.Game/Screens/Ranking/Statistics/AverageHitError.cs +++ b/osu.Game/Screens/Ranking/Statistics/AverageHitError.cs @@ -12,7 +12,7 @@ namespace osu.Game.Screens.Ranking.Statistics /// /// Displays the unstable rate statistic for a given play. /// - public class AverageHitError : SimpleStatisticItem + public partial class AverageHitError : SimpleStatisticItem { /// /// Creates and computes an statistic. diff --git a/osu.Game/Screens/Ranking/Statistics/HitEventTimingDistributionGraph.cs b/osu.Game/Screens/Ranking/Statistics/HitEventTimingDistributionGraph.cs index 764237ef96..6b1850002d 100644 --- a/osu.Game/Screens/Ranking/Statistics/HitEventTimingDistributionGraph.cs +++ b/osu.Game/Screens/Ranking/Statistics/HitEventTimingDistributionGraph.cs @@ -18,7 +18,7 @@ namespace osu.Game.Screens.Ranking.Statistics /// /// A graph which displays the distribution of hit timing in a series of s. /// - public class HitEventTimingDistributionGraph : CompositeDrawable + public partial class HitEventTimingDistributionGraph : CompositeDrawable { /// /// The number of bins on each side of the timing distribution. @@ -204,7 +204,7 @@ namespace osu.Game.Screens.Ranking.Statistics } } - private class Bar : CompositeDrawable + private partial class Bar : CompositeDrawable { private readonly IReadOnlyList> values; private readonly float maxValue; diff --git a/osu.Game/Screens/Ranking/Statistics/PerformanceBreakdownChart.cs b/osu.Game/Screens/Ranking/Statistics/PerformanceBreakdownChart.cs index 3462a85e1c..10cb77fa91 100644 --- a/osu.Game/Screens/Ranking/Statistics/PerformanceBreakdownChart.cs +++ b/osu.Game/Screens/Ranking/Statistics/PerformanceBreakdownChart.cs @@ -26,7 +26,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.Ranking.Statistics { - public class PerformanceBreakdownChart : Container + public partial class PerformanceBreakdownChart : Container { private readonly ScoreInfo score; private readonly IBeatmap playableBeatmap; diff --git a/osu.Game/Screens/Ranking/Statistics/SimpleStatisticItem.cs b/osu.Game/Screens/Ranking/Statistics/SimpleStatisticItem.cs index ecff631c7e..99f4e1e342 100644 --- a/osu.Game/Screens/Ranking/Statistics/SimpleStatisticItem.cs +++ b/osu.Game/Screens/Ranking/Statistics/SimpleStatisticItem.cs @@ -14,7 +14,7 @@ namespace osu.Game.Screens.Ranking.Statistics /// Represents a simple statistic item (one that only needs textual display). /// Richer visualisations should be done with s. /// - public abstract class SimpleStatisticItem : Container + public abstract partial class SimpleStatisticItem : Container { /// /// The text to display as the statistic's value. @@ -59,7 +59,7 @@ namespace osu.Game.Screens.Ranking.Statistics /// /// Strongly-typed generic specialisation for . /// - public class SimpleStatisticItem : SimpleStatisticItem + public partial class SimpleStatisticItem : SimpleStatisticItem { private TValue value; diff --git a/osu.Game/Screens/Ranking/Statistics/SimpleStatisticTable.cs b/osu.Game/Screens/Ranking/Statistics/SimpleStatisticTable.cs index f1eb16ca80..d10888be43 100644 --- a/osu.Game/Screens/Ranking/Statistics/SimpleStatisticTable.cs +++ b/osu.Game/Screens/Ranking/Statistics/SimpleStatisticTable.cs @@ -19,7 +19,7 @@ namespace osu.Game.Screens.Ranking.Statistics /// Represents a table with simple statistics (ones that only need textual display). /// Richer visualisations should be done with s and s. /// - public class SimpleStatisticTable : CompositeDrawable + public partial class SimpleStatisticTable : CompositeDrawable { private readonly SimpleStatisticItem[] items; private readonly int columnCount; @@ -98,7 +98,7 @@ namespace osu.Game.Screens.Ranking.Statistics Direction = FillDirection.Vertical }; - private class Spacer : CompositeDrawable + private partial class Spacer : CompositeDrawable { public Spacer() { diff --git a/osu.Game/Screens/Ranking/Statistics/SoloStatisticsPanel.cs b/osu.Game/Screens/Ranking/Statistics/SoloStatisticsPanel.cs new file mode 100644 index 0000000000..57d072b7de --- /dev/null +++ b/osu.Game/Screens/Ranking/Statistics/SoloStatisticsPanel.cs @@ -0,0 +1,54 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using System.Linq; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Game.Beatmaps; +using osu.Game.Online.Solo; +using osu.Game.Scoring; +using osu.Game.Screens.Ranking.Statistics.User; + +namespace osu.Game.Screens.Ranking.Statistics +{ + public partial class SoloStatisticsPanel : StatisticsPanel + { + private readonly ScoreInfo achievedScore; + + public SoloStatisticsPanel(ScoreInfo achievedScore) + { + this.achievedScore = achievedScore; + } + + public Bindable StatisticsUpdate { get; } = new Bindable(); + + protected override ICollection CreateStatisticRows(ScoreInfo newScore, IBeatmap playableBeatmap) + { + var rows = base.CreateStatisticRows(newScore, playableBeatmap); + + if (newScore.UserID > 1 + && newScore.UserID == achievedScore.UserID + && newScore.OnlineID > 0 + && newScore.OnlineID == achievedScore.OnlineID) + { + rows = rows.Append(new StatisticRow + { + Columns = new[] + { + new StatisticItem("Overall Ranking", () => new OverallRanking + { + RelativeSizeAxes = Axes.X, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Width = 0.5f, + StatisticsUpdate = { BindTarget = StatisticsUpdate } + }) + } + }).ToArray(); + } + + return rows; + } + } +} diff --git a/osu.Game/Screens/Ranking/Statistics/StatisticContainer.cs b/osu.Game/Screens/Ranking/Statistics/StatisticContainer.cs index 1505585205..d3327224dc 100644 --- a/osu.Game/Screens/Ranking/Statistics/StatisticContainer.cs +++ b/osu.Game/Screens/Ranking/Statistics/StatisticContainer.cs @@ -18,7 +18,7 @@ namespace osu.Game.Screens.Ranking.Statistics /// /// Wraps a to add a header and suitable layout for use in . /// - internal class StatisticContainer : CompositeDrawable + internal partial class StatisticContainer : CompositeDrawable { /// /// Creates a new . diff --git a/osu.Game/Screens/Ranking/Statistics/StatisticsPanel.cs b/osu.Game/Screens/Ranking/Statistics/StatisticsPanel.cs index 79d7b99e51..4c22afd8f7 100644 --- a/osu.Game/Screens/Ranking/Statistics/StatisticsPanel.cs +++ b/osu.Game/Screens/Ranking/Statistics/StatisticsPanel.cs @@ -24,7 +24,7 @@ using osuTK; namespace osu.Game.Screens.Ranking.Statistics { - public class StatisticsPanel : VisibilityContainer + public partial class StatisticsPanel : VisibilityContainer { public const float SIDE_PADDING = 30; @@ -100,7 +100,7 @@ namespace osu.Game.Screens.Ranking.Statistics bool hitEventsAvailable = newScore.HitEvents.Count != 0; Container container; - var statisticRows = newScore.Ruleset.CreateInstance().CreateStatisticsForScore(newScore, task.GetResultSafely()); + var statisticRows = CreateStatisticRows(newScore, task.GetResultSafely()); if (!hitEventsAvailable && statisticRows.SelectMany(r => r.Columns).All(c => c.RequiresHitEvents)) { @@ -218,6 +218,14 @@ namespace osu.Game.Screens.Ranking.Statistics }), localCancellationSource.Token); } + /// + /// Creates the s to be displayed in this panel for a given . + /// + /// The score to create the rows for. + /// The beatmap on which the score was set. + protected virtual ICollection CreateStatisticRows(ScoreInfo newScore, IBeatmap playableBeatmap) + => newScore.Ruleset.CreateInstance().CreateStatisticsForScore(newScore, playableBeatmap); + protected override bool OnClick(ClickEvent e) { ToggleVisibility(); diff --git a/osu.Game/Screens/Ranking/Statistics/UnstableRate.cs b/osu.Game/Screens/Ranking/Statistics/UnstableRate.cs index 4ab085fa23..de01668029 100644 --- a/osu.Game/Screens/Ranking/Statistics/UnstableRate.cs +++ b/osu.Game/Screens/Ranking/Statistics/UnstableRate.cs @@ -11,7 +11,7 @@ namespace osu.Game.Screens.Ranking.Statistics /// /// Displays the unstable rate statistic for a given play. /// - public class UnstableRate : SimpleStatisticItem + public partial class UnstableRate : SimpleStatisticItem { /// /// Creates and computes an statistic. diff --git a/osu.Game/Screens/Ranking/Statistics/User/AccuracyChangeRow.cs b/osu.Game/Screens/Ranking/Statistics/User/AccuracyChangeRow.cs new file mode 100644 index 0000000000..0fd666e9d0 --- /dev/null +++ b/osu.Game/Screens/Ranking/Statistics/User/AccuracyChangeRow.cs @@ -0,0 +1,35 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Localisation; +using osu.Game.Resources.Localisation.Web; +using osu.Game.Utils; + +namespace osu.Game.Screens.Ranking.Statistics.User +{ + public partial class AccuracyChangeRow : RankingChangeRow + { + public AccuracyChangeRow() + : base(stats => stats.Accuracy) + { + } + + protected override LocalisableString Label => UsersStrings.ShowStatsHitAccuracy; + + protected override LocalisableString FormatCurrentValue(double current) => (current / 100).FormatAccuracy(); + + protected override int CalculateDifference(double previous, double current, out LocalisableString formattedDifference) + { + double difference = (current - previous) / 100; + + if (difference < 0) + formattedDifference = difference.FormatAccuracy(); + else if (difference > 0) + formattedDifference = LocalisableString.Interpolate($@"+{difference.FormatAccuracy()}"); + else + formattedDifference = string.Empty; + + return current.CompareTo(previous); + } + } +} diff --git a/osu.Game/Screens/Ranking/Statistics/User/GlobalRankChangeRow.cs b/osu.Game/Screens/Ranking/Statistics/User/GlobalRankChangeRow.cs new file mode 100644 index 0000000000..0d91d6f8f9 --- /dev/null +++ b/osu.Game/Screens/Ranking/Statistics/User/GlobalRankChangeRow.cs @@ -0,0 +1,58 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Diagnostics; +using osu.Framework.Localisation; +using osu.Game.Resources.Localisation.Web; +using osu.Game.Utils; + +namespace osu.Game.Screens.Ranking.Statistics.User +{ + public partial class GlobalRankChangeRow : RankingChangeRow + { + public GlobalRankChangeRow() + : base(stats => stats.GlobalRank) + { + } + + protected override LocalisableString Label => UsersStrings.ShowRankGlobalSimple; + + protected override LocalisableString FormatCurrentValue(int? current) + => current == null ? string.Empty : current.Value.FormatRank(); + + protected override int CalculateDifference(int? previous, int? current, out LocalisableString formattedDifference) + { + if (previous == null && current == null) + { + formattedDifference = string.Empty; + return 0; + } + + if (previous == null && current != null) + { + formattedDifference = LocalisableString.Interpolate($"+{current.Value.FormatRank()}"); + return 1; + } + + if (previous != null && current == null) + { + formattedDifference = LocalisableString.Interpolate($"-{previous.Value.FormatRank()}"); + return -1; + } + + Debug.Assert(previous != null && current != null); + + // note that ranks work backwards, i.e. lower rank is _better_. + int difference = previous.Value - current.Value; + + if (difference < 0) + formattedDifference = difference.FormatRank(); + else if (difference > 0) + formattedDifference = LocalisableString.Interpolate($"+{difference.FormatRank()}"); + else + formattedDifference = string.Empty; + + return difference; + } + } +} diff --git a/osu.Game/Screens/Ranking/Statistics/User/MaximumComboChangeRow.cs b/osu.Game/Screens/Ranking/Statistics/User/MaximumComboChangeRow.cs new file mode 100644 index 0000000000..37e3cec52f --- /dev/null +++ b/osu.Game/Screens/Ranking/Statistics/User/MaximumComboChangeRow.cs @@ -0,0 +1,34 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Localisation; +using osu.Game.Resources.Localisation.Web; + +namespace osu.Game.Screens.Ranking.Statistics.User +{ + public partial class MaximumComboChangeRow : RankingChangeRow + { + public MaximumComboChangeRow() + : base(stats => stats.MaxCombo) + { + } + + protected override LocalisableString Label => UsersStrings.ShowStatsMaximumCombo; + + protected override LocalisableString FormatCurrentValue(int current) => LocalisableString.Interpolate($@"{current:N0}x"); + + protected override int CalculateDifference(int previous, int current, out LocalisableString formattedDifference) + { + int difference = current - previous; + + if (difference < 0) + formattedDifference = LocalisableString.Interpolate($@"{difference:N0}x"); + else if (difference > 0) + formattedDifference = LocalisableString.Interpolate($@"+{difference:N0}x"); + else + formattedDifference = string.Empty; + + return current.CompareTo(previous); + } + } +} diff --git a/osu.Game/Screens/Ranking/Statistics/User/OverallRanking.cs b/osu.Game/Screens/Ranking/Statistics/User/OverallRanking.cs new file mode 100644 index 0000000000..447f206128 --- /dev/null +++ b/osu.Game/Screens/Ranking/Statistics/User/OverallRanking.cs @@ -0,0 +1,78 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics.UserInterface; +using osu.Game.Online.Solo; +using osuTK; + +namespace osu.Game.Screens.Ranking.Statistics.User +{ + public partial class OverallRanking : CompositeDrawable + { + private const float transition_duration = 300; + + public Bindable StatisticsUpdate { get; } = new Bindable(); + + private LoadingLayer loadingLayer = null!; + private FillFlowContainer content = null!; + + [BackgroundDependencyLoader] + private void load() + { + AutoSizeAxes = Axes.Y; + AutoSizeEasing = Easing.OutQuint; + AutoSizeDuration = transition_duration; + + InternalChildren = new Drawable[] + { + loadingLayer = new LoadingLayer(withBox: false) + { + RelativeSizeAxes = Axes.Both, + }, + content = new FillFlowContainer + { + AlwaysPresent = true, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Spacing = new Vector2(10), + Children = new Drawable[] + { + new GlobalRankChangeRow { StatisticsUpdate = { BindTarget = StatisticsUpdate } }, + new AccuracyChangeRow { StatisticsUpdate = { BindTarget = StatisticsUpdate } }, + new MaximumComboChangeRow { StatisticsUpdate = { BindTarget = StatisticsUpdate } }, + new RankedScoreChangeRow { StatisticsUpdate = { BindTarget = StatisticsUpdate } }, + new TotalScoreChangeRow { StatisticsUpdate = { BindTarget = StatisticsUpdate } }, + new PerformancePointsChangeRow { StatisticsUpdate = { BindTarget = StatisticsUpdate } } + } + } + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + StatisticsUpdate.BindValueChanged(onUpdateReceived, true); + FinishTransforms(true); + } + + private void onUpdateReceived(ValueChangedEvent update) + { + if (update.NewValue == null) + { + loadingLayer.Show(); + content.FadeOut(transition_duration, Easing.OutQuint); + } + else + { + loadingLayer.Hide(); + content.FadeIn(transition_duration, Easing.OutQuint); + } + } + } +} diff --git a/osu.Game/Screens/Ranking/Statistics/User/PerformancePointsChangeRow.cs b/osu.Game/Screens/Ranking/Statistics/User/PerformancePointsChangeRow.cs new file mode 100644 index 0000000000..c1faf1a3e3 --- /dev/null +++ b/osu.Game/Screens/Ranking/Statistics/User/PerformancePointsChangeRow.cs @@ -0,0 +1,56 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Diagnostics; +using osu.Framework.Localisation; +using osu.Game.Resources.Localisation.Web; + +namespace osu.Game.Screens.Ranking.Statistics.User +{ + public partial class PerformancePointsChangeRow : RankingChangeRow + { + public PerformancePointsChangeRow() + : base(stats => stats.PP) + { + } + + protected override LocalisableString Label => RankingsStrings.StatPerformance; + + protected override LocalisableString FormatCurrentValue(decimal? current) + => current == null ? string.Empty : LocalisableString.Interpolate($@"{current:N0}pp"); + + protected override int CalculateDifference(decimal? previous, decimal? current, out LocalisableString formattedDifference) + { + if (previous == null && current == null) + { + formattedDifference = string.Empty; + return 0; + } + + if (previous == null && current != null) + { + formattedDifference = LocalisableString.Interpolate($"+{current.Value:N0}pp"); + return 1; + } + + if (previous != null && current == null) + { + formattedDifference = LocalisableString.Interpolate($"-{previous.Value:N0}pp"); + return -1; + } + + Debug.Assert(previous != null && current != null); + + decimal difference = current.Value - previous.Value; + + if (difference < 0) + formattedDifference = LocalisableString.Interpolate($@"{difference:N0}pp"); + else if (difference > 0) + formattedDifference = LocalisableString.Interpolate($@"+{difference:N0}pp"); + else + formattedDifference = string.Empty; + + return current.Value.CompareTo(previous.Value); + } + } +} diff --git a/osu.Game/Screens/Ranking/Statistics/User/RankedScoreChangeRow.cs b/osu.Game/Screens/Ranking/Statistics/User/RankedScoreChangeRow.cs new file mode 100644 index 0000000000..1cdf22bd75 --- /dev/null +++ b/osu.Game/Screens/Ranking/Statistics/User/RankedScoreChangeRow.cs @@ -0,0 +1,35 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Extensions.LocalisationExtensions; +using osu.Framework.Localisation; +using osu.Game.Resources.Localisation.Web; + +namespace osu.Game.Screens.Ranking.Statistics.User +{ + public partial class RankedScoreChangeRow : RankingChangeRow + { + public RankedScoreChangeRow() + : base(stats => stats.RankedScore) + { + } + + protected override LocalisableString Label => UsersStrings.ShowStatsRankedScore; + + protected override LocalisableString FormatCurrentValue(long current) => current.ToLocalisableString(@"N0"); + + protected override int CalculateDifference(long previous, long current, out LocalisableString formattedDifference) + { + long difference = current - previous; + + if (difference < 0) + formattedDifference = difference.ToLocalisableString(@"N0"); + else if (difference > 0) + formattedDifference = LocalisableString.Interpolate($@"+{difference:N0}"); + else + formattedDifference = string.Empty; + + return current.CompareTo(previous); + } + } +} diff --git a/osu.Game/Screens/Ranking/Statistics/User/RankingChangeRow.cs b/osu.Game/Screens/Ranking/Statistics/User/RankingChangeRow.cs new file mode 100644 index 0000000000..5348b4a522 --- /dev/null +++ b/osu.Game/Screens/Ranking/Statistics/User/RankingChangeRow.cs @@ -0,0 +1,144 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Localisation; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Online.Solo; +using osu.Game.Users; +using osuTK; + +namespace osu.Game.Screens.Ranking.Statistics.User +{ + public abstract partial class RankingChangeRow : CompositeDrawable + { + public Bindable StatisticsUpdate { get; } = new Bindable(); + + private readonly Func accessor; + + private OsuSpriteText currentValueText = null!; + private SpriteIcon changeIcon = null!; + private OsuSpriteText changeText = null!; + + [Resolved] + private OsuColour colours { get; set; } = null!; + + protected RankingChangeRow( + Func accessor) + { + this.accessor = accessor; + } + + [BackgroundDependencyLoader] + private void load() + { + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + + InternalChildren = new Drawable[] + { + new OsuSpriteText + { + Text = Label, + Font = OsuFont.Default.With(size: 18) + }, + new FillFlowContainer + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Direction = FillDirection.Vertical, + AutoSizeAxes = Axes.Both, + Children = new Drawable[] + { + new FillFlowContainer + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Direction = FillDirection.Horizontal, + AutoSizeAxes = Axes.Both, + Spacing = new Vector2(5), + Children = new Drawable[] + { + changeIcon = new SpriteIcon + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + Size = new Vector2(18) + }, + currentValueText = new OsuSpriteText + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + Font = OsuFont.Default.With(size: 18, weight: FontWeight.Bold) + }, + } + }, + changeText = new OsuSpriteText + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Font = OsuFont.Default.With(weight: FontWeight.Bold) + } + } + } + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + StatisticsUpdate.BindValueChanged(onStatisticsUpdate, true); + } + + private void onStatisticsUpdate(ValueChangedEvent statisticsUpdate) + { + var update = statisticsUpdate.NewValue; + + if (update == null) + return; + + T previousValue = accessor.Invoke(update.Before); + T currentValue = accessor.Invoke(update.After); + int comparisonResult = CalculateDifference(previousValue, currentValue, out var formattedDifference); + + Colour4 comparisonColour; + IconUsage icon; + + if (comparisonResult < 0) + { + comparisonColour = colours.Red1; + icon = FontAwesome.Solid.ArrowDown; + } + else if (comparisonResult > 0) + { + comparisonColour = colours.Lime1; + icon = FontAwesome.Solid.ArrowUp; + } + else + { + comparisonColour = colours.Orange1; + icon = FontAwesome.Solid.Minus; + } + + currentValueText.Text = FormatCurrentValue(currentValue); + + changeIcon.Icon = icon; + changeIcon.Colour = comparisonColour; + + changeText.Text = formattedDifference; + changeText.Colour = comparisonColour; + } + + protected abstract LocalisableString Label { get; } + + protected abstract LocalisableString FormatCurrentValue(T current); + protected abstract int CalculateDifference(T previous, T current, out LocalisableString formattedDifference); + } +} diff --git a/osu.Game/Screens/Ranking/Statistics/User/TotalScoreChangeRow.cs b/osu.Game/Screens/Ranking/Statistics/User/TotalScoreChangeRow.cs new file mode 100644 index 0000000000..346de18e14 --- /dev/null +++ b/osu.Game/Screens/Ranking/Statistics/User/TotalScoreChangeRow.cs @@ -0,0 +1,35 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Extensions.LocalisationExtensions; +using osu.Framework.Localisation; +using osu.Game.Resources.Localisation.Web; + +namespace osu.Game.Screens.Ranking.Statistics.User +{ + public partial class TotalScoreChangeRow : RankingChangeRow + { + public TotalScoreChangeRow() + : base(stats => stats.TotalScore) + { + } + + protected override LocalisableString Label => UsersStrings.ShowStatsTotalScore; + + protected override LocalisableString FormatCurrentValue(long current) => current.ToLocalisableString(@"N0"); + + protected override int CalculateDifference(long previous, long current, out LocalisableString formattedDifference) + { + long difference = current - previous; + + if (difference < 0) + formattedDifference = difference.ToLocalisableString(@"N0"); + else if (difference > 0) + formattedDifference = LocalisableString.Interpolate($@"+{difference:N0}"); + else + formattedDifference = string.Empty; + + return current.CompareTo(previous); + } + } +} diff --git a/osu.Game/Screens/ScreenWhiteBox.cs b/osu.Game/Screens/ScreenWhiteBox.cs index 550fda5480..25afe119be 100644 --- a/osu.Game/Screens/ScreenWhiteBox.cs +++ b/osu.Game/Screens/ScreenWhiteBox.cs @@ -20,7 +20,7 @@ using osu.Framework.Graphics.Sprites; namespace osu.Game.Screens { - public class ScreenWhiteBox : OsuScreen + public partial class ScreenWhiteBox : OsuScreen { private readonly UnderConstructionMessage message; @@ -95,7 +95,7 @@ namespace osu.Game.Screens return new Color4(r, g, b, 255); } - private class ChildModeButton : TwoLayerButton + private partial class ChildModeButton : TwoLayerButton { public ChildModeButton() { @@ -105,7 +105,7 @@ namespace osu.Game.Screens } } - public class UnderConstructionMessage : CompositeDrawable + public partial class UnderConstructionMessage : CompositeDrawable { public FillFlowContainer TextContainer { get; } diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index 752a1ede64..19eced08d9 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -32,7 +32,7 @@ using Realms; namespace osu.Game.Screens.Select { - public class BeatmapCarousel : CompositeDrawable, IKeyBindingHandler + public partial class BeatmapCarousel : CompositeDrawable, IKeyBindingHandler { /// /// Height of the area above the carousel that should be treated as visible due to transparency of elements in front of it. @@ -64,7 +64,7 @@ namespace osu.Game.Screens.Select /// /// A function to optionally decide on a recommended difficulty from a beatmap set. /// - public Func, BeatmapInfo>? GetRecommendedBeatmap; + public Func, BeatmapInfo?>? GetRecommendedBeatmap; private CarouselBeatmapSet? selectedBeatmapSet; @@ -119,7 +119,7 @@ namespace osu.Game.Screens.Select { CarouselRoot newRoot = new CarouselRoot(this); - newRoot.AddItems(beatmapSets.Select(s => createCarouselSet(s.Detach())).Where(g => g != null)); + newRoot.AddItems(beatmapSets.Select(s => createCarouselSet(s.Detach())).OfType()); root = newRoot; @@ -739,6 +739,8 @@ namespace osu.Game.Screens.Select foreach (var panel in Scroll.Children) { + Debug.Assert(panel.Item != null); + if (toDisplay.Remove(panel.Item)) { // panel already displayed. @@ -770,6 +772,8 @@ namespace osu.Game.Screens.Select { updateItem(item); + Debug.Assert(item.Item != null); + if (item.Item.Visible) { bool isSelected = item.Item.State.Value == CarouselItemState.Selected; @@ -1075,7 +1079,7 @@ namespace osu.Game.Screens.Select } } - protected class CarouselScrollContainer : UserTrackingScrollContainer + protected partial class CarouselScrollContainer : UserTrackingScrollContainer { private bool rightMouseScrollBlocked; diff --git a/osu.Game/Screens/Select/BeatmapClearScoresDialog.cs b/osu.Game/Screens/Select/BeatmapClearScoresDialog.cs index 0996e3e202..c0f97a05e2 100644 --- a/osu.Game/Screens/Select/BeatmapClearScoresDialog.cs +++ b/osu.Game/Screens/Select/BeatmapClearScoresDialog.cs @@ -10,7 +10,7 @@ using osu.Game.Scoring; namespace osu.Game.Screens.Select { - public class BeatmapClearScoresDialog : DeleteConfirmationDialog + public partial class BeatmapClearScoresDialog : DeleteConfirmationDialog { [Resolved] private ScoreManager scoreManager { get; set; } = null!; diff --git a/osu.Game/Screens/Select/BeatmapDeleteDialog.cs b/osu.Game/Screens/Select/BeatmapDeleteDialog.cs index 3d3e8b6d73..4ab23c3a3a 100644 --- a/osu.Game/Screens/Select/BeatmapDeleteDialog.cs +++ b/osu.Game/Screens/Select/BeatmapDeleteDialog.cs @@ -7,7 +7,7 @@ using osu.Game.Overlays.Dialog; namespace osu.Game.Screens.Select { - public class BeatmapDeleteDialog : DeleteConfirmationDialog + public partial class BeatmapDeleteDialog : DeleteConfirmationDialog { private readonly BeatmapSetInfo beatmapSet; diff --git a/osu.Game/Screens/Select/BeatmapDetailArea.cs b/osu.Game/Screens/Select/BeatmapDetailArea.cs index bf6803f551..595b86924b 100644 --- a/osu.Game/Screens/Select/BeatmapDetailArea.cs +++ b/osu.Game/Screens/Select/BeatmapDetailArea.cs @@ -11,7 +11,7 @@ using osu.Game.Beatmaps; namespace osu.Game.Screens.Select { - public abstract class BeatmapDetailArea : Container + public abstract partial class BeatmapDetailArea : Container { private const float details_padding = 10; diff --git a/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs b/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs index 3c0d621abe..f9dab2bb1d 100644 --- a/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs +++ b/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs @@ -17,7 +17,7 @@ using osu.Framework.Graphics.Shapes; namespace osu.Game.Screens.Select { - public class BeatmapDetailAreaTabControl : Container + public partial class BeatmapDetailAreaTabControl : Container { public const float HEIGHT = 24; diff --git a/osu.Game/Screens/Select/BeatmapDetails.cs b/osu.Game/Screens/Select/BeatmapDetails.cs index 90418efe15..712b610515 100644 --- a/osu.Game/Screens/Select/BeatmapDetails.cs +++ b/osu.Game/Screens/Select/BeatmapDetails.cs @@ -23,7 +23,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.Select { - public class BeatmapDetails : Container + public partial class BeatmapDetails : Container { private const float spacing = 10; private const float transition_duration = 250; @@ -141,9 +141,9 @@ namespace osu.Game.Screens.Select LayoutEasing = Easing.OutQuad, Children = new[] { - description = new MetadataSection(MetadataType.Description, searchOnSongSelect), - source = new MetadataSection(MetadataType.Source, searchOnSongSelect), - tags = new MetadataSection(MetadataType.Tags, searchOnSongSelect), + description = new MetadataSectionDescription(searchOnSongSelect), + source = new MetadataSectionSource(searchOnSongSelect), + tags = new MetadataSectionTags(searchOnSongSelect), }, }, }, @@ -187,9 +187,9 @@ namespace osu.Game.Screens.Select private void updateStatistics() { advanced.BeatmapInfo = BeatmapInfo; - description.Text = BeatmapInfo?.DifficultyName; - source.Text = BeatmapInfo?.Metadata.Source; - tags.Text = BeatmapInfo?.Metadata.Tags; + description.Metadata = BeatmapInfo?.DifficultyName ?? string.Empty; + source.Metadata = BeatmapInfo?.Metadata.Source ?? string.Empty; + tags.Metadata = BeatmapInfo?.Metadata.Tags ?? string.Empty; // failTimes may have been previously fetched if (ratings != null && failTimes != null) @@ -273,7 +273,7 @@ namespace osu.Game.Screens.Select loading.Hide(); } - private class DetailBox : Container + private partial class DetailBox : Container { private readonly Container content; protected override Container Content => content; diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 3ee9a11b24..2102df1022 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -33,7 +33,7 @@ using osu.Game.Graphics.Containers; namespace osu.Game.Screens.Select { - public class BeatmapInfoWedge : VisibilityContainer + public partial class BeatmapInfoWedge : VisibilityContainer { public const float BORDER_THICKNESS = 2.5f; private const float shear_width = 36.75f; @@ -148,7 +148,7 @@ namespace osu.Game.Screens.Select } } - public class WedgeInfoText : Container + public partial class WedgeInfoText : Container { public OsuSpriteText VersionLabel { get; private set; } public OsuSpriteText TitleLabel { get; private set; } @@ -456,7 +456,7 @@ namespace osu.Game.Screens.Select cancellationSource?.Cancel(); } - public class InfoLabel : Container, IHasTooltip + public partial class InfoLabel : Container, IHasTooltip { public LocalisableString TooltipText { get; } diff --git a/osu.Game/Screens/Select/BeatmapInfoWedgeBackground.cs b/osu.Game/Screens/Select/BeatmapInfoWedgeBackground.cs index 68f0c92097..d5d258704b 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedgeBackground.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedgeBackground.cs @@ -15,7 +15,7 @@ using osu.Framework.Graphics.Shapes; namespace osu.Game.Screens.Select { - internal class BeatmapInfoWedgeBackground : CompositeDrawable + internal partial class BeatmapInfoWedgeBackground : CompositeDrawable { private readonly IWorkingBeatmap beatmap; diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs index 03490ff37b..837939716b 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Linq; using osu.Game.Beatmaps; diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs index 9a4319c6b2..a360ddabc7 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; @@ -33,7 +31,7 @@ namespace osu.Game.Screens.Select.Carousel public BeatmapSetInfo BeatmapSet; - public Func, BeatmapInfo> GetRecommendedBeatmap; + public Func, BeatmapInfo?>? GetRecommendedBeatmap; public CarouselBeatmapSet(BeatmapSetInfo beatmapSet) { @@ -47,7 +45,7 @@ namespace osu.Game.Screens.Select.Carousel .ForEach(AddItem); } - protected override CarouselItem GetNextToSelect() + protected override CarouselItem? GetNextToSelect() { if (LastSelected == null || LastSelected.Filtered.Value) { @@ -132,8 +130,8 @@ namespace osu.Game.Screens.Select.Carousel bool filtered = Items.All(i => i.Filtered.Value); - filtered |= criteria.Sort == SortMode.DateRanked && BeatmapSet?.DateRanked == null; - filtered |= criteria.Sort == SortMode.DateSubmitted && BeatmapSet?.DateSubmitted == null; + filtered |= criteria.Sort == SortMode.DateRanked && BeatmapSet.DateRanked == null; + filtered |= criteria.Sort == SortMode.DateSubmitted && BeatmapSet.DateSubmitted == null; Filtered.Value = filtered; } diff --git a/osu.Game/Screens/Select/Carousel/CarouselGroupEagerSelect.cs b/osu.Game/Screens/Select/Carousel/CarouselGroupEagerSelect.cs index 6366fc8050..7f90e05744 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselGroupEagerSelect.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselGroupEagerSelect.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; @@ -26,7 +24,7 @@ namespace osu.Game.Screens.Select.Carousel /// /// The last selected item. /// - protected CarouselItem LastSelected { get; private set; } + protected CarouselItem? LastSelected { get; private set; } /// /// We need to keep track of the index for cases where the selection is removed but we want to select a new item based on its old location. @@ -112,7 +110,7 @@ namespace osu.Game.Screens.Select.Carousel /// Finds the item this group would select next if it attempted selection /// /// An unfiltered item nearest to the last selected one or null if all items are filtered - protected virtual CarouselItem GetNextToSelect() + protected virtual CarouselItem? GetNextToSelect() { if (Items.Count == 0) return null; @@ -141,7 +139,7 @@ namespace osu.Game.Screens.Select.Carousel protected virtual void PerformSelection() { - CarouselItem nextToSelect = GetNextToSelect(); + CarouselItem? nextToSelect = GetNextToSelect(); if (nextToSelect != null) nextToSelect.State.Value = CarouselItemState.Selected; @@ -149,7 +147,7 @@ namespace osu.Game.Screens.Select.Carousel updateSelected(null); } - private void updateSelected(CarouselItem newSelection) + private void updateSelected(CarouselItem? newSelection) { if (newSelection != null) LastSelected = newSelection; diff --git a/osu.Game/Screens/Select/Carousel/CarouselHeader.cs b/osu.Game/Screens/Select/Carousel/CarouselHeader.cs index 5cde5f7d5a..e46f0da45d 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselHeader.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselHeader.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; @@ -21,7 +19,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.Select.Carousel { - public class CarouselHeader : Container + public partial class CarouselHeader : Container { public Container BorderContainer; @@ -93,11 +91,11 @@ namespace osu.Game.Screens.Select.Carousel } } - public class HoverLayer : HoverSampleDebounceComponent + public partial class HoverLayer : HoverSampleDebounceComponent { - private Sample sampleHover; + private Sample? sampleHover; - private Box box; + private Box box = null!; public HoverLayer() { diff --git a/osu.Game/Screens/Select/Carousel/CarouselItem.cs b/osu.Game/Screens/Select/Carousel/CarouselItem.cs index cbf079eb4b..5e425a4a1c 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselItem.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselItem.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using osu.Framework.Bindables; @@ -43,7 +41,7 @@ namespace osu.Game.Screens.Select.Carousel /// /// Create a fresh drawable version of this item. /// - public abstract DrawableCarouselItem CreateDrawableRepresentation(); + public abstract DrawableCarouselItem? CreateDrawableRepresentation(); public virtual void Filter(FilterCriteria criteria) { @@ -51,7 +49,12 @@ namespace osu.Game.Screens.Select.Carousel public virtual int CompareTo(FilterCriteria criteria, CarouselItem other) => ItemID.CompareTo(other.ItemID); - public int CompareTo(CarouselItem other) => CarouselYPosition.CompareTo(other.CarouselYPosition); + public int CompareTo(CarouselItem? other) + { + if (other == null) return 1; + + return CarouselYPosition.CompareTo(other.CarouselYPosition); + } } public enum CarouselItemState diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs index c3cb04680b..e05d950369 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; @@ -34,7 +32,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.Select.Carousel { - public class DrawableCarouselBeatmap : DrawableCarouselItem, IHasContextMenu + public partial class DrawableCarouselBeatmap : DrawableCarouselItem, IHasContextMenu { public const float CAROUSEL_BEATMAP_SPACING = 5; @@ -47,31 +45,31 @@ namespace osu.Game.Screens.Select.Carousel private readonly BeatmapInfo beatmapInfo; - private Sprite background; + private Sprite background = null!; - private Action startRequested; - private Action editRequested; - private Action hideRequested; + private Action? startRequested; + private Action? editRequested; + private Action? hideRequested; - private Triangles triangles; + private Triangles triangles = null!; - private StarCounter starCounter; - private DifficultyIcon difficultyIcon; - - [Resolved(CanBeNull = true)] - private BeatmapSetOverlay beatmapOverlay { get; set; } + private StarCounter starCounter = null!; + private DifficultyIcon difficultyIcon = null!; [Resolved] - private BeatmapDifficultyCache difficultyCache { get; set; } - - [Resolved(CanBeNull = true)] - private ManageCollectionsDialog manageCollectionsDialog { get; set; } + private BeatmapSetOverlay? beatmapOverlay { get; set; } [Resolved] - private RealmAccess realm { get; set; } + private BeatmapDifficultyCache difficultyCache { get; set; } = null!; - private IBindable starDifficultyBindable; - private CancellationTokenSource starDifficultyCancellationSource; + [Resolved] + private ManageCollectionsDialog? manageCollectionsDialog { get; set; } + + [Resolved] + private RealmAccess realm { get; set; } = null!; + + private IBindable starDifficultyBindable = null!; + private CancellationTokenSource? starDifficultyCancellationSource; public DrawableCarouselBeatmap(CarouselBeatmap panel) { @@ -79,8 +77,8 @@ namespace osu.Game.Screens.Select.Carousel Item = panel; } - [BackgroundDependencyLoader(true)] - private void load(BeatmapManager manager, SongSelect songSelect) + [BackgroundDependencyLoader] + private void load(BeatmapManager? manager, SongSelect? songSelect) { Header.Height = height; @@ -194,7 +192,7 @@ namespace osu.Game.Screens.Select.Carousel protected override bool OnClick(ClickEvent e) { - if (Item.State.Value == CarouselItemState.Selected) + if (Item?.State.Value == CarouselItemState.Selected) startRequested?.Invoke(beatmapInfo); return base.OnClick(e); @@ -202,13 +200,13 @@ namespace osu.Game.Screens.Select.Carousel protected override void ApplyState() { - if (Item.State.Value != CarouselItemState.Collapsed && Alpha == 0) + if (Item?.State.Value != CarouselItemState.Collapsed && Alpha == 0) starCounter.ReplayAnimation(); starDifficultyCancellationSource?.Cancel(); // Only compute difficulty when the item is visible. - if (Item.State.Value != CarouselItemState.Collapsed) + if (Item?.State.Value != CarouselItemState.Collapsed) { // We've potentially cancelled the computation above so a new bindable is required. starDifficultyBindable = difficultyCache.GetBindableDifficulty(beatmapInfo, (starDifficultyCancellationSource = new CancellationTokenSource()).Token); diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs index 040f954bba..3975bb6bb6 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs @@ -1,14 +1,11 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading.Tasks; -using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -23,34 +20,32 @@ using osu.Game.Overlays; namespace osu.Game.Screens.Select.Carousel { - public class DrawableCarouselBeatmapSet : DrawableCarouselItem, IHasContextMenu + public partial class DrawableCarouselBeatmapSet : DrawableCarouselItem, IHasContextMenu { public const float HEIGHT = MAX_HEIGHT; - private Action restoreHiddenRequested; - private Action viewDetails; - - [Resolved(CanBeNull = true)] - private IDialogOverlay dialogOverlay { get; set; } - - [Resolved(CanBeNull = true)] - private ManageCollectionsDialog manageCollectionsDialog { get; set; } + private Action restoreHiddenRequested = null!; + private Action? viewDetails; [Resolved] - private RealmAccess realm { get; set; } + private IDialogOverlay? dialogOverlay { get; set; } + + [Resolved] + private ManageCollectionsDialog? manageCollectionsDialog { get; set; } + + [Resolved] + private RealmAccess realm { get; set; } = null!; public IEnumerable DrawableBeatmaps => beatmapContainer?.IsLoaded != true ? Enumerable.Empty() : beatmapContainer.AliveChildren; - [CanBeNull] - private Container beatmapContainer; + private Container? beatmapContainer; - private BeatmapSetInfo beatmapSet; + private BeatmapSetInfo beatmapSet = null!; - [CanBeNull] - private Task beatmapsLoadTask; + private Task? beatmapsLoadTask; [Resolved] - private BeatmapManager manager { get; set; } + private BeatmapManager manager { get; set; } = null!; protected override void FreeAfterUse() { @@ -61,8 +56,8 @@ namespace osu.Game.Screens.Select.Carousel ClearTransforms(); } - [BackgroundDependencyLoader(true)] - private void load(BeatmapSetOverlay beatmapOverlay) + [BackgroundDependencyLoader] + private void load(BeatmapSetOverlay? beatmapOverlay) { restoreHiddenRequested = s => { @@ -78,10 +73,11 @@ namespace osu.Game.Screens.Select.Carousel { base.Update(); + Debug.Assert(Item != null); + // position updates should not occur if the item is filtered away. // this avoids panels flying across the screen only to be eventually off-screen or faded out. - if (!Item.Visible) - return; + if (!Item.Visible) return; float targetY = Item.CarouselYPosition; @@ -151,6 +147,8 @@ namespace osu.Game.Screens.Select.Carousel private void updateBeatmapDifficulties() { + Debug.Assert(Item != null); + var carouselBeatmapSet = (CarouselBeatmapSet)Item; var visibleBeatmaps = carouselBeatmapSet.Items.Where(c => c.Visible).ToArray(); @@ -171,7 +169,7 @@ namespace osu.Game.Screens.Select.Carousel { X = 100, RelativeSizeAxes = Axes.Both, - ChildrenEnumerable = visibleBeatmaps.Select(c => c.CreateDrawableRepresentation()) + ChildrenEnumerable = visibleBeatmaps.Select(c => c.CreateDrawableRepresentation()!) }; beatmapsLoadTask = LoadComponentAsync(beatmapContainer, loaded => @@ -196,10 +194,12 @@ namespace osu.Game.Screens.Select.Carousel float yPos = DrawableCarouselBeatmap.CAROUSEL_BEATMAP_SPACING; - bool isSelected = Item.State.Value == CarouselItemState.Selected; + bool isSelected = Item?.State.Value == CarouselItemState.Selected; foreach (var panel in beatmapContainer.Children) { + Debug.Assert(panel.Item != null); + if (isSelected) { panel.MoveToY(yPos, 800, Easing.OutQuint); @@ -218,7 +218,7 @@ namespace osu.Game.Screens.Select.Carousel List items = new List(); - if (Item.State.Value == CarouselItemState.NotSelected) + if (Item?.State.Value == CarouselItemState.NotSelected) items.Add(new OsuMenuItem("Expand", MenuItemType.Highlighted, () => Item.State.Value = CarouselItemState.Selected)); if (beatmapSet.OnlineID > 0 && viewDetails != null) diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs index 133bf5f9c3..f065926eb7 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Diagnostics; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -13,7 +11,7 @@ using osuTK; namespace osu.Game.Screens.Select.Carousel { - public abstract class DrawableCarouselItem : PoolableDrawable + public abstract partial class DrawableCarouselItem : PoolableDrawable { public const float MAX_HEIGHT = 80; @@ -34,9 +32,9 @@ namespace osu.Game.Screens.Select.Carousel public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => Header.ReceivePositionalInputAt(screenSpacePos); - private CarouselItem item; + private CarouselItem? item; - public CarouselItem Item + public CarouselItem? Item { get => item; set @@ -105,7 +103,7 @@ namespace osu.Game.Screens.Select.Carousel protected virtual void UpdateItem() { - if (item == null) + if (Item == null) return; Scheduler.AddOnce(ApplyState); @@ -128,12 +126,12 @@ namespace osu.Game.Screens.Select.Carousel protected virtual void ApplyState() { + Debug.Assert(Item != null); + // Use the fact that we know the precise height of the item from the model to avoid the need for AutoSize overhead. // Additionally, AutoSize doesn't work well due to content starting off-screen and being masked away. Height = Item.TotalHeight; - Debug.Assert(Item != null); - switch (Item.State.Value) { case CarouselItemState.NotSelected: @@ -162,6 +160,8 @@ namespace osu.Game.Screens.Select.Carousel protected override bool OnClick(ClickEvent e) { + Debug.Assert(Item != null); + Item.State.Value = CarouselItemState.Selected; return true; } diff --git a/osu.Game/Screens/Select/Carousel/FilterableDifficultyIcon.cs b/osu.Game/Screens/Select/Carousel/FilterableDifficultyIcon.cs index cc904fc1da..cd8e20ad39 100644 --- a/osu.Game/Screens/Select/Carousel/FilterableDifficultyIcon.cs +++ b/osu.Game/Screens/Select/Carousel/FilterableDifficultyIcon.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Input.Events; @@ -10,7 +8,7 @@ using osu.Game.Beatmaps.Drawables; namespace osu.Game.Screens.Select.Carousel { - public class FilterableDifficultyIcon : DifficultyIcon + public partial class FilterableDifficultyIcon : DifficultyIcon { private readonly BindableBool filtered = new BindableBool(); diff --git a/osu.Game/Screens/Select/Carousel/GroupedDifficultyIcon.cs b/osu.Game/Screens/Select/Carousel/GroupedDifficultyIcon.cs index 8b4140df56..3de44fa032 100644 --- a/osu.Game/Screens/Select/Carousel/GroupedDifficultyIcon.cs +++ b/osu.Game/Screens/Select/Carousel/GroupedDifficultyIcon.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Collections.Generic; using System.Linq; using osu.Framework.Graphics; @@ -21,7 +19,7 @@ namespace osu.Game.Screens.Select.Carousel /// /// Used in cases when there are too many difficulty icons to show. /// - public class GroupedDifficultyIcon : DifficultyIcon + public partial class GroupedDifficultyIcon : DifficultyIcon { public readonly List Items; diff --git a/osu.Game/Screens/Select/Carousel/SetPanelBackground.cs b/osu.Game/Screens/Select/Carousel/SetPanelBackground.cs index 2a435e084c..6f13a34bfc 100644 --- a/osu.Game/Screens/Select/Carousel/SetPanelBackground.cs +++ b/osu.Game/Screens/Select/Carousel/SetPanelBackground.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; @@ -14,7 +12,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.Select.Carousel { - public class SetPanelBackground : BufferedContainer + public partial class SetPanelBackground : BufferedContainer { public SetPanelBackground(IWorkingBeatmap working) : base(cachedFrameBuffer: true) diff --git a/osu.Game/Screens/Select/Carousel/SetPanelContent.cs b/osu.Game/Screens/Select/Carousel/SetPanelContent.cs index a95d9078a2..8d6fbbf256 100644 --- a/osu.Game/Screens/Select/Carousel/SetPanelContent.cs +++ b/osu.Game/Screens/Select/Carousel/SetPanelContent.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; @@ -16,13 +14,15 @@ using osuTK; namespace osu.Game.Screens.Select.Carousel { - public class SetPanelContent : CompositeDrawable + public partial class SetPanelContent : CompositeDrawable { // Disallow interacting with difficulty icons on a panel until the panel has been selected. public override bool PropagatePositionalInputSubTree => carouselSet.State.Value == CarouselItemState.Selected; private readonly CarouselBeatmapSet carouselSet; + private FillFlowContainer iconFlow = null!; + public SetPanelContent(CarouselBeatmapSet carouselSet) { this.carouselSet = carouselSet; @@ -84,13 +84,12 @@ namespace osu.Game.Screens.Select.Carousel TextPadding = new MarginPadding { Horizontal = 8, Vertical = 2 }, Status = beatmapSet.Status }, - new FillFlowContainer + iconFlow = new FillFlowContainer { AutoSizeAxes = Axes.Both, Origin = Anchor.CentreLeft, Anchor = Anchor.CentreLeft, Spacing = new Vector2(3), - ChildrenEnumerable = getDifficultyIcons(), }, } } @@ -98,6 +97,12 @@ namespace osu.Game.Screens.Select.Carousel }; } + protected override void LoadComplete() + { + base.LoadComplete(); + iconFlow.ChildrenEnumerable = getDifficultyIcons(); + } + private const int maximum_difficulty_icons = 18; private IEnumerable getDifficultyIcons() diff --git a/osu.Game/Screens/Select/Carousel/TopLocalRank.cs b/osu.Game/Screens/Select/Carousel/TopLocalRank.cs index 0f000555d5..f1b773c831 100644 --- a/osu.Game/Screens/Select/Carousel/TopLocalRank.cs +++ b/osu.Game/Screens/Select/Carousel/TopLocalRank.cs @@ -19,7 +19,7 @@ using Realms; namespace osu.Game.Screens.Select.Carousel { - public class TopLocalRank : CompositeDrawable + public partial class TopLocalRank : CompositeDrawable { private readonly BeatmapInfo beatmapInfo; diff --git a/osu.Game/Screens/Select/Carousel/UpdateBeatmapSetButton.cs b/osu.Game/Screens/Select/Carousel/UpdateBeatmapSetButton.cs index 1bb607bcf3..e45583887a 100644 --- a/osu.Game/Screens/Select/Carousel/UpdateBeatmapSetButton.cs +++ b/osu.Game/Screens/Select/Carousel/UpdateBeatmapSetButton.cs @@ -20,7 +20,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.Select.Carousel { - public class UpdateBeatmapSetButton : OsuAnimatedButton + public partial class UpdateBeatmapSetButton : OsuAnimatedButton { private readonly BeatmapSetInfo beatmapSetInfo; private SpriteIcon icon = null!; diff --git a/osu.Game/Screens/Select/Carousel/UpdateLocalConfirmationDialog.cs b/osu.Game/Screens/Select/Carousel/UpdateLocalConfirmationDialog.cs index f5267e905e..e1aa662942 100644 --- a/osu.Game/Screens/Select/Carousel/UpdateLocalConfirmationDialog.cs +++ b/osu.Game/Screens/Select/Carousel/UpdateLocalConfirmationDialog.cs @@ -8,7 +8,7 @@ using osu.Game.Localisation; namespace osu.Game.Screens.Select.Carousel { - public class UpdateLocalConfirmationDialog : DeleteConfirmationDialog + public partial class UpdateLocalConfirmationDialog : DeleteConfirmationDialog { public UpdateLocalConfirmationDialog(Action onConfirm) { diff --git a/osu.Game/Screens/Select/Details/AdvancedStats.cs b/osu.Game/Screens/Select/Details/AdvancedStats.cs index 693f182065..5d0588e67b 100644 --- a/osu.Game/Screens/Select/Details/AdvancedStats.cs +++ b/osu.Game/Screens/Select/Details/AdvancedStats.cs @@ -28,7 +28,7 @@ using osu.Game.Rulesets; namespace osu.Game.Screens.Select.Details { - public class AdvancedStats : Container + public partial class AdvancedStats : Container { [Resolved] private IBindable> mods { get; set; } @@ -173,7 +173,7 @@ namespace osu.Game.Screens.Select.Details starDifficultyCancellationSource?.Cancel(); } - public class StatisticRow : Container, IHasAccentColour + public partial class StatisticRow : Container, IHasAccentColour { private const float value_width = 25; private const float name_width = 70; diff --git a/osu.Game/Screens/Select/Details/FailRetryGraph.cs b/osu.Game/Screens/Select/Details/FailRetryGraph.cs index 6fa6d50217..9891ef6463 100644 --- a/osu.Game/Screens/Select/Details/FailRetryGraph.cs +++ b/osu.Game/Screens/Select/Details/FailRetryGraph.cs @@ -14,7 +14,7 @@ using osu.Game.Beatmaps; namespace osu.Game.Screens.Select.Details { - public class FailRetryGraph : Container + public partial class FailRetryGraph : Container { private readonly BarGraph retryGraph, failGraph; diff --git a/osu.Game/Screens/Select/Details/UserRatings.cs b/osu.Game/Screens/Select/Details/UserRatings.cs index 39cb9c3d15..3664a89394 100644 --- a/osu.Game/Screens/Select/Details/UserRatings.cs +++ b/osu.Game/Screens/Select/Details/UserRatings.cs @@ -15,7 +15,7 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Screens.Select.Details { - public class UserRatings : Container + public partial class UserRatings : Container { private readonly FillFlowContainer header; private readonly Bar ratingsBar; diff --git a/osu.Game/Screens/Select/DifficultyRangeFilterControl.cs b/osu.Game/Screens/Select/DifficultyRangeFilterControl.cs deleted file mode 100644 index 45e7ff4caa..0000000000 --- a/osu.Game/Screens/Select/DifficultyRangeFilterControl.cs +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System; -using osu.Framework.Allocation; -using osu.Framework.Bindables; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Input.Events; -using osu.Framework.Localisation; -using osu.Game.Configuration; -using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; -using osu.Game.Localisation; -using osuTK; -using osuTK.Graphics; - -namespace osu.Game.Screens.Select -{ - internal class DifficultyRangeFilterControl : CompositeDrawable - { - private Bindable lowerStars = null!; - private Bindable upperStars = null!; - - [BackgroundDependencyLoader] - private void load(OsuConfigManager config) - { - const float vertical_offset = 13; - - InternalChildren = new Drawable[] - { - new OsuSpriteText - { - Text = "Difficulty range", - Font = OsuFont.GetFont(size: 14), - }, - new MaximumStarsSlider - { - Current = config.GetBindable(OsuSetting.DisplayStarsMaximum), - KeyboardStep = 0.1f, - RelativeSizeAxes = Axes.X, - Y = vertical_offset, - }, - new MinimumStarsSlider - { - Current = config.GetBindable(OsuSetting.DisplayStarsMinimum), - KeyboardStep = 0.1f, - RelativeSizeAxes = Axes.X, - Y = vertical_offset, - } - }; - - lowerStars = config.GetBindable(OsuSetting.DisplayStarsMinimum); - upperStars = config.GetBindable(OsuSetting.DisplayStarsMaximum); - } - - protected override void LoadComplete() - { - base.LoadComplete(); - - lowerStars.ValueChanged += min => upperStars.Value = Math.Max(min.NewValue + 0.1, upperStars.Value); - upperStars.ValueChanged += max => lowerStars.Value = Math.Min(max.NewValue - 0.1, lowerStars.Value); - } - - private class MinimumStarsSlider : StarsSlider - { - public MinimumStarsSlider() - : base("0") - { - } - - public override LocalisableString TooltipText => Current.Value.ToString(@"0.## stars"); - - protected override void LoadComplete() - { - base.LoadComplete(); - - LeftBox.Height = 6; // hide any colour bleeding from overlap - - AccentColour = BackgroundColour; - BackgroundColour = Color4.Transparent; - } - - public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => - base.ReceivePositionalInputAt(screenSpacePos) - && screenSpacePos.X <= Nub.ScreenSpaceDrawQuad.TopRight.X; - } - - private class MaximumStarsSlider : StarsSlider - { - public MaximumStarsSlider() - : base("∞") - { - } - - protected override void LoadComplete() - { - base.LoadComplete(); - - RightBox.Height = 6; // just to match the left bar height really - } - - public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => - base.ReceivePositionalInputAt(screenSpacePos) - && screenSpacePos.X >= Nub.ScreenSpaceDrawQuad.TopLeft.X; - } - - private class StarsSlider : OsuSliderBar - { - private readonly string defaultString; - - public override LocalisableString TooltipText => Current.IsDefault - ? UserInterfaceStrings.NoLimit - : Current.Value.ToString(@"0.## stars"); - - protected StarsSlider(string defaultString) - { - this.defaultString = defaultString; - } - - protected override bool OnHover(HoverEvent e) - { - base.OnHover(e); - return true; // Make sure only one nub shows hover effect at once. - } - - protected override void LoadComplete() - { - base.LoadComplete(); - Nub.Width = Nub.HEIGHT; - RangePadding = Nub.Width / 2; - - OsuSpriteText currentDisplay; - - Nub.Add(currentDisplay = new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Y = -0.5f, - Colour = Color4.White, - Font = OsuFont.Torus.With(size: 10), - }); - - Current.BindValueChanged(current => - { - currentDisplay.Text = current.NewValue != Current.Default ? current.NewValue.ToString("N1") : defaultString; - }, true); - } - } - } -} diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index ae82285fba..2f21ffbe6a 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -16,6 +16,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osu.Game.Localisation; using osu.Game.Resources.Localisation.Web; using osu.Game.Rulesets; using osu.Game.Screens.Select.Filter; @@ -24,7 +25,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.Select { - public class FilterControl : Container + public partial class FilterControl : Container { public const float HEIGHT = 2 * side_margin + 85; private const float side_margin = 20; @@ -172,12 +173,19 @@ namespace osu.Game.Screens.Select Height = 40, Children = new Drawable[] { - new DifficultyRangeFilterControl + new RangeSlider { Anchor = Anchor.TopLeft, Origin = Anchor.TopLeft, + Label = "Difficulty range", + LowerBound = config.GetBindable(OsuSetting.DisplayStarsMinimum), + UpperBound = config.GetBindable(OsuSetting.DisplayStarsMaximum), RelativeSizeAxes = Axes.Both, Width = 0.48f, + DefaultStringLowerBound = "0", + DefaultStringUpperBound = "∞", + DefaultTooltipUpperBound = UserInterfaceStrings.NoLimit, + TooltipSuffix = "stars" }, collectionDropdown = new CollectionDropdown { diff --git a/osu.Game/Screens/Select/Footer.cs b/osu.Game/Screens/Select/Footer.cs index f9fc2890b0..933df2464a 100644 --- a/osu.Game/Screens/Select/Footer.cs +++ b/osu.Game/Screens/Select/Footer.cs @@ -16,7 +16,7 @@ using osu.Game.Graphics.UserInterface; namespace osu.Game.Screens.Select { - public class Footer : Container + public partial class Footer : Container { private readonly Box modeLight; diff --git a/osu.Game/Screens/Select/FooterButton.cs b/osu.Game/Screens/Select/FooterButton.cs index 230cdfc13e..128e750dca 100644 --- a/osu.Game/Screens/Select/FooterButton.cs +++ b/osu.Game/Screens/Select/FooterButton.cs @@ -19,7 +19,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.Select { - public class FooterButton : OsuClickableContainer, IKeyBindingHandler + public partial class FooterButton : OsuClickableContainer, IKeyBindingHandler { public const float SHEAR_WIDTH = 7.5f; diff --git a/osu.Game/Screens/Select/FooterButtonMods.cs b/osu.Game/Screens/Select/FooterButtonMods.cs index 21f81995be..9a84f9a0aa 100644 --- a/osu.Game/Screens/Select/FooterButtonMods.cs +++ b/osu.Game/Screens/Select/FooterButtonMods.cs @@ -22,7 +22,7 @@ using osu.Game.Input.Bindings; namespace osu.Game.Screens.Select { - public class FooterButtonMods : FooterButton, IHasCurrentValue> + public partial class FooterButtonMods : FooterButton, IHasCurrentValue> { public Bindable> Current { diff --git a/osu.Game/Screens/Select/FooterButtonOptions.cs b/osu.Game/Screens/Select/FooterButtonOptions.cs index 764f56e79c..e56efcb458 100644 --- a/osu.Game/Screens/Select/FooterButtonOptions.cs +++ b/osu.Game/Screens/Select/FooterButtonOptions.cs @@ -10,7 +10,7 @@ using osu.Game.Input.Bindings; namespace osu.Game.Screens.Select { - public class FooterButtonOptions : FooterButton + public partial class FooterButtonOptions : FooterButton { [BackgroundDependencyLoader] private void load(OsuColour colours) diff --git a/osu.Game/Screens/Select/FooterButtonRandom.cs b/osu.Game/Screens/Select/FooterButtonRandom.cs index aad7fdff39..f413126e87 100644 --- a/osu.Game/Screens/Select/FooterButtonRandom.cs +++ b/osu.Game/Screens/Select/FooterButtonRandom.cs @@ -17,7 +17,7 @@ using osuTK.Input; namespace osu.Game.Screens.Select { - public class FooterButtonRandom : FooterButton + public partial class FooterButtonRandom : FooterButton { public Action NextRandom { get; set; } public Action PreviousRandom { get; set; } @@ -119,7 +119,7 @@ namespace osu.Game.Screens.Select protected override void OnMouseUp(MouseUpEvent e) { - if (e.Button == MouseButton.Right) + if (e.Button == MouseButton.Right && IsHovered) { rewindSearch = true; TriggerClick(); diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index 4cc3a30a1e..c419501add 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -21,7 +21,7 @@ using Realms; namespace osu.Game.Screens.Select.Leaderboards { - public class BeatmapLeaderboard : Leaderboard + public partial class BeatmapLeaderboard : Leaderboard { public Action? ScoreSelected; @@ -152,14 +152,23 @@ namespace osu.Game.Screens.Select.Leaderboards else if (filterMods) requestMods = mods.Value; - scoreRetrievalRequest = new GetScoresRequest(fetchBeatmapInfo, fetchRuleset, Scope, requestMods); + scoreRetrievalRequest?.Cancel(); - scoreRetrievalRequest.Success += response => SetScores( - scoreManager.OrderByTotalScore(response.Scores.Select(s => s.ToScoreInfo(rulesets, fetchBeatmapInfo))), - response.UserScore?.CreateScoreInfo(rulesets, fetchBeatmapInfo) - ); + var newRequest = new GetScoresRequest(fetchBeatmapInfo, fetchRuleset, Scope, requestMods); + newRequest.Success += response => Schedule(() => + { + // Request may have changed since fetch request. + // Can't rely on request cancellation due to Schedule inside SetScores so let's play it safe. + if (!newRequest.Equals(scoreRetrievalRequest)) + return; - return scoreRetrievalRequest; + SetScores( + scoreManager.OrderByTotalScore(response.Scores.Select(s => s.ToScoreInfo(rulesets, fetchBeatmapInfo))), + response.UserScore?.CreateScoreInfo(rulesets, fetchBeatmapInfo) + ); + }); + + return scoreRetrievalRequest = newRequest; } protected override LeaderboardScore CreateDrawableScore(ScoreInfo model, int index) => new LeaderboardScore(model, index, IsOnlineScope) diff --git a/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs b/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs index d9312679bc..6349e9e5eb 100644 --- a/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs +++ b/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs @@ -10,7 +10,7 @@ using osu.Game.Beatmaps; namespace osu.Game.Screens.Select { - public class LocalScoreDeleteDialog : DeleteConfirmationDialog + public partial class LocalScoreDeleteDialog : DeleteConfirmationDialog { private readonly ScoreInfo score; diff --git a/osu.Game/Screens/Select/NoResultsPlaceholder.cs b/osu.Game/Screens/Select/NoResultsPlaceholder.cs index 73b53defe0..9f870503d3 100644 --- a/osu.Game/Screens/Select/NoResultsPlaceholder.cs +++ b/osu.Game/Screens/Select/NoResultsPlaceholder.cs @@ -17,7 +17,7 @@ using osuTK; namespace osu.Game.Screens.Select { - public class NoResultsPlaceholder : VisibilityContainer + public partial class NoResultsPlaceholder : VisibilityContainer { private FilterCriteria? filter; diff --git a/osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs b/osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs index 69800c4e86..0d3e1238f3 100644 --- a/osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs +++ b/osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs @@ -20,7 +20,7 @@ using osu.Game.Graphics.UserInterface; namespace osu.Game.Screens.Select.Options { - public class BeatmapOptionsButton : OsuClickableContainer + public partial class BeatmapOptionsButton : OsuClickableContainer { private const float width = 130; diff --git a/osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs b/osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs index 8785dac0aa..c92dc2e343 100644 --- a/osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs +++ b/osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs @@ -19,7 +19,7 @@ using osu.Framework.Localisation; namespace osu.Game.Screens.Select.Options { - public class BeatmapOptionsOverlay : OsuFocusedOverlayContainer + public partial class BeatmapOptionsOverlay : OsuFocusedOverlayContainer { private const float transition_duration = 500; private const float x_position = 0.2f; diff --git a/osu.Game/Screens/Select/PlayBeatmapDetailArea.cs b/osu.Game/Screens/Select/PlayBeatmapDetailArea.cs index a19acddb48..8a1b9ef3e1 100644 --- a/osu.Game/Screens/Select/PlayBeatmapDetailArea.cs +++ b/osu.Game/Screens/Select/PlayBeatmapDetailArea.cs @@ -14,7 +14,7 @@ using osu.Game.Screens.Select.Leaderboards; namespace osu.Game.Screens.Select { - public class PlayBeatmapDetailArea : BeatmapDetailArea + public partial class PlayBeatmapDetailArea : BeatmapDetailArea { public readonly BeatmapLeaderboard Leaderboard; diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index 94e4215175..9edca1d0c0 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; using osu.Framework.Screens; using osu.Game.Graphics; +using osu.Game.Localisation; using osu.Game.Overlays; using osu.Game.Overlays.Notifications; using osu.Game.Rulesets.Mods; @@ -20,11 +21,11 @@ using osuTK.Input; namespace osu.Game.Screens.Select { - public class PlaySongSelect : SongSelect + public partial class PlaySongSelect : SongSelect { private OsuScreen? playerLoader; - [Resolved(CanBeNull = true)] + [Resolved] private INotificationOverlay? notifications { get; set; } public override bool AllowExternalScreenChange => true; @@ -89,7 +90,7 @@ namespace osu.Game.Screens.Select { notifications?.Post(new SimpleNotification { - Text = "The current ruleset doesn't have an autoplay mod avalaible!" + Text = NotificationsStrings.NoAutoplayMod }); return false; } diff --git a/osu.Game/Screens/Select/SkinDeleteDialog.cs b/osu.Game/Screens/Select/SkinDeleteDialog.cs index c701d9049f..9e11629890 100644 --- a/osu.Game/Screens/Select/SkinDeleteDialog.cs +++ b/osu.Game/Screens/Select/SkinDeleteDialog.cs @@ -7,7 +7,7 @@ using osu.Game.Overlays.Dialog; namespace osu.Game.Screens.Select { - public class SkinDeleteDialog : DeleteConfirmationDialog + public partial class SkinDeleteDialog : DeleteConfirmationDialog { private readonly Skin skin; diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 18ea0f69a2..f4804c6a6c 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -42,7 +42,7 @@ using osu.Game.Skinning; namespace osu.Game.Screens.Select { - public abstract class SongSelect : ScreenWithBeatmapBackground, IKeyBindingHandler + public abstract partial class SongSelect : ScreenWithBeatmapBackground, IKeyBindingHandler { public static readonly float WEDGE_HEIGHT = 245; @@ -925,7 +925,7 @@ namespace osu.Game.Screens.Select return base.OnKeyDown(e); } - private class VerticalMaskingContainer : Container + private partial class VerticalMaskingContainer : Container { private const float panel_overflow = 1.2f; @@ -948,7 +948,7 @@ namespace osu.Game.Screens.Select } } - private class ResetScrollContainer : Container + private partial class ResetScrollContainer : Container { private readonly Action onHoverAction; @@ -964,7 +964,7 @@ namespace osu.Game.Screens.Select } } - internal class SoloModSelectOverlay : UserModSelectOverlay + internal partial class SoloModSelectOverlay : UserModSelectOverlay { protected override bool ShowPresets => true; } diff --git a/osu.Game/Screens/Select/WedgeBackground.cs b/osu.Game/Screens/Select/WedgeBackground.cs index 4a5b9d8911..da12c1a67a 100644 --- a/osu.Game/Screens/Select/WedgeBackground.cs +++ b/osu.Game/Screens/Select/WedgeBackground.cs @@ -12,7 +12,7 @@ using osu.Framework.Graphics.Shapes; namespace osu.Game.Screens.Select { - public class WedgeBackground : Container + public partial class WedgeBackground : Container { public WedgeBackground() { diff --git a/osu.Game/Screens/Spectate/SpectatorScreen.cs b/osu.Game/Screens/Spectate/SpectatorScreen.cs index 259ac0160d..2b56767bd0 100644 --- a/osu.Game/Screens/Spectate/SpectatorScreen.cs +++ b/osu.Game/Screens/Spectate/SpectatorScreen.cs @@ -26,7 +26,7 @@ namespace osu.Game.Screens.Spectate /// /// A which spectates one or more users. /// - public abstract class SpectatorScreen : OsuScreen + public abstract partial class SpectatorScreen : OsuScreen { protected IReadOnlyList Users => users; diff --git a/osu.Game/Screens/StartupScreen.cs b/osu.Game/Screens/StartupScreen.cs index 89761d80de..84ef3eac78 100644 --- a/osu.Game/Screens/StartupScreen.cs +++ b/osu.Game/Screens/StartupScreen.cs @@ -10,7 +10,7 @@ namespace osu.Game.Screens /// /// A screen which is shown once as part of the startup procedure. /// - public abstract class StartupScreen : OsuScreen + public abstract partial class StartupScreen : OsuScreen { public override bool AllowBackButton => false; diff --git a/osu.Game/Screens/Utility/ButtonWithKeyBind.cs b/osu.Game/Screens/Utility/ButtonWithKeyBind.cs index 7df9a22ce4..7c78836b12 100644 --- a/osu.Game/Screens/Utility/ButtonWithKeyBind.cs +++ b/osu.Game/Screens/Utility/ButtonWithKeyBind.cs @@ -11,7 +11,7 @@ using osuTK.Input; namespace osu.Game.Screens.Utility { - public class ButtonWithKeyBind : SettingsButton + public partial class ButtonWithKeyBind : SettingsButton { private readonly Key key; @@ -47,6 +47,8 @@ namespace osu.Game.Screens.Utility Height = 100; SpriteText.Colour = overlayColourProvider.Background6; SpriteText.Font = OsuFont.TorusAlternate.With(size: 34); + + Triangles?.Hide(); } } } diff --git a/osu.Game/Screens/Utility/CircleGameplay.cs b/osu.Game/Screens/Utility/CircleGameplay.cs index 1ee5567c43..d97812acb4 100644 --- a/osu.Game/Screens/Utility/CircleGameplay.cs +++ b/osu.Game/Screens/Utility/CircleGameplay.cs @@ -18,7 +18,7 @@ using osuTK; namespace osu.Game.Screens.Utility { - public class CircleGameplay : LatencySampleComponent + public partial class CircleGameplay : LatencySampleComponent { private int nextLocation; @@ -111,7 +111,7 @@ namespace osu.Game.Screens.Utility hitEvents.Add(h); } - public class SampleHitCircle : LatencySampleComponent + public partial class SampleHitCircle : LatencySampleComponent { public HitEvent? HitEvent; diff --git a/osu.Game/Screens/Utility/LatencyArea.cs b/osu.Game/Screens/Utility/LatencyArea.cs index b7d45ba642..b225171f5d 100644 --- a/osu.Game/Screens/Utility/LatencyArea.cs +++ b/osu.Game/Screens/Utility/LatencyArea.cs @@ -17,7 +17,7 @@ using osuTK.Input; namespace osu.Game.Screens.Utility { [Cached] - public class LatencyArea : CompositeDrawable, IProvideCursor + public partial class LatencyArea : CompositeDrawable, IProvideCursor { [Resolved] private OverlayColourProvider overlayColourProvider { get; set; } = null!; diff --git a/osu.Game/Screens/Utility/LatencyCertifierScreen.cs b/osu.Game/Screens/Utility/LatencyCertifierScreen.cs index bacaccd68e..5c8e448931 100644 --- a/osu.Game/Screens/Utility/LatencyCertifierScreen.cs +++ b/osu.Game/Screens/Utility/LatencyCertifierScreen.cs @@ -30,7 +30,7 @@ using osuTK.Input; namespace osu.Game.Screens.Utility { [Cached] - public class LatencyCertifierScreen : OsuScreen + public partial class LatencyCertifierScreen : OsuScreen { private FrameSync previousFrameSyncMode; private double previousActiveHz; @@ -237,7 +237,7 @@ namespace osu.Game.Screens.Utility switch (e.Key) { case Key.Space: - int availableModes = Enum.GetValues(typeof(LatencyVisualMode)).Length; + int availableModes = Enum.GetValues().Length; VisualMode.Value = (LatencyVisualMode)(((int)VisualMode.Value + 1) % availableModes); return true; @@ -259,10 +259,7 @@ namespace osu.Game.Screens.Utility var displayMode = host.Window?.CurrentDisplayMode.Value; - string exclusive = "unknown"; - - if (host.Renderer is IWindowsRenderer windowsRenderer) - exclusive = windowsRenderer.FullscreenCapability.ToString(); + string exclusive = (host.Renderer as IWindowsRenderer)?.FullscreenCapability.ToString() ?? "unknown"; statusText.Clear(); diff --git a/osu.Game/Screens/Utility/SampleComponents/LatencyCursorContainer.cs b/osu.Game/Screens/Utility/SampleComponents/LatencyCursorContainer.cs index aaf837eb60..251d283242 100644 --- a/osu.Game/Screens/Utility/SampleComponents/LatencyCursorContainer.cs +++ b/osu.Game/Screens/Utility/SampleComponents/LatencyCursorContainer.cs @@ -12,7 +12,7 @@ using osuTK.Input; namespace osu.Game.Screens.Utility.SampleComponents { - public class LatencyCursorContainer : CursorContainer + public partial class LatencyCursorContainer : CursorContainer { protected override Drawable CreateCursor() => new LatencyCursor(); @@ -32,7 +32,7 @@ namespace osu.Game.Screens.Utility.SampleComponents return false; } - private class LatencyCursor : LatencySampleComponent + private partial class LatencyCursor : LatencySampleComponent { public LatencyCursor() { diff --git a/osu.Game/Screens/Utility/SampleComponents/LatencyMovableBox.cs b/osu.Game/Screens/Utility/SampleComponents/LatencyMovableBox.cs index 8b6841caf0..dcfcf602bf 100644 --- a/osu.Game/Screens/Utility/SampleComponents/LatencyMovableBox.cs +++ b/osu.Game/Screens/Utility/SampleComponents/LatencyMovableBox.cs @@ -10,7 +10,7 @@ using osuTK.Input; namespace osu.Game.Screens.Utility.SampleComponents { - public class LatencyMovableBox : LatencySampleComponent + public partial class LatencyMovableBox : LatencySampleComponent { private Box box = null!; diff --git a/osu.Game/Screens/Utility/SampleComponents/LatencySampleComponent.cs b/osu.Game/Screens/Utility/SampleComponents/LatencySampleComponent.cs index 834865d237..690376cf52 100644 --- a/osu.Game/Screens/Utility/SampleComponents/LatencySampleComponent.cs +++ b/osu.Game/Screens/Utility/SampleComponents/LatencySampleComponent.cs @@ -10,7 +10,7 @@ using osu.Game.Overlays; namespace osu.Game.Screens.Utility.SampleComponents { - public abstract class LatencySampleComponent : CompositeDrawable + public abstract partial class LatencySampleComponent : CompositeDrawable { protected readonly BindableDouble SampleBPM = new BindableDouble(); protected readonly BindableDouble SampleApproachRate = new BindableDouble(); diff --git a/osu.Game/Screens/Utility/ScrollingGameplay.cs b/osu.Game/Screens/Utility/ScrollingGameplay.cs index 1f40514cd5..f1331d8fb2 100644 --- a/osu.Game/Screens/Utility/ScrollingGameplay.cs +++ b/osu.Game/Screens/Utility/ScrollingGameplay.cs @@ -18,7 +18,7 @@ using osuTK.Input; namespace osu.Game.Screens.Utility { - public class ScrollingGameplay : LatencySampleComponent + public partial class ScrollingGameplay : LatencySampleComponent { private const float judgement_position = 0.8f; private const float bar_height = 20; @@ -100,7 +100,7 @@ namespace osu.Game.Screens.Utility hitEvents.Add(h); } - public class SampleNote : LatencySampleComponent + public partial class SampleNote : LatencySampleComponent { public HitEvent? HitEvent; diff --git a/osu.Game/Skinning/ArgonProSkin.cs b/osu.Game/Skinning/ArgonProSkin.cs new file mode 100644 index 0000000000..b753dd8fbe --- /dev/null +++ b/osu.Game/Skinning/ArgonProSkin.cs @@ -0,0 +1,48 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using JetBrains.Annotations; +using osu.Framework.Audio.Sample; +using osu.Game.Audio; +using osu.Game.Extensions; +using osu.Game.IO; + +namespace osu.Game.Skinning +{ + public class ArgonProSkin : ArgonSkin + { + public new static SkinInfo CreateInfo() => new SkinInfo + { + ID = Skinning.SkinInfo.ARGON_PRO_SKIN, + Name = "osu! \"argon\" pro (2022)", + Creator = "team osu!", + Protected = true, + InstantiationInfo = typeof(ArgonProSkin).GetInvariantInstantiationInfo() + }; + + public override ISample? GetSample(ISampleInfo sampleInfo) + { + foreach (string lookup in sampleInfo.LookupNames) + { + string remappedLookup = lookup.Replace(@"Gameplay/", @"Gameplay/ArgonPro/"); + + var sample = Samples?.Get(remappedLookup) ?? Resources.AudioManager?.Samples.Get(remappedLookup); + if (sample != null) + return sample; + } + + return null; + } + + public ArgonProSkin(IStorageResourceProvider resources) + : this(CreateInfo(), resources) + { + } + + [UsedImplicitly(ImplicitUseKindFlags.InstantiatedWithFixedConstructorSignature)] + public ArgonProSkin(SkinInfo skin, IStorageResourceProvider resources) + : base(skin, resources) + { + } + } +} diff --git a/osu.Game/Skinning/ArgonSkin.cs b/osu.Game/Skinning/ArgonSkin.cs index 6a0c4a23e5..d78147aaea 100644 --- a/osu.Game/Skinning/ArgonSkin.cs +++ b/osu.Game/Skinning/ArgonSkin.cs @@ -30,7 +30,7 @@ namespace osu.Game.Skinning InstantiationInfo = typeof(ArgonSkin).GetInvariantInstantiationInfo() }; - private readonly IStorageResourceProvider resources; + protected readonly IStorageResourceProvider Resources; public ArgonSkin(IStorageResourceProvider resources) : this(CreateInfo(), resources) @@ -41,7 +41,7 @@ namespace osu.Game.Skinning public ArgonSkin(SkinInfo skin, IStorageResourceProvider resources) : base(skin, resources) { - this.resources = resources; + Resources = resources; Configuration.CustomComboColours = new List { @@ -72,7 +72,7 @@ namespace osu.Game.Skinning { foreach (string lookup in sampleInfo.LookupNames) { - var sample = Samples?.Get(lookup) ?? resources.AudioManager?.Samples.Get(lookup); + var sample = Samples?.Get(lookup) ?? Resources.AudioManager?.Samples.Get(lookup); if (sample != null) return sample; } diff --git a/osu.Game/Skinning/BeatmapSkinProvidingContainer.cs b/osu.Game/Skinning/BeatmapSkinProvidingContainer.cs index e14287c318..4486c8a9f0 100644 --- a/osu.Game/Skinning/BeatmapSkinProvidingContainer.cs +++ b/osu.Game/Skinning/BeatmapSkinProvidingContainer.cs @@ -15,7 +15,7 @@ namespace osu.Game.Skinning /// /// A container which overrides existing skin options with beatmap-local values. /// - public class BeatmapSkinProvidingContainer : SkinProvidingContainer + public partial class BeatmapSkinProvidingContainer : SkinProvidingContainer { private Bindable beatmapSkins; private Bindable beatmapColours; diff --git a/osu.Game/Skinning/Components/BeatmapAttributeText.cs b/osu.Game/Skinning/Components/BeatmapAttributeText.cs index ec84831fb4..8361619574 100644 --- a/osu.Game/Skinning/Components/BeatmapAttributeText.cs +++ b/osu.Game/Skinning/Components/BeatmapAttributeText.cs @@ -24,7 +24,7 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Skinning.Components { [UsedImplicitly] - public class BeatmapAttributeText : Container, ISkinnableDrawable + public partial class BeatmapAttributeText : Container, ISkinnableDrawable { public bool UsesFixedAnchor { get; set; } @@ -115,7 +115,7 @@ namespace osu.Game.Skinning.Components .Cast() .ToArray(); - foreach (var type in Enum.GetValues(typeof(BeatmapAttribute)).Cast()) + foreach (var type in Enum.GetValues()) { numberedTemplate = numberedTemplate.Replace($"{{{{{type}}}}}", $"{{{1 + (int)type}}}"); } diff --git a/osu.Game/Skinning/Components/BigBlackBox.cs b/osu.Game/Skinning/Components/BigBlackBox.cs index 5bdee827ca..4210a70b72 100644 --- a/osu.Game/Skinning/Components/BigBlackBox.cs +++ b/osu.Game/Skinning/Components/BigBlackBox.cs @@ -21,7 +21,7 @@ namespace osu.Game.Skinning.Components /// Intended to be a test bed for skinning. May be removed at some point in the future. /// [UsedImplicitly] - public class BigBlackBox : CompositeDrawable, ISkinnableDrawable + public partial class BigBlackBox : CompositeDrawable, ISkinnableDrawable { public bool UsesFixedAnchor { get; set; } diff --git a/osu.Game/Skinning/Components/TextElement.cs b/osu.Game/Skinning/Components/TextElement.cs index 1e618a7f82..74a0acb979 100644 --- a/osu.Game/Skinning/Components/TextElement.cs +++ b/osu.Game/Skinning/Components/TextElement.cs @@ -12,7 +12,7 @@ using osu.Game.Graphics.Sprites; namespace osu.Game.Skinning.Components { [UsedImplicitly] - public class TextElement : Container, ISkinnableDrawable + public partial class TextElement : Container, ISkinnableDrawable { public bool UsesFixedAnchor { get; set; } diff --git a/osu.Game/Skinning/Editor/SkinBlueprint.cs b/osu.Game/Skinning/Editor/SkinBlueprint.cs index ecf1de89da..fc7e9e8ef1 100644 --- a/osu.Game/Skinning/Editor/SkinBlueprint.cs +++ b/osu.Game/Skinning/Editor/SkinBlueprint.cs @@ -18,7 +18,7 @@ using osuTK.Graphics; namespace osu.Game.Skinning.Editor { - public class SkinBlueprint : SelectionBlueprint + public partial class SkinBlueprint : SelectionBlueprint { private Container box; @@ -131,7 +131,7 @@ namespace osu.Game.Skinning.Editor public override Quad SelectionQuad => drawable.ScreenSpaceDrawQuad; } - internal class AnchorOriginVisualiser : CompositeDrawable + internal partial class AnchorOriginVisualiser : CompositeDrawable { private readonly Drawable drawable; diff --git a/osu.Game/Skinning/Editor/SkinBlueprintContainer.cs b/osu.Game/Skinning/Editor/SkinBlueprintContainer.cs index 2937b62eec..9812406aad 100644 --- a/osu.Game/Skinning/Editor/SkinBlueprintContainer.cs +++ b/osu.Game/Skinning/Editor/SkinBlueprintContainer.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Collections.Specialized; +using System.Diagnostics; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -20,7 +21,7 @@ using osuTK.Input; namespace osu.Game.Skinning.Editor { - public class SkinBlueprintContainer : BlueprintContainer + public partial class SkinBlueprintContainer : BlueprintContainer { private readonly Drawable target; @@ -65,17 +66,24 @@ namespace osu.Game.Skinning.Editor switch (e.Action) { case NotifyCollectionChangedAction.Add: + Debug.Assert(e.NewItems != null); + foreach (var item in e.NewItems.Cast()) AddBlueprintFor(item); break; case NotifyCollectionChangedAction.Remove: case NotifyCollectionChangedAction.Reset: + Debug.Assert(e.OldItems != null); + foreach (var item in e.OldItems.Cast()) RemoveBlueprintFor(item); break; case NotifyCollectionChangedAction.Replace: + Debug.Assert(e.NewItems != null); + Debug.Assert(e.OldItems != null); + foreach (var item in e.OldItems.Cast()) RemoveBlueprintFor(item); diff --git a/osu.Game/Skinning/Editor/SkinComponentToolbox.cs b/osu.Game/Skinning/Editor/SkinComponentToolbox.cs index 469657c03c..9985b81059 100644 --- a/osu.Game/Skinning/Editor/SkinComponentToolbox.cs +++ b/osu.Game/Skinning/Editor/SkinComponentToolbox.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Diagnostics; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -11,6 +10,7 @@ using osu.Framework.Logging; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osu.Game.Localisation; using osu.Game.Overlays; using osu.Game.Screens.Edit.Components; using osu.Game.Screens.Play.HUD; @@ -18,7 +18,7 @@ using osuTK; namespace osu.Game.Skinning.Editor { - public class SkinComponentToolbox : EditorSidebarSection + public partial class SkinComponentToolbox : EditorSidebarSection { public Action? RequestPlacement; @@ -27,7 +27,7 @@ namespace osu.Game.Skinning.Editor private FillFlowContainer fill = null!; public SkinComponentToolbox(CompositeDrawable? target = null) - : base("Components") + : base(SkinEditorStrings.Components) { this.target = target; } @@ -59,9 +59,7 @@ namespace osu.Game.Skinning.Editor { try { - var instance = (Drawable)Activator.CreateInstance(type); - - Debug.Assert(instance != null); + Drawable instance = (Drawable)Activator.CreateInstance(type)!; if (!((ISkinnableDrawable)instance).IsEditable) return; @@ -81,7 +79,7 @@ namespace osu.Game.Skinning.Editor } } - public class ToolboxComponentButton : OsuButton + public partial class ToolboxComponentButton : OsuButton { public Action? RequestPlacement; @@ -171,7 +169,7 @@ namespace osu.Game.Skinning.Editor } } - public class DependencyBorrowingContainer : Container + public partial class DependencyBorrowingContainer : Container { protected override bool ShouldBeConsideredForInput(Drawable child) => false; diff --git a/osu.Game/Skinning/Editor/SkinEditor.cs b/osu.Game/Skinning/Editor/SkinEditor.cs index 410f5d9347..98b4e960dd 100644 --- a/osu.Game/Skinning/Editor/SkinEditor.cs +++ b/osu.Game/Skinning/Editor/SkinEditor.cs @@ -32,7 +32,7 @@ using osu.Game.Screens.Edit.Components.Menus; namespace osu.Game.Skinning.Editor { [Cached(typeof(SkinEditor))] - public class SkinEditor : VisibilityContainer, ICanAcceptFiles, IKeyBindingHandler + public partial class SkinEditor : VisibilityContainer, ICanAcceptFiles, IKeyBindingHandler { public const double TRANSITION_DURATION = 500; @@ -109,7 +109,7 @@ namespace osu.Game.Skinning.Editor { new Container { - Name = "Menu container", + Name = @"Menu container", RelativeSizeAxes = Axes.X, Depth = float.MinValue, Height = MENU_HEIGHT, @@ -122,14 +122,14 @@ namespace osu.Game.Skinning.Editor RelativeSizeAxes = Axes.Both, Items = new[] { - new MenuItem("File") + new MenuItem(CommonStrings.MenuBarFile) { Items = new[] { - new EditorMenuItem("Save", MenuItemType.Standard, Save), - new EditorMenuItem("Revert to default", MenuItemType.Destructive, revert), + new EditorMenuItem(Resources.Localisation.Web.CommonStrings.ButtonsSave, MenuItemType.Standard, Save), + new EditorMenuItem(CommonStrings.RevertToDefault, MenuItemType.Destructive, revert), new EditorMenuItemSpacer(), - new EditorMenuItem("Exit", MenuItemType.Standard, () => skinEditorOverlay?.Hide()), + new EditorMenuItem(CommonStrings.Exit, MenuItemType.Standard, () => skinEditorOverlay?.Hide()), }, }, } @@ -234,7 +234,6 @@ namespace osu.Game.Skinning.Editor // Immediately clear the previous blueprint container to ensure it doesn't try to interact with the old target. content?.Clear(); - Scheduler.AddOnce(loadBlueprintContainer); Scheduler.AddOnce(populateSettings); @@ -253,7 +252,7 @@ namespace osu.Game.Skinning.Editor { headerText.Clear(); - headerText.AddParagraph("Skin editor", cp => cp.Font = OsuFont.Default.With(size: 16)); + headerText.AddParagraph(SkinEditorStrings.SkinEditor, cp => cp.Font = OsuFont.Default.With(size: 16)); headerText.NewParagraph(); headerText.AddText("Currently editing ", cp => { @@ -411,7 +410,7 @@ namespace osu.Game.Skinning.Editor return Task.CompletedTask; } - public Task Import(params ImportTask[] tasks) => throw new NotImplementedException(); + Task ICanAcceptFiles.Import(ImportTask[] tasks, ImportParameters parameters) => throw new NotImplementedException(); public IEnumerable HandledExtensions => new[] { ".jpg", ".jpeg", ".png" }; @@ -424,7 +423,7 @@ namespace osu.Game.Skinning.Editor game?.UnregisterImportHandler(this); } - private class SkinEditorToast : Toast + private partial class SkinEditorToast : Toast { public SkinEditorToast(LocalisableString value, string skinDisplayName) : base(SkinSettingsStrings.SkinLayoutEditor, value, skinDisplayName) diff --git a/osu.Game/Skinning/Editor/SkinEditorOverlay.cs b/osu.Game/Skinning/Editor/SkinEditorOverlay.cs index 000917f728..35e28ee665 100644 --- a/osu.Game/Skinning/Editor/SkinEditorOverlay.cs +++ b/osu.Game/Skinning/Editor/SkinEditorOverlay.cs @@ -23,7 +23,7 @@ namespace osu.Game.Skinning.Editor /// A container which handles loading a skin editor on user request for a specified target. /// This also handles the scaling / positioning adjustment of the target. /// - public class SkinEditorOverlay : OverlayContainer, IKeyBindingHandler + public partial class SkinEditorOverlay : OverlayContainer, IKeyBindingHandler { private readonly ScalingContainer scalingContainer; diff --git a/osu.Game/Skinning/Editor/SkinEditorSceneLibrary.cs b/osu.Game/Skinning/Editor/SkinEditorSceneLibrary.cs index 4efbf58881..44045e8916 100644 --- a/osu.Game/Skinning/Editor/SkinEditorSceneLibrary.cs +++ b/osu.Game/Skinning/Editor/SkinEditorSceneLibrary.cs @@ -16,6 +16,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osu.Game.Localisation; using osu.Game.Overlays; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; @@ -27,7 +28,7 @@ using osuTK; namespace osu.Game.Skinning.Editor { - public class SkinEditorSceneLibrary : CompositeDrawable + public partial class SkinEditorSceneLibrary : CompositeDrawable { public const float HEIGHT = BUTTON_HEIGHT + padding * 2; @@ -66,7 +67,7 @@ namespace osu.Game.Skinning.Editor { new FillFlowContainer { - Name = "Scene library", + Name = @"Scene library", AutoSizeAxes = Axes.X, RelativeSizeAxes = Axes.Y, Spacing = new Vector2(padding), @@ -76,14 +77,14 @@ namespace osu.Game.Skinning.Editor { new OsuSpriteText { - Text = "Scene library", + Text = SkinEditorStrings.SceneLibrary, Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, Margin = new MarginPadding(10), }, new SceneButton { - Text = "Song Select", + Text = SkinEditorStrings.SongSelect, Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, Action = () => performer?.PerformFromScreen(screen => @@ -96,7 +97,7 @@ namespace osu.Game.Skinning.Editor }, new SceneButton { - Text = "Gameplay", + Text = SkinEditorStrings.Gameplay, Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, Action = () => performer?.PerformFromScreen(screen => @@ -120,7 +121,7 @@ namespace osu.Game.Skinning.Editor }; } - public class SceneButton : OsuButton + public partial class SceneButton : OsuButton { public SceneButton() { diff --git a/osu.Game/Skinning/Editor/SkinSelectionHandler.cs b/osu.Game/Skinning/Editor/SkinSelectionHandler.cs index 2e2122f7c2..2c3f6238ec 100644 --- a/osu.Game/Skinning/Editor/SkinSelectionHandler.cs +++ b/osu.Game/Skinning/Editor/SkinSelectionHandler.cs @@ -20,7 +20,7 @@ using osuTK; namespace osu.Game.Skinning.Editor { - public class SkinSelectionHandler : SelectionHandler + public partial class SkinSelectionHandler : SelectionHandler { [Resolved] private SkinEditor skinEditor { get; set; } diff --git a/osu.Game/Skinning/Editor/SkinSettingsToolbox.cs b/osu.Game/Skinning/Editor/SkinSettingsToolbox.cs index 3e19fc3afe..6afe92c6b2 100644 --- a/osu.Game/Skinning/Editor/SkinSettingsToolbox.cs +++ b/osu.Game/Skinning/Editor/SkinSettingsToolbox.cs @@ -1,23 +1,22 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Configuration; +using osu.Game.Localisation; using osu.Game.Screens.Edit.Components; using osuTK; namespace osu.Game.Skinning.Editor { - internal class SkinSettingsToolbox : EditorSidebarSection + internal partial class SkinSettingsToolbox : EditorSidebarSection { protected override Container Content { get; } public SkinSettingsToolbox(Drawable component) - : base($"Settings ({component.GetType().Name})") + : base(SkinEditorStrings.Settings(component.GetType().Name)) { base.Content.Add(Content = new FillFlowContainer { diff --git a/osu.Game/Skinning/GameplaySkinComponentLookup.cs b/osu.Game/Skinning/GameplaySkinComponentLookup.cs index 2d1dec4691..9247ca0e4d 100644 --- a/osu.Game/Skinning/GameplaySkinComponentLookup.cs +++ b/osu.Game/Skinning/GameplaySkinComponentLookup.cs @@ -16,7 +16,7 @@ namespace osu.Game.Skinning } protected virtual string RulesetPrefix => string.Empty; - protected virtual string ComponentName => Component.ToString(); + protected virtual string ComponentName => Component.ToString() ?? string.Empty; public string LookupName => string.Join('/', new[] { "Gameplay", RulesetPrefix, ComponentName }.Where(s => !string.IsNullOrEmpty(s))); diff --git a/osu.Game/Skinning/LegacyAccuracyCounter.cs b/osu.Game/Skinning/LegacyAccuracyCounter.cs index bdcb85456a..e75fb1e7e9 100644 --- a/osu.Game/Skinning/LegacyAccuracyCounter.cs +++ b/osu.Game/Skinning/LegacyAccuracyCounter.cs @@ -8,7 +8,7 @@ using osuTK; namespace osu.Game.Skinning { - public class LegacyAccuracyCounter : GameplayAccuracyCounter, ISkinnableDrawable + public partial class LegacyAccuracyCounter : GameplayAccuracyCounter, ISkinnableDrawable { public bool UsesFixedAnchor { get; set; } diff --git a/osu.Game/Skinning/LegacyComboCounter.cs b/osu.Game/Skinning/LegacyComboCounter.cs index f4caef26c2..c132a72001 100644 --- a/osu.Game/Skinning/LegacyComboCounter.cs +++ b/osu.Game/Skinning/LegacyComboCounter.cs @@ -15,7 +15,7 @@ namespace osu.Game.Skinning /// /// Uses the 'x' symbol and has a pop-out effect while rolling over. /// - public class LegacyComboCounter : CompositeDrawable, ISkinnableDrawable + public partial class LegacyComboCounter : CompositeDrawable, ISkinnableDrawable { public Bindable Current { get; } = new BindableInt { MinValue = 0 }; diff --git a/osu.Game/Skinning/LegacyHealthDisplay.cs b/osu.Game/Skinning/LegacyHealthDisplay.cs index 236e9c355e..c3cb9770fa 100644 --- a/osu.Game/Skinning/LegacyHealthDisplay.cs +++ b/osu.Game/Skinning/LegacyHealthDisplay.cs @@ -19,7 +19,7 @@ using osuTK.Graphics; namespace osu.Game.Skinning { - public class LegacyHealthDisplay : HealthDisplay, ISkinnableDrawable + public partial class LegacyHealthDisplay : HealthDisplay, ISkinnableDrawable { private const double epic_cutoff = 0.5; @@ -94,7 +94,7 @@ namespace osu.Game.Skinning return Color4.White; } - public class LegacyOldStyleMarker : LegacyMarker + public partial class LegacyOldStyleMarker : LegacyMarker { private readonly Texture normalTexture; private readonly Texture dangerTexture; @@ -129,7 +129,7 @@ namespace osu.Game.Skinning } } - public class LegacyNewStyleMarker : LegacyMarker + public partial class LegacyNewStyleMarker : LegacyMarker { private readonly ISkin skin; @@ -153,7 +153,7 @@ namespace osu.Game.Skinning } } - internal abstract class LegacyFill : LegacyHealthPiece + internal abstract partial class LegacyFill : LegacyHealthPiece { protected LegacyFill(ISkin skin) { @@ -175,7 +175,7 @@ namespace osu.Game.Skinning } } - internal class LegacyOldStyleFill : LegacyFill + internal partial class LegacyOldStyleFill : LegacyFill { public LegacyOldStyleFill(ISkin skin) : base(skin) @@ -184,7 +184,7 @@ namespace osu.Game.Skinning } } - internal class LegacyNewStyleFill : LegacyFill + internal partial class LegacyNewStyleFill : LegacyFill { public LegacyNewStyleFill(ISkin skin) : base(skin) @@ -199,7 +199,7 @@ namespace osu.Game.Skinning } } - public abstract class LegacyMarker : LegacyHealthPiece + public abstract partial class LegacyMarker : LegacyHealthPiece { protected Sprite Main; @@ -252,7 +252,7 @@ namespace osu.Game.Skinning Main.ScaleTo(1.4f).Then().ScaleTo(1, 200, Easing.Out); } - public class LegacyHealthPiece : CompositeDrawable + public partial class LegacyHealthPiece : CompositeDrawable { public Bindable Current { get; } = new Bindable(); diff --git a/osu.Game/Skinning/LegacyJudgementPieceNew.cs b/osu.Game/Skinning/LegacyJudgementPieceNew.cs index 39b266ab9f..2430e511c4 100644 --- a/osu.Game/Skinning/LegacyJudgementPieceNew.cs +++ b/osu.Game/Skinning/LegacyJudgementPieceNew.cs @@ -14,7 +14,7 @@ using osuTK; namespace osu.Game.Skinning { - public class LegacyJudgementPieceNew : CompositeDrawable, IAnimatableJudgement + public partial class LegacyJudgementPieceNew : CompositeDrawable, IAnimatableJudgement { private readonly HitResult result; diff --git a/osu.Game/Skinning/LegacyJudgementPieceOld.cs b/osu.Game/Skinning/LegacyJudgementPieceOld.cs index 3f4d13c082..0223e7a5a2 100644 --- a/osu.Game/Skinning/LegacyJudgementPieceOld.cs +++ b/osu.Game/Skinning/LegacyJudgementPieceOld.cs @@ -13,7 +13,7 @@ using osu.Game.Rulesets.Scoring; namespace osu.Game.Skinning { - public class LegacyJudgementPieceOld : CompositeDrawable, IAnimatableJudgement + public partial class LegacyJudgementPieceOld : CompositeDrawable, IAnimatableJudgement { private readonly HitResult result; diff --git a/osu.Game/Skinning/LegacyKiaiFlashingDrawable.cs b/osu.Game/Skinning/LegacyKiaiFlashingDrawable.cs index 2bcdd5b5a1..2f79512ed8 100644 --- a/osu.Game/Skinning/LegacyKiaiFlashingDrawable.cs +++ b/osu.Game/Skinning/LegacyKiaiFlashingDrawable.cs @@ -6,14 +6,21 @@ using osu.Framework.Audio.Track; using osu.Framework.Graphics; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics.Containers; +using osuTK.Graphics; namespace osu.Game.Skinning { - public class LegacyKiaiFlashingDrawable : BeatSyncedContainer + public partial class LegacyKiaiFlashingDrawable : BeatSyncedContainer { + public Color4 KiaiGlowColour + { + get => flashingDrawable.Colour; + set => flashingDrawable.Colour = value; + } + private readonly Drawable flashingDrawable; - private const float flash_opacity = 0.55f; + private const float flash_opacity = 0.3f; public LegacyKiaiFlashingDrawable(Func creationFunc) { diff --git a/osu.Game/Skinning/LegacyRollingCounter.cs b/osu.Game/Skinning/LegacyRollingCounter.cs index fd17b06a21..465f1c3a20 100644 --- a/osu.Game/Skinning/LegacyRollingCounter.cs +++ b/osu.Game/Skinning/LegacyRollingCounter.cs @@ -12,7 +12,7 @@ namespace osu.Game.Skinning /// /// An integer that uses number sprites from a legacy skin. /// - public class LegacyRollingCounter : RollingCounter + public partial class LegacyRollingCounter : RollingCounter { private readonly LegacyFont font; diff --git a/osu.Game/Skinning/LegacyScoreCounter.cs b/osu.Game/Skinning/LegacyScoreCounter.cs index aee594454f..6a14ed93e9 100644 --- a/osu.Game/Skinning/LegacyScoreCounter.cs +++ b/osu.Game/Skinning/LegacyScoreCounter.cs @@ -10,7 +10,7 @@ using osuTK; namespace osu.Game.Skinning { - public class LegacyScoreCounter : GameplayScoreCounter, ISkinnableDrawable + public partial class LegacyScoreCounter : GameplayScoreCounter, ISkinnableDrawable { protected override double RollingDuration => 1000; protected override Easing RollingEasing => Easing.Out; diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index ea223d172d..5f12d2ce23 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -105,7 +105,7 @@ namespace osu.Game.Skinning return SkinUtils.As(GetComboColour(Configuration, comboColour.ColourIndex, comboColour.Combo)); case SkinCustomColourLookup customColour: - return SkinUtils.As(getCustomColour(Configuration, customColour.Lookup.ToString())); + return SkinUtils.As(getCustomColour(Configuration, customColour.Lookup.ToString() ?? string.Empty)); case LegacyManiaSkinConfigurationLookup maniaLookup: if (!AllowManiaSkin) @@ -277,7 +277,7 @@ namespace osu.Game.Skinning => source.CustomColours.TryGetValue(lookup, out var col) ? new Bindable(col) : null; private IBindable? getManiaImage(LegacyManiaSkinConfiguration source, string lookup) - => source.ImageLookups.TryGetValue(lookup, out string image) ? new Bindable(image) : null; + => source.ImageLookups.TryGetValue(lookup, out string? image) ? new Bindable(image) : null; private IBindable? legacySettingLookup(SkinConfiguration.LegacySetting legacySetting) where TValue : notnull @@ -298,7 +298,7 @@ namespace osu.Game.Skinning { try { - if (Configuration.ConfigDictionary.TryGetValue(lookup.ToString(), out string val)) + if (Configuration.ConfigDictionary.TryGetValue(lookup.ToString() ?? string.Empty, out string? val)) { // special case for handling skins which use 1 or 0 to signify a boolean state. // ..or in some cases 2 (https://github.com/ppy/osu/issues/18579). diff --git a/osu.Game/Skinning/LegacySkinExtensions.cs b/osu.Game/Skinning/LegacySkinExtensions.cs index 8765882af2..0d2461567f 100644 --- a/osu.Game/Skinning/LegacySkinExtensions.cs +++ b/osu.Game/Skinning/LegacySkinExtensions.cs @@ -15,7 +15,7 @@ using static osu.Game.Skinning.SkinConfiguration; namespace osu.Game.Skinning { - public static class LegacySkinExtensions + public static partial class LegacySkinExtensions { public static Drawable? GetAnimation(this ISkin? source, string componentName, bool animatable, bool looping, bool applyConfigFrameRate = false, string animationSeparator = "-", bool startAtCurrentTime = true, double? frameLength = null) @@ -146,7 +146,7 @@ namespace osu.Game.Skinning } } - public class SkinnableTextureAnimation : TextureAnimation + public partial class SkinnableTextureAnimation : TextureAnimation { [Resolved(canBeNull: true)] private IAnimationTimeReference? timeReference { get; set; } diff --git a/osu.Game/Skinning/LegacySongProgress.cs b/osu.Game/Skinning/LegacySongProgress.cs index f828e301f2..10d1431ed4 100644 --- a/osu.Game/Skinning/LegacySongProgress.cs +++ b/osu.Game/Skinning/LegacySongProgress.cs @@ -11,7 +11,7 @@ using osuTK; namespace osu.Game.Skinning { - public class LegacySongProgress : SongProgress + public partial class LegacySongProgress : SongProgress { private CircularProgress circularProgress = null!; diff --git a/osu.Game/Skinning/LegacySpriteText.cs b/osu.Game/Skinning/LegacySpriteText.cs index c5d65cb0c7..b89f85778b 100644 --- a/osu.Game/Skinning/LegacySpriteText.cs +++ b/osu.Game/Skinning/LegacySpriteText.cs @@ -12,7 +12,7 @@ using osuTK; namespace osu.Game.Skinning { - public sealed class LegacySpriteText : OsuSpriteText + public sealed partial class LegacySpriteText : OsuSpriteText { private readonly LegacyFont font; diff --git a/osu.Game/Skinning/PausableSkinnableSound.cs b/osu.Game/Skinning/PausableSkinnableSound.cs index ebcaeaa3ff..e752160984 100644 --- a/osu.Game/Skinning/PausableSkinnableSound.cs +++ b/osu.Game/Skinning/PausableSkinnableSound.cs @@ -13,7 +13,7 @@ using osu.Game.Audio; namespace osu.Game.Skinning { - public class PausableSkinnableSound : SkinnableSound + public partial class PausableSkinnableSound : SkinnableSound { public double Length => !DrawableSamples.Any() ? 0 : DrawableSamples.Max(sample => sample.Length); diff --git a/osu.Game/Skinning/PoolableSkinnableSample.cs b/osu.Game/Skinning/PoolableSkinnableSample.cs index d0a22f9656..0158c47ea3 100644 --- a/osu.Game/Skinning/PoolableSkinnableSample.cs +++ b/osu.Game/Skinning/PoolableSkinnableSample.cs @@ -20,7 +20,7 @@ namespace osu.Game.Skinning /// /// A sample corresponding to an that supports being pooled and responding to skin changes. /// - public class PoolableSkinnableSample : SkinReloadableDrawable, IAdjustableAudioComponent + public partial class PoolableSkinnableSample : SkinReloadableDrawable, IAdjustableAudioComponent { /// /// The currently-loaded . diff --git a/osu.Game/Skinning/RealmBackedResourceStore.cs b/osu.Game/Skinning/RealmBackedResourceStore.cs index 0cc90f1dcb..cc887a7a61 100644 --- a/osu.Game/Skinning/RealmBackedResourceStore.cs +++ b/osu.Game/Skinning/RealmBackedResourceStore.cs @@ -52,7 +52,7 @@ namespace osu.Game.Skinning private string? getPathForFile(string filename) { - if (fileToStoragePathMapping.Value.TryGetValue(filename.ToLowerInvariant(), out string path)) + if (fileToStoragePathMapping.Value.TryGetValue(filename.ToLowerInvariant(), out string? path)) return path; return null; diff --git a/osu.Game/Skinning/RulesetSkinProvidingContainer.cs b/osu.Game/Skinning/RulesetSkinProvidingContainer.cs index 7267ebd92d..07e238243b 100644 --- a/osu.Game/Skinning/RulesetSkinProvidingContainer.cs +++ b/osu.Game/Skinning/RulesetSkinProvidingContainer.cs @@ -23,7 +23,7 @@ namespace osu.Game.Skinning /// A type of specialized for and other gameplay-related components. /// Providing access to parent skin sources and the beatmap skin each surrounded with the ruleset legacy skin transformer. /// - public class RulesetSkinProvidingContainer : SkinProvidingContainer + public partial class RulesetSkinProvidingContainer : SkinProvidingContainer { protected readonly Ruleset Ruleset; protected readonly IBeatmap Beatmap; diff --git a/osu.Game/Skinning/Skin.cs b/osu.Game/Skinning/Skin.cs index 25d1dc903c..19e8bc7092 100644 --- a/osu.Game/Skinning/Skin.cs +++ b/osu.Game/Skinning/Skin.cs @@ -97,7 +97,7 @@ namespace osu.Game.Skinning Configuration = new SkinConfiguration(); // skininfo files may be null for default skin. - foreach (GlobalSkinComponentLookup.LookupType skinnableTarget in Enum.GetValues(typeof(GlobalSkinComponentLookup.LookupType))) + foreach (GlobalSkinComponentLookup.LookupType skinnableTarget in Enum.GetValues()) { string filename = $"{skinnableTarget}.json"; diff --git a/osu.Game/Skinning/SkinImporter.cs b/osu.Game/Skinning/SkinImporter.cs index f594a7b2d2..1685562cc7 100644 --- a/osu.Game/Skinning/SkinImporter.cs +++ b/osu.Game/Skinning/SkinImporter.cs @@ -37,7 +37,7 @@ namespace osu.Game.Skinning protected override string[] HashableFileTypes => new[] { ".ini", ".json" }; - protected override bool ShouldDeleteArchive(string path) => Path.GetExtension(path)?.ToLowerInvariant() == @".osk"; + protected override bool ShouldDeleteArchive(string path) => Path.GetExtension(path).ToLowerInvariant() == @".osk"; protected override SkinInfo CreateModel(ArchiveReader archive) => new SkinInfo { Name = archive.Name ?? @"No name" }; diff --git a/osu.Game/Skinning/SkinInfo.cs b/osu.Game/Skinning/SkinInfo.cs index d051149155..9ad91f8725 100644 --- a/osu.Game/Skinning/SkinInfo.cs +++ b/osu.Game/Skinning/SkinInfo.cs @@ -20,6 +20,7 @@ namespace osu.Game.Skinning { internal static readonly Guid TRIANGLES_SKIN = new Guid("2991CFD8-2140-469A-BCB9-2EC23FBCE4AD"); internal static readonly Guid ARGON_SKIN = new Guid("CFFA69DE-B3E3-4DEE-8563-3C4F425C05D0"); + internal static readonly Guid ARGON_PRO_SKIN = new Guid("9FC9CF5D-0F16-4C71-8256-98868321AC43"); internal static readonly Guid CLASSIC_SKIN = new Guid("81F02CD3-EEC6-4865-AC23-FAE26A386187"); internal static readonly Guid RANDOM_SKIN = new Guid("D39DFEFB-477C-4372-B1EA-2BCEA5FB8908"); @@ -56,7 +57,7 @@ namespace osu.Game.Skinning return new TrianglesSkin(this, resources); } - return (Skin)Activator.CreateInstance(type, this, resources); + return (Skin)Activator.CreateInstance(type, this, resources)!; } public IList Files { get; } = null!; diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index 4a5277f3bf..a4cf83b32e 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -64,6 +64,16 @@ namespace osu.Game.Skinning private Skin trianglesSkin { get; } + public override bool PauseImports + { + get => base.PauseImports; + set + { + base.PauseImports = value; + skinImporter.PauseImports = value; + } + } + public SkinManager(Storage storage, RealmAccess realm, GameHost host, IResourceStore resources, AudioManager audio, Scheduler scheduler) : base(storage, realm) { @@ -84,6 +94,7 @@ namespace osu.Game.Skinning DefaultClassicSkin = new DefaultLegacySkin(this), trianglesSkin = new TrianglesSkin(this), argonSkin = new ArgonSkin(this), + new ArgonProSkin(this), }; // Ensure the default entries are present. @@ -270,15 +281,18 @@ namespace osu.Game.Skinning public Task Import(params string[] paths) => skinImporter.Import(paths); - public Task Import(params ImportTask[] tasks) => skinImporter.Import(tasks); + public Task Import(ImportTask[] imports, ImportParameters parameters = default) => skinImporter.Import(imports, parameters); public IEnumerable HandledExtensions => skinImporter.HandledExtensions; - public Task>> Import(ProgressNotification notification, params ImportTask[] tasks) => skinImporter.Import(notification, tasks); + public Task>> Import(ProgressNotification notification, ImportTask[] tasks, ImportParameters parameters = default) => + skinImporter.Import(notification, tasks, parameters); - public Task> ImportAsUpdate(ProgressNotification notification, ImportTask task, SkinInfo original) => skinImporter.ImportAsUpdate(notification, task, original); + public Task> ImportAsUpdate(ProgressNotification notification, ImportTask task, SkinInfo original) => + skinImporter.ImportAsUpdate(notification, task, original); - public Task> Import(ImportTask task, bool batchImport = false, CancellationToken cancellationToken = default) => skinImporter.Import(task, batchImport, cancellationToken); + public Task> Import(ImportTask task, ImportParameters parameters = default, CancellationToken cancellationToken = default) => + skinImporter.Import(task, parameters, cancellationToken); #endregion diff --git a/osu.Game/Skinning/SkinProvidingContainer.cs b/osu.Game/Skinning/SkinProvidingContainer.cs index e7d0683005..afead7b072 100644 --- a/osu.Game/Skinning/SkinProvidingContainer.cs +++ b/osu.Game/Skinning/SkinProvidingContainer.cs @@ -17,7 +17,7 @@ namespace osu.Game.Skinning /// /// A container which adds a local to the hierarchy. /// - public class SkinProvidingContainer : Container, ISkinSource + public partial class SkinProvidingContainer : Container, ISkinSource { public event Action? SourceChanged; diff --git a/osu.Game/Skinning/SkinReloadableDrawable.cs b/osu.Game/Skinning/SkinReloadableDrawable.cs index f1c8388f71..1c947a4a84 100644 --- a/osu.Game/Skinning/SkinReloadableDrawable.cs +++ b/osu.Game/Skinning/SkinReloadableDrawable.cs @@ -11,7 +11,7 @@ namespace osu.Game.Skinning /// /// A drawable which has a callback when the skin changes. /// - public abstract class SkinReloadableDrawable : PoolableDrawable + public abstract partial class SkinReloadableDrawable : PoolableDrawable { /// /// Invoked when has changed. diff --git a/osu.Game/Skinning/SkinnableDrawable.cs b/osu.Game/Skinning/SkinnableDrawable.cs index 15d371cdd5..255aba94ae 100644 --- a/osu.Game/Skinning/SkinnableDrawable.cs +++ b/osu.Game/Skinning/SkinnableDrawable.cs @@ -12,7 +12,7 @@ namespace osu.Game.Skinning /// /// A drawable which can be skinned via an . /// - public class SkinnableDrawable : SkinReloadableDrawable + public partial class SkinnableDrawable : SkinReloadableDrawable { /// /// The displayed component. diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index 8f71b40801..aeced9b517 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.cs @@ -21,7 +21,7 @@ namespace osu.Game.Skinning /// /// A sound consisting of one or more samples to be played. /// - public class SkinnableSound : SkinReloadableDrawable, IAdjustableAudioComponent + public partial class SkinnableSound : SkinReloadableDrawable, IAdjustableAudioComponent { public override bool RemoveWhenNotAlive => false; public override bool RemoveCompletedTransforms => false; diff --git a/osu.Game/Skinning/SkinnableSprite.cs b/osu.Game/Skinning/SkinnableSprite.cs index 7fd0e43562..a66f3e0549 100644 --- a/osu.Game/Skinning/SkinnableSprite.cs +++ b/osu.Game/Skinning/SkinnableSprite.cs @@ -20,7 +20,7 @@ namespace osu.Game.Skinning /// /// A skinnable element which uses a single texture backing. /// - public class SkinnableSprite : SkinnableDrawable, ISkinnableDrawable + public partial class SkinnableSprite : SkinnableDrawable, ISkinnableDrawable { protected override bool ApplySizeRestrictionsToDefault => true; @@ -75,7 +75,7 @@ namespace osu.Game.Skinning } } - public class SpriteSelectorControl : SettingsDropdown + public partial class SpriteSelectorControl : SettingsDropdown { protected override void LoadComplete() { @@ -111,13 +111,14 @@ namespace osu.Game.Skinning // Temporarily used to exclude undesirable ISkin implementations static bool isUserSkin(ISkin skin) => skin.GetType() == typeof(TrianglesSkin) + || skin.GetType() == typeof(ArgonProSkin) || skin.GetType() == typeof(ArgonSkin) || skin.GetType() == typeof(DefaultLegacySkin) || skin.GetType() == typeof(LegacySkin); } } - public class SpriteNotFound : CompositeDrawable + public partial class SpriteNotFound : CompositeDrawable { public SpriteNotFound(string lookup) { diff --git a/osu.Game/Skinning/SkinnableSpriteText.cs b/osu.Game/Skinning/SkinnableSpriteText.cs index c01cec2f0c..7c42449ae7 100644 --- a/osu.Game/Skinning/SkinnableSpriteText.cs +++ b/osu.Game/Skinning/SkinnableSpriteText.cs @@ -7,7 +7,7 @@ using osu.Framework.Localisation; namespace osu.Game.Skinning { - public class SkinnableSpriteText : SkinnableDrawable, IHasText + public partial class SkinnableSpriteText : SkinnableDrawable, IHasText { public SkinnableSpriteText(ISkinComponentLookup lookup, Func defaultImplementation, ConfineMode confineMode = ConfineMode.NoScaling) : base(lookup, defaultImplementation, confineMode) diff --git a/osu.Game/Skinning/SkinnableTargetComponentsContainer.cs b/osu.Game/Skinning/SkinnableTargetComponentsContainer.cs index e38afedeb9..8c6726c3f4 100644 --- a/osu.Game/Skinning/SkinnableTargetComponentsContainer.cs +++ b/osu.Game/Skinning/SkinnableTargetComponentsContainer.cs @@ -13,7 +13,7 @@ namespace osu.Game.Skinning /// Optionally also applies a default layout to the components. /// [Serializable] - public class SkinnableTargetComponentsContainer : Container, ISkinnableDrawable + public partial class SkinnableTargetComponentsContainer : Container, ISkinnableDrawable { public bool IsEditable => false; diff --git a/osu.Game/Skinning/SkinnableTargetContainer.cs b/osu.Game/Skinning/SkinnableTargetContainer.cs index a8038f5f5c..794a12da82 100644 --- a/osu.Game/Skinning/SkinnableTargetContainer.cs +++ b/osu.Game/Skinning/SkinnableTargetContainer.cs @@ -9,7 +9,7 @@ using osu.Framework.Graphics; namespace osu.Game.Skinning { - public class SkinnableTargetContainer : SkinReloadableDrawable, ISkinnableTarget + public partial class SkinnableTargetContainer : SkinReloadableDrawable, ISkinnableTarget { private SkinnableTargetComponentsContainer? content; diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs index 6295604438..aa264fa719 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs @@ -20,7 +20,7 @@ using osu.Game.Screens.Play; namespace osu.Game.Storyboards.Drawables { - public class DrawableStoryboard : Container + public partial class DrawableStoryboard : Container { [Cached] public Storyboard Storyboard { get; } diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs index 07e1e86617..e598c79b08 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs @@ -16,7 +16,7 @@ using osuTK; namespace osu.Game.Storyboards.Drawables { - public class DrawableStoryboardAnimation : TextureAnimation, IFlippable, IVectorScalable + public partial class DrawableStoryboardAnimation : TextureAnimation, IFlippable, IVectorScalable { public StoryboardAnimation Animation { get; } @@ -137,7 +137,7 @@ namespace osu.Game.Storyboards.Drawables // When reading from a skin, we match stables weird behaviour where `FrameCount` is ignored // and resources are retrieved until the end of the animation. - foreach (var texture in skin.GetTextures(Path.GetFileNameWithoutExtension(Animation.Path), default, default, true, string.Empty, out _)) + foreach (var texture in skin.GetTextures(Path.GetFileNameWithoutExtension(Animation.Path)!, default, default, true, string.Empty, out _)) AddFrame(texture, Animation.FrameDelay); } diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardLayer.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardLayer.cs index 13f116af24..6fc8d124c7 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardLayer.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardLayer.cs @@ -11,7 +11,7 @@ using osuTK; namespace osu.Game.Storyboards.Drawables { - public class DrawableStoryboardLayer : CompositeDrawable + public partial class DrawableStoryboardLayer : CompositeDrawable { public StoryboardLayer Layer { get; } public bool Enabled; @@ -32,7 +32,7 @@ namespace osu.Game.Storyboards.Drawables InternalChild = ElementContainer = new LayerElementContainer(layer); } - protected class LayerElementContainer : LifetimeManagementContainer + protected partial class LayerElementContainer : LifetimeManagementContainer { private readonly StoryboardLayer storyboardLayer; diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs index 2e7ca31fe9..c281d23804 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs @@ -12,7 +12,7 @@ using osu.Game.Skinning; namespace osu.Game.Storyboards.Drawables { - public class DrawableStoryboardSample : PausableSkinnableSound + public partial class DrawableStoryboardSample : PausableSkinnableSound { /// /// The amount of time allowable beyond the start time of the sample, for the sample to start. diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs index b86b021d51..f9b09ed57c 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs @@ -14,7 +14,7 @@ using osuTK; namespace osu.Game.Storyboards.Drawables { - public class DrawableStoryboardSprite : Sprite, IFlippable, IVectorScalable + public partial class DrawableStoryboardSprite : Sprite, IFlippable, IVectorScalable { public StoryboardSprite Sprite { get; } diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardVideo.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardVideo.cs index ebd056ba50..f4b0692619 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardVideo.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardVideo.cs @@ -11,7 +11,7 @@ using osu.Game.Beatmaps; namespace osu.Game.Storyboards.Drawables { - public class DrawableStoryboardVideo : CompositeDrawable + public partial class DrawableStoryboardVideo : CompositeDrawable { public readonly StoryboardVideo Video; diff --git a/osu.Game/Storyboards/Storyboard.cs b/osu.Game/Storyboards/Storyboard.cs index 8133244e89..566e064aad 100644 --- a/osu.Game/Storyboards/Storyboard.cs +++ b/osu.Game/Storyboards/Storyboard.cs @@ -32,7 +32,7 @@ namespace osu.Game.Storyboards /// /// This iterates all elements and as such should be used sparingly or stored locally. /// - public double? EarliestEventTime => Layers.SelectMany(l => l.Elements).OrderBy(e => e.StartTime).FirstOrDefault()?.StartTime; + public double? EarliestEventTime => Layers.SelectMany(l => l.Elements).MinBy(e => e.StartTime)?.StartTime; /// /// Across all layers, find the latest point in time that a storyboard element ends at. @@ -42,7 +42,7 @@ namespace osu.Game.Storyboards /// This iterates all elements and as such should be used sparingly or stored locally. /// Videos and samples return StartTime as their EndTIme. /// - public double? LatestEventTime => Layers.SelectMany(l => l.Elements).OrderBy(e => e.GetEndTime()).LastOrDefault()?.GetEndTime(); + public double? LatestEventTime => Layers.SelectMany(l => l.Elements).MaxBy(e => e.GetEndTime())?.GetEndTime(); /// /// Depth of the currently front-most storyboard layer, excluding the overlay layer. diff --git a/osu.Game/Storyboards/StoryboardSprite.cs b/osu.Game/Storyboards/StoryboardSprite.cs index cd7788bb08..5b7b194be7 100644 --- a/osu.Game/Storyboards/StoryboardSprite.cs +++ b/osu.Game/Storyboards/StoryboardSprite.cs @@ -48,7 +48,7 @@ namespace osu.Game.Storyboards if (alphaCommands.Count > 0) { - var firstAlpha = alphaCommands.OrderBy(t => t.startTime).First(); + var firstAlpha = alphaCommands.MinBy(t => t.startTime); if (firstAlpha.isZeroStartValue) return firstAlpha.startTime; diff --git a/osu.Game/Storyboards/StoryboardVideoLayer.cs b/osu.Game/Storyboards/StoryboardVideoLayer.cs index 339e70d677..f08c02cfd2 100644 --- a/osu.Game/Storyboards/StoryboardVideoLayer.cs +++ b/osu.Game/Storyboards/StoryboardVideoLayer.cs @@ -9,7 +9,7 @@ using osuTK; namespace osu.Game.Storyboards { - public class StoryboardVideoLayer : StoryboardLayer + public partial class StoryboardVideoLayer : StoryboardLayer { public StoryboardVideoLayer(string name, int depth, bool masking) : base(name, depth, masking) @@ -19,7 +19,7 @@ namespace osu.Game.Storyboards public override DrawableStoryboardLayer CreateDrawable() => new DrawableStoryboardVideoLayer(this) { Depth = Depth, Name = Name }; - public class DrawableStoryboardVideoLayer : DrawableStoryboardLayer + public partial class DrawableStoryboardVideoLayer : DrawableStoryboardLayer { public DrawableStoryboardVideoLayer(StoryboardVideoLayer layer) : base(layer) diff --git a/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs b/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs index c5f6f58b86..79f629ce49 100644 --- a/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs +++ b/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs @@ -185,7 +185,7 @@ namespace osu.Game.Tests.Beatmaps private Stream openResource(string name) { - string localPath = Path.GetDirectoryName(Uri.UnescapeDataString(new UriBuilder(Assembly.GetExecutingAssembly().CodeBase).Path)).AsNonNull(); + string localPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location).AsNonNull(); return Assembly.LoadFrom(Path.Combine(localPath, $"{ResourceAssembly}.dll")).GetManifestResourceStream($@"{ResourceAssembly}.Resources.{name}"); } diff --git a/osu.Game/Tests/Beatmaps/DifficultyCalculatorTest.cs b/osu.Game/Tests/Beatmaps/DifficultyCalculatorTest.cs index c7441f68bd..16434406b5 100644 --- a/osu.Game/Tests/Beatmaps/DifficultyCalculatorTest.cs +++ b/osu.Game/Tests/Beatmaps/DifficultyCalculatorTest.cs @@ -3,7 +3,6 @@ #nullable disable -using System; using System.IO; using System.Reflection; using NUnit.Framework; @@ -54,7 +53,7 @@ namespace osu.Game.Tests.Beatmaps private Stream openResource(string name) { - string localPath = Path.GetDirectoryName(Uri.UnescapeDataString(new UriBuilder(Assembly.GetExecutingAssembly().CodeBase).Path)).AsNonNull(); + string localPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location).AsNonNull(); return Assembly.LoadFrom(Path.Combine(localPath, $"{ResourceAssembly}.dll")).GetManifestResourceStream($@"{ResourceAssembly}.Resources.{name}"); } diff --git a/osu.Game/Tests/Beatmaps/HitObjectSampleTest.cs b/osu.Game/Tests/Beatmaps/HitObjectSampleTest.cs index c97eec116c..bb4e06654a 100644 --- a/osu.Game/Tests/Beatmaps/HitObjectSampleTest.cs +++ b/osu.Game/Tests/Beatmaps/HitObjectSampleTest.cs @@ -33,7 +33,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Tests.Beatmaps { [HeadlessTest] - public abstract class HitObjectSampleTest : PlayerTestScene, IStorageResourceProvider + public abstract partial class HitObjectSampleTest : PlayerTestScene, IStorageResourceProvider { protected abstract IResourceStore RulesetResources { get; } protected LegacySkin Skin { get; private set; } @@ -164,7 +164,7 @@ namespace osu.Game.Tests.Beatmaps return fallback.Get(type, info); } - public void Inject(T instance) where T : class + public void Inject(T instance) where T : class, IDependencyInjectionCandidate { // Never used directly } diff --git a/osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs b/osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs index 06600c4681..2488aecced 100644 --- a/osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs +++ b/osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs @@ -17,7 +17,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Beatmaps { - public abstract class LegacyBeatmapSkinColourTest : ScreenTestScene + public abstract partial class LegacyBeatmapSkinColourTest : ScreenTestScene { protected readonly Bindable BeatmapSkins = new Bindable(); protected readonly Bindable BeatmapColours = new Bindable(); @@ -60,7 +60,7 @@ namespace osu.Game.Tests.Beatmaps protected virtual ExposedPlayer CreateTestPlayer(bool userHasCustomColours) => new ExposedPlayer(userHasCustomColours); - protected class ExposedPlayer : TestPlayer + protected partial class ExposedPlayer : TestPlayer { protected readonly bool UserHasCustomColours; diff --git a/osu.Game/Tests/OsuTestBrowser.cs b/osu.Game/Tests/OsuTestBrowser.cs index 064fdeee94..7431679ab9 100644 --- a/osu.Game/Tests/OsuTestBrowser.cs +++ b/osu.Game/Tests/OsuTestBrowser.cs @@ -12,7 +12,7 @@ using osu.Game.Screens.Backgrounds; namespace osu.Game.Tests { - public class OsuTestBrowser : OsuGameBase + public partial class OsuTestBrowser : OsuGameBase { protected override void LoadComplete() { diff --git a/osu.Game/Tests/PollingNotificationsClient.cs b/osu.Game/Tests/PollingNotificationsClient.cs index c1f032a647..450c763170 100644 --- a/osu.Game/Tests/PollingNotificationsClient.cs +++ b/osu.Game/Tests/PollingNotificationsClient.cs @@ -24,8 +24,8 @@ namespace osu.Game.Tests { while (!cancellationToken.IsCancellationRequested) { - await API.PerformAsync(CreateFetchMessagesRequest()); - await Task.Delay(1000, cancellationToken); + await API.PerformAsync(CreateInitialFetchRequest()).ConfigureAwait(true); + await Task.Delay(1000, cancellationToken).ConfigureAwait(true); } }, cancellationToken); diff --git a/osu.Game/Tests/Visual/DependencyProvidingContainer.cs b/osu.Game/Tests/Visual/DependencyProvidingContainer.cs index 8d9108f376..ae0225d8df 100644 --- a/osu.Game/Tests/Visual/DependencyProvidingContainer.cs +++ b/osu.Game/Tests/Visual/DependencyProvidingContainer.cs @@ -15,7 +15,7 @@ namespace osu.Game.Tests.Visual /// /// The must be set while this is not loaded. /// - public class DependencyProvidingContainer : Container + public partial class DependencyProvidingContainer : Container { /// /// The dependencies provided to the children. diff --git a/osu.Game/Tests/Visual/EditorClockTestScene.cs b/osu.Game/Tests/Visual/EditorClockTestScene.cs index 8f1e7abd9e..204a817b3a 100644 --- a/osu.Game/Tests/Visual/EditorClockTestScene.cs +++ b/osu.Game/Tests/Visual/EditorClockTestScene.cs @@ -19,7 +19,7 @@ namespace osu.Game.Tests.Visual /// Provides a clock, beat-divisor, and scrolling capability for test cases of editor components that /// are preferrably tested within the presence of a clock and seek controls. /// - public abstract class EditorClockTestScene : OsuManualInputManagerTestScene + public abstract partial class EditorClockTestScene : OsuManualInputManagerTestScene { [Cached] private readonly OverlayColourProvider overlayColour = new OverlayColourProvider(OverlayColourScheme.Aquamarine); diff --git a/osu.Game/Tests/Visual/EditorSavingTestScene.cs b/osu.Game/Tests/Visual/EditorSavingTestScene.cs index 3b7b6780b1..cd9e9e1d52 100644 --- a/osu.Game/Tests/Visual/EditorSavingTestScene.cs +++ b/osu.Game/Tests/Visual/EditorSavingTestScene.cs @@ -18,7 +18,7 @@ namespace osu.Game.Tests.Visual /// /// Tests the general expected flow of creating a new beatmap, saving it, then loading it back from song select. /// - public abstract class EditorSavingTestScene : OsuGameTestScene + public abstract partial class EditorSavingTestScene : OsuGameTestScene { protected Editor Editor => Game.ChildrenOfType().FirstOrDefault(); diff --git a/osu.Game/Tests/Visual/EditorTestScene.cs b/osu.Game/Tests/Visual/EditorTestScene.cs index 0e7bb72162..6e2f1e99cd 100644 --- a/osu.Game/Tests/Visual/EditorTestScene.cs +++ b/osu.Game/Tests/Visual/EditorTestScene.cs @@ -23,7 +23,7 @@ using osu.Game.Skinning; namespace osu.Game.Tests.Visual { - public abstract class EditorTestScene : ScreenTestScene + public abstract partial class EditorTestScene : ScreenTestScene { private TestEditorLoader editorLoader; @@ -83,7 +83,7 @@ namespace osu.Game.Tests.Visual protected sealed override Ruleset CreateRuleset() => CreateEditorRuleset(); - protected class TestEditorLoader : EditorLoader + protected partial class TestEditorLoader : EditorLoader { public TestEditor Editor { get; private set; } @@ -92,7 +92,7 @@ namespace osu.Game.Tests.Visual protected virtual TestEditor CreateTestEditor(EditorLoader loader) => new TestEditor(loader); } - protected class TestEditor : Editor + protected partial class TestEditor : Editor { [Resolved(canBeNull: true)] [CanBeNull] @@ -102,6 +102,8 @@ namespace osu.Game.Tests.Visual public new void Redo() => base.Redo(); + public new void SetPreviewPointToCurrentTime() => base.SetPreviewPointToCurrentTime(); + public new bool Save() => base.Save(); public new void Cut() => base.Cut(); diff --git a/osu.Game/Tests/Visual/LegacySkinPlayerTestScene.cs b/osu.Game/Tests/Visual/LegacySkinPlayerTestScene.cs index f6b5d861be..c5efdf36b4 100644 --- a/osu.Game/Tests/Visual/LegacySkinPlayerTestScene.cs +++ b/osu.Game/Tests/Visual/LegacySkinPlayerTestScene.cs @@ -14,7 +14,7 @@ using osu.Game.Skinning; namespace osu.Game.Tests.Visual { [TestFixture] - public abstract class LegacySkinPlayerTestScene : PlayerTestScene + public abstract partial class LegacySkinPlayerTestScene : PlayerTestScene { protected LegacySkin LegacySkin { get; private set; } @@ -54,7 +54,7 @@ namespace osu.Game.Tests.Visual AddUntilStep("wait for components to load", () => this.ChildrenOfType().All(t => t.ComponentsLoaded)); } - public class SkinProvidingPlayer : TestPlayer + public partial class SkinProvidingPlayer : TestPlayer { [Cached(typeof(ISkinSource))] private readonly ISkinSource skinSource; diff --git a/osu.Game/Tests/Visual/ModPerfectTestScene.cs b/osu.Game/Tests/Visual/ModPerfectTestScene.cs index f1ad2656cd..167d5450e9 100644 --- a/osu.Game/Tests/Visual/ModPerfectTestScene.cs +++ b/osu.Game/Tests/Visual/ModPerfectTestScene.cs @@ -10,7 +10,7 @@ using osu.Game.Rulesets.Objects; namespace osu.Game.Tests.Visual { - public abstract class ModPerfectTestScene : ModTestScene + public abstract partial class ModPerfectTestScene : ModTestScene { private readonly ModPerfect mod; @@ -33,7 +33,7 @@ namespace osu.Game.Tests.Visual protected override TestPlayer CreateModPlayer(Ruleset ruleset) => new PerfectModTestPlayer(); - private class PerfectModTestPlayer : TestPlayer + private partial class PerfectModTestPlayer : TestPlayer { public PerfectModTestPlayer() : base(showResults: false) diff --git a/osu.Game/Tests/Visual/ModTestScene.cs b/osu.Game/Tests/Visual/ModTestScene.cs index 28778f1ac3..0559d80384 100644 --- a/osu.Game/Tests/Visual/ModTestScene.cs +++ b/osu.Game/Tests/Visual/ModTestScene.cs @@ -16,7 +16,7 @@ using osu.Game.Scoring; namespace osu.Game.Tests.Visual { - public abstract class ModTestScene : PlayerTestScene + public abstract partial class ModTestScene : PlayerTestScene { protected sealed override bool HasCustomSteps => true; @@ -58,7 +58,7 @@ namespace osu.Game.Tests.Visual protected virtual TestPlayer CreateModPlayer(Ruleset ruleset) => new ModTestPlayer(currentTestData, AllowFail); - protected class ModTestPlayer : TestPlayer + protected partial class ModTestPlayer : TestPlayer { private readonly bool allowFail; private readonly ModTestData currentTestData; diff --git a/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs index 101a347749..93c6e72aa2 100644 --- a/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs +++ b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs @@ -13,7 +13,7 @@ namespace osu.Game.Tests.Visual.Multiplayer /// /// The base test scene for all multiplayer components and screens. /// - public abstract class MultiplayerTestScene : OnlinePlayTestScene, IMultiplayerTestSceneDependencies + public abstract partial class MultiplayerTestScene : OnlinePlayTestScene, IMultiplayerTestSceneDependencies { public const int PLAYER_1_ID = 55; public const int PLAYER_2_ID = 56; diff --git a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs index 84737bce3f..ad5e3f6c4d 100644 --- a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs +++ b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs @@ -23,7 +23,7 @@ namespace osu.Game.Tests.Visual.Multiplayer /// /// A for use in multiplayer test scenes. Should generally not be used by itself outside of a . /// - public class TestMultiplayerClient : MultiplayerClient + public partial class TestMultiplayerClient : MultiplayerClient { public override IBindable IsConnected => isConnected; private readonly Bindable isConnected = new Bindable(true); @@ -108,9 +108,7 @@ namespace osu.Game.Tests.Visual.Multiplayer // simulate the server's automatic assignment of users to teams on join. // the "best" team is the one with the least users on it. int bestTeam = teamVersus.Teams - .Select(team => (teamID: team.ID, userCount: ServerRoom.Users.Count(u => (u.MatchState as TeamVersusUserState)?.TeamID == team.ID))) - .OrderBy(pair => pair.userCount) - .First().teamID; + .Select(team => (teamID: team.ID, userCount: ServerRoom.Users.Count(u => (u.MatchState as TeamVersusUserState)?.TeamID == team.ID))).MinBy(pair => pair.userCount).teamID; user.MatchState = new TeamVersusUserState { TeamID = bestTeam }; ((IMultiplayerClient)this).MatchUserStateChanged(clone(user.UserID), clone(user.MatchState)).WaitSafely(); diff --git a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerRoomManager.cs b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerRoomManager.cs index b2283af9e7..8d04c808fd 100644 --- a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerRoomManager.cs +++ b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerRoomManager.cs @@ -17,7 +17,7 @@ namespace osu.Game.Tests.Visual.Multiplayer /// A for use in multiplayer test scenes. /// Should generally not be used by itself outside of a . /// - public class TestMultiplayerRoomManager : MultiplayerRoomManager + public partial class TestMultiplayerRoomManager : MultiplayerRoomManager { private readonly TestRoomRequestsHandler requestsHandler; diff --git a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs index b9c293c3aa..87488710a7 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs @@ -20,7 +20,7 @@ namespace osu.Game.Tests.Visual.OnlinePlay /// /// A base test scene for all online play components and screens. /// - public abstract class OnlinePlayTestScene : ScreenTestScene, IOnlinePlayTestSceneDependencies + public abstract partial class OnlinePlayTestScene : ScreenTestScene, IOnlinePlayTestSceneDependencies { public Bindable SelectedRoom => OnlinePlayDependencies?.SelectedRoom; public IRoomManager RoomManager => OnlinePlayDependencies?.RoomManager; @@ -128,7 +128,7 @@ namespace osu.Game.Tests.Visual.OnlinePlay => OnlinePlayDependencies?.Get(type, info) ?? parent.Get(type, info); public void Inject(T instance) - where T : class + where T : class, IDependencyInjectionCandidate => injectableDependencies.Inject(instance); } } diff --git a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs index 35bdba0038..a9acbdcd7e 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs @@ -65,7 +65,7 @@ namespace osu.Game.Tests.Visual.OnlinePlay => dependencies.Get(type, info); public void Inject(T instance) - where T : class + where T : class, IDependencyInjectionCandidate => dependencies.Inject(instance); protected void Cache(object instance) diff --git a/osu.Game/Tests/Visual/OnlinePlay/TestRoomManager.cs b/osu.Game/Tests/Visual/OnlinePlay/TestRoomManager.cs index f905eb26d3..e9980e822c 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/TestRoomManager.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/TestRoomManager.cs @@ -15,7 +15,7 @@ namespace osu.Game.Tests.Visual.OnlinePlay /// /// A very simple for use in online play test scenes. /// - public class TestRoomManager : RoomManager + public partial class TestRoomManager : RoomManager { public Action JoinRoomRequested; diff --git a/osu.Game/Tests/Visual/OsuGameTestScene.cs b/osu.Game/Tests/Visual/OsuGameTestScene.cs index 3ca83a4781..94be4a375d 100644 --- a/osu.Game/Tests/Visual/OsuGameTestScene.cs +++ b/osu.Game/Tests/Visual/OsuGameTestScene.cs @@ -20,6 +20,7 @@ using osu.Game.Database; using osu.Game.Graphics.Cursor; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; +using osu.Game.Online.Spectator; using osu.Game.Overlays; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; @@ -35,7 +36,7 @@ namespace osu.Game.Tests.Visual /// /// A scene which tests full game flow. /// - public abstract class OsuGameTestScene : OsuManualInputManagerTestScene + public abstract partial class OsuGameTestScene : OsuManualInputManagerTestScene { protected TestOsuGame Game; @@ -114,7 +115,7 @@ namespace osu.Game.Tests.Visual /// protected void DismissAnyNotifications() => Game.Notifications.State.Value = Visibility.Hidden; - public class TestOsuGame : OsuGame + public partial class TestOsuGame : OsuGame { public new const float SIDE_OVERLAY_OFFSET_RATIO = OsuGame.SIDE_OVERLAY_OFFSET_RATIO; @@ -148,6 +149,8 @@ namespace osu.Game.Tests.Visual public new Bindable> SelectedMods => base.SelectedMods; + public new SpectatorClient SpectatorClient => base.SpectatorClient; + // if we don't apply these changes, when running under nUnit the version that gets populated is that of nUnit. public override Version AssemblyVersion => new Version(0, 0); public override string Version => "test game"; @@ -189,11 +192,11 @@ namespace osu.Game.Tests.Visual } } - public class TestLoader : Loader + public partial class TestLoader : Loader { protected override ShaderPrecompiler CreateShaderPrecompiler() => new TestShaderPrecompiler(); - private class TestShaderPrecompiler : ShaderPrecompiler + private partial class TestShaderPrecompiler : ShaderPrecompiler { protected override bool AllLoaded => true; } diff --git a/osu.Game/Tests/Visual/OsuGridTestScene.cs b/osu.Game/Tests/Visual/OsuGridTestScene.cs index f9a609f663..9ef3b2a59d 100644 --- a/osu.Game/Tests/Visual/OsuGridTestScene.cs +++ b/osu.Game/Tests/Visual/OsuGridTestScene.cs @@ -13,7 +13,7 @@ namespace osu.Game.Tests.Visual /// An abstract test case which exposes small cells arranged in a grid. /// Useful for displaying multiple configurations of a tested component at a glance. /// - public abstract class OsuGridTestScene : OsuTestScene + public abstract partial class OsuGridTestScene : OsuTestScene { private readonly Drawable[,] cells; diff --git a/osu.Game/Tests/Visual/OsuManualInputManagerTestScene.cs b/osu.Game/Tests/Visual/OsuManualInputManagerTestScene.cs index e56c546bac..b0043b902c 100644 --- a/osu.Game/Tests/Visual/OsuManualInputManagerTestScene.cs +++ b/osu.Game/Tests/Visual/OsuManualInputManagerTestScene.cs @@ -12,7 +12,7 @@ using osu.Framework.Testing; using osu.Framework.Testing.Input; using osu.Game.Graphics.Cursor; using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; +using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Input.Bindings; using osuTK; using osuTK.Graphics; @@ -20,15 +20,15 @@ using osuTK.Input; namespace osu.Game.Tests.Visual { - public abstract class OsuManualInputManagerTestScene : OsuTestScene + public abstract partial class OsuManualInputManagerTestScene : OsuTestScene { protected override Container Content => content; private readonly Container content; protected readonly ManualInputManager InputManager; - private readonly TriangleButton buttonTest; - private readonly TriangleButton buttonLocal; + private readonly RoundedButton buttonTest; + private readonly RoundedButton buttonLocal; /// /// Whether to create a nested container to handle s that result from local (manual) test input. @@ -110,13 +110,13 @@ namespace osu.Game.Tests.Visual Children = new Drawable[] { - buttonLocal = new TriangleButton + buttonLocal = new RoundedButton { Text = "local", Size = new Vector2(50, 30), Action = returnUserInput }, - buttonTest = new TriangleButton + buttonTest = new RoundedButton { Text = "test", Size = new Vector2(50, 30), diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index 5055153691..46c7c3a57c 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -37,7 +37,7 @@ using osu.Game.Tests.Rulesets; namespace osu.Game.Tests.Visual { [ExcludeFromDynamicCompile] - public abstract class OsuTestScene : TestScene + public abstract partial class OsuTestScene : TestScene { [Cached] protected Bindable Beatmap { get; } = new Bindable(); @@ -503,7 +503,7 @@ namespace osu.Game.Tests.Visual } } - public class OsuTestSceneTestRunner : OsuGameBase, ITestSceneTestRunner + public partial class OsuTestSceneTestRunner : OsuGameBase, ITestSceneTestRunner { private TestSceneTestRunner.TestRunner runner; diff --git a/osu.Game/Tests/Visual/PlacementBlueprintTestScene.cs b/osu.Game/Tests/Visual/PlacementBlueprintTestScene.cs index 7e5681ee81..0027e03492 100644 --- a/osu.Game/Tests/Visual/PlacementBlueprintTestScene.cs +++ b/osu.Game/Tests/Visual/PlacementBlueprintTestScene.cs @@ -16,7 +16,7 @@ using osu.Game.Screens.Edit.Compose; namespace osu.Game.Tests.Visual { - public abstract class PlacementBlueprintTestScene : OsuManualInputManagerTestScene, IPlacementHandler + public abstract partial class PlacementBlueprintTestScene : OsuManualInputManagerTestScene, IPlacementHandler { protected readonly Container HitObjectContainer; protected PlacementBlueprint CurrentBlueprint { get; private set; } diff --git a/osu.Game/Tests/Visual/PlayerTestScene.cs b/osu.Game/Tests/Visual/PlayerTestScene.cs index 9bad867206..3ecc5a3280 100644 --- a/osu.Game/Tests/Visual/PlayerTestScene.cs +++ b/osu.Game/Tests/Visual/PlayerTestScene.cs @@ -14,7 +14,7 @@ using osu.Game.Rulesets.Mods; namespace osu.Game.Tests.Visual { - public abstract class PlayerTestScene : RateAdjustedBeatmapTestScene + public abstract partial class PlayerTestScene : RateAdjustedBeatmapTestScene { /// /// Whether custom test steps are provided. Custom tests should invoke to create the test steps. diff --git a/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs b/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs index a4f768800c..0f3f9f2199 100644 --- a/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs +++ b/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs @@ -8,7 +8,7 @@ namespace osu.Game.Tests.Visual /// /// Test case which adjusts the beatmap's rate to match any speed adjustments in visual tests. /// - public abstract class RateAdjustedBeatmapTestScene : ScreenTestScene + public abstract partial class RateAdjustedBeatmapTestScene : ScreenTestScene { protected override void Update() { diff --git a/osu.Game/Tests/Visual/ScreenTestScene.cs b/osu.Game/Tests/Visual/ScreenTestScene.cs index 803db07fa0..7d382ca1bc 100644 --- a/osu.Game/Tests/Visual/ScreenTestScene.cs +++ b/osu.Game/Tests/Visual/ScreenTestScene.cs @@ -20,7 +20,7 @@ namespace osu.Game.Tests.Visual /// /// A test case which can be used to test a screen (that relies on OnEntering being called to execute startup instructions). /// - public abstract class ScreenTestScene : OsuManualInputManagerTestScene, IOverlayManager + public abstract partial class ScreenTestScene : OsuManualInputManagerTestScene, IOverlayManager { protected readonly OsuScreenStack Stack; diff --git a/osu.Game/Tests/Visual/ScrollingTestContainer.cs b/osu.Game/Tests/Visual/ScrollingTestContainer.cs index 1817a704b9..b8b39e16b5 100644 --- a/osu.Game/Tests/Visual/ScrollingTestContainer.cs +++ b/osu.Game/Tests/Visual/ScrollingTestContainer.cs @@ -18,7 +18,7 @@ namespace osu.Game.Tests.Visual /// A container which provides a to children. /// This should only be used when testing /// - public class ScrollingTestContainer : Container + public partial class ScrollingTestContainer : Container { public SortedList ControlPoints => scrollingInfo.Algorithm.ControlPoints; diff --git a/osu.Game/Tests/Visual/SelectionBlueprintTestScene.cs b/osu.Game/Tests/Visual/SelectionBlueprintTestScene.cs index ac0d1cd366..350410e7c6 100644 --- a/osu.Game/Tests/Visual/SelectionBlueprintTestScene.cs +++ b/osu.Game/Tests/Visual/SelectionBlueprintTestScene.cs @@ -11,7 +11,7 @@ using osu.Game.Screens.Edit; namespace osu.Game.Tests.Visual { - public abstract class SelectionBlueprintTestScene : OsuManualInputManagerTestScene + public abstract partial class SelectionBlueprintTestScene : OsuManualInputManagerTestScene { [Cached] private readonly EditorClock editorClock = new EditorClock(); diff --git a/osu.Game/Tests/Visual/SkinnableTestScene.cs b/osu.Game/Tests/Visual/SkinnableTestScene.cs index f8f15e2729..e8f51f9afa 100644 --- a/osu.Game/Tests/Visual/SkinnableTestScene.cs +++ b/osu.Game/Tests/Visual/SkinnableTestScene.cs @@ -27,7 +27,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual { - public abstract class SkinnableTestScene : OsuGridTestScene, IStorageResourceProvider + public abstract partial class SkinnableTestScene : OsuGridTestScene, IStorageResourceProvider { private TrianglesSkin trianglesSkin; private Skin metricsSkin; @@ -171,7 +171,7 @@ namespace osu.Game.Tests.Visual #endregion - private class OutlineBox : CompositeDrawable + private partial class OutlineBox : CompositeDrawable { public OutlineBox() { diff --git a/osu.Game/Tests/Visual/Spectator/TestSpectatorClient.cs b/osu.Game/Tests/Visual/Spectator/TestSpectatorClient.cs index e6d8e473bb..1db35b3aaa 100644 --- a/osu.Game/Tests/Visual/Spectator/TestSpectatorClient.cs +++ b/osu.Game/Tests/Visual/Spectator/TestSpectatorClient.cs @@ -17,7 +17,7 @@ using osu.Game.Scoring; namespace osu.Game.Tests.Visual.Spectator { - public class TestSpectatorClient : SpectatorClient + public partial class TestSpectatorClient : SpectatorClient { /// /// Maximum number of frames sent per bundle via . @@ -126,7 +126,7 @@ namespace osu.Game.Tests.Visual.Spectator } } - protected override Task BeginPlayingInternal(SpectatorState state) + protected override Task BeginPlayingInternal(long? scoreToken, SpectatorState state) { // Track the local user's playing beatmap ID. Debug.Assert(state.BeatmapID != null); diff --git a/osu.Game/Tests/Visual/TestPlayer.cs b/osu.Game/Tests/Visual/TestPlayer.cs index 93a155e083..d9cae6b03b 100644 --- a/osu.Game/Tests/Visual/TestPlayer.cs +++ b/osu.Game/Tests/Visual/TestPlayer.cs @@ -8,6 +8,7 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Screens; using osu.Game.Online.API; using osu.Game.Online.Rooms; using osu.Game.Online.Spectator; @@ -23,7 +24,7 @@ namespace osu.Game.Tests.Visual /// /// A player that exposes many components that would otherwise not be available, for testing purposes. /// - public class TestPlayer : SoloPlayer + public partial class TestPlayer : SoloPlayer { protected override bool PauseOnFocusLost { get; } @@ -103,6 +104,19 @@ namespace osu.Game.Tests.Visual ScoreProcessor.NewJudgement += r => Results.Add(r); } + public override bool OnExiting(ScreenExitEvent e) + { + bool exiting = base.OnExiting(e); + + // SubmittingPlayer performs EndPlaying on a fire-and-forget async task, which allows for the chance of BeginPlaying to be called before EndPlaying is called here. + // Until this is handled properly at game-side, ensure EndPlaying is called before exiting player. + // see: https://github.com/ppy/osu/issues/22220 + if (LoadedBeatmapSuccessfully) + spectatorClient?.EndPlaying(GameplayState); + + return exiting; + } + protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); diff --git a/osu.Game/Tests/Visual/TestReplayPlayer.cs b/osu.Game/Tests/Visual/TestReplayPlayer.cs index a33a6763af..bc6dc9bb27 100644 --- a/osu.Game/Tests/Visual/TestReplayPlayer.cs +++ b/osu.Game/Tests/Visual/TestReplayPlayer.cs @@ -17,7 +17,7 @@ namespace osu.Game.Tests.Visual /// /// A player that exposes many components that would otherwise not be available, for testing purposes. /// - public class TestReplayPlayer : ReplayPlayer + public partial class TestReplayPlayer : ReplayPlayer { protected override bool PauseOnFocusLost { get; } diff --git a/osu.Game/Tests/Visual/TestUserLookupCache.cs b/osu.Game/Tests/Visual/TestUserLookupCache.cs index 414166fdd8..a3028f1a34 100644 --- a/osu.Game/Tests/Visual/TestUserLookupCache.cs +++ b/osu.Game/Tests/Visual/TestUserLookupCache.cs @@ -10,7 +10,7 @@ using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Tests.Visual { - public class TestUserLookupCache : UserLookupCache + public partial class TestUserLookupCache : UserLookupCache { /// /// A special user ID which would return a for. diff --git a/osu.Game/Updater/NoActionUpdateManager.cs b/osu.Game/Updater/NoActionUpdateManager.cs index 8a96cdb968..97d3275757 100644 --- a/osu.Game/Updater/NoActionUpdateManager.cs +++ b/osu.Game/Updater/NoActionUpdateManager.cs @@ -16,7 +16,7 @@ namespace osu.Game.Updater /// An update manager that shows notifications if a newer release is detected. /// This is a case where updates are handled externally by a package manager or other means, so no action is performed on clicking the notification. /// - public class NoActionUpdateManager : UpdateManager + public partial class NoActionUpdateManager : UpdateManager { private string version; diff --git a/osu.Game/Updater/SimpleUpdateManager.cs b/osu.Game/Updater/SimpleUpdateManager.cs index fb5794d92e..1ecb73a154 100644 --- a/osu.Game/Updater/SimpleUpdateManager.cs +++ b/osu.Game/Updater/SimpleUpdateManager.cs @@ -20,7 +20,7 @@ namespace osu.Game.Updater /// An update manager that shows notifications if a newer release is detected. /// Installation is left up to the user. /// - public class SimpleUpdateManager : UpdateManager + public partial class SimpleUpdateManager : UpdateManager { private string version; diff --git a/osu.Game/Updater/UpdateManager.cs b/osu.Game/Updater/UpdateManager.cs index 7b540cb564..47c2a169ed 100644 --- a/osu.Game/Updater/UpdateManager.cs +++ b/osu.Game/Updater/UpdateManager.cs @@ -17,7 +17,7 @@ namespace osu.Game.Updater /// /// An update manager which only shows notifications after an update completes. /// - public class UpdateManager : CompositeDrawable + public partial class UpdateManager : CompositeDrawable { /// /// Whether this UpdateManager should be or is capable of checking for updates. @@ -85,7 +85,7 @@ namespace osu.Game.Updater /// Whether any update is waiting. May return true if an error occured (there is potentially an update available). protected virtual Task PerformUpdateCheck() => Task.FromResult(false); - private class UpdateCompleteNotification : SimpleNotification + private partial class UpdateCompleteNotification : SimpleNotification { private readonly string version; @@ -110,7 +110,7 @@ namespace osu.Game.Updater } } - public class UpdateApplicationCompleteNotification : ProgressCompletionNotification + public partial class UpdateApplicationCompleteNotification : ProgressCompletionNotification { public UpdateApplicationCompleteNotification() { @@ -118,7 +118,7 @@ namespace osu.Game.Updater } } - public class UpdateProgressNotification : ProgressNotification + public partial class UpdateProgressNotification : ProgressNotification { protected override Notification CreateCompletionNotification() => new UpdateApplicationCompleteNotification { diff --git a/osu.Game/Users/Drawables/ClickableAvatar.cs b/osu.Game/Users/Drawables/ClickableAvatar.cs index 62e966c48f..5a3009dfcd 100644 --- a/osu.Game/Users/Drawables/ClickableAvatar.cs +++ b/osu.Game/Users/Drawables/ClickableAvatar.cs @@ -13,7 +13,7 @@ using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Users.Drawables { - public class ClickableAvatar : Container + public partial class ClickableAvatar : Container { private const string default_tooltip_text = "view profile"; @@ -71,7 +71,7 @@ namespace osu.Game.Users.Drawables game?.ShowUser(user); } - private class ClickableArea : OsuClickableContainer + private partial class ClickableArea : OsuClickableContainer { private LocalisableString tooltip = default_tooltip_text; diff --git a/osu.Game/Users/Drawables/DrawableAvatar.cs b/osu.Game/Users/Drawables/DrawableAvatar.cs index 155f63dc18..bd09b95164 100644 --- a/osu.Game/Users/Drawables/DrawableAvatar.cs +++ b/osu.Game/Users/Drawables/DrawableAvatar.cs @@ -12,7 +12,7 @@ using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Users.Drawables { [LongRunningLoad] - public class DrawableAvatar : Sprite + public partial class DrawableAvatar : Sprite { private readonly IUser user; diff --git a/osu.Game/Users/Drawables/DrawableFlag.cs b/osu.Game/Users/Drawables/DrawableFlag.cs index 253835b415..929a29251d 100644 --- a/osu.Game/Users/Drawables/DrawableFlag.cs +++ b/osu.Game/Users/Drawables/DrawableFlag.cs @@ -13,7 +13,7 @@ using osu.Framework.Localisation; namespace osu.Game.Users.Drawables { - public class DrawableFlag : Sprite, IHasTooltip + public partial class DrawableFlag : Sprite, IHasTooltip { private readonly CountryCode countryCode; @@ -27,8 +27,7 @@ namespace osu.Game.Users.Drawables [BackgroundDependencyLoader] private void load(TextureStore ts) { - if (ts == null) - throw new ArgumentNullException(nameof(ts)); + ArgumentNullException.ThrowIfNull(ts); string textureName = countryCode == CountryCode.Unknown ? "__" : countryCode.ToString(); Texture = ts.Get($@"Flags/{textureName}") ?? ts.Get(@"Flags/__"); diff --git a/osu.Game/Users/Drawables/StatusIcon.cs b/osu.Game/Users/Drawables/StatusIcon.cs new file mode 100644 index 0000000000..18d06a48f8 --- /dev/null +++ b/osu.Game/Users/Drawables/StatusIcon.cs @@ -0,0 +1,26 @@ +// Copyright (c) ppy Pty Ltd . 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.Framework.Graphics.Shapes; +using osuTK; + +namespace osu.Game.Users.Drawables +{ + public partial class StatusIcon : CircularContainer + { + public StatusIcon() + { + Size = new Vector2(25); + BorderThickness = 4; + BorderColour = Colour4.White; // the colour is being applied through Colour - since it's multiplicative it applies to the border as well + Masking = true; + Child = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Colour4.White.Opacity(0) + }; + } + } +} diff --git a/osu.Game/Users/Drawables/UpdateableAvatar.cs b/osu.Game/Users/Drawables/UpdateableAvatar.cs index dab3dc59f9..9c04eb5706 100644 --- a/osu.Game/Users/Drawables/UpdateableAvatar.cs +++ b/osu.Game/Users/Drawables/UpdateableAvatar.cs @@ -13,7 +13,7 @@ namespace osu.Game.Users.Drawables /// /// An avatar which can update to a new user when needed. /// - public class UpdateableAvatar : ModelBackedDrawable + public partial class UpdateableAvatar : ModelBackedDrawable { public APIUser User { diff --git a/osu.Game/Users/Drawables/UpdateableFlag.cs b/osu.Game/Users/Drawables/UpdateableFlag.cs index 9b101131b3..a208f3c7c4 100644 --- a/osu.Game/Users/Drawables/UpdateableFlag.cs +++ b/osu.Game/Users/Drawables/UpdateableFlag.cs @@ -13,7 +13,7 @@ using osu.Game.Overlays; namespace osu.Game.Users.Drawables { - public class UpdateableFlag : ModelBackedDrawable + public partial class UpdateableFlag : ModelBackedDrawable { public CountryCode CountryCode { diff --git a/osu.Game/Users/ExtendedUserPanel.cs b/osu.Game/Users/ExtendedUserPanel.cs index a4cba8b920..4ea3c036c1 100644 --- a/osu.Game/Users/ExtendedUserPanel.cs +++ b/osu.Game/Users/ExtendedUserPanel.cs @@ -10,14 +10,13 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -using osu.Framework.Graphics.Sprites; using osu.Game.Users.Drawables; using osu.Framework.Input.Events; using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Users { - public abstract class ExtendedUserPanel : UserPanel + public abstract partial class ExtendedUserPanel : UserPanel { public readonly Bindable Status = new Bindable(); @@ -25,7 +24,7 @@ namespace osu.Game.Users protected TextFlowContainer LastVisitMessage { get; private set; } - private SpriteIcon statusIcon; + private StatusIcon statusIcon; private OsuSpriteText statusMessage; protected ExtendedUserPanel(APIUser user) @@ -59,11 +58,7 @@ namespace osu.Game.Users Action = Action, }; - protected SpriteIcon CreateStatusIcon() => statusIcon = new SpriteIcon - { - Icon = FontAwesome.Regular.Circle, - Size = new Vector2(25) - }; + protected Container CreateStatusIcon() => statusIcon = new StatusIcon(); protected FillFlowContainer CreateStatusMessage(bool rightAlignedChildren) { diff --git a/osu.Game/Users/UserBrickPanel.cs b/osu.Game/Users/UserBrickPanel.cs index a214b72795..69b390b36e 100644 --- a/osu.Game/Users/UserBrickPanel.cs +++ b/osu.Game/Users/UserBrickPanel.cs @@ -14,7 +14,7 @@ using osuTK; namespace osu.Game.Users { - public class UserBrickPanel : UserPanel + public partial class UserBrickPanel : UserPanel { public UserBrickPanel(APIUser user) : base(user) diff --git a/osu.Game/Users/UserCoverBackground.cs b/osu.Game/Users/UserCoverBackground.cs index c799bbb1ea..de6a306b2a 100644 --- a/osu.Game/Users/UserCoverBackground.cs +++ b/osu.Game/Users/UserCoverBackground.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; @@ -17,15 +15,15 @@ using osuTK.Graphics; namespace osu.Game.Users { - public class UserCoverBackground : ModelBackedDrawable + public partial class UserCoverBackground : ModelBackedDrawable { - public APIUser User + public APIUser? User { get => Model; set => Model = value; } - protected override Drawable CreateDrawable(APIUser user) => new Cover(user); + protected override Drawable CreateDrawable(APIUser? user) => new Cover(user); protected override double LoadDelay => 300; @@ -38,11 +36,11 @@ namespace osu.Game.Users => new DelayedLoadUnloadWrapper(createContentFunc, timeBeforeLoad, UnloadDelay); [LongRunningLoad] - private class Cover : CompositeDrawable + private partial class Cover : CompositeDrawable { - private readonly APIUser user; + private readonly APIUser? user; - public Cover(APIUser user) + public Cover(APIUser? user) { this.user = user; diff --git a/osu.Game/Users/UserGridPanel.cs b/osu.Game/Users/UserGridPanel.cs index 38d8f6fb33..90b6c11f0e 100644 --- a/osu.Game/Users/UserGridPanel.cs +++ b/osu.Game/Users/UserGridPanel.cs @@ -12,7 +12,7 @@ using osuTK; namespace osu.Game.Users { - public class UserGridPanel : ExtendedUserPanel + public partial class UserGridPanel : ExtendedUserPanel { private const int margin = 10; diff --git a/osu.Game/Users/UserListPanel.cs b/osu.Game/Users/UserListPanel.cs index 6d45481dbe..bbd3c60a33 100644 --- a/osu.Game/Users/UserListPanel.cs +++ b/osu.Game/Users/UserListPanel.cs @@ -15,7 +15,7 @@ using osu.Game.Overlays.Profile.Header.Components; namespace osu.Game.Users { - public class UserListPanel : ExtendedUserPanel + public partial class UserListPanel : ExtendedUserPanel { public UserListPanel(APIUser user) : base(user) diff --git a/osu.Game/Users/UserPanel.cs b/osu.Game/Users/UserPanel.cs index d150b38c45..e2dc511391 100644 --- a/osu.Game/Users/UserPanel.cs +++ b/osu.Game/Users/UserPanel.cs @@ -1,9 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; +using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; @@ -14,12 +13,15 @@ using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics.UserInterface; using osu.Framework.Graphics.Cursor; using osu.Game.Graphics.Containers; -using JetBrains.Annotations; +using osu.Game.Online.API; using osu.Game.Online.API.Requests.Responses; +using osu.Game.Online.Chat; +using osu.Game.Resources.Localisation.Web; +using osu.Game.Localisation; namespace osu.Game.Users { - public abstract class UserPanel : OsuClickableContainer, IHasContextMenu + public abstract partial class UserPanel : OsuClickableContainer, IHasContextMenu { public readonly APIUser User; @@ -27,29 +29,37 @@ namespace osu.Game.Users /// Perform an action in addition to showing the user's profile. /// This should be used to perform auxiliary tasks and not as a primary action for clicking a user panel (to maintain a consistent UX). /// - public new Action Action; + public new Action? Action; - protected Action ViewProfile { get; private set; } + protected Action ViewProfile { get; private set; } = null!; - protected Drawable Background { get; private set; } + protected Drawable Background { get; private set; } = null!; protected UserPanel(APIUser user) : base(HoverSampleSet.Button) { - if (user == null) - throw new ArgumentNullException(nameof(user)); + ArgumentNullException.ThrowIfNull(user); User = user; } - [Resolved(canBeNull: true)] - private UserProfileOverlay profileOverlay { get; set; } - - [Resolved(canBeNull: true)] - protected OverlayColourProvider ColourProvider { get; private set; } + [Resolved] + private UserProfileOverlay? profileOverlay { get; set; } [Resolved] - protected OsuColour Colours { get; private set; } + private IAPIProvider api { get; set; } = null!; + + [Resolved] + private ChannelManager? channelManager { get; set; } + + [Resolved] + private ChatOverlay? chatOverlay { get; set; } + + [Resolved] + protected OverlayColourProvider? ColourProvider { get; private set; } + + [Resolved] + protected OsuColour Colours { get; private set; } = null!; [BackgroundDependencyLoader] private void load() @@ -80,7 +90,6 @@ namespace osu.Game.Users }; } - [NotNull] protected abstract Drawable CreateLayout(); protected OsuSpriteText CreateUsername() => new OsuSpriteText @@ -90,9 +99,26 @@ namespace osu.Game.Users Text = User.Username, }; - public MenuItem[] ContextMenuItems => new MenuItem[] + public MenuItem[] ContextMenuItems { - new OsuMenuItem("View Profile", MenuItemType.Highlighted, ViewProfile), - }; + get + { + List items = new List + { + new OsuMenuItem(ContextMenuStrings.ViewProfile, MenuItemType.Highlighted, ViewProfile) + }; + + if (!User.Equals(api.LocalUser.Value)) + { + items.Add(new OsuMenuItem(UsersStrings.CardSendMessage, MenuItemType.Standard, () => + { + channelManager?.OpenPrivateChannel(User); + chatOverlay?.Show(); + })); + } + + return items.ToArray(); + } + } } } diff --git a/osu.Game/Utils/NamingUtils.cs b/osu.Game/Utils/NamingUtils.cs index 482e3d0954..97220f4201 100644 --- a/osu.Game/Utils/NamingUtils.cs +++ b/osu.Game/Utils/NamingUtils.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using System.IO; using System.Text.RegularExpressions; namespace osu.Game.Utils @@ -28,8 +29,53 @@ namespace osu.Game.Utils /// public static string GetNextBestName(IEnumerable existingNames, string desiredName) { - string pattern = $@"^(?i){Regex.Escape(desiredName)}(?-i)( \((?[1-9][0-9]*)\))?$"; + string pattern = $@"^{getBaselineNameDetectingPattern(desiredName)}$"; var regex = new Regex(pattern, RegexOptions.Compiled); + + int bestNumber = findBestNumber(existingNames, regex); + + return bestNumber == 0 + ? desiredName + : $"{desiredName} ({bestNumber.ToString()})"; + } + + /// + /// Given a set of and a desired target + /// finds a filename closest to that is not in + /// + public static string GetNextBestFilename(IEnumerable existingFilenames, string desiredFilename) + { + string name = Path.GetFileNameWithoutExtension(desiredFilename); + string extension = Path.GetExtension(desiredFilename); + + string pattern = $@"^{getBaselineNameDetectingPattern(name)}(?i){Regex.Escape(extension)}(?-i)$"; + var regex = new Regex(pattern, RegexOptions.Compiled); + + int bestNumber = findBestNumber(existingFilenames, regex); + + return bestNumber == 0 + ? desiredFilename + : $"{name} ({bestNumber.ToString()}){extension}"; + } + + /// + /// Generates a basic regex pattern that will match all possible conflicting filenames when picking the best available name, given the . + /// The generated pattern can be composed into more complicated regexes for particular uses, such as picking filenames, which need additional file extension handling. + /// + /// + /// The regex shall detect: + /// + /// all strings that are equal to , + /// all strings of the format desiredName (number), where number is a number written using Arabic numerals. + /// + /// All comparisons are made in a case-insensitive manner. + /// If a number is detected in the matches, it will be output to the copyNumber named group. + /// + private static string getBaselineNameDetectingPattern(string desiredName) + => $@"(?i){Regex.Escape(desiredName)}(?-i)( \((?[1-9][0-9]*)\))?"; + + private static int findBestNumber(IEnumerable existingNames, Regex regex) + { var takenNumbers = new HashSet(); foreach (string name in existingNames) @@ -53,9 +99,7 @@ namespace osu.Game.Utils while (takenNumbers.Contains(bestNumber)) bestNumber += 1; - return bestNumber == 0 - ? desiredName - : $"{desiredName} ({bestNumber})"; + return bestNumber; } } } diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 5c4b5642b5..cce3e42be4 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -1,6 +1,6 @@ - netstandard2.1 + net6.0 Library true @@ -29,19 +29,24 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + + + + + diff --git a/osu.iOS.props b/osu.iOS.props index 19f4248055..6201022da1 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -1,92 +1,21 @@  - 8.0 - {FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - Resources - PackageReference - bin\$(Platform)\$(Configuration) - cjk,mideast,other,rare,west - false - NSUrlSessionHandler - iPhone Developer - true - - - - --nosymbolstrip=BASS_FX_BPM_BeatCallbackReset --nosymbolstrip=BASS_FX_BPM_BeatCallbackSet --nosymbolstrip=BASS_FX_BPM_BeatDecodeGet --nosymbolstrip=BASS_FX_BPM_BeatFree --nosymbolstrip=BASS_FX_BPM_BeatGetParameters --nosymbolstrip=BASS_FX_BPM_BeatSetParameters --nosymbolstrip=BASS_FX_BPM_CallbackReset --nosymbolstrip=BASS_FX_BPM_CallbackSet --nosymbolstrip=BASS_FX_BPM_DecodeGet --nosymbolstrip=BASS_FX_BPM_Free --nosymbolstrip=BASS_FX_BPM_Translate --nosymbolstrip=BASS_FX_GetVersion --nosymbolstrip=BASS_FX_ReverseCreate --nosymbolstrip=BASS_FX_ReverseGetSource --nosymbolstrip=BASS_FX_TempoCreate --nosymbolstrip=BASS_FX_TempoGetRateRatio --nosymbolstrip=BASS_FX_TempoGetSource --nosymbolstrip=BASS_Mixer_ChannelFlags --nosymbolstrip=BASS_Mixer_ChannelGetData --nosymbolstrip=BASS_Mixer_ChannelGetEnvelopePos --nosymbolstrip=BASS_Mixer_ChannelGetLevel --nosymbolstrip=BASS_Mixer_ChannelGetLevelEx --nosymbolstrip=BASS_Mixer_ChannelGetMatrix --nosymbolstrip=BASS_Mixer_ChannelGetMixer --nosymbolstrip=BASS_Mixer_ChannelGetPosition --nosymbolstrip=BASS_Mixer_ChannelGetPositionEx --nosymbolstrip=BASS_Mixer_ChannelIsActive --nosymbolstrip=BASS_Mixer_ChannelRemove --nosymbolstrip=BASS_Mixer_ChannelRemoveSync --nosymbolstrip=BASS_Mixer_ChannelSetEnvelope --nosymbolstrip=BASS_Mixer_ChannelSetEnvelopePos --nosymbolstrip=BASS_Mixer_ChannelSetMatrix --nosymbolstrip=BASS_Mixer_ChannelSetMatrixEx --nosymbolstrip=BASS_Mixer_ChannelSetPosition --nosymbolstrip=BASS_Mixer_ChannelSetSync --nosymbolstrip=BASS_Mixer_GetVersion --nosymbolstrip=BASS_Mixer_StreamAddChannel --nosymbolstrip=BASS_Mixer_StreamAddChannelEx --nosymbolstrip=BASS_Mixer_StreamCreate --nosymbolstrip=BASS_Mixer_StreamGetChannels --nosymbolstrip=BASS_Split_StreamCreate --nosymbolstrip=BASS_Split_StreamGetAvailable --nosymbolstrip=BASS_Split_StreamGetSource --nosymbolstrip=BASS_Split_StreamGetSplits --nosymbolstrip=BASS_Split_StreamReset --nosymbolstrip=BASS_Split_StreamResetEx - - --nolinkaway --nostrip $(GeneratedMtouchSymbolStripFlags) - - - true - full - false - DEBUG;ENABLE_TEST_CLOUD; - true - true - - - pdbonly - true - - - x86_64 - None + true + + true + + $(NoWarn);MT7091 - true - SdkOnly - ARM64 - Entitlements.plist + ios-arm64 - - true - 25823 - false - - - true - - - true - 28126 + + iossimulator-x64 - - - - - - - - - - - - - - $(NoWarn);NU1605 - - - - - none - - - none - - - - - - - - - - - - - + diff --git a/osu.iOS/Application.cs b/osu.iOS/Application.cs index c5b2d0b451..64eb5c63f5 100644 --- a/osu.iOS/Application.cs +++ b/osu.iOS/Application.cs @@ -3,7 +3,6 @@ #nullable disable -using osu.Framework.iOS; using UIKit; namespace osu.iOS @@ -12,7 +11,7 @@ namespace osu.iOS { public static void Main(string[] args) { - UIApplication.Main(args, typeof(GameUIApplication), typeof(AppDelegate)); + UIApplication.Main(args, null, typeof(AppDelegate)); } } } diff --git a/osu.iOS/IOSMouseSettings.cs b/osu.iOS/IOSMouseSettings.cs index 1979a881f7..f464bd93b8 100644 --- a/osu.iOS/IOSMouseSettings.cs +++ b/osu.iOS/IOSMouseSettings.cs @@ -10,7 +10,7 @@ using osu.Game.Overlays.Settings; namespace osu.iOS { - public class IOSMouseSettings : SettingsSubsection + public partial class IOSMouseSettings : SettingsSubsection { protected override LocalisableString Header => MouseSettingsStrings.Mouse; diff --git a/osu.iOS/Info.plist b/osu.iOS/Info.plist index 16cb68fa7d..0ce1d952d0 100644 --- a/osu.iOS/Info.plist +++ b/osu.iOS/Info.plist @@ -8,14 +8,10 @@ osu! CFBundleDisplayName osu! - CFBundleShortVersionString - 0.1 - CFBundleVersion - 0.1.0 LSRequiresIPhoneOS MinimumOSVersion - 10.0 + 13.4 UIDeviceFamily 1 diff --git a/osu.iOS/Linker.xml b/osu.iOS/Linker.xml deleted file mode 100644 index 04591c55d0..0000000000 --- a/osu.iOS/Linker.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/osu.iOS/OsuGameIOS.cs b/osu.iOS/OsuGameIOS.cs index ecbea42d74..3e79bc6ad6 100644 --- a/osu.iOS/OsuGameIOS.cs +++ b/osu.iOS/OsuGameIOS.cs @@ -5,6 +5,7 @@ using System; using Foundation; +using Microsoft.Maui.Devices; using osu.Framework.Graphics; using osu.Framework.Input.Handlers; using osu.Framework.iOS.Input; @@ -12,11 +13,10 @@ using osu.Game; using osu.Game.Overlays.Settings; using osu.Game.Updater; using osu.Game.Utils; -using Xamarin.Essentials; namespace osu.iOS { - public class OsuGameIOS : OsuGame + public partial class OsuGameIOS : OsuGame { public override Version AssemblyVersion => new Version(NSBundle.MainBundle.InfoDictionary["CFBundleVersion"].ToString()); @@ -33,7 +33,7 @@ namespace osu.iOS { switch (handler) { - case IOSMouseHandler _: + case IOSMouseHandler: return new IOSMouseSettings(); default: diff --git a/osu.iOS/osu.iOS.csproj b/osu.iOS/osu.iOS.csproj index b9da874f30..2d61b73125 100644 --- a/osu.iOS/osu.iOS.csproj +++ b/osu.iOS/osu.iOS.csproj @@ -1,124 +1,19 @@ - - - - Debug - iPhoneSimulator + + + net6.0-ios + 13.4 Exe - {3F082D0B-A964-43D7-BDF7-C256D76A50D0} - osu.iOS - osu.iOS - false + true + 0.1.0 + $(Version) + $(Version) - + + + + + - - - - - - - - - - - - - - - - - - - {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D} - osu.Game - - - {58F6C80C-1253-4A0E-A465-B8C85EBEADF3} - osu.Game.Rulesets.Catch - - - {48F4582B-7687-4621-9CBE-5C24197CB536} - osu.Game.Rulesets.Mania - - - {C92A607B-1FDD-4954-9F92-03FF547D9080} - osu.Game.Rulesets.Osu - - - {F167E17A-7DE6-4AF5-B920-A5112296C695} - osu.Game.Rulesets.Taiko - - - - - - - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - - - - diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index 154ad0fe8c..367dfccb71 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -146,7 +146,7 @@ HINT HINT WARNING - WARNING + HINT WARNING WARNING WARNING @@ -218,6 +218,7 @@ WARNING WARNING WARNING + WARNING WARNING HINT WARNING