Compare commits
2 Commits
Author | SHA1 | Date | |
---|---|---|---|
34a85b5a1e | |||
21a98b3fc7 |
79
.github/workflows/android-build.yml
vendored
79
.github/workflows/android-build.yml
vendored
@ -1,79 +0,0 @@
|
|||||||
# SPDX-FileCopyrightText: 2022 yuzu Emulator Project
|
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
name: 'yuzu-android-build'
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
tags: [ "*" ]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
android:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
submodules: recursive
|
|
||||||
fetch-depth: 0
|
|
||||||
- name: Set up JDK 17
|
|
||||||
uses: actions/setup-java@v3
|
|
||||||
with:
|
|
||||||
java-version: '17'
|
|
||||||
distribution: 'temurin'
|
|
||||||
- name: Set up cache
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
~/.gradle/caches
|
|
||||||
~/.gradle/wrapper
|
|
||||||
~/.ccache
|
|
||||||
key: ${{ runner.os }}-android-${{ github.sha }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-android-
|
|
||||||
- name: Query tag name
|
|
||||||
uses: olegtarasov/get-tag@v2.1.2
|
|
||||||
id: tagName
|
|
||||||
- name: Install dependencies
|
|
||||||
run: |
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install -y ccache apksigner glslang-dev glslang-tools
|
|
||||||
- name: Build
|
|
||||||
run: ./.ci/scripts/android/build.sh
|
|
||||||
- name: Copy and sign artifacts
|
|
||||||
env:
|
|
||||||
ANDROID_KEYSTORE_B64: ${{ secrets.ANDROID_KEYSTORE_B64 }}
|
|
||||||
ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }}
|
|
||||||
ANDROID_KEYSTORE_PASS: ${{ secrets.ANDROID_KEYSTORE_PASS }}
|
|
||||||
run: ./.ci/scripts/android/upload.sh
|
|
||||||
- name: Upload
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: android
|
|
||||||
path: artifacts/
|
|
||||||
# release steps
|
|
||||||
release-android:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: [android]
|
|
||||||
if: ${{ startsWith(github.ref, 'refs/tags/') }}
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
steps:
|
|
||||||
- uses: actions/download-artifact@v3
|
|
||||||
- name: Query tag name
|
|
||||||
uses: olegtarasov/get-tag@v2.1.2
|
|
||||||
id: tagName
|
|
||||||
- name: Create release
|
|
||||||
uses: actions/create-release@v1
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
with:
|
|
||||||
tag_name: ${{ steps.tagName.outputs.tag }}
|
|
||||||
release_name: ${{ steps.tagName.outputs.tag }}
|
|
||||||
draft: false
|
|
||||||
prerelease: false
|
|
||||||
- name: Upload artifacts
|
|
||||||
uses: alexellis/upload-assets@0.2.3
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
with:
|
|
||||||
asset_paths: '["./**/*.apk","./**/*.aab"]'
|
|
218
.github/workflows/android-merge.js
vendored
218
.github/workflows/android-merge.js
vendored
@ -1,218 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
// Note: This is a GitHub Actions script
|
|
||||||
// It is not meant to be executed directly on your machine without modifications
|
|
||||||
|
|
||||||
const fs = require("fs");
|
|
||||||
// which label to check for changes
|
|
||||||
const CHANGE_LABEL = 'android-merge';
|
|
||||||
// how far back in time should we consider the changes are "recent"? (default: 24 hours)
|
|
||||||
const DETECTION_TIME_FRAME = (parseInt(process.env.DETECTION_TIME_FRAME)) || (24 * 3600 * 1000);
|
|
||||||
|
|
||||||
async function checkBaseChanges(github, context) {
|
|
||||||
// query the commit date of the latest commit on this branch
|
|
||||||
const query = `query($owner:String!, $name:String!, $ref:String!) {
|
|
||||||
repository(name:$name, owner:$owner) {
|
|
||||||
ref(qualifiedName:$ref) {
|
|
||||||
target {
|
|
||||||
... on Commit { id pushedDate oid }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}`;
|
|
||||||
const variables = {
|
|
||||||
owner: context.repo.owner,
|
|
||||||
name: context.repo.repo,
|
|
||||||
ref: 'refs/heads/master',
|
|
||||||
};
|
|
||||||
const result = await github.graphql(query, variables);
|
|
||||||
const pushedAt = result.repository.ref.target.pushedDate;
|
|
||||||
console.log(`Last commit pushed at ${pushedAt}.`);
|
|
||||||
const delta = new Date() - new Date(pushedAt);
|
|
||||||
if (delta <= DETECTION_TIME_FRAME) {
|
|
||||||
console.info('New changes detected, triggering a new build.');
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
console.info('No new changes detected.');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function checkAndroidChanges(github, context) {
|
|
||||||
if (checkBaseChanges(github, context)) return true;
|
|
||||||
const query = `query($owner:String!, $name:String!, $label:String!) {
|
|
||||||
repository(name:$name, owner:$owner) {
|
|
||||||
pullRequests(labels: [$label], states: OPEN, first: 100) {
|
|
||||||
nodes { number headRepository { pushedAt } }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}`;
|
|
||||||
const variables = {
|
|
||||||
owner: context.repo.owner,
|
|
||||||
name: context.repo.repo,
|
|
||||||
label: CHANGE_LABEL,
|
|
||||||
};
|
|
||||||
const result = await github.graphql(query, variables);
|
|
||||||
const pulls = result.repository.pullRequests.nodes;
|
|
||||||
for (let i = 0; i < pulls.length; i++) {
|
|
||||||
let pull = pulls[i];
|
|
||||||
if (new Date() - new Date(pull.headRepository.pushedAt) <= DETECTION_TIME_FRAME) {
|
|
||||||
console.info(`${pull.number} updated at ${pull.headRepository.pushedAt}`);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
console.info("No changes detected in any tagged pull requests.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function tagAndPush(github, owner, repo, execa, commit=false) {
|
|
||||||
let altToken = process.env.ALT_GITHUB_TOKEN;
|
|
||||||
if (!altToken) {
|
|
||||||
throw `Please set ALT_GITHUB_TOKEN environment variable. This token should have write access to ${owner}/${repo}.`;
|
|
||||||
}
|
|
||||||
const query = `query ($owner:String!, $name:String!) {
|
|
||||||
repository(name:$name, owner:$owner) {
|
|
||||||
refs(refPrefix: "refs/tags/", orderBy: {field: TAG_COMMIT_DATE, direction: DESC}, first: 10) {
|
|
||||||
nodes { name }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}`;
|
|
||||||
const variables = {
|
|
||||||
owner: owner,
|
|
||||||
name: repo,
|
|
||||||
};
|
|
||||||
const tags = await github.graphql(query, variables);
|
|
||||||
const tagList = tags.repository.refs.nodes;
|
|
||||||
const lastTag = tagList[0] ? tagList[0].name : 'dummy-0';
|
|
||||||
const tagNumber = /\w+-(\d+)/.exec(lastTag)[1] | 0;
|
|
||||||
const channel = repo.split('-')[1];
|
|
||||||
const newTag = `${channel}-${tagNumber + 1}`;
|
|
||||||
console.log(`New tag: ${newTag}`);
|
|
||||||
if (commit) {
|
|
||||||
let channelName = channel[0].toUpperCase() + channel.slice(1);
|
|
||||||
console.info(`Committing pending commit as ${channelName} #${tagNumber + 1}`);
|
|
||||||
await execa("git", ['commit', '-m', `${channelName} #${tagNumber + 1}`]);
|
|
||||||
}
|
|
||||||
console.info('Pushing tags to GitHub ...');
|
|
||||||
await execa("git", ['tag', newTag]);
|
|
||||||
await execa("git", ['remote', 'add', 'target', `https://${altToken}@github.com/${owner}/${repo}.git`]);
|
|
||||||
await execa("git", ['push', 'target', 'master', '-f']);
|
|
||||||
await execa("git", ['push', 'target', 'master', '--tags']);
|
|
||||||
console.info('Successfully pushed new changes.');
|
|
||||||
}
|
|
||||||
|
|
||||||
async function generateReadme(pulls, context, mergeResults, execa) {
|
|
||||||
let baseUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/`;
|
|
||||||
let output =
|
|
||||||
"| Pull Request | Commit | Title | Author | Merged? |\n|----|----|----|----|----|\n";
|
|
||||||
for (let pull of pulls) {
|
|
||||||
let pr = pull.number;
|
|
||||||
let result = mergeResults[pr];
|
|
||||||
output += `| [${pr}](${baseUrl}/pull/${pr}) | [\`${result.rev || "N/A"}\`](${baseUrl}/pull/${pr}/files) | ${pull.title} | [${pull.author.login}](https://github.com/${pull.author.login}/) | ${result.success ? "Yes" : "No"} |\n`;
|
|
||||||
}
|
|
||||||
output +=
|
|
||||||
"\n\nEnd of merge log. You can find the original README.md below the break.\n\n-----\n\n";
|
|
||||||
output += fs.readFileSync("./README.md");
|
|
||||||
fs.writeFileSync("./README.md", output);
|
|
||||||
await execa("git", ["add", "README.md"]);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function fetchPullRequests(pulls, repoUrl, execa) {
|
|
||||||
console.log("::group::Fetch pull requests");
|
|
||||||
for (let pull of pulls) {
|
|
||||||
let pr = pull.number;
|
|
||||||
console.info(`Fetching PR ${pr} ...`);
|
|
||||||
await execa("git", [
|
|
||||||
"fetch",
|
|
||||||
"-f",
|
|
||||||
"--no-recurse-submodules",
|
|
||||||
repoUrl,
|
|
||||||
`pull/${pr}/head:pr-${pr}`,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
console.log("::endgroup::");
|
|
||||||
}
|
|
||||||
|
|
||||||
async function mergePullRequests(pulls, execa) {
|
|
||||||
let mergeResults = {};
|
|
||||||
console.log("::group::Merge pull requests");
|
|
||||||
await execa("git", ["config", "--global", "user.name", "yuzubot"]);
|
|
||||||
await execa("git", [
|
|
||||||
"config",
|
|
||||||
"--global",
|
|
||||||
"user.email",
|
|
||||||
"yuzu\x40yuzu-emu\x2eorg", // prevent email harvesters from scraping the address
|
|
||||||
]);
|
|
||||||
let hasFailed = false;
|
|
||||||
for (let pull of pulls) {
|
|
||||||
let pr = pull.number;
|
|
||||||
console.info(`Merging PR ${pr} ...`);
|
|
||||||
try {
|
|
||||||
const process1 = execa("git", [
|
|
||||||
"merge",
|
|
||||||
"--squash",
|
|
||||||
"--no-edit",
|
|
||||||
`pr-${pr}`,
|
|
||||||
]);
|
|
||||||
process1.stdout.pipe(process.stdout);
|
|
||||||
await process1;
|
|
||||||
|
|
||||||
const process2 = execa("git", ["commit", "-m", `Merge PR ${pr}`]);
|
|
||||||
process2.stdout.pipe(process.stdout);
|
|
||||||
await process2;
|
|
||||||
|
|
||||||
const process3 = await execa("git", ["rev-parse", "--short", `pr-${pr}`]);
|
|
||||||
mergeResults[pr] = {
|
|
||||||
success: true,
|
|
||||||
rev: process3.stdout,
|
|
||||||
};
|
|
||||||
} catch (err) {
|
|
||||||
console.log(
|
|
||||||
`::error title=#${pr} not merged::Failed to merge pull request: ${pr}: ${err}`
|
|
||||||
);
|
|
||||||
mergeResults[pr] = { success: false };
|
|
||||||
hasFailed = true;
|
|
||||||
await execa("git", ["reset", "--hard"]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
console.log("::endgroup::");
|
|
||||||
if (hasFailed) {
|
|
||||||
throw 'There are merge failures. Aborting!';
|
|
||||||
}
|
|
||||||
return mergeResults;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function mergebot(github, context, execa) {
|
|
||||||
const query = `query ($owner:String!, $name:String!, $label:String!) {
|
|
||||||
repository(name:$name, owner:$owner) {
|
|
||||||
pullRequests(labels: [$label], states: OPEN, first: 100) {
|
|
||||||
nodes {
|
|
||||||
number title author { login }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}`;
|
|
||||||
const variables = {
|
|
||||||
owner: context.repo.owner,
|
|
||||||
name: context.repo.repo,
|
|
||||||
label: CHANGE_LABEL,
|
|
||||||
};
|
|
||||||
const result = await github.graphql(query, variables);
|
|
||||||
const pulls = result.repository.pullRequests.nodes;
|
|
||||||
let displayList = [];
|
|
||||||
for (let i = 0; i < pulls.length; i++) {
|
|
||||||
let pull = pulls[i];
|
|
||||||
displayList.push({ PR: pull.number, Title: pull.title });
|
|
||||||
}
|
|
||||||
console.info("The following pull requests will be merged:");
|
|
||||||
console.table(displayList);
|
|
||||||
await fetchPullRequests(pulls, "https://github.com/yuzu-emu/yuzu", execa);
|
|
||||||
const mergeResults = await mergePullRequests(pulls, execa);
|
|
||||||
await generateReadme(pulls, context, mergeResults, execa);
|
|
||||||
await tagAndPush(github, context.repo.owner, `${context.repo.repo}-android`, execa, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports.mergebot = mergebot;
|
|
||||||
module.exports.checkAndroidChanges = checkAndroidChanges;
|
|
||||||
module.exports.tagAndPush = tagAndPush;
|
|
||||||
module.exports.checkBaseChanges = checkBaseChanges;
|
|
57
.github/workflows/android-publish.yml
vendored
57
.github/workflows/android-publish.yml
vendored
@ -1,57 +0,0 @@
|
|||||||
# SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
|
||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
name: yuzu-android-publish
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: '37 0 * * *'
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
android:
|
|
||||||
description: 'Whether to trigger an Android build (true/false/auto)'
|
|
||||||
required: false
|
|
||||||
default: 'true'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
android:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: ${{ github.event.inputs.android != 'false' && github.repository == 'yuzu-emu/yuzu' }}
|
|
||||||
steps:
|
|
||||||
# this checkout is required to make sure the GitHub Actions scripts are available
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
name: Pre-checkout
|
|
||||||
with:
|
|
||||||
submodules: false
|
|
||||||
- uses: actions/github-script@v6
|
|
||||||
id: check-changes
|
|
||||||
name: 'Check for new changes'
|
|
||||||
env:
|
|
||||||
# 24 hours
|
|
||||||
DETECTION_TIME_FRAME: 86400000
|
|
||||||
with:
|
|
||||||
script: |
|
|
||||||
if (context.payload.inputs && context.payload.inputs.android === 'true') return true;
|
|
||||||
const checkAndroidChanges = require('./.github/workflows/android-merge.js').checkAndroidChanges;
|
|
||||||
return checkAndroidChanges(github, context);
|
|
||||||
- run: npm install execa@5
|
|
||||||
if: ${{ steps.check-changes.outputs.result == 'true' }}
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
name: Checkout
|
|
||||||
if: ${{ steps.check-changes.outputs.result == 'true' }}
|
|
||||||
with:
|
|
||||||
path: 'yuzu-merge'
|
|
||||||
fetch-depth: 0
|
|
||||||
submodules: true
|
|
||||||
token: ${{ secrets.ALT_GITHUB_TOKEN }}
|
|
||||||
- uses: actions/github-script@v5
|
|
||||||
name: 'Check and merge Android changes'
|
|
||||||
if: ${{ steps.check-changes.outputs.result == 'true' }}
|
|
||||||
env:
|
|
||||||
ALT_GITHUB_TOKEN: ${{ secrets.ALT_GITHUB_TOKEN }}
|
|
||||||
with:
|
|
||||||
script: |
|
|
||||||
const execa = require("execa");
|
|
||||||
const mergebot = require('./.github/workflows/android-merge.js').mergebot;
|
|
||||||
process.chdir('${{ github.workspace }}/yuzu-merge');
|
|
||||||
mergebot(github, context, execa);
|
|
4
.github/workflows/verify.yml
vendored
4
.github/workflows/verify.yml
vendored
@ -129,12 +129,11 @@ jobs:
|
|||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
fetch-depth: 0
|
|
||||||
- name: set up JDK 17
|
- name: set up JDK 17
|
||||||
uses: actions/setup-java@v3
|
uses: actions/setup-java@v3
|
||||||
with:
|
with:
|
||||||
java-version: '17'
|
java-version: '17'
|
||||||
distribution: 'temurin'
|
distribution: 'adopt'
|
||||||
- name: Set up cache
|
- name: Set up cache
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
@ -152,6 +151,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install -y ccache apksigner glslang-dev glslang-tools
|
sudo apt-get install -y ccache apksigner glslang-dev glslang-tools
|
||||||
|
git -C ./externals/vcpkg/ fetch --all --unshallow
|
||||||
- name: Build
|
- name: Build
|
||||||
run: ./.ci/scripts/android/build.sh
|
run: ./.ci/scripts/android/build.sh
|
||||||
- name: Copy and sign artifacts
|
- name: Copy and sign artifacts
|
||||||
|
@ -54,7 +54,6 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||||||
<activity
|
<activity
|
||||||
android:name="org.yuzu.yuzu_emu.activities.EmulationActivity"
|
android:name="org.yuzu.yuzu_emu.activities.EmulationActivity"
|
||||||
android:theme="@style/Theme.Yuzu.Main"
|
android:theme="@style/Theme.Yuzu.Main"
|
||||||
android:launchMode="singleTop"
|
|
||||||
android:screenOrientation="userLandscape"
|
android:screenOrientation="userLandscape"
|
||||||
android:supportsPictureInPicture="true"
|
android:supportsPictureInPicture="true"
|
||||||
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|uiMode"
|
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|uiMode"
|
||||||
|
@ -112,36 +112,25 @@ class Settings {
|
|||||||
|
|
||||||
const val PREF_MEMORY_WARNING_SHOWN = "MemoryWarningShown"
|
const val PREF_MEMORY_WARNING_SHOWN = "MemoryWarningShown"
|
||||||
|
|
||||||
const val PREF_OVERLAY_VERSION = "OverlayVersion"
|
const val PREF_OVERLAY_INIT = "OverlayInit"
|
||||||
const val PREF_LANDSCAPE_OVERLAY_VERSION = "LandscapeOverlayVersion"
|
|
||||||
const val PREF_PORTRAIT_OVERLAY_VERSION = "PortraitOverlayVersion"
|
|
||||||
const val PREF_FOLDABLE_OVERLAY_VERSION = "FoldableOverlayVersion"
|
|
||||||
val overlayLayoutPrefs = listOf(
|
|
||||||
PREF_LANDSCAPE_OVERLAY_VERSION,
|
|
||||||
PREF_PORTRAIT_OVERLAY_VERSION,
|
|
||||||
PREF_FOLDABLE_OVERLAY_VERSION
|
|
||||||
)
|
|
||||||
|
|
||||||
const val PREF_CONTROL_SCALE = "controlScale"
|
const val PREF_CONTROL_SCALE = "controlScale"
|
||||||
const val PREF_CONTROL_OPACITY = "controlOpacity"
|
const val PREF_CONTROL_OPACITY = "controlOpacity"
|
||||||
const val PREF_TOUCH_ENABLED = "isTouchEnabled"
|
const val PREF_TOUCH_ENABLED = "isTouchEnabled"
|
||||||
const val PREF_BUTTON_A = "buttonToggle0"
|
const val PREF_BUTTON_TOGGLE_0 = "buttonToggle0"
|
||||||
const val PREF_BUTTON_B = "buttonToggle1"
|
const val PREF_BUTTON_TOGGLE_1 = "buttonToggle1"
|
||||||
const val PREF_BUTTON_X = "buttonToggle2"
|
const val PREF_BUTTON_TOGGLE_2 = "buttonToggle2"
|
||||||
const val PREF_BUTTON_Y = "buttonToggle3"
|
const val PREF_BUTTON_TOGGLE_3 = "buttonToggle3"
|
||||||
const val PREF_BUTTON_L = "buttonToggle4"
|
const val PREF_BUTTON_TOGGLE_4 = "buttonToggle4"
|
||||||
const val PREF_BUTTON_R = "buttonToggle5"
|
const val PREF_BUTTON_TOGGLE_5 = "buttonToggle5"
|
||||||
const val PREF_BUTTON_ZL = "buttonToggle6"
|
const val PREF_BUTTON_TOGGLE_6 = "buttonToggle6"
|
||||||
const val PREF_BUTTON_ZR = "buttonToggle7"
|
const val PREF_BUTTON_TOGGLE_7 = "buttonToggle7"
|
||||||
const val PREF_BUTTON_PLUS = "buttonToggle8"
|
const val PREF_BUTTON_TOGGLE_8 = "buttonToggle8"
|
||||||
const val PREF_BUTTON_MINUS = "buttonToggle9"
|
const val PREF_BUTTON_TOGGLE_9 = "buttonToggle9"
|
||||||
const val PREF_BUTTON_DPAD = "buttonToggle10"
|
const val PREF_BUTTON_TOGGLE_10 = "buttonToggle10"
|
||||||
const val PREF_STICK_L = "buttonToggle11"
|
const val PREF_BUTTON_TOGGLE_11 = "buttonToggle11"
|
||||||
const val PREF_STICK_R = "buttonToggle12"
|
const val PREF_BUTTON_TOGGLE_12 = "buttonToggle12"
|
||||||
const val PREF_BUTTON_STICK_L = "buttonToggle13"
|
const val PREF_BUTTON_TOGGLE_13 = "buttonToggle13"
|
||||||
const val PREF_BUTTON_STICK_R = "buttonToggle14"
|
const val PREF_BUTTON_TOGGLE_14 = "buttonToggle14"
|
||||||
const val PREF_BUTTON_HOME = "buttonToggle15"
|
|
||||||
const val PREF_BUTTON_SCREENSHOT = "buttonToggle16"
|
|
||||||
|
|
||||||
const val PREF_MENU_SETTINGS_JOYSTICK_REL_CENTER = "EmulationMenuSettings_JoystickRelCenter"
|
const val PREF_MENU_SETTINGS_JOYSTICK_REL_CENTER = "EmulationMenuSettings_JoystickRelCenter"
|
||||||
const val PREF_MENU_SETTINGS_DPAD_SLIDE = "EmulationMenuSettings_DpadSlideEnable"
|
const val PREF_MENU_SETTINGS_DPAD_SLIDE = "EmulationMenuSettings_DpadSlideEnable"
|
||||||
@ -156,30 +145,6 @@ class Settings {
|
|||||||
|
|
||||||
private val configFileSectionsMap: MutableMap<String, List<String>> = HashMap()
|
private val configFileSectionsMap: MutableMap<String, List<String>> = HashMap()
|
||||||
|
|
||||||
val overlayPreferences = listOf(
|
|
||||||
PREF_OVERLAY_VERSION,
|
|
||||||
PREF_CONTROL_SCALE,
|
|
||||||
PREF_CONTROL_OPACITY,
|
|
||||||
PREF_TOUCH_ENABLED,
|
|
||||||
PREF_BUTTON_A,
|
|
||||||
PREF_BUTTON_B,
|
|
||||||
PREF_BUTTON_X,
|
|
||||||
PREF_BUTTON_Y,
|
|
||||||
PREF_BUTTON_L,
|
|
||||||
PREF_BUTTON_R,
|
|
||||||
PREF_BUTTON_ZL,
|
|
||||||
PREF_BUTTON_ZR,
|
|
||||||
PREF_BUTTON_PLUS,
|
|
||||||
PREF_BUTTON_MINUS,
|
|
||||||
PREF_BUTTON_DPAD,
|
|
||||||
PREF_STICK_L,
|
|
||||||
PREF_STICK_R,
|
|
||||||
PREF_BUTTON_HOME,
|
|
||||||
PREF_BUTTON_SCREENSHOT,
|
|
||||||
PREF_BUTTON_STICK_L,
|
|
||||||
PREF_BUTTON_STICK_R
|
|
||||||
)
|
|
||||||
|
|
||||||
const val LayoutOption_Unspecified = 0
|
const val LayoutOption_Unspecified = 0
|
||||||
const val LayoutOption_MobilePortrait = 4
|
const val LayoutOption_MobilePortrait = 4
|
||||||
const val LayoutOption_MobileLandscape = 5
|
const val LayoutOption_MobileLandscape = 5
|
||||||
|
@ -212,9 +212,9 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|||||||
}
|
}
|
||||||
if (!isInFoldableLayout) {
|
if (!isInFoldableLayout) {
|
||||||
if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
|
if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
|
||||||
binding.surfaceInputOverlay.layout = InputOverlay.PORTRAIT
|
binding.surfaceInputOverlay.orientation = InputOverlay.PORTRAIT
|
||||||
} else {
|
} else {
|
||||||
binding.surfaceInputOverlay.layout = InputOverlay.LANDSCAPE
|
binding.surfaceInputOverlay.orientation = InputOverlay.LANDSCAPE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!binding.surfaceInputOverlay.isInEditMode) {
|
if (!binding.surfaceInputOverlay.isInEditMode) {
|
||||||
@ -260,9 +260,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|||||||
.remove(Settings.PREF_CONTROL_SCALE)
|
.remove(Settings.PREF_CONTROL_SCALE)
|
||||||
.remove(Settings.PREF_CONTROL_OPACITY)
|
.remove(Settings.PREF_CONTROL_OPACITY)
|
||||||
.apply()
|
.apply()
|
||||||
binding.surfaceInputOverlay.post {
|
binding.surfaceInputOverlay.post { binding.surfaceInputOverlay.resetButtonPlacement() }
|
||||||
binding.surfaceInputOverlay.resetLayoutVisibilityAndPlacement()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateShowFpsOverlay() {
|
private fun updateShowFpsOverlay() {
|
||||||
@ -339,7 +337,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|||||||
binding.inGameMenu.layoutParams.height = it.bounds.bottom
|
binding.inGameMenu.layoutParams.height = it.bounds.bottom
|
||||||
|
|
||||||
isInFoldableLayout = true
|
isInFoldableLayout = true
|
||||||
binding.surfaceInputOverlay.layout = InputOverlay.FOLDABLE
|
binding.surfaceInputOverlay.orientation = InputOverlay.FOLDABLE
|
||||||
refreshInputOverlay()
|
refreshInputOverlay()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -412,9 +410,9 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|||||||
R.id.menu_toggle_controls -> {
|
R.id.menu_toggle_controls -> {
|
||||||
val preferences =
|
val preferences =
|
||||||
PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext)
|
PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext)
|
||||||
val optionsArray = BooleanArray(Settings.overlayPreferences.size)
|
val optionsArray = BooleanArray(15)
|
||||||
Settings.overlayPreferences.forEachIndexed { i, _ ->
|
for (i in 0..14) {
|
||||||
optionsArray[i] = preferences.getBoolean("buttonToggle$i", i < 15)
|
optionsArray[i] = preferences.getBoolean("buttonToggle$i", i < 13)
|
||||||
}
|
}
|
||||||
|
|
||||||
val dialog = MaterialAlertDialogBuilder(requireContext())
|
val dialog = MaterialAlertDialogBuilder(requireContext())
|
||||||
@ -438,7 +436,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|||||||
dialog.getButton(AlertDialog.BUTTON_NEUTRAL)
|
dialog.getButton(AlertDialog.BUTTON_NEUTRAL)
|
||||||
.setOnClickListener {
|
.setOnClickListener {
|
||||||
val isChecked = !optionsArray[0]
|
val isChecked = !optionsArray[0]
|
||||||
Settings.overlayPreferences.forEachIndexed { i, _ ->
|
for (i in 0..14) {
|
||||||
optionsArray[i] = isChecked
|
optionsArray[i] = isChecked
|
||||||
dialog.listView.setItemChecked(i, isChecked)
|
dialog.listView.setItemChecked(i, isChecked)
|
||||||
preferences.edit()
|
preferences.edit()
|
||||||
|
@ -51,23 +51,15 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
|||||||
|
|
||||||
private lateinit var windowInsets: WindowInsets
|
private lateinit var windowInsets: WindowInsets
|
||||||
|
|
||||||
var layout = LANDSCAPE
|
var orientation = LANDSCAPE
|
||||||
|
|
||||||
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
|
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
|
||||||
super.onLayout(changed, left, top, right, bottom)
|
super.onLayout(changed, left, top, right, bottom)
|
||||||
|
|
||||||
windowInsets = rootWindowInsets
|
windowInsets = rootWindowInsets
|
||||||
|
|
||||||
val overlayVersion = preferences.getInt(Settings.PREF_OVERLAY_VERSION, 0)
|
if (!preferences.getBoolean("${Settings.PREF_OVERLAY_INIT}$orientation", false)) {
|
||||||
if (overlayVersion != OVERLAY_VERSION) {
|
defaultOverlay()
|
||||||
resetAllLayouts()
|
|
||||||
} else {
|
|
||||||
val layoutIndex = overlayLayouts.indexOf(layout)
|
|
||||||
val currentLayoutVersion =
|
|
||||||
preferences.getInt(Settings.overlayLayoutPrefs[layoutIndex], 0)
|
|
||||||
if (currentLayoutVersion != overlayLayoutVersions[layoutIndex]) {
|
|
||||||
resetCurrentLayout()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the controls.
|
// Load the controls.
|
||||||
@ -274,10 +266,10 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
|||||||
MotionEvent.ACTION_POINTER_UP -> if (buttonBeingConfigured === button) {
|
MotionEvent.ACTION_POINTER_UP -> if (buttonBeingConfigured === button) {
|
||||||
// Persist button position by saving new place.
|
// Persist button position by saving new place.
|
||||||
saveControlPosition(
|
saveControlPosition(
|
||||||
buttonBeingConfigured!!.prefId,
|
buttonBeingConfigured!!.buttonId,
|
||||||
buttonBeingConfigured!!.bounds.centerX(),
|
buttonBeingConfigured!!.bounds.centerX(),
|
||||||
buttonBeingConfigured!!.bounds.centerY(),
|
buttonBeingConfigured!!.bounds.centerY(),
|
||||||
layout
|
orientation
|
||||||
)
|
)
|
||||||
buttonBeingConfigured = null
|
buttonBeingConfigured = null
|
||||||
}
|
}
|
||||||
@ -307,10 +299,10 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
|||||||
MotionEvent.ACTION_POINTER_UP -> if (dpadBeingConfigured === dpad) {
|
MotionEvent.ACTION_POINTER_UP -> if (dpadBeingConfigured === dpad) {
|
||||||
// Persist button position by saving new place.
|
// Persist button position by saving new place.
|
||||||
saveControlPosition(
|
saveControlPosition(
|
||||||
Settings.PREF_BUTTON_DPAD,
|
dpadBeingConfigured!!.upId,
|
||||||
dpadBeingConfigured!!.bounds.centerX(),
|
dpadBeingConfigured!!.bounds.centerX(),
|
||||||
dpadBeingConfigured!!.bounds.centerY(),
|
dpadBeingConfigured!!.bounds.centerY(),
|
||||||
layout
|
orientation
|
||||||
)
|
)
|
||||||
dpadBeingConfigured = null
|
dpadBeingConfigured = null
|
||||||
}
|
}
|
||||||
@ -338,10 +330,10 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
|||||||
MotionEvent.ACTION_UP,
|
MotionEvent.ACTION_UP,
|
||||||
MotionEvent.ACTION_POINTER_UP -> if (joystickBeingConfigured != null) {
|
MotionEvent.ACTION_POINTER_UP -> if (joystickBeingConfigured != null) {
|
||||||
saveControlPosition(
|
saveControlPosition(
|
||||||
joystickBeingConfigured!!.prefId,
|
joystickBeingConfigured!!.buttonId,
|
||||||
joystickBeingConfigured!!.bounds.centerX(),
|
joystickBeingConfigured!!.bounds.centerX(),
|
||||||
joystickBeingConfigured!!.bounds.centerY(),
|
joystickBeingConfigured!!.bounds.centerY(),
|
||||||
layout
|
orientation
|
||||||
)
|
)
|
||||||
joystickBeingConfigured = null
|
joystickBeingConfigured = null
|
||||||
}
|
}
|
||||||
@ -351,9 +343,9 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addOverlayControls(layout: String) {
|
private fun addOverlayControls(orientation: String) {
|
||||||
val windowSize = getSafeScreenSize(context)
|
val windowSize = getSafeScreenSize(context)
|
||||||
if (preferences.getBoolean(Settings.PREF_BUTTON_A, true)) {
|
if (preferences.getBoolean(Settings.PREF_BUTTON_TOGGLE_0, true)) {
|
||||||
overlayButtons.add(
|
overlayButtons.add(
|
||||||
initializeOverlayButton(
|
initializeOverlayButton(
|
||||||
context,
|
context,
|
||||||
@ -361,12 +353,11 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
|||||||
R.drawable.facebutton_a,
|
R.drawable.facebutton_a,
|
||||||
R.drawable.facebutton_a_depressed,
|
R.drawable.facebutton_a_depressed,
|
||||||
ButtonType.BUTTON_A,
|
ButtonType.BUTTON_A,
|
||||||
Settings.PREF_BUTTON_A,
|
orientation
|
||||||
layout
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (preferences.getBoolean(Settings.PREF_BUTTON_B, true)) {
|
if (preferences.getBoolean(Settings.PREF_BUTTON_TOGGLE_1, true)) {
|
||||||
overlayButtons.add(
|
overlayButtons.add(
|
||||||
initializeOverlayButton(
|
initializeOverlayButton(
|
||||||
context,
|
context,
|
||||||
@ -374,12 +365,11 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
|||||||
R.drawable.facebutton_b,
|
R.drawable.facebutton_b,
|
||||||
R.drawable.facebutton_b_depressed,
|
R.drawable.facebutton_b_depressed,
|
||||||
ButtonType.BUTTON_B,
|
ButtonType.BUTTON_B,
|
||||||
Settings.PREF_BUTTON_B,
|
orientation
|
||||||
layout
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (preferences.getBoolean(Settings.PREF_BUTTON_X, true)) {
|
if (preferences.getBoolean(Settings.PREF_BUTTON_TOGGLE_2, true)) {
|
||||||
overlayButtons.add(
|
overlayButtons.add(
|
||||||
initializeOverlayButton(
|
initializeOverlayButton(
|
||||||
context,
|
context,
|
||||||
@ -387,12 +377,11 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
|||||||
R.drawable.facebutton_x,
|
R.drawable.facebutton_x,
|
||||||
R.drawable.facebutton_x_depressed,
|
R.drawable.facebutton_x_depressed,
|
||||||
ButtonType.BUTTON_X,
|
ButtonType.BUTTON_X,
|
||||||
Settings.PREF_BUTTON_X,
|
orientation
|
||||||
layout
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (preferences.getBoolean(Settings.PREF_BUTTON_Y, true)) {
|
if (preferences.getBoolean(Settings.PREF_BUTTON_TOGGLE_3, true)) {
|
||||||
overlayButtons.add(
|
overlayButtons.add(
|
||||||
initializeOverlayButton(
|
initializeOverlayButton(
|
||||||
context,
|
context,
|
||||||
@ -400,12 +389,11 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
|||||||
R.drawable.facebutton_y,
|
R.drawable.facebutton_y,
|
||||||
R.drawable.facebutton_y_depressed,
|
R.drawable.facebutton_y_depressed,
|
||||||
ButtonType.BUTTON_Y,
|
ButtonType.BUTTON_Y,
|
||||||
Settings.PREF_BUTTON_Y,
|
orientation
|
||||||
layout
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (preferences.getBoolean(Settings.PREF_BUTTON_L, true)) {
|
if (preferences.getBoolean(Settings.PREF_BUTTON_TOGGLE_4, true)) {
|
||||||
overlayButtons.add(
|
overlayButtons.add(
|
||||||
initializeOverlayButton(
|
initializeOverlayButton(
|
||||||
context,
|
context,
|
||||||
@ -413,12 +401,11 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
|||||||
R.drawable.l_shoulder,
|
R.drawable.l_shoulder,
|
||||||
R.drawable.l_shoulder_depressed,
|
R.drawable.l_shoulder_depressed,
|
||||||
ButtonType.TRIGGER_L,
|
ButtonType.TRIGGER_L,
|
||||||
Settings.PREF_BUTTON_L,
|
orientation
|
||||||
layout
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (preferences.getBoolean(Settings.PREF_BUTTON_R, true)) {
|
if (preferences.getBoolean(Settings.PREF_BUTTON_TOGGLE_5, true)) {
|
||||||
overlayButtons.add(
|
overlayButtons.add(
|
||||||
initializeOverlayButton(
|
initializeOverlayButton(
|
||||||
context,
|
context,
|
||||||
@ -426,12 +413,11 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
|||||||
R.drawable.r_shoulder,
|
R.drawable.r_shoulder,
|
||||||
R.drawable.r_shoulder_depressed,
|
R.drawable.r_shoulder_depressed,
|
||||||
ButtonType.TRIGGER_R,
|
ButtonType.TRIGGER_R,
|
||||||
Settings.PREF_BUTTON_R,
|
orientation
|
||||||
layout
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (preferences.getBoolean(Settings.PREF_BUTTON_ZL, true)) {
|
if (preferences.getBoolean(Settings.PREF_BUTTON_TOGGLE_6, true)) {
|
||||||
overlayButtons.add(
|
overlayButtons.add(
|
||||||
initializeOverlayButton(
|
initializeOverlayButton(
|
||||||
context,
|
context,
|
||||||
@ -439,12 +425,11 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
|||||||
R.drawable.zl_trigger,
|
R.drawable.zl_trigger,
|
||||||
R.drawable.zl_trigger_depressed,
|
R.drawable.zl_trigger_depressed,
|
||||||
ButtonType.TRIGGER_ZL,
|
ButtonType.TRIGGER_ZL,
|
||||||
Settings.PREF_BUTTON_ZL,
|
orientation
|
||||||
layout
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (preferences.getBoolean(Settings.PREF_BUTTON_ZR, true)) {
|
if (preferences.getBoolean(Settings.PREF_BUTTON_TOGGLE_7, true)) {
|
||||||
overlayButtons.add(
|
overlayButtons.add(
|
||||||
initializeOverlayButton(
|
initializeOverlayButton(
|
||||||
context,
|
context,
|
||||||
@ -452,12 +437,11 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
|||||||
R.drawable.zr_trigger,
|
R.drawable.zr_trigger,
|
||||||
R.drawable.zr_trigger_depressed,
|
R.drawable.zr_trigger_depressed,
|
||||||
ButtonType.TRIGGER_ZR,
|
ButtonType.TRIGGER_ZR,
|
||||||
Settings.PREF_BUTTON_ZR,
|
orientation
|
||||||
layout
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (preferences.getBoolean(Settings.PREF_BUTTON_PLUS, true)) {
|
if (preferences.getBoolean(Settings.PREF_BUTTON_TOGGLE_8, true)) {
|
||||||
overlayButtons.add(
|
overlayButtons.add(
|
||||||
initializeOverlayButton(
|
initializeOverlayButton(
|
||||||
context,
|
context,
|
||||||
@ -465,12 +449,11 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
|||||||
R.drawable.facebutton_plus,
|
R.drawable.facebutton_plus,
|
||||||
R.drawable.facebutton_plus_depressed,
|
R.drawable.facebutton_plus_depressed,
|
||||||
ButtonType.BUTTON_PLUS,
|
ButtonType.BUTTON_PLUS,
|
||||||
Settings.PREF_BUTTON_PLUS,
|
orientation
|
||||||
layout
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (preferences.getBoolean(Settings.PREF_BUTTON_MINUS, true)) {
|
if (preferences.getBoolean(Settings.PREF_BUTTON_TOGGLE_9, true)) {
|
||||||
overlayButtons.add(
|
overlayButtons.add(
|
||||||
initializeOverlayButton(
|
initializeOverlayButton(
|
||||||
context,
|
context,
|
||||||
@ -478,12 +461,11 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
|||||||
R.drawable.facebutton_minus,
|
R.drawable.facebutton_minus,
|
||||||
R.drawable.facebutton_minus_depressed,
|
R.drawable.facebutton_minus_depressed,
|
||||||
ButtonType.BUTTON_MINUS,
|
ButtonType.BUTTON_MINUS,
|
||||||
Settings.PREF_BUTTON_MINUS,
|
orientation
|
||||||
layout
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (preferences.getBoolean(Settings.PREF_BUTTON_DPAD, true)) {
|
if (preferences.getBoolean(Settings.PREF_BUTTON_TOGGLE_10, true)) {
|
||||||
overlayDpads.add(
|
overlayDpads.add(
|
||||||
initializeOverlayDpad(
|
initializeOverlayDpad(
|
||||||
context,
|
context,
|
||||||
@ -491,11 +473,11 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
|||||||
R.drawable.dpad_standard,
|
R.drawable.dpad_standard,
|
||||||
R.drawable.dpad_standard_cardinal_depressed,
|
R.drawable.dpad_standard_cardinal_depressed,
|
||||||
R.drawable.dpad_standard_diagonal_depressed,
|
R.drawable.dpad_standard_diagonal_depressed,
|
||||||
layout
|
orientation
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (preferences.getBoolean(Settings.PREF_STICK_L, true)) {
|
if (preferences.getBoolean(Settings.PREF_BUTTON_TOGGLE_11, true)) {
|
||||||
overlayJoysticks.add(
|
overlayJoysticks.add(
|
||||||
initializeOverlayJoystick(
|
initializeOverlayJoystick(
|
||||||
context,
|
context,
|
||||||
@ -505,12 +487,11 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
|||||||
R.drawable.joystick_depressed,
|
R.drawable.joystick_depressed,
|
||||||
StickType.STICK_L,
|
StickType.STICK_L,
|
||||||
ButtonType.STICK_L,
|
ButtonType.STICK_L,
|
||||||
Settings.PREF_STICK_L,
|
orientation
|
||||||
layout
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (preferences.getBoolean(Settings.PREF_STICK_R, true)) {
|
if (preferences.getBoolean(Settings.PREF_BUTTON_TOGGLE_12, true)) {
|
||||||
overlayJoysticks.add(
|
overlayJoysticks.add(
|
||||||
initializeOverlayJoystick(
|
initializeOverlayJoystick(
|
||||||
context,
|
context,
|
||||||
@ -520,12 +501,11 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
|||||||
R.drawable.joystick_depressed,
|
R.drawable.joystick_depressed,
|
||||||
StickType.STICK_R,
|
StickType.STICK_R,
|
||||||
ButtonType.STICK_R,
|
ButtonType.STICK_R,
|
||||||
Settings.PREF_STICK_R,
|
orientation
|
||||||
layout
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (preferences.getBoolean(Settings.PREF_BUTTON_HOME, false)) {
|
if (preferences.getBoolean(Settings.PREF_BUTTON_TOGGLE_13, false)) {
|
||||||
overlayButtons.add(
|
overlayButtons.add(
|
||||||
initializeOverlayButton(
|
initializeOverlayButton(
|
||||||
context,
|
context,
|
||||||
@ -533,12 +513,11 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
|||||||
R.drawable.facebutton_home,
|
R.drawable.facebutton_home,
|
||||||
R.drawable.facebutton_home_depressed,
|
R.drawable.facebutton_home_depressed,
|
||||||
ButtonType.BUTTON_HOME,
|
ButtonType.BUTTON_HOME,
|
||||||
Settings.PREF_BUTTON_HOME,
|
orientation
|
||||||
layout
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (preferences.getBoolean(Settings.PREF_BUTTON_SCREENSHOT, false)) {
|
if (preferences.getBoolean(Settings.PREF_BUTTON_TOGGLE_14, false)) {
|
||||||
overlayButtons.add(
|
overlayButtons.add(
|
||||||
initializeOverlayButton(
|
initializeOverlayButton(
|
||||||
context,
|
context,
|
||||||
@ -546,34 +525,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
|||||||
R.drawable.facebutton_screenshot,
|
R.drawable.facebutton_screenshot,
|
||||||
R.drawable.facebutton_screenshot_depressed,
|
R.drawable.facebutton_screenshot_depressed,
|
||||||
ButtonType.BUTTON_CAPTURE,
|
ButtonType.BUTTON_CAPTURE,
|
||||||
Settings.PREF_BUTTON_SCREENSHOT,
|
orientation
|
||||||
layout
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
if (preferences.getBoolean(Settings.PREF_BUTTON_STICK_L, true)) {
|
|
||||||
overlayButtons.add(
|
|
||||||
initializeOverlayButton(
|
|
||||||
context,
|
|
||||||
windowSize,
|
|
||||||
R.drawable.button_l3,
|
|
||||||
R.drawable.button_l3_depressed,
|
|
||||||
ButtonType.STICK_L,
|
|
||||||
Settings.PREF_BUTTON_STICK_L,
|
|
||||||
layout
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
if (preferences.getBoolean(Settings.PREF_BUTTON_STICK_R, true)) {
|
|
||||||
overlayButtons.add(
|
|
||||||
initializeOverlayButton(
|
|
||||||
context,
|
|
||||||
windowSize,
|
|
||||||
R.drawable.button_r3,
|
|
||||||
R.drawable.button_r3_depressed,
|
|
||||||
ButtonType.STICK_R,
|
|
||||||
Settings.PREF_BUTTON_STICK_R,
|
|
||||||
layout
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -587,18 +539,18 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
|||||||
|
|
||||||
// Add all the enabled overlay items back to the HashSet.
|
// Add all the enabled overlay items back to the HashSet.
|
||||||
if (EmulationMenuSettings.showOverlay) {
|
if (EmulationMenuSettings.showOverlay) {
|
||||||
addOverlayControls(layout)
|
addOverlayControls(orientation)
|
||||||
}
|
}
|
||||||
invalidate()
|
invalidate()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun saveControlPosition(prefId: String, x: Int, y: Int, layout: String) {
|
private fun saveControlPosition(sharedPrefsId: Int, x: Int, y: Int, orientation: String) {
|
||||||
val windowSize = getSafeScreenSize(context)
|
val windowSize = getSafeScreenSize(context)
|
||||||
val min = windowSize.first
|
val min = windowSize.first
|
||||||
val max = windowSize.second
|
val max = windowSize.second
|
||||||
PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext).edit()
|
PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext).edit()
|
||||||
.putFloat("$prefId-X$layout", (x - min.x).toFloat() / max.x)
|
.putFloat("$sharedPrefsId-X$orientation", (x - min.x).toFloat() / max.x)
|
||||||
.putFloat("$prefId-Y$layout", (y - min.y).toFloat() / max.y)
|
.putFloat("$sharedPrefsId-Y$orientation", (y - min.y).toFloat() / max.y)
|
||||||
.apply()
|
.apply()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -606,31 +558,19 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
|||||||
inEditMode = editMode
|
inEditMode = editMode
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun resetCurrentLayout() {
|
private fun defaultOverlay() {
|
||||||
defaultOverlayByLayout(layout)
|
if (!preferences.getBoolean("${Settings.PREF_OVERLAY_INIT}$orientation", false)) {
|
||||||
val layoutIndex = overlayLayouts.indexOf(layout)
|
defaultOverlayByLayout(orientation)
|
||||||
|
}
|
||||||
|
|
||||||
|
resetButtonPlacement()
|
||||||
preferences.edit()
|
preferences.edit()
|
||||||
.putInt(Settings.overlayLayoutPrefs[layoutIndex], overlayLayoutVersions[layoutIndex])
|
.putBoolean("${Settings.PREF_OVERLAY_INIT}$orientation", true)
|
||||||
.apply()
|
.apply()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun resetAllLayouts() {
|
fun resetButtonPlacement() {
|
||||||
val editor = preferences.edit()
|
defaultOverlayByLayout(orientation)
|
||||||
overlayLayouts.forEachIndexed { i, layout ->
|
|
||||||
defaultOverlayByLayout(layout)
|
|
||||||
editor.putInt(Settings.overlayLayoutPrefs[i], overlayLayoutVersions[i])
|
|
||||||
}
|
|
||||||
editor.putInt(Settings.PREF_OVERLAY_VERSION, OVERLAY_VERSION)
|
|
||||||
editor.apply()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun resetLayoutVisibilityAndPlacement() {
|
|
||||||
defaultOverlayByLayout(layout)
|
|
||||||
val editor = preferences.edit()
|
|
||||||
Settings.overlayPreferences.forEachIndexed { _, pref ->
|
|
||||||
editor.remove(pref)
|
|
||||||
}
|
|
||||||
editor.apply()
|
|
||||||
refreshControls()
|
refreshControls()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -664,11 +604,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
|||||||
R.integer.SWITCH_STICK_R_X,
|
R.integer.SWITCH_STICK_R_X,
|
||||||
R.integer.SWITCH_STICK_R_Y,
|
R.integer.SWITCH_STICK_R_Y,
|
||||||
R.integer.SWITCH_STICK_L_X,
|
R.integer.SWITCH_STICK_L_X,
|
||||||
R.integer.SWITCH_STICK_L_Y,
|
R.integer.SWITCH_STICK_L_Y
|
||||||
R.integer.SWITCH_BUTTON_STICK_L_X,
|
|
||||||
R.integer.SWITCH_BUTTON_STICK_L_Y,
|
|
||||||
R.integer.SWITCH_BUTTON_STICK_R_X,
|
|
||||||
R.integer.SWITCH_BUTTON_STICK_R_Y
|
|
||||||
)
|
)
|
||||||
|
|
||||||
private val portraitResources = arrayOf(
|
private val portraitResources = arrayOf(
|
||||||
@ -701,11 +637,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
|||||||
R.integer.SWITCH_STICK_R_X_PORTRAIT,
|
R.integer.SWITCH_STICK_R_X_PORTRAIT,
|
||||||
R.integer.SWITCH_STICK_R_Y_PORTRAIT,
|
R.integer.SWITCH_STICK_R_Y_PORTRAIT,
|
||||||
R.integer.SWITCH_STICK_L_X_PORTRAIT,
|
R.integer.SWITCH_STICK_L_X_PORTRAIT,
|
||||||
R.integer.SWITCH_STICK_L_Y_PORTRAIT,
|
R.integer.SWITCH_STICK_L_Y_PORTRAIT
|
||||||
R.integer.SWITCH_BUTTON_STICK_L_X_PORTRAIT,
|
|
||||||
R.integer.SWITCH_BUTTON_STICK_L_Y_PORTRAIT,
|
|
||||||
R.integer.SWITCH_BUTTON_STICK_R_X_PORTRAIT,
|
|
||||||
R.integer.SWITCH_BUTTON_STICK_R_Y_PORTRAIT
|
|
||||||
)
|
)
|
||||||
|
|
||||||
private val foldableResources = arrayOf(
|
private val foldableResources = arrayOf(
|
||||||
@ -738,159 +670,139 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
|||||||
R.integer.SWITCH_STICK_R_X_FOLDABLE,
|
R.integer.SWITCH_STICK_R_X_FOLDABLE,
|
||||||
R.integer.SWITCH_STICK_R_Y_FOLDABLE,
|
R.integer.SWITCH_STICK_R_Y_FOLDABLE,
|
||||||
R.integer.SWITCH_STICK_L_X_FOLDABLE,
|
R.integer.SWITCH_STICK_L_X_FOLDABLE,
|
||||||
R.integer.SWITCH_STICK_L_Y_FOLDABLE,
|
R.integer.SWITCH_STICK_L_Y_FOLDABLE
|
||||||
R.integer.SWITCH_BUTTON_STICK_L_X_FOLDABLE,
|
|
||||||
R.integer.SWITCH_BUTTON_STICK_L_Y_FOLDABLE,
|
|
||||||
R.integer.SWITCH_BUTTON_STICK_R_X_FOLDABLE,
|
|
||||||
R.integer.SWITCH_BUTTON_STICK_R_Y_FOLDABLE
|
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun getResourceValue(layout: String, position: Int): Float {
|
private fun getResourceValue(orientation: String, position: Int): Float {
|
||||||
return when (layout) {
|
return when (orientation) {
|
||||||
PORTRAIT -> resources.getInteger(portraitResources[position]).toFloat() / 1000
|
PORTRAIT -> resources.getInteger(portraitResources[position]).toFloat() / 1000
|
||||||
FOLDABLE -> resources.getInteger(foldableResources[position]).toFloat() / 1000
|
FOLDABLE -> resources.getInteger(foldableResources[position]).toFloat() / 1000
|
||||||
else -> resources.getInteger(landscapeResources[position]).toFloat() / 1000
|
else -> resources.getInteger(landscapeResources[position]).toFloat() / 1000
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun defaultOverlayByLayout(layout: String) {
|
private fun defaultOverlayByLayout(orientation: String) {
|
||||||
// Each value represents the position of the button in relation to the screen size without insets.
|
// Each value represents the position of the button in relation to the screen size without insets.
|
||||||
preferences.edit()
|
preferences.edit()
|
||||||
.putFloat(
|
.putFloat(
|
||||||
"${Settings.PREF_BUTTON_A}-X$layout",
|
ButtonType.BUTTON_A.toString() + "-X$orientation",
|
||||||
getResourceValue(layout, 0)
|
getResourceValue(orientation, 0)
|
||||||
)
|
)
|
||||||
.putFloat(
|
.putFloat(
|
||||||
"${Settings.PREF_BUTTON_A}-Y$layout",
|
ButtonType.BUTTON_A.toString() + "-Y$orientation",
|
||||||
getResourceValue(layout, 1)
|
getResourceValue(orientation, 1)
|
||||||
)
|
)
|
||||||
.putFloat(
|
.putFloat(
|
||||||
"${Settings.PREF_BUTTON_B}-X$layout",
|
ButtonType.BUTTON_B.toString() + "-X$orientation",
|
||||||
getResourceValue(layout, 2)
|
getResourceValue(orientation, 2)
|
||||||
)
|
)
|
||||||
.putFloat(
|
.putFloat(
|
||||||
"${Settings.PREF_BUTTON_B}-Y$layout",
|
ButtonType.BUTTON_B.toString() + "-Y$orientation",
|
||||||
getResourceValue(layout, 3)
|
getResourceValue(orientation, 3)
|
||||||
)
|
)
|
||||||
.putFloat(
|
.putFloat(
|
||||||
"${Settings.PREF_BUTTON_X}-X$layout",
|
ButtonType.BUTTON_X.toString() + "-X$orientation",
|
||||||
getResourceValue(layout, 4)
|
getResourceValue(orientation, 4)
|
||||||
)
|
)
|
||||||
.putFloat(
|
.putFloat(
|
||||||
"${Settings.PREF_BUTTON_X}-Y$layout",
|
ButtonType.BUTTON_X.toString() + "-Y$orientation",
|
||||||
getResourceValue(layout, 5)
|
getResourceValue(orientation, 5)
|
||||||
)
|
)
|
||||||
.putFloat(
|
.putFloat(
|
||||||
"${Settings.PREF_BUTTON_Y}-X$layout",
|
ButtonType.BUTTON_Y.toString() + "-X$orientation",
|
||||||
getResourceValue(layout, 6)
|
getResourceValue(orientation, 6)
|
||||||
)
|
)
|
||||||
.putFloat(
|
.putFloat(
|
||||||
"${Settings.PREF_BUTTON_Y}-Y$layout",
|
ButtonType.BUTTON_Y.toString() + "-Y$orientation",
|
||||||
getResourceValue(layout, 7)
|
getResourceValue(orientation, 7)
|
||||||
)
|
)
|
||||||
.putFloat(
|
.putFloat(
|
||||||
"${Settings.PREF_BUTTON_ZL}-X$layout",
|
ButtonType.TRIGGER_ZL.toString() + "-X$orientation",
|
||||||
getResourceValue(layout, 8)
|
getResourceValue(orientation, 8)
|
||||||
)
|
)
|
||||||
.putFloat(
|
.putFloat(
|
||||||
"${Settings.PREF_BUTTON_ZL}-Y$layout",
|
ButtonType.TRIGGER_ZL.toString() + "-Y$orientation",
|
||||||
getResourceValue(layout, 9)
|
getResourceValue(orientation, 9)
|
||||||
)
|
)
|
||||||
.putFloat(
|
.putFloat(
|
||||||
"${Settings.PREF_BUTTON_ZR}-X$layout",
|
ButtonType.TRIGGER_ZR.toString() + "-X$orientation",
|
||||||
getResourceValue(layout, 10)
|
getResourceValue(orientation, 10)
|
||||||
)
|
)
|
||||||
.putFloat(
|
.putFloat(
|
||||||
"${Settings.PREF_BUTTON_ZR}-Y$layout",
|
ButtonType.TRIGGER_ZR.toString() + "-Y$orientation",
|
||||||
getResourceValue(layout, 11)
|
getResourceValue(orientation, 11)
|
||||||
)
|
)
|
||||||
.putFloat(
|
.putFloat(
|
||||||
"${Settings.PREF_BUTTON_DPAD}-X$layout",
|
ButtonType.DPAD_UP.toString() + "-X$orientation",
|
||||||
getResourceValue(layout, 12)
|
getResourceValue(orientation, 12)
|
||||||
)
|
)
|
||||||
.putFloat(
|
.putFloat(
|
||||||
"${Settings.PREF_BUTTON_DPAD}-Y$layout",
|
ButtonType.DPAD_UP.toString() + "-Y$orientation",
|
||||||
getResourceValue(layout, 13)
|
getResourceValue(orientation, 13)
|
||||||
)
|
)
|
||||||
.putFloat(
|
.putFloat(
|
||||||
"${Settings.PREF_BUTTON_L}-X$layout",
|
ButtonType.TRIGGER_L.toString() + "-X$orientation",
|
||||||
getResourceValue(layout, 14)
|
getResourceValue(orientation, 14)
|
||||||
)
|
)
|
||||||
.putFloat(
|
.putFloat(
|
||||||
"${Settings.PREF_BUTTON_L}-Y$layout",
|
ButtonType.TRIGGER_L.toString() + "-Y$orientation",
|
||||||
getResourceValue(layout, 15)
|
getResourceValue(orientation, 15)
|
||||||
)
|
)
|
||||||
.putFloat(
|
.putFloat(
|
||||||
"${Settings.PREF_BUTTON_R}-X$layout",
|
ButtonType.TRIGGER_R.toString() + "-X$orientation",
|
||||||
getResourceValue(layout, 16)
|
getResourceValue(orientation, 16)
|
||||||
)
|
)
|
||||||
.putFloat(
|
.putFloat(
|
||||||
"${Settings.PREF_BUTTON_R}-Y$layout",
|
ButtonType.TRIGGER_R.toString() + "-Y$orientation",
|
||||||
getResourceValue(layout, 17)
|
getResourceValue(orientation, 17)
|
||||||
)
|
)
|
||||||
.putFloat(
|
.putFloat(
|
||||||
"${Settings.PREF_BUTTON_PLUS}-X$layout",
|
ButtonType.BUTTON_PLUS.toString() + "-X$orientation",
|
||||||
getResourceValue(layout, 18)
|
getResourceValue(orientation, 18)
|
||||||
)
|
)
|
||||||
.putFloat(
|
.putFloat(
|
||||||
"${Settings.PREF_BUTTON_PLUS}-Y$layout",
|
ButtonType.BUTTON_PLUS.toString() + "-Y$orientation",
|
||||||
getResourceValue(layout, 19)
|
getResourceValue(orientation, 19)
|
||||||
)
|
)
|
||||||
.putFloat(
|
.putFloat(
|
||||||
"${Settings.PREF_BUTTON_MINUS}-X$layout",
|
ButtonType.BUTTON_MINUS.toString() + "-X$orientation",
|
||||||
getResourceValue(layout, 20)
|
getResourceValue(orientation, 20)
|
||||||
)
|
)
|
||||||
.putFloat(
|
.putFloat(
|
||||||
"${Settings.PREF_BUTTON_MINUS}-Y$layout",
|
ButtonType.BUTTON_MINUS.toString() + "-Y$orientation",
|
||||||
getResourceValue(layout, 21)
|
getResourceValue(orientation, 21)
|
||||||
)
|
)
|
||||||
.putFloat(
|
.putFloat(
|
||||||
"${Settings.PREF_BUTTON_HOME}-X$layout",
|
ButtonType.BUTTON_HOME.toString() + "-X$orientation",
|
||||||
getResourceValue(layout, 22)
|
getResourceValue(orientation, 22)
|
||||||
)
|
)
|
||||||
.putFloat(
|
.putFloat(
|
||||||
"${Settings.PREF_BUTTON_HOME}-Y$layout",
|
ButtonType.BUTTON_HOME.toString() + "-Y$orientation",
|
||||||
getResourceValue(layout, 23)
|
getResourceValue(orientation, 23)
|
||||||
)
|
)
|
||||||
.putFloat(
|
.putFloat(
|
||||||
"${Settings.PREF_BUTTON_SCREENSHOT}-X$layout",
|
ButtonType.BUTTON_CAPTURE.toString() + "-X$orientation",
|
||||||
getResourceValue(layout, 24)
|
getResourceValue(orientation, 24)
|
||||||
)
|
)
|
||||||
.putFloat(
|
.putFloat(
|
||||||
"${Settings.PREF_BUTTON_SCREENSHOT}-Y$layout",
|
ButtonType.BUTTON_CAPTURE.toString() + "-Y$orientation",
|
||||||
getResourceValue(layout, 25)
|
getResourceValue(orientation, 25)
|
||||||
)
|
)
|
||||||
.putFloat(
|
.putFloat(
|
||||||
"${Settings.PREF_STICK_R}-X$layout",
|
ButtonType.STICK_R.toString() + "-X$orientation",
|
||||||
getResourceValue(layout, 26)
|
getResourceValue(orientation, 26)
|
||||||
)
|
)
|
||||||
.putFloat(
|
.putFloat(
|
||||||
"${Settings.PREF_STICK_R}-Y$layout",
|
ButtonType.STICK_R.toString() + "-Y$orientation",
|
||||||
getResourceValue(layout, 27)
|
getResourceValue(orientation, 27)
|
||||||
)
|
)
|
||||||
.putFloat(
|
.putFloat(
|
||||||
"${Settings.PREF_STICK_L}-X$layout",
|
ButtonType.STICK_L.toString() + "-X$orientation",
|
||||||
getResourceValue(layout, 28)
|
getResourceValue(orientation, 28)
|
||||||
)
|
)
|
||||||
.putFloat(
|
.putFloat(
|
||||||
"${Settings.PREF_STICK_L}-Y$layout",
|
ButtonType.STICK_L.toString() + "-Y$orientation",
|
||||||
getResourceValue(layout, 29)
|
getResourceValue(orientation, 29)
|
||||||
)
|
|
||||||
.putFloat(
|
|
||||||
"${Settings.PREF_BUTTON_STICK_L}-X$layout",
|
|
||||||
getResourceValue(layout, 30)
|
|
||||||
)
|
|
||||||
.putFloat(
|
|
||||||
"${Settings.PREF_BUTTON_STICK_L}-Y$layout",
|
|
||||||
getResourceValue(layout, 31)
|
|
||||||
)
|
|
||||||
.putFloat(
|
|
||||||
"${Settings.PREF_BUTTON_STICK_R}-X$layout",
|
|
||||||
getResourceValue(layout, 32)
|
|
||||||
)
|
|
||||||
.putFloat(
|
|
||||||
"${Settings.PREF_BUTTON_STICK_R}-Y$layout",
|
|
||||||
getResourceValue(layout, 33)
|
|
||||||
)
|
)
|
||||||
.apply()
|
.apply()
|
||||||
}
|
}
|
||||||
@ -900,30 +812,12 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
// Increase this number every time there is a breaking change to every overlay layout
|
|
||||||
const val OVERLAY_VERSION = 1
|
|
||||||
|
|
||||||
// Increase the corresponding layout version number whenever that layout has a breaking change
|
|
||||||
private const val LANDSCAPE_OVERLAY_VERSION = 1
|
|
||||||
private const val PORTRAIT_OVERLAY_VERSION = 1
|
|
||||||
private const val FOLDABLE_OVERLAY_VERSION = 1
|
|
||||||
val overlayLayoutVersions = listOf(
|
|
||||||
LANDSCAPE_OVERLAY_VERSION,
|
|
||||||
PORTRAIT_OVERLAY_VERSION,
|
|
||||||
FOLDABLE_OVERLAY_VERSION
|
|
||||||
)
|
|
||||||
|
|
||||||
private val preferences: SharedPreferences =
|
private val preferences: SharedPreferences =
|
||||||
PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext)
|
PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext)
|
||||||
|
|
||||||
const val LANDSCAPE = "_Landscape"
|
const val LANDSCAPE = ""
|
||||||
const val PORTRAIT = "_Portrait"
|
const val PORTRAIT = "_Portrait"
|
||||||
const val FOLDABLE = "_Foldable"
|
const val FOLDABLE = "_Foldable"
|
||||||
val overlayLayouts = listOf(
|
|
||||||
LANDSCAPE,
|
|
||||||
PORTRAIT,
|
|
||||||
FOLDABLE
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resizes a [Bitmap] by a given scale factor
|
* Resizes a [Bitmap] by a given scale factor
|
||||||
@ -1054,8 +948,6 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
|||||||
* @param defaultResId The resource ID of the [Drawable] to get the [Bitmap] of (Default State).
|
* @param defaultResId The resource ID of the [Drawable] to get the [Bitmap] of (Default State).
|
||||||
* @param pressedResId The resource ID of the [Drawable] to get the [Bitmap] of (Pressed State).
|
* @param pressedResId The resource ID of the [Drawable] to get the [Bitmap] of (Pressed State).
|
||||||
* @param buttonId Identifier for determining what type of button the initialized InputOverlayDrawableButton represents.
|
* @param buttonId Identifier for determining what type of button the initialized InputOverlayDrawableButton represents.
|
||||||
* @param prefId Identifier for determining where a button appears on screen.
|
|
||||||
* @param layout The current screen layout as determined by [LANDSCAPE], [PORTRAIT], or [FOLDABLE].
|
|
||||||
* @return An [InputOverlayDrawableButton] with the correct drawing bounds set.
|
* @return An [InputOverlayDrawableButton] with the correct drawing bounds set.
|
||||||
*/
|
*/
|
||||||
private fun initializeOverlayButton(
|
private fun initializeOverlayButton(
|
||||||
@ -1064,8 +956,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
|||||||
defaultResId: Int,
|
defaultResId: Int,
|
||||||
pressedResId: Int,
|
pressedResId: Int,
|
||||||
buttonId: Int,
|
buttonId: Int,
|
||||||
prefId: String,
|
orientation: String
|
||||||
layout: String
|
|
||||||
): InputOverlayDrawableButton {
|
): InputOverlayDrawableButton {
|
||||||
// Resources handle for fetching the initial Drawable resource.
|
// Resources handle for fetching the initial Drawable resource.
|
||||||
val res = context.resources
|
val res = context.resources
|
||||||
@ -1073,20 +964,17 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
|||||||
// SharedPreference to retrieve the X and Y coordinates for the InputOverlayDrawableButton.
|
// SharedPreference to retrieve the X and Y coordinates for the InputOverlayDrawableButton.
|
||||||
val sPrefs = PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext)
|
val sPrefs = PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext)
|
||||||
|
|
||||||
// Decide scale based on button preference ID and user preference
|
// Decide scale based on button ID and user preference
|
||||||
var scale: Float = when (prefId) {
|
var scale: Float = when (buttonId) {
|
||||||
Settings.PREF_BUTTON_HOME,
|
ButtonType.BUTTON_HOME,
|
||||||
Settings.PREF_BUTTON_SCREENSHOT,
|
ButtonType.BUTTON_CAPTURE,
|
||||||
Settings.PREF_BUTTON_PLUS,
|
ButtonType.BUTTON_PLUS,
|
||||||
Settings.PREF_BUTTON_MINUS -> 0.07f
|
ButtonType.BUTTON_MINUS -> 0.07f
|
||||||
|
|
||||||
Settings.PREF_BUTTON_L,
|
ButtonType.TRIGGER_L,
|
||||||
Settings.PREF_BUTTON_R,
|
ButtonType.TRIGGER_R,
|
||||||
Settings.PREF_BUTTON_ZL,
|
ButtonType.TRIGGER_ZL,
|
||||||
Settings.PREF_BUTTON_ZR -> 0.26f
|
ButtonType.TRIGGER_ZR -> 0.26f
|
||||||
|
|
||||||
Settings.PREF_BUTTON_STICK_L,
|
|
||||||
Settings.PREF_BUTTON_STICK_R -> 0.155f
|
|
||||||
|
|
||||||
else -> 0.11f
|
else -> 0.11f
|
||||||
}
|
}
|
||||||
@ -1096,13 +984,8 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
|||||||
// Initialize the InputOverlayDrawableButton.
|
// Initialize the InputOverlayDrawableButton.
|
||||||
val defaultStateBitmap = getBitmap(context, defaultResId, scale)
|
val defaultStateBitmap = getBitmap(context, defaultResId, scale)
|
||||||
val pressedStateBitmap = getBitmap(context, pressedResId, scale)
|
val pressedStateBitmap = getBitmap(context, pressedResId, scale)
|
||||||
val overlayDrawable = InputOverlayDrawableButton(
|
val overlayDrawable =
|
||||||
res,
|
InputOverlayDrawableButton(res, defaultStateBitmap, pressedStateBitmap, buttonId)
|
||||||
defaultStateBitmap,
|
|
||||||
pressedStateBitmap,
|
|
||||||
buttonId,
|
|
||||||
prefId
|
|
||||||
)
|
|
||||||
|
|
||||||
// Get the minimum and maximum coordinates of the screen where the button can be placed.
|
// Get the minimum and maximum coordinates of the screen where the button can be placed.
|
||||||
val min = windowSize.first
|
val min = windowSize.first
|
||||||
@ -1110,8 +993,8 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
|||||||
|
|
||||||
// The X and Y coordinates of the InputOverlayDrawableButton on the InputOverlay.
|
// The X and Y coordinates of the InputOverlayDrawableButton on the InputOverlay.
|
||||||
// These were set in the input overlay configuration menu.
|
// These were set in the input overlay configuration menu.
|
||||||
val xKey = "$prefId-X$layout"
|
val xKey = "$buttonId-X$orientation"
|
||||||
val yKey = "$prefId-Y$layout"
|
val yKey = "$buttonId-Y$orientation"
|
||||||
val drawableXPercent = sPrefs.getFloat(xKey, 0f)
|
val drawableXPercent = sPrefs.getFloat(xKey, 0f)
|
||||||
val drawableYPercent = sPrefs.getFloat(yKey, 0f)
|
val drawableYPercent = sPrefs.getFloat(yKey, 0f)
|
||||||
val drawableX = (drawableXPercent * max.x + min.x).toInt()
|
val drawableX = (drawableXPercent * max.x + min.x).toInt()
|
||||||
@ -1146,8 +1029,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
|||||||
* @param defaultResId The [Bitmap] resource ID of the default state.
|
* @param defaultResId The [Bitmap] resource ID of the default state.
|
||||||
* @param pressedOneDirectionResId The [Bitmap] resource ID of the pressed state in one direction.
|
* @param pressedOneDirectionResId The [Bitmap] resource ID of the pressed state in one direction.
|
||||||
* @param pressedTwoDirectionsResId The [Bitmap] resource ID of the pressed state in two directions.
|
* @param pressedTwoDirectionsResId The [Bitmap] resource ID of the pressed state in two directions.
|
||||||
* @param layout The current screen layout as determined by [LANDSCAPE], [PORTRAIT], or [FOLDABLE].
|
* @return the initialized [InputOverlayDrawableDpad]
|
||||||
* @return The initialized [InputOverlayDrawableDpad]
|
|
||||||
*/
|
*/
|
||||||
private fun initializeOverlayDpad(
|
private fun initializeOverlayDpad(
|
||||||
context: Context,
|
context: Context,
|
||||||
@ -1155,7 +1037,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
|||||||
defaultResId: Int,
|
defaultResId: Int,
|
||||||
pressedOneDirectionResId: Int,
|
pressedOneDirectionResId: Int,
|
||||||
pressedTwoDirectionsResId: Int,
|
pressedTwoDirectionsResId: Int,
|
||||||
layout: String
|
orientation: String
|
||||||
): InputOverlayDrawableDpad {
|
): InputOverlayDrawableDpad {
|
||||||
// Resources handle for fetching the initial Drawable resource.
|
// Resources handle for fetching the initial Drawable resource.
|
||||||
val res = context.resources
|
val res = context.resources
|
||||||
@ -1192,8 +1074,8 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
|||||||
|
|
||||||
// The X and Y coordinates of the InputOverlayDrawableDpad on the InputOverlay.
|
// The X and Y coordinates of the InputOverlayDrawableDpad on the InputOverlay.
|
||||||
// These were set in the input overlay configuration menu.
|
// These were set in the input overlay configuration menu.
|
||||||
val drawableXPercent = sPrefs.getFloat("${Settings.PREF_BUTTON_DPAD}-X$layout", 0f)
|
val drawableXPercent = sPrefs.getFloat("${ButtonType.DPAD_UP}-X$orientation", 0f)
|
||||||
val drawableYPercent = sPrefs.getFloat("${Settings.PREF_BUTTON_DPAD}-Y$layout", 0f)
|
val drawableYPercent = sPrefs.getFloat("${ButtonType.DPAD_UP}-Y$orientation", 0f)
|
||||||
val drawableX = (drawableXPercent * max.x + min.x).toInt()
|
val drawableX = (drawableXPercent * max.x + min.x).toInt()
|
||||||
val drawableY = (drawableYPercent * max.y + min.y).toInt()
|
val drawableY = (drawableYPercent * max.y + min.y).toInt()
|
||||||
val width = overlayDrawable.width
|
val width = overlayDrawable.width
|
||||||
@ -1225,9 +1107,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
|||||||
* @param pressedResInner Resource ID for the pressed inner image of the joystick.
|
* @param pressedResInner Resource ID for the pressed inner image of the joystick.
|
||||||
* @param joystick Identifier for which joystick this is.
|
* @param joystick Identifier for which joystick this is.
|
||||||
* @param button Identifier for which joystick button this is.
|
* @param button Identifier for which joystick button this is.
|
||||||
* @param prefId Identifier for determining where a button appears on screen.
|
* @return the initialized [InputOverlayDrawableJoystick].
|
||||||
* @param layout The current screen layout as determined by [LANDSCAPE], [PORTRAIT], or [FOLDABLE].
|
|
||||||
* @return The initialized [InputOverlayDrawableJoystick].
|
|
||||||
*/
|
*/
|
||||||
private fun initializeOverlayJoystick(
|
private fun initializeOverlayJoystick(
|
||||||
context: Context,
|
context: Context,
|
||||||
@ -1237,8 +1117,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
|||||||
pressedResInner: Int,
|
pressedResInner: Int,
|
||||||
joystick: Int,
|
joystick: Int,
|
||||||
button: Int,
|
button: Int,
|
||||||
prefId: String,
|
orientation: String
|
||||||
layout: String
|
|
||||||
): InputOverlayDrawableJoystick {
|
): InputOverlayDrawableJoystick {
|
||||||
// Resources handle for fetching the initial Drawable resource.
|
// Resources handle for fetching the initial Drawable resource.
|
||||||
val res = context.resources
|
val res = context.resources
|
||||||
@ -1262,8 +1141,8 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
|||||||
|
|
||||||
// The X and Y coordinates of the InputOverlayDrawableButton on the InputOverlay.
|
// The X and Y coordinates of the InputOverlayDrawableButton on the InputOverlay.
|
||||||
// These were set in the input overlay configuration menu.
|
// These were set in the input overlay configuration menu.
|
||||||
val drawableXPercent = sPrefs.getFloat("$prefId-X$layout", 0f)
|
val drawableXPercent = sPrefs.getFloat("$button-X$orientation", 0f)
|
||||||
val drawableYPercent = sPrefs.getFloat("$prefId-Y$layout", 0f)
|
val drawableYPercent = sPrefs.getFloat("$button-Y$orientation", 0f)
|
||||||
val drawableX = (drawableXPercent * max.x + min.x).toInt()
|
val drawableX = (drawableXPercent * max.x + min.x).toInt()
|
||||||
val drawableY = (drawableYPercent * max.y + min.y).toInt()
|
val drawableY = (drawableYPercent * max.y + min.y).toInt()
|
||||||
val outerScale = 1.66f
|
val outerScale = 1.66f
|
||||||
@ -1289,8 +1168,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
|||||||
outerRect,
|
outerRect,
|
||||||
innerRect,
|
innerRect,
|
||||||
joystick,
|
joystick,
|
||||||
button,
|
button
|
||||||
prefId
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Need to set the image's position
|
// Need to set the image's position
|
||||||
|
@ -24,8 +24,7 @@ class InputOverlayDrawableButton(
|
|||||||
res: Resources,
|
res: Resources,
|
||||||
defaultStateBitmap: Bitmap,
|
defaultStateBitmap: Bitmap,
|
||||||
pressedStateBitmap: Bitmap,
|
pressedStateBitmap: Bitmap,
|
||||||
val buttonId: Int,
|
val buttonId: Int
|
||||||
val prefId: String
|
|
||||||
) {
|
) {
|
||||||
// The ID value what motion event is tracking
|
// The ID value what motion event is tracking
|
||||||
var trackId: Int
|
var trackId: Int
|
||||||
|
@ -37,8 +37,7 @@ class InputOverlayDrawableJoystick(
|
|||||||
rectOuter: Rect,
|
rectOuter: Rect,
|
||||||
rectInner: Rect,
|
rectInner: Rect,
|
||||||
val joystickId: Int,
|
val joystickId: Int,
|
||||||
val buttonId: Int,
|
val buttonId: Int
|
||||||
val prefId: String
|
|
||||||
) {
|
) {
|
||||||
// The ID value what motion event is tracking
|
// The ID value what motion event is tracking
|
||||||
var trackId = -1
|
var trackId = -1
|
||||||
|
@ -1,128 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:aapt="http://schemas.android.com/aapt"
|
|
||||||
android:width="34.963dp"
|
|
||||||
android:height="37.265dp"
|
|
||||||
android:viewportWidth="34.963"
|
|
||||||
android:viewportHeight="37.265">
|
|
||||||
<path
|
|
||||||
android:fillAlpha="0.5"
|
|
||||||
android:pathData="M19.451,19.024A3.498,3.498 0,0 0,21.165 19.508c1.336,0 1.749,-0.852 1.738,-1.49 0,-1.077 -0.982,-1.537 -1.987,-1.537L20.327,16.481L20.327,15.7L20.901,15.7c0.757,0 1.714,-0.392 1.714,-1.302C22.621,13.785 22.224,13.229 21.271,13.229a2.834,2.834 0,0 0,-1.537 0.529l-0.265,-0.757a3.662,3.662 0,0 1,2.008 -0.59c1.513,0 2.201,0.897 2.201,1.834 0,0.794 -0.474,1.466 -1.421,1.807l0,0.024c0.947,0.19 1.714,0.9 1.714,1.976C23.967,19.27 23.017,20.346 21.165,20.346a3.929,3.929 135,0 1,-1.998 -0.529z"
|
|
||||||
android:strokeAlpha="0.6">
|
|
||||||
<aapt:attr name="android:fillColor">
|
|
||||||
<gradient
|
|
||||||
android:endX="21.568"
|
|
||||||
android:endY="33.938"
|
|
||||||
android:startX="21.568"
|
|
||||||
android:startY="16.14"
|
|
||||||
android:type="linear">
|
|
||||||
<item
|
|
||||||
android:color="#FFC3C4C5"
|
|
||||||
android:offset="0" />
|
|
||||||
<item
|
|
||||||
android:color="#FFC5C6C6"
|
|
||||||
android:offset="0.03" />
|
|
||||||
<item
|
|
||||||
android:color="#FFC7C7C7"
|
|
||||||
android:offset="0.19" />
|
|
||||||
<item
|
|
||||||
android:color="#DBB5B5B5"
|
|
||||||
android:offset="0.44" />
|
|
||||||
<item
|
|
||||||
android:color="#7F878787"
|
|
||||||
android:offset="1" />
|
|
||||||
</gradient>
|
|
||||||
</aapt:attr>
|
|
||||||
</path>
|
|
||||||
<path
|
|
||||||
android:fillAlpha="0.5"
|
|
||||||
android:pathData="M16.062,9.353 L9.624,3.405A1.963,1.963 0,0 1,10.955 0l12.88,0a1.963,1.963 135,0 1,1.323 3.405L18.726,9.353a1.961,1.961 135,0 1,-2.664 0z"
|
|
||||||
android:strokeAlpha="0.6">
|
|
||||||
<aapt:attr name="android:fillColor">
|
|
||||||
<gradient
|
|
||||||
android:endX="17.395"
|
|
||||||
android:endY="18.74"
|
|
||||||
android:startX="17.395"
|
|
||||||
android:startY="-1.296"
|
|
||||||
android:type="linear">
|
|
||||||
<item
|
|
||||||
android:color="#FFC3C4C5"
|
|
||||||
android:offset="0" />
|
|
||||||
<item
|
|
||||||
android:color="#FFC5C6C6"
|
|
||||||
android:offset="0.03" />
|
|
||||||
<item
|
|
||||||
android:color="#FFC7C7C7"
|
|
||||||
android:offset="0.19" />
|
|
||||||
<item
|
|
||||||
android:color="#DBB5B5B5"
|
|
||||||
android:offset="0.44" />
|
|
||||||
<item
|
|
||||||
android:color="#7F878787"
|
|
||||||
android:offset="1" />
|
|
||||||
</gradient>
|
|
||||||
</aapt:attr>
|
|
||||||
</path>
|
|
||||||
<path
|
|
||||||
android:fillAlpha="0.5"
|
|
||||||
android:pathData="m25.79,5.657l0,0a2.09,2.09 45,0 0,0.23 3.262c3.522,2.402 4.762,5.927 4.741,10.52A13.279,13.279 135,0 1,4.206 19.365c0,-4.516 0.931,-7.71 4.374,-10.107a2.098,2.098 0,0 0,0.233 -3.265l0,0a2.101,2.101 135,0 0,-2.646 -0.169C1.433,9.133 -0.266,13.941 0.033,20.233a17.468,17.468 0,0 0,34.925 -0.868c0,-6.006 -1.971,-10.771 -6.585,-13.917a2.088,2.088 45,0 0,-2.582 0.209z"
|
|
||||||
android:strokeAlpha="0.6">
|
|
||||||
<aapt:attr name="android:fillColor">
|
|
||||||
<gradient
|
|
||||||
android:centerX="17.477"
|
|
||||||
android:centerY="19.92"
|
|
||||||
android:gradientRadius="17.201"
|
|
||||||
android:type="radial">
|
|
||||||
<item
|
|
||||||
android:color="#FFC3C4C5"
|
|
||||||
android:offset="0.58" />
|
|
||||||
<item
|
|
||||||
android:color="#FFC6C6C6"
|
|
||||||
android:offset="0.84" />
|
|
||||||
<item
|
|
||||||
android:color="#FFC7C7C7"
|
|
||||||
android:offset="0.88" />
|
|
||||||
<item
|
|
||||||
android:color="#FFC2C2C2"
|
|
||||||
android:offset="0.91" />
|
|
||||||
<item
|
|
||||||
android:color="#FFB5B5B5"
|
|
||||||
android:offset="0.94" />
|
|
||||||
<item
|
|
||||||
android:color="#FF9E9E9E"
|
|
||||||
android:offset="0.98" />
|
|
||||||
<item
|
|
||||||
android:color="#FF8F8F8F"
|
|
||||||
android:offset="1" />
|
|
||||||
</gradient>
|
|
||||||
</aapt:attr>
|
|
||||||
</path>
|
|
||||||
<path
|
|
||||||
android:fillAlpha="0.5"
|
|
||||||
android:pathData="m12.516,12.729l2,0l0,13.822l6.615,0l0,1.68L12.516,28.231Z"
|
|
||||||
android:strokeAlpha="0.6">
|
|
||||||
<aapt:attr name="android:fillColor">
|
|
||||||
<gradient
|
|
||||||
android:endX="16.829"
|
|
||||||
android:endY="46.882"
|
|
||||||
android:startX="16.829"
|
|
||||||
android:startY="20.479"
|
|
||||||
android:type="linear">
|
|
||||||
<item
|
|
||||||
android:color="#FFC3C4C5"
|
|
||||||
android:offset="0" />
|
|
||||||
<item
|
|
||||||
android:color="#FFC5C6C6"
|
|
||||||
android:offset="0.03" />
|
|
||||||
<item
|
|
||||||
android:color="#FFC7C7C7"
|
|
||||||
android:offset="0.19" />
|
|
||||||
<item
|
|
||||||
android:color="#DBB5B5B5"
|
|
||||||
android:offset="0.44" />
|
|
||||||
<item
|
|
||||||
android:color="#7F878787"
|
|
||||||
android:offset="1" />
|
|
||||||
</gradient>
|
|
||||||
</aapt:attr>
|
|
||||||
</path>
|
|
||||||
</vector>
|
|
@ -1,75 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:aapt="http://schemas.android.com/aapt"
|
|
||||||
android:width="34.963dp"
|
|
||||||
android:height="37.265dp"
|
|
||||||
android:viewportWidth="34.963"
|
|
||||||
android:viewportHeight="37.265">
|
|
||||||
<path
|
|
||||||
android:fillAlpha="0.3"
|
|
||||||
android:fillColor="#151515"
|
|
||||||
android:pathData="M16.062,9.353 L9.624,3.405A1.963,1.963 0,0 1,10.955 0l12.88,0a1.963,1.963 135,0 1,1.323 3.405L18.726,9.353a1.961,1.961 135,0 1,-2.664 0z"
|
|
||||||
android:strokeAlpha="0.3" />
|
|
||||||
<path
|
|
||||||
android:fillAlpha="0.6"
|
|
||||||
android:fillColor="#151515"
|
|
||||||
android:pathData="m25.79,5.657l0,0a2.09,2.09 45,0 0,0.23 3.262c3.522,2.402 4.762,5.927 4.741,10.52A13.279,13.279 135,0 1,4.206 19.365c0,-4.516 0.931,-7.71 4.374,-10.107a2.098,2.098 0,0 0,0.233 -3.265l0,0a2.101,2.101 135,0 0,-2.646 -0.169C1.433,9.133 -0.266,13.941 0.033,20.233a17.468,17.468 0,0 0,34.925 -0.868c0,-6.006 -1.971,-10.771 -6.585,-13.917a2.088,2.088 45,0 0,-2.582 0.209z"
|
|
||||||
android:strokeAlpha="0.6" />
|
|
||||||
<path
|
|
||||||
android:fillAlpha="0.6"
|
|
||||||
android:pathData="M19.451,19.024A3.498,3.498 0,0 0,21.165 19.508c1.336,0 1.749,-0.852 1.738,-1.49 0,-1.077 -0.982,-1.537 -1.987,-1.537L20.327,16.481L20.327,15.7L20.901,15.7c0.757,0 1.714,-0.392 1.714,-1.302C22.621,13.785 22.224,13.229 21.271,13.229a2.834,2.834 0,0 0,-1.537 0.529l-0.265,-0.757a3.662,3.662 0,0 1,2.008 -0.59c1.513,0 2.201,0.897 2.201,1.834 0,0.794 -0.474,1.466 -1.421,1.807l0,0.024c0.947,0.19 1.714,0.9 1.714,1.976C23.967,19.27 23.017,20.346 21.165,20.346a3.929,3.929 135,0 1,-1.998 -0.529z"
|
|
||||||
android:strokeAlpha="0.6">
|
|
||||||
<aapt:attr name="android:fillColor">
|
|
||||||
<gradient
|
|
||||||
android:endX="21.568"
|
|
||||||
android:endY="33.938"
|
|
||||||
android:startX="21.568"
|
|
||||||
android:startY="16.14"
|
|
||||||
android:type="linear">
|
|
||||||
<item
|
|
||||||
android:color="#FFC3C4C5"
|
|
||||||
android:offset="0" />
|
|
||||||
<item
|
|
||||||
android:color="#FFC5C6C6"
|
|
||||||
android:offset="0.03" />
|
|
||||||
<item
|
|
||||||
android:color="#FFC7C7C7"
|
|
||||||
android:offset="0.19" />
|
|
||||||
<item
|
|
||||||
android:color="#DBB5B5B5"
|
|
||||||
android:offset="0.44" />
|
|
||||||
<item
|
|
||||||
android:color="#7F878787"
|
|
||||||
android:offset="1" />
|
|
||||||
</gradient>
|
|
||||||
</aapt:attr>
|
|
||||||
</path>
|
|
||||||
<path
|
|
||||||
android:fillAlpha="0.6"
|
|
||||||
android:pathData="m12.516,12.729l2,0l0,13.822l6.615,0l0,1.68L12.516,28.231Z"
|
|
||||||
android:strokeAlpha="0.6">
|
|
||||||
<aapt:attr name="android:fillColor">
|
|
||||||
<gradient
|
|
||||||
android:endX="16.829"
|
|
||||||
android:endY="46.882"
|
|
||||||
android:startX="16.829"
|
|
||||||
android:startY="20.479"
|
|
||||||
android:type="linear">
|
|
||||||
<item
|
|
||||||
android:color="#FFC3C4C5"
|
|
||||||
android:offset="0" />
|
|
||||||
<item
|
|
||||||
android:color="#FFC5C6C6"
|
|
||||||
android:offset="0.03" />
|
|
||||||
<item
|
|
||||||
android:color="#FFC7C7C7"
|
|
||||||
android:offset="0.19" />
|
|
||||||
<item
|
|
||||||
android:color="#DBB5B5B5"
|
|
||||||
android:offset="0.44" />
|
|
||||||
<item
|
|
||||||
android:color="#7F878787"
|
|
||||||
android:offset="1" />
|
|
||||||
</gradient>
|
|
||||||
</aapt:attr>
|
|
||||||
</path>
|
|
||||||
</vector>
|
|
@ -1,128 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:aapt="http://schemas.android.com/aapt"
|
|
||||||
android:width="34.963dp"
|
|
||||||
android:height="37.265dp"
|
|
||||||
android:viewportWidth="34.963"
|
|
||||||
android:viewportHeight="37.265">
|
|
||||||
<path
|
|
||||||
android:fillAlpha="0.5"
|
|
||||||
android:pathData="m10.781,12.65a19.579,19.579 0,0 1,3.596 -0.302c2.003,0 3.294,0.368 4.199,1.185a3.622,3.622 0,0 1,1.14 2.757c0,1.916 -1.206,3.175 -2.733,3.704l0,0.063c1.119,0.386 1.786,1.421 2.117,2.929 0.474,2.024 0.818,3.424 1.119,3.982l-1.924,0c-0.238,-0.407 -0.561,-1.656 -0.968,-3.466 -0.431,-2.003 -1.206,-2.757 -2.91,-2.82l-1.762,0l0,6.286l-1.873,0zM12.654,19.264l1.916,0c2.003,0 3.273,-1.098 3.273,-2.757 0,-1.873 -1.357,-2.691 -3.336,-2.712a7.649,7.649 0,0 0,-1.852 0.172z"
|
|
||||||
android:strokeAlpha="0.6">
|
|
||||||
<aapt:attr name="android:fillColor">
|
|
||||||
<gradient
|
|
||||||
android:endX="15.506"
|
|
||||||
android:endY="48.977"
|
|
||||||
android:startX="15.506"
|
|
||||||
android:startY="19.659"
|
|
||||||
android:type="linear">
|
|
||||||
<item
|
|
||||||
android:color="#FFC3C4C5"
|
|
||||||
android:offset="0" />
|
|
||||||
<item
|
|
||||||
android:color="#FFC5C6C6"
|
|
||||||
android:offset="0.03" />
|
|
||||||
<item
|
|
||||||
android:color="#FFC7C7C7"
|
|
||||||
android:offset="0.19" />
|
|
||||||
<item
|
|
||||||
android:color="#DBB5B5B5"
|
|
||||||
android:offset="0.44" />
|
|
||||||
<item
|
|
||||||
android:color="#7F878787"
|
|
||||||
android:offset="1" />
|
|
||||||
</gradient>
|
|
||||||
</aapt:attr>
|
|
||||||
</path>
|
|
||||||
<path
|
|
||||||
android:fillAlpha="0.5"
|
|
||||||
android:pathData="M16.062,9.353 L9.624,3.405A1.963,1.963 0,0 1,10.955 0l12.88,0a1.963,1.963 135,0 1,1.323 3.405L18.726,9.353a1.961,1.961 135,0 1,-2.664 0z"
|
|
||||||
android:strokeAlpha="0.6">
|
|
||||||
<aapt:attr name="android:fillColor">
|
|
||||||
<gradient
|
|
||||||
android:endX="17.395"
|
|
||||||
android:endY="18.74"
|
|
||||||
android:startX="17.395"
|
|
||||||
android:startY="-1.296"
|
|
||||||
android:type="linear">
|
|
||||||
<item
|
|
||||||
android:color="#FFC3C4C5"
|
|
||||||
android:offset="0" />
|
|
||||||
<item
|
|
||||||
android:color="#FFC5C6C6"
|
|
||||||
android:offset="0.03" />
|
|
||||||
<item
|
|
||||||
android:color="#FFC7C7C7"
|
|
||||||
android:offset="0.19" />
|
|
||||||
<item
|
|
||||||
android:color="#DBB5B5B5"
|
|
||||||
android:offset="0.44" />
|
|
||||||
<item
|
|
||||||
android:color="#7F878787"
|
|
||||||
android:offset="1" />
|
|
||||||
</gradient>
|
|
||||||
</aapt:attr>
|
|
||||||
</path>
|
|
||||||
<path
|
|
||||||
android:fillAlpha="0.5"
|
|
||||||
android:pathData="m25.79,5.657l0,0a2.09,2.09 45,0 0,0.23 3.262c3.522,2.402 4.762,5.927 4.741,10.52A13.279,13.279 135,0 1,4.206 19.365c0,-4.516 0.931,-7.71 4.374,-10.107a2.098,2.098 0,0 0,0.233 -3.265l0,0a2.101,2.101 135,0 0,-2.646 -0.169C1.433,9.133 -0.266,13.941 0.033,20.233a17.468,17.468 0,0 0,34.925 -0.868c0,-6.006 -1.971,-10.771 -6.585,-13.917a2.088,2.088 45,0 0,-2.582 0.209z"
|
|
||||||
android:strokeAlpha="0.6">
|
|
||||||
<aapt:attr name="android:fillColor">
|
|
||||||
<gradient
|
|
||||||
android:centerX="17.477"
|
|
||||||
android:centerY="19.92"
|
|
||||||
android:gradientRadius="17.201"
|
|
||||||
android:type="radial">
|
|
||||||
<item
|
|
||||||
android:color="#FFC3C4C5"
|
|
||||||
android:offset="0.58" />
|
|
||||||
<item
|
|
||||||
android:color="#FFC6C6C6"
|
|
||||||
android:offset="0.84" />
|
|
||||||
<item
|
|
||||||
android:color="#FFC7C7C7"
|
|
||||||
android:offset="0.88" />
|
|
||||||
<item
|
|
||||||
android:color="#FFC2C2C2"
|
|
||||||
android:offset="0.91" />
|
|
||||||
<item
|
|
||||||
android:color="#FFB5B5B5"
|
|
||||||
android:offset="0.94" />
|
|
||||||
<item
|
|
||||||
android:color="#FF9E9E9E"
|
|
||||||
android:offset="0.98" />
|
|
||||||
<item
|
|
||||||
android:color="#FF8F8F8F"
|
|
||||||
android:offset="1" />
|
|
||||||
</gradient>
|
|
||||||
</aapt:attr>
|
|
||||||
</path>
|
|
||||||
<path
|
|
||||||
android:fillAlpha="0.5"
|
|
||||||
android:pathData="M21.832,19.024A3.498,3.498 0,0 0,23.547 19.508c1.336,0 1.749,-0.852 1.738,-1.49 0,-1.077 -0.982,-1.537 -1.987,-1.537L22.708,16.481L22.708,15.7L23.282,15.7c0.757,0 1.714,-0.392 1.714,-1.302C25.002,13.785 24.605,13.229 23.652,13.229a2.834,2.834 0,0 0,-1.537 0.529l-0.265,-0.757a3.662,3.662 0,0 1,2.008 -0.59c1.513,0 2.201,0.897 2.201,1.834 0,0.794 -0.474,1.466 -1.421,1.807l0,0.024c0.947,0.19 1.714,0.9 1.714,1.976C26.349,19.27 25.399,20.346 23.547,20.346a3.929,3.929 135,0 1,-1.998 -0.529z"
|
|
||||||
android:strokeAlpha="0.6">
|
|
||||||
<aapt:attr name="android:fillColor">
|
|
||||||
<gradient
|
|
||||||
android:endX="23.949"
|
|
||||||
android:endY="33.938"
|
|
||||||
android:startX="23.949"
|
|
||||||
android:startY="16.14"
|
|
||||||
android:type="linear">
|
|
||||||
<item
|
|
||||||
android:color="#FFC3C4C5"
|
|
||||||
android:offset="0" />
|
|
||||||
<item
|
|
||||||
android:color="#FFC5C6C6"
|
|
||||||
android:offset="0.03" />
|
|
||||||
<item
|
|
||||||
android:color="#FFC7C7C7"
|
|
||||||
android:offset="0.19" />
|
|
||||||
<item
|
|
||||||
android:color="#DBB5B5B5"
|
|
||||||
android:offset="0.44" />
|
|
||||||
<item
|
|
||||||
android:color="#7F878787"
|
|
||||||
android:offset="1" />
|
|
||||||
</gradient>
|
|
||||||
</aapt:attr>
|
|
||||||
</path>
|
|
||||||
</vector>
|
|
@ -1,75 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:aapt="http://schemas.android.com/aapt"
|
|
||||||
android:width="34.963dp"
|
|
||||||
android:height="37.265dp"
|
|
||||||
android:viewportWidth="34.963"
|
|
||||||
android:viewportHeight="37.265">
|
|
||||||
<path
|
|
||||||
android:fillAlpha="0.3"
|
|
||||||
android:fillColor="#151515"
|
|
||||||
android:pathData="M16.062,9.353 L9.624,3.405A1.963,1.963 0,0 1,10.955 0l12.88,0a1.963,1.963 135,0 1,1.323 3.405L18.726,9.353a1.961,1.961 135,0 1,-2.664 0z"
|
|
||||||
android:strokeAlpha="0.3" />
|
|
||||||
<path
|
|
||||||
android:fillAlpha="0.6"
|
|
||||||
android:fillColor="#151515"
|
|
||||||
android:pathData="m25.79,5.657l0,0a2.09,2.09 45,0 0,0.23 3.262c3.522,2.402 4.762,5.927 4.741,10.52A13.279,13.279 135,0 1,4.206 19.365c0,-4.516 0.931,-7.71 4.374,-10.107a2.098,2.098 0,0 0,0.233 -3.265l0,0a2.101,2.101 135,0 0,-2.646 -0.169C1.433,9.133 -0.266,13.941 0.033,20.233a17.468,17.468 0,0 0,34.925 -0.868c0,-6.006 -1.971,-10.771 -6.585,-13.917a2.088,2.088 45,0 0,-2.582 0.209z"
|
|
||||||
android:strokeAlpha="0.6" />
|
|
||||||
<path
|
|
||||||
android:fillAlpha="0.6"
|
|
||||||
android:pathData="m10.781,12.65a19.579,19.579 0,0 1,3.596 -0.302c2.003,0 3.294,0.368 4.199,1.185a3.622,3.622 0,0 1,1.14 2.757c0,1.916 -1.206,3.175 -2.733,3.704l0,0.063c1.119,0.386 1.786,1.421 2.117,2.929 0.474,2.024 0.818,3.424 1.119,3.982l-1.924,0c-0.238,-0.407 -0.561,-1.656 -0.968,-3.466 -0.431,-2.003 -1.206,-2.757 -2.91,-2.82l-1.762,0l0,6.286l-1.873,0zM12.654,19.264l1.916,0c2.003,0 3.273,-1.098 3.273,-2.757 0,-1.873 -1.357,-2.691 -3.336,-2.712a7.649,7.649 0,0 0,-1.852 0.172z"
|
|
||||||
android:strokeAlpha="0.6">
|
|
||||||
<aapt:attr name="android:fillColor">
|
|
||||||
<gradient
|
|
||||||
android:endX="15.506"
|
|
||||||
android:endY="48.977"
|
|
||||||
android:startX="15.506"
|
|
||||||
android:startY="19.659"
|
|
||||||
android:type="linear">
|
|
||||||
<item
|
|
||||||
android:color="#FFC3C4C5"
|
|
||||||
android:offset="0" />
|
|
||||||
<item
|
|
||||||
android:color="#FFC5C6C6"
|
|
||||||
android:offset="0.03" />
|
|
||||||
<item
|
|
||||||
android:color="#FFC7C7C7"
|
|
||||||
android:offset="0.19" />
|
|
||||||
<item
|
|
||||||
android:color="#DBB5B5B5"
|
|
||||||
android:offset="0.44" />
|
|
||||||
<item
|
|
||||||
android:color="#7F878787"
|
|
||||||
android:offset="1" />
|
|
||||||
</gradient>
|
|
||||||
</aapt:attr>
|
|
||||||
</path>
|
|
||||||
<path
|
|
||||||
android:fillAlpha="0.6"
|
|
||||||
android:pathData="M21.832,19.024A3.498,3.498 0,0 0,23.547 19.508c1.336,0 1.749,-0.852 1.738,-1.49 0,-1.077 -0.982,-1.537 -1.987,-1.537L22.708,16.481L22.708,15.7L23.282,15.7c0.757,0 1.714,-0.392 1.714,-1.302C25.002,13.785 24.605,13.229 23.652,13.229a2.834,2.834 0,0 0,-1.537 0.529l-0.265,-0.757a3.662,3.662 0,0 1,2.008 -0.59c1.513,0 2.201,0.897 2.201,1.834 0,0.794 -0.474,1.466 -1.421,1.807l0,0.024c0.947,0.19 1.714,0.9 1.714,1.976C26.349,19.27 25.399,20.346 23.547,20.346a3.929,3.929 135,0 1,-1.998 -0.529z"
|
|
||||||
android:strokeAlpha="0.6">
|
|
||||||
<aapt:attr name="android:fillColor">
|
|
||||||
<gradient
|
|
||||||
android:endX="23.949"
|
|
||||||
android:endY="33.938"
|
|
||||||
android:startX="23.949"
|
|
||||||
android:startY="16.14"
|
|
||||||
android:type="linear">
|
|
||||||
<item
|
|
||||||
android:color="#FFC3C4C5"
|
|
||||||
android:offset="0" />
|
|
||||||
<item
|
|
||||||
android:color="#FFC5C6C6"
|
|
||||||
android:offset="0.03" />
|
|
||||||
<item
|
|
||||||
android:color="#FFC7C7C7"
|
|
||||||
android:offset="0.19" />
|
|
||||||
<item
|
|
||||||
android:color="#DBB5B5B5"
|
|
||||||
android:offset="0.44" />
|
|
||||||
<item
|
|
||||||
android:color="#7F878787"
|
|
||||||
android:offset="1" />
|
|
||||||
</gradient>
|
|
||||||
</aapt:attr>
|
|
||||||
</path>
|
|
||||||
</vector>
|
|
@ -205,8 +205,6 @@
|
|||||||
<item>@string/gamepad_d_pad</item>
|
<item>@string/gamepad_d_pad</item>
|
||||||
<item>@string/gamepad_left_stick</item>
|
<item>@string/gamepad_left_stick</item>
|
||||||
<item>@string/gamepad_right_stick</item>
|
<item>@string/gamepad_right_stick</item>
|
||||||
<item>L3</item>
|
|
||||||
<item>R3</item>
|
|
||||||
<item>@string/gamepad_home</item>
|
<item>@string/gamepad_home</item>
|
||||||
<item>@string/gamepad_screenshot</item>
|
<item>@string/gamepad_screenshot</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
@ -33,10 +33,6 @@
|
|||||||
<integer name="SWITCH_BUTTON_CAPTURE_Y">950</integer>
|
<integer name="SWITCH_BUTTON_CAPTURE_Y">950</integer>
|
||||||
<integer name="SWITCH_BUTTON_DPAD_X">260</integer>
|
<integer name="SWITCH_BUTTON_DPAD_X">260</integer>
|
||||||
<integer name="SWITCH_BUTTON_DPAD_Y">790</integer>
|
<integer name="SWITCH_BUTTON_DPAD_Y">790</integer>
|
||||||
<integer name="SWITCH_BUTTON_STICK_L_X">870</integer>
|
|
||||||
<integer name="SWITCH_BUTTON_STICK_L_Y">400</integer>
|
|
||||||
<integer name="SWITCH_BUTTON_STICK_R_X">960</integer>
|
|
||||||
<integer name="SWITCH_BUTTON_STICK_R_Y">430</integer>
|
|
||||||
|
|
||||||
<!-- Default SWITCH portrait layout -->
|
<!-- Default SWITCH portrait layout -->
|
||||||
<integer name="SWITCH_BUTTON_A_X_PORTRAIT">840</integer>
|
<integer name="SWITCH_BUTTON_A_X_PORTRAIT">840</integer>
|
||||||
@ -69,10 +65,6 @@
|
|||||||
<integer name="SWITCH_BUTTON_CAPTURE_Y_PORTRAIT">950</integer>
|
<integer name="SWITCH_BUTTON_CAPTURE_Y_PORTRAIT">950</integer>
|
||||||
<integer name="SWITCH_BUTTON_DPAD_X_PORTRAIT">240</integer>
|
<integer name="SWITCH_BUTTON_DPAD_X_PORTRAIT">240</integer>
|
||||||
<integer name="SWITCH_BUTTON_DPAD_Y_PORTRAIT">840</integer>
|
<integer name="SWITCH_BUTTON_DPAD_Y_PORTRAIT">840</integer>
|
||||||
<integer name="SWITCH_BUTTON_STICK_L_X_PORTRAIT">730</integer>
|
|
||||||
<integer name="SWITCH_BUTTON_STICK_L_Y_PORTRAIT">510</integer>
|
|
||||||
<integer name="SWITCH_BUTTON_STICK_R_X_PORTRAIT">900</integer>
|
|
||||||
<integer name="SWITCH_BUTTON_STICK_R_Y_PORTRAIT">540</integer>
|
|
||||||
|
|
||||||
<!-- Default SWITCH foldable layout -->
|
<!-- Default SWITCH foldable layout -->
|
||||||
<integer name="SWITCH_BUTTON_A_X_FOLDABLE">840</integer>
|
<integer name="SWITCH_BUTTON_A_X_FOLDABLE">840</integer>
|
||||||
@ -105,9 +97,5 @@
|
|||||||
<integer name="SWITCH_BUTTON_CAPTURE_Y_FOLDABLE">470</integer>
|
<integer name="SWITCH_BUTTON_CAPTURE_Y_FOLDABLE">470</integer>
|
||||||
<integer name="SWITCH_BUTTON_DPAD_X_FOLDABLE">240</integer>
|
<integer name="SWITCH_BUTTON_DPAD_X_FOLDABLE">240</integer>
|
||||||
<integer name="SWITCH_BUTTON_DPAD_Y_FOLDABLE">390</integer>
|
<integer name="SWITCH_BUTTON_DPAD_Y_FOLDABLE">390</integer>
|
||||||
<integer name="SWITCH_BUTTON_STICK_L_X_FOLDABLE">550</integer>
|
|
||||||
<integer name="SWITCH_BUTTON_STICK_L_Y_FOLDABLE">210</integer>
|
|
||||||
<integer name="SWITCH_BUTTON_STICK_R_X_FOLDABLE">550</integer>
|
|
||||||
<integer name="SWITCH_BUTTON_STICK_R_Y_FOLDABLE">280</integer>
|
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -14,11 +14,21 @@ constexpr Result VibrationInvalidStyleIndex{ErrorModule::HID, 122};
|
|||||||
constexpr Result VibrationInvalidNpadId{ErrorModule::HID, 123};
|
constexpr Result VibrationInvalidNpadId{ErrorModule::HID, 123};
|
||||||
constexpr Result VibrationDeviceIndexOutOfRange{ErrorModule::HID, 124};
|
constexpr Result VibrationDeviceIndexOutOfRange{ErrorModule::HID, 124};
|
||||||
constexpr Result InvalidSixAxisFusionRange{ErrorModule::HID, 423};
|
constexpr Result InvalidSixAxisFusionRange{ErrorModule::HID, 423};
|
||||||
|
|
||||||
|
constexpr Result ResultMcuInvalidHandle{ErrorModule::HID, 541};
|
||||||
|
constexpr Result ResultMcuNotEnabled{ErrorModule::HID, 542};
|
||||||
|
constexpr Result ResultMcuNoDeviceConnected{ErrorModule::HID, 543};
|
||||||
|
constexpr Result ResultMcuUnknown544{ErrorModule::HID, 544};
|
||||||
|
constexpr Result ResultMcuUnknown546{ErrorModule::HID, 546};
|
||||||
|
constexpr Result ResultMcuUnknown548{ErrorModule::HID, 548};
|
||||||
|
|
||||||
constexpr Result NpadIsDualJoycon{ErrorModule::HID, 601};
|
constexpr Result NpadIsDualJoycon{ErrorModule::HID, 601};
|
||||||
constexpr Result NpadIsSameType{ErrorModule::HID, 602};
|
constexpr Result NpadIsSameType{ErrorModule::HID, 602};
|
||||||
constexpr Result InvalidNpadId{ErrorModule::HID, 709};
|
constexpr Result InvalidNpadId{ErrorModule::HID, 709};
|
||||||
constexpr Result NpadNotConnected{ErrorModule::HID, 710};
|
constexpr Result NpadNotConnected{ErrorModule::HID, 710};
|
||||||
constexpr Result InvalidArraySize{ErrorModule::HID, 715};
|
constexpr Result InvalidArraySize{ErrorModule::HID, 715};
|
||||||
|
|
||||||
|
constexpr Result ResultControllerUpdateFailed{ErrorModule::HID, 3201};
|
||||||
constexpr Result InvalidPalmaHandle{ErrorModule::HID, 3302};
|
constexpr Result InvalidPalmaHandle{ErrorModule::HID, 3302};
|
||||||
|
|
||||||
} // namespace Service::HID
|
} // namespace Service::HID
|
||||||
@ -29,3 +39,17 @@ constexpr Result InvalidProcessorState{ErrorModule::Irsensor, 78};
|
|||||||
constexpr Result InvalidIrCameraHandle{ErrorModule::Irsensor, 204};
|
constexpr Result InvalidIrCameraHandle{ErrorModule::Irsensor, 204};
|
||||||
|
|
||||||
} // namespace Service::IRS
|
} // namespace Service::IRS
|
||||||
|
|
||||||
|
namespace Service::HIDBUS {
|
||||||
|
|
||||||
|
constexpr Result ResultNotEnabled{ErrorModule::HIDBUS, 1};
|
||||||
|
constexpr Result ResultControllerUpdateFailed{ErrorModule::HIDBUS, 3};
|
||||||
|
constexpr Result ResultInvalidBusHandle{ErrorModule::HIDBUS, 4};
|
||||||
|
constexpr Result ResultNoDeviceConnected{ErrorModule::HIDBUS, 5};
|
||||||
|
constexpr Result ResultUknown6{ErrorModule::HIDBUS, 6};
|
||||||
|
constexpr Result ResultPollingRecieveDataNotAvailable{ErrorModule::HIDBUS, 7};
|
||||||
|
constexpr Result ResultDeviceEnabledNotSet{ErrorModule::HIDBUS, 8};
|
||||||
|
constexpr Result ResultBusHandleAlreadyInitialized{ErrorModule::HIDBUS, 10};
|
||||||
|
constexpr Result ResultInvalidBusType{ErrorModule::HIDBUS, 11};
|
||||||
|
|
||||||
|
} // namespace Service::HIDBUS
|
||||||
|
@ -10,6 +10,8 @@
|
|||||||
#include "core/hle/kernel/k_readable_event.h"
|
#include "core/hle/kernel/k_readable_event.h"
|
||||||
#include "core/hle/kernel/k_shared_memory.h"
|
#include "core/hle/kernel/k_shared_memory.h"
|
||||||
#include "core/hle/kernel/k_transfer_memory.h"
|
#include "core/hle/kernel/k_transfer_memory.h"
|
||||||
|
#include "core/hle/service/hid/controllers/npad.h"
|
||||||
|
#include "core/hle/service/hid/errors.h"
|
||||||
#include "core/hle/service/hid/hidbus.h"
|
#include "core/hle/service/hid/hidbus.h"
|
||||||
#include "core/hle/service/hid/hidbus/ringcon.h"
|
#include "core/hle/service/hid/hidbus/ringcon.h"
|
||||||
#include "core/hle/service/hid/hidbus/starlink.h"
|
#include "core/hle/service/hid/hidbus/starlink.h"
|
||||||
@ -64,25 +66,7 @@ HidBus::~HidBus() {
|
|||||||
system.CoreTiming().UnscheduleEvent(hidbus_update_event, 0);
|
system.CoreTiming().UnscheduleEvent(hidbus_update_event, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HidBus::UpdateHidbus(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
|
void HidBus::UpdateHidbus(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {}
|
||||||
if (is_hidbus_enabled) {
|
|
||||||
for (std::size_t i = 0; i < devices.size(); ++i) {
|
|
||||||
if (!devices[i].is_device_initializated) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
auto& device = devices[i].device;
|
|
||||||
device->OnUpdate();
|
|
||||||
auto& cur_entry = hidbus_status.entries[devices[i].handle.internal_index];
|
|
||||||
cur_entry.is_polling_mode = device->IsPollingMode();
|
|
||||||
cur_entry.polling_mode = device->GetPollingMode();
|
|
||||||
cur_entry.is_enabled = device->IsEnabled();
|
|
||||||
|
|
||||||
u8* shared_memory = system.Kernel().GetHidBusSharedMem().GetPointer();
|
|
||||||
std::memcpy(shared_memory + (i * sizeof(HidbusStatusManagerEntry)), &hidbus_status,
|
|
||||||
sizeof(HidbusStatusManagerEntry));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<std::size_t> HidBus::GetDeviceIndexFromHandle(BusHandle handle) const {
|
std::optional<std::size_t> HidBus::GetDeviceIndexFromHandle(BusHandle handle) const {
|
||||||
for (std::size_t i = 0; i < devices.size(); ++i) {
|
for (std::size_t i = 0; i < devices.size(); ++i) {
|
||||||
@ -108,45 +92,6 @@ void HidBus::GetBusHandle(HLERequestContext& ctx) {
|
|||||||
};
|
};
|
||||||
static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
|
static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
|
||||||
|
|
||||||
const auto parameters{rp.PopRaw<Parameters>()};
|
|
||||||
|
|
||||||
LOG_INFO(Service_HID, "called, npad_id={}, bus_type={}, applet_resource_user_id={}",
|
|
||||||
parameters.npad_id, parameters.bus_type, parameters.applet_resource_user_id);
|
|
||||||
|
|
||||||
bool is_handle_found = 0;
|
|
||||||
std::size_t handle_index = 0;
|
|
||||||
|
|
||||||
for (std::size_t i = 0; i < devices.size(); i++) {
|
|
||||||
const auto& handle = devices[i].handle;
|
|
||||||
if (!handle.is_valid) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (static_cast<Core::HID::NpadIdType>(handle.player_number) == parameters.npad_id &&
|
|
||||||
handle.bus_type_id == static_cast<u8>(parameters.bus_type)) {
|
|
||||||
is_handle_found = true;
|
|
||||||
handle_index = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle not found. Create a new one
|
|
||||||
if (!is_handle_found) {
|
|
||||||
for (std::size_t i = 0; i < devices.size(); i++) {
|
|
||||||
if (devices[i].handle.is_valid) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
devices[i].handle = {
|
|
||||||
.abstracted_pad_id = static_cast<u8>(i),
|
|
||||||
.internal_index = static_cast<u8>(i),
|
|
||||||
.player_number = static_cast<u8>(parameters.npad_id),
|
|
||||||
.bus_type_id = static_cast<u8>(parameters.bus_type),
|
|
||||||
.is_valid = true,
|
|
||||||
};
|
|
||||||
handle_index = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct OutData {
|
struct OutData {
|
||||||
bool is_valid;
|
bool is_valid;
|
||||||
INSERT_PADDING_BYTES(7);
|
INSERT_PADDING_BYTES(7);
|
||||||
@ -154,16 +99,158 @@ void HidBus::GetBusHandle(HLERequestContext& ctx) {
|
|||||||
};
|
};
|
||||||
static_assert(sizeof(OutData) == 0x10, "OutData has incorrect size.");
|
static_assert(sizeof(OutData) == 0x10, "OutData has incorrect size.");
|
||||||
|
|
||||||
const OutData out_data{
|
const auto parameters{rp.PopRaw<Parameters>()};
|
||||||
.is_valid = true,
|
|
||||||
.handle = devices[handle_index].handle,
|
LOG_INFO(Service_HID, "called, npad_id={}, bus_type={}, applet_resource_user_id={}",
|
||||||
};
|
parameters.npad_id, parameters.bus_type, parameters.applet_resource_user_id);
|
||||||
|
|
||||||
|
if (parameters.bus_type >= BusType::MaxBusType) {
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(HIDBUS::ResultInvalidBusType);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
OutData out_data{};
|
||||||
|
out_data.is_valid = GetBusHandleImpl(out_data.handle, parameters.npad_id, parameters.bus_type);
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 6};
|
IPC::ResponseBuilder rb{ctx, 6};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushRaw(out_data);
|
rb.PushRaw(out_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool HidBus::GetBusHandleImpl(BusHandle& handle, Core::HID::NpadIdType npad_id,
|
||||||
|
BusType bus_type) const {
|
||||||
|
if (!Controller_NPad::IsNpadIdValid(npad_id)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MakeBusHandle(handle, npad_id, bus_type).IsError()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bus_type == BusType::LeftJoyRail || bus_type == BusType::RightJoyRail) {
|
||||||
|
// TODO: IsBusHandleValid(*npad_id,bus_type)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bus_type == BusType::InternalBus) {
|
||||||
|
// TODO: IsBusHandleValid(*npad_id,BusType::RightJoyRail)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result HidBus::MakeBusHandle(BusHandle& handle, Core::HID::NpadIdType npad_id,
|
||||||
|
BusType bus_type) const {
|
||||||
|
u32 abstracted_pad_id{};
|
||||||
|
const Result result = GetAbstractedHidbusPadId(abstracted_pad_id, npad_id, bus_type);
|
||||||
|
|
||||||
|
if (result.IsError()) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 internal_index = static_cast<u8>(npad_id);
|
||||||
|
if (bus_type < BusType::MaxBusType) {
|
||||||
|
internal_index = internal_index << 1 | 1;
|
||||||
|
}
|
||||||
|
if (bus_type == BusType::LeftJoyRail) {
|
||||||
|
internal_index = internal_index << 1;
|
||||||
|
}
|
||||||
|
if (npad_id == Core::HID::NpadIdType::Handheld) {
|
||||||
|
switch (bus_type) {
|
||||||
|
case BusType::LeftJoyRail:
|
||||||
|
internal_index = 0x10;
|
||||||
|
break;
|
||||||
|
case BusType::InternalBus:
|
||||||
|
internal_index = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
internal_index = 0x11;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handle = {
|
||||||
|
.abstracted_pad_id = abstracted_pad_id,
|
||||||
|
.internal_index = internal_index,
|
||||||
|
.player_number = static_cast<u8>(npad_id) && 0xff,
|
||||||
|
.bus_type_id = static_cast<u8>(bus_type) && 0xff,
|
||||||
|
.is_valid = true, // This is hardcoded on the sysmodule
|
||||||
|
};
|
||||||
|
return ResultSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result HidBus::GetAbstractedHidbusPadId(u32& abstracted_pad_id, Core::HID::NpadIdType npad_id,
|
||||||
|
BusType bus_type) const {
|
||||||
|
// This struct is unknown
|
||||||
|
struct LeftData {
|
||||||
|
std::array<u8, 4> data;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ControllerData {
|
||||||
|
u32 data_1;
|
||||||
|
u32 data_2;
|
||||||
|
u32 is_connected; // ((d + 0x8) >> 1 & 1)
|
||||||
|
u32 abstracted_pad_id;
|
||||||
|
u32 data_5;
|
||||||
|
u32 data_6;
|
||||||
|
u32 data_7;
|
||||||
|
u32 data_8;
|
||||||
|
LeftData left_data;
|
||||||
|
u32 right_data;
|
||||||
|
u32 data_11;
|
||||||
|
u32 data_12;
|
||||||
|
u32 data_13;
|
||||||
|
u32 has_battery; // ((d + 0x3a) & 6) ((d + 0x38) & 0x60000)
|
||||||
|
u32 data_15;
|
||||||
|
u32 data_16;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(ControllerData) == 0x40, "ControllerData has incorrect size.");
|
||||||
|
|
||||||
|
// auto& controller = GetControllerFromNpadIdType(npad_id);
|
||||||
|
const std::array<ControllerData, 5> data_pointer{}; // controller->GetControllerData(5);
|
||||||
|
|
||||||
|
if (data_pointer.size() == 0) {
|
||||||
|
return ResultMcuInvalidHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const ControllerData& data : data_pointer) {
|
||||||
|
bool is_valid = false;
|
||||||
|
switch (bus_type) {
|
||||||
|
case BusType::LeftJoyRail:
|
||||||
|
if ((data.left_data.data[3] >> 1 & 1) != 0) {
|
||||||
|
is_valid = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BusType::RightJoyRail: {
|
||||||
|
if (((data.right_data >> 9 & 1) == 0) && ((data.right_data >> 10 & 1) != 0)) {
|
||||||
|
is_valid = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case BusType::InternalBus:
|
||||||
|
if ((data.right_data & 0xe00) == 0x800) {
|
||||||
|
is_valid = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_valid) {
|
||||||
|
abstracted_pad_id = data.abstracted_pad_id;
|
||||||
|
return ResultSuccess;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// STUB this function for now
|
||||||
|
abstracted_pad_id = static_cast<u32>(npad_id);
|
||||||
|
return ResultSuccess;
|
||||||
|
|
||||||
|
return ResultMcuInvalidHandle;
|
||||||
|
}
|
||||||
|
|
||||||
void HidBus::IsExternalDeviceConnected(HLERequestContext& ctx) {
|
void HidBus::IsExternalDeviceConnected(HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
const auto bus_handle_{rp.PopRaw<BusHandle>()};
|
const auto bus_handle_{rp.PopRaw<BusHandle>()};
|
||||||
|
@ -95,6 +95,10 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
void GetBusHandle(HLERequestContext& ctx);
|
void GetBusHandle(HLERequestContext& ctx);
|
||||||
|
bool GetBusHandleImpl(BusHandle& handle, Core::HID::NpadIdType npad_id, BusType bus_type) const;
|
||||||
|
Result MakeBusHandle(BusHandle& handle, Core::HID::NpadIdType npad_id, BusType bus_type) const;
|
||||||
|
Result GetAbstractedHidbusPadId(u32& abstracted_pad_id, Core::HID::NpadIdType npad_id,
|
||||||
|
BusType bus_type) const;
|
||||||
void IsExternalDeviceConnected(HLERequestContext& ctx);
|
void IsExternalDeviceConnected(HLERequestContext& ctx);
|
||||||
void Initialize(HLERequestContext& ctx);
|
void Initialize(HLERequestContext& ctx);
|
||||||
void Finalize(HLERequestContext& ctx);
|
void Finalize(HLERequestContext& ctx);
|
||||||
|
@ -160,9 +160,8 @@ void Mouse::Move(int x, int y, int center_x, int center_y) {
|
|||||||
last_mouse_change.y += mouse_change.y * y_sensitivity;
|
last_mouse_change.y += mouse_change.y * y_sensitivity;
|
||||||
|
|
||||||
// Bind the mouse change to [0 <= deadzone_counterweight <= 1.0]
|
// Bind the mouse change to [0 <= deadzone_counterweight <= 1.0]
|
||||||
const float length = last_mouse_change.Length();
|
if (last_mouse_change.Length() < deadzone_counterweight) {
|
||||||
if (length < deadzone_counterweight && length != 0.0f) {
|
last_mouse_change /= last_mouse_change.Length();
|
||||||
last_mouse_change /= length;
|
|
||||||
last_mouse_change *= deadzone_counterweight;
|
last_mouse_change *= deadzone_counterweight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ Common::Input::DriverResult JoyconDriver::InitializeDevice() {
|
|||||||
passive_enabled = false;
|
passive_enabled = false;
|
||||||
irs_enabled = false;
|
irs_enabled = false;
|
||||||
input_only_device = false;
|
input_only_device = false;
|
||||||
gyro_sensitivity = Joycon::GyroSensitivity::DPS2000;
|
gyro_sensitivity = Joycon::GyroSensitivity::DPS250;
|
||||||
gyro_performance = Joycon::GyroPerformance::HZ833;
|
gyro_performance = Joycon::GyroPerformance::HZ833;
|
||||||
accelerometer_sensitivity = Joycon::AccelerometerSensitivity::G8;
|
accelerometer_sensitivity = Joycon::AccelerometerSensitivity::G8;
|
||||||
accelerometer_performance = Joycon::AccelerometerPerformance::HZ100;
|
accelerometer_performance = Joycon::AccelerometerPerformance::HZ100;
|
||||||
@ -172,34 +172,94 @@ void JoyconDriver::InputThread(std::stop_token stop_token) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void JoyconDriver::OnNewData(std::span<u8> buffer) {
|
void JoyconDriver::OnNewData(std::span<u8> buffer) {
|
||||||
const u8 report_mode_byte = buffer[0];
|
|
||||||
const auto report_mode = static_cast<ReportMode>(buffer[0]);
|
const auto report_mode = static_cast<ReportMode>(buffer[0]);
|
||||||
|
std::string str = "";
|
||||||
if (report_mode_byte > 0x33 || ((1L << report_mode_byte) & 0xf000a00000000U) == 0) {
|
for (u8 dat : buffer) {
|
||||||
// ParceUSBMode();
|
str += fmt::format("{:02x} ", dat);
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 motion_samples = 0;
|
LOG_CRITICAL(Input, "{}", str);
|
||||||
if (motion_enabled) {
|
|
||||||
// Packages can be a little bit inconsistent. Average the delta time to provide a smoother
|
// Packages can be a little bit inconsistent. Average the delta time to provide a smoother
|
||||||
// motion experience
|
// motion experience
|
||||||
|
switch (report_mode) {
|
||||||
|
case ReportMode::STANDARD_FULL_60HZ:
|
||||||
|
case ReportMode::NFC_IR_MODE_60HZ:
|
||||||
|
case ReportMode::SIMPLE_HID_MODE: {
|
||||||
const auto now = std::chrono::steady_clock::now();
|
const auto now = std::chrono::steady_clock::now();
|
||||||
const auto new_delta_time = static_cast<u64>(
|
const auto new_delta_time = static_cast<u64>(
|
||||||
std::chrono::duration_cast<std::chrono::microseconds>(now - last_update).count());
|
std::chrono::duration_cast<std::chrono::microseconds>(now - last_update).count());
|
||||||
delta_time = ((delta_time * 8) + (new_delta_time * 2)) / 10;
|
delta_time = ((delta_time * 8) + (new_delta_time * 2)) / 10;
|
||||||
last_update = now;
|
last_update = now;
|
||||||
motion_samples = 3;
|
joycon_poller->UpdateColor(color);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (irs_enabled) {
|
const MotionStatus motion_status{
|
||||||
motion_samples = 2;
|
.is_enabled = motion_enabled,
|
||||||
|
.delta_time = delta_time,
|
||||||
|
.gyro_sensitivity = gyro_sensitivity,
|
||||||
|
.accelerometer_sensitivity = accelerometer_sensitivity,
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: Remove this when calibration is properly loaded and not calculated
|
||||||
|
if (ring_connected && report_mode == ReportMode::STANDARD_FULL_60HZ) {
|
||||||
|
InputReportActive data{};
|
||||||
|
memcpy(&data, buffer.data(), sizeof(InputReportActive));
|
||||||
|
//calibration_protocol->GetRingCalibration(ring_calibration, data.ring_input);
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool is_not_reply_or_state =
|
const RingStatus ring_status{
|
||||||
report_mode != ReportMode::SUBCMD_REPLY && report_mode != ReportMode::MCU_UPDATE_STATE;
|
.is_enabled = ring_connected,
|
||||||
|
.default_value = ring_calibration.default_value,
|
||||||
|
.max_value = ring_calibration.max_value,
|
||||||
|
.min_value = ring_calibration.min_value,
|
||||||
|
};
|
||||||
|
|
||||||
joycon_poller->ReadActiveMode(buffer, motion);
|
if (irs_protocol->IsEnabled()) {
|
||||||
|
irs_protocol->RequestImage(buffer);
|
||||||
|
joycon_poller->UpdateCamera(irs_protocol->GetImage(), irs_protocol->GetIrsFormat());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nfc_protocol->IsPolling()) {
|
||||||
|
if (amiibo_detected) {
|
||||||
|
if (!nfc_protocol->HasAmiibo()) {
|
||||||
|
joycon_poller->UpdateAmiibo({});
|
||||||
|
amiibo_detected = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!amiibo_detected) {
|
||||||
|
Joycon::TagInfo tag_info;
|
||||||
|
const auto result = nfc_protocol->GetTagInfo(tag_info);
|
||||||
|
if (result == Common::Input::DriverResult::Success) {
|
||||||
|
joycon_poller->UpdateAmiibo(tag_info);
|
||||||
|
amiibo_detected = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (report_mode) {
|
||||||
|
case ReportMode::STANDARD_FULL_60HZ:
|
||||||
|
joycon_poller->ReadActiveMode(buffer, motion_status, ring_status);
|
||||||
|
break;
|
||||||
|
case ReportMode::NFC_IR_MODE_60HZ:
|
||||||
|
joycon_poller->ReadNfcIRMode(buffer, motion_status);
|
||||||
|
break;
|
||||||
|
case ReportMode::SIMPLE_HID_MODE:
|
||||||
|
joycon_poller->ReadPassiveMode(buffer);
|
||||||
|
break;
|
||||||
|
case ReportMode::SUBCMD_REPLY:
|
||||||
|
LOG_DEBUG(Input, "Unhandled command reply");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOG_ERROR(Input, "Report mode not Implemented {}", report_mode);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Common::Input::DriverResult JoyconDriver::SetPollingMode() {
|
Common::Input::DriverResult JoyconDriver::SetPollingMode() {
|
||||||
@ -210,8 +270,8 @@ Common::Input::DriverResult JoyconDriver::SetPollingMode() {
|
|||||||
|
|
||||||
if (motion_enabled && supported_features.motion) {
|
if (motion_enabled && supported_features.motion) {
|
||||||
generic_protocol->EnableImu(true);
|
generic_protocol->EnableImu(true);
|
||||||
generic_protocol->SetImuConfig(gyro_sensitivity, gyro_performance,
|
//generic_protocol->SetImuConfig(gyro_sensitivity, gyro_performance,
|
||||||
accelerometer_sensitivity, accelerometer_performance);
|
// accelerometer_sensitivity, accelerometer_performance);
|
||||||
} else {
|
} else {
|
||||||
generic_protocol->EnableImu(false);
|
generic_protocol->EnableImu(false);
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ Common::Input::DriverResult GenericProtocol::GetControllerType(ControllerType& c
|
|||||||
|
|
||||||
Common::Input::DriverResult GenericProtocol::EnableImu(bool enable) {
|
Common::Input::DriverResult GenericProtocol::EnableImu(bool enable) {
|
||||||
ScopedSetBlocking sb(this);
|
ScopedSetBlocking sb(this);
|
||||||
const std::array<u8, 1> buffer{static_cast<u8>(enable ? 1 : 0)};
|
const std::array<u8, 1> buffer{static_cast<u8>(enable ? 3 : 0)};
|
||||||
return SendSubCommand(SubCommand::ENABLE_IMU, buffer);
|
return SendSubCommand(SubCommand::ENABLE_IMU, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -528,11 +528,9 @@ struct InputReportActive {
|
|||||||
std::array<u8, 3> left_stick_state;
|
std::array<u8, 3> left_stick_state;
|
||||||
std::array<u8, 3> right_stick_state;
|
std::array<u8, 3> right_stick_state;
|
||||||
u8 vibration_code;
|
u8 vibration_code;
|
||||||
std::array<s16, 6 * 2> motion_input;
|
std::array<s16, 6 * 3> motion_input;
|
||||||
INSERT_PADDING_BYTES(0x2);
|
|
||||||
s16 ring_input;
|
|
||||||
};
|
};
|
||||||
static_assert(sizeof(InputReportActive) == 0x29, "InputReportActive is an invalid size");
|
static_assert(sizeof(InputReportActive) > 0x29, "InputReportActive is an invalid size");
|
||||||
|
|
||||||
struct InputReportNfcIr {
|
struct InputReportNfcIr {
|
||||||
ReportMode report_mode;
|
ReportMode report_mode;
|
||||||
|
@ -16,13 +16,6 @@ void JoyconPoller::SetCallbacks(const JoyconCallbacks& callbacks_) {
|
|||||||
callbacks = std::move(callbacks_);
|
callbacks = std::move(callbacks_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void JoyconPoller::ReadButtonAndMotionInput(std::span<u8> buffer, const MotionStatus& motion_status,
|
|
||||||
std::size_t motion_samples, bool is_not_reply_or_state) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void JoyconPoller::ReadActiveMode(std::span<u8> buffer, const MotionStatus& motion_status,
|
void JoyconPoller::ReadActiveMode(std::span<u8> buffer, const MotionStatus& motion_status,
|
||||||
const RingStatus& ring_status) {
|
const RingStatus& ring_status) {
|
||||||
InputReportActive data{};
|
InputReportActive data{};
|
||||||
@ -43,7 +36,7 @@ void JoyconPoller::ReadActiveMode(std::span<u8> buffer, const MotionStatus& moti
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ring_status.is_enabled) {
|
if (ring_status.is_enabled) {
|
||||||
UpdateRing(data.ring_input, ring_status);
|
// UpdateRing(data.ring_input, ring_status);
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks.on_battery_data(data.battery_status);
|
callbacks.on_battery_data(data.battery_status);
|
||||||
@ -354,14 +347,18 @@ s16 JoyconPoller::GetRawIMUValues(std::size_t sensor, size_t axis,
|
|||||||
MotionData JoyconPoller::GetMotionInput(const InputReportActive& input,
|
MotionData JoyconPoller::GetMotionInput(const InputReportActive& input,
|
||||||
const MotionStatus& motion_status) const {
|
const MotionStatus& motion_status) const {
|
||||||
MotionData motion{};
|
MotionData motion{};
|
||||||
|
for (int i = 0; i < 1; i++) {
|
||||||
const auto& accel_cal = motion_calibration.accelerometer;
|
const auto& accel_cal = motion_calibration.accelerometer;
|
||||||
const auto& gyro_cal = motion_calibration.gyro;
|
const auto& gyro_cal = motion_calibration.gyro;
|
||||||
const s16 raw_accel_x = input.motion_input[1];
|
const s16 raw_accel_x = input.motion_input[1 + (i*6)];
|
||||||
const s16 raw_accel_y = input.motion_input[0];
|
const s16 raw_accel_y = input.motion_input[0 + (i * 6)];
|
||||||
const s16 raw_accel_z = input.motion_input[2];
|
const s16 raw_accel_z = input.motion_input[2 + (i * 6)];
|
||||||
const s16 raw_gyro_x = input.motion_input[4];
|
const s16 raw_gyro_x = input.motion_input[4 + (i * 6)];
|
||||||
const s16 raw_gyro_y = input.motion_input[3];
|
const s16 raw_gyro_y = input.motion_input[3 + (i * 6)];
|
||||||
const s16 raw_gyro_z = input.motion_input[5];
|
const s16 raw_gyro_z = input.motion_input[5 + (i * 6)];
|
||||||
|
|
||||||
|
LOG_WARNING(Input, "raw sample{}, accel ({},{},{}), gyro ({},{},{})", i, raw_accel_x, raw_accel_y, raw_accel_z,
|
||||||
|
raw_gyro_x, raw_gyro_y, raw_gyro_z);
|
||||||
|
|
||||||
motion.delta_timestamp = motion_status.delta_time;
|
motion.delta_timestamp = motion_status.delta_time;
|
||||||
motion.accel_x =
|
motion.accel_x =
|
||||||
@ -374,6 +371,10 @@ MotionData JoyconPoller::GetMotionInput(const InputReportActive& input,
|
|||||||
motion.gyro_y = GetGyroValue(raw_gyro_y, gyro_cal[0], motion_status.gyro_sensitivity);
|
motion.gyro_y = GetGyroValue(raw_gyro_y, gyro_cal[0], motion_status.gyro_sensitivity);
|
||||||
motion.gyro_z = GetGyroValue(raw_gyro_z, gyro_cal[2], motion_status.gyro_sensitivity);
|
motion.gyro_z = GetGyroValue(raw_gyro_z, gyro_cal[2], motion_status.gyro_sensitivity);
|
||||||
|
|
||||||
|
|
||||||
|
LOG_ERROR(Input, "calibrated samples{}, accel ({},{},{}), gyro ({},{},{})", i, motion.accel_x, motion.accel_y,
|
||||||
|
motion.accel_z, motion.gyro_x, motion.gyro_y, motion.gyro_z);
|
||||||
|
}
|
||||||
// TODO(German77): Return all three samples data
|
// TODO(German77): Return all three samples data
|
||||||
return motion;
|
return motion;
|
||||||
}
|
}
|
||||||
|
@ -24,10 +24,6 @@ public:
|
|||||||
|
|
||||||
void SetCallbacks(const JoyconCallbacks& callbacks_);
|
void SetCallbacks(const JoyconCallbacks& callbacks_);
|
||||||
|
|
||||||
/// Handles data from active packages
|
|
||||||
void ReadButtonAndMotionInput(std::span<u8> buffer, const MotionStatus& motion_status,
|
|
||||||
std::size_t motion_samples, bool is_not_reply_or_state);
|
|
||||||
|
|
||||||
/// Handles data from passive packages
|
/// Handles data from passive packages
|
||||||
void ReadPassiveMode(std::span<u8> buffer);
|
void ReadPassiveMode(std::span<u8> buffer);
|
||||||
|
|
||||||
|
@ -598,10 +598,6 @@ void TextureCache<P>::UnmapGPUMemory(size_t as_id, GPUVAddr gpu_addr, size_t siz
|
|||||||
[&](ImageId id, Image&) { deleted_images.push_back(id); });
|
[&](ImageId id, Image&) { deleted_images.push_back(id); });
|
||||||
for (const ImageId id : deleted_images) {
|
for (const ImageId id : deleted_images) {
|
||||||
Image& image = slot_images[id];
|
Image& image = slot_images[id];
|
||||||
if (True(image.flags & ImageFlagBits::CpuModified)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
image.flags |= ImageFlagBits::CpuModified;
|
|
||||||
if (True(image.flags & ImageFlagBits::Remapped)) {
|
if (True(image.flags & ImageFlagBits::Remapped)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -485,7 +485,7 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
|||||||
loaded_extensions.erase(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
|
loaded_extensions.erase(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (extensions.extended_dynamic_state2 && is_radv) {
|
if (extensions.extended_dynamic_state2 && (is_radv || is_qualcomm)) {
|
||||||
const u32 version = (properties.properties.driverVersion << 3) >> 3;
|
const u32 version = (properties.properties.driverVersion << 3) >> 3;
|
||||||
if (version < VK_MAKE_API_VERSION(0, 22, 3, 1)) {
|
if (version < VK_MAKE_API_VERSION(0, 22, 3, 1)) {
|
||||||
LOG_WARNING(
|
LOG_WARNING(
|
||||||
@ -498,20 +498,6 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
|||||||
loaded_extensions.erase(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
|
loaded_extensions.erase(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (extensions.extended_dynamic_state2 && is_qualcomm) {
|
|
||||||
const u32 version = (properties.properties.driverVersion << 3) >> 3;
|
|
||||||
if (version >= VK_MAKE_API_VERSION(0, 0, 676, 0) &&
|
|
||||||
version < VK_MAKE_API_VERSION(0, 0, 680, 0)) {
|
|
||||||
// Qualcomm Adreno 7xx drivers do not properly support extended_dynamic_state2.
|
|
||||||
LOG_WARNING(Render_Vulkan,
|
|
||||||
"Qualcomm Adreno 7xx drivers have broken VK_EXT_extended_dynamic_state2");
|
|
||||||
features.extended_dynamic_state2.extendedDynamicState2 = false;
|
|
||||||
features.extended_dynamic_state2.extendedDynamicState2LogicOp = false;
|
|
||||||
features.extended_dynamic_state2.extendedDynamicState2PatchControlPoints = false;
|
|
||||||
extensions.extended_dynamic_state2 = false;
|
|
||||||
loaded_extensions.erase(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (extensions.extended_dynamic_state3 && is_radv) {
|
if (extensions.extended_dynamic_state3 && is_radv) {
|
||||||
LOG_WARNING(Render_Vulkan, "RADV has broken extendedDynamicState3ColorBlendEquation");
|
LOG_WARNING(Render_Vulkan, "RADV has broken extendedDynamicState3ColorBlendEquation");
|
||||||
features.extended_dynamic_state3.extendedDynamicState3ColorBlendEnable = false;
|
features.extended_dynamic_state3.extendedDynamicState3ColorBlendEnable = false;
|
||||||
@ -526,7 +512,8 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
|||||||
dynamic_state3_enables = false;
|
dynamic_state3_enables = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (extensions.vertex_input_dynamic_state && is_radv) {
|
if (extensions.vertex_input_dynamic_state && (is_radv || is_qualcomm)) {
|
||||||
|
// Qualcomm S8gen2 drivers do not properly support vertex_input_dynamic_state.
|
||||||
// TODO(ameerj): Blacklist only offending driver versions
|
// TODO(ameerj): Blacklist only offending driver versions
|
||||||
// TODO(ameerj): Confirm if RDNA1 is affected
|
// TODO(ameerj): Confirm if RDNA1 is affected
|
||||||
const bool is_rdna2 =
|
const bool is_rdna2 =
|
||||||
@ -539,19 +526,6 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
|||||||
loaded_extensions.erase(VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
|
loaded_extensions.erase(VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (extensions.vertex_input_dynamic_state && is_qualcomm) {
|
|
||||||
const u32 version = (properties.properties.driverVersion << 3) >> 3;
|
|
||||||
if (version >= VK_MAKE_API_VERSION(0, 0, 676, 0) &&
|
|
||||||
version < VK_MAKE_API_VERSION(0, 0, 680, 0)) {
|
|
||||||
// Qualcomm Adreno 7xx drivers do not properly support vertex_input_dynamic_state.
|
|
||||||
LOG_WARNING(
|
|
||||||
Render_Vulkan,
|
|
||||||
"Qualcomm Adreno 7xx drivers have broken VK_EXT_vertex_input_dynamic_state");
|
|
||||||
features.vertex_input_dynamic_state.vertexInputDynamicState = false;
|
|
||||||
extensions.vertex_input_dynamic_state = false;
|
|
||||||
loaded_extensions.erase(VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sets_per_pool = 64;
|
sets_per_pool = 64;
|
||||||
if (extensions.extended_dynamic_state3 && is_amd_driver &&
|
if (extensions.extended_dynamic_state3 && is_amd_driver &&
|
||||||
@ -800,17 +774,6 @@ bool Device::ShouldBoostClocks() const {
|
|||||||
return validated_driver && !is_steam_deck && !is_debugging;
|
return validated_driver && !is_steam_deck && !is_debugging;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Device::HasTimelineSemaphore() const {
|
|
||||||
if (GetDriverID() == VK_DRIVER_ID_QUALCOMM_PROPRIETARY ||
|
|
||||||
GetDriverID() == VK_DRIVER_ID_MESA_TURNIP) {
|
|
||||||
// Timeline semaphores do not work properly on all Qualcomm drivers.
|
|
||||||
// They generally work properly with Turnip drivers, but are problematic on some devices
|
|
||||||
// (e.g. ZTE handsets with Snapdragon 870).
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return features.timeline_semaphore.timelineSemaphore;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Device::GetSuitability(bool requires_swapchain) {
|
bool Device::GetSuitability(bool requires_swapchain) {
|
||||||
// Assume we will be suitable.
|
// Assume we will be suitable.
|
||||||
bool suitable = true;
|
bool suitable = true;
|
||||||
|
@ -528,7 +528,13 @@ public:
|
|||||||
return extensions.shader_atomic_int64;
|
return extensions.shader_atomic_int64;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HasTimelineSemaphore() const;
|
bool HasTimelineSemaphore() const {
|
||||||
|
if (GetDriverID() == VK_DRIVER_ID_QUALCOMM_PROPRIETARY) {
|
||||||
|
// Timeline semaphores do not work properly on all Qualcomm drivers.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return features.timeline_semaphore.timelineSemaphore;
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the minimum supported version of SPIR-V.
|
/// Returns the minimum supported version of SPIR-V.
|
||||||
u32 SupportedSpirvVersion() const {
|
u32 SupportedSpirvVersion() const {
|
||||||
|
@ -221,8 +221,8 @@ vk::Image MemoryAllocator::CreateImage(const VkImageCreateInfo& ci) const {
|
|||||||
const VmaAllocationCreateInfo alloc_ci = {
|
const VmaAllocationCreateInfo alloc_ci = {
|
||||||
.flags = VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT,
|
.flags = VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT,
|
||||||
.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE,
|
.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE,
|
||||||
.requiredFlags = 0,
|
.requiredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||||
.preferredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
.preferredFlags = 0,
|
||||||
.memoryTypeBits = 0,
|
.memoryTypeBits = 0,
|
||||||
.pool = VK_NULL_HANDLE,
|
.pool = VK_NULL_HANDLE,
|
||||||
.pUserData = nullptr,
|
.pUserData = nullptr,
|
||||||
|
@ -454,7 +454,7 @@ GMainWindow::GMainWindow(std::unique_ptr<Config> config_, bool has_broken_vulkan
|
|||||||
// the user through their desktop environment.
|
// the user through their desktop environment.
|
||||||
//: TRANSLATORS: This string is shown to the user to explain why yuzu needs to prevent the
|
//: TRANSLATORS: This string is shown to the user to explain why yuzu needs to prevent the
|
||||||
//: computer from sleeping
|
//: computer from sleeping
|
||||||
QByteArray wakelock_reason = tr("Running a game").toUtf8();
|
QByteArray wakelock_reason = tr("Running a game").toLatin1();
|
||||||
SDL_SetHint(SDL_HINT_SCREENSAVER_INHIBIT_ACTIVITY_NAME, wakelock_reason.data());
|
SDL_SetHint(SDL_HINT_SCREENSAVER_INHIBIT_ACTIVITY_NAME, wakelock_reason.data());
|
||||||
|
|
||||||
// SDL disables the screen saver by default, and setting the hint
|
// SDL disables the screen saver by default, and setting the hint
|
||||||
|
Reference in New Issue
Block a user