Compare commits
2 Commits
@@ -3,25 +3,28 @@
|
||||
"isRoot": true,
|
||||
"tools": {
|
||||
"jetbrains.resharper.globaltools": {
|
||||
"version": "2025.2.3",
|
||||
"version": "2022.2.3",
|
||||
"commands": [
|
||||
"jb"
|
||||
],
|
||||
"rollForward": false
|
||||
]
|
||||
},
|
||||
"nvika": {
|
||||
"version": "2.2.0",
|
||||
"commands": [
|
||||
"nvika"
|
||||
]
|
||||
},
|
||||
"codefilesanity": {
|
||||
"version": "0.0.41",
|
||||
"version": "0.0.37",
|
||||
"commands": [
|
||||
"CodeFileSanity"
|
||||
],
|
||||
"rollForward": false
|
||||
]
|
||||
},
|
||||
"ppy.localisationanalyser.tools": {
|
||||
"version": "2025.1208.0",
|
||||
"version": "2023.712.0",
|
||||
"commands": [
|
||||
"localisation"
|
||||
],
|
||||
"rollForward": false
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,11 +19,6 @@ indent_style = space
|
||||
indent_size = 4
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
# temporary workaround for https://youtrack.jetbrains.com/issue/RIDER-130051/Cannot-resolve-symbol-inspections-incorrectly-firing-for-xmldoc-protected-member-references
|
||||
resharper_c_sharp_warnings_cs1574_cs1584_cs1581_cs1580_highlighting = hint
|
||||
# temporary workaround for https://youtrack.jetbrains.com/issue/RIDER-130381/Rider-does-not-respect-propagated-NoWarn-CS1591?backToIssues=false
|
||||
dotnet_diagnostic.CS1591.severity = none
|
||||
|
||||
#license header
|
||||
file_header_template = Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.\nSee the LICENCE file in the repository root for full licence text.
|
||||
|
||||
@@ -201,9 +196,6 @@ csharp_style_prefer_switch_expression = false:none
|
||||
|
||||
csharp_style_namespace_declarations = block_scoped:warning
|
||||
|
||||
#Style - C# 12 features
|
||||
csharp_style_prefer_primary_constructors = false
|
||||
|
||||
[*.{yaml,yml}]
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
|
||||
@@ -11,10 +11,6 @@ body:
|
||||
- Current open `priority:0` issues, filterable [here](https://github.com/ppy/osu/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3Apriority%3A0).
|
||||
- And most importantly, search for your issue both in the [issue listing](https://github.com/ppy/osu/issues) and the [Q&A discussion listing](https://github.com/ppy/osu/discussions/categories/q-a). If you find that it already exists, respond with a reaction or add any further information that may be helpful.
|
||||
|
||||
# ATTENTION LINUX USERS
|
||||
|
||||
If you are having an issue and it is hardware related, **please open a [q&a discussion](https://github.com/ppy/osu/discussions/categories/q-a)** instead of an issue. There's a high chance your issue is due to your system configuration, and not our software.
|
||||
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: Type
|
||||
@@ -42,7 +38,7 @@ body:
|
||||
- type: input
|
||||
attributes:
|
||||
label: Version
|
||||
description: The version you encountered this bug on. This is shown at the end of the settings overlay.
|
||||
description: The version you encountered this bug on. This is shown at the bottom of the main menu and also at the end of the settings screen.
|
||||
validations:
|
||||
required: true
|
||||
- type: markdown
|
||||
@@ -50,16 +46,22 @@ body:
|
||||
value: |
|
||||
## Logs
|
||||
|
||||
Attaching log files is required for **every** issue, regardless of whether you deem them required or not. See instructions below on how to find them.
|
||||
Attaching log files is required for every reported bug. See instructions below on how to find them.
|
||||
|
||||
**Logs are reset when you reopen the game.** If the game crashed or has been closed since you found the bug, retrieve the logs using the file explorer instead.
|
||||
|
||||
### Desktop platforms
|
||||
|
||||
If the game has not yet been closed since you found the bug:
|
||||
1. Head on to game settings and click on "Export logs"
|
||||
2. Click the notification to locate the file
|
||||
3. Drag the generated `.zip` files into the github issue window
|
||||
1. Head on to game settings and click on "Open osu! folder"
|
||||
2. Then open the `logs` folder located there
|
||||
|
||||

|
||||
The default places to find the logs on desktop platforms are as follows:
|
||||
- `%AppData%/osu/logs` *on Windows*
|
||||
- `~/.local/share/osu/logs` *on Linux*
|
||||
- `~/Library/Application Support/osu/logs` *on macOS*
|
||||
|
||||
If you have selected a custom location for the game files, you can find the `logs` folder there.
|
||||
|
||||
### Mobile platforms
|
||||
|
||||
@@ -67,6 +69,10 @@ body:
|
||||
- *On Android*, navigate to `Android/data/sh.ppy.osulazer/files/logs` using a file browser app.
|
||||
- *On iOS*, connect your device to a PC and copy the `logs` directory from the app's document storage using iTunes. (https://support.apple.com/en-us/HT201301#copy-to-computer)
|
||||
|
||||
---
|
||||
|
||||
After locating the `logs` folder, select all log files inside and drag them into the "Logs" box below.
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Logs
|
||||
|
||||
@@ -1,228 +0,0 @@
|
||||
name: "🔒diffcalc (do not use)"
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
id:
|
||||
type: string
|
||||
head-sha:
|
||||
type: string
|
||||
pr-url:
|
||||
type: string
|
||||
pr-text:
|
||||
type: string
|
||||
dispatch-inputs:
|
||||
type: string
|
||||
outputs:
|
||||
target:
|
||||
description: The comparison target.
|
||||
value: ${{ jobs.generator.outputs.target }}
|
||||
sheet:
|
||||
description: The comparison spreadsheet.
|
||||
value: ${{ jobs.generator.outputs.sheet }}
|
||||
secrets:
|
||||
DIFFCALC_GOOGLE_CREDENTIALS:
|
||||
required: true
|
||||
|
||||
env:
|
||||
GENERATOR_DIR: ${{ github.workspace }}/${{ inputs.id }}
|
||||
GENERATOR_ENV: ${{ github.workspace }}/${{ inputs.id }}/.env
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash -euo pipefail {0}
|
||||
|
||||
jobs:
|
||||
generator:
|
||||
name: Run
|
||||
runs-on: self-hosted
|
||||
timeout-minutes: 1440
|
||||
|
||||
outputs:
|
||||
target: ${{ steps.run.outputs.target }}
|
||||
sheet: ${{ steps.run.outputs.sheet }}
|
||||
|
||||
steps:
|
||||
- name: Checkout diffcalc-sheet-generator
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
path: ${{ inputs.id }}
|
||||
repository: 'smoogipoo/diffcalc-sheet-generator'
|
||||
|
||||
- name: Add base environment
|
||||
env:
|
||||
GOOGLE_CREDS_FILE: ${{ github.workspace }}/${{ inputs.id }}/google-credentials.json
|
||||
VARS_JSON: ${{ (vars != null && toJSON(vars)) || '' }}
|
||||
run: |
|
||||
# Required by diffcalc-sheet-generator
|
||||
cp '${{ env.GENERATOR_DIR }}/.env.sample' "${{ env.GENERATOR_ENV }}"
|
||||
|
||||
# Add Google credentials
|
||||
echo '${{ secrets.DIFFCALC_GOOGLE_CREDENTIALS }}' | base64 -d > "${{ env.GOOGLE_CREDS_FILE }}"
|
||||
|
||||
# Add repository variables
|
||||
echo "${VARS_JSON}" | jq -c '. | to_entries | .[]' | while read -r line; do
|
||||
opt=$(jq -r '.key' <<< ${line})
|
||||
val=$(jq -r '.value' <<< ${line})
|
||||
|
||||
if [[ "${opt}" =~ ^DIFFCALC_ ]]; then
|
||||
optNoPrefix=$(echo "${opt}" | cut -d '_' -f2-)
|
||||
sed -i "s;^${optNoPrefix}=.*$;${optNoPrefix}=${val};" "${{ env.GENERATOR_ENV }}"
|
||||
fi
|
||||
done
|
||||
|
||||
- name: Add HEAD environment
|
||||
run: |
|
||||
sed -i "s;^OSU_A=.*$;OSU_A=${{ inputs.head-sha }};" "${{ env.GENERATOR_ENV }}"
|
||||
|
||||
- name: Add pull-request environment
|
||||
if: ${{ inputs.pr-url != '' }}
|
||||
run: |
|
||||
sed -i "s;^OSU_B=.*$;OSU_B=${{ inputs.pr-url }};" "${{ env.GENERATOR_ENV }}"
|
||||
|
||||
- name: Add comment environment
|
||||
if: ${{ inputs.pr-text != '' }}
|
||||
env:
|
||||
PR_TEXT: ${{ inputs.pr-text }}
|
||||
run: |
|
||||
# Add comment environment
|
||||
echo "${PR_TEXT}" | sed -r 's/\r$//' | { grep -E '^\w+=' || true; } | while read -r line; do
|
||||
opt=$(echo "${line}" | cut -d '=' -f1)
|
||||
sed -i "s;^${opt}=.*$;${line};" "${{ env.GENERATOR_ENV }}"
|
||||
done
|
||||
|
||||
- name: Add dispatch environment
|
||||
if: ${{ inputs.dispatch-inputs != '' }}
|
||||
env:
|
||||
DISPATCH_INPUTS_JSON: ${{ inputs.dispatch-inputs }}
|
||||
run: |
|
||||
function get_input() {
|
||||
echo "${DISPATCH_INPUTS_JSON}" | jq -r ".\"$1\""
|
||||
}
|
||||
|
||||
osu_a=$(get_input 'osu-a')
|
||||
osu_b=$(get_input 'osu-b')
|
||||
ruleset=$(get_input 'ruleset')
|
||||
generators=$(get_input 'generators')
|
||||
difficulty_calculator_a=$(get_input 'difficulty-calculator-a')
|
||||
difficulty_calculator_b=$(get_input 'difficulty-calculator-b')
|
||||
score_processor_a=$(get_input 'score-processor-a')
|
||||
score_processor_b=$(get_input 'score-processor-b')
|
||||
converts=$(get_input 'converts')
|
||||
ranked_only=$(get_input 'ranked-only')
|
||||
|
||||
sed -i "s;^OSU_B=.*$;OSU_B=${osu_b};" "${{ env.GENERATOR_ENV }}"
|
||||
sed -i "s/^RULESET=.*$/RULESET=${ruleset}/" "${{ env.GENERATOR_ENV }}"
|
||||
sed -i "s/^GENERATORS=.*$/GENERATORS=${generators}/" "${{ env.GENERATOR_ENV }}"
|
||||
|
||||
if [[ "${osu_a}" != 'latest' ]]; then
|
||||
sed -i "s;^OSU_A=.*$;OSU_A=${osu_a};" "${{ env.GENERATOR_ENV }}"
|
||||
fi
|
||||
|
||||
if [[ "${difficulty_calculator_a}" != 'latest' ]]; then
|
||||
sed -i "s;^DIFFICULTY_CALCULATOR_A=.*$;DIFFICULTY_CALCULATOR_A=${difficulty_calculator_a};" "${{ env.GENERATOR_ENV }}"
|
||||
fi
|
||||
|
||||
if [[ "${difficulty_calculator_b}" != 'latest' ]]; then
|
||||
sed -i "s;^DIFFICULTY_CALCULATOR_B=.*$;DIFFICULTY_CALCULATOR_B=${difficulty_calculator_b};" "${{ env.GENERATOR_ENV }}"
|
||||
fi
|
||||
|
||||
if [[ "${score_processor_a}" != 'latest' ]]; then
|
||||
sed -i "s;^SCORE_PROCESSOR_A=.*$;SCORE_PROCESSOR_A=${score_processor_a};" "${{ env.GENERATOR_ENV }}"
|
||||
fi
|
||||
|
||||
if [[ "${score_processor_b}" != 'latest' ]]; then
|
||||
sed -i "s;^SCORE_PROCESSOR_B=.*$;SCORE_PROCESSOR_B=${score_processor_b};" "${{ env.GENERATOR_ENV }}"
|
||||
fi
|
||||
|
||||
if [[ "${converts}" == 'true' ]]; then
|
||||
sed -i 's/^NO_CONVERTS=.*$/NO_CONVERTS=0/' "${{ env.GENERATOR_ENV }}"
|
||||
else
|
||||
sed -i 's/^NO_CONVERTS=.*$/NO_CONVERTS=1/' "${{ env.GENERATOR_ENV }}"
|
||||
fi
|
||||
|
||||
if [[ "${ranked_only}" == 'true' ]]; then
|
||||
sed -i 's/^RANKED_ONLY=.*$/RANKED_ONLY=1/' "${{ env.GENERATOR_ENV }}"
|
||||
else
|
||||
sed -i 's/^RANKED_ONLY=.*$/RANKED_ONLY=0/' "${{ env.GENERATOR_ENV }}"
|
||||
fi
|
||||
|
||||
- name: Query latest scores
|
||||
id: query-scores
|
||||
run: |
|
||||
ruleset=$(cat ${{ env.GENERATOR_ENV }} | grep -E '^RULESET=' | cut -d '=' -f2-)
|
||||
performance_data_name=$(curl -s "https://data.ppy.sh/" | grep "performance_${ruleset}_top_1000\b" | tail -1 | awk -F "'" '{print $2}' | sed 's/\.tar\.bz2//g')
|
||||
|
||||
echo "TARGET_DIR=${{ env.GENERATOR_DIR }}/sql/${ruleset}" >> "${GITHUB_OUTPUT}"
|
||||
echo "DATA_NAME=${performance_data_name}" >> "${GITHUB_OUTPUT}"
|
||||
echo "DATA_PKG=${performance_data_name}.tar.bz2" >> "${GITHUB_OUTPUT}"
|
||||
|
||||
- name: Restore score cache
|
||||
id: restore-score-cache
|
||||
uses: maxnowack/local-cache@720e69c948191660a90aa1cf6a42fc4d2dacdf30 # v2
|
||||
with:
|
||||
path: ${{ steps.query-scores.outputs.DATA_PKG }}
|
||||
key: ${{ steps.query-scores.outputs.DATA_NAME }}
|
||||
|
||||
- name: Download scores
|
||||
if: steps.restore-score-cache.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
wget -q -O "${{ steps.query-scores.outputs.DATA_PKG }}" "https://data.ppy.sh/${{ steps.query-scores.outputs.DATA_PKG }}"
|
||||
|
||||
- name: Extract scores
|
||||
run: |
|
||||
tar -I lbzip2 -xf "${{ steps.query-scores.outputs.DATA_PKG }}"
|
||||
rm -r "${{ steps.query-scores.outputs.TARGET_DIR }}"
|
||||
mv "${{ steps.query-scores.outputs.DATA_NAME }}" "${{ steps.query-scores.outputs.TARGET_DIR }}"
|
||||
|
||||
- name: Query latest beatmaps
|
||||
id: query-beatmaps
|
||||
run: |
|
||||
beatmaps_data_name=$(curl -s "https://data.ppy.sh/" | grep "osu_files" | tail -1 | awk -F "'" '{print $2}' | sed 's/\.tar\.bz2//g')
|
||||
|
||||
echo "TARGET_DIR=${{ env.GENERATOR_DIR }}/beatmaps" >> "${GITHUB_OUTPUT}"
|
||||
echo "DATA_NAME=${beatmaps_data_name}" >> "${GITHUB_OUTPUT}"
|
||||
echo "DATA_PKG=${beatmaps_data_name}.tar.bz2" >> "${GITHUB_OUTPUT}"
|
||||
|
||||
- name: Restore beatmap cache
|
||||
id: restore-beatmap-cache
|
||||
uses: maxnowack/local-cache@720e69c948191660a90aa1cf6a42fc4d2dacdf30 # v2
|
||||
with:
|
||||
path: ${{ steps.query-beatmaps.outputs.DATA_PKG }}
|
||||
key: ${{ steps.query-beatmaps.outputs.DATA_NAME }}
|
||||
|
||||
- name: Download beatmap
|
||||
if: steps.restore-beatmap-cache.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
wget -q -O "${{ steps.query-beatmaps.outputs.DATA_PKG }}" "https://data.ppy.sh/${{ steps.query-beatmaps.outputs.DATA_PKG }}"
|
||||
|
||||
- name: Extract beatmap
|
||||
run: |
|
||||
tar -I lbzip2 -xf "${{ steps.query-beatmaps.outputs.DATA_PKG }}"
|
||||
rm -r "${{ steps.query-beatmaps.outputs.TARGET_DIR }}"
|
||||
mv "${{ steps.query-beatmaps.outputs.DATA_NAME }}" "${{ steps.query-beatmaps.outputs.TARGET_DIR }}"
|
||||
|
||||
- name: Run
|
||||
id: run
|
||||
run: |
|
||||
# Add the GitHub token. This needs to be done here because it's unique per-job.
|
||||
sed -i 's/^GH_TOKEN=.*$/GH_TOKEN=${{ github.token }}/' "${{ env.GENERATOR_ENV }}"
|
||||
|
||||
cd "${{ env.GENERATOR_DIR }}"
|
||||
|
||||
docker compose up --build --detach
|
||||
docker compose logs --follow &
|
||||
docker compose wait generator
|
||||
|
||||
link=$(docker compose logs --tail 10 generator | grep 'http' | sed -E 's/^.*(http.*)$/\1/')
|
||||
target=$(cat "${{ env.GENERATOR_ENV }}" | grep -E '^OSU_B=' | cut -d '=' -f2-)
|
||||
|
||||
echo "target=${target}" >> "${GITHUB_OUTPUT}"
|
||||
echo "sheet=${link}" >> "${GITHUB_OUTPUT}"
|
||||
|
||||
- name: Shutdown
|
||||
if: ${{ always() }}
|
||||
run: |
|
||||
cd "${{ env.GENERATOR_DIR }}"
|
||||
docker compose down --volumes
|
||||
rm -rf "${{ env.GENERATOR_DIR }}"
|
||||
@@ -6,7 +6,6 @@ concurrency:
|
||||
|
||||
permissions:
|
||||
contents: read # to fetch code (actions/checkout)
|
||||
security-events: write # for reporting InspectCode issues
|
||||
|
||||
jobs:
|
||||
inspect-code:
|
||||
@@ -14,12 +13,19 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install .NET 8.0.x
|
||||
uses: actions/setup-dotnet@v5
|
||||
# FIXME: Tools won't run in .NET 6.0 unless you install 3.1.x LTS side by side.
|
||||
# https://itnext.io/how-to-support-multiple-net-sdks-in-github-actions-workflows-b988daa884e
|
||||
- name: Install .NET 3.1.x LTS
|
||||
uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: "8.0.x"
|
||||
dotnet-version: "3.1.x"
|
||||
|
||||
- name: Install .NET 6.0.x
|
||||
uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: "6.0.x"
|
||||
|
||||
- name: Restore Tools
|
||||
run: dotnet tool restore
|
||||
@@ -28,7 +34,7 @@ jobs:
|
||||
run: dotnet restore osu.Desktop.slnf
|
||||
|
||||
- name: Restore inspectcode cache
|
||||
uses: actions/cache@v5
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{ github.workspace }}/inspectcode
|
||||
key: inspectcode-${{ hashFiles('.config/dotnet-tools.json', '.github/workflows/ci.yml', 'osu.sln*', 'osu*.slnf', '.editorconfig', '.globalconfig', 'CodeAnalysis/*', '**/*.csproj', '**/*.props') }}
|
||||
@@ -50,14 +56,10 @@ jobs:
|
||||
exit $exit_code
|
||||
|
||||
- name: InspectCode
|
||||
uses: JetBrains/ReSharper-InspectCode@v0.12
|
||||
with:
|
||||
# this is WTF tier but if you don't specify *both* of these the defaults assume `build: true`
|
||||
build: false
|
||||
no-build: true
|
||||
solution: ./osu.Desktop.slnf
|
||||
caches-home: inspectcode
|
||||
verbosity: WARN
|
||||
run: dotnet jb inspectcode $(pwd)/osu.Desktop.slnf --no-build --output="inspectcodereport.xml" --caches-home="inspectcode" --verbosity=WARN
|
||||
|
||||
- name: NVika
|
||||
run: dotnet nvika parsereport "${{github.workspace}}/inspectcodereport.xml" --treatwarningsaserrors
|
||||
|
||||
test:
|
||||
name: Test
|
||||
@@ -69,119 +71,81 @@ jobs:
|
||||
matrix:
|
||||
os:
|
||||
- { prettyname: Windows, fullname: windows-latest }
|
||||
# macOS runner performance has gotten unbearably slow so let's turn them off temporarily.
|
||||
# - { prettyname: macOS, fullname: macos-latest }
|
||||
- { prettyname: macOS, fullname: macos-latest }
|
||||
- { prettyname: Linux, fullname: ubuntu-latest }
|
||||
threadingMode: ['SingleThread', 'MultiThreaded']
|
||||
timeout-minutes: 120
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install .NET 8.0.x
|
||||
uses: actions/setup-dotnet@v5
|
||||
- name: Install .NET 6.0.x
|
||||
uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: "8.0.x"
|
||||
dotnet-version: "6.0.x"
|
||||
|
||||
- name: Compile
|
||||
run: dotnet build -c Debug -warnaserror osu.Desktop.slnf
|
||||
|
||||
- name: Test
|
||||
run: >
|
||||
dotnet test
|
||||
osu.Game.Tests/bin/Debug/**/osu.Game.Tests.dll
|
||||
osu.Game.Rulesets.Osu.Tests/bin/Debug/**/osu.Game.Rulesets.Osu.Tests.dll
|
||||
osu.Game.Rulesets.Taiko.Tests/bin/Debug/**/osu.Game.Rulesets.Taiko.Tests.dll
|
||||
osu.Game.Rulesets.Catch.Tests/bin/Debug/**/osu.Game.Rulesets.Catch.Tests.dll
|
||||
osu.Game.Rulesets.Mania.Tests/bin/Debug/**/osu.Game.Rulesets.Mania.Tests.dll
|
||||
osu.Game.Tournament.Tests/bin/Debug/**/osu.Game.Tournament.Tests.dll
|
||||
Templates/**/*.Tests/bin/Debug/**/*.Tests.dll
|
||||
--logger "trx;LogFileName=TestResults-${{matrix.os.prettyname}}-${{matrix.threadingMode}}.trx"
|
||||
--
|
||||
NUnit.ConsoleOut=0
|
||||
run: dotnet test $pwd/**/*.Tests/bin/Debug/*/*.Tests.dll --logger "trx;LogFileName=TestResults-${{matrix.os.prettyname}}-${{matrix.threadingMode}}.trx" -- NUnit.ConsoleOut=0
|
||||
shell: pwsh
|
||||
|
||||
# Attempt to upload results even if test fails.
|
||||
# https://docs.github.com/en/actions/reference/workflows-and-actions/expressions#cancelled
|
||||
# https://docs.github.com/en/actions/reference/context-and-expression-syntax-for-github-actions#always
|
||||
- name: Upload Test Results
|
||||
uses: actions/upload-artifact@v7
|
||||
if: ${{ !cancelled() }}
|
||||
uses: actions/upload-artifact@v3
|
||||
if: ${{ always() }}
|
||||
with:
|
||||
name: osu-test-results-${{matrix.os.prettyname}}-${{matrix.threadingMode}}
|
||||
path: ${{github.workspace}}/TestResults/TestResults-${{matrix.os.prettyname}}-${{matrix.threadingMode}}.trx
|
||||
|
||||
test-results:
|
||||
name: Test results
|
||||
runs-on: ubuntu-latest
|
||||
# we want to wait for the `test` job to complete, but run regardless of whether it succeeds or fails
|
||||
# https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax#example-not-requiring-successful-dependent-jobs
|
||||
if: ${{ !cancelled() }}
|
||||
needs: test
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Download results
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
pattern: osu-test-results-*
|
||||
merge-multiple: true
|
||||
|
||||
- name: Add test results summary to workflow run
|
||||
uses: dorny/test-reporter@v3.0.0
|
||||
with:
|
||||
name: Results
|
||||
path: "*.trx"
|
||||
reporter: dotnet-trx
|
||||
list-suites: 'failed'
|
||||
list-tests: 'failed'
|
||||
use-actions-summary: 'true'
|
||||
|
||||
build-only-android:
|
||||
name: Build only (Android)
|
||||
runs-on: windows-latest
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup JDK 11
|
||||
uses: actions/setup-java@v5
|
||||
- name: Install .NET 6.0.x
|
||||
uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
distribution: microsoft
|
||||
java-version: 11
|
||||
|
||||
- name: Install .NET 8.0.x
|
||||
uses: actions/setup-dotnet@v5
|
||||
with:
|
||||
dotnet-version: "8.0.x"
|
||||
dotnet-version: "6.0.x"
|
||||
|
||||
- name: Install .NET workloads
|
||||
run: dotnet workload install android
|
||||
run: dotnet workload install maui-android
|
||||
|
||||
- name: Compile
|
||||
run: dotnet build -c Debug osu.Android.slnf
|
||||
|
||||
build-only-ios:
|
||||
name: Build only (iOS)
|
||||
runs-on: macos-15
|
||||
# `macos-13` is required, because Xcode 14.3 is required (see below).
|
||||
# TODO: can be changed to `macos-latest` once `macos-13` becomes latest (currently in beta)
|
||||
runs-on: macos-13
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install .NET 8.0.x
|
||||
uses: actions/setup-dotnet@v5
|
||||
# newest Microsoft.iOS.Sdk versions require Xcode 14.3.
|
||||
# 14.3 is currently not the default Xcode version (https://github.com/actions/runner-images/blob/main/images/macos/macos-13-Readme.md#xcode),
|
||||
# so set it manually.
|
||||
# TODO: remove when 14.3 becomes the default Xcode version.
|
||||
- name: Set Xcode version
|
||||
shell: bash
|
||||
run: |
|
||||
sudo xcode-select -s "/Applications/Xcode_14.3.app"
|
||||
echo "MD_APPLE_SDK_ROOT=/Applications/Xcode_14.3.app" >> $GITHUB_ENV
|
||||
|
||||
- name: Install .NET 6.0.x
|
||||
uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: "8.0.x"
|
||||
dotnet-version: "6.0.x"
|
||||
|
||||
- name: Install .NET Workloads
|
||||
run: dotnet workload install ios
|
||||
|
||||
# https://github.com/dotnet/macios/issues/19157
|
||||
# https://github.com/actions/runner-images/issues/12758
|
||||
- name: Use Xcode 16.4
|
||||
run: sudo xcode-select -switch /Applications/Xcode_16.4.app
|
||||
run: dotnet workload install maui-ios
|
||||
|
||||
- name: Build
|
||||
run: dotnet build -c Debug osu.iOS.slnf
|
||||
run: dotnet build -c Debug osu.iOS
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
name: Pack and nuget
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '*.*.*'
|
||||
- '!*-*'
|
||||
|
||||
jobs:
|
||||
notify_pending_production_deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Submit pending deployment notification
|
||||
run: |
|
||||
export TITLE="Pending osu Production Deployment: $GITHUB_REF_NAME"
|
||||
export URL="https://github.com/ppy/osu/actions/runs/$GITHUB_RUN_ID"
|
||||
export DESCRIPTION="Awaiting approval for building NuGet packages for tag $GITHUB_REF_NAME:
|
||||
[View Workflow Run]($URL)"
|
||||
export ACTOR_ICON="https://avatars.githubusercontent.com/u/$GITHUB_ACTOR_ID"
|
||||
|
||||
BODY="$(jq --null-input '{
|
||||
"embeds": [
|
||||
{
|
||||
"title": env.TITLE,
|
||||
"color": 15098112,
|
||||
"description": env.DESCRIPTION,
|
||||
"url": env.URL,
|
||||
"author": {
|
||||
"name": env.GITHUB_ACTOR,
|
||||
"icon_url": env.ACTOR_ICON
|
||||
}
|
||||
}
|
||||
]
|
||||
}')"
|
||||
|
||||
curl \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$BODY" \
|
||||
"${{ secrets.DISCORD_INFRA_WEBHOOK_URL }}"
|
||||
|
||||
pack:
|
||||
name: Pack
|
||||
runs-on: ubuntu-latest
|
||||
environment: production
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- 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@v5
|
||||
with:
|
||||
dotnet-version: "8.0.x"
|
||||
|
||||
- name: Pack
|
||||
run: |
|
||||
# Replace project references in templates with package reference, because they're included as source files.
|
||||
dotnet remove Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/osu.Game.Rulesets.EmptyFreeform.csproj reference osu.Game/osu.Game.csproj
|
||||
dotnet remove Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/osu.Game.Rulesets.Pippidon.csproj reference osu.Game/osu.Game.csproj
|
||||
dotnet remove Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/osu.Game.Rulesets.EmptyScrolling.csproj reference osu.Game/osu.Game.csproj
|
||||
dotnet remove Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/osu.Game.Rulesets.Pippidon.csproj reference osu.Game/osu.Game.csproj
|
||||
|
||||
dotnet add Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/osu.Game.Rulesets.EmptyFreeform.csproj package ppy.osu.Game -n -v ${{ github.ref_name }}
|
||||
dotnet add Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/osu.Game.Rulesets.Pippidon.csproj package ppy.osu.Game -n -v ${{ github.ref_name }}
|
||||
dotnet add Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/osu.Game.Rulesets.EmptyScrolling.csproj package ppy.osu.Game -n -v ${{ github.ref_name }}
|
||||
dotnet add Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/osu.Game.Rulesets.Pippidon.csproj package ppy.osu.Game -n -v ${{ github.ref_name }}
|
||||
|
||||
# Pack
|
||||
dotnet pack -c Release osu.Game /p:Version=${{ github.ref_name }} /p:GenerateDocumentationFile=true /p:IncludeSymbols=true /p:SymbolPackageFormat=snupkg -o ${{steps.artifactsPath.outputs.nuget_artifacts}}
|
||||
dotnet pack -c Release osu.Game.Rulesets.Osu /p:Version=${{ github.ref_name }} /p:GenerateDocumentationFile=true /p:IncludeSymbols=true /p:SymbolPackageFormat=snupkg -o ${{steps.artifactsPath.outputs.nuget_artifacts}}
|
||||
dotnet pack -c Release osu.Game.Rulesets.Taiko /p:Version=${{ github.ref_name }} /p:GenerateDocumentationFile=true /p:IncludeSymbols=true /p:SymbolPackageFormat=snupkg -o ${{steps.artifactsPath.outputs.nuget_artifacts}}
|
||||
dotnet pack -c Release osu.Game.Rulesets.Catch /p:Version=${{ github.ref_name }} /p:GenerateDocumentationFile=true /p:IncludeSymbols=true /p:SymbolPackageFormat=snupkg -o ${{steps.artifactsPath.outputs.nuget_artifacts}}
|
||||
dotnet pack -c Release osu.Game.Rulesets.Mania /p:Version=${{ github.ref_name }} /p:GenerateDocumentationFile=true /p:IncludeSymbols=true /p:SymbolPackageFormat=snupkg -o ${{steps.artifactsPath.outputs.nuget_artifacts}}
|
||||
dotnet pack -c Release Templates /p:Version=${{ github.ref_name }} -o ${{steps.artifactsPath.outputs.nuget_artifacts}}
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: osu
|
||||
path: |
|
||||
${{steps.artifactsPath.outputs.nuget_artifacts}}/*.nupkg
|
||||
${{steps.artifactsPath.outputs.nuget_artifacts}}/*.snupkg
|
||||
|
||||
- name: Publish packages to nuget.org
|
||||
run: dotnet nuget push ${{steps.artifactsPath.outputs.nuget_artifacts}}/*.nupkg --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json
|
||||
@@ -14,8 +14,8 @@
|
||||
#
|
||||
# The workflow can be run in two ways:
|
||||
# 1. Via workflow dispatch.
|
||||
# 2. By an owner of the repository posting a pull request or issue comment containing `!diffcalc`.
|
||||
# For pull requests, the workflow will assume the pull request as the target to compare against (i.e. the `OSU_B` variable).
|
||||
# 2. By an owner of the repository posting a pull request or issue comment containing `!diffcalc`.
|
||||
# For pull requests, the workflow will assume the pull request as the target to compare against (i.e. the `OSU_B` variable).
|
||||
# Any lines in the comment of the form `KEY=VALUE` are treated as variables for the generator.
|
||||
#
|
||||
# ## Google Service Account
|
||||
@@ -101,96 +101,265 @@ permissions:
|
||||
pull-requests: write
|
||||
|
||||
env:
|
||||
EXECUTION_ID: execution-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash -euo pipefail {0}
|
||||
COMMENT_TAG: execution-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}
|
||||
|
||||
jobs:
|
||||
check-permissions:
|
||||
name: Check permissions
|
||||
wait-for-queue:
|
||||
name: "Wait for previous workflows"
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event_name == 'workflow_dispatch' || contains(github.event.comment.body, '!diffcalc') }}
|
||||
if: ${{ !cancelled() && (github.event_name == 'workflow_dispatch' || contains(github.event.comment.body, '!diffcalc') && github.event.comment.author_association == 'OWNER') }}
|
||||
timeout-minutes: 50400 # 35 days, the maximum for jobs.
|
||||
steps:
|
||||
- name: Check permissions
|
||||
run: |
|
||||
ALLOWED_USERS=(smoogipoo peppy bdach frenzibyte tsunyoku stanriders)
|
||||
for i in "${ALLOWED_USERS[@]}"; do
|
||||
if [[ "${{ github.actor }}" == "$i" ]]; then
|
||||
exit 0
|
||||
fi
|
||||
done
|
||||
exit 1
|
||||
|
||||
run-diffcalc:
|
||||
name: Run spreadsheet generator
|
||||
needs: check-permissions
|
||||
uses: ./.github/workflows/_diffcalc_processor.yml
|
||||
with:
|
||||
# Can't reference env... Why GitHub, WHY?
|
||||
id: execution-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}
|
||||
head-sha: https://github.com/${{ github.repository }}/commit/${{ github.event.pull_request.head.sha || github.sha }}
|
||||
pr-url: ${{ github.event.issue.pull_request.html_url || '' }}
|
||||
pr-text: ${{ github.event.comment.body || '' }}
|
||||
dispatch-inputs: ${{ (github.event.type == 'workflow_dispatch' && toJSON(inputs)) || '' }}
|
||||
secrets:
|
||||
DIFFCALC_GOOGLE_CREDENTIALS: ${{ secrets.DIFFCALC_GOOGLE_CREDENTIALS }}
|
||||
- uses: ahmadnassri/action-workflow-queue@v1
|
||||
with:
|
||||
timeout: 2147483647 # Around 24 days, maximum supported.
|
||||
delay: 120000 # Poll every 2 minutes. API seems fairly low on this one.
|
||||
|
||||
create-comment:
|
||||
name: Create PR comment
|
||||
needs: check-permissions
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event_name == 'issue_comment' && github.event.issue.pull_request }}
|
||||
if: ${{ github.event_name == 'issue_comment' && github.event.issue.pull_request && contains(github.event.comment.body, '!diffcalc') && github.event.comment.author_association == 'OWNER' }}
|
||||
steps:
|
||||
- name: Create comment
|
||||
uses: thollander/actions-comment-pull-request@fabd468d3a1a0b97feee5f6b9e499eab0dd903f6 # v2.5.0
|
||||
uses: thollander/actions-comment-pull-request@v2
|
||||
with:
|
||||
comment_tag: ${{ env.EXECUTION_ID }}
|
||||
comment_tag: ${{ env.COMMENT_TAG }}
|
||||
message: |
|
||||
Difficulty calculation queued -- please wait! (${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})
|
||||
|
||||
*This comment will update on completion*
|
||||
|
||||
output-cli:
|
||||
name: Info
|
||||
needs: run-diffcalc
|
||||
runs-on: ubuntu-latest
|
||||
directory:
|
||||
name: Prepare directory
|
||||
needs: wait-for-queue
|
||||
runs-on: self-hosted
|
||||
if: ${{ !cancelled() && (github.event_name == 'workflow_dispatch' || contains(github.event.comment.body, '!diffcalc') && github.event.comment.author_association == 'OWNER') }}
|
||||
outputs:
|
||||
GENERATOR_DIR: ${{ steps.set-outputs.outputs.GENERATOR_DIR }}
|
||||
GENERATOR_ENV: ${{ steps.set-outputs.outputs.GENERATOR_ENV }}
|
||||
GOOGLE_CREDS_FILE: ${{ steps.set-outputs.outputs.GOOGLE_CREDS_FILE }}
|
||||
steps:
|
||||
- name: Output info
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Checkout diffcalc-sheet-generator
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
path: 'diffcalc-sheet-generator'
|
||||
repository: 'smoogipoo/diffcalc-sheet-generator'
|
||||
|
||||
- name: Set outputs
|
||||
id: set-outputs
|
||||
run: |
|
||||
echo "Target: ${{ needs.run-diffcalc.outputs.target }}"
|
||||
echo "Spreadsheet: ${{ needs.run-diffcalc.outputs.sheet }}"
|
||||
echo "GENERATOR_DIR=${{ github.workspace }}/diffcalc-sheet-generator" >> "${GITHUB_OUTPUT}"
|
||||
echo "GENERATOR_ENV=${{ github.workspace }}/diffcalc-sheet-generator/.env" >> "${GITHUB_OUTPUT}"
|
||||
echo "GOOGLE_CREDS_FILE=${{ github.workspace }}/diffcalc-sheet-generator/google-credentials.json" >> "${GITHUB_OUTPUT}"
|
||||
|
||||
environment:
|
||||
name: Setup environment
|
||||
needs: directory
|
||||
runs-on: self-hosted
|
||||
if: ${{ !cancelled() && needs.directory.result == 'success' }}
|
||||
env:
|
||||
VARS_JSON: ${{ toJSON(vars) }}
|
||||
steps:
|
||||
- name: Add base environment
|
||||
run: |
|
||||
# Required by diffcalc-sheet-generator
|
||||
cp '${{ github.workspace }}/diffcalc-sheet-generator/.env.sample' "${{ needs.directory.outputs.GENERATOR_ENV }}"
|
||||
|
||||
# Add Google credentials
|
||||
echo '${{ secrets.DIFFCALC_GOOGLE_CREDENTIALS }}' | base64 -d > "${{ needs.directory.outputs.GOOGLE_CREDS_FILE }}"
|
||||
|
||||
# Add repository variables
|
||||
echo "${VARS_JSON}" | jq -c '. | to_entries | .[]' | while read -r line; do
|
||||
opt=$(jq -r '.key' <<< ${line})
|
||||
val=$(jq -r '.value' <<< ${line})
|
||||
|
||||
if [[ "${opt}" =~ ^DIFFCALC_ ]]; then
|
||||
optNoPrefix=$(echo "${opt}" | cut -d '_' -f2-)
|
||||
sed -i "s;^${optNoPrefix}=.*$;${optNoPrefix}=${val};" "${{ needs.directory.outputs.GENERATOR_ENV }}"
|
||||
fi
|
||||
done
|
||||
|
||||
- name: Add pull-request environment
|
||||
if: ${{ github.event_name == 'issue_comment' && github.event.issue.pull_request }}
|
||||
run: |
|
||||
sed -i "s;^OSU_B=.*$;OSU_B=${{ github.event.issue.pull_request.url }};" "${{ needs.directory.outputs.GENERATOR_ENV }}"
|
||||
|
||||
- name: Add comment environment
|
||||
if: ${{ github.event_name == 'issue_comment' }}
|
||||
run: |
|
||||
# Add comment environment
|
||||
echo '${{ github.event.comment.body }}' | sed -r 's/\r$//' | grep -E '^\w+=' | while read -r line; do
|
||||
opt=$(echo ${line} | cut -d '=' -f1)
|
||||
sed -i "s;^${opt}=.*$;${line};" "${{ needs.directory.outputs.GENERATOR_ENV }}"
|
||||
done
|
||||
|
||||
- name: Add dispatch environment
|
||||
if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||
run: |
|
||||
sed -i 's;^OSU_B=.*$;OSU_B=${{ inputs.osu-b }};' "${{ needs.directory.outputs.GENERATOR_ENV }}"
|
||||
sed -i 's/^RULESET=.*$/RULESET=${{ inputs.ruleset }}/' "${{ needs.directory.outputs.GENERATOR_ENV }}"
|
||||
sed -i 's/^GENERATORS=.*$/GENERATORS=${{ inputs.generators }}/' "${{ needs.directory.outputs.GENERATOR_ENV }}"
|
||||
|
||||
if [[ '${{ inputs.osu-a }}' != 'latest' ]]; then
|
||||
sed -i 's;^OSU_A=.*$;OSU_A=${{ inputs.osu-a }};' "${{ needs.directory.outputs.GENERATOR_ENV }}"
|
||||
fi
|
||||
|
||||
if [[ '${{ inputs.difficulty-calculator-a }}' != 'latest' ]]; then
|
||||
sed -i 's;^DIFFICULTY_CALCULATOR_A=.*$;DIFFICULTY_CALCULATOR_A=${{ inputs.difficulty-calculator-a }};' "${{ needs.directory.outputs.GENERATOR_ENV }}"
|
||||
fi
|
||||
|
||||
if [[ '${{ inputs.difficulty-calculator-b }}' != 'latest' ]]; then
|
||||
sed -i 's;^DIFFICULTY_CALCULATOR_B=.*$;DIFFICULTY_CALCULATOR_B=${{ inputs.difficulty-calculator-b }};' "${{ needs.directory.outputs.GENERATOR_ENV }}"
|
||||
fi
|
||||
|
||||
if [[ '${{ inputs.score-processor-a }}' != 'latest' ]]; then
|
||||
sed -i 's;^SCORE_PROCESSOR_A=.*$;SCORE_PROCESSOR_A=${{ inputs.score-processor-a }};' "${{ needs.directory.outputs.GENERATOR_ENV }}"
|
||||
fi
|
||||
|
||||
if [[ '${{ inputs.score-processor-b }}' != 'latest' ]]; then
|
||||
sed -i 's;^SCORE_PROCESSOR_B=.*$;SCORE_PROCESSOR_B=${{ inputs.score-processor-b }};' "${{ needs.directory.outputs.GENERATOR_ENV }}"
|
||||
fi
|
||||
|
||||
if [[ '${{ inputs.converts }}' == 'true' ]]; then
|
||||
sed -i 's/^NO_CONVERTS=.*$/NO_CONVERTS=0/' "${{ needs.directory.outputs.GENERATOR_ENV }}"
|
||||
else
|
||||
sed -i 's/^NO_CONVERTS=.*$/NO_CONVERTS=1/' "${{ needs.directory.outputs.GENERATOR_ENV }}"
|
||||
fi
|
||||
|
||||
if [[ '${{ inputs.ranked-only }}' == 'true' ]]; then
|
||||
sed -i 's/^RANKED_ONLY=.*$/RANKED_ONLY=1/' "${{ needs.directory.outputs.GENERATOR_ENV }}"
|
||||
else
|
||||
sed -i 's/^RANKED_ONLY=.*$/RANKED_ONLY=0/' "${{ needs.directory.outputs.GENERATOR_ENV }}"
|
||||
fi
|
||||
|
||||
scores:
|
||||
name: Setup scores
|
||||
needs: [ directory, environment ]
|
||||
runs-on: self-hosted
|
||||
if: ${{ !cancelled() && needs.environment.result == 'success' }}
|
||||
steps:
|
||||
- name: Query latest data
|
||||
id: query
|
||||
run: |
|
||||
ruleset=$(cat ${{ needs.directory.outputs.GENERATOR_ENV }} | grep -E '^RULESET=' | cut -d '=' -f2-)
|
||||
performance_data_name=$(curl -s "https://data.ppy.sh/" | grep "performance_${ruleset}_top_1000\b" | tail -1 | awk -F "'" '{print $2}' | sed 's/\.tar\.bz2//g')
|
||||
|
||||
echo "TARGET_DIR=${{ needs.directory.outputs.GENERATOR_DIR }}/sql/${ruleset}" >> "${GITHUB_OUTPUT}"
|
||||
echo "DATA_NAME=${performance_data_name}" >> "${GITHUB_OUTPUT}"
|
||||
|
||||
- name: Restore cache
|
||||
id: restore-cache
|
||||
uses: maxnowack/local-cache@v1
|
||||
with:
|
||||
path: ${{ steps.query.outputs.DATA_NAME }}.tar.bz2
|
||||
key: ${{ steps.query.outputs.DATA_NAME }}
|
||||
|
||||
- name: Download
|
||||
if: steps.restore-cache.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
wget -q -nc "https://data.ppy.sh/${{ steps.query.outputs.DATA_NAME }}.tar.bz2"
|
||||
|
||||
- name: Extract
|
||||
run: |
|
||||
tar -I lbzip2 -xf "${{ steps.query.outputs.DATA_NAME }}.tar.bz2"
|
||||
rm -r "${{ steps.query.outputs.TARGET_DIR }}"
|
||||
mv "${{ steps.query.outputs.DATA_NAME }}" "${{ steps.query.outputs.TARGET_DIR }}"
|
||||
|
||||
beatmaps:
|
||||
name: Setup beatmaps
|
||||
needs: directory
|
||||
runs-on: self-hosted
|
||||
if: ${{ !cancelled() && needs.directory.result == 'success' }}
|
||||
steps:
|
||||
- name: Query latest data
|
||||
id: query
|
||||
run: |
|
||||
beatmaps_data_name=$(curl -s "https://data.ppy.sh/" | grep "osu_files" | tail -1 | awk -F "'" '{print $2}' | sed 's/\.tar\.bz2//g')
|
||||
|
||||
echo "TARGET_DIR=${{ needs.directory.outputs.GENERATOR_DIR }}/beatmaps" >> "${GITHUB_OUTPUT}"
|
||||
echo "DATA_NAME=${beatmaps_data_name}" >> "${GITHUB_OUTPUT}"
|
||||
|
||||
- name: Restore cache
|
||||
id: restore-cache
|
||||
uses: maxnowack/local-cache@v1
|
||||
with:
|
||||
path: ${{ steps.query.outputs.DATA_NAME }}.tar.bz2
|
||||
key: ${{ steps.query.outputs.DATA_NAME }}
|
||||
|
||||
- name: Download
|
||||
if: steps.restore-cache.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
wget -q -nc "https://data.ppy.sh/${{ steps.query.outputs.DATA_NAME }}.tar.bz2"
|
||||
|
||||
- name: Extract
|
||||
run: |
|
||||
tar -I lbzip2 -xf "${{ steps.query.outputs.DATA_NAME }}.tar.bz2"
|
||||
rm -r "${{ steps.query.outputs.TARGET_DIR }}"
|
||||
mv "${{ steps.query.outputs.DATA_NAME }}" "${{ steps.query.outputs.TARGET_DIR }}"
|
||||
|
||||
generator:
|
||||
name: Run generator
|
||||
needs: [ directory, environment, scores, beatmaps ]
|
||||
runs-on: self-hosted
|
||||
timeout-minutes: 720
|
||||
if: ${{ !cancelled() && needs.scores.result == 'success' && needs.beatmaps.result == 'success' }}
|
||||
outputs:
|
||||
TARGET: ${{ steps.run.outputs.TARGET }}
|
||||
SPREADSHEET_LINK: ${{ steps.run.outputs.SPREADSHEET_LINK }}
|
||||
steps:
|
||||
- name: Run
|
||||
id: run
|
||||
run: |
|
||||
# Add the GitHub token. This needs to be done here because it's unique per-job.
|
||||
sed -i 's/^GH_TOKEN=.*$/GH_TOKEN=${{ github.token }}/' "${{ needs.directory.outputs.GENERATOR_ENV }}"
|
||||
|
||||
cd "${{ needs.directory.outputs.GENERATOR_DIR }}"
|
||||
docker-compose up --build generator
|
||||
|
||||
link=$(docker-compose logs generator -n 10 | grep 'http' | sed -E 's/^.*(http.*)$/\1/')
|
||||
target=$(cat "${{ needs.directory.outputs.GENERATOR_ENV }}" | grep -E '^OSU_B=' | cut -d '=' -f2-)
|
||||
|
||||
echo "TARGET=${target}" >> "${GITHUB_OUTPUT}"
|
||||
echo "SPREADSHEET_LINK=${link}" >> "${GITHUB_OUTPUT}"
|
||||
|
||||
- name: Shutdown
|
||||
if: ${{ always() }}
|
||||
run: |
|
||||
cd "${{ needs.directory.outputs.GENERATOR_DIR }}"
|
||||
docker-compose down
|
||||
|
||||
- name: Output info
|
||||
if: ${{ success() }}
|
||||
run: |
|
||||
echo "Target: ${{ steps.run.outputs.TARGET }}"
|
||||
echo "Spreadsheet: ${{ steps.run.outputs.SPREADSHEET_LINK }}"
|
||||
|
||||
update-comment:
|
||||
name: Update PR comment
|
||||
needs: [ create-comment, run-diffcalc ]
|
||||
needs: [ create-comment, generator ]
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ always() && needs.create-comment.result == 'success' }}
|
||||
if: ${{ github.event_name == 'issue_comment' && github.event.issue.pull_request && contains(github.event.comment.body, '!diffcalc') && github.event.comment.author_association == 'OWNER' }}
|
||||
steps:
|
||||
- name: Update comment on success
|
||||
if: ${{ needs.run-diffcalc.result == 'success' }}
|
||||
uses: thollander/actions-comment-pull-request@fabd468d3a1a0b97feee5f6b9e499eab0dd903f6 # v2.5.0
|
||||
if: ${{ needs.generator.result == 'success' }}
|
||||
uses: thollander/actions-comment-pull-request@v2
|
||||
with:
|
||||
comment_tag: ${{ env.EXECUTION_ID }}
|
||||
mode: recreate
|
||||
comment_tag: ${{ env.COMMENT_TAG }}
|
||||
mode: upsert
|
||||
create_if_not_exists: false
|
||||
message: |
|
||||
Target: ${{ needs.run-diffcalc.outputs.target }}
|
||||
Spreadsheet: ${{ needs.run-diffcalc.outputs.sheet }}
|
||||
Target: ${{ needs.generator.outputs.TARGET }}
|
||||
Spreadsheet: ${{ needs.generator.outputs.SPREADSHEET_LINK }}
|
||||
|
||||
- name: Update comment on failure
|
||||
if: ${{ needs.run-diffcalc.result == 'failure' }}
|
||||
uses: thollander/actions-comment-pull-request@fabd468d3a1a0b97feee5f6b9e499eab0dd903f6 # v2.5.0
|
||||
if: ${{ needs.generator.result == 'failure' }}
|
||||
uses: thollander/actions-comment-pull-request@v2
|
||||
with:
|
||||
comment_tag: ${{ env.EXECUTION_ID }}
|
||||
mode: recreate
|
||||
comment_tag: ${{ env.COMMENT_TAG }}
|
||||
mode: upsert
|
||||
create_if_not_exists: false
|
||||
message: |
|
||||
Difficulty calculation failed: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
|
||||
- name: Update comment on cancellation
|
||||
if: ${{ needs.run-diffcalc.result == 'cancelled' }}
|
||||
uses: thollander/actions-comment-pull-request@fabd468d3a1a0b97feee5f6b9e499eab0dd903f6 # v2.5.0
|
||||
with:
|
||||
comment_tag: ${{ env.EXECUTION_ID }}
|
||||
mode: delete
|
||||
message: '.' # Appears to be required by this action for non-error status code.
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
# This is a workaround to allow PRs to report their coverage. This will run inside the base repository.
|
||||
# See:
|
||||
# * https://github.com/dorny/test-reporter#recommended-setup-for-public-repositories
|
||||
# * https://docs.github.com/en/actions/reference/authentication-in-a-workflow#permissions-for-the-github_token
|
||||
name: Annotate CI run with test results
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ["Continuous Integration"]
|
||||
types:
|
||||
- completed
|
||||
permissions: {}
|
||||
jobs:
|
||||
annotate:
|
||||
permissions:
|
||||
checks: write # to create checks (dorny/test-reporter)
|
||||
|
||||
name: Annotate CI run with test results
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event.workflow_run.conclusion != 'cancelled' }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os:
|
||||
- { prettyname: Windows }
|
||||
- { prettyname: macOS }
|
||||
- { prettyname: Linux }
|
||||
threadingMode: ['SingleThread', 'MultiThreaded']
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: Annotate CI run with test results
|
||||
uses: dorny/test-reporter@v1.6.0
|
||||
with:
|
||||
artifact: osu-test-results-${{matrix.os.prettyname}}-${{matrix.threadingMode}}
|
||||
name: Test Results (${{matrix.os.prettyname}}, ${{matrix.threadingMode}})
|
||||
path: "*.trx"
|
||||
reporter: dotnet-trx
|
||||
list-suites: 'failed'
|
||||
list-tests: 'failed'
|
||||
@@ -13,12 +13,12 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Create Sentry release
|
||||
uses: getsentry/action-release@v3
|
||||
uses: getsentry/action-release@v1
|
||||
env:
|
||||
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
||||
SENTRY_ORG: ppy
|
||||
|
||||
@@ -12,24 +12,24 @@ jobs:
|
||||
name: Update osu-web mod definitions
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Install .NET 8.0.x
|
||||
uses: actions/setup-dotnet@v4
|
||||
- name: Install .NET 6.0.x
|
||||
uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: "8.0.x"
|
||||
dotnet-version: "6.0.x"
|
||||
|
||||
- name: Checkout ppy/osu
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
path: osu
|
||||
|
||||
- name: Checkout ppy/osu-tools
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: ppy/osu-tools
|
||||
path: osu-tools
|
||||
|
||||
- name: Checkout ppy/osu-web
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: ppy/osu-web
|
||||
path: osu-web
|
||||
@@ -38,16 +38,12 @@ jobs:
|
||||
run: ./UseLocalOsu.sh
|
||||
working-directory: ./osu-tools
|
||||
|
||||
- name: Build tools
|
||||
run: dotnet build PerformanceCalculator --nologo --verbosity quiet
|
||||
working-directory: ./osu-tools
|
||||
|
||||
- name: Regenerate mod definitions
|
||||
run: dotnet run --project PerformanceCalculator --no-build -- mods > ../osu-web/database/mods.json
|
||||
run: dotnet run --project PerformanceCalculator -- mods > ../osu-web/database/mods.json
|
||||
working-directory: ./osu-tools
|
||||
|
||||
- name: Create pull request with changes
|
||||
uses: peter-evans/create-pull-request@v6
|
||||
uses: peter-evans/create-pull-request@v5
|
||||
with:
|
||||
title: Update mod definitions
|
||||
body: "This PR has been auto-generated to update the mod definitions to match ppy/osu@${{ github.ref_name }}."
|
||||
|
||||
@@ -265,8 +265,6 @@ __pycache__/
|
||||
.idea/**/usage.statistics.xml
|
||||
.idea/**/dictionaries
|
||||
.idea/**/shelf
|
||||
.idea/*/.idea/projectSettingsUpdater.xml
|
||||
.idea/*/.idea/encodings.xml
|
||||
|
||||
# Generated files
|
||||
.idea/**/contentModel.xml
|
||||
@@ -342,5 +340,4 @@ inspectcode
|
||||
# Fody (pulled in by Realm) - schema file
|
||||
FodyWeavers.xsd
|
||||
|
||||
.idea/.idea.osu.Desktop/.idea/misc.xml
|
||||
.idea/.idea.osu.Android/.idea/deploymentTargetDropDown.xml
|
||||
.idea/.idea.osu.Desktop/.idea/misc.xml
|
||||
@@ -0,0 +1,59 @@
|
||||
is_global = true
|
||||
|
||||
# .NET Code Style
|
||||
# IDE styles reference: https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/
|
||||
|
||||
# IDE0001: Simplify names
|
||||
dotnet_diagnostic.IDE0001.severity = warning
|
||||
|
||||
# IDE0002: Simplify member access
|
||||
dotnet_diagnostic.IDE0002.severity = warning
|
||||
|
||||
# IDE0003: Remove qualification
|
||||
dotnet_diagnostic.IDE0003.severity = warning
|
||||
|
||||
# IDE0004: Remove unnecessary cast
|
||||
dotnet_diagnostic.IDE0004.severity = warning
|
||||
|
||||
# IDE0005: Remove unnecessary imports
|
||||
dotnet_diagnostic.IDE0005.severity = warning
|
||||
|
||||
# IDE0034: Simplify default literal
|
||||
dotnet_diagnostic.IDE0034.severity = warning
|
||||
|
||||
# IDE0036: Sort modifiers
|
||||
dotnet_diagnostic.IDE0036.severity = warning
|
||||
|
||||
# IDE0040: Add accessibility modifier
|
||||
dotnet_diagnostic.IDE0040.severity = warning
|
||||
|
||||
# IDE0049: Use keyword for type name
|
||||
dotnet_diagnostic.IDE0040.severity = warning
|
||||
|
||||
# IDE0055: Fix formatting
|
||||
dotnet_diagnostic.IDE0055.severity = warning
|
||||
|
||||
# IDE0051: Private method is unused
|
||||
dotnet_diagnostic.IDE0051.severity = silent
|
||||
|
||||
# IDE0052: Private member is unused
|
||||
dotnet_diagnostic.IDE0052.severity = silent
|
||||
|
||||
# IDE0073: File header
|
||||
dotnet_diagnostic.IDE0073.severity = warning
|
||||
|
||||
# IDE0130: Namespace mismatch with folder
|
||||
dotnet_diagnostic.IDE0130.severity = warning
|
||||
|
||||
# IDE1006: Naming style
|
||||
dotnet_diagnostic.IDE1006.severity = warning
|
||||
|
||||
#Disable operator overloads requiring alternate named methods
|
||||
dotnet_diagnostic.CA2225.severity = none
|
||||
|
||||
# Banned APIs
|
||||
dotnet_diagnostic.RS0030.severity = error
|
||||
|
||||
# Temporarily disable analysing CanBeNull = true in NRT contexts due to mobile issues.
|
||||
# See: https://github.com/ppy/osu/pull/19677
|
||||
dotnet_diagnostic.OSUF001.severity = none
|
||||
@@ -1,10 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="deploymentTargetSelector">
|
||||
<selectionStates>
|
||||
<SelectionState runConfigName="osu.Android">
|
||||
<option name="selectionMode" value="DROPDOWN" />
|
||||
</SelectionState>
|
||||
</selectionStates>
|
||||
</component>
|
||||
</project>
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RiderProjectSettingsUpdater">
|
||||
<option name="vcsConfiguration" value="2" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding" addBOMForNewFiles="with NO BOM" />
|
||||
</project>
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RiderProjectSettingsUpdater">
|
||||
<option name="vcsConfiguration" value="2" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -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.Game.Benchmarks/bin/Debug/net8.0/osu.Game.Benchmarks.dll" />
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Game.Benchmarks/bin/Debug/net6.0/osu.Game.Benchmarks.dll" />
|
||||
<option name="PROGRAM_PARAMETERS" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Game.Benchmarks/bin/Debug/net8.0" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Game.Benchmarks/bin/Debug/net6.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="net8.0" />
|
||||
<option name="PROJECT_TFM" value="net6.0" />
|
||||
<method v="2">
|
||||
<option name="Build" />
|
||||
</method>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="CatchRuleset (Tests)" type="DotNetProject" factoryName=".NET Project" folderName="Ruleset" activateToolWindowBeforeRun="false">
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Game.Rulesets.Catch.Tests/bin/Debug/net8.0/osu.Game.Rulesets.Catch.Tests.dll" />
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Game.Rulesets.Catch.Tests/bin/Debug/net6.0/osu.Game.Rulesets.Catch.Tests.dll" />
|
||||
<option name="PROGRAM_PARAMETERS" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Game.Rulesets.Catch.Tests/bin/Debug/net8.0" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Game.Rulesets.Catch.Tests/bin/Debug/net6.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="net8.0" />
|
||||
<option name="PROJECT_TFM" value="net6.0" />
|
||||
<browser url="http://localhost:5000" />
|
||||
<method v="2">
|
||||
<option name="Build" />
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="ManiaRuleset (Tests)" type="DotNetProject" factoryName=".NET Project" folderName="Ruleset" activateToolWindowBeforeRun="false">
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Game.Rulesets.Mania.Tests/bin/Debug/net8.0/osu.Game.Rulesets.Mania.Tests.dll" />
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Game.Rulesets.Mania.Tests/bin/Debug/net6.0/osu.Game.Rulesets.Mania.Tests.dll" />
|
||||
<option name="PROGRAM_PARAMETERS" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Game.Rulesets.Mania.Tests/bin/Debug/net8.0" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Game.Rulesets.Mania.Tests/bin/Debug/net6.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="net8.0" />
|
||||
<option name="PROJECT_TFM" value="net6.0" />
|
||||
<browser url="http://localhost:5000" />
|
||||
<method v="2">
|
||||
<option name="Build" />
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="OsuRuleset (Tests)" type="DotNetProject" factoryName=".NET Project" folderName="Ruleset" activateToolWindowBeforeRun="false">
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Game.Rulesets.Osu.Tests/bin/Debug/net8.0/osu.Game.Rulesets.Osu.Tests.dll" />
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Game.Rulesets.Osu.Tests/bin/Debug/net6.0/osu.Game.Rulesets.Osu.Tests.dll" />
|
||||
<option name="PROGRAM_PARAMETERS" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Game.Rulesets.Osu.Tests/bin/Debug/net8.0" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Game.Rulesets.Osu.Tests/bin/Debug/net6.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="net8.0" />
|
||||
<option name="PROJECT_TFM" value="net6.0" />
|
||||
<browser url="http://localhost:5000" />
|
||||
<method v="2">
|
||||
<option name="Build" />
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="TaikoRuleset (Tests)" type="DotNetProject" factoryName=".NET Project" folderName="Ruleset" activateToolWindowBeforeRun="false">
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Game.Rulesets.Taiko.Tests/bin/Debug/net8.0/osu.Game.Rulesets.Taiko.Tests.dll" />
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Game.Rulesets.Taiko.Tests/bin/Debug/net6.0/osu.Game.Rulesets.Taiko.Tests.dll" />
|
||||
<option name="PROGRAM_PARAMETERS" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Game.Rulesets.Taiko.Tests/bin/Debug/net8.0" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Game.Rulesets.Taiko.Tests/bin/Debug/net6.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="net8.0" />
|
||||
<option name="PROJECT_TFM" value="net6.0" />
|
||||
<browser url="http://localhost:5000" />
|
||||
<method v="2">
|
||||
<option name="Build" />
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Tournament" type="DotNetProject" factoryName=".NET Project" folderName="Tournament" activateToolWindowBeforeRun="false">
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Desktop/bin/Debug/net8.0/osu!.dll" />
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Desktop/bin/Debug/net6.0/osu!.dll" />
|
||||
<option name="PROGRAM_PARAMETERS" value="--tournament" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Desktop/bin/Debug/net8.0" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Desktop/bin/Debug/net6.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="net8.0" />
|
||||
<option name="PROJECT_TFM" value="net6.0" />
|
||||
<method v="2">
|
||||
<option name="Build" />
|
||||
</method>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Tournament (Tests)" type="DotNetProject" factoryName=".NET Project" folderName="Tournament" activateToolWindowBeforeRun="false">
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Game.Tournament.Tests/bin/Debug/net8.0/osu.Game.Tournament.Tests.dll" />
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Game.Tournament.Tests/bin/Debug/net6.0/osu.Game.Tournament.Tests.dll" />
|
||||
<option name="PROGRAM_PARAMETERS" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Game.Tournament.Tests/bin/Debug/net8.0" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Game.Tournament.Tests/bin/Debug/net6.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="net8.0" />
|
||||
<option name="PROJECT_TFM" value="net6.0" />
|
||||
<browser url="http://localhost:5000" />
|
||||
<method v="2">
|
||||
<option name="Build" />
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="osu!" type="DotNetProject" factoryName=".NET Project" folderName="osu!" activateToolWindowBeforeRun="false">
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Desktop/bin/Debug/net8.0/osu!.dll" />
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Desktop/bin/Debug/net6.0/osu!.dll" />
|
||||
<option name="PROGRAM_PARAMETERS" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Desktop/bin/Debug/net8.0" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Desktop/bin/Debug/net6.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="net8.0" />
|
||||
<option name="PROJECT_TFM" value="net6.0" />
|
||||
<method v="2">
|
||||
<option name="Build" />
|
||||
</method>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="osu! (Tests)" type="DotNetProject" factoryName=".NET Project" folderName="osu!" activateToolWindowBeforeRun="false">
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Game.Tests/bin/Debug/net8.0/osu.Game.Tests.dll" />
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Game.Tests/bin/Debug/net6.0/osu.Game.Tests.dll" />
|
||||
<option name="PROGRAM_PARAMETERS" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Game.Tests/bin/Debug/net8.0" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Game.Tests/bin/Debug/net6.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="net8.0" />
|
||||
<option name="PROJECT_TFM" value="net6.0" />
|
||||
<method v="2">
|
||||
<option name="Build" />
|
||||
</method>
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RiderProjectSettingsUpdater">
|
||||
<option name="vcsConfiguration" value="2" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RiderProjectSettingsUpdater">
|
||||
<option name="vcsConfiguration" value="2" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -1,8 +1,8 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="osu! (Second Client)" type="DotNetProject" factoryName=".NET Project" folderName="osu!" activateToolWindowBeforeRun="false">
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Desktop/bin/Debug/net8.0/osu!.dll" />
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Desktop/bin/Debug/net6.0/osu!.dll" />
|
||||
<option name="PROGRAM_PARAMETERS" value="--debug-client-id=1" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Desktop/bin/Debug/net8.0" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Desktop/bin/Debug/net6.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="net8.0" />
|
||||
<option name="PROJECT_TFM" value="net6.0" />
|
||||
<method v="2">
|
||||
<option name="Build" />
|
||||
</method>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"editorconfig.editorconfig",
|
||||
"ms-dotnettools.csdevkit"
|
||||
"ms-dotnettools.csharp"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -7,20 +7,7 @@
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/osu.Desktop/bin/Debug/net8.0/osu!.dll"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build osu! (Debug)",
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
"name": "osu! (Debug, Second Client)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/osu.Desktop/bin/Debug/net8.0/osu!.dll",
|
||||
"--debug-client-id=1"
|
||||
"${workspaceRoot}/osu.Desktop/bin/Debug/net6.0/osu!.dll"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build osu! (Debug)",
|
||||
@@ -32,7 +19,7 @@
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/osu.Desktop/bin/Release/net8.0/osu!.dll"
|
||||
"${workspaceRoot}/osu.Desktop/bin/Release/net6.0/osu!.dll"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build osu! (Release)",
|
||||
@@ -44,7 +31,7 @@
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/osu.Game.Tests/bin/Debug/net8.0/osu.Game.Tests.dll"
|
||||
"${workspaceRoot}/osu.Game.Tests/bin/Debug/net6.0/osu.Game.Tests.dll"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build tests (Debug)",
|
||||
@@ -56,7 +43,7 @@
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/osu.Game.Tests/bin/Release/net8.0/osu.Game.Tests.dll"
|
||||
"${workspaceRoot}/osu.Game.Tests/bin/Release/net6.0/osu.Game.Tests.dll"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build tests (Release)",
|
||||
@@ -68,7 +55,7 @@
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/osu.Desktop/bin/Debug/net8.0/osu!.dll",
|
||||
"${workspaceRoot}/osu.Desktop/bin/Debug/net6.0/osu!.dll",
|
||||
"--tournament"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
@@ -81,7 +68,7 @@
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/osu.Desktop/bin/Release/net8.0/osu!.dll",
|
||||
"${workspaceRoot}/osu.Desktop/bin/Release/net6.0/osu!.dll",
|
||||
"--tournament"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
@@ -94,7 +81,7 @@
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/osu.Game.Tournament.Tests/bin/Debug/net8.0/osu.Game.Tournament.Tests.dll",
|
||||
"${workspaceRoot}/osu.Game.Tournament.Tests/bin/Debug/net6.0/osu.Game.Tournament.Tests.dll",
|
||||
"--tournament"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
@@ -107,7 +94,7 @@
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/osu.Game.Tournament.Tests/bin/Debug/net8.0/osu.Game.Tournament.Tests.dll",
|
||||
"${workspaceRoot}/osu.Game.Tournament.Tests/bin/Debug/net6.0/osu.Game.Tournament.Tests.dll",
|
||||
"--tournament"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
@@ -118,7 +105,7 @@
|
||||
"name": "Benchmark",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"program": "${workspaceRoot}/osu.Game.Benchmarks/bin/Release/net8.0/osu.Game.Benchmarks.dll",
|
||||
"program": "${workspaceRoot}/osu.Game.Benchmarks/bin/Release/net6.0/osu.Game.Benchmarks.dll",
|
||||
"args": [
|
||||
"--filter",
|
||||
"*"
|
||||
|
||||
@@ -2,10 +2,6 @@
|
||||
|
||||
Thank you for showing interest in the development of osu!. We aim to provide a good collaborating environment for everyone involved, and as such have decided to list some of the most important things to keep in mind in the process. The guidelines below have been chosen based on past experience.
|
||||
|
||||
## Foreword on AI usage
|
||||
|
||||
Our team believes in **human contributions**. Any contribution – be it an issue report or a pull request – which is created by, documented by, or aided by AI/LLM usage will typically be **closed and locked without further discussion**.
|
||||
|
||||
## Table of contents
|
||||
|
||||
1. [Reporting bugs](#reporting-bugs)
|
||||
@@ -59,9 +55,11 @@ When in doubt, it's probably best to start with a discussion first. We will esca
|
||||
|
||||
While pull requests from unaffiliated contributors are welcome, please note that due to significant community interest and limited review throughput, the core team's primary focus is on the issues which are currently [on the roadmap](https://github.com/orgs/ppy/projects/7/views/6). Reviewing PRs that fall outside of the scope of the roadmap is done on a best-effort basis, so please be aware that it may take a while before a core maintainer gets around to review your change.
|
||||
|
||||
The [issue tracker](https://github.com/ppy/osu/issues) should provide plenty of issues to start with. In the case of simple issues, a direct PR is okay. However, if you decide to work on an existing issue which doesn't seem trivial, **please ask us first**. This way we can try to estimate if it is a good fit for you and provide the correct direction on how to address it. In addition, note that while we do not rule out external contributors from working on roadmapped issues, we will generally prefer to handle them ourselves unless they're not very time sensitive.
|
||||
The [issue tracker](https://github.com/ppy/osu/issues) should provide plenty of issues to start with. We also have a [`good-first-issue`](https://github.com/ppy/osu/issues?q=is%3Aissue+is%3Aopen+label%3Agood-first-issue) label, although from experience it is not used very often, as it is relatively rare that we can spot an issue that will definitively be a good first issue for a new contributor regardless of their programming experience.
|
||||
|
||||
If you'd like to propose a subjective change to one of the visual aspects of the game, or there is a bigger task you'd like to work on, but there is no corresponding issue or discussion thread yet for it, **please open a discussion or issue first** to avoid wasted effort. This in particular applies if you want to work on [one of the available designs from the osu! Figma master library](https://www.figma.com/file/VIkXMYNPMtQem2RJg9k2iQ/Master-Library).
|
||||
In the case of simple issues, a direct PR is okay. However, if you decide to work on an existing issue which doesn't seem trivial, **please ask us first**. This way we can try to estimate if it is a good fit for you and provide the correct direction on how to address it. In addition, note that while we do not rule out external contributors from working on roadmapped issues, we will generally prefer to handle them ourselves unless they're not very time sensitive.
|
||||
|
||||
If you'd like to propose a subjective change to one of the visual aspects of the game, or there is a bigger task you'd like to work on, but there is no corresponding issue or discussion thread yet for it, **please open a discussion or issue first** to avoid wasted effort. This in particular applies if you want to work on [one of the available designs from the osu! public Figma library](https://www.figma.com/file/6m10GiGEncVFWmgOoSyakH/osu!-Figma-Library).
|
||||
|
||||
Aside from the above, below is a brief checklist of things to watch out when you're preparing your code changes:
|
||||
|
||||
@@ -70,14 +68,10 @@ Aside from the above, below is a brief checklist of things to watch out when you
|
||||
- Please do not make code changes via the GitHub web interface.
|
||||
- Please add tests for your changes. We expect most new features and bugfixes to have test coverage, unless the effort of adding them is prohibitive. The visual testing methodology we use is described in more detail [here](https://github.com/ppy/osu-framework/wiki/Development-and-Testing).
|
||||
- Please run tests and code style analysis (via `InspectCode.{ps1,sh}` scripts in the root of this repository) before opening the PR. This is particularly important if you're a first-time contributor, as CI will not run for your PR until we allow it to do so.
|
||||
- **Do not run the game in release configuration at any point during your testing** (the sole exception to this being benchmarks). Using release is an unnecessary and harmful practice, and can even lead to you losing your local realm database if you start making changes to the schema. The debug configuration has a completely separated full-stack environment, including a development website instance at https://dev.ppy.sh/. It is permitted to register an account on that development instance for testing purposes and not worry about multi-accounting infractions.
|
||||
|
||||
After you're done with your changes and you wish to open the PR, please observe the following recommendations:
|
||||
|
||||
- Please submit the pull request from a [topic branch](https://git-scm.com/book/en/v2/Git-Branching-Branching-Workflows#_topic_branch) (not `master`), and keep the *Allow edits from maintainers* check box selected, so that we can push fixes to your PR if necessary.
|
||||
- Please pick the following target branch for your pull request:
|
||||
- `pp-dev`, if the change impacts star rating or performance points calculations for any of the rulesets,
|
||||
- `master`, otherwise.
|
||||
- Please avoid pushing untested or incomplete code.
|
||||
- Please do not force-push or rebase unless we ask you to.
|
||||
- Please do not merge `master` continually if there are no conflicts to resolve. We will do this for you when the change is ready for merge.
|
||||
@@ -91,4 +85,4 @@ If you're uncertain about some part of the codebase or some inner workings of th
|
||||
- [Development roadmap](https://github.com/orgs/ppy/projects/7/views/6): What the core team is currently working on
|
||||
- [`ppy/osu-framework` wiki](https://github.com/ppy/osu-framework/wiki): Contains introductory information about osu!framework, the bespoke 2D game framework we use for the game
|
||||
- [`ppy/osu` wiki](https://github.com/ppy/osu/wiki): Contains articles about various technical aspects of the game
|
||||
- [Figma master library](https://www.figma.com/file/VIkXMYNPMtQem2RJg9k2iQ/Master-Library): Contains finished and draft designs for osu!
|
||||
- [Public Figma library](https://www.figma.com/file/6m10GiGEncVFWmgOoSyakH/osu!-Figma-Library): Contains finished and draft designs for osu!
|
||||
|
||||
@@ -7,6 +7,7 @@ T:SixLabors.ImageSharp.IDeepCloneable`1;Use osu.Game.Utils.IDeepCloneable<T> ins
|
||||
M:osu.Framework.Graphics.Sprites.SpriteText.#ctor;Use OsuSpriteText.
|
||||
M:osu.Framework.Bindables.IBindableList`1.GetBoundCopy();Fails on iOS. Use manual ctor + BindTo instead. (see https://github.com/mono/mono/issues/19900)
|
||||
T:NuGet.Packaging.CollectionExtensions;Don't use internal extension methods.
|
||||
M:System.Enum.HasFlag(System.Enum);Use osu.Framework.Extensions.EnumExtensions.HasFlagFast<T>() instead.
|
||||
M:Realms.IRealmCollection`1.SubscribeForNotifications`1(Realms.NotificationCallbackDelegate{``0});Use osu.Game.Database.RealmObjectExtensions.QueryAsyncWithNotifications(IRealmCollection<T>,NotificationCallbackDelegate<T>) instead.
|
||||
M:System.Guid.#ctor;Probably meaning to use Guid.NewGuid() instead. If actually wanting empty, use Guid.Empty.
|
||||
M:Realms.CollectionExtensions.SubscribeForNotifications`1(System.Linq.IQueryable{``0},Realms.NotificationCallbackDelegate{``0});Use osu.Game.Database.RealmObjectExtensions.QueryAsyncWithNotifications(IQueryable<T>,NotificationCallbackDelegate<T>) instead.
|
||||
@@ -14,14 +15,11 @@ M:Realms.CollectionExtensions.SubscribeForNotifications`1(System.Collections.Gen
|
||||
M:System.Threading.Tasks.Task.Wait();Don't use Task.Wait. Use Task.WaitSafely() to ensure we avoid deadlocks.
|
||||
P:System.Threading.Tasks.Task`1.Result;Don't use Task.Result. Use Task.GetResultSafely() to ensure we avoid deadlocks.
|
||||
M:System.Threading.ManualResetEventSlim.Wait();Specify a timeout to avoid waiting forever.
|
||||
M:System.Char.ToLower(System.Char);char.ToLower() changes behaviour depending on CultureInfo.CurrentCulture. Use char.ToLowerInvariant() instead. If wanting culture-sensitive behaviour, explicitly provide CultureInfo.CurrentCulture.
|
||||
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:Humanizer.InflectorExtensions.Pascalize(System.String);Humanizer's .Pascalize() extension method changes behaviour depending on CultureInfo.CurrentCulture. Use StringDehumanizeExtensions.ToPascalCase() instead.
|
||||
M:Humanizer.InflectorExtensions.Camelize(System.String);Humanizer's .Camelize() extension method changes behaviour depending on CultureInfo.CurrentCulture. Use StringDehumanizeExtensions.ToCamelCase() instead.
|
||||
M:Humanizer.InflectorExtensions.Underscore(System.String);Humanizer's .Underscore() extension method changes behaviour depending on CultureInfo.CurrentCulture. Use StringDehumanizeExtensions.ToSnakeCase() instead.
|
||||
M:Humanizer.InflectorExtensions.Kebaberize(System.String);Humanizer's .Kebaberize() extension method changes behaviour depending on CultureInfo.CurrentCulture. Use StringDehumanizeExtensions.ToKebabCase() instead.
|
||||
M:osuTK.MathHelper.Clamp(System.Int32,System.Int32,System.Int32)~System.Int32;Use Math.Clamp() instead.
|
||||
M:osuTK.MathHelper.Clamp(System.Single,System.Single,System.Single)~System.Single;This osuTK helper has unsafe semantics when one of the bounds provided is NaN. Use Math.Clamp() instead.
|
||||
M:osuTK.MathHelper.Clamp(System.Double,System.Double,System.Double)~System.Double;This osuTK helper has unsafe semantics when one of the bounds provided is NaN. Use Math.Clamp() instead.
|
||||
M:TagLib.File.Create(System.String);TagLib's MIME type detection changes behaviour depending on CultureInfo.CurrentCulture. Use TagLibUtils.GetTagLibFile() instead.
|
||||
M:TagLib.File.Create(TagLib.File.IFileAbstraction);TagLib's MIME type detection changes behaviour depending on CultureInfo.CurrentCulture. Use TagLibUtils.GetTagLibFile() instead.
|
||||
M:TagLib.File.Create(System.String,TagLib.ReadStyle);TagLib's MIME type detection changes behaviour depending on CultureInfo.CurrentCulture. Use TagLibUtils.GetTagLibFile() instead.
|
||||
M:TagLib.File.Create(TagLib.File.IFileAbstraction,TagLib.ReadStyle);TagLib's MIME type detection changes behaviour depending on CultureInfo.CurrentCulture. Use TagLibUtils.GetTagLibFile() instead.
|
||||
|
||||
@@ -1,112 +0,0 @@
|
||||
# .NET Code Style
|
||||
# IDE styles reference: https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/
|
||||
is_global = true
|
||||
|
||||
# IDE0001: Simplify names
|
||||
dotnet_diagnostic.IDE0001.severity = warning
|
||||
|
||||
# IDE0002: Simplify member access
|
||||
dotnet_diagnostic.IDE0002.severity = warning
|
||||
|
||||
# IDE0003: Remove qualification
|
||||
dotnet_diagnostic.IDE0003.severity = warning
|
||||
|
||||
# IDE0004: Remove unnecessary cast
|
||||
dotnet_diagnostic.IDE0004.severity = warning
|
||||
|
||||
# IDE0005: Remove unnecessary imports
|
||||
dotnet_diagnostic.IDE0005.severity = warning
|
||||
|
||||
# IDE0034: Simplify default literal
|
||||
dotnet_diagnostic.IDE0034.severity = warning
|
||||
|
||||
# IDE0036: Sort modifiers
|
||||
dotnet_diagnostic.IDE0036.severity = warning
|
||||
|
||||
# IDE0040: Add accessibility modifier
|
||||
dotnet_diagnostic.IDE0040.severity = warning
|
||||
|
||||
# IDE0049: Use keyword for type name
|
||||
dotnet_diagnostic.IDE0040.severity = warning
|
||||
|
||||
# IDE0055: Fix formatting
|
||||
dotnet_diagnostic.IDE0055.severity = warning
|
||||
|
||||
# IDE0051: Private method is unused
|
||||
dotnet_diagnostic.IDE0051.severity = silent
|
||||
|
||||
# IDE0052: Private member is unused
|
||||
dotnet_diagnostic.IDE0052.severity = silent
|
||||
|
||||
# IDE0073: File header
|
||||
dotnet_diagnostic.IDE0073.severity = warning
|
||||
|
||||
# IDE0130: Namespace mismatch with folder
|
||||
dotnet_diagnostic.IDE0130.severity = warning
|
||||
|
||||
# IDE1006: Naming style
|
||||
dotnet_diagnostic.IDE1006.severity = warning
|
||||
|
||||
# CA1305: Specify IFormatProvider
|
||||
# Too many noisy warnings for parsing/formatting numbers
|
||||
dotnet_diagnostic.CA1305.severity = none
|
||||
|
||||
# messagepack complains about "osu" not being title cased due to reserved words
|
||||
dotnet_diagnostic.CS8981.severity = none
|
||||
|
||||
# CA1507: Use nameof to express symbol names
|
||||
# Flags serialization name attributes
|
||||
dotnet_diagnostic.CA1507.severity = suggestion
|
||||
|
||||
# CA1806: Do not ignore method results
|
||||
# The usages for numeric parsing are explicitly optional
|
||||
dotnet_diagnostic.CA1806.severity = suggestion
|
||||
|
||||
# CA1822: Mark members as static
|
||||
# Potential false positive around reflection/too much noise
|
||||
dotnet_diagnostic.CA1822.severity = none
|
||||
|
||||
# CA1826: Do not use Enumerable method on indexable collections
|
||||
dotnet_diagnostic.CA1826.severity = suggestion
|
||||
|
||||
# CA1859: Use concrete types when possible for improved performance
|
||||
# Involves design considerations
|
||||
dotnet_diagnostic.CA1859.severity = suggestion
|
||||
|
||||
# CA1860: Avoid using 'Enumerable.Any()' extension method
|
||||
dotnet_diagnostic.CA1860.severity = suggestion
|
||||
|
||||
# CA1861: Avoid constant arrays as arguments
|
||||
# Outdated with collection expressions
|
||||
dotnet_diagnostic.CA1861.severity = suggestion
|
||||
|
||||
# CA2007: Consider calling ConfigureAwait on the awaited task
|
||||
dotnet_diagnostic.CA2007.severity = warning
|
||||
|
||||
# CA2016: Forward the 'CancellationToken' parameter to methods
|
||||
# Some overloads are having special handling for debugger
|
||||
dotnet_diagnostic.CA2016.severity = suggestion
|
||||
|
||||
# CA2021: Do not call Enumerable.Cast<T> or Enumerable.OfType<T> with incompatible types
|
||||
# Causing a lot of false positives with generics
|
||||
dotnet_diagnostic.CA2021.severity = none
|
||||
|
||||
# CA2101: Specify marshaling for P/Invoke string arguments
|
||||
# Reports warning for all non-UTF16 usages on DllImport; consider migrating to LibraryImport
|
||||
dotnet_diagnostic.CA2101.severity = none
|
||||
|
||||
# CA2201: Do not raise reserved exception types
|
||||
dotnet_diagnostic.CA2201.severity = warning
|
||||
|
||||
# CA2208: Instantiate argument exceptions correctly
|
||||
dotnet_diagnostic.CA2208.severity = suggestion
|
||||
|
||||
# CA2242: Test for NaN correctly
|
||||
dotnet_diagnostic.CA2242.severity = warning
|
||||
|
||||
# Banned APIs
|
||||
dotnet_diagnostic.RS0030.severity = error
|
||||
|
||||
# Temporarily disable analysing CanBeNull = true in NRT contexts due to mobile issues.
|
||||
# See: https://github.com/ppy/osu/pull/19677
|
||||
dotnet_diagnostic.OSUF001.severity = none
|
||||
@@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RuleSet Name="osu! Rule Set" Description=" " ToolsVersion="16.0">
|
||||
<Rules AnalyzerId="Microsoft.CodeQuality.Analyzers" RuleNamespace="Microsoft.CodeQuality.Analyzers">
|
||||
<Rule Id="CA1016" Action="None" />
|
||||
<Rule Id="CA1028" Action="None" />
|
||||
<Rule Id="CA1031" Action="None" />
|
||||
<Rule Id="CA1034" Action="None" />
|
||||
<Rule Id="CA1036" Action="None" />
|
||||
<Rule Id="CA1040" Action="None" />
|
||||
<Rule Id="CA1044" Action="None" />
|
||||
<Rule Id="CA1051" Action="None" />
|
||||
<Rule Id="CA1054" Action="None" />
|
||||
<Rule Id="CA1056" Action="None" />
|
||||
<Rule Id="CA1062" Action="None" />
|
||||
<Rule Id="CA1063" Action="None" />
|
||||
<Rule Id="CA1067" Action="None" />
|
||||
<Rule Id="CA1707" Action="None" />
|
||||
<Rule Id="CA1710" Action="None" />
|
||||
<Rule Id="CA1714" Action="None" />
|
||||
<Rule Id="CA1716" Action="None" />
|
||||
<Rule Id="CA1717" Action="None" />
|
||||
<Rule Id="CA1720" Action="None" />
|
||||
<Rule Id="CA1721" Action="None" />
|
||||
<Rule Id="CA1724" Action="None" />
|
||||
<Rule Id="CA1801" Action="None" />
|
||||
<Rule Id="CA1806" Action="None" />
|
||||
<Rule Id="CA1812" Action="None" />
|
||||
<Rule Id="CA1814" Action="None" />
|
||||
<Rule Id="CA1815" Action="None" />
|
||||
<Rule Id="CA1819" Action="None" />
|
||||
<Rule Id="CA1822" Action="None" />
|
||||
<Rule Id="CA1823" Action="None" />
|
||||
<Rule Id="CA2007" Action="Warning" />
|
||||
<Rule Id="CA2214" Action="None" />
|
||||
<Rule Id="CA2227" Action="None" />
|
||||
</Rules>
|
||||
<Rules AnalyzerId="Microsoft.CodeQuality.CSharp.Analyzers" RuleNamespace="Microsoft.CodeQuality.CSharp.Analyzers">
|
||||
<Rule Id="CA1001" Action="None" />
|
||||
<Rule Id="CA1032" Action="None" />
|
||||
</Rules>
|
||||
<Rules AnalyzerId="Microsoft.NetCore.Analyzers" RuleNamespace="Microsoft.NetCore.Analyzers">
|
||||
<Rule Id="CA1303" Action="None" />
|
||||
<Rule Id="CA1304" Action="None" />
|
||||
<Rule Id="CA1305" Action="None" />
|
||||
<Rule Id="CA1307" Action="None" />
|
||||
<Rule Id="CA1308" Action="None" />
|
||||
<Rule Id="CA1816" Action="None" />
|
||||
<Rule Id="CA1826" Action="None" />
|
||||
<Rule Id="CA2000" Action="None" />
|
||||
<Rule Id="CA2008" Action="None" />
|
||||
<Rule Id="CA2213" Action="None" />
|
||||
<Rule Id="CA2235" Action="None" />
|
||||
</Rules>
|
||||
<Rules AnalyzerId="Microsoft.NetCore.CSharp.Analyzers" RuleNamespace="Microsoft.NetCore.CSharp.Analyzers">
|
||||
<Rule Id="CA1309" Action="Warning" />
|
||||
<Rule Id="CA2201" Action="Warning" />
|
||||
</Rules>
|
||||
</RuleSet>
|
||||
@@ -1,12 +1,9 @@
|
||||
<!-- Contains required properties for osu!framework projects. -->
|
||||
<Project>
|
||||
<PropertyGroup Label="C#">
|
||||
<LangVersion>12.0</LangVersion>
|
||||
<LangVersion>10.0</LangVersion>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<Nullable>enable</Nullable>
|
||||
<!-- Stabilises hot reload, see: https://platform.uno/docs/articles/studio/Hot%20Reload/hot-reload-overview.html?tabs=vswin%2Cwindows%2Cskia-desktop%2Ccommon-issues -->
|
||||
<GenerateAssemblyInfo Condition="'$(Configuration)'=='Debug'">false</GenerateAssemblyInfo>
|
||||
<!-- Required due to the above -->
|
||||
<NoWarn Condition="'$(Configuration)'=='Debug'">$(NoWarn);CA1416</NoWarn>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationManifest>$(MSBuildThisFileDirectory)app.manifest</ApplicationManifest>
|
||||
@@ -22,21 +19,9 @@
|
||||
<ItemGroup Label="Code Analysis">
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.4" PrivateAssets="All" />
|
||||
<AdditionalFiles Include="$(MSBuildThisFileDirectory)CodeAnalysis\BannedSymbols.txt" />
|
||||
<!-- Rider compatibility: .globalconfig needs to be explicitly referenced instead of using the global file name. -->
|
||||
<GlobalAnalyzerConfigFiles Include="$(MSBuildThisFileDirectory)CodeAnalysis\osu.globalconfig" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Code Analysis">
|
||||
<AnalysisMode>Default</AnalysisMode>
|
||||
<AnalysisModeDesign>Default</AnalysisModeDesign>
|
||||
<AnalysisModeDocumentation>Recommended</AnalysisModeDocumentation>
|
||||
<AnalysisModeGlobalization>Recommended</AnalysisModeGlobalization>
|
||||
<AnalysisModeInteroperability>Recommended</AnalysisModeInteroperability>
|
||||
<AnalysisModeMaintainability>Recommended</AnalysisModeMaintainability>
|
||||
<AnalysisModeNaming>Default</AnalysisModeNaming>
|
||||
<AnalysisModePerformance>Minimum</AnalysisModePerformance>
|
||||
<AnalysisModeReliability>Recommended</AnalysisModeReliability>
|
||||
<AnalysisModeSecurity>Default</AnalysisModeSecurity>
|
||||
<AnalysisModeUsage>Default</AnalysisModeUsage>
|
||||
<CodeAnalysisRuleSet>$(MSBuildThisFileDirectory)CodeAnalysis\osu.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Documentation">
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
@@ -50,7 +35,7 @@
|
||||
<RepositoryUrl>https://github.com/ppy/osu</RepositoryUrl>
|
||||
<PackageReleaseNotes>Automated release.</PackageReleaseNotes>
|
||||
<Company>ppy Pty Ltd</Company>
|
||||
<Copyright>Copyright (c) 2025 ppy Pty Ltd</Copyright>
|
||||
<Copyright>Copyright (c) 2022 ppy Pty Ltd</Copyright>
|
||||
<PackageTags>osu game</PackageTags>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2025 ppy Pty Ltd <contact@ppy.sh>.
|
||||
Copyright (c) 2022 ppy Pty Ltd <contact@ppy.sh>.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -22,7 +22,7 @@ A few resources are available as starting points to getting involved and underst
|
||||
|
||||
- Detailed release changelogs are available on the [official osu! site](https://osu.ppy.sh/home/changelog/lazer).
|
||||
- You can learn more about our approach to [project management](https://github.com/ppy/osu/wiki/Project-management).
|
||||
- Track our current efforts [towards improving the game](https://github.com/orgs/ppy/projects/7/views/6).
|
||||
- Track our current efforts [towards full "ranked play" support](https://github.com/orgs/ppy/projects/13?query=is%3Aopen+sort%3Aupdated-desc).
|
||||
|
||||
## Running osu!
|
||||
|
||||
@@ -30,14 +30,14 @@ If you are just looking to give the game a whirl, you can grab the latest releas
|
||||
|
||||
### Latest release:
|
||||
|
||||
| [Windows 10+ (x64)](https://github.com/ppy/osu/releases/latest/download/install.exe) | macOS 12+ ([Intel](https://github.com/ppy/osu/releases/latest/download/osu.app.Intel.zip), [Apple Silicon](https://github.com/ppy/osu/releases/latest/download/osu.app.Apple.Silicon.zip)) | [Linux (x64)](https://github.com/ppy/osu/releases/latest/download/osu.AppImage) | [iOS 13.4+](https://osu.ppy.sh/home/testflight) | [Android 5+](https://github.com/ppy/osu/releases/latest/download/sh.ppy.osulazer.apk) |
|
||||
|--------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| ------------- | ------------- | ------------- |
|
||||
| [Windows 8.1+ (x64)](https://github.com/ppy/osu/releases/latest/download/install.exe) | macOS 10.15+ ([Intel](https://github.com/ppy/osu/releases/latest/download/osu.app.Intel.zip), [Apple Silicon](https://github.com/ppy/osu/releases/latest/download/osu.app.Apple.Silicon.zip)) | [Linux (x64)](https://github.com/ppy/osu/releases/latest/download/osu.AppImage) | [iOS 13.4+](https://osu.ppy.sh/home/testflight) | [Android 5+](https://github.com/ppy/osu/releases/latest/download/sh.ppy.osulazer.apk) |
|
||||
| ------------- | ------------- | ------------- | ------------- | ------------- |
|
||||
|
||||
You can also generally download a version for your current device from the [osu! site](https://osu.ppy.sh/home/download).
|
||||
|
||||
If your platform is unsupported or not listed above, there is still a chance you can run the release or manually build it by following the instructions below.
|
||||
If your platform is not listed above, there is still a chance you can manually build it by following the instructions below.
|
||||
|
||||
**For iOS/iPadOS users**: The iOS testflight link fills up very fast (Apple has a hard limit of 10,000 users). We reset it occasionally. Please do not ask about this. Check back regularly for link resets or follow [peppy](https://twitter.com/ppy) on twitter for announcements. Our goal is to get the game on mobile app stores very soon so we don't have to live with this limitation.
|
||||
**For iOS/iPadOS users**: The iOS testflight link fills up very fast (Apple has a hard limit of 10,000 users). We reset it occasionally. Please do not ask about this. Check back regularly for link resets or follow [peppy](https://twitter.com/ppy) on twitter for announcements. Our goal is to get the game on mobile app stores in early 2024.
|
||||
|
||||
## Developing a custom ruleset
|
||||
|
||||
@@ -51,9 +51,9 @@ You can see some examples of custom rulesets by visiting the [custom ruleset dir
|
||||
|
||||
Please make sure you have the following prerequisites:
|
||||
|
||||
- A desktop platform with the [.NET 8.0 SDK](https://dotnet.microsoft.com/download) installed.
|
||||
- A desktop platform with the [.NET 6.0 SDK](https://dotnet.microsoft.com/download) installed.
|
||||
|
||||
When working with the codebase, we recommend using an IDE with intelligent code completion and syntax highlighting, such as the latest version of [Visual Studio](https://visualstudio.microsoft.com/vs/), [JetBrains Rider](https://www.jetbrains.com/rider/), or [Visual Studio Code](https://code.visualstudio.com/) with the [EditorConfig](https://marketplace.visualstudio.com/items?itemName=EditorConfig.EditorConfig) and [C# Dev Kit](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csdevkit) plugin installed.
|
||||
When working with the codebase, we recommend using an IDE with intelligent code completion and syntax highlighting, such as the latest version of [Visual Studio](https://visualstudio.microsoft.com/vs/), [JetBrains Rider](https://www.jetbrains.com/rider/), or [Visual Studio Code](https://code.visualstudio.com/) with the [EditorConfig](https://marketplace.visualstudio.com/items?itemName=EditorConfig.EditorConfig) and [C#](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csharp) plugin installed.
|
||||
|
||||
### Downloading the source code
|
||||
|
||||
@@ -138,8 +138,6 @@ If you wish to help with localisation efforts, head over to [crowdin](https://cr
|
||||
|
||||
We love to reward quality contributions. If you have made a large contribution, or are a regular contributor, you are welcome to [submit an expense via opencollective](https://opencollective.com/ppy/expenses/new). If you have any questions, feel free to [reach out to peppy](mailto:pe@ppy.sh) before doing so.
|
||||
|
||||
Our team believes in **human contributions**. Any contribution – be it an issue report or a pull request – which is created by, documented by, or aided by AI/LLM usage will typically be **closed and locked without further discussion**.
|
||||
|
||||
## Licence
|
||||
|
||||
*osu!*'s code and framework are licensed under the [MIT licence](https://opensource.org/licenses/MIT). Please see [the licence file](LICENCE) for more information. [tl;dr](https://tldrlegal.com/license/mit-license) you can do whatever you want as long as you include the original copyright and license notice in any copy of the software/source.
|
||||
|
||||
@@ -7,7 +7,7 @@ Templates for use when creating osu! dependent projects. Create a fully-testable
|
||||
```bash
|
||||
# install (or update) templates package.
|
||||
# this only needs to be done once
|
||||
dotnet new install ppy.osu.Game.Templates
|
||||
dotnet new -i ppy.osu.Game.Templates
|
||||
|
||||
# create an empty freeform ruleset
|
||||
dotnet new ruleset -n MyCoolRuleset
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
<!-- Contains required properties for osu!framework projects. -->
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<ApplicationManifest>$(MSBuildThisFileDirectory)app.manifest</ApplicationManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Documentation">
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -1,46 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
|
||||
<assemblyIdentity version="1.0.0.0" name="MyNewProject" />
|
||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
|
||||
<security>
|
||||
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
|
||||
</requestedPrivileges>
|
||||
<applicationRequestMinimum>
|
||||
<defaultAssemblyRequest permissionSetReference="Custom" />
|
||||
<PermissionSet class="System.Security.PermissionSet" version="1" Unrestricted="true" ID="Custom" SameSite="site" />
|
||||
</applicationRequestMinimum>
|
||||
</security>
|
||||
</trustInfo>
|
||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||
<application>
|
||||
<!-- Windows Vista -->
|
||||
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />
|
||||
<!-- Windows 7 -->
|
||||
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />
|
||||
<!-- Windows 8 -->
|
||||
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />
|
||||
<!-- Windows 8.1 -->
|
||||
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />
|
||||
<!-- Windows 10 -->
|
||||
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
|
||||
</application>
|
||||
</compatibility>
|
||||
<asmv3:application>
|
||||
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
|
||||
<dpiAware>true</dpiAware>
|
||||
</asmv3:windowsSettings>
|
||||
</asmv3:application>
|
||||
<dependency>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity
|
||||
type="win32"
|
||||
name="Microsoft.Windows.Common-Controls"
|
||||
version="6.0.0.0"
|
||||
processorArchitecture="*"
|
||||
publicKeyToken="6595b64144ccf1df"
|
||||
language="*"
|
||||
/>
|
||||
</dependentAssembly>
|
||||
</dependency>
|
||||
</asmv1:assembly>
|
||||
@@ -7,7 +7,7 @@
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/bin/Debug/net8.0/osu.Game.Rulesets.EmptyFreeformRuleset.Tests.dll"
|
||||
"${workspaceRoot}/bin/Debug/net6.0/osu.Game.Rulesets.EmptyFreeformRuleset.Tests.dll"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build (Debug)",
|
||||
@@ -20,7 +20,7 @@
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/bin/Release/net8.0/osu.Game.Rulesets.EmptyFreeformRuleset.Tests.dll"
|
||||
"${workspaceRoot}/bin/Release/net6.0/osu.Game.Rulesets.EmptyFreeformRuleset.Tests.dll"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build (Release)",
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.EmptyFreeform.Tests
|
||||
[STAThread]
|
||||
public static int Main(string[] args)
|
||||
{
|
||||
using (DesktopGameHost host = Host.GetSuitableDesktopHost(@"osu"))
|
||||
using (DesktopGameHost host = Host.GetSuitableDesktopHost(@"osu", new HostOptions { BindIPC = true }))
|
||||
{
|
||||
host.Run(new OsuTestBrowser());
|
||||
return 0;
|
||||
|
||||
@@ -9,16 +9,16 @@
|
||||
<GenerateProgramFile>false</GenerateProgramFile>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Label="Package References">
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
|
||||
<PackageReference Include="NUnit" Version="4.5.1" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="6.1.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.2" />
|
||||
<PackageReference Include="NUnit" Version="3.13.3" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\osu.Game.Rulesets.EmptyFreeform\osu.Game.Rulesets.EmptyFreeform.csproj" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Project">
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<RootNamespace>osu.Game.Rulesets.EmptyFreeform.Tests</RootNamespace>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.EmptyFreeform.Objects.Drawables
|
||||
{
|
||||
if (timeOffset >= 0)
|
||||
// todo: implement judgement logic
|
||||
ApplyResult(HitResult.Perfect);
|
||||
ApplyResult(r => r.Type = HitResult.Perfect);
|
||||
}
|
||||
|
||||
protected override void UpdateHitStateTransforms(ArmedState state)
|
||||
|
||||
@@ -14,16 +14,7 @@ namespace osu.Game.Rulesets.EmptyFreeform.Objects
|
||||
|
||||
public Vector2 Position { get; set; }
|
||||
|
||||
public float X
|
||||
{
|
||||
get => Position.X;
|
||||
set => Position = new Vector2(value, Y);
|
||||
}
|
||||
|
||||
public float Y
|
||||
{
|
||||
get => Position.Y;
|
||||
set => Position = new Vector2(X, value);
|
||||
}
|
||||
public float X => Position.X;
|
||||
public float Y => Position.Y;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Game.Rulesets.Replays;
|
||||
using osuTK;
|
||||
|
||||
@@ -18,8 +17,5 @@ namespace osu.Game.Rulesets.EmptyFreeform.Replays
|
||||
if (button.HasValue)
|
||||
Actions.Add(button.Value);
|
||||
}
|
||||
|
||||
public override bool IsEquivalentTo(ReplayFrame other)
|
||||
=> other is EmptyFreeformReplayFrame freeformFrame && Time == freeformFrame.Time && Position == freeformFrame.Position && Actions.SequenceEqual(freeformFrame.Actions);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup Label="Project">
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<AssemblyTitle>osu.Game.Rulesets.EmptyFreeform</AssemblyTitle>
|
||||
<OutputType>Library</OutputType>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
<!-- Contains required properties for osu!framework projects. -->
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<ApplicationManifest>$(MSBuildThisFileDirectory)app.manifest</ApplicationManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Documentation">
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -1,46 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
|
||||
<assemblyIdentity version="1.0.0.0" name="MyNewProject" />
|
||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
|
||||
<security>
|
||||
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
|
||||
</requestedPrivileges>
|
||||
<applicationRequestMinimum>
|
||||
<defaultAssemblyRequest permissionSetReference="Custom" />
|
||||
<PermissionSet class="System.Security.PermissionSet" version="1" Unrestricted="true" ID="Custom" SameSite="site" />
|
||||
</applicationRequestMinimum>
|
||||
</security>
|
||||
</trustInfo>
|
||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||
<application>
|
||||
<!-- Windows Vista -->
|
||||
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />
|
||||
<!-- Windows 7 -->
|
||||
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />
|
||||
<!-- Windows 8 -->
|
||||
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />
|
||||
<!-- Windows 8.1 -->
|
||||
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />
|
||||
<!-- Windows 10 -->
|
||||
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
|
||||
</application>
|
||||
</compatibility>
|
||||
<asmv3:application>
|
||||
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
|
||||
<dpiAware>true</dpiAware>
|
||||
</asmv3:windowsSettings>
|
||||
</asmv3:application>
|
||||
<dependency>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity
|
||||
type="win32"
|
||||
name="Microsoft.Windows.Common-Controls"
|
||||
version="6.0.0.0"
|
||||
processorArchitecture="*"
|
||||
publicKeyToken="6595b64144ccf1df"
|
||||
language="*"
|
||||
/>
|
||||
</dependentAssembly>
|
||||
</dependency>
|
||||
</asmv1:assembly>
|
||||
@@ -7,7 +7,7 @@
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/bin/Debug/net8.0/osu.Game.Rulesets.Pippidon.Tests.dll"
|
||||
"${workspaceRoot}/bin/Debug/net6.0/osu.Game.Rulesets.Pippidon.Tests.dll"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build (Debug)",
|
||||
@@ -20,7 +20,7 @@
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/bin/Release/net8.0/osu.Game.Rulesets.Pippidon.Tests.dll"
|
||||
"${workspaceRoot}/bin/Release/net6.0/osu.Game.Rulesets.Pippidon.Tests.dll"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build (Release)",
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.Pippidon.Tests
|
||||
[STAThread]
|
||||
public static int Main(string[] args)
|
||||
{
|
||||
using (DesktopGameHost host = Host.GetSuitableDesktopHost(@"osu"))
|
||||
using (DesktopGameHost host = Host.GetSuitableDesktopHost(@"osu", new HostOptions { BindIPC = true }))
|
||||
{
|
||||
host.Run(new OsuTestBrowser());
|
||||
return 0;
|
||||
|
||||
@@ -9,16 +9,16 @@
|
||||
<GenerateProgramFile>false</GenerateProgramFile>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Label="Package References">
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
|
||||
<PackageReference Include="NUnit" Version="4.5.1" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="6.1.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.2" />
|
||||
<PackageReference Include="NUnit" Version="3.13.3" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\osu.Game.Rulesets.Pippidon\osu.Game.Rulesets.Pippidon.csproj" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Project">
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<RootNamespace>osu.Game.Rulesets.Pippidon.Tests</RootNamespace>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
||||
@@ -9,6 +9,7 @@ using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Game.Audio;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
@@ -48,12 +49,7 @@ namespace osu.Game.Rulesets.Pippidon.Objects.Drawables
|
||||
protected override void CheckForResult(bool userTriggered, double timeOffset)
|
||||
{
|
||||
if (timeOffset >= 0)
|
||||
{
|
||||
if (IsHovered)
|
||||
ApplyMaxResult();
|
||||
else
|
||||
ApplyMinResult();
|
||||
}
|
||||
ApplyResult(r => r.Type = IsHovered ? HitResult.Perfect : HitResult.Miss);
|
||||
}
|
||||
|
||||
protected override double InitialLifetimeOffset => time_preempt;
|
||||
|
||||
@@ -14,16 +14,7 @@ namespace osu.Game.Rulesets.Pippidon.Objects
|
||||
|
||||
public Vector2 Position { get; set; }
|
||||
|
||||
public float X
|
||||
{
|
||||
get => Position.X;
|
||||
set => Position = new Vector2(value, Y);
|
||||
}
|
||||
|
||||
public float Y
|
||||
{
|
||||
get => Position.Y;
|
||||
set => Position = new Vector2(X, value);
|
||||
}
|
||||
public float X => Position.X;
|
||||
public float Y => Position.Y;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,8 +9,5 @@ namespace osu.Game.Rulesets.Pippidon.Replays
|
||||
public class PippidonReplayFrame : ReplayFrame
|
||||
{
|
||||
public Vector2 Position;
|
||||
|
||||
public override bool IsEquivalentTo(ReplayFrame other)
|
||||
=> other is PippidonReplayFrame pippidonFrame && Time == pippidonFrame.Time && Position == pippidonFrame.Position;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup Label="Project">
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<AssemblyTitle>osu.Game.Rulesets.Pippidon</AssemblyTitle>
|
||||
<OutputType>Library</OutputType>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
<!-- Contains required properties for osu!framework projects. -->
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<ApplicationManifest>$(MSBuildThisFileDirectory)app.manifest</ApplicationManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Documentation">
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -1,46 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
|
||||
<assemblyIdentity version="1.0.0.0" name="MyNewProject" />
|
||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
|
||||
<security>
|
||||
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
|
||||
</requestedPrivileges>
|
||||
<applicationRequestMinimum>
|
||||
<defaultAssemblyRequest permissionSetReference="Custom" />
|
||||
<PermissionSet class="System.Security.PermissionSet" version="1" Unrestricted="true" ID="Custom" SameSite="site" />
|
||||
</applicationRequestMinimum>
|
||||
</security>
|
||||
</trustInfo>
|
||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||
<application>
|
||||
<!-- Windows Vista -->
|
||||
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />
|
||||
<!-- Windows 7 -->
|
||||
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />
|
||||
<!-- Windows 8 -->
|
||||
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />
|
||||
<!-- Windows 8.1 -->
|
||||
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />
|
||||
<!-- Windows 10 -->
|
||||
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
|
||||
</application>
|
||||
</compatibility>
|
||||
<asmv3:application>
|
||||
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
|
||||
<dpiAware>true</dpiAware>
|
||||
</asmv3:windowsSettings>
|
||||
</asmv3:application>
|
||||
<dependency>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity
|
||||
type="win32"
|
||||
name="Microsoft.Windows.Common-Controls"
|
||||
version="6.0.0.0"
|
||||
processorArchitecture="*"
|
||||
publicKeyToken="6595b64144ccf1df"
|
||||
language="*"
|
||||
/>
|
||||
</dependentAssembly>
|
||||
</dependency>
|
||||
</asmv1:assembly>
|
||||
@@ -7,7 +7,7 @@
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/bin/Debug/net8.0/osu.Game.Rulesets.EmptyScrolling.Tests.dll"
|
||||
"${workspaceRoot}/bin/Debug/net6.0/osu.Game.Rulesets.EmptyScrolling.Tests.dll"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build (Debug)",
|
||||
@@ -20,7 +20,7 @@
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/bin/Release/net8.0/osu.Game.Rulesets.EmptyScrolling.Tests.dll"
|
||||
"${workspaceRoot}/bin/Release/net6.0/osu.Game.Rulesets.EmptyScrolling.Tests.dll"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build (Release)",
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.EmptyScrolling.Tests
|
||||
[STAThread]
|
||||
public static int Main(string[] args)
|
||||
{
|
||||
using (DesktopGameHost host = Host.GetSuitableDesktopHost(@"osu"))
|
||||
using (DesktopGameHost host = Host.GetSuitableDesktopHost(@"osu", new HostOptions { BindIPC = true }))
|
||||
{
|
||||
host.Run(new OsuTestBrowser());
|
||||
return 0;
|
||||
|
||||
@@ -9,16 +9,16 @@
|
||||
<GenerateProgramFile>false</GenerateProgramFile>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Label="Package References">
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
|
||||
<PackageReference Include="NUnit" Version="4.5.1" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="6.1.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.2" />
|
||||
<PackageReference Include="NUnit" Version="3.13.3" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\osu.Game.Rulesets.EmptyScrolling\osu.Game.Rulesets.EmptyScrolling.csproj" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Project">
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<RootNamespace>osu.Game.Rulesets.EmptyScrolling.Tests</RootNamespace>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
@@ -23,7 +24,7 @@ namespace osu.Game.Rulesets.EmptyScrolling.Objects.Drawables
|
||||
{
|
||||
if (timeOffset >= 0)
|
||||
// todo: implement judgement logic
|
||||
ApplyMaxResult();
|
||||
ApplyResult(r => r.Type = HitResult.Perfect);
|
||||
}
|
||||
|
||||
protected override void UpdateHitStateTransforms(ArmedState state)
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Game.Rulesets.Replays;
|
||||
|
||||
namespace osu.Game.Rulesets.EmptyScrolling.Replays
|
||||
@@ -16,8 +15,5 @@ namespace osu.Game.Rulesets.EmptyScrolling.Replays
|
||||
if (button.HasValue)
|
||||
Actions.Add(button.Value);
|
||||
}
|
||||
|
||||
public override bool IsEquivalentTo(ReplayFrame other)
|
||||
=> other is EmptyScrollingReplayFrame scrollingFrame && Time == scrollingFrame.Time && Actions.SequenceEqual(scrollingFrame.Actions);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup Label="Project">
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<AssemblyTitle>osu.Game.Rulesets.EmptyScrolling</AssemblyTitle>
|
||||
<OutputType>Library</OutputType>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
<!-- Contains required properties for osu!framework projects. -->
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<ApplicationManifest>$(MSBuildThisFileDirectory)app.manifest</ApplicationManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Documentation">
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -1,46 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
|
||||
<assemblyIdentity version="1.0.0.0" name="MyNewProject" />
|
||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
|
||||
<security>
|
||||
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
|
||||
</requestedPrivileges>
|
||||
<applicationRequestMinimum>
|
||||
<defaultAssemblyRequest permissionSetReference="Custom" />
|
||||
<PermissionSet class="System.Security.PermissionSet" version="1" Unrestricted="true" ID="Custom" SameSite="site" />
|
||||
</applicationRequestMinimum>
|
||||
</security>
|
||||
</trustInfo>
|
||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||
<application>
|
||||
<!-- Windows Vista -->
|
||||
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />
|
||||
<!-- Windows 7 -->
|
||||
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />
|
||||
<!-- Windows 8 -->
|
||||
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />
|
||||
<!-- Windows 8.1 -->
|
||||
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />
|
||||
<!-- Windows 10 -->
|
||||
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
|
||||
</application>
|
||||
</compatibility>
|
||||
<asmv3:application>
|
||||
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
|
||||
<dpiAware>true</dpiAware>
|
||||
</asmv3:windowsSettings>
|
||||
</asmv3:application>
|
||||
<dependency>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity
|
||||
type="win32"
|
||||
name="Microsoft.Windows.Common-Controls"
|
||||
version="6.0.0.0"
|
||||
processorArchitecture="*"
|
||||
publicKeyToken="6595b64144ccf1df"
|
||||
language="*"
|
||||
/>
|
||||
</dependentAssembly>
|
||||
</dependency>
|
||||
</asmv1:assembly>
|
||||
@@ -7,7 +7,7 @@
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/bin/Debug/net8.0/osu.Game.Rulesets.Pippidon.Tests.dll"
|
||||
"${workspaceRoot}/bin/Debug/net6.0/osu.Game.Rulesets.Pippidon.Tests.dll"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build (Debug)",
|
||||
@@ -20,7 +20,7 @@
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/bin/Release/net8.0/osu.Game.Rulesets.Pippidon.Tests.dll"
|
||||
"${workspaceRoot}/bin/Release/net6.0/osu.Game.Rulesets.Pippidon.Tests.dll"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build (Release)",
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.Pippidon.Tests
|
||||
[STAThread]
|
||||
public static int Main(string[] args)
|
||||
{
|
||||
using (DesktopGameHost host = Host.GetSuitableDesktopHost(@"osu"))
|
||||
using (DesktopGameHost host = Host.GetSuitableDesktopHost(@"osu", new HostOptions { BindIPC = true }))
|
||||
{
|
||||
host.Run(new OsuTestBrowser());
|
||||
return 0;
|
||||
|
||||
@@ -9,16 +9,16 @@
|
||||
<GenerateProgramFile>false</GenerateProgramFile>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Label="Package References">
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
|
||||
<PackageReference Include="NUnit" Version="4.5.1" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="6.1.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.2" />
|
||||
<PackageReference Include="NUnit" Version="3.13.3" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\osu.Game.Rulesets.Pippidon\osu.Game.Rulesets.Pippidon.csproj" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Project">
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<RootNamespace>osu.Game.Rulesets.Pippidon.Tests</RootNamespace>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
@@ -10,6 +9,7 @@ using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Rulesets.Pippidon.Objects;
|
||||
using osu.Game.Rulesets.Pippidon.UI;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Pippidon.Beatmaps
|
||||
{
|
||||
@@ -40,7 +40,7 @@ namespace osu.Game.Rulesets.Pippidon.Beatmaps
|
||||
};
|
||||
}
|
||||
|
||||
private int getLane(HitObject hitObject) => (int)Math.Clamp(
|
||||
private int getLane(HitObject hitObject) => (int)MathHelper.Clamp(
|
||||
(getUsablePosition(hitObject) - minPosition) / (maxPosition - minPosition) * PippidonPlayfield.LANE_COUNT, 0, PippidonPlayfield.LANE_COUNT - 1);
|
||||
|
||||
private float getUsablePosition(HitObject h) => (h as IHasYPosition)?.Y ?? ((IHasXPosition)h).X;
|
||||
|
||||
@@ -10,6 +10,7 @@ using osu.Framework.Graphics.Textures;
|
||||
using osu.Game.Audio;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Pippidon.UI;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
@@ -48,12 +49,7 @@ namespace osu.Game.Rulesets.Pippidon.Objects.Drawables
|
||||
protected override void CheckForResult(bool userTriggered, double timeOffset)
|
||||
{
|
||||
if (timeOffset >= 0)
|
||||
{
|
||||
if (currentLane.Value == HitObject.Lane)
|
||||
ApplyMaxResult();
|
||||
else
|
||||
ApplyMinResult();
|
||||
}
|
||||
ApplyResult(r => r.Type = currentLane.Value == HitObject.Lane ? HitResult.Perfect : HitResult.Miss);
|
||||
}
|
||||
|
||||
protected override void UpdateHitStateTransforms(ArmedState state)
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Game.Rulesets.Replays;
|
||||
|
||||
namespace osu.Game.Rulesets.Pippidon.Replays
|
||||
@@ -16,8 +15,5 @@ namespace osu.Game.Rulesets.Pippidon.Replays
|
||||
if (button.HasValue)
|
||||
Actions.Add(button.Value);
|
||||
}
|
||||
|
||||
public override bool IsEquivalentTo(ReplayFrame other)
|
||||
=> other is PippidonReplayFrame pippidonFrame && Time == pippidonFrame.Time && Actions.SequenceEqual(pippidonFrame.Actions);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup Label="Project">
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<AssemblyTitle>osu.Game.Rulesets.Pippidon</AssemblyTitle>
|
||||
<OutputType>Library</OutputType>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<PackageType>Template</PackageType>
|
||||
<PackageId>ppy.osu.Game.Templates</PackageId>
|
||||
@@ -8,7 +8,7 @@
|
||||
<PackageProjectUrl>https://github.com/ppy/osu/blob/master/Templates</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/ppy/osu</RepositoryUrl>
|
||||
<PackageReleaseNotes>Automated release.</PackageReleaseNotes>
|
||||
<copyright>Copyright (c) 2025 ppy Pty Ltd</copyright>
|
||||
<copyright>Copyright (c) 2022 ppy Pty Ltd</copyright>
|
||||
<Description>Templates to use when creating a ruleset for consumption in osu!.</Description>
|
||||
<PackageTags>dotnet-new;templates;osu</PackageTags>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
clone_depth: 1
|
||||
version: '{branch}-{build}'
|
||||
image: Visual Studio 2022
|
||||
cache:
|
||||
- '%LOCALAPPDATA%\NuGet\v3-cache -> appveyor.yml'
|
||||
|
||||
dotnet_csproj:
|
||||
patch: true
|
||||
file: 'osu.Game\osu.Game.csproj' # Use wildcard when it's able to exclude Xamarin projects
|
||||
version: '0.0.{build}'
|
||||
|
||||
before_build:
|
||||
- cmd: dotnet --info # Useful when version mismatch between CI and local
|
||||
- cmd: dotnet workload install maui-android # Change to `dotnet workload restore` once there's no old projects
|
||||
- cmd: dotnet workload install maui-ios # Change to `dotnet workload restore` once there's no old projects
|
||||
- cmd: nuget restore -verbosity quiet # Only nuget.exe knows both new (.NET Core) and old (Xamarin) projects
|
||||
|
||||
build:
|
||||
project: osu.sln
|
||||
parallel: true
|
||||
verbosity: minimal
|
||||
publish_nuget: true
|
||||
|
||||
after_build:
|
||||
- ps: .\InspectCode.ps1
|
||||
|
||||
test:
|
||||
assemblies:
|
||||
except:
|
||||
- '**\*Android*'
|
||||
- '**\*iOS*'
|
||||
- 'build\**\*'
|
||||
@@ -0,0 +1,86 @@
|
||||
clone_depth: 1
|
||||
version: '{build}'
|
||||
image: Visual Studio 2022
|
||||
test: off
|
||||
skip_non_tags: true
|
||||
configuration: Release
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
- job_name: osu-game
|
||||
- job_name: osu-ruleset
|
||||
job_depends_on: osu-game
|
||||
- job_name: taiko-ruleset
|
||||
job_depends_on: osu-game
|
||||
- job_name: catch-ruleset
|
||||
job_depends_on: osu-game
|
||||
- job_name: mania-ruleset
|
||||
job_depends_on: osu-game
|
||||
- job_name: templates
|
||||
job_depends_on: osu-game
|
||||
|
||||
nuget:
|
||||
project_feed: true
|
||||
|
||||
for:
|
||||
-
|
||||
matrix:
|
||||
only:
|
||||
- job_name: osu-game
|
||||
build_script:
|
||||
- cmd: dotnet pack osu.Game\osu.Game.csproj /p:Version=%APPVEYOR_REPO_TAG_NAME%
|
||||
-
|
||||
matrix:
|
||||
only:
|
||||
- job_name: osu-ruleset
|
||||
build_script:
|
||||
- cmd: dotnet remove osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj reference osu.Game\osu.Game.csproj
|
||||
- cmd: dotnet add osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj package ppy.osu.Game -v %APPVEYOR_REPO_TAG_NAME%
|
||||
- cmd: dotnet pack osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj /p:Version=%APPVEYOR_REPO_TAG_NAME%
|
||||
-
|
||||
matrix:
|
||||
only:
|
||||
- job_name: taiko-ruleset
|
||||
build_script:
|
||||
- cmd: dotnet remove osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj reference osu.Game\osu.Game.csproj
|
||||
- cmd: dotnet add osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj package ppy.osu.Game -v %APPVEYOR_REPO_TAG_NAME%
|
||||
- cmd: dotnet pack osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj /p:Version=%APPVEYOR_REPO_TAG_NAME%
|
||||
-
|
||||
matrix:
|
||||
only:
|
||||
- job_name: catch-ruleset
|
||||
build_script:
|
||||
- cmd: dotnet remove osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj reference osu.Game\osu.Game.csproj
|
||||
- cmd: dotnet add osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj package ppy.osu.Game -v %APPVEYOR_REPO_TAG_NAME%
|
||||
- cmd: dotnet pack osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj /p:Version=%APPVEYOR_REPO_TAG_NAME%
|
||||
-
|
||||
matrix:
|
||||
only:
|
||||
- job_name: mania-ruleset
|
||||
build_script:
|
||||
- cmd: dotnet remove osu.Game.Rulesets.Mania\osu.Game.Rulesets.Mania.csproj reference osu.Game\osu.Game.csproj
|
||||
- cmd: dotnet add osu.Game.Rulesets.Mania\osu.Game.Rulesets.Mania.csproj package ppy.osu.Game -v %APPVEYOR_REPO_TAG_NAME%
|
||||
- cmd: dotnet pack osu.Game.Rulesets.Mania\osu.Game.Rulesets.Mania.csproj /p:Version=%APPVEYOR_REPO_TAG_NAME%
|
||||
-
|
||||
matrix:
|
||||
only:
|
||||
- job_name: templates
|
||||
build_script:
|
||||
- cmd: dotnet remove Templates\Rulesets\ruleset-empty\osu.Game.Rulesets.EmptyFreeform\osu.Game.Rulesets.EmptyFreeform.csproj reference osu.Game\osu.Game.csproj
|
||||
- cmd: dotnet remove Templates\Rulesets\ruleset-example\osu.Game.Rulesets.Pippidon\osu.Game.Rulesets.Pippidon.csproj reference osu.Game\osu.Game.csproj
|
||||
- cmd: dotnet remove Templates\Rulesets\ruleset-scrolling-empty\osu.Game.Rulesets.EmptyScrolling\osu.Game.Rulesets.EmptyScrolling.csproj reference osu.Game\osu.Game.csproj
|
||||
- cmd: dotnet remove Templates\Rulesets\ruleset-scrolling-example\osu.Game.Rulesets.Pippidon\osu.Game.Rulesets.Pippidon.csproj reference osu.Game\osu.Game.csproj
|
||||
|
||||
- cmd: dotnet add Templates\Rulesets\ruleset-empty\osu.Game.Rulesets.EmptyFreeform\osu.Game.Rulesets.EmptyFreeform.csproj package ppy.osu.Game -v %APPVEYOR_REPO_TAG_NAME%
|
||||
- cmd: dotnet add Templates\Rulesets\ruleset-example\osu.Game.Rulesets.Pippidon\osu.Game.Rulesets.Pippidon.csproj package ppy.osu.Game -v %APPVEYOR_REPO_TAG_NAME%
|
||||
- cmd: dotnet add Templates\Rulesets\ruleset-scrolling-empty\osu.Game.Rulesets.EmptyScrolling\osu.Game.Rulesets.EmptyScrolling.csproj package ppy.osu.Game -v %APPVEYOR_REPO_TAG_NAME%
|
||||
- cmd: dotnet add Templates\Rulesets\ruleset-scrolling-example\osu.Game.Rulesets.Pippidon\osu.Game.Rulesets.Pippidon.csproj package ppy.osu.Game -v %APPVEYOR_REPO_TAG_NAME%
|
||||
|
||||
- cmd: dotnet pack Templates\osu.Game.Templates.csproj /p:Version=%APPVEYOR_REPO_TAG_NAME%
|
||||
|
||||
artifacts:
|
||||
- path: '**\*.nupkg'
|
||||
|
||||
deploy:
|
||||
- provider: Environment
|
||||
name: nuget
|
||||
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 438 KiB After Width: | Height: | Size: 187 KiB |
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"sdk": {
|
||||
"version": "8.0.100",
|
||||
"rollForward": "latestFeature",
|
||||
"allowPrerelease": false
|
||||
"version": "6.0.100",
|
||||
"rollForward": "latestFeature"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2026.513.0" />
|
||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2023.1006.0" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<!-- Fody does not handle Android build well, and warns when unchanged.
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Android.Input;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Overlays.Settings;
|
||||
|
||||
namespace osu.Android
|
||||
{
|
||||
public partial class AndroidJoystickSettings : SettingsSubsection
|
||||
{
|
||||
protected override LocalisableString Header => JoystickSettingsStrings.JoystickGamepad;
|
||||
|
||||
private readonly AndroidJoystickHandler joystickHandler;
|
||||
|
||||
private readonly Bindable<bool> enabled = new BindableBool(true);
|
||||
|
||||
private SettingsSlider<float> deadzoneSlider = null!;
|
||||
|
||||
private Bindable<float> handlerDeadzone = null!;
|
||||
|
||||
private Bindable<float> localDeadzone = null!;
|
||||
|
||||
public AndroidJoystickSettings(AndroidJoystickHandler joystickHandler)
|
||||
{
|
||||
this.joystickHandler = joystickHandler;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
// use local bindable to avoid changing enabled state of game host's bindable.
|
||||
handlerDeadzone = joystickHandler.DeadzoneThreshold.GetBoundCopy();
|
||||
localDeadzone = handlerDeadzone.GetUnboundCopy();
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new SettingsCheckbox
|
||||
{
|
||||
LabelText = CommonStrings.Enabled,
|
||||
Current = enabled
|
||||
},
|
||||
deadzoneSlider = new SettingsSlider<float>
|
||||
{
|
||||
LabelText = JoystickSettingsStrings.DeadzoneThreshold,
|
||||
KeyboardStep = 0.01f,
|
||||
DisplayAsPercentage = true,
|
||||
Current = localDeadzone,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
enabled.BindTo(joystickHandler.Enabled);
|
||||
enabled.BindValueChanged(e => deadzoneSlider.Current.Disabled = !e.NewValue, true);
|
||||
|
||||
handlerDeadzone.BindValueChanged(val =>
|
||||
{
|
||||
bool disabled = localDeadzone.Disabled;
|
||||
|
||||
localDeadzone.Disabled = false;
|
||||
localDeadzone.Value = val.NewValue;
|
||||
localDeadzone.Disabled = disabled;
|
||||
}, true);
|
||||
|
||||
localDeadzone.BindValueChanged(val => handlerDeadzone.Value = val.NewValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="sh.ppy.osulazer" android:installLocation="auto">
|
||||
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="34" />
|
||||
<application android:allowBackup="true"
|
||||
android:supportsRtl="true"
|
||||
android:label="osu!"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:roundIcon="@mipmap/ic_launcher">
|
||||
<provider android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="sh.ppy.osulazer.fileprovider"
|
||||
android:grantUriPermissions="true"
|
||||
android:exported="false">
|
||||
<meta-data android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/filepaths" />
|
||||
</provider>
|
||||
</application>
|
||||
</manifest>
|
||||
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="33" />
|
||||
<application android:allowBackup="true" android:supportsRtl="true" android:label="osu!" android:icon="@drawable/lazer" />
|
||||
<!-- for editor usage -->
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
|
||||
</manifest>
|
||||
@@ -0,0 +1,97 @@
|
||||
// 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 Android.OS;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Android.Input;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Overlays.Settings;
|
||||
using osu.Game.Overlays.Settings.Sections.Input;
|
||||
|
||||
namespace osu.Android
|
||||
{
|
||||
public partial class AndroidMouseSettings : SettingsSubsection
|
||||
{
|
||||
private readonly AndroidMouseHandler mouseHandler;
|
||||
|
||||
protected override LocalisableString Header => MouseSettingsStrings.Mouse;
|
||||
|
||||
private Bindable<double> handlerSensitivity = null!;
|
||||
|
||||
private Bindable<double> localSensitivity = null!;
|
||||
|
||||
private Bindable<bool> relativeMode = null!;
|
||||
|
||||
public AndroidMouseSettings(AndroidMouseHandler mouseHandler)
|
||||
{
|
||||
this.mouseHandler = mouseHandler;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuConfigManager osuConfig)
|
||||
{
|
||||
// use local bindable to avoid changing enabled state of game host's bindable.
|
||||
handlerSensitivity = mouseHandler.Sensitivity.GetBoundCopy();
|
||||
localSensitivity = handlerSensitivity.GetUnboundCopy();
|
||||
|
||||
relativeMode = mouseHandler.UseRelativeMode.GetBoundCopy();
|
||||
|
||||
// High precision/pointer capture is only available on Android 8.0 and up
|
||||
if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
|
||||
{
|
||||
AddRange(new Drawable[]
|
||||
{
|
||||
new SettingsCheckbox
|
||||
{
|
||||
LabelText = MouseSettingsStrings.HighPrecisionMouse,
|
||||
TooltipText = MouseSettingsStrings.HighPrecisionMouseTooltip,
|
||||
Current = relativeMode,
|
||||
Keywords = new[] { @"raw", @"input", @"relative", @"cursor", @"captured", @"pointer" },
|
||||
},
|
||||
new MouseSettings.SensitivitySetting
|
||||
{
|
||||
LabelText = MouseSettingsStrings.CursorSensitivity,
|
||||
Current = localSensitivity,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
AddRange(new Drawable[]
|
||||
{
|
||||
new SettingsCheckbox
|
||||
{
|
||||
LabelText = MouseSettingsStrings.DisableMouseWheelVolumeAdjust,
|
||||
TooltipText = MouseSettingsStrings.DisableMouseWheelVolumeAdjustTooltip,
|
||||
Current = osuConfig.GetBindable<bool>(OsuSetting.MouseDisableWheel),
|
||||
},
|
||||
new SettingsCheckbox
|
||||
{
|
||||
LabelText = MouseSettingsStrings.DisableMouseButtons,
|
||||
Current = osuConfig.GetBindable<bool>(OsuSetting.MouseDisableButtons),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
relativeMode.BindValueChanged(relative => localSensitivity.Disabled = !relative.NewValue, true);
|
||||
|
||||
handlerSensitivity.BindValueChanged(val =>
|
||||
{
|
||||
bool disabled = localSensitivity.Disabled;
|
||||
|
||||
localSensitivity.Disabled = false;
|
||||
localSensitivity.Value = val.NewValue;
|
||||
localSensitivity.Disabled = disabled;
|
||||
}, true);
|
||||
|
||||
localSensitivity.BindValueChanged(val => handlerSensitivity.Value = val.NewValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using Android.Content.PM;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game;
|
||||
|
||||
namespace osu.Android
|
||||
{
|
||||
public partial class GameplayScreenRotationLocker : Component
|
||||
{
|
||||
private Bindable<bool> localUserPlaying = null!;
|
||||
|
||||
[Resolved]
|
||||
private OsuGameActivity gameActivity { get; set; } = null!;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuGame game)
|
||||
{
|
||||
localUserPlaying = game.LocalUserPlaying.GetBoundCopy();
|
||||
localUserPlaying.BindValueChanged(updateLock, true);
|
||||
}
|
||||
|
||||
private void updateLock(ValueChangedEvent<bool> userPlaying)
|
||||
{
|
||||
gameActivity.RunOnUiThread(() =>
|
||||
{
|
||||
gameActivity.RequestedOrientation = userPlaying.NewValue ? ScreenOrientation.Locked : gameActivity.DefaultOrientation;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ using Android.Graphics;
|
||||
using Android.OS;
|
||||
using Android.Views;
|
||||
using osu.Framework.Android;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
using osu.Game.Database;
|
||||
using Debug = System.Diagnostics.Debug;
|
||||
using Uri = Android.Net.Uri;
|
||||
@@ -20,24 +21,13 @@ using Uri = Android.Net.Uri;
|
||||
namespace osu.Android
|
||||
{
|
||||
[Activity(ConfigurationChanges = DEFAULT_CONFIG_CHANGES, Exported = true, LaunchMode = DEFAULT_LAUNCH_MODE, MainLauncher = true)]
|
||||
[IntentFilter(new[] { Intent.ActionView }, Categories = new[] { Intent.CategoryDefault }, Label = "Import beatmap", DataScheme = "content", DataPathPattern = ".*\\\\.osz", DataHost = "*",
|
||||
DataMimeType = "*/*")]
|
||||
[IntentFilter(new[] { Intent.ActionView }, Categories = new[] { Intent.CategoryDefault }, Label = "Import skin", DataScheme = "content", DataPathPattern = ".*\\\\.osk", DataHost = "*",
|
||||
DataMimeType = "*/*")]
|
||||
[IntentFilter(new[] { Intent.ActionView }, Categories = new[] { Intent.CategoryDefault }, Label = "Import replay", DataScheme = "content", DataPathPattern = ".*\\\\.osr", DataHost = "*",
|
||||
DataMimeType = "*/*")]
|
||||
[IntentFilter(new[] { Intent.ActionView }, Categories = new[] { Intent.CategoryDefault }, Label = "Import beatmap", DataScheme = "content", DataMimeType = "application/x-osu-beatmap-archive")]
|
||||
[IntentFilter(new[] { Intent.ActionView }, Categories = new[] { Intent.CategoryDefault }, Label = "Import skin", DataScheme = "content", DataMimeType = "application/x-osu-skin-archive")]
|
||||
[IntentFilter(new[] { Intent.ActionView }, Categories = new[] { Intent.CategoryDefault }, Label = "Import replay", DataScheme = "content", DataMimeType = "application/x-osu-replay")]
|
||||
[IntentFilter(new[] { Intent.ActionView }, Categories = new[] { Intent.CategoryDefault }, Label = "Import file", DataScheme = "content", DataMimeTypes = new[]
|
||||
{
|
||||
"application/zip",
|
||||
"application/octet-stream",
|
||||
"application/download",
|
||||
"application/x-zip",
|
||||
"application/x-zip-compressed",
|
||||
})]
|
||||
[IntentFilter(new[] { Intent.ActionSend, Intent.ActionSendMultiple }, Categories = new[] { Intent.CategoryDefault }, Label = "Import", DataMimeTypes = new[]
|
||||
[IntentFilter(new[] { Intent.ActionView }, Categories = new[] { Intent.CategoryDefault }, DataScheme = "content", DataPathPattern = ".*\\\\.osz", DataHost = "*", DataMimeType = "*/*")]
|
||||
[IntentFilter(new[] { Intent.ActionView }, Categories = new[] { Intent.CategoryDefault }, DataScheme = "content", DataPathPattern = ".*\\\\.osk", DataHost = "*", DataMimeType = "*/*")]
|
||||
[IntentFilter(new[] { Intent.ActionView }, Categories = new[] { Intent.CategoryDefault }, DataScheme = "content", DataPathPattern = ".*\\\\.osr", DataHost = "*", DataMimeType = "*/*")]
|
||||
[IntentFilter(new[] { Intent.ActionView }, Categories = new[] { Intent.CategoryDefault }, DataScheme = "content", DataMimeType = "application/x-osu-beatmap-archive")]
|
||||
[IntentFilter(new[] { Intent.ActionView }, Categories = new[] { Intent.CategoryDefault }, DataScheme = "content", DataMimeType = "application/x-osu-skin-archive")]
|
||||
[IntentFilter(new[] { Intent.ActionView }, Categories = new[] { Intent.CategoryDefault }, DataScheme = "content", DataMimeType = "application/x-osu-replay")]
|
||||
[IntentFilter(new[] { Intent.ActionSend, Intent.ActionSendMultiple }, Categories = new[] { Intent.CategoryDefault }, DataMimeTypes = new[]
|
||||
{
|
||||
"application/zip",
|
||||
"application/octet-stream",
|
||||
@@ -60,25 +50,9 @@ namespace osu.Android
|
||||
/// <remarks>Adjusted on startup to match expected UX for the current device type (phone/tablet).</remarks>
|
||||
public ScreenOrientation DefaultOrientation = ScreenOrientation.Unspecified;
|
||||
|
||||
public new bool IsTablet { get; private set; }
|
||||
private OsuGameAndroid game = null!;
|
||||
|
||||
private readonly OsuGameAndroid game;
|
||||
|
||||
private bool gameCreated;
|
||||
|
||||
protected override Framework.Game CreateGame()
|
||||
{
|
||||
if (gameCreated)
|
||||
throw new InvalidOperationException("Framework tried to create a game twice.");
|
||||
|
||||
gameCreated = true;
|
||||
return game;
|
||||
}
|
||||
|
||||
public OsuGameActivity()
|
||||
{
|
||||
game = new OsuGameAndroid(this);
|
||||
}
|
||||
protected override Framework.Game CreateGame() => game = new OsuGameAndroid(this);
|
||||
|
||||
protected override void OnCreate(Bundle? savedInstanceState)
|
||||
{
|
||||
@@ -98,13 +72,13 @@ namespace osu.Android
|
||||
Debug.Assert(Resources?.DisplayMetrics != null);
|
||||
|
||||
Point displaySize = new Point();
|
||||
#pragma warning disable CA1422 // GetSize is deprecated
|
||||
#pragma warning disable 618 // GetSize is deprecated
|
||||
WindowManager.DefaultDisplay.GetSize(displaySize);
|
||||
#pragma warning restore CA1422
|
||||
#pragma warning restore 618
|
||||
float smallestWidthDp = Math.Min(displaySize.X, displaySize.Y) / Resources.DisplayMetrics.Density;
|
||||
IsTablet = smallestWidthDp >= 600f;
|
||||
bool isTablet = smallestWidthDp >= 600f;
|
||||
|
||||
RequestedOrientation = DefaultOrientation = IsTablet ? ScreenOrientation.FullUser : ScreenOrientation.SensorLandscape;
|
||||
RequestedOrientation = DefaultOrientation = isTablet ? ScreenOrientation.FullUser : ScreenOrientation.SensorLandscape;
|
||||
|
||||
// Currently (SDK 6.0.200), BundleAssemblies is not runnable for net6-android.
|
||||
// The assembly files are not available as files either after native AOT.
|
||||
@@ -121,38 +95,25 @@ namespace osu.Android
|
||||
|
||||
private void handleIntent(Intent? intent)
|
||||
{
|
||||
if (intent == null)
|
||||
return;
|
||||
|
||||
switch (intent.Action)
|
||||
switch (intent?.Action)
|
||||
{
|
||||
case Intent.ActionDefault:
|
||||
if (intent.Scheme == ContentResolver.SchemeContent)
|
||||
{
|
||||
if (intent.Data != null)
|
||||
handleImportFromUris(intent.Data);
|
||||
}
|
||||
handleImportFromUris(intent.Data.AsNonNull());
|
||||
else if (osu_url_schemes.Contains(intent.Scheme))
|
||||
{
|
||||
if (intent.DataString != null)
|
||||
game.HandleLink(intent.DataString);
|
||||
}
|
||||
|
||||
game.HandleLink(intent.DataString);
|
||||
break;
|
||||
|
||||
case Intent.ActionSend:
|
||||
case Intent.ActionSendMultiple:
|
||||
{
|
||||
if (intent.ClipData == null)
|
||||
break;
|
||||
|
||||
var uris = new List<Uri>();
|
||||
|
||||
for (int i = 0; i < intent.ClipData.ItemCount; i++)
|
||||
for (int i = 0; i < intent.ClipData?.ItemCount; i++)
|
||||
{
|
||||
var item = intent.ClipData.GetItemAt(i);
|
||||
if (item?.Uri != null)
|
||||
uris.Add(item.Uri);
|
||||
var content = intent.ClipData?.GetItemAt(i);
|
||||
if (content != null)
|
||||
uris.Add(content.Uri.AsNonNull());
|
||||
}
|
||||
|
||||
handleImportFromUris(uris.ToArray());
|
||||
|
||||
@@ -2,19 +2,17 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Android.App;
|
||||
using Android.Content.PM;
|
||||
using Microsoft.Maui.Devices;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Development;
|
||||
using osu.Framework.Android.Input;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
using osu.Framework.Input.Handlers;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game;
|
||||
using osu.Game.Screens;
|
||||
using osu.Game.Overlays.Settings;
|
||||
using osu.Game.Updater;
|
||||
using osu.Game.Utils;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Android
|
||||
{
|
||||
@@ -23,62 +21,60 @@ namespace osu.Android
|
||||
[Cached]
|
||||
private readonly OsuGameActivity gameActivity;
|
||||
|
||||
private readonly PackageInfo packageInfo;
|
||||
|
||||
public override Vector2 ScalingContainerTargetDrawSize => new Vector2(1024, 1024 * DrawHeight / DrawWidth);
|
||||
|
||||
public OsuGameAndroid(OsuGameActivity activity)
|
||||
: base(null)
|
||||
{
|
||||
gameActivity = activity;
|
||||
packageInfo = Application.Context.ApplicationContext!.PackageManager!.GetPackageInfo(Application.Context.ApplicationContext.PackageName!, 0).AsNonNull();
|
||||
}
|
||||
|
||||
public override string Version
|
||||
public override Version AssemblyVersion
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!IsDeployedBuild)
|
||||
return @"local " + (DebugUtils.IsDebugBuild ? @"debug" : @"release");
|
||||
var packageInfo = Application.Context.ApplicationContext!.PackageManager!.GetPackageInfo(Application.Context.ApplicationContext.PackageName!, 0).AsNonNull();
|
||||
|
||||
return packageInfo.VersionName.AsNonNull();
|
||||
try
|
||||
{
|
||||
// We store the osu! build number in the "VersionCode" field to better support google play releases.
|
||||
// If we were to use the main build number, it would require a new submission each time (similar to TestFlight).
|
||||
// In order to do this, we should split it up and pad the numbers to still ensure sequential increase over time.
|
||||
//
|
||||
// We also need to be aware that older SDK versions store this as a 32bit int.
|
||||
//
|
||||
// Basic conversion format (as done in Fastfile): 2020.606.0 -> 202006060
|
||||
|
||||
// https://stackoverflow.com/questions/52977079/android-sdk-28-versioncode-in-packageinfo-has-been-deprecated
|
||||
string versionName;
|
||||
|
||||
if (OperatingSystem.IsAndroidVersionAtLeast(28))
|
||||
{
|
||||
versionName = packageInfo.LongVersionCode.ToString();
|
||||
// ensure we only read the trailing portion of long (the part we are interested in).
|
||||
versionName = versionName.Substring(versionName.Length - 9);
|
||||
}
|
||||
else
|
||||
{
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
// this is required else older SDKs will report missing method exception.
|
||||
versionName = packageInfo.VersionCode.ToString();
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
}
|
||||
|
||||
// undo play store version garbling (as mentioned above).
|
||||
return new Version(int.Parse(versionName.Substring(0, 4)), int.Parse(versionName.Substring(4, 4)), int.Parse(versionName.Substring(8, 1)));
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
return new Version(packageInfo.VersionName.AsNonNull());
|
||||
}
|
||||
}
|
||||
|
||||
public override Version AssemblyVersion => new Version(packageInfo.VersionName.AsNonNull().Split('-').First());
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
UserPlayingState.BindValueChanged(_ => updateOrientation());
|
||||
}
|
||||
|
||||
protected override void ScreenChanged(IOsuScreen? current, IOsuScreen? newScreen)
|
||||
{
|
||||
base.ScreenChanged(current, newScreen);
|
||||
|
||||
if (newScreen != null)
|
||||
updateOrientation();
|
||||
}
|
||||
|
||||
private void updateOrientation()
|
||||
{
|
||||
var orientation = MobileUtils.GetOrientation(this, (IOsuScreen)ScreenStack.CurrentScreen, gameActivity.IsTablet);
|
||||
|
||||
switch (orientation)
|
||||
{
|
||||
case MobileUtils.Orientation.Locked:
|
||||
gameActivity.RequestedOrientation = ScreenOrientation.Locked;
|
||||
break;
|
||||
|
||||
case MobileUtils.Orientation.Portrait:
|
||||
gameActivity.RequestedOrientation = ScreenOrientation.Portrait;
|
||||
break;
|
||||
|
||||
case MobileUtils.Orientation.Default:
|
||||
gameActivity.RequestedOrientation = gameActivity.DefaultOrientation;
|
||||
break;
|
||||
}
|
||||
LoadComponentAsync(new GameplayScreenRotationLocker(), Add);
|
||||
}
|
||||
|
||||
public override void SetHost(GameHost host)
|
||||
@@ -87,10 +83,25 @@ namespace osu.Android
|
||||
host.Window.CursorState |= CursorState.Hidden;
|
||||
}
|
||||
|
||||
protected override UpdateManager CreateUpdateManager() => new MobileUpdateNotifier();
|
||||
protected override UpdateManager CreateUpdateManager() => new SimpleUpdateManager();
|
||||
|
||||
protected override BatteryInfo CreateBatteryInfo() => new AndroidBatteryInfo();
|
||||
|
||||
public override SettingsSubsection CreateSettingsSubsectionFor(InputHandler handler)
|
||||
{
|
||||
switch (handler)
|
||||
{
|
||||
case AndroidMouseHandler mh:
|
||||
return new AndroidMouseSettings(mh);
|
||||
|
||||
case AndroidJoystickHandler jh:
|
||||
return new AndroidJoystickSettings(jh);
|
||||
|
||||
default:
|
||||
return base.CreateSettingsSubsectionFor(handler);
|
||||
}
|
||||
}
|
||||
|
||||
private class AndroidBatteryInfo : BatteryInfo
|
||||
{
|
||||
public override double? ChargeLevel => Battery.ChargeLevel;
|
||||
|
||||
@@ -1,618 +0,0 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<group android:scaleX="0.67"
|
||||
android:scaleY="0.67"
|
||||
android:translateX="17.82"
|
||||
android:translateY="17.82">
|
||||
<group>
|
||||
<clip-path
|
||||
android:pathData="M0,0h108v108h-108z"/>
|
||||
<path
|
||||
android:pathData="M109.48,-1.48H-1.48V109.48H109.48V-1.48Z"
|
||||
android:fillColor="#404041"/>
|
||||
<group>
|
||||
<clip-path
|
||||
android:pathData="M0,-0.31H108V107.69H0V-0.31Z"/>
|
||||
<group>
|
||||
<clip-path
|
||||
android:pathData="M215.01,-78.1H-78.39V215.3H215.01V-78.1Z"/>
|
||||
<group>
|
||||
<clip-path
|
||||
android:pathData="M149.56,96.97H96.68V149.85H149.56V96.97Z"/>
|
||||
<group>
|
||||
<clip-path
|
||||
android:pathData="M149.56,96.97H96.68V149.85H149.56V96.97Z"/>
|
||||
<path
|
||||
android:pathData="M100.57,98.05C100.34,98.05 100.15,98.24 100.15,98.47V102.61C100.15,102.84 100.34,103.03 100.57,103.03C100.79,103.03 100.98,102.84 100.98,102.61V98.47C100.98,98.24 100.79,98.05 100.57,98.05Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M101.86,99.22C101.63,99.22 101.44,99.41 101.44,99.63V101.45C101.44,101.67 101.63,101.86 101.86,101.86C102.08,101.86 102.27,101.67 102.27,101.45V99.63C102.27,99.41 102.08,99.22 101.86,99.22Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M104.44,100.54C104.44,101.06 104.33,101.57 104.13,102.05C103.94,102.51 103.65,102.92 103.3,103.28C102.95,103.63 102.53,103.91 102.07,104.11C101.59,104.31 101.09,104.41 100.57,104.41C100.04,104.41 99.54,104.31 99.06,104.11C98.6,103.91 98.19,103.63 97.83,103.28C97.48,102.92 97.2,102.51 97,102.05C96.8,101.57 96.7,101.06 96.7,100.54C96.7,100.02 96.8,99.51 97,99.04C97.2,98.58 97.48,98.16 97.83,97.81C98.19,97.45 98.6,97.18 99.06,96.98C99.54,96.78 100.04,96.67 100.57,96.67C101.09,96.67 101.59,96.77 102.07,96.98C102.53,97.17 102.95,97.45 103.3,97.81C103.65,98.16 103.93,98.58 104.13,99.04C104.33,99.51 104.44,100.02 104.44,100.54ZM103.78,100.54C103.78,98.77 102.34,97.33 100.57,97.33C98.8,97.33 97.36,98.77 97.36,100.54C97.36,102.31 98.8,103.75 100.57,103.75C102.34,103.75 103.78,102.31 103.78,100.54Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M99.28,101.86C99.51,101.86 99.69,101.67 99.69,101.45V99.64C99.69,99.41 99.51,99.23 99.28,99.23C99.05,99.23 98.87,99.41 98.87,99.64V101.45C98.87,101.68 99.05,101.86 99.28,101.86Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
</group>
|
||||
</group>
|
||||
<group>
|
||||
<clip-path
|
||||
android:pathData="M149.56,44.09H96.68V96.97H149.56V44.09Z"/>
|
||||
<group>
|
||||
<clip-path
|
||||
android:pathData="M149.56,44.09H96.68V96.97H149.56V44.09Z"/>
|
||||
<path
|
||||
android:pathData="M104.44,100.54C104.44,101.06 104.33,101.57 104.13,102.05C103.94,102.51 103.65,102.92 103.3,103.28C102.95,103.63 102.53,103.91 102.07,104.11C101.59,104.31 101.09,104.41 100.57,104.41C100.04,104.41 99.54,104.31 99.06,104.11C98.6,103.91 98.19,103.63 97.83,103.28C97.48,102.92 97.2,102.51 97,102.05C96.8,101.57 96.7,101.06 96.7,100.54C96.7,100.02 96.8,99.51 97,99.04C97.2,98.58 97.48,98.16 97.83,97.81C98.19,97.45 98.6,97.18 99.06,96.98C99.54,96.78 100.04,96.67 100.57,96.67C101.09,96.67 101.59,96.77 102.07,96.98C102.53,97.17 102.95,97.45 103.3,97.81C103.65,98.16 103.93,98.58 104.13,99.04C104.33,99.51 104.44,100.02 104.44,100.54ZM103.78,100.54C103.78,98.77 102.34,97.33 100.57,97.33C98.8,97.33 97.36,98.77 97.36,100.54C97.36,102.31 98.8,103.75 100.57,103.75C102.34,103.75 103.78,102.31 103.78,100.54Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M100.57,70.97C100.34,70.97 100.15,71.16 100.15,71.38V75.53C100.15,75.76 100.34,75.94 100.57,75.94C100.79,75.94 100.98,75.76 100.98,75.53V71.38C100.98,71.15 100.79,70.97 100.57,70.97Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M101.86,72.14C101.63,72.14 101.44,72.33 101.44,72.55V74.36C101.44,74.59 101.63,74.77 101.86,74.77C102.08,74.77 102.27,74.59 102.27,74.36V72.55C102.27,72.32 102.08,72.14 101.86,72.14Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M99.28,74.78C99.51,74.78 99.69,74.59 99.69,74.37V72.55C99.69,72.33 99.51,72.14 99.28,72.14C99.05,72.14 98.87,72.33 98.87,72.55V74.37C98.87,74.59 99.05,74.78 99.28,74.78Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M100.57,45.18C100.34,45.18 100.15,45.37 100.15,45.59V49.74C100.15,49.97 100.34,50.15 100.57,50.15C100.79,50.15 100.98,49.97 100.98,49.74V45.59C100.98,45.36 100.79,45.18 100.57,45.18Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M101.86,46.35C101.63,46.35 101.44,46.53 101.44,46.76V48.57C101.44,48.8 101.63,48.98 101.86,48.98C102.08,48.98 102.27,48.79 102.27,48.57V46.76C102.27,46.53 102.08,46.35 101.86,46.35Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M104.44,47.67C104.44,48.19 104.33,48.69 104.13,49.17C103.94,49.63 103.65,50.04 103.3,50.4C102.95,50.75 102.53,51.03 102.07,51.23C101.59,51.43 101.09,51.53 100.57,51.53C100.04,51.53 99.54,51.43 99.06,51.23C98.6,51.03 98.19,50.75 97.83,50.4C97.48,50.04 97.2,49.63 97,49.17C96.8,48.69 96.7,48.19 96.7,47.67C96.7,47.14 96.8,46.64 97,46.16C97.2,45.7 97.48,45.29 97.83,44.93C98.19,44.58 98.6,44.3 99.06,44.1C99.54,43.9 100.04,43.8 100.57,43.8C101.09,43.8 101.59,43.9 102.07,44.1C102.53,44.3 102.95,44.58 103.3,44.93C103.65,45.29 103.93,45.7 104.13,46.16C104.33,46.64 104.44,47.14 104.44,47.67ZM103.78,47.67C103.78,45.89 102.34,44.46 100.57,44.46C98.8,44.46 97.36,45.89 97.36,47.67C97.36,49.44 98.8,50.87 100.57,50.87C102.34,50.87 103.78,49.44 103.78,47.67Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M104.44,73.46C104.44,73.98 104.33,74.49 104.13,74.96C103.94,75.42 103.65,75.84 103.3,76.19C102.95,76.55 102.53,76.83 102.07,77.02C101.59,77.22 101.09,77.33 100.57,77.33C100.04,77.33 99.54,77.23 99.06,77.02C98.6,76.83 98.19,76.55 97.83,76.19C97.48,75.84 97.2,75.42 97,74.96C96.8,74.49 96.7,73.98 96.7,73.46C96.7,72.94 96.8,72.43 97,71.95C97.2,71.49 97.48,71.08 97.83,70.72C98.19,70.37 98.6,70.09 99.06,69.89C99.54,69.69 100.04,69.59 100.57,69.59C101.09,69.59 101.59,69.69 102.07,69.89C102.53,70.09 102.95,70.37 103.3,70.72C103.65,71.08 103.93,71.49 104.13,71.95C104.33,72.43 104.44,72.94 104.44,73.46ZM103.78,73.46C103.78,71.68 102.34,70.25 100.57,70.25C98.8,70.25 97.36,71.69 97.36,73.46C97.36,75.23 98.8,76.67 100.57,76.67C102.34,76.67 103.78,75.23 103.78,73.46Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M99.28,48.98C99.51,48.98 99.69,48.8 99.69,48.57V46.76C99.69,46.53 99.51,46.35 99.28,46.35C99.05,46.35 98.87,46.54 98.87,46.76V48.57C98.87,48.8 99.05,48.98 99.28,48.98Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
</group>
|
||||
</group>
|
||||
<group>
|
||||
<clip-path
|
||||
android:pathData="M149.56,-8.78H96.68V44.09H149.56V-8.78Z"/>
|
||||
<group>
|
||||
<clip-path
|
||||
android:pathData="M149.56,-8.78H96.68V44.09H149.56V-8.78Z"/>
|
||||
<path
|
||||
android:pathData="M104.44,47.67C104.44,48.19 104.33,48.69 104.13,49.17C103.94,49.63 103.65,50.04 103.3,50.4C102.95,50.75 102.53,51.03 102.07,51.23C101.59,51.43 101.09,51.53 100.57,51.53C100.04,51.53 99.54,51.43 99.06,51.23C98.6,51.03 98.19,50.75 97.83,50.4C97.48,50.04 97.2,49.63 97,49.17C96.8,48.69 96.7,48.19 96.7,47.67C96.7,47.14 96.8,46.64 97,46.16C97.2,45.7 97.48,45.29 97.83,44.93C98.19,44.58 98.6,44.3 99.06,44.1C99.54,43.9 100.04,43.8 100.57,43.8C101.09,43.8 101.59,43.9 102.07,44.1C102.53,44.3 102.95,44.58 103.3,44.93C103.65,45.29 103.93,45.7 104.13,46.16C104.33,46.64 104.44,47.14 104.44,47.67ZM103.78,47.67C103.78,45.89 102.34,44.46 100.57,44.46C98.8,44.46 97.36,45.89 97.36,47.67C97.36,49.44 98.8,50.87 100.57,50.87C102.34,50.87 103.78,49.44 103.78,47.67Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M100.57,18.1C100.34,18.1 100.15,18.28 100.15,18.51V22.66C100.15,22.89 100.34,23.07 100.57,23.07C100.79,23.07 100.98,22.88 100.98,22.66V18.51C100.98,18.28 100.79,18.1 100.57,18.1Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M101.86,19.27C101.63,19.27 101.44,19.45 101.44,19.68V21.49C101.44,21.72 101.63,21.9 101.86,21.9C102.08,21.9 102.27,21.71 102.27,21.49V19.68C102.27,19.45 102.08,19.27 101.86,19.27Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M99.28,21.9C99.51,21.9 99.69,21.71 99.69,21.49V19.68C99.69,19.45 99.51,19.27 99.28,19.27C99.05,19.27 98.87,19.45 98.87,19.68V21.49C98.87,21.72 99.05,21.9 99.28,21.9Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M104.44,20.58C104.44,21.1 104.33,21.61 104.13,22.09C103.94,22.55 103.65,22.96 103.3,23.32C102.95,23.67 102.53,23.95 102.07,24.15C101.59,24.35 101.09,24.45 100.57,24.45C100.04,24.45 99.54,24.35 99.06,24.15C98.6,23.95 98.19,23.67 97.83,23.32C97.48,22.96 97.2,22.55 97,22.09C96.8,21.61 96.7,21.1 96.7,20.58C96.7,20.06 96.8,19.55 97,19.08C97.2,18.62 97.48,18.2 97.83,17.85C98.19,17.49 98.6,17.22 99.06,17.02C99.54,16.82 100.04,16.71 100.57,16.71C101.09,16.71 101.59,16.81 102.07,17.02C102.53,17.21 102.95,17.49 103.3,17.85C103.65,18.2 103.93,18.62 104.13,19.08C104.33,19.55 104.44,20.06 104.44,20.58ZM103.78,20.58C103.78,18.81 102.34,17.37 100.57,17.37C98.8,17.37 97.36,18.81 97.36,20.58C97.36,22.35 98.8,23.79 100.57,23.79C102.34,23.79 103.78,22.35 103.78,20.58Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
</group>
|
||||
</group>
|
||||
<group>
|
||||
<clip-path
|
||||
android:pathData="M96.68,96.97H43.8V149.85H96.68V96.97Z"/>
|
||||
<group>
|
||||
<clip-path
|
||||
android:pathData="M96.68,96.97H43.8V149.85H96.68V96.97Z"/>
|
||||
<path
|
||||
android:pathData="M73.51,98.07C72.15,98.07 71.04,99.18 71.04,100.54C71.04,101.91 72.15,103.01 73.51,103.01C74.87,103.01 75.98,101.91 75.98,100.54C75.98,99.18 74.87,98.07 73.51,98.07Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M77.38,100.54C77.38,101.06 77.28,101.57 77.07,102.05C76.88,102.51 76.6,102.92 76.24,103.28C75.89,103.63 75.48,103.91 75.02,104.11C74.54,104.31 74.03,104.41 73.51,104.41C72.99,104.41 72.48,104.31 72.01,104.11C71.55,103.91 71.13,103.63 70.78,103.28C70.42,102.92 70.14,102.51 69.95,102.05C69.75,101.57 69.64,101.06 69.64,100.54C69.64,100.02 69.74,99.51 69.95,99.04C70.14,98.58 70.42,98.16 70.78,97.81C71.13,97.45 71.55,97.18 72.01,96.98C72.48,96.78 72.99,96.67 73.51,96.67C74.03,96.67 74.54,96.77 75.02,96.98C75.48,97.17 75.89,97.45 76.24,97.81C76.6,98.16 76.88,98.58 77.07,99.04C77.28,99.51 77.38,100.02 77.38,100.54ZM76.72,100.54C76.72,98.77 75.28,97.33 73.51,97.33C71.74,97.33 70.3,98.77 70.3,100.54C70.3,102.31 71.74,103.75 73.51,103.75C75.28,103.75 76.72,102.31 76.72,100.54Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M47.69,98.05C47.46,98.05 47.28,98.24 47.28,98.47V102.61C47.28,102.84 47.46,103.03 47.69,103.03C47.92,103.03 48.11,102.84 48.11,102.61V98.47C48.11,98.24 47.92,98.05 47.69,98.05Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M48.98,99.22C48.75,99.22 48.57,99.41 48.57,99.63V101.45C48.57,101.67 48.75,101.86 48.98,101.86C49.21,101.86 49.4,101.67 49.4,101.45V99.63C49.4,99.41 49.21,99.22 48.98,99.22Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M51.56,100.54C51.56,101.06 51.46,101.57 51.26,102.05C51.06,102.51 50.78,102.92 50.43,103.28C50.07,103.63 49.66,103.91 49.2,104.11C48.72,104.31 48.21,104.41 47.69,104.41C47.17,104.41 46.67,104.31 46.19,104.11C45.73,103.91 45.31,103.63 44.96,103.28C44.6,102.92 44.33,102.51 44.13,102.05C43.93,101.57 43.82,101.06 43.82,100.54C43.82,100.02 43.93,99.51 44.13,99.04C44.32,98.58 44.6,98.16 44.96,97.81C45.31,97.45 45.73,97.18 46.19,96.98C46.67,96.78 47.17,96.67 47.69,96.67C48.21,96.67 48.72,96.77 49.2,96.98C49.66,97.17 50.07,97.45 50.43,97.81C50.78,98.16 51.06,98.58 51.26,99.04C51.46,99.51 51.56,100.02 51.56,100.54ZM50.9,100.54C50.9,98.77 49.46,97.33 47.69,97.33C45.92,97.33 44.48,98.77 44.48,100.54C44.48,102.31 45.92,103.75 47.69,103.75C49.46,103.75 50.9,102.31 50.9,100.54Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M46.4,101.86C46.63,101.86 46.82,101.67 46.82,101.45V99.64C46.82,99.41 46.63,99.23 46.4,99.23C46.17,99.23 45.99,99.41 45.99,99.64V101.45C45.99,101.68 46.17,101.86 46.4,101.86Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
</group>
|
||||
</group>
|
||||
<group>
|
||||
<clip-path
|
||||
android:pathData="M96.68,44.09H43.8V96.97H96.68V44.09Z"/>
|
||||
<group>
|
||||
<clip-path
|
||||
android:pathData="M96.68,44.09H43.8V96.97H96.68V44.09Z"/>
|
||||
<path
|
||||
android:pathData="M77.38,100.54C77.38,101.06 77.28,101.57 77.07,102.05C76.88,102.51 76.6,102.92 76.24,103.28C75.89,103.63 75.48,103.91 75.02,104.11C74.54,104.31 74.03,104.41 73.51,104.41C72.99,104.41 72.48,104.31 72.01,104.11C71.55,103.91 71.13,103.63 70.78,103.28C70.42,102.92 70.14,102.51 69.95,102.05C69.75,101.57 69.64,101.06 69.64,100.54C69.64,100.02 69.74,99.51 69.95,99.04C70.14,98.58 70.42,98.16 70.78,97.81C71.13,97.45 71.55,97.18 72.01,96.98C72.48,96.78 72.99,96.67 73.51,96.67C74.03,96.67 74.54,96.77 75.02,96.98C75.48,97.17 75.89,97.45 76.24,97.81C76.6,98.16 76.88,98.58 77.07,99.04C77.28,99.51 77.38,100.02 77.38,100.54ZM76.72,100.54C76.72,98.77 75.28,97.33 73.51,97.33C71.74,97.33 70.3,98.77 70.3,100.54C70.3,102.31 71.74,103.75 73.51,103.75C75.28,103.75 76.72,102.31 76.72,100.54Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M51.56,100.54C51.56,101.06 51.46,101.57 51.26,102.05C51.06,102.51 50.78,102.92 50.43,103.28C50.07,103.63 49.66,103.91 49.2,104.11C48.72,104.31 48.21,104.41 47.69,104.41C47.17,104.41 46.67,104.31 46.19,104.11C45.73,103.91 45.31,103.63 44.96,103.28C44.6,102.92 44.33,102.51 44.13,102.05C43.93,101.57 43.82,101.06 43.82,100.54C43.82,100.02 43.93,99.51 44.13,99.04C44.32,98.58 44.6,98.16 44.96,97.81C45.31,97.45 45.73,97.18 46.19,96.98C46.67,96.78 47.17,96.67 47.69,96.67C48.21,96.67 48.72,96.77 49.2,96.98C49.66,97.17 50.07,97.45 50.43,97.81C50.78,98.16 51.06,98.58 51.26,99.04C51.46,99.51 51.56,100.02 51.56,100.54ZM50.9,100.54C50.9,98.77 49.46,97.33 47.69,97.33C45.92,97.33 44.48,98.77 44.48,100.54C44.48,102.31 45.92,103.75 47.69,103.75C49.46,103.75 50.9,102.31 50.9,100.54Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M47.69,70.97C47.46,70.97 47.28,71.16 47.28,71.38V75.53C47.28,75.76 47.46,75.94 47.69,75.94C47.92,75.94 48.11,75.76 48.11,75.53V71.38C48.11,71.15 47.92,70.97 47.69,70.97Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M48.98,72.14C48.75,72.14 48.57,72.33 48.57,72.55V74.36C48.57,74.59 48.75,74.77 48.98,74.77C49.21,74.77 49.4,74.59 49.4,74.36V72.55C49.4,72.32 49.21,72.14 48.98,72.14Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M46.4,74.78C46.63,74.78 46.82,74.59 46.82,74.37V72.55C46.82,72.33 46.63,72.14 46.4,72.14C46.17,72.14 45.99,72.33 45.99,72.55V74.37C45.99,74.59 46.17,74.78 46.4,74.78Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M73.51,45.2C72.15,45.2 71.04,46.3 71.04,47.67C71.04,49.03 72.15,50.13 73.51,50.13C74.87,50.13 75.98,49.03 75.98,47.67C75.98,46.3 74.87,45.2 73.51,45.2Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M77.38,47.67C77.38,48.19 77.28,48.69 77.07,49.17C76.88,49.63 76.6,50.04 76.24,50.4C75.89,50.75 75.48,51.03 75.02,51.23C74.54,51.43 74.03,51.53 73.51,51.53C72.99,51.53 72.48,51.43 72.01,51.23C71.55,51.03 71.13,50.75 70.78,50.4C70.42,50.04 70.14,49.63 69.95,49.17C69.75,48.69 69.64,48.19 69.64,47.67C69.64,47.14 69.74,46.64 69.95,46.16C70.14,45.7 70.42,45.29 70.78,44.93C71.13,44.58 71.55,44.3 72.01,44.1C72.48,43.9 72.99,43.8 73.51,43.8C74.03,43.8 74.54,43.9 75.02,44.1C75.48,44.3 75.89,44.58 76.24,44.93C76.6,45.29 76.88,45.7 77.07,46.16C77.28,46.64 77.38,47.14 77.38,47.67ZM76.72,47.67C76.72,45.89 75.28,44.46 73.51,44.46C71.74,44.46 70.3,45.89 70.3,47.67C70.3,49.44 71.74,50.87 73.51,50.87C75.28,50.87 76.72,49.44 76.72,47.67Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M90.28,60.56C90.28,61.08 90.17,61.59 89.97,62.07C89.78,62.53 89.5,62.94 89.14,63.3C88.79,63.65 88.37,63.93 87.91,64.13C87.43,64.33 86.93,64.43 86.41,64.43C85.88,64.43 85.38,64.33 84.9,64.13C84.44,63.93 84.03,63.65 83.67,63.3C83.32,62.94 83.04,62.53 82.84,62.07C82.64,61.59 82.54,61.08 82.54,60.56C82.54,60.04 82.64,59.54 82.84,59.06C83.04,58.6 83.32,58.18 83.67,57.83C84.03,57.47 84.44,57.2 84.9,57C85.38,56.8 85.88,56.69 86.41,56.69C86.93,56.69 87.43,56.8 87.91,57C88.37,57.19 88.79,57.47 89.14,57.83C89.5,58.18 89.77,58.6 89.97,59.06C90.17,59.54 90.28,60.04 90.28,60.56ZM89.62,60.56C89.62,58.79 88.18,57.35 86.41,57.35C84.64,57.35 83.2,58.79 83.2,60.56C83.2,62.33 84.64,63.77 86.41,63.77C88.18,63.77 89.62,62.33 89.62,60.56Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M87.38,59.95C87.03,59.95 86.76,60.22 86.76,60.56C86.76,60.9 87.04,61.18 87.38,61.18C87.71,61.18 87.99,60.9 87.99,60.56C87.99,60.22 87.71,59.95 87.38,59.95Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M85.93,58.69C85.59,58.69 85.32,58.97 85.32,59.31C85.32,59.65 85.59,59.92 85.93,59.92C86.27,59.92 86.55,59.65 86.55,59.31C86.55,58.97 86.27,58.69 85.93,58.69Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M85.93,61.2C85.59,61.2 85.32,61.48 85.32,61.82C85.32,62.16 85.59,62.43 85.93,62.43C86.27,62.43 86.55,62.16 86.55,61.82C86.55,61.48 86.27,61.2 85.93,61.2Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M73.51,70.99C72.15,70.99 71.04,72.09 71.04,73.46C71.04,74.82 72.15,75.93 73.51,75.93C74.87,75.93 75.98,74.82 75.98,73.46C75.98,72.09 74.87,70.99 73.51,70.99Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M77.38,73.46C77.38,73.98 77.28,74.49 77.07,74.96C76.88,75.42 76.6,75.84 76.24,76.19C75.89,76.55 75.48,76.83 75.02,77.02C74.54,77.22 74.03,77.33 73.51,77.33C72.99,77.33 72.48,77.23 72.01,77.02C71.55,76.83 71.13,76.55 70.78,76.19C70.42,75.84 70.14,75.42 69.95,74.96C69.75,74.49 69.64,73.98 69.64,73.46C69.64,72.94 69.74,72.43 69.95,71.95C70.14,71.49 70.42,71.08 70.78,70.72C71.13,70.37 71.55,70.09 72.01,69.89C72.48,69.69 72.99,69.59 73.51,69.59C74.03,69.59 74.54,69.69 75.02,69.89C75.48,70.09 75.89,70.37 76.24,70.72C76.6,71.08 76.88,71.49 77.07,71.95C77.28,72.43 77.38,72.94 77.38,73.46ZM76.72,73.46C76.72,71.68 75.28,70.25 73.51,70.25C71.74,70.25 70.3,71.69 70.3,73.46C70.3,75.23 71.74,76.67 73.51,76.67C75.28,76.67 76.72,75.23 76.72,73.46Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M90.28,86.36C90.28,86.88 90.17,87.38 89.97,87.86C89.78,88.32 89.5,88.74 89.14,89.09C88.79,89.45 88.37,89.72 87.91,89.92C87.43,90.12 86.93,90.23 86.41,90.23C85.88,90.23 85.38,90.12 84.9,89.92C84.44,89.73 84.03,89.45 83.67,89.09C83.32,88.74 83.04,88.32 82.84,87.86C82.64,87.38 82.54,86.88 82.54,86.36C82.54,85.84 82.64,85.33 82.84,84.85C83.04,84.39 83.32,83.98 83.67,83.62C84.03,83.27 84.44,82.99 84.9,82.79C85.38,82.59 85.88,82.49 86.41,82.49C86.93,82.49 87.43,82.59 87.91,82.79C88.37,82.99 88.79,83.27 89.14,83.62C89.5,83.98 89.77,84.39 89.97,84.85C90.17,85.33 90.28,85.84 90.28,86.36ZM89.62,86.36C89.62,84.58 88.18,83.15 86.41,83.15C84.64,83.15 83.2,84.59 83.2,86.36C83.2,88.13 84.64,89.57 86.41,89.57C88.18,89.57 89.62,88.13 89.62,86.36Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M87.38,85.74C87.03,85.74 86.76,86.01 86.76,86.35C86.76,86.69 87.04,86.97 87.38,86.97C87.71,86.97 87.99,86.69 87.99,86.35C87.99,86.01 87.71,85.74 87.38,85.74Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M85.93,84.48C85.59,84.48 85.32,84.76 85.32,85.1C85.32,85.44 85.59,85.72 85.93,85.72C86.27,85.72 86.55,85.44 86.55,85.1C86.55,84.76 86.27,84.48 85.93,84.48Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M85.93,86.99C85.59,86.99 85.32,87.27 85.32,87.61C85.32,87.95 85.59,88.23 85.93,88.23C86.27,88.23 86.55,87.95 86.55,87.61C86.55,87.27 86.27,86.99 85.93,86.99Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M47.69,45.18C47.46,45.18 47.28,45.37 47.28,45.59V49.74C47.28,49.97 47.46,50.15 47.69,50.15C47.92,50.15 48.11,49.97 48.11,49.74V45.59C48.11,45.36 47.92,45.18 47.69,45.18Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M48.98,46.35C48.75,46.35 48.57,46.53 48.57,46.76V48.57C48.57,48.8 48.75,48.98 48.98,48.98C49.21,48.98 49.4,48.79 49.4,48.57V46.76C49.4,46.53 49.21,46.35 48.98,46.35Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M51.56,47.67C51.56,48.19 51.46,48.69 51.26,49.17C51.06,49.63 50.78,50.04 50.43,50.4C50.07,50.75 49.66,51.03 49.2,51.23C48.72,51.43 48.21,51.53 47.69,51.53C47.17,51.53 46.67,51.43 46.19,51.23C45.73,51.03 45.31,50.75 44.96,50.4C44.6,50.04 44.33,49.63 44.13,49.17C43.93,48.69 43.82,48.19 43.82,47.67C43.82,47.14 43.93,46.64 44.13,46.16C44.32,45.7 44.6,45.29 44.96,44.93C45.31,44.58 45.73,44.3 46.19,44.1C46.67,43.9 47.17,43.8 47.69,43.8C48.21,43.8 48.72,43.9 49.2,44.1C49.66,44.3 50.07,44.58 50.43,44.93C50.78,45.29 51.06,45.7 51.26,46.16C51.46,46.64 51.56,47.14 51.56,47.67ZM50.9,47.67C50.9,45.89 49.46,44.46 47.69,44.46C45.92,44.46 44.48,45.89 44.48,47.67C44.48,49.44 45.92,50.87 47.69,50.87C49.46,50.87 50.9,49.44 50.9,47.67Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M63.06,60.56C63.06,61.93 61.96,63.03 60.59,63.03C59.23,63.03 58.12,61.93 58.12,60.56C58.12,59.2 59.23,58.09 60.59,58.09C61.96,58.09 63.06,59.2 63.06,60.56ZM60.18,62.16V58.97C59.48,59.15 58.94,59.8 58.94,60.56C58.94,61.33 59.48,61.97 60.18,62.16M62.24,60.56C62.24,59.8 61.7,59.15 61,58.97V62.16C61.7,61.97 62.24,61.33 62.24,60.56"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M64.46,60.56C64.46,61.08 64.36,61.59 64.15,62.07C63.96,62.53 63.68,62.94 63.32,63.3C62.97,63.65 62.55,63.93 62.09,64.13C61.62,64.33 61.11,64.43 60.59,64.43C60.07,64.43 59.56,64.33 59.08,64.13C58.62,63.93 58.21,63.65 57.85,63.3C57.5,62.94 57.22,62.53 57.02,62.07C56.82,61.59 56.72,61.08 56.72,60.56C56.72,60.04 56.82,59.54 57.02,59.06C57.22,58.6 57.5,58.18 57.85,57.83C58.21,57.47 58.62,57.2 59.08,57C59.56,56.8 60.07,56.69 60.59,56.69C61.11,56.69 61.62,56.8 62.09,57C62.55,57.19 62.97,57.47 63.32,57.83C63.68,58.18 63.95,58.6 64.15,59.06C64.35,59.54 64.46,60.04 64.46,60.56ZM63.8,60.56C63.8,58.79 62.36,57.35 60.59,57.35C58.82,57.35 57.38,58.79 57.38,60.56C57.38,62.33 58.82,63.77 60.59,63.77C62.36,63.77 63.8,62.33 63.8,60.56Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M51.56,73.46C51.56,73.98 51.46,74.49 51.26,74.96C51.06,75.42 50.78,75.84 50.43,76.19C50.07,76.55 49.66,76.83 49.2,77.02C48.72,77.22 48.21,77.33 47.69,77.33C47.17,77.33 46.67,77.23 46.19,77.02C45.73,76.83 45.31,76.55 44.96,76.19C44.6,75.84 44.33,75.42 44.13,74.96C43.93,74.49 43.82,73.98 43.82,73.46C43.82,72.94 43.93,72.43 44.13,71.95C44.32,71.49 44.6,71.08 44.96,70.72C45.31,70.37 45.73,70.09 46.19,69.89C46.67,69.69 47.17,69.59 47.69,69.59C48.21,69.59 48.72,69.69 49.2,69.89C49.66,70.09 50.07,70.37 50.43,70.72C50.78,71.08 51.06,71.49 51.26,71.95C51.46,72.43 51.56,72.94 51.56,73.46ZM50.9,73.46C50.9,71.68 49.46,70.25 47.69,70.25C45.92,70.25 44.48,71.69 44.48,73.46C44.48,75.23 45.92,76.67 47.69,76.67C49.46,76.67 50.9,75.23 50.9,73.46Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M63.06,86.36C63.06,87.72 61.96,88.83 60.59,88.83C59.23,88.83 58.12,87.72 58.12,86.36C58.12,84.99 59.23,83.89 60.59,83.89C61.96,83.89 63.06,84.99 63.06,86.36ZM60.18,87.95V84.76C59.48,84.94 58.94,85.59 58.94,86.36C58.94,87.12 59.48,87.77 60.18,87.95M62.24,86.36C62.24,85.59 61.7,84.95 61,84.76V87.95C61.7,87.77 62.24,87.12 62.24,86.35"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M64.46,86.36C64.46,86.88 64.36,87.38 64.15,87.86C63.96,88.32 63.68,88.74 63.32,89.09C62.97,89.45 62.55,89.72 62.09,89.92C61.62,90.12 61.11,90.23 60.59,90.23C60.07,90.23 59.56,90.12 59.08,89.92C58.62,89.73 58.21,89.45 57.85,89.09C57.5,88.74 57.22,88.32 57.02,87.86C56.82,87.38 56.72,86.88 56.72,86.36C56.72,85.84 56.82,85.33 57.02,84.85C57.22,84.39 57.5,83.98 57.85,83.62C58.21,83.27 58.62,82.99 59.08,82.79C59.56,82.59 60.07,82.49 60.59,82.49C61.11,82.49 61.62,82.59 62.09,82.79C62.55,82.99 62.97,83.27 63.32,83.62C63.68,83.98 63.95,84.39 64.15,84.85C64.35,85.33 64.46,85.84 64.46,86.36ZM63.8,86.36C63.8,84.58 62.36,83.15 60.59,83.15C58.82,83.15 57.38,84.59 57.38,86.36C57.38,88.13 58.82,89.57 60.59,89.57C62.36,89.57 63.8,88.13 63.8,86.36Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M46.4,48.98C46.63,48.98 46.82,48.8 46.82,48.57V46.76C46.82,46.53 46.63,46.35 46.4,46.35C46.17,46.35 45.99,46.54 45.99,46.76V48.57C45.99,48.8 46.17,48.98 46.4,48.98Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
</group>
|
||||
</group>
|
||||
<group>
|
||||
<clip-path
|
||||
android:pathData="M96.68,-8.78H43.8V44.09H96.68V-8.78Z"/>
|
||||
<group>
|
||||
<clip-path
|
||||
android:pathData="M96.68,-8.78H43.8V44.09H96.68V-8.78Z"/>
|
||||
<path
|
||||
android:pathData="M77.38,47.67C77.38,48.19 77.28,48.69 77.07,49.17C76.88,49.63 76.6,50.04 76.24,50.4C75.89,50.75 75.48,51.03 75.02,51.23C74.54,51.43 74.03,51.53 73.51,51.53C72.99,51.53 72.48,51.43 72.01,51.23C71.55,51.03 71.13,50.75 70.78,50.4C70.42,50.04 70.14,49.63 69.95,49.17C69.75,48.69 69.64,48.19 69.64,47.67C69.64,47.14 69.74,46.64 69.95,46.16C70.14,45.7 70.42,45.29 70.78,44.93C71.13,44.58 71.55,44.3 72.01,44.1C72.48,43.9 72.99,43.8 73.51,43.8C74.03,43.8 74.54,43.9 75.02,44.1C75.48,44.3 75.89,44.58 76.24,44.93C76.6,45.29 76.88,45.7 77.07,46.16C77.28,46.64 77.38,47.14 77.38,47.67ZM76.72,47.67C76.72,45.89 75.28,44.46 73.51,44.46C71.74,44.46 70.3,45.89 70.3,47.67C70.3,49.44 71.74,50.87 73.51,50.87C75.28,50.87 76.72,49.44 76.72,47.67Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M51.56,47.67C51.56,48.19 51.46,48.69 51.26,49.17C51.06,49.63 50.78,50.04 50.43,50.4C50.07,50.75 49.66,51.03 49.2,51.23C48.72,51.43 48.21,51.53 47.69,51.53C47.17,51.53 46.67,51.43 46.19,51.23C45.73,51.03 45.31,50.75 44.96,50.4C44.6,50.04 44.33,49.63 44.13,49.17C43.93,48.69 43.82,48.19 43.82,47.67C43.82,47.14 43.93,46.64 44.13,46.16C44.32,45.7 44.6,45.29 44.96,44.93C45.31,44.58 45.73,44.3 46.19,44.1C46.67,43.9 47.17,43.8 47.69,43.8C48.21,43.8 48.72,43.9 49.2,44.1C49.66,44.3 50.07,44.58 50.43,44.93C50.78,45.29 51.06,45.7 51.26,46.16C51.46,46.64 51.56,47.14 51.56,47.67ZM50.9,47.67C50.9,45.89 49.46,44.46 47.69,44.46C45.92,44.46 44.48,45.89 44.48,47.67C44.48,49.44 45.92,50.87 47.69,50.87C49.46,50.87 50.9,49.44 50.9,47.67Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M47.69,18.1C47.46,18.1 47.28,18.28 47.28,18.51V22.66C47.28,22.89 47.46,23.07 47.69,23.07C47.92,23.07 48.11,22.88 48.11,22.66V18.51C48.11,18.28 47.92,18.1 47.69,18.1Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M48.98,19.27C48.75,19.27 48.57,19.45 48.57,19.68V21.49C48.57,21.72 48.75,21.9 48.98,21.9C49.21,21.9 49.4,21.71 49.4,21.49V19.68C49.4,19.45 49.21,19.27 48.98,19.27Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M46.4,21.9C46.63,21.9 46.82,21.71 46.82,21.49V19.68C46.82,19.45 46.63,19.27 46.4,19.27C46.17,19.27 45.99,19.45 45.99,19.68V21.49C45.99,21.72 46.17,21.9 46.4,21.9Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M90.28,7.69C90.28,8.21 90.17,8.71 89.97,9.19C89.78,9.65 89.5,10.07 89.14,10.42C88.79,10.78 88.37,11.05 87.91,11.25C87.43,11.45 86.93,11.56 86.41,11.56C85.88,11.56 85.38,11.45 84.9,11.25C84.44,11.06 84.03,10.78 83.67,10.42C83.32,10.07 83.04,9.65 82.84,9.19C82.64,8.71 82.54,8.21 82.54,7.69C82.54,7.17 82.64,6.66 82.84,6.18C83.04,5.72 83.32,5.31 83.67,4.95C84.03,4.6 84.44,4.32 84.9,4.12C85.38,3.92 85.88,3.82 86.41,3.82C86.93,3.82 87.43,3.92 87.91,4.12C88.37,4.32 88.79,4.6 89.14,4.95C89.5,5.31 89.77,5.72 89.97,6.18C90.17,6.66 90.28,7.17 90.28,7.69ZM89.62,7.69C89.62,5.91 88.18,4.48 86.41,4.48C84.64,4.48 83.2,5.92 83.2,7.69C83.2,9.46 84.64,10.9 86.41,10.9C88.18,10.9 89.62,9.46 89.62,7.69Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M87.38,7.07C87.03,7.07 86.76,7.35 86.76,7.69C86.76,8.03 87.04,8.3 87.38,8.3C87.71,8.3 87.99,8.03 87.99,7.69C87.99,7.35 87.71,7.07 87.38,7.07Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M85.93,5.81C85.59,5.81 85.32,6.09 85.32,6.43C85.32,6.77 85.59,7.05 85.93,7.05C86.27,7.05 86.55,6.77 86.55,6.43C86.55,6.09 86.27,5.81 85.93,5.81Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M85.93,8.33C85.59,8.33 85.32,8.6 85.32,8.94C85.32,9.28 85.59,9.56 85.93,9.56C86.27,9.56 86.55,9.28 86.55,8.94C86.55,8.6 86.27,8.33 85.93,8.33Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M73.51,18.11C72.15,18.11 71.04,19.22 71.04,20.58C71.04,21.95 72.15,23.05 73.51,23.05C74.87,23.05 75.98,21.95 75.98,20.58C75.98,19.22 74.87,18.11 73.51,18.11Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M77.38,20.58C77.38,21.1 77.28,21.61 77.07,22.09C76.88,22.55 76.6,22.96 76.24,23.32C75.89,23.67 75.48,23.95 75.02,24.15C74.54,24.35 74.03,24.45 73.51,24.45C72.99,24.45 72.48,24.35 72.01,24.15C71.55,23.95 71.13,23.67 70.78,23.32C70.42,22.96 70.14,22.55 69.95,22.09C69.75,21.61 69.64,21.1 69.64,20.58C69.64,20.06 69.74,19.55 69.95,19.08C70.14,18.62 70.42,18.2 70.78,17.85C71.13,17.49 71.55,17.22 72.01,17.02C72.48,16.82 72.99,16.71 73.51,16.71C74.03,16.71 74.54,16.81 75.02,17.02C75.48,17.21 75.89,17.49 76.24,17.85C76.6,18.2 76.88,18.62 77.07,19.08C77.28,19.55 77.38,20.06 77.38,20.58ZM76.72,20.58C76.72,18.81 75.28,17.37 73.51,17.37C71.74,17.37 70.3,18.81 70.3,20.58C70.3,22.35 71.74,23.79 73.51,23.79C75.28,23.79 76.72,22.35 76.72,20.58Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M90.28,33.48C90.28,34 90.17,34.51 89.97,34.99C89.78,35.45 89.5,35.86 89.14,36.21C88.79,36.57 88.37,36.85 87.91,37.04C87.43,37.24 86.93,37.35 86.41,37.35C85.88,37.35 85.38,37.25 84.9,37.04C84.44,36.85 84.03,36.57 83.67,36.21C83.32,35.86 83.04,35.45 82.84,34.99C82.64,34.51 82.54,34 82.54,33.48C82.54,32.96 82.64,32.45 82.84,31.97C83.04,31.51 83.32,31.1 83.67,30.75C84.03,30.39 84.44,30.11 84.9,29.92C85.38,29.72 85.88,29.61 86.41,29.61C86.93,29.61 87.43,29.71 87.91,29.92C88.37,30.11 88.79,30.39 89.14,30.75C89.5,31.1 89.77,31.51 89.97,31.97C90.17,32.45 90.28,32.96 90.28,33.48ZM89.62,33.48C89.62,31.71 88.18,30.27 86.41,30.27C84.64,30.27 83.2,31.71 83.2,33.48C83.2,35.25 84.64,36.69 86.41,36.69C88.18,36.69 89.62,35.25 89.62,33.48Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M87.38,32.86C87.03,32.86 86.76,33.14 86.76,33.48C86.76,33.82 87.04,34.1 87.38,34.1C87.71,34.1 87.99,33.82 87.99,33.48C87.99,33.14 87.71,32.86 87.38,32.86Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M85.93,31.61C85.59,31.61 85.32,31.88 85.32,32.22C85.32,32.56 85.59,32.84 85.93,32.84C86.27,32.84 86.55,32.56 86.55,32.22C86.55,31.88 86.27,31.61 85.93,31.61Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M85.93,34.12C85.59,34.12 85.32,34.4 85.32,34.74C85.32,35.08 85.59,35.35 85.93,35.35C86.27,35.35 86.55,35.08 86.55,34.74C86.55,34.4 86.27,34.12 85.93,34.12Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M63.06,7.69C63.06,9.05 61.96,10.16 60.59,10.16C59.23,10.16 58.12,9.05 58.12,7.69C58.12,6.32 59.23,5.22 60.59,5.22C61.96,5.22 63.06,6.32 63.06,7.69ZM60.18,9.28V6.09C59.48,6.28 58.94,6.92 58.94,7.69C58.94,8.45 59.48,9.1 60.18,9.28M62.24,7.69C62.24,6.92 61.7,6.28 61,6.09V9.28C61.7,9.1 62.24,8.45 62.24,7.68"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M64.46,7.69C64.46,8.21 64.36,8.71 64.15,9.19C63.96,9.65 63.68,10.07 63.32,10.42C62.97,10.78 62.55,11.05 62.09,11.25C61.62,11.45 61.11,11.56 60.59,11.56C60.07,11.56 59.56,11.45 59.08,11.25C58.62,11.06 58.21,10.78 57.85,10.42C57.5,10.07 57.22,9.65 57.02,9.19C56.82,8.71 56.72,8.21 56.72,7.69C56.72,7.17 56.82,6.66 57.02,6.18C57.22,5.72 57.5,5.31 57.85,4.95C58.21,4.6 58.62,4.32 59.08,4.12C59.56,3.92 60.07,3.82 60.59,3.82C61.11,3.82 61.62,3.92 62.09,4.12C62.55,4.32 62.97,4.6 63.32,4.95C63.68,5.31 63.95,5.72 64.15,6.18C64.35,6.66 64.46,7.17 64.46,7.69ZM63.8,7.69C63.8,5.91 62.36,4.48 60.59,4.48C58.82,4.48 57.38,5.92 57.38,7.69C57.38,9.46 58.82,10.9 60.59,10.9C62.36,10.9 63.8,9.46 63.8,7.69Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M51.56,20.58C51.56,21.1 51.46,21.61 51.26,22.09C51.06,22.55 50.78,22.96 50.43,23.32C50.07,23.67 49.66,23.95 49.2,24.15C48.72,24.35 48.21,24.45 47.69,24.45C47.17,24.45 46.67,24.35 46.19,24.15C45.73,23.95 45.31,23.67 44.96,23.32C44.6,22.96 44.33,22.55 44.13,22.09C43.93,21.61 43.82,21.1 43.82,20.58C43.82,20.06 43.93,19.55 44.13,19.08C44.32,18.62 44.6,18.2 44.96,17.85C45.31,17.49 45.73,17.22 46.19,17.02C46.67,16.82 47.17,16.71 47.69,16.71C48.21,16.71 48.72,16.81 49.2,17.02C49.66,17.21 50.07,17.49 50.43,17.85C50.78,18.2 51.06,18.62 51.26,19.08C51.46,19.55 51.56,20.06 51.56,20.58ZM50.9,20.58C50.9,18.81 49.46,17.37 47.69,17.37C45.92,17.37 44.48,18.81 44.48,20.58C44.48,22.35 45.92,23.79 47.69,23.79C49.46,23.79 50.9,22.35 50.9,20.58Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M63.06,33.48C63.06,34.84 61.96,35.95 60.59,35.95C59.23,35.95 58.12,34.84 58.12,33.48C58.12,32.12 59.23,31.01 60.59,31.01C61.96,31.01 63.06,32.12 63.06,33.48ZM60.18,35.08V31.89C59.48,32.07 58.94,32.72 58.94,33.48C58.94,34.25 59.48,34.89 60.18,35.08M62.24,33.48C62.24,32.71 61.7,32.07 61,31.88V35.07C61.7,34.89 62.24,34.24 62.24,33.48"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M64.46,33.48C64.46,34 64.36,34.51 64.15,34.99C63.96,35.45 63.68,35.86 63.32,36.21C62.97,36.57 62.55,36.85 62.09,37.04C61.62,37.24 61.11,37.35 60.59,37.35C60.07,37.35 59.56,37.25 59.08,37.04C58.62,36.85 58.21,36.57 57.85,36.21C57.5,35.86 57.22,35.45 57.02,34.99C56.82,34.51 56.72,34 56.72,33.48C56.72,32.96 56.82,32.45 57.02,31.97C57.22,31.51 57.5,31.1 57.85,30.75C58.21,30.39 58.62,30.11 59.08,29.92C59.56,29.72 60.07,29.61 60.59,29.61C61.11,29.61 61.62,29.71 62.09,29.92C62.55,30.11 62.97,30.39 63.32,30.75C63.68,31.1 63.95,31.51 64.15,31.97C64.35,32.45 64.46,32.96 64.46,33.48ZM63.8,33.48C63.8,31.71 62.36,30.27 60.59,30.27C58.82,30.27 57.38,31.71 57.38,33.48C57.38,35.25 58.82,36.69 60.59,36.69C62.36,36.69 63.8,35.25 63.8,33.48Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
</group>
|
||||
</group>
|
||||
<group>
|
||||
<clip-path
|
||||
android:pathData="M43.81,96.97H-9.07V149.85H43.81V96.97Z"/>
|
||||
<group>
|
||||
<clip-path
|
||||
android:pathData="M43.81,96.97H-9.07V149.85H43.81V96.97Z"/>
|
||||
<path
|
||||
android:pathData="M20.63,98.07C19.27,98.07 18.17,99.18 18.17,100.54C18.17,101.91 19.27,103.01 20.63,103.01C22,103.01 23.1,101.91 23.1,100.54C23.1,99.18 22,98.07 20.63,98.07Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M24.5,100.54C24.5,101.06 24.4,101.57 24.2,102.05C24,102.51 23.72,102.92 23.37,103.28C23.01,103.63 22.6,103.91 22.14,104.11C21.66,104.31 21.16,104.41 20.63,104.41C20.11,104.41 19.61,104.31 19.13,104.11C18.67,103.91 18.25,103.63 17.9,103.28C17.55,102.92 17.27,102.51 17.07,102.05C16.87,101.57 16.76,101.06 16.76,100.54C16.76,100.02 16.87,99.51 17.07,99.04C17.26,98.58 17.55,98.16 17.9,97.81C18.25,97.45 18.67,97.18 19.13,96.98C19.61,96.78 20.11,96.67 20.63,96.67C21.16,96.67 21.66,96.77 22.14,96.98C22.6,97.17 23.01,97.45 23.37,97.81C23.72,98.16 24,98.58 24.2,99.04C24.4,99.51 24.5,100.02 24.5,100.54ZM23.85,100.54C23.85,98.77 22.41,97.33 20.64,97.33C18.87,97.33 17.43,98.77 17.43,100.54C17.43,102.31 18.87,103.75 20.64,103.75C22.41,103.75 23.85,102.31 23.85,100.54Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
</group>
|
||||
</group>
|
||||
<group>
|
||||
<clip-path
|
||||
android:pathData="M43.81,44.09H-9.07V96.97H43.81V44.09Z"/>
|
||||
<group>
|
||||
<clip-path
|
||||
android:pathData="M43.81,44.09H-9.07V96.97H43.81V44.09Z"/>
|
||||
<path
|
||||
android:pathData="M24.5,100.54C24.5,101.06 24.4,101.57 24.2,102.05C24,102.51 23.72,102.92 23.37,103.28C23.01,103.63 22.6,103.91 22.14,104.11C21.66,104.31 21.16,104.41 20.63,104.41C20.11,104.41 19.61,104.31 19.13,104.11C18.67,103.91 18.25,103.63 17.9,103.28C17.55,102.92 17.27,102.51 17.07,102.05C16.87,101.57 16.76,101.06 16.76,100.54C16.76,100.02 16.87,99.51 17.07,99.04C17.26,98.58 17.55,98.16 17.9,97.81C18.25,97.45 18.67,97.18 19.13,96.98C19.61,96.78 20.11,96.67 20.63,96.67C21.16,96.67 21.66,96.77 22.14,96.98C22.6,97.17 23.01,97.45 23.37,97.81C23.72,98.16 24,98.58 24.2,99.04C24.4,99.51 24.5,100.02 24.5,100.54ZM23.85,100.54C23.85,98.77 22.41,97.33 20.64,97.33C18.87,97.33 17.43,98.77 17.43,100.54C17.43,102.31 18.87,103.75 20.64,103.75C22.41,103.75 23.85,102.31 23.85,100.54Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M20.63,45.2C19.27,45.2 18.17,46.3 18.17,47.67C18.17,49.03 19.27,50.13 20.63,50.13C22,50.13 23.1,49.03 23.1,47.67C23.1,46.3 22,45.2 20.63,45.2Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M24.5,47.67C24.5,48.19 24.4,48.69 24.2,49.17C24,49.63 23.72,50.04 23.37,50.4C23.01,50.75 22.6,51.03 22.14,51.23C21.66,51.43 21.16,51.53 20.63,51.53C20.11,51.53 19.61,51.43 19.13,51.23C18.67,51.03 18.25,50.75 17.9,50.4C17.55,50.04 17.27,49.63 17.07,49.17C16.87,48.69 16.76,48.19 16.76,47.67C16.76,47.14 16.87,46.64 17.07,46.16C17.26,45.7 17.55,45.29 17.9,44.93C18.25,44.58 18.67,44.3 19.13,44.1C19.61,43.9 20.11,43.8 20.63,43.8C21.16,43.8 21.66,43.9 22.14,44.1C22.6,44.3 23.01,44.58 23.37,44.93C23.72,45.29 24,45.7 24.2,46.16C24.4,46.64 24.5,47.14 24.5,47.67ZM23.85,47.67C23.85,45.89 22.41,44.46 20.64,44.46C18.87,44.46 17.43,45.89 17.43,47.67C17.43,49.44 18.87,50.87 20.64,50.87C22.41,50.87 23.85,49.44 23.85,47.67Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M37.4,60.56C37.4,61.08 37.3,61.59 37.1,62.07C36.9,62.53 36.62,62.94 36.27,63.3C35.91,63.65 35.5,63.93 35.04,64.13C34.56,64.33 34.05,64.43 33.53,64.43C33.01,64.43 32.5,64.33 32.03,64.13C31.57,63.93 31.15,63.65 30.8,63.3C30.44,62.94 30.17,62.53 29.97,62.07C29.77,61.59 29.66,61.08 29.66,60.56C29.66,60.04 29.76,59.54 29.97,59.06C30.16,58.6 30.44,58.18 30.8,57.83C31.15,57.47 31.57,57.2 32.03,57C32.5,56.8 33.01,56.69 33.53,56.69C34.05,56.69 34.56,56.8 35.04,57C35.5,57.19 35.91,57.47 36.27,57.83C36.62,58.18 36.9,58.6 37.1,59.06C37.3,59.54 37.4,60.04 37.4,60.56ZM36.74,60.56C36.74,58.79 35.3,57.35 33.53,57.35C31.76,57.35 30.32,58.79 30.32,60.56C30.32,62.33 31.76,63.77 33.53,63.77C35.3,63.77 36.74,62.33 36.74,60.56Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M34.5,59.95C34.16,59.95 33.88,60.22 33.88,60.56C33.88,60.9 34.16,61.18 34.5,61.18C34.84,61.18 35.12,60.9 35.12,60.56C35.12,60.22 34.84,59.95 34.5,59.95Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M33.06,58.69C32.71,58.69 32.44,58.97 32.44,59.31C32.44,59.65 32.72,59.92 33.06,59.92C33.4,59.92 33.67,59.65 33.67,59.31C33.67,58.97 33.4,58.69 33.06,58.69Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M33.06,61.2C32.71,61.2 32.44,61.48 32.44,61.82C32.44,62.16 32.72,62.43 33.06,62.43C33.4,62.43 33.67,62.16 33.67,61.82C33.67,61.48 33.4,61.2 33.06,61.2Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M20.63,70.99C19.27,70.99 18.17,72.09 18.17,73.46C18.17,74.82 19.27,75.93 20.63,75.93C22,75.93 23.1,74.82 23.1,73.46C23.1,72.09 22,70.99 20.63,70.99Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M24.5,73.46C24.5,73.98 24.4,74.49 24.2,74.96C24,75.42 23.72,75.84 23.37,76.19C23.01,76.55 22.6,76.83 22.14,77.02C21.66,77.22 21.16,77.33 20.63,77.33C20.11,77.33 19.61,77.23 19.13,77.02C18.67,76.83 18.25,76.55 17.9,76.19C17.55,75.84 17.27,75.42 17.07,74.96C16.87,74.49 16.76,73.98 16.76,73.46C16.76,72.94 16.87,72.43 17.07,71.95C17.26,71.49 17.55,71.08 17.9,70.72C18.25,70.37 18.67,70.09 19.13,69.89C19.61,69.69 20.11,69.59 20.63,69.59C21.16,69.59 21.66,69.69 22.14,69.89C22.6,70.09 23.01,70.37 23.37,70.72C23.72,71.08 24,71.49 24.2,71.95C24.4,72.43 24.5,72.94 24.5,73.46ZM23.85,73.46C23.85,71.68 22.41,70.25 20.64,70.25C18.87,70.25 17.43,71.69 17.43,73.46C17.43,75.23 18.87,76.67 20.64,76.67C22.41,76.67 23.85,75.23 23.85,73.46Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M37.4,86.36C37.4,86.88 37.3,87.38 37.1,87.86C36.9,88.32 36.62,88.74 36.27,89.09C35.91,89.45 35.5,89.72 35.04,89.92C34.56,90.12 34.05,90.23 33.53,90.23C33.01,90.23 32.5,90.12 32.03,89.92C31.57,89.73 31.15,89.45 30.8,89.09C30.44,88.74 30.17,88.32 29.97,87.86C29.77,87.38 29.66,86.88 29.66,86.36C29.66,85.84 29.76,85.33 29.97,84.85C30.16,84.39 30.44,83.98 30.8,83.62C31.15,83.27 31.57,82.99 32.03,82.79C32.5,82.59 33.01,82.49 33.53,82.49C34.05,82.49 34.56,82.59 35.04,82.79C35.5,82.99 35.91,83.27 36.27,83.62C36.62,83.98 36.9,84.39 37.1,84.85C37.3,85.33 37.4,85.84 37.4,86.36ZM36.74,86.36C36.74,84.58 35.3,83.15 33.53,83.15C31.76,83.15 30.32,84.59 30.32,86.36C30.32,88.13 31.76,89.57 33.53,89.57C35.3,89.57 36.74,88.13 36.74,86.36Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M34.5,85.74C34.16,85.74 33.88,86.01 33.88,86.35C33.88,86.69 34.16,86.97 34.5,86.97C34.84,86.97 35.12,86.69 35.12,86.35C35.12,86.01 34.84,85.74 34.5,85.74Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M33.06,84.48C32.71,84.48 32.44,84.76 32.44,85.1C32.44,85.44 32.72,85.72 33.06,85.72C33.4,85.72 33.67,85.44 33.67,85.1C33.67,84.76 33.4,84.48 33.06,84.48Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M33.06,86.99C32.71,86.99 32.44,87.27 32.44,87.61C32.44,87.95 32.72,88.23 33.06,88.23C33.4,88.23 33.67,87.95 33.67,87.61C33.67,87.27 33.4,86.99 33.06,86.99Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M10.18,60.56C10.18,61.93 9.08,63.03 7.71,63.03C6.35,63.03 5.25,61.93 5.25,60.56C5.25,59.2 6.35,58.09 7.71,58.09C9.08,58.09 10.18,59.2 10.18,60.56ZM7.3,62.16V58.97C6.6,59.15 6.07,59.8 6.07,60.56C6.07,61.33 6.6,61.97 7.3,62.16M9.36,60.56C9.36,59.8 8.83,59.15 8.13,58.97V62.16C8.83,61.97 9.36,61.33 9.36,60.56"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M11.58,60.56C11.58,61.08 11.48,61.59 11.28,62.07C11.08,62.53 10.8,62.94 10.45,63.3C10.09,63.65 9.68,63.93 9.22,64.13C8.74,64.33 8.23,64.43 7.71,64.43C7.19,64.43 6.68,64.33 6.21,64.13C5.75,63.93 5.33,63.65 4.98,63.3C4.62,62.94 4.34,62.53 4.15,62.07C3.95,61.59 3.84,61.08 3.84,60.56C3.84,60.04 3.94,59.54 4.15,59.06C4.34,58.6 4.62,58.18 4.98,57.83C5.33,57.47 5.75,57.2 6.21,57C6.68,56.8 7.19,56.69 7.71,56.69C8.23,56.69 8.74,56.8 9.22,57C9.68,57.19 10.09,57.47 10.45,57.83C10.8,58.18 11.08,58.6 11.28,59.06C11.48,59.54 11.58,60.04 11.58,60.56ZM10.92,60.56C10.92,58.79 9.49,57.35 7.71,57.35C5.94,57.35 4.51,58.79 4.51,60.56C4.51,62.33 5.94,63.77 7.71,63.77C9.49,63.77 10.92,62.33 10.92,60.56Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M10.18,86.36C10.18,87.72 9.08,88.83 7.71,88.83C6.35,88.83 5.25,87.72 5.25,86.36C5.25,84.99 6.35,83.89 7.71,83.89C9.08,83.89 10.18,84.99 10.18,86.36ZM7.3,87.95V84.76C6.6,84.94 6.07,85.59 6.07,86.36C6.07,87.12 6.6,87.77 7.3,87.95M9.36,86.36C9.36,85.59 8.83,84.95 8.13,84.76V87.95C8.83,87.77 9.36,87.12 9.36,86.35"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M11.58,86.36C11.58,86.88 11.48,87.38 11.28,87.86C11.08,88.32 10.8,88.74 10.45,89.09C10.09,89.45 9.68,89.72 9.22,89.92C8.74,90.12 8.23,90.23 7.71,90.23C7.19,90.23 6.68,90.12 6.21,89.92C5.75,89.73 5.33,89.45 4.98,89.09C4.62,88.74 4.34,88.32 4.15,87.86C3.95,87.38 3.84,86.88 3.84,86.36C3.84,85.84 3.94,85.33 4.15,84.85C4.34,84.39 4.62,83.98 4.98,83.62C5.33,83.27 5.75,82.99 6.21,82.79C6.68,82.59 7.19,82.49 7.71,82.49C8.23,82.49 8.74,82.59 9.22,82.79C9.68,82.99 10.09,83.27 10.45,83.62C10.8,83.98 11.08,84.39 11.28,84.85C11.48,85.33 11.58,85.84 11.58,86.36ZM10.92,86.36C10.92,84.58 9.49,83.15 7.71,83.15C5.94,83.15 4.51,84.59 4.51,86.36C4.51,88.13 5.94,89.57 7.71,89.57C9.49,89.57 10.92,88.13 10.92,86.36Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
</group>
|
||||
</group>
|
||||
<group>
|
||||
<clip-path
|
||||
android:pathData="M43.81,-8.78H-9.07V44.09H43.81V-8.78Z"/>
|
||||
<group>
|
||||
<clip-path
|
||||
android:pathData="M43.81,-8.78H-9.07V44.09H43.81V-8.78Z"/>
|
||||
<path
|
||||
android:pathData="M24.5,47.67C24.5,48.19 24.4,48.69 24.2,49.17C24,49.63 23.72,50.04 23.37,50.4C23.01,50.75 22.6,51.03 22.14,51.23C21.66,51.43 21.16,51.53 20.63,51.53C20.11,51.53 19.61,51.43 19.13,51.23C18.67,51.03 18.25,50.75 17.9,50.4C17.55,50.04 17.27,49.63 17.07,49.17C16.87,48.69 16.76,48.19 16.76,47.67C16.76,47.14 16.87,46.64 17.07,46.16C17.26,45.7 17.55,45.29 17.9,44.93C18.25,44.58 18.67,44.3 19.13,44.1C19.61,43.9 20.11,43.8 20.63,43.8C21.16,43.8 21.66,43.9 22.14,44.1C22.6,44.3 23.01,44.58 23.37,44.93C23.72,45.29 24,45.7 24.2,46.16C24.4,46.64 24.5,47.14 24.5,47.67ZM23.85,47.67C23.85,45.89 22.41,44.46 20.64,44.46C18.87,44.46 17.43,45.89 17.43,47.67C17.43,49.44 18.87,50.87 20.64,50.87C22.41,50.87 23.85,49.44 23.85,47.67Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M37.4,7.69C37.4,8.21 37.3,8.71 37.1,9.19C36.9,9.65 36.62,10.07 36.27,10.42C35.91,10.78 35.5,11.05 35.04,11.25C34.56,11.45 34.05,11.56 33.53,11.56C33.01,11.56 32.5,11.45 32.03,11.25C31.57,11.06 31.15,10.78 30.8,10.42C30.44,10.07 30.17,9.65 29.97,9.19C29.77,8.71 29.66,8.21 29.66,7.69C29.66,7.17 29.76,6.66 29.97,6.18C30.16,5.72 30.44,5.31 30.8,4.95C31.15,4.6 31.57,4.32 32.03,4.12C32.5,3.92 33.01,3.82 33.53,3.82C34.05,3.82 34.56,3.92 35.04,4.12C35.5,4.32 35.91,4.6 36.27,4.95C36.62,5.31 36.9,5.72 37.1,6.18C37.3,6.66 37.4,7.17 37.4,7.69ZM36.74,7.69C36.74,5.91 35.3,4.48 33.53,4.48C31.76,4.48 30.32,5.92 30.32,7.69C30.32,9.46 31.76,10.9 33.53,10.9C35.3,10.9 36.74,9.46 36.74,7.69Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M34.5,7.07C34.16,7.07 33.88,7.35 33.88,7.69C33.88,8.03 34.16,8.3 34.5,8.3C34.84,8.3 35.12,8.03 35.12,7.69C35.12,7.35 34.84,7.07 34.5,7.07Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M33.06,5.81C32.71,5.81 32.44,6.09 32.44,6.43C32.44,6.77 32.72,7.05 33.06,7.05C33.4,7.05 33.67,6.77 33.67,6.43C33.67,6.09 33.4,5.81 33.06,5.81Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M33.06,8.33C32.71,8.33 32.44,8.6 32.44,8.94C32.44,9.28 32.72,9.56 33.06,9.56C33.4,9.56 33.67,9.28 33.67,8.94C33.67,8.6 33.4,8.33 33.06,8.33Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M20.63,18.11C19.27,18.11 18.17,19.22 18.17,20.58C18.17,21.95 19.27,23.05 20.63,23.05C22,23.05 23.1,21.95 23.1,20.58C23.1,19.22 22,18.11 20.63,18.11Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M24.5,20.58C24.5,21.1 24.4,21.61 24.2,22.09C24,22.55 23.72,22.96 23.37,23.32C23.01,23.67 22.6,23.95 22.14,24.15C21.66,24.35 21.16,24.45 20.63,24.45C20.11,24.45 19.61,24.35 19.13,24.15C18.67,23.95 18.25,23.67 17.9,23.32C17.55,22.96 17.27,22.55 17.07,22.09C16.87,21.61 16.76,21.1 16.76,20.58C16.76,20.06 16.87,19.55 17.07,19.08C17.26,18.62 17.55,18.2 17.9,17.85C18.25,17.49 18.67,17.22 19.13,17.02C19.61,16.82 20.11,16.71 20.63,16.71C21.16,16.71 21.66,16.81 22.14,17.02C22.6,17.21 23.01,17.49 23.37,17.85C23.72,18.2 24,18.62 24.2,19.08C24.4,19.55 24.5,20.06 24.5,20.58ZM23.85,20.58C23.85,18.81 22.41,17.37 20.64,17.37C18.87,17.37 17.43,18.81 17.43,20.58C17.43,22.35 18.87,23.79 20.64,23.79C22.41,23.79 23.85,22.35 23.85,20.58Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M37.4,33.48C37.4,34 37.3,34.51 37.1,34.99C36.9,35.45 36.62,35.86 36.27,36.21C35.91,36.57 35.5,36.85 35.04,37.04C34.56,37.24 34.05,37.35 33.53,37.35C33.01,37.35 32.5,37.25 32.03,37.04C31.57,36.85 31.15,36.57 30.8,36.21C30.44,35.86 30.17,35.45 29.97,34.99C29.77,34.51 29.66,34 29.66,33.48C29.66,32.96 29.76,32.45 29.97,31.97C30.16,31.51 30.44,31.1 30.8,30.75C31.15,30.39 31.57,30.11 32.03,29.92C32.5,29.72 33.01,29.61 33.53,29.61C34.05,29.61 34.56,29.71 35.04,29.92C35.5,30.11 35.91,30.39 36.27,30.75C36.62,31.1 36.9,31.51 37.1,31.97C37.3,32.45 37.4,32.96 37.4,33.48ZM36.74,33.48C36.74,31.71 35.3,30.27 33.53,30.27C31.76,30.27 30.32,31.71 30.32,33.48C30.32,35.25 31.76,36.69 33.53,36.69C35.3,36.69 36.74,35.25 36.74,33.48Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M34.5,32.86C34.16,32.86 33.88,33.14 33.88,33.48C33.88,33.82 34.16,34.1 34.5,34.1C34.84,34.1 35.12,33.82 35.12,33.48C35.12,33.14 34.84,32.86 34.5,32.86Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M33.06,31.61C32.71,31.61 32.44,31.88 32.44,32.22C32.44,32.56 32.72,32.84 33.06,32.84C33.4,32.84 33.67,32.56 33.67,32.22C33.67,31.88 33.4,31.61 33.06,31.61Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M33.06,34.12C32.71,34.12 32.44,34.4 32.44,34.74C32.44,35.08 32.72,35.35 33.06,35.35C33.4,35.35 33.67,35.08 33.67,34.74C33.67,34.4 33.4,34.12 33.06,34.12Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M10.18,7.69C10.18,9.05 9.08,10.16 7.71,10.16C6.35,10.16 5.25,9.05 5.25,7.69C5.25,6.32 6.35,5.22 7.71,5.22C9.08,5.22 10.18,6.32 10.18,7.69ZM7.3,9.28V6.09C6.6,6.28 6.07,6.92 6.07,7.69C6.07,8.45 6.6,9.1 7.3,9.28M9.36,7.69C9.36,6.92 8.83,6.28 8.13,6.09V9.28C8.83,9.1 9.36,8.45 9.36,7.68"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M11.58,7.69C11.58,8.21 11.48,8.71 11.28,9.19C11.08,9.65 10.8,10.07 10.45,10.42C10.09,10.78 9.68,11.05 9.22,11.25C8.74,11.45 8.23,11.56 7.71,11.56C7.19,11.56 6.68,11.45 6.21,11.25C5.75,11.06 5.33,10.78 4.98,10.42C4.62,10.07 4.34,9.65 4.15,9.19C3.95,8.71 3.84,8.21 3.84,7.69C3.84,7.17 3.94,6.66 4.15,6.18C4.34,5.72 4.62,5.31 4.98,4.95C5.33,4.6 5.75,4.32 6.21,4.12C6.68,3.92 7.19,3.82 7.71,3.82C8.23,3.82 8.74,3.92 9.22,4.12C9.68,4.32 10.09,4.6 10.45,4.95C10.8,5.31 11.08,5.72 11.28,6.18C11.48,6.66 11.58,7.17 11.58,7.69ZM10.92,7.69C10.92,5.91 9.49,4.48 7.71,4.48C5.94,4.48 4.51,5.92 4.51,7.69C4.51,9.46 5.94,10.9 7.71,10.9C9.49,10.9 10.92,9.46 10.92,7.69Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M10.18,33.48C10.18,34.84 9.08,35.95 7.71,35.95C6.35,35.95 5.25,34.84 5.25,33.48C5.25,32.12 6.35,31.01 7.71,31.01C9.08,31.01 10.18,32.12 10.18,33.48ZM7.3,35.08V31.89C6.6,32.07 6.07,32.72 6.07,33.48C6.07,34.25 6.6,34.89 7.3,35.08M9.36,33.48C9.36,32.71 8.83,32.07 8.13,31.88V35.07C8.83,34.89 9.36,34.24 9.36,33.48"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M11.58,33.48C11.58,34 11.48,34.51 11.28,34.99C11.08,35.45 10.8,35.86 10.45,36.21C10.09,36.57 9.68,36.85 9.22,37.04C8.74,37.24 8.23,37.35 7.71,37.35C7.19,37.35 6.68,37.25 6.21,37.04C5.75,36.85 5.33,36.57 4.98,36.21C4.62,35.86 4.34,35.45 4.15,34.99C3.95,34.51 3.84,34 3.84,33.48C3.84,32.96 3.94,32.45 4.15,31.97C4.34,31.51 4.62,31.1 4.98,30.75C5.33,30.39 5.75,30.11 6.21,29.92C6.68,29.72 7.19,29.61 7.71,29.61C8.23,29.61 8.74,29.71 9.22,29.92C9.68,30.11 10.09,30.39 10.45,30.75C10.8,31.1 11.08,31.51 11.28,31.97C11.48,32.45 11.58,32.96 11.58,33.48ZM10.92,33.48C10.92,31.71 9.49,30.27 7.71,30.27C5.94,30.27 4.51,31.71 4.51,33.48C4.51,35.25 5.94,36.69 7.71,36.69C9.49,36.69 10.92,35.25 10.92,33.48Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.2"/>
|
||||
</group>
|
||||
</group>
|
||||
</group>
|
||||
</group>
|
||||
</group>
|
||||
</group>
|
||||
</vector>
|
||||
|
After Width: | Height: | Size: 38 KiB |
@@ -1,8 +0,0 @@
|
||||
<vector android:height="108dp" android:viewportHeight="434"
|
||||
android:viewportWidth="434" android:width="108dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#000000" android:pathData="M299.36,178.05C303.08,178.05 305.62,180.81 305.62,184.62V219.92C305.62,223.74 303.08,226.5 299.36,226.5C295.55,226.5 293.11,223.74 293.11,219.92V184.62C293.11,180.81 295.55,178.05 299.36,178.05ZM299.36,248.97C294.81,248.97 291.2,245.37 291.2,240.81C291.2,236.35 294.81,232.75 299.36,232.75C303.92,232.75 307.53,236.35 307.53,240.81C307.53,245.37 303.92,248.97 299.36,248.97Z"/>
|
||||
<path android:fillColor="#000000" android:pathData="M276.52,195.12C280.34,195.12 282.77,197.87 282.77,201.58V225.01C282.77,242.29 272.12,248.97 259.19,248.97C246.15,248.97 235.49,242.29 235.49,225.01V201.58C235.49,197.87 237.93,195.12 241.75,195.12C245.46,195.12 248,197.87 248,201.58V224.16C248,233.6 251.98,237.31 259.19,237.31C266.29,237.31 270.27,233.6 270.27,224.16V201.58C270.27,197.87 272.81,195.12 276.52,195.12Z"/>
|
||||
<path android:fillColor="#000000" android:pathData="M200.02,209.43C200.02,212.93 203.63,214.2 210.52,215.79C220.06,218.12 229.18,220.56 229.18,232.33C229.18,243.78 220.7,248.97 208.51,248.97C198.43,248.97 191.12,245.47 187.73,241.44C185.08,238.26 185.4,235.51 187.94,233.07C191.12,229.99 193.88,231.27 195.68,232.86C198.54,235.51 202.04,238.26 208.82,238.26C213.91,238.26 217.09,236.57 217.09,233.18C217.09,229.78 213.7,228.62 204.8,226.18C196,223.74 188.15,221.41 188.15,210.91C188.15,199.15 197.69,194.27 208.29,194.27C214.34,194.27 221.23,195.86 225.47,200.42C227.27,202.22 228.65,204.76 225.47,208.26C222.29,211.55 219.96,210.6 217.73,208.9C215.71,207.41 212.22,204.87 206.92,204.87C203.31,204.87 200.02,206.04 200.02,209.43Z"/>
|
||||
<path android:fillColor="#000000" android:pathData="M153.74,248.97C138.46,248.97 127.5,237.27 127.5,221.53C127.5,205.68 138.46,194.09 153.74,194.09C169.03,194.09 179.99,205.68 179.99,221.53C179.99,237.27 169.03,248.97 153.74,248.97ZM153.74,237.27C162.59,237.27 168.12,230.46 168.12,221.53C168.12,212.6 162.59,205.68 153.74,205.68C144.89,205.68 139.36,212.6 139.36,221.53C139.36,230.46 144.89,237.27 153.74,237.27Z"/>
|
||||
<path android:fillColor="#000000" android:pathData="M349,217.5C349,290.13 290.13,349 217.5,349C144.88,349 86,290.13 86,217.5C86,144.88 144.88,86 217.5,86C290.13,86 349,144.88 349,217.5ZM99.15,217.5C99.15,282.86 152.14,335.85 217.5,335.85C282.86,335.85 335.85,282.86 335.85,217.5C335.85,152.14 282.86,99.15 217.5,99.15C152.14,99.15 99.15,152.14 99.15,217.5Z"/>
|
||||
</vector>
|
||||
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
<monochrome android:drawable="@drawable/monochrome"/>
|
||||
</adaptive-icon>
|
||||
|
Before Width: | Height: | Size: 5.9 KiB |
|
Before Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 49 KiB |