mirror of
https://github.com/SK-la/osu-framework.git
synced 2026-03-15 03:20:30 +00:00
Merge master and update Android to SDL3
This commit is contained in:
38
.github/workflows/build-ffmpeg.yml
vendored
38
.github/workflows/build-ffmpeg.yml
vendored
@@ -13,7 +13,7 @@ jobs:
|
||||
- arm64
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- uses: ilammy/setup-nasm@v1
|
||||
|
||||
@@ -23,7 +23,7 @@ jobs:
|
||||
arch: ${{ matrix.arch }}
|
||||
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: macOS-${{ matrix.arch }}
|
||||
path: macOS-${{ matrix.arch }}
|
||||
@@ -34,13 +34,13 @@ jobs:
|
||||
needs: build-macos
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/download-artifact@v3
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: macOS-x86_64
|
||||
path: macOS-x86_64
|
||||
- uses: actions/download-artifact@v3
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: macOS-arm64
|
||||
path: macOS-arm64
|
||||
@@ -49,7 +49,7 @@ jobs:
|
||||
run: osu.Framework.NativeLibs/scripts/ffmpeg/combine_dylibs.sh
|
||||
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: macOS-universal
|
||||
path: macOS-universal
|
||||
@@ -65,7 +65,7 @@ jobs:
|
||||
- x64
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
@@ -78,7 +78,7 @@ jobs:
|
||||
arch: ${{ matrix.arch }}
|
||||
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: win-${{ matrix.arch }}
|
||||
path: win-${{ matrix.arch }}
|
||||
@@ -91,7 +91,7 @@ jobs:
|
||||
image: mstorsjo/llvm-mingw:latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Build
|
||||
run: osu.Framework.NativeLibs/scripts/ffmpeg/build-win.sh
|
||||
@@ -99,7 +99,7 @@ jobs:
|
||||
arch: arm64
|
||||
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: win-arm64
|
||||
path: win-arm64
|
||||
@@ -115,13 +115,13 @@ jobs:
|
||||
sudo apt-get install nasm libva-dev libvdpau-dev
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Build
|
||||
run: osu.Framework.NativeLibs/scripts/ffmpeg/build-linux.sh
|
||||
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: linux-x64
|
||||
path: linux-x64
|
||||
@@ -136,30 +136,30 @@ jobs:
|
||||
- build-linux
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/download-artifact@v3
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: macOS-universal
|
||||
path: osu.Framework.NativeLibs/runtimes/osx/native
|
||||
- uses: actions/download-artifact@v3
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: linux-x64
|
||||
path: osu.Framework.NativeLibs/runtimes/linux-x64/native
|
||||
- uses: actions/download-artifact@v3
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: win-arm64
|
||||
path: osu.Framework.NativeLibs/runtimes/win-arm64/native
|
||||
- uses: actions/download-artifact@v3
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: win-x64
|
||||
path: osu.Framework.NativeLibs/runtimes/win-x64/native
|
||||
- uses: actions/download-artifact@v3
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: win-x86
|
||||
path: osu.Framework.NativeLibs/runtimes/win-x86/native
|
||||
|
||||
- uses: peter-evans/create-pull-request@v4
|
||||
- uses: peter-evans/create-pull-request@v6
|
||||
with:
|
||||
commit-message: Update FFmpeg binaries
|
||||
title: Update FFmpeg binaries
|
||||
|
||||
22
.github/workflows/ci.yml
vendored
22
.github/workflows/ci.yml
vendored
@@ -7,10 +7,10 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install .NET 8.0.x
|
||||
uses: actions/setup-dotnet@v3
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: "8.0.x"
|
||||
|
||||
@@ -21,7 +21,7 @@ jobs:
|
||||
run: dotnet restore osu-framework.Desktop.slnf
|
||||
|
||||
- name: Restore inspectcode cache
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{ github.workspace }}/inspectcode
|
||||
key: inspectcode-${{ hashFiles('.config/dotnet-tools.json', '.github/workflows/ci.yml', 'osu-framework.sln*', 'osu-framework*.slnf', '.editorconfig', '.globalconfig', 'CodeAnalysis/*', '**/*.csproj', '**/*.props') }}
|
||||
@@ -67,15 +67,15 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install .NET 8.0.x
|
||||
uses: actions/setup-dotnet@v3
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: "8.0.x"
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v3
|
||||
uses: actions/setup-go@v5
|
||||
|
||||
- name: Install httpbin
|
||||
run: go install github.com/mccutchen/go-httpbin/v2/cmd/go-httpbin@latest
|
||||
@@ -106,16 +106,16 @@ jobs:
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup JDK 11
|
||||
uses: actions/setup-java@v3
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: microsoft
|
||||
java-version: 11
|
||||
|
||||
- name: Install .NET 8.0.x
|
||||
uses: actions/setup-dotnet@v3
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: "8.0.x"
|
||||
|
||||
@@ -131,10 +131,10 @@ jobs:
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install .NET 8.0.x
|
||||
uses: actions/setup-dotnet@v3
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: "8.0.x"
|
||||
|
||||
|
||||
6
.github/workflows/deploy-nativelibs.yml
vendored
6
.github/workflows/deploy-nativelibs.yml
vendored
@@ -40,14 +40,14 @@ jobs:
|
||||
needs: check-if-tag
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set Artifacts Directory
|
||||
id: artifactsPath
|
||||
run: echo "::set-output name=NUGET_ARTIFACTS::${{github.workspace}}/artifacts"
|
||||
|
||||
- name: Setup .NET 8.0.x
|
||||
uses: actions/setup-dotnet@v3
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: "8.0.x"
|
||||
|
||||
@@ -55,7 +55,7 @@ jobs:
|
||||
run: dotnet pack -c Release osu.Framework.NativeLibs /p:Configuration=Release /p:Version=${{needs.check-if-tag.outputs.version}} /p:GenerateDocumentationFile=true -o ${{steps.artifactsPath.outputs.nuget_artifacts}}
|
||||
|
||||
- name: Upload Artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: osu-framework-nativelibs
|
||||
path: ${{steps.artifactsPath.outputs.nuget_artifacts}}/*.nupkg
|
||||
|
||||
26
.github/workflows/deploy-pack.yml
vendored
26
.github/workflows/deploy-pack.yml
vendored
@@ -47,14 +47,14 @@ jobs:
|
||||
shell: powershell
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set artifacts directory
|
||||
id: artifactsPath
|
||||
run: echo "::set-output name=NUGET_ARTIFACTS::${{github.workspace}}\artifacts"
|
||||
|
||||
- name: Install .NET 8.0.x
|
||||
uses: actions/setup-dotnet@v3
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: "8.0.x"
|
||||
|
||||
@@ -62,7 +62,7 @@ jobs:
|
||||
run: dotnet pack -c Release osu.Framework /p:Version=${{ github.ref_name }} /p:GenerateDocumentationFile=true /p:IncludeSymbols=true /p:SymbolPackageFormat=snupkg -o ${{steps.artifactsPath.outputs.nuget_artifacts}}
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: osu-framework
|
||||
path: |
|
||||
@@ -78,14 +78,14 @@ jobs:
|
||||
environment: production
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set artifacts Directory
|
||||
id: artifactsPath
|
||||
run: echo "::set-output name=NUGET_ARTIFACTS::${{github.workspace}}/artifacts"
|
||||
|
||||
- name: Install .NET 8.0.x
|
||||
uses: actions/setup-dotnet@v3
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: "8.0.x"
|
||||
|
||||
@@ -96,7 +96,7 @@ jobs:
|
||||
run: dotnet pack -c Release osu.Framework.Templates /p:Configuration=Release /p:Version=${{ github.ref_name }} /p:GenerateDocumentationFile=true /p:NoDefaultExcludes=true -o ${{steps.artifactsPath.outputs.nuget_artifacts}}
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: osu-framework-templates
|
||||
path: ${{steps.artifactsPath.outputs.nuget_artifacts}}/*.nupkg
|
||||
@@ -113,19 +113,19 @@ jobs:
|
||||
shell: powershell
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set artifacts directory
|
||||
id: artifactsPath
|
||||
run: echo "::set-output name=NUGET_ARTIFACTS::${{github.workspace}}\artifacts"
|
||||
|
||||
- name: Install .NET 8.0.x
|
||||
uses: actions/setup-dotnet@v3
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: "8.0.x"
|
||||
|
||||
- name: Setup JDK 11
|
||||
uses: actions/setup-java@v3
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: microsoft
|
||||
java-version: 11
|
||||
@@ -137,7 +137,7 @@ jobs:
|
||||
run: dotnet pack -c Release osu.Framework.Android /p:Version=${{ github.ref_name }} /p:GenerateDocumentationFile=true -o ${{steps.artifactsPath.outputs.nuget_artifacts}}
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: osu-framework-android
|
||||
path: ${{steps.artifactsPath.outputs.nuget_artifacts}}\*.nupkg
|
||||
@@ -154,14 +154,14 @@ jobs:
|
||||
shell: bash
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set artifacts directory
|
||||
id: artifactsPath
|
||||
run: echo "::set-output name=NUGET_ARTIFACTS::${{github.workspace}}/artifacts"
|
||||
|
||||
- name: Install .NET 8.0.x
|
||||
uses: actions/setup-dotnet@v3
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: "8.0.x"
|
||||
|
||||
@@ -174,7 +174,7 @@ jobs:
|
||||
run: dotnet pack -c Release osu.Framework.iOS /p:Version=${{ github.ref_name }} /p:GenerateDocumentationFile=true -o ${{steps.artifactsPath.outputs.nuget_artifacts}}
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: osu-framework-ios
|
||||
path: ${{steps.artifactsPath.outputs.nuget_artifacts}}/*.nupkg
|
||||
|
||||
2
.github/workflows/report-nunit.yml
vendored
2
.github/workflows/report-nunit.yml
vendored
@@ -25,7 +25,7 @@ jobs:
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: Annotate CI run with test results
|
||||
uses: dorny/test-reporter@v1.6.0
|
||||
uses: dorny/test-reporter@v1.8.0
|
||||
with:
|
||||
artifact: osu-framework-test-results-${{matrix.os.prettyname}}-${{matrix.threadingMode}}-${{matrix.os.configuration}}
|
||||
name: Test Results (${{matrix.os.prettyname}}, ${{matrix.threadingMode}}, ${{matrix.os.configuration}})
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Benchmarks" type="DotNetProject" factoryName=".NET Project">
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Framework.Benchmarks/bin/Debug/net5.0/osu.Framework.Benchmarks.dll" />
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Framework.Benchmarks/bin/Debug/net8.0/osu.Framework.Benchmarks.dll" />
|
||||
<option name="PROGRAM_PARAMETERS" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Framework.Benchmarks/bin/Debug/net5.0" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Framework.Benchmarks/bin/Debug/net8.0" />
|
||||
<option name="PASS_PARENT_ENVS" value="1" />
|
||||
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
||||
<option name="USE_MONO" value="0" />
|
||||
@@ -12,7 +12,7 @@
|
||||
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
||||
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
||||
<option name="PROJECT_KIND" value="DotNetCore" />
|
||||
<option name="PROJECT_TFM" value="net5.0" />
|
||||
<option name="PROJECT_TFM" value="net8.0" />
|
||||
<method v="2">
|
||||
<option name="Build" />
|
||||
</method>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="SampleGame" type="DotNetProject" factoryName=".NET Project" activateToolWindowBeforeRun="false">
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/SampleGame.Desktop/bin/Debug/net5.0/SampleGame.Desktop.dll" />
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/SampleGame.Desktop/bin/Debug/net8.0/SampleGame.Desktop.dll" />
|
||||
<option name="PROGRAM_PARAMETERS" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/SampleGame.Desktop/bin/Debug/net5.0" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/SampleGame.Desktop/bin/Debug/net8.0" />
|
||||
<option name="PASS_PARENT_ENVS" value="1" />
|
||||
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
||||
<option name="USE_MONO" value="0" />
|
||||
@@ -12,7 +12,7 @@
|
||||
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
||||
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
||||
<option name="PROJECT_KIND" value="DotNetCore" />
|
||||
<option name="PROJECT_TFM" value="net5.0" />
|
||||
<option name="PROJECT_TFM" value="net8.0" />
|
||||
<method v="2">
|
||||
<option name="Build" />
|
||||
</method>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="VisualTests" type="DotNetProject" factoryName=".NET Project" activateToolWindowBeforeRun="false">
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Framework.Tests/bin/Debug/net5.0/osu.Framework.Tests.dll" />
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Framework.Tests/bin/Debug/net8.0/osu.Framework.Tests.dll" />
|
||||
<option name="PROGRAM_PARAMETERS" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Framework.Tests/bin/Debug/net5.0" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Framework.Tests/bin/Debug/net8.0" />
|
||||
<option name="PASS_PARENT_ENVS" value="1" />
|
||||
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
||||
<option name="USE_MONO" value="0" />
|
||||
@@ -12,7 +12,7 @@
|
||||
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
||||
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
||||
<option name="PROJECT_KIND" value="DotNetCore" />
|
||||
<option name="PROJECT_TFM" value="net5.0" />
|
||||
<option name="PROJECT_TFM" value="net8.0" />
|
||||
<method v="2">
|
||||
<option name="Build" />
|
||||
</method>
|
||||
|
||||
20
.vscode/launch.json
vendored
20
.vscode/launch.json
vendored
@@ -21,13 +21,13 @@
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/osu.Framework.Tests/bin/Debug/net6.0/osu.Framework.Tests.dll",
|
||||
"${workspaceRoot}/osu.Framework.Tests/bin/Debug/net8.0/osu.Framework.Tests.dll",
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build (Debug)",
|
||||
"linux": {
|
||||
"env": {
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/osu.Framework.Tests/bin/Debug/net6.0:${env:LD_LIBRARY_PATH}"
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/osu.Framework.Tests/bin/Debug/net8.0:${env:LD_LIBRARY_PATH}"
|
||||
}
|
||||
},
|
||||
"console": "internalConsole"
|
||||
@@ -38,13 +38,13 @@
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/osu.Framework.Tests/bin/Release/net6.0/osu.Framework.Tests.dll",
|
||||
"${workspaceRoot}/osu.Framework.Tests/bin/Release/net8.0/osu.Framework.Tests.dll",
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build (Release)",
|
||||
"linux": {
|
||||
"env": {
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/osu.Framework.Tests/bin/Release/net6.0:${env:LD_LIBRARY_PATH}"
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/osu.Framework.Tests/bin/Release/net8.0:${env:LD_LIBRARY_PATH}"
|
||||
}
|
||||
},
|
||||
"console": "internalConsole"
|
||||
@@ -55,13 +55,13 @@
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/SampleGame.Desktop/bin/Debug/net6.0/SampleGame.Desktop.dll",
|
||||
"${workspaceRoot}/SampleGame.Desktop/bin/Debug/net8.0/SampleGame.Desktop.dll",
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build (Debug)",
|
||||
"linux": {
|
||||
"env": {
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/SampleGame.Desktop/bin/Debug/net6.0:${env:LD_LIBRARY_PATH}"
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/SampleGame.Desktop/bin/Debug/net8.0:${env:LD_LIBRARY_PATH}"
|
||||
}
|
||||
},
|
||||
"console": "internalConsole"
|
||||
@@ -72,13 +72,13 @@
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/SampleGame.Desktop/bin/Release/net6.0/SampleGame.Desktop.dll",
|
||||
"${workspaceRoot}/SampleGame.Desktop/bin/Release/net8.0/SampleGame.Desktop.dll",
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build (Release)",
|
||||
"linux": {
|
||||
"env": {
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/SampleGame.Desktop/bin/Release/net6.0:${env:LD_LIBRARY_PATH}"
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/SampleGame.Desktop/bin/Release/net8.0:${env:LD_LIBRARY_PATH}"
|
||||
}
|
||||
},
|
||||
"console": "internalConsole"
|
||||
@@ -89,7 +89,7 @@
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/osu.Framework.Benchmarks/bin/Release/net6.0/osu.Framework.Benchmarks.dll",
|
||||
"${workspaceRoot}/osu.Framework.Benchmarks/bin/Release/net8.0/osu.Framework.Benchmarks.dll",
|
||||
"--filter",
|
||||
"*",
|
||||
],
|
||||
@@ -97,7 +97,7 @@
|
||||
"preLaunchTask": "Build Benchmarks",
|
||||
"linux": {
|
||||
"env": {
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/osu.Framework.Benchmarks/bin/Release/net6.0:${env:LD_LIBRARY_PATH}"
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/osu.Framework.Benchmarks/bin/Release/net8.0:${env:LD_LIBRARY_PATH}"
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
@@ -12,3 +12,4 @@ M:System.Char.ToLower(System.Char);char.ToLower() changes behaviour depending on
|
||||
M:System.Char.ToUpper(System.Char);char.ToUpper() changes behaviour depending on CultureInfo.CurrentCulture. Use char.ToUpperInvariant() instead. If wanting culture-sensitive behaviour, explicitly provide CultureInfo.CurrentCulture.
|
||||
M:System.String.ToLower();string.ToLower() changes behaviour depending on CultureInfo.CurrentCulture. Use string.ToLowerInvariant() instead. If wanting culture-sensitive behaviour, explicitly provide CultureInfo.CurrentCulture or use LocalisableString.
|
||||
M:System.String.ToUpper();string.ToUpper() changes behaviour depending on CultureInfo.CurrentCulture. Use string.ToUpperInvariant() instead. If wanting culture-sensitive behaviour, explicitly provide CultureInfo.CurrentCulture or use LocalisableString.
|
||||
M:System.Reflection.Assembly.GetEntryAssembly();Use osu.Framework.RuntimeInfo.EntryAssembly instead
|
||||
|
||||
@@ -71,7 +71,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Framework.SourceGenerat
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Framework.SourceGeneration.Tests", "osu.Framework.SourceGeneration.Tests\osu.Framework.SourceGeneration.Tests.csproj", "{A0DDCF0A-A352-4CC6-8E6E-0E16CAA50CDD}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SDL2-CS-Android", "..\SDL2-CS\SDL2-CS-Android\SDL2-CS-Android.csproj", "{E577CC6E-3616-4951-BDDE-F766291D623F}"
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CodeAnalysis", "CodeAnalysis", "{50334A1F-990D-45FA-A1FE-C92F1994D97B}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
CodeAnalysis\BannedSymbols.txt = CodeAnalysis\BannedSymbols.txt
|
||||
CodeAnalysis\osu-framework.ruleset = CodeAnalysis\osu-framework.ruleset
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SDL3-CS-Android", "..\SDL3-CS\SDL3-CS-Android\SDL3-CS-Android.csproj", "{7C43DA3A-1707-4A56-B9E1-247A695FD294}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
@@ -367,18 +373,18 @@ Global
|
||||
{A0DDCF0A-A352-4CC6-8E6E-0E16CAA50CDD}.Release|iPhone.Build.0 = Release|Any CPU
|
||||
{A0DDCF0A-A352-4CC6-8E6E-0E16CAA50CDD}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||
{A0DDCF0A-A352-4CC6-8E6E-0E16CAA50CDD}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||
{E577CC6E-3616-4951-BDDE-F766291D623F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E577CC6E-3616-4951-BDDE-F766291D623F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E577CC6E-3616-4951-BDDE-F766291D623F}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
||||
{E577CC6E-3616-4951-BDDE-F766291D623F}.Debug|iPhone.Build.0 = Debug|Any CPU
|
||||
{E577CC6E-3616-4951-BDDE-F766291D623F}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||
{E577CC6E-3616-4951-BDDE-F766291D623F}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||
{E577CC6E-3616-4951-BDDE-F766291D623F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E577CC6E-3616-4951-BDDE-F766291D623F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E577CC6E-3616-4951-BDDE-F766291D623F}.Release|iPhone.ActiveCfg = Release|Any CPU
|
||||
{E577CC6E-3616-4951-BDDE-F766291D623F}.Release|iPhone.Build.0 = Release|Any CPU
|
||||
{E577CC6E-3616-4951-BDDE-F766291D623F}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||
{E577CC6E-3616-4951-BDDE-F766291D623F}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||
{7C43DA3A-1707-4A56-B9E1-247A695FD294}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7C43DA3A-1707-4A56-B9E1-247A695FD294}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7C43DA3A-1707-4A56-B9E1-247A695FD294}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
||||
{7C43DA3A-1707-4A56-B9E1-247A695FD294}.Debug|iPhone.Build.0 = Debug|Any CPU
|
||||
{7C43DA3A-1707-4A56-B9E1-247A695FD294}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||
{7C43DA3A-1707-4A56-B9E1-247A695FD294}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||
{7C43DA3A-1707-4A56-B9E1-247A695FD294}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7C43DA3A-1707-4A56-B9E1-247A695FD294}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7C43DA3A-1707-4A56-B9E1-247A695FD294}.Release|iPhone.ActiveCfg = Release|Any CPU
|
||||
{7C43DA3A-1707-4A56-B9E1-247A695FD294}.Release|iPhone.Build.0 = Release|Any CPU
|
||||
{7C43DA3A-1707-4A56-B9E1-247A695FD294}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||
{7C43DA3A-1707-4A56-B9E1-247A695FD294}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -397,6 +403,7 @@ Global
|
||||
{0309CF11-621A-4F23-8FBA-A583303A8531} = {139F6FAA-EF59-4ADC-A69B-33CA7D1C1D4E}
|
||||
{7AA1DB5D-78DB-4693-AE50-D6078F5A0CAB} = {5307589D-87A1-459B-BBD2-1077AA25EB1E}
|
||||
{48783186-230D-4048-A97A-E4F1DF43BF5C} = {139F6FAA-EF59-4ADC-A69B-33CA7D1C1D4E}
|
||||
{50334A1F-990D-45FA-A1FE-C92F1994D97B} = {D29A2153-C171-457E-A147-720976BA430F}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {27D12E10-E38E-4ECE-8DD1-77E8C387B2DD}
|
||||
|
||||
@@ -775,9 +775,19 @@ See the LICENCE file in the repository root for full licence text.
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticReadonly/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=StaticReadonly/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=TypeParameters/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=15b5b1f1_002D457c_002D4ca6_002Db278_002D5615aedc07d3/@EntryIndexedValue"><Policy><Descriptor Staticness="Static" AccessRightKinds="Private" Description="Static readonly fields (private)"><ElementKinds><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /></Policy></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=236f7aa5_002D7b06_002D43ca_002Dbf2a_002D9b31bfcff09a/@EntryIndexedValue"><Policy><Descriptor Staticness="Any" AccessRightKinds="Private" Description="Constant fields (private)"><ElementKinds><Kind Name="CONSTANT_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /></Policy></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=2c62818f_002D621b_002D4425_002Dadc9_002D78611099bfcb/@EntryIndexedValue"><Policy><Descriptor Staticness="Any" AccessRightKinds="Any" Description="Type parameters"><ElementKinds><Kind Name="TYPE_PARAMETER" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></Policy></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=4a98fdf6_002D7d98_002D4f5a_002Dafeb_002Dea44ad98c70c/@EntryIndexedValue"><Policy><Descriptor Staticness="Instance" AccessRightKinds="Private" Description="Instance fields (private)"><ElementKinds><Kind Name="FIELD" /><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb"><ExtraRule Prefix="_" Suffix="" Style="aaBb" /></Policy></Policy></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=669e5282_002Dfb4b_002D4e90_002D91e7_002D07d269d04b60/@EntryIndexedValue"><Policy><Descriptor Staticness="Any" AccessRightKinds="Protected, ProtectedInternal, Internal, Public, PrivateProtected" Description="Constant fields (not private)"><ElementKinds><Kind Name="CONSTANT_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /></Policy></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=76f79b1e_002Dece7_002D4df2_002Da322_002D1bd7fea25eb7/@EntryIndexedValue"><Policy><Descriptor Staticness="Any" AccessRightKinds="Any" Description="Local functions"><ElementKinds><Kind Name="LOCAL_FUNCTION" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></Policy></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=8b8504e3_002Df0be_002D4c14_002D9103_002Dc732f2bddc15/@EntryIndexedValue"><Policy><Descriptor Staticness="Any" AccessRightKinds="Any" Description="Enum members"><ElementKinds><Kind Name="ENUM_MEMBER" /></ElementKinds></Descriptor><Policy Inspect="False" Prefix="" Suffix="" Style="AaBb" /></Policy></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=9d1af99b_002Dbefe_002D48a4_002D9eb3_002D661384e29869/@EntryIndexedValue"><Policy><Descriptor Staticness="Static, Instance" AccessRightKinds="Private" Description="private methods"><ElementKinds><Kind Name="ASYNC_METHOD" /><Kind Name="METHOD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></Policy></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=9ffbe43b_002Dc610_002D411b_002D9839_002D1416a146d9b0/@EntryIndexedValue"><Policy><Descriptor Staticness="Static, Instance" AccessRightKinds="Protected, ProtectedInternal, Internal, Public" Description="internal/protected/public methods"><ElementKinds><Kind Name="ASYNC_METHOD" /><Kind Name="METHOD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></Policy></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=a4c2df6c_002Db202_002D48d5_002Db077_002De678cb548c25/@EntryIndexedValue"><Policy><Descriptor Staticness="Static, Instance" AccessRightKinds="Private" Description="private properties"><ElementKinds><Kind Name="PROPERTY" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></Policy></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=a4f433b8_002Dabcd_002D4e55_002Da08f_002D82e78cef0f0c/@EntryIndexedValue"><Policy><Descriptor Staticness="Any" AccessRightKinds="Any" Description="Local constants"><ElementKinds><Kind Name="LOCAL_CONSTANT" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /></Policy></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=c873eafb_002Dd57f_002D481d_002D8c93_002D77f6863c2f88/@EntryIndexedValue"><Policy><Descriptor Staticness="Static" AccessRightKinds="Protected, ProtectedInternal, Internal, Public, PrivateProtected" Description="Static readonly fields (not private)"><ElementKinds><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /></Policy></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=f9fce829_002De6f4_002D4cb2_002D80f1_002D5497c44f51df/@EntryIndexedValue"><Policy><Descriptor Staticness="Static" AccessRightKinds="Private" Description="Static fields (private)"><ElementKinds><Kind Name="FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></Policy></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=fd562728_002Dc23d_002D417f_002Da19f_002D9d854247fbea/@EntryIndexedValue"><Policy><Descriptor Staticness="Static, Instance" AccessRightKinds="Protected, ProtectedInternal, Internal, Public" Description="internal/protected/public properties"><ElementKinds><Kind Name="PROPERTY" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></Policy></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FBLOCK_005FSCOPE_005FCONSTANT/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FBLOCK_005FSCOPE_005FFUNCTION/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
||||
@@ -843,6 +853,7 @@ See the LICENCE file in the repository root for full licence text.
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002ECSharpPlaceAttributeOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateThisQualifierSettings/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EPredefinedNamingRulesToUserRulesUpgrade/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:String x:Key="/Default/Environment/UnitTesting/NUnitProvider/SetCurrentDirectoryTo/@EntryValue">TestFolder</s:String>
|
||||
<s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=28A2A5FC43E07C488A4BC7430879479E/@KeyIndexDefined">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=28A2A5FC43E07C488A4BC7430879479E/Applicability/=Live/@EntryIndexedValue">True</s:Boolean>
|
||||
|
||||
@@ -14,6 +14,8 @@ using Org.Libsdl.App;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
using osu.Framework.Platform;
|
||||
using SDL;
|
||||
using Debug = System.Diagnostics.Debug;
|
||||
|
||||
namespace osu.Framework.Android
|
||||
{
|
||||
@@ -74,17 +76,14 @@ namespace osu.Framework.Android
|
||||
host?.Collect();
|
||||
}
|
||||
|
||||
protected override string[] GetLibraries() => new string[] { "SDL2" };
|
||||
protected override string[] GetLibraries() => new string[] { "SDL3" };
|
||||
|
||||
protected override SDLSurface CreateSDLSurface(Context context) => new AndroidGameSurface(this, context);
|
||||
protected override SDLSurface CreateSDLSurface(Context? context) => new AndroidGameSurface(this, context);
|
||||
|
||||
protected override IRunnable CreateSDLMainRunnable() => new Runnable(() =>
|
||||
{
|
||||
// blocks back button
|
||||
SDL2.SDL.SDL_SetHint(SDL2.SDL.SDL_HINT_ANDROID_TRAP_BACK_BUTTON, "1");
|
||||
|
||||
// accelerometer spams input thread
|
||||
SDL2.SDL.SDL_SetHint(SDL2.SDL.SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0");
|
||||
SDL3.SDL_SetHint(SDL3.SDL_HINT_ANDROID_TRAP_BACK_BUTTON, "1"u8);
|
||||
|
||||
// hints are here because they don't apply well in another location such as SDL2Window
|
||||
|
||||
@@ -99,6 +98,9 @@ namespace osu.Framework.Android
|
||||
|
||||
protected override void OnCreate(Bundle? savedInstanceState)
|
||||
{
|
||||
Debug.Assert(RuntimeInfo.EntryAssembly.IsNull(), "RuntimeInfo.EntryAssembly should be null on Android and therefore needs to be manually updated.");
|
||||
RuntimeInfo.EntryAssembly = GetType().Assembly;
|
||||
|
||||
// The default current directory on android is '/'.
|
||||
// On some devices '/' maps to the app data directory. On others it maps to the root of the internal storage.
|
||||
// In order to have a consistent current directory on all devices the full path of the app data directory is set as the current directory.
|
||||
|
||||
@@ -10,6 +10,7 @@ using osu.Framework.Android.Graphics.Textures;
|
||||
using osu.Framework.Android.Graphics.Video;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.Graphics.Video;
|
||||
@@ -20,7 +21,7 @@ using Uri = Android.Net.Uri;
|
||||
|
||||
namespace osu.Framework.Android
|
||||
{
|
||||
public class AndroidGameHost : SDL2GameHost
|
||||
public class AndroidGameHost : SDL3GameHost
|
||||
{
|
||||
private readonly AndroidGameActivity activity;
|
||||
|
||||
@@ -56,11 +57,9 @@ namespace osu.Framework.Android
|
||||
|
||||
public override Storage GetStorage(string path) => new AndroidStorage(path, this);
|
||||
|
||||
public override IEnumerable<string> UserStoragePaths => new[]
|
||||
{
|
||||
public override IEnumerable<string> UserStoragePaths
|
||||
// not null as internal "external storage" is always available.
|
||||
Application.Context.GetExternalFilesDir(string.Empty).AsNonNull().ToString(),
|
||||
};
|
||||
=> Application.Context.GetExternalFilesDir(string.Empty).AsNonNull().ToString().Yield();
|
||||
|
||||
public override bool OpenFileExternally(string filename) => false;
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace osu.Framework.Android
|
||||
|
||||
public BindableSafeArea SafeAreaPadding { get; } = new BindableSafeArea();
|
||||
|
||||
public AndroidGameSurface(AndroidGameActivity activity, Context context)
|
||||
public AndroidGameSurface(AndroidGameActivity activity, Context? context)
|
||||
: base(context)
|
||||
{
|
||||
init();
|
||||
|
||||
@@ -6,7 +6,7 @@ using osu.Framework.Platform;
|
||||
|
||||
namespace osu.Framework.Android
|
||||
{
|
||||
internal class AndroidGameWindow : SDL2Window
|
||||
internal class AndroidGameWindow : SDL3Window
|
||||
{
|
||||
public override IntPtr DisplayHandle => AndroidGameActivity.Surface.NativeSurface?.Handle ?? IntPtr.Zero;
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<PackageTags>osu game framework</PackageTags>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\SDL2-CS\SDL2-CS-Android\SDL2-CS-Android.csproj" />
|
||||
<ProjectReference Include="..\..\SDL3-CS\SDL3-CS-Android\SDL3-CS-Android.csproj" />
|
||||
<ProjectReference Include="..\osu.Framework\osu.Framework.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -11,15 +11,27 @@ namespace osu.Framework.Benchmarks
|
||||
{
|
||||
private readonly BindableInt source1 = new BindableInt();
|
||||
private readonly BindableInt source2 = new BindableInt();
|
||||
private readonly AggregateBindable<int> boundAggregate = new AggregateBindable<int>(((i, j) => i + j));
|
||||
private readonly AggregateBindable<int> aggregate = new AggregateBindable<int>(((i, j) => i + j));
|
||||
|
||||
[GlobalSetup]
|
||||
public void GlobalSetup()
|
||||
{
|
||||
boundAggregate.AddSource(source1);
|
||||
boundAggregate.AddSource(source2);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void AggregateRecalculation()
|
||||
public void AddRemoveSource()
|
||||
{
|
||||
var aggregate = new AggregateBindable<int>(((i, j) => i + j));
|
||||
|
||||
aggregate.AddSource(source1);
|
||||
aggregate.AddSource(source2);
|
||||
aggregate.RemoveAllSources();
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void SetValue()
|
||||
{
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
source1.Value = i;
|
||||
|
||||
131
osu.Framework.Benchmarks/BenchmarkEventList.cs
Normal file
131
osu.Framework.Benchmarks/BenchmarkEventList.cs
Normal file
@@ -0,0 +1,131 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using osu.Framework.Graphics.Rendering.Deferred.Allocation;
|
||||
using osu.Framework.Graphics.Rendering.Deferred.Events;
|
||||
|
||||
namespace osu.Framework.Benchmarks
|
||||
{
|
||||
public class BenchmarkEventList
|
||||
{
|
||||
// Used for benchmark-local testing.
|
||||
private ResourceAllocator localAllocator = null!;
|
||||
private List<RenderEvent> localEventList = null!;
|
||||
|
||||
// Used for benchmark-static testing.
|
||||
// 0: Basic events
|
||||
// 1: Events with data
|
||||
// 2: Mixed events
|
||||
private readonly (ResourceAllocator allocator, List<RenderEvent> list)[] staticItems = new (ResourceAllocator allocator, List<RenderEvent> list)[3];
|
||||
|
||||
[GlobalSetup]
|
||||
public void GlobalSetup()
|
||||
{
|
||||
localAllocator = new ResourceAllocator();
|
||||
localEventList = new List<RenderEvent>();
|
||||
|
||||
for (int i = 0; i < staticItems.Length; i++)
|
||||
{
|
||||
ResourceAllocator allocator = new ResourceAllocator();
|
||||
staticItems[i] = (allocator, new List<RenderEvent>());
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10000; i++)
|
||||
{
|
||||
staticItems[0].list.Add(RenderEvent.Init(new FlushEvent(new ResourceReference(1), 10)));
|
||||
staticItems[1].list.Add(RenderEvent.Init(new AddPrimitiveToBatchEvent(new ResourceReference(0), staticItems[1].allocator.AllocateRegion(1024))));
|
||||
staticItems[2].list.Add(i % 2 == 0
|
||||
? RenderEvent.Init(new FlushEvent(new ResourceReference(1), 10))
|
||||
: RenderEvent.Init(new AddPrimitiveToBatchEvent(new ResourceReference(0), staticItems[2].allocator.AllocateRegion(1024))));
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void Write()
|
||||
{
|
||||
localAllocator.NewFrame();
|
||||
|
||||
for (int i = 0; i < 10000; i++)
|
||||
localEventList.Add(RenderEvent.Init(new FlushEvent()));
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void WriteWithData()
|
||||
{
|
||||
localAllocator.NewFrame();
|
||||
|
||||
for (int i = 0; i < 10000; i++)
|
||||
localEventList.Add(RenderEvent.Init(new AddPrimitiveToBatchEvent(new ResourceReference(0), localAllocator.AllocateRegion(1024))));
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public int Read()
|
||||
{
|
||||
int totalVertices = 0;
|
||||
|
||||
foreach (var renderEvent in staticItems[0].list)
|
||||
{
|
||||
switch (renderEvent.Type)
|
||||
{
|
||||
case RenderEventType.Flush:
|
||||
FlushEvent e = (FlushEvent)renderEvent;
|
||||
totalVertices += e.VertexCount;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return totalVertices;
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public int ReadWithData()
|
||||
{
|
||||
int data = 0;
|
||||
|
||||
foreach (var renderEvent in staticItems[1].list)
|
||||
{
|
||||
switch (renderEvent.Type)
|
||||
{
|
||||
case RenderEventType.AddPrimitiveToBatch:
|
||||
AddPrimitiveToBatchEvent e = (AddPrimitiveToBatchEvent)renderEvent;
|
||||
foreach (byte b in staticItems[1].allocator.GetRegion(e.Memory))
|
||||
data += b;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public int ReadMixed()
|
||||
{
|
||||
int data = 0;
|
||||
|
||||
foreach (var renderEvent in staticItems[2].list)
|
||||
{
|
||||
switch (renderEvent.Type)
|
||||
{
|
||||
case RenderEventType.Flush:
|
||||
{
|
||||
FlushEvent e = (FlushEvent)renderEvent;
|
||||
data += e.VertexCount;
|
||||
break;
|
||||
}
|
||||
|
||||
case RenderEventType.AddPrimitiveToBatch:
|
||||
{
|
||||
AddPrimitiveToBatchEvent e = (AddPrimitiveToBatchEvent)renderEvent;
|
||||
foreach (byte b in staticItems[2].allocator.GetRegion(e.Memory))
|
||||
data += b;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -19,13 +19,16 @@ FFMPEG_FLAGS+=(
|
||||
|
||||
pushd . > /dev/null
|
||||
prep_ffmpeg linux-x64
|
||||
# Apply patch from upstream to fix errors with new binutils versions:
|
||||
# Ticket: https://fftrac-bg.ffmpeg.org/ticket/10405
|
||||
# This patch should be removed when FFmpeg is updated to >=6.1
|
||||
patch -p1 < "$SCRIPT_PATH/fix-binutils-2.41.patch"
|
||||
build_ffmpeg
|
||||
popd > /dev/null
|
||||
|
||||
# gcc creates multiple symlinks per .so file for versioning.
|
||||
# We want to delete the symlinks to prevent weird behaviour with GitHub actions.
|
||||
# We delete the symlinks and rename the real files to include the major library version
|
||||
rm linux-x64/*.so
|
||||
for f in linux-x64/*.so.*.*.*; do
|
||||
mv -v "$f" "${f%.*.*.*}"
|
||||
mv -vf "$f" "${f%.*.*}"
|
||||
done
|
||||
rm linux-x64/*.so.*
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
From effadce6c756247ea8bae32dc13bb3e6f464f0eb Mon Sep 17 00:00:00 2001
|
||||
From: =?utf8?q?R=C3=A9mi=20Denis-Courmont?= <remi@remlab.net>
|
||||
Date: Sun, 16 Jul 2023 18:18:02 +0300
|
||||
Subject: [PATCH] avcodec/x86/mathops: clip constants used with shift
|
||||
instructions within inline assembly
|
||||
|
||||
Fixes assembling with binutil as >= 2.41
|
||||
|
||||
Signed-off-by: James Almer <jamrial@gmail.com>
|
||||
---
|
||||
libavcodec/x86/mathops.h | 26 +++++++++++++++++++++++---
|
||||
1 file changed, 23 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/libavcodec/x86/mathops.h b/libavcodec/x86/mathops.h
|
||||
index 6298f5ed19..ca7e2dffc1 100644
|
||||
--- a/libavcodec/x86/mathops.h
|
||||
+++ b/libavcodec/x86/mathops.h
|
||||
@@ -35,12 +35,20 @@
|
||||
static av_always_inline av_const int MULL(int a, int b, unsigned shift)
|
||||
{
|
||||
int rt, dummy;
|
||||
+ if (__builtin_constant_p(shift))
|
||||
__asm__ (
|
||||
"imull %3 \n\t"
|
||||
"shrdl %4, %%edx, %%eax \n\t"
|
||||
:"=a"(rt), "=d"(dummy)
|
||||
- :"a"(a), "rm"(b), "ci"((uint8_t)shift)
|
||||
+ :"a"(a), "rm"(b), "i"(shift & 0x1F)
|
||||
);
|
||||
+ else
|
||||
+ __asm__ (
|
||||
+ "imull %3 \n\t"
|
||||
+ "shrdl %4, %%edx, %%eax \n\t"
|
||||
+ :"=a"(rt), "=d"(dummy)
|
||||
+ :"a"(a), "rm"(b), "c"((uint8_t)shift)
|
||||
+ );
|
||||
return rt;
|
||||
}
|
||||
|
||||
@@ -113,19 +121,31 @@ __asm__ volatile(\
|
||||
// avoid +32 for shift optimization (gcc should do that ...)
|
||||
#define NEG_SSR32 NEG_SSR32
|
||||
static inline int32_t NEG_SSR32( int32_t a, int8_t s){
|
||||
+ if (__builtin_constant_p(s))
|
||||
__asm__ ("sarl %1, %0\n\t"
|
||||
: "+r" (a)
|
||||
- : "ic" ((uint8_t)(-s))
|
||||
+ : "i" (-s & 0x1F)
|
||||
);
|
||||
+ else
|
||||
+ __asm__ ("sarl %1, %0\n\t"
|
||||
+ : "+r" (a)
|
||||
+ : "c" ((uint8_t)(-s))
|
||||
+ );
|
||||
return a;
|
||||
}
|
||||
|
||||
#define NEG_USR32 NEG_USR32
|
||||
static inline uint32_t NEG_USR32(uint32_t a, int8_t s){
|
||||
+ if (__builtin_constant_p(s))
|
||||
__asm__ ("shrl %1, %0\n\t"
|
||||
: "+r" (a)
|
||||
- : "ic" ((uint8_t)(-s))
|
||||
+ : "i" (-s & 0x1F)
|
||||
);
|
||||
+ else
|
||||
+ __asm__ ("shrl %1, %0\n\t"
|
||||
+ : "+r" (a)
|
||||
+ : "c" ((uint8_t)(-s))
|
||||
+ );
|
||||
return a;
|
||||
}
|
||||
|
||||
--
|
||||
2.30.2
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="TemplateGame.Desktop" type="DotNetProject" factoryName=".NET Project">
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/TemplateGame.Desktop/bin/Debug/net5.0/TemplateGame.dll" />
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/TemplateGame.Desktop/bin/Debug/net8.0/TemplateGame.dll" />
|
||||
<option name="PROGRAM_PARAMETERS" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/TemplateGame.Desktop/bin/Debug/net5.0" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/TemplateGame.Desktop/bin/Debug/net8.0" />
|
||||
<option name="PASS_PARENT_ENVS" value="1" />
|
||||
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
||||
<option name="USE_MONO" value="0" />
|
||||
@@ -12,7 +12,7 @@
|
||||
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
||||
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
||||
<option name="PROJECT_KIND" value="DotNetCore" />
|
||||
<option name="PROJECT_TFM" value="net5.0" />
|
||||
<option name="PROJECT_TFM" value="net8.0" />
|
||||
<method v="2">
|
||||
<option name="Build" enabled="true" />
|
||||
</method>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="TemplateGame.Tests" type="DotNetProject" factoryName=".NET Project">
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/TemplateGame.Game.Tests/bin/Debug/net5.0/TemplateGame.Game.Tests.dll" />
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/TemplateGame.Game.Tests/bin/Debug/net8.0/TemplateGame.Game.Tests.dll" />
|
||||
<option name="PROGRAM_PARAMETERS" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/TemplateGame.Game.Tests/bin/Debug/net5.0" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/TemplateGame.Game.Tests/bin/Debug/net8.0" />
|
||||
<option name="PASS_PARENT_ENVS" value="1" />
|
||||
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
||||
<option name="USE_MONO" value="0" />
|
||||
@@ -12,7 +12,7 @@
|
||||
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
||||
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
||||
<option name="PROJECT_KIND" value="DotNetCore" />
|
||||
<option name="PROJECT_TFM" value="net5.0" />
|
||||
<option name="PROJECT_TFM" value="net8.0" />
|
||||
<method v="2">
|
||||
<option name="Build" enabled="true" />
|
||||
</method>
|
||||
|
||||
@@ -9,13 +9,13 @@
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/TemplateGame.Game.Tests/bin/Debug/net6.0/TemplateGame.Game.Tests.dll",
|
||||
"${workspaceRoot}/TemplateGame.Game.Tests/bin/Debug/net8.0/TemplateGame.Game.Tests.dll",
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build (Tests, Debug)",
|
||||
"linux": {
|
||||
"env": {
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/TemplateGame.Game.Tests/bin/Debug/net6.0:${env:LD_LIBRARY_PATH}"
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/TemplateGame.Game.Tests/bin/Debug/net8.0:${env:LD_LIBRARY_PATH}"
|
||||
}
|
||||
},
|
||||
"console": "internalConsole"
|
||||
@@ -26,13 +26,13 @@
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/TemplateGame.Game.Tests/bin/Release/net6.0/TemplateGame.Game.Tests.dll",
|
||||
"${workspaceRoot}/TemplateGame.Game.Tests/bin/Release/net8.0/TemplateGame.Game.Tests.dll",
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build (Tests, Release)",
|
||||
"linux": {
|
||||
"env": {
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/TemplateGame.Game.Tests/bin/Release/net6.0:${env:LD_LIBRARY_PATH}"
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/TemplateGame.Game.Tests/bin/Release/net8.0:${env:LD_LIBRARY_PATH}"
|
||||
}
|
||||
},
|
||||
"console": "internalConsole"
|
||||
@@ -43,13 +43,13 @@
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/TemplateGame.Desktop/bin/Debug/net6.0/TemplateGame.dll",
|
||||
"${workspaceRoot}/TemplateGame.Desktop/bin/Debug/net8.0/TemplateGame.dll",
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build (Desktop, Debug)",
|
||||
"linux": {
|
||||
"env": {
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/TemplateGame.Desktop/bin/Debug/net6.0:${env:LD_LIBRARY_PATH}"
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/TemplateGame.Desktop/bin/Debug/net8.0:${env:LD_LIBRARY_PATH}"
|
||||
}
|
||||
},
|
||||
"console": "internalConsole"
|
||||
@@ -60,13 +60,13 @@
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/TemplateGame.Desktop/bin/Debug/net6.0/TemplateGame.dll",
|
||||
"${workspaceRoot}/TemplateGame.Desktop/bin/Debug/net8.0/TemplateGame.dll",
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build (Desktop, Release)",
|
||||
"linux": {
|
||||
"env": {
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/TemplateGame.Desktop/bin/Debug/net6.0:${env:LD_LIBRARY_PATH}"
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/TemplateGame.Desktop/bin/Debug/net8.0:${env:LD_LIBRARY_PATH}"
|
||||
}
|
||||
},
|
||||
"console": "internalConsole"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="FlappyDon.Desktop" type="DotNetProject" factoryName=".NET Project">
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/FlappyDon.Desktop/bin/Debug/net5.0/FlappyDon.dll" />
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/FlappyDon.Desktop/bin/Debug/net8.0/FlappyDon.dll" />
|
||||
<option name="PROGRAM_PARAMETERS" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/FlappyDon.Desktop/bin/Debug/net5.0" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/FlappyDon.Desktop/bin/Debug/net8.0" />
|
||||
<option name="PASS_PARENT_ENVS" value="1" />
|
||||
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
||||
<option name="USE_MONO" value="0" />
|
||||
@@ -12,7 +12,7 @@
|
||||
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
||||
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
||||
<option name="PROJECT_KIND" value="DotNetCore" />
|
||||
<option name="PROJECT_TFM" value="net5.0" />
|
||||
<option name="PROJECT_TFM" value="net8.0" />
|
||||
<method v="2">
|
||||
<option name="Build" enabled="true" />
|
||||
</method>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="FlappyDon.Tests" type="DotNetProject" factoryName=".NET Project">
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/FlappyDon.Game.Tests/bin/Debug/net5.0/FlappyDon.Game.Tests.dll" />
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/FlappyDon.Game.Tests/bin/Debug/net8.0/FlappyDon.Game.Tests.dll" />
|
||||
<option name="PROGRAM_PARAMETERS" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/FlappyDon.Game.Tests/bin/Debug/net5.0" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/FlappyDon.Game.Tests/bin/Debug/net8.0" />
|
||||
<option name="PASS_PARENT_ENVS" value="1" />
|
||||
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
||||
<option name="USE_MONO" value="0" />
|
||||
@@ -12,7 +12,7 @@
|
||||
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
||||
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
||||
<option name="PROJECT_KIND" value="DotNetCore" />
|
||||
<option name="PROJECT_TFM" value="net5.0" />
|
||||
<option name="PROJECT_TFM" value="net8.0" />
|
||||
<method v="2">
|
||||
<option name="Build" enabled="true" />
|
||||
</method>
|
||||
|
||||
@@ -9,13 +9,13 @@
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/FlappyDon.Game.Tests/bin/Debug/net6.0/FlappyDon.Game.Tests.dll",
|
||||
"${workspaceRoot}/FlappyDon.Game.Tests/bin/Debug/net8.0/FlappyDon.Game.Tests.dll",
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build (Tests, Debug)",
|
||||
"linux": {
|
||||
"env": {
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/FlappyDon.Game.Tests/bin/Debug/net6.0:${env:LD_LIBRARY_PATH}"
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/FlappyDon.Game.Tests/bin/Debug/net8.0:${env:LD_LIBRARY_PATH}"
|
||||
}
|
||||
},
|
||||
"console": "internalConsole"
|
||||
@@ -26,13 +26,13 @@
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/FlappyDon.Game.Tests/bin/Release/net6.0/FlappyDon.Game.Tests.dll",
|
||||
"${workspaceRoot}/FlappyDon.Game.Tests/bin/Release/net8.0/FlappyDon.Game.Tests.dll",
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build (Tests, Release)",
|
||||
"linux": {
|
||||
"env": {
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/FlappyDon.Game.Tests/bin/Release/net6.0:${env:LD_LIBRARY_PATH}"
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/FlappyDon.Game.Tests/bin/Release/net8.0:${env:LD_LIBRARY_PATH}"
|
||||
}
|
||||
},
|
||||
"console": "internalConsole"
|
||||
@@ -43,13 +43,13 @@
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/FlappyDon.Desktop/bin/Debug/net6.0/FlappyDon.dll",
|
||||
"${workspaceRoot}/FlappyDon.Desktop/bin/Debug/net8.0/FlappyDon.dll",
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build (Desktop, Debug)",
|
||||
"linux": {
|
||||
"env": {
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/FlappyDon.Desktop/bin/Debug/net6.0:${env:LD_LIBRARY_PATH}"
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/FlappyDon.Desktop/bin/Debug/net8.0:${env:LD_LIBRARY_PATH}"
|
||||
}
|
||||
},
|
||||
"console": "internalConsole"
|
||||
@@ -60,13 +60,13 @@
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/FlappyDon.Desktop/bin/Debug/net6.0/FlappyDon.dll",
|
||||
"${workspaceRoot}/FlappyDon.Desktop/bin/Debug/net8.0/FlappyDon.dll",
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build (Desktop, Release)",
|
||||
"linux": {
|
||||
"env": {
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/FlappyDon.Desktop/bin/Debug/net6.0:${env:LD_LIBRARY_PATH}"
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/FlappyDon.Desktop/bin/Debug/net8.0:${env:LD_LIBRARY_PATH}"
|
||||
}
|
||||
},
|
||||
"console": "internalConsole"
|
||||
|
||||
@@ -121,6 +121,14 @@ namespace osu.Framework.Tests.Visual.Containers
|
||||
assertSpriteTextCount(0);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestWordSplittingEdgeCases()
|
||||
{
|
||||
AddStep("set latin text", () => textContainer.Text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer mattis eu turpis vitae posuere. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Etiam mauris nibh, faucibus maximus ornare eu, ultrices ut ipsum. Proin rhoncus, nunc et faucibus pretium, nisl nunc dapibus massa, et scelerisque nibh ligula id odio. Praesent dapibus ex sed nunc egestas, in placerat risus mattis. Nulla sed ligula velit. Vestibulum auctor porta eros et condimentum. Etiam laoreet nunc nec lacinia pulvinar. Mauris hendrerit, mi at aliquet condimentum, ex ex cursus dolor, non porta erat eros id justo. Cras malesuada tincidunt nunc, at tincidunt risus eleifend id. Maecenas hendrerit venenatis mi et lobortis. Etiam sem tortor, elementum eget lacus non, porta tristique quam. Morbi sed lacinia odio. Phasellus ut pretium nunc. Fusce vitae mollis magna, vel scelerisque dui. ");
|
||||
AddStep("set url", () => textContainer.Text = "https://osu.ppy.sh/home/news/2024-03-27-osutaiko-world-cup-2024-round-of-32-recap");
|
||||
AddStep("set cjk text", () => textContainer.Text = "日本の桜は世界中から観光客を引きつけています。寿司は美味しい伝統的な日本食です。東京タワーは景色が美しいです。速い新幹線は、便利な交通手段です。富士山は、その美しさと完全な形状で知られています。日本文化は、優雅さと繊細さを象徴しています。抹茶は特別な日本の茶です。着物は、伝統的な日本の衣装で、特別な場面でよく着用されます。");
|
||||
}
|
||||
|
||||
private void assertSpriteTextCount(int count)
|
||||
=> AddAssert($"text flow has {count} sprite texts", () => textContainer.ChildrenOfType<SpriteText>().Count() == count);
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ namespace osu.Framework.Tests.Visual.Graphics
|
||||
Size = new Vector2(circle_radius),
|
||||
RelativePositionAxes = Axes.Both,
|
||||
Position = new Vector2(xPos, yPos),
|
||||
Current = { Value = 1 }
|
||||
Progress = 1
|
||||
});
|
||||
|
||||
circlesContainerBuffered.Add(new CircularProgress
|
||||
@@ -91,7 +91,7 @@ namespace osu.Framework.Tests.Visual.Graphics
|
||||
Size = new Vector2(circle_radius),
|
||||
RelativePositionAxes = Axes.Both,
|
||||
Position = new Vector2(xPos, yPos),
|
||||
Current = { Value = 1 }
|
||||
Progress = 1
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,23 +20,37 @@ namespace osu.Framework.Tests.Visual.Input
|
||||
{
|
||||
public partial class TestSceneTabletInput : FrameworkTestScene
|
||||
{
|
||||
private readonly FillFlowContainer contentFlow;
|
||||
private readonly SpriteText tabletInfo;
|
||||
private readonly TabletAreaVisualiser areaVisualizer;
|
||||
private readonly FillFlowContainer penButtonFlow;
|
||||
private readonly FillFlowContainer auxButtonFlow;
|
||||
private IBindable<TabletInfo?> tablet = new Bindable<TabletInfo?>();
|
||||
private IBindable<bool> tabletEnabled = new Bindable<bool>();
|
||||
|
||||
[Resolved]
|
||||
private FrameworkConfigManager frameworkConfigManager { get; set; } = null!;
|
||||
|
||||
public TestSceneTabletInput()
|
||||
{
|
||||
var penButtonFlow = new FillFlowContainer
|
||||
Child = new FillFlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
};
|
||||
|
||||
var auxButtonFlow = new FillFlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Vertical,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
tabletInfo = new SpriteText(),
|
||||
areaVisualizer = new TabletAreaVisualiser(),
|
||||
penButtonFlow = new FillFlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
},
|
||||
auxButtonFlow = new FillFlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
@@ -44,13 +58,6 @@ namespace osu.Framework.Tests.Visual.Input
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
auxButtonFlow.Add(new AuxiliaryButtonHandler(i));
|
||||
|
||||
Child = contentFlow = new FillFlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Vertical,
|
||||
Children = new[] { penButtonFlow, auxButtonFlow }
|
||||
};
|
||||
}
|
||||
|
||||
[Resolved]
|
||||
@@ -64,9 +71,17 @@ namespace osu.Framework.Tests.Visual.Input
|
||||
|
||||
if (tabletHandler != null)
|
||||
{
|
||||
areaVisualizer.AreaSize.BindTo(tabletHandler.AreaSize);
|
||||
areaVisualizer.AreaOffset.BindTo(tabletHandler.AreaOffset);
|
||||
|
||||
tablet = tabletHandler.Tablet.GetBoundCopy();
|
||||
tablet.BindValueChanged(_ => updateState(), true);
|
||||
|
||||
tabletEnabled = tabletHandler.Enabled.GetBoundCopy();
|
||||
tabletEnabled.BindValueChanged(_ => updateState(), true);
|
||||
|
||||
AddToggleStep("toggle tablet handling", t => tabletHandler.Enabled.Value = t);
|
||||
|
||||
contentFlow.Insert(-1, new TabletAreaVisualiser(tabletHandler));
|
||||
AddSliderStep("change width", 0, 1, 1f,
|
||||
width => tabletHandler.AreaSize.Value = new Vector2(
|
||||
tabletHandler.AreaSize.Default.X * width,
|
||||
@@ -92,20 +107,25 @@ namespace osu.Framework.Tests.Visual.Input
|
||||
enabled ? ConfineMouseMode.Always : ConfineMouseMode.Never));
|
||||
}
|
||||
|
||||
private void updateState()
|
||||
{
|
||||
if (tabletEnabled.Value)
|
||||
tabletInfo.Text = tablet.Value != null ? $"Name: {tablet.Value.Name} Size: {tablet.Value.Size}" : "No tablet detected!";
|
||||
else
|
||||
tabletInfo.Text = "Tablet input is disabled.";
|
||||
|
||||
areaVisualizer.Alpha = penButtonFlow.Alpha = auxButtonFlow.Alpha = tablet.Value != null && tabletEnabled.Value ? 1 : 0;
|
||||
}
|
||||
|
||||
private partial class TabletAreaVisualiser : CompositeDrawable
|
||||
{
|
||||
private readonly OpenTabletDriverHandler handler;
|
||||
public readonly Bindable<Vector2> AreaSize = new Bindable<Vector2>();
|
||||
public readonly Bindable<Vector2> AreaOffset = new Bindable<Vector2>();
|
||||
|
||||
private Box fullArea = null!;
|
||||
private Container activeArea = null!;
|
||||
|
||||
private Bindable<Vector2> areaSize = null!;
|
||||
private Bindable<Vector2> areaOffset = null!;
|
||||
|
||||
public TabletAreaVisualiser(OpenTabletDriverHandler handler)
|
||||
{
|
||||
this.handler = handler;
|
||||
}
|
||||
private SpriteText areaText = null!;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
@@ -119,8 +139,8 @@ namespace osu.Framework.Tests.Visual.Input
|
||||
{
|
||||
fullArea = new Box
|
||||
{
|
||||
Width = handler.AreaSize.Default.X,
|
||||
Height = handler.AreaSize.Default.Y,
|
||||
Width = AreaSize.Default.X,
|
||||
Height = AreaSize.Default.Y,
|
||||
Colour = FrameworkColour.GreenDark
|
||||
},
|
||||
activeArea = new Container
|
||||
@@ -133,14 +153,13 @@ namespace osu.Framework.Tests.Visual.Input
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = FrameworkColour.YellowGreen
|
||||
},
|
||||
new SpriteText
|
||||
areaText = new SpriteText
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Text = "Active area"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -149,13 +168,15 @@ namespace osu.Framework.Tests.Visual.Input
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
areaSize = handler.AreaSize.GetBoundCopy();
|
||||
areaSize.BindValueChanged(size => activeArea.Size = size.NewValue, true);
|
||||
areaSize.DefaultChanged += fullSize => fullArea.Size = fullSize.NewValue;
|
||||
fullArea.Size = areaSize.Default;
|
||||
AreaSize.BindValueChanged(size =>
|
||||
{
|
||||
activeArea.Size = size.NewValue;
|
||||
areaText.Text = $"Active area: {size.NewValue}";
|
||||
}, true);
|
||||
AreaSize.DefaultChanged += fullSize => fullArea.Size = fullSize.NewValue;
|
||||
fullArea.Size = AreaSize.Default;
|
||||
|
||||
areaOffset = handler.AreaOffset.GetBoundCopy();
|
||||
areaOffset.BindValueChanged(offset => activeArea.Position = offset.NewValue, true);
|
||||
AreaOffset.BindValueChanged(offset => activeArea.Position = offset.NewValue, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace osu.Framework.Tests.Visual.Performance
|
||||
base.Update();
|
||||
|
||||
foreach (var p in Flow.OfType<CircularProgress>())
|
||||
p.Current.Value = (p.Current.Value + (Time.Elapsed * RNG.NextSingle()) / 1000) % 1;
|
||||
p.Progress = (p.Progress + (Time.Elapsed * RNG.NextSingle()) / 1000) % 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace osu.Framework.Tests.Visual.Platform
|
||||
private readonly SpriteText currentWindowMode = new SpriteText();
|
||||
private readonly SpriteText currentDisplay = new SpriteText();
|
||||
|
||||
private SDL2Window? window;
|
||||
private SDL3Window? window;
|
||||
private readonly Bindable<WindowMode> windowMode = new Bindable<WindowMode>();
|
||||
|
||||
public TestSceneBorderless()
|
||||
@@ -57,7 +57,7 @@ namespace osu.Framework.Tests.Visual.Platform
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(FrameworkConfigManager config, GameHost host)
|
||||
{
|
||||
window = host.Window as SDL2Window;
|
||||
window = host.Window as SDL3Window;
|
||||
config.BindWith(FrameworkSetting.WindowMode, windowMode);
|
||||
|
||||
windowMode.BindValueChanged(mode => currentWindowMode.Text = $"Window Mode: {mode.NewValue}", true);
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace osu.Framework.Tests.Visual.Platform
|
||||
|
||||
WindowMode startingMode = getWindowModeForState(startingState);
|
||||
|
||||
// this shouldn't be necessary, but SDL2DesktopWindow doesn't set the config WindowMode when changing the WindowState only.
|
||||
// this shouldn't be necessary, but SDL3DesktopWindow doesn't set the config WindowMode when changing the WindowState only.
|
||||
AddStep($"switch to {startingMode}", () => window.WindowMode.Value = startingMode);
|
||||
|
||||
AddStep($"switch to {startingState}", () => window.WindowState = startingState);
|
||||
|
||||
85
osu.Framework.Tests/Visual/Platform/TestSceneDebugUtils.cs
Normal file
85
osu.Framework.Tests/Visual/Platform/TestSceneDebugUtils.cs
Normal file
@@ -0,0 +1,85 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Development;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Framework.Platform;
|
||||
|
||||
namespace osu.Framework.Tests.Visual.Platform
|
||||
{
|
||||
public partial class TestSceneDebugUtils : FrameworkTestScene
|
||||
{
|
||||
private readonly TextFlowContainer textFlow;
|
||||
|
||||
private bool isHeadlessTestRun;
|
||||
|
||||
public TestSceneDebugUtils()
|
||||
{
|
||||
Child = textFlow = new TextFlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(GameHost host)
|
||||
{
|
||||
isHeadlessTestRun = host.Window == null;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void LogStatics()
|
||||
{
|
||||
AddStep("log DebugUtils statics", () =>
|
||||
{
|
||||
textFlow.Clear();
|
||||
log(DebugUtils.IsNUnitRunning);
|
||||
log(DebugUtils.IsDebugBuild);
|
||||
log(RuntimeInfo.EntryAssembly);
|
||||
#pragma warning disable RS0030
|
||||
log(Assembly.GetEntryAssembly());
|
||||
#pragma warning restore RS0030
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestIsNUnitRunning()
|
||||
{
|
||||
AddAssert("check IsNUnitRunning", () => DebugUtils.IsNUnitRunning, () => Is.EqualTo(isHeadlessTestRun));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestIsDebugBuild()
|
||||
{
|
||||
AddAssert("check IsDebugBuild", () => DebugUtils.IsDebugBuild, () => Is.EqualTo(
|
||||
#if DEBUG
|
||||
true
|
||||
#else
|
||||
false
|
||||
#endif
|
||||
));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestEntryAssembly()
|
||||
{
|
||||
AddAssert("check RuntimeInfo.EntryAssembly", () => RuntimeInfo.EntryAssembly.FullName, () => Does.StartWith("osu.Framework.Tests"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs the <paramref name="name"/> and <paramref name="value"/> on the screen and in the logs.
|
||||
/// </summary>
|
||||
private void log<T>(T value, [CallerArgumentExpression("value")] string? name = null)
|
||||
{
|
||||
string text = $"{name}: {value}";
|
||||
textFlow.AddParagraph(text);
|
||||
Logger.Log(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -129,7 +129,7 @@ namespace osu.Framework.Tests.Visual.Platform
|
||||
if (window.SupportedWindowModes.Contains(WindowMode.Fullscreen))
|
||||
{
|
||||
AddStep("change to fullscreen", () => windowMode.Value = WindowMode.Fullscreen);
|
||||
AddAssert("window position updated", () => ((SDL2Window)window).Position, () => Is.EqualTo(window.CurrentDisplayBindable.Value.Bounds.Location));
|
||||
AddAssert("window position updated", () => ((SDL3Window)window).Position, () => Is.EqualTo(window.CurrentDisplayBindable.Value.Bounds.Location));
|
||||
testResolution(1920, 1080);
|
||||
testResolution(1280, 960);
|
||||
testResolution(9999, 9999);
|
||||
|
||||
@@ -31,12 +31,12 @@ namespace osu.Framework.Tests.Visual.Platform
|
||||
[Resolved]
|
||||
private FrameworkConfigManager config { get; set; }
|
||||
|
||||
private SDL2Window sdlWindow;
|
||||
private SDL3Window sdlWindow;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
sdlWindow = (SDL2Window)host.Window;
|
||||
sdlWindow = (SDL3Window)host.Window;
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new FillFlowContainer
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace osu.Framework.Tests.Visual.Platform
|
||||
private static readonly Color4 window_fill = new Color4(95, 113, 197, 255);
|
||||
private static readonly Color4 window_stroke = new Color4(36, 59, 166, 255);
|
||||
|
||||
private SDL2Window? window;
|
||||
private SDL3Window? window;
|
||||
private readonly Bindable<WindowMode> windowMode = new Bindable<WindowMode>();
|
||||
private readonly Bindable<Display> currentDisplay = new Bindable<Display>();
|
||||
|
||||
@@ -90,7 +90,7 @@ namespace osu.Framework.Tests.Visual.Platform
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(FrameworkConfigManager config, GameHost host)
|
||||
{
|
||||
window = host.Window as SDL2Window;
|
||||
window = host.Window as SDL3Window;
|
||||
config.BindWith(FrameworkSetting.WindowMode, windowMode);
|
||||
|
||||
if (window != null)
|
||||
|
||||
@@ -145,23 +145,23 @@ namespace osu.Framework.Tests.Visual.UserInterface
|
||||
switch (rotateMode)
|
||||
{
|
||||
case 0:
|
||||
clock.Current.Value = Time.Current % (period * 2) / period - 1;
|
||||
clock.Progress = Time.Current % (period * 2) / period - 1;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
clock.Current.Value = Time.Current % period / period;
|
||||
clock.Progress = Time.Current % period / period;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
clock.Current.Value = Time.Current % period / period - 1;
|
||||
clock.Progress = Time.Current % period / period - 1;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
clock.Current.Value = Time.Current % transition_period / transition_period / 5 - 0.1f;
|
||||
clock.Progress = Time.Current % transition_period / transition_period / 5 - 0.1f;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
clock.Current.Value = (Time.Current % transition_period / transition_period / 5 - 0.1f + 2) % 2 - 1;
|
||||
clock.Progress = (Time.Current % transition_period / transition_period / 5 - 0.1f + 2) % 2 - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -245,19 +245,19 @@ namespace osu.Framework.Tests.Visual.UserInterface
|
||||
switch (tf)
|
||||
{
|
||||
case 0:
|
||||
clock.FillTo(0).Then().FillTo(1, 1000).Loop();
|
||||
clock.ProgressTo(0).Then().ProgressTo(1, 1000).Loop();
|
||||
break;
|
||||
|
||||
case 1:
|
||||
clock.FillTo(1).Then().FillTo(0, 1000).Loop();
|
||||
clock.ProgressTo(1).Then().ProgressTo(0, 1000).Loop();
|
||||
break;
|
||||
|
||||
case 2:
|
||||
clock.FillTo(0, 1000).Then().FillTo(1, 1000).Loop();
|
||||
clock.ProgressTo(0, 1000).Then().ProgressTo(1, 1000).Loop();
|
||||
break;
|
||||
|
||||
case 3:
|
||||
clock.FillTo(0).Then().FillTo(1, 1000, Easing.InOutQuart).Loop();
|
||||
clock.ProgressTo(0).Then().ProgressTo(1, 1000, Easing.InOutQuart).Loop();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,9 +86,27 @@ Line below";
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestFencedCode()
|
||||
public void TestIndentedCodeBlock()
|
||||
{
|
||||
AddStep("Markdown Fenced Code", () =>
|
||||
AddStep("Markdown Indented Code Block", () =>
|
||||
{
|
||||
markdownContainer.Text = @"
|
||||
[Escape me]
|
||||
[[Escape me]]
|
||||
|
||||
{{
|
||||
x = ""5"" # This assignment will not output anything
|
||||
x # This expression will print 5
|
||||
x + 1 # This expression will print 6
|
||||
}}
|
||||
";
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestFencedCodeBlock()
|
||||
{
|
||||
AddStep("Markdown Fenced Code Block", () =>
|
||||
{
|
||||
markdownContainer.Text = @"```scriban-html
|
||||
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Framework.Input;
|
||||
using osu.Framework.Testing;
|
||||
using osuTK;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Framework.Tests.Visual.UserInterface
|
||||
{
|
||||
public partial class TestSceneTabControlEvents : ManualInputManagerTestScene
|
||||
{
|
||||
private EventQueuesTabControl tabControl = null!;
|
||||
|
||||
[SetUpSteps]
|
||||
public void SetUpSteps()
|
||||
{
|
||||
AddStep("add tab control", () => Child = tabControl = new EventQueuesTabControl
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Size = new Vector2(150, 40),
|
||||
Items = Enum.GetValues<TestEnum>(),
|
||||
});
|
||||
|
||||
AddAssert("selected tab queue empty", () => tabControl.UserTabSelectionChangedQueue.Count == 0);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestClickSendsEvent()
|
||||
{
|
||||
AddStep("click second tab", () =>
|
||||
{
|
||||
InputManager.MoveMouseTo(this.ChildrenOfType<TabItem<TestEnum>>().ElementAt(1));
|
||||
InputManager.Click(MouseButton.Left);
|
||||
});
|
||||
|
||||
AddAssert("selected tab = second", () => tabControl.Current.Value == TestEnum.Second);
|
||||
AddAssert("selected tab queue has \"second\"", () => tabControl.UserTabSelectionChangedQueue.Dequeue().Value == TestEnum.Second);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestClickSameTabDoesNotSendEvent()
|
||||
{
|
||||
AddAssert("first tab selected", () => tabControl.Current.Value == TestEnum.First);
|
||||
AddStep("click first tab", () =>
|
||||
{
|
||||
InputManager.MoveMouseTo(this.ChildrenOfType<TabItem<TestEnum>>().First());
|
||||
InputManager.Click(MouseButton.Left);
|
||||
});
|
||||
|
||||
AddAssert("first tab still selected", () => tabControl.Current.Value == TestEnum.First);
|
||||
AddAssert("selected tab queue empty", () => tabControl.UserTabSelectionChangedQueue.Count == 0);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSelectItemMethodSendsEvent()
|
||||
{
|
||||
AddStep("call select item", () => tabControl.SelectItem(TestEnum.Second));
|
||||
AddAssert("selected tab queue has \"second\"", () => tabControl.UserTabSelectionChangedQueue.Dequeue().Value == TestEnum.Second);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSwitchTabMethodSendsEvent()
|
||||
{
|
||||
AddStep("set switchable", () => tabControl.IsSwitchable = true);
|
||||
AddStep("call switch tab", () => tabControl.SwitchTab(1));
|
||||
AddAssert("selected tab = second", () => tabControl.Current.Value == TestEnum.Second);
|
||||
AddAssert("selected tab queue has \"second\"", () => tabControl.UserTabSelectionChangedQueue.Dequeue().Value == TestEnum.Second);
|
||||
AddStep("call switch tab", () => tabControl.SwitchTab(-1));
|
||||
AddAssert("selected tab = second", () => tabControl.Current.Value == TestEnum.First);
|
||||
AddAssert("selected tab queue has \"second\"", () => tabControl.UserTabSelectionChangedQueue.Dequeue().Value == TestEnum.First);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSwitchUsingKeyBindingSendsEvent()
|
||||
{
|
||||
AddStep("set switchable", () => tabControl.IsSwitchable = true);
|
||||
AddStep("switch forward", () => InputManager.Keys(PlatformAction.DocumentNext));
|
||||
AddAssert("selected tab = second", () => tabControl.Current.Value == TestEnum.Second);
|
||||
AddAssert("selected tab queue has \"second\"", () => tabControl.UserTabSelectionChangedQueue.Dequeue().Value == TestEnum.Second);
|
||||
AddStep("switch backward", () => InputManager.Keys(PlatformAction.DocumentPrevious));
|
||||
AddAssert("selected tab = second", () => tabControl.Current.Value == TestEnum.First);
|
||||
AddAssert("selected tab queue has \"second\"", () => tabControl.UserTabSelectionChangedQueue.Dequeue().Value == TestEnum.First);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSwitchOnRemovalDoesNotSendEvent()
|
||||
{
|
||||
AddStep("set switchable", () => tabControl.IsSwitchable = true);
|
||||
AddStep("remove first tab", () => tabControl.RemoveItem(TestEnum.First));
|
||||
|
||||
AddAssert("selected tab = second", () => tabControl.Current.Value == TestEnum.Second);
|
||||
AddAssert("selected tab queue still empty", () => tabControl.UserTabSelectionChangedQueue.Count == 0);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestBindableChangeDoesNotSendEvent()
|
||||
{
|
||||
AddStep("set selected tab = second", () => tabControl.Current.Value = TestEnum.Second);
|
||||
AddAssert("selected tab queue still empty", () => tabControl.UserTabSelectionChangedQueue.Count == 0);
|
||||
}
|
||||
|
||||
[TearDownSteps]
|
||||
public void TearDownSteps()
|
||||
{
|
||||
AddAssert("selected tab queue empty", () => tabControl.UserTabSelectionChangedQueue.Count == 0);
|
||||
}
|
||||
|
||||
private partial class EventQueuesTabControl : BasicTabControl<TestEnum>
|
||||
{
|
||||
public readonly Queue<TabItem<TestEnum>> UserTabSelectionChangedQueue = new Queue<TabItem<TestEnum>>();
|
||||
|
||||
private Box background = null!;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
AddInternal(background = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = FrameworkColour.YellowGreen,
|
||||
Alpha = 0,
|
||||
});
|
||||
}
|
||||
|
||||
protected override void OnUserTabSelectionChanged(TabItem<TestEnum> item)
|
||||
{
|
||||
UserTabSelectionChangedQueue.Enqueue(item);
|
||||
background.FadeOutFromOne(500);
|
||||
}
|
||||
}
|
||||
|
||||
private enum TestEnum
|
||||
{
|
||||
First,
|
||||
Second,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
@@ -828,6 +827,60 @@ namespace osu.Framework.Tests.Visual.UserInterface
|
||||
AddAssert("all text selected", () => textBox.SelectedText, () => Is.EqualTo(textBox.Text));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestCursorMovementWithSelection()
|
||||
{
|
||||
TextBox textBox = null;
|
||||
|
||||
AddStep("add textbox", () =>
|
||||
{
|
||||
textBoxes.Add(textBox = new BasicTextBox
|
||||
{
|
||||
Size = new Vector2(300, 40),
|
||||
Text = "cwm fjord glyphs vext bank quiz",
|
||||
ReadOnly = false
|
||||
});
|
||||
});
|
||||
|
||||
AddStep("focus textbox", () =>
|
||||
{
|
||||
InputManager.MoveMouseTo(textBox);
|
||||
InputManager.Click(MouseButton.Left);
|
||||
});
|
||||
|
||||
// left char move should put cursor at left end of selection
|
||||
AddStep("select all", () => textBox.SelectAll());
|
||||
AddStep("move cursor backward (char)", () => InputManager.Keys(PlatformAction.MoveBackwardChar));
|
||||
AddStep("select next word", () => InputManager.Keys(PlatformAction.SelectForwardWord));
|
||||
AddAssert("first word selected", () => textBox.SelectedText == "cwm");
|
||||
|
||||
// forward word move should put cursor at right end of selection
|
||||
AddStep("move cursor forward (word)", () => InputManager.Keys(PlatformAction.MoveForwardWord));
|
||||
AddStep("select next word", () => InputManager.Keys(PlatformAction.SelectForwardWord));
|
||||
AddAssert("second word selected", () => textBox.SelectedText == " fjord");
|
||||
|
||||
// same thing but for "back-facing" selection
|
||||
AddStep("move cursor forward (word)", () => InputManager.Keys(PlatformAction.MoveForwardWord));
|
||||
AddStep("select previous word", () => InputManager.Keys(PlatformAction.SelectBackwardWord));
|
||||
AddAssert("second word selected", () => textBox.SelectedText == "fjord");
|
||||
|
||||
// right char move should put cursor at right end of selection
|
||||
AddStep("select all", () => textBox.SelectAll());
|
||||
AddStep("move cursor forward (char)", () => InputManager.Keys(PlatformAction.MoveForwardChar));
|
||||
AddStep("select previous word", () => InputManager.Keys(PlatformAction.SelectBackwardWord));
|
||||
AddAssert("last word selected", () => textBox.SelectedText == "quiz");
|
||||
|
||||
// backward word move should put cursor at left end of selection
|
||||
AddStep("move cursor backward (word)", () => InputManager.Keys(PlatformAction.MoveBackwardWord));
|
||||
AddStep("select previous word", () => InputManager.Keys(PlatformAction.SelectBackwardWord));
|
||||
AddAssert("second-from-last word selected", () => textBox.SelectedText == "bank ");
|
||||
|
||||
// same thing but for "front-facing" selection
|
||||
AddStep("move cursor backward (word)", () => InputManager.Keys(PlatformAction.MoveBackwardWord));
|
||||
AddStep("select next word", () => InputManager.Keys(PlatformAction.SelectForwardWord));
|
||||
AddAssert("second-from-last word selected", () => textBox.SelectedText == "bank");
|
||||
}
|
||||
|
||||
private void prependString(InsertableTextBox textBox, string text)
|
||||
{
|
||||
InputManager.Keys(PlatformAction.MoveBackwardLine);
|
||||
@@ -870,7 +923,7 @@ namespace osu.Framework.Tests.Visual.UserInterface
|
||||
|
||||
private partial class NumberTextBox : BasicTextBox
|
||||
{
|
||||
protected override bool CanAddCharacter(char character) => character.IsAsciiDigit();
|
||||
protected override bool CanAddCharacter(char character) => char.IsAsciiDigit(character);
|
||||
|
||||
protected override bool AllowIme => false;
|
||||
}
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using AVFoundation;
|
||||
using Foundation;
|
||||
using ManagedBass;
|
||||
using ManagedBass.Fx;
|
||||
using ManagedBass.Mix;
|
||||
using ObjCRuntime;
|
||||
using SDL2;
|
||||
using SDL;
|
||||
|
||||
namespace osu.Framework.iOS
|
||||
{
|
||||
@@ -22,20 +22,20 @@ namespace osu.Framework.iOS
|
||||
|
||||
private static readonly OutputVolumeObserver output_volume_observer = new OutputVolumeObserver();
|
||||
|
||||
public static void Main(Game target)
|
||||
public static unsafe void Main(Game target)
|
||||
{
|
||||
NativeLibrary.SetDllImportResolver(typeof(Bass).Assembly, (_, assembly, path) => NativeLibrary.Load("@rpath/bass.framework/bass", assembly, path));
|
||||
NativeLibrary.SetDllImportResolver(typeof(BassFx).Assembly, (_, assembly, path) => NativeLibrary.Load("@rpath/bass_fx.framework/bass_fx", assembly, path));
|
||||
NativeLibrary.SetDllImportResolver(typeof(BassMix).Assembly, (_, assembly, path) => NativeLibrary.Load("@rpath/bassmix.framework/bassmix", assembly, path));
|
||||
NativeLibrary.SetDllImportResolver(typeof(SDL3).Assembly, (_, assembly, path) => NativeLibrary.Load("@rpath/SDL3.framework/SDL3", assembly, path));
|
||||
|
||||
game = target;
|
||||
|
||||
SDL.PrepareLibraryForIOS();
|
||||
SDL.SDL_UIKitRunApp(0, IntPtr.Zero, main);
|
||||
SDL3.SDL_RunApp(0, null, &main, IntPtr.Zero);
|
||||
}
|
||||
|
||||
[MonoPInvokeCallback(typeof(SDL.SDL_main_func))]
|
||||
private static int main(int argc, IntPtr argv)
|
||||
[UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })]
|
||||
private static unsafe int main(int argc, byte** argv)
|
||||
{
|
||||
var audioSession = AVAudioSession.SharedInstance();
|
||||
audioSession.AddObserver(output_volume_observer, output_volume, NSKeyValueObservingOptions.New, 0);
|
||||
|
||||
@@ -21,7 +21,7 @@ using UIKit;
|
||||
|
||||
namespace osu.Framework.iOS
|
||||
{
|
||||
public class IOSGameHost : SDL2GameHost
|
||||
public class IOSGameHost : SDL3GameHost
|
||||
{
|
||||
public IOSGameHost()
|
||||
: base(string.Empty)
|
||||
|
||||
@@ -4,16 +4,18 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using ObjCRuntime;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Platform;
|
||||
using SDL2;
|
||||
using SDL;
|
||||
using UIKit;
|
||||
|
||||
namespace osu.Framework.iOS
|
||||
{
|
||||
internal class IOSWindow : SDL2Window
|
||||
internal class IOSWindow : SDL3Window
|
||||
{
|
||||
private UIWindow? window;
|
||||
|
||||
@@ -34,10 +36,10 @@ namespace osu.Framework.iOS
|
||||
{
|
||||
}
|
||||
|
||||
protected override void UpdateWindowStateAndSize(WindowState state, Display display, DisplayMode displayMode)
|
||||
protected override unsafe void UpdateWindowStateAndSize(WindowState state, Display display, DisplayMode displayMode)
|
||||
{
|
||||
// This sets the status bar to hidden.
|
||||
SDL.SDL_SetWindowFullscreen(SDLWindowHandle, (uint)SDL.SDL_WindowFlags.SDL_WINDOW_FULLSCREEN);
|
||||
SDL3.SDL_SetWindowFullscreen(SDLWindowHandle, SDL_bool.SDL_TRUE);
|
||||
|
||||
// Don't run base logic at all. Let's keep things simple.
|
||||
}
|
||||
@@ -50,7 +52,7 @@ namespace osu.Framework.iOS
|
||||
updateSafeArea();
|
||||
}
|
||||
|
||||
protected override void RunMainLoop()
|
||||
protected override unsafe void RunMainLoop()
|
||||
{
|
||||
// Delegate running the main loop to CADisplayLink.
|
||||
//
|
||||
@@ -60,11 +62,11 @@ namespace osu.Framework.iOS
|
||||
// iOS may be a good forward direction if this ever comes up, as a user may see a potentially higher
|
||||
// frame rate with multi-threaded mode turned on, but it is going to give them worse input latency
|
||||
// and higher power usage.
|
||||
SDL.SDL_iPhoneSetEventPump(SDL.SDL_bool.SDL_FALSE);
|
||||
SDL.SDL_iPhoneSetAnimationCallback(SDLWindowHandle, 1, runFrame, ObjectHandle.Handle);
|
||||
SDL3.SDL_iPhoneSetEventPump(SDL_bool.SDL_FALSE);
|
||||
SDL3.SDL_iPhoneSetAnimationCallback(SDLWindowHandle, 1, &runFrame, ObjectHandle.Handle);
|
||||
}
|
||||
|
||||
[ObjCRuntime.MonoPInvokeCallback(typeof(SDL.SDL_iPhoneAnimationCallback))]
|
||||
[UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })]
|
||||
private static void runFrame(IntPtr userdata)
|
||||
{
|
||||
var handle = new ObjectHandle<IOSWindow>(userdata);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace osu.Framework.Allocation
|
||||
{
|
||||
@@ -58,7 +59,7 @@ namespace osu.Framework.Allocation
|
||||
/// </summary>
|
||||
/// <param name="sender">The sender which should appear in the <paramref name="action"/> callback.</param>
|
||||
/// <param name="action">The action to invoke during disposal.</param>
|
||||
public InvokeOnDisposal(T sender, Action<T> action)
|
||||
public InvokeOnDisposal(T sender, [RequireStaticDelegate(IsError = true)] Action<T> action)
|
||||
{
|
||||
this.sender = sender;
|
||||
this.action = action ?? throw new ArgumentNullException(nameof(action));
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace osu.Framework.Allocation
|
||||
{
|
||||
@@ -62,7 +63,7 @@ namespace osu.Framework.Allocation
|
||||
/// </summary>
|
||||
/// <param name="sender">The sender which should appear in the <paramref name="action"/> callback.</param>
|
||||
/// <param name="action">The action to invoke during disposal.</param>
|
||||
public ValueInvokeOnDisposal(T sender, Action<T> action)
|
||||
public ValueInvokeOnDisposal(T sender, [RequireStaticDelegate(IsError = true)] Action<T> action)
|
||||
{
|
||||
this.sender = sender;
|
||||
this.action = action ?? throw new ArgumentNullException(nameof(action));
|
||||
|
||||
@@ -74,8 +74,7 @@ namespace osu.Framework.Audio
|
||||
{
|
||||
ThreadSafety.EnsureNotUpdateThread();
|
||||
|
||||
if (IsDisposed)
|
||||
throw new ObjectDisposedException(ToString(), "Can not update disposed audio components.");
|
||||
ObjectDisposedException.ThrowIf(IsDisposed, this);
|
||||
|
||||
FrameStatistics.Add(StatisticsCounterType.TasksRun, PendingActions.Count);
|
||||
FrameStatistics.Increment(StatisticsCounterType.Components);
|
||||
|
||||
@@ -10,7 +10,6 @@ using System.Runtime.InteropServices;
|
||||
using ManagedBass;
|
||||
using ManagedBass.Mix;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Development;
|
||||
using osu.Framework.Extensions.EnumExtensions;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
using osu.Framework.Statistics;
|
||||
@@ -158,7 +157,7 @@ namespace osu.Framework.Audio.Mixing.Bass
|
||||
/// If successful, the position is returned.
|
||||
/// </returns>
|
||||
public long ChannelGetPosition(IBassAudioChannel channel, PositionFlags mode = PositionFlags.Bytes)
|
||||
=> BassMix.ChannelGetPosition(channel.Handle);
|
||||
=> BassMix.ChannelGetPosition(channel.Handle, mode);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the playback position of a channel.
|
||||
@@ -421,13 +420,7 @@ namespace osu.Framework.Audio.Mixing.Bass
|
||||
// Effects with greatest priority are stored at the front of the list.
|
||||
effect.Priority = -i;
|
||||
|
||||
if (effect.Handle != 0)
|
||||
{
|
||||
// Todo: Temporary bypass to attempt to fix failing test runs.
|
||||
if (!DebugUtils.IsNUnitRunning)
|
||||
ManagedBass.Bass.FXSetPriority(effect.Handle, effect.Priority);
|
||||
}
|
||||
else
|
||||
if (effect.Handle == 0)
|
||||
effect.Handle = ManagedBass.Bass.ChannelSetFX(Handle, effect.Effect.FXType, effect.Priority);
|
||||
|
||||
ManagedBass.Bass.FXSetParameters(effect.Handle, effect.Effect);
|
||||
|
||||
@@ -33,8 +33,7 @@ namespace osu.Framework.Audio.Sample
|
||||
|
||||
public SampleChannel GetChannel()
|
||||
{
|
||||
if (IsDisposed)
|
||||
throw new ObjectDisposedException(ToString(), "Can not get a channel from a disposed sample.");
|
||||
ObjectDisposedException.ThrowIf(IsDisposed, this);
|
||||
|
||||
var channel = CreateChannel();
|
||||
channel.OnPlay = onPlay;
|
||||
|
||||
@@ -22,8 +22,7 @@ namespace osu.Framework.Audio.Sample
|
||||
|
||||
public virtual void Play()
|
||||
{
|
||||
if (IsDisposed)
|
||||
throw new ObjectDisposedException(ToString(), "Can not play disposed sample channels.");
|
||||
ObjectDisposedException.ThrowIf(IsDisposed, this);
|
||||
|
||||
Played = true;
|
||||
OnPlay?.Invoke(this);
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace osu.Framework.Audio.Sample
|
||||
|
||||
public Sample Get(string name)
|
||||
{
|
||||
if (IsDisposed) throw new ObjectDisposedException($"Cannot retrieve items for an already disposed {nameof(SampleStore)}");
|
||||
ObjectDisposedException.ThrowIf(IsDisposed, this);
|
||||
|
||||
if (string.IsNullOrEmpty(name)) return null;
|
||||
|
||||
|
||||
@@ -256,8 +256,7 @@ namespace osu.Framework.Audio.Track
|
||||
|
||||
public override void Start()
|
||||
{
|
||||
if (IsDisposed)
|
||||
throw new ObjectDisposedException(ToString(), "Can not start disposed tracks.");
|
||||
ObjectDisposedException.ThrowIf(IsDisposed, this);
|
||||
|
||||
StartAsync().WaitSafely();
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace osu.Framework.Audio.Track
|
||||
|
||||
public Track GetVirtual(double length = double.PositiveInfinity, string name = "virtual")
|
||||
{
|
||||
if (IsDisposed) throw new ObjectDisposedException($"Cannot retrieve items for an already disposed {nameof(TrackStore)}");
|
||||
ObjectDisposedException.ThrowIf(IsDisposed, this);
|
||||
|
||||
var track = new TrackVirtual(length, name);
|
||||
AddItem(track);
|
||||
@@ -38,7 +38,7 @@ namespace osu.Framework.Audio.Track
|
||||
|
||||
public Track Get(string name)
|
||||
{
|
||||
if (IsDisposed) throw new ObjectDisposedException($"Cannot retrieve items for an already disposed {nameof(TrackStore)}");
|
||||
ObjectDisposedException.ThrowIf(IsDisposed, this);
|
||||
|
||||
if (string.IsNullOrEmpty(name)) return null;
|
||||
|
||||
|
||||
@@ -99,14 +99,30 @@ namespace osu.Framework.Audio.Track
|
||||
|
||||
int decodeStream = Bass.CreateStream(StreamSystem.NoBuffer, BassFlags.Decode | BassFlags.Float, fileCallbacks.Callbacks, fileCallbacks.Handle);
|
||||
|
||||
if (decodeStream == 0)
|
||||
{
|
||||
logBassError("could not create stream");
|
||||
return;
|
||||
}
|
||||
|
||||
float[]? sampleBuffer = null;
|
||||
|
||||
try
|
||||
{
|
||||
Bass.ChannelGetInfo(decodeStream, out ChannelInfo info);
|
||||
if (!Bass.ChannelGetInfo(decodeStream, out ChannelInfo info))
|
||||
{
|
||||
logBassError("could not retrieve channel information");
|
||||
return;
|
||||
}
|
||||
|
||||
long length = Bass.ChannelGetLength(decodeStream);
|
||||
|
||||
if (length < 0)
|
||||
{
|
||||
logBassError("could not retrieve channel length");
|
||||
return;
|
||||
}
|
||||
|
||||
// Each "point" is generated from a number of samples, each sample contains a number of channels
|
||||
int samplesPerPoint = (int)(info.Frequency * resolution * info.Channels);
|
||||
|
||||
@@ -127,6 +143,13 @@ namespace osu.Framework.Audio.Track
|
||||
while (length > 0)
|
||||
{
|
||||
length = Bass.ChannelGetData(decodeStream, sampleBuffer, bytesPerIteration);
|
||||
|
||||
if (length < 0 && Bass.LastError != Errors.Ended)
|
||||
{
|
||||
logBassError("could not retrieve sample data");
|
||||
return;
|
||||
}
|
||||
|
||||
int samplesRead = (int)(length / bytes_per_sample);
|
||||
|
||||
// Each point is composed of multiple samples
|
||||
@@ -157,9 +180,20 @@ namespace osu.Framework.Audio.Track
|
||||
}
|
||||
}
|
||||
|
||||
Bass.ChannelSetPosition(decodeStream, 0);
|
||||
if (!Bass.ChannelSetPosition(decodeStream, 0))
|
||||
{
|
||||
logBassError("could not reset channel position");
|
||||
return;
|
||||
}
|
||||
|
||||
length = Bass.ChannelGetLength(decodeStream);
|
||||
|
||||
if (length < 0)
|
||||
{
|
||||
logBassError("could not retrieve channel length");
|
||||
return;
|
||||
}
|
||||
|
||||
// Read FFT data
|
||||
float[] bins = new float[fft_bins];
|
||||
int currentPoint = 0;
|
||||
@@ -168,6 +202,13 @@ namespace osu.Framework.Audio.Track
|
||||
while (length > 0)
|
||||
{
|
||||
length = Bass.ChannelGetData(decodeStream, bins, (int)fft_samples);
|
||||
|
||||
if (length < 0 && Bass.LastError != Errors.Ended)
|
||||
{
|
||||
logBassError("could not retrieve FFT data");
|
||||
return;
|
||||
}
|
||||
|
||||
currentByte += length;
|
||||
|
||||
float lowIntensity = computeIntensity(info, bins, low_min, mid_min);
|
||||
@@ -191,7 +232,9 @@ namespace osu.Framework.Audio.Track
|
||||
}
|
||||
finally
|
||||
{
|
||||
Bass.StreamFree(decodeStream);
|
||||
if (!Bass.StreamFree(decodeStream))
|
||||
logBassError("failed to free decode stream");
|
||||
|
||||
fileCallbacks.Dispose();
|
||||
|
||||
data.Dispose();
|
||||
@@ -201,6 +244,8 @@ namespace osu.Framework.Audio.Track
|
||||
ArrayPool<float>.Shared.Return(sampleBuffer);
|
||||
}
|
||||
}, cancelSource.Token);
|
||||
|
||||
void logBassError(string reason) => Logger.Log($"BASS failure while reading waveform: {reason} ({Bass.LastError})");
|
||||
}
|
||||
|
||||
private float computeIntensity(ChannelInfo info, float[] bins, float startFrequency, float endFrequency)
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace osu.Framework.Bindables
|
||||
{
|
||||
@@ -52,7 +51,7 @@ namespace osu.Framework.Bindables
|
||||
return;
|
||||
|
||||
var boundCopy = bindable.GetBoundCopy();
|
||||
sourceMapping.Add(new WeakRefPair(new WeakReference<IBindable<T>>(bindable), boundCopy));
|
||||
sourceMapping.Add(new WeakRefPair(bindable.GetWeakReference(), boundCopy));
|
||||
boundCopy.BindValueChanged(recalculateAggregate, true);
|
||||
}
|
||||
}
|
||||
@@ -65,20 +64,26 @@ namespace osu.Framework.Bindables
|
||||
{
|
||||
lock (sourceMapping)
|
||||
{
|
||||
var weak = findExistingPair(bindable);
|
||||
|
||||
if (weak != null)
|
||||
if (findExistingPair(bindable) is WeakRefPair pair)
|
||||
{
|
||||
weak.BoundCopy.UnbindAll();
|
||||
sourceMapping.Remove(weak);
|
||||
pair.BoundCopy.UnbindAll();
|
||||
sourceMapping.Remove(pair);
|
||||
}
|
||||
|
||||
recalculateAggregate();
|
||||
}
|
||||
}
|
||||
|
||||
private WeakRefPair findExistingPair(IBindable<T> bindable) =>
|
||||
sourceMapping.FirstOrDefault(p => p.WeakReference.TryGetTarget(out var target) && target == bindable);
|
||||
private WeakRefPair? findExistingPair(IBindable<T> bindable)
|
||||
{
|
||||
foreach (var p in sourceMapping)
|
||||
{
|
||||
if (p.WeakReference.TryGetTarget(out var target) && target == bindable)
|
||||
return p;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void recalculateAggregate(ValueChangedEvent<T> obj = null)
|
||||
{
|
||||
@@ -112,16 +117,6 @@ namespace osu.Framework.Bindables
|
||||
}
|
||||
}
|
||||
|
||||
private class WeakRefPair
|
||||
{
|
||||
public readonly WeakReference<IBindable<T>> WeakReference;
|
||||
public readonly IBindable<T> BoundCopy;
|
||||
|
||||
public WeakRefPair(WeakReference<IBindable<T>> weakReference, IBindable<T> boundCopy)
|
||||
{
|
||||
WeakReference = weakReference;
|
||||
BoundCopy = boundCopy;
|
||||
}
|
||||
}
|
||||
private readonly record struct WeakRefPair(WeakReference<Bindable<T>> WeakReference, IBindable<T> BoundCopy);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -440,6 +440,8 @@ namespace osu.Framework.Bindables
|
||||
|
||||
IBindable IBindable.GetBoundCopy() => GetBoundCopy();
|
||||
|
||||
WeakReference<Bindable<T>> IBindable<T>.GetWeakReference() => weakReference;
|
||||
|
||||
IBindable<T> IBindable<T>.GetBoundCopy() => GetBoundCopy();
|
||||
|
||||
/// <inheritdoc cref="IBindable{T}.GetBoundCopy"/>
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace osu.Framework.Bindables
|
||||
|
||||
public override void Parse(object? input, IFormatProvider provider)
|
||||
{
|
||||
if (input == null) throw new ArgumentNullException(nameof(input));
|
||||
ArgumentNullException.ThrowIfNull(input);
|
||||
|
||||
if (input is "1")
|
||||
Value = true;
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace osu.Framework.Bindables
|
||||
|
||||
public override void Parse(object? input, IFormatProvider provider)
|
||||
{
|
||||
if (input == null) throw new ArgumentNullException(nameof(input));
|
||||
ArgumentNullException.ThrowIfNull(input);
|
||||
|
||||
switch (input)
|
||||
{
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace osu.Framework.Bindables
|
||||
|
||||
public override void Parse(object? input, IFormatProvider provider)
|
||||
{
|
||||
if (input == null) throw new ArgumentNullException(nameof(input));
|
||||
ArgumentNullException.ThrowIfNull(input);
|
||||
|
||||
switch (input)
|
||||
{
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace osu.Framework.Bindables
|
||||
|
||||
public override void Parse(object? input, IFormatProvider provider)
|
||||
{
|
||||
if (input == null) throw new ArgumentNullException(nameof(input));
|
||||
ArgumentNullException.ThrowIfNull(input);
|
||||
|
||||
switch (input)
|
||||
{
|
||||
|
||||
@@ -111,5 +111,10 @@ namespace osu.Framework.Bindables
|
||||
|
||||
/// <inheritdoc cref="IBindable.GetBoundCopy"/>
|
||||
IBindable<T> GetBoundCopy();
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a weak reference to this bindable.
|
||||
/// </summary>
|
||||
internal WeakReference<Bindable<T>> GetWeakReference();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using osu.Framework.Graphics.OpenGL;
|
||||
|
||||
namespace osu.Framework.Configuration
|
||||
{
|
||||
@@ -19,10 +21,27 @@ namespace osu.Framework.Configuration
|
||||
[Description("Direct3D 11")]
|
||||
Direct3D11,
|
||||
|
||||
/// <summary>
|
||||
/// Uses <see cref="GLRenderer"/>.
|
||||
/// </summary>
|
||||
[Description("OpenGL")]
|
||||
OpenGL,
|
||||
|
||||
// Can be removed 20240820
|
||||
[Obsolete]
|
||||
[Description("OpenGL (Legacy)")]
|
||||
OpenGLLegacy,
|
||||
|
||||
[Description("Metal (Experimental)")]
|
||||
Deferred_Metal = 32,
|
||||
|
||||
[Description("Vulkan (Experimental)")]
|
||||
Deferred_Vulkan,
|
||||
|
||||
[Description("Direct3D 11 (Experimental)")]
|
||||
Deferred_Direct3D11,
|
||||
|
||||
[Description("OpenGL (Experimental)")]
|
||||
Deferred_OpenGL
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,11 +17,15 @@ namespace osu.Framework.Development
|
||||
|
||||
private static readonly Lazy<bool> is_nunit_running = new Lazy<bool>(() =>
|
||||
{
|
||||
#pragma warning disable RS0030
|
||||
var entry = Assembly.GetEntryAssembly();
|
||||
#pragma warning restore RS0030
|
||||
|
||||
string? assemblyName = entry?.GetName().Name;
|
||||
|
||||
// when running under nunit + netcore, entry assembly becomes nunit itself (testhost, Version=15.0.0.0), which isn't what we want.
|
||||
// when running under nunit + Rider > 2020.2 EAP6, entry assembly becomes ReSharperTestRunner[32|64], which isn't what we want.
|
||||
bool entryIsKnownTestAssembly = entry != null && (entry.Location.Contains("testhost") || entry.Location.Contains("ReSharperTestRunner"));
|
||||
bool entryIsKnownTestAssembly = entry != null && (assemblyName!.Contains("testhost") || assemblyName.Contains("ReSharperTestRunner"));
|
||||
|
||||
// null assembly can indicate nunit, but it can also indicate native code (e.g. android).
|
||||
// to distinguish nunit runs from android launches, check the class name of the current test.
|
||||
@@ -33,6 +37,8 @@ namespace osu.Framework.Development
|
||||
}
|
||||
);
|
||||
|
||||
internal static Assembly NUnitTestAssembly => nunit_test_assembly.Value;
|
||||
|
||||
private static readonly Lazy<Assembly> nunit_test_assembly = new Lazy<Assembly>(() =>
|
||||
{
|
||||
Debug.Assert(IsNUnitRunning);
|
||||
@@ -45,7 +51,7 @@ namespace osu.Framework.Development
|
||||
public static bool IsDebugBuild => is_debug_build.Value;
|
||||
|
||||
private static readonly Lazy<bool> is_debug_build = new Lazy<bool>(() =>
|
||||
isDebugAssembly(typeof(DebugUtils).Assembly) || isDebugAssembly(GetEntryAssembly())
|
||||
isDebugAssembly(typeof(DebugUtils).Assembly) || isDebugAssembly(RuntimeInfo.EntryAssembly)
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
@@ -56,18 +62,5 @@ namespace osu.Framework.Development
|
||||
|
||||
// https://stackoverflow.com/a/2186634
|
||||
private static bool isDebugAssembly(Assembly? assembly) => assembly?.GetCustomAttributes(false).OfType<DebuggableAttribute>().Any(da => da.IsJITTrackingEnabled) ?? false;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the entry assembly, or calling assembly otherwise.
|
||||
/// When running under NUnit, the assembly of the current test will be returned instead.
|
||||
/// </summary>
|
||||
/// <returns>The entry assembly (usually obtained via <see cref="Assembly.GetEntryAssembly()"/>.</returns>
|
||||
public static Assembly GetEntryAssembly()
|
||||
{
|
||||
if (IsNUnitRunning)
|
||||
return nunit_test_assembly.Value;
|
||||
|
||||
return Assembly.GetEntryAssembly() ?? Assembly.GetCallingAssembly();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace osu.Framework.Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Temporary extension functions for bridging between osuTK, System.Drawing, and System.Numerics
|
||||
/// Can be removed when the SDL2 migration is complete.
|
||||
/// Can be removed when the SDL3 migration is complete.
|
||||
/// </summary>
|
||||
public static class BridgingExtensions
|
||||
{
|
||||
|
||||
@@ -119,8 +119,7 @@ namespace osu.Framework.Extensions.Color4Extensions
|
||||
/// <param name="scalar">A scalar to multiply with</param>
|
||||
public static Color4 Multiply(this Color4 colour, float scalar)
|
||||
{
|
||||
if (scalar < 0)
|
||||
throw new ArgumentOutOfRangeException(nameof(scalar), scalar, "Can not multiply colours by negative values.");
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(scalar);
|
||||
|
||||
return new Color4(
|
||||
Math.Min(1, colour.R * scalar),
|
||||
|
||||
@@ -332,7 +332,8 @@ namespace osu.Framework.Extensions
|
||||
/// </remarks>
|
||||
/// <param name="character">The character to check.</param>
|
||||
/// <returns>True if the character is an ASCII digit.</returns>
|
||||
public static bool IsAsciiDigit(this char character) => character >= '0' && character <= '9';
|
||||
[Obsolete("Use char.IsAsciiDigit.")] // can be removed 20240901
|
||||
public static bool IsAsciiDigit(this char character) => char.IsAsciiDigit(character);
|
||||
|
||||
/// <summary>
|
||||
/// Converts an osuTK <see cref="DisplayDevice"/> to a <see cref="Display"/> structure.
|
||||
@@ -349,7 +350,7 @@ namespace osu.Framework.Extensions
|
||||
/// <param name="resolution">The <see cref="DisplayResolution"/> to convert.</param>
|
||||
/// <returns>A <see cref="DisplayMode"/> structure populated with the corresponding properties.</returns>
|
||||
internal static DisplayMode ToDisplayMode(this DisplayResolution resolution) =>
|
||||
new DisplayMode(null, new Size(resolution.Width, resolution.Height), resolution.BitsPerPixel, (int)Math.Round(resolution.RefreshRate), 0);
|
||||
new DisplayMode(null, new Size(resolution.Width, resolution.Height), resolution.BitsPerPixel, resolution.RefreshRate, 0);
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the provided URL is a safe protocol to execute a system <see cref="Process.Start()"/> call with.
|
||||
|
||||
@@ -63,7 +63,7 @@ namespace osu.Framework.Extensions
|
||||
public static byte[] ReadBytesToArray(this Stream stream, int length)
|
||||
{
|
||||
byte[] bytes = new byte[length];
|
||||
stream.ReadToFill(bytes);
|
||||
stream.ReadExactly(bytes);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ namespace osu.Framework.Extensions
|
||||
public static async Task<byte[]> ReadBytesToArrayAsync(this Stream stream, int length, CancellationToken cancellationToken = default)
|
||||
{
|
||||
byte[] bytes = new byte[length];
|
||||
await stream.ReadToFillAsync(bytes, cancellationToken).ConfigureAwait(false);
|
||||
await stream.ReadExactlyAsync(bytes, cancellationToken).ConfigureAwait(false);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
@@ -117,19 +117,8 @@ namespace osu.Framework.Extensions
|
||||
/// <param name="stream">The stream to read.</param>
|
||||
/// <param name="buffer">The buffer to read into.</param>
|
||||
/// <exception cref="EndOfStreamException">Throws if the stream didn't have enough content to fill the buffer.</exception>
|
||||
public static void ReadToFill(this Stream stream, Span<byte> buffer)
|
||||
{
|
||||
Span<byte> remainingBuffer = buffer;
|
||||
|
||||
while (!remainingBuffer.IsEmpty)
|
||||
{
|
||||
int bytesRead = stream.Read(remainingBuffer);
|
||||
remainingBuffer = remainingBuffer[bytesRead..];
|
||||
|
||||
if (bytesRead == 0)
|
||||
throw new EndOfStreamException();
|
||||
}
|
||||
}
|
||||
[Obsolete("Use Stream.ReadExactly")] // can be removed 20240901
|
||||
public static void ReadToFill(this Stream stream, Span<byte> buffer) => stream.ReadExactly(buffer);
|
||||
|
||||
/// <summary>
|
||||
/// Reads bytes from a stream until the provided buffer is full.
|
||||
@@ -138,18 +127,7 @@ namespace osu.Framework.Extensions
|
||||
/// <param name="buffer">The buffer to read into.</param>
|
||||
/// <param name="cancellationToken">A cancellation token.</param>
|
||||
/// <exception cref="EndOfStreamException">Throws if the stream didn't have enough content to fill the buffer.</exception>
|
||||
public static async Task ReadToFillAsync(this Stream stream, Memory<byte> buffer, CancellationToken cancellationToken = default)
|
||||
{
|
||||
Memory<byte> remainingBuffer = buffer;
|
||||
|
||||
while (!remainingBuffer.IsEmpty)
|
||||
{
|
||||
int bytesRead = await stream.ReadAsync(remainingBuffer, cancellationToken).ConfigureAwait(false);
|
||||
remainingBuffer = remainingBuffer[bytesRead..];
|
||||
|
||||
if (bytesRead == 0)
|
||||
throw new EndOfStreamException();
|
||||
}
|
||||
}
|
||||
[Obsolete("Use Stream.ReadExactlyAsync")] // can be removed 20240901
|
||||
public static Task ReadToFillAsync(this Stream stream, Memory<byte> buffer, CancellationToken cancellationToken = default) => stream.ReadExactlyAsync(buffer, cancellationToken).AsTask();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ namespace osu.Framework
|
||||
public static int? StagingBufferType { get; }
|
||||
public static int? VertexBufferCount { get; }
|
||||
public static bool NoStructuredBuffers { get; }
|
||||
public static string? DeferredRendererEventsOutputPath { get; }
|
||||
|
||||
static FrameworkEnvironment()
|
||||
{
|
||||
@@ -34,6 +35,8 @@ namespace osu.Framework
|
||||
StagingBufferType = stagingBufferImplementation;
|
||||
|
||||
NoStructuredBuffers = parseBool(Environment.GetEnvironmentVariable("OSU_GRAPHICS_NO_SSBO")) ?? false;
|
||||
|
||||
DeferredRendererEventsOutputPath = Environment.GetEnvironmentVariable("DEFERRED_RENDERER_EVENTS_OUTPUT");
|
||||
}
|
||||
|
||||
private static bool? parseBool(string? value)
|
||||
|
||||
@@ -46,8 +46,7 @@ namespace osu.Framework.Graphics.Audio
|
||||
get => resolution;
|
||||
set
|
||||
{
|
||||
if (value < 0)
|
||||
throw new ArgumentOutOfRangeException(nameof(value));
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(value);
|
||||
|
||||
if (resolution == value)
|
||||
return;
|
||||
|
||||
@@ -150,7 +150,7 @@ namespace osu.Framework.Graphics
|
||||
|
||||
frameBuffer.Bind();
|
||||
|
||||
return new ValueInvokeOnDisposal<IFrameBuffer>(frameBuffer, b => b.Unbind());
|
||||
return new ValueInvokeOnDisposal<IFrameBuffer>(frameBuffer, static b => b.Unbind());
|
||||
}
|
||||
|
||||
private IDisposable establishFrameBufferViewport(IRenderer renderer)
|
||||
@@ -175,7 +175,7 @@ namespace osu.Framework.Graphics
|
||||
renderer.PushScissor(new RectangleI(0, 0, (int)frameBufferSize.X, (int)frameBufferSize.Y));
|
||||
renderer.PushScissorOffset(screenSpaceMaskingRect.Location);
|
||||
|
||||
return new ValueInvokeOnDisposal<(BufferedDrawNode node, IRenderer renderer)>((this, renderer), tup => tup.node.returnViewport(tup.renderer));
|
||||
return new ValueInvokeOnDisposal<(BufferedDrawNode node, IRenderer renderer)>((this, renderer), static tup => tup.node.returnViewport(tup.renderer));
|
||||
}
|
||||
|
||||
private void returnViewport(IRenderer renderer)
|
||||
|
||||
@@ -67,8 +67,7 @@ namespace osu.Framework.Graphics
|
||||
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="effectBufferCount"/> is less than 0.</exception>
|
||||
public BufferedDrawNodeSharedData(int effectBufferCount, RenderBufferFormat[] mainBufferFormats = null, bool pixelSnapping = false, bool clipToRootNode = false)
|
||||
{
|
||||
if (effectBufferCount < 0)
|
||||
throw new ArgumentOutOfRangeException(nameof(effectBufferCount), "Must be positive.");
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(effectBufferCount);
|
||||
|
||||
this.mainBufferFormats = mainBufferFormats;
|
||||
PixelSnapping = pixelSnapping;
|
||||
|
||||
@@ -93,8 +93,7 @@ namespace osu.Framework.Graphics
|
||||
/// <param name="scalar">The value that the existing alpha will be multiplied by.</param>
|
||||
public Colour4 MultiplyAlpha(float scalar)
|
||||
{
|
||||
if (scalar < 0)
|
||||
throw new ArgumentOutOfRangeException(nameof(scalar), scalar, "Cannot multiply alpha by a negative value.");
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(scalar);
|
||||
|
||||
return new Colour4(R, G, B, Math.Min(1f, A * scalar));
|
||||
}
|
||||
@@ -174,8 +173,7 @@ namespace osu.Framework.Graphics
|
||||
/// <exception cref="ArgumentOutOfRangeException">Thrown if <paramref name="scalar"/> is negative.</exception>
|
||||
public static Colour4 operator *(Colour4 colour, float scalar)
|
||||
{
|
||||
if (scalar < 0)
|
||||
throw new ArgumentOutOfRangeException(nameof(scalar), scalar, "Cannot multiply colours by negative values.");
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(scalar);
|
||||
|
||||
return new Colour4(Vector4.Min(colour.Vector * scalar, Vector4.One));
|
||||
}
|
||||
@@ -188,8 +186,7 @@ namespace osu.Framework.Graphics
|
||||
/// <exception cref="ArgumentOutOfRangeException">Thrown if <paramref name="scalar"/> is zero or negative.</exception>
|
||||
public static Colour4 operator /(Colour4 colour, float scalar)
|
||||
{
|
||||
if (scalar <= 0)
|
||||
throw new ArgumentOutOfRangeException(nameof(scalar), scalar, "Cannot divide colours by non-positive values.");
|
||||
ArgumentOutOfRangeException.ThrowIfNegativeOrZero(scalar);
|
||||
|
||||
return colour * (1 / scalar);
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ namespace osu.Framework.Graphics.Containers
|
||||
|
||||
using (BindFrameBuffer(target))
|
||||
{
|
||||
float radians = MathUtils.DegreesToRadians(blurRotation);
|
||||
float radians = float.DegreesToRadians(blurRotation);
|
||||
|
||||
blurParametersBuffer.Data = blurParametersBuffer.Data with
|
||||
{
|
||||
|
||||
@@ -145,8 +145,7 @@ namespace osu.Framework.Graphics.Containers
|
||||
|
||||
EnsureMutationAllowed($"load components via {nameof(LoadComponentsAsync)}");
|
||||
|
||||
if (IsDisposed)
|
||||
throw new ObjectDisposedException(ToString());
|
||||
ObjectDisposedException.ThrowIf(IsDisposed, this);
|
||||
|
||||
disposalCancellationSource ??= new CancellationTokenSource();
|
||||
|
||||
@@ -222,8 +221,7 @@ namespace osu.Framework.Graphics.Containers
|
||||
if (LoadState < LoadState.Loading)
|
||||
throw new InvalidOperationException($"May not invoke {nameof(LoadComponent)} prior to this {nameof(CompositeDrawable)} being loaded.");
|
||||
|
||||
if (IsDisposed)
|
||||
throw new ObjectDisposedException(ToString());
|
||||
ObjectDisposedException.ThrowIf(IsDisposed, this);
|
||||
|
||||
loadComponents(components.ToList(), Dependencies, false);
|
||||
}
|
||||
|
||||
@@ -220,9 +220,7 @@ namespace osu.Framework.Graphics.Containers
|
||||
throw new InvalidOperationException("Content may not be added to itself.");
|
||||
|
||||
ArgumentNullException.ThrowIfNull(drawable);
|
||||
|
||||
if (drawable.IsDisposed)
|
||||
throw new ObjectDisposedException(nameof(drawable));
|
||||
ObjectDisposedException.ThrowIf(drawable.IsDisposed, drawable);
|
||||
|
||||
if (Content == this)
|
||||
AddInternal(drawable);
|
||||
|
||||
@@ -139,7 +139,7 @@ namespace osu.Framework.Graphics.Containers
|
||||
}
|
||||
|
||||
private readonly Cached cellContent = new Cached();
|
||||
private readonly LayoutValue cellLayout = new LayoutValue(Invalidation.DrawInfo | Invalidation.RequiredParentSizeToFit);
|
||||
private readonly LayoutValue cellLayout = new LayoutValue(Invalidation.DrawSize);
|
||||
private readonly LayoutValue cellChildLayout = new LayoutValue(Invalidation.RequiredParentSizeToFit | Invalidation.Presence, InvalidationSource.Child);
|
||||
|
||||
private CellContainer[,] cells = new CellContainer[0, 0];
|
||||
@@ -420,11 +420,8 @@ namespace osu.Framework.Graphics.Containers
|
||||
/// <param name="maxSize">The maximum size of this row or column.</param>
|
||||
public Dimension(GridSizeMode mode = GridSizeMode.Distributed, float size = 0, float minSize = 0, float maxSize = float.MaxValue)
|
||||
{
|
||||
if (minSize < 0)
|
||||
throw new ArgumentOutOfRangeException(nameof(minSize), "Must be greater than 0.");
|
||||
|
||||
if (minSize > maxSize)
|
||||
throw new ArgumentOutOfRangeException(nameof(minSize), $"Must be less than {nameof(maxSize)}.");
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(minSize);
|
||||
ArgumentOutOfRangeException.ThrowIfGreaterThan(minSize, maxSize);
|
||||
|
||||
Mode = mode;
|
||||
Size = size;
|
||||
|
||||
@@ -9,23 +9,32 @@ using osuTK.Graphics;
|
||||
namespace osu.Framework.Graphics.Containers.Markdown
|
||||
{
|
||||
/// <summary>
|
||||
/// Visualises a fenced code block.
|
||||
/// Visualises an indented/fenced code block.
|
||||
/// </summary>
|
||||
/// <code>
|
||||
/// ```
|
||||
/// code
|
||||
/// code1
|
||||
/// code2
|
||||
/// code3
|
||||
/// ```
|
||||
/// </code>
|
||||
public partial class MarkdownFencedCodeBlock : CompositeDrawable, IMarkdownTextFlowComponent
|
||||
/// <code>
|
||||
///
|
||||
/// code1
|
||||
/// code2
|
||||
/// code3
|
||||
///
|
||||
/// </code>
|
||||
public partial class MarkdownCodeBlock : CompositeDrawable, IMarkdownTextFlowComponent
|
||||
{
|
||||
private readonly FencedCodeBlock fencedCodeBlock;
|
||||
private readonly CodeBlock codeBlock;
|
||||
|
||||
[Resolved]
|
||||
private IMarkdownTextFlowComponent parentFlowComponent { get; set; } = null!;
|
||||
|
||||
public MarkdownFencedCodeBlock(FencedCodeBlock fencedCodeBlock)
|
||||
public MarkdownCodeBlock(CodeBlock codeBlock)
|
||||
{
|
||||
this.fencedCodeBlock = fencedCodeBlock;
|
||||
this.codeBlock = codeBlock;
|
||||
|
||||
AutoSizeAxes = Axes.Y;
|
||||
RelativeSizeAxes = Axes.X;
|
||||
@@ -42,8 +51,8 @@ namespace osu.Framework.Graphics.Containers.Markdown
|
||||
};
|
||||
|
||||
// Markdig sometimes appends empty lines to the processed block, only add original lines to the container
|
||||
for (int i = 0; i < fencedCodeBlock.Lines.Count; i++)
|
||||
textFlowContainer.AddParagraph(fencedCodeBlock.Lines.Lines[i].ToString());
|
||||
for (int i = 0; i < codeBlock.Lines.Count; i++)
|
||||
textFlowContainer.AddParagraph(codeBlock.Lines.Lines[i].ToString());
|
||||
}
|
||||
|
||||
protected virtual Drawable CreateBackground() => new Box
|
||||
@@ -241,8 +241,8 @@ namespace osu.Framework.Graphics.Containers.Markdown
|
||||
container.Add(CreateQuoteBlock(quoteBlock));
|
||||
break;
|
||||
|
||||
case FencedCodeBlock fencedCodeBlock:
|
||||
container.Add(CreateFencedCodeBlock(fencedCodeBlock));
|
||||
case CodeBlock codeBlock:
|
||||
container.Add(CreateCodeBlock(codeBlock));
|
||||
break;
|
||||
|
||||
case Table table:
|
||||
@@ -311,11 +311,11 @@ namespace osu.Framework.Graphics.Containers.Markdown
|
||||
protected virtual MarkdownQuoteBlock CreateQuoteBlock(QuoteBlock quoteBlock) => new MarkdownQuoteBlock(quoteBlock);
|
||||
|
||||
/// <summary>
|
||||
/// Creates the visualiser for a <see cref="FencedCodeBlock"/>.
|
||||
/// Creates the visualiser for a <see cref="CodeBlock"/>.
|
||||
/// </summary>
|
||||
/// <param name="fencedCodeBlock">The <see cref="FencedCodeBlock"/> to visualise.</param>
|
||||
/// <param name="codeBlock">The <see cref="CodeBlock"/> to visualise.</param>
|
||||
/// <returns>The visualiser.</returns>
|
||||
protected virtual MarkdownFencedCodeBlock CreateFencedCodeBlock(FencedCodeBlock fencedCodeBlock) => new MarkdownFencedCodeBlock(fencedCodeBlock);
|
||||
protected virtual MarkdownCodeBlock CreateCodeBlock(CodeBlock codeBlock) => new MarkdownCodeBlock(codeBlock);
|
||||
|
||||
/// <summary>
|
||||
/// Creates the visualiser for a <see cref="Table"/>.
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
@@ -88,7 +89,13 @@ namespace osu.Framework.Graphics.Containers
|
||||
|
||||
for (int i = 0; i < text.Length; i++)
|
||||
{
|
||||
if (i == 0 || char.IsSeparator(text[i - 1]) || char.IsControl(text[i - 1]))
|
||||
if (i == 0
|
||||
|| char.IsSeparator(text[i - 1])
|
||||
|| char.IsControl(text[i - 1])
|
||||
|| char.GetUnicodeCategory(text[i - 1]) == UnicodeCategory.DashPunctuation
|
||||
|| text[i - 1] == '/'
|
||||
|| text[i - 1] == '\\'
|
||||
|| (isCjkCharacter(text[i - 1]) && !char.IsPunctuation(text[i])))
|
||||
{
|
||||
words.Add(builder.ToString());
|
||||
builder.Clear();
|
||||
@@ -101,6 +108,8 @@ namespace osu.Framework.Graphics.Containers
|
||||
words.Add(builder.ToString());
|
||||
|
||||
return words.ToArray();
|
||||
|
||||
bool isCjkCharacter(char c) => c >= '\x2E80' && c <= '\x9FFF';
|
||||
}
|
||||
|
||||
protected virtual TSpriteText CreateSpriteText(TextFlowContainer textFlowContainer)
|
||||
|
||||
@@ -148,8 +148,8 @@ namespace osu.Framework.Graphics.Cursor
|
||||
progress.FadeColour(Color4.SkyBlue)
|
||||
.TransformTo(nameof(progress.InnerRadius), 0.2f)
|
||||
.TransformTo(nameof(progress.InnerRadius), 0.3f, 150, Easing.OutQuint)
|
||||
.TransformBindableTo(progress.Current, 0)
|
||||
.TransformBindableTo(progress.Current, 1, duration / 3 * 2);
|
||||
.ProgressTo(0)
|
||||
.ProgressTo(1, duration / 3 * 2);
|
||||
|
||||
using (BeginDelayedSequence(duration / 3 * 2))
|
||||
{
|
||||
@@ -165,7 +165,7 @@ namespace osu.Framework.Graphics.Cursor
|
||||
{
|
||||
this.FadeOut(400, Easing.OutQuint);
|
||||
|
||||
progress.TransformBindableTo(progress.Current, 0, 400, Easing.OutQuint)
|
||||
progress.ProgressTo(0, 400, Easing.OutQuint)
|
||||
.TransformTo(nameof(progress.InnerRadius), 0.2f, 50, Easing.OutQuint);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,9 +5,10 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using osu.Framework.Extensions.ListExtensions;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Input;
|
||||
using osu.Framework.Lists;
|
||||
|
||||
namespace osu.Framework.Graphics.Cursor
|
||||
{
|
||||
@@ -84,14 +85,21 @@ namespace osu.Framework.Graphics.Cursor
|
||||
|
||||
// Assuming we did _not_ end up terminating, then all found drawables are children of ours
|
||||
// and need to be added.
|
||||
childDrawables.UnionWith(newChildDrawables);
|
||||
foreach (var newChild in newChildDrawables)
|
||||
childDrawables.Add(newChild);
|
||||
|
||||
// Keep track of child drawables whose effects are managed by a nested effect container.
|
||||
// Note, that nested effect containers themselves could implement TTarget and
|
||||
// are still our own responsibility to handle.
|
||||
nestedTtcChildDrawables.UnionWith(
|
||||
((IEnumerable<IDrawable>)newChildDrawables).Reverse()
|
||||
.SkipWhile(d => d.Parent == this || (!(d.Parent is TSelf) && !nestedTtcChildDrawables.Contains(d.Parent))));
|
||||
for (int j = newChildDrawables.Count - 1; j >= 0; j--)
|
||||
{
|
||||
var d = newChildDrawables[j];
|
||||
|
||||
if (d.Parent == this || (!(d.Parent is TSelf) && !nestedTtcChildDrawables.Contains(d.Parent)))
|
||||
continue;
|
||||
|
||||
nestedTtcChildDrawables.Add(d);
|
||||
}
|
||||
|
||||
// Ignore drawables whose effects are managed by a nested effect container.
|
||||
if (nestedTtcChildDrawables.Contains(candidate))
|
||||
@@ -102,7 +110,9 @@ namespace osu.Framework.Graphics.Cursor
|
||||
}
|
||||
}
|
||||
|
||||
protected IEnumerable<TTarget> FindTargets()
|
||||
private static readonly SlimReadOnlyListWrapper<TTarget> empty_list = new SlimReadOnlyListWrapper<TTarget>(new List<TTarget>(0));
|
||||
|
||||
protected SlimReadOnlyListWrapper<TTarget> FindTargets()
|
||||
{
|
||||
findTargetChildren();
|
||||
|
||||
@@ -112,14 +122,14 @@ namespace osu.Framework.Graphics.Cursor
|
||||
newChildDrawables.Clear();
|
||||
|
||||
if (targetChildren.Count == 0)
|
||||
return Enumerable.Empty<TTarget>();
|
||||
return empty_list;
|
||||
|
||||
List<TTarget> result = new List<TTarget>(targetChildren);
|
||||
result.Reverse();
|
||||
|
||||
targetChildren.Clear();
|
||||
|
||||
return result;
|
||||
return result.AsSlimReadOnly();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
@@ -184,7 +183,7 @@ namespace osu.Framework.Graphics.Cursor
|
||||
object targetContent = getTargetContent(target);
|
||||
|
||||
if (targetContent is LocalisableString localisableString)
|
||||
return !string.IsNullOrEmpty(localisableString.Data?.ToString());
|
||||
return !LocalisableString.IsNullOrEmpty(localisableString);
|
||||
|
||||
return targetContent != null;
|
||||
}
|
||||
@@ -255,24 +254,34 @@ namespace osu.Framework.Graphics.Cursor
|
||||
if (appearDelay > 0 && (recentMousePositions.Count == 0 || lastRecordedPositionTime - recentMousePositions[0].Time < appearDelay - positionRecordInterval))
|
||||
return null;
|
||||
|
||||
recentMousePositions.RemoveAll(t => Time.Current - t.Time > appearDelay);
|
||||
for (int i = recentMousePositions.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (Time.Current - recentMousePositions[i].Time > appearDelay)
|
||||
recentMousePositions.RemoveAt(i);
|
||||
}
|
||||
|
||||
// For determining whether to show a tooltip we first select only those positions
|
||||
// which happened within a shorter, alpha-adjusted appear delay.
|
||||
double alphaModifiedAppearDelay = (1 - CurrentTooltip.Alpha) * appearDelay;
|
||||
var relevantPositions = recentMousePositions.Where(t => Time.Current - t.Time <= alphaModifiedAppearDelay);
|
||||
|
||||
// We then check whether all relevant positions fall within a radius of AppearRadius within the
|
||||
// first relevant position. If so, then the mouse has stayed within a small circular region of
|
||||
// AppearRadius for the duration of the modified appear delay, and we therefore want to display
|
||||
// the tooltip.
|
||||
Vector2 first = relevantPositions.FirstOrDefault().Position;
|
||||
Vector2? first = null;
|
||||
float appearRadiusSq = AppearRadius * AppearRadius;
|
||||
|
||||
if (relevantPositions.All(t => Vector2Extensions.DistanceSquared(t.Position, first) < appearRadiusSq))
|
||||
return targetCandidate;
|
||||
foreach (var mPos in recentMousePositions)
|
||||
{
|
||||
if (Time.Current - mPos.Time > alphaModifiedAppearDelay)
|
||||
continue;
|
||||
|
||||
return null;
|
||||
first ??= mPos.Position;
|
||||
if (Vector2Extensions.DistanceSquared(mPos.Position, (Vector2)first) > appearRadiusSq)
|
||||
return null;
|
||||
}
|
||||
|
||||
return targetCandidate;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user