Compare commits
73 commits
v0.2.0-rc2
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c95cb8f8ec | ||
|
|
3d0eb4b5d7 | ||
|
|
1b4a79c7ee | ||
|
|
c05d999225 | ||
|
|
71d3dd67d3 | ||
|
|
9b2fba1275 | ||
|
|
19eab4d7aa | ||
|
|
50a6f331cf | ||
|
|
9c13c71da8 | ||
|
|
7d53849cd3 | ||
|
|
fd0c5655c4 | ||
|
|
88f0e7862a | ||
|
|
d99a8c65cc | ||
|
|
876884e783 | ||
|
|
028050cf04 | ||
|
|
1f787ffc39 | ||
|
|
148dc7b480 | ||
|
|
612a203ab2 | ||
|
|
5e927199c5 | ||
|
|
ac99ea96da | ||
|
|
d1b7824443 | ||
|
|
34fa39eae8 | ||
|
|
9ace6742d7 | ||
|
|
79f29abcba | ||
|
|
3ce5463d2d | ||
|
|
cae70c30fa | ||
|
|
bcceced96d | ||
|
|
82e374f66c | ||
|
|
6e76014824 | ||
|
|
bb71ace365 | ||
|
|
21f9db1c27 | ||
|
|
b4a485e244 | ||
|
|
81a344f3db | ||
|
|
c0fbb2526d | ||
|
|
c3afd2fabd | ||
|
|
ee2891c55e | ||
|
|
dd91b41a78 | ||
|
|
e9f4541069 | ||
|
|
cf7086de7c | ||
|
|
8e14f07a69 | ||
|
|
0b179517b3 | ||
|
|
7a8176f63f | ||
|
|
5322bce4b8 | ||
|
|
276dcdd8ea | ||
|
|
59254cd1e7 | ||
|
|
9a3af3a6a3 | ||
|
|
b473c18d6e | ||
|
|
c984c387d7 | ||
|
|
5856beac54 | ||
|
|
16e7e034d7 | ||
|
|
47c6a73971 | ||
|
|
813a35abca | ||
|
|
93472023e2 | ||
|
|
9cb7001656 | ||
|
|
f0d77e86e3 | ||
|
|
24fe223692 | ||
|
|
8f770618d2 | ||
|
|
b673dad40d | ||
|
|
56d3f0e353 | ||
|
|
ad58ab8976 | ||
|
|
772e38cb8d | ||
|
|
811cc18d74 | ||
|
|
c5b519380c | ||
|
|
5ebdb29afd | ||
|
|
96e177702e | ||
|
|
844e0360c7 | ||
|
|
2650d22057 | ||
|
|
dc27aef542 | ||
|
|
cf860c5319 | ||
|
|
f1aa790545 | ||
|
|
c41209f137 | ||
|
|
ad7aea4863 | ||
|
|
af554c0baa |
22
.ci/actool.sh
Executable file
|
|
@ -0,0 +1,22 @@
|
||||||
|
#!/bin/sh -e
|
||||||
|
|
||||||
|
# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
# SPDX-FileCopyrightText: Copyright 2026 crueter
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
_svg=dev.eden_emu.eden.svg
|
||||||
|
_icon=dist/eden.icon
|
||||||
|
_composed="$_icon/Assets/$_svg"
|
||||||
|
_svg="dist/$_svg"
|
||||||
|
|
||||||
|
rm "$_composed"
|
||||||
|
cp "$_svg" "$_composed"
|
||||||
|
|
||||||
|
xcrun actool "$_icon" \
|
||||||
|
--compile dist \
|
||||||
|
--platform macosx \
|
||||||
|
--minimum-deployment-target 11.0 \
|
||||||
|
--app-icon eden \
|
||||||
|
--output-partial-info-plist /dev/null
|
||||||
|
|
@ -1,10 +1,9 @@
|
||||||
name: tx-pull
|
name: tx-pull
|
||||||
|
|
||||||
on:
|
on:
|
||||||
# monday, wednesday, saturday at 2pm
|
# tuesday, saturday at 2pm
|
||||||
schedule:
|
schedule:
|
||||||
cron:
|
- cron: '0 14 * * 2,6'
|
||||||
- '0 14 * * 1,3,6'
|
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|
@ -59,4 +58,3 @@ jobs:
|
||||||
-H 'Authorization: Bearer ${{ secrets.CI_FJ_TOKEN }}' \
|
-H 'Authorization: Bearer ${{ secrets.CI_FJ_TOKEN }}' \
|
||||||
-H 'Content-Type: application/json' \
|
-H 'Content-Type: application/json' \
|
||||||
-d "@data.json" --fail
|
-d "@data.json" --fail
|
||||||
|
|
||||||
54
.forgejo/workflows/update-deps.yml
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
name: update-deps
|
||||||
|
|
||||||
|
on:
|
||||||
|
# saturday at noon
|
||||||
|
schedule:
|
||||||
|
- cron: '0 12 * * 6'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
tx-update:
|
||||||
|
runs-on: source
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Update deps
|
||||||
|
run: |
|
||||||
|
git config --local user.name "Eden CI"
|
||||||
|
git config --local user.email "ci@eden-emu.dev"
|
||||||
|
git config --local user.signingkey "D57652791BB25D2A"
|
||||||
|
git config --local push.autoSetupRemote true
|
||||||
|
|
||||||
|
git remote set-url origin ci:eden-emu/eden.git
|
||||||
|
|
||||||
|
DATE=$(date +"%b %d")
|
||||||
|
echo "DATE=$DATE" >> "$GITHUB_ENV"
|
||||||
|
|
||||||
|
git switch -c update-deps-$DATE
|
||||||
|
tools/cpmutil.sh package update -ac
|
||||||
|
git push
|
||||||
|
|
||||||
|
- name: Create PR
|
||||||
|
run: |
|
||||||
|
TITLE="[externals] Dependency update for $DATE"
|
||||||
|
BODY="$(git show -s --format='%b')"
|
||||||
|
BASE=master
|
||||||
|
HEAD=update-deps-$DATE
|
||||||
|
|
||||||
|
cat << EOF > data.json
|
||||||
|
{
|
||||||
|
"base": "$BASE",
|
||||||
|
"body": "$BODY",
|
||||||
|
"head": "$HEAD",
|
||||||
|
"title": "$TITLE"
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
curl -X 'POST' \
|
||||||
|
'https://git.eden-emu.dev/api/v1/repos/eden-emu/eden/pulls' \
|
||||||
|
-H 'accept: application/json' \
|
||||||
|
-H 'Authorization: Bearer ${{ secrets.CI_FJ_TOKEN }}' \
|
||||||
|
-H 'Content-Type: application/json' \
|
||||||
|
-d "@data.json" --fail
|
||||||
|
|
@ -1,55 +0,0 @@
|
||||||
diff --git a/include/mcl/assert.hpp b/include/mcl/assert.hpp
|
|
||||||
index f77dbe7..9ec0b9c 100644
|
|
||||||
--- a/include/mcl/assert.hpp
|
|
||||||
+++ b/include/mcl/assert.hpp
|
|
||||||
@@ -23,8 +23,11 @@ template<typename... Ts>
|
|
||||||
|
|
||||||
} // namespace mcl::detail
|
|
||||||
|
|
||||||
+#ifndef UNREACHABLE
|
|
||||||
#define UNREACHABLE() ASSERT_FALSE("Unreachable code!")
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
+#ifndef ASSERT
|
|
||||||
#define ASSERT(expr) \
|
|
||||||
[&] { \
|
|
||||||
if (std::is_constant_evaluated()) { \
|
|
||||||
@@ -37,7 +40,9 @@ template<typename... Ts>
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
}()
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
+#ifndef ASSERT_MSG
|
|
||||||
#define ASSERT_MSG(expr, ...) \
|
|
||||||
[&] { \
|
|
||||||
if (std::is_constant_evaluated()) { \
|
|
||||||
@@ -50,13 +55,24 @@ template<typename... Ts>
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
}()
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
+#ifndef ASSERT_FALSE
|
|
||||||
#define ASSERT_FALSE(...) ::mcl::detail::assert_terminate("false", __VA_ARGS__)
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
#if defined(NDEBUG) || defined(MCL_IGNORE_ASSERTS)
|
|
||||||
-# define DEBUG_ASSERT(expr) ASSUME(expr)
|
|
||||||
-# define DEBUG_ASSERT_MSG(expr, ...) ASSUME(expr)
|
|
||||||
+# ifndef DEBUG_ASSERT
|
|
||||||
+# define DEBUG_ASSERT(expr) ASSUME(expr)
|
|
||||||
+# endif
|
|
||||||
+# ifndef DEBUG_ASSERT_MSG
|
|
||||||
+# define DEBUG_ASSERT_MSG(expr, ...) ASSUME(expr)
|
|
||||||
+# endif
|
|
||||||
#else
|
|
||||||
-# define DEBUG_ASSERT(expr) ASSERT(expr)
|
|
||||||
-# define DEBUG_ASSERT_MSG(expr, ...) ASSERT_MSG(expr, __VA_ARGS__)
|
|
||||||
+# ifndef DEBUG_ASSERT
|
|
||||||
+# define DEBUG_ASSERT(expr) ASSERT(expr)
|
|
||||||
+# endif
|
|
||||||
+# ifndef DEBUG_ASSERT_MSG
|
|
||||||
+# define DEBUG_ASSERT_MSG(expr, ...) ASSERT_MSG(expr, __VA_ARGS__)
|
|
||||||
+# endif
|
|
||||||
#endif
|
|
||||||
|
|
@ -143,8 +143,8 @@ if (MSVC AND ARCHITECTURE_x86)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (CXX_CLANG_CL)
|
if (CXX_CLANG_CL)
|
||||||
|
# clang-cl prints literally 10000+ warnings without this
|
||||||
add_compile_options(
|
add_compile_options(
|
||||||
# clang-cl prints literally 10000+ warnings without this
|
|
||||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-unused-command-line-argument>
|
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-unused-command-line-argument>
|
||||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-unsafe-buffer-usage>
|
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-unsafe-buffer-usage>
|
||||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-unused-value>
|
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-unused-value>
|
||||||
|
|
@ -154,12 +154,12 @@ if (CXX_CLANG_CL)
|
||||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-deprecated-declarations>
|
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-deprecated-declarations>
|
||||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-cast-function-type-mismatch>
|
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-cast-function-type-mismatch>
|
||||||
$<$<COMPILE_LANGUAGE:C,CXX>:/EHsc>)
|
$<$<COMPILE_LANGUAGE:C,CXX>:/EHsc>)
|
||||||
|
|
||||||
# REQUIRED CPU features IN Windows-amd64
|
# REQUIRED CPU features IN Windows-amd64
|
||||||
if (ARCHITECTURE_x86_64)
|
if (ARCHITECTURE_x86_64)
|
||||||
add_compile_options(
|
add_compile_options(
|
||||||
$<$<COMPILE_LANGUAGE:C,CXX>:-msse4.1>
|
$<$<COMPILE_LANGUAGE:C,CXX>:-msse4.1>
|
||||||
$<$<COMPILE_LANGUAGE:C,CXX>:-mcx16>)
|
$<$<COMPILE_LANGUAGE:C,CXX>:-mcx16>
|
||||||
|
)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
@ -395,13 +395,15 @@ if (Boost_ADDED)
|
||||||
if (NOT MSVC OR CXX_CLANG)
|
if (NOT MSVC OR CXX_CLANG)
|
||||||
# boost sucks
|
# boost sucks
|
||||||
if (PLATFORM_SUN)
|
if (PLATFORM_SUN)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthreads")
|
add_compile_options($<$<COMPILE_LANGUAGE:C,CXX>:-pthreads>)
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthreads")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_compile_options(boost_heap INTERFACE -Wno-shadow)
|
target_compile_options(boost_heap INTERFACE $<$<COMPILE_LANGUAGE:C,CXX>:-Wno-shadow>)
|
||||||
target_compile_options(boost_icl INTERFACE -Wno-shadow)
|
target_compile_options(boost_icl INTERFACE $<$<COMPILE_LANGUAGE:C,CXX>:-Wno-shadow>)
|
||||||
target_compile_options(boost_asio INTERFACE -Wno-conversion -Wno-implicit-fallthrough)
|
target_compile_options(boost_asio INTERFACE
|
||||||
|
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-conversion>
|
||||||
|
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-implicit-fallthrough>
|
||||||
|
)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
@ -440,7 +442,7 @@ if (NOT YUZU_STATIC_ROOM)
|
||||||
if (Opus_ADDED)
|
if (Opus_ADDED)
|
||||||
if (MSVC AND CXX_CLANG)
|
if (MSVC AND CXX_CLANG)
|
||||||
target_compile_options(opus PRIVATE
|
target_compile_options(opus PRIVATE
|
||||||
-Wno-implicit-function-declaration
|
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-implicit-function-declaration>
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
@ -484,10 +486,10 @@ endfunction()
|
||||||
# =============================================
|
# =============================================
|
||||||
|
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
# Umbrella framework for everything GUI-related
|
foreach(fw Carbon Metal Cocoa IOKit CoreVideo CoreMedia)
|
||||||
find_library(COCOA_LIBRARY Cocoa REQUIRED)
|
find_library(${fw}_LIBRARY ${fw} REQUIRED)
|
||||||
find_library(IOKIT_LIBRARY IOKit REQUIRED)
|
list(APPEND PLATFORM_LIBRARIES ${${fw}_LIBRARY})
|
||||||
set(PLATFORM_LIBRARIES ${COCOA_LIBRARY} ${IOKIT_LIBRARY} ${COREVIDEO_LIBRARY})
|
endforeach()
|
||||||
elseif (WIN32)
|
elseif (WIN32)
|
||||||
# Target Windows 10
|
# Target Windows 10
|
||||||
add_compile_definitions(_WIN32_WINNT=0x0A00 WINVER=0x0A00)
|
add_compile_definitions(_WIN32_WINNT=0x0A00 WINVER=0x0A00)
|
||||||
|
|
@ -524,7 +526,6 @@ if (NOT YUZU_STATIC_ROOM)
|
||||||
find_package(SPIRV-Tools)
|
find_package(SPIRV-Tools)
|
||||||
find_package(sirit)
|
find_package(sirit)
|
||||||
find_package(gamemode)
|
find_package(gamemode)
|
||||||
find_package(mcl)
|
|
||||||
find_package(frozen)
|
find_package(frozen)
|
||||||
|
|
||||||
if (ARCHITECTURE_riscv64)
|
if (ARCHITECTURE_riscv64)
|
||||||
|
|
|
||||||
|
|
@ -37,10 +37,10 @@ set(GIT_DESC ${BUILD_VERSION})
|
||||||
|
|
||||||
# Auto-updater metadata! Must somewhat mirror GitHub API endpoint
|
# Auto-updater metadata! Must somewhat mirror GitHub API endpoint
|
||||||
if (NIGHTLY_BUILD)
|
if (NIGHTLY_BUILD)
|
||||||
set(BUILD_AUTO_UPDATE_WEBSITE "https://github.com")
|
set(BUILD_AUTO_UPDATE_WEBSITE "https://git.eden-emu.dev")
|
||||||
set(BUILD_AUTO_UPDATE_API "api.github.com")
|
set(BUILD_AUTO_UPDATE_API "git.eden-emu.dev")
|
||||||
set(BUILD_AUTO_UPDATE_API_PATH "/repos/")
|
set(BUILD_AUTO_UPDATE_API_PATH "/api/v1/repos/")
|
||||||
set(BUILD_AUTO_UPDATE_REPO "Eden-CI/Nightly")
|
set(BUILD_AUTO_UPDATE_REPO "eden-ci/nightly")
|
||||||
set(REPO_NAME "Eden Nightly")
|
set(REPO_NAME "Eden Nightly")
|
||||||
else()
|
else()
|
||||||
set(BUILD_AUTO_UPDATE_WEBSITE "https://git.eden-emu.dev")
|
set(BUILD_AUTO_UPDATE_WEBSITE "https://git.eden-emu.dev")
|
||||||
|
|
|
||||||
|
|
@ -87,8 +87,8 @@
|
||||||
"bundled": true
|
"bundled": true
|
||||||
},
|
},
|
||||||
"llvm-mingw": {
|
"llvm-mingw": {
|
||||||
"repo": "misc/llvm-mingw",
|
"repo": "eden-emu/llvm-mingw",
|
||||||
"git_host": "git.crueter.xyz",
|
"git_host": "git.eden-emu.dev",
|
||||||
"tag": "%VERSION%",
|
"tag": "%VERSION%",
|
||||||
"version": "20250828",
|
"version": "20250828",
|
||||||
"artifact": "clang-rt-builtins.tar.zst",
|
"artifact": "clang-rt-builtins.tar.zst",
|
||||||
|
|
|
||||||
BIN
dist/Assets.car
vendored
396
dist/dev.eden_emu.eden.svg
vendored
|
|
@ -6,191 +6,225 @@
|
||||||
viewBox="0 0 512 512"
|
viewBox="0 0 512 512"
|
||||||
version="1.1"
|
version="1.1"
|
||||||
id="svg7"
|
id="svg7"
|
||||||
sodipodi:docname="saintpatrick2026_named.svg"
|
sodipodi:docname="base.svg.2026_01_12_14_43_47.0.svg"
|
||||||
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
|
inkscape:version="1.4.2 (ebf0e94, 2025-05-08)"
|
||||||
xml:space="preserve"
|
inkscape:export-filename="base.svg.2026_01_12_14_43_47.0.svg"
|
||||||
inkscape:export-filename="dev.eden_emu.eden.png"
|
|
||||||
inkscape:export-xdpi="96"
|
inkscape:export-xdpi="96"
|
||||||
inkscape:export-ydpi="96"
|
inkscape:export-ydpi="96"
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
|
||||||
<metadata
|
|
||||||
id="metadata1">
|
|
||||||
<rdf:RDF>
|
|
||||||
<cc:Work
|
|
||||||
rdf:about="">
|
|
||||||
|
|
||||||
<dc:creator>
|
|
||||||
<cc:Agent>
|
|
||||||
<dc:title>Madeline_Dev</dc:title>
|
|
||||||
<dc:identifier>mailto:madelvidel@gmail.com</dc:identifier>
|
|
||||||
</cc:Agent>
|
|
||||||
</dc:creator>
|
|
||||||
<dc:date>2025</dc:date>
|
|
||||||
<dc:license
|
|
||||||
rdf:resource="https://www.gnu.org/licenses/gpl-3.0.html" />
|
|
||||||
<dc:rights>2025 Eden Emulator Project</dc:rights>
|
|
||||||
<dc:source>https://git.eden-emu.dev</dc:source>
|
|
||||||
</cc:Work>
|
|
||||||
</rdf:RDF>
|
|
||||||
</metadata>
|
|
||||||
<defs
|
<defs
|
||||||
id="defs7"><linearGradient
|
id="defs7">
|
||||||
id="swatch14"
|
<linearGradient
|
||||||
inkscape:swatch="solid"><stop
|
id="linearGradient1"
|
||||||
style="stop-color:#66003b;stop-opacity:1;"
|
inkscape:collect="always">
|
||||||
offset="0"
|
<stop
|
||||||
id="stop14" /></linearGradient><linearGradient
|
style="stop-color:#ff2e88;stop-opacity:0.5;"
|
||||||
id="linearGradient11"
|
offset="0"
|
||||||
inkscape:collect="always"><stop
|
id="stop3" />
|
||||||
style="stop-color:#f6d512;stop-opacity:1;"
|
<stop
|
||||||
offset="0"
|
style="stop-color:#bf42f6;stop-opacity:0.5;"
|
||||||
id="stop11" /><stop
|
offset="0.44631511"
|
||||||
style="stop-color:#1d8e53;stop-opacity:1;"
|
id="stop4" />
|
||||||
offset="0.99898213"
|
<stop
|
||||||
id="stop20" /><stop
|
style="stop-color:#5da5ed;stop-opacity:0.5;"
|
||||||
style="stop-color:#ffffff;stop-opacity:0;"
|
offset="0.90088946"
|
||||||
offset="0.99898213"
|
id="stop2" />
|
||||||
id="stop12" /></linearGradient><linearGradient
|
</linearGradient>
|
||||||
inkscape:collect="always"
|
<linearGradient
|
||||||
xlink:href="#linearGradient11"
|
id="linearGradient138"
|
||||||
id="linearGradient12"
|
inkscape:collect="always">
|
||||||
x1="109.74531"
|
<stop
|
||||||
y1="106.54533"
|
style="stop-color:#ff2e88;stop-opacity:1;"
|
||||||
x2="431.05463"
|
offset="0"
|
||||||
y2="427.85461"
|
id="stop152" />
|
||||||
gradientUnits="userSpaceOnUse"
|
<stop
|
||||||
spreadMethod="reflect"
|
style="stop-color:#bf42f6;stop-opacity:1;"
|
||||||
gradientTransform="matrix(1.0945321,0,0,1.0945321,-39.661525,-35.159057)" /><filter
|
offset="0.44971901"
|
||||||
inkscape:label="Light Contour"
|
id="stop137" />
|
||||||
inkscape:menu="Image Paint and Draw"
|
<stop
|
||||||
inkscape:menu-tooltip="Uses vertical specular light to draw lines"
|
style="stop-color:#5da5ed;stop-opacity:1;"
|
||||||
style="color-interpolation-filters:sRGB"
|
offset="0.89793283"
|
||||||
id="filter11"
|
id="stop138" />
|
||||||
x="-0.01907517"
|
</linearGradient>
|
||||||
y="-0.054959154"
|
<linearGradient
|
||||||
width="1.0379885"
|
id="swatch37"
|
||||||
height="1.1092314"><feGaussianBlur
|
inkscape:swatch="solid">
|
||||||
in="SourceGraphic"
|
<stop
|
||||||
stdDeviation="0.38250006"
|
style="stop-color:#ffffff;stop-opacity:1;"
|
||||||
result="result3"
|
offset="0"
|
||||||
id="feGaussianBlur9" /><feComponentTransfer
|
id="stop37" />
|
||||||
result="result1"
|
</linearGradient>
|
||||||
in="result3"
|
<linearGradient
|
||||||
id="feComponentTransfer9"><feFuncR
|
id="swatch28"
|
||||||
type="discrete"
|
inkscape:swatch="solid">
|
||||||
tableValues="0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1"
|
<stop
|
||||||
id="feFuncR9" /><feFuncG
|
style="stop-color:#252525;stop-opacity:1;"
|
||||||
type="discrete"
|
offset="0"
|
||||||
tableValues="0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1"
|
id="stop28" />
|
||||||
id="feFuncG9" /><feFuncB
|
</linearGradient>
|
||||||
type="discrete"
|
<linearGradient
|
||||||
tableValues="0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1"
|
id="swatch27"
|
||||||
id="feFuncB9" /></feComponentTransfer><feGaussianBlur
|
inkscape:swatch="solid">
|
||||||
result="result5"
|
<stop
|
||||||
stdDeviation="0.01"
|
style="stop-color:#000000;stop-opacity:1;"
|
||||||
id="feGaussianBlur10" /><feBlend
|
offset="0"
|
||||||
in2="result5"
|
id="stop27" />
|
||||||
result="result6"
|
</linearGradient>
|
||||||
mode="lighten"
|
<linearGradient
|
||||||
in="result5"
|
id="swatch15"
|
||||||
id="feBlend10" /><feColorMatrix
|
inkscape:swatch="solid">
|
||||||
in="result6"
|
<stop
|
||||||
type="luminanceToAlpha"
|
style="stop-color:#ffffff;stop-opacity:1;"
|
||||||
result="result2"
|
offset="0"
|
||||||
id="feColorMatrix10" /><feSpecularLighting
|
id="stop16" />
|
||||||
surfaceScale="5"
|
</linearGradient>
|
||||||
result="result9"
|
<linearGradient
|
||||||
specularExponent="20"
|
id="linearGradient14"
|
||||||
in="result2"
|
inkscape:swatch="gradient">
|
||||||
specularConstant="1"
|
<stop
|
||||||
id="feSpecularLighting10"><feDistantLight
|
style="stop-color:#ffffff;stop-opacity:1;"
|
||||||
azimuth="180"
|
offset="0"
|
||||||
elevation="90"
|
id="stop14" />
|
||||||
id="feDistantLight10" /></feSpecularLighting><feComposite
|
<stop
|
||||||
in2="result6"
|
style="stop-color:#ffffff;stop-opacity:0;"
|
||||||
operator="arithmetic"
|
offset="1"
|
||||||
in="result9"
|
id="stop15" />
|
||||||
k1="0.4"
|
</linearGradient>
|
||||||
k3="0.7"
|
<linearGradient
|
||||||
result="result3"
|
id="swatch9"
|
||||||
id="feComposite10"
|
inkscape:swatch="solid">
|
||||||
k2="0"
|
<stop
|
||||||
k4="0" /><feBlend
|
style="stop-color:#ffffff;stop-opacity:1;"
|
||||||
in2="result1"
|
offset="0"
|
||||||
in="result3"
|
id="stop10" />
|
||||||
mode="normal"
|
</linearGradient>
|
||||||
result="result8"
|
<linearGradient
|
||||||
id="feBlend11" /><feComposite
|
id="swatch8"
|
||||||
in2="SourceGraphic"
|
inkscape:swatch="solid">
|
||||||
in="result8"
|
<stop
|
||||||
operator="in"
|
style="stop-color:#ffffff;stop-opacity:1;"
|
||||||
result="result7"
|
offset="0"
|
||||||
id="feComposite11" /></filter></defs><sodipodi:namedview
|
id="stop9" />
|
||||||
id="namedview7"
|
</linearGradient>
|
||||||
pagecolor="#ffffff"
|
<rect
|
||||||
bordercolor="#000000"
|
x="22.627417"
|
||||||
borderopacity="0.25"
|
y="402.76802"
|
||||||
inkscape:showpageshadow="2"
|
width="521.34025"
|
||||||
inkscape:pageopacity="0.0"
|
height="248.94868"
|
||||||
inkscape:pagecheckerboard="0"
|
id="rect24" />
|
||||||
inkscape:deskcolor="#d1d1d1"
|
<linearGradient
|
||||||
inkscape:zoom="0.6363961"
|
id="linearGradient11"
|
||||||
inkscape:cx="172.06265"
|
inkscape:collect="always">
|
||||||
inkscape:cy="122.56518"
|
<stop
|
||||||
inkscape:window-width="1600"
|
style="stop-color:#ff2e88;stop-opacity:1;"
|
||||||
inkscape:window-height="849"
|
offset="0"
|
||||||
inkscape:window-x="0"
|
id="stop11" />
|
||||||
inkscape:window-y="27"
|
<stop
|
||||||
inkscape:window-maximized="1"
|
style="stop-color:#bf42f6;stop-opacity:1;"
|
||||||
inkscape:current-layer="svg7"
|
offset="0.44971901"
|
||||||
showguides="false" /><circle
|
id="stop154" />
|
||||||
style="fill:url(#linearGradient12);fill-opacity:1;stroke:#e4e4e4;stroke-width:14.0448;stroke-opacity:1;paint-order:stroke fill markers"
|
<stop
|
||||||
id="path8"
|
style="stop-color:#5da5ed;stop-opacity:1;"
|
||||||
cx="256.2999"
|
offset="0.89793283"
|
||||||
cy="257.2999"
|
id="stop12" />
|
||||||
r="248.67769" /><path
|
</linearGradient>
|
||||||
id="path15"
|
<linearGradient
|
||||||
style="fill:#f3ffeb;fill-opacity:1;stroke:#ffffff;stroke-width:16.9642;stroke-linejoin:round;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.33910036;paint-order:stroke fill markers"
|
inkscape:collect="always"
|
||||||
d="m 306.72111,24.233031 c 0,0 -11.98397,40.08696 -18.0546,60.431848 -12.96613,9.503601 -21.49377,18.397701 -21.49377,18.397701 0,0 -23.41313,-31.029398 -45.74145,-43.934598 -22.32833,-12.905201 -52.42065,-11.242483 -52.42065,-11.242483 0,0 -12.50052,4e-4 -27.63117,5.537132 -15.13066,5.536732 -21.27107,9.227888 -21.27107,9.227888 0,0 15.35165,-0.410529 37.93799,6.766716 22.58635,7.177243 32.45374,11.484796 32.45374,11.484796 l 31.02752,-6.562453 -8.44161,11.074275 c 0,0 14.80259,8.920284 22.80648,16.917787 8.0039,7.9975 11.73088,12.50812 11.73088,12.50812 0,0 -13.92373,-5.43341 -56.68427,-1.74226 -42.76055,3.69116 -84.86368,56.39265 -84.86368,56.39265 0,0 41.22428,-15.9958 65.5649,-21.32747 24.34062,-5.33166 47.58524,-7.9983 47.58524,-7.9983 0,0 -18.41865,7.3827 -38.15428,38.3474 -19.73564,30.96468 -14.0351,80.18128 -14.0351,80.18128 0,0 31.35774,-59.05848 61.39977,-78.94969 30.04203,-19.89124 36.182,-20.50642 36.182,-20.50642 0,0 -24.1209,48.39514 -33.55015,126.11445 -9.42924,77.71931 30.26089,207.72959 30.26089,207.72959 l 47.80367,-6.97298 c 0,0 -45.61041,-42.24281 -49.55753,-151.33695 -3.94713,-109.09413 16.66479,-174.30453 16.66479,-174.30453 0,0 17.10508,1.23039 42.54213,32.81027 25.43704,31.57987 40.34713,57.41795 40.34713,57.41795 0,0 9.65024,-51.26683 -11.4011,-74.64415 -21.05135,-23.3773 -53.50637,-33.62931 -53.50637,-33.62931 0,0 13.70573,-6.66419 42.10313,-4.71609 28.39738,1.94813 87.30278,27.12897 87.30278,27.12896 0,0 -15.8158,-25.5214 -52.87463,-43.21167 -37.05881,-17.69028 -81.35597,0.29238 -81.35597,0.29238 0,0 4.13589,-15.37277 29.10021,-32.628037 24.96432,-17.25527 56.907,-34.36427 56.907,-34.36427 0,0 -26.3595,1.160335 -55.20025,12.035504 -7.176,2.7059 -14.064,6.299542 -20.36309,10.173104 l 17.40574,-51.051762 z" /><path
|
xlink:href="#linearGradient138"
|
||||||
d="m 364.02341,369.59545 c -1.05628,0.0923 -4.67136,0.65996 -7.06652,1.09993 -1.73317,0.31934 -2.17946,0.41869 -2.99769,0.68125 -0.51326,0.15613 -0.62485,0.17032 -0.91495,0.0993 -0.43144,-0.10644 -2.3208,-0.2058 -4.86474,-0.26256 -4.47793,-0.10645 -6.76898,0.3761 -9.18647,1.91601 -1.68109,1.07865 -2.9754,2.40567 -4.18788,4.3075 -0.72897,1.14251 -0.92234,2.15729 -0.77357,4.17266 0.11901,1.59667 0.37935,2.58307 1.19757,4.54877 1.61417,3.84622 3.75641,6.6209 9.60302,12.41863 4.25482,4.22943 5.65324,5.72676 5.65324,6.07449 0,0.15612 -0.0298,0.17031 -0.40911,0.17031 -0.52812,0 -0.77362,-0.0993 -1.69599,-0.69545 -1.0711,-0.68834 -2.31333,-1.61087 -4.66389,-3.46302 -3.42913,-2.69661 -3.92749,-3.07982 -5.19948,-4.02364 -2.0307,-1.49024 -3.6374,-2.49082 -4.74571,-2.95209 -1.8968,-0.78769 -5.02097,-1.24895 -7.31945,-1.07864 -2.68526,0.20579 -4.72343,0.85866 -6.76156,2.16438 -1.98605,1.28445 -5.15484,4.17977 -5.58628,5.11648 -0.29009,0.62448 -0.46118,1.93022 -0.59505,4.4991 -0.11158,2.05794 -0.0373,3.37077 0.29011,5.40033 l 0.20083,1.24187 -0.45376,1.59667 c -0.70663,2.45535 -0.95956,4.18686 -1.04882,6.95444 -0.0819,2.76759 0.19338,4.45651 0.94467,5.90417 0.97445,1.85925 3.83081,4.98875 5.91358,6.46479 1.23478,0.87994 2.98284,1.48315 5.09534,1.7599 1.10831,0.14903 3.4663,0.12773 4.23992,-0.0355 1.02649,-0.21289 2.61833,-0.73092 3.39936,-1.10704 1.47284,-0.70253 3.91264,-2.36308 6.97727,-4.75455 4.66392,-3.63334 6.5235,-5.01713 7.28968,-5.40744 0.3868,-0.20579 0.51327,-0.23417 1.00417,-0.23417 0.49094,0 0.60253,0.0284 0.94471,0.21289 l 0.37936,0.21999 -1.78522,1.76698 c -8.50216,8.44468 -9.78157,9.89943 -11.44034,13.02184 -1.42817,2.69662 -2.41749,5.54225 -2.78942,8.01888 -0.23059,1.5825 -0.0892,4.59135 0.29753,6.03192 0.28267,1.06444 0.78846,2.24244 1.24966,2.87403 0.6546,0.90832 1.65877,2.09341 1.76292,2.09341 0.2901,0 1.77778,-1.12122 2.11996,-1.59668 0.14134,-0.1916 0.31243,-0.49673 0.37936,-0.67415 0.17852,-0.47546 0.20827,-1.52571 0.0744,-2.79596 -0.15619,-1.46186 -0.15619,-3.64754 -0.007,-4.48491 0.14877,-0.81607 0.60996,-2.44825 1.03396,-3.61204 0.78105,-2.18569 1.71829,-3.94559 3.35473,-6.31577 1.65877,-2.39857 4.64161,-6.0319 6.28548,-7.65697 0.66203,-0.65287 2.0456,-1.73151 2.12743,-1.66056 0.0297,0.0355 -0.61742,1.5683 -1.2199,2.85984 -0.41659,0.90123 -1.32407,2.62566 -2.13486,4.04493 -1.4505,2.54049 -1.98605,3.66882 -2.16458,4.55586 -0.29009,1.45476 -0.43143,3.34239 -0.43143,5.76934 0,2.12891 0.0147,2.48374 0.16362,3.40625 0.19341,1.15672 0.54301,2.77469 0.76619,3.49851 0.51322,1.67475 1.71084,3.49141 3.25803,4.94616 1.56209,1.47606 2.98283,2.16441 5.43008,2.63985 0.83307,0.15613 1.04881,0.16322 3.46631,0.0993 2.26129,-0.0639 2.98283,-0.23417 6.02513,-1.39088 1.74807,-0.66706 2.57372,-0.94382 3.64486,-1.22767 2.96051,-0.7806 5.22924,-0.9864 6.96983,-0.63158 0.78848,0.16322 0.7959,0.16322 1.07858,0.0284 0.15619,-0.0781 0.81822,-0.30515 1.46536,-0.50385 0.6546,-0.1987 1.4505,-0.49674 1.77778,-0.66705 2.14971,-1.09285 6.40453,-4.93907 7.26737,-6.57833 0.66945,-1.27735 1.17528,-3.87462 1.09345,-5.64871 -0.10415,-2.18568 -0.78103,-4.1017 -2.3059,-6.52156 -0.95956,-1.53281 -1.7555,-2.44825 -3.76387,-4.36426 -1.78521,-1.70313 -3.14646,-2.85984 -6.8136,-5.81901 -4.55235,-3.66173 -6.17394,-5.06681 -6.12187,-5.30809 0.0151,-0.071 0.0819,-0.11354 0.17109,-0.0993 0.27521,0.0497 1.85962,1.06446 6.00286,3.85334 4.28453,2.88111 6.06231,3.92428 7.81781,4.60554 3.94235,1.51151 8.04839,2.29922 11.44773,2.17857 1.95634,-0.0639 3.31758,-0.36901 4.85734,-1.08575 0.88516,-0.41157 2.40259,-1.3625 3.49606,-2.19986 1.07115,-0.81608 3.03487,-2.68952 3.51838,-3.34949 0.97443,-1.3412 1.65877,-3.95977 1.55462,-5.94674 -0.0595,-1.08575 -0.25287,-1.90184 -0.93723,-4.04494 -0.69179,-2.16438 -1.15298,-3.77526 -1.28684,-4.4636 -0.15624,-0.82319 -0.11901,-3.30691 0.0819,-4.8965 0.20827,-1.66764 0.28263,-4.11589 0.16362,-5.10938 -0.18594,-1.52571 -0.6397,-3.1153 -1.23476,-4.34298 -0.99674,-2.05794 -3.33244,-4.20814 -5.7276,-5.27968 -1.41332,-0.62449 -3.4961,-1.09994 -5.89127,-1.34831 -1.24965,-0.12065 -3.91264,-0.0497 -5.04324,0.14192 -1.815,0.30515 -4.71601,1.09994 -5.31849,1.44766 -0.80337,0.46836 -2.80432,2.24955 -7.21533,6.39382 -1.77778,1.67474 -3.8531,3.60496 -4.61181,4.28621 -1.24966,1.12832 -2.1051,1.79538 -2.19437,1.71022 -0.0967,-0.0993 1.34635,-2.19987 4.90939,-7.16023 4.95399,-6.89057 5.67552,-8.06147 6.44171,-10.41036 1.12318,-3.47012 0.052,-8.16082 -2.67041,-11.73029 -0.8852,-1.15671 -2.05303,-2.05085 -3.73412,-2.86694 -1.43561,-0.69544 -2.86379,-1.12122 -4.53745,-1.3554 -0.75872,-0.10644 -4.11344,-0.1987 -4.83498,-0.13482 z"
|
id="linearGradient6"
|
||||||
id="path1"
|
gradientUnits="userSpaceOnUse"
|
||||||
style="fill:#e5ffd5;fill-opacity:1;stroke:none;stroke-width:0.00726536" /><path
|
gradientTransform="matrix(1.118028,0,0,1.116699,-46.314723,-42.388667)"
|
||||||
d="m 83.20673,250.24331 c -1.05628,0.0923 -4.67136,0.65996 -7.06652,1.09993 -1.73317,0.31934 -2.17946,0.41869 -2.99769,0.68125 -0.51326,0.15613 -0.62485,0.17032 -0.91495,0.0993 -0.43144,-0.10644 -2.3208,-0.2058 -4.86474,-0.26256 -4.47793,-0.10645 -6.76898,0.3761 -9.18647,1.91601 -1.68109,1.07865 -2.9754,2.40567 -4.18788,4.3075 -0.72897,1.14251 -0.92234,2.15729 -0.77357,4.17266 0.11901,1.59667 0.37935,2.58307 1.19757,4.54877 1.61417,3.84622 3.75641,6.6209 9.60302,12.41863 4.25482,4.22943 5.65324,5.72676 5.65324,6.07449 0,0.15612 -0.0298,0.17031 -0.40911,0.17031 -0.52812,0 -0.77362,-0.0993 -1.69599,-0.69545 -1.0711,-0.68834 -2.31333,-1.61087 -4.66389,-3.46302 -3.42913,-2.69661 -3.92749,-3.07982 -5.19948,-4.02364 -2.0307,-1.49024 -3.6374,-2.49082 -4.74571,-2.95209 -1.8968,-0.78769 -5.02097,-1.24895 -7.31945,-1.07864 -2.68526,0.20579 -4.72343,0.85866 -6.76156,2.16438 -1.98605,1.28445 -5.15484,4.17977 -5.58628,5.11648 -0.29009,0.62448 -0.46118,1.93022 -0.59505,4.4991 -0.11158,2.05794 -0.0373,3.37077 0.29011,5.40033 l 0.20083,1.24187 -0.45376,1.59667 c -0.70663,2.45535 -0.95956,4.18686 -1.04882,6.95444 -0.0819,2.76759 0.19338,4.45651 0.94467,5.90417 0.97445,1.85925 3.83081,4.98875 5.91358,6.46479 1.23478,0.87994 2.98284,1.48315 5.09534,1.7599 1.10831,0.14903 3.4663,0.12773 4.23992,-0.0355 1.02649,-0.21289 2.61833,-0.73092 3.39936,-1.10704 1.47284,-0.70253 3.91264,-2.36308 6.97727,-4.75455 4.66392,-3.63334 6.5235,-5.01713 7.28968,-5.40744 0.3868,-0.20579 0.51327,-0.23417 1.00417,-0.23417 0.49094,0 0.60253,0.0284 0.94471,0.21289 l 0.37936,0.21999 -1.78522,1.76698 c -8.50216,8.44468 -9.78157,9.89943 -11.44034,13.02184 -1.42817,2.69662 -2.41749,5.54225 -2.78942,8.01888 -0.23059,1.5825 -0.0892,4.59135 0.29753,6.03192 0.28267,1.06444 0.78846,2.24244 1.24966,2.87403 0.6546,0.90832 1.65877,2.09341 1.76292,2.09341 0.2901,0 1.77778,-1.12122 2.11996,-1.59668 0.14134,-0.1916 0.31243,-0.49673 0.37936,-0.67415 0.17852,-0.47546 0.20827,-1.52571 0.0744,-2.79596 -0.15619,-1.46186 -0.15619,-3.64754 -0.007,-4.48491 0.14877,-0.81607 0.60996,-2.44825 1.03396,-3.61204 0.78105,-2.18569 1.71829,-3.94559 3.35473,-6.31577 1.65877,-2.39857 4.64161,-6.0319 6.28548,-7.65697 0.66203,-0.65287 2.0456,-1.73151 2.12743,-1.66056 0.0297,0.0355 -0.61742,1.5683 -1.2199,2.85984 -0.41659,0.90123 -1.32407,2.62566 -2.13486,4.04493 -1.4505,2.54049 -1.98605,3.66882 -2.16458,4.55586 -0.29009,1.45476 -0.43143,3.34239 -0.43143,5.76934 0,2.12891 0.0147,2.48374 0.16362,3.40625 0.19341,1.15672 0.54301,2.77469 0.76619,3.49851 0.51322,1.67475 1.71084,3.49141 3.25803,4.94616 1.56209,1.47606 2.98283,2.16441 5.43008,2.63985 0.83307,0.15613 1.04881,0.16322 3.46631,0.0993 2.26129,-0.0639 2.98283,-0.23417 6.02513,-1.39088 1.74807,-0.66706 2.57372,-0.94382 3.64486,-1.22767 2.96051,-0.7806 5.22924,-0.9864 6.96983,-0.63158 0.78848,0.16322 0.7959,0.16322 1.07858,0.0284 0.15619,-0.0781 0.81822,-0.30515 1.46536,-0.50385 0.6546,-0.1987 1.4505,-0.49674 1.77778,-0.66705 2.14971,-1.09285 6.40453,-4.93907 7.26737,-6.57833 0.66945,-1.27735 1.17528,-3.87462 1.09345,-5.64871 -0.10415,-2.18568 -0.78103,-4.1017 -2.3059,-6.52156 -0.95956,-1.53281 -1.7555,-2.44825 -3.76387,-4.36426 -1.78521,-1.70313 -3.14646,-2.85984 -6.8136,-5.81901 -4.55235,-3.66173 -6.17394,-5.06681 -6.12187,-5.30809 0.0151,-0.071 0.0819,-0.11354 0.17109,-0.0993 0.27521,0.0497 1.85962,1.06446 6.00286,3.85334 4.28453,2.88111 6.06231,3.92428 7.81781,4.60554 3.94235,1.51151 8.04839,2.29922 11.44773,2.17857 1.95634,-0.0639 3.31758,-0.36901 4.85734,-1.08575 0.88516,-0.41157 2.40259,-1.3625 3.49606,-2.19986 1.07115,-0.81608 3.03487,-2.68952 3.51838,-3.34949 0.97443,-1.3412 1.65877,-3.95977 1.55462,-5.94674 -0.0595,-1.08575 -0.25287,-1.90184 -0.93723,-4.04494 -0.69179,-2.16438 -1.15298,-3.77526 -1.28684,-4.4636 -0.15624,-0.82319 -0.11901,-3.30691 0.0819,-4.8965 0.20827,-1.66764 0.28263,-4.11589 0.16362,-5.10938 -0.18594,-1.52571 -0.6397,-3.1153 -1.23476,-4.34298 -0.99674,-2.05794 -3.33244,-4.20814 -5.7276,-5.27968 -1.41332,-0.62449 -3.4961,-1.09994 -5.89127,-1.34831 -1.24965,-0.12065 -3.91264,-0.0497 -5.04324,0.14192 -1.815,0.30515 -4.71601,1.09994 -5.31849,1.44766 -0.80337,0.46836 -2.80432,2.24955 -7.21533,6.39382 -1.77778,1.67474 -3.8531,3.60496 -4.61181,4.28621 -1.24966,1.12832 -2.1051,1.79538 -2.19437,1.71022 -0.0967,-0.0993 1.34635,-2.19987 4.90939,-7.16023 4.95399,-6.89057 5.67552,-8.06147 6.44171,-10.41036 1.12318,-3.47012 0.052,-8.16082 -2.67041,-11.73029 -0.8852,-1.15671 -2.05303,-2.05085 -3.73412,-2.86694 -1.43561,-0.69544 -2.86379,-1.12122 -4.53745,-1.3554 -0.75872,-0.10644 -4.11344,-0.1987 -4.83498,-0.13482 z"
|
x1="270.39996"
|
||||||
id="path1-9"
|
y1="40.000019"
|
||||||
style="fill:#e5ffd5;fill-opacity:1;stroke:none;stroke-width:0.00726536" /><path
|
x2="270.39996"
|
||||||
d="m 439.21947,248.58317 c -1.32752,0.12081 -5.87092,0.86387 -8.88113,1.43979 -2.17823,0.41802 -2.73912,0.54806 -3.76747,0.89175 -0.64506,0.20437 -0.7853,0.22295 -1.1499,0.12998 -0.54223,-0.13933 -2.91676,-0.26938 -6.11395,-0.34369 -5.62782,-0.13934 -8.50719,0.49231 -11.54547,2.50804 -2.11277,1.41194 -3.73945,3.14899 -5.26329,5.63847 -0.91615,1.49553 -1.15918,2.82387 -0.97221,5.46197 0.14957,2.09002 0.47676,3.38121 1.5051,5.9543 2.02866,5.03465 4.72101,8.66669 12.06898,16.25585 5.34741,5.53628 7.10493,7.49627 7.10493,7.95145 0,0.20436 -0.0375,0.22293 -0.51416,0.22293 -0.66374,0 -0.97228,-0.12998 -2.13151,-0.91034 -1.34614,-0.90103 -2.90737,-2.10861 -5.86153,-4.53305 -4.30969,-3.52984 -4.93603,-4.03145 -6.53465,-5.26691 -2.55217,-1.95071 -4.57145,-3.26045 -5.96436,-3.86425 -2.38388,-1.03107 -6.3103,-1.63487 -9.19901,-1.41193 -3.37482,0.26938 -5.93636,1.12398 -8.49786,2.83315 -2.49604,1.68134 -6.47855,5.47127 -7.02078,6.69742 -0.36459,0.81743 -0.57961,2.52664 -0.74785,5.88927 -0.14024,2.69383 -0.0469,4.4123 0.3646,7.06898 l 0.25241,1.6256 -0.57028,2.09002 c -0.8881,3.21403 -1.20598,5.48056 -1.31815,9.10329 -0.10293,3.62275 0.24303,5.83353 1.18725,7.7285 1.22468,2.43373 4.81452,6.53023 7.43213,8.46235 1.55185,1.15183 3.7488,1.94142 6.40377,2.30368 1.39291,0.19508 4.35641,0.16719 5.32868,-0.0464 1.29009,-0.27867 3.29069,-0.95677 4.27229,-1.44911 1.85104,-0.91959 4.91736,-3.09324 8.76896,-6.22365 5.86156,-4.756 8.19866,-6.56736 9.1616,-7.07828 0.48612,-0.26938 0.64507,-0.30652 1.26203,-0.30652 0.617,0 0.75725,0.0371 1.1873,0.27867 l 0.47677,0.28796 -2.24364,2.31295 c -10.68543,11.05401 -12.29338,12.95826 -14.37811,17.04546 -1.79491,3.52986 -3.03827,7.25475 -3.50571,10.49663 -0.28981,2.07148 -0.11211,6.01003 0.37392,7.89573 0.35526,1.39333 0.99094,2.93533 1.57057,3.76207 0.82269,1.18898 2.08473,2.74025 2.21562,2.74025 0.36459,0 2.2343,-1.46767 2.66435,-2.09004 0.17763,-0.2508 0.39265,-0.65021 0.47676,-0.88245 0.22437,-0.62238 0.26176,-1.99714 0.0935,-3.65989 -0.19629,-1.91355 -0.19629,-4.77458 -0.009,-5.87069 0.18698,-1.06823 0.7666,-3.20474 1.29948,-4.72813 0.98162,-2.86105 2.15954,-5.16473 4.21619,-8.26728 2.08473,-3.13971 5.83353,-7.89569 7.89953,-10.02289 0.83203,-0.8546 2.57089,-2.26653 2.67373,-2.17366 0.0373,0.0465 -0.77596,2.05289 -1.53315,3.7435 -0.52357,1.17971 -1.66408,3.43696 -2.68307,5.29478 -1.82298,3.32547 -2.49605,4.80245 -2.72043,5.96357 -0.36458,1.90426 -0.54221,4.37516 -0.54221,7.55201 0,2.78672 0.0185,3.25118 0.20563,4.45874 0.24308,1.51413 0.68245,3.63204 0.96294,4.57952 0.64501,2.19223 2.15017,4.57021 4.09466,6.47447 1.96322,1.93214 3.74879,2.83318 6.82447,3.45554 1.04699,0.20437 1.31814,0.21365 4.35643,0.12998 2.84196,-0.0837 3.74879,-0.30652 7.57232,-1.82065 2.19695,-0.87318 3.23462,-1.23545 4.58082,-1.60701 3.72074,-1.0218 6.57206,-1.29118 8.75961,-0.82673 0.99096,0.21366 1.00028,0.21366 1.35555,0.0371 0.1963,-0.10223 1.02833,-0.39944 1.84165,-0.65953 0.8227,-0.26009 1.82298,-0.65022 2.2343,-0.87316 2.70173,-1.43052 8.04915,-6.46519 9.13355,-8.61097 0.84136,-1.67203 1.47709,-5.07183 1.37424,-7.3941 -0.13089,-2.86103 -0.98159,-5.36908 -2.89803,-8.53665 -1.20597,-2.00643 -2.2063,-3.20474 -4.73039,-5.71278 -2.24364,-2.22938 -3.95444,-3.74349 -8.56327,-7.61702 -5.72135,-4.79316 -7.75934,-6.6324 -7.6939,-6.94823 0.019,-0.093 0.10293,-0.14863 0.21502,-0.12998 0.34588,0.0651 2.33715,1.39336 7.54434,5.04398 5.38475,3.77133 7.61905,5.13684 9.82534,6.02861 4.95471,1.97854 10.11514,3.00965 14.38739,2.85172 2.45871,-0.0837 4.1695,-0.48304 6.10466,-1.42124 1.11246,-0.53874 3.01955,-1.7835 4.39381,-2.87959 1.34621,-1.06825 3.81419,-3.52055 4.42187,-4.38445 1.22465,-1.75562 2.08472,-5.1833 1.95383,-7.78422 -0.0748,-1.42123 -0.31781,-2.48949 -1.17791,-5.29478 -0.86943,-2.83316 -1.44905,-4.94178 -1.61728,-5.84282 -0.19636,-1.07754 -0.14957,-4.3287 0.10293,-6.40946 0.26175,-2.18293 0.35521,-5.38765 0.20563,-6.68813 -0.23368,-1.99714 -0.80396,-4.07789 -1.55183,-5.68491 -1.25269,-2.69382 -4.18818,-5.50842 -7.19839,-6.91105 -1.77624,-0.81744 -4.39386,-1.43981 -7.40409,-1.76492 -1.57055,-0.15793 -4.91736,-0.0651 -6.33829,0.18577 -2.28107,0.39944 -5.92703,1.43981 -6.68423,1.89497 -1.00966,0.61308 -3.52444,2.94464 -9.06815,8.36945 -2.2343,2.19222 -4.84254,4.71885 -5.79608,5.6106 -1.57056,1.47696 -2.64567,2.35014 -2.75786,2.23867 -0.12153,-0.12999 1.69208,-2.87962 6.17007,-9.37268 6.22613,-9.01968 7.13294,-10.55238 8.09588,-13.62705 1.4116,-4.54234 0.0654,-10.68243 -3.35615,-15.35482 -1.11251,-1.51413 -2.58022,-2.68454 -4.693,-3.75281 -1.80426,-0.91031 -3.59918,-1.46765 -5.70262,-1.77419 -0.95355,-0.13933 -5.16973,-0.2601 -6.07655,-0.17649 z"
|
y2="494.39996"
|
||||||
id="path1-1"
|
spreadMethod="pad" />
|
||||||
style="fill:#e5ffd5;fill-opacity:1;stroke:none;stroke-width:0.00931876" /><path
|
<clipPath
|
||||||
d="m 324.26695,283.12908 c -0.83436,0.0787 -3.6899,0.56207 -5.58184,0.93679 -1.36902,0.27198 -1.72154,0.3566 -2.36787,0.58021 -0.40542,0.13298 -0.49356,0.14506 -0.72272,0.0846 -0.34079,-0.0907 -1.83319,-0.17527 -3.84264,-0.22362 -3.53711,-0.0907 -5.34681,0.32032 -7.25638,1.63185 -1.32789,0.91866 -2.35026,2.04887 -3.308,3.66862 -0.57581,0.97307 -0.72855,1.83734 -0.61104,3.5538 0.094,1.35986 0.29964,2.19996 0.94596,3.87412 1.27502,3.27577 2.96718,5.63893 7.58541,10.57676 3.36087,3.60215 4.46548,4.87741 4.46548,5.17356 0,0.13297 -0.0236,0.14505 -0.32315,0.14505 -0.41716,0 -0.61108,-0.0846 -1.33966,-0.59231 -0.84606,-0.58625 -1.8273,-1.37195 -3.684,-2.9494 -2.70866,-2.29666 -3.10232,-2.62303 -4.10706,-3.42687 -1.60405,-1.26922 -2.87318,-2.12139 -3.74863,-2.51425 -1.49828,-0.67086 -3.96605,-1.06372 -5.78162,-0.91867 -2.12109,0.17527 -3.73103,0.73132 -5.34094,1.84337 -1.56877,1.09396 -4.0718,3.55984 -4.41259,4.35764 -0.22915,0.53185 -0.36429,1.64394 -0.47003,3.83181 -0.0881,1.75272 -0.0295,2.87083 0.22915,4.59939 l 0.15864,1.05768 -0.35842,1.35985 c -0.55818,2.0912 -0.75797,3.56589 -0.82846,5.923 -0.0647,2.35711 0.15274,3.79555 0.74619,5.0285 0.76971,1.58348 3.02595,4.24885 4.67113,5.50597 0.97534,0.74943 2.35613,1.26316 4.02479,1.49887 0.87545,0.12693 2.73803,0.10877 3.3491,-0.0302 0.81083,-0.1813 2.06822,-0.62251 2.68516,-0.94285 1.16338,-0.59832 3.09058,-2.01259 5.51133,-4.04938 3.68402,-3.09445 5.15289,-4.273 5.75811,-4.60543 0.30552,-0.17527 0.40543,-0.19943 0.79319,-0.19943 0.38779,0 0.47593,0.0241 0.74622,0.18132 l 0.29965,0.18735 -1.41013,1.5049 c -6.71585,7.19222 -7.72645,8.43121 -9.03671,11.09052 -1.12811,2.29668 -1.90957,4.72026 -2.20336,6.82956 -0.18214,1.34779 -0.0705,3.91039 0.23501,5.1373 0.22329,0.90657 0.62281,1.90985 0.98711,2.44777 0.51707,0.7736 1.31027,1.78292 1.39253,1.78292 0.22915,0 1.40427,-0.95492 1.67456,-1.35986 0.11164,-0.16318 0.24678,-0.42306 0.29964,-0.57417 0.14102,-0.40495 0.16452,-1.29942 0.0588,-2.38128 -0.12337,-1.24503 -0.12337,-3.10655 -0.006,-3.81973 0.11752,-0.69503 0.48181,-2.08513 0.81673,-3.07632 0.61695,-1.86152 1.35728,-3.36039 2.6499,-5.37905 1.31026,-2.04283 3.6664,-5.13728 4.96489,-6.52133 0.52293,-0.55603 1.61581,-1.47469 1.68045,-1.41427 0.0234,0.0302 -0.4877,1.3357 -0.96359,2.43569 -0.32907,0.76756 -1.04589,2.23623 -1.68633,3.44501 -1.14575,2.16368 -1.56877,3.12468 -1.7098,3.88015 -0.22914,1.23899 -0.34078,2.84667 -0.34078,4.91367 0,1.81315 0.0116,2.11536 0.12924,2.90105 0.15278,0.98516 0.42892,2.36316 0.60521,2.97963 0.40539,1.42635 1.35139,2.97357 2.57351,4.21257 1.2339,1.25713 2.35614,1.84339 4.28921,2.24832 0.65804,0.13298 0.82846,0.13901 2.73804,0.0846 1.78619,-0.0544 2.35613,-0.19944 4.75924,-1.18459 1.38079,-0.56813 2.03297,-0.80384 2.87906,-1.0456 2.33851,-0.66482 4.13057,-0.84009 5.50546,-0.5379 0.62282,0.13902 0.62868,0.13902 0.85197,0.0241 0.12337,-0.0665 0.64631,-0.25989 1.15748,-0.42912 0.51708,-0.16923 1.14576,-0.42306 1.40427,-0.56811 1.69805,-0.93077 5.05893,-4.20654 5.74048,-5.60268 0.5288,-1.08789 0.92836,-3.29995 0.86372,-4.81092 -0.0823,-1.8615 -0.61694,-3.49335 -1.82143,-5.55431 -0.75796,-1.30547 -1.38667,-2.08515 -2.97307,-3.71698 -1.41014,-1.45053 -2.48538,-2.43568 -5.38205,-4.95597 -3.5959,-3.11863 -4.87679,-4.31532 -4.83566,-4.52081 0.012,-0.0606 0.0647,-0.0967 0.13515,-0.0846 0.21738,0.0424 1.4689,0.90657 4.74165,3.28183 3.38434,2.45378 4.7886,3.34224 6.17527,3.92248 3.11406,1.28731 6.35741,1.9582 9.04254,1.85544 1.54531,-0.0544 2.62055,-0.31428 3.83681,-0.92471 0.69918,-0.35054 1.8978,-1.16042 2.76153,-1.87359 0.84609,-0.69505 2.39723,-2.29063 2.77916,-2.85272 0.7697,-1.14228 1.31026,-3.37248 1.22799,-5.06474 -0.047,-0.92472 -0.19974,-1.61977 -0.74032,-3.44502 -0.54644,-1.84337 -0.91073,-3.21533 -1.01647,-3.80159 -0.12341,-0.70109 -0.094,-2.81644 0.0647,-4.17027 0.16452,-1.42031 0.22326,-3.50544 0.12924,-4.35159 -0.14687,-1.29942 -0.50529,-2.65325 -0.97533,-3.69885 -0.78732,-1.75271 -2.63229,-3.58402 -4.52422,-4.49663 -1.11637,-0.53186 -2.76156,-0.9368 -4.6535,-1.14832 -0.9871,-0.10275 -3.09059,-0.0424 -3.98365,0.12086 -1.43366,0.2599 -3.72516,0.93681 -4.20107,1.23295 -0.63457,0.3989 -2.21512,1.91592 -5.69937,5.44552 -1.40427,1.42636 -3.04356,3.0703 -3.64286,3.65051 -0.98711,0.96097 -1.66282,1.5291 -1.73333,1.45657 -0.0764,-0.0846 1.06348,-1.8736 3.87792,-6.09827 3.91315,-5.86859 4.48308,-6.86583 5.08829,-8.86635 0.8872,-2.95544 0.0411,-6.95045 -2.10935,-9.9905 -0.69922,-0.98516 -1.62168,-1.74668 -2.94957,-2.44175 -1.13399,-0.59228 -2.26211,-0.95492 -3.58413,-1.15436 -0.59931,-0.0907 -3.2492,-0.16924 -3.81914,-0.11483 z"
|
clipPathUnits="userSpaceOnUse"
|
||||||
id="path1-1-7"
|
id="clipPath18">
|
||||||
style="fill:#e5ffd5;fill-opacity:1;stroke:none;stroke-width:0.00595914" /><path
|
<circle
|
||||||
d="m 166.59227,332.97105 c -4.12429,0.42662 -8.02317,1.5205 -12.83475,3.62077 l -1.10432,0.4813 -1.82543,-0.86416 c -4.62007,-2.20966 -8.27101,-3.06288 -12.59815,-2.94255 -2.32129,0.0656 -3.39176,0.21877 -5.27361,0.79853 -6.5131,1.97994 -11.32468,7.43841 -12.77834,14.50492 -1.09306,5.25064 -0.38311,11.54049 1.78042,15.98166 1.83677,3.75203 4.57499,6.79303 12.23748,13.62981 3.52702,3.15038 8.64287,8.10569 10.52472,10.18408 1.88177,2.10025 3.4481,3.98173 3.4481,4.17864 0,0.16407 -0.45069,0.63444 -0.60853,0.63444 -0.0563,0 -0.67604,-0.60163 -1.39724,-1.34547 -15.06588,-15.45661 -24.88064,-22.01991 -35.1236,-23.5076 -0.68745,-0.0985 -2.14102,-0.1422 -4.56374,-0.1422 -3.84253,0.0109 -4.92426,0.10938 -7.944252,0.76572 -8.237179,1.78303 -14.479919,6.60706 -16.485689,12.74376 -0.61971,1.90335 -0.75496,2.78941 -0.74371,5.14126 0,1.88148 0.0453,2.29715 0.31552,3.55512 0.56344,2.60345 1.63392,5.31628 3.15516,7.97443 0.61978,1.08295 0.61978,1.09388 0.43952,1.47674 -1.81426,4.14583 -2.91856,7.76658 -3.42567,11.33266 -0.2141,1.45486 -0.18027,4.80214 0.0563,6.06012 0.66479,3.52231 2.3438,6.26796 5.03694,8.21511 4.10171,2.96443 10.49088,3.83951 17.826601,2.45029 8.69921,-1.65182 21.45505,-7.90882 31.46141,-15.45662 5.4877,-4.14582 10.08527,-8.7292 12.39531,-12.3609 0.41686,-0.65633 0.67604,-0.82042 0.80004,-0.50319 0.15775,0.38286 -2.77206,3.87235 -5.58913,6.66176 -2.36637,2.34091 -4.15805,3.93798 -8.56403,7.61344 -1.82543,1.52051 -3.95521,3.32541 -4.73275,4.00362 -8.38368,7.30718 -11.56135,12.63435 -13.01501,21.81209 -0.29294,1.82677 -0.34927,5.15214 -0.12393,6.67266 0.5747,3.76301 1.84802,6.45398 4.11297,8.65264 1.94944,1.89241 4.19188,3.01914 7.21179,3.6098 1.44233,0.28442 4.48483,0.3938 6.26525,0.21885 3.39176,-0.33911 7.66249,-1.37836 11.1895,-2.73471 0.76629,-0.29538 0.94655,-0.28442 1.52125,0.0656 0.83387,0.51414 2.91849,1.57522 3.85378,1.96901 3.32418,1.40019 5.88215,1.99085 8.95839,2.07841 1.65643,0.044 2.18612,0.0216 3.32418,-0.16408 8.23718,-1.3674 13.97282,-7.91972 15.42647,-17.63342 0.54087,-3.56607 0.49578,-7.97443 -0.11267,-11.09198 -0.10143,-0.56885 0.10142,-0.51415 1.02539,0.27346 6.24274,5.30535 11.43744,9.37459 16.85755,13.18124 5.97223,4.21151 10.27679,6.92431 14.90812,9.38556 1.90434,1.01734 5.08202,2.58159 5.22852,2.58159 0.11268,0 0.18034,-0.12034 0.94655,-1.85964 1.44233,-3.22694 2.23112,-6.18042 2.23112,-8.39004 0,-0.85325 -0.16901,-2.06744 -0.32677,-2.30813 -0.0453,-0.0763 -0.66479,-0.22973 -1.38599,-0.35006 -10.26554,-1.67365 -20.51974,-7.02273 -32.14877,-16.7474 -2.58047,-2.15492 -3.93271,-3.36912 -3.97779,-3.56602 -0.0454,-0.18596 0.10143,-0.12033 1.48749,0.66723 7.15538,4.12403 16.1701,5.75384 22.91995,4.16776 2.71565,-0.63448 5.09327,-1.89241 6.83986,-3.59892 1.84802,-1.8049 2.97491,-3.92703 3.57211,-6.73831 0.28168,-1.3783 0.39443,-4.37555 0.20284,-6.03825 -0.3606,-3.28166 -1.35224,-7.05555 -2.76073,-10.54505 -0.21417,-0.53601 -0.39444,-1.07201 -0.39444,-1.19233 0,-0.13128 0.2141,-0.56883 0.48453,-0.98451 1.96069,-3.10663 3.29042,-6.43204 3.74112,-9.35272 0.1465,-0.95167 0.18033,-1.67364 0.13525,-2.95348 -0.0902,-2.3628 -0.42819,-3.74109 -1.43107,-5.7429 -4.13555,-8.29165 -16.74489,-12.40465 -30.80787,-10.05281 -4.91301,0.82041 -9.9951,3.06289 -15.61798,6.89147 -3.92146,2.66909 -7.29072,5.49131 -12.23748,10.23877 -1.80301,1.73929 -3.31293,3.1504 -3.35801,3.1504 -0.13526,0 0.3606,-0.62352 1.78043,-2.24247 2.20861,-2.505 3.56077,-3.89423 9.25132,-9.46211 5.43136,-5.30534 6.94136,-6.84772 8.50769,-8.69639 4.01155,-4.69276 6.41167,-9.36365 7.53856,-14.65806 1.64517,-7.76658 0.60845,-14.51585 -2.90724,-18.77106 -2.45654,-2.98631 -5.93847,-4.51775 -10.5473,-4.62714 -0.99155,-0.0219 -2.00577,-0.0219 -2.25362,0 z"
|
style="opacity:1;mix-blend-mode:normal;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10.8382;stroke-opacity:0.566238;paint-order:stroke fill markers"
|
||||||
id="path1-2"
|
id="circle18"
|
||||||
style="fill:#e5ffd5;fill-opacity:1;stroke:none;stroke-width:0.0111024" /><path
|
cx="-246.8315"
|
||||||
d="m 465.56025,185.2456 c -0.9371,0.0986 -1.47259,0.23385 -2.432,0.62118 -1.53059,0.61754 -3.04333,1.57124 -4.03846,2.55052 -0.5444,0.52983 -1.4815,1.67354 -1.80279,2.19242 -0.22312,0.36175 -0.33468,0.90619 -0.51317,2.52859 -0.0937,0.82946 -0.13387,1.2643 -0.33915,3.59921 -0.19634,2.21435 -0.33021,3.3142 -0.41946,3.44212 -0.0714,0.106 -0.22757,-0.82218 -0.67382,-3.97194 -0.63812,-4.51274 -0.80322,-5.28374 -1.38334,-6.39822 -0.8657,-1.65162 -2.88269,-3.02554 -5.42178,-3.69057 -1.27179,-0.33251 -2.30706,-0.33982 -3.6904,-0.0292 -1.20484,0.27404 -2.23118,0.72349 -3.37355,1.49083 -1.02635,0.68697 -1.602,1.19121 -2.93624,2.56148 -1.25394,1.28623 -1.96345,2.07549 -2.22673,2.47378 -0.0893,0.13886 -0.1785,0.21559 -0.30791,0.27041 -0.22311,0.095 -0.3079,0.1498 -1.41011,0.88792 -1.22716,0.82581 -1.75372,1.20583 -2.2535,1.63701 -1.03526,0.89158 -1.57968,1.62238 -1.93221,2.60532 -0.23651,0.65772 -0.29452,1.01947 -0.29452,1.827 0.005,0.98659 0.13834,1.71739 0.40607,2.15224 0.22759,0.37636 1.04867,1.17293 1.61093,1.56756 0.87463,0.6139 2.75329,1.42144 4.13216,1.77955 1.81173,0.46771 3.55652,0.69789 7.45663,0.98655 3.1549,0.23386 4.33744,0.35079 4.65873,0.46043 l 0.15172,0.0512 -0.15172,0.13155 c -0.18742,0.15714 -0.415,0.21559 -1.15576,0.28502 -0.7943,0.0767 -1.86527,0.12425 -3.88226,0.16807 -3.71271,0.0804 -5.30578,0.18272 -6.47045,0.42022 -1.55737,0.31792 -3.56545,1.43604 -4.73013,2.63091 -1.22269,1.26066 -1.6957,2.38609 -1.94114,4.62235 -0.0893,0.78928 -0.0893,1.53834 0,1.77588 0.12049,0.33616 0.78985,1.15466 1.75372,2.14489 0.7006,0.7162 1.2227,1.16564 2.03039,1.73932 l 0.76753,0.54811 0.39714,0.69793 c 0.21866,0.38368 0.49534,0.84041 0.61582,1.01582 0.72737,1.0414 1.95452,2.36051 2.905,3.1242 0.89694,0.71983 1.52168,1.01581 2.67297,1.2643 1.55737,0.3398 3.95367,0.48599 4.9934,0.30326 1.19145,-0.2046 2.68635,-0.91716 3.79749,-1.80509 0.49978,-0.39828 1.01742,-1.00851 1.44134,-1.70644 0.52211,-0.85867 0.9371,-2.26182 1.51721,-5.1741 0.42838,-2.12665 0.69613,-3.29958 0.87016,-3.75634 0.17404,-0.45676 0.43286,-0.66868 0.91033,-0.74178 l 0.16956,-0.0254 -0.0268,0.30694 c -0.0357,0.40192 -0.18741,3.10593 -0.25434,4.52734 -0.058,1.20218 -0.0312,3.1242 0.0491,3.69057 0.19635,1.40679 0.81215,3.084 1.67339,4.56024 0.62919,1.07427 1.16021,1.68085 2.22672,2.54685 0.83001,0.67599 1.31195,0.98292 1.99024,1.26063 0.52655,0.21559 0.94155,0.32523 1.83849,0.47502 0.78092,0.13521 0.80323,0.13156 0.88355,-0.10588 0.0223,-0.0731 0.0848,-0.32156 0.13833,-0.55178 0.12496,-0.55542 0.0982,-0.76369 -0.14726,-1.16928 -0.16956,-0.28502 -0.24989,-0.36542 -1.02634,-0.99755 -1.36103,-1.11448 -1.72694,-1.50547 -2.26689,-2.41899 -1.24054,-2.09376 -1.70909,-3.80747 -1.94114,-7.08881 -0.11601,-1.6041 -0.0893,-2.96707 0.067,-3.54439 0.0893,-0.3435 0.0937,-0.34715 0.18741,-0.12792 0.46409,1.10352 0.79877,2.09743 1.19146,3.56269 0.53995,1.98414 0.65151,2.22164 1.602,3.33248 1.29855,1.52007 2.29812,2.41896 3.71269,3.33615 1.24501,0.80751 2.15534,1.17656 3.42265,1.38487 1.66893,0.27403 2.90054,0.14615 4.25264,-0.44217 0.70952,-0.31057 1.13791,-0.56269 1.43689,-0.84404 0.15172,-0.14251 0.44624,-0.37637 0.65597,-0.52256 0.81661,-0.55174 1.16467,-0.97196 2.15533,-2.59069 0.70952,-1.15469 1.16468,-1.7576 1.99468,-2.63091 0.62027,-0.6504 1.14683,-1.05236 1.76264,-1.352 l 0.53102,-0.25578 0.20973,-0.32887 c 0.11603,-0.18269 0.3213,-0.48598 0.46409,-0.67599 0.415,-0.56637 0.60689,-1.04871 0.80769,-2.02432 0.18742,-0.92446 0.26329,-1.65893 0.26329,-2.5615 -0.005,-1.02677 -0.0402,-1.16928 -0.52656,-1.97315 -1.02635,-1.69184 -2.28921,-2.65285 -4.35529,-3.31788 -1.01742,-0.32521 -1.91881,-0.51521 -2.96748,-0.62482 -1.35656,-0.14252 -1.72694,-0.14983 -6.69357,-0.14983 -2.75774,0 -4.89076,-0.0145 -4.92646,-0.0329 -0.0491,-0.0254 -0.0491,-0.0365 0.005,-0.0621 0.1428,-0.0658 1.16021,-0.17174 3.94028,-0.41655 3.67253,-0.32521 4.65426,-0.4604 5.84571,-0.82215 1.91883,-0.57735 3.35571,-1.20949 4.864,-2.1376 1.70909,-1.05239 2.5614,-1.99877 3.07904,-3.42018 0.34806,-0.94275 0.60242,-2.36781 0.60242,-3.32152 -0.005,-0.76369 -0.12049,-1.15833 -0.58011,-1.91836 -0.6649,-1.09621 -1.36549,-1.73567 -2.61942,-2.40071 -0.35252,-0.18635 -1.1513,-0.61388 -1.77156,-0.95004 -1.60646,-0.86236 -2.02592,-1.20583 -3.22184,-2.6236 -0.67829,-0.8112 -1.13345,-1.28988 -1.63322,-1.74297 -1.17807,-1.05967 -2.6462,-1.78682 -4.09647,-2.02433 -0.49532,-0.0841 -1.75818,-0.12059 -2.27581,-0.0695 z"
|
cy="246.8338"
|
||||||
id="path1-3-3"
|
inkscape:label="Circle"
|
||||||
style="fill:#e5ffd5;fill-opacity:1;stroke:none;stroke-width:0.00403802" /><path
|
r="191.89999" />
|
||||||
d="m 129.33803,187.58044 c -0.9371,0.10563 -1.47259,0.25052 -2.432,0.66548 -1.53059,0.66158 -3.04333,1.6833 -4.03846,2.73242 -0.5444,0.56761 -1.4815,1.79289 -1.80279,2.34878 -0.22312,0.38755 -0.33468,0.97082 -0.51317,2.70892 -0.0937,0.88862 -0.13387,1.35447 -0.33915,3.8559 -0.19634,2.37228 -0.33021,3.55057 -0.41946,3.68761 -0.0714,0.11356 -0.22757,-0.88082 -0.67382,-4.25521 -0.63812,-4.83459 -0.80322,-5.66057 -1.38334,-6.85453 -0.8657,-1.76942 -2.88269,-3.24132 -5.42178,-3.95378 -1.27179,-0.35622 -2.30706,-0.36406 -3.6904,-0.0313 -1.20484,0.29358 -2.23118,0.77509 -3.37355,1.59715 -1.02635,0.73596 -1.602,1.27617 -2.93624,2.74416 -1.25394,1.37796 -1.96345,2.22351 -2.22673,2.65021 -0.0893,0.14876 -0.178502,0.23096 -0.307912,0.28969 -0.22311,0.10178 -0.3079,0.16049 -1.41011,0.95125 -1.22716,0.8847 -1.75372,1.29183 -2.2535,1.75376 -1.03526,0.95516 -1.57968,1.73808 -1.93221,2.79112 -0.23651,0.70463 -0.29452,1.09218 -0.29452,1.9573 0.005,1.05695 0.13834,1.83987 0.40607,2.30574 0.22759,0.4032 1.04867,1.25658 1.61093,1.67935 0.87463,0.65769 2.75329,1.52282 4.132162,1.90647 1.81173,0.50106 3.55652,0.74766 7.45663,1.05691 3.1549,0.25054 4.33744,0.3758 4.65873,0.49326 l 0.15172,0.0549 -0.15172,0.14093 c -0.18742,0.16834 -0.415,0.23096 -1.15576,0.30534 -0.7943,0.0822 -1.86527,0.13312 -3.88226,0.18006 -3.71271,0.0861 -5.30578,0.19575 -6.47045,0.45019 -1.557372,0.34059 -3.565452,1.53846 -4.730132,2.81854 -1.22269,1.35057 -1.6957,2.55627 -1.94114,4.95201 -0.0893,0.84557 -0.0893,1.64805 0,1.90253 0.12049,0.36014 0.78985,1.23701 1.75372,2.29786 0.7006,0.76728 1.2227,1.24878 2.03039,1.86337 l 0.76753,0.5872 0.39714,0.74771 c 0.21866,0.41104 0.49534,0.90034 0.61582,1.08826 0.727372,1.11567 1.954522,2.52886 2.905002,3.34702 0.89694,0.77116 1.52168,1.08825 2.67297,1.35446 1.55737,0.36404 3.95367,0.52065 4.9934,0.32489 1.19145,-0.21919 2.68635,-0.98257 3.79749,-1.93382 0.49978,-0.42669 1.01742,-1.08044 1.44134,-1.82815 0.52211,-0.9199 0.9371,-2.42312 1.51721,-5.5431 0.42838,-2.27832 0.69613,-3.5349 0.87016,-4.02424 0.17404,-0.48934 0.43286,-0.71637 0.91033,-0.79468 l 0.16956,-0.0272 -0.0268,0.32883 c -0.0357,0.43058 -0.18741,3.32744 -0.25434,4.85022 -0.058,1.28792 -0.0312,3.34701 0.0491,3.95377 0.19635,1.50712 0.81215,3.30395 1.67339,4.88547 0.62919,1.15089 1.16021,1.80073 2.22672,2.72849 0.83001,0.7242 1.31195,1.05302 1.99024,1.35054 0.52655,0.23096 0.94155,0.34842 1.83849,0.50889 0.78092,0.14486 0.80323,0.14095 0.88355,-0.11343 0.0223,-0.0783 0.0848,-0.34449 0.13833,-0.59113 0.12496,-0.59503 0.0982,-0.81815 -0.14726,-1.25267 -0.16956,-0.30535 -0.24989,-0.39148 -1.02634,-1.06869 -1.36103,-1.19397 -1.72694,-1.61284 -2.26689,-2.59151 -1.24054,-2.24309 -1.70909,-4.07901 -1.94114,-7.59437 -0.11601,-1.71851 -0.0893,-3.17868 0.067,-3.79717 0.0893,-0.368 0.0937,-0.37191 0.18741,-0.13705 0.46409,1.18222 0.79877,2.24702 1.19146,3.81678 0.53995,2.12564 0.65151,2.38008 1.602,3.57014 1.29855,1.62848 2.29812,2.59148 3.71269,3.57408 1.24501,0.8651 2.15534,1.26047 3.42265,1.48364 1.66893,0.29357 2.90054,0.15657 4.25264,-0.4737 0.70952,-0.33272 1.13791,-0.60282 1.43689,-0.90424 0.15172,-0.15267 0.44624,-0.40321 0.65597,-0.55983 0.81661,-0.59109 1.16467,-1.04128 2.15533,-2.77545 0.70952,-1.23704 1.16468,-1.88295 1.99468,-2.81854 0.62027,-0.69679 1.14683,-1.12742 1.76264,-1.44843 l 0.53102,-0.27402 0.20973,-0.35232 c 0.11603,-0.19572 0.3213,-0.52064 0.46409,-0.7242 0.415,-0.60677 0.60689,-1.12351 0.80769,-2.1687 0.18742,-0.99039 0.26329,-1.77724 0.26329,-2.74418 -0.005,-1.09999 -0.0402,-1.25267 -0.52656,-2.11387 -1.02635,-1.8125 -2.28921,-2.84205 -4.35529,-3.55451 -1.01742,-0.3484 -1.91881,-0.55195 -2.96748,-0.66938 -1.35656,-0.15268 -1.72694,-0.16051 -6.69357,-0.16051 -2.75774,0 -4.89076,-0.0155 -4.92646,-0.0353 -0.0491,-0.0272 -0.0491,-0.0391 0.005,-0.0665 0.1428,-0.0705 1.16021,-0.18399 3.94028,-0.44625 3.67253,-0.34841 4.65426,-0.49324 5.84571,-0.88079 1.91883,-0.61853 3.35571,-1.29575 4.864,-2.29005 1.70909,-1.12744 2.5614,-2.14132 3.07904,-3.6641 0.34806,-1.00999 0.60242,-2.53668 0.60242,-3.55841 -0.005,-0.81815 -0.12049,-1.24094 -0.58011,-2.05517 -0.6649,-1.17439 -1.36549,-1.85946 -2.61942,-2.57193 -0.35252,-0.19964 -1.1513,-0.65766 -1.77156,-1.01779 -1.60646,-0.92386 -2.02592,-1.29183 -3.22184,-2.81071 -0.67829,-0.86906 -1.13345,-1.38187 -1.63322,-1.86728 -1.17807,-1.13524 -2.6462,-1.91425 -4.09647,-2.1687 -0.49532,-0.0901 -1.75818,-0.12919 -2.27581,-0.0745 z"
|
</clipPath>
|
||||||
id="path1-3-3-3"
|
<clipPath
|
||||||
style="fill:#e5ffd5;fill-opacity:1;stroke:none;stroke-width:0.00417953" /><path
|
clipPathUnits="userSpaceOnUse"
|
||||||
d="m 181.97617,266.85651 c -0.67575,0.64029 -1.01388,1.06776 -1.53142,1.94677 -0.82591,1.402 -1.43323,3.05558 -1.61859,4.41795 -0.10501,0.74073 -0.14474,2.1965 -0.0812,2.79453 0.0449,0.41641 0.28862,0.90832 1.13586,2.28156 0.4312,0.70353 0.66429,1.06698 1.92402,3.01229 1.1934,1.84589 1.7576,2.78457 1.76538,2.93802 0.008,0.12563 -0.679,-0.50471 -2.94617,-2.69417 -3.24722,-3.13763 -3.84604,-3.63997 -4.97973,-4.16083 -1.68478,-0.76832 -4.10447,-0.62779 -6.50269,0.37974 -1.20085,0.50514 -2.01813,1.12178 -2.91522,2.19577 -0.77918,0.93815 -1.31147,1.90587 -1.74142,3.19138 -0.38776,1.15305 -0.53286,1.89258 -0.74653,3.76389 -0.20177,1.75747 -0.27852,2.79987 -0.24285,3.26893 0.0145,0.16203 -0.009,0.27552 -0.0772,0.3961 -0.11736,0.20827 -0.15058,0.30199 -0.56677,1.54057 -0.46093,1.38212 -0.64309,1.99519 -0.77308,2.63208 -0.27025,1.31807 -0.25296,2.21559 0.0684,3.19451 0.21449,0.65542 0.3892,0.97253 0.88059,1.60266 0.60431,0.7668 1.15373,1.25688 1.62856,1.43525 0.40772,0.15685 1.53713,0.2848 2.21873,0.25469 1.06028,-0.0468 3.02671,-0.54603 4.32722,-1.09559 1.70709,-0.72416 3.21702,-1.59353 6.45478,-3.71296 2.61931,-1.71416 3.6189,-2.33386 3.93789,-2.44144 l 0.15029,-0.0513 -0.0391,0.19387 c -0.0515,0.23528 -0.19464,0.41769 -0.73398,0.9172 -0.57692,0.53738 -1.38886,1.21831 -2.94579,2.46507 -2.86604,2.29471 -4.05453,3.33228 -4.82441,4.21777 -1.02926,1.18432 -1.92543,3.264 -2.11272,4.89652 -0.19279,1.71872 0.12071,2.88127 1.28889,4.77374 0.4102,0.66956 0.86603,1.25404 1.0807,1.3857 0.29919,0.18988 1.32282,0.42613 2.68218,0.61934 0.9859,0.13767 1.66933,0.17448 2.65257,0.13657 l 0.93618,-0.0338 0.73652,0.30584 c 0.40517,0.16793 0.90034,0.35798 1.10167,0.4224 1.20483,0.37532 2.97105,0.66689 4.18203,0.69137 1.14227,0.0225 1.8129,-0.12216 2.86802,-0.62038 1.42954,-0.67109 3.39989,-1.99764 4.10501,-2.76527 0.81094,-0.87594 1.551,-2.33064 1.88304,-3.69146 0.15001,-0.61124 0.18507,-1.39859 0.0932,-2.19803 -0.11263,-0.98388 -0.64069,-2.32822 -1.9575,-4.9494 -0.95783,-1.91694 -1.4614,-2.99312 -1.60274,-3.45416 -0.14127,-0.46104 -0.067,-0.782 0.26333,-1.12607 l 0.11765,-0.12184 0.16576,0.25561 c 0.21655,0.33508 1.74296,2.53621 2.55542,3.68556 0.68604,0.97289 1.87672,2.45652 2.28443,2.85018 1.01026,0.97967 2.51442,1.91816 4.08896,2.55231 1.14775,0.45998 1.9338,0.61405 3.29816,0.64862 1.06302,0.0285 1.6282,-0.0218 2.32975,-0.21281 0.5446,-0.14832 0.93714,-0.31233 1.73252,-0.73457 0.69541,-0.36398 0.71074,-0.3802 0.62928,-0.6138 -0.0268,-0.0705 -0.12909,-0.3019 -0.22718,-0.51371 -0.23993,-0.5085 -0.38765,-0.65493 -0.82719,-0.82384 -0.30658,-0.12047 -0.41856,-0.13492 -1.41286,-0.16137 -1.74681,-0.0514 -2.27202,-0.13652 -3.25188,-0.52473 -2.24814,-0.88795 -3.65889,-1.94345 -5.83794,-4.36435 -1.06726,-1.18192 -1.87572,-2.26149 -2.10432,-2.80592 -0.13894,-0.32171 -0.1378,-0.32718 0.0693,-0.21249 1.0359,0.58207 1.90353,1.15641 3.10353,2.06365 1.63136,1.22361 1.86349,1.34186 3.28575,1.63722 1.94456,0.40544 3.27637,0.50592 4.94514,0.37119 1.46891,-0.11838 2.40822,-0.37767 3.52998,-0.97701 1.47709,-0.78951 2.36624,-1.62971 3.0698,-2.90161 0.36807,-0.66889 0.55097,-1.12316 0.6145,-1.52243 0.0324,-0.20242 0.12132,-0.56194 0.19702,-0.8021 0.30538,-0.92146 0.32292,-1.45858 0.11565,-3.31723 -0.14562,-1.32753 -0.15518,-2.07161 -0.035,-3.25201 0.0912,-0.88041 0.25999,-1.5106 0.56112,-2.11463 l 0.26129,-0.51882 -0.0355,-0.38269 c -0.02,-0.21234 -0.0435,-0.57237 -0.047,-0.80647 -0.0188,-0.69142 -0.1617,-1.18315 -0.59777,-2.06513 -0.41543,-0.83401 -0.80282,-1.45273 -1.35208,-2.15699 -0.62876,-0.79817 -0.74312,-0.88822 -1.61417,-1.22307 -1.83539,-0.70311 -3.41173,-0.69377 -5.43857,0.0294 -0.9967,0.3579 -1.82002,0.75157 -2.71008,1.29644 -1.1518,0.70434 -1.44705,0.9213 -5.34648,3.90712 -2.16519,1.65789 -3.84869,2.92893 -3.88796,2.93596 -0.054,0.009 -0.0608,10e-4 -0.0338,-0.0515 0.0721,-0.13718 0.80639,-0.83149 2.84013,-2.69382 2.6855,-2.4616 3.37401,-3.15727 4.08931,-4.15582 1.15518,-1.60406 1.89863,-2.96113 2.51803,-4.59207 0.70142,-1.84864 0.79467,-3.09948 0.3361,-4.51978 -0.30049,-0.94486 -0.96796,-2.20974 -1.54836,-2.95392 -0.46865,-0.59288 -0.79949,-0.83139 -1.62286,-1.14813 -1.18913,-0.45564 -2.12833,-0.53342 -3.51754,-0.29852 -0.39015,0.0666 -1.27749,0.2131 -1.96905,0.3237 -1.78606,0.29293 -2.32442,0.27703 -4.12615,-0.11028 -1.02621,-0.2252 -1.67487,-0.32508 -2.34298,-0.37816 -1.5698,-0.11863 -3.16497,0.19659 -4.44811,0.88336 -0.44007,0.23218 -1.45377,0.96289 -1.82913,1.31389 z"
|
id="clipPath22">
|
||||||
id="path1-3-3-3-6"
|
<circle
|
||||||
style="fill:#e5ffd5;fill-opacity:1;stroke:none;stroke-width:0.00399432"
|
style="opacity:1;mix-blend-mode:normal;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10.8382;stroke-opacity:0.566238;paint-order:stroke fill markers"
|
||||||
inkscape:transform-center-x="323.33333"
|
id="circle22"
|
||||||
inkscape:transform-center-y="-3.4874273" /><path
|
cx="256"
|
||||||
d="m 309.70135,218.68714 c -0.77928,0.0869 -1.22459,0.20605 -2.02242,0.54734 -1.27283,0.54414 -2.53081,1.38448 -3.35835,2.24735 -0.45271,0.46686 -1.232,1.47462 -1.49918,1.93182 -0.18554,0.31876 -0.27831,0.79848 -0.42674,2.22804 -0.0779,0.73086 -0.11133,1.11402 -0.28204,3.17139 -0.16327,1.95114 -0.2746,2.92026 -0.34882,3.03298 -0.0594,0.0934 -0.18924,-0.72446 -0.56034,-3.49982 -0.53065,-3.97634 -0.66795,-4.6557 -1.15037,-5.63771 -0.7199,-1.4553 -2.39721,-2.66591 -4.50869,-3.25189 -1.05761,-0.29299 -1.91853,-0.29943 -3.0689,-0.0257 -1.00193,0.24147 -1.85543,0.63749 -2.80541,1.31362 -0.8535,0.60532 -1.33221,1.04962 -2.44175,2.25702 -1.04276,1.13334 -1.63278,1.82879 -1.85172,2.17973 -0.0743,0.12236 -0.14844,0.18997 -0.25606,0.23827 -0.18553,0.0837 -0.25604,0.13199 -1.17263,0.78238 -1.02049,0.72765 -1.45837,1.0625 -1.87398,1.44243 -0.86092,0.7856 -1.31365,1.42953 -1.60681,2.29564 -0.19668,0.57954 -0.24492,0.89829 -0.24492,1.60983 0.004,0.86932 0.11504,1.51326 0.33768,1.89642 0.18926,0.33162 0.87207,1.03351 1.33964,1.38123 0.72733,0.54093 2.2896,1.25249 3.43626,1.56803 1.50661,0.41212 2.95756,0.61494 6.20085,0.86928 2.62358,0.20607 3.60697,0.3091 3.87415,0.40571 l 0.12617,0.0451 -0.12617,0.11591 c -0.15585,0.13846 -0.34511,0.18996 -0.96112,0.25114 -0.66053,0.0676 -1.55113,0.10948 -3.22844,0.14809 -3.08745,0.0708 -4.41223,0.161 -5.38076,0.37027 -1.29509,0.28013 -2.96499,1.26535 -3.93353,2.31819 -1.01677,1.11082 -1.41012,2.10247 -1.61423,4.07292 -0.0743,0.69547 -0.0743,1.35549 0,1.56479 0.1002,0.29621 0.65683,1.01742 1.45838,1.88994 0.58261,0.63107 1.01678,1.02709 1.68845,1.53258 l 0.63827,0.48296 0.33026,0.61497 c 0.18183,0.33808 0.41191,0.74052 0.5121,0.89508 0.60488,0.91761 1.62536,2.07993 2.41577,2.75284 0.74589,0.63427 1.26542,0.89507 2.22282,1.11402 1.29509,0.29941 3.28783,0.42823 4.15245,0.26722 0.9908,-0.18028 2.23394,-0.80815 3.15796,-1.59053 0.41561,-0.35094 0.84607,-0.88864 1.1986,-1.50361 0.43418,-0.7566 0.77928,-1.99297 1.2617,-4.55909 0.35623,-1.87386 0.57889,-2.90737 0.72361,-3.30984 0.14473,-0.40247 0.35996,-0.5892 0.75702,-0.65361 l 0.14101,-0.0224 -0.0223,0.27046 c -0.0297,0.35414 -0.15585,2.73674 -0.21151,3.9892 -0.0482,1.05928 -0.0259,2.75284 0.0408,3.25189 0.16328,1.23958 0.67537,2.71743 1.39157,4.01819 0.52323,0.94658 0.96482,1.48106 1.85172,2.24412 0.69022,0.59564 1.091,0.86609 1.65506,1.11079 0.43787,0.18996 0.78298,0.28657 1.52887,0.41856 0.6494,0.11914 0.66795,0.11592 0.73475,-0.0933 0.0185,-0.0644 0.0705,-0.28334 0.11503,-0.4862 0.10392,-0.4894 0.0817,-0.67291 -0.12246,-1.03029 -0.141,-0.25114 -0.2078,-0.32198 -0.85349,-0.87898 -1.13182,-0.98201 -1.43611,-1.32652 -1.88512,-2.13146 -1.03162,-1.84488 -1.42126,-3.35489 -1.61424,-6.2462 -0.0965,-1.41343 -0.0743,-2.61439 0.0557,-3.12309 0.0743,-0.30267 0.0779,-0.30589 0.15585,-0.11272 0.38593,0.97236 0.66425,1.84813 0.99081,3.13922 0.44901,1.7483 0.54178,1.95757 1.3322,2.93637 1.07986,1.33938 1.91109,2.13143 3.08744,2.9396 1.03533,0.71152 1.79235,1.03671 2.84623,1.22026 1.38787,0.24145 2.41206,0.12878 3.53646,-0.38961 0.59002,-0.27366 0.94627,-0.49581 1.1949,-0.74372 0.12617,-0.12557 0.37109,-0.33163 0.5455,-0.46045 0.67908,-0.48615 0.96852,-0.85642 1.79235,-2.28275 0.59002,-1.01743 0.96853,-1.54868 1.65875,-2.31818 0.51581,-0.5731 0.95369,-0.92728 1.46579,-1.1913 l 0.44159,-0.22538 0.17441,-0.28978 c 0.0965,-0.16097 0.26719,-0.42821 0.38594,-0.59564 0.34511,-0.49904 0.50468,-0.92405 0.67166,-1.7837 0.15586,-0.81457 0.21895,-1.46174 0.21895,-2.25703 -0.004,-0.90472 -0.0334,-1.03029 -0.43788,-1.73861 -0.8535,-1.49074 -1.90368,-2.33752 -3.62181,-2.9235 -0.84608,-0.28656 -1.59567,-0.45397 -2.46773,-0.55056 -1.1281,-0.12557 -1.4361,-0.13202 -5.5663,-0.13202 -2.29331,0 -4.06711,-0.0128 -4.09679,-0.029 -0.0408,-0.0224 -0.0408,-0.0322 0.004,-0.0547 0.11876,-0.058 0.96482,-0.15132 3.2767,-0.36703 3.05404,-0.28656 3.87043,-0.40568 4.86123,-0.72443 1.59568,-0.50872 2.79057,-1.06572 4.04485,-1.88352 1.42126,-0.92729 2.13004,-1.76118 2.5605,-3.01364 0.28944,-0.83069 0.50097,-2.08636 0.50097,-2.92671 -0.004,-0.67291 -0.1002,-1.02065 -0.48242,-1.69034 -0.55292,-0.96591 -1.13553,-1.52936 -2.17828,-2.11535 -0.29315,-0.1642 -0.95741,-0.54091 -1.47321,-0.83711 -1.33592,-0.75986 -1.68473,-1.0625 -2.67925,-2.31175 -0.56406,-0.71478 -0.94256,-1.13656 -1.35817,-1.53579 -0.97967,-0.93372 -2.20055,-1.57444 -3.40658,-1.78371 -0.4119,-0.0741 -1.46208,-0.10626 -1.89254,-0.0612 z"
|
cy="256"
|
||||||
id="path1-3-3-2"
|
inkscape:label="Circle"
|
||||||
style="fill:#e5ffd5;fill-opacity:1;stroke:none;stroke-width:0.00345656" /><path
|
r="191.89999" />
|
||||||
d="m 434.17193,103.02813 c -0.71225,0.32793 -1.09736,0.58128 -1.74709,1.15649 -1.03665,0.91735 -1.96592,2.11115 -2.47956,3.19075 -0.28262,0.58569 -0.70482,1.78761 -0.8144,2.30569 -0.0757,0.36098 -0.0126,0.8455 0.29675,2.24905 0.15627,0.71819 0.24522,1.09238 0.73122,3.0988 0.45959,1.90326 0.65918,2.85811 0.62424,2.98847 -0.027,0.10736 -0.4078,-0.62798 -1.63417,-3.14519 -1.75608,-3.60681 -2.10037,-4.20834 -2.86754,-4.98842 -1.14163,-1.15448 -3.11488,-1.77516 -5.30345,-1.66626 -1.09607,0.055 -1.9152,0.3201 -2.9208,0.94223 -0.87487,0.54476 -1.56019,1.18945 -2.24886,2.13038 -0.6194,0.84334 -0.9338,1.41581 -1.60657,2.91123 -0.63271,1.40409 -0.97365,2.24998 -1.07091,2.65202 -0.032,0.13953 -0.0811,0.22706 -0.16798,0.30679 -0.14972,0.13788 -0.20143,0.20592 -0.86652,1.11191 -0.73935,1.01204 -1.04948,1.46776 -1.32427,1.95926 -0.56965,1.01678 -0.79652,1.77053 -0.80196,2.6849 -0.004,0.61199 0.0505,0.92971 0.2746,1.60503 0.27761,0.82381 0.58582,1.4 0.91781,1.69353 0.28408,0.25513 1.15321,0.70623 1.7065,0.88898 0.86069,0.28431 2.56757,0.46758 3.75525,0.40589 1.55973,-0.0834 3.00071,-0.34791 6.15903,-1.12806 2.55495,-0.63077 3.52074,-0.84273 3.80475,-0.83519 l 0.13395,0.003 -0.0832,0.14975 c -0.10431,0.1805 -0.26771,0.28899 -0.8331,0.54108 -0.60562,0.27221 -1.43769,0.59247 -3.01747,1.15742 -2.908,1.03966 -4.13694,1.54254 -4.99026,2.04621 -1.14094,0.67379 -2.41552,2.13484 -3.00315,3.43915 -0.61514,1.37454 -0.67613,2.43961 -0.24921,4.37405 0.14854,0.68348 0.35642,1.3099 0.49286,1.48515 0.1884,0.24957 0.94386,0.75875 1.97943,1.33439 0.75173,0.41544 1.28854,0.65456 2.08523,0.92276 l 0.7579,0.25734 0.50715,0.47965 c 0.27906,0.2636 0.62419,0.57308 0.76796,0.68822 0.86312,0.68038 2.19775,1.46212 3.15988,1.85182 0.9077,0.36705 1.48293,0.45094 2.46057,0.35719 1.32347,-0.12374 3.25536,-0.62914 4.02526,-1.05428 0.88358,-0.48318 1.86569,-1.47065 2.49625,-2.50425 0.28392,-0.46398 0.52311,-1.1099 0.66399,-1.8046 0.17378,-0.85485 0.11189,-2.13698 -0.2385,-4.72444 -0.25212,-1.89068 -0.36632,-2.94172 -0.35573,-3.36929 0.0106,-0.42757 0.15606,-0.67259 0.51262,-0.85878 l 0.12678,-0.0657 0.064,0.26371 c 0.0833,0.34547 0.71408,2.64653 1.05574,3.85278 0.2879,1.02054 0.84249,2.62088 1.06298,3.07352 0.5454,1.12506 1.49691,2.36639 2.58636,3.37536 0.79474,0.7336 1.3822,1.10178 2.4643,1.54666 0.8427,0.34792 1.30827,0.47837 1.92069,0.53295 0.47541,0.0424 0.83339,0.0254 1.58289,-0.0843 0.65387,-0.0915 0.67046,-0.10036 0.66796,-0.31997 -0.003,-0.067 -0.0223,-0.29113 -0.044,-0.49769 -0.0555,-0.49722 -0.13441,-0.66439 -0.44074,-0.93928 -0.21293,-0.19394 -0.29864,-0.24014 -1.08691,-0.56541 -1.38351,-0.57554 -1.78083,-0.80667 -2.46052,-1.42921 -1.56019,-1.42605 -2.40561,-2.73647 -3.49945,-5.41983 -0.53678,-1.3111 -0.89398,-2.45792 -0.93082,-2.98168 -0.0248,-0.31066 -0.0224,-0.31485 0.11241,-0.15607 0.67255,0.80131 1.21255,1.54485 1.92915,2.66736 0.97682,1.51789 1.13078,1.68729 2.18926,2.36731 1.44677,0.93108 2.48516,1.421 3.85619,1.81752 1.20674,0.3492 2.02765,0.4194 3.08571,0.26166 1.39327,-0.20798 2.32985,-0.6375 3.23374,-1.48366 0.47379,-0.44557 0.74194,-0.76863 0.89983,-1.08223 0.0802,-0.15892 0.24774,-0.43163 0.3727,-0.60883 0.49139,-0.6753 0.64948,-1.11789 0.98212,-2.7311 0.23953,-1.15148 0.43144,-1.77491 0.84416,-2.72265 0.30904,-0.70639 0.61308,-1.18046 1.01595,-1.59234 l 0.34813,-0.353 0.0743,-0.32997 c 0.0409,-0.18317 0.11872,-0.49057 0.17869,-0.68688 0.17036,-0.58234 0.18794,-1.03598 0.0756,-1.90446 -0.10864,-0.8222 -0.2526,-1.45631 -0.50309,-2.21112 -0.28876,-0.85741 -0.35622,-0.96733 -0.96321,-1.51219 -1.2796,-1.14604 -2.54304,-1.61894 -4.35828,-1.63393 -0.89328,-0.005 -1.65744,0.0717 -2.51554,0.25473 -1.11023,0.23614 -1.40459,0.32703 -5.32456,1.62793 -2.17659,0.72233 -3.86413,1.26888 -3.8974,1.26285 -0.0458,-0.008 -0.0489,-0.0177 -0.0134,-0.0532 0.0944,-0.0925 0.86805,-0.44751 2.99432,-1.38042 2.80833,-1.23391 3.54565,-1.60411 4.38562,-2.21871 1.35423,-0.98542 2.31286,-1.89043 3.24571,-3.06167 1.05685,-1.32775 1.4669,-2.34244 1.48096,-3.66673 0.0131,-0.87958 -0.18167,-2.13796 -0.44636,-2.93554 -0.21574,-0.6374 -0.41657,-0.93714 -0.99027,-1.45235 -0.82901,-0.74259 -1.55944,-1.09386 -2.73369,-1.32158 -0.32994,-0.0635 -1.07905,-0.21183 -1.66189,-0.33049 -1.50726,-0.3004 -1.93364,-0.47777 -3.27101,-1.35019 -0.76049,-0.50074 -1.25257,-0.78183 -1.77278,-1.02983 -1.2239,-0.57763 -2.58444,-0.80119 -3.795,-0.61995 -0.41428,0.0594 -1.42113,0.35967 -1.81549,0.53802 z"
|
</clipPath>
|
||||||
id="path1-3-3-2-0"
|
<linearGradient
|
||||||
style="fill:#e5ffd5;fill-opacity:1;stroke:none;stroke-width:0.00345656" /><path
|
inkscape:collect="always"
|
||||||
d="m 99.090959,92.821662 c -0.71225,0.32793 -1.09736,0.58128 -1.74709,1.15649 -1.03665,0.91735 -1.96592,2.11115 -2.47956,3.19075 -0.28262,0.58569 -0.70482,1.78761 -0.8144,2.30569 -0.0757,0.36098 -0.0126,0.845498 0.29675,2.249048 0.15627,0.71819 0.24522,1.09238 0.73122,3.0988 0.45959,1.90326 0.65918,2.85811 0.62424,2.98847 -0.027,0.10736 -0.4078,-0.62798 -1.63417,-3.14519 -1.75608,-3.60681 -2.10037,-4.20834 -2.86754,-4.988418 -1.14163,-1.15448 -3.11488,-1.77516 -5.30345,-1.66626 -1.09607,0.055 -1.9152,0.3201 -2.9208,0.94223 -0.87487,0.54476 -1.56019,1.189448 -2.24886,2.130378 -0.6194,0.84334 -0.9338,1.41581 -1.60657,2.91123 -0.63271,1.40409 -0.97365,2.24998 -1.07091,2.65202 -0.032,0.13953 -0.0811,0.22706 -0.16798,0.30679 -0.14972,0.13788 -0.20143,0.20592 -0.86652,1.11191 -0.73935,1.01204 -1.04948,1.46776 -1.32427,1.95926 -0.56965,1.01678 -0.79652,1.77053 -0.80196,2.6849 -0.004,0.61199 0.0505,0.92971 0.2746,1.60503 0.27761,0.82381 0.58582,1.4 0.91781,1.69353 0.28408,0.25513 1.15321,0.70623 1.7065,0.88898 0.86069,0.28431 2.56757,0.46758 3.75525,0.40589 1.55973,-0.0834 3.00071,-0.34791 6.15903,-1.12806 2.55495,-0.63077 3.52074,-0.84273 3.80475,-0.83519 l 0.13395,0.003 -0.0832,0.14975 c -0.10431,0.1805 -0.26771,0.28899 -0.8331,0.54108 -0.60562,0.27221 -1.43769,0.59247 -3.01747,1.15742 -2.908,1.03966 -4.13694,1.54254 -4.99026,2.04621 -1.14094,0.67379 -2.41552,2.13484 -3.00315,3.43915 -0.61514,1.37454 -0.67613,2.43961 -0.24921,4.37405 0.14854,0.68348 0.35642,1.3099 0.49286,1.48515 0.1884,0.24957 0.94386,0.75875 1.97943,1.33439 0.75173,0.41544 1.28854,0.65456 2.08523,0.92276 l 0.7579,0.25734 0.50715,0.47965 c 0.27906,0.2636 0.62419,0.57308 0.76796,0.68822 0.86312,0.68038 2.19775,1.46212 3.15988,1.85182 0.9077,0.36705 1.48293,0.45094 2.46057,0.35719 1.32347,-0.12374 3.25536,-0.62914 4.02526,-1.05428 0.88358,-0.48318 1.86569,-1.47065 2.49625,-2.50425 0.28392,-0.46398 0.52311,-1.1099 0.66399,-1.8046 0.17378,-0.85485 0.11189,-2.13698 -0.2385,-4.72444 -0.25212,-1.89068 -0.36632,-2.94172 -0.35573,-3.36929 0.0106,-0.42757 0.15606,-0.67259 0.51262,-0.85878 l 0.12678,-0.0657 0.064,0.26371 c 0.0833,0.34547 0.71408,2.64653 1.055741,3.85278 0.2879,1.02054 0.84249,2.62088 1.06298,3.07352 0.5454,1.12506 1.49691,2.36639 2.58636,3.37536 0.79474,0.7336 1.3822,1.10178 2.4643,1.54666 0.8427,0.34792 1.30827,0.47837 1.92069,0.53295 0.47541,0.0424 0.83339,0.0254 1.58289,-0.0843 0.65387,-0.0915 0.67046,-0.10036 0.66796,-0.31997 -0.003,-0.067 -0.0223,-0.29113 -0.044,-0.49769 -0.0555,-0.49722 -0.13441,-0.66439 -0.44074,-0.93928 -0.21293,-0.19394 -0.29864,-0.24014 -1.08691,-0.56541 -1.38351,-0.57554 -1.78083,-0.80667 -2.46052,-1.42921 -1.56019,-1.42605 -2.40561,-2.73647 -3.49945,-5.41983 -0.53678,-1.3111 -0.89398,-2.45792 -0.93082,-2.98168 -0.0248,-0.31066 -0.0224,-0.31485 0.11241,-0.15607 0.67255,0.80131 1.21255,1.54485 1.92915,2.66736 0.97682,1.51789 1.13078,1.68729 2.18926,2.36731 1.44677,0.93108 2.48516,1.421 3.85619,1.81752 1.20674,0.3492 2.02765,0.4194 3.08571,0.26166 1.39327,-0.20798 2.32985,-0.6375 3.23374,-1.48366 0.47379,-0.44557 0.74194,-0.76863 0.89983,-1.08223 0.0802,-0.15892 0.24774,-0.43163 0.3727,-0.60883 0.49139,-0.6753 0.64948,-1.11789 0.98212,-2.7311 0.23953,-1.15148 0.43144,-1.77491 0.84416,-2.72265 0.30904,-0.70639 0.61308,-1.18046 1.01595,-1.59234 l 0.34813,-0.353 0.0743,-0.32997 c 0.0409,-0.18317 0.11872,-0.49057 0.17869,-0.68688 0.17036,-0.58234 0.18794,-1.03598 0.0756,-1.90446 -0.10864,-0.8222 -0.2526,-1.45631 -0.50309,-2.21112 -0.28876,-0.85741 -0.35622,-0.96733 -0.96321,-1.51219 -1.2796,-1.14604 -2.54304,-1.61894 -4.35828,-1.63393 -0.89328,-0.005 -1.65744,0.0717 -2.51554,0.25473 -1.11023,0.23614 -1.40459,0.32703 -5.32456,1.62793 -2.17659,0.72233 -3.86413,1.26888 -3.8974,1.26285 -0.0458,-0.008 -0.0489,-0.0177 -0.0134,-0.0532 0.0944,-0.0925 0.86805,-0.44751 2.99432,-1.38042 2.80833,-1.23391 3.54565,-1.60411 4.38562,-2.21871 1.35423,-0.98542 2.31286,-1.89043 3.24571,-3.06167 1.05685,-1.32775 1.4669,-2.34244 1.48096,-3.66673 0.0131,-0.87958 -0.18167,-2.137958 -0.44636,-2.935538 -0.21574,-0.6374 -0.41657,-0.93714 -0.99027,-1.45235 -0.82901,-0.74259 -1.55944,-1.09386 -2.73369,-1.32158 -0.32994,-0.0635 -1.07905,-0.21183 -1.66189,-0.33049 -1.50726,-0.3004 -1.93364,-0.47777 -3.27101,-1.35019 -0.76049,-0.50074 -1.25257,-0.78183 -1.77278,-1.02983 -1.2239,-0.57763 -2.58444,-0.80119 -3.795,-0.61995 -0.41428,0.0594 -1.421131,0.35967 -1.815491,0.53802 z"
|
xlink:href="#linearGradient11"
|
||||||
id="path1-3-3-2-0-4"
|
id="linearGradient27"
|
||||||
style="fill:#e5ffd5;fill-opacity:1;stroke:none;stroke-width:0.00345656" /></svg>
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="translate(-6.9401139e-5,-2.8678628)"
|
||||||
|
x1="256.00012"
|
||||||
|
y1="102.94693"
|
||||||
|
x2="256.00012"
|
||||||
|
y2="409.05307" />
|
||||||
|
<clipPath
|
||||||
|
clipPathUnits="userSpaceOnUse"
|
||||||
|
id="clipPath128">
|
||||||
|
<circle
|
||||||
|
style="fill:none;fill-opacity:1;stroke:#03ffff;stroke-width:0;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="circle128"
|
||||||
|
cx="256"
|
||||||
|
cy="256"
|
||||||
|
r="192" />
|
||||||
|
</clipPath>
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient1"
|
||||||
|
id="linearGradient2"
|
||||||
|
x1="256"
|
||||||
|
y1="64"
|
||||||
|
x2="256"
|
||||||
|
y2="448"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(1.3229974,0,0,1.3214002,-82.687336,-82.290326)" />
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview7"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#000000"
|
||||||
|
borderopacity="0.25"
|
||||||
|
inkscape:showpageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:deskcolor="#d1d1d1"
|
||||||
|
inkscape:zoom="1.4142136"
|
||||||
|
inkscape:cx="261.62951"
|
||||||
|
inkscape:cy="230.87036"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1008"
|
||||||
|
inkscape:window-x="1080"
|
||||||
|
inkscape:window-y="351"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg7" />
|
||||||
|
<path
|
||||||
|
id="path8-7"
|
||||||
|
style="display:inline;mix-blend-mode:multiply;fill:url(#linearGradient6);fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient2);stroke-width:3.9666;stroke-dasharray:none;stroke-opacity:0.566238;paint-order:stroke fill markers"
|
||||||
|
inkscape:label="Circle"
|
||||||
|
d="M 256,2.2792898 A 254.0155,253.71401 0 0 0 150.68475,25.115202 c 19.54414,1.070775 38.74692,5.250294 51.56848,11.647658 14.14361,7.056691 28.63804,19.185961 39.4212,29.347551 h 40.60981 c 1.03847,-0.68139 2.10297,-1.36938 3.1938,-2.05957 5.45602,-15.78533 14.79164,-43.183497 19.49612,-57.0097682 A 254.0155,253.71401 0 0 0 256,2.2792898 Z m 61.57106,7.567234 -18.26098,46.1544672 c 7.79702,-4.13918 16.35655,-7.87447 25.20671,-10.87081 23.1229,-7.828433 43.96931,-10.170904 54.94058,-10.868226 A 254.0155,253.71401 0 0 0 317.57106,9.8465238 Z m 65.39277,26.4001532 c -9.68256,4.806644 -33.05532,16.642034 -55.68217,29.863734 H 424.4677 A 254.0155,253.71401 0 0 0 382.96383,36.246677 Z M 113.90698,45.690231 A 254.0155,253.71401 0 0 0 87.532302,66.110411 H 194.2739 c -1.47402,-0.80231 -2.35141,-1.25949 -2.35141,-1.25949 l 10.4496,-11.83348 -38.40568,7.01234 c 0,1e-5 -12.21537,-4.60266 -40.17313,-12.27223 -3.45336,-0.94731 -6.75329,-1.61824 -9.8863,-2.06732 z m -36.803618,30.18635 a 254.0155,253.71401 0 0 0 -34.88372,43.090929 h 59.976738 c 18.11461,-12.04145 40.14252,-22.882149 62.31266,-24.534159 52.93006,-3.9444 70.16538,1.86342 70.16538,1.86342 0,0 -4.612,-4.8206 -14.51938,-13.36656 -2.72366,-2.34942 -6.0844,-4.77373 -9.52455,-7.05363 z m 174.472868,0 c 4.57322,4.7186 7.29716,7.83565 7.29716,7.83565 0,0 3.53501,-3.18484 9.62532,-7.83565 z m 60.27649,0 c -21.56573,15.45339 -25.4703,27.979669 -25.4703,27.979669 0,0 54.83326,-19.215729 100.70543,-0.31228 11.63986,4.79661 21.58481,10.13159 29.94832,15.42354 h 52.74419 A 254.0155,253.71401 0 0 0 434.89664,75.876581 Z M 36.250648,128.73367 A 254.0155,253.71401 0 0 0 16.372095,171.82459 H 147.45478 c 1.45695,-2.5815 3.06539,-5.08648 4.83979,-7.48982 14.23694,-19.28301 27.92088,-30.0088 36.86047,-35.6011 h -30.25323 c -5.87346,0.93472 -12.04945,1.99094 -18.28166,3.16937 -30.12936,5.69727 -81.157618,22.78945 -81.157618,22.78945 0,0 11.47125,-12.39249 29.11369,-25.95882 z m 265.630492,0 c 33.48676,11.2434 52.42799,26.78443 62.7752,43.09092 h 130.97157 a 254.0155,253.71401 0 0 0 -19.87856,-43.09092 h -44.81136 c 14.85233,11.5863 21.59948,20.9854 21.59948,20.9854 0,0 -33.5226,-12.37087 -66.0646,-20.9854 z m -45.96641,16.27007 c -1.00419,0.0106 -10.12705,0.72026 -44.98966,20.64729 -3.12132,1.78406 -6.25434,3.86182 -9.37468,6.17356 h 41.81911 c 7.17181,-17.34774 12.64083,-26.82085 12.64083,-26.82085 0,0 -0.0287,-7.1e-4 -0.0957,0 z m 14.18088,0.0465 c 0,0 -3.31228,9.32762 -7.30492,26.77438 h 51.78554 C 287.6577,146.14158 270.09561,145.0502 270.09561,145.0502 Z M 13.152456,181.59075 A 254.0155,253.71401 0 0 0 3.927651,224.68167 H 134.1447 c 0.56161,-12.72411 2.67825,-28.50188 8.61499,-43.09092 z m 176.661504,0 c -14.27121,13.10564 -27.60733,29.58761 -37.56073,43.09092 h 73.3721 c 4.47018,-16.79061 9.35068,-31.26371 13.86562,-43.09092 z m 70.85787,0 c -2.41384,11.76417 -4.9032,26.20707 -6.94831,43.09092 H 360.4832 c -8.32133,-10.88917 -20.66988,-26.17008 -36.35141,-43.09092 z m 109.17313,0 c 6.63611,15.24089 6.92441,30.5373 5.57882,43.09092 h 132.64857 a 254.0155,253.71401 0 0 0 -9.22481,-43.09092 z M 2.90181,234.44783 A 254.0155,253.71401 0 0 0 1.984498,255.9933 254.0155,253.71401 0 0 0 2.90181,277.53876 h 211.89923 c 2.25762,-15.52555 5.14325,-29.93448 8.3385,-43.09093 h -77.8863 c -6.46396,9.27617 -10.33076,15.56549 -10.33076,15.56549 0,0 -0.82623,-6.14945 -0.9354,-15.56549 z m 249.72093,0 c -1.3692,13.09684 -2.4456,27.49209 -3.02068,43.09093 h 259.49613 a 254.0155,253.71401 0 0 0 0.91731,-21.54546 254.0155,253.71401 0 0 0 -0.91731,-21.54547 H 374.02584 c -0.445,2.5469 -0.90878,4.89768 -1.32817,7.01751 0,0 -1.69726,-2.53821 -4.94056,-7.01751 z M 3.927651,287.30493 a 254.0155,253.71401 0 0 0 9.224805,43.09091 H 214.04393 c -1.29238,-15.40742 -1.57503,-30.04388 -0.41861,-43.09091 z m 245.385009,0 c -0.30355,13.54349 -0.22032,27.92598 0.36951,43.09091 h 249.16537 a 254.0155,253.71401 0 0 0 9.22481,-43.09091 z M 16.369511,340.16201 a 254.0155,253.71401 0 0 0 19.878554,43.09091 H 221.4677 c -2.69781,-14.4523 -4.96108,-29.01285 -6.4832,-43.09091 z m 233.842379,0 c 1.15864,15.47765 3.81286,29.83979 7.51679,43.09091 h 218.02325 a 254.0155,253.71401 0 0 0 19.87856,-43.09091 z M 42.217052,393.01909 a 254.0155,253.71401 0 0 0 34.88372,43.09093 H 233.09561 c -3.40902,-13.67281 -6.76794,-28.2531 -9.73902,-43.09093 z m 218.490958,0 c 5.34985,16.15926 12.22007,30.51982 19.68733,43.09093 h 154.50389 a 254.0155,253.71401 0 0 0 34.88371,-43.09093 z M 87.529722,445.87618 a 254.0155,253.71401 0 0 0 166.229968,63.8208 c -3.67805,-12.0825 -10.85464,-35.49828 -18.18088,-63.8208 z m 199.010328,0 c 17.5887,26.43772 36.99259,43.60598 47.33592,51.61309 a 254.0155,253.71401 0 0 0 90.59431,-51.61309 z" />
|
||||||
|
<path
|
||||||
|
id="path27"
|
||||||
|
style="display:inline;mix-blend-mode:multiply;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient27);stroke-width:3;stroke-linejoin:round;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers"
|
||||||
|
d="m 318.98012,441.7375 c -9.87518,-6.73978 -64.39137,-49.0272 -67.68975,-127.81978 -3.69298,-88.21893 15.36468,-141.91029 15.36468,-141.91029 0,0 16.00378,0.99513 39.80316,26.53195 23.79939,25.53753 37.74965,46.43102 37.74965,46.43102 3.91262,-19.79992 12.84563,-66.32402 -60.72865,-87.55523 0,0 12.82326,-5.38883 39.3925,-3.81382 26.56907,1.57572 81.6822,21.93799 81.6822,21.93799 0,0 -14.79766,-20.63773 -49.47063,-34.94295 -34.67291,-14.30533 -76.1182,0.23644 -76.1182,0.23644 0,0 3.86959,-12.43127 27.22669,-26.38478 23.35718,-13.9537 49.27409,-26.501533 49.27409,-26.501533 0,0 -21.97854,-0.26548 -47.67725,8.44535 -6.68948,2.267506 -13.15863,5.094213 -19.05208,8.226563 l 16.05803,-40.634103 -4.4617,-1.89059 -5.1305,-0.95965 c 0,0 -11.24072,33.12428 -16.92051,49.576513 -12.13137,7.68489 -20.11005,14.87735 -20.11005,14.87735 0,0 -21.90573,-25.09227 -42.79668,-35.527803 -26.03412,-13.00525 -86.88249,-13.90359 -94.0044,10.401173 0,0 13.56804,-7.884703 34.70032,-2.080917 21.13214,5.803997 30.3644,9.287307 30.3644,9.287307 l 29.02989,-5.30681 -7.89811,8.95527 c 0,0 13.8496,7.21324 21.33822,13.68063 7.48859,6.46722 10.9757,10.11472 10.9757,10.11472 0,0 -13.02739,-4.39388 -53.03507,-1.40893 -40.00771,2.98473 -79.40016,45.60209 -79.40016,45.60209 0,0 38.57037,-12.93531 61.34393,-17.24677 22.77354,-4.31126 44.52166,-6.46757 44.52166,-6.46757 0,0 -17.23298,5.97003 -35.69792,31.00932 -18.46522,25.03987 -13.13146,64.83866 -13.13146,64.83866 0,0 29.33874,-47.7577 57.44675,-63.84249 28.10798,-16.08527 34.0799,-15.6238 34.0799,-15.6238 0,0 -22.56785,39.13486 -31.39017,101.98268 -8.03005,57.2039 26.77689,163.75449 31.1572,178.89699"
|
||||||
|
sodipodi:nodetypes="cscsccscscscsccccccscscccscscscscscsc"
|
||||||
|
inkscape:label="MainOutline"
|
||||||
|
clip-path="url(#clipPath128)"
|
||||||
|
transform="matrix(1.3229974,0,0,1.3214002,-82.687282,-82.278451)" />
|
||||||
|
</svg>
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 13 KiB |
BIN
dist/eden.bmp
vendored
|
Before Width: | Height: | Size: 256 KiB After Width: | Height: | Size: 256 KiB |
BIN
dist/eden.icns
vendored
BIN
dist/eden.ico
vendored
|
Before Width: | Height: | Size: 352 KiB After Width: | Height: | Size: 335 KiB |
230
dist/eden.icon/Assets/dev.eden_emu.eden.svg
vendored
Normal file
|
|
@ -0,0 +1,230 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
width="512"
|
||||||
|
height="512"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 512 512"
|
||||||
|
version="1.1"
|
||||||
|
id="svg7"
|
||||||
|
sodipodi:docname="base.svg.2026_01_12_14_43_47.0.svg"
|
||||||
|
inkscape:version="1.4.2 (ebf0e94, 2025-05-08)"
|
||||||
|
inkscape:export-filename="base.svg.2026_01_12_14_43_47.0.svg"
|
||||||
|
inkscape:export-xdpi="96"
|
||||||
|
inkscape:export-ydpi="96"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs7">
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient1"
|
||||||
|
inkscape:collect="always">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#ff2e88;stop-opacity:0.5;"
|
||||||
|
offset="0"
|
||||||
|
id="stop3" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#bf42f6;stop-opacity:0.5;"
|
||||||
|
offset="0.44631511"
|
||||||
|
id="stop4" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#5da5ed;stop-opacity:0.5;"
|
||||||
|
offset="0.90088946"
|
||||||
|
id="stop2" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient138"
|
||||||
|
inkscape:collect="always">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#ff2e88;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop152" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#bf42f6;stop-opacity:1;"
|
||||||
|
offset="0.44971901"
|
||||||
|
id="stop137" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#5da5ed;stop-opacity:1;"
|
||||||
|
offset="0.89793283"
|
||||||
|
id="stop138" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="swatch37"
|
||||||
|
inkscape:swatch="solid">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#ffffff;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop37" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="swatch28"
|
||||||
|
inkscape:swatch="solid">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#252525;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop28" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="swatch27"
|
||||||
|
inkscape:swatch="solid">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#000000;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop27" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="swatch15"
|
||||||
|
inkscape:swatch="solid">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#ffffff;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop16" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient14"
|
||||||
|
inkscape:swatch="gradient">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#ffffff;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop14" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#ffffff;stop-opacity:0;"
|
||||||
|
offset="1"
|
||||||
|
id="stop15" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="swatch9"
|
||||||
|
inkscape:swatch="solid">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#ffffff;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop10" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="swatch8"
|
||||||
|
inkscape:swatch="solid">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#ffffff;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop9" />
|
||||||
|
</linearGradient>
|
||||||
|
<rect
|
||||||
|
x="22.627417"
|
||||||
|
y="402.76802"
|
||||||
|
width="521.34025"
|
||||||
|
height="248.94868"
|
||||||
|
id="rect24" />
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient11"
|
||||||
|
inkscape:collect="always">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#ff2e88;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop11" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#bf42f6;stop-opacity:1;"
|
||||||
|
offset="0.44971901"
|
||||||
|
id="stop154" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#5da5ed;stop-opacity:1;"
|
||||||
|
offset="0.89793283"
|
||||||
|
id="stop12" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient138"
|
||||||
|
id="linearGradient6"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(1.118028,0,0,1.116699,-46.314723,-42.388667)"
|
||||||
|
x1="270.39996"
|
||||||
|
y1="40.000019"
|
||||||
|
x2="270.39996"
|
||||||
|
y2="494.39996"
|
||||||
|
spreadMethod="pad" />
|
||||||
|
<clipPath
|
||||||
|
clipPathUnits="userSpaceOnUse"
|
||||||
|
id="clipPath18">
|
||||||
|
<circle
|
||||||
|
style="opacity:1;mix-blend-mode:normal;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10.8382;stroke-opacity:0.566238;paint-order:stroke fill markers"
|
||||||
|
id="circle18"
|
||||||
|
cx="-246.8315"
|
||||||
|
cy="246.8338"
|
||||||
|
inkscape:label="Circle"
|
||||||
|
r="191.89999" />
|
||||||
|
</clipPath>
|
||||||
|
<clipPath
|
||||||
|
clipPathUnits="userSpaceOnUse"
|
||||||
|
id="clipPath22">
|
||||||
|
<circle
|
||||||
|
style="opacity:1;mix-blend-mode:normal;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10.8382;stroke-opacity:0.566238;paint-order:stroke fill markers"
|
||||||
|
id="circle22"
|
||||||
|
cx="256"
|
||||||
|
cy="256"
|
||||||
|
inkscape:label="Circle"
|
||||||
|
r="191.89999" />
|
||||||
|
</clipPath>
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient11"
|
||||||
|
id="linearGradient27"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="translate(-6.9401139e-5,-2.8678628)"
|
||||||
|
x1="256.00012"
|
||||||
|
y1="102.94693"
|
||||||
|
x2="256.00012"
|
||||||
|
y2="409.05307" />
|
||||||
|
<clipPath
|
||||||
|
clipPathUnits="userSpaceOnUse"
|
||||||
|
id="clipPath128">
|
||||||
|
<circle
|
||||||
|
style="fill:none;fill-opacity:1;stroke:#03ffff;stroke-width:0;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="circle128"
|
||||||
|
cx="256"
|
||||||
|
cy="256"
|
||||||
|
r="192" />
|
||||||
|
</clipPath>
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient1"
|
||||||
|
id="linearGradient2"
|
||||||
|
x1="256"
|
||||||
|
y1="64"
|
||||||
|
x2="256"
|
||||||
|
y2="448"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(1.3229974,0,0,1.3214002,-82.687336,-82.290326)" />
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview7"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#000000"
|
||||||
|
borderopacity="0.25"
|
||||||
|
inkscape:showpageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:deskcolor="#d1d1d1"
|
||||||
|
inkscape:zoom="1.4142136"
|
||||||
|
inkscape:cx="261.62951"
|
||||||
|
inkscape:cy="230.87036"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1008"
|
||||||
|
inkscape:window-x="1080"
|
||||||
|
inkscape:window-y="351"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg7" />
|
||||||
|
<path
|
||||||
|
id="path8-7"
|
||||||
|
style="display:inline;mix-blend-mode:multiply;fill:url(#linearGradient6);fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient2);stroke-width:3.9666;stroke-dasharray:none;stroke-opacity:0.566238;paint-order:stroke fill markers"
|
||||||
|
inkscape:label="Circle"
|
||||||
|
d="M 256,2.2792898 A 254.0155,253.71401 0 0 0 150.68475,25.115202 c 19.54414,1.070775 38.74692,5.250294 51.56848,11.647658 14.14361,7.056691 28.63804,19.185961 39.4212,29.347551 h 40.60981 c 1.03847,-0.68139 2.10297,-1.36938 3.1938,-2.05957 5.45602,-15.78533 14.79164,-43.183497 19.49612,-57.0097682 A 254.0155,253.71401 0 0 0 256,2.2792898 Z m 61.57106,7.567234 -18.26098,46.1544672 c 7.79702,-4.13918 16.35655,-7.87447 25.20671,-10.87081 23.1229,-7.828433 43.96931,-10.170904 54.94058,-10.868226 A 254.0155,253.71401 0 0 0 317.57106,9.8465238 Z m 65.39277,26.4001532 c -9.68256,4.806644 -33.05532,16.642034 -55.68217,29.863734 H 424.4677 A 254.0155,253.71401 0 0 0 382.96383,36.246677 Z M 113.90698,45.690231 A 254.0155,253.71401 0 0 0 87.532302,66.110411 H 194.2739 c -1.47402,-0.80231 -2.35141,-1.25949 -2.35141,-1.25949 l 10.4496,-11.83348 -38.40568,7.01234 c 0,1e-5 -12.21537,-4.60266 -40.17313,-12.27223 -3.45336,-0.94731 -6.75329,-1.61824 -9.8863,-2.06732 z m -36.803618,30.18635 a 254.0155,253.71401 0 0 0 -34.88372,43.090929 h 59.976738 c 18.11461,-12.04145 40.14252,-22.882149 62.31266,-24.534159 52.93006,-3.9444 70.16538,1.86342 70.16538,1.86342 0,0 -4.612,-4.8206 -14.51938,-13.36656 -2.72366,-2.34942 -6.0844,-4.77373 -9.52455,-7.05363 z m 174.472868,0 c 4.57322,4.7186 7.29716,7.83565 7.29716,7.83565 0,0 3.53501,-3.18484 9.62532,-7.83565 z m 60.27649,0 c -21.56573,15.45339 -25.4703,27.979669 -25.4703,27.979669 0,0 54.83326,-19.215729 100.70543,-0.31228 11.63986,4.79661 21.58481,10.13159 29.94832,15.42354 h 52.74419 A 254.0155,253.71401 0 0 0 434.89664,75.876581 Z M 36.250648,128.73367 A 254.0155,253.71401 0 0 0 16.372095,171.82459 H 147.45478 c 1.45695,-2.5815 3.06539,-5.08648 4.83979,-7.48982 14.23694,-19.28301 27.92088,-30.0088 36.86047,-35.6011 h -30.25323 c -5.87346,0.93472 -12.04945,1.99094 -18.28166,3.16937 -30.12936,5.69727 -81.157618,22.78945 -81.157618,22.78945 0,0 11.47125,-12.39249 29.11369,-25.95882 z m 265.630492,0 c 33.48676,11.2434 52.42799,26.78443 62.7752,43.09092 h 130.97157 a 254.0155,253.71401 0 0 0 -19.87856,-43.09092 h -44.81136 c 14.85233,11.5863 21.59948,20.9854 21.59948,20.9854 0,0 -33.5226,-12.37087 -66.0646,-20.9854 z m -45.96641,16.27007 c -1.00419,0.0106 -10.12705,0.72026 -44.98966,20.64729 -3.12132,1.78406 -6.25434,3.86182 -9.37468,6.17356 h 41.81911 c 7.17181,-17.34774 12.64083,-26.82085 12.64083,-26.82085 0,0 -0.0287,-7.1e-4 -0.0957,0 z m 14.18088,0.0465 c 0,0 -3.31228,9.32762 -7.30492,26.77438 h 51.78554 C 287.6577,146.14158 270.09561,145.0502 270.09561,145.0502 Z M 13.152456,181.59075 A 254.0155,253.71401 0 0 0 3.927651,224.68167 H 134.1447 c 0.56161,-12.72411 2.67825,-28.50188 8.61499,-43.09092 z m 176.661504,0 c -14.27121,13.10564 -27.60733,29.58761 -37.56073,43.09092 h 73.3721 c 4.47018,-16.79061 9.35068,-31.26371 13.86562,-43.09092 z m 70.85787,0 c -2.41384,11.76417 -4.9032,26.20707 -6.94831,43.09092 H 360.4832 c -8.32133,-10.88917 -20.66988,-26.17008 -36.35141,-43.09092 z m 109.17313,0 c 6.63611,15.24089 6.92441,30.5373 5.57882,43.09092 h 132.64857 a 254.0155,253.71401 0 0 0 -9.22481,-43.09092 z M 2.90181,234.44783 A 254.0155,253.71401 0 0 0 1.984498,255.9933 254.0155,253.71401 0 0 0 2.90181,277.53876 h 211.89923 c 2.25762,-15.52555 5.14325,-29.93448 8.3385,-43.09093 h -77.8863 c -6.46396,9.27617 -10.33076,15.56549 -10.33076,15.56549 0,0 -0.82623,-6.14945 -0.9354,-15.56549 z m 249.72093,0 c -1.3692,13.09684 -2.4456,27.49209 -3.02068,43.09093 h 259.49613 a 254.0155,253.71401 0 0 0 0.91731,-21.54546 254.0155,253.71401 0 0 0 -0.91731,-21.54547 H 374.02584 c -0.445,2.5469 -0.90878,4.89768 -1.32817,7.01751 0,0 -1.69726,-2.53821 -4.94056,-7.01751 z M 3.927651,287.30493 a 254.0155,253.71401 0 0 0 9.224805,43.09091 H 214.04393 c -1.29238,-15.40742 -1.57503,-30.04388 -0.41861,-43.09091 z m 245.385009,0 c -0.30355,13.54349 -0.22032,27.92598 0.36951,43.09091 h 249.16537 a 254.0155,253.71401 0 0 0 9.22481,-43.09091 z M 16.369511,340.16201 a 254.0155,253.71401 0 0 0 19.878554,43.09091 H 221.4677 c -2.69781,-14.4523 -4.96108,-29.01285 -6.4832,-43.09091 z m 233.842379,0 c 1.15864,15.47765 3.81286,29.83979 7.51679,43.09091 h 218.02325 a 254.0155,253.71401 0 0 0 19.87856,-43.09091 z M 42.217052,393.01909 a 254.0155,253.71401 0 0 0 34.88372,43.09093 H 233.09561 c -3.40902,-13.67281 -6.76794,-28.2531 -9.73902,-43.09093 z m 218.490958,0 c 5.34985,16.15926 12.22007,30.51982 19.68733,43.09093 h 154.50389 a 254.0155,253.71401 0 0 0 34.88371,-43.09093 z M 87.529722,445.87618 a 254.0155,253.71401 0 0 0 166.229968,63.8208 c -3.67805,-12.0825 -10.85464,-35.49828 -18.18088,-63.8208 z m 199.010328,0 c 17.5887,26.43772 36.99259,43.60598 47.33592,51.61309 a 254.0155,253.71401 0 0 0 90.59431,-51.61309 z" />
|
||||||
|
<path
|
||||||
|
id="path27"
|
||||||
|
style="display:inline;mix-blend-mode:multiply;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient27);stroke-width:3;stroke-linejoin:round;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers"
|
||||||
|
d="m 318.98012,441.7375 c -9.87518,-6.73978 -64.39137,-49.0272 -67.68975,-127.81978 -3.69298,-88.21893 15.36468,-141.91029 15.36468,-141.91029 0,0 16.00378,0.99513 39.80316,26.53195 23.79939,25.53753 37.74965,46.43102 37.74965,46.43102 3.91262,-19.79992 12.84563,-66.32402 -60.72865,-87.55523 0,0 12.82326,-5.38883 39.3925,-3.81382 26.56907,1.57572 81.6822,21.93799 81.6822,21.93799 0,0 -14.79766,-20.63773 -49.47063,-34.94295 -34.67291,-14.30533 -76.1182,0.23644 -76.1182,0.23644 0,0 3.86959,-12.43127 27.22669,-26.38478 23.35718,-13.9537 49.27409,-26.501533 49.27409,-26.501533 0,0 -21.97854,-0.26548 -47.67725,8.44535 -6.68948,2.267506 -13.15863,5.094213 -19.05208,8.226563 l 16.05803,-40.634103 -4.4617,-1.89059 -5.1305,-0.95965 c 0,0 -11.24072,33.12428 -16.92051,49.576513 -12.13137,7.68489 -20.11005,14.87735 -20.11005,14.87735 0,0 -21.90573,-25.09227 -42.79668,-35.527803 -26.03412,-13.00525 -86.88249,-13.90359 -94.0044,10.401173 0,0 13.56804,-7.884703 34.70032,-2.080917 21.13214,5.803997 30.3644,9.287307 30.3644,9.287307 l 29.02989,-5.30681 -7.89811,8.95527 c 0,0 13.8496,7.21324 21.33822,13.68063 7.48859,6.46722 10.9757,10.11472 10.9757,10.11472 0,0 -13.02739,-4.39388 -53.03507,-1.40893 -40.00771,2.98473 -79.40016,45.60209 -79.40016,45.60209 0,0 38.57037,-12.93531 61.34393,-17.24677 22.77354,-4.31126 44.52166,-6.46757 44.52166,-6.46757 0,0 -17.23298,5.97003 -35.69792,31.00932 -18.46522,25.03987 -13.13146,64.83866 -13.13146,64.83866 0,0 29.33874,-47.7577 57.44675,-63.84249 28.10798,-16.08527 34.0799,-15.6238 34.0799,-15.6238 0,0 -22.56785,39.13486 -31.39017,101.98268 -8.03005,57.2039 26.77689,163.75449 31.1572,178.89699"
|
||||||
|
sodipodi:nodetypes="cscsccscscscsccccccscscccscscscscscsc"
|
||||||
|
inkscape:label="MainOutline"
|
||||||
|
clip-path="url(#clipPath128)"
|
||||||
|
transform="matrix(1.3229974,0,0,1.3214002,-82.687282,-82.278451)" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 13 KiB |
37
dist/eden.icon/icon.json
vendored
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
{
|
||||||
|
"fill" : {
|
||||||
|
"automatic-gradient" : "srgb:0.00000,0.00000,0.00000,1.00000"
|
||||||
|
},
|
||||||
|
"groups" : [
|
||||||
|
{
|
||||||
|
"layers" : [
|
||||||
|
{
|
||||||
|
"fill" : "none",
|
||||||
|
"image-name" : "dev.eden_emu.eden.svg",
|
||||||
|
"name" : "dev.eden_emu.eden",
|
||||||
|
"position" : {
|
||||||
|
"scale" : 1.8,
|
||||||
|
"translation-in-points" : [
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"shadow" : {
|
||||||
|
"kind" : "neutral",
|
||||||
|
"opacity" : 0.5
|
||||||
|
},
|
||||||
|
"translucency" : {
|
||||||
|
"enabled" : true,
|
||||||
|
"value" : 0.5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"supported-platforms" : {
|
||||||
|
"circles" : [
|
||||||
|
"watchOS"
|
||||||
|
],
|
||||||
|
"squares" : "shared"
|
||||||
|
}
|
||||||
|
}
|
||||||
89
dist/icon_variations/aprilfools2026.svg
vendored
Normal file
|
After Width: | Height: | Size: 19 KiB |
1
dist/icon_variations/aprilfools2026_bgcolor
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
#43fcfcff
|
||||||
830
dist/languages/ar.ts
vendored
808
dist/languages/ca.ts
vendored
808
dist/languages/cs.ts
vendored
808
dist/languages/da.ts
vendored
808
dist/languages/de.ts
vendored
808
dist/languages/el.ts
vendored
958
dist/languages/es.ts
vendored
808
dist/languages/fi.ts
vendored
810
dist/languages/fr.ts
vendored
808
dist/languages/hu.ts
vendored
808
dist/languages/id.ts
vendored
1114
dist/languages/it.ts
vendored
808
dist/languages/ja_JP.ts
vendored
808
dist/languages/ko_KR.ts
vendored
818
dist/languages/nb.ts
vendored
808
dist/languages/nl.ts
vendored
810
dist/languages/pl.ts
vendored
808
dist/languages/pt_BR.ts
vendored
808
dist/languages/pt_PT.ts
vendored
810
dist/languages/ru_RU.ts
vendored
810
dist/languages/sv.ts
vendored
818
dist/languages/tr_TR.ts
vendored
814
dist/languages/uk.ts
vendored
808
dist/languages/vi.ts
vendored
809
dist/languages/vi_VN.ts
vendored
817
dist/languages/zh_CN.ts
vendored
808
dist/languages/zh_TW.ts
vendored
BIN
dist/qt_themes/default/icons/256x256/eden.png
vendored
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 35 KiB |
|
|
@ -76,7 +76,6 @@ Certain other dependencies will be fetched by CPM regardless. System packages *c
|
||||||
* This package is known to be broken on the AUR.
|
* This package is known to be broken on the AUR.
|
||||||
* [cpp-jwt](https://github.com/arun11299/cpp-jwt) 1.4+ - if `ENABLE_WEB_SERVICE` is on
|
* [cpp-jwt](https://github.com/arun11299/cpp-jwt) 1.4+ - if `ENABLE_WEB_SERVICE` is on
|
||||||
* [unordered-dense](https://github.com/martinus/unordered_dense)
|
* [unordered-dense](https://github.com/martinus/unordered_dense)
|
||||||
* [mcl](https://github.com/azahar-emu/mcl) - subject to removal
|
|
||||||
|
|
||||||
On amd64:
|
On amd64:
|
||||||
|
|
||||||
|
|
@ -335,7 +334,7 @@ pacman -Syuu --needed --noconfirm $packages
|
||||||
<summary>HaikuOS</summary>
|
<summary>HaikuOS</summary>
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
pkgman install git cmake patch libfmt_devel nlohmann_json lz4_devel opus_devel boost1.89_devel vulkan_devel qt6_base_devel qt6_declarative_devel libsdl2_devel ffmpeg7_devel libx11_devel enet_devel catch2_devel quazip1_qt5_devel qt6_5compat_devel glslang qt6_devel qt6_charts_devel
|
pkgman install git cmake patch libfmt_devel nlohmann_json lz4_devel opus_devel boost1.90_devel vulkan_devel qt6_base_devel qt6_declarative_devel libsdl2_devel ffmpeg7_devel libx11_devel enet_devel catch2_devel quazip1_qt5_devel qt6_5compat_devel glslang qt6_devel qt6_charts_devel
|
||||||
```
|
```
|
||||||
|
|
||||||
[Caveats](./Caveats.md#haikuos).
|
[Caveats](./Caveats.md#haikuos).
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ This contains documentation created by developers. This contains build instructi
|
||||||
- **[Dynarmic](./dynarmic)**
|
- **[Dynarmic](./dynarmic)**
|
||||||
- **[Cross compilation](./CrossCompile.md)**
|
- **[Cross compilation](./CrossCompile.md)**
|
||||||
- **[Driver Bugs](./DriverBugs.md)**
|
- **[Driver Bugs](./DriverBugs.md)**
|
||||||
|
- **[Building Older Commits](./build/OlderCommits.md)**
|
||||||
|
|
||||||
## Policies
|
## Policies
|
||||||
|
|
||||||
|
|
|
||||||
40
docs/build/OlderCommits.md
vendored
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
# Building Older Commits
|
||||||
|
|
||||||
|
Bisecting and debugging older versions of Eden can be difficult, as many of our submodules have been deleted or removed. However, work has been done to make this process as simple as possible for users.
|
||||||
|
|
||||||
|
## Script
|
||||||
|
|
||||||
|
Copy the following script and store it in `fix.sh`:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
#!/bin/sh -e
|
||||||
|
|
||||||
|
git -C externals/discord-rpc checkout 0d8b2d6a37c6e47d62b37caa14708bf747c883bb
|
||||||
|
git add externals/discord-rpc
|
||||||
|
|
||||||
|
git -C externals/dynarmic checkout 05b7ba50588d1004e23ef91f1bda8be234be68f4
|
||||||
|
git add externals/dynarmic
|
||||||
|
|
||||||
|
git -C externals/mbedtls checkout ce4f81f4a926a0e0dcadd0128e016baba416e8ea
|
||||||
|
git add externals/mbedtls
|
||||||
|
|
||||||
|
git -C externals/oboe checkout e4f06f2143eb0173bf4a2bd15aae5e8cc3179405
|
||||||
|
git add externals/oboe
|
||||||
|
|
||||||
|
git -C externals/sirit checkout b870b062998244231a4f08004d3b25151732c5c5
|
||||||
|
git add externals/sirit
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, run `chmod +x fix.sh`
|
||||||
|
|
||||||
|
## Submodules
|
||||||
|
|
||||||
|
To check out submodules successfully, use this order of operations:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
git submodule update --init --recursive --depth 1 --jobs 8 --progress
|
||||||
|
./fix.sh
|
||||||
|
git submodule update --init --recursive --depth 1 --jobs 8 --progress
|
||||||
|
```
|
||||||
|
|
||||||
|
And you should be good to go! If you check out a different commit that changes submodule commits, run the above command list again.
|
||||||
|
|
@ -56,7 +56,7 @@ Use this when you need to connect to a multiplayer room for LDN functionality in
|
||||||
- Multiplayer Options Configured in Eden Settings
|
- Multiplayer Options Configured in Eden Settings
|
||||||
- Network Access
|
- Network Access
|
||||||
|
|
||||||
## Steps
|
### Steps
|
||||||
There are 2 primary methods that you can use to connect to an existing room, depending on how the room is hosted.
|
There are 2 primary methods that you can use to connect to an existing room, depending on how the room is hosted.
|
||||||
|
|
||||||
- Joining a Public Lobby
|
- Joining a Public Lobby
|
||||||
|
|
@ -70,7 +70,7 @@ There are 2 primary methods that you can use to connect to an existing room, dep
|
||||||
|
|
||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
### Joining a Public Lobby
|
## Joining a Public Lobby
|
||||||
1. Open Eden and navigate to *Multiplayer → Browse Public Game Lobby*.
|
1. Open Eden and navigate to *Multiplayer → Browse Public Game Lobby*.
|
||||||
2. The **Public Room Browser** will now open and display a list of publicly accessible rooms. Find one you want to connect to and double click it.
|
2. The **Public Room Browser** will now open and display a list of publicly accessible rooms. Find one you want to connect to and double click it.
|
||||||
|
|
||||||
|
|
@ -90,7 +90,7 @@ If the hoster has not made the lobby public, or you don't want to find it in the
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# Hosting a Multiplayer Room
|
## Hosting a Multiplayer Room
|
||||||
Use this guide for when you want to host a multiplayer lobby to play with others in Eden. In order to have someone access the room from outside your local network, see the *Access Your Multiplayer Room Externally* section for next steps.
|
Use this guide for when you want to host a multiplayer lobby to play with others in Eden. In order to have someone access the room from outside your local network, see the *Access Your Multiplayer Room Externally* section for next steps.
|
||||||
|
|
||||||
**Click [Here](https://evilperson1337.notion.site/Hosting-a-Multiplayer-Room-2c357c2edaf6819481dbe8a99926cea2) for a version of this guide with images & visual elements.**
|
**Click [Here](https://evilperson1337.notion.site/Hosting-a-Multiplayer-Room-2c357c2edaf6819481dbe8a99926cea2) for a version of this guide with images & visual elements.**
|
||||||
|
|
@ -100,7 +100,7 @@ Use this guide for when you want to host a multiplayer lobby to play with others
|
||||||
- Network Access
|
- Network Access
|
||||||
- Ability to allow programs through the firewall on your device.
|
- Ability to allow programs through the firewall on your device.
|
||||||
|
|
||||||
## Steps
|
### Steps
|
||||||
1. Open Eden and navigate to *Emulation → Multiplayer → Create Room.*
|
1. Open Eden and navigate to *Emulation → Multiplayer → Create Room.*
|
||||||
2. Fill out the following information in the popup dialog box.
|
2. Fill out the following information in the popup dialog box.
|
||||||
|
|
||||||
|
|
@ -120,7 +120,7 @@ Use this guide for when you want to host a multiplayer lobby to play with others
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# Access Your Multiplayer Room Externally
|
## Access Your Multiplayer Room Externally
|
||||||
Quite often the person with whom you want to play is located off of your internal network (LAN). If you want to host a room and play with them you will need to get your devices to communicate with each other. This guide will go over your options on how to do this so that you can play together.
|
Quite often the person with whom you want to play is located off of your internal network (LAN). If you want to host a room and play with them you will need to get your devices to communicate with each other. This guide will go over your options on how to do this so that you can play together.
|
||||||
|
|
||||||
**Click [Here](https://evilperson1337.notion.site/Access-Your-Multiplayer-Room-Externally-2c357c2edaf681c0ab2ce2ee624d809d) for a version of this guide with images & visual elements.**
|
**Click [Here](https://evilperson1337.notion.site/Access-Your-Multiplayer-Room-Externally-2c357c2edaf681c0ab2ce2ee624d809d) for a version of this guide with images & visual elements.**
|
||||||
|
|
@ -129,9 +129,9 @@ Quite often the person with whom you want to play is located off of your interna
|
||||||
- Eden set up and Functioning
|
- Eden set up and Functioning
|
||||||
- Network Access
|
- Network Access
|
||||||
|
|
||||||
## Options
|
### Options
|
||||||
|
|
||||||
### Port Forwarding
|
#### Port Forwarding
|
||||||
|
|
||||||
- **Difficulty Level**: High
|
- **Difficulty Level**: High
|
||||||
|
|
||||||
|
|
@ -148,8 +148,9 @@ The process works by creating a static mapping—often called a “port-forward
|
||||||
|
|
||||||
For our purposes we would pick the port we want to expose (*e.g. 24872*) and we would access our router's configuration and create a port-forward rule to send the traffic from an external connection to your local machine over our specified port (*24872)*. The exact way to do so, varies greatly by router manufacturer - and sometimes require contacting your ISP to do so depending on your agreement. You can look up your router on [*portforward.com*](https://portforward.com/router.htm) which may have instructions on how to do so for your specific equipment. If it is not there, you will have to use Google/ChatGPT to determine the steps for your equipment.
|
For our purposes we would pick the port we want to expose (*e.g. 24872*) and we would access our router's configuration and create a port-forward rule to send the traffic from an external connection to your local machine over our specified port (*24872)*. The exact way to do so, varies greatly by router manufacturer - and sometimes require contacting your ISP to do so depending on your agreement. You can look up your router on [*portforward.com*](https://portforward.com/router.htm) which may have instructions on how to do so for your specific equipment. If it is not there, you will have to use Google/ChatGPT to determine the steps for your equipment.
|
||||||
|
|
||||||
|
Remember you can't have one port open for multiple devices at the same time - you must only host from one device (or do more convoluted networking which we will not cover here).
|
||||||
|
|
||||||
### Use a Tunnelling Service
|
#### Use a Tunnelling Service
|
||||||
- **Difficulty Level**: Easy
|
- **Difficulty Level**: Easy
|
||||||
|
|
||||||
<aside>
|
<aside>
|
||||||
|
|
@ -167,7 +168,7 @@ For our purposes we would spawn the listener for the port that way chose when ho
|
||||||
- [*Playit.GG*](https://playit.gg/)
|
- [*Playit.GG*](https://playit.gg/)
|
||||||
|
|
||||||
|
|
||||||
### Use a VPN Service
|
#### Use a VPN Service
|
||||||
|
|
||||||
- **Difficulty**: Easy
|
- **Difficulty**: Easy
|
||||||
|
|
||||||
|
|
@ -189,7 +190,7 @@ The VPN solution is a good compromise between the tunnelling solution and port f
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# Finding the Server Information for a Multiplayer Room
|
## Finding the Server Information for a Multiplayer Room
|
||||||
Use this guide when you need to determine the connection information for the Public Multiplayer Lobby you are connected to.
|
Use this guide when you need to determine the connection information for the Public Multiplayer Lobby you are connected to.
|
||||||
|
|
||||||
**Click [Here](https://evilperson1337.notion.site/Finding-the-Server-Information-for-a-Multiplayer-Room-2c557c2edaf6809e94e8ed3429b9eb26) for a version of this guide with images & visual elements.**
|
**Click [Here](https://evilperson1337.notion.site/Finding-the-Server-Information-for-a-Multiplayer-Room-2c557c2edaf6809e94e8ed3429b9eb26) for a version of this guide with images & visual elements.**
|
||||||
|
|
@ -198,7 +199,7 @@ Use this guide when you need to determine the connection information for the Pub
|
||||||
- Eden set up and configured
|
- Eden set up and configured
|
||||||
- Internet Access
|
- Internet Access
|
||||||
|
|
||||||
## Steps
|
### Steps
|
||||||
|
|
||||||
### Method 1: Grabbing the Address from the Log File
|
### Method 1: Grabbing the Address from the Log File
|
||||||
1. Open Eden and Connect to the room you want to identify.
|
1. Open Eden and Connect to the room you want to identify.
|
||||||
|
|
@ -222,7 +223,7 @@ Use this guide when you need to determine the connection information for the Pub
|
||||||
2. Open the terminal supported by your operating system.
|
2. Open the terminal supported by your operating system.
|
||||||
3. Run one of the following commands, replacing *<Name>* with the name of the server from step 1.
|
3. Run one of the following commands, replacing *<Name>* with the name of the server from step 1.
|
||||||
|
|
||||||
### PowerShell Command [Windows Users]
|
#### PowerShell Command [Windows Users]
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Calls the API to get the address and port information
|
# Calls the API to get the address and port information
|
||||||
|
|
@ -235,7 +236,7 @@ Use this guide when you need to determine the connection information for the Pub
|
||||||
#}
|
#}
|
||||||
```
|
```
|
||||||
|
|
||||||
### CURL Command [MacOS/Linux Users] **Requires jq*
|
#### CURL Command [MacOS/Linux Users] **Requires jq*
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Calls the API to get the address and port information
|
# Calls the API to get the address and port information
|
||||||
|
|
@ -252,7 +253,7 @@ Use this guide when you need to determine the connection information for the Pub
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# Multiplayer for Local Co-Op Games
|
## Multiplayer for Local Co-Op Games
|
||||||
Use this guide when you want to play with a friend on a different system for games that only support local co-op.
|
Use this guide when you want to play with a friend on a different system for games that only support local co-op.
|
||||||
|
|
||||||
**Click [Here](https://evilperson1337.notion.site/Multiplayer-for-Local-Co-Op-Games-2c657c2edaf680c59975ec6b52022a2d) for a version of this guide with images & visual elements.**
|
**Click [Here](https://evilperson1337.notion.site/Multiplayer-for-Local-Co-Op-Games-2c657c2edaf680c59975ec6b52022a2d) for a version of this guide with images & visual elements.**
|
||||||
|
|
@ -271,7 +272,7 @@ In either situation at its core, we are emulating an input device on the host ma
|
||||||
- Parsec is free to use for personal, non-commercial use. For instructions on how to set up an account and install the client you should refer to the Parsec documentation on it's site.
|
- Parsec is free to use for personal, non-commercial use. For instructions on how to set up an account and install the client you should refer to the Parsec documentation on it's site.
|
||||||
- Parsec client installed on your machine and remote (friend's) machine
|
- Parsec client installed on your machine and remote (friend's) machine
|
||||||
|
|
||||||
## Steps
|
### Steps
|
||||||
|
|
||||||
<aside>
|
<aside>
|
||||||
|
|
||||||
|
|
@ -294,3 +295,22 @@ This guide will assume you are the one hosting the game and go over things *Pars
|
||||||
10. Set up the remote player's controller.
|
10. Set up the remote player's controller.
|
||||||
11. Hit **OK** to apply the changes.
|
11. Hit **OK** to apply the changes.
|
||||||
12. Launch the game you want to play and enter the co-op mode. How this works depends on the game, so you will have to look in the menus or online to find out.
|
12. Launch the game you want to play and enter the co-op mode. How this works depends on the game, so you will have to look in the menus or online to find out.
|
||||||
|
|
||||||
|
## Metaserver troubleshooting
|
||||||
|
|
||||||
|
If you can't connect to the metaserver, it's likely your ISP is blocking the requests.
|
||||||
|
|
||||||
|
### Linux and Steamdeck
|
||||||
|
|
||||||
|
Most Linux systems and Steamdeck should allow to modify the base `/etc/hosts` file, this should fix the DNS lookup issue; hence add the following to said file:
|
||||||
|
```
|
||||||
|
28.165.181.135 api.ynet-fun.xyz api.ynet-fun.xyz
|
||||||
|
```
|
||||||
|
|
||||||
|
### Zapret
|
||||||
|
|
||||||
|
In `lists/list-general.txt` add the following:
|
||||||
|
```
|
||||||
|
api.ynet-fun.xyz
|
||||||
|
ynet-fun.xyz
|
||||||
|
```
|
||||||
|
|
|
||||||
31
externals/CMakeLists.txt
vendored
|
|
@ -62,6 +62,12 @@ endif()
|
||||||
# unordered_dense
|
# unordered_dense
|
||||||
AddJsonPackage(unordered-dense)
|
AddJsonPackage(unordered-dense)
|
||||||
|
|
||||||
|
# httplib
|
||||||
|
if (IOS)
|
||||||
|
set(HTTPLIB_USE_BROTLI_IF_AVAILABLE OFF)
|
||||||
|
endif()
|
||||||
|
AddJsonPackage(httplib)
|
||||||
|
|
||||||
if (YUZU_STATIC_ROOM)
|
if (YUZU_STATIC_ROOM)
|
||||||
return()
|
return()
|
||||||
endif()
|
endif()
|
||||||
|
|
@ -76,9 +82,6 @@ if (ARCHITECTURE_riscv64)
|
||||||
AddJsonPackage(biscuit)
|
AddJsonPackage(biscuit)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# mcl
|
|
||||||
AddJsonPackage(mcl)
|
|
||||||
|
|
||||||
# Vulkan stuff
|
# Vulkan stuff
|
||||||
AddDependentPackages(vulkan-headers vulkan-utility-libraries)
|
AddDependentPackages(vulkan-headers vulkan-utility-libraries)
|
||||||
|
|
||||||
|
|
@ -109,16 +112,15 @@ if(ENABLE_CUBEB)
|
||||||
if (cubeb_ADDED)
|
if (cubeb_ADDED)
|
||||||
if (NOT MSVC)
|
if (NOT MSVC)
|
||||||
if (TARGET speex)
|
if (TARGET speex)
|
||||||
target_compile_options(speex PRIVATE -Wno-sign-compare)
|
target_compile_options(speex PRIVATE $<$<COMPILE_LANGUAGE:C,CXX>:-Wno-sign-compare>)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set_target_properties(cubeb PROPERTIES COMPILE_OPTIONS "")
|
set_target_properties(cubeb PROPERTIES COMPILE_OPTIONS "")
|
||||||
target_compile_options(cubeb INTERFACE
|
target_compile_options(cubeb INTERFACE
|
||||||
-Wno-implicit-const-int-float-conversion
|
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-implicit-const-int-float-conversion>
|
||||||
-Wno-shadow
|
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-shadow>
|
||||||
-Wno-missing-declarations
|
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-missing-declarations>
|
||||||
-Wno-return-type
|
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-return-type>
|
||||||
-Wno-uninitialized
|
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-uninitialized>
|
||||||
)
|
)
|
||||||
else()
|
else()
|
||||||
target_compile_options(cubeb PRIVATE
|
target_compile_options(cubeb PRIVATE
|
||||||
|
|
@ -184,7 +186,9 @@ if (YUZU_USE_BUNDLED_SIRIT)
|
||||||
else()
|
else()
|
||||||
AddJsonPackage(sirit)
|
AddJsonPackage(sirit)
|
||||||
if(MSVC AND CXX_CLANG)
|
if(MSVC AND CXX_CLANG)
|
||||||
target_compile_options(siritobj PRIVATE -Wno-error=unused-command-line-argument)
|
target_compile_options(siritobj PRIVATE
|
||||||
|
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-error=unused-command-line-argument>
|
||||||
|
)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
@ -220,7 +224,7 @@ AddJsonPackage(vulkan-memory-allocator)
|
||||||
if (VulkanMemoryAllocator_ADDED)
|
if (VulkanMemoryAllocator_ADDED)
|
||||||
if (CXX_CLANG)
|
if (CXX_CLANG)
|
||||||
target_compile_options(VulkanMemoryAllocator INTERFACE
|
target_compile_options(VulkanMemoryAllocator INTERFACE
|
||||||
-Wno-unused-variable
|
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-unused-variable>
|
||||||
)
|
)
|
||||||
elseif(MSVC)
|
elseif(MSVC)
|
||||||
target_compile_options(VulkanMemoryAllocator INTERFACE
|
target_compile_options(VulkanMemoryAllocator INTERFACE
|
||||||
|
|
@ -229,9 +233,6 @@ if (VulkanMemoryAllocator_ADDED)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# httplib
|
|
||||||
AddJsonPackage(httplib)
|
|
||||||
|
|
||||||
# cpp-jwt
|
# cpp-jwt
|
||||||
if (ENABLE_WEB_SERVICE OR ENABLE_UPDATE_CHECKER)
|
if (ENABLE_WEB_SERVICE OR ENABLE_UPDATE_CHECKER)
|
||||||
AddJsonPackage(cpp-jwt)
|
AddJsonPackage(cpp-jwt)
|
||||||
|
|
|
||||||
25
externals/cpmfile.json
vendored
|
|
@ -30,13 +30,15 @@
|
||||||
"tag": "v%VERSION%",
|
"tag": "v%VERSION%",
|
||||||
"hash": "5efa8140aadffe105dcf39935b732476e95755f6c7473ada3d0b64df2bc02c557633ae3948a25b45e1cf67e89a3ff6329fb30362e4ac033b9a1d1e453aa2eded",
|
"hash": "5efa8140aadffe105dcf39935b732476e95755f6c7473ada3d0b64df2bc02c557633ae3948a25b45e1cf67e89a3ff6329fb30362e4ac033b9a1d1e453aa2eded",
|
||||||
"git_version": "0.37.0",
|
"git_version": "0.37.0",
|
||||||
|
"version": "0.18.7",
|
||||||
"find_args": "MODULE GLOBAL",
|
"find_args": "MODULE GLOBAL",
|
||||||
"patches": [
|
"patches": [
|
||||||
"0001-mingw.patch",
|
"0001-mingw.patch",
|
||||||
"0002-fix-zstd.patch"
|
"0002-fix-zstd.patch"
|
||||||
],
|
],
|
||||||
"options": [
|
"options": [
|
||||||
"HTTPLIB_REQUIRE_OPENSSL ON"
|
"HTTPLIB_REQUIRE_OPENSSL ON",
|
||||||
|
"HTTPLIB_DISABLE_MACOSX_AUTOMATIC_ROOT_CERTIFICATES ON"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"cpp-jwt": {
|
"cpp-jwt": {
|
||||||
|
|
@ -208,18 +210,6 @@
|
||||||
"version": "0.9.1",
|
"version": "0.9.1",
|
||||||
"git_version": "0.19.0"
|
"git_version": "0.19.0"
|
||||||
},
|
},
|
||||||
"mcl": {
|
|
||||||
"version": "0.1.12",
|
|
||||||
"repo": "azahar-emu/mcl",
|
|
||||||
"sha": "7b08d83418",
|
|
||||||
"hash": "9c6ba624cb22ef622f78046a82abb99bf5026284ba17dfacaf46ac842cbd3b0f515f5ba45a1598c7671318a78a2e648db72ce8d10e7537f34e39800bdcb57694",
|
|
||||||
"options": [
|
|
||||||
"MCL_INSTALL OFF"
|
|
||||||
],
|
|
||||||
"patches": [
|
|
||||||
"0001-assert-macro.patch"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"libusb": {
|
"libusb": {
|
||||||
"repo": "libusb/libusb",
|
"repo": "libusb/libusb",
|
||||||
"tag": "v%VERSION%",
|
"tag": "v%VERSION%",
|
||||||
|
|
@ -246,12 +236,13 @@
|
||||||
},
|
},
|
||||||
"tzdb": {
|
"tzdb": {
|
||||||
"package": "nx_tzdb",
|
"package": "nx_tzdb",
|
||||||
"repo": "misc/tzdb_to_nx",
|
"repo": "eden-emu/tzdb_to_nx",
|
||||||
"git_host": "git.crueter.xyz",
|
"git_host": "git.eden-emu.dev",
|
||||||
"artifact": "%VERSION%.tar.gz",
|
"artifact": "%VERSION%.tar.gz",
|
||||||
"tag": "%VERSION%",
|
"tag": "%VERSION%",
|
||||||
"hash": "dc37a189a44ce8b5c988ca550582431a6c7eadfd3c6e709bee6277116ee803e714333e85c9e6cbb5c69346a14d6f2cc7ed96e8aa09cc5fb8a89f945059651db6",
|
"hash": "cce65a12bf90f4ead43b24a0b95dfad77ac3d9bfbaaf66c55e6701346e7a1e44ca5d2f23f47ee35ee02271eb1082bf1762af207aad9fb236f1c8476812d008ed",
|
||||||
"version": "121125"
|
"version": "121125",
|
||||||
|
"git_version": "230326"
|
||||||
},
|
},
|
||||||
"vulkan-headers": {
|
"vulkan-headers": {
|
||||||
"repo": "KhronosGroup/Vulkan-Headers",
|
"repo": "KhronosGroup/Vulkan-Headers",
|
||||||
|
|
|
||||||
4
externals/libusb/CMakeLists.txt
vendored
|
|
@ -1,4 +1,4 @@
|
||||||
# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
# SPDX-FileCopyrightText: 2020 yuzu Emulator Project
|
# SPDX-FileCopyrightText: 2020 yuzu Emulator Project
|
||||||
|
|
@ -232,7 +232,7 @@ else() # MINGW OR (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||||
)
|
)
|
||||||
find_package(Threads REQUIRED)
|
find_package(Threads REQUIRED)
|
||||||
if(THREADS_HAVE_PTHREAD_ARG)
|
if(THREADS_HAVE_PTHREAD_ARG)
|
||||||
target_compile_options(usb PUBLIC "-pthread")
|
target_compile_options(usb PUBLIC $<$<COMPILE_LANGUAGE:C,CXX>:-pthread>)
|
||||||
endif()
|
endif()
|
||||||
if(CMAKE_THREAD_LIBS_INIT)
|
if(CMAKE_THREAD_LIBS_INIT)
|
||||||
target_link_libraries(usb PRIVATE "${CMAKE_THREAD_LIBS_INIT}")
|
target_link_libraries(usb PRIVATE "${CMAKE_THREAD_LIBS_INIT}")
|
||||||
|
|
|
||||||
164
externals/renderdoc/renderdoc_app.h
vendored
|
|
@ -7,7 +7,7 @@
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2019-2025 Baldur Karlsson
|
* Copyright (c) 2015-2026 Baldur Karlsson
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -72,6 +72,10 @@ extern "C" {
|
||||||
// truncated version when only a uint64_t is available (e.g. Vulkan tags):
|
// truncated version when only a uint64_t is available (e.g. Vulkan tags):
|
||||||
#define RENDERDOC_ShaderDebugMagicValue_truncated 0x48656670eab25520ULL
|
#define RENDERDOC_ShaderDebugMagicValue_truncated 0x48656670eab25520ULL
|
||||||
|
|
||||||
|
// this is a magic value for vulkan user tags to indicate which dispatchable API objects are which
|
||||||
|
// for object annotations
|
||||||
|
#define RENDERDOC_APIObjectAnnotationHelper 0xfbb3b337b664d0adULL
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// RenderDoc capture options
|
// RenderDoc capture options
|
||||||
//
|
//
|
||||||
|
|
@ -564,6 +568,128 @@ typedef uint32_t(RENDERDOC_CC *pRENDERDOC_DiscardFrameCapture)(RENDERDOC_DeviceP
|
||||||
// multiple times only the last title will be used.
|
// multiple times only the last title will be used.
|
||||||
typedef void(RENDERDOC_CC *pRENDERDOC_SetCaptureTitle)(const char *title);
|
typedef void(RENDERDOC_CC *pRENDERDOC_SetCaptureTitle)(const char *title);
|
||||||
|
|
||||||
|
// Annotations API:
|
||||||
|
//
|
||||||
|
// These functions allow you to specify annotations either on a per-command level, or a per-object
|
||||||
|
// level.
|
||||||
|
//
|
||||||
|
// Basic types of annotations are supported, as well as vector versions and references to API objects.
|
||||||
|
//
|
||||||
|
// The annotations are stored as keys, with the key being a dot-separated path allowing arbitrary
|
||||||
|
// nesting and user organisation. The keys are sorted in human order so `foo.2.bar` will be displayed
|
||||||
|
// before `foo.10.bar` to allow creation of arrays if desired.
|
||||||
|
//
|
||||||
|
// Deleting an annotation can be done by assigning an empty value to it.
|
||||||
|
|
||||||
|
// the type of an annotation value, or Empty to delete an annotation
|
||||||
|
typedef enum RENDERDOC_AnnotationType
|
||||||
|
{
|
||||||
|
eRENDERDOC_Empty,
|
||||||
|
eRENDERDOC_Bool,
|
||||||
|
eRENDERDOC_Int32,
|
||||||
|
eRENDERDOC_UInt32,
|
||||||
|
eRENDERDOC_Int64,
|
||||||
|
eRENDERDOC_UInt64,
|
||||||
|
eRENDERDOC_Float,
|
||||||
|
eRENDERDOC_Double,
|
||||||
|
eRENDERDOC_String,
|
||||||
|
eRENDERDOC_APIObject,
|
||||||
|
eRENDERDOC_AnnotationMax = 0x7FFFFFFF,
|
||||||
|
} RENDERDOC_AnnotationType;
|
||||||
|
|
||||||
|
// a union with vector annotation value data
|
||||||
|
typedef union RENDERDOC_AnnotationVectorValue
|
||||||
|
{
|
||||||
|
bool boolean[4];
|
||||||
|
int32_t int32[4];
|
||||||
|
int64_t int64[4];
|
||||||
|
uint32_t uint32[4];
|
||||||
|
uint64_t uint64[4];
|
||||||
|
float float32[4];
|
||||||
|
double float64[4];
|
||||||
|
} RENDERDOC_AnnotationVectorValue;
|
||||||
|
|
||||||
|
// a union with scalar annotation value data
|
||||||
|
typedef union RENDERDOC_AnnotationValue
|
||||||
|
{
|
||||||
|
bool boolean;
|
||||||
|
int32_t int32;
|
||||||
|
int64_t int64;
|
||||||
|
uint32_t uint32;
|
||||||
|
uint64_t uint64;
|
||||||
|
float float32;
|
||||||
|
double float64;
|
||||||
|
|
||||||
|
RENDERDOC_AnnotationVectorValue vector;
|
||||||
|
|
||||||
|
const char *string;
|
||||||
|
void *apiObject;
|
||||||
|
} RENDERDOC_AnnotationValue;
|
||||||
|
|
||||||
|
// a struct for specifying a GL object, as we don't have pointers we can use so instead we specify a
|
||||||
|
// pointer to this struct giving both the type and the name
|
||||||
|
typedef struct RENDERDOC_GLResourceReference
|
||||||
|
{
|
||||||
|
// this is the same GLenum identifier as passed to glObjectLabel
|
||||||
|
uint32_t identifier;
|
||||||
|
uint32_t name;
|
||||||
|
} GLResourceReference;
|
||||||
|
|
||||||
|
// simple C++ helpers to avoid the need for a temporary objects for value passing and GL object specification
|
||||||
|
#ifdef __cplusplus
|
||||||
|
struct RDGLObjectHelper
|
||||||
|
{
|
||||||
|
RENDERDOC_GLResourceReference gl;
|
||||||
|
|
||||||
|
RDGLObjectHelper(uint32_t identifier, uint32_t name)
|
||||||
|
{
|
||||||
|
gl.identifier = identifier;
|
||||||
|
gl.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
operator RENDERDOC_GLResourceReference *() { return ≷ }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RDAnnotationHelper
|
||||||
|
{
|
||||||
|
RENDERDOC_AnnotationValue val;
|
||||||
|
|
||||||
|
RDAnnotationHelper(bool b) { val.boolean = b; }
|
||||||
|
RDAnnotationHelper(int32_t i) { val.int32 = i; }
|
||||||
|
RDAnnotationHelper(int64_t i) { val.int64 = i; }
|
||||||
|
RDAnnotationHelper(uint32_t i) { val.uint32 = i; }
|
||||||
|
RDAnnotationHelper(uint64_t i) { val.uint64 = i; }
|
||||||
|
RDAnnotationHelper(float f) { val.float32 = f; }
|
||||||
|
RDAnnotationHelper(double d) { val.float64 = d; }
|
||||||
|
RDAnnotationHelper(const char *s) { val.string = s; }
|
||||||
|
|
||||||
|
operator RENDERDOC_AnnotationValue *() { return &val; }
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// The device is specified in the same way as other API calls that take a RENDERDOC_DevicePointer
|
||||||
|
// to specify the device.
|
||||||
|
//
|
||||||
|
// The object or queue/commandbuffer will depend on the graphics API in question.
|
||||||
|
//
|
||||||
|
// Return value:
|
||||||
|
// 0 - The annotation was applied successfully.
|
||||||
|
// 1 - The device is unknown/invalid
|
||||||
|
// 2 - The device is valid but the annotation is not supported for API-specific reasons, such as an
|
||||||
|
// unrecognised or invalid object or queue/commandbuffer
|
||||||
|
// 3 - The call is ill-formed or invalid e.g. empty is specified with a value pointer, or non-empty
|
||||||
|
// is specified with a NULL value pointer
|
||||||
|
typedef uint32_t(RENDERDOC_CC *pRENDERDOC_SetObjectAnnotation)(RENDERDOC_DevicePointer device,
|
||||||
|
void *object, const char *key,
|
||||||
|
RENDERDOC_AnnotationType valueType,
|
||||||
|
uint32_t valueVectorWidth,
|
||||||
|
const RENDERDOC_AnnotationValue *value);
|
||||||
|
|
||||||
|
typedef uint32_t(RENDERDOC_CC *pRENDERDOC_SetCommandAnnotation)(
|
||||||
|
RENDERDOC_DevicePointer device, void *queueOrCommandBuffer, const char *key,
|
||||||
|
RENDERDOC_AnnotationType valueType, uint32_t valueVectorWidth,
|
||||||
|
const RENDERDOC_AnnotationValue *value);
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// RenderDoc API versions
|
// RenderDoc API versions
|
||||||
//
|
//
|
||||||
|
|
@ -592,6 +718,7 @@ typedef enum RENDERDOC_Version
|
||||||
eRENDERDOC_API_Version_1_4_2 = 10402, // RENDERDOC_API_1_4_2 = 1 04 02
|
eRENDERDOC_API_Version_1_4_2 = 10402, // RENDERDOC_API_1_4_2 = 1 04 02
|
||||||
eRENDERDOC_API_Version_1_5_0 = 10500, // RENDERDOC_API_1_5_0 = 1 05 00
|
eRENDERDOC_API_Version_1_5_0 = 10500, // RENDERDOC_API_1_5_0 = 1 05 00
|
||||||
eRENDERDOC_API_Version_1_6_0 = 10600, // RENDERDOC_API_1_6_0 = 1 06 00
|
eRENDERDOC_API_Version_1_6_0 = 10600, // RENDERDOC_API_1_6_0 = 1 06 00
|
||||||
|
eRENDERDOC_API_Version_1_7_0 = 10700, // RENDERDOC_API_1_7_0 = 1 07 00
|
||||||
} RENDERDOC_Version;
|
} RENDERDOC_Version;
|
||||||
|
|
||||||
// API version changelog:
|
// API version changelog:
|
||||||
|
|
@ -622,8 +749,10 @@ typedef enum RENDERDOC_Version
|
||||||
// 1.5.0 - Added feature: ShowReplayUI() to request that the replay UI show itself if connected
|
// 1.5.0 - Added feature: ShowReplayUI() to request that the replay UI show itself if connected
|
||||||
// 1.6.0 - Added feature: SetCaptureTitle() which can be used to set a title for a
|
// 1.6.0 - Added feature: SetCaptureTitle() which can be used to set a title for a
|
||||||
// capture made with StartFrameCapture() or EndFrameCapture()
|
// capture made with StartFrameCapture() or EndFrameCapture()
|
||||||
|
// 1.7.0 - Added feature: SetObjectAnnotation() / SetCommandAnnotation() for adding rich
|
||||||
|
// annotations to objects and command streams
|
||||||
|
|
||||||
typedef struct RENDERDOC_API_1_6_0
|
typedef struct RENDERDOC_API_1_7_0
|
||||||
{
|
{
|
||||||
pRENDERDOC_GetAPIVersion GetAPIVersion;
|
pRENDERDOC_GetAPIVersion GetAPIVersion;
|
||||||
|
|
||||||
|
|
@ -701,20 +830,25 @@ typedef struct RENDERDOC_API_1_6_0
|
||||||
|
|
||||||
// new function in 1.6.0
|
// new function in 1.6.0
|
||||||
pRENDERDOC_SetCaptureTitle SetCaptureTitle;
|
pRENDERDOC_SetCaptureTitle SetCaptureTitle;
|
||||||
} RENDERDOC_API_1_6_0;
|
|
||||||
|
|
||||||
typedef RENDERDOC_API_1_6_0 RENDERDOC_API_1_0_0;
|
// new functions in 1.7.0
|
||||||
typedef RENDERDOC_API_1_6_0 RENDERDOC_API_1_0_1;
|
pRENDERDOC_SetObjectAnnotation SetObjectAnnotation;
|
||||||
typedef RENDERDOC_API_1_6_0 RENDERDOC_API_1_0_2;
|
pRENDERDOC_SetCommandAnnotation SetCommandAnnotation;
|
||||||
typedef RENDERDOC_API_1_6_0 RENDERDOC_API_1_1_0;
|
} RENDERDOC_API_1_7_0;
|
||||||
typedef RENDERDOC_API_1_6_0 RENDERDOC_API_1_1_1;
|
|
||||||
typedef RENDERDOC_API_1_6_0 RENDERDOC_API_1_1_2;
|
typedef RENDERDOC_API_1_7_0 RENDERDOC_API_1_0_0;
|
||||||
typedef RENDERDOC_API_1_6_0 RENDERDOC_API_1_2_0;
|
typedef RENDERDOC_API_1_7_0 RENDERDOC_API_1_0_1;
|
||||||
typedef RENDERDOC_API_1_6_0 RENDERDOC_API_1_3_0;
|
typedef RENDERDOC_API_1_7_0 RENDERDOC_API_1_0_2;
|
||||||
typedef RENDERDOC_API_1_6_0 RENDERDOC_API_1_4_0;
|
typedef RENDERDOC_API_1_7_0 RENDERDOC_API_1_1_0;
|
||||||
typedef RENDERDOC_API_1_6_0 RENDERDOC_API_1_4_1;
|
typedef RENDERDOC_API_1_7_0 RENDERDOC_API_1_1_1;
|
||||||
typedef RENDERDOC_API_1_6_0 RENDERDOC_API_1_4_2;
|
typedef RENDERDOC_API_1_7_0 RENDERDOC_API_1_1_2;
|
||||||
typedef RENDERDOC_API_1_6_0 RENDERDOC_API_1_5_0;
|
typedef RENDERDOC_API_1_7_0 RENDERDOC_API_1_2_0;
|
||||||
|
typedef RENDERDOC_API_1_7_0 RENDERDOC_API_1_3_0;
|
||||||
|
typedef RENDERDOC_API_1_7_0 RENDERDOC_API_1_4_0;
|
||||||
|
typedef RENDERDOC_API_1_7_0 RENDERDOC_API_1_4_1;
|
||||||
|
typedef RENDERDOC_API_1_7_0 RENDERDOC_API_1_4_2;
|
||||||
|
typedef RENDERDOC_API_1_7_0 RENDERDOC_API_1_5_0;
|
||||||
|
typedef RENDERDOC_API_1_7_0 RENDERDOC_API_1_6_0;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// RenderDoc API entry point
|
// RenderDoc API entry point
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
include_directories(.)
|
include_directories(.)
|
||||||
|
|
||||||
# Dynarmic
|
# Dynarmic
|
||||||
if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64 AND NOT YUZU_STATIC_ROOM)
|
if ((ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64 OR ARCHITECTURE_riscv64) AND NOT YUZU_STATIC_ROOM)
|
||||||
add_subdirectory(dynarmic)
|
add_subdirectory(dynarmic)
|
||||||
add_library(dynarmic::dynarmic ALIAS dynarmic)
|
add_library(dynarmic::dynarmic ALIAS dynarmic)
|
||||||
endif()
|
endif()
|
||||||
|
|
@ -118,47 +118,42 @@ if (MSVC AND NOT CXX_CLANG)
|
||||||
else()
|
else()
|
||||||
if (NOT MSVC)
|
if (NOT MSVC)
|
||||||
add_compile_options(
|
add_compile_options(
|
||||||
-fwrapv
|
$<$<COMPILE_LANGUAGE:C,CXX>:-fwrapv>
|
||||||
-fno-rtti # Disable RTTI
|
$<$<COMPILE_LANGUAGE:C,CXX>:-pipe>
|
||||||
-pipe
|
# Disable RTTI (C++ only)
|
||||||
)
|
$<$<COMPILE_LANGUAGE:CXX>:-fno-rtti>)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_compile_options(
|
add_compile_options(
|
||||||
-Werror=all
|
$<$<COMPILE_LANGUAGE:C,CXX>:-Werror=all>
|
||||||
-Werror=extra
|
$<$<COMPILE_LANGUAGE:C,CXX>:-Werror=extra>
|
||||||
-Werror=missing-declarations
|
$<$<COMPILE_LANGUAGE:C,CXX>:-Werror=missing-declarations>
|
||||||
-Werror=shadow
|
$<$<COMPILE_LANGUAGE:C,CXX>:-Werror=shadow>
|
||||||
-Werror=unused
|
$<$<COMPILE_LANGUAGE:C,CXX>:-Werror=unused>
|
||||||
|
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-attributes>
|
||||||
-Wno-attributes
|
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-invalid-offsetof>
|
||||||
-Wno-invalid-offsetof
|
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-unused-parameter>
|
||||||
-Wno-unused-parameter
|
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-missing-field-initializers>)
|
||||||
-Wno-missing-field-initializers
|
|
||||||
)
|
|
||||||
|
|
||||||
if (CXX_CLANG OR CXX_ICC OR CXX_APPLE) # Clang, AppleClang, or Intel C++
|
if (CXX_CLANG OR CXX_ICC OR CXX_APPLE) # Clang, AppleClang, or Intel C++
|
||||||
if (NOT MSVC)
|
if (NOT MSVC)
|
||||||
add_compile_options(
|
add_compile_options(
|
||||||
-Werror=shadow-uncaptured-local
|
$<$<COMPILE_LANGUAGE:C,CXX>:-Werror=shadow-uncaptured-local>
|
||||||
-Werror=implicit-fallthrough
|
$<$<COMPILE_LANGUAGE:C,CXX>:-Werror=implicit-fallthrough>
|
||||||
-Werror=type-limits
|
$<$<COMPILE_LANGUAGE:C,CXX>:-Werror=type-limits>)
|
||||||
)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_compile_options(
|
add_compile_options(
|
||||||
-Wno-braced-scalar-init
|
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-braced-scalar-init>
|
||||||
-Wno-unused-private-field
|
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-unused-private-field>
|
||||||
-Wno-nullability-completeness
|
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-nullability-completeness>)
|
||||||
)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (ARCHITECTURE_x86_64)
|
if (ARCHITECTURE_x86_64)
|
||||||
add_compile_options("-mcx16")
|
add_compile_options(-mcx16)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (APPLE AND CXX_CLANG)
|
if (APPLE AND CXX_CLANG)
|
||||||
add_compile_options("-stdlib=libc++")
|
add_compile_options($<$<COMPILE_LANGUAGE:C,CXX>:-stdlib=libc++>)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# GCC bugs
|
# GCC bugs
|
||||||
|
|
@ -166,10 +161,9 @@ else()
|
||||||
# These diagnostics would be great if they worked, but are just completely broken
|
# These diagnostics would be great if they worked, but are just completely broken
|
||||||
# and produce bogus errors on external libraries like fmt.
|
# and produce bogus errors on external libraries like fmt.
|
||||||
add_compile_options(
|
add_compile_options(
|
||||||
-Wno-array-bounds
|
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-array-bounds>
|
||||||
-Wno-stringop-overread
|
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-stringop-overread>
|
||||||
-Wno-stringop-overflow
|
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-stringop-overflow>)
|
||||||
)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Set file offset size to 64 bits.
|
# Set file offset size to 64 bits.
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,11 @@ import android.hardware.SensorEventListener
|
||||||
import android.hardware.SensorManager
|
import android.hardware.SensorManager
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
|
import androidx.navigation.NavOptions
|
||||||
|
import org.yuzu.yuzu_emu.fragments.EmulationFragment
|
||||||
|
import org.yuzu.yuzu_emu.utils.CustomSettingsHandler
|
||||||
import android.util.Rational
|
import android.util.Rational
|
||||||
import android.view.InputDevice
|
import android.view.InputDevice
|
||||||
import android.view.KeyEvent
|
import android.view.KeyEvent
|
||||||
|
|
@ -87,6 +92,28 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager
|
||||||
private val emulationViewModel: EmulationViewModel by viewModels()
|
private val emulationViewModel: EmulationViewModel by viewModels()
|
||||||
|
|
||||||
private var foregroundService: Intent? = null
|
private var foregroundService: Intent? = null
|
||||||
|
private val mainHandler = Handler(Looper.getMainLooper())
|
||||||
|
private var pendingRomSwapIntent: Intent? = null
|
||||||
|
private var isWaitingForRomSwapStop = false
|
||||||
|
private var romSwapNativeStopped = false
|
||||||
|
private var romSwapThreadStopped = false
|
||||||
|
private var romSwapGeneration = 0
|
||||||
|
private var hasEmulationSession = processHasEmulationSession
|
||||||
|
private val romSwapStopTimeoutRunnable = Runnable { onRomSwapStopTimeout() }
|
||||||
|
|
||||||
|
private fun onRomSwapStopTimeout() {
|
||||||
|
if (!isWaitingForRomSwapStop) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
Log.warning("[EmulationActivity] ROM swap stop timed out; retrying native stop and continuing to wait")
|
||||||
|
NativeLibrary.stopEmulation()
|
||||||
|
scheduleRomSwapStopTimeout()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun scheduleRomSwapStopTimeout() {
|
||||||
|
mainHandler.removeCallbacks(romSwapStopTimeoutRunnable)
|
||||||
|
mainHandler.postDelayed(romSwapStopTimeoutRunnable, ROM_SWAP_STOP_TIMEOUT_MS)
|
||||||
|
}
|
||||||
|
|
||||||
override fun attachBaseContext(base: Context) {
|
override fun attachBaseContext(base: Context) {
|
||||||
super.attachBaseContext(YuzuApplication.applyLanguage(base))
|
super.attachBaseContext(YuzuApplication.applyLanguage(base))
|
||||||
|
|
@ -128,9 +155,29 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager
|
||||||
binding = ActivityEmulationBinding.inflate(layoutInflater)
|
binding = ActivityEmulationBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
|
|
||||||
|
val launchIntent = Intent(intent)
|
||||||
|
val shouldDeferLaunchForSwap = hasEmulationSession && isSwapIntent(launchIntent)
|
||||||
|
if (shouldDeferLaunchForSwap) {
|
||||||
|
Log.info("[EmulationActivity] onCreate detected existing session; deferring new game setup for swap")
|
||||||
|
emulationViewModel.setIsEmulationStopping(true)
|
||||||
|
emulationViewModel.setEmulationStopped(false)
|
||||||
|
}
|
||||||
|
|
||||||
val navHostFragment =
|
val navHostFragment =
|
||||||
supportFragmentManager.findFragmentById(R.id.fragment_container) as NavHostFragment
|
supportFragmentManager.findFragmentById(R.id.fragment_container) as NavHostFragment
|
||||||
navHostFragment.navController.setGraph(R.navigation.emulation_navigation, intent.extras)
|
val initialArgs = if (shouldDeferLaunchForSwap) {
|
||||||
|
Bundle(intent.extras ?: Bundle()).apply {
|
||||||
|
processSessionGame?.let { putParcelable("game", it) }
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
intent.extras
|
||||||
|
}
|
||||||
|
navHostFragment.navController.setGraph(R.navigation.emulation_navigation, initialArgs)
|
||||||
|
if (shouldDeferLaunchForSwap) {
|
||||||
|
mainHandler.post {
|
||||||
|
handleSwapIntent(launchIntent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
isActivityRecreated = savedInstanceState != null
|
isActivityRecreated = savedInstanceState != null
|
||||||
|
|
||||||
|
|
@ -199,6 +246,7 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager
|
||||||
nfcReader.startScanning()
|
nfcReader.startScanning()
|
||||||
startMotionSensorListener()
|
startMotionSensorListener()
|
||||||
InputHandler.updateControllerData()
|
InputHandler.updateControllerData()
|
||||||
|
notifyPhysicalControllerState()
|
||||||
|
|
||||||
buildPictureInPictureParams()
|
buildPictureInPictureParams()
|
||||||
}
|
}
|
||||||
|
|
@ -210,6 +258,7 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
|
mainHandler.removeCallbacks(romSwapStopTimeoutRunnable)
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
inputManager.unregisterInputDeviceListener(this)
|
inputManager.unregisterInputDeviceListener(this)
|
||||||
stopForegroundService(this)
|
stopForegroundService(this)
|
||||||
|
|
@ -228,17 +277,123 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager
|
||||||
|
|
||||||
override fun onNewIntent(intent: Intent) {
|
override fun onNewIntent(intent: Intent) {
|
||||||
super.onNewIntent(intent)
|
super.onNewIntent(intent)
|
||||||
setIntent(intent)
|
handleSwapIntent(intent)
|
||||||
|
|
||||||
// Reset navigation graph with new intent data to recreate EmulationFragment
|
|
||||||
val navHostFragment =
|
|
||||||
supportFragmentManager.findFragmentById(R.id.fragment_container) as NavHostFragment
|
|
||||||
navHostFragment.navController.setGraph(R.navigation.emulation_navigation, intent.extras)
|
|
||||||
|
|
||||||
nfcReader.onNewIntent(intent)
|
nfcReader.onNewIntent(intent)
|
||||||
InputHandler.updateControllerData()
|
InputHandler.updateControllerData()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun isSwapIntent(intent: Intent): Boolean {
|
||||||
|
return when {
|
||||||
|
intent.getBooleanExtra(EXTRA_OVERLAY_GAMELESS_EDIT_MODE, false) -> false
|
||||||
|
intent.action == CustomSettingsHandler.CUSTOM_CONFIG_ACTION -> true
|
||||||
|
intent.data != null -> true
|
||||||
|
else -> {
|
||||||
|
val extras = intent.extras
|
||||||
|
extras != null &&
|
||||||
|
BundleCompat.getParcelable(extras, EXTRA_SELECTED_GAME, Game::class.java) != null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleSwapIntent(intent: Intent) {
|
||||||
|
if (!isSwapIntent(intent)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
pendingRomSwapIntent = Intent(intent)
|
||||||
|
|
||||||
|
if (!isWaitingForRomSwapStop) {
|
||||||
|
Log.info("[EmulationActivity] Begin ROM swap: data=${intent.data}")
|
||||||
|
isWaitingForRomSwapStop = true
|
||||||
|
romSwapNativeStopped = false
|
||||||
|
romSwapThreadStopped = false
|
||||||
|
romSwapGeneration += 1
|
||||||
|
val thisSwapGeneration = romSwapGeneration
|
||||||
|
emulationViewModel.setIsEmulationStopping(true)
|
||||||
|
emulationViewModel.setEmulationStopped(false)
|
||||||
|
val navHostFragment =
|
||||||
|
supportFragmentManager.findFragmentById(R.id.fragment_container) as? NavHostFragment
|
||||||
|
val childFragmentManager = navHostFragment?.childFragmentManager
|
||||||
|
val stoppingFragmentForSwap =
|
||||||
|
(childFragmentManager?.primaryNavigationFragment as? EmulationFragment) ?:
|
||||||
|
childFragmentManager
|
||||||
|
?.fragments
|
||||||
|
?.asReversed()
|
||||||
|
?.firstOrNull {
|
||||||
|
it is EmulationFragment &&
|
||||||
|
it.isAdded &&
|
||||||
|
it.view != null &&
|
||||||
|
!it.isRemoving
|
||||||
|
} as? EmulationFragment
|
||||||
|
|
||||||
|
val hasSessionForSwap = hasEmulationSession || stoppingFragmentForSwap != null
|
||||||
|
|
||||||
|
if (!hasSessionForSwap) {
|
||||||
|
romSwapNativeStopped = true
|
||||||
|
romSwapThreadStopped = true
|
||||||
|
} else {
|
||||||
|
if (stoppingFragmentForSwap != null) {
|
||||||
|
stoppingFragmentForSwap.stopForRomSwap()
|
||||||
|
stoppingFragmentForSwap.notifyWhenEmulationThreadStops {
|
||||||
|
if (!isWaitingForRomSwapStop || romSwapGeneration != thisSwapGeneration) {
|
||||||
|
return@notifyWhenEmulationThreadStops
|
||||||
|
}
|
||||||
|
romSwapThreadStopped = true
|
||||||
|
Log.info("[EmulationActivity] ROM swap thread stop acknowledged")
|
||||||
|
launchPendingRomSwap(force = false)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.warning("[EmulationActivity] ROM swap stop target fragment not found; requesting native stop")
|
||||||
|
romSwapThreadStopped = true
|
||||||
|
NativeLibrary.stopEmulation()
|
||||||
|
}
|
||||||
|
|
||||||
|
scheduleRomSwapStopTimeout()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
launchPendingRomSwap(force = false)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun launchPendingRomSwap(force: Boolean) {
|
||||||
|
if (!isWaitingForRomSwapStop) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!force && (!romSwapNativeStopped || !romSwapThreadStopped)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val swapIntent = pendingRomSwapIntent ?: return
|
||||||
|
Log.info("[EmulationActivity] Launching pending ROM swap: data=${swapIntent.data}")
|
||||||
|
pendingRomSwapIntent = null
|
||||||
|
isWaitingForRomSwapStop = false
|
||||||
|
romSwapNativeStopped = false
|
||||||
|
romSwapThreadStopped = false
|
||||||
|
mainHandler.removeCallbacks(romSwapStopTimeoutRunnable)
|
||||||
|
applyGameLaunchIntent(swapIntent)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun applyGameLaunchIntent(intent: Intent) {
|
||||||
|
hasEmulationSession = true
|
||||||
|
processHasEmulationSession = true
|
||||||
|
emulationViewModel.setIsEmulationStopping(false)
|
||||||
|
emulationViewModel.setEmulationStopped(false)
|
||||||
|
setIntent(Intent(intent))
|
||||||
|
val navHostFragment =
|
||||||
|
supportFragmentManager.findFragmentById(R.id.fragment_container) as NavHostFragment
|
||||||
|
val navController = navHostFragment.navController
|
||||||
|
val startArgs = intent.extras?.let { Bundle(it) } ?: Bundle()
|
||||||
|
val navOptions = NavOptions.Builder()
|
||||||
|
.setPopUpTo(R.id.emulationFragment, true)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
runCatching {
|
||||||
|
navController.navigate(R.id.emulationFragment, startArgs, navOptions)
|
||||||
|
}.onFailure {
|
||||||
|
Log.warning("[EmulationActivity] ROM swap navigate fallback to setGraph: ${it.message}")
|
||||||
|
navController.setGraph(R.navigation.emulation_navigation, startArgs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun dispatchKeyEvent(event: KeyEvent): Boolean {
|
override fun dispatchKeyEvent(event: KeyEvent): Boolean {
|
||||||
|
|
||||||
if (event.keyCode == KeyEvent.KEYCODE_VOLUME_UP ||
|
if (event.keyCode == KeyEvent.KEYCODE_VOLUME_UP ||
|
||||||
|
|
@ -249,8 +404,7 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager
|
||||||
val isPhysicalKeyboard = event.source and InputDevice.SOURCE_KEYBOARD == InputDevice.SOURCE_KEYBOARD &&
|
val isPhysicalKeyboard = event.source and InputDevice.SOURCE_KEYBOARD == InputDevice.SOURCE_KEYBOARD &&
|
||||||
event.device?.isVirtual == false
|
event.device?.isVirtual == false
|
||||||
|
|
||||||
val isControllerInput = event.source and InputDevice.SOURCE_JOYSTICK == InputDevice.SOURCE_JOYSTICK ||
|
val isControllerInput = InputHandler.isPhysicalGameController(event.device)
|
||||||
event.source and InputDevice.SOURCE_GAMEPAD == InputDevice.SOURCE_GAMEPAD
|
|
||||||
|
|
||||||
if (!isControllerInput &&
|
if (!isControllerInput &&
|
||||||
event.source and InputDevice.SOURCE_MOUSE != InputDevice.SOURCE_MOUSE &&
|
event.source and InputDevice.SOURCE_MOUSE != InputDevice.SOURCE_MOUSE &&
|
||||||
|
|
@ -271,8 +425,7 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun dispatchGenericMotionEvent(event: MotionEvent): Boolean {
|
override fun dispatchGenericMotionEvent(event: MotionEvent): Boolean {
|
||||||
val isControllerInput = event.source and InputDevice.SOURCE_JOYSTICK == InputDevice.SOURCE_JOYSTICK ||
|
val isControllerInput = InputHandler.isPhysicalGameController(event.device)
|
||||||
event.source and InputDevice.SOURCE_GAMEPAD == InputDevice.SOURCE_GAMEPAD
|
|
||||||
|
|
||||||
if (!isControllerInput &&
|
if (!isControllerInput &&
|
||||||
event.source and InputDevice.SOURCE_KEYBOARD != InputDevice.SOURCE_KEYBOARD &&
|
event.source and InputDevice.SOURCE_KEYBOARD != InputDevice.SOURCE_KEYBOARD &&
|
||||||
|
|
@ -306,38 +459,36 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isGameController(deviceId: Int): Boolean {
|
private fun isGameController(deviceId: Int): Boolean {
|
||||||
val device = InputDevice.getDevice(deviceId) ?: return false
|
return InputHandler.isPhysicalGameController(InputDevice.getDevice(deviceId))
|
||||||
val sources = device.sources
|
|
||||||
return sources and InputDevice.SOURCE_GAMEPAD == InputDevice.SOURCE_GAMEPAD ||
|
|
||||||
sources and InputDevice.SOURCE_JOYSTICK == InputDevice.SOURCE_JOYSTICK
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onInputDeviceAdded(deviceId: Int) {
|
override fun onInputDeviceAdded(deviceId: Int) {
|
||||||
if (isGameController(deviceId)) {
|
if (isGameController(deviceId)) {
|
||||||
InputHandler.updateControllerData()
|
InputHandler.updateControllerData()
|
||||||
val navHostFragment =
|
notifyPhysicalControllerState()
|
||||||
supportFragmentManager.findFragmentById(R.id.fragment_container) as? NavHostFragment
|
|
||||||
val emulationFragment =
|
|
||||||
navHostFragment?.childFragmentManager?.fragments?.firstOrNull() as? org.yuzu.yuzu_emu.fragments.EmulationFragment
|
|
||||||
emulationFragment?.onControllerConnected()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onInputDeviceRemoved(deviceId: Int) {
|
override fun onInputDeviceRemoved(deviceId: Int) {
|
||||||
InputHandler.updateControllerData()
|
InputHandler.updateControllerData()
|
||||||
val navHostFragment =
|
notifyPhysicalControllerState()
|
||||||
supportFragmentManager.findFragmentById(R.id.fragment_container) as? NavHostFragment
|
|
||||||
val emulationFragment =
|
|
||||||
navHostFragment?.childFragmentManager?.fragments?.firstOrNull() as? org.yuzu.yuzu_emu.fragments.EmulationFragment
|
|
||||||
emulationFragment?.onControllerDisconnected()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onInputDeviceChanged(deviceId: Int) {
|
override fun onInputDeviceChanged(deviceId: Int) {
|
||||||
if (isGameController(deviceId)) {
|
if (isGameController(deviceId)) {
|
||||||
InputHandler.updateControllerData()
|
InputHandler.updateControllerData()
|
||||||
|
notifyPhysicalControllerState()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun notifyPhysicalControllerState() {
|
||||||
|
val navHostFragment =
|
||||||
|
supportFragmentManager.findFragmentById(R.id.fragment_container) as? NavHostFragment
|
||||||
|
val emulationFragment =
|
||||||
|
navHostFragment?.childFragmentManager?.fragments?.firstOrNull() as? org.yuzu.yuzu_emu.fragments.EmulationFragment
|
||||||
|
emulationFragment?.onPhysicalControllerStateChanged(InputHandler.androidControllers.isNotEmpty())
|
||||||
|
}
|
||||||
|
|
||||||
override fun onSensorChanged(event: SensorEvent) {
|
override fun onSensorChanged(event: SensorEvent) {
|
||||||
if (!NativeLibrary.isRunning() || NativeLibrary.isPaused()) {
|
if (!NativeLibrary.isRunning() || NativeLibrary.isPaused()) {
|
||||||
return
|
return
|
||||||
|
|
@ -608,19 +759,48 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onEmulationStarted() {
|
fun onEmulationStarted() {
|
||||||
|
if (Looper.myLooper() != Looper.getMainLooper()) {
|
||||||
|
mainHandler.post { onEmulationStarted() }
|
||||||
|
return
|
||||||
|
}
|
||||||
|
hasEmulationSession = true
|
||||||
|
processHasEmulationSession = true
|
||||||
emulationViewModel.setEmulationStarted(true)
|
emulationViewModel.setEmulationStarted(true)
|
||||||
|
emulationViewModel.setIsEmulationStopping(false)
|
||||||
|
emulationViewModel.setEmulationStopped(false)
|
||||||
NativeLibrary.playTimeManagerStart()
|
NativeLibrary.playTimeManagerStart()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onEmulationStopped(status: Int) {
|
fun onEmulationStopped(status: Int) {
|
||||||
if (status == 0 && emulationViewModel.programChanged.value == -1) {
|
if (Looper.myLooper() != Looper.getMainLooper()) {
|
||||||
|
mainHandler.post { onEmulationStopped(status) }
|
||||||
|
return
|
||||||
|
}
|
||||||
|
hasEmulationSession = false
|
||||||
|
processHasEmulationSession = false
|
||||||
|
if (isWaitingForRomSwapStop) {
|
||||||
|
romSwapNativeStopped = true
|
||||||
|
Log.info("[EmulationActivity] ROM swap native stop acknowledged")
|
||||||
|
launchPendingRomSwap(force = false)
|
||||||
|
} else if (status == 0 && emulationViewModel.programChanged.value == -1) {
|
||||||
|
processSessionGame = null
|
||||||
finish()
|
finish()
|
||||||
|
} else if (!isWaitingForRomSwapStop) {
|
||||||
|
processSessionGame = null
|
||||||
}
|
}
|
||||||
emulationViewModel.setEmulationStopped(true)
|
emulationViewModel.setEmulationStopped(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun updateSessionGame(game: Game?) {
|
||||||
|
processSessionGame = game
|
||||||
|
}
|
||||||
|
|
||||||
fun onProgramChanged(programIndex: Int) {
|
fun onProgramChanged(programIndex: Int) {
|
||||||
|
if (Looper.myLooper() != Looper.getMainLooper()) {
|
||||||
|
mainHandler.post { onProgramChanged(programIndex) }
|
||||||
|
return
|
||||||
|
}
|
||||||
emulationViewModel.setProgramChanged(programIndex)
|
emulationViewModel.setProgramChanged(programIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -644,6 +824,11 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager
|
||||||
companion object {
|
companion object {
|
||||||
const val EXTRA_SELECTED_GAME = "SelectedGame"
|
const val EXTRA_SELECTED_GAME = "SelectedGame"
|
||||||
const val EXTRA_OVERLAY_GAMELESS_EDIT_MODE = "overlayGamelessEditMode"
|
const val EXTRA_OVERLAY_GAMELESS_EDIT_MODE = "overlayGamelessEditMode"
|
||||||
|
private const val ROM_SWAP_STOP_TIMEOUT_MS = 5000L
|
||||||
|
@Volatile
|
||||||
|
private var processHasEmulationSession = false
|
||||||
|
@Volatile
|
||||||
|
private var processSessionGame: Game? = null
|
||||||
|
|
||||||
fun stopForegroundService(activity: Activity) {
|
fun stopForegroundService(activity: Activity) {
|
||||||
val startIntent = Intent(activity, ForegroundService::class.java)
|
val startIntent = Intent(activity, ForegroundService::class.java)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
package org.yuzu.yuzu_emu.dialogs
|
package org.yuzu.yuzu_emu.dialogs
|
||||||
|
|
@ -20,6 +20,8 @@ import org.yuzu.yuzu_emu.databinding.DialogChatBinding
|
||||||
import org.yuzu.yuzu_emu.databinding.ItemChatMessageBinding
|
import org.yuzu.yuzu_emu.databinding.ItemChatMessageBinding
|
||||||
import org.yuzu.yuzu_emu.features.settings.model.StringSetting
|
import org.yuzu.yuzu_emu.features.settings.model.StringSetting
|
||||||
import org.yuzu.yuzu_emu.network.NetPlayManager
|
import org.yuzu.yuzu_emu.network.NetPlayManager
|
||||||
|
import org.yuzu.yuzu_emu.utils.CompatUtils
|
||||||
|
import org.yuzu.yuzu_emu.utils.FullscreenHelper
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
|
@ -34,6 +36,13 @@ class ChatDialog(context: Context) : BottomSheetDialog(context) {
|
||||||
private lateinit var binding: DialogChatBinding
|
private lateinit var binding: DialogChatBinding
|
||||||
private lateinit var chatAdapter: ChatAdapter
|
private lateinit var chatAdapter: ChatAdapter
|
||||||
private val handler = Handler(Looper.getMainLooper())
|
private val handler = Handler(Looper.getMainLooper())
|
||||||
|
private val hideSystemBars: Boolean by lazy {
|
||||||
|
runCatching {
|
||||||
|
FullscreenHelper.shouldHideSystemBars(CompatUtils.findActivity(context))
|
||||||
|
}.getOrElse {
|
||||||
|
FullscreenHelper.isFullscreenEnabled(context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(alekpop, crueter): Top drawer for message notifications, perhaps use system notifs?
|
// TODO(alekpop, crueter): Top drawer for message notifications, perhaps use system notifs?
|
||||||
// TODO(alekpop, crueter): Context menu actions for chat users
|
// TODO(alekpop, crueter): Context menu actions for chat users
|
||||||
|
|
@ -41,6 +50,7 @@ class ChatDialog(context: Context) : BottomSheetDialog(context) {
|
||||||
@SuppressLint("NotifyDataSetChanged")
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
setOnShowListener { applyFullscreenMode() }
|
||||||
binding = DialogChatBinding.inflate(LayoutInflater.from(context))
|
binding = DialogChatBinding.inflate(LayoutInflater.from(context))
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
|
|
||||||
|
|
@ -75,6 +85,11 @@ class ChatDialog(context: Context) : BottomSheetDialog(context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onStart() {
|
||||||
|
super.onStart()
|
||||||
|
applyFullscreenMode()
|
||||||
|
}
|
||||||
|
|
||||||
override fun dismiss() {
|
override fun dismiss() {
|
||||||
NetPlayManager.setChatOpen(false)
|
NetPlayManager.setChatOpen(false)
|
||||||
super.dismiss()
|
super.dismiss()
|
||||||
|
|
@ -108,6 +123,12 @@ class ChatDialog(context: Context) : BottomSheetDialog(context) {
|
||||||
private fun scrollToBottom() {
|
private fun scrollToBottom() {
|
||||||
binding.chatRecyclerView.scrollToPosition(chatAdapter.itemCount - 1)
|
binding.chatRecyclerView.scrollToPosition(chatAdapter.itemCount - 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun applyFullscreenMode() {
|
||||||
|
window?.let { window ->
|
||||||
|
FullscreenHelper.applyToWindow(window, hideSystemBars)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ChatAdapter(private val messages: List<ChatMessage>) :
|
class ChatAdapter(private val messages: List<ChatMessage>) :
|
||||||
|
|
|
||||||
|
|
@ -31,15 +31,25 @@ import org.yuzu.yuzu_emu.databinding.DialogLobbyBrowserBinding
|
||||||
import org.yuzu.yuzu_emu.databinding.ItemLobbyRoomBinding
|
import org.yuzu.yuzu_emu.databinding.ItemLobbyRoomBinding
|
||||||
import org.yuzu.yuzu_emu.features.settings.model.StringSetting
|
import org.yuzu.yuzu_emu.features.settings.model.StringSetting
|
||||||
import org.yuzu.yuzu_emu.network.NetPlayManager
|
import org.yuzu.yuzu_emu.network.NetPlayManager
|
||||||
|
import org.yuzu.yuzu_emu.utils.CompatUtils
|
||||||
|
import org.yuzu.yuzu_emu.utils.FullscreenHelper
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
class LobbyBrowser(context: Context) : BottomSheetDialog(context) {
|
class LobbyBrowser(context: Context) : BottomSheetDialog(context) {
|
||||||
private lateinit var binding: DialogLobbyBrowserBinding
|
private lateinit var binding: DialogLobbyBrowserBinding
|
||||||
private lateinit var adapter: LobbyRoomAdapter
|
private lateinit var adapter: LobbyRoomAdapter
|
||||||
private val handler = Handler(Looper.getMainLooper())
|
private val handler = Handler(Looper.getMainLooper())
|
||||||
|
private val hideSystemBars: Boolean by lazy {
|
||||||
|
runCatching {
|
||||||
|
FullscreenHelper.shouldHideSystemBars(CompatUtils.findActivity(context))
|
||||||
|
}.getOrElse {
|
||||||
|
FullscreenHelper.isFullscreenEnabled(context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
setOnShowListener { applyFullscreenMode() }
|
||||||
|
|
||||||
behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
||||||
behavior.skipCollapsed =
|
behavior.skipCollapsed =
|
||||||
|
|
@ -81,6 +91,7 @@ class LobbyBrowser(context: Context) : BottomSheetDialog(context) {
|
||||||
behavior.expandedOffset = 0
|
behavior.expandedOffset = 0
|
||||||
behavior.skipCollapsed = true
|
behavior.skipCollapsed = true
|
||||||
behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
||||||
|
applyFullscreenMode()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupRecyclerView() {
|
private fun setupRecyclerView() {
|
||||||
|
|
@ -274,4 +285,10 @@ class LobbyBrowser(context: Context) : BottomSheetDialog(context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
private inner class ScoreItem(val score: Double, val item: NetPlayManager.RoomInfo)
|
private inner class ScoreItem(val score: Double, val item: NetPlayManager.RoomInfo)
|
||||||
|
|
||||||
|
private fun applyFullscreenMode() {
|
||||||
|
window?.let { window ->
|
||||||
|
FullscreenHelper.applyToWindow(window, hideSystemBars)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
package org.yuzu.yuzu_emu.dialogs
|
package org.yuzu.yuzu_emu.dialogs
|
||||||
|
|
@ -36,6 +36,7 @@ import org.yuzu.yuzu_emu.features.settings.model.StringSetting
|
||||||
import org.yuzu.yuzu_emu.network.NetDataValidators
|
import org.yuzu.yuzu_emu.network.NetDataValidators
|
||||||
import org.yuzu.yuzu_emu.network.NetPlayManager
|
import org.yuzu.yuzu_emu.network.NetPlayManager
|
||||||
import org.yuzu.yuzu_emu.utils.CompatUtils
|
import org.yuzu.yuzu_emu.utils.CompatUtils
|
||||||
|
import org.yuzu.yuzu_emu.utils.FullscreenHelper
|
||||||
import org.yuzu.yuzu_emu.utils.GameHelper
|
import org.yuzu.yuzu_emu.utils.GameHelper
|
||||||
|
|
||||||
class NetPlayDialog(context: Context) : BottomSheetDialog(context) {
|
class NetPlayDialog(context: Context) : BottomSheetDialog(context) {
|
||||||
|
|
@ -43,9 +44,17 @@ class NetPlayDialog(context: Context) : BottomSheetDialog(context) {
|
||||||
|
|
||||||
private val gameNameList: MutableList<Array<String>> = mutableListOf()
|
private val gameNameList: MutableList<Array<String>> = mutableListOf()
|
||||||
private val gameIdList: MutableList<Array<Long>> = mutableListOf()
|
private val gameIdList: MutableList<Array<Long>> = mutableListOf()
|
||||||
|
private val hideSystemBars: Boolean by lazy {
|
||||||
|
runCatching {
|
||||||
|
FullscreenHelper.shouldHideSystemBars(CompatUtils.findActivity(context))
|
||||||
|
}.getOrElse {
|
||||||
|
FullscreenHelper.isFullscreenEnabled(context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
setOnShowListener { applyFullscreenMode() }
|
||||||
|
|
||||||
behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
||||||
behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
||||||
|
|
@ -118,6 +127,11 @@ class NetPlayDialog(context: Context) : BottomSheetDialog(context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onStart() {
|
||||||
|
super.onStart()
|
||||||
|
applyFullscreenMode()
|
||||||
|
}
|
||||||
|
|
||||||
data class NetPlayItems(
|
data class NetPlayItems(
|
||||||
val option: Int,
|
val option: Int,
|
||||||
val name: String,
|
val name: String,
|
||||||
|
|
@ -352,6 +366,11 @@ class NetPlayDialog(context: Context) : BottomSheetDialog(context) {
|
||||||
TextValidatorWatcher.validStates.clear()
|
TextValidatorWatcher.validStates.clear()
|
||||||
val activity = CompatUtils.findActivity(context)
|
val activity = CompatUtils.findActivity(context)
|
||||||
val dialog = BottomSheetDialog(activity)
|
val dialog = BottomSheetDialog(activity)
|
||||||
|
dialog.setOnShowListener {
|
||||||
|
dialog.window?.let { window ->
|
||||||
|
FullscreenHelper.applyToWindow(window, hideSystemBars)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dialog.behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
dialog.behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
||||||
dialog.behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
dialog.behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
||||||
|
|
@ -582,6 +601,12 @@ class NetPlayDialog(context: Context) : BottomSheetDialog(context) {
|
||||||
dialog.show()
|
dialog.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun applyFullscreenMode() {
|
||||||
|
window?.let { window ->
|
||||||
|
FullscreenHelper.applyToWindow(window, hideSystemBars)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun showModerationDialog() {
|
private fun showModerationDialog() {
|
||||||
val activity = CompatUtils.findActivity(context)
|
val activity = CompatUtils.findActivity(context)
|
||||||
val dialog = MaterialAlertDialogBuilder(activity)
|
val dialog = MaterialAlertDialogBuilder(activity)
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,8 @@ class QuickSettings(val emulationFragment: EmulationFragment) {
|
||||||
container: ViewGroup,
|
container: ViewGroup,
|
||||||
setting: IntSetting,
|
setting: IntSetting,
|
||||||
namesArrayId: Int,
|
namesArrayId: Int,
|
||||||
valuesArrayId: Int
|
valuesArrayId: Int,
|
||||||
|
onValueChanged: ((Int) -> Unit)? = null
|
||||||
) {
|
) {
|
||||||
val inflater = LayoutInflater.from(emulationFragment.requireContext())
|
val inflater = LayoutInflater.from(emulationFragment.requireContext())
|
||||||
val itemView = inflater.inflate(R.layout.item_quick_settings_menu, container, false)
|
val itemView = inflater.inflate(R.layout.item_quick_settings_menu, container, false)
|
||||||
|
|
@ -89,6 +90,7 @@ class QuickSettings(val emulationFragment: EmulationFragment) {
|
||||||
setting.setInt(values[index])
|
setting.setInt(values[index])
|
||||||
saveSettings()
|
saveSettings()
|
||||||
valueView.text = name
|
valueView.text = name
|
||||||
|
onValueChanged?.invoke(values[index])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
radioGroup.addView(radioButton)
|
radioGroup.addView(radioButton)
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,8 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting {
|
||||||
USE_AUTO_STUB("use_auto_stub"),
|
USE_AUTO_STUB("use_auto_stub"),
|
||||||
RENDERER_USE_DISK_SHADER_CACHE("use_disk_shader_cache"),
|
RENDERER_USE_DISK_SHADER_CACHE("use_disk_shader_cache"),
|
||||||
RENDERER_FORCE_MAX_CLOCK("force_max_clock"),
|
RENDERER_FORCE_MAX_CLOCK("force_max_clock"),
|
||||||
|
RENDERER_ASYNCHRONOUS_GPU_EMULATION("use_asynchronous_gpu_emulation"),
|
||||||
|
RENDERER_ASYNC_PRESENTATION("async_presentation"),
|
||||||
RENDERER_ASYNCHRONOUS_SHADERS("use_asynchronous_shaders"),
|
RENDERER_ASYNCHRONOUS_SHADERS("use_asynchronous_shaders"),
|
||||||
RENDERER_REACTIVE_FLUSHING("use_reactive_flushing"),
|
RENDERER_REACTIVE_FLUSHING("use_reactive_flushing"),
|
||||||
ENABLE_BUFFER_HISTORY("enable_buffer_history"),
|
ENABLE_BUFFER_HISTORY("enable_buffer_history"),
|
||||||
|
|
@ -31,8 +33,6 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting {
|
||||||
RENDERER_DEBUG("debug"),
|
RENDERER_DEBUG("debug"),
|
||||||
RENDERER_PATCH_OLD_QCOM_DRIVERS("patch_old_qcom_drivers"),
|
RENDERER_PATCH_OLD_QCOM_DRIVERS("patch_old_qcom_drivers"),
|
||||||
RENDERER_VERTEX_INPUT_DYNAMIC_STATE("vertex_input_dynamic_state"),
|
RENDERER_VERTEX_INPUT_DYNAMIC_STATE("vertex_input_dynamic_state"),
|
||||||
RENDERER_PROVOKING_VERTEX("provoking_vertex"),
|
|
||||||
RENDERER_DESCRIPTOR_INDEXING("descriptor_indexing"),
|
|
||||||
RENDERER_SAMPLE_SHADING("sample_shading"),
|
RENDERER_SAMPLE_SHADING("sample_shading"),
|
||||||
GPU_UNSWIZZLE_ENABLED("gpu_unswizzle_enabled"),
|
GPU_UNSWIZZLE_ENABLED("gpu_unswizzle_enabled"),
|
||||||
PICTURE_IN_PICTURE("picture_in_picture"),
|
PICTURE_IN_PICTURE("picture_in_picture"),
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@ enum class IntSetting(override val key: String) : AbstractIntSetting {
|
||||||
RENDERER_VRAM_USAGE_MODE("vram_usage_mode"),
|
RENDERER_VRAM_USAGE_MODE("vram_usage_mode"),
|
||||||
RENDERER_NVDEC_EMULATION("nvdec_emulation"),
|
RENDERER_NVDEC_EMULATION("nvdec_emulation"),
|
||||||
RENDERER_ASTC_DECODE_METHOD("accelerate_astc"),
|
RENDERER_ASTC_DECODE_METHOD("accelerate_astc"),
|
||||||
RENDERER_ASTC_RECOMPRESSION("astc_recompression"),
|
|
||||||
RENDERER_ACCURACY("gpu_accuracy"),
|
RENDERER_ACCURACY("gpu_accuracy"),
|
||||||
RENDERER_RESOLUTION("resolution_setup"),
|
RENDERER_RESOLUTION("resolution_setup"),
|
||||||
RENDERER_VSYNC("use_vsync"),
|
RENDERER_VSYNC("use_vsync"),
|
||||||
|
|
|
||||||
|
|
@ -104,6 +104,8 @@ object Settings {
|
||||||
const val PREF_THEME_MODE = "ThemeMode"
|
const val PREF_THEME_MODE = "ThemeMode"
|
||||||
const val PREF_BLACK_BACKGROUNDS = "BlackBackgrounds"
|
const val PREF_BLACK_BACKGROUNDS = "BlackBackgrounds"
|
||||||
const val PREF_STATIC_THEME_COLOR = "StaticThemeColor"
|
const val PREF_STATIC_THEME_COLOR = "StaticThemeColor"
|
||||||
|
const val PREF_APP_FULLSCREEN = "AppFullscreen"
|
||||||
|
const val APP_FULLSCREEN_DEFAULT = false
|
||||||
|
|
||||||
enum class EmulationOrientation(val int: Int) {
|
enum class EmulationOrientation(val int: Int) {
|
||||||
Unspecified(0),
|
Unspecified(0),
|
||||||
|
|
|
||||||
|
|
@ -141,13 +141,6 @@ abstract class SettingsItem(
|
||||||
valuesId = R.array.dynaStateValues
|
valuesId = R.array.dynaStateValues
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
put(
|
|
||||||
SwitchSetting(
|
|
||||||
BooleanSetting.RENDERER_PROVOKING_VERTEX,
|
|
||||||
titleId = R.string.provoking_vertex,
|
|
||||||
descriptionId = R.string.provoking_vertex_description
|
|
||||||
)
|
|
||||||
)
|
|
||||||
put(
|
put(
|
||||||
SwitchSetting(
|
SwitchSetting(
|
||||||
BooleanSetting.RENDERER_VERTEX_INPUT_DYNAMIC_STATE,
|
BooleanSetting.RENDERER_VERTEX_INPUT_DYNAMIC_STATE,
|
||||||
|
|
@ -155,13 +148,6 @@ abstract class SettingsItem(
|
||||||
descriptionId = R.string.vertex_input_dynamic_state_description
|
descriptionId = R.string.vertex_input_dynamic_state_description
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
put(
|
|
||||||
SwitchSetting(
|
|
||||||
BooleanSetting.RENDERER_DESCRIPTOR_INDEXING,
|
|
||||||
titleId = R.string.descriptor_indexing,
|
|
||||||
descriptionId = R.string.descriptor_indexing_description
|
|
||||||
)
|
|
||||||
)
|
|
||||||
put(
|
put(
|
||||||
SliderSetting(
|
SliderSetting(
|
||||||
IntSetting.RENDERER_SAMPLE_SHADING,
|
IntSetting.RENDERER_SAMPLE_SHADING,
|
||||||
|
|
@ -349,15 +335,6 @@ abstract class SettingsItem(
|
||||||
valuesId = R.array.astcDecodingMethodValues
|
valuesId = R.array.astcDecodingMethodValues
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
put(
|
|
||||||
SingleChoiceSetting(
|
|
||||||
IntSetting.RENDERER_ASTC_RECOMPRESSION,
|
|
||||||
titleId = R.string.astc_recompression,
|
|
||||||
descriptionId = R.string.astc_recompression_description,
|
|
||||||
choicesId = R.array.astcRecompressionMethodNames,
|
|
||||||
valuesId = R.array.astcRecompressionMethodValues
|
|
||||||
)
|
|
||||||
)
|
|
||||||
put(
|
put(
|
||||||
SingleChoiceSetting(
|
SingleChoiceSetting(
|
||||||
IntSetting.RENDERER_VRAM_USAGE_MODE,
|
IntSetting.RENDERER_VRAM_USAGE_MODE,
|
||||||
|
|
@ -652,6 +629,20 @@ abstract class SettingsItem(
|
||||||
descriptionId = R.string.renderer_force_max_clock_description
|
descriptionId = R.string.renderer_force_max_clock_description
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
put(
|
||||||
|
SwitchSetting(
|
||||||
|
BooleanSetting.RENDERER_ASYNCHRONOUS_GPU_EMULATION,
|
||||||
|
titleId = R.string.renderer_asynchronous_gpu_emulation,
|
||||||
|
descriptionId = R.string.renderer_asynchronous_gpu_emulation_description
|
||||||
|
)
|
||||||
|
)
|
||||||
|
put(
|
||||||
|
SwitchSetting(
|
||||||
|
BooleanSetting.RENDERER_ASYNC_PRESENTATION,
|
||||||
|
titleId = R.string.renderer_async_presentation,
|
||||||
|
descriptionId = R.string.renderer_async_presentation_description
|
||||||
|
)
|
||||||
|
)
|
||||||
put(
|
put(
|
||||||
SingleChoiceSetting(
|
SingleChoiceSetting(
|
||||||
IntSetting.RENDERER_OPTIMIZE_SPIRV_OUTPUT,
|
IntSetting.RENDERER_OPTIMIZE_SPIRV_OUTPUT,
|
||||||
|
|
@ -670,15 +661,6 @@ abstract class SettingsItem(
|
||||||
valuesId = R.array.dmaAccuracyValues
|
valuesId = R.array.dmaAccuracyValues
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
put(
|
|
||||||
SingleChoiceSetting(
|
|
||||||
IntSetting.FRAME_PACING_MODE,
|
|
||||||
titleId = R.string.frame_pacing_mode,
|
|
||||||
descriptionId = R.string.frame_pacing_mode_description,
|
|
||||||
choicesId = R.array.framePacingModeNames,
|
|
||||||
valuesId = R.array.framePacingModeValues
|
|
||||||
)
|
|
||||||
)
|
|
||||||
put(
|
put(
|
||||||
SwitchSetting(
|
SwitchSetting(
|
||||||
BooleanSetting.RENDERER_ASYNCHRONOUS_SHADERS,
|
BooleanSetting.RENDERER_ASYNCHRONOUS_SHADERS,
|
||||||
|
|
|
||||||
|
|
@ -103,6 +103,7 @@ class SettingsActivity : AppCompatActivity() {
|
||||||
)
|
)
|
||||||
|
|
||||||
setInsets()
|
setInsets()
|
||||||
|
applyFullscreenPreference()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun navigateBack() {
|
fun navigateBack() {
|
||||||
|
|
@ -122,6 +123,18 @@ class SettingsActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
applyFullscreenPreference()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onWindowFocusChanged(hasFocus: Boolean) {
|
||||||
|
super.onWindowFocusChanged(hasFocus)
|
||||||
|
if (hasFocus) {
|
||||||
|
applyFullscreenPreference()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onStop() {
|
override fun onStop() {
|
||||||
super.onStop()
|
super.onStop()
|
||||||
Log.info("[SettingsActivity] Settings activity stopping. Saving settings to INI...")
|
Log.info("[SettingsActivity] Settings activity stopping. Saving settings to INI...")
|
||||||
|
|
@ -188,4 +201,8 @@ class SettingsActivity : AppCompatActivity() {
|
||||||
windowInsets
|
windowInsets
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun applyFullscreenPreference() {
|
||||||
|
FullscreenHelper.applyToActivity(this)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ import org.yuzu.yuzu_emu.databinding.DialogSliderBinding
|
||||||
import org.yuzu.yuzu_emu.databinding.DialogSpinboxBinding
|
import org.yuzu.yuzu_emu.databinding.DialogSpinboxBinding
|
||||||
import org.yuzu.yuzu_emu.features.input.NativeInput
|
import org.yuzu.yuzu_emu.features.input.NativeInput
|
||||||
import org.yuzu.yuzu_emu.features.input.model.AnalogDirection
|
import org.yuzu.yuzu_emu.features.input.model.AnalogDirection
|
||||||
|
import org.yuzu.yuzu_emu.features.settings.model.IntSetting
|
||||||
import org.yuzu.yuzu_emu.features.settings.model.view.AnalogInputSetting
|
import org.yuzu.yuzu_emu.features.settings.model.view.AnalogInputSetting
|
||||||
import org.yuzu.yuzu_emu.features.settings.model.view.ButtonInputSetting
|
import org.yuzu.yuzu_emu.features.settings.model.view.ButtonInputSetting
|
||||||
import org.yuzu.yuzu_emu.features.settings.model.view.IntSingleChoiceSetting
|
import org.yuzu.yuzu_emu.features.settings.model.view.IntSingleChoiceSetting
|
||||||
|
|
@ -381,6 +382,10 @@ class SettingsDialogFragment : DialogFragment(), DialogInterface.OnClickListener
|
||||||
}
|
}
|
||||||
scSetting.setSelectedValue(value)
|
scSetting.setSelectedValue(value)
|
||||||
|
|
||||||
|
if (scSetting.setting.key == IntSetting.RENDERER_SCALING_FILTER.key) {
|
||||||
|
settingsViewModel.setShouldReloadSettingsList(true)
|
||||||
|
}
|
||||||
|
|
||||||
if (scSetting.setting.key == "app_language") {
|
if (scSetting.setting.key == "app_language") {
|
||||||
settingsViewModel.setShouldRecreateForLanguageChange(true)
|
settingsViewModel.setShouldRecreateForLanguageChange(true)
|
||||||
// recreate page apply language change instantly
|
// recreate page apply language change instantly
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,8 @@ import org.yuzu.yuzu_emu.features.settings.model.view.*
|
||||||
import org.yuzu.yuzu_emu.utils.InputHandler
|
import org.yuzu.yuzu_emu.utils.InputHandler
|
||||||
import org.yuzu.yuzu_emu.utils.NativeConfig
|
import org.yuzu.yuzu_emu.utils.NativeConfig
|
||||||
import org.yuzu.yuzu_emu.utils.DirectoryInitialization
|
import org.yuzu.yuzu_emu.utils.DirectoryInitialization
|
||||||
|
import org.yuzu.yuzu_emu.utils.FullscreenHelper
|
||||||
|
import androidx.core.content.edit
|
||||||
import androidx.fragment.app.FragmentActivity
|
import androidx.fragment.app.FragmentActivity
|
||||||
import org.yuzu.yuzu_emu.fragments.MessageDialogFragment
|
import org.yuzu.yuzu_emu.fragments.MessageDialogFragment
|
||||||
|
|
||||||
|
|
@ -56,19 +58,38 @@ class SettingsFragmentPresenter(
|
||||||
val pairedSettingKey = item.setting.pairedSettingKey
|
val pairedSettingKey = item.setting.pairedSettingKey
|
||||||
|
|
||||||
if (pairedSettingKey.isNotEmpty()) {
|
if (pairedSettingKey.isNotEmpty()) {
|
||||||
|
val needsGlobal = getNeedsGlobalForKey(pairedSettingKey)
|
||||||
val pairedSettingValue = NativeConfig.getBoolean(
|
val pairedSettingValue = NativeConfig.getBoolean(
|
||||||
pairedSettingKey,
|
pairedSettingKey,
|
||||||
if (NativeLibrary.isRunning() && !NativeConfig.isPerGameConfigLoaded()) {
|
needsGlobal
|
||||||
!NativeConfig.usingGlobal(pairedSettingKey)
|
|
||||||
} else {
|
|
||||||
NativeConfig.usingGlobal(pairedSettingKey)
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
if (!pairedSettingValue) return
|
if (!pairedSettingValue) return
|
||||||
}
|
}
|
||||||
add(item)
|
add(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getNeedsGlobalForKey(key: String): Boolean {
|
||||||
|
return if (NativeLibrary.isRunning() && !NativeConfig.isPerGameConfigLoaded()) {
|
||||||
|
!NativeConfig.usingGlobal(key)
|
||||||
|
} else {
|
||||||
|
NativeConfig.usingGlobal(key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isFsrScalingFilterSelected(): Boolean {
|
||||||
|
val fsrFilterValue = resolveFsrScalingFilterValue() ?: return false
|
||||||
|
val needsGlobal = getNeedsGlobalForKey(IntSetting.RENDERER_SCALING_FILTER.key)
|
||||||
|
val selectedFilter = IntSetting.RENDERER_SCALING_FILTER.getInt(needsGlobal)
|
||||||
|
return selectedFilter == fsrFilterValue
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun resolveFsrScalingFilterValue(): Int? {
|
||||||
|
val names = context.resources.getStringArray(R.array.rendererScalingFilterNames)
|
||||||
|
val values = context.resources.getIntArray(R.array.rendererScalingFilterValues)
|
||||||
|
val fsrIndex = names.indexOf(context.getString(R.string.scaling_filter_fsr))
|
||||||
|
return if (fsrIndex in values.indices) values[fsrIndex] else null
|
||||||
|
}
|
||||||
|
|
||||||
// Allows you to show/hide abstract settings based on the paired setting key
|
// Allows you to show/hide abstract settings based on the paired setting key
|
||||||
private fun ArrayList<SettingsItem>.addAbstract(item: SettingsItem) {
|
private fun ArrayList<SettingsItem>.addAbstract(item: SettingsItem) {
|
||||||
val pairedSettingKey = item.setting.pairedSettingKey
|
val pairedSettingKey = item.setting.pairedSettingKey
|
||||||
|
|
@ -246,7 +267,9 @@ class SettingsFragmentPresenter(
|
||||||
add(IntSetting.RENDERER_RESOLUTION.key)
|
add(IntSetting.RENDERER_RESOLUTION.key)
|
||||||
add(IntSetting.RENDERER_VSYNC.key)
|
add(IntSetting.RENDERER_VSYNC.key)
|
||||||
add(IntSetting.RENDERER_SCALING_FILTER.key)
|
add(IntSetting.RENDERER_SCALING_FILTER.key)
|
||||||
add(IntSetting.FSR_SHARPENING_SLIDER.key)
|
if (isFsrScalingFilterSelected()) {
|
||||||
|
add(IntSetting.FSR_SHARPENING_SLIDER.key)
|
||||||
|
}
|
||||||
add(IntSetting.RENDERER_ANTI_ALIASING.key)
|
add(IntSetting.RENDERER_ANTI_ALIASING.key)
|
||||||
add(IntSetting.RENDERER_OPTIMIZE_SPIRV_OUTPUT.key)
|
add(IntSetting.RENDERER_OPTIMIZE_SPIRV_OUTPUT.key)
|
||||||
|
|
||||||
|
|
@ -254,15 +277,15 @@ class SettingsFragmentPresenter(
|
||||||
|
|
||||||
add(IntSetting.RENDERER_ACCURACY.key)
|
add(IntSetting.RENDERER_ACCURACY.key)
|
||||||
add(IntSetting.DMA_ACCURACY.key)
|
add(IntSetting.DMA_ACCURACY.key)
|
||||||
add(IntSetting.FRAME_PACING_MODE.key)
|
|
||||||
add(IntSetting.MAX_ANISOTROPY.key)
|
add(IntSetting.MAX_ANISOTROPY.key)
|
||||||
add(IntSetting.RENDERER_VRAM_USAGE_MODE.key)
|
add(IntSetting.RENDERER_VRAM_USAGE_MODE.key)
|
||||||
add(IntSetting.RENDERER_ASTC_DECODE_METHOD.key)
|
add(IntSetting.RENDERER_ASTC_DECODE_METHOD.key)
|
||||||
add(IntSetting.RENDERER_ASTC_RECOMPRESSION.key)
|
|
||||||
|
|
||||||
add(BooleanSetting.SYNC_MEMORY_OPERATIONS.key)
|
add(BooleanSetting.SYNC_MEMORY_OPERATIONS.key)
|
||||||
add(BooleanSetting.RENDERER_USE_DISK_SHADER_CACHE.key)
|
add(BooleanSetting.RENDERER_USE_DISK_SHADER_CACHE.key)
|
||||||
add(BooleanSetting.RENDERER_FORCE_MAX_CLOCK.key)
|
add(BooleanSetting.RENDERER_FORCE_MAX_CLOCK.key)
|
||||||
|
add(BooleanSetting.RENDERER_ASYNCHRONOUS_GPU_EMULATION.key)
|
||||||
|
add(BooleanSetting.RENDERER_ASYNC_PRESENTATION.key)
|
||||||
add(BooleanSetting.RENDERER_REACTIVE_FLUSHING.key)
|
add(BooleanSetting.RENDERER_REACTIVE_FLUSHING.key)
|
||||||
add(BooleanSetting.ENABLE_BUFFER_HISTORY.key)
|
add(BooleanSetting.ENABLE_BUFFER_HISTORY.key)
|
||||||
add(BooleanSetting.USE_OPTIMIZED_VERTEX_BUFFERS.key)
|
add(BooleanSetting.USE_OPTIMIZED_VERTEX_BUFFERS.key)
|
||||||
|
|
@ -279,8 +302,6 @@ class SettingsFragmentPresenter(
|
||||||
|
|
||||||
add(IntSetting.RENDERER_DYNA_STATE.key)
|
add(IntSetting.RENDERER_DYNA_STATE.key)
|
||||||
add(BooleanSetting.RENDERER_VERTEX_INPUT_DYNAMIC_STATE.key)
|
add(BooleanSetting.RENDERER_VERTEX_INPUT_DYNAMIC_STATE.key)
|
||||||
add(BooleanSetting.RENDERER_PROVOKING_VERTEX.key)
|
|
||||||
add(BooleanSetting.RENDERER_DESCRIPTOR_INDEXING.key)
|
|
||||||
add(IntSetting.RENDERER_SAMPLE_SHADING.key)
|
add(IntSetting.RENDERER_SAMPLE_SHADING.key)
|
||||||
|
|
||||||
add(HeaderSetting(R.string.display))
|
add(HeaderSetting(R.string.display))
|
||||||
|
|
@ -1187,6 +1208,39 @@ class SettingsFragmentPresenter(
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val fullscreenSetting: AbstractBooleanSetting = object : AbstractBooleanSetting {
|
||||||
|
override fun getBoolean(needsGlobal: Boolean): Boolean =
|
||||||
|
FullscreenHelper.isFullscreenEnabled(context)
|
||||||
|
|
||||||
|
override fun setBoolean(value: Boolean) {
|
||||||
|
FullscreenHelper.setFullscreenEnabled(context, value)
|
||||||
|
settingsViewModel.setShouldRecreate(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val key: String = Settings.PREF_APP_FULLSCREEN
|
||||||
|
override val isRuntimeModifiable: Boolean = true
|
||||||
|
override val pairedSettingKey: String = ""
|
||||||
|
override val isSwitchable: Boolean = false
|
||||||
|
override var global: Boolean = true
|
||||||
|
override val isSaveable: Boolean = true
|
||||||
|
override val defaultValue: Boolean = Settings.APP_FULLSCREEN_DEFAULT
|
||||||
|
|
||||||
|
override fun getValueAsString(needsGlobal: Boolean): String =
|
||||||
|
getBoolean(needsGlobal).toString()
|
||||||
|
|
||||||
|
override fun reset() {
|
||||||
|
setBoolean(defaultValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
add(
|
||||||
|
SwitchSetting(
|
||||||
|
fullscreenSetting,
|
||||||
|
titleId = R.string.fullscreen_mode,
|
||||||
|
descriptionId = R.string.fullscreen_mode_description
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
add(HeaderSetting(R.string.buttons))
|
add(HeaderSetting(R.string.buttons))
|
||||||
add(BooleanSetting.ENABLE_FOLDER_BUTTON.key)
|
add(BooleanSetting.ENABLE_FOLDER_BUTTON.key)
|
||||||
add(BooleanSetting.ENABLE_QLAUNCH_BUTTON.key)
|
add(BooleanSetting.ENABLE_QLAUNCH_BUTTON.key)
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ import org.yuzu.yuzu_emu.R
|
||||||
import org.yuzu.yuzu_emu.YuzuApplication
|
import org.yuzu.yuzu_emu.YuzuApplication
|
||||||
import org.yuzu.yuzu_emu.databinding.ActivitySettingsBinding
|
import org.yuzu.yuzu_emu.databinding.ActivitySettingsBinding
|
||||||
import org.yuzu.yuzu_emu.utils.DirectoryInitialization
|
import org.yuzu.yuzu_emu.utils.DirectoryInitialization
|
||||||
|
import org.yuzu.yuzu_emu.utils.FullscreenHelper
|
||||||
import org.yuzu.yuzu_emu.utils.InsetsHelper
|
import org.yuzu.yuzu_emu.utils.InsetsHelper
|
||||||
import org.yuzu.yuzu_emu.utils.ThemeHelper
|
import org.yuzu.yuzu_emu.utils.ThemeHelper
|
||||||
|
|
||||||
|
|
@ -89,6 +90,7 @@ class SettingsSubscreenActivity : AppCompatActivity() {
|
||||||
)
|
)
|
||||||
|
|
||||||
setInsets()
|
setInsets()
|
||||||
|
applyFullscreenPreference()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStart() {
|
override fun onStart() {
|
||||||
|
|
@ -98,6 +100,18 @@ class SettingsSubscreenActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
applyFullscreenPreference()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onWindowFocusChanged(hasFocus: Boolean) {
|
||||||
|
super.onWindowFocusChanged(hasFocus)
|
||||||
|
if (hasFocus) {
|
||||||
|
applyFullscreenPreference()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun navigateBack() {
|
fun navigateBack() {
|
||||||
val navHostFragment =
|
val navHostFragment =
|
||||||
supportFragmentManager.findFragmentById(R.id.fragment_container) as NavHostFragment
|
supportFragmentManager.findFragmentById(R.id.fragment_container) as NavHostFragment
|
||||||
|
|
@ -149,4 +163,8 @@ class SettingsSubscreenActivity : AppCompatActivity() {
|
||||||
windowInsets
|
windowInsets
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun applyFullscreenPreference() {
|
||||||
|
FullscreenHelper.applyToActivity(this)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ import org.yuzu.yuzu_emu.model.AddonViewModel
|
||||||
import org.yuzu.yuzu_emu.model.HomeViewModel
|
import org.yuzu.yuzu_emu.model.HomeViewModel
|
||||||
import org.yuzu.yuzu_emu.utils.AddonUtil
|
import org.yuzu.yuzu_emu.utils.AddonUtil
|
||||||
import org.yuzu.yuzu_emu.utils.FileUtil.copyFilesTo
|
import org.yuzu.yuzu_emu.utils.FileUtil.copyFilesTo
|
||||||
|
import org.yuzu.yuzu_emu.utils.InstallableActions
|
||||||
import org.yuzu.yuzu_emu.utils.ViewUtils.updateMargins
|
import org.yuzu.yuzu_emu.utils.ViewUtils.updateMargins
|
||||||
import org.yuzu.yuzu_emu.utils.collect
|
import org.yuzu.yuzu_emu.utils.collect
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
@ -107,6 +108,12 @@ class AddonsFragment : Fragment() {
|
||||||
).show(parentFragmentManager, MessageDialogFragment.TAG)
|
).show(parentFragmentManager, MessageDialogFragment.TAG)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
parentFragmentManager.setFragmentResultListener(
|
||||||
|
ContentTypeSelectionDialogFragment.REQUEST_INSTALL_GAME_UPDATE,
|
||||||
|
viewLifecycleOwner
|
||||||
|
) { _, _ ->
|
||||||
|
installGameUpdate.launch(arrayOf("*/*"))
|
||||||
|
}
|
||||||
|
|
||||||
binding.buttonInstall.setOnClickListener {
|
binding.buttonInstall.setOnClickListener {
|
||||||
ContentTypeSelectionDialogFragment().show(
|
ContentTypeSelectionDialogFragment().show(
|
||||||
|
|
@ -130,7 +137,7 @@ class AddonsFragment : Fragment() {
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
}
|
}
|
||||||
|
|
||||||
val installAddon =
|
private val installAddon =
|
||||||
registerForActivityResult(ActivityResultContracts.OpenDocumentTree()) { result ->
|
registerForActivityResult(ActivityResultContracts.OpenDocumentTree()) { result ->
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
return@registerForActivityResult
|
return@registerForActivityResult
|
||||||
|
|
@ -175,6 +182,17 @@ class AddonsFragment : Fragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val installGameUpdate =
|
||||||
|
registerForActivityResult(ActivityResultContracts.OpenMultipleDocuments()) { documents ->
|
||||||
|
InstallableActions.verifyAndInstallContent(
|
||||||
|
activity = requireActivity(),
|
||||||
|
fragmentManager = parentFragmentManager,
|
||||||
|
addonViewModel = addonViewModel,
|
||||||
|
documents = documents,
|
||||||
|
programId = args.game.programId
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
private fun setInsets() =
|
private fun setInsets() =
|
||||||
ViewCompat.setOnApplyWindowInsetsListener(
|
ViewCompat.setOnApplyWindowInsetsListener(
|
||||||
binding.root
|
binding.root
|
||||||
|
|
|
||||||
|
|
@ -8,18 +8,14 @@ package org.yuzu.yuzu_emu.fragments
|
||||||
|
|
||||||
import android.app.Dialog
|
import android.app.Dialog
|
||||||
import android.content.DialogInterface
|
import android.content.DialogInterface
|
||||||
import android.net.Uri
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
|
||||||
import androidx.fragment.app.DialogFragment
|
import androidx.fragment.app.DialogFragment
|
||||||
import androidx.fragment.app.activityViewModels
|
import androidx.fragment.app.activityViewModels
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import org.yuzu.yuzu_emu.NativeLibrary
|
|
||||||
import org.yuzu.yuzu_emu.R
|
import org.yuzu.yuzu_emu.R
|
||||||
import org.yuzu.yuzu_emu.YuzuApplication
|
import org.yuzu.yuzu_emu.YuzuApplication
|
||||||
import org.yuzu.yuzu_emu.model.AddonViewModel
|
import org.yuzu.yuzu_emu.model.AddonViewModel
|
||||||
import org.yuzu.yuzu_emu.utils.InstallableActions
|
|
||||||
|
|
||||||
class ContentTypeSelectionDialogFragment : DialogFragment() {
|
class ContentTypeSelectionDialogFragment : DialogFragment() {
|
||||||
private val addonViewModel: AddonViewModel by activityViewModels()
|
private val addonViewModel: AddonViewModel by activityViewModels()
|
||||||
|
|
@ -29,52 +25,6 @@ class ContentTypeSelectionDialogFragment : DialogFragment() {
|
||||||
|
|
||||||
private var selectedItem = 0
|
private var selectedItem = 0
|
||||||
|
|
||||||
private val installGameUpdateLauncher =
|
|
||||||
registerForActivityResult(ActivityResultContracts.OpenMultipleDocuments()) { documents ->
|
|
||||||
if (documents.isEmpty()) {
|
|
||||||
return@registerForActivityResult
|
|
||||||
}
|
|
||||||
|
|
||||||
val game = addonViewModel.game
|
|
||||||
if (game == null) {
|
|
||||||
installContent(documents)
|
|
||||||
return@registerForActivityResult
|
|
||||||
}
|
|
||||||
|
|
||||||
ProgressDialogFragment.newInstance(
|
|
||||||
requireActivity(),
|
|
||||||
R.string.verifying_content,
|
|
||||||
false
|
|
||||||
) { _, _ ->
|
|
||||||
var updatesMatchProgram = true
|
|
||||||
for (document in documents) {
|
|
||||||
val valid = NativeLibrary.doesUpdateMatchProgram(
|
|
||||||
game.programId,
|
|
||||||
document.toString()
|
|
||||||
)
|
|
||||||
if (!valid) {
|
|
||||||
updatesMatchProgram = false
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
requireActivity().runOnUiThread {
|
|
||||||
if (updatesMatchProgram) {
|
|
||||||
installContent(documents)
|
|
||||||
} else {
|
|
||||||
MessageDialogFragment.newInstance(
|
|
||||||
requireActivity(),
|
|
||||||
titleId = R.string.content_install_notice,
|
|
||||||
descriptionId = R.string.content_install_notice_description,
|
|
||||||
positiveAction = { installContent(documents) },
|
|
||||||
negativeAction = {}
|
|
||||||
).show(parentFragmentManager, MessageDialogFragment.TAG)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return@newInstance Any()
|
|
||||||
}.show(parentFragmentManager, ProgressDialogFragment.TAG)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||||
val launchOptions =
|
val launchOptions =
|
||||||
arrayOf(getString(R.string.updates_and_dlc), getString(R.string.mods_and_cheats))
|
arrayOf(getString(R.string.updates_and_dlc), getString(R.string.mods_and_cheats))
|
||||||
|
|
@ -87,7 +37,10 @@ class ContentTypeSelectionDialogFragment : DialogFragment() {
|
||||||
.setTitle(R.string.select_content_type)
|
.setTitle(R.string.select_content_type)
|
||||||
.setPositiveButton(android.R.string.ok) { _: DialogInterface, _: Int ->
|
.setPositiveButton(android.R.string.ok) { _: DialogInterface, _: Int ->
|
||||||
when (selectedItem) {
|
when (selectedItem) {
|
||||||
0 -> installGameUpdateLauncher.launch(arrayOf("*/*"))
|
0 -> parentFragmentManager.setFragmentResult(
|
||||||
|
REQUEST_INSTALL_GAME_UPDATE,
|
||||||
|
Bundle()
|
||||||
|
)
|
||||||
else -> {
|
else -> {
|
||||||
if (!preferences.getBoolean(MOD_NOTICE_SEEN, false)) {
|
if (!preferences.getBoolean(MOD_NOTICE_SEEN, false)) {
|
||||||
preferences.edit().putBoolean(MOD_NOTICE_SEEN, true).apply()
|
preferences.edit().putBoolean(MOD_NOTICE_SEEN, true).apply()
|
||||||
|
|
@ -112,17 +65,9 @@ class ContentTypeSelectionDialogFragment : DialogFragment() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val TAG = "ContentTypeSelectionDialogFragment"
|
const val TAG = "ContentTypeSelectionDialogFragment"
|
||||||
|
const val REQUEST_INSTALL_GAME_UPDATE = "RequestInstallGameUpdate"
|
||||||
|
|
||||||
private const val SELECTED_ITEM = "SelectedItem"
|
private const val SELECTED_ITEM = "SelectedItem"
|
||||||
private const val MOD_NOTICE_SEEN = "ModNoticeSeen"
|
private const val MOD_NOTICE_SEEN = "ModNoticeSeen"
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun installContent(documents: List<Uri>) {
|
|
||||||
InstallableActions.installContent(
|
|
||||||
activity = requireActivity(),
|
|
||||||
fragmentManager = parentFragmentManager,
|
|
||||||
addonViewModel = addonViewModel,
|
|
||||||
documents = documents
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,6 @@ import org.yuzu.yuzu_emu.databinding.FragmentDriverManagerBinding
|
||||||
import org.yuzu.yuzu_emu.features.settings.model.Settings
|
import org.yuzu.yuzu_emu.features.settings.model.Settings
|
||||||
import org.yuzu.yuzu_emu.features.settings.model.StringSetting
|
import org.yuzu.yuzu_emu.features.settings.model.StringSetting
|
||||||
import org.yuzu.yuzu_emu.features.settings.ui.SettingsSubscreen
|
import org.yuzu.yuzu_emu.features.settings.ui.SettingsSubscreen
|
||||||
import org.yuzu.yuzu_emu.model.Driver.Companion.toDriver
|
|
||||||
import org.yuzu.yuzu_emu.model.DriverViewModel
|
import org.yuzu.yuzu_emu.model.DriverViewModel
|
||||||
import org.yuzu.yuzu_emu.model.HomeViewModel
|
import org.yuzu.yuzu_emu.model.HomeViewModel
|
||||||
import org.yuzu.yuzu_emu.utils.FileUtil
|
import org.yuzu.yuzu_emu.utils.FileUtil
|
||||||
|
|
@ -142,6 +141,17 @@ class DriverManagerFragment : Fragment() {
|
||||||
driverViewModel.onCloseDriverManager(args.game)
|
driverViewModel.onCloseDriverManager(args.game)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
refreshDriverList()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun refreshDriverList() {
|
||||||
|
driverViewModel.reloadDriverData()
|
||||||
|
(binding.listDrivers.adapter as? DriverAdapter)
|
||||||
|
?.replaceList(driverViewModel.driverList.value)
|
||||||
|
}
|
||||||
|
|
||||||
private fun setInsets() =
|
private fun setInsets() =
|
||||||
ViewCompat.setOnApplyWindowInsetsListener(
|
ViewCompat.setOnApplyWindowInsetsListener(
|
||||||
binding.root
|
binding.root
|
||||||
|
|
@ -205,19 +215,23 @@ class DriverManagerFragment : Fragment() {
|
||||||
|
|
||||||
val driverData = GpuDriverHelper.getMetadataFromZip(driverFile)
|
val driverData = GpuDriverHelper.getMetadataFromZip(driverFile)
|
||||||
val driverInList =
|
val driverInList =
|
||||||
driverViewModel.driverData.firstOrNull { it.second == driverData }
|
driverViewModel.driverData.firstOrNull {
|
||||||
|
it.first == driverPath || it.second == driverData
|
||||||
|
}
|
||||||
if (driverInList != null) {
|
if (driverInList != null) {
|
||||||
return@newInstance getString(R.string.driver_already_installed)
|
return@newInstance getString(R.string.driver_already_installed)
|
||||||
} else {
|
} else {
|
||||||
driverViewModel.onDriverAdded(Pair(driverPath, driverData))
|
driverViewModel.onDriverAdded(Pair(driverPath, driverData))
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
if (_binding != null) {
|
if (_binding != null) {
|
||||||
|
refreshDriverList()
|
||||||
val adapter = binding.listDrivers.adapter as DriverAdapter
|
val adapter = binding.listDrivers.adapter as DriverAdapter
|
||||||
adapter.addItem(driverData.toDriver())
|
val selectedPosition = adapter.currentList
|
||||||
adapter.selectItem(adapter.currentList.indices.last)
|
.indexOfFirst { it.selected }
|
||||||
|
.let { if (it == -1) 0 else it }
|
||||||
driverViewModel.showClearButton(!StringSetting.DRIVER_PATH.global)
|
driverViewModel.showClearButton(!StringSetting.DRIVER_PATH.global)
|
||||||
binding.listDrivers
|
binding.listDrivers
|
||||||
.smoothScrollToPosition(adapter.currentList.indices.last)
|
.smoothScrollToPosition(selectedPosition)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,7 @@ import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.activityViewModels
|
import androidx.fragment.app.activityViewModels
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.navigation.findNavController
|
import androidx.navigation.findNavController
|
||||||
|
import androidx.navigation.fragment.NavHostFragment
|
||||||
import androidx.navigation.fragment.navArgs
|
import androidx.navigation.fragment.navArgs
|
||||||
import androidx.window.layout.FoldingFeature
|
import androidx.window.layout.FoldingFeature
|
||||||
import androidx.window.layout.WindowInfoTracker
|
import androidx.window.layout.WindowInfoTracker
|
||||||
|
|
@ -89,6 +90,7 @@ import org.yuzu.yuzu_emu.utils.FileUtil
|
||||||
import org.yuzu.yuzu_emu.utils.GameHelper
|
import org.yuzu.yuzu_emu.utils.GameHelper
|
||||||
import org.yuzu.yuzu_emu.utils.GameIconUtils
|
import org.yuzu.yuzu_emu.utils.GameIconUtils
|
||||||
import org.yuzu.yuzu_emu.utils.GpuDriverHelper
|
import org.yuzu.yuzu_emu.utils.GpuDriverHelper
|
||||||
|
import org.yuzu.yuzu_emu.utils.InputHandler
|
||||||
import org.yuzu.yuzu_emu.utils.Log
|
import org.yuzu.yuzu_emu.utils.Log
|
||||||
import org.yuzu.yuzu_emu.utils.NativeConfig
|
import org.yuzu.yuzu_emu.utils.NativeConfig
|
||||||
import org.yuzu.yuzu_emu.utils.NativeFreedrenoConfig
|
import org.yuzu.yuzu_emu.utils.NativeFreedrenoConfig
|
||||||
|
|
@ -113,6 +115,8 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||||
val handler = Handler(Looper.getMainLooper())
|
val handler = Handler(Looper.getMainLooper())
|
||||||
|
|
||||||
private var controllerInputReceived = false
|
private var controllerInputReceived = false
|
||||||
|
private var hasPhysicalControllerConnected = false
|
||||||
|
private var overlayHiddenByPhysicalController = false
|
||||||
|
|
||||||
private var _binding: FragmentEmulationBinding? = null
|
private var _binding: FragmentEmulationBinding? = null
|
||||||
|
|
||||||
|
|
@ -135,6 +139,8 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||||
|
|
||||||
private var intentGame: Game? = null
|
private var intentGame: Game? = null
|
||||||
private var isCustomSettingsIntent = false
|
private var isCustomSettingsIntent = false
|
||||||
|
private var isStoppingForRomSwap = false
|
||||||
|
private var deferGameSetupUntilStopCompletes = false
|
||||||
|
|
||||||
private var perfStatsRunnable: Runnable? = null
|
private var perfStatsRunnable: Runnable? = null
|
||||||
private var socRunnable: Runnable? = null
|
private var socRunnable: Runnable? = null
|
||||||
|
|
@ -238,6 +244,14 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (emulationViewModel.isEmulationStopping.value) {
|
||||||
|
deferGameSetupUntilStopCompletes = true
|
||||||
|
if (game == null) {
|
||||||
|
game = args.game ?: intentGame
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
finishGameSetup()
|
finishGameSetup()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -260,6 +274,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||||
}
|
}
|
||||||
|
|
||||||
game = gameToUse
|
game = gameToUse
|
||||||
|
emulationActivity?.updateSessionGame(gameToUse)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.error("[EmulationFragment] Error during game setup: ${e.message}")
|
Log.error("[EmulationFragment] Error during game setup: ${e.message}")
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
|
|
@ -334,7 +349,8 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||||
}
|
}
|
||||||
|
|
||||||
emulationState = EmulationState(game!!.path) {
|
emulationState = EmulationState(game!!.path) {
|
||||||
return@EmulationState driverViewModel.isInteractionAllowed.value
|
return@EmulationState driverViewModel.isInteractionAllowed.value &&
|
||||||
|
!isStoppingForRomSwap
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -653,6 +669,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||||
driverInUse = driverViewModel.selectedDriverVersion.value
|
driverInUse = driverViewModel.selectedDriverVersion.value
|
||||||
|
|
||||||
updateQuickOverlayMenuEntry(BooleanSetting.SHOW_INPUT_OVERLAY.getBoolean())
|
updateQuickOverlayMenuEntry(BooleanSetting.SHOW_INPUT_OVERLAY.getBoolean())
|
||||||
|
onPhysicalControllerStateChanged(InputHandler.androidControllers.isNotEmpty())
|
||||||
|
|
||||||
binding.surfaceEmulation.holder.addCallback(this)
|
binding.surfaceEmulation.holder.addCallback(this)
|
||||||
binding.doneControlConfig.setOnClickListener { stopConfiguringControls() }
|
binding.doneControlConfig.setOnClickListener { stopConfiguringControls() }
|
||||||
|
|
@ -747,11 +764,8 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||||
|
|
||||||
R.id.menu_quick_overlay -> {
|
R.id.menu_quick_overlay -> {
|
||||||
val newState = !BooleanSetting.SHOW_INPUT_OVERLAY.getBoolean()
|
val newState = !BooleanSetting.SHOW_INPUT_OVERLAY.getBoolean()
|
||||||
BooleanSetting.SHOW_INPUT_OVERLAY.setBoolean(newState)
|
|
||||||
updateQuickOverlayMenuEntry(newState)
|
|
||||||
binding.surfaceInputOverlay.refreshControls()
|
|
||||||
// Sync view visibility with the setting
|
|
||||||
toggleOverlay(newState)
|
toggleOverlay(newState)
|
||||||
|
updateQuickOverlayMenuEntry(BooleanSetting.SHOW_INPUT_OVERLAY.getBoolean())
|
||||||
NativeConfig.saveGlobalConfig()
|
NativeConfig.saveGlobalConfig()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
@ -890,8 +904,12 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
GameIconUtils.loadGameIcon(game!!, binding.loadingImage)
|
game?.let {
|
||||||
binding.loadingTitle.text = game!!.title
|
GameIconUtils.loadGameIcon(it, binding.loadingImage)
|
||||||
|
binding.loadingTitle.text = it.title
|
||||||
|
} ?: run {
|
||||||
|
binding.loadingTitle.text = ""
|
||||||
|
}
|
||||||
binding.loadingTitle.isSelected = true
|
binding.loadingTitle.isSelected = true
|
||||||
binding.loadingText.isSelected = true
|
binding.loadingText.isSelected = true
|
||||||
|
|
||||||
|
|
@ -959,6 +977,12 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||||
ViewUtils.showView(binding.loadingIndicator)
|
ViewUtils.showView(binding.loadingIndicator)
|
||||||
ViewUtils.hideView(binding.inputContainer)
|
ViewUtils.hideView(binding.inputContainer)
|
||||||
ViewUtils.hideView(binding.showStatsOverlayText)
|
ViewUtils.hideView(binding.showStatsOverlayText)
|
||||||
|
} else if (deferGameSetupUntilStopCompletes) {
|
||||||
|
if (!isAdded) {
|
||||||
|
return@collect
|
||||||
|
}
|
||||||
|
deferGameSetupUntilStopCompletes = false
|
||||||
|
finishGameSetup()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
emulationViewModel.drawerOpen.collect(viewLifecycleOwner) {
|
emulationViewModel.drawerOpen.collect(viewLifecycleOwner) {
|
||||||
|
|
@ -995,26 +1019,24 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||||
}
|
}
|
||||||
|
|
||||||
driverViewModel.isInteractionAllowed.collect(viewLifecycleOwner) {
|
driverViewModel.isInteractionAllowed.collect(viewLifecycleOwner) {
|
||||||
if (it && !NativeLibrary.isRunning() && !NativeLibrary.isPaused()) {
|
if (it &&
|
||||||
startEmulation()
|
!isStoppingForRomSwap &&
|
||||||
|
!NativeLibrary.isRunning() &&
|
||||||
|
!NativeLibrary.isPaused()
|
||||||
|
) {
|
||||||
|
if (!DirectoryInitialization.areDirectoriesReady) {
|
||||||
|
DirectoryInitialization.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
updateScreenLayout()
|
||||||
|
|
||||||
|
emulationState.run(emulationActivity!!.isActivityRecreated)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
driverViewModel.onLaunchGame()
|
driverViewModel.onLaunchGame()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun startEmulation(programIndex: Int = 0) {
|
|
||||||
if (!NativeLibrary.isRunning() && !NativeLibrary.isPaused()) {
|
|
||||||
if (!DirectoryInitialization.areDirectoriesReady) {
|
|
||||||
DirectoryInitialization.start()
|
|
||||||
}
|
|
||||||
|
|
||||||
updateScreenLayout()
|
|
||||||
|
|
||||||
emulationState.run(emulationActivity!!.isActivityRecreated, programIndex)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onConfigurationChanged(newConfig: Configuration) {
|
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||||
super.onConfigurationChanged(newConfig)
|
super.onConfigurationChanged(newConfig)
|
||||||
val b = _binding ?: return
|
val b = _binding ?: return
|
||||||
|
|
@ -1032,7 +1054,8 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||||
val shouldShowOverlay = if (args.overlayGamelessEditMode) {
|
val shouldShowOverlay = if (args.overlayGamelessEditMode) {
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
showInputOverlay && emulationViewModel.emulationStarted.value
|
showInputOverlay && emulationViewModel.emulationStarted.value &&
|
||||||
|
!hasPhysicalControllerConnected
|
||||||
}
|
}
|
||||||
b.surfaceInputOverlay.setVisible(shouldShowOverlay)
|
b.surfaceInputOverlay.setVisible(shouldShowOverlay)
|
||||||
if (!isInFoldableLayout) {
|
if (!isInFoldableLayout) {
|
||||||
|
|
@ -1057,6 +1080,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||||
private fun addQuickSettings() {
|
private fun addQuickSettings() {
|
||||||
binding.quickSettingsSheet.apply {
|
binding.quickSettingsSheet.apply {
|
||||||
val container = binding.quickSettingsSheet.findViewById<ViewGroup>(R.id.quick_settings_container)
|
val container = binding.quickSettingsSheet.findViewById<ViewGroup>(R.id.quick_settings_container)
|
||||||
|
val isFsrSelected = isFsrScalingFilterSelected()
|
||||||
|
|
||||||
container.removeAllViews()
|
container.removeAllViews()
|
||||||
|
|
||||||
|
|
@ -1138,16 +1162,20 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||||
IntSetting.RENDERER_SCALING_FILTER,
|
IntSetting.RENDERER_SCALING_FILTER,
|
||||||
R.array.rendererScalingFilterNames,
|
R.array.rendererScalingFilterNames,
|
||||||
R.array.rendererScalingFilterValues
|
R.array.rendererScalingFilterValues
|
||||||
)
|
) {
|
||||||
|
addQuickSettings()
|
||||||
|
}
|
||||||
|
|
||||||
quickSettings.addSliderSetting(
|
if (isFsrSelected) {
|
||||||
R.string.fsr_sharpness,
|
quickSettings.addSliderSetting(
|
||||||
container,
|
R.string.fsr_sharpness,
|
||||||
IntSetting.FSR_SHARPENING_SLIDER,
|
container,
|
||||||
minValue = 0,
|
IntSetting.FSR_SHARPENING_SLIDER,
|
||||||
maxValue = 100,
|
minValue = 0,
|
||||||
units = "%"
|
maxValue = 100,
|
||||||
)
|
units = "%"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
quickSettings.addIntSetting(
|
quickSettings.addIntSetting(
|
||||||
R.string.renderer_anti_aliasing,
|
R.string.renderer_anti_aliasing,
|
||||||
|
|
@ -1159,6 +1187,19 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun isFsrScalingFilterSelected(): Boolean {
|
||||||
|
val fsrFilterValue = resolveFsrScalingFilterValue() ?: return false
|
||||||
|
val selectedFilter = IntSetting.RENDERER_SCALING_FILTER.getInt(needsGlobal = false)
|
||||||
|
return selectedFilter == fsrFilterValue
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun resolveFsrScalingFilterValue(): Int? {
|
||||||
|
val names = resources.getStringArray(R.array.rendererScalingFilterNames)
|
||||||
|
val values = resources.getIntArray(R.array.rendererScalingFilterValues)
|
||||||
|
val fsrIndex = names.indexOf(getString(R.string.scaling_filter_fsr))
|
||||||
|
return if (fsrIndex in values.indices) values[fsrIndex] else null
|
||||||
|
}
|
||||||
|
|
||||||
private fun openQuickSettingsMenu() {
|
private fun openQuickSettingsMenu() {
|
||||||
binding.drawerLayout.closeDrawer(binding.inGameMenu)
|
binding.drawerLayout.closeDrawer(binding.inGameMenu)
|
||||||
binding.drawerLayout.openDrawer(binding.quickSettingsSheet)
|
binding.drawerLayout.openDrawer(binding.quickSettingsSheet)
|
||||||
|
|
@ -1375,6 +1416,9 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
amiiboLoadJob?.cancel()
|
amiiboLoadJob?.cancel()
|
||||||
amiiboLoadJob = null
|
amiiboLoadJob = null
|
||||||
|
perfStatsRunnable?.let { perfStatsUpdateHandler.removeCallbacks(it) }
|
||||||
|
socRunnable?.let { socUpdateHandler.removeCallbacks(it) }
|
||||||
|
handler.removeCallbacksAndMessages(null)
|
||||||
clearPausedFrame()
|
clearPausedFrame()
|
||||||
_binding?.surfaceInputOverlay?.touchEventListener = null
|
_binding?.surfaceInputOverlay?.touchEventListener = null
|
||||||
_binding = null
|
_binding = null
|
||||||
|
|
@ -1382,7 +1426,9 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDetach() {
|
override fun onDetach() {
|
||||||
NativeLibrary.clearEmulationActivity()
|
if (!hasNewerEmulationFragment()) {
|
||||||
|
NativeLibrary.clearEmulationActivity()
|
||||||
|
}
|
||||||
super.onDetach()
|
super.onDetach()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1840,10 +1886,74 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun surfaceDestroyed(holder: SurfaceHolder) {
|
override fun surfaceDestroyed(holder: SurfaceHolder) {
|
||||||
emulationState.clearSurface()
|
if (this::emulationState.isInitialized && !hasNewerEmulationFragment()) {
|
||||||
|
emulationState.clearSurface()
|
||||||
|
}
|
||||||
emulationStarted = false
|
emulationStarted = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun hasNewerEmulationFragment(): Boolean {
|
||||||
|
val activity = emulationActivity ?: return false
|
||||||
|
return try {
|
||||||
|
val navHostFragment =
|
||||||
|
activity.supportFragmentManager.findFragmentById(R.id.fragment_container) as? NavHostFragment
|
||||||
|
?: return false
|
||||||
|
val currentFragment = navHostFragment.childFragmentManager.fragments
|
||||||
|
.filterIsInstance<EmulationFragment>()
|
||||||
|
.firstOrNull()
|
||||||
|
currentFragment != null && currentFragment !== this
|
||||||
|
} catch (_: Exception) {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// xbzk: called from EmulationActivity when a new game is loaded while this fragment is still active,
|
||||||
|
// to wait for the emulation thread to stop before allowing the ROM swap to proceed
|
||||||
|
fun notifyWhenEmulationThreadStops(onStopped: () -> Unit) {
|
||||||
|
if (!this::emulationState.isInitialized) {
|
||||||
|
onStopped()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val emuThread = runCatching { emulationState.emulationThread }.getOrNull()
|
||||||
|
if (emuThread == null || !emuThread.isAlive) {
|
||||||
|
onStopped()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
Thread({
|
||||||
|
runCatching { emuThread.join() }
|
||||||
|
Handler(Looper.getMainLooper()).post {
|
||||||
|
onStopped()
|
||||||
|
}
|
||||||
|
}, "RomSwapWait").start()
|
||||||
|
}
|
||||||
|
|
||||||
|
// xbzk: called from EmulationActivity when a new game is loaded while this
|
||||||
|
// fragment is still active, to stop the current emulation before swapping the ROM
|
||||||
|
fun stopForRomSwap() {
|
||||||
|
if (isStoppingForRomSwap) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
isStoppingForRomSwap = true
|
||||||
|
clearPausedFrame()
|
||||||
|
emulationViewModel.setIsEmulationStopping(true)
|
||||||
|
_binding?.let {
|
||||||
|
binding.loadingText.setText(R.string.shutting_down)
|
||||||
|
ViewUtils.showView(binding.loadingIndicator)
|
||||||
|
ViewUtils.hideView(binding.inputContainer)
|
||||||
|
ViewUtils.hideView(binding.showStatsOverlayText)
|
||||||
|
}
|
||||||
|
if (this::emulationState.isInitialized) {
|
||||||
|
emulationState.stop()
|
||||||
|
if (NativeLibrary.isRunning() || NativeLibrary.isPaused()) {
|
||||||
|
Log.warning("[EmulationFragment] ROM swap stop fallback: forcing native stop request.")
|
||||||
|
NativeLibrary.stopEmulation()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
NativeLibrary.stopEmulation()
|
||||||
|
}
|
||||||
|
NativeConfig.reloadGlobalConfig()
|
||||||
|
}
|
||||||
|
|
||||||
private fun showOverlayOptions() {
|
private fun showOverlayOptions() {
|
||||||
val anchor = binding.inGameMenu.findViewById<View>(R.id.menu_overlay_controls)
|
val anchor = binding.inGameMenu.findViewById<View>(R.id.menu_overlay_controls)
|
||||||
val popup = PopupMenu(requireContext(), anchor)
|
val popup = PopupMenu(requireContext(), anchor)
|
||||||
|
|
@ -2134,6 +2244,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||||
state = State.STOPPED
|
state = State.STOPPED
|
||||||
} else {
|
} else {
|
||||||
Log.warning("[EmulationFragment] Stop called while already stopped.")
|
Log.warning("[EmulationFragment] Stop called while already stopped.")
|
||||||
|
NativeLibrary.stopEmulation()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2388,6 +2499,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||||
|
|
||||||
fun toggleOverlay(enable: Boolean) {
|
fun toggleOverlay(enable: Boolean) {
|
||||||
if (!isAdded || _binding == null) return
|
if (!isAdded || _binding == null) return
|
||||||
|
if (enable && hasPhysicalControllerConnected && !args.overlayGamelessEditMode) return
|
||||||
if (enable == !BooleanSetting.SHOW_INPUT_OVERLAY.getBoolean()) {
|
if (enable == !BooleanSetting.SHOW_INPUT_OVERLAY.getBoolean()) {
|
||||||
// Reset controller input flag so controller can hide overlay again
|
// Reset controller input flag so controller can hide overlay again
|
||||||
if (!enable) {
|
if (!enable) {
|
||||||
|
|
@ -2411,13 +2523,30 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onControllerConnected() {
|
fun onControllerConnected() {
|
||||||
controllerInputReceived = false
|
onPhysicalControllerStateChanged(InputHandler.androidControllers.isNotEmpty())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onControllerDisconnected() {
|
fun onControllerDisconnected() {
|
||||||
if (!BooleanSetting.HIDE_OVERLAY_ON_CONTROLLER_INPUT.getBoolean()) return
|
onPhysicalControllerStateChanged(InputHandler.androidControllers.isNotEmpty())
|
||||||
if (!BooleanSetting.SHOW_INPUT_OVERLAY.getBoolean()) return
|
}
|
||||||
|
|
||||||
|
fun onPhysicalControllerStateChanged(hasConnectedControllers: Boolean) {
|
||||||
|
hasPhysicalControllerConnected = hasConnectedControllers
|
||||||
controllerInputReceived = false
|
controllerInputReceived = false
|
||||||
toggleOverlay(true)
|
if (!isAdded || _binding == null) return
|
||||||
|
if (binding.surfaceInputOverlay.isGamelessMode()) return
|
||||||
|
|
||||||
|
if (hasConnectedControllers) {
|
||||||
|
if (BooleanSetting.SHOW_INPUT_OVERLAY.getBoolean()) {
|
||||||
|
overlayHiddenByPhysicalController = true
|
||||||
|
toggleOverlay(false)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (overlayHiddenByPhysicalController) {
|
||||||
|
overlayHiddenByPhysicalController = false
|
||||||
|
toggleOverlay(true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ import org.yuzu.yuzu_emu.databinding.FragmentGamePropertiesBinding
|
||||||
import org.yuzu.yuzu_emu.features.DocumentProvider
|
import org.yuzu.yuzu_emu.features.DocumentProvider
|
||||||
import org.yuzu.yuzu_emu.features.settings.model.Settings
|
import org.yuzu.yuzu_emu.features.settings.model.Settings
|
||||||
import org.yuzu.yuzu_emu.features.settings.ui.SettingsSubscreen
|
import org.yuzu.yuzu_emu.features.settings.ui.SettingsSubscreen
|
||||||
|
import org.yuzu.yuzu_emu.model.AddonViewModel
|
||||||
import org.yuzu.yuzu_emu.model.DriverViewModel
|
import org.yuzu.yuzu_emu.model.DriverViewModel
|
||||||
import org.yuzu.yuzu_emu.model.GameProperty
|
import org.yuzu.yuzu_emu.model.GameProperty
|
||||||
import org.yuzu.yuzu_emu.model.GamesViewModel
|
import org.yuzu.yuzu_emu.model.GamesViewModel
|
||||||
|
|
@ -46,6 +47,7 @@ import org.yuzu.yuzu_emu.model.SubmenuProperty
|
||||||
import org.yuzu.yuzu_emu.model.TaskState
|
import org.yuzu.yuzu_emu.model.TaskState
|
||||||
import org.yuzu.yuzu_emu.utils.DirectoryInitialization
|
import org.yuzu.yuzu_emu.utils.DirectoryInitialization
|
||||||
import org.yuzu.yuzu_emu.utils.FileUtil
|
import org.yuzu.yuzu_emu.utils.FileUtil
|
||||||
|
import org.yuzu.yuzu_emu.utils.GameHelper
|
||||||
import org.yuzu.yuzu_emu.utils.GameIconUtils
|
import org.yuzu.yuzu_emu.utils.GameIconUtils
|
||||||
import org.yuzu.yuzu_emu.utils.GpuDriverHelper
|
import org.yuzu.yuzu_emu.utils.GpuDriverHelper
|
||||||
import org.yuzu.yuzu_emu.utils.MemoryUtil
|
import org.yuzu.yuzu_emu.utils.MemoryUtil
|
||||||
|
|
@ -61,6 +63,7 @@ class GamePropertiesFragment : Fragment() {
|
||||||
|
|
||||||
private val homeViewModel: HomeViewModel by activityViewModels()
|
private val homeViewModel: HomeViewModel by activityViewModels()
|
||||||
private val gamesViewModel: GamesViewModel by activityViewModels()
|
private val gamesViewModel: GamesViewModel by activityViewModels()
|
||||||
|
private val addonViewModel: AddonViewModel by activityViewModels()
|
||||||
private val driverViewModel: DriverViewModel by activityViewModels()
|
private val driverViewModel: DriverViewModel by activityViewModels()
|
||||||
|
|
||||||
private val args by navArgs<GamePropertiesFragmentArgs>()
|
private val args by navArgs<GamePropertiesFragmentArgs>()
|
||||||
|
|
@ -118,6 +121,20 @@ class GamePropertiesFragment : Fragment() {
|
||||||
.show(childFragmentManager, LaunchGameDialogFragment.TAG)
|
.show(childFragmentManager, LaunchGameDialogFragment.TAG)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (GameHelper.cachedGameList.isEmpty()) {
|
||||||
|
binding.buttonStart.isEnabled = false
|
||||||
|
viewLifecycleOwner.lifecycleScope.launch {
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
GameHelper.restoreContentForGame(args.game)
|
||||||
|
}
|
||||||
|
if (_binding == null) {
|
||||||
|
return@launch
|
||||||
|
}
|
||||||
|
addonViewModel.onAddonsViewStarted(args.game)
|
||||||
|
binding.buttonStart.isEnabled = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
reloadList()
|
reloadList()
|
||||||
|
|
||||||
homeViewModel.openImportSaves.collect(
|
homeViewModel.openImportSaves.collect(
|
||||||
|
|
@ -133,8 +150,11 @@ class GamePropertiesFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
|
val isChangingConfigurations = activity?.isChangingConfigurations == true
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
gamesViewModel.reloadGames(true)
|
if (!isChangingConfigurations) {
|
||||||
|
gamesViewModel.reloadGames(true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getPlayTime() {
|
private fun getPlayTime() {
|
||||||
|
|
|
||||||
|
|
@ -227,66 +227,13 @@ class InstallableFragment : Fragment() {
|
||||||
|
|
||||||
private val installGameUpdateLauncher =
|
private val installGameUpdateLauncher =
|
||||||
registerForActivityResult(ActivityResultContracts.OpenMultipleDocuments()) { documents ->
|
registerForActivityResult(ActivityResultContracts.OpenMultipleDocuments()) { documents ->
|
||||||
if (documents.isEmpty()) {
|
InstallableActions.verifyAndInstallContent(
|
||||||
return@registerForActivityResult
|
activity = requireActivity(),
|
||||||
}
|
fragmentManager = parentFragmentManager,
|
||||||
|
addonViewModel = addonViewModel,
|
||||||
if (addonViewModel.game == null) {
|
documents = documents,
|
||||||
InstallableActions.installContent(
|
programId = addonViewModel.game?.programId
|
||||||
activity = requireActivity(),
|
)
|
||||||
fragmentManager = parentFragmentManager,
|
|
||||||
addonViewModel = addonViewModel,
|
|
||||||
documents = documents
|
|
||||||
)
|
|
||||||
return@registerForActivityResult
|
|
||||||
}
|
|
||||||
|
|
||||||
ProgressDialogFragment.newInstance(
|
|
||||||
requireActivity(),
|
|
||||||
R.string.verifying_content,
|
|
||||||
false
|
|
||||||
) { _, _ ->
|
|
||||||
var updatesMatchProgram = true
|
|
||||||
for (document in documents) {
|
|
||||||
val valid = NativeLibrary.doesUpdateMatchProgram(
|
|
||||||
addonViewModel.game!!.programId,
|
|
||||||
document.toString()
|
|
||||||
)
|
|
||||||
if (!valid) {
|
|
||||||
updatesMatchProgram = false
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (updatesMatchProgram) {
|
|
||||||
requireActivity().runOnUiThread {
|
|
||||||
InstallableActions.installContent(
|
|
||||||
activity = requireActivity(),
|
|
||||||
fragmentManager = parentFragmentManager,
|
|
||||||
addonViewModel = addonViewModel,
|
|
||||||
documents = documents
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
requireActivity().runOnUiThread {
|
|
||||||
MessageDialogFragment.newInstance(
|
|
||||||
requireActivity(),
|
|
||||||
titleId = R.string.content_install_notice,
|
|
||||||
descriptionId = R.string.content_install_notice_description,
|
|
||||||
positiveAction = {
|
|
||||||
InstallableActions.installContent(
|
|
||||||
activity = requireActivity(),
|
|
||||||
fragmentManager = parentFragmentManager,
|
|
||||||
addonViewModel = addonViewModel,
|
|
||||||
documents = documents
|
|
||||||
)
|
|
||||||
},
|
|
||||||
negativeAction = {}
|
|
||||||
).show(parentFragmentManager, MessageDialogFragment.TAG)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return@newInstance Any()
|
|
||||||
}.show(parentFragmentManager, ProgressDialogFragment.TAG)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val importUserDataLauncher =
|
private val importUserDataLauncher =
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.core.view.ViewCompat
|
import androidx.core.view.ViewCompat
|
||||||
import androidx.core.view.WindowInsetsCompat
|
import androidx.core.view.WindowInsetsCompat
|
||||||
|
import androidx.core.view.updatePadding
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.activityViewModels
|
import androidx.fragment.app.activityViewModels
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
|
|
@ -22,6 +23,7 @@ import org.yuzu.yuzu_emu.databinding.FragmentProfileManagerBinding
|
||||||
import org.yuzu.yuzu_emu.model.HomeViewModel
|
import org.yuzu.yuzu_emu.model.HomeViewModel
|
||||||
import org.yuzu.yuzu_emu.model.UserProfile
|
import org.yuzu.yuzu_emu.model.UserProfile
|
||||||
import org.yuzu.yuzu_emu.utils.NativeConfig
|
import org.yuzu.yuzu_emu.utils.NativeConfig
|
||||||
|
import org.yuzu.yuzu_emu.utils.ViewUtils.updateMargins
|
||||||
|
|
||||||
class ProfileManagerFragment : Fragment() {
|
class ProfileManagerFragment : Fragment() {
|
||||||
private var _binding: FragmentProfileManagerBinding? = null
|
private var _binding: FragmentProfileManagerBinding? = null
|
||||||
|
|
@ -172,11 +174,19 @@ class ProfileManagerFragment : Fragment() {
|
||||||
val leftInsets = barInsets.left + cutoutInsets.left
|
val leftInsets = barInsets.left + cutoutInsets.left
|
||||||
val rightInsets = barInsets.right + cutoutInsets.right
|
val rightInsets = barInsets.right + cutoutInsets.right
|
||||||
|
|
||||||
val fabLayoutParams = binding.buttonAddUser.layoutParams as ViewGroup.MarginLayoutParams
|
binding.toolbarProfiles.updateMargins(left = leftInsets, right = rightInsets)
|
||||||
fabLayoutParams.leftMargin = leftInsets + 24
|
binding.listProfiles.updateMargins(left = leftInsets, right = rightInsets)
|
||||||
fabLayoutParams.rightMargin = rightInsets + 24
|
binding.listProfiles.updatePadding(
|
||||||
fabLayoutParams.bottomMargin = barInsets.bottom + 24
|
bottom = barInsets.bottom +
|
||||||
binding.buttonAddUser.layoutParams = fabLayoutParams
|
resources.getDimensionPixelSize(R.dimen.spacing_bottom_list_fab)
|
||||||
|
)
|
||||||
|
|
||||||
|
val fabSpacing = resources.getDimensionPixelSize(R.dimen.spacing_fab)
|
||||||
|
binding.buttonAddUser.updateMargins(
|
||||||
|
left = leftInsets + fabSpacing,
|
||||||
|
right = rightInsets + fabSpacing,
|
||||||
|
bottom = barInsets.bottom + fabSpacing
|
||||||
|
)
|
||||||
|
|
||||||
windowInsets
|
windowInsets
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,7 @@ class DriverViewModel : ViewModel() {
|
||||||
private val driversToDelete = mutableListOf<String>()
|
private val driversToDelete = mutableListOf<String>()
|
||||||
|
|
||||||
private var previousDriverPath: String = ""
|
private var previousDriverPath: String = ""
|
||||||
|
private var activeGame: Game? = null
|
||||||
|
|
||||||
private val _shouldShowDriverShaderDialog = MutableStateFlow(false)
|
private val _shouldShowDriverShaderDialog = MutableStateFlow(false)
|
||||||
val shouldShowDriverShaderDialog: StateFlow<Boolean> get() = _shouldShowDriverShaderDialog
|
val shouldShowDriverShaderDialog: StateFlow<Boolean> get() = _shouldShowDriverShaderDialog
|
||||||
|
|
@ -71,6 +72,8 @@ class DriverViewModel : ViewModel() {
|
||||||
fun reloadDriverData() {
|
fun reloadDriverData() {
|
||||||
_areDriversLoading.value = true
|
_areDriversLoading.value = true
|
||||||
driverData = GpuDriverHelper.getDrivers()
|
driverData = GpuDriverHelper.getDrivers()
|
||||||
|
.filterNot { driversToDelete.contains(it.first) }
|
||||||
|
.toMutableList()
|
||||||
updateDriverList()
|
updateDriverList()
|
||||||
_areDriversLoading.value = false
|
_areDriversLoading.value = false
|
||||||
}
|
}
|
||||||
|
|
@ -96,6 +99,7 @@ class DriverViewModel : ViewModel() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onOpenDriverManager(game: Game?) {
|
fun onOpenDriverManager(game: Game?) {
|
||||||
|
activeGame = game
|
||||||
if (game != null) {
|
if (game != null) {
|
||||||
SettingsFile.loadCustomConfig(game)
|
SettingsFile.loadCustomConfig(game)
|
||||||
}
|
}
|
||||||
|
|
@ -114,10 +118,12 @@ class DriverViewModel : ViewModel() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!skipShaderWipe && newDriverPath != previousDriverPath) {
|
if (!skipShaderWipe && newDriverPath != previousDriverPath) {
|
||||||
wipeAllShaders()
|
activeGame?.let {
|
||||||
|
wipeGameShaders(it)
|
||||||
|
|
||||||
if (!BooleanSetting.DONT_SHOW_DRIVER_SHADER_WARNING.getBoolean(needsGlobal = true)) {
|
if (!BooleanSetting.DONT_SHOW_DRIVER_SHADER_WARNING.getBoolean(needsGlobal = true)) {
|
||||||
_shouldShowDriverShaderDialog.value = true
|
_shouldShowDriverShaderDialog.value = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -137,12 +143,14 @@ class DriverViewModel : ViewModel() {
|
||||||
_shouldShowDriverShaderDialog.value = false
|
_shouldShowDriverShaderDialog.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun wipeAllShaders() {
|
private fun wipeGameShaders(game: Game) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
|
val externalFilesDir = YuzuApplication.appContext.getExternalFilesDir(null)
|
||||||
|
?: return@withContext
|
||||||
val shaderDir = File(
|
val shaderDir = File(
|
||||||
YuzuApplication.appContext.getExternalFilesDir(null)?.canonicalPath +
|
externalFilesDir.absolutePath +
|
||||||
"/shader/"
|
"/shader/" + game.settingsName.lowercase()
|
||||||
)
|
)
|
||||||
if (shaderDir.exists()) {
|
if (shaderDir.exists()) {
|
||||||
shaderDir.deleteRecursively()
|
shaderDir.deleteRecursively()
|
||||||
|
|
@ -152,41 +160,56 @@ class DriverViewModel : ViewModel() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onDriverRemoved(removedPosition: Int, selectedPosition: Int) {
|
fun onDriverRemoved(removedPosition: Int, selectedPosition: Int) {
|
||||||
driversToDelete.add(driverData[removedPosition - 1].first)
|
val driverIndex = removedPosition - 1
|
||||||
driverData.removeAt(removedPosition - 1)
|
if (driverIndex !in driverData.indices) {
|
||||||
onDriverSelected(selectedPosition)
|
updateDriverList()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
driversToDelete.add(driverData[driverIndex].first)
|
||||||
|
driverData.removeAt(driverIndex)
|
||||||
|
val safeSelectedPosition = selectedPosition.coerceIn(0, driverData.size)
|
||||||
|
onDriverSelected(safeSelectedPosition)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onDriverAdded(driver: Pair<String, GpuDriverMetadata>) {
|
fun onDriverAdded(driver: Pair<String, GpuDriverMetadata>) {
|
||||||
if (driversToDelete.contains(driver.first)) {
|
if (driversToDelete.contains(driver.first)) {
|
||||||
driversToDelete.remove(driver.first)
|
driversToDelete.remove(driver.first)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val existingDriverIndex = driverData.indexOfFirst {
|
||||||
|
it.first == driver.first || it.second == driver.second
|
||||||
|
}
|
||||||
|
if (existingDriverIndex != -1) {
|
||||||
|
onDriverSelected(existingDriverIndex + 1)
|
||||||
|
return
|
||||||
|
}
|
||||||
driverData.add(driver)
|
driverData.add(driver)
|
||||||
onDriverSelected(driverData.size)
|
onDriverSelected(driverData.size)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onCloseDriverManager(game: Game?) {
|
fun onCloseDriverManager(game: Game?) {
|
||||||
_isDeletingDrivers.value = true
|
_isDeletingDrivers.value = true
|
||||||
updateDriverNameForGame(game)
|
try {
|
||||||
if (game == null) {
|
updateDriverNameForGame(game)
|
||||||
NativeConfig.saveGlobalConfig()
|
if (game == null) {
|
||||||
} else {
|
NativeConfig.saveGlobalConfig()
|
||||||
NativeConfig.savePerGameConfig()
|
} else {
|
||||||
NativeConfig.unloadPerGameConfig()
|
NativeConfig.savePerGameConfig()
|
||||||
NativeConfig.reloadGlobalConfig()
|
NativeConfig.unloadPerGameConfig()
|
||||||
}
|
NativeConfig.reloadGlobalConfig()
|
||||||
|
|
||||||
viewModelScope.launch {
|
|
||||||
withContext(Dispatchers.IO) {
|
|
||||||
driversToDelete.forEach {
|
|
||||||
val driver = File(it)
|
|
||||||
if (driver.exists()) {
|
|
||||||
driver.delete()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
driversToDelete.clear()
|
|
||||||
_isDeletingDrivers.value = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
driversToDelete.forEach {
|
||||||
|
val driver = File(it)
|
||||||
|
if (driver.exists()) {
|
||||||
|
driver.delete()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
driversToDelete.clear()
|
||||||
|
} finally {
|
||||||
|
activeGame = null
|
||||||
|
_isDeletingDrivers.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -100,42 +100,45 @@ class GamesViewModel : ViewModel() {
|
||||||
|
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
if (firstStartup) {
|
try {
|
||||||
// Retrieve list of cached games
|
if (firstStartup) {
|
||||||
val storedGames =
|
// Retrieve list of cached games
|
||||||
PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext)
|
val storedGames =
|
||||||
.getStringSet(GameHelper.KEY_GAMES, emptySet())
|
PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext)
|
||||||
if (storedGames!!.isNotEmpty()) {
|
.getStringSet(GameHelper.KEY_GAMES, emptySet())
|
||||||
val deserializedGames = mutableSetOf<Game>()
|
if (storedGames!!.isNotEmpty()) {
|
||||||
storedGames.forEach {
|
val deserializedGames = mutableSetOf<Game>()
|
||||||
val game: Game
|
storedGames.forEach {
|
||||||
try {
|
val game: Game
|
||||||
game = Json.decodeFromString(it)
|
try {
|
||||||
} catch (e: Exception) {
|
game = Json.decodeFromString(it)
|
||||||
// We don't care about any errors related to parsing the game cache
|
} catch (e: Exception) {
|
||||||
return@forEach
|
// We don't care about any errors related to parsing the game cache
|
||||||
}
|
return@forEach
|
||||||
|
}
|
||||||
|
|
||||||
val gameExists =
|
val gameExists =
|
||||||
DocumentFile.fromSingleUri(
|
DocumentFile.fromSingleUri(
|
||||||
YuzuApplication.appContext,
|
YuzuApplication.appContext,
|
||||||
Uri.parse(game.path)
|
Uri.parse(game.path)
|
||||||
)?.exists()
|
)?.exists()
|
||||||
if (gameExists == true) {
|
if (gameExists == true) {
|
||||||
deserializedGames.add(game)
|
deserializedGames.add(game)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
setGames(deserializedGames.toList())
|
||||||
}
|
}
|
||||||
setGames(deserializedGames.toList())
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
setGames(GameHelper.getGames())
|
setGames(GameHelper.getGames())
|
||||||
reloading.set(false)
|
_shouldScrollAfterReload.value = true
|
||||||
_isReloading.value = false
|
|
||||||
_shouldScrollAfterReload.value = true
|
|
||||||
|
|
||||||
if (directoriesChanged) {
|
if (directoriesChanged) {
|
||||||
setShouldSwapData(true)
|
setShouldSwapData(true)
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
reloading.set(false)
|
||||||
|
_isReloading.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,6 @@ import org.yuzu.yuzu_emu.databinding.ActivityMainBinding
|
||||||
import org.yuzu.yuzu_emu.dialogs.NetPlayDialog
|
import org.yuzu.yuzu_emu.dialogs.NetPlayDialog
|
||||||
import org.yuzu.yuzu_emu.features.settings.model.Settings
|
import org.yuzu.yuzu_emu.features.settings.model.Settings
|
||||||
import org.yuzu.yuzu_emu.fragments.AddGameFolderDialogFragment
|
import org.yuzu.yuzu_emu.fragments.AddGameFolderDialogFragment
|
||||||
import org.yuzu.yuzu_emu.fragments.ProgressDialogFragment
|
|
||||||
import org.yuzu.yuzu_emu.fragments.MessageDialogFragment
|
import org.yuzu.yuzu_emu.fragments.MessageDialogFragment
|
||||||
import org.yuzu.yuzu_emu.model.AddonViewModel
|
import org.yuzu.yuzu_emu.model.AddonViewModel
|
||||||
import org.yuzu.yuzu_emu.model.DriverViewModel
|
import org.yuzu.yuzu_emu.model.DriverViewModel
|
||||||
|
|
@ -87,8 +86,6 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
|
||||||
|
|
||||||
binding = ActivityMainBinding.inflate(layoutInflater)
|
binding = ActivityMainBinding.inflate(layoutInflater)
|
||||||
|
|
||||||
// Since Android 15, google automatically forces "games" to be 60 hrz
|
|
||||||
// This ensures the display's max refresh rate is actually used
|
|
||||||
display?.let {
|
display?.let {
|
||||||
val supportedModes = it.supportedModes
|
val supportedModes = it.supportedModes
|
||||||
val maxRefreshRate = supportedModes.maxByOrNull { mode -> mode.refreshRate }
|
val maxRefreshRate = supportedModes.maxByOrNull { mode -> mode.refreshRate }
|
||||||
|
|
@ -170,6 +167,7 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
|
||||||
checkForUpdates()
|
checkForUpdates()
|
||||||
}
|
}
|
||||||
setInsets()
|
setInsets()
|
||||||
|
applyFullscreenPreference()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkForUpdates() {
|
private fun checkForUpdates() {
|
||||||
|
|
@ -346,6 +344,14 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
ThemeHelper.setCorrectTheme(this)
|
ThemeHelper.setCorrectTheme(this)
|
||||||
super.onResume()
|
super.onResume()
|
||||||
|
applyFullscreenPreference()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onWindowFocusChanged(hasFocus: Boolean) {
|
||||||
|
super.onWindowFocusChanged(hasFocus)
|
||||||
|
if (hasFocus) {
|
||||||
|
applyFullscreenPreference()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setInsets() = ViewCompat.setOnApplyWindowInsetsListener(
|
private fun setInsets() = ViewCompat.setOnApplyWindowInsetsListener(
|
||||||
|
|
@ -365,6 +371,10 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
|
||||||
windowInsets
|
windowInsets
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun applyFullscreenPreference() {
|
||||||
|
FullscreenHelper.applyToActivity(this)
|
||||||
|
}
|
||||||
|
|
||||||
override fun setTheme(resId: Int) {
|
override fun setTheme(resId: Int) {
|
||||||
super.setTheme(resId)
|
super.setTheme(resId)
|
||||||
themeId = resId
|
themeId = resId
|
||||||
|
|
@ -479,49 +489,6 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val installGameUpdate = registerForActivityResult(
|
|
||||||
ActivityResultContracts.OpenMultipleDocuments()
|
|
||||||
) { documents: List<Uri> ->
|
|
||||||
if (documents.isEmpty()) {
|
|
||||||
return@registerForActivityResult
|
|
||||||
}
|
|
||||||
|
|
||||||
if (addonViewModel.game == null) {
|
|
||||||
installContent(documents)
|
|
||||||
return@registerForActivityResult
|
|
||||||
}
|
|
||||||
|
|
||||||
ProgressDialogFragment.newInstance(
|
|
||||||
this@MainActivity,
|
|
||||||
R.string.verifying_content,
|
|
||||||
false
|
|
||||||
) { _, _ ->
|
|
||||||
var updatesMatchProgram = true
|
|
||||||
for (document in documents) {
|
|
||||||
val valid = NativeLibrary.doesUpdateMatchProgram(
|
|
||||||
addonViewModel.game!!.programId,
|
|
||||||
document.toString()
|
|
||||||
)
|
|
||||||
if (!valid) {
|
|
||||||
updatesMatchProgram = false
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (updatesMatchProgram) {
|
|
||||||
homeViewModel.setContentToInstall(documents)
|
|
||||||
} else {
|
|
||||||
MessageDialogFragment.newInstance(
|
|
||||||
this@MainActivity,
|
|
||||||
titleId = R.string.content_install_notice,
|
|
||||||
descriptionId = R.string.content_install_notice_description,
|
|
||||||
positiveAction = { homeViewModel.setContentToInstall(documents) },
|
|
||||||
negativeAction = {}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}.show(supportFragmentManager, ProgressDialogFragment.TAG)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun installContent(documents: List<Uri>) {
|
private fun installContent(documents: List<Uri>) {
|
||||||
InstallableActions.installContent(
|
InstallableActions.installContent(
|
||||||
activity = this,
|
activity = this,
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,8 @@ object DirectoryInitialization {
|
||||||
fun start() {
|
fun start() {
|
||||||
if (!areDirectoriesReady) {
|
if (!areDirectoriesReady) {
|
||||||
initializeInternalStorage()
|
initializeInternalStorage()
|
||||||
NativeLibrary.initializeSystem(false)
|
|
||||||
NativeConfig.initializeGlobalConfig()
|
NativeConfig.initializeGlobalConfig()
|
||||||
|
NativeLibrary.initializeSystem(false)
|
||||||
NativeLibrary.reloadProfiles()
|
NativeLibrary.reloadProfiles()
|
||||||
migrateSettings()
|
migrateSettings()
|
||||||
areDirectoriesReady = true
|
areDirectoriesReady = true
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
package org.yuzu.yuzu_emu.utils
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Context
|
||||||
|
import android.view.Window
|
||||||
|
import androidx.core.content.edit
|
||||||
|
import androidx.core.view.ViewCompat
|
||||||
|
import androidx.core.view.WindowInsetsCompat
|
||||||
|
import androidx.core.view.WindowInsetsControllerCompat
|
||||||
|
import androidx.preference.PreferenceManager
|
||||||
|
import org.yuzu.yuzu_emu.features.settings.model.Settings
|
||||||
|
|
||||||
|
object FullscreenHelper {
|
||||||
|
fun isFullscreenEnabled(context: Context): Boolean {
|
||||||
|
return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(
|
||||||
|
Settings.PREF_APP_FULLSCREEN,
|
||||||
|
Settings.APP_FULLSCREEN_DEFAULT
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setFullscreenEnabled(context: Context, enabled: Boolean) {
|
||||||
|
PreferenceManager.getDefaultSharedPreferences(context).edit {
|
||||||
|
putBoolean(Settings.PREF_APP_FULLSCREEN, enabled)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun shouldHideSystemBars(activity: Activity): Boolean {
|
||||||
|
val rootInsets = ViewCompat.getRootWindowInsets(activity.window.decorView)
|
||||||
|
val barsCurrentlyHidden =
|
||||||
|
rootInsets?.isVisible(WindowInsetsCompat.Type.systemBars())?.not() ?: false
|
||||||
|
return isFullscreenEnabled(activity) || barsCurrentlyHidden
|
||||||
|
}
|
||||||
|
|
||||||
|
fun applyToWindow(window: Window, hideSystemBars: Boolean) {
|
||||||
|
val controller = WindowInsetsControllerCompat(window, window.decorView)
|
||||||
|
|
||||||
|
if (hideSystemBars) {
|
||||||
|
controller.hide(WindowInsetsCompat.Type.systemBars())
|
||||||
|
controller.systemBarsBehavior =
|
||||||
|
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
|
||||||
|
} else {
|
||||||
|
controller.show(WindowInsetsCompat.Type.systemBars())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun applyToActivity(activity: Activity) {
|
||||||
|
applyToWindow(activity.window, isFullscreenEnabled(activity))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -8,9 +8,11 @@ package org.yuzu.yuzu_emu.utils
|
||||||
|
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
import android.provider.DocumentsContract
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import kotlinx.serialization.encodeToString
|
import kotlinx.serialization.encodeToString
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
|
import java.io.File
|
||||||
import org.yuzu.yuzu_emu.NativeLibrary
|
import org.yuzu.yuzu_emu.NativeLibrary
|
||||||
import org.yuzu.yuzu_emu.YuzuApplication
|
import org.yuzu.yuzu_emu.YuzuApplication
|
||||||
import org.yuzu.yuzu_emu.model.Game
|
import org.yuzu.yuzu_emu.model.Game
|
||||||
|
|
@ -49,29 +51,8 @@ object GameHelper {
|
||||||
// Remove previous filesystem provider information so we can get up to date version info
|
// Remove previous filesystem provider information so we can get up to date version info
|
||||||
NativeLibrary.clearFilesystemProvider()
|
NativeLibrary.clearFilesystemProvider()
|
||||||
|
|
||||||
// Scan External Content directories and register all NSP/XCI files
|
|
||||||
val externalContentDirs = NativeConfig.getExternalContentDirs()
|
|
||||||
val uniqueExternalContentDirs = linkedSetOf<String>()
|
|
||||||
externalContentDirs.forEach { externalDir ->
|
|
||||||
if (externalDir.isNotEmpty()) {
|
|
||||||
uniqueExternalContentDirs.add(externalDir)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val mountedContainerUris = mutableSetOf<String>()
|
val mountedContainerUris = mutableSetOf<String>()
|
||||||
for (externalDir in uniqueExternalContentDirs) {
|
mountExternalContentDirectories(mountedContainerUris)
|
||||||
if (externalDir.isNotEmpty()) {
|
|
||||||
val externalDirUri = externalDir.toUri()
|
|
||||||
if (FileUtil.isTreeUriValid(externalDirUri)) {
|
|
||||||
scanContentContainersRecursive(FileUtil.listFiles(externalDirUri), 3) {
|
|
||||||
val containerUri = it.uri.toString()
|
|
||||||
if (mountedContainerUris.add(containerUri)) {
|
|
||||||
NativeLibrary.addFileToFilesystemProvider(containerUri)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val badDirs = mutableListOf<Int>()
|
val badDirs = mutableListOf<Int>()
|
||||||
gameDirs.forEachIndexed { index: Int, gameDir: GameDir ->
|
gameDirs.forEachIndexed { index: Int, gameDir: GameDir ->
|
||||||
|
|
@ -115,6 +96,15 @@ object GameHelper {
|
||||||
return games.toList()
|
return games.toList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun restoreContentForGame(game: Game) {
|
||||||
|
NativeLibrary.reloadKeys()
|
||||||
|
|
||||||
|
val mountedContainerUris = mutableSetOf<String>()
|
||||||
|
mountExternalContentDirectories(mountedContainerUris)
|
||||||
|
mountGameFolderContent(Uri.parse(game.path), mountedContainerUris)
|
||||||
|
NativeLibrary.addFileToFilesystemProvider(game.path)
|
||||||
|
}
|
||||||
|
|
||||||
// File extensions considered as external content, buuut should
|
// File extensions considered as external content, buuut should
|
||||||
// be done better imo.
|
// be done better imo.
|
||||||
private val externalContentExtensions = setOf("nsp", "xci")
|
private val externalContentExtensions = setOf("nsp", "xci")
|
||||||
|
|
@ -181,6 +171,71 @@ object GameHelper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun mountExternalContentDirectories(mountedContainerUris: MutableSet<String>) {
|
||||||
|
val uniqueExternalContentDirs = linkedSetOf<String>()
|
||||||
|
NativeConfig.getExternalContentDirs().forEach { externalDir ->
|
||||||
|
if (externalDir.isNotEmpty()) {
|
||||||
|
uniqueExternalContentDirs.add(externalDir)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (externalDir in uniqueExternalContentDirs) {
|
||||||
|
val externalDirUri = externalDir.toUri()
|
||||||
|
if (FileUtil.isTreeUriValid(externalDirUri)) {
|
||||||
|
scanContentContainersRecursive(FileUtil.listFiles(externalDirUri), 3) {
|
||||||
|
val containerUri = it.uri.toString()
|
||||||
|
if (mountedContainerUris.add(containerUri)) {
|
||||||
|
NativeLibrary.addFileToFilesystemProvider(containerUri)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun mountGameFolderContent(gameUri: Uri, mountedContainerUris: MutableSet<String>) {
|
||||||
|
if (gameUri.scheme == "content") {
|
||||||
|
val parentUri = getParentDocumentUri(gameUri) ?: return
|
||||||
|
scanContentContainersRecursive(FileUtil.listFiles(parentUri), 1) {
|
||||||
|
val containerUri = it.uri.toString()
|
||||||
|
if (mountedContainerUris.add(containerUri)) {
|
||||||
|
NativeLibrary.addGameFolderFileToFilesystemProvider(containerUri)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val gameFile = File(gameUri.path ?: gameUri.toString())
|
||||||
|
val parentDir = gameFile.parentFile ?: return
|
||||||
|
parentDir.listFiles()?.forEach { sibling ->
|
||||||
|
if (!sibling.isFile) {
|
||||||
|
return@forEach
|
||||||
|
}
|
||||||
|
|
||||||
|
val extension = sibling.extension.lowercase()
|
||||||
|
if (externalContentExtensions.contains(extension)) {
|
||||||
|
val containerUri = Uri.fromFile(sibling).toString()
|
||||||
|
if (mountedContainerUris.add(containerUri)) {
|
||||||
|
NativeLibrary.addGameFolderFileToFilesystemProvider(containerUri)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getParentDocumentUri(uri: Uri): Uri? {
|
||||||
|
return try {
|
||||||
|
val documentId = DocumentsContract.getDocumentId(uri)
|
||||||
|
val separatorIndex = documentId.lastIndexOf('/')
|
||||||
|
if (separatorIndex == -1) {
|
||||||
|
null
|
||||||
|
} else {
|
||||||
|
val parentDocumentId = documentId.substring(0, separatorIndex)
|
||||||
|
DocumentsContract.buildDocumentUriUsingTree(uri, parentDocumentId)
|
||||||
|
}
|
||||||
|
} catch (_: Exception) {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun getGame(
|
fun getGame(
|
||||||
uri: Uri,
|
uri: Uri,
|
||||||
addedToLibrary: Boolean,
|
addedToLibrary: Boolean,
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,6 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
|
@ -14,6 +17,60 @@ object InputHandler {
|
||||||
var androidControllers = mapOf<Int, YuzuPhysicalDevice>()
|
var androidControllers = mapOf<Int, YuzuPhysicalDevice>()
|
||||||
var registeredControllers = mutableListOf<ParamPackage>()
|
var registeredControllers = mutableListOf<ParamPackage>()
|
||||||
|
|
||||||
|
private val controllerButtons = intArrayOf(
|
||||||
|
KeyEvent.KEYCODE_BUTTON_A,
|
||||||
|
KeyEvent.KEYCODE_BUTTON_B,
|
||||||
|
KeyEvent.KEYCODE_BUTTON_X,
|
||||||
|
KeyEvent.KEYCODE_BUTTON_Y,
|
||||||
|
KeyEvent.KEYCODE_BUTTON_L1,
|
||||||
|
KeyEvent.KEYCODE_BUTTON_R1,
|
||||||
|
KeyEvent.KEYCODE_BUTTON_L2,
|
||||||
|
KeyEvent.KEYCODE_BUTTON_R2,
|
||||||
|
KeyEvent.KEYCODE_BUTTON_THUMBL,
|
||||||
|
KeyEvent.KEYCODE_BUTTON_THUMBR,
|
||||||
|
KeyEvent.KEYCODE_BUTTON_START,
|
||||||
|
KeyEvent.KEYCODE_BUTTON_SELECT,
|
||||||
|
KeyEvent.KEYCODE_DPAD_UP,
|
||||||
|
KeyEvent.KEYCODE_DPAD_DOWN,
|
||||||
|
KeyEvent.KEYCODE_DPAD_LEFT,
|
||||||
|
KeyEvent.KEYCODE_DPAD_RIGHT
|
||||||
|
)
|
||||||
|
|
||||||
|
private val controllerAxes = intArrayOf(
|
||||||
|
MotionEvent.AXIS_X,
|
||||||
|
MotionEvent.AXIS_Y,
|
||||||
|
MotionEvent.AXIS_Z,
|
||||||
|
MotionEvent.AXIS_RX,
|
||||||
|
MotionEvent.AXIS_RY,
|
||||||
|
MotionEvent.AXIS_RZ,
|
||||||
|
MotionEvent.AXIS_HAT_X,
|
||||||
|
MotionEvent.AXIS_HAT_Y,
|
||||||
|
MotionEvent.AXIS_LTRIGGER,
|
||||||
|
MotionEvent.AXIS_RTRIGGER
|
||||||
|
)
|
||||||
|
|
||||||
|
fun isPhysicalGameController(device: InputDevice?): Boolean {
|
||||||
|
device ?: return false
|
||||||
|
|
||||||
|
if (device.isVirtual) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
val sources = device.sources
|
||||||
|
val hasControllerSource =
|
||||||
|
sources and InputDevice.SOURCE_GAMEPAD == InputDevice.SOURCE_GAMEPAD ||
|
||||||
|
sources and InputDevice.SOURCE_JOYSTICK == InputDevice.SOURCE_JOYSTICK
|
||||||
|
if (!hasControllerSource) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
val hasControllerButtons = device.hasKeys(*controllerButtons).any { it }
|
||||||
|
val hasControllerAxes = device.motionRanges.any { range ->
|
||||||
|
controllerAxes.contains(range.axis)
|
||||||
|
}
|
||||||
|
return hasControllerButtons || hasControllerAxes
|
||||||
|
}
|
||||||
|
|
||||||
fun dispatchKeyEvent(event: KeyEvent): Boolean {
|
fun dispatchKeyEvent(event: KeyEvent): Boolean {
|
||||||
val action = when (event.action) {
|
val action = when (event.action) {
|
||||||
KeyEvent.ACTION_DOWN -> NativeInput.ButtonState.PRESSED
|
KeyEvent.ACTION_DOWN -> NativeInput.ButtonState.PRESSED
|
||||||
|
|
@ -57,10 +114,7 @@ object InputHandler {
|
||||||
val inputSettings = NativeConfig.getInputSettings(true)
|
val inputSettings = NativeConfig.getInputSettings(true)
|
||||||
deviceIds.forEach { deviceId ->
|
deviceIds.forEach { deviceId ->
|
||||||
InputDevice.getDevice(deviceId)?.apply {
|
InputDevice.getDevice(deviceId)?.apply {
|
||||||
// Verify that the device has gamepad buttons, control sticks, or both.
|
if (isPhysicalGameController(this)) {
|
||||||
if (sources and InputDevice.SOURCE_GAMEPAD == InputDevice.SOURCE_GAMEPAD ||
|
|
||||||
sources and InputDevice.SOURCE_JOYSTICK == InputDevice.SOURCE_JOYSTICK
|
|
||||||
) {
|
|
||||||
if (!gameControllerDeviceIds.contains(controllerNumber)) {
|
if (!gameControllerDeviceIds.contains(controllerNumber)) {
|
||||||
gameControllerDeviceIds[controllerNumber] = YuzuPhysicalDevice(
|
gameControllerDeviceIds[controllerNumber] = YuzuPhysicalDevice(
|
||||||
this,
|
this,
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,78 @@ import java.util.zip.ZipEntry
|
||||||
import java.util.zip.ZipInputStream
|
import java.util.zip.ZipInputStream
|
||||||
|
|
||||||
object InstallableActions {
|
object InstallableActions {
|
||||||
|
private fun verifyGameContentAndInstall(
|
||||||
|
activity: FragmentActivity,
|
||||||
|
fragmentManager: FragmentManager,
|
||||||
|
documents: List<Uri>,
|
||||||
|
programId: String?,
|
||||||
|
onInstallConfirmed: () -> Unit
|
||||||
|
) {
|
||||||
|
if (documents.isEmpty()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (programId == null) {
|
||||||
|
onInstallConfirmed()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ProgressDialogFragment.newInstance(
|
||||||
|
activity,
|
||||||
|
R.string.verifying_content,
|
||||||
|
false
|
||||||
|
) { _, _ ->
|
||||||
|
var updatesMatchProgram = true
|
||||||
|
for (document in documents) {
|
||||||
|
val valid = NativeLibrary.doesUpdateMatchProgram(
|
||||||
|
programId,
|
||||||
|
document.toString()
|
||||||
|
)
|
||||||
|
if (!valid) {
|
||||||
|
updatesMatchProgram = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
activity.runOnUiThread {
|
||||||
|
if (updatesMatchProgram) {
|
||||||
|
onInstallConfirmed()
|
||||||
|
} else {
|
||||||
|
MessageDialogFragment.newInstance(
|
||||||
|
activity,
|
||||||
|
titleId = R.string.content_install_notice,
|
||||||
|
descriptionId = R.string.content_install_notice_description,
|
||||||
|
positiveAction = onInstallConfirmed,
|
||||||
|
negativeAction = {}
|
||||||
|
).show(fragmentManager, MessageDialogFragment.TAG)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return@newInstance Any()
|
||||||
|
}.show(fragmentManager, ProgressDialogFragment.TAG)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun verifyAndInstallContent(
|
||||||
|
activity: FragmentActivity,
|
||||||
|
fragmentManager: FragmentManager,
|
||||||
|
addonViewModel: AddonViewModel,
|
||||||
|
documents: List<Uri>,
|
||||||
|
programId: String?
|
||||||
|
) {
|
||||||
|
verifyGameContentAndInstall(
|
||||||
|
activity = activity,
|
||||||
|
fragmentManager = fragmentManager,
|
||||||
|
documents = documents,
|
||||||
|
programId = programId
|
||||||
|
) {
|
||||||
|
installContent(
|
||||||
|
activity = activity,
|
||||||
|
fragmentManager = fragmentManager,
|
||||||
|
addonViewModel = addonViewModel,
|
||||||
|
documents = documents
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun processKey(
|
fun processKey(
|
||||||
activity: FragmentActivity,
|
activity: FragmentActivity,
|
||||||
fragmentManager: FragmentManager,
|
fragmentManager: FragmentManager,
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ namespace AndroidSettings {
|
||||||
|
|
||||||
Settings::Setting<s32> theme{linkage, 0, "theme", Settings::Category::Android};
|
Settings::Setting<s32> theme{linkage, 0, "theme", Settings::Category::Android};
|
||||||
Settings::Setting<s32> theme_mode{linkage, -1, "theme_mode", Settings::Category::Android};
|
Settings::Setting<s32> theme_mode{linkage, -1, "theme_mode", Settings::Category::Android};
|
||||||
Settings::Setting<s32> static_theme_color{linkage, 5, "static_theme_color", Settings::Category::Android};
|
Settings::Setting<s32> static_theme_color{linkage, 0, "static_theme_color", Settings::Category::Android};
|
||||||
Settings::Setting<bool> black_backgrounds{linkage, false, "black_backgrounds",
|
Settings::Setting<bool> black_backgrounds{linkage, false, "black_backgrounds",
|
||||||
Settings::Category::Android};
|
Settings::Category::Android};
|
||||||
Settings::Setting<s32> app_language{linkage, 0, "app_language", Settings::Category::Android};
|
Settings::Setting<s32> app_language{linkage, 0, "app_language", Settings::Category::Android};
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,15 @@
|
||||||
|
|
||||||
#include <android/native_window_jni.h>
|
#include <android/native_window_jni.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <array>
|
||||||
|
#include <cmath>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
|
||||||
#include "common/android/id_cache.h"
|
#include "common/android/id_cache.h"
|
||||||
#include "common/logging.h"
|
#include "common/logging.h"
|
||||||
|
#include "common/settings.h"
|
||||||
#include "input_common/drivers/android.h"
|
#include "input_common/drivers/android.h"
|
||||||
#include "input_common/drivers/touch_screen.h"
|
#include "input_common/drivers/touch_screen.h"
|
||||||
#include "input_common/drivers/virtual_amiibo.h"
|
#include "input_common/drivers/virtual_amiibo.h"
|
||||||
|
|
@ -22,6 +29,12 @@ void EmuWindow_Android::OnSurfaceChanged(ANativeWindow* surface) {
|
||||||
m_window_width = 0;
|
m_window_width = 0;
|
||||||
m_window_height = 0;
|
m_window_height = 0;
|
||||||
window_info.render_surface = nullptr;
|
window_info.render_surface = nullptr;
|
||||||
|
m_last_frame_rate_hint = -1.0f;
|
||||||
|
m_pending_frame_rate_hint = -1.0f;
|
||||||
|
m_pending_frame_rate_hint_votes = 0;
|
||||||
|
m_smoothed_present_rate = 0.0f;
|
||||||
|
m_last_frame_display_time = {};
|
||||||
|
m_pending_frame_rate_since = {};
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -32,6 +45,7 @@ void EmuWindow_Android::OnSurfaceChanged(ANativeWindow* surface) {
|
||||||
UpdateCurrentFramebufferLayout(m_window_width, m_window_height);
|
UpdateCurrentFramebufferLayout(m_window_width, m_window_height);
|
||||||
|
|
||||||
window_info.render_surface = reinterpret_cast<void*>(surface);
|
window_info.render_surface = reinterpret_cast<void*>(surface);
|
||||||
|
UpdateFrameRateHint();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmuWindow_Android::OnTouchPressed(int id, float x, float y) {
|
void EmuWindow_Android::OnTouchPressed(int id, float x, float y) {
|
||||||
|
|
@ -51,6 +65,9 @@ void EmuWindow_Android::OnTouchReleased(int id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmuWindow_Android::OnFrameDisplayed() {
|
void EmuWindow_Android::OnFrameDisplayed() {
|
||||||
|
UpdateObservedFrameRate();
|
||||||
|
UpdateFrameRateHint();
|
||||||
|
|
||||||
if (!m_first_frame) {
|
if (!m_first_frame) {
|
||||||
Common::Android::RunJNIOnFiber<void>(
|
Common::Android::RunJNIOnFiber<void>(
|
||||||
[&](JNIEnv* env) { EmulationSession::GetInstance().OnEmulationStarted(); });
|
[&](JNIEnv* env) { EmulationSession::GetInstance().OnEmulationStarted(); });
|
||||||
|
|
@ -58,6 +75,175 @@ void EmuWindow_Android::OnFrameDisplayed() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EmuWindow_Android::UpdateObservedFrameRate() {
|
||||||
|
const auto now = Clock::now();
|
||||||
|
if (m_last_frame_display_time.time_since_epoch().count() != 0) {
|
||||||
|
const auto frame_time = std::chrono::duration<float>(now - m_last_frame_display_time);
|
||||||
|
const float seconds = frame_time.count();
|
||||||
|
if (seconds > 0.0f) {
|
||||||
|
const float instantaneous_rate = 1.0f / seconds;
|
||||||
|
if (std::isfinite(instantaneous_rate) && instantaneous_rate >= 1.0f &&
|
||||||
|
instantaneous_rate <= 240.0f) {
|
||||||
|
constexpr float SmoothingFactor = 0.15f;
|
||||||
|
if (m_smoothed_present_rate <= 0.0f) {
|
||||||
|
m_smoothed_present_rate = instantaneous_rate;
|
||||||
|
} else {
|
||||||
|
m_smoothed_present_rate +=
|
||||||
|
(instantaneous_rate - m_smoothed_present_rate) * SmoothingFactor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_last_frame_display_time = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
float EmuWindow_Android::QuantizeFrameRateHint(float frame_rate) {
|
||||||
|
if (!std::isfinite(frame_rate) || frame_rate <= 0.0f) {
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
frame_rate = std::clamp(frame_rate, 1.0f, 240.0f);
|
||||||
|
|
||||||
|
constexpr float Step = 0.5f;
|
||||||
|
return std::round(frame_rate / Step) * Step;
|
||||||
|
}
|
||||||
|
|
||||||
|
float EmuWindow_Android::GetFrameTimeVerifiedHint() const {
|
||||||
|
if (!EmulationSession::GetInstance().IsRunning()) {
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
const double frame_time_scale =
|
||||||
|
EmulationSession::GetInstance().System().GetPerfStats().GetLastFrameTimeScale();
|
||||||
|
if (!std::isfinite(frame_time_scale) || frame_time_scale <= 0.0) {
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
const float verified_rate =
|
||||||
|
std::clamp(60.0f / static_cast<float>(frame_time_scale), 0.0f, 240.0f);
|
||||||
|
return QuantizeFrameRateHint(verified_rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
float EmuWindow_Android::GetFrameRateHint() const {
|
||||||
|
const float observed_rate = std::clamp(m_smoothed_present_rate, 0.0f, 240.0f);
|
||||||
|
const float frame_time_verified_hint = GetFrameTimeVerifiedHint();
|
||||||
|
|
||||||
|
if (m_last_frame_rate_hint > 0.0f && observed_rate > 0.0f) {
|
||||||
|
const float tolerance = std::max(m_last_frame_rate_hint * 0.12f, 4.0f);
|
||||||
|
if (std::fabs(observed_rate - m_last_frame_rate_hint) <= tolerance) {
|
||||||
|
return m_last_frame_rate_hint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const float observed_hint = QuantizeFrameRateHint(observed_rate);
|
||||||
|
if (observed_hint > 0.0f) {
|
||||||
|
if (frame_time_verified_hint > 0.0f) {
|
||||||
|
const float tolerance = std::max(observed_hint * 0.20f, 3.0f);
|
||||||
|
if (std::fabs(observed_hint - frame_time_verified_hint) <= tolerance) {
|
||||||
|
return QuantizeFrameRateHint((observed_hint + frame_time_verified_hint) * 0.5f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return observed_hint;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frame_time_verified_hint > 0.0f) {
|
||||||
|
return frame_time_verified_hint;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr float NominalFrameRate = 60.0f;
|
||||||
|
if (!Settings::values.use_speed_limit.GetValue()) {
|
||||||
|
return NominalFrameRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
const u16 speed_limit = Settings::SpeedLimit();
|
||||||
|
if (speed_limit == 0) {
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
const float speed_limited_rate =
|
||||||
|
NominalFrameRate * (static_cast<float>(std::min<u16>(speed_limit, 100)) / 100.0f);
|
||||||
|
return QuantizeFrameRateHint(speed_limited_rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmuWindow_Android::UpdateFrameRateHint() {
|
||||||
|
auto* const surface = reinterpret_cast<ANativeWindow*>(window_info.render_surface);
|
||||||
|
if (!surface) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto now = Clock::now();
|
||||||
|
const float frame_rate_hint = GetFrameRateHint();
|
||||||
|
if (std::fabs(frame_rate_hint - m_last_frame_rate_hint) < 0.01f) {
|
||||||
|
m_pending_frame_rate_hint = frame_rate_hint;
|
||||||
|
m_pending_frame_rate_hint_votes = 0;
|
||||||
|
m_pending_frame_rate_since = {};
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frame_rate_hint == 0.0f) {
|
||||||
|
m_pending_frame_rate_hint = frame_rate_hint;
|
||||||
|
m_pending_frame_rate_hint_votes = 0;
|
||||||
|
m_pending_frame_rate_since = now;
|
||||||
|
} else if (m_last_frame_rate_hint >= 0.0f) {
|
||||||
|
if (std::fabs(frame_rate_hint - m_pending_frame_rate_hint) >= 0.01f) {
|
||||||
|
m_pending_frame_rate_hint = frame_rate_hint;
|
||||||
|
m_pending_frame_rate_hint_votes = 1;
|
||||||
|
m_pending_frame_rate_since = now;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
++m_pending_frame_rate_hint_votes;
|
||||||
|
if (m_pending_frame_rate_since.time_since_epoch().count() == 0) {
|
||||||
|
m_pending_frame_rate_since = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto stable_for = now - m_pending_frame_rate_since;
|
||||||
|
const float reference_rate = std::max(frame_rate_hint, 1.0f);
|
||||||
|
const auto stable_duration = std::chrono::duration_cast<Clock::duration>(
|
||||||
|
std::chrono::duration<float>(std::clamp(3.0f / reference_rate, 0.15f, 0.40f)));
|
||||||
|
constexpr std::uint32_t MinStableVotes = 3;
|
||||||
|
|
||||||
|
if (m_pending_frame_rate_hint_votes < MinStableVotes || stable_for < stable_duration) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
m_pending_frame_rate_since = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
using SetFrameRateWithChangeStrategyFn =
|
||||||
|
int32_t (*)(ANativeWindow*, float, int8_t, int8_t);
|
||||||
|
using SetFrameRateFn = int32_t (*)(ANativeWindow*, float, int8_t);
|
||||||
|
static const auto set_frame_rate_with_change_strategy =
|
||||||
|
reinterpret_cast<SetFrameRateWithChangeStrategyFn>(
|
||||||
|
dlsym(RTLD_DEFAULT, "ANativeWindow_setFrameRateWithChangeStrategy"));
|
||||||
|
static const auto set_frame_rate = reinterpret_cast<SetFrameRateFn>(
|
||||||
|
dlsym(RTLD_DEFAULT, "ANativeWindow_setFrameRate"));
|
||||||
|
|
||||||
|
constexpr int8_t FrameRateCompatibilityDefault = 0;
|
||||||
|
constexpr int8_t ChangeFrameRateOnlyIfSeamless = 0;
|
||||||
|
|
||||||
|
int32_t result = -1;
|
||||||
|
if (set_frame_rate_with_change_strategy) {
|
||||||
|
result = set_frame_rate_with_change_strategy(surface, frame_rate_hint,
|
||||||
|
FrameRateCompatibilityDefault,
|
||||||
|
ChangeFrameRateOnlyIfSeamless);
|
||||||
|
} else if (set_frame_rate) {
|
||||||
|
result = set_frame_rate(surface, frame_rate_hint, FrameRateCompatibilityDefault);
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result != 0) {
|
||||||
|
LOG_DEBUG(Frontend, "Failed to update Android surface frame rate hint: {}", result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_last_frame_rate_hint = frame_rate_hint;
|
||||||
|
m_pending_frame_rate_hint = frame_rate_hint;
|
||||||
|
m_pending_frame_rate_hint_votes = 0;
|
||||||
|
m_pending_frame_rate_since = {};
|
||||||
|
}
|
||||||
|
|
||||||
EmuWindow_Android::EmuWindow_Android(ANativeWindow* surface,
|
EmuWindow_Android::EmuWindow_Android(ANativeWindow* surface,
|
||||||
std::shared_ptr<Common::DynamicLibrary> driver_library)
|
std::shared_ptr<Common::DynamicLibrary> driver_library)
|
||||||
: m_driver_library{driver_library} {
|
: m_driver_library{driver_library} {
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,13 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <cstdint>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <span>
|
#include <span>
|
||||||
|
|
||||||
|
|
@ -50,10 +55,24 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
using Clock = std::chrono::steady_clock;
|
||||||
|
|
||||||
|
void UpdateFrameRateHint();
|
||||||
|
void UpdateObservedFrameRate();
|
||||||
|
[[nodiscard]] float GetFrameRateHint() const;
|
||||||
|
[[nodiscard]] float GetFrameTimeVerifiedHint() const;
|
||||||
|
[[nodiscard]] static float QuantizeFrameRateHint(float frame_rate);
|
||||||
|
|
||||||
float m_window_width{};
|
float m_window_width{};
|
||||||
float m_window_height{};
|
float m_window_height{};
|
||||||
|
|
||||||
std::shared_ptr<Common::DynamicLibrary> m_driver_library;
|
std::shared_ptr<Common::DynamicLibrary> m_driver_library;
|
||||||
|
|
||||||
bool m_first_frame = false;
|
bool m_first_frame = false;
|
||||||
|
float m_last_frame_rate_hint = -1.0f;
|
||||||
|
float m_pending_frame_rate_hint = -1.0f;
|
||||||
|
float m_smoothed_present_rate = 0.0f;
|
||||||
|
Clock::time_point m_last_frame_display_time{};
|
||||||
|
Clock::time_point m_pending_frame_rate_since{};
|
||||||
|
std::uint32_t m_pending_frame_rate_hint_votes = 0;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 206 KiB After Width: | Height: | Size: 131 KiB |
|
Before Width: | Height: | Size: 73 KiB After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 51 KiB |
|
|
@ -5,21 +5,22 @@
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="?attr/colorSurface"
|
android:background="?attr/colorSurface">
|
||||||
android:fitsSystemWindows="true">
|
|
||||||
|
|
||||||
<com.google.android.material.appbar.AppBarLayout
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
android:id="@+id/appbar"
|
android:id="@+id/appbar"
|
||||||
style="@style/Widget.Eden.TransparentTopAppBarLayout"
|
style="@style/Widget.Eden.TransparentTopAppBarLayout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:fitsSystemWindows="true">
|
android:fitsSystemWindows="true"
|
||||||
|
android:touchscreenBlocksFocus="false">
|
||||||
|
|
||||||
<com.google.android.material.appbar.MaterialToolbar
|
<com.google.android.material.appbar.MaterialToolbar
|
||||||
android:id="@+id/toolbar_profiles"
|
android:id="@+id/toolbar_profiles"
|
||||||
style="@style/Widget.Eden.TransparentTopToolbar"
|
style="@style/Widget.Eden.TransparentTopToolbar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="?attr/actionBarSize"
|
android:layout_height="?attr/actionBarSize"
|
||||||
|
android:touchscreenBlocksFocus="false"
|
||||||
app:title="@string/profile_manager"
|
app:title="@string/profile_manager"
|
||||||
app:navigationIcon="@drawable/ic_back"
|
app:navigationIcon="@drawable/ic_back"
|
||||||
app:titleCentered="false" />
|
app:titleCentered="false" />
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 164 KiB After Width: | Height: | Size: 67 KiB |