Compare commits
106 commits
Author | SHA1 | Date | |
---|---|---|---|
|
a1fd418685 | ||
|
bb5a79f234 | ||
|
4eb90a7a65 | ||
|
94fcdc3c61 | ||
|
8911a44766 | ||
|
89368f63c9 | ||
|
d4a0603bf2 | ||
|
666238ba9f | ||
|
bcdd0dd7fd | ||
|
6096de8c13 | ||
|
582ec7aa54 | ||
|
e14083c87c | ||
|
c2f0932670 | ||
|
7a490b5aae | ||
|
4c8209762c | ||
|
76690a319c | ||
|
36816db7ac | ||
|
801f902bea | ||
|
74d39e6314 | ||
|
40a9dee4ed | ||
|
6bfbcfc456 | ||
|
e00f5fae9d | ||
|
4164255ef9 | ||
|
b790fb3fb5 | ||
|
b4f051395f | ||
|
420809b24e | ||
|
7d820bd4ab | ||
|
aa3a3b8bbc | ||
|
ccecc67d74 | ||
|
dcd2e6af4a | ||
|
7a01ac0d41 | ||
|
796a128456 | ||
|
695da18473 | ||
|
7870a28cdd | ||
|
a44000ea2b | ||
|
2b4a7426ff | ||
|
f50b060795 | ||
|
a049ed43ec | ||
|
ae3ca1ac7a | ||
|
2257030ade | ||
|
6df937a57c | ||
|
078e83ec70 | ||
|
ac8a3a3a3c | ||
|
fcdc414692 | ||
|
505910bc5f | ||
|
f8b34febbe | ||
|
35130b08b7 | ||
|
5699c06dd8 | ||
|
cb5870f30d | ||
|
28f017d640 | ||
|
bae081d5b3 | ||
|
baa034fa3f | ||
|
fa44a3269c | ||
|
5914ceec77 | ||
|
402782b4af | ||
|
e6af02a35c | ||
|
367489e230 | ||
|
9a0ef224a0 | ||
|
510064c899 | ||
|
3a90ef0a65 | ||
|
b69bf280f8 | ||
|
c1a4504470 | ||
|
7c00b13818 | ||
|
3b85e147b6 | ||
|
2906cfdd69 | ||
|
2a4b67b58e | ||
|
bb4e5398b2 | ||
|
0b6e479e0b | ||
|
fc58e83e9c | ||
|
1b8fa556f8 | ||
|
12054a91c9 | ||
|
acf15480f2 | ||
|
9ab84e6054 | ||
|
a0c3768edb | ||
|
7785c310a9 | ||
|
96cbd5d9b8 | ||
|
42a3b864d0 | ||
|
24d73064db | ||
|
cb827a525a | ||
|
170dcd4d65 | ||
|
32e1539c22 | ||
|
88c03aa744 | ||
|
698bce8022 | ||
|
20c54b05ad | ||
|
abc9a27208 | ||
|
0e324a41a0 | ||
|
3272f47dc6 | ||
|
c5246541a9 | ||
|
0af3ae27d4 | ||
|
1ee23e0fa2 | ||
|
b9a9ea497c | ||
|
e531a90d26 | ||
|
7cf370c70d | ||
|
d4dc0ffee1 | ||
|
a2955d21fc | ||
|
da051803f5 | ||
|
49d65ad14a | ||
|
042e02eb3e | ||
|
3c2e9a0418 | ||
|
6c46920adb | ||
|
81984b7d48 | ||
|
fbb19f94ea | ||
|
85d9594ebc | ||
|
89c3175d71 | ||
|
9e698dd7c4 | ||
|
1ce2dbd5d2 |
|
@ -5,6 +5,7 @@ image:
|
|||
branches:
|
||||
only:
|
||||
- master
|
||||
- develop
|
||||
- /^v\d.*$/
|
||||
- /^deploy-test(-.*)?$/
|
||||
|
||||
|
@ -36,14 +37,14 @@ for:
|
|||
install:
|
||||
- git submodule update --init --recursive
|
||||
- sudo pip3 install protobuf
|
||||
- brew install qt opus openssl@1.1 nasm sdl2 protobuf
|
||||
- HOMEBREW_NO_AUTO_UPDATE=1 brew install qt@5 opus openssl@1.1 nasm sdl2 protobuf
|
||||
- scripts/build-ffmpeg.sh
|
||||
|
||||
build_script:
|
||||
- export CMAKE_PREFIX_PATH="`pwd`/ffmpeg-prefix;/usr/local/opt/openssl@1.1;/usr/local/opt/qt"
|
||||
- export CMAKE_PREFIX_PATH="`pwd`/ffmpeg-prefix;/usr/local/opt/openssl@1.1;/usr/local/opt/qt@5"
|
||||
- scripts/build-common.sh
|
||||
- cp -a build/gui/chiaki.app Chiaki.app
|
||||
- /usr/local/opt/qt/bin/macdeployqt Chiaki.app -dmg
|
||||
- /usr/local/opt/qt@5/bin/macdeployqt Chiaki.app -dmg
|
||||
|
||||
artifacts:
|
||||
- path: Chiaki.dmg
|
||||
|
|
|
@ -22,7 +22,7 @@ tasks:
|
|||
sudo docker run \
|
||||
-v /home/build:/home/build \
|
||||
-u $(id -u):$(id -g) \
|
||||
thestr4ng3r/android:f064ea6 \
|
||||
thestr4ng3r/android:90d826e \
|
||||
/bin/bash -c "cd /home/build/chiaki/android && ./gradlew assembleRelease bundleRelease"
|
||||
cp chiaki/android/app/build/outputs/apk/release/app-release*.apk Chiaki.apk
|
||||
cp chiaki/android/app/build/outputs/bundle/release/app-release*.aab Chiaki.aab
|
||||
|
|
|
@ -9,38 +9,47 @@ packages:
|
|||
- ninja
|
||||
- protoc
|
||||
- py3-protobuf
|
||||
- py3-setuptools
|
||||
- opus-dev
|
||||
- qt5-qtbase-dev
|
||||
- qt5-qtsvg-dev
|
||||
- qt5-qtmultimedia-dev
|
||||
- ffmpeg-dev
|
||||
- sdl2-dev
|
||||
- sdl2-static # this is gone on alpine edge so might be necessary to remove later
|
||||
- docker
|
||||
- podman
|
||||
- fuse
|
||||
- udev
|
||||
- argp-standalone
|
||||
|
||||
artifacts:
|
||||
- chiaki.nro
|
||||
- Chiaki.AppImage
|
||||
|
||||
tasks:
|
||||
- start_docker: |
|
||||
sudo service docker start
|
||||
sudo chmod +s /usr/bin/docker # Yes, I know what I am doing
|
||||
sudo service fuse start # Fuse for AppImages
|
||||
- setup_podman: |
|
||||
sudo rc-service udev start
|
||||
sudo rc-service cgroups start
|
||||
sudo rc-service fuse start # Fuse for AppImages
|
||||
echo build:100000:65536 | sudo tee /etc/subuid
|
||||
echo build:100000:65536 | sudo tee /etc/subgid
|
||||
# https://www.kernel.org/doc/Documentation/networking/tuntap.txt
|
||||
# for slirp4netns
|
||||
sudo mkdir -p /dev/net
|
||||
sudo mknod /dev/net/tun c 10 200
|
||||
sudo chmod 0666 /dev/net/tun
|
||||
- local_build_and_test: |
|
||||
cd chiaki
|
||||
cmake -Bbuild -GNinja
|
||||
cmake -Bbuild -GNinja -DCHIAKI_ENABLE_CLI=ON -DCHIAKI_ENABLE_GUI=ON -DCHIAKI_CLI_ARGP_STANDALONE=ON
|
||||
ninja -C build
|
||||
build/test/chiaki-unit
|
||||
- appimage: |
|
||||
cd chiaki
|
||||
scripts/run-docker-build-appimage.sh
|
||||
scripts/run-podman-build-appimage.sh
|
||||
cp appimage/Chiaki.AppImage ../Chiaki.AppImage
|
||||
- switch: |
|
||||
cd chiaki
|
||||
scripts/switch/run-docker-build-chiaki.sh
|
||||
scripts/switch/run-podman-build-chiaki.sh
|
||||
cp build_switch/switch/chiaki.nro ../chiaki.nro
|
||||
- bullseye: |
|
||||
cd chiaki
|
||||
scripts/run-docker-build-bullseye.sh
|
||||
scripts/run-podman-build-bullseye.sh
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
image: freebsd/latest
|
||||
image: freebsd/14.x
|
||||
|
||||
sources:
|
||||
- https://git.sr.ht/~thestr4ng3r/chiaki
|
||||
|
@ -7,7 +7,8 @@ sources:
|
|||
packages:
|
||||
- cmake
|
||||
- protobuf
|
||||
- py37-protobuf
|
||||
- py311-setuptools # should not be needed with nanopb >= 0.4.9
|
||||
- py311-protobuf
|
||||
- opus
|
||||
- qt5-core
|
||||
- qt5-qmake
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
image: openbsd/6.7
|
||||
image: openbsd/latest
|
||||
|
||||
sources:
|
||||
- https://git.sr.ht/~thestr4ng3r/chiaki
|
||||
|
@ -7,6 +7,7 @@ sources:
|
|||
packages:
|
||||
- cmake
|
||||
- protobuf
|
||||
- py3-setuptools # should not be needed with nanopb >= 0.4.9
|
||||
- py3-protobuf
|
||||
- opus
|
||||
- qtbase
|
||||
|
|
2
.gitignore
vendored
|
@ -29,3 +29,5 @@ compile_commands.json
|
|||
chiaki.conf
|
||||
/appimage
|
||||
.cache/
|
||||
/*.app
|
||||
/*.dmg
|
||||
|
|
2
.gitmodules
vendored
|
@ -15,4 +15,4 @@
|
|||
url = https://github.com/google/oboe
|
||||
[submodule "switch/borealis"]
|
||||
path = switch/borealis
|
||||
url = https://github.com/natinusala/borealis.git
|
||||
url = https://git.sr.ht/~thestr4ng3r/borealis
|
||||
|
|
|
@ -24,6 +24,7 @@ endif()
|
|||
tri_option(CHIAKI_ENABLE_FFMPEG_DECODER "Enable FFMPEG video decoder" ${CHIAKI_FFMPEG_DEFAULT})
|
||||
tri_option(CHIAKI_ENABLE_PI_DECODER "Enable Raspberry Pi-specific video decoder (requires libraspberrypi0 and libraspberrypi-doc)" AUTO)
|
||||
option(CHIAKI_LIB_ENABLE_MBEDTLS "Use mbedtls instead of OpenSSL as part of Chiaki Lib" OFF)
|
||||
option(CHIAKI_LIB_MBEDTLS_EXTERNAL_PROJECT "Fetch Mbed TLS instead of using system-provided libs" OFF)
|
||||
option(CHIAKI_LIB_OPENSSL_EXTERNAL_PROJECT "Use OpenSSL as CMake external project" OFF)
|
||||
option(CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER "Use SDL Gamecontroller for Input" ON)
|
||||
option(CHIAKI_CLI_ARGP_STANDALONE "Search for standalone argp lib for CLI" OFF)
|
||||
|
@ -31,7 +32,7 @@ tri_option(CHIAKI_USE_SYSTEM_JERASURE "Use system-provided jerasure instead of s
|
|||
tri_option(CHIAKI_USE_SYSTEM_NANOPB "Use system-provided nanopb instead of submodule" AUTO)
|
||||
|
||||
set(CHIAKI_VERSION_MAJOR 2)
|
||||
set(CHIAKI_VERSION_MINOR 0)
|
||||
set(CHIAKI_VERSION_MINOR 2)
|
||||
set(CHIAKI_VERSION_PATCH 0)
|
||||
set(CHIAKI_VERSION ${CHIAKI_VERSION_MAJOR}.${CHIAKI_VERSION_MINOR}.${CHIAKI_VERSION_PATCH})
|
||||
|
||||
|
@ -89,6 +90,20 @@ endif()
|
|||
|
||||
if(CHIAKI_LIB_ENABLE_MBEDTLS)
|
||||
add_definitions(-DCHIAKI_LIB_ENABLE_MBEDTLS)
|
||||
if(CHIAKI_LIB_MBEDTLS_EXTERNAL_PROJECT)
|
||||
set(FETCHCONTENT_QUIET CACHE BOOL FALSE)
|
||||
include(FetchContent)
|
||||
set(ENABLE_TESTING CACHE INTERNAL OFF)
|
||||
set(ENABLE_PROGRAMS CACHE INTERNAL OFF)
|
||||
set(USE_SHARED_MBEDTLS_LIBRARY CACHE INTERNAL OFF)
|
||||
FetchContent_Declare(
|
||||
mbedtls
|
||||
GIT_REPOSITORY https://github.com/Mbed-TLS/mbedtls.git
|
||||
GIT_TAG 8b3f26a5ac38d4fdccbc5c5366229f3e01dafcc0 # v2.28.0
|
||||
GIT_PROGRESS TRUE
|
||||
)
|
||||
FetchContent_MakeAvailable(mbedtls)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CHIAKI_ENABLE_FFMPEG_DECODER)
|
||||
|
@ -135,21 +150,30 @@ if(CHIAKI_ENABLE_CLI)
|
|||
add_subdirectory(cli)
|
||||
endif()
|
||||
|
||||
if(CHIAKI_ENABLE_GUI AND CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER)
|
||||
find_package(SDL2 MODULE REQUIRED)
|
||||
endif()
|
||||
|
||||
if(CHIAKI_ENABLE_SETSU)
|
||||
find_package(Udev QUIET)
|
||||
find_package(Evdev QUIET)
|
||||
if(Udev_FOUND AND Evdev_FOUND)
|
||||
set(CHIAKI_ENABLE_SETSU ON)
|
||||
else()
|
||||
if(NOT CHIAKI_ENABLE_SETSU STREQUAL AUTO)
|
||||
message(FATAL_ERROR "
|
||||
CHIAKI_ENABLE_SETSU is set to ON, but its dependencies (udev and evdev) could not be resolved.
|
||||
Keep in mind that setsu is only supported on Linux!")
|
||||
endif()
|
||||
if(CHIAKI_ENABLE_SETSU STREQUAL AUTO AND SDL2_FOUND AND (SDL2_VERSION_MINOR GREATER 0 OR SDL2_VERSION_PATCH GREATER_EQUAL 14))
|
||||
message(STATUS "SDL version ${SDL2_VERSION} is >= 2.0.14, disabling Setsu")
|
||||
set(CHIAKI_ENABLE_SETSU OFF)
|
||||
endif()
|
||||
if(CHIAKI_ENABLE_SETSU)
|
||||
add_subdirectory(setsu)
|
||||
else()
|
||||
find_package(Udev QUIET)
|
||||
find_package(Evdev QUIET)
|
||||
if(Udev_FOUND AND Evdev_FOUND)
|
||||
set(CHIAKI_ENABLE_SETSU ON)
|
||||
else()
|
||||
if(NOT CHIAKI_ENABLE_SETSU STREQUAL AUTO)
|
||||
message(FATAL_ERROR "
|
||||
CHIAKI_ENABLE_SETSU is set to ON, but its dependencies (udev and evdev) could not be resolved.
|
||||
Keep in mind that setsu is only supported on Linux!")
|
||||
endif()
|
||||
set(CHIAKI_ENABLE_SETSU OFF)
|
||||
endif()
|
||||
if(CHIAKI_ENABLE_SETSU)
|
||||
add_subdirectory(setsu)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
@ -160,7 +184,6 @@ else()
|
|||
endif()
|
||||
|
||||
if(CHIAKI_ENABLE_GUI)
|
||||
#add_subdirectory(setsu)
|
||||
add_subdirectory(gui)
|
||||
endif()
|
||||
|
||||
|
|
39
README.md
|
@ -8,33 +8,35 @@
|
|||
[](https://ci.appveyor.com/project/thestr4ng3r/chiaki) [](https://builds.sr.ht/~thestr4ng3r/chiaki?)
|
||||
|
||||
Chiaki is a Free and Open Source Software Client for PlayStation 4 and PlayStation 5 Remote Play
|
||||
for Linux, FreeBSD, OpenBSD, Android, macOS, Windows, Nintendo Switch and potentially even more platforms.
|
||||
for Linux, FreeBSD, OpenBSD, NetBSD, Android, macOS, Windows, Nintendo Switch and potentially even more platforms.
|
||||
|
||||
## Project Status and Contributing
|
||||
|
||||
As all relevant features are implemented, this project is considered to be finished and in maintenance mode only.
|
||||
No major updates are planned and contributions are only accepted in special cases such as security issues.
|
||||
The objective is to keep a stable base and not break existing support for less mainstream platforms such as BSDs.
|
||||
|
||||
**For a more active, fast moving and community-oriented project, refer
|
||||
to [chiaki-ng](https://streetpea.github.io/chiaki-ng/) ("next generation").
|
||||
If you would like to contribute, this will likely also be the best place to do so.**
|
||||
|
||||

|
||||
|
||||
## Features
|
||||
|
||||
Everything necessary for a full streaming session, including the initial
|
||||
registration and wakeup of the console, is supported.
|
||||
The following features however are yet to be implemented:
|
||||
* Rumble
|
||||
* Accelerometer/Gyroscope
|
||||
|
||||
## Installing
|
||||
|
||||
You can either download a pre-built release (easier) or build Chiaki from source.
|
||||
You can either download a pre-built release or build Chiaki from source.
|
||||
|
||||
### Downloading a Release
|
||||
|
||||
Builds are provided for Linux, Android, macOS and Windows.
|
||||
Builds are provided for Linux, Android, macOS, Nintendo Switch and Windows.
|
||||
|
||||
You can download them [here](https://git.sr.ht/~thestr4ng3r/chiaki/refs).
|
||||
|
||||
* **Linux**: The provided file is an [AppImage](https://appimage.org/). Simply make it executable (`chmod +x <file>.AppImage`) and run it.
|
||||
* **Android**: Install from [Google Play](https://play.google.com/store/apps/details?id=com.metallic.chiaki), [F-Droid](https://f-droid.org/packages/com.metallic.chiaki/) or download the APK from Sourcehut.
|
||||
* **Android**: Install from [F-Droid](https://f-droid.org/packages/com.metallic.chiaki/) or download the APK from Sourcehut.
|
||||
* **macOS**: Drag the application from the `.dmg` into your Applications folder.
|
||||
* **Windows**: Extract the `.zip` file and execute `chiaki.exe`.
|
||||
* **Switch**: Follow README specific [instructions](./switch/README.md)
|
||||
* **Switch**: Download the `.nro` file and copy it into the `switch/` directory on your SD card.
|
||||
|
||||
### Building from Source
|
||||
|
||||
|
@ -47,8 +49,8 @@ cmake ..
|
|||
make
|
||||
```
|
||||
|
||||
For more detailed platform-specific instructions, see [doc/platform-build.md](doc/platform-build.md).
|
||||
in
|
||||
For more detailed platform-specific instructions, see [doc/platform-build.md](doc/platform-build.md) or [switch/](./switch/README.md) for Nintendo Switch.
|
||||
|
||||
## Usage
|
||||
|
||||
If your Console is on your local network, is turned on or in standby mode and does not have Discovery explicitly disabled, Chiaki should find it.
|
||||
|
@ -71,13 +73,6 @@ Settings -> Remote Play -> Add Device, or on a PS5: Settings -> System -> Remote
|
|||
|
||||
You can now double-click your Console in Chiaki's main window to start Remote Play.
|
||||
|
||||
## Joining the Community or Getting Help
|
||||
|
||||
There are official groups for Chiaki on Telegram and IRC. They are bridged so you can join whichever you like:
|
||||
|
||||
- **Telegram:** https://t.me/chiakitg
|
||||
- **IRC:** #chiaki on irc.freenode.net
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
This project has only been made possible because of the following Open Source projects:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
apply plugin: 'kotlin-parcelize'
|
||||
apply plugin: 'kotlin-kapt'
|
||||
|
||||
def rootCMakeLists = "../../CMakeLists.txt"
|
||||
|
@ -18,13 +18,12 @@ def chiakiVersion = "$chiakiVersionMajor.$chiakiVersionMinor.$chiakiVersionPatch
|
|||
println("Determined Chiaki Version: $chiakiVersion")
|
||||
|
||||
android {
|
||||
compileSdkVersion 30
|
||||
buildToolsVersion "30.0.2"
|
||||
compileSdkVersion 33
|
||||
defaultConfig {
|
||||
applicationId "com.metallic.chiaki"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 30
|
||||
versionCode 8
|
||||
targetSdkVersion 33
|
||||
versionCode 12
|
||||
versionName chiakiVersion
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
|
@ -33,11 +32,16 @@ android {
|
|||
"-DCHIAKI_ENABLE_GUI=OFF",
|
||||
"-DCHIAKI_ENABLE_SETSU=OFF",
|
||||
"-DCHIAKI_ENABLE_ANDROID=ON",
|
||||
"-DCHIAKI_ENABLE_FFMPEG_DECODER=OFF",
|
||||
"-DCHIAKI_ENABLE_PI_DECODER=OFF",
|
||||
"-DCHIAKI_LIB_ENABLE_OPUS=OFF",
|
||||
"-DCHIAKI_LIB_OPENSSL_EXTERNAL_PROJECT=ON"
|
||||
}
|
||||
}
|
||||
}
|
||||
buildFeatures {
|
||||
viewBinding true
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
|
@ -47,7 +51,7 @@ android {
|
|||
}
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
version "3.10.2+"
|
||||
version "3.22.1"
|
||||
path rootCMakeLists
|
||||
}
|
||||
}
|
||||
|
@ -61,6 +65,7 @@ android {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
Properties properties = new Properties()
|
||||
def propertiesFile = file("../local.properties")
|
||||
if (propertiesFile.exists()) {
|
||||
|
@ -86,31 +91,26 @@ tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
|
|||
}
|
||||
}
|
||||
|
||||
androidExtensions {
|
||||
// for @Parcelize
|
||||
experimental = true
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||
implementation 'androidx.core:core-ktx:1.2.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||
implementation 'androidx.recyclerview:recyclerview:1.1.0'
|
||||
implementation 'androidx.preference:preference:1.1.0'
|
||||
implementation 'com.google.android.material:material:1.1.0-beta02'
|
||||
implementation 'androidx.appcompat:appcompat:1.6.0'
|
||||
implementation 'androidx.core:core-ktx:1.9.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
||||
implementation 'androidx.recyclerview:recyclerview:1.2.1'
|
||||
implementation 'androidx.preference:preference:1.2.0'
|
||||
implementation 'com.google.android.material:material:1.8.0'
|
||||
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
|
||||
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'
|
||||
implementation 'androidx.lifecycle:lifecycle-reactivestreams:2.2.0'
|
||||
implementation "io.reactivex.rxjava2:rxjava:2.2.12"
|
||||
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1'
|
||||
implementation 'androidx.lifecycle:lifecycle-reactivestreams:2.5.1'
|
||||
implementation "io.reactivex.rxjava2:rxjava:2.2.20"
|
||||
implementation "io.reactivex.rxjava2:rxkotlin:2.4.0"
|
||||
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
|
||||
def room_version = "2.2.4"
|
||||
def room_version = "2.5.0"
|
||||
implementation "androidx.room:room-runtime:$room_version"
|
||||
kapt "androidx.room:room-compiler:$room_version"
|
||||
implementation "androidx.room:room-ktx:$room_version"
|
||||
implementation "androidx.room:room-rxjava2:$room_version"
|
||||
implementation "com.squareup.moshi:moshi:1.9.2"
|
||||
kapt "com.squareup.moshi:moshi-kotlin-codegen:1.9.2"
|
||||
implementation "com.squareup.moshi:moshi:1.14.0"
|
||||
kapt "com.squareup.moshi:moshi-kotlin-codegen:1.14.0"
|
||||
}
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<uses-permission android:name="android.permission.HIGH_SAMPLING_RATE_SENSORS" />
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
|
@ -27,7 +29,8 @@
|
|||
</provider>
|
||||
|
||||
<activity android:name=".main.MainActivity"
|
||||
android:configChanges="keyboard|keyboardHidden|orientation|screenSize">
|
||||
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
|
|
|
@ -110,9 +110,9 @@ JNIEXPORT jstring JNICALL JNI_FCN(quitReasonToString)(JNIEnv *env, jobject obj,
|
|||
return E->NewStringUTF(env, chiaki_quit_reason_string((ChiakiQuitReason)value));
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL JNI_FCN(quitReasonIsStopped)(JNIEnv *env, jobject obj, jint value)
|
||||
JNIEXPORT jboolean JNICALL JNI_FCN(quitReasonIsError)(JNIEnv *env, jobject obj, jint value)
|
||||
{
|
||||
return value == CHIAKI_QUIT_REASON_STOPPED;
|
||||
return chiaki_quit_reason_is_error(value);
|
||||
}
|
||||
|
||||
JNIEXPORT jobject JNICALL JNI_FCN(videoProfilePreset)(JNIEnv *env, jobject obj, jint resolution_preset, jint fps_preset, jobject codec)
|
||||
|
@ -133,6 +133,7 @@ typedef struct android_chiaki_session_t
|
|||
jmethodID java_session_event_connected_meth;
|
||||
jmethodID java_session_event_login_pin_request_meth;
|
||||
jmethodID java_session_event_quit_meth;
|
||||
jmethodID java_session_event_rumble_meth;
|
||||
jfieldID java_controller_state_buttons;
|
||||
jfieldID java_controller_state_l2_state;
|
||||
jfieldID java_controller_state_r2_state;
|
||||
|
@ -140,6 +141,20 @@ typedef struct android_chiaki_session_t
|
|||
jfieldID java_controller_state_left_y;
|
||||
jfieldID java_controller_state_right_x;
|
||||
jfieldID java_controller_state_right_y;
|
||||
jfieldID java_controller_state_touches;
|
||||
jfieldID java_controller_state_gyro_x;
|
||||
jfieldID java_controller_state_gyro_y;
|
||||
jfieldID java_controller_state_gyro_z;
|
||||
jfieldID java_controller_state_accel_x;
|
||||
jfieldID java_controller_state_accel_y;
|
||||
jfieldID java_controller_state_accel_z;
|
||||
jfieldID java_controller_state_orient_x;
|
||||
jfieldID java_controller_state_orient_y;
|
||||
jfieldID java_controller_state_orient_z;
|
||||
jfieldID java_controller_state_orient_w;
|
||||
jfieldID java_controller_touch_x;
|
||||
jfieldID java_controller_touch_y;
|
||||
jfieldID java_controller_touch_id;
|
||||
|
||||
AndroidChiakiVideoDecoder video_decoder;
|
||||
AndroidChiakiAudioDecoder audio_decoder;
|
||||
|
@ -178,6 +193,14 @@ static void android_chiaki_event_cb(ChiakiEvent *event, void *user)
|
|||
free(reason_str);
|
||||
break;
|
||||
}
|
||||
case CHIAKI_EVENT_RUMBLE:
|
||||
E->CallVoidMethod(env, session->java_session,
|
||||
session->java_session_event_rumble_meth,
|
||||
(jint)event->rumble.left,
|
||||
(jint)event->rumble.right);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
(*global_vm)->DetachCurrentThread(global_vm);
|
||||
|
@ -296,6 +319,7 @@ JNIEXPORT void JNICALL JNI_FCN(sessionCreate)(JNIEnv *env, jobject obj, jobject
|
|||
session->java_session_event_connected_meth = E->GetMethodID(env, session->java_session_class, "eventConnected", "()V");
|
||||
session->java_session_event_login_pin_request_meth = E->GetMethodID(env, session->java_session_class, "eventLoginPinRequest", "(Z)V");
|
||||
session->java_session_event_quit_meth = E->GetMethodID(env, session->java_session_class, "eventQuit", "(ILjava/lang/String;)V");
|
||||
session->java_session_event_rumble_meth = E->GetMethodID(env, session->java_session_class, "eventRumble", "(II)V");
|
||||
|
||||
jclass controller_state_class = E->FindClass(env, BASE_PACKAGE"/ControllerState");
|
||||
session->java_controller_state_buttons = E->GetFieldID(env, controller_state_class, "buttons", "I");
|
||||
|
@ -305,6 +329,22 @@ JNIEXPORT void JNICALL JNI_FCN(sessionCreate)(JNIEnv *env, jobject obj, jobject
|
|||
session->java_controller_state_left_y = E->GetFieldID(env, controller_state_class, "leftY", "S");
|
||||
session->java_controller_state_right_x = E->GetFieldID(env, controller_state_class, "rightX", "S");
|
||||
session->java_controller_state_right_y = E->GetFieldID(env, controller_state_class, "rightY", "S");
|
||||
session->java_controller_state_touches = E->GetFieldID(env, controller_state_class, "touches", "[L"BASE_PACKAGE"/ControllerTouch;");
|
||||
session->java_controller_state_gyro_x = E->GetFieldID(env, controller_state_class, "gyroX", "F");
|
||||
session->java_controller_state_gyro_y = E->GetFieldID(env, controller_state_class, "gyroY", "F");
|
||||
session->java_controller_state_gyro_z = E->GetFieldID(env, controller_state_class, "gyroZ", "F");
|
||||
session->java_controller_state_accel_x = E->GetFieldID(env, controller_state_class, "accelX", "F");
|
||||
session->java_controller_state_accel_y = E->GetFieldID(env, controller_state_class, "accelY", "F");
|
||||
session->java_controller_state_accel_z = E->GetFieldID(env, controller_state_class, "accelZ", "F");
|
||||
session->java_controller_state_orient_x = E->GetFieldID(env, controller_state_class, "orientX", "F");
|
||||
session->java_controller_state_orient_y = E->GetFieldID(env, controller_state_class, "orientY", "F");
|
||||
session->java_controller_state_orient_z = E->GetFieldID(env, controller_state_class, "orientZ", "F");
|
||||
session->java_controller_state_orient_w = E->GetFieldID(env, controller_state_class, "orientW", "F");
|
||||
|
||||
jclass controller_touch_class = E->FindClass(env, BASE_PACKAGE"/ControllerTouch");
|
||||
session->java_controller_touch_x = E->GetFieldID(env, controller_touch_class, "x", "S");
|
||||
session->java_controller_touch_y = E->GetFieldID(env, controller_touch_class, "y", "S");
|
||||
session->java_controller_touch_id = E->GetFieldID(env, controller_touch_class, "id", "B");
|
||||
|
||||
chiaki_session_set_event_cb(&session->session, android_chiaki_event_cb, session);
|
||||
chiaki_session_set_video_sample_cb(&session->session, android_chiaki_video_decoder_video_sample, &session->video_decoder);
|
||||
|
@ -373,7 +413,8 @@ JNIEXPORT void JNICALL JNI_FCN(sessionSetSurface)(JNIEnv *env, jobject obj, jlon
|
|||
JNIEXPORT void JNICALL JNI_FCN(sessionSetControllerState)(JNIEnv *env, jobject obj, jlong ptr, jobject controller_state_java)
|
||||
{
|
||||
AndroidChiakiSession *session = (AndroidChiakiSession *)ptr;
|
||||
ChiakiControllerState controller_state = { 0 };
|
||||
ChiakiControllerState controller_state;
|
||||
chiaki_controller_state_set_idle(&controller_state);
|
||||
controller_state.buttons = (uint32_t)E->GetIntField(env, controller_state_java, session->java_controller_state_buttons);
|
||||
controller_state.l2_state = (uint8_t)E->GetByteField(env, controller_state_java, session->java_controller_state_l2_state);
|
||||
controller_state.r2_state = (uint8_t)E->GetByteField(env, controller_state_java, session->java_controller_state_r2_state);
|
||||
|
@ -381,6 +422,34 @@ JNIEXPORT void JNICALL JNI_FCN(sessionSetControllerState)(JNIEnv *env, jobject o
|
|||
controller_state.left_y = (int16_t)E->GetShortField(env, controller_state_java, session->java_controller_state_left_y);
|
||||
controller_state.right_x = (int16_t)E->GetShortField(env, controller_state_java, session->java_controller_state_right_x);
|
||||
controller_state.right_y = (int16_t)E->GetShortField(env, controller_state_java, session->java_controller_state_right_y);
|
||||
jobjectArray touch_array = E->GetObjectField(env, controller_state_java, session->java_controller_state_touches);
|
||||
size_t touch_array_len = (size_t)E->GetArrayLength(env, touch_array);
|
||||
for(size_t i = 0; i < CHIAKI_CONTROLLER_TOUCHES_MAX; i++)
|
||||
{
|
||||
if(i < touch_array_len)
|
||||
{
|
||||
jobject touch = E->GetObjectArrayElement(env, touch_array, i);
|
||||
controller_state.touches[i].x = (uint16_t)E->GetShortField(env, touch, session->java_controller_touch_x);
|
||||
controller_state.touches[i].y = (uint16_t)E->GetShortField(env, touch, session->java_controller_touch_y);
|
||||
controller_state.touches[i].id = (int8_t)E->GetByteField(env, touch, session->java_controller_touch_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
controller_state.touches[i].x = 0;
|
||||
controller_state.touches[i].y = 0;
|
||||
controller_state.touches[i].id = -1;
|
||||
}
|
||||
}
|
||||
controller_state.gyro_x = E->GetFloatField(env, controller_state_java, session->java_controller_state_gyro_x);
|
||||
controller_state.gyro_y = E->GetFloatField(env, controller_state_java, session->java_controller_state_gyro_y);
|
||||
controller_state.gyro_z = E->GetFloatField(env, controller_state_java, session->java_controller_state_gyro_z);
|
||||
controller_state.accel_x = E->GetFloatField(env, controller_state_java, session->java_controller_state_accel_x);
|
||||
controller_state.accel_y = E->GetFloatField(env, controller_state_java, session->java_controller_state_accel_y);
|
||||
controller_state.accel_z = E->GetFloatField(env, controller_state_java, session->java_controller_state_accel_z);
|
||||
controller_state.orient_x = E->GetFloatField(env, controller_state_java, session->java_controller_state_orient_x);
|
||||
controller_state.orient_y = E->GetFloatField(env, controller_state_java, session->java_controller_state_orient_y);
|
||||
controller_state.orient_z = E->GetFloatField(env, controller_state_java, session->java_controller_state_orient_z);
|
||||
controller_state.orient_w = E->GetFloatField(env, controller_state_java, session->java_controller_state_orient_w);
|
||||
chiaki_session_set_controller_state(&session->session, &controller_state);
|
||||
}
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 0ab5b12a5bc3630a3d6c83b20eed2a669ebf7a24
|
||||
Subproject commit 8740d0fc321a55489dbbf6067298201b7d2e106d
|
|
@ -26,29 +26,34 @@ ChiakiErrorCode android_chiaki_video_decoder_init(AndroidChiakiVideoDecoder *dec
|
|||
return chiaki_mutex_init(&decoder->codec_mutex, false);
|
||||
}
|
||||
|
||||
static void kill_decoder(AndroidChiakiVideoDecoder *decoder)
|
||||
{
|
||||
chiaki_mutex_lock(&decoder->codec_mutex);
|
||||
decoder->shutdown_output = true;
|
||||
ssize_t codec_buf_index = AMediaCodec_dequeueInputBuffer(decoder->codec, 1000);
|
||||
if(codec_buf_index >= 0)
|
||||
{
|
||||
CHIAKI_LOGI(decoder->log, "Video Decoder sending EOS buffer");
|
||||
AMediaCodec_queueInputBuffer(decoder->codec, (size_t)codec_buf_index, 0, 0, decoder->timestamp_cur++, AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM);
|
||||
AMediaCodec_stop(decoder->codec);
|
||||
chiaki_mutex_unlock(&decoder->codec_mutex);
|
||||
chiaki_thread_join(&decoder->output_thread, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
CHIAKI_LOGE(decoder->log, "Failed to get input buffer for shutting down Video Decoder!");
|
||||
AMediaCodec_stop(decoder->codec);
|
||||
chiaki_mutex_unlock(&decoder->codec_mutex);
|
||||
}
|
||||
AMediaCodec_delete(decoder->codec);
|
||||
decoder->codec = NULL;
|
||||
decoder->shutdown_output = false;
|
||||
}
|
||||
|
||||
void android_chiaki_video_decoder_fini(AndroidChiakiVideoDecoder *decoder)
|
||||
{
|
||||
if(decoder->codec)
|
||||
{
|
||||
chiaki_mutex_lock(&decoder->codec_mutex);
|
||||
decoder->shutdown_output = true;
|
||||
ssize_t codec_buf_index = AMediaCodec_dequeueInputBuffer(decoder->codec, -1);
|
||||
if(codec_buf_index >= 0)
|
||||
{
|
||||
CHIAKI_LOGI(decoder->log, "Video Decoder sending EOS buffer");
|
||||
AMediaCodec_queueInputBuffer(decoder->codec, (size_t)codec_buf_index, 0, 0, decoder->timestamp_cur++, AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM);
|
||||
AMediaCodec_stop(decoder->codec);
|
||||
chiaki_mutex_unlock(&decoder->codec_mutex);
|
||||
chiaki_thread_join(&decoder->output_thread, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
CHIAKI_LOGE(decoder->log, "Failed to get input buffer for shutting down Video Decoder!");
|
||||
AMediaCodec_stop(decoder->codec);
|
||||
chiaki_mutex_unlock(&decoder->codec_mutex);
|
||||
}
|
||||
AMediaCodec_delete(decoder->codec);
|
||||
}
|
||||
kill_decoder(decoder);
|
||||
chiaki_mutex_fini(&decoder->codec_mutex);
|
||||
}
|
||||
|
||||
|
@ -56,6 +61,16 @@ void android_chiaki_video_decoder_set_surface(AndroidChiakiVideoDecoder *decoder
|
|||
{
|
||||
chiaki_mutex_lock(&decoder->codec_mutex);
|
||||
|
||||
if(!surface)
|
||||
{
|
||||
if(decoder->codec)
|
||||
{
|
||||
kill_decoder(decoder);
|
||||
CHIAKI_LOGI(decoder->log, "Decoder shut down after surface was removed");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if(decoder->codec)
|
||||
{
|
||||
#if __ANDROID_API__ >= 23
|
||||
|
|
|
@ -23,9 +23,11 @@ val MIGRATION_1_2 = object : Migration(1, 2)
|
|||
{
|
||||
override fun migrate(database: SupportSQLiteDatabase)
|
||||
{
|
||||
database.execSQL("ALTER TABLE registered_host RENAME ps4_mac TO server_mac")
|
||||
database.execSQL("ALTER TABLE registered_host RENAME ps4_nickname TO server_nickname")
|
||||
database.execSQL("ALTER TABLE registered_host ADD target INTEGER NOT NULL DEFAULT 1000")
|
||||
database.execSQL("CREATE TABLE `new_registered_host` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `target` INTEGER NOT NULL, `ap_ssid` TEXT, `ap_bssid` TEXT, `ap_key` TEXT, `ap_name` TEXT, `server_mac` INTEGER NOT NULL, `server_nickname` TEXT, `rp_regist_key` BLOB NOT NULL, `rp_key_type` INTEGER NOT NULL, `rp_key` BLOB NOT NULL)");
|
||||
database.execSQL("INSERT INTO `new_registered_host` SELECT `id`, `target`, `ap_ssid`, `ap_bssid`, `ap_key`, `ap_name`, `ps4_mac`, `ps4_nickname`, `rp_regist_key`, `rp_key_type`, `rp_key` FROM `registered_host`")
|
||||
database.execSQL("DROP TABLE registered_host")
|
||||
database.execSQL("ALTER TABLE new_registered_host RENAME TO registered_host")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
package com.metallic.chiaki.common
|
||||
|
||||
import androidx.room.*
|
||||
import androidx.room.ForeignKey.SET_NULL
|
||||
import androidx.room.ForeignKey.Companion.SET_NULL
|
||||
import io.reactivex.Completable
|
||||
import io.reactivex.Flowable
|
||||
import io.reactivex.Single
|
||||
|
|
|
@ -68,11 +68,26 @@ class Preferences(context: Context)
|
|||
get() = sharedPreferences.getBoolean(onScreenControlsEnabledKey, true)
|
||||
set(value) { sharedPreferences.edit().putBoolean(onScreenControlsEnabledKey, value).apply() }
|
||||
|
||||
val touchpadOnlyEnabledKey get() = resources.getString(R.string.preferences_touchpad_only_key)
|
||||
val touchpadOnlyEnabledKey get() = resources.getString(R.string.preferences_touchpad_only_enabled_key)
|
||||
var touchpadOnlyEnabled
|
||||
get() = sharedPreferences.getBoolean(touchpadOnlyEnabledKey, false)
|
||||
set(value) { sharedPreferences.edit().putBoolean(touchpadOnlyEnabledKey, value).apply() }
|
||||
|
||||
val rumbleEnabledKey get() = resources.getString(R.string.preferences_rumble_enabled_key)
|
||||
var rumbleEnabled
|
||||
get() = sharedPreferences.getBoolean(rumbleEnabledKey, true)
|
||||
set(value) { sharedPreferences.edit().putBoolean(rumbleEnabledKey, value).apply() }
|
||||
|
||||
val motionEnabledKey get() = resources.getString(R.string.preferences_motion_enabled_key)
|
||||
var motionEnabled
|
||||
get() = sharedPreferences.getBoolean(motionEnabledKey, true)
|
||||
set(value) { sharedPreferences.edit().putBoolean(motionEnabledKey, value).apply() }
|
||||
|
||||
val buttonHapticEnabledKey get() = resources.getString(R.string.preferences_button_haptic_enabled_key)
|
||||
var buttonHapticEnabled
|
||||
get() = sharedPreferences.getBoolean(buttonHapticEnabledKey, true)
|
||||
set(value) { sharedPreferences.edit().putBoolean(buttonHapticEnabledKey, value).apply() }
|
||||
|
||||
val logVerboseKey get() = resources.getString(R.string.preferences_log_verbose_key)
|
||||
var logVerbose
|
||||
get() = sharedPreferences.getBoolean(logVerboseKey, false)
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
package com.metallic.chiaki.common
|
||||
|
||||
import androidx.room.*
|
||||
import androidx.room.ColumnInfo.BLOB
|
||||
import androidx.room.ColumnInfo.Companion.BLOB
|
||||
import com.metallic.chiaki.lib.RegistHost
|
||||
import com.metallic.chiaki.lib.Target
|
||||
import io.reactivex.Completable
|
||||
|
|
|
@ -25,6 +25,8 @@ import io.reactivex.rxkotlin.addTo
|
|||
import io.reactivex.schedulers.Schedulers
|
||||
import okio.Buffer
|
||||
import okio.Okio
|
||||
import okio.buffer
|
||||
import okio.source
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
|
||||
|
@ -164,7 +166,7 @@ fun importSettingsFromUri(activity: Activity, uri: Uri, disposable: CompositeDis
|
|||
try
|
||||
{
|
||||
val inputStream = activity.contentResolver.openInputStream(uri) ?: throw IOException()
|
||||
val buffer = Okio.buffer(Okio.source(inputStream))
|
||||
val buffer = inputStream.source().buffer()
|
||||
val reader = JsonReader.of(buffer)
|
||||
val adapter = moshi().serializedSettingsAdapter()
|
||||
|
||||
|
|
|
@ -3,8 +3,7 @@ package com.metallic.chiaki.lib
|
|||
import android.os.Parcelable
|
||||
import android.util.Log
|
||||
import android.view.Surface
|
||||
import kotlinx.android.parcel.IgnoredOnParcel
|
||||
import kotlinx.android.parcel.Parcelize
|
||||
import kotlinx.parcelize.Parcelize
|
||||
import java.lang.Exception
|
||||
import java.net.InetSocketAddress
|
||||
import kotlin.math.abs
|
||||
|
@ -84,14 +83,14 @@ private class ChiakiNative
|
|||
}
|
||||
@JvmStatic external fun errorCodeToString(value: Int): String
|
||||
@JvmStatic external fun quitReasonToString(value: Int): String
|
||||
@JvmStatic external fun quitReasonIsStopped(value: Int): Boolean
|
||||
@JvmStatic external fun quitReasonIsError(value: Int): Boolean
|
||||
@JvmStatic external fun videoProfilePreset(resolutionPreset: Int, fpsPreset: Int, codec: Codec): ConnectVideoProfile
|
||||
@JvmStatic external fun sessionCreate(result: CreateResult, connectInfo: ConnectInfo, logFile: String?, logVerbose: Boolean, javaSession: Session)
|
||||
@JvmStatic external fun sessionFree(ptr: Long)
|
||||
@JvmStatic external fun sessionStart(ptr: Long): Int
|
||||
@JvmStatic external fun sessionStop(ptr: Long): Int
|
||||
@JvmStatic external fun sessionJoin(ptr: Long): Int
|
||||
@JvmStatic external fun sessionSetSurface(ptr: Long, surface: Surface)
|
||||
@JvmStatic external fun sessionSetSurface(ptr: Long, surface: Surface?)
|
||||
@JvmStatic external fun sessionSetControllerState(ptr: Long, controllerState: ControllerState)
|
||||
@JvmStatic external fun sessionSetLoginPin(ptr: Long, pin: String)
|
||||
@JvmStatic external fun discoveryServiceCreate(result: CreateResult, options: DiscoveryServiceOptions, javaService: DiscoveryService)
|
||||
|
@ -150,6 +149,14 @@ class ChiakiLog(val levelMask: Int, val callback: (level: Int, text: String) ->
|
|||
|
||||
private fun maxAbs(a: Short, b: Short) = if(abs(a.toInt()) > abs(b.toInt())) a else b
|
||||
|
||||
private val CONTROLLER_TOUCHES_MAX = 2 // must be the same as CHIAKI_CONTROLLER_TOUCHES_MAX
|
||||
|
||||
data class ControllerTouch(
|
||||
var x: UShort = 0U,
|
||||
var y: UShort = 0U,
|
||||
var id: Byte = -1 // -1 = up
|
||||
)
|
||||
|
||||
data class ControllerState constructor(
|
||||
var buttons: UInt = 0U,
|
||||
var l2State: UByte = 0U,
|
||||
|
@ -157,26 +164,40 @@ data class ControllerState constructor(
|
|||
var leftX: Short = 0,
|
||||
var leftY: Short = 0,
|
||||
var rightX: Short = 0,
|
||||
var rightY: Short = 0
|
||||
var rightY: Short = 0,
|
||||
private var touchIdNext: UByte = 0U,
|
||||
var touches: Array<ControllerTouch> = arrayOf(ControllerTouch(), ControllerTouch()),
|
||||
var gyroX: Float = 0.0f,
|
||||
var gyroY: Float = 0.0f,
|
||||
var gyroZ: Float = 0.0f,
|
||||
var accelX: Float = 0.0f,
|
||||
var accelY: Float = 1.0f,
|
||||
var accelZ: Float = 0.0f,
|
||||
var orientX: Float = 0.0f,
|
||||
var orientY: Float = 0.0f,
|
||||
var orientZ: Float = 0.0f,
|
||||
var orientW: Float = 1.0f
|
||||
){
|
||||
companion object
|
||||
{
|
||||
val BUTTON_CROSS = (1 shl 0).toUInt()
|
||||
val BUTTON_MOON = (1 shl 1).toUInt()
|
||||
val BUTTON_BOX = (1 shl 2).toUInt()
|
||||
val BUTTON_PYRAMID = (1 shl 3).toUInt()
|
||||
val BUTTON_BOX = (1 shl 2).toUInt()
|
||||
val BUTTON_PYRAMID = (1 shl 3).toUInt()
|
||||
val BUTTON_DPAD_LEFT = (1 shl 4).toUInt()
|
||||
val BUTTON_DPAD_RIGHT = (1 shl 5).toUInt()
|
||||
val BUTTON_DPAD_UP = (1 shl 6).toUInt()
|
||||
val BUTTON_DPAD_UP = (1 shl 6).toUInt()
|
||||
val BUTTON_DPAD_DOWN = (1 shl 7).toUInt()
|
||||
val BUTTON_L1 = (1 shl 8).toUInt()
|
||||
val BUTTON_R1 = (1 shl 9).toUInt()
|
||||
val BUTTON_L1 = (1 shl 8).toUInt()
|
||||
val BUTTON_R1 = (1 shl 9).toUInt()
|
||||
val BUTTON_L3 = (1 shl 10).toUInt()
|
||||
val BUTTON_R3 = (1 shl 11).toUInt()
|
||||
val BUTTON_OPTIONS = (1 shl 12).toUInt()
|
||||
val BUTTON_OPTIONS = (1 shl 12).toUInt()
|
||||
val BUTTON_SHARE = (1 shl 13).toUInt()
|
||||
val BUTTON_TOUCHPAD = (1 shl 14).toUInt()
|
||||
val BUTTON_TOUCHPAD = (1 shl 14).toUInt()
|
||||
val BUTTON_PS = (1 shl 15).toUInt()
|
||||
val TOUCHPAD_WIDTH: UShort = 1920U
|
||||
val TOUCHPAD_HEIGHT: UShort = 942U
|
||||
}
|
||||
|
||||
infix fun or(o: ControllerState) = ControllerState(
|
||||
|
@ -186,24 +207,116 @@ data class ControllerState constructor(
|
|||
leftX = maxAbs(leftX, o.leftX),
|
||||
leftY = maxAbs(leftY, o.leftY),
|
||||
rightX = maxAbs(rightX, o.rightX),
|
||||
rightY = maxAbs(rightY, o.rightY)
|
||||
rightY = maxAbs(rightY, o.rightY),
|
||||
touches = touches.zip(o.touches) { a, b -> if(a.id >= 0) a else b }.toTypedArray(),
|
||||
gyroX = gyroX,
|
||||
gyroY = gyroY,
|
||||
gyroZ = gyroZ,
|
||||
accelX = accelX,
|
||||
accelY = accelY,
|
||||
accelZ = accelZ,
|
||||
orientX = orientX,
|
||||
orientY = orientY,
|
||||
orientZ = orientZ,
|
||||
orientW = orientW
|
||||
)
|
||||
|
||||
override fun equals(other: Any?): Boolean
|
||||
{
|
||||
if(this === other) return true
|
||||
if(javaClass != other?.javaClass) return false
|
||||
|
||||
other as ControllerState
|
||||
|
||||
if(buttons != other.buttons) return false
|
||||
if(l2State != other.l2State) return false
|
||||
if(r2State != other.r2State) return false
|
||||
if(leftX != other.leftX) return false
|
||||
if(leftY != other.leftY) return false
|
||||
if(rightX != other.rightX) return false
|
||||
if(rightY != other.rightY) return false
|
||||
if(touchIdNext != other.touchIdNext) return false
|
||||
if(!touches.contentEquals(other.touches)) return false
|
||||
if(gyroX != other.gyroX) return false
|
||||
if(gyroY != other.gyroY) return false
|
||||
if(gyroZ != other.gyroZ) return false
|
||||
if(accelX != other.accelX) return false
|
||||
if(accelY != other.accelY) return false
|
||||
if(accelZ != other.accelZ) return false
|
||||
if(orientX != other.orientX) return false
|
||||
if(orientY != other.orientY) return false
|
||||
if(orientZ != other.orientZ) return false
|
||||
if(orientW != other.orientW) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int
|
||||
{
|
||||
var result = buttons.hashCode()
|
||||
result = 31 * result + l2State.hashCode()
|
||||
result = 31 * result + r2State.hashCode()
|
||||
result = 31 * result + leftX
|
||||
result = 31 * result + leftY
|
||||
result = 31 * result + rightX
|
||||
result = 31 * result + rightY
|
||||
result = 31 * result + touchIdNext.hashCode()
|
||||
result = 31 * result + touches.contentHashCode()
|
||||
result = 31 * result + gyroX.hashCode()
|
||||
result = 31 * result + gyroY.hashCode()
|
||||
result = 31 * result + gyroZ.hashCode()
|
||||
result = 31 * result + accelX.hashCode()
|
||||
result = 31 * result + accelY.hashCode()
|
||||
result = 31 * result + accelZ.hashCode()
|
||||
result = 31 * result + orientX.hashCode()
|
||||
result = 31 * result + orientY.hashCode()
|
||||
result = 31 * result + orientZ.hashCode()
|
||||
result = 31 * result + orientW.hashCode()
|
||||
return result
|
||||
}
|
||||
|
||||
fun startTouch(x: UShort, y: UShort): UByte? =
|
||||
touches
|
||||
.find { it.id < 0 }
|
||||
?.also {
|
||||
it.id = touchIdNext.toByte()
|
||||
it.x = x
|
||||
it.y = y
|
||||
touchIdNext = ((touchIdNext + 1U) and 0x7fU).toUByte()
|
||||
}?.id?.toUByte()
|
||||
|
||||
fun stopTouch(id: UByte)
|
||||
{
|
||||
touches.find {
|
||||
it.id >= 0 && it.id == id.toByte()
|
||||
}?.let {
|
||||
it.id = -1
|
||||
}
|
||||
}
|
||||
|
||||
fun setTouchPos(id: UByte, x: UShort, y: UShort): Boolean
|
||||
= touches.find {
|
||||
it.id >= 0 && it.id == id.toByte()
|
||||
}?.let {
|
||||
val r = it.x != x || it.y != y
|
||||
it.x = x
|
||||
it.y = y
|
||||
r
|
||||
} ?: false
|
||||
}
|
||||
|
||||
class QuitReason(val value: Int)
|
||||
{
|
||||
override fun toString() = ChiakiNative.quitReasonToString(value)
|
||||
|
||||
/**
|
||||
* whether the reason is CHIAKI_QUIT_REASON_STOPPED
|
||||
*/
|
||||
val isStopped = ChiakiNative.quitReasonIsStopped(value)
|
||||
val isError = ChiakiNative.quitReasonIsError(value)
|
||||
}
|
||||
|
||||
sealed class Event
|
||||
object ConnectedEvent: Event()
|
||||
data class LoginPinRequestEvent(val pinIncorrect: Boolean): Event()
|
||||
data class QuitEvent(val reason: QuitReason, val reasonString: String?): Event()
|
||||
data class RumbleEvent(val left: UByte, val right: UByte): Event()
|
||||
|
||||
class CreateError(val errorCode: ErrorCode): Exception("Failed to create a native object: $errorCode")
|
||||
|
||||
|
@ -259,7 +372,12 @@ class Session(connectInfo: ConnectInfo, logFile: String?, logVerbose: Boolean)
|
|||
event(QuitEvent(QuitReason(reasonValue), reasonString))
|
||||
}
|
||||
|
||||
fun setSurface(surface: Surface)
|
||||
private fun eventRumble(left: Int, right: Int)
|
||||
{
|
||||
event(RumbleEvent(left.toUByte(), right.toUByte()))
|
||||
}
|
||||
|
||||
fun setSurface(surface: Surface?)
|
||||
{
|
||||
ChiakiNative.sessionSetSurface(nativePtr, surface)
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
package com.metallic.chiaki.main
|
||||
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.animation.AnimationUtils
|
||||
|
@ -16,8 +17,8 @@ import com.metallic.chiaki.common.DiscoveredDisplayHost
|
|||
import com.metallic.chiaki.common.DisplayHost
|
||||
import com.metallic.chiaki.common.ManualDisplayHost
|
||||
import com.metallic.chiaki.common.ext.inflate
|
||||
import com.metallic.chiaki.databinding.ItemDisplayHostBinding
|
||||
import com.metallic.chiaki.lib.DiscoveryHost
|
||||
import kotlinx.android.synthetic.main.item_display_host.view.*
|
||||
|
||||
class DisplayHostDiffCallback(val old: List<DisplayHost>, val new: List<DisplayHost>): DiffUtil.Callback()
|
||||
{
|
||||
|
@ -42,10 +43,10 @@ class DisplayHostRecyclerViewAdapter(
|
|||
diff.dispatchUpdatesTo(this)
|
||||
}
|
||||
|
||||
class ViewHolder(itemView: View): RecyclerView.ViewHolder(itemView)
|
||||
class ViewHolder(val binding: ItemDisplayHostBinding): RecyclerView.ViewHolder(binding.root)
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int)
|
||||
= ViewHolder(parent.inflate(R.layout.item_display_host))
|
||||
= ViewHolder(ItemDisplayHostBinding.inflate(LayoutInflater.from(parent.context), parent, false))
|
||||
|
||||
override fun getItemCount() = hosts.count()
|
||||
|
||||
|
@ -53,7 +54,7 @@ class DisplayHostRecyclerViewAdapter(
|
|||
{
|
||||
val context = holder.itemView.context
|
||||
val host = hosts[position]
|
||||
holder.itemView.also {
|
||||
holder.binding.also {
|
||||
it.nameTextView.text = host.name
|
||||
it.hostTextView.text = context.getString(R.string.display_host_host, host.host)
|
||||
val id = host.id
|
||||
|
@ -87,7 +88,7 @@ class DisplayHostRecyclerViewAdapter(
|
|||
else -> R.drawable.ic_console
|
||||
}
|
||||
)
|
||||
it.setOnClickListener { clickCallback(host) }
|
||||
it.root.setOnClickListener { clickCallback(host) }
|
||||
|
||||
val canWakeup = host.registeredHost != null
|
||||
val canEditDelete = host is ManualDisplayHost
|
||||
|
|
|
@ -17,52 +17,54 @@ import com.metallic.chiaki.R
|
|||
import com.metallic.chiaki.common.*
|
||||
import com.metallic.chiaki.common.ext.putRevealExtra
|
||||
import com.metallic.chiaki.common.ext.viewModelFactory
|
||||
import com.metallic.chiaki.databinding.ActivityMainBinding
|
||||
import com.metallic.chiaki.lib.ConnectInfo
|
||||
import com.metallic.chiaki.lib.DiscoveryHost
|
||||
import com.metallic.chiaki.manualconsole.EditManualConsoleActivity
|
||||
import com.metallic.chiaki.regist.RegistActivity
|
||||
import com.metallic.chiaki.settings.SettingsActivity
|
||||
import com.metallic.chiaki.stream.StreamActivity
|
||||
import kotlinx.android.synthetic.main.activity_main.*
|
||||
|
||||
class MainActivity : AppCompatActivity()
|
||||
{
|
||||
private lateinit var viewModel: MainViewModel
|
||||
|
||||
private lateinit var binding: ActivityMainBinding
|
||||
private var discoveryMenuItem: MenuItem? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?)
|
||||
{
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_main)
|
||||
binding = ActivityMainBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
title = ""
|
||||
setSupportActionBar(toolbar)
|
||||
setSupportActionBar(binding.toolbar)
|
||||
|
||||
floatingActionButton.setOnClickListener {
|
||||
expandFloatingActionButton(!floatingActionButton.isExpanded)
|
||||
binding.floatingActionButton.setOnClickListener {
|
||||
expandFloatingActionButton(!binding.floatingActionButton.isExpanded)
|
||||
}
|
||||
floatingActionButtonDialBackground.setOnClickListener {
|
||||
binding.floatingActionButtonDialBackground.setOnClickListener {
|
||||
expandFloatingActionButton(false)
|
||||
}
|
||||
|
||||
addManualButton.setOnClickListener { addManualConsole() }
|
||||
addManualLabelButton.setOnClickListener { addManualConsole() }
|
||||
binding.addManualButton.setOnClickListener { addManualConsole() }
|
||||
binding.addManualLabelButton.setOnClickListener { addManualConsole() }
|
||||
|
||||
registerButton.setOnClickListener { showRegistration() }
|
||||
registerLabelButton.setOnClickListener { showRegistration() }
|
||||
binding.registerButton.setOnClickListener { showRegistration() }
|
||||
binding.registerLabelButton.setOnClickListener { showRegistration() }
|
||||
|
||||
viewModel = ViewModelProvider(this, viewModelFactory { MainViewModel(getDatabase(this), Preferences(this)) })
|
||||
.get(MainViewModel::class.java)
|
||||
|
||||
val recyclerViewAdapter = DisplayHostRecyclerViewAdapter(this::hostTriggered, this::wakeupHost, this::editHost, this::deleteHost)
|
||||
hostsRecyclerView.adapter = recyclerViewAdapter
|
||||
hostsRecyclerView.layoutManager = LinearLayoutManager(this)
|
||||
binding.hostsRecyclerView.adapter = recyclerViewAdapter
|
||||
binding.hostsRecyclerView.layoutManager = LinearLayoutManager(this)
|
||||
viewModel.displayHosts.observe(this, Observer {
|
||||
val top = hostsRecyclerView.computeVerticalScrollOffset() == 0
|
||||
val top = binding.hostsRecyclerView.computeVerticalScrollOffset() == 0
|
||||
recyclerViewAdapter.hosts = it
|
||||
if(top)
|
||||
hostsRecyclerView.scrollToPosition(0)
|
||||
binding.hostsRecyclerView.scrollToPosition(0)
|
||||
updateEmptyInfo()
|
||||
})
|
||||
|
||||
|
@ -76,19 +78,19 @@ class MainActivity : AppCompatActivity()
|
|||
{
|
||||
if(viewModel.displayHosts.value?.isEmpty() ?: true)
|
||||
{
|
||||
emptyInfoLayout.visibility = View.VISIBLE
|
||||
binding.emptyInfoLayout.visibility = View.VISIBLE
|
||||
val discoveryActive = viewModel.discoveryActive.value ?: false
|
||||
emptyInfoImageView.setImageResource(if(discoveryActive) R.drawable.ic_discover_on else R.drawable.ic_discover_off)
|
||||
emptyInfoTextView.setText(if(discoveryActive) R.string.display_hosts_empty_discovery_on_info else R.string.display_hosts_empty_discovery_off_info)
|
||||
binding.emptyInfoImageView.setImageResource(if(discoveryActive) R.drawable.ic_discover_on else R.drawable.ic_discover_off)
|
||||
binding.emptyInfoTextView.setText(if(discoveryActive) R.string.display_hosts_empty_discovery_on_info else R.string.display_hosts_empty_discovery_off_info)
|
||||
}
|
||||
else
|
||||
emptyInfoLayout.visibility = View.GONE
|
||||
binding.emptyInfoLayout.visibility = View.GONE
|
||||
}
|
||||
|
||||
private fun expandFloatingActionButton(expand: Boolean)
|
||||
{
|
||||
floatingActionButton.isExpanded = expand
|
||||
floatingActionButton.isActivated = floatingActionButton.isExpanded
|
||||
binding.floatingActionButton.isExpanded = expand
|
||||
binding.floatingActionButton.isActivated = binding.floatingActionButton.isExpanded
|
||||
}
|
||||
|
||||
override fun onStart()
|
||||
|
@ -105,7 +107,7 @@ class MainActivity : AppCompatActivity()
|
|||
|
||||
override fun onBackPressed()
|
||||
{
|
||||
if(floatingActionButton.isExpanded)
|
||||
if(binding.floatingActionButton.isExpanded)
|
||||
{
|
||||
expandFloatingActionButton(false)
|
||||
return
|
||||
|
@ -151,7 +153,7 @@ class MainActivity : AppCompatActivity()
|
|||
private fun addManualConsole()
|
||||
{
|
||||
Intent(this, EditManualConsoleActivity::class.java).also {
|
||||
it.putRevealExtra(addManualButton, rootLayout)
|
||||
it.putRevealExtra(binding.addManualButton, binding.rootLayout)
|
||||
startActivity(it, ActivityOptions.makeSceneTransitionAnimation(this).toBundle())
|
||||
}
|
||||
}
|
||||
|
@ -159,7 +161,7 @@ class MainActivity : AppCompatActivity()
|
|||
private fun showRegistration()
|
||||
{
|
||||
Intent(this, RegistActivity::class.java).also {
|
||||
it.putRevealExtra(registerButton, rootLayout)
|
||||
it.putRevealExtra(binding.registerButton, binding.rootLayout)
|
||||
startActivity(it, ActivityOptions.makeSceneTransitionAnimation(this).toBundle())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,10 +16,10 @@ import com.metallic.chiaki.common.RegisteredHost
|
|||
import com.metallic.chiaki.common.ext.RevealActivity
|
||||
import com.metallic.chiaki.common.ext.viewModelFactory
|
||||
import com.metallic.chiaki.common.getDatabase
|
||||
import com.metallic.chiaki.databinding.ActivityEditManualBinding
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import io.reactivex.rxkotlin.addTo
|
||||
import kotlinx.android.synthetic.main.activity_edit_manual.*
|
||||
|
||||
class EditManualConsoleActivity: AppCompatActivity(), RevealActivity
|
||||
{
|
||||
|
@ -28,18 +28,20 @@ class EditManualConsoleActivity: AppCompatActivity(), RevealActivity
|
|||
const val EXTRA_MANUAL_HOST_ID = "manual_host_id"
|
||||
}
|
||||
|
||||
override val revealIntent: Intent get() = intent
|
||||
override val revealRootLayout: View get() = rootLayout
|
||||
override val revealWindow: Window get() = window
|
||||
|
||||
private lateinit var viewModel: EditManualConsoleViewModel
|
||||
private lateinit var binding: ActivityEditManualBinding
|
||||
|
||||
override val revealIntent: Intent get() = intent
|
||||
override val revealRootLayout: View get() = binding.rootLayout
|
||||
override val revealWindow: Window get() = window
|
||||
|
||||
private val disposable = CompositeDisposable()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?)
|
||||
{
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_edit_manual)
|
||||
binding = ActivityEditManualBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
handleReveal()
|
||||
|
||||
viewModel = ViewModelProvider(this, viewModelFactory {
|
||||
|
@ -52,17 +54,17 @@ class EditManualConsoleActivity: AppCompatActivity(), RevealActivity
|
|||
.get(EditManualConsoleViewModel::class.java)
|
||||
|
||||
viewModel.existingHost?.observe(this, Observer {
|
||||
hostEditText.setText(it.host)
|
||||
binding.hostEditText.setText(it.host)
|
||||
})
|
||||
|
||||
viewModel.selectedRegisteredHost.observe(this, Observer {
|
||||
registeredHostTextView.setText(titleForRegisteredHost(it))
|
||||
binding.registeredHostTextView.setText(titleForRegisteredHost(it))
|
||||
})
|
||||
|
||||
viewModel.registeredHosts.observe(this, Observer { hosts ->
|
||||
registeredHostTextView.setAdapter(ArrayAdapter<String>(this, R.layout.dropdown_menu_popup_item,
|
||||
binding.registeredHostTextView.setAdapter(ArrayAdapter<String>(this, R.layout.dropdown_menu_popup_item,
|
||||
hosts.map { titleForRegisteredHost(it) }))
|
||||
registeredHostTextView.onItemClickListener = object: AdapterView.OnItemClickListener {
|
||||
binding.registeredHostTextView.onItemClickListener = object: AdapterView.OnItemClickListener {
|
||||
override fun onItemClick(parent: AdapterView<*>?, view: View?, position: Int, id: Long)
|
||||
{
|
||||
if(position >= hosts.size)
|
||||
|
@ -73,8 +75,7 @@ class EditManualConsoleActivity: AppCompatActivity(), RevealActivity
|
|||
}
|
||||
})
|
||||
|
||||
|
||||
saveButton.setOnClickListener { saveHost() }
|
||||
binding.saveButton.setOnClickListener { saveHost() }
|
||||
}
|
||||
|
||||
private fun titleForRegisteredHost(registeredHost: RegisteredHost?) =
|
||||
|
@ -85,14 +86,14 @@ class EditManualConsoleActivity: AppCompatActivity(), RevealActivity
|
|||
|
||||
private fun saveHost()
|
||||
{
|
||||
val host = hostEditText.text.toString().trim()
|
||||
val host = binding.hostEditText.text.toString().trim()
|
||||
if(host.isEmpty())
|
||||
{
|
||||
hostEditText.error = getString(R.string.entered_host_invalid)
|
||||
binding.hostEditText.error = getString(R.string.entered_host_invalid)
|
||||
return
|
||||
}
|
||||
|
||||
saveButton.isEnabled = false
|
||||
binding.saveButton.isEnabled = false
|
||||
viewModel.saveHost(host)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe {
|
||||
|
|
|
@ -12,9 +12,9 @@ import androidx.lifecycle.Observer
|
|||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.metallic.chiaki.R
|
||||
import com.metallic.chiaki.common.ext.RevealActivity
|
||||
import com.metallic.chiaki.databinding.ActivityRegistBinding
|
||||
import com.metallic.chiaki.lib.RegistInfo
|
||||
import com.metallic.chiaki.lib.Target
|
||||
import kotlinx.android.synthetic.main.activity_regist.*
|
||||
import java.lang.IllegalArgumentException
|
||||
|
||||
class RegistActivity: AppCompatActivity(), RevealActivity
|
||||
|
@ -30,33 +30,35 @@ class RegistActivity: AppCompatActivity(), RevealActivity
|
|||
private const val REQUEST_REGIST = 1
|
||||
}
|
||||
|
||||
private lateinit var viewModel: RegistViewModel
|
||||
private lateinit var binding: ActivityRegistBinding
|
||||
|
||||
override val revealWindow: Window get() = window
|
||||
override val revealIntent: Intent get() = intent
|
||||
override val revealRootLayout: View get() = rootLayout
|
||||
|
||||
private lateinit var viewModel: RegistViewModel
|
||||
override val revealRootLayout: View get() = binding.rootLayout
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?)
|
||||
{
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_regist)
|
||||
binding = ActivityRegistBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
handleReveal()
|
||||
|
||||
viewModel = ViewModelProvider(this).get(RegistViewModel::class.java)
|
||||
|
||||
hostEditText.setText(intent.getStringExtra(EXTRA_HOST) ?: "255.255.255.255")
|
||||
broadcastCheckBox.isChecked = intent.getBooleanExtra(EXTRA_BROADCAST, true)
|
||||
binding.hostEditText.setText(intent.getStringExtra(EXTRA_HOST) ?: "255.255.255.255")
|
||||
binding.broadcastCheckBox.isChecked = intent.getBooleanExtra(EXTRA_BROADCAST, true)
|
||||
|
||||
registButton.setOnClickListener { doRegist() }
|
||||
binding.registButton.setOnClickListener { doRegist() }
|
||||
|
||||
ps4VersionRadioGroup.check(when(viewModel.ps4Version.value ?: RegistViewModel.ConsoleVersion.PS5) {
|
||||
binding.ps4VersionRadioGroup.check(when(viewModel.ps4Version.value ?: RegistViewModel.ConsoleVersion.PS5) {
|
||||
RegistViewModel.ConsoleVersion.PS5 -> R.id.ps5RadioButton
|
||||
RegistViewModel.ConsoleVersion.PS4_GE_8 -> R.id.ps4VersionGE8RadioButton
|
||||
RegistViewModel.ConsoleVersion.PS4_GE_7 -> R.id.ps4VersionGE7RadioButton
|
||||
RegistViewModel.ConsoleVersion.PS4_LT_7 -> R.id.ps4VersionLT7RadioButton
|
||||
})
|
||||
|
||||
ps4VersionRadioGroup.setOnCheckedChangeListener { _, checkedId ->
|
||||
binding.ps4VersionRadioGroup.setOnCheckedChangeListener { _, checkedId ->
|
||||
viewModel.ps4Version.value = when(checkedId)
|
||||
{
|
||||
R.id.ps5RadioButton -> RegistViewModel.ConsoleVersion.PS5
|
||||
|
@ -68,14 +70,14 @@ class RegistActivity: AppCompatActivity(), RevealActivity
|
|||
}
|
||||
|
||||
viewModel.ps4Version.observe(this, Observer {
|
||||
psnAccountIdHelpGroup.visibility = if(it == RegistViewModel.ConsoleVersion.PS4_LT_7) View.GONE else View.VISIBLE
|
||||
psnIdTextInputLayout.hint = getString(when(it!!)
|
||||
binding.psnAccountIdHelpGroup.visibility = if(it == RegistViewModel.ConsoleVersion.PS4_LT_7) View.GONE else View.VISIBLE
|
||||
binding.psnIdTextInputLayout.hint = getString(when(it!!)
|
||||
{
|
||||
RegistViewModel.ConsoleVersion.PS4_LT_7 -> R.string.hint_regist_psn_online_id
|
||||
else -> R.string.hint_regist_psn_account_id
|
||||
})
|
||||
pinHelpBeforeTextView.setText(if(it.isPS5) R.string.regist_pin_instructions_ps5_before else R.string.regist_pin_instructions_ps4_before)
|
||||
pinHelpNavigationTextView.setText(if(it.isPS5) R.string.regist_pin_instructions_ps5_navigation else R.string.regist_pin_instructions_ps4_navigation)
|
||||
binding.pinHelpBeforeTextView.setText(if(it.isPS5) R.string.regist_pin_instructions_ps5_before else R.string.regist_pin_instructions_ps4_before)
|
||||
binding.pinHelpNavigationTextView.setText(if(it.isPS5) R.string.regist_pin_instructions_ps5_navigation else R.string.regist_pin_instructions_ps4_navigation)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -83,11 +85,11 @@ class RegistActivity: AppCompatActivity(), RevealActivity
|
|||
{
|
||||
val ps4Version = viewModel.ps4Version.value ?: RegistViewModel.ConsoleVersion.PS5
|
||||
|
||||
val host = hostEditText.text.toString().trim()
|
||||
val host = binding.hostEditText.text.toString().trim()
|
||||
val hostValid = host.isNotEmpty()
|
||||
val broadcast = broadcastCheckBox.isChecked
|
||||
val broadcast = binding.broadcastCheckBox.isChecked
|
||||
|
||||
val psnId = psnIdEditText.text.toString().trim()
|
||||
val psnId = binding.psnIdEditText.text.toString().trim()
|
||||
val psnOnlineId: String? = if(ps4Version == RegistViewModel.ConsoleVersion.PS4_LT_7) psnId else null
|
||||
val psnAccountId: ByteArray? =
|
||||
if(ps4Version != RegistViewModel.ConsoleVersion.PS4_LT_7)
|
||||
|
@ -101,11 +103,11 @@ class RegistActivity: AppCompatActivity(), RevealActivity
|
|||
}
|
||||
|
||||
|
||||
val pin = pinEditText.text.toString()
|
||||
val pin = binding.pinEditText.text.toString()
|
||||
val pinValid = pin.length == PIN_LENGTH
|
||||
|
||||
hostEditText.error = if(!hostValid) getString(R.string.entered_host_invalid) else null
|
||||
psnIdEditText.error =
|
||||
binding.hostEditText.error = if(!hostValid) getString(R.string.entered_host_invalid) else null
|
||||
binding.psnIdEditText.error =
|
||||
if(!psnIdValid)
|
||||
getString(when(ps4Version)
|
||||
{
|
||||
|
@ -114,7 +116,7 @@ class RegistActivity: AppCompatActivity(), RevealActivity
|
|||
})
|
||||
else
|
||||
null
|
||||
pinEditText.error = if(!pinValid) getString(R.string.regist_pin_invalid, PIN_LENGTH) else null
|
||||
binding.pinEditText.error = if(!pinValid) getString(R.string.regist_pin_invalid, PIN_LENGTH) else null
|
||||
|
||||
if(!hostValid || !psnIdValid || !pinValid)
|
||||
return
|
||||
|
|
|
@ -16,8 +16,8 @@ import com.metallic.chiaki.R
|
|||
import com.metallic.chiaki.common.MacAddress
|
||||
import com.metallic.chiaki.common.ext.viewModelFactory
|
||||
import com.metallic.chiaki.common.getDatabase
|
||||
import com.metallic.chiaki.databinding.ActivityRegistExecuteBinding
|
||||
import com.metallic.chiaki.lib.RegistInfo
|
||||
import kotlinx.android.synthetic.main.activity_regist_execute.*
|
||||
import kotlin.math.max
|
||||
|
||||
class RegistExecuteActivity: AppCompatActivity()
|
||||
|
@ -31,55 +31,57 @@ class RegistExecuteActivity: AppCompatActivity()
|
|||
}
|
||||
|
||||
private lateinit var viewModel: RegistExecuteViewModel
|
||||
private lateinit var binding: ActivityRegistExecuteBinding
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?)
|
||||
{
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_regist_execute)
|
||||
binding = ActivityRegistExecuteBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
viewModel = ViewModelProvider(this, viewModelFactory { RegistExecuteViewModel(getDatabase(this)) })
|
||||
.get(RegistExecuteViewModel::class.java)
|
||||
|
||||
logTextView.setHorizontallyScrolling(true)
|
||||
logTextView.movementMethod = ScrollingMovementMethod()
|
||||
binding.logTextView.setHorizontallyScrolling(true)
|
||||
binding.logTextView.movementMethod = ScrollingMovementMethod()
|
||||
viewModel.logText.observe(this, Observer {
|
||||
val textLayout = logTextView.layout ?: return@Observer
|
||||
val textLayout = binding.logTextView.layout ?: return@Observer
|
||||
val lineCount = textLayout.lineCount
|
||||
if(lineCount < 1)
|
||||
return@Observer
|
||||
logTextView.text = it
|
||||
val scrollY = textLayout.getLineBottom(lineCount - 1) - logTextView.height + logTextView.paddingTop + logTextView.paddingBottom
|
||||
logTextView.scrollTo(0, max(scrollY, 0))
|
||||
binding.logTextView.text = it
|
||||
val scrollY = textLayout.getLineBottom(lineCount - 1) - binding.logTextView.height + binding.logTextView.paddingTop + binding.logTextView.paddingBottom
|
||||
binding.logTextView.scrollTo(0, max(scrollY, 0))
|
||||
})
|
||||
|
||||
viewModel.state.observe(this, Observer {
|
||||
progressBar.visibility = if(it == RegistExecuteViewModel.State.RUNNING) View.VISIBLE else View.GONE
|
||||
binding.progressBar.visibility = if(it == RegistExecuteViewModel.State.RUNNING) View.VISIBLE else View.GONE
|
||||
when(it)
|
||||
{
|
||||
RegistExecuteViewModel.State.FAILED ->
|
||||
{
|
||||
infoTextView.visibility = View.VISIBLE
|
||||
infoTextView.setText(R.string.regist_info_failed)
|
||||
binding.infoTextView.visibility = View.VISIBLE
|
||||
binding.infoTextView.setText(R.string.regist_info_failed)
|
||||
setResult(RESULT_FAILED)
|
||||
}
|
||||
RegistExecuteViewModel.State.SUCCESSFUL, RegistExecuteViewModel.State.SUCCESSFUL_DUPLICATE ->
|
||||
{
|
||||
infoTextView.visibility = View.VISIBLE
|
||||
infoTextView.setText(R.string.regist_info_success)
|
||||
binding.infoTextView.visibility = View.VISIBLE
|
||||
binding.infoTextView.setText(R.string.regist_info_success)
|
||||
setResult(RESULT_OK)
|
||||
if(it == RegistExecuteViewModel.State.SUCCESSFUL_DUPLICATE)
|
||||
showDuplicateDialog()
|
||||
}
|
||||
RegistExecuteViewModel.State.STOPPED ->
|
||||
{
|
||||
infoTextView.visibility = View.GONE
|
||||
binding.infoTextView.visibility = View.GONE
|
||||
setResult(Activity.RESULT_CANCELED)
|
||||
}
|
||||
else -> infoTextView.visibility = View.GONE
|
||||
else -> binding.infoTextView.visibility = View.GONE
|
||||
}
|
||||
})
|
||||
|
||||
shareLogButton.setOnClickListener {
|
||||
binding.shareLogButton.setOnClickListener {
|
||||
val log = viewModel.logText.value ?: ""
|
||||
Intent(Intent.ACTION_SEND).also {
|
||||
it.type = "text/plain"
|
||||
|
|
|
@ -1,19 +1,37 @@
|
|||
package com.metallic.chiaki.session
|
||||
|
||||
import android.util.Log
|
||||
import android.view.InputDevice
|
||||
import android.view.KeyEvent
|
||||
import android.view.MotionEvent
|
||||
import android.content.Context
|
||||
import android.hardware.*
|
||||
import android.view.*
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.LifecycleObserver
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.OnLifecycleEvent
|
||||
import com.metallic.chiaki.common.Preferences
|
||||
import com.metallic.chiaki.lib.ControllerState
|
||||
|
||||
class StreamInput(val preferences: Preferences)
|
||||
class StreamInput(val context: Context, val preferences: Preferences)
|
||||
{
|
||||
var controllerStateChangedCallback: ((ControllerState) -> Unit)? = null
|
||||
|
||||
val controllerState: ControllerState get()
|
||||
{
|
||||
val controllerState = keyControllerState or motionControllerState
|
||||
val controllerState = sensorControllerState or keyControllerState or motionControllerState
|
||||
|
||||
val windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
|
||||
@Suppress("DEPRECATION")
|
||||
when(windowManager.defaultDisplay.rotation)
|
||||
{
|
||||
Surface.ROTATION_90 -> {
|
||||
controllerState.accelX *= -1.0f
|
||||
controllerState.accelZ *= -1.0f
|
||||
controllerState.gyroX *= -1.0f
|
||||
controllerState.gyroZ *= -1.0f
|
||||
controllerState.orientX *= -1.0f
|
||||
controllerState.orientZ *= -1.0f
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
|
||||
// prioritize motion controller's l2 and r2 over key
|
||||
// (some controllers send only key, others both but key earlier than full press)
|
||||
|
@ -25,6 +43,7 @@ class StreamInput(val preferences: Preferences)
|
|||
return controllerState or touchControllerState
|
||||
}
|
||||
|
||||
private val sensorControllerState = ControllerState() // from Motion Sensors
|
||||
private val keyControllerState = ControllerState() // from KeyEvents
|
||||
private val motionControllerState = ControllerState() // from MotionEvents
|
||||
var touchControllerState = ControllerState()
|
||||
|
@ -36,6 +55,66 @@ class StreamInput(val preferences: Preferences)
|
|||
|
||||
private val swapCrossMoon = preferences.swapCrossMoon
|
||||
|
||||
private val sensorEventListener = object: SensorEventListener {
|
||||
override fun onSensorChanged(event: SensorEvent)
|
||||
{
|
||||
when(event.sensor.type)
|
||||
{
|
||||
Sensor.TYPE_ACCELEROMETER -> {
|
||||
sensorControllerState.accelX = event.values[1] / SensorManager.GRAVITY_EARTH
|
||||
sensorControllerState.accelY = event.values[2] / SensorManager.GRAVITY_EARTH
|
||||
sensorControllerState.accelZ = event.values[0] / SensorManager.GRAVITY_EARTH
|
||||
}
|
||||
Sensor.TYPE_GYROSCOPE -> {
|
||||
sensorControllerState.gyroX = event.values[1]
|
||||
sensorControllerState.gyroY = event.values[2]
|
||||
sensorControllerState.gyroZ = event.values[0]
|
||||
}
|
||||
Sensor.TYPE_ROTATION_VECTOR -> {
|
||||
val q = floatArrayOf(0f, 0f, 0f, 0f)
|
||||
SensorManager.getQuaternionFromVector(q, event.values)
|
||||
sensorControllerState.orientX = q[2]
|
||||
sensorControllerState.orientY = q[3]
|
||||
sensorControllerState.orientZ = q[1]
|
||||
sensorControllerState.orientW = q[0]
|
||||
}
|
||||
else -> return
|
||||
}
|
||||
controllerStateUpdated()
|
||||
}
|
||||
|
||||
override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {}
|
||||
}
|
||||
|
||||
private val motionLifecycleObserver = object: LifecycleObserver {
|
||||
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
|
||||
fun onResume()
|
||||
{
|
||||
val samplingPeriodUs = 4000
|
||||
val sensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager
|
||||
listOfNotNull(
|
||||
sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
|
||||
sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE),
|
||||
sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR)
|
||||
).forEach {
|
||||
sensorManager.registerListener(sensorEventListener, it, samplingPeriodUs)
|
||||
}
|
||||
}
|
||||
|
||||
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
|
||||
fun onPause()
|
||||
{
|
||||
val sensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager
|
||||
sensorManager.unregisterListener(sensorEventListener)
|
||||
}
|
||||
}
|
||||
|
||||
fun observe(lifecycleOwner: LifecycleOwner)
|
||||
{
|
||||
if(preferences.motionEnabled)
|
||||
lifecycleOwner.lifecycle.addObserver(motionLifecycleObserver)
|
||||
}
|
||||
|
||||
private fun controllerStateUpdated()
|
||||
{
|
||||
controllerStateChangedCallback?.let { it(controllerState) }
|
||||
|
@ -98,7 +177,7 @@ class StreamInput(val preferences: Preferences)
|
|||
{
|
||||
if(event.source and InputDevice.SOURCE_CLASS_JOYSTICK != InputDevice.SOURCE_CLASS_JOYSTICK)
|
||||
return false
|
||||
fun Float.signedAxis() = (this * Short.MAX_VALUE).toShort()
|
||||
fun Float.signedAxis() = (this * Short.MAX_VALUE).toInt().toShort()
|
||||
fun Float.unsignedAxis() = (this * UByte.MAX_VALUE.toFloat()).toUInt().toUByte()
|
||||
motionControllerState.leftX = event.getAxisValue(MotionEvent.AXIS_X).signedAxis()
|
||||
motionControllerState.leftY = event.getAxisValue(MotionEvent.AXIS_Y).signedAxis()
|
||||
|
|
|
@ -25,8 +25,11 @@ class StreamSession(val connectInfo: ConnectInfo, val logManager: LogManager, va
|
|||
|
||||
private val _state = MutableLiveData<StreamState>(StreamStateIdle)
|
||||
val state: LiveData<StreamState> get() = _state
|
||||
private val _rumbleState = MutableLiveData<RumbleEvent>(RumbleEvent(0U, 0U))
|
||||
val rumbleState: LiveData<RumbleEvent> get() = _rumbleState
|
||||
|
||||
var surfaceTexture: SurfaceTexture? = null
|
||||
private var surfaceTexture: SurfaceTexture? = null
|
||||
private var surface: Surface? = null
|
||||
|
||||
init
|
||||
{
|
||||
|
@ -59,9 +62,9 @@ class StreamSession(val connectInfo: ConnectInfo, val logManager: LogManager, va
|
|||
_state.value = StreamStateConnecting
|
||||
session.eventCallback = this::eventCallback
|
||||
session.start()
|
||||
val surfaceTexture = surfaceTexture
|
||||
if(surfaceTexture != null)
|
||||
session.setSurface(Surface(surfaceTexture))
|
||||
val surface = surface
|
||||
if(surface != null)
|
||||
session.setSurface(surface)
|
||||
this.session = session
|
||||
}
|
||||
catch(e: CreateError)
|
||||
|
@ -86,9 +89,30 @@ class StreamSession(val connectInfo: ConnectInfo, val logManager: LogManager, va
|
|||
event.pinIncorrect
|
||||
)
|
||||
)
|
||||
is RumbleEvent -> _rumbleState.postValue(event)
|
||||
}
|
||||
}
|
||||
|
||||
fun attachToSurfaceView(surfaceView: SurfaceView)
|
||||
{
|
||||
surfaceView.holder.addCallback(object: SurfaceHolder.Callback {
|
||||
override fun surfaceCreated(holder: SurfaceHolder) { }
|
||||
|
||||
override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int)
|
||||
{
|
||||
val surface = holder.surface
|
||||
this@StreamSession.surface = surface
|
||||
session?.setSurface(surface)
|
||||
}
|
||||
|
||||
override fun surfaceDestroyed(holder: SurfaceHolder)
|
||||
{
|
||||
this@StreamSession.surface = null
|
||||
session?.setSurface(null)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun attachToTextureView(textureView: TextureView)
|
||||
{
|
||||
textureView.surfaceTextureListener = object: TextureView.SurfaceTextureListener {
|
||||
|
@ -97,6 +121,7 @@ class StreamSession(val connectInfo: ConnectInfo, val logManager: LogManager, va
|
|||
if(surfaceTexture != null)
|
||||
return
|
||||
surfaceTexture = surface
|
||||
this@StreamSession.surface = Surface(surfaceTexture)
|
||||
session?.setSurface(Surface(surface))
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ import androidx.fragment.app.Fragment
|
|||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceFragmentCompat
|
||||
import com.metallic.chiaki.R
|
||||
import kotlinx.android.synthetic.main.activity_settings.*
|
||||
import com.metallic.chiaki.databinding.ActivitySettingsBinding
|
||||
|
||||
interface TitleFragment
|
||||
{
|
||||
|
@ -18,20 +18,23 @@ interface TitleFragment
|
|||
|
||||
class SettingsActivity: AppCompatActivity(), PreferenceFragmentCompat.OnPreferenceStartFragmentCallback
|
||||
{
|
||||
private lateinit var binding: ActivitySettingsBinding
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?)
|
||||
{
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_settings)
|
||||
binding = ActivitySettingsBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
title = ""
|
||||
setSupportActionBar(toolbar)
|
||||
setSupportActionBar(binding.toolbar)
|
||||
|
||||
val rootFragment = SettingsFragment()
|
||||
replaceFragment(rootFragment, false)
|
||||
supportFragmentManager.addOnBackStackChangedListener {
|
||||
val titleFragment = supportFragmentManager.findFragmentById(R.id.settingsFragment) as? TitleFragment ?: return@addOnBackStackChangedListener
|
||||
titleTextView.text = titleFragment.getTitle(resources)
|
||||
binding.titleTextView.text = titleFragment.getTitle(resources)
|
||||
}
|
||||
titleTextView.text = rootFragment.getTitle(resources)
|
||||
binding.titleTextView.text = rootFragment.getTitle(resources)
|
||||
}
|
||||
|
||||
override fun onPreferenceStartFragment(caller: PreferenceFragmentCompat, pref: Preference) = when(pref.fragment)
|
||||
|
|
|
@ -16,7 +16,6 @@ import com.metallic.chiaki.common.exportAndShareAllSettings
|
|||
import com.metallic.chiaki.common.ext.viewModelFactory
|
||||
import com.metallic.chiaki.common.getDatabase
|
||||
import com.metallic.chiaki.common.importSettingsFromUri
|
||||
import com.metallic.chiaki.lib.Codec
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import io.reactivex.rxkotlin.addTo
|
||||
|
||||
|
@ -26,6 +25,9 @@ class DataStore(val preferences: Preferences): PreferenceDataStore()
|
|||
{
|
||||
preferences.logVerboseKey -> preferences.logVerbose
|
||||
preferences.swapCrossMoonKey -> preferences.swapCrossMoon
|
||||
preferences.rumbleEnabledKey -> preferences.rumbleEnabled
|
||||
preferences.motionEnabledKey -> preferences.motionEnabled
|
||||
preferences.buttonHapticEnabledKey -> preferences.buttonHapticEnabled
|
||||
else -> defValue
|
||||
}
|
||||
|
||||
|
@ -35,6 +37,9 @@ class DataStore(val preferences: Preferences): PreferenceDataStore()
|
|||
{
|
||||
preferences.logVerboseKey -> preferences.logVerbose = value
|
||||
preferences.swapCrossMoonKey -> preferences.swapCrossMoon = value
|
||||
preferences.rumbleEnabledKey -> preferences.rumbleEnabled = value
|
||||
preferences.motionEnabledKey -> preferences.motionEnabled = value
|
||||
preferences.buttonHapticEnabledKey -> preferences.buttonHapticEnabled = value
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,13 +2,13 @@
|
|||
|
||||
package com.metallic.chiaki.settings
|
||||
|
||||
import android.view.View
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.metallic.chiaki.R
|
||||
import com.metallic.chiaki.common.LogFile
|
||||
import com.metallic.chiaki.common.ext.inflate
|
||||
import kotlinx.android.synthetic.main.item_log_file.view.*
|
||||
import com.metallic.chiaki.databinding.ItemLogFileBinding
|
||||
import java.text.DateFormat
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
@ -20,7 +20,7 @@ class SettingsLogsAdapter: RecyclerView.Adapter<SettingsLogsAdapter.ViewHolder>(
|
|||
private val dateFormat: DateFormat = DateFormat.getDateInstance(DateFormat.SHORT)
|
||||
private val timeFormat = SimpleDateFormat("HH:mm:ss:SSS", Locale.getDefault())
|
||||
|
||||
class ViewHolder(itemView: View): RecyclerView.ViewHolder(itemView)
|
||||
class ViewHolder(val binding: ItemLogFileBinding): RecyclerView.ViewHolder(binding.root)
|
||||
|
||||
var logFiles: List<LogFile> = listOf()
|
||||
set(value)
|
||||
|
@ -29,16 +29,16 @@ class SettingsLogsAdapter: RecyclerView.Adapter<SettingsLogsAdapter.ViewHolder>(
|
|||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ViewHolder(parent.inflate(R.layout.item_log_file))
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
|
||||
ViewHolder(ItemLogFileBinding.inflate(LayoutInflater.from(parent.context), parent, false))
|
||||
|
||||
override fun getItemCount() = logFiles.size
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int)
|
||||
{
|
||||
val view = holder.itemView
|
||||
val logFile = logFiles[position]
|
||||
view.nameTextView.text = "${dateFormat.format(logFile.date)} ${timeFormat.format(logFile.date)}"
|
||||
view.summaryTextView.text = logFile.filename
|
||||
view.shareButton.setOnClickListener { shareCallback?.let { it(logFile) } }
|
||||
holder.binding.nameTextView.text = "${dateFormat.format(logFile.date)} ${timeFormat.format(logFile.date)}"
|
||||
holder.binding.summaryTextView.text = logFile.filename
|
||||
holder.binding.shareButton.setOnClickListener { shareCallback?.let { it(logFile) } }
|
||||
}
|
||||
}
|
|
@ -21,29 +21,35 @@ import com.metallic.chiaki.common.LogFile
|
|||
import com.metallic.chiaki.common.LogManager
|
||||
import com.metallic.chiaki.common.ext.viewModelFactory
|
||||
import com.metallic.chiaki.common.fileProviderAuthority
|
||||
import kotlinx.android.synthetic.main.fragment_settings_logs.*
|
||||
import com.metallic.chiaki.databinding.FragmentSettingsLogsBinding
|
||||
|
||||
class SettingsLogsFragment: AppCompatDialogFragment(), TitleFragment
|
||||
{
|
||||
private lateinit var viewModel: SettingsLogsViewModel
|
||||
|
||||
private var _binding: FragmentSettingsLogsBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
|
||||
inflater.inflate(R.layout.fragment_settings_logs, container, false)
|
||||
FragmentSettingsLogsBinding.inflate(inflater, container, false).let {
|
||||
_binding = it
|
||||
it.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?)
|
||||
{
|
||||
val context = context!!
|
||||
val context = requireContext()
|
||||
|
||||
viewModel = ViewModelProvider(this, viewModelFactory { SettingsLogsViewModel(LogManager(context)) })
|
||||
.get(SettingsLogsViewModel::class.java)
|
||||
|
||||
val adapter = SettingsLogsAdapter()
|
||||
logsRecyclerView.layoutManager = LinearLayoutManager(context)
|
||||
logsRecyclerView.adapter = adapter
|
||||
binding.logsRecyclerView.layoutManager = LinearLayoutManager(context)
|
||||
binding.logsRecyclerView.adapter = adapter
|
||||
adapter.shareCallback = this::shareLogFile
|
||||
viewModel.sessionLogs.observe(viewLifecycleOwner, Observer {
|
||||
adapter.logFiles = it
|
||||
emptyInfoGroup.visibility = if(it.isEmpty()) View.VISIBLE else View.GONE
|
||||
binding.emptyInfoGroup.visibility = if(it.isEmpty()) View.VISIBLE else View.GONE
|
||||
})
|
||||
|
||||
val itemTouchSwipeCallback = object : ItemTouchSwipeCallback(context)
|
||||
|
@ -55,7 +61,7 @@ class SettingsLogsFragment: AppCompatDialogFragment(), TitleFragment
|
|||
viewModel.deleteLog(file)
|
||||
}
|
||||
}
|
||||
ItemTouchHelper(itemTouchSwipeCallback).attachToRecyclerView(logsRecyclerView)
|
||||
ItemTouchHelper(itemTouchSwipeCallback).attachToRecyclerView(binding.logsRecyclerView)
|
||||
}
|
||||
|
||||
override fun getTitle(resources: Resources): String = resources.getString(R.string.preferences_logs_title)
|
||||
|
|
|
@ -2,17 +2,15 @@
|
|||
|
||||
package com.metallic.chiaki.settings
|
||||
|
||||
import android.view.View
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.metallic.chiaki.R
|
||||
import com.metallic.chiaki.common.RegisteredHost
|
||||
import com.metallic.chiaki.common.ext.inflate
|
||||
import kotlinx.android.synthetic.main.item_registered_host.view.*
|
||||
import com.metallic.chiaki.databinding.ItemRegisteredHostBinding
|
||||
|
||||
class SettingsRegisteredHostsAdapter: RecyclerView.Adapter<SettingsRegisteredHostsAdapter.ViewHolder>()
|
||||
{
|
||||
class ViewHolder(itemView: View): RecyclerView.ViewHolder(itemView)
|
||||
class ViewHolder(val binding: ItemRegisteredHostBinding): RecyclerView.ViewHolder(binding.root)
|
||||
|
||||
var hosts: List<RegisteredHost> = listOf()
|
||||
set(value)
|
||||
|
@ -21,15 +19,15 @@ class SettingsRegisteredHostsAdapter: RecyclerView.Adapter<SettingsRegisteredHos
|
|||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ViewHolder(parent.inflate(R.layout.item_registered_host))
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int)
|
||||
= ViewHolder(ItemRegisteredHostBinding.inflate(LayoutInflater.from(parent.context), parent, false))
|
||||
|
||||
override fun getItemCount() = hosts.size
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int)
|
||||
{
|
||||
val view = holder.itemView
|
||||
val host = hosts[position]
|
||||
view.nameTextView.text = "${host.serverNickname} (${if(host.target.isPS5) "PS5" else "PS4"})"
|
||||
view.summaryTextView.text = host.serverMac.toString()
|
||||
holder.binding.nameTextView.text = "${host.serverNickname} (${if(host.target.isPS5) "PS5" else "PS4"})"
|
||||
holder.binding.summaryTextView.text = host.serverMac.toString()
|
||||
}
|
||||
}
|
|
@ -20,25 +20,32 @@ import com.metallic.chiaki.R
|
|||
import com.metallic.chiaki.common.ext.putRevealExtra
|
||||
import com.metallic.chiaki.common.ext.viewModelFactory
|
||||
import com.metallic.chiaki.common.getDatabase
|
||||
import com.metallic.chiaki.databinding.FragmentSettingsRegisteredHostsBinding
|
||||
import com.metallic.chiaki.regist.RegistActivity
|
||||
import kotlinx.android.synthetic.main.fragment_settings_registered_hosts.*
|
||||
|
||||
class SettingsRegisteredHostsFragment: AppCompatDialogFragment(), TitleFragment
|
||||
{
|
||||
private lateinit var viewModel: SettingsRegisteredHostsViewModel
|
||||
|
||||
private var _binding: FragmentSettingsRegisteredHostsBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
|
||||
inflater.inflate(R.layout.fragment_settings_registered_hosts, container, false)
|
||||
FragmentSettingsRegisteredHostsBinding.inflate(inflater, container, false).let {
|
||||
_binding = it
|
||||
it.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?)
|
||||
{
|
||||
viewModel = ViewModelProvider(this, viewModelFactory { SettingsRegisteredHostsViewModel(getDatabase(context!!)) })
|
||||
val context = requireContext()
|
||||
viewModel = ViewModelProvider(this, viewModelFactory { SettingsRegisteredHostsViewModel(getDatabase(context)) })
|
||||
.get(SettingsRegisteredHostsViewModel::class.java)
|
||||
|
||||
val adapter = SettingsRegisteredHostsAdapter()
|
||||
hostsRecyclerView.layoutManager = LinearLayoutManager(context)
|
||||
hostsRecyclerView.adapter = adapter
|
||||
val itemTouchSwipeCallback = object : ItemTouchSwipeCallback(context!!)
|
||||
binding.hostsRecyclerView.layoutManager = LinearLayoutManager(context)
|
||||
binding.hostsRecyclerView.adapter = adapter
|
||||
val itemTouchSwipeCallback = object : ItemTouchSwipeCallback(context)
|
||||
{
|
||||
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int)
|
||||
{
|
||||
|
@ -56,15 +63,15 @@ class SettingsRegisteredHostsFragment: AppCompatDialogFragment(), TitleFragment
|
|||
.show()
|
||||
}
|
||||
}
|
||||
ItemTouchHelper(itemTouchSwipeCallback).attachToRecyclerView(hostsRecyclerView)
|
||||
ItemTouchHelper(itemTouchSwipeCallback).attachToRecyclerView(binding.hostsRecyclerView)
|
||||
viewModel.registeredHosts.observe(this, Observer {
|
||||
adapter.hosts = it
|
||||
emptyInfoGroup.visibility = if(it.isEmpty()) View.VISIBLE else View.GONE
|
||||
binding.emptyInfoGroup.visibility = if(it.isEmpty()) View.VISIBLE else View.GONE
|
||||
})
|
||||
|
||||
floatingActionButton.setOnClickListener {
|
||||
binding.floatingActionButton.setOnClickListener {
|
||||
Intent(context, RegistActivity::class.java).also {
|
||||
it.putRevealExtra(floatingActionButton, rootLayout)
|
||||
it.putRevealExtra(binding.floatingActionButton, binding.rootLayout)
|
||||
startActivity(it, ActivityOptions.makeSceneTransitionAnimation(activity).toBundle())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
package com.metallic.chiaki.stream
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.widget.FrameLayout
|
||||
|
||||
// see ExoPlayer's AspectRatioFrameLayout
|
||||
class AspectRatioFrameLayout @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null): FrameLayout(context, attrs)
|
||||
{
|
||||
companion object
|
||||
{
|
||||
private const val MAX_ASPECT_RATIO_DEFORMATION_FRACTION = 0.01f
|
||||
}
|
||||
|
||||
var aspectRatio = 0f
|
||||
set(value)
|
||||
{
|
||||
if(field != value)
|
||||
{
|
||||
field = value
|
||||
requestLayout()
|
||||
}
|
||||
}
|
||||
|
||||
var mode: TransformMode = TransformMode.FIT
|
||||
set(value)
|
||||
{
|
||||
if(field != value)
|
||||
{
|
||||
field = value
|
||||
requestLayout()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int)
|
||||
{
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
|
||||
if(aspectRatio <= 0)
|
||||
{
|
||||
// Aspect ratio not set.
|
||||
return
|
||||
}
|
||||
var width = measuredWidth
|
||||
var height = measuredHeight
|
||||
val viewAspectRatio = width.toFloat() / height
|
||||
val aspectDeformation = aspectRatio / viewAspectRatio - 1
|
||||
if(Math.abs(aspectDeformation) <= MAX_ASPECT_RATIO_DEFORMATION_FRACTION)
|
||||
return
|
||||
when(mode)
|
||||
{
|
||||
TransformMode.ZOOM ->
|
||||
if(aspectDeformation > 0)
|
||||
width = (height * aspectRatio).toInt()
|
||||
else
|
||||
height = (width / aspectRatio).toInt()
|
||||
TransformMode.FIT ->
|
||||
if(aspectDeformation > 0)
|
||||
height = (width / aspectRatio).toInt()
|
||||
else
|
||||
width = (height * aspectRatio).toInt()
|
||||
TransformMode.STRETCH -> {}
|
||||
}
|
||||
super.onMeasure(
|
||||
MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
|
||||
MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
|
||||
)
|
||||
}
|
||||
}
|
|
@ -6,12 +6,8 @@ import android.animation.Animator
|
|||
import android.animation.AnimatorListenerAdapter
|
||||
import android.app.AlertDialog
|
||||
import android.graphics.Matrix
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.view.KeyEvent
|
||||
import android.view.MotionEvent
|
||||
import android.view.TextureView
|
||||
import android.view.View
|
||||
import android.os.*
|
||||
import android.view.*
|
||||
import android.widget.EditText
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.isGone
|
||||
|
@ -20,15 +16,18 @@ import androidx.fragment.app.Fragment
|
|||
import androidx.lifecycle.*
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.metallic.chiaki.R
|
||||
import com.metallic.chiaki.common.LogManager
|
||||
import com.metallic.chiaki.common.Preferences
|
||||
import com.metallic.chiaki.common.ext.viewModelFactory
|
||||
import com.metallic.chiaki.databinding.ActivityStreamBinding
|
||||
import com.metallic.chiaki.lib.ConnectInfo
|
||||
import com.metallic.chiaki.lib.ConnectVideoProfile
|
||||
import com.metallic.chiaki.session.*
|
||||
import com.metallic.chiaki.touchcontrols.TouchpadOnlyFragment
|
||||
import com.metallic.chiaki.touchcontrols.DefaultTouchControlsFragment
|
||||
import com.metallic.chiaki.touchcontrols.TouchControlsFragment
|
||||
import kotlinx.android.synthetic.main.activity_stream.*
|
||||
import com.metallic.chiaki.touchcontrols.TouchpadOnlyFragment
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import io.reactivex.rxkotlin.addTo
|
||||
import kotlin.math.min
|
||||
|
||||
private sealed class DialogContents
|
||||
private object StreamQuitDialog: DialogContents()
|
||||
|
@ -44,6 +43,8 @@ class StreamActivity : AppCompatActivity(), View.OnSystemUiVisibilityChangeListe
|
|||
}
|
||||
|
||||
private lateinit var viewModel: StreamViewModel
|
||||
private lateinit var binding: ActivityStreamBinding
|
||||
|
||||
private val uiVisibilityHandler = Handler()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?)
|
||||
|
@ -58,64 +59,76 @@ class StreamActivity : AppCompatActivity(), View.OnSystemUiVisibilityChangeListe
|
|||
}
|
||||
|
||||
viewModel = ViewModelProvider(this, viewModelFactory {
|
||||
StreamViewModel(Preferences(this), LogManager(this), connectInfo)
|
||||
StreamViewModel(application, connectInfo)
|
||||
})[StreamViewModel::class.java]
|
||||
|
||||
setContentView(R.layout.activity_stream)
|
||||
viewModel.input.observe(this)
|
||||
|
||||
binding = ActivityStreamBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
window.decorView.setOnSystemUiVisibilityChangeListener(this)
|
||||
|
||||
viewModel.onScreenControlsEnabled.observe(this, Observer {
|
||||
if(onScreenControlsSwitch.isChecked != it)
|
||||
onScreenControlsSwitch.isChecked = it
|
||||
if(onScreenControlsSwitch.isChecked)
|
||||
touchpadOnlySwitch.isChecked = false
|
||||
if(binding.onScreenControlsSwitch.isChecked != it)
|
||||
binding.onScreenControlsSwitch.isChecked = it
|
||||
if(binding.onScreenControlsSwitch.isChecked)
|
||||
binding.touchpadOnlySwitch.isChecked = false
|
||||
})
|
||||
onScreenControlsSwitch.setOnCheckedChangeListener { _, isChecked ->
|
||||
binding.onScreenControlsSwitch.setOnCheckedChangeListener { _, isChecked ->
|
||||
viewModel.setOnScreenControlsEnabled(isChecked)
|
||||
showOverlay()
|
||||
}
|
||||
|
||||
viewModel.touchpadOnlyEnabled.observe(this, Observer {
|
||||
if(touchpadOnlySwitch.isChecked != it)
|
||||
touchpadOnlySwitch.isChecked = it
|
||||
if(touchpadOnlySwitch.isChecked)
|
||||
onScreenControlsSwitch.isChecked = false
|
||||
if(binding.touchpadOnlySwitch.isChecked != it)
|
||||
binding.touchpadOnlySwitch.isChecked = it
|
||||
if(binding.touchpadOnlySwitch.isChecked)
|
||||
binding.onScreenControlsSwitch.isChecked = false
|
||||
})
|
||||
touchpadOnlySwitch.setOnCheckedChangeListener { _, isChecked ->
|
||||
binding.touchpadOnlySwitch.setOnCheckedChangeListener { _, isChecked ->
|
||||
viewModel.setTouchpadOnlyEnabled(isChecked)
|
||||
showOverlay()
|
||||
}
|
||||
|
||||
displayModeToggle.addOnButtonCheckedListener { _, checkedId, _ ->
|
||||
// following 'if' is a workaround until selectionRequired for MaterialButtonToggleGroup
|
||||
// comes out of alpha.
|
||||
// See https://stackoverflow.com/questions/56164004/required-single-selection-on-materialbuttontogglegroup
|
||||
if (displayModeToggle.checkedButtonId == -1)
|
||||
displayModeToggle.check(checkedId)
|
||||
|
||||
adjustTextureViewAspect()
|
||||
binding.displayModeToggle.addOnButtonCheckedListener { _, _, _ ->
|
||||
adjustStreamViewAspect()
|
||||
showOverlay()
|
||||
}
|
||||
|
||||
viewModel.session.attachToTextureView(textureView)
|
||||
//viewModel.session.attachToTextureView(textureView)
|
||||
viewModel.session.attachToSurfaceView(binding.surfaceView)
|
||||
viewModel.session.state.observe(this, Observer { this.stateChanged(it) })
|
||||
textureView.addOnLayoutChangeListener { _, _, _, _, _, _, _, _, _ ->
|
||||
adjustTextureViewAspect()
|
||||
adjustStreamViewAspect()
|
||||
|
||||
if(Preferences(this).rumbleEnabled)
|
||||
{
|
||||
val vibrator = getSystemService(VIBRATOR_SERVICE) as Vibrator
|
||||
viewModel.session.rumbleState.observe(this, Observer {
|
||||
val amplitude = min(255, (it.left.toInt() + it.right.toInt()) / 2)
|
||||
vibrator.cancel()
|
||||
if(amplitude == 0)
|
||||
return@Observer
|
||||
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
|
||||
vibrator.vibrate(VibrationEffect.createOneShot(1000, amplitude))
|
||||
else
|
||||
vibrator.vibrate(1000)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private val controlsDisposable = CompositeDisposable()
|
||||
|
||||
override fun onAttachFragment(fragment: Fragment)
|
||||
{
|
||||
super.onAttachFragment(fragment)
|
||||
if(fragment is TouchControlsFragment)
|
||||
{
|
||||
fragment.controllerStateCallback = { viewModel.input.touchControllerState = it }
|
||||
fragment.controllerState
|
||||
.subscribe { viewModel.input.touchControllerState = it }
|
||||
.addTo(controlsDisposable)
|
||||
fragment.onScreenControlsEnabled = viewModel.onScreenControlsEnabled
|
||||
}
|
||||
if(fragment is TouchpadOnlyFragment)
|
||||
{
|
||||
fragment.controllerStateCallback = { viewModel.input.touchControllerState = it }
|
||||
fragment.touchpadOnlyEnabled = viewModel.touchpadOnlyEnabled
|
||||
if(fragment is TouchpadOnlyFragment)
|
||||
fragment.touchpadOnlyEnabled = viewModel.touchpadOnlyEnabled
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -132,6 +145,12 @@ class StreamActivity : AppCompatActivity(), View.OnSystemUiVisibilityChangeListe
|
|||
viewModel.session.pause()
|
||||
}
|
||||
|
||||
override fun onDestroy()
|
||||
{
|
||||
super.onDestroy()
|
||||
controlsDisposable.dispose()
|
||||
}
|
||||
|
||||
private fun reconnect()
|
||||
{
|
||||
viewModel.session.shutdown()
|
||||
|
@ -150,14 +169,14 @@ class StreamActivity : AppCompatActivity(), View.OnSystemUiVisibilityChangeListe
|
|||
|
||||
private fun showOverlay()
|
||||
{
|
||||
overlay.isVisible = true
|
||||
overlay.animate()
|
||||
binding.overlay.isVisible = true
|
||||
binding.overlay.animate()
|
||||
.alpha(1.0f)
|
||||
.setListener(object: AnimatorListenerAdapter()
|
||||
{
|
||||
override fun onAnimationEnd(animation: Animator?)
|
||||
override fun onAnimationEnd(animation: Animator)
|
||||
{
|
||||
overlay.alpha = 1.0f
|
||||
binding.overlay.alpha = 1.0f
|
||||
}
|
||||
})
|
||||
uiVisibilityHandler.removeCallbacks(hideSystemUIRunnable)
|
||||
|
@ -166,13 +185,13 @@ class StreamActivity : AppCompatActivity(), View.OnSystemUiVisibilityChangeListe
|
|||
|
||||
private fun hideOverlay()
|
||||
{
|
||||
overlay.animate()
|
||||
binding.overlay.animate()
|
||||
.alpha(0.0f)
|
||||
.setListener(object: AnimatorListenerAdapter()
|
||||
{
|
||||
override fun onAnimationEnd(animation: Animator?)
|
||||
override fun onAnimationEnd(animation: Animator)
|
||||
{
|
||||
overlay.isGone = true
|
||||
binding.overlay.isGone = true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -205,34 +224,39 @@ class StreamActivity : AppCompatActivity(), View.OnSystemUiVisibilityChangeListe
|
|||
|
||||
private fun stateChanged(state: StreamState)
|
||||
{
|
||||
progressBar.visibility = if(state == StreamStateConnecting) View.VISIBLE else View.GONE
|
||||
binding.progressBar.visibility = if(state == StreamStateConnecting) View.VISIBLE else View.GONE
|
||||
|
||||
when(state)
|
||||
{
|
||||
is StreamStateQuit ->
|
||||
{
|
||||
if(!state.reason.isStopped && dialogContents != StreamQuitDialog)
|
||||
if(dialogContents != StreamQuitDialog)
|
||||
{
|
||||
dialog?.dismiss()
|
||||
val reasonStr = state.reasonString
|
||||
val dialog = MaterialAlertDialogBuilder(this)
|
||||
.setMessage(getString(R.string.alert_message_session_quit, state.reason.toString())
|
||||
+ (if(reasonStr != null) "\n$reasonStr" else ""))
|
||||
.setPositiveButton(R.string.action_reconnect) { _, _ ->
|
||||
dialog = null
|
||||
reconnect()
|
||||
}
|
||||
.setOnCancelListener {
|
||||
dialog = null
|
||||
finish()
|
||||
}
|
||||
.setNegativeButton(R.string.action_quit_session) { _, _ ->
|
||||
dialog = null
|
||||
finish()
|
||||
}
|
||||
.create()
|
||||
dialogContents = StreamQuitDialog
|
||||
dialog.show()
|
||||
if(state.reason.isError)
|
||||
{
|
||||
dialog?.dismiss()
|
||||
val reasonStr = state.reasonString
|
||||
val dialog = MaterialAlertDialogBuilder(this)
|
||||
.setMessage(getString(R.string.alert_message_session_quit, state.reason.toString())
|
||||
+ (if(reasonStr != null) "\n$reasonStr" else ""))
|
||||
.setPositiveButton(R.string.action_reconnect) { _, _ ->
|
||||
dialog = null
|
||||
reconnect()
|
||||
}
|
||||
.setOnCancelListener {
|
||||
dialog = null
|
||||
finish()
|
||||
}
|
||||
.setNegativeButton(R.string.action_quit_session) { _, _ ->
|
||||
dialog = null
|
||||
finish()
|
||||
}
|
||||
.create()
|
||||
dialogContents = StreamQuitDialog
|
||||
dialog.show()
|
||||
}
|
||||
else
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -287,77 +311,89 @@ class StreamActivity : AppCompatActivity(), View.OnSystemUiVisibilityChangeListe
|
|||
dialog.show()
|
||||
}
|
||||
}
|
||||
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
private fun adjustTextureViewAspect()
|
||||
private fun adjustTextureViewAspect(textureView: TextureView)
|
||||
{
|
||||
val displayInfo = DisplayInfo(viewModel.session.connectInfo.videoProfile, textureView)
|
||||
val resolution = displayInfo.computeResolutionFor(displayModeToggle.checkedButtonId)
|
||||
|
||||
val trans = TextureViewTransform(viewModel.session.connectInfo.videoProfile, textureView)
|
||||
val resolution = trans.resolutionFor(TransformMode.fromButton(binding.displayModeToggle.checkedButtonId))
|
||||
Matrix().also {
|
||||
textureView.getTransform(it)
|
||||
it.setScale(resolution.width / displayInfo.viewWidth, resolution.height / displayInfo.viewHeight)
|
||||
it.postTranslate((displayInfo.viewWidth - resolution.width) * 0.5f, (displayInfo.viewHeight - resolution.height) * 0.5f)
|
||||
it.setScale(resolution.width / trans.viewWidth, resolution.height / trans.viewHeight)
|
||||
it.postTranslate((trans.viewWidth - resolution.width) * 0.5f, (trans.viewHeight - resolution.height) * 0.5f)
|
||||
textureView.setTransform(it)
|
||||
}
|
||||
}
|
||||
|
||||
private fun adjustSurfaceViewAspect()
|
||||
{
|
||||
val videoProfile = viewModel.session.connectInfo.videoProfile
|
||||
binding.aspectRatioLayout.aspectRatio = videoProfile.width.toFloat() / videoProfile.height.toFloat()
|
||||
binding.aspectRatioLayout.mode = TransformMode.fromButton(binding.displayModeToggle.checkedButtonId)
|
||||
}
|
||||
|
||||
private fun adjustStreamViewAspect() = adjustSurfaceViewAspect()
|
||||
|
||||
override fun dispatchKeyEvent(event: KeyEvent) = viewModel.input.dispatchKeyEvent(event) || super.dispatchKeyEvent(event)
|
||||
override fun onGenericMotionEvent(event: MotionEvent) = viewModel.input.onGenericMotionEvent(event) || super.onGenericMotionEvent(event)
|
||||
|
||||
}
|
||||
|
||||
|
||||
class DisplayInfo constructor(val videoProfile: ConnectVideoProfile, val textureView: TextureView)
|
||||
enum class TransformMode
|
||||
{
|
||||
val contentWidth : Float get() = videoProfile.width.toFloat()
|
||||
val contentHeight : Float get() = videoProfile.height.toFloat()
|
||||
FIT,
|
||||
STRETCH,
|
||||
ZOOM;
|
||||
|
||||
companion object
|
||||
{
|
||||
fun fromButton(displayModeButtonId: Int)
|
||||
= when (displayModeButtonId)
|
||||
{
|
||||
R.id.display_mode_stretch_button -> STRETCH
|
||||
R.id.display_mode_zoom_button -> ZOOM
|
||||
else -> FIT
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TextureViewTransform(private val videoProfile: ConnectVideoProfile, private val textureView: TextureView)
|
||||
{
|
||||
private val contentWidth : Float get() = videoProfile.width.toFloat()
|
||||
private val contentHeight : Float get() = videoProfile.height.toFloat()
|
||||
val viewWidth : Float get() = textureView.width.toFloat()
|
||||
val viewHeight : Float get() = textureView.height.toFloat()
|
||||
val contentAspect : Float get() = contentHeight / contentWidth
|
||||
private val contentAspect : Float get() = contentHeight / contentWidth
|
||||
|
||||
fun computeResolutionFor(displayModeButtonId: Int) : Resolution
|
||||
{
|
||||
when (displayModeButtonId)
|
||||
fun resolutionFor(mode: TransformMode): Resolution
|
||||
= when(mode)
|
||||
{
|
||||
R.id.display_mode_stretch_button -> return computeStrechedResolution()
|
||||
R.id.display_mode_zoom_button -> return computeZoomedResolution()
|
||||
else -> return computeNormalResolution()
|
||||
TransformMode.STRETCH -> strechedResolution
|
||||
TransformMode.ZOOM -> zoomedResolution
|
||||
TransformMode.FIT -> normalResolution
|
||||
}
|
||||
}
|
||||
|
||||
private fun computeStrechedResolution(): Resolution
|
||||
{
|
||||
return Resolution(viewWidth, viewHeight)
|
||||
}
|
||||
private val strechedResolution get() = Resolution(viewWidth, viewHeight)
|
||||
|
||||
private fun computeZoomedResolution(): Resolution
|
||||
{
|
||||
if (viewHeight > viewWidth * contentAspect)
|
||||
private val zoomedResolution get() =
|
||||
if(viewHeight > viewWidth * contentAspect)
|
||||
{
|
||||
val zoomFactor = viewHeight / contentHeight
|
||||
return Resolution(contentWidth * zoomFactor, viewHeight)
|
||||
Resolution(contentWidth * zoomFactor, viewHeight)
|
||||
}
|
||||
else
|
||||
{
|
||||
val zoomFactor = viewWidth / contentWidth
|
||||
return Resolution(viewWidth, contentHeight * zoomFactor)
|
||||
Resolution(viewWidth, contentHeight * zoomFactor)
|
||||
}
|
||||
}
|
||||
|
||||
private fun computeNormalResolution(): Resolution
|
||||
{
|
||||
if (viewHeight > viewWidth * contentAspect)
|
||||
{
|
||||
return Resolution(viewWidth, viewWidth * contentAspect)
|
||||
}
|
||||
private val normalResolution get() =
|
||||
if(viewHeight > viewWidth * contentAspect)
|
||||
Resolution(viewWidth, viewWidth * contentAspect)
|
||||
else
|
||||
{
|
||||
return Resolution(viewHeight / contentAspect, viewHeight)
|
||||
}
|
||||
}
|
||||
|
||||
Resolution(viewHeight / contentAspect, viewHeight)
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -2,19 +2,22 @@
|
|||
|
||||
package com.metallic.chiaki.stream
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import androidx.lifecycle.*
|
||||
import com.metallic.chiaki.common.LogManager
|
||||
import com.metallic.chiaki.session.StreamSession
|
||||
import com.metallic.chiaki.common.Preferences
|
||||
import com.metallic.chiaki.lib.*
|
||||
import com.metallic.chiaki.session.StreamInput
|
||||
|
||||
class StreamViewModel(val preferences: Preferences, val logManager: LogManager, val connectInfo: ConnectInfo): ViewModel()
|
||||
class StreamViewModel(val application: Application, val connectInfo: ConnectInfo): ViewModel()
|
||||
{
|
||||
val preferences = Preferences(application)
|
||||
val logManager = LogManager(application)
|
||||
|
||||
private var _session: StreamSession? = null
|
||||
val input = StreamInput(preferences)
|
||||
val input = StreamInput(application, preferences)
|
||||
val session = StreamSession(connectInfo, logManager, preferences.logVerbose, input)
|
||||
|
||||
private var _onScreenControlsEnabled = MutableLiveData<Boolean>(preferences.onScreenControlsEnabled)
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
package com.metallic.chiaki.touchcontrols
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.os.VibrationEffect
|
||||
import android.os.Vibrator
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.metallic.chiaki.common.Preferences
|
||||
|
||||
class ButtonHaptics(val context: Context)
|
||||
{
|
||||
private val enabled = Preferences(context).buttonHapticEnabled
|
||||
|
||||
fun trigger(harder: Boolean = false)
|
||||
{
|
||||
if(!enabled)
|
||||
return
|
||||
val vibrator = context.getSystemService(AppCompatActivity.VIBRATOR_SERVICE) as Vibrator
|
||||
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
|
||||
vibrator.vibrate(
|
||||
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
|
||||
VibrationEffect.createPredefined(if(harder) VibrationEffect.EFFECT_CLICK else VibrationEffect.EFFECT_TICK)
|
||||
else
|
||||
VibrationEffect.createOneShot(10, if(harder) 200 else 100)
|
||||
)
|
||||
else
|
||||
vibrator.vibrate(10)
|
||||
}
|
||||
}
|
|
@ -6,14 +6,19 @@ import android.content.Context
|
|||
import android.graphics.Canvas
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.util.AttributeSet
|
||||
import android.util.Log
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.view.children
|
||||
import com.metallic.chiaki.R
|
||||
|
||||
class ButtonView @JvmOverloads constructor(
|
||||
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
|
||||
) : View(context, attrs, defStyleAttr)
|
||||
{
|
||||
private val haptics = ButtonHaptics(context)
|
||||
|
||||
var buttonPressed = false
|
||||
private set(value)
|
||||
{
|
||||
|
@ -21,6 +26,8 @@ class ButtonView @JvmOverloads constructor(
|
|||
field = value
|
||||
if(diff)
|
||||
{
|
||||
if(value)
|
||||
haptics.trigger()
|
||||
invalidate()
|
||||
buttonPressedCallback?.let { it(field) }
|
||||
}
|
||||
|
@ -46,16 +53,39 @@ class ButtonView @JvmOverloads constructor(
|
|||
{
|
||||
super.onDraw(canvas)
|
||||
val drawable = if(buttonPressed) drawablePressed else drawableIdle
|
||||
drawable?.setBounds(0, 0, width, height)
|
||||
drawable?.setBounds(paddingLeft, paddingTop, width - paddingRight, height - paddingBottom)
|
||||
drawable?.draw(canvas)
|
||||
}
|
||||
|
||||
/**
|
||||
* If this button overlaps with others in the same layout,
|
||||
* let the one whose center is closest to the touch handle it.
|
||||
*/
|
||||
private fun bestFittingTouchView(x: Float, y: Float): View
|
||||
{
|
||||
val loc = locationOnScreen + Vector(x, y)
|
||||
return (parent as? ViewGroup)?.children?.filter {
|
||||
it is ButtonView
|
||||
}?.filter {
|
||||
val pos = it.locationOnScreen
|
||||
loc.x >= pos.x && loc.x < pos.x + it.width && loc.y >= pos.y && loc.y < pos.y + it.height
|
||||
}?.sortedBy {
|
||||
(loc - (it.locationOnScreen + Vector(it.width.toFloat(), it.height.toFloat()) * 0.5f)).lengthSq
|
||||
}?.firstOrNull() ?: this
|
||||
}
|
||||
|
||||
override fun onTouchEvent(event: MotionEvent): Boolean
|
||||
{
|
||||
when(event.action)
|
||||
when(event.actionMasked)
|
||||
{
|
||||
MotionEvent.ACTION_DOWN -> buttonPressed = true
|
||||
MotionEvent.ACTION_UP -> buttonPressed = false
|
||||
MotionEvent.ACTION_DOWN, MotionEvent.ACTION_POINTER_DOWN -> {
|
||||
if(bestFittingTouchView(event.getX(event.actionIndex), event.getY(event.actionIndex)) != this)
|
||||
return false
|
||||
buttonPressed = true
|
||||
}
|
||||
MotionEvent.ACTION_UP, MotionEvent.ACTION_POINTER_UP -> {
|
||||
buttonPressed = false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -16,6 +16,8 @@ class DPadView @JvmOverloads constructor(
|
|||
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
|
||||
) : View(context, attrs, defStyleAttr)
|
||||
{
|
||||
private val haptics = ButtonHaptics(context)
|
||||
|
||||
enum class Direction {
|
||||
LEFT,
|
||||
RIGHT,
|
||||
|
@ -71,7 +73,7 @@ class DPadView @JvmOverloads constructor(
|
|||
else
|
||||
drawable = dpadIdleDrawable
|
||||
|
||||
drawable?.setBounds(0, 0, width, height)
|
||||
drawable?.setBounds(paddingLeft, paddingTop, width - paddingRight, height - paddingBottom)
|
||||
//drawable?.alpha = 127
|
||||
drawable?.draw(canvas)
|
||||
}
|
||||
|
@ -113,6 +115,8 @@ class DPadView @JvmOverloads constructor(
|
|||
|
||||
if(state != newState)
|
||||
{
|
||||
if(newState != null)
|
||||
haptics.trigger()
|
||||
state = newState
|
||||
invalidate()
|
||||
stateChangeCallback?.let { it(state) }
|
||||
|
|
|
@ -3,74 +3,97 @@
|
|||
package com.metallic.chiaki.touchcontrols
|
||||
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.Observer
|
||||
import com.metallic.chiaki.R
|
||||
import com.metallic.chiaki.databinding.FragmentControlsBinding
|
||||
import com.metallic.chiaki.lib.ControllerState
|
||||
import kotlinx.android.synthetic.main.fragment_controls.*
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.rxkotlin.Observables.combineLatest
|
||||
import io.reactivex.subjects.BehaviorSubject
|
||||
import io.reactivex.subjects.Subject
|
||||
|
||||
class TouchControlsFragment : Fragment()
|
||||
abstract class TouchControlsFragment : Fragment()
|
||||
{
|
||||
private var controllerState = ControllerState()
|
||||
private set(value)
|
||||
protected var ownControllerState = ControllerState()
|
||||
set(value)
|
||||
{
|
||||
val diff = field != value
|
||||
field = value
|
||||
if(diff)
|
||||
controllerStateCallback?.let { it(value) }
|
||||
ownControllerStateSubject.onNext(ownControllerState)
|
||||
}
|
||||
|
||||
var controllerStateCallback: ((ControllerState) -> Unit)? = null
|
||||
var onScreenControlsEnabled: LiveData<Boolean>? = null
|
||||
protected val ownControllerStateSubject: Subject<ControllerState>
|
||||
= BehaviorSubject.create<ControllerState>().also { it.onNext(ownControllerState) }
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View
|
||||
= inflater.inflate(R.layout.fragment_controls, container, false)
|
||||
// to delay attaching to the touchpadView until it's available
|
||||
protected val controllerStateProxy: Subject<Observable<ControllerState>>
|
||||
= BehaviorSubject.create<Observable<ControllerState>>().also { it.onNext(ownControllerStateSubject) }
|
||||
val controllerState: Observable<ControllerState> get() =
|
||||
controllerStateProxy.flatMap { it }
|
||||
|
||||
var onScreenControlsEnabled: LiveData<Boolean>? = null
|
||||
}
|
||||
|
||||
class DefaultTouchControlsFragment : TouchControlsFragment()
|
||||
{
|
||||
private var _binding: FragmentControlsBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
|
||||
FragmentControlsBinding.inflate(inflater, container, false).let {
|
||||
_binding = it
|
||||
controllerStateProxy.onNext(
|
||||
combineLatest(ownControllerStateSubject, binding.touchpadView.controllerState) { a, b -> a or b }
|
||||
)
|
||||
it.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?)
|
||||
{
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
dpadView.stateChangeCallback = this::dpadStateChanged
|
||||
crossButtonView.buttonPressedCallback = buttonStateChanged(ControllerState.BUTTON_CROSS)
|
||||
moonButtonView.buttonPressedCallback = buttonStateChanged(ControllerState.BUTTON_MOON)
|
||||
pyramidButtonView.buttonPressedCallback = buttonStateChanged(ControllerState.BUTTON_PYRAMID)
|
||||
boxButtonView.buttonPressedCallback = buttonStateChanged(ControllerState.BUTTON_BOX)
|
||||
l1ButtonView.buttonPressedCallback = buttonStateChanged(ControllerState.BUTTON_L1)
|
||||
r1ButtonView.buttonPressedCallback = buttonStateChanged(ControllerState.BUTTON_R1)
|
||||
optionsButtonView.buttonPressedCallback = buttonStateChanged(ControllerState.BUTTON_OPTIONS)
|
||||
shareButtonView.buttonPressedCallback = buttonStateChanged(ControllerState.BUTTON_SHARE)
|
||||
psButtonView.buttonPressedCallback = buttonStateChanged(ControllerState.BUTTON_PS)
|
||||
touchpadButtonView.buttonPressedCallback = buttonStateChanged(ControllerState.BUTTON_TOUCHPAD)
|
||||
binding.dpadView.stateChangeCallback = this::dpadStateChanged
|
||||
binding.crossButtonView.buttonPressedCallback = buttonStateChanged(ControllerState.BUTTON_CROSS)
|
||||
binding.moonButtonView.buttonPressedCallback = buttonStateChanged(ControllerState.BUTTON_MOON)
|
||||
binding.pyramidButtonView.buttonPressedCallback = buttonStateChanged(ControllerState.BUTTON_PYRAMID)
|
||||
binding.boxButtonView.buttonPressedCallback = buttonStateChanged(ControllerState.BUTTON_BOX)
|
||||
binding.l1ButtonView.buttonPressedCallback = buttonStateChanged(ControllerState.BUTTON_L1)
|
||||
binding.r1ButtonView.buttonPressedCallback = buttonStateChanged(ControllerState.BUTTON_R1)
|
||||
binding.l3ButtonView.buttonPressedCallback = buttonStateChanged(ControllerState.BUTTON_L3)
|
||||
binding.r3ButtonView.buttonPressedCallback = buttonStateChanged(ControllerState.BUTTON_R3)
|
||||
binding.optionsButtonView.buttonPressedCallback = buttonStateChanged(ControllerState.BUTTON_OPTIONS)
|
||||
binding.shareButtonView.buttonPressedCallback = buttonStateChanged(ControllerState.BUTTON_SHARE)
|
||||
binding.psButtonView.buttonPressedCallback = buttonStateChanged(ControllerState.BUTTON_PS)
|
||||
|
||||
l2ButtonView.buttonPressedCallback = { controllerState = controllerState.copy().apply { l2State = if(it) 255U else 0U } }
|
||||
r2ButtonView.buttonPressedCallback = { controllerState = controllerState.copy().apply { r2State = if(it) 255U else 0U } }
|
||||
binding.l2ButtonView.buttonPressedCallback = { ownControllerState = ownControllerState.copy().apply { l2State = if(it) 255U else 0U } }
|
||||
binding.r2ButtonView.buttonPressedCallback = { ownControllerState = ownControllerState.copy().apply { r2State = if(it) 255U else 0U } }
|
||||
|
||||
val quantizeStick = { f: Float ->
|
||||
(Short.MAX_VALUE * f).toShort()
|
||||
(Short.MAX_VALUE * f).toInt().toShort()
|
||||
}
|
||||
|
||||
leftAnalogStickView.stateChangedCallback = { controllerState = controllerState.copy().apply {
|
||||
binding.leftAnalogStickView.stateChangedCallback = { ownControllerState = ownControllerState.copy().apply {
|
||||
leftX = quantizeStick(it.x)
|
||||
leftY = quantizeStick(it.y)
|
||||
}}
|
||||
|
||||
rightAnalogStickView.stateChangedCallback = { controllerState = controllerState.copy().apply {
|
||||
binding.rightAnalogStickView.stateChangedCallback = { ownControllerState = ownControllerState.copy().apply {
|
||||
rightX = quantizeStick(it.x)
|
||||
rightY = quantizeStick(it.y)
|
||||
}}
|
||||
|
||||
onScreenControlsEnabled?.observe(this, Observer {
|
||||
onScreenControlsEnabled?.observe(viewLifecycleOwner, Observer {
|
||||
view.visibility = if(it) View.VISIBLE else View.GONE
|
||||
})
|
||||
}
|
||||
|
||||
private fun dpadStateChanged(direction: DPadView.Direction?)
|
||||
{
|
||||
controllerState = controllerState.copy().apply {
|
||||
ownControllerState = ownControllerState.copy().apply {
|
||||
buttons = ((buttons
|
||||
and ControllerState.BUTTON_DPAD_LEFT.inv()
|
||||
and ControllerState.BUTTON_DPAD_RIGHT.inv()
|
||||
|
@ -92,7 +115,7 @@ class TouchControlsFragment : Fragment()
|
|||
}
|
||||
|
||||
private fun buttonStateChanged(buttonMask: UInt) = { pressed: Boolean ->
|
||||
controllerState = controllerState.copy().apply {
|
||||
ownControllerState = ownControllerState.copy().apply {
|
||||
buttons =
|
||||
if(pressed)
|
||||
buttons or buttonMask
|
||||
|
|
|
@ -26,7 +26,7 @@ class TouchTracker
|
|||
if(pointerId == null)
|
||||
{
|
||||
pointerId = event.getPointerId(event.actionIndex)
|
||||
currentPosition = Vector(event.x, event.y)
|
||||
currentPosition = Vector(event.getX(event.actionIndex), event.getY(event.actionIndex))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,49 +6,42 @@ import android.os.Bundle
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.Observer
|
||||
import com.metallic.chiaki.R
|
||||
import com.metallic.chiaki.lib.ControllerState
|
||||
import kotlinx.android.synthetic.main.fragment_controls.*
|
||||
import com.metallic.chiaki.databinding.FragmentTouchpadOnlyBinding
|
||||
import io.reactivex.rxkotlin.Observables.combineLatest
|
||||
|
||||
class TouchpadOnlyFragment : Fragment()
|
||||
class TouchpadOnlyFragment : TouchControlsFragment()
|
||||
{
|
||||
private var controllerState = ControllerState()
|
||||
private set(value)
|
||||
{
|
||||
val diff = field != value
|
||||
field = value
|
||||
if(diff)
|
||||
controllerStateCallback?.let { it(value) }
|
||||
}
|
||||
|
||||
var controllerStateCallback: ((ControllerState) -> Unit)? = null
|
||||
var touchpadOnlyEnabled: LiveData<Boolean>? = null
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View
|
||||
= inflater.inflate(R.layout.fragment_touchpad_only, container, false)
|
||||
private var _binding: FragmentTouchpadOnlyBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
|
||||
FragmentTouchpadOnlyBinding.inflate(inflater, container, false).let {
|
||||
_binding = it
|
||||
controllerStateProxy.onNext(
|
||||
combineLatest(ownControllerStateSubject, binding.touchpadView.controllerState) { a, b -> a or b }
|
||||
)
|
||||
it.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?)
|
||||
{
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
touchpadButtonView.buttonPressedCallback = buttonStateChanged(ControllerState.BUTTON_TOUCHPAD)
|
||||
|
||||
touchpadOnlyEnabled?.observe(this, Observer {
|
||||
touchpadOnlyEnabled?.observe(viewLifecycleOwner, Observer {
|
||||
view.visibility = if(it) View.VISIBLE else View.GONE
|
||||
})
|
||||
}
|
||||
|
||||
private fun buttonStateChanged(buttonMask: UInt) = { pressed: Boolean ->
|
||||
controllerState = controllerState.copy().apply {
|
||||
ownControllerState = ownControllerState.copy().apply {
|
||||
buttons =
|
||||
if(pressed)
|
||||
buttons or buttonMask
|
||||
else
|
||||
buttons and buttonMask.inv()
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,168 @@
|
|||
// SPDX-License-Identifier: LicenseRef-AGPL-3.0-only-OpenSSL
|
||||
|
||||
package com.metallic.chiaki.touchcontrols
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.util.AttributeSet
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import com.metallic.chiaki.R
|
||||
import com.metallic.chiaki.lib.ControllerState
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.subjects.BehaviorSubject
|
||||
import io.reactivex.subjects.Subject
|
||||
import kotlin.math.max
|
||||
|
||||
class TouchpadView @JvmOverloads constructor(
|
||||
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
|
||||
) : View(context, attrs, defStyleAttr)
|
||||
{
|
||||
companion object
|
||||
{
|
||||
private const val BUTTON_PRESS_MAX_MOVE_DIST_DP = 32.0f
|
||||
private const val SHORT_BUTTON_PRESS_DURATION_MS = 200L
|
||||
private const val BUTTON_HOLD_DELAY_MS = 500L
|
||||
}
|
||||
|
||||
private val haptics = ButtonHaptics(context)
|
||||
|
||||
private val drawableIdle: Drawable?
|
||||
private val drawablePressed: Drawable?
|
||||
|
||||
private val state: ControllerState = ControllerState()
|
||||
|
||||
inner class Touch(
|
||||
val stateId: UByte,
|
||||
private val startX: Float,
|
||||
private val startY: Float)
|
||||
{
|
||||
var lifted = false // will be true but touch still in list when only relevant for short touch
|
||||
private var maxDist: Float = 0.0f
|
||||
val moveInsignificant: Boolean get() = maxDist < BUTTON_PRESS_MAX_MOVE_DIST_DP
|
||||
|
||||
fun onMove(x: Float, y: Float)
|
||||
{
|
||||
val d = (Vector(x, y) - Vector(startX, startY)).length / resources.displayMetrics.density
|
||||
maxDist = max(d, maxDist)
|
||||
}
|
||||
|
||||
val startButtonHoldRunnable = Runnable {
|
||||
if(!moveInsignificant || buttonHeld)
|
||||
return@Runnable
|
||||
haptics.trigger(true)
|
||||
state.buttons = state.buttons or ControllerState.BUTTON_TOUCHPAD
|
||||
buttonHeld = true
|
||||
triggerStateChanged()
|
||||
}
|
||||
}
|
||||
private val pointerTouches = mutableMapOf<Int, Touch>()
|
||||
|
||||
private val stateSubject: Subject<ControllerState>
|
||||
= BehaviorSubject.create<ControllerState>().also { it.onNext(state) }
|
||||
val controllerState: Observable<ControllerState> get() = stateSubject
|
||||
|
||||
private var shortPressingTouches = listOf<Touch>()
|
||||
private val shortButtonPressLiftRunnable = Runnable {
|
||||
state.buttons = state.buttons and ControllerState.BUTTON_TOUCHPAD.inv()
|
||||
shortPressingTouches.forEach {
|
||||
state.stopTouch(it.stateId)
|
||||
}
|
||||
shortPressingTouches = listOf()
|
||||
triggerStateChanged()
|
||||
}
|
||||
|
||||
private var buttonHeld = false
|
||||
|
||||
init
|
||||
{
|
||||
context.theme.obtainStyledAttributes(attrs, R.styleable.TouchpadView, 0, 0).apply {
|
||||
drawableIdle = getDrawable(R.styleable.TouchpadView_drawableIdle)
|
||||
drawablePressed = getDrawable(R.styleable.TouchpadView_drawablePressed)
|
||||
recycle()
|
||||
}
|
||||
isClickable = true
|
||||
}
|
||||
|
||||
override fun onDraw(canvas: Canvas)
|
||||
{
|
||||
super.onDraw(canvas)
|
||||
if(pointerTouches.values.find { !it.lifted } == null)
|
||||
return
|
||||
val drawable = if(state.buttons and ControllerState.BUTTON_TOUCHPAD != 0U) drawablePressed else drawableIdle
|
||||
drawable?.setBounds(paddingLeft, paddingTop, width - paddingRight, height - paddingBottom)
|
||||
drawable?.draw(canvas)
|
||||
}
|
||||
|
||||
private fun touchX(event: MotionEvent, index: Int): UShort =
|
||||
maxOf(0U.toUShort(), minOf((ControllerState.TOUCHPAD_WIDTH - 1u).toUShort(),
|
||||
(ControllerState.TOUCHPAD_WIDTH.toFloat() * event.getX(index) / width.toFloat()).toUInt().toUShort()))
|
||||
|
||||
private fun touchY(event: MotionEvent, index: Int): UShort =
|
||||
maxOf(0U.toUShort(), minOf((ControllerState.TOUCHPAD_HEIGHT - 1u).toUShort(),
|
||||
(ControllerState.TOUCHPAD_HEIGHT.toFloat() * event.getY(index) / height.toFloat()).toUInt().toUShort()))
|
||||
|
||||
override fun onTouchEvent(event: MotionEvent): Boolean
|
||||
{
|
||||
when(event.actionMasked)
|
||||
{
|
||||
MotionEvent.ACTION_DOWN, MotionEvent.ACTION_POINTER_DOWN -> {
|
||||
state.startTouch(touchX(event, event.actionIndex), touchY(event, event.actionIndex))?.let {
|
||||
haptics.trigger()
|
||||
val touch = Touch(it, event.getX(event.actionIndex), event.getY(event.actionIndex))
|
||||
pointerTouches[event.getPointerId(event.actionIndex)] = touch
|
||||
if(!buttonHeld)
|
||||
postDelayed(touch.startButtonHoldRunnable, BUTTON_HOLD_DELAY_MS)
|
||||
triggerStateChanged()
|
||||
}
|
||||
}
|
||||
MotionEvent.ACTION_UP, MotionEvent.ACTION_POINTER_UP -> {
|
||||
pointerTouches.remove(event.getPointerId(event.actionIndex))?.let {
|
||||
removeCallbacks(it.startButtonHoldRunnable)
|
||||
when
|
||||
{
|
||||
buttonHeld ->
|
||||
{
|
||||
buttonHeld = false
|
||||
state.buttons = state.buttons and ControllerState.BUTTON_TOUCHPAD.inv()
|
||||
state.stopTouch(it.stateId)
|
||||
}
|
||||
it.moveInsignificant -> triggerShortButtonPress(it)
|
||||
else -> state.stopTouch(it.stateId)
|
||||
}
|
||||
triggerStateChanged()
|
||||
}
|
||||
}
|
||||
MotionEvent.ACTION_MOVE -> {
|
||||
val changed = pointerTouches.entries.fold(false) { acc, it ->
|
||||
val index = event.findPointerIndex(it.key)
|
||||
if(index < 0)
|
||||
acc
|
||||
else
|
||||
{
|
||||
it.value.onMove(event.getX(event.actionIndex), event.getY(event.actionIndex))
|
||||
acc || state.setTouchPos(it.value.stateId, touchX(event, index), touchY(event, index))
|
||||
}
|
||||
}
|
||||
if(changed)
|
||||
triggerStateChanged()
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun triggerShortButtonPress(touch: Touch)
|
||||
{
|
||||
shortPressingTouches = shortPressingTouches + listOf(touch)
|
||||
removeCallbacks(shortButtonPressLiftRunnable)
|
||||
state.buttons = state.buttons or ControllerState.BUTTON_TOUCHPAD
|
||||
postDelayed(shortButtonPressLiftRunnable, SHORT_BUTTON_PRESS_DURATION_MS)
|
||||
}
|
||||
|
||||
private fun triggerStateChanged()
|
||||
{
|
||||
invalidate()
|
||||
stateSubject.onNext(state)
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
package com.metallic.chiaki.touchcontrols
|
||||
|
||||
import android.view.View
|
||||
import kotlin.math.sqrt
|
||||
|
||||
data class Vector(val x: Float, val y: Float)
|
||||
|
@ -18,4 +19,10 @@ data class Vector(val x: Float, val y: Float)
|
|||
val lengthSq get() = x*x + y*y
|
||||
val length get() = sqrt(lengthSq)
|
||||
val normalized get() = this / length
|
||||
}
|
||||
|
||||
val View.locationOnScreen: Vector get() {
|
||||
val v = intArrayOf(0, 0)
|
||||
this.getLocationOnScreen(v)
|
||||
return Vector(v[0].toFloat(), v[1].toFloat())
|
||||
}
|
|
@ -1,13 +1,12 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="256dp"
|
||||
android:height="128dp"
|
||||
android:height="256dp"
|
||||
android:viewportWidth="67.73333"
|
||||
android:viewportHeight="33.86667">
|
||||
android:viewportHeight="67.73334">
|
||||
<path
|
||||
android:pathData="M0,0L0,33.8667L67.7333,33.8667L67.7333,0ZM21.7852,8.2563l2.3337,0L24.1189,23.6745L31.89,23.6745L31.89,25.8299L21.7852,25.8299ZM40.6771,8.2563l2.3342,0L43.0113,25.8299l-2.3342,0L40.6771,11.5512l-3.1853,3.1853 -1.6474,-1.6474z"
|
||||
android:pathData="M39.2255,0 L0,39.2255 20.3838,59.6093a27.7366,27.7366 88.4859,0 0,39.2255 0,27.7366 27.7366,88.4859 0,0 0,-39.2255zM25.4129,29.4287l2.7735,0l0,18.1643l9.9818,0l0,2.3342L25.4129,49.9272ZM46.3098,29.4287l2.7735,0l0,18.1643l4.5305,0l0,2.3342l-11.8076,0l0,-2.3342l4.531,0l0,-15.6383l-4.9289,0.9886l0,-2.5259z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="23.7399"
|
||||
android:strokeWidth="5.54109"
|
||||
android:fillColor="@color/control_primary"
|
||||
android:strokeColor="#00000000"
|
||||
android:strokeLineCap="round"/>
|
||||
</vector>
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="256dp"
|
||||
android:height="128dp"
|
||||
android:height="256dp"
|
||||
android:viewportWidth="67.73333"
|
||||
android:viewportHeight="33.86667">
|
||||
android:viewportHeight="67.73334">
|
||||
<path
|
||||
android:pathData="M0,0L0,33.8667L67.7333,33.8667L67.7333,0ZM21.7852,8.2563l2.3337,0L24.1189,23.6745L31.89,23.6745L31.89,25.8299L21.7852,25.8299ZM40.6771,8.2563l2.3342,0L43.0113,25.8299l-2.3342,0L40.6771,11.5512l-3.1853,3.1853 -1.6474,-1.6474z"
|
||||
android:pathData="M39.2255,0 L0,39.2255 20.3838,59.6093a27.7366,27.7366 88.4859,0 0,39.2255 0,27.7366 27.7366,88.4859 0,0 0,-39.2255zM25.4129,29.4287l2.7735,0l0,18.1643l9.9818,0l0,2.3342L25.4129,49.9272ZM46.3098,29.4287l2.7735,0l0,18.1643l4.5305,0l0,2.3342l-11.8076,0l0,-2.3342l4.531,0l0,-15.6383l-4.9289,0.9886l0,-2.5259z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="23.7399"
|
||||
android:strokeWidth="5.54109"
|
||||
android:fillColor="@color/control_pressed"
|
||||
android:strokeColor="#00000000"
|
||||
android:strokeLineCap="round"/>
|
||||
</vector>
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="256dp"
|
||||
android:height="128dp"
|
||||
android:height="256dp"
|
||||
android:viewportWidth="67.73333"
|
||||
android:viewportHeight="33.86667">
|
||||
android:viewportHeight="67.73334">
|
||||
<path
|
||||
android:pathData="M0,0L0,33.8667L67.7333,33.8667L67.7333,0ZM40.6771,8.0367c1.556,0 2.7872,0.3659 3.6933,1.0981 0.9062,0.7322 1.3591,1.7348 1.3591,3.0071 0,0.4027 -0.0139,0.7136 -0.0413,0.9333 -0.0183,0.2105 -0.0867,0.4989 -0.2057,0.8651 -0.1098,0.357 -0.3021,0.7506 -0.5767,1.1808 -0.2746,0.421 -0.6453,0.9242 -1.1121,1.51l-5.6291,7.0435l7.7845,0L45.9491,25.8299l-10.5441,0l0,-2.1554l6.6999,-8.3886c0.4119,-0.5126 0.7142,-0.9612 0.9064,-1.3457 0.1922,-0.3936 0.3017,-0.6911 0.3292,-0.8925 0.0366,-0.2105 0.0548,-0.5123 0.0548,-0.9059 0,-0.6041 -0.2425,-1.0805 -0.7276,-1.4283 -0.4851,-0.3478 -1.1485,-0.5214 -1.9906,-0.5214 -0.8421,0 -1.506,0.1736 -1.9911,0.5214 -0.4851,0.3478 -0.7276,0.8242 -0.7276,1.4283l-2.3337,-0.371c0,-1.1533 0.4529,-2.064 1.3591,-2.7321 0.9062,-0.6682 2.1373,-1.002 3.6933,-1.002zM21.7852,8.2563l2.3337,0L24.1189,23.6745L31.89,23.6745L31.89,25.8299L21.7852,25.8299Z"
|
||||
android:pathData="m27.6526,0a27.7366,27.7366 88.4859,0 0,-19.5285 8.1241,27.7366 27.7366,88.4859 0,0 0,39.2255L28.5078,67.7333 67.7333,28.5078 47.3496,8.1241A27.7366,27.7366 88.4859,0 0,27.6526 0ZM34.9017,15.1846c2.1235,0 3.8172,0.5309 5.0803,1.5927 1.2631,1.0618 1.8945,2.4804 1.8945,4.2561 0,0.8421 -0.1602,1.6432 -0.4806,2.403 -0.3112,0.7506 -0.8832,1.6383 -1.7162,2.6634 -0.2288,0.2654 -0.9563,1.034 -2.1828,2.3063 -1.2265,1.2631 -2.9565,3.0342 -5.1899,5.3134l9.6795,0l0,2.3342l-13.0157,0l0,-2.3342c1.0526,-1.0892 2.4851,-2.549 4.2974,-4.3796 1.8215,-1.8398 2.9655,-3.025 3.4323,-3.5559 0.8879,-0.9977 1.5058,-1.84 1.8536,-2.5265 0.357,-0.6956 0.5354,-1.3777 0.5354,-2.0459 0,-1.0892 -0.3846,-1.9769 -1.1534,-2.6634 -0.7597,-0.6865 -1.7526,-1.0299 -2.9791,-1.0299 -0.8695,-0 -1.7898,0.1511 -2.76,0.4532 -0.9611,0.3021 -1.9908,0.7598 -3.0892,1.373L29.1078,16.5437c1.1167,-0.4485 2.1603,-0.7871 3.1306,-1.016 0.9702,-0.2288 1.8579,-0.3431 2.6634,-0.3431zM14.0053,15.5551l2.7735,0l0,18.1643l9.9813,0l0,2.3342L14.0053,36.0536Z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="23.7399"
|
||||
android:strokeWidth="5.54109"
|
||||
android:fillColor="@color/control_primary"
|
||||
android:strokeColor="#00000000"
|
||||
android:strokeLineCap="round"/>
|
||||
</vector>
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="256dp"
|
||||
android:height="128dp"
|
||||
android:height="256dp"
|
||||
android:viewportWidth="67.73333"
|
||||
android:viewportHeight="33.86667">
|
||||
android:viewportHeight="67.73334">
|
||||
<path
|
||||
android:pathData="M0,0L0,33.8667L67.7333,33.8667L67.7333,0ZM40.6771,8.0367c1.556,0 2.7872,0.3659 3.6933,1.0981 0.9062,0.7322 1.3591,1.7348 1.3591,3.0071 0,0.4027 -0.0139,0.7136 -0.0413,0.9333 -0.0183,0.2105 -0.0867,0.4989 -0.2057,0.8651 -0.1098,0.357 -0.3021,0.7506 -0.5767,1.1808 -0.2746,0.421 -0.6453,0.9242 -1.1121,1.51l-5.6291,7.0435l7.7845,0L45.9491,25.8299l-10.5441,0l0,-2.1554l6.6999,-8.3886c0.4119,-0.5126 0.7142,-0.9612 0.9064,-1.3457 0.1922,-0.3936 0.3017,-0.6911 0.3292,-0.8925 0.0366,-0.2105 0.0548,-0.5123 0.0548,-0.9059 0,-0.6041 -0.2425,-1.0805 -0.7276,-1.4283 -0.4851,-0.3478 -1.1485,-0.5214 -1.9906,-0.5214 -0.8421,0 -1.506,0.1736 -1.9911,0.5214 -0.4851,0.3478 -0.7276,0.8242 -0.7276,1.4283l-2.3337,-0.371c0,-1.1533 0.4529,-2.064 1.3591,-2.7321 0.9062,-0.6682 2.1373,-1.002 3.6933,-1.002zM21.7852,8.2563l2.3337,0L24.1189,23.6745L31.89,23.6745L31.89,25.8299L21.7852,25.8299Z"
|
||||
android:pathData="m27.6526,0a27.7366,27.7366 88.4859,0 0,-19.5285 8.1241,27.7366 27.7366,88.4859 0,0 0,39.2255L28.5078,67.7333 67.7333,28.5078 47.3496,8.1241A27.7366,27.7366 88.4859,0 0,27.6526 0ZM34.9017,15.1846c2.1235,0 3.8172,0.5309 5.0803,1.5927 1.2631,1.0618 1.8945,2.4804 1.8945,4.2561 0,0.8421 -0.1602,1.6432 -0.4806,2.403 -0.3112,0.7506 -0.8832,1.6383 -1.7162,2.6634 -0.2288,0.2654 -0.9563,1.034 -2.1828,2.3063 -1.2265,1.2631 -2.9565,3.0342 -5.1899,5.3134l9.6795,0l0,2.3342l-13.0157,0l0,-2.3342c1.0526,-1.0892 2.4851,-2.549 4.2974,-4.3796 1.8215,-1.8398 2.9655,-3.025 3.4323,-3.5559 0.8879,-0.9977 1.5058,-1.84 1.8536,-2.5265 0.357,-0.6956 0.5354,-1.3777 0.5354,-2.0459 0,-1.0892 -0.3846,-1.9769 -1.1534,-2.6634 -0.7597,-0.6865 -1.7526,-1.0299 -2.9791,-1.0299 -0.8695,-0 -1.7898,0.1511 -2.76,0.4532 -0.9611,0.3021 -1.9908,0.7598 -3.0892,1.373L29.1078,16.5437c1.1167,-0.4485 2.1603,-0.7871 3.1306,-1.016 0.9702,-0.2288 1.8579,-0.3431 2.6634,-0.3431zM14.0053,15.5551l2.7735,0l0,18.1643l9.9813,0l0,2.3342L14.0053,36.0536Z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="23.7399"
|
||||
android:strokeWidth="5.54109"
|
||||
android:fillColor="@color/control_pressed"
|
||||
android:strokeColor="#00000000"
|
||||
android:strokeLineCap="round"/>
|
||||
</vector>
|
||||
|
|
12
android/app/src/main/res/drawable/control_button_l3.xml
Normal file
|
@ -0,0 +1,12 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="256dp"
|
||||
android:height="256dp"
|
||||
android:viewportWidth="67.73333"
|
||||
android:viewportHeight="67.73334">
|
||||
<path
|
||||
android:pathData="M0,0 L-41.939,102.093 67.7333,67.7333C67.7333,30.3253 37.4081,0 0,0ZM33.6093,31.3252c2.1052,0 3.7711,0.4807 4.9976,1.4418 1.2265,0.9519 1.8397,2.2423 1.8397,3.8716 0,1.135 -0.3253,2.0964 -0.9751,2.8835 -0.6499,0.778 -1.5739,1.318 -2.773,1.6201 1.3272,0.2837 2.3613,0.8739 3.1027,1.771 0.7506,0.897 1.126,2.0047 1.126,3.3228 0,2.0228 -0.6959,3.5878 -2.0872,4.6953 -1.3913,1.1075 -3.368,1.6614 -5.9309,1.6614 -0.8604,0 -1.7486,-0.0871 -2.6639,-0.261 -0.9062,-0.1648 -1.8441,-0.4163 -2.8143,-0.755l0,-2.6774c0.7689,0.4485 1.6106,0.7871 2.5259,1.016 0.9153,0.2288 1.8719,0.3431 2.8696,0.3431 1.7391,0 3.0621,-0.3434 3.9682,-1.0299 0.9153,-0.6865 1.3725,-1.6837 1.3725,-2.9926 0,-1.2082 -0.4252,-2.1514 -1.2764,-2.8288 -0.8421,-0.6865 -2.0187,-1.0294 -3.529,-1.0294l-2.3885,0l0,-2.2794l2.4986,0c1.3638,0 2.4075,-0.2697 3.1306,-0.8098 0.7231,-0.5492 1.0847,-1.3365 1.0847,-2.3616 0,-1.0526 -0.3755,-1.858 -1.126,-2.4164 -0.7414,-0.5675 -1.808,-0.8511 -3.1993,-0.8511 -0.7597,0 -1.5742,0.0823 -2.4438,0.247 -0.8695,0.1648 -1.8261,0.4211 -2.8696,0.7689l0,-2.4717c1.0526,-0.2929 2.037,-0.5124 2.9523,-0.6589 0.9245,-0.1464 1.794,-0.2196 2.6086,-0.2196zM12.3832,31.6957l2.7735,0l0,18.1648l9.9813,0l0,2.3337L12.3832,52.1942Z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="11.0688"
|
||||
android:fillColor="@color/control_primary"
|
||||
android:strokeLineCap="round"/>
|
||||
</vector>
|
|
@ -0,0 +1,12 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="256dp"
|
||||
android:height="256dp"
|
||||
android:viewportWidth="67.73333"
|
||||
android:viewportHeight="67.73334">
|
||||
<path
|
||||
android:pathData="M0,0 L-41.939,102.093 67.7333,67.7333C67.7333,30.3253 37.4081,0 0,0ZM33.6093,31.3252c2.1052,0 3.7711,0.4807 4.9976,1.4418 1.2265,0.9519 1.8397,2.2423 1.8397,3.8716 0,1.135 -0.3253,2.0964 -0.9751,2.8835 -0.6499,0.778 -1.5739,1.318 -2.773,1.6201 1.3272,0.2837 2.3613,0.8739 3.1027,1.771 0.7506,0.897 1.126,2.0047 1.126,3.3228 0,2.0228 -0.6959,3.5878 -2.0872,4.6953 -1.3913,1.1075 -3.368,1.6614 -5.9309,1.6614 -0.8604,0 -1.7486,-0.0871 -2.6639,-0.261 -0.9062,-0.1648 -1.8441,-0.4163 -2.8143,-0.755l0,-2.6774c0.7689,0.4485 1.6106,0.7871 2.5259,1.016 0.9153,0.2288 1.8719,0.3431 2.8696,0.3431 1.7391,0 3.0621,-0.3434 3.9682,-1.0299 0.9153,-0.6865 1.3725,-1.6837 1.3725,-2.9926 0,-1.2082 -0.4252,-2.1514 -1.2764,-2.8288 -0.8421,-0.6865 -2.0187,-1.0294 -3.529,-1.0294l-2.3885,0l0,-2.2794l2.4986,0c1.3638,0 2.4075,-0.2697 3.1306,-0.8098 0.7231,-0.5492 1.0847,-1.3365 1.0847,-2.3616 0,-1.0526 -0.3755,-1.858 -1.126,-2.4164 -0.7414,-0.5675 -1.808,-0.8511 -3.1993,-0.8511 -0.7597,0 -1.5742,0.0823 -2.4438,0.247 -0.8695,0.1648 -1.8261,0.4211 -2.8696,0.7689l0,-2.4717c1.0526,-0.2929 2.037,-0.5124 2.9523,-0.6589 0.9245,-0.1464 1.794,-0.2196 2.6086,-0.2196zM12.3832,31.6957l2.7735,0l0,18.1648l9.9813,0l0,2.3337L12.3832,52.1942Z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="11.0688"
|
||||
android:fillColor="@color/control_pressed"
|
||||
android:strokeLineCap="round"/>
|
||||
</vector>
|
|
@ -1,13 +1,12 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="256dp"
|
||||
android:height="128dp"
|
||||
android:height="256dp"
|
||||
android:viewportWidth="67.73333"
|
||||
android:viewportHeight="33.86667">
|
||||
android:viewportHeight="67.73334">
|
||||
<path
|
||||
android:pathData="M0,0L0,33.8667L67.7333,33.8667L67.7333,0ZM21.3455,8.2563L27.4417,8.2563c1.5286,0 2.6865,0.352 3.4737,1.0568 0.7963,0.7048 1.1942,1.8814 1.1942,3.529 -0,2.2517 -1.034,3.6703 -3.1027,4.2561L32.7685,25.8299L30.2286,25.8299L26.618,17.4413L23.6797,17.4413L23.6797,25.8299l-2.3342,0zM40.6771,8.2563l2.3342,0L43.0113,25.8299l-2.3342,0L40.6771,11.5512l-3.1853,3.1853 -1.6474,-1.6474zM23.6797,10.4118l0,4.8741l2.3342,0c1.2265,0 2.1601,-0.188 2.8009,-0.5633 0.6407,-0.3753 0.9607,-1.0018 0.9607,-1.8805 0,-0.8695 -0.2014,-1.4923 -0.6041,-1.8676 -0.3936,-0.3753 -0.9699,-0.5628 -1.7296,-0.5628z"
|
||||
android:pathData="M28.5078,0 L8.1241,20.3838a27.7366,27.7366 88.4859,0 0,0 39.2255,27.7366 27.7366,88.4859 0,0 39.2255,0L67.7333,39.2255ZM12.4178,29.4287l6.2606,0c2.3432,0 4.0913,0.4898 5.2446,1.4692 1.1533,0.9794 1.7301,2.4573 1.7301,4.4344 0,1.2906 -0.3018,2.3615 -0.9059,3.2127 -0.595,0.8512 -1.4645,1.442 -2.6086,1.7715 0.595,0.2014 1.1713,0.6313 1.7296,1.2904 0.5675,0.659 1.1352,1.5654 1.7027,2.7187L28.3853,49.9272L25.4062,49.9272l-2.6226,-5.2586C22.1063,43.2956 21.4472,42.385 20.8065,41.9365c-0.6316,-0.4485 -1.4963,-0.6728 -2.5947,-0.6728L15.1913,41.2636l0,8.6636L12.4178,49.9272ZM37.1864,29.4287l2.7735,0l0,18.1643l4.5305,0l0,2.3342l-11.8075,0l0,-2.3342l4.531,0l0,-15.6383l-4.9289,0.9886l0,-2.5259zM15.1913,31.7076l0,7.2766l3.4871,0c1.3364,0 2.3432,-0.3066 3.0205,-0.9198 0.6865,-0.6224 1.0299,-1.5331 1.0299,-2.7321 0,-1.1991 -0.3434,-2.1006 -1.0299,-2.7047 -0.6773,-0.6133 -1.6841,-0.9198 -3.0205,-0.9198z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="23.7399"
|
||||
android:strokeWidth="5.54109"
|
||||
android:fillColor="@color/control_primary"
|
||||
android:strokeColor="#00000000"
|
||||
android:strokeLineCap="round"/>
|
||||
</vector>
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="256dp"
|
||||
android:height="128dp"
|
||||
android:height="256dp"
|
||||
android:viewportWidth="67.73333"
|
||||
android:viewportHeight="33.86667">
|
||||
android:viewportHeight="67.73334">
|
||||
<path
|
||||
android:pathData="M0,0L0,33.8667L67.7333,33.8667L67.7333,0ZM21.3455,8.2563L27.4417,8.2563c1.5286,0 2.6865,0.352 3.4737,1.0568 0.7963,0.7048 1.1942,1.8814 1.1942,3.529 -0,2.2517 -1.034,3.6703 -3.1027,4.2561L32.7685,25.8299L30.2286,25.8299L26.618,17.4413L23.6797,17.4413L23.6797,25.8299l-2.3342,0zM40.6771,8.2563l2.3342,0L43.0113,25.8299l-2.3342,0L40.6771,11.5512l-3.1853,3.1853 -1.6474,-1.6474zM23.6797,10.4118l0,4.8741l2.3342,0c1.2265,0 2.1601,-0.188 2.8009,-0.5633 0.6407,-0.3753 0.9607,-1.0018 0.9607,-1.8805 0,-0.8695 -0.2014,-1.4923 -0.6041,-1.8676 -0.3936,-0.3753 -0.9699,-0.5628 -1.7296,-0.5628z"
|
||||
android:pathData="M28.5078,0 L8.1241,20.3838a27.7366,27.7366 88.4859,0 0,0 39.2255,27.7366 27.7366,88.4859 0,0 39.2255,0L67.7333,39.2255ZM12.4178,29.4287l6.2606,0c2.3432,0 4.0913,0.4898 5.2446,1.4692 1.1533,0.9794 1.7301,2.4573 1.7301,4.4344 0,1.2906 -0.3018,2.3615 -0.9059,3.2127 -0.595,0.8512 -1.4645,1.442 -2.6086,1.7715 0.595,0.2014 1.1713,0.6313 1.7296,1.2904 0.5675,0.659 1.1352,1.5654 1.7027,2.7187L28.3853,49.9272L25.4062,49.9272l-2.6226,-5.2586C22.1063,43.2956 21.4472,42.385 20.8065,41.9365c-0.6316,-0.4485 -1.4963,-0.6728 -2.5947,-0.6728L15.1913,41.2636l0,8.6636L12.4178,49.9272ZM37.1864,29.4287l2.7735,0l0,18.1643l4.5305,0l0,2.3342l-11.8075,0l0,-2.3342l4.531,0l0,-15.6383l-4.9289,0.9886l0,-2.5259zM15.1913,31.7076l0,7.2766l3.4871,0c1.3364,0 2.3432,-0.3066 3.0205,-0.9198 0.6865,-0.6224 1.0299,-1.5331 1.0299,-2.7321 0,-1.1991 -0.3434,-2.1006 -1.0299,-2.7047 -0.6773,-0.6133 -1.6841,-0.9198 -3.0205,-0.9198z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="23.7399"
|
||||
android:strokeWidth="5.54109"
|
||||
android:fillColor="@color/control_pressed"
|
||||
android:strokeColor="#00000000"
|
||||
android:strokeLineCap="round"/>
|
||||
</vector>
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="256dp"
|
||||
android:height="128dp"
|
||||
android:height="256dp"
|
||||
android:viewportWidth="67.73333"
|
||||
android:viewportHeight="33.86667">
|
||||
android:viewportHeight="67.73334">
|
||||
<path
|
||||
android:pathData="M0,0L0,33.8667L67.7333,33.8667L67.7333,0ZM40.6771,8.0367c1.556,0 2.7872,0.3659 3.6933,1.0981 0.9062,0.7322 1.3591,1.7348 1.3591,3.0071 0,0.4027 -0.0139,0.7136 -0.0413,0.9333 -0.0183,0.2105 -0.0867,0.4989 -0.2057,0.8651 -0.1098,0.357 -0.3021,0.7506 -0.5767,1.1808 -0.2746,0.421 -0.6453,0.9242 -1.1121,1.51l-5.6291,7.0435l7.7845,0L45.9491,25.8299l-10.5441,0l0,-2.1554l6.6999,-8.3886c0.4119,-0.5126 0.7142,-0.9612 0.9064,-1.3457 0.1922,-0.3936 0.3017,-0.6911 0.3292,-0.8925 0.0366,-0.2105 0.0548,-0.5123 0.0548,-0.9059 0,-0.6041 -0.2425,-1.0805 -0.7276,-1.4283 -0.4851,-0.3478 -1.1485,-0.5214 -1.9906,-0.5214 -0.8421,0 -1.506,0.1736 -1.9911,0.5214 -0.4851,0.3478 -0.7276,0.8242 -0.7276,1.4283l-2.3337,-0.371c0,-1.1533 0.4529,-2.064 1.3591,-2.7321C37.8899,8.3705 39.1211,8.0367 40.6771,8.0367ZM21.3455,8.2563L27.4417,8.2563c1.5286,0 2.6865,0.352 3.4737,1.0568 0.7963,0.7048 1.1942,1.8814 1.1942,3.529 -0,2.2517 -1.034,3.6703 -3.1027,4.2561L32.7685,25.8299L30.2286,25.8299L26.618,17.4413L23.6797,17.4413L23.6797,25.8299l-2.3342,0zM23.6797,10.4118l0,4.8741l2.3342,0c1.2265,0 2.1601,-0.188 2.8009,-0.5633 0.6407,-0.3753 0.9607,-1.0018 0.9607,-1.8805 0,-0.8695 -0.2014,-1.4923 -0.6041,-1.8676 -0.3936,-0.3753 -0.9699,-0.5628 -1.7296,-0.5628z"
|
||||
android:pathData="M20.3838,8.1241 L0,28.5078 39.2255,67.7333 59.6093,47.3496a27.7366,27.7366 88.4859,0 0,0 -39.2255,27.7366 27.7366,88.4859 0,0 -39.2255,0zM48.9278,15.1846c2.1235,0 3.8167,0.5309 5.0798,1.5927 1.2631,1.0618 1.895,2.4804 1.895,4.2561 0,0.8421 -0.1602,1.6432 -0.4806,2.403 -0.3112,0.7506 -0.8832,1.6383 -1.7162,2.6634 -0.2288,0.2654 -0.9568,1.034 -2.1833,2.3063 -1.2265,1.2631 -2.956,3.0342 -5.1893,5.3134l9.679,0l0,2.3342l-13.0157,0l0,-2.3342c1.0526,-1.0892 2.4851,-2.549 4.2974,-4.3796 1.8215,-1.8398 2.9655,-3.025 3.4323,-3.5559 0.8879,-0.9977 1.5058,-1.84 1.8536,-2.5265 0.357,-0.6956 0.5354,-1.3777 0.5354,-2.0459 0,-1.0892 -0.384,-1.9769 -1.1529,-2.6634 -0.7597,-0.6865 -1.7531,-1.0299 -2.9797,-1.0299 -0.8695,-0 -1.7893,0.1511 -2.7595,0.4532 -0.9611,0.3021 -1.9908,0.7598 -3.0892,1.373L43.1338,16.5437c1.1167,-0.4485 2.1603,-0.7871 3.1306,-1.016 0.9702,-0.2288 1.8579,-0.3431 2.6634,-0.3431zM24.1593,15.5551l6.2611,0c2.3432,0 4.0913,0.4898 5.2446,1.4692 1.1533,0.9794 1.7296,2.4578 1.7296,4.4349 0,1.2906 -0.3018,2.3615 -0.9059,3.2127 -0.595,0.8512 -1.4645,1.4414 -2.6086,1.771 0.595,0.2014 1.1713,0.6313 1.7296,1.2904 0.5675,0.659 1.1352,1.5654 1.7027,2.7187l2.8148,5.6017l-2.9797,0l-2.6221,-5.2586c-0.6773,-1.373 -1.3364,-2.2836 -1.9771,-2.7321 -0.6316,-0.4485 -1.4968,-0.6728 -2.5952,-0.6728l-3.0205,0l0,8.6636L24.1593,36.0536ZM26.9327,17.8346l0,7.2766l3.4876,0c1.3364,0 2.3432,-0.3066 3.0205,-0.9198 0.6865,-0.6224 1.0294,-1.5331 1.0294,-2.7321 0,-1.1991 -0.3429,-2.1006 -1.0294,-2.7047 -0.6773,-0.6133 -1.6841,-0.9198 -3.0205,-0.9198z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="23.7399"
|
||||
android:strokeWidth="5.54109"
|
||||
android:fillColor="@color/control_primary"
|
||||
android:strokeColor="#00000000"
|
||||
android:strokeLineCap="round"/>
|
||||
</vector>
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="256dp"
|
||||
android:height="128dp"
|
||||
android:height="256dp"
|
||||
android:viewportWidth="67.73333"
|
||||
android:viewportHeight="33.86667">
|
||||
android:viewportHeight="67.73334">
|
||||
<path
|
||||
android:pathData="M0,0L0,33.8667L67.7333,33.8667L67.7333,0ZM40.6771,8.0367c1.556,0 2.7872,0.3659 3.6933,1.0981 0.9062,0.7322 1.3591,1.7348 1.3591,3.0071 0,0.4027 -0.0139,0.7136 -0.0413,0.9333 -0.0183,0.2105 -0.0867,0.4989 -0.2057,0.8651 -0.1098,0.357 -0.3021,0.7506 -0.5767,1.1808 -0.2746,0.421 -0.6453,0.9242 -1.1121,1.51l-5.6291,7.0435l7.7845,0L45.9491,25.8299l-10.5441,0l0,-2.1554l6.6999,-8.3886c0.4119,-0.5126 0.7142,-0.9612 0.9064,-1.3457 0.1922,-0.3936 0.3017,-0.6911 0.3292,-0.8925 0.0366,-0.2105 0.0548,-0.5123 0.0548,-0.9059 0,-0.6041 -0.2425,-1.0805 -0.7276,-1.4283 -0.4851,-0.3478 -1.1485,-0.5214 -1.9906,-0.5214 -0.8421,0 -1.506,0.1736 -1.9911,0.5214 -0.4851,0.3478 -0.7276,0.8242 -0.7276,1.4283l-2.3337,-0.371c0,-1.1533 0.4529,-2.064 1.3591,-2.7321C37.8899,8.3705 39.1211,8.0367 40.6771,8.0367ZM21.3455,8.2563L27.4417,8.2563c1.5286,0 2.6865,0.352 3.4737,1.0568 0.7963,0.7048 1.1942,1.8814 1.1942,3.529 -0,2.2517 -1.034,3.6703 -3.1027,4.2561L32.7685,25.8299L30.2286,25.8299L26.618,17.4413L23.6797,17.4413L23.6797,25.8299l-2.3342,0zM23.6797,10.4118l0,4.8741l2.3342,0c1.2265,0 2.1601,-0.188 2.8009,-0.5633 0.6407,-0.3753 0.9607,-1.0018 0.9607,-1.8805 0,-0.8695 -0.2014,-1.4923 -0.6041,-1.8676 -0.3936,-0.3753 -0.9699,-0.5628 -1.7296,-0.5628z"
|
||||
android:pathData="M20.3838,8.1241 L0,28.5078 39.2255,67.7333 59.6093,47.3496a27.7366,27.7366 88.4859,0 0,0 -39.2255,27.7366 27.7366,88.4859 0,0 -39.2255,0zM48.9278,15.1846c2.1235,0 3.8167,0.5309 5.0798,1.5927 1.2631,1.0618 1.895,2.4804 1.895,4.2561 0,0.8421 -0.1602,1.6432 -0.4806,2.403 -0.3112,0.7506 -0.8832,1.6383 -1.7162,2.6634 -0.2288,0.2654 -0.9568,1.034 -2.1833,2.3063 -1.2265,1.2631 -2.956,3.0342 -5.1893,5.3134l9.679,0l0,2.3342l-13.0157,0l0,-2.3342c1.0526,-1.0892 2.4851,-2.549 4.2974,-4.3796 1.8215,-1.8398 2.9655,-3.025 3.4323,-3.5559 0.8879,-0.9977 1.5058,-1.84 1.8536,-2.5265 0.357,-0.6956 0.5354,-1.3777 0.5354,-2.0459 0,-1.0892 -0.384,-1.9769 -1.1529,-2.6634 -0.7597,-0.6865 -1.7531,-1.0299 -2.9797,-1.0299 -0.8695,-0 -1.7893,0.1511 -2.7595,0.4532 -0.9611,0.3021 -1.9908,0.7598 -3.0892,1.373L43.1338,16.5437c1.1167,-0.4485 2.1603,-0.7871 3.1306,-1.016 0.9702,-0.2288 1.8579,-0.3431 2.6634,-0.3431zM24.1593,15.5551l6.2611,0c2.3432,0 4.0913,0.4898 5.2446,1.4692 1.1533,0.9794 1.7296,2.4578 1.7296,4.4349 0,1.2906 -0.3018,2.3615 -0.9059,3.2127 -0.595,0.8512 -1.4645,1.4414 -2.6086,1.771 0.595,0.2014 1.1713,0.6313 1.7296,1.2904 0.5675,0.659 1.1352,1.5654 1.7027,2.7187l2.8148,5.6017l-2.9797,0l-2.6221,-5.2586c-0.6773,-1.373 -1.3364,-2.2836 -1.9771,-2.7321 -0.6316,-0.4485 -1.4968,-0.6728 -2.5952,-0.6728l-3.0205,0l0,8.6636L24.1593,36.0536ZM26.9327,17.8346l0,7.2766l3.4876,0c1.3364,0 2.3432,-0.3066 3.0205,-0.9198 0.6865,-0.6224 1.0294,-1.5331 1.0294,-2.7321 0,-1.1991 -0.3429,-2.1006 -1.0294,-2.7047 -0.6773,-0.6133 -1.6841,-0.9198 -3.0205,-0.9198z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="23.7399"
|
||||
android:strokeWidth="5.54109"
|
||||
android:fillColor="@color/control_pressed"
|
||||
android:strokeColor="#00000000"
|
||||
android:strokeLineCap="round"/>
|
||||
</vector>
|
||||
|
|
12
android/app/src/main/res/drawable/control_button_r3.xml
Normal file
|
@ -0,0 +1,12 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="256dp"
|
||||
android:height="256dp"
|
||||
android:viewportWidth="67.73333"
|
||||
android:viewportHeight="67.73334">
|
||||
<path
|
||||
android:pathData="M67.7333,0C30.3252,0 0,30.3252 0,67.7333l109.6724,34.3597zM50.2982,31.3252c2.1052,0 3.7711,0.4807 4.9976,1.4418 1.2265,0.9519 1.8402,2.2423 1.8402,3.8716 0,1.135 -0.3253,2.0964 -0.9751,2.8835 -0.6499,0.778 -1.5744,1.318 -2.7735,1.6201 1.3272,0.2837 2.3618,0.8739 3.1032,1.771 0.7506,0.897 1.1255,2.0047 1.1255,3.3228 0,2.0228 -0.6954,3.5878 -2.0867,4.6953 -1.3913,1.1075 -3.3685,1.6614 -5.9314,1.6614 -0.8604,0 -1.7481,-0.0871 -2.6634,-0.261 -0.9062,-0.1648 -1.8441,-0.4163 -2.8143,-0.755l0,-2.6774c0.7689,0.4485 1.6106,0.7871 2.5259,1.016 0.9153,0.2288 1.8719,0.3431 2.8696,0.3431 1.7391,0 3.0616,-0.3434 3.9677,-1.0299 0.9153,-0.6865 1.373,-1.6837 1.373,-2.9926 0,-1.2082 -0.4257,-2.1514 -1.2769,-2.8288 -0.8421,-0.6865 -2.0182,-1.0294 -3.5285,-1.0294l-2.389,0l0,-2.2794l2.4991,0c1.3638,0 2.4069,-0.2697 3.13,-0.8098 0.7231,-0.5492 1.0847,-1.3365 1.0847,-2.3616 0,-1.0526 -0.375,-1.858 -1.1255,-2.4164 -0.7414,-0.5675 -1.808,-0.8511 -3.1993,-0.8511 -0.7597,0 -1.5742,0.0823 -2.4438,0.247 -0.8695,0.1648 -1.8261,0.4211 -2.8696,0.7689l0,-2.4717c1.0526,-0.2929 2.0364,-0.5124 2.9518,-0.6589 0.9245,-0.1464 1.794,-0.2196 2.6086,-0.2196zM25.2005,31.6957L31.4611,31.6957c2.3432,0 4.0913,0.4898 5.2446,1.4692 1.1533,0.9794 1.7301,2.4578 1.7301,4.4349 0,1.2906 -0.3018,2.3615 -0.9059,3.2127 -0.595,0.8512 -1.4645,1.4414 -2.6086,1.771 0.595,0.2014 1.1713,0.6319 1.7296,1.2909 0.5675,0.659 1.1352,1.5649 1.7027,2.7182l2.8143,5.6017l-2.9791,0l-2.6226,-5.2581c-0.6773,-1.373 -1.3364,-2.2841 -1.9771,-2.7326 -0.6316,-0.4485 -1.4963,-0.6723 -2.5947,-0.6723l-3.0205,0l0,8.663L25.2005,52.1942ZM27.974,33.9752l0,7.2766l3.4871,0c1.3364,0 2.3432,-0.3066 3.0205,-0.9198 0.6865,-0.6224 1.0299,-1.5331 1.0299,-2.7321 0,-1.1991 -0.3434,-2.1006 -1.0299,-2.7047 -0.6773,-0.6133 -1.6841,-0.9198 -3.0205,-0.9198z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="11.0688"
|
||||
android:fillColor="@color/control_primary"
|
||||
android:strokeLineCap="round"/>
|
||||
</vector>
|
|
@ -0,0 +1,12 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="256dp"
|
||||
android:height="256dp"
|
||||
android:viewportWidth="67.73333"
|
||||
android:viewportHeight="67.73334">
|
||||
<path
|
||||
android:pathData="M67.7333,0C30.3252,0 0,30.3252 0,67.7333l109.6724,34.3597zM50.2982,31.3252c2.1052,0 3.7711,0.4807 4.9976,1.4418 1.2265,0.9519 1.8402,2.2423 1.8402,3.8716 0,1.135 -0.3253,2.0964 -0.9751,2.8835 -0.6499,0.778 -1.5744,1.318 -2.7735,1.6201 1.3272,0.2837 2.3618,0.8739 3.1032,1.771 0.7506,0.897 1.1255,2.0047 1.1255,3.3228 0,2.0228 -0.6954,3.5878 -2.0867,4.6953 -1.3913,1.1075 -3.3685,1.6614 -5.9314,1.6614 -0.8604,0 -1.7481,-0.0871 -2.6634,-0.261 -0.9062,-0.1648 -1.8441,-0.4163 -2.8143,-0.755l0,-2.6774c0.7689,0.4485 1.6106,0.7871 2.5259,1.016 0.9153,0.2288 1.8719,0.3431 2.8696,0.3431 1.7391,0 3.0616,-0.3434 3.9677,-1.0299 0.9153,-0.6865 1.373,-1.6837 1.373,-2.9926 0,-1.2082 -0.4257,-2.1514 -1.2769,-2.8288 -0.8421,-0.6865 -2.0182,-1.0294 -3.5285,-1.0294l-2.389,0l0,-2.2794l2.4991,0c1.3638,0 2.4069,-0.2697 3.13,-0.8098 0.7231,-0.5492 1.0847,-1.3365 1.0847,-2.3616 0,-1.0526 -0.375,-1.858 -1.1255,-2.4164 -0.7414,-0.5675 -1.808,-0.8511 -3.1993,-0.8511 -0.7597,0 -1.5742,0.0823 -2.4438,0.247 -0.8695,0.1648 -1.8261,0.4211 -2.8696,0.7689l0,-2.4717c1.0526,-0.2929 2.0364,-0.5124 2.9518,-0.6589 0.9245,-0.1464 1.794,-0.2196 2.6086,-0.2196zM25.2005,31.6957L31.4611,31.6957c2.3432,0 4.0913,0.4898 5.2446,1.4692 1.1533,0.9794 1.7301,2.4578 1.7301,4.4349 0,1.2906 -0.3018,2.3615 -0.9059,3.2127 -0.595,0.8512 -1.4645,1.4414 -2.6086,1.771 0.595,0.2014 1.1713,0.6319 1.7296,1.2909 0.5675,0.659 1.1352,1.5649 1.7027,2.7182l2.8143,5.6017l-2.9791,0l-2.6226,-5.2581c-0.6773,-1.373 -1.3364,-2.2841 -1.9771,-2.7326 -0.6316,-0.4485 -1.4963,-0.6723 -2.5947,-0.6723l-3.0205,0l0,8.663L25.2005,52.1942ZM27.974,33.9752l0,7.2766l3.4871,0c1.3364,0 2.3432,-0.3066 3.0205,-0.9198 0.6865,-0.6224 1.0299,-1.5331 1.0299,-2.7321 0,-1.1991 -0.3434,-2.1006 -1.0299,-2.7047 -0.6773,-0.6133 -1.6841,-0.9198 -3.0205,-0.9198z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="11.0688"
|
||||
android:fillColor="@color/control_pressed"
|
||||
android:strokeLineCap="round"/>
|
||||
</vector>
|
|
@ -1,12 +0,0 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="256dp"
|
||||
android:height="256dp"
|
||||
android:viewportWidth="67.73333"
|
||||
android:viewportHeight="67.73334">
|
||||
<path
|
||||
android:pathData="M16.9333,4.2333C7.5523,4.2333 0,10.8416 0,19.05l0,29.6333c0,8.2084 7.5523,14.8167 16.9333,14.8167l33.8667,0c9.3811,0 16.9333,-6.6082 16.9333,-14.8167L67.7333,19.05C67.7333,10.8416 60.1811,4.2333 50.8,4.2333ZM11.8701,15.3458a3.7042,3.7042 0,0 1,3.7042 3.7042,3.7042 3.7042,0 0,1 -3.7042,3.7042 3.7042,3.7042 0,0 1,-3.7042 -3.7042,3.7042 3.7042,0 0,1 3.7042,-3.7042zM26.6867,15.3458a3.7042,3.7042 0,0 1,3.7042 3.7042,3.7042 3.7042,0 0,1 -3.7042,3.7042A3.7042,3.7042 0,0 1,22.9826 19.05,3.7042 3.7042,0 0,1 26.6867,15.3458ZM41.5034,15.3458a3.7042,3.7042 0,0 1,3.7042 3.7042,3.7042 3.7042,0 0,1 -3.7042,3.7042 3.7042,3.7042 0,0 1,-3.7042 -3.7042,3.7042 3.7042,0 0,1 3.7042,-3.7042zM56.3201,15.3458a3.7042,3.7042 0,0 1,3.7042 3.7042,3.7042 3.7042,0 0,1 -3.7042,3.7042 3.7042,3.7042 0,0 1,-3.7042 -3.7042,3.7042 3.7042,0 0,1 3.7042,-3.7042zM11.8701,30.1625a3.7042,3.7042 0,0 1,3.7042 3.7042,3.7042 3.7042,135 0,1 -3.7042,3.7042 3.7042,3.7042 135,0 1,-3.7042 -3.7042,3.7042 3.7042,0 0,1 3.7042,-3.7042zM26.6867,30.1625a3.7042,3.7042 0,0 1,3.7042 3.7042,3.7042 3.7042,135 0,1 -3.7042,3.7042 3.7042,3.7042 135,0 1,-3.7042 -3.7042,3.7042 3.7042,0 0,1 3.7042,-3.7042zM41.5034,30.1625a3.7042,3.7042 0,0 1,3.7042 3.7042,3.7042 3.7042,135 0,1 -3.7042,3.7042 3.7042,3.7042 135,0 1,-3.7042 -3.7042,3.7042 3.7042,0 0,1 3.7042,-3.7042zM56.3201,30.1625a3.7042,3.7042 0,0 1,3.7042 3.7042,3.7042 3.7042,135 0,1 -3.7042,3.7042 3.7042,3.7042 135,0 1,-3.7042 -3.7042,3.7042 3.7042,0 0,1 3.7042,-3.7042zM11.8701,44.9792a3.7042,3.7042 0,0 1,3.7042 3.7042,3.7042 3.7042,0 0,1 -3.7042,3.7042 3.7042,3.7042 0,0 1,-3.7042 -3.7042,3.7042 3.7042,0 0,1 3.7042,-3.7042zM26.6867,44.9792a3.7042,3.7042 0,0 1,3.7042 3.7042,3.7042 3.7042,0 0,1 -3.7042,3.7042 3.7042,3.7042 0,0 1,-3.7042 -3.7042,3.7042 3.7042,0 0,1 3.7042,-3.7042zM41.5034,44.9792a3.7042,3.7042 0,0 1,3.7042 3.7042,3.7042 3.7042,0 0,1 -3.7042,3.7042 3.7042,3.7042 0,0 1,-3.7042 -3.7042,3.7042 3.7042,0 0,1 3.7042,-3.7042zM56.3201,44.9792a3.7042,3.7042 0,0 1,3.7042 3.7042,3.7042 3.7042,0 0,1 -3.7042,3.7042 3.7042,3.7042 0,0 1,-3.7042 -3.7042,3.7042 3.7042,0 0,1 3.7042,-3.7042z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="22.6959"
|
||||
android:fillColor="@color/control_primary"
|
||||
android:strokeLineCap="round"/>
|
||||
</vector>
|
|
@ -1,12 +0,0 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="256dp"
|
||||
android:height="256dp"
|
||||
android:viewportWidth="67.73333"
|
||||
android:viewportHeight="67.73334">
|
||||
<path
|
||||
android:pathData="M16.9333,4.2333C7.5523,4.2333 0,10.8416 0,19.05l0,29.6333c0,8.2084 7.5523,14.8167 16.9333,14.8167l33.8667,0c9.3811,0 16.9333,-6.6082 16.9333,-14.8167L67.7333,19.05C67.7333,10.8416 60.1811,4.2333 50.8,4.2333ZM11.8701,15.3458a3.7042,3.7042 0,0 1,3.7042 3.7042,3.7042 3.7042,0 0,1 -3.7042,3.7042 3.7042,3.7042 0,0 1,-3.7042 -3.7042,3.7042 3.7042,0 0,1 3.7042,-3.7042zM26.6867,15.3458a3.7042,3.7042 0,0 1,3.7042 3.7042,3.7042 3.7042,0 0,1 -3.7042,3.7042A3.7042,3.7042 0,0 1,22.9826 19.05,3.7042 3.7042,0 0,1 26.6867,15.3458ZM41.5034,15.3458a3.7042,3.7042 0,0 1,3.7042 3.7042,3.7042 3.7042,0 0,1 -3.7042,3.7042 3.7042,3.7042 0,0 1,-3.7042 -3.7042,3.7042 3.7042,0 0,1 3.7042,-3.7042zM56.3201,15.3458a3.7042,3.7042 0,0 1,3.7042 3.7042,3.7042 3.7042,0 0,1 -3.7042,3.7042 3.7042,3.7042 0,0 1,-3.7042 -3.7042,3.7042 3.7042,0 0,1 3.7042,-3.7042zM11.8701,30.1625a3.7042,3.7042 0,0 1,3.7042 3.7042,3.7042 3.7042,135 0,1 -3.7042,3.7042 3.7042,3.7042 135,0 1,-3.7042 -3.7042,3.7042 3.7042,0 0,1 3.7042,-3.7042zM26.6867,30.1625a3.7042,3.7042 0,0 1,3.7042 3.7042,3.7042 3.7042,135 0,1 -3.7042,3.7042 3.7042,3.7042 135,0 1,-3.7042 -3.7042,3.7042 3.7042,0 0,1 3.7042,-3.7042zM41.5034,30.1625a3.7042,3.7042 0,0 1,3.7042 3.7042,3.7042 3.7042,135 0,1 -3.7042,3.7042 3.7042,3.7042 135,0 1,-3.7042 -3.7042,3.7042 3.7042,0 0,1 3.7042,-3.7042zM56.3201,30.1625a3.7042,3.7042 0,0 1,3.7042 3.7042,3.7042 3.7042,135 0,1 -3.7042,3.7042 3.7042,3.7042 135,0 1,-3.7042 -3.7042,3.7042 3.7042,0 0,1 3.7042,-3.7042zM11.8701,44.9792a3.7042,3.7042 0,0 1,3.7042 3.7042,3.7042 3.7042,0 0,1 -3.7042,3.7042 3.7042,3.7042 0,0 1,-3.7042 -3.7042,3.7042 3.7042,0 0,1 3.7042,-3.7042zM26.6867,44.9792a3.7042,3.7042 0,0 1,3.7042 3.7042,3.7042 3.7042,0 0,1 -3.7042,3.7042 3.7042,3.7042 0,0 1,-3.7042 -3.7042,3.7042 3.7042,0 0,1 3.7042,-3.7042zM41.5034,44.9792a3.7042,3.7042 0,0 1,3.7042 3.7042,3.7042 3.7042,0 0,1 -3.7042,3.7042 3.7042,3.7042 0,0 1,-3.7042 -3.7042,3.7042 3.7042,0 0,1 3.7042,-3.7042zM56.3201,44.9792a3.7042,3.7042 0,0 1,3.7042 3.7042,3.7042 3.7042,0 0,1 -3.7042,3.7042 3.7042,3.7042 0,0 1,-3.7042 -3.7042,3.7042 3.7042,0 0,1 3.7042,-3.7042z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="22.6959"
|
||||
android:fillColor="@color/control_pressed"
|
||||
android:strokeLineCap="round"/>
|
||||
</vector>
|
12
android/app/src/main/res/drawable/control_touchpad.xml
Normal file
|
@ -0,0 +1,12 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="1920dp"
|
||||
android:height="942dp"
|
||||
android:viewportWidth="508"
|
||||
android:viewportHeight="249.2375">
|
||||
<path
|
||||
android:pathData="M32,0L476,0A32,32 0,0 1,508 32L508,217.238A32,32 0,0 1,476 249.238L32,249.238A32,32 0,0 1,-0 217.238L-0,32A32,32 0,0 1,32 0z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="1.59637"
|
||||
android:fillColor="@color/control_primary"
|
||||
android:strokeLineCap="round"/>
|
||||
</vector>
|
|
@ -0,0 +1,12 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="1920dp"
|
||||
android:height="942dp"
|
||||
android:viewportWidth="508"
|
||||
android:viewportHeight="249.2375">
|
||||
<path
|
||||
android:pathData="M32,0L476,0A32,32 0,0 1,508 32L508,217.238A32,32 0,0 1,476 249.238L32,249.238A32,32 0,0 1,-0 217.238L-0,32A32,32 0,0 1,32 0z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="1.59637"
|
||||
android:fillColor="@color/control_pressed"
|
||||
android:strokeLineCap="round"/>
|
||||
</vector>
|
9
android/app/src/main/res/drawable/ic_button_haptic.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="?android:attr/textColorPrimary"
|
||||
android:pathData="M9,11.24V7.5C9,6.12 10.12,5 11.5,5S14,6.12 14,7.5v3.74c1.21,-0.81 2,-2.18 2,-3.74C16,5.01 13.99,3 11.5,3S7,5.01 7,7.5C7,9.06 7.79,10.43 9,11.24zM18.84,15.87l-4.54,-2.26c-0.17,-0.07 -0.35,-0.11 -0.54,-0.11H13v-6C13,6.67 12.33,6 11.5,6S10,6.67 10,7.5v10.74c-3.6,-0.76 -3.54,-0.75 -3.67,-0.75c-0.31,0 -0.59,0.13 -0.79,0.33l-0.79,0.8l4.94,4.94C9.96,23.83 10.34,24 10.75,24h6.79c0.75,0 1.33,-0.55 1.44,-1.28l0.75,-5.27c0.01,-0.07 0.02,-0.14 0.02,-0.2C19.75,16.63 19.37,16.09 18.84,15.87z"/>
|
||||
</vector>
|
9
android/app/src/main/res/drawable/ic_motion.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="?android:attr/textColorPrimary"
|
||||
android:pathData="M16.48,2.52c3.27,1.55 5.61,4.72 5.97,8.48h1.5C23.44,4.84 18.29,0 12,0l-0.66,0.03 3.81,3.81 1.33,-1.32zM10.23,1.75c-0.59,-0.59 -1.54,-0.59 -2.12,0L1.75,8.11c-0.59,0.59 -0.59,1.54 0,2.12l12.02,12.02c0.59,0.59 1.54,0.59 2.12,0l6.36,-6.36c0.59,-0.59 0.59,-1.54 0,-2.12L10.23,1.75zM14.83,21.19L2.81,9.17l6.36,-6.36 12.02,12.02 -6.36,6.36zM7.52,21.48C4.25,19.94 1.91,16.76 1.55,13L0.05,13C0.56,19.16 5.71,24 12,24l0.66,-0.03 -3.81,-3.81 -1.33,1.32z"/>
|
||||
</vector>
|
9
android/app/src/main/res/drawable/ic_rumble.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="?android:attr/textColorPrimary"
|
||||
android:pathData="M0,15h2L2,9L0,9v6zM3,17h2L5,7L3,7v10zM22,9v6h2L24,9h-2zM19,17h2L21,7h-2v10zM16.5,3h-9C6.67,3 6,3.67 6,4.5v15c0,0.83 0.67,1.5 1.5,1.5h9c0.83,0 1.5,-0.67 1.5,-1.5v-15c0,-0.83 -0.67,-1.5 -1.5,-1.5zM16,19L8,19L8,5h8v14z"/>
|
||||
</vector>
|
|
@ -1,16 +1,24 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<FrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/mainStreamLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
tools:context=".stream.StreamActivity"
|
||||
android:keepScreenOn="true">
|
||||
|
||||
<TextureView
|
||||
android:id="@+id/textureView"
|
||||
<com.metallic.chiaki.stream.AspectRatioFrameLayout
|
||||
android:id="@+id/aspectRatioLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center">
|
||||
<SurfaceView
|
||||
android:id="@+id/surfaceView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
</com.metallic.chiaki.stream.AspectRatioFrameLayout>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBar"
|
||||
|
@ -20,7 +28,7 @@
|
|||
|
||||
<fragment
|
||||
android:id="@+id/controlsFragment"
|
||||
android:name="com.metallic.chiaki.touchcontrols.TouchControlsFragment"
|
||||
android:name="com.metallic.chiaki.touchcontrols.DefaultTouchControlsFragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
|
||||
|
@ -34,7 +42,6 @@
|
|||
android:id="@+id/overlay"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="bottom"
|
||||
android:fitsSystemWindows="true">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
|
@ -76,6 +83,7 @@
|
|||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:singleSelection="true"
|
||||
app:selectionRequired="true"
|
||||
app:checkedButton="@id/display_mode_normal_button">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:clipChildren="false">
|
||||
android:clipChildren="false"
|
||||
tools:ignore="RtlHardcoded,RtlSymmetry">
|
||||
|
||||
<com.metallic.chiaki.touchcontrols.ControlsBackgroundView
|
||||
android:layout_width="match_parent"
|
||||
|
@ -45,20 +47,34 @@
|
|||
app:drawableHandle="@drawable/control_analog_stick_handle"
|
||||
/>
|
||||
|
||||
<com.metallic.chiaki.touchcontrols.TouchpadView
|
||||
android:id="@+id/touchpadView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:drawableIdle="@drawable/control_touchpad"
|
||||
app:drawablePressed="@drawable/control_touchpad_pressed"
|
||||
android:layout_marginTop="32dp"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintWidth_max="300dp"
|
||||
app:layout_constraintDimensionRatio="1920:942"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"/>
|
||||
|
||||
<com.metallic.chiaki.touchcontrols.DPadView
|
||||
android:id="@+id/dpadView"
|
||||
android:layout_width="128dp"
|
||||
android:layout_height="128dp"
|
||||
android:layout_marginLeft="32dp"
|
||||
android:layout_marginBottom="32dp"
|
||||
android:layout_width="160dp"
|
||||
android:layout_height="160dp"
|
||||
android:padding="16dp"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/faceButtonsLayout"
|
||||
android:layout_width="144dp"
|
||||
android:layout_height="144dp"
|
||||
android:layout_width="@dimen/control_face_button_size_full"
|
||||
android:layout_height="@dimen/control_face_button_size_full"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
|
@ -67,9 +83,12 @@
|
|||
|
||||
<com.metallic.chiaki.touchcontrols.ButtonView
|
||||
android:id="@+id/crossButtonView"
|
||||
android:layout_width="@dimen/control_face_button_size"
|
||||
android:layout_height="@dimen/control_face_button_size"
|
||||
android:padding="8dp"
|
||||
android:layout_width="@dimen/control_face_button_size_full"
|
||||
android:layout_height="@dimen/control_face_button_size_half"
|
||||
android:paddingLeft="@dimen/control_face_button_padding_to_full"
|
||||
android:paddingRight="@dimen/control_face_button_padding_to_full"
|
||||
android:paddingTop="@dimen/control_face_button_padding_to_center"
|
||||
android:paddingBottom="@dimen/control_face_button_padding_to_outside"
|
||||
app:drawableIdle="@drawable/control_button_cross"
|
||||
app:drawablePressed="@drawable/control_button_cross_pressed"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
|
@ -78,9 +97,12 @@
|
|||
|
||||
<com.metallic.chiaki.touchcontrols.ButtonView
|
||||
android:id="@+id/moonButtonView"
|
||||
android:layout_width="@dimen/control_face_button_size"
|
||||
android:layout_height="@dimen/control_face_button_size"
|
||||
android:padding="8dp"
|
||||
android:layout_width="@dimen/control_face_button_size_half"
|
||||
android:layout_height="@dimen/control_face_button_size_full"
|
||||
android:paddingTop="@dimen/control_face_button_padding_to_full"
|
||||
android:paddingBottom="@dimen/control_face_button_padding_to_full"
|
||||
android:paddingLeft="@dimen/control_face_button_padding_to_center"
|
||||
android:paddingRight="@dimen/control_face_button_padding_to_outside"
|
||||
app:drawableIdle="@drawable/control_button_moon"
|
||||
app:drawablePressed="@drawable/control_button_moon_pressed"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
|
@ -89,9 +111,12 @@
|
|||
|
||||
<com.metallic.chiaki.touchcontrols.ButtonView
|
||||
android:id="@+id/pyramidButtonView"
|
||||
android:layout_width="@dimen/control_face_button_size"
|
||||
android:layout_height="@dimen/control_face_button_size"
|
||||
android:padding="8dp"
|
||||
android:layout_width="@dimen/control_face_button_size_full"
|
||||
android:layout_height="@dimen/control_face_button_size_half"
|
||||
android:paddingLeft="@dimen/control_face_button_padding_to_full"
|
||||
android:paddingRight="@dimen/control_face_button_padding_to_full"
|
||||
android:paddingBottom="@dimen/control_face_button_padding_to_center"
|
||||
android:paddingTop="@dimen/control_face_button_padding_to_outside"
|
||||
app:drawableIdle="@drawable/control_button_pyramid"
|
||||
app:drawablePressed="@drawable/control_button_pyramid_pressed"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
|
@ -100,24 +125,45 @@
|
|||
|
||||
<com.metallic.chiaki.touchcontrols.ButtonView
|
||||
android:id="@+id/boxButtonView"
|
||||
android:layout_width="@dimen/control_face_button_size"
|
||||
android:layout_height="@dimen/control_face_button_size"
|
||||
android:padding="8dp"
|
||||
android:layout_width="@dimen/control_face_button_size_half"
|
||||
android:layout_height="@dimen/control_face_button_size_full"
|
||||
android:paddingTop="@dimen/control_face_button_padding_to_full"
|
||||
android:paddingBottom="@dimen/control_face_button_padding_to_full"
|
||||
android:paddingRight="@dimen/control_face_button_padding_to_center"
|
||||
android:paddingLeft="@dimen/control_face_button_padding_to_outside"
|
||||
app:drawableIdle="@drawable/control_button_box"
|
||||
app:drawablePressed="@drawable/control_button_box_pressed"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"/>
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
|
||||
<com.metallic.chiaki.touchcontrols.ButtonView
|
||||
android:id="@+id/l3ButtonView"
|
||||
android:layout_width="64dp"
|
||||
android:layout_height="64dp"
|
||||
app:drawableIdle="@drawable/control_button_l3"
|
||||
app:drawablePressed="@drawable/control_button_l3_pressed"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"/>
|
||||
|
||||
<com.metallic.chiaki.touchcontrols.ButtonView
|
||||
android:id="@+id/r3ButtonView"
|
||||
android:layout_width="64dp"
|
||||
android:layout_height="64dp"
|
||||
app:drawableIdle="@drawable/control_button_r3"
|
||||
app:drawablePressed="@drawable/control_button_r3_pressed"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"/>
|
||||
|
||||
|
||||
<com.metallic.chiaki.touchcontrols.ButtonView
|
||||
android:id="@+id/psButtonView"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:padding="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
app:drawableIdle="@drawable/control_button_home"
|
||||
app:drawablePressed="@drawable/control_button_home_pressed"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
|
@ -125,25 +171,14 @@
|
|||
app:layout_constraintBottom_toBottomOf="parent"/>
|
||||
|
||||
|
||||
<com.metallic.chiaki.touchcontrols.ButtonView
|
||||
android:id="@+id/touchpadButtonView"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:padding="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
app:drawableIdle="@drawable/control_button_touchpad"
|
||||
app:drawablePressed="@drawable/control_button_touchpad_pressed"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
<com.metallic.chiaki.touchcontrols.ButtonView
|
||||
android:id="@+id/l2ButtonView"
|
||||
android:layout_width="64dp"
|
||||
android:layout_height="32dp"
|
||||
android:padding="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_width="88dp"
|
||||
android:layout_height="80dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingBottom="8dp"
|
||||
android:paddingRight="8dp"
|
||||
android:paddingLeft="16dp"
|
||||
app:drawableIdle="@drawable/control_button_l2"
|
||||
app:drawablePressed="@drawable/control_button_l2_pressed"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
|
@ -151,23 +186,22 @@
|
|||
|
||||
<com.metallic.chiaki.touchcontrols.ButtonView
|
||||
android:id="@+id/l1ButtonView"
|
||||
android:layout_width="64dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_width="80dp"
|
||||
android:layout_height="80dp"
|
||||
android:padding="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginTop="32dp"
|
||||
android:layout_marginLeft="40dp"
|
||||
app:drawableIdle="@drawable/control_button_l1"
|
||||
app:drawablePressed="@drawable/control_button_l1_pressed"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/l2ButtonView"/>
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
<com.metallic.chiaki.touchcontrols.ButtonView
|
||||
android:id="@+id/shareButtonView"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:padding="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginLeft="32dp"
|
||||
app:drawableIdle="@drawable/control_button_share"
|
||||
app:drawablePressed="@drawable/control_button_share_pressed"
|
||||
app:layout_constraintLeft_toRightOf="@id/l2ButtonView"
|
||||
|
@ -175,11 +209,12 @@
|
|||
|
||||
<com.metallic.chiaki.touchcontrols.ButtonView
|
||||
android:id="@+id/r2ButtonView"
|
||||
android:layout_width="64dp"
|
||||
android:layout_height="32dp"
|
||||
android:padding="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_width="88dp"
|
||||
android:layout_height="80dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingRight="16dp"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingBottom="8dp"
|
||||
app:drawableIdle="@drawable/control_button_r2"
|
||||
app:drawablePressed="@drawable/control_button_r2_pressed"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
|
@ -187,23 +222,22 @@
|
|||
|
||||
<com.metallic.chiaki.touchcontrols.ButtonView
|
||||
android:id="@+id/r1ButtonView"
|
||||
android:layout_width="64dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_width="80dp"
|
||||
android:layout_height="80dp"
|
||||
android:padding="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_marginTop="32dp"
|
||||
android:layout_marginRight="40dp"
|
||||
app:drawableIdle="@drawable/control_button_r1"
|
||||
app:drawablePressed="@drawable/control_button_r1_pressed"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/r2ButtonView"/>
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
<com.metallic.chiaki.touchcontrols.ButtonView
|
||||
android:id="@+id/optionsButtonView"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:padding="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_marginRight="32dp"
|
||||
app:drawableIdle="@drawable/control_button_options"
|
||||
app:drawablePressed="@drawable/control_button_options_pressed"
|
||||
app:layout_constraintRight_toLeftOf="@id/r2ButtonView"
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
|
@ -12,16 +13,18 @@
|
|||
tools:layout_editor_absoluteX="0dp"
|
||||
tools:layout_editor_absoluteY="90dp" />
|
||||
|
||||
<com.metallic.chiaki.touchcontrols.ButtonView
|
||||
android:id="@+id/touchpadButtonView"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_marginEnd="32dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:padding="8dp"
|
||||
app:drawableIdle="@drawable/control_button_touchpad"
|
||||
app:drawablePressed="@drawable/control_button_touchpad_pressed"
|
||||
<com.metallic.chiaki.touchcontrols.TouchpadView
|
||||
android:id="@+id/touchpadView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:drawableIdle="@drawable/control_touchpad"
|
||||
app:drawablePressed="@drawable/control_touchpad_pressed"
|
||||
app:layout_constraintDimensionRatio="1920:942"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
android:layout_marginLeft="80dp"
|
||||
android:layout_marginRight="80dp"/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -1,8 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<attr name="drawableIdle" format="reference" />
|
||||
<attr name="drawablePressed" format="reference" />
|
||||
|
||||
<declare-styleable name="ButtonView">
|
||||
<attr name="drawableIdle" format="reference" />
|
||||
<attr name="drawablePressed" format="integer" />
|
||||
<attr name="drawableIdle" />
|
||||
<attr name="drawablePressed" />
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="AnalogStickView">
|
||||
|
@ -11,4 +14,9 @@
|
|||
<attr name="drawableBase" format="reference" />
|
||||
<attr name="drawableHandle" format="reference" />
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="TouchpadView">
|
||||
<attr name="drawableIdle" />
|
||||
<attr name="drawablePressed" />
|
||||
</declare-styleable>
|
||||
</resources>
|
|
@ -1,6 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<dimen name="control_face_button_size">48dp</dimen>
|
||||
<dimen name="control_face_button_size_half">88dp</dimen>
|
||||
<dimen name="control_face_button_size_full">176dp</dimen>
|
||||
<dimen name="control_face_button_padding_to_center">24dp</dimen>
|
||||
<dimen name="control_face_button_padding_to_outside">16dp</dimen>
|
||||
<dimen name="control_face_button_padding_to_full">64dp</dimen>
|
||||
<dimen name="control_analog_stick_radius">48dp</dimen>
|
||||
<dimen name="control_analog_stick_handle_radius">32dp</dimen>
|
||||
<dimen name="floating_action_button_speed_dial_anim_offset">48dp</dimen>
|
||||
|
|
|
@ -88,6 +88,12 @@
|
|||
<string name="preferences_codec_title_h265">H265 (PS5 only)</string>
|
||||
<string name="preferences_swap_cross_moon_title">Swap Cross/Moon and Box/Pyramid Buttons</string>
|
||||
<string name="preferences_swap_cross_moon_summary">Swap face buttons if default mapping is incorrect (e.g. for 8BitDo controllers)</string>
|
||||
<string name="preferences_rumble_enabled_title">Rumble</string>
|
||||
<string name="preferences_rumble_enabled_summary">Use phone vibration motor for rumble</string>
|
||||
<string name="preferences_motion_enabled_title">Motion</string>
|
||||
<string name="preferences_motion_enabled_summary">Use device\'s motion sensors for controller motion</string>
|
||||
<string name="preferences_button_haptic_enabled_title">Touch Haptics</string>
|
||||
<string name="preferences_button_haptic_enabled_summary">Use phone vibration motor for short haptic feedback on button touches</string>
|
||||
<string name="alert_message_delete_registered_host">Are you sure you want to delete the registered console %s with ID %s?</string>
|
||||
<string name="alert_message_delete_manual_host">Are you sure you want to delete the console entry for %s?</string>
|
||||
<string name="action_keep">Keep</string>
|
||||
|
@ -101,7 +107,10 @@
|
|||
<!-- Don't localize these -->
|
||||
<string name="preferences_discovery_enabled_key">discovery_enabled</string>
|
||||
<string name="preferences_on_screen_controls_enabled_key">on_screen_controls_enabled</string>
|
||||
<string name="preferences_touchpad_only_key">touchpad_only_enabled</string>
|
||||
<string name="preferences_touchpad_only_enabled_key">touchpad_only_enabled</string>
|
||||
<string name="preferences_rumble_enabled_key">rumble_enabled</string>
|
||||
<string name="preferences_motion_enabled_key">motion_enabled</string>
|
||||
<string name="preferences_button_haptic_enabled_key">button_haptic_enabled</string>
|
||||
<string name="preferences_log_verbose_key">log_verbose</string>
|
||||
<string name="preferences_import_settings_key">import_settings</string>
|
||||
<string name="preferences_export_settings_key">export_settings</string>
|
||||
|
|
|
@ -19,6 +19,24 @@
|
|||
app:summary="@string/preferences_swap_cross_moon_summary"
|
||||
app:icon="@drawable/ic_gamepad" />
|
||||
|
||||
<SwitchPreference
|
||||
app:key="@string/preferences_rumble_enabled_key"
|
||||
app:title="@string/preferences_rumble_enabled_title"
|
||||
app:summary="@string/preferences_rumble_enabled_summary"
|
||||
app:icon="@drawable/ic_rumble" />
|
||||
|
||||
<SwitchPreference
|
||||
app:key="@string/preferences_motion_enabled_key"
|
||||
app:title="@string/preferences_motion_enabled_title"
|
||||
app:summary="@string/preferences_motion_enabled_summary"
|
||||
app:icon="@drawable/ic_motion" />
|
||||
|
||||
<SwitchPreference
|
||||
app:key="@string/preferences_button_haptic_enabled_key"
|
||||
app:title="@string/preferences_button_haptic_enabled_title"
|
||||
app:summary="@string/preferences_button_haptic_enabled_summary"
|
||||
app:icon="@drawable/ic_button_haptic" />
|
||||
|
||||
<SwitchPreference
|
||||
app:key="@string/preferences_log_verbose_key"
|
||||
app:title="@string/preferences_log_verbose_title"
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.3.61'
|
||||
ext.kotlin_version = '1.8.0'
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.5.2'
|
||||
classpath 'com.android.tools.build:gradle:7.4.1'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#Wed Mar 11 18:48:31 CET 2020
|
||||
#Sun Feb 05 16:25:19 CET 2023
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
|
266
assets/chiaki_macos.svg
Normal file
|
@ -0,0 +1,266 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="1024"
|
||||
height="1024"
|
||||
viewBox="0 0 270.93332 270.93334"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
inkscape:version="1.2.1 (9c6d41e, 2022-07-14)"
|
||||
sodipodi:docname="chiaki_macos.svg"
|
||||
xml:space="preserve"
|
||||
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"><sodipodi:namedview
|
||||
id="namedview7"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#eeeeee"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="true"
|
||||
inkscape:deskcolor="#505050"
|
||||
inkscape:document-units="mm"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.5946522"
|
||||
inkscape:cx="616.32665"
|
||||
inkscape:cy="519.63148"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="978"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="25"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1"
|
||||
showguides="true"><sodipodi:guide
|
||||
position="26.458333,219.96511"
|
||||
orientation="-1,0"
|
||||
id="guide1357"
|
||||
inkscape:locked="false"
|
||||
inkscape:label=""
|
||||
inkscape:color="rgb(0,134,229)" /><sodipodi:guide
|
||||
position="50.653599,244.475"
|
||||
orientation="0,1"
|
||||
id="guide1359"
|
||||
inkscape:locked="false"
|
||||
inkscape:label=""
|
||||
inkscape:color="rgb(0,134,229)" /><sodipodi:guide
|
||||
position="244.475,210.52655"
|
||||
orientation="-1,0"
|
||||
id="guide1361"
|
||||
inkscape:locked="false"
|
||||
inkscape:label=""
|
||||
inkscape:color="rgb(0,134,229)" /><sodipodi:guide
|
||||
position="67.733332,26.458333"
|
||||
orientation="0,1"
|
||||
id="guide1363"
|
||||
inkscape:locked="false"
|
||||
inkscape:label=""
|
||||
inkscape:color="rgb(0,134,229)" /><sodipodi:guide
|
||||
position="135.46666,253.78662"
|
||||
orientation="-1,0"
|
||||
id="guide4345"
|
||||
inkscape:locked="false"
|
||||
inkscape:label=""
|
||||
inkscape:color="rgb(0,134,229)" /></sodipodi:namedview><defs
|
||||
id="defs2"><linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient4465"><stop
|
||||
style="stop-color:#f1ff7f;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4461" /><stop
|
||||
style="stop-color:#b2d400;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop4463" /></linearGradient><filter
|
||||
x="-0.014563107"
|
||||
y="-0.014563107"
|
||||
width="1.0291262"
|
||||
height="1.0412621"
|
||||
filterUnits="objectBoundingBox"
|
||||
id="filter-80aygx4sbj-3"><feOffset
|
||||
dx="0"
|
||||
dy="5"
|
||||
in="SourceAlpha"
|
||||
result="shadowOffsetOuter1"
|
||||
id="feOffset424" /><feGaussianBlur
|
||||
stdDeviation="2.5"
|
||||
in="shadowOffsetOuter1"
|
||||
result="shadowBlurOuter1"
|
||||
id="feGaussianBlur426" /><feColorMatrix
|
||||
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.3 0"
|
||||
type="matrix"
|
||||
in="shadowBlurOuter1"
|
||||
id="feColorMatrix428" /></filter><clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath869"><path
|
||||
d="m -143.73827,56.831818 a 79.375,79.375 0 0 1 102.042535,2e-6 l -51.021268,60.80478 z"
|
||||
sodipodi:end="5.4105207"
|
||||
sodipodi:start="4.0142573"
|
||||
sodipodi:ry="79.375"
|
||||
sodipodi:rx="79.375"
|
||||
sodipodi:cy="117.6366"
|
||||
sodipodi:cx="-92.717003"
|
||||
sodipodi:type="arc"
|
||||
id="path871"
|
||||
style="fill:#008080;fill-opacity:1;stroke:none;stroke-width:11.1206;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
sodipodi:arc-type="slice" /></clipPath><clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath964"><circle
|
||||
style="display:inline;fill:#ff9955;fill-opacity:1;stroke:none;stroke-width:8.46667;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="circle966"
|
||||
cx="-135.46669"
|
||||
cy="161.49431"
|
||||
r="135.46667"
|
||||
inkscape:label="circle"
|
||||
transform="scale(-1,1)" /></clipPath><clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath4387"><path
|
||||
d="m 270.31599,96.939968 c 0,-3.20165 0,-6.403627 -0.0173,-9.605605 -0.0174,-2.697285 -0.0473,-5.393909 -0.12049,-8.089885 -0.15834,-5.876017 -0.50503,-11.802446 -1.55009,-17.613009 -1.05975,-5.894353 -2.79053,-11.380228 -5.51791,-16.735846 -2.68122,-5.26397 -6.18365,-10.080848 -10.3626,-14.256872 -4.17798,-4.176024 -8.99614,-7.676173 -14.26207,-10.355782 -5.36116,-2.728048 -10.85292,-4.458156 -16.75377,-5.517628 -5.81122,-1.043433 -11.73926,-1.38939 -17.61526,-1.54813 -2.69792,-0.07299 -5.39585,-0.103764 -8.09443,-0.120439 -3.2036,-0.01955 -6.40721,-0.01806 -9.61081,-0.01806 L 149.2133,12.945506 h -27.8204 l -36.538684,0.133205 c -3.209827,0 -6.419646,-0.0016 -9.629466,0.01806 -2.704145,0.01657 -5.406981,0.04745 -8.110144,0.120439 -5.889745,0.158737 -11.831203,0.505024 -17.656149,1.549765 -5.908728,1.059145 -11.408663,2.788599 -16.777022,5.514685 -5.277041,2.679934 -10.105685,6.18041 -14.292493,10.35709 -4.186156,4.175697 -7.695131,8.991593 -10.3812753,14.254581 -2.734911,5.35823 -4.4689412,10.84739 -5.5313527,16.74501 -1.0460477,5.808273 -1.3926574,11.732737 -1.55205319,17.606136 -0.0726642,2.696304 -0.10408515,5.392927 -0.12043909,8.089885 -0.0195464,3.202305 -0.18427009,7.179987 -0.18427009,10.381964 v 36.032494 28.11836 l 0.16625869,36.79805 c 0,3.20624 -0.001309,6.41247 0.0180605,9.6187 0.0163323,2.70089 0.0477729,5.40111 0.12078473,8.10101 0.15905935,5.88356 0.50633015,11.81849 1.55336045,17.63691 1.0620848,5.90221 2.7957884,11.39593 5.5284083,16.75842 2.6864707,5.27149 6.1960987,10.09461 10.3825837,14.27651 4.186482,4.18193 9.013815,7.68665 14.289876,10.3702 5.37163,2.73164 10.874184,4.46402 16.786519,5.52481 5.82232,1.04508 11.761815,1.39168 17.649275,1.55042 2.703163,0.073 5.406326,0.10416 8.110465,0.12049 3.20982,0.0198 6.419318,0.0198 9.629138,0.0198 h 36.868929 27.88948 36.79758 c 3.2036,0 6.40721,0 9.61081,-0.0198 2.69858,-0.0174 5.39651,-0.0475 8.09444,-0.12049 5.87828,-0.15908 11.8083,-0.506 17.62211,-1.55173 5.89727,-1.06076 11.38641,-2.79253 16.74462,-5.52253 5.26689,-2.68321 10.08605,-6.18859 14.26436,-10.37117 4.17829,-4.18126 7.68039,-9.00371 10.36162,-14.27421 2.72902,-5.36511 4.45979,-10.86145 5.52024,-16.7676 1.04409,-5.81612 1.39036,-11.74877 1.5491,-17.63003 0.073,-2.70023 0.10416,-5.40045 0.11999,-8.10101 0.0173,-3.20623 0.0173,-6.41246 0.0173,-9.6187 0,0 0,-36.14835 0,-36.79805 v -28.14782 c 0,-0.47982 0,-36.779393 0,-36.779393"
|
||||
id="path4389"
|
||||
style="fill:#cfff0d;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.654602"
|
||||
inkscape:label="clip" /></clipPath><linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4465"
|
||||
id="linearGradient4467"
|
||||
x1="67.73333"
|
||||
y1="13.229165"
|
||||
x2="67.73333"
|
||||
y2="122.2375"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(2.0000001,0,0,2.0000001,5.0529028e-6,-2.9497097e-5)" /><linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4465"
|
||||
id="linearGradient1573"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="67.73333"
|
||||
y1="13.229165"
|
||||
x2="67.73333"
|
||||
y2="122.2375"
|
||||
gradientTransform="matrix(1.9999999,0,0,1.9999999,-8.9032287e-4,7.677083e-6)" /></defs><g
|
||||
inkscape:label="Ebene 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"><path
|
||||
d="m 417,128.31353 c 0,-4.89098 0,-9.78246 -0.0281,-14.67394 -0.0245,-4.12049 -0.072,-8.23997 -0.184,-12.35846 -0.242,-8.976466 -0.77149,-18.029933 -2.36798,-26.906401 C 412.80098,65.370262 410.157,56.989792 405.99053,48.808322 401.89456,40.766852 396.5441,33.408378 390.16015,27.028902 383.7777,20.649425 376.41725,15.302444 368.37281,11.208959 360.18287,7.0414744 351.79343,4.398484 342.779,2.7799899 333.90156,1.1859957 324.84563,0.65749761 315.8692,0.41499849 311.74773,0.3034989 307.62626,0.25649907 303.50379,0.23099916 298.60983,0.20099927 293.71586,0.20349926 288.8219,0.20349926 L 231.99832,0 h -42.49969 l -55.81808,0.20349926 c -4.90347,0 -9.80693,-0.0025 -14.71039,0.0274999 -4.13097,0.0254999 -8.25994,0.0724997 -12.38941,0.18399933 C 97.583315,0.65749761 88.506882,1.1864957 79.608448,2.7824899 70.582015,4.400484 62.180077,7.0424744 53.979137,11.206959 45.917697,15.300944 38.541252,20.648425 32.145299,27.028902 25.750346,33.407878 20.389886,40.764852 16.286417,48.804822 12.108447,56.990293 9.459467,65.375762 7.836479,74.385229 6.2384908,83.258197 5.7089948,92.308664 5.4654965,101.28113 5.3544974,105.40012 5.3064977,109.5196 5.2814979,113.63959 5.2514981,118.53157 5,124.60805 5,129.49953 v 55.0448 42.95484 l 0.2539981,56.2143 c 0,4.89798 -0.002,9.79596 0.0275,14.69394 0.025,4.12599 0.072999,8.25097 0.1844986,12.37546 0.2429983,8.98797 0.7734943,18.05443 2.3729825,26.9429 1.622488,9.01647 4.2709678,17.40894 8.4454378,25.60091 4.103969,8.05297 9.465429,15.42094 15.860882,21.80942 6.395453,6.38848 13.769898,11.74245 21.829839,15.84194 8.205939,4.17298 16.611876,6.81947 25.64381,8.43997 8.894434,1.59649 17.967867,2.12599 26.961802,2.36849 4.12947,0.1115 8.25894,0.159 12.38991,0.184 C 123.87412,412 128.77708,412 133.68055,412 h 56.32258 42.60518 56.21359 c 4.89396,0 9.78793,0 14.68189,-0.0295 4.12247,-0.025 8.24394,-0.0725 12.36541,-0.184 8.97993,-0.243 18.03887,-0.773 26.9203,-2.37049 9.00893,-1.62049 17.39437,-4.26598 25.57981,-8.43647 8.04594,-4.09898 15.40789,-9.45397 21.79084,-15.84344 6.38295,-6.38748 11.73291,-13.75445 15.82888,-21.80592 4.16897,-8.19597 6.81295,-16.59244 8.43294,-25.61491 1.59499,-8.88497 2.12398,-17.94793 2.36648,-26.9324 0.1115,-4.12499 0.159,-8.24997 0.1835,-12.37546 C 417,293.50943 417,288.61145 417,283.71347 c 0,0 0,-55.2218 0,-56.2143 v -42.99984 c 0,-0.733 0,-56.1858 0,-56.1858"
|
||||
id="use436"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;filter:url(#filter-80aygx4sbj-3)"
|
||||
transform="matrix(0.52916669,0,0,0.52916669,23.8125,26.458334)" /><path
|
||||
d="m 244.475,94.357609 c 0,-2.588144 0,-5.176552 -0.014,-7.76496 -0.014,-2.180426 -0.0382,-4.360318 -0.0974,-6.539686 -0.128,-4.750046 -0.40826,-9.540837 -1.25306,-14.237969 -0.85668,-4.764864 -2.2558,-9.199528 -4.46056,-13.52889 -2.16744,-4.255278 -4.99872,-8.149136 -8.3769,-11.524941 -3.37738,-3.375806 -7.27228,-6.20525 -11.52914,-8.371386 -4.33384,-2.205294 -8.77326,-3.603876 -13.54338,-4.46033 -4.69766,-0.843488 -9.48976,-1.123152 -14.23978,-1.251474 -2.18094,-0.059 -4.3619,-0.08388 -6.54336,-0.09736 -2.58972,-0.0158 -5.17946,-0.0146 -7.76918,-0.0146 l -30.06997,-0.10768 h -22.48942 l -29.537067,0.10768 c -2.594752,0 -5.1895,-0.0013 -7.784248,0.0146 -2.185972,0.0134 -4.370884,0.03836 -6.556062,0.09736 -4.761142,0.12832 -9.564087,0.40825 -14.272841,1.252796 -4.776488,0.85619 -9.222514,2.254242 -13.562178,4.45795 -4.265844,2.1664 -8.169214,4.996108 -11.553737,8.372444 -3.383996,3.375541 -6.220574,7.268605 -8.391994,11.523089 -2.210842,4.331478 -3.612594,8.76879 -4.471424,13.536298 -0.845602,4.69528 -1.125794,9.484485 -1.254646,14.232413 -0.05874,2.179634 -0.08414,4.359524 -0.09736,6.539686 -0.0158,2.588674 -0.14896,5.804144 -0.14896,8.392552 v 29.127869 22.73027 l 0.1344,29.74674 c 0,2.59184 -0.0011,5.18368 0.0146,7.77554 0.0132,2.18334 0.03862,4.36614 0.09764,6.54868 0.12858,4.75614 0.409306,9.5538 1.255702,14.25728 0.858566,4.77122 2.260054,9.21222 4.469044,13.54714 2.171684,4.26136 5.00879,8.16026 8.393052,11.54082 3.384259,3.38058 7.286569,6.21372 11.551621,8.38304 4.34231,2.2082 8.790452,3.60862 13.56985,4.46614 4.706638,0.84482 9.507995,1.125 14.267285,1.25332 2.185178,0.059 4.370356,0.0842 6.556326,0.0974 2.594748,0.016 5.189232,0.016 7.783984,0.016 h 29.804033 22.54524 29.74635 c 2.58972,0 5.17944,0 7.76916,-0.016 2.18148,-0.014 4.36242,-0.0384 6.54338,-0.0974 4.75188,-0.1286 9.54556,-0.40904 14.24532,-1.25438 4.76722,-0.8575 9.20452,-2.25742 13.53598,-4.4643 4.25764,-2.16904 8.15334,-5.00272 11.531,-8.38382 3.37764,-3.38004 6.20866,-7.2784 8.3761,-11.53896 2.20608,-4.33704 3.6052,-8.78016 4.46244,-13.55456 0.84402,-4.70162 1.12394,-9.49744 1.25226,-14.25172 0.059,-2.18282 0.0842,-4.36562 0.097,-6.54868 0.014,-2.59186 0.014,-5.1837 0.014,-7.77554 0,0 0,-29.22154 0,-29.74674 v -22.75408 c 0,-0.38788 0,-29.731651 0,-29.731651"
|
||||
id="use438"
|
||||
style="display:inline;fill:url(#linearGradient1573);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.529166" /><path
|
||||
id="path1446"
|
||||
style="display:none;fill:url(#linearGradient4467);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.529166"
|
||||
inkscape:label="bg_cut"
|
||||
d="m 124.0896,26.458306 -29.537222,0.10748 c -2.59475,0 -5.188758,-0.0015 -7.783504,0.0144 -2.18597,0.0134 -4.37153,0.03918 -6.556706,0.09818 -4.761139,0.12832 -9.564283,0.408092 -14.273031,1.252638 -4.776484,0.856188 -9.222305,2.253902 -13.561965,4.457609 -4.26584,2.166398 -8.169296,4.996284 -11.553817,8.372616 -3.383992,3.375538 -6.219802,7.268332 -8.39122,11.522813 -2.210838,4.331472 -3.613248,8.76862 -4.472078,13.536124 -0.8456,4.695277 -1.125852,9.484801 -1.254704,14.232723 -0.05874,2.179632 -0.08394,4.358977 -0.09716,6.539137 -0.0158,2.588672 -0.14882,5.804882 -0.14882,8.393286 V 108.73021 H 244.47502 V 94.35796 h 0.001 c 0,-2.58814 -4.8e-4,-5.177528 -0.014,-7.765934 -0.014,-2.180424 -0.038,-4.359771 -0.0972,-6.539137 -0.128,-4.75004 -0.40784,-9.540762 -1.25264,-14.237891 -0.85668,-4.76486 -2.25596,-9.199532 -4.46072,-13.52889 -2.16744,-4.255275 -4.99856,-8.149077 -8.37674,-11.524879 -3.37738,-3.375802 -7.27216,-6.205448 -11.52902,-8.371582 -4.33384,-2.205293 -8.77324,-3.604257 -13.54336,-4.460711 -4.69766,-0.843486 -9.48993,-1.122248 -14.23996,-1.25057 -2.18094,-0.059 -4.36179,-0.0847 -6.54327,-0.09818 -2.58971,-0.0158 -5.18035,-0.0144 -7.77006,-0.0144 l -30.06949,-0.10748 z m -97.498969,149.491654 0.0032,0.63976 c 0,2.59184 -0.0012,5.18442 0.0144,7.77627 0.0132,2.18333 0.03916,4.36589 0.09818,6.54843 0.12858,4.75613 0.408308,9.55406 1.254704,14.25754 0.858566,4.7712 2.261024,9.21154 4.470012,13.54646 2.171682,4.26134 5.007994,8.16086 8.392252,11.5414 3.384257,3.38058 7.286703,6.21364 11.551751,8.38296 4.342306,2.2082 8.790839,3.60836 13.570231,4.46588 4.706634,0.84482 9.507544,1.12534 14.266831,1.25366 2.185176,0.059 4.370738,0.084 6.556706,0.0972 2.594746,0.016 5.188754,0.016 7.783504,0.016 h 29.804898 22.54437 29.74702 c 2.58972,0 5.17932,5e-4 7.76903,-0.016 2.18148,-0.014 4.36233,-0.0382 6.54327,-0.0972 4.75188,-0.1286 9.54537,-0.40936 14.24513,-1.2547 4.76722,-0.8575 9.20466,-2.25694 13.53612,-4.4638 4.25764,-2.16904 8.15342,-5.0029 11.53108,-8.384 3.37764,-3.38002 6.20828,-7.27878 8.37572,-11.53934 2.20608,-4.33704 3.60554,-8.78034 4.46278,-13.55472 0.84402,-4.70162 1.12432,-9.49706 1.25264,-14.25134 0.059,-2.1828 0.0834,-4.36536 0.0962,-6.54843 0.014,-2.59185 0.014,-5.18443 0.014,-7.77627 v -0.63976 z" /><g
|
||||
id="g1005"
|
||||
inkscape:label="main icon"
|
||||
clip-path="url(#clipPath4387)"
|
||||
style="display:inline"
|
||||
transform="matrix(0.80837807,0,0,0.80837807,25.958398,15.993434)"><rect
|
||||
inkscape:label="bg"
|
||||
ry="1.0565645"
|
||||
y="20.8298"
|
||||
x="-4.0937502e-07"
|
||||
height="270.93335"
|
||||
width="270.93335"
|
||||
id="rect873"
|
||||
style="display:none;fill:#cfff0d;fill-opacity:1;stroke:none;stroke-width:8.46431;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /><g
|
||||
id="g1033"
|
||||
inkscape:label="right (original)"
|
||||
transform="matrix(-1,0,0,1,262.28035,14.266743)"
|
||||
style="display:none;stroke:none"><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path1019"
|
||||
d="M -8.6529992,183.6071 H 107.72321 l 19.09046,28.9079 V 100.45235 H -8.6529992 Z"
|
||||
style="display:inline;fill:#162d50;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
sodipodi:nodetypes="cccccc"
|
||||
inkscape:label="face" /><rect
|
||||
style="fill:#ffaaee;fill-opacity:1;stroke:none;stroke-width:0.185662;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
id="rect1021"
|
||||
width="15.497028"
|
||||
height="31.75"
|
||||
x="92.382744"
|
||||
y="131.06844"
|
||||
inkscape:label="eye" /><path
|
||||
sodipodi:type="star"
|
||||
style="fill:#162d50;fill-opacity:1;stroke:none;stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
id="path1023"
|
||||
sodipodi:sides="3"
|
||||
sodipodi:cx="75.635689"
|
||||
sodipodi:cy="87.601158"
|
||||
sodipodi:r1="33.042126"
|
||||
sodipodi:r2="16.521063"
|
||||
sodipodi:arg1="0.52359878"
|
||||
sodipodi:arg2="1.5707963"
|
||||
inkscape:flatsided="false"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="m 104.25101,104.12222 -28.615321,0 -28.615321,0 14.30766,-24.781593 14.307661,-24.781595 14.30766,24.781594 z"
|
||||
inkscape:transform-center-y="-7.0654063"
|
||||
transform="matrix(0.70280031,0,0,0.85532099,32.495272,20.355967)"
|
||||
inkscape:label="ear" /><flowRoot
|
||||
xml:space="preserve"
|
||||
id="flowRoot1031"
|
||||
style="font-style:normal;font-weight:normal;font-size:40px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;display:inline;fill:#000000;fill-opacity:1;stroke:none"
|
||||
transform="matrix(0.26458333,0,0,0.26458333,-8.6529992,15.861276)"
|
||||
inkscape:label="flowRoot4545"><flowRegion
|
||||
id="flowRegion1027"
|
||||
style="stroke:none"><rect
|
||||
id="rect1025"
|
||||
width="104.28571"
|
||||
height="78.571426"
|
||||
x="-374.28571"
|
||||
y="54"
|
||||
style="stroke:none" /></flowRegion><flowPara
|
||||
id="flowPara1029" /></flowRoot></g><use
|
||||
style="display:none"
|
||||
inkscape:label="left"
|
||||
transform="matrix(-1,0,0,1,270.93336,-5.3256301e-6)"
|
||||
height="100%"
|
||||
width="100%"
|
||||
id="use4535"
|
||||
xlink:href="#g4527"
|
||||
y="0"
|
||||
x="0" /><g
|
||||
style="display:inline;stroke:none"
|
||||
transform="matrix(-1,0,0,1,262.28035,14.266743)"
|
||||
inkscape:label="face"
|
||||
id="g4527"><path
|
||||
style="display:inline;fill:#162d50;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 356.42773,228.50391 -38.0039,80.11132 -21.9375,46.24219 H -619.27414 V 669.14258 H 439.84766 L 512,778.40039 584.15234,669.14258 H 1613.2487 V 354.85742 H 727.51367 l -21.9375,-46.24219 -38.0039,-80.11132 -38.00586,80.11132 -21.9375,46.24219 H 512 416.37109 l -21.9375,-46.24219 z"
|
||||
id="path4518"
|
||||
inkscape:connector-curvature="0"
|
||||
inkscape:label="shape"
|
||||
transform="matrix(-0.26458333,0,0,0.26458333,262.28035,6.563066)"
|
||||
sodipodi:nodetypes="ccccccccccccccccccc" /><rect
|
||||
inkscape:label="eye right"
|
||||
y="131.18182"
|
||||
x="92.153267"
|
||||
height="31.75"
|
||||
width="15.875"
|
||||
id="rect1043"
|
||||
style="display:inline;fill:#ffaaee;fill-opacity:1;stroke:none;stroke-width:0.187912;stroke-miterlimit:4;stroke-dasharray:none" /><rect
|
||||
style="display:inline;fill:#ffaaee;fill-opacity:1;stroke:none;stroke-width:0.187912;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
id="rect1047"
|
||||
width="15.875"
|
||||
height="31.75"
|
||||
x="145.59911"
|
||||
y="131.18182"
|
||||
inkscape:label="eye left" /></g><g
|
||||
inkscape:label="dangerous_microwaves"
|
||||
clip-path="url(#clipPath869)"
|
||||
style="fill:none"
|
||||
transform="translate(187.02207,-8.675551)"
|
||||
id="g844"><circle
|
||||
inkscape:label="path830"
|
||||
r="58.208332"
|
||||
style="fill:none;fill-opacity:1;stroke:#162d50;stroke-width:8.46667;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path830"
|
||||
cx="-92.71701"
|
||||
cy="117.6366" /><circle
|
||||
r="41.241978"
|
||||
cy="117.6366"
|
||||
cx="-92.71701"
|
||||
id="circle840"
|
||||
style="fill:none;fill-opacity:1;stroke:#162d50;stroke-width:8.46667;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /></g></g></g></svg>
|
After Width: | Height: | Size: 20 KiB |
102
assets/chiaki_macos_simple.svg
Normal file
|
@ -0,0 +1,102 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="1024"
|
||||
height="1024"
|
||||
viewBox="0 0 270.93332 270.93334"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
xml:space="preserve"
|
||||
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="defs2"><linearGradient
|
||||
id="linearGradient4465"><stop
|
||||
style="stop-color:#f6ffbc;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4461" /><stop
|
||||
style="stop-color:#b4d700;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop4463" /></linearGradient><filter
|
||||
x="-0.014563107"
|
||||
y="-0.014563107"
|
||||
width="1.0291262"
|
||||
height="1.0412621"
|
||||
filterUnits="objectBoundingBox"
|
||||
id="filter-80aygx4sbj-3"><feOffset
|
||||
dx="0"
|
||||
dy="5"
|
||||
in="SourceAlpha"
|
||||
result="shadowOffsetOuter1"
|
||||
id="feOffset424" /><feGaussianBlur
|
||||
stdDeviation="2.5"
|
||||
in="shadowOffsetOuter1"
|
||||
result="shadowBlurOuter1"
|
||||
id="feGaussianBlur426" /><feColorMatrix
|
||||
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.3 0"
|
||||
type="matrix"
|
||||
in="shadowBlurOuter1"
|
||||
id="feColorMatrix428" /></filter><clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath964"><circle
|
||||
style="display:inline;fill:#ff9955;fill-opacity:1;stroke:none;stroke-width:8.46667;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="circle966"
|
||||
cx="-135.46669"
|
||||
cy="161.49431"
|
||||
r="135.46667"
|
||||
transform="scale(-1,1)" /></clipPath><linearGradient
|
||||
xlink:href="#linearGradient4465"
|
||||
id="linearGradient4467"
|
||||
x1="67.73333"
|
||||
y1="13.229165"
|
||||
x2="67.73333"
|
||||
y2="122.2375"
|
||||
gradientUnits="userSpaceOnUse" /><linearGradient
|
||||
xlink:href="#linearGradient4465-9"
|
||||
id="linearGradient4467-7"
|
||||
x1="67.73333"
|
||||
y1="13.229165"
|
||||
x2="67.73333"
|
||||
y2="122.2375"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(-7.288516e-4,6.5027792e-5)" /><linearGradient
|
||||
id="linearGradient4465-9"><stop
|
||||
style="stop-color:#f1ff7f;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4461-3" /><stop
|
||||
style="stop-color:#b2d400;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop4463-8" /></linearGradient></defs><g
|
||||
id="layer1"
|
||||
transform="matrix(2.0000001,0,0,2.0000001,4.2905177e-6,-3.0059484e-5)"><path
|
||||
d="m 417,128.31353 c 0,-4.89098 0,-9.78246 -0.0281,-14.67394 -0.0245,-4.12049 -0.072,-8.23997 -0.184,-12.35846 -0.242,-8.976466 -0.77149,-18.029933 -2.36798,-26.906401 C 412.80098,65.370262 410.157,56.989792 405.99053,48.808322 401.89456,40.766852 396.5441,33.408378 390.16015,27.028902 383.7777,20.649425 376.41725,15.302444 368.37281,11.208959 360.18287,7.0414744 351.79343,4.398484 342.779,2.7799899 333.90156,1.1859957 324.84563,0.65749761 315.8692,0.41499849 311.74773,0.3034989 307.62626,0.25649907 303.50379,0.23099916 298.60983,0.20099927 293.71586,0.20349926 288.8219,0.20349926 L 231.99832,0 h -42.49969 l -55.81808,0.20349926 c -4.90347,0 -9.80693,-0.0025 -14.71039,0.0274999 -4.13097,0.0254999 -8.25994,0.0724997 -12.38941,0.18399933 C 97.583315,0.65749761 88.506882,1.1864957 79.608448,2.7824899 70.582015,4.400484 62.180077,7.0424744 53.979137,11.206959 45.917697,15.300944 38.541252,20.648425 32.145299,27.028902 25.750346,33.407878 20.389886,40.764852 16.286417,48.804822 12.108447,56.990293 9.459467,65.375762 7.836479,74.385229 6.2384908,83.258197 5.7089948,92.308664 5.4654965,101.28113 5.3544974,105.40012 5.3064977,109.5196 5.2814979,113.63959 5.2514981,118.53157 5,124.60805 5,129.49953 v 55.0448 42.95484 l 0.2539981,56.2143 c 0,4.89798 -0.002,9.79596 0.0275,14.69394 0.025,4.12599 0.072999,8.25097 0.1844986,12.37546 0.2429983,8.98797 0.7734943,18.05443 2.3729825,26.9429 1.622488,9.01647 4.2709678,17.40894 8.4454378,25.60091 4.103969,8.05297 9.465429,15.42094 15.860882,21.80942 6.395453,6.38848 13.769898,11.74245 21.829839,15.84194 8.205939,4.17298 16.611876,6.81947 25.64381,8.43997 8.894434,1.59649 17.967867,2.12599 26.961802,2.36849 4.12947,0.1115 8.25894,0.159 12.38991,0.184 C 123.87412,412 128.77708,412 133.68055,412 h 56.32258 42.60518 56.21359 c 4.89396,0 9.78793,0 14.68189,-0.0295 4.12247,-0.025 8.24394,-0.0725 12.36541,-0.184 8.97993,-0.243 18.03887,-0.773 26.9203,-2.37049 9.00893,-1.62049 17.39437,-4.26598 25.57981,-8.43647 8.04594,-4.09898 15.40789,-9.45397 21.79084,-15.84344 6.38295,-6.38748 11.73291,-13.75445 15.82888,-21.80592 4.16897,-8.19597 6.81295,-16.59244 8.43294,-25.61491 1.59499,-8.88497 2.12398,-17.94793 2.36648,-26.9324 0.1115,-4.12499 0.159,-8.24997 0.1835,-12.37546 C 417,293.50943 417,288.61145 417,283.71347 c 0,0 0,-55.2218 0,-56.2143 v -42.99984 c 0,-0.733 0,-56.1858 0,-56.1858"
|
||||
id="use436"
|
||||
style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;filter:url(#filter-80aygx4sbj-3)"
|
||||
transform="matrix(0.26458333,0,0,0.26458333,11.906247,13.229181)" /><path
|
||||
id="path1446-0"
|
||||
style="display:inline;fill:url(#linearGradient4467-7);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.264583"
|
||||
d="m 62.044061,13.229232 -14.7686,0.05374 c -1.29738,0 -2.59438,-7.27e-4 -3.89175,0.0072 -1.09299,0.0067 -2.18577,0.01959 -3.27836,0.04909 -2.38057,0.06416 -4.78214,0.204046 -7.13651,0.626319 -2.38824,0.428094 -4.61115,1.126951 -6.78098,2.228804 -2.13292,1.083199 -4.08465,2.498142 -5.77691,4.186308 -1.692,1.687769 -3.1099,3.634166 -4.19561,5.761406 -1.10542,2.165736 -1.80663,4.38431 -2.23604,6.768062 -0.4228,2.347638 -0.56293,4.7424 -0.62735,7.116361 -0.0294,1.089816 -0.042,2.179488 -0.0486,3.269568 -0.008,1.294336 -0.0744,2.902441 -0.0744,4.196643 v 6.872449 H 122.23676 v -7.186125 h 5.2e-4 c 0,-1.29407 -2.4e-4,-2.588764 -0.007,-3.882967 -0.007,-1.090212 -0.019,-2.179885 -0.0486,-3.269568 -0.064,-2.37502 -0.20392,-4.770381 -0.62632,-7.118945 -0.42834,-2.38243 -1.12798,-4.599766 -2.23036,-6.764445 -1.08372,-2.127637 -2.49928,-4.074538 -4.18837,-5.762439 -1.68869,-1.687901 -3.63608,-3.102724 -5.76451,-4.185791 -2.16692,-1.102646 -4.38662,-1.802128 -6.77168,-2.230355 -2.34883,-0.421743 -4.744969,-0.561124 -7.119979,-0.625285 -1.09047,-0.0295 -2.1809,-0.04235 -3.27163,-0.04909 -1.29486,-0.0079 -2.59018,-0.0072 -3.88504,-0.0072 l -15.03474,-0.05374 z m -48.74947,74.745825 0.002,0.319877 c 0,1.295923 -6e-4,2.592212 0.007,3.888135 0.007,1.091667 0.0196,2.182948 0.0491,3.274218 0.0643,2.378065 0.20415,4.777033 0.62735,7.128773 0.42928,2.3856 1.13051,4.60577 2.235,6.77323 1.08584,2.13067 2.504,4.08043 4.19613,5.7707 1.69213,1.69029 3.64335,3.10682 5.77587,4.19148 2.17116,1.1041 4.39542,1.80418 6.78512,2.23294 2.35332,0.42241 4.75377,0.56267 7.13341,0.62683 1.09259,0.0295 2.18537,0.042 3.27836,0.0486 1.29737,0.008 2.59437,0.008 3.89175,0.008 h 14.90244 11.27219 14.87351 c 1.29485,0 2.58965,2.5e-4 3.88451,-0.008 1.09074,-0.007 2.18117,-0.0191 3.27164,-0.0486 2.37594,-0.0643 4.772679,-0.20468 7.122559,-0.62735 2.38361,-0.42875 4.60233,-1.12847 6.76806,-2.2319 2.12882,-1.08452 4.07671,-2.50145 5.76554,-4.192 1.68882,-1.69001 3.10414,-3.63939 4.18786,-5.76967 1.10304,-2.16852 1.80277,-4.39017 2.23139,-6.77736 0.42201,-2.35081 0.56216,-4.748534 0.62632,-7.125673 0.0295,-1.091402 0.0417,-2.182683 0.0481,-3.274218 0.007,-1.295923 0.007,-2.592212 0.007,-3.888135 v -0.319877 z" /><path
|
||||
id="path4518"
|
||||
style="display:inline;fill:#162d50;stroke:none;stroke-width:0.106942px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 51.096105,40.852287 -4.064351,8.567436 -2.345593,4.945434 H 13.229682 v 7.69152 11.365198 l 0.06563,14.553117 H 60.017007 L 67.733332,99.65955 75.449657,87.974992 H 122.2375 V 73.421875 62.044791 54.365157 H 90.780505 l -2.345594,-4.945434 -4.064351,-8.567436 -4.064351,8.567436 -2.346111,4.945434 H 67.733332 57.506567 l -2.34611,-4.945434 z" /><rect
|
||||
y="66.785446"
|
||||
x="-81.742691"
|
||||
height="12.833001"
|
||||
width="6.4165006"
|
||||
id="rect1043"
|
||||
style="display:inline;fill:#ffaaee;fill-opacity:1;stroke:none;stroke-width:0.075952;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
transform="scale(-1,1)" /><rect
|
||||
style="display:inline;fill:#ffaaee;fill-opacity:1;stroke:none;stroke-width:0.075952;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
id="rect1047"
|
||||
width="6.4165006"
|
||||
height="12.833001"
|
||||
x="-60.140472"
|
||||
y="66.785446"
|
||||
transform="scale(-1,1)" /><path
|
||||
id="path830"
|
||||
style="color:#000000;fill:#162d50;-inkscape-stroke:none"
|
||||
d="m 51.095589,26.798881 c -6.169023,0 -11.826367,2.225125 -16.215031,5.913334 l 2.185913,2.605009 c 3.790164,-3.181711 8.681211,-5.09633 14.029118,-5.09633 5.348221,0 10.239895,1.9148 14.030152,5.096847 l 2.185913,-2.605009 C 62.922884,29.024147 57.264963,26.798881 51.095589,26.798881 Z" /><path
|
||||
id="circle840"
|
||||
style="color:#000000;fill:#162d50;-inkscape-stroke:none"
|
||||
d="m 51.095589,33.656344 c -4.49058,0 -8.610793,1.621713 -11.807548,4.308781 l 2.18643,2.605525 c 2.597877,-2.180752 5.951484,-3.492293 9.621118,-3.492293 3.669777,0 7.024322,1.311388 9.622669,3.492293 l 2.185913,-2.605009 C 59.707311,35.278198 55.58652,33.656344 51.095589,33.656344 Z" /></g></svg>
|
After Width: | Height: | Size: 9.2 KiB |
|
@ -5,37 +5,13 @@
|
|||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
sodipodi:docname="l1.svg"
|
||||
inkscape:version="1.0beta1 (5c3063637d, 2019-10-15)"
|
||||
id="svg8"
|
||||
version="1.1"
|
||||
viewBox="0 0 67.733332 33.866668"
|
||||
height="128"
|
||||
viewBox="0 0 67.733332 67.733336"
|
||||
height="256"
|
||||
width="256">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:window-y="15"
|
||||
inkscape:window-x="1920"
|
||||
inkscape:window-height="1048"
|
||||
inkscape:window-width="1918"
|
||||
units="px"
|
||||
showgrid="false"
|
||||
inkscape:document-rotation="0"
|
||||
inkscape:current-layer="layer1"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:cy="61.042937"
|
||||
inkscape:cx="87.179174"
|
||||
inkscape:zoom="2.8"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0"
|
||||
borderopacity="1.0"
|
||||
bordercolor="#666666"
|
||||
pagecolor="#000000"
|
||||
id="base" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
|
@ -49,28 +25,12 @@
|
|||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
style="display:inline"
|
||||
id="layer1"
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="Ebene 1">
|
||||
<rect
|
||||
y="0"
|
||||
x="0"
|
||||
height="33.866665"
|
||||
width="67.73333"
|
||||
id="rect1406"
|
||||
style="display:none;fill:#ffffff;stroke:none;stroke-width:6.28119;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;paint-order:stroke markers fill" />
|
||||
<text
|
||||
id="text1404"
|
||||
y="25.830172"
|
||||
x="-3.9868231"
|
||||
style="font-style:normal;font-weight:normal;font-size:28.1184px;line-height:1.25;font-family:sans-serif;text-align:start;letter-spacing:0px;word-spacing:0px;text-anchor:start;inline-size:75.2671;display:none;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.70296"
|
||||
xml:space="preserve" />
|
||||
id="g2115"
|
||||
style="display:inline">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
transform="scale(0.26458333)"
|
||||
d="M 0,0 V 128 H 256 V 0 Z m 82.337891,31.205078 h 8.820312 V 89.478516 H 120.5293 V 97.625 H 82.337891 Z m 71.402339,0 h 8.82227 V 97.625 h -8.82227 V 43.658203 l -12.03906,12.039063 -6.22656,-6.226563 z"
|
||||
style="display:inline;fill:#ffffff;stroke:none;stroke-width:23.7399;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;paint-order:stroke markers fill"
|
||||
id="rect1518" />
|
||||
id="path2031"
|
||||
style="fill:#ffffff;stroke-width:5.54109;stroke-linecap:round;stroke-linejoin:round;paint-order:stroke markers fill"
|
||||
d="M 148.25391,0 0,148.25391 77.041016,225.29492 a 104.83116,104.83117 0 0 0 148.253904,0 104.83116,104.83117 0 0 0 0,-148.253904 z M 96.048828,111.22656 h 10.482422 v 68.65235 h 37.72656 v 8.82226 H 96.048828 Z m 78.980472,0 h 10.48242 v 68.65235 h 17.12305 v 8.82226 h -44.62696 v -8.82226 h 17.125 v -59.10547 l -18.6289,3.73633 v -9.54688 z"
|
||||
transform="scale(0.26458334)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 1.3 KiB |
|
@ -5,37 +5,13 @@
|
|||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
sodipodi:docname="l2.svg"
|
||||
inkscape:version="1.0beta1 (5c3063637d, 2019-10-15)"
|
||||
id="svg8"
|
||||
version="1.1"
|
||||
viewBox="0 0 67.733332 33.866668"
|
||||
height="128"
|
||||
viewBox="0 0 67.733332 67.733336"
|
||||
height="256"
|
||||
width="256">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:window-y="15"
|
||||
inkscape:window-x="1920"
|
||||
inkscape:window-height="1048"
|
||||
inkscape:window-width="1918"
|
||||
units="px"
|
||||
showgrid="false"
|
||||
inkscape:document-rotation="0"
|
||||
inkscape:current-layer="layer1"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:cy="66.072659"
|
||||
inkscape:cx="112.07001"
|
||||
inkscape:zoom="2.8"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0"
|
||||
borderopacity="1.0"
|
||||
bordercolor="#666666"
|
||||
pagecolor="#000000"
|
||||
id="base" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
|
@ -49,28 +25,12 @@
|
|||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
style="display:inline"
|
||||
id="layer1"
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="Ebene 1">
|
||||
<rect
|
||||
y="0"
|
||||
x="0"
|
||||
height="33.866665"
|
||||
width="67.73333"
|
||||
id="rect1406"
|
||||
style="display:none;fill:#ffffff;stroke:none;stroke-width:6.28119;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;paint-order:stroke markers fill" />
|
||||
<text
|
||||
id="text1404"
|
||||
y="25.830172"
|
||||
x="-3.9868231"
|
||||
style="font-style:normal;font-weight:normal;font-size:28.1184px;line-height:1.25;font-family:sans-serif;text-align:start;letter-spacing:0px;word-spacing:0px;text-anchor:start;inline-size:75.2671;display:none;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.70296"
|
||||
xml:space="preserve" />
|
||||
id="g2135"
|
||||
style="display:inline">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
transform="scale(0.26458333)"
|
||||
d="M 0,0 V 128 H 256 V 0 Z m 153.74023,30.375 c 5.88107,0 10.53413,1.382832 13.95899,4.150391 3.42485,2.767558 5.13672,6.556599 5.13672,11.365234 0,1.522157 -0.0525,2.697075 -0.15625,3.527344 -0.0692,0.795671 -0.32762,1.88575 -0.77735,3.269531 -0.41513,1.349186 -1.14185,2.83695 -2.17968,4.462891 -1.03784,1.591347 -2.43881,3.492984 -4.20313,5.707031 l -21.27539,26.621094 h 29.42188 V 97.625 h -39.85157 v -8.146484 l 25.32227,-31.705078 c 1.55675,-1.937291 2.6993,-3.632969 3.42578,-5.085938 0.72648,-1.487564 1.14035,-2.611968 1.24414,-3.373047 0.13843,-0.795674 0.20703,-1.936266 0.20703,-3.423828 0,-2.283238 -0.91649,-4.083848 -2.75,-5.398437 -1.83351,-1.314591 -4.34074,-1.970704 -7.52344,-1.970704 -3.18269,0 -5.69188,0.656113 -7.52539,1.970704 -1.8335,1.314589 -2.75,3.115199 -2.75,5.398437 l -8.82031,-1.402344 c 0,-4.358904 1.71187,-7.800773 5.13672,-10.326172 3.42485,-2.525397 8.07792,-3.787109 13.95898,-3.787109 z m -71.402339,0.830078 h 8.820312 V 89.478516 H 120.5293 V 97.625 H 82.337891 Z"
|
||||
style="fill:#ffffff;stroke:none;stroke-width:23.7399;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;paint-order:stroke markers fill"
|
||||
id="rect1462" />
|
||||
id="path2127"
|
||||
style="fill:#ffffff;stroke-width:5.54109;stroke-linecap:round;stroke-linejoin:round;paint-order:stroke markers fill"
|
||||
d="m 104.51367,0 a 104.83116,104.83117 0 0 0 -73.808592,30.705078 104.83116,104.83117 0 0 0 0,148.253902 L 107.74609,256 256,107.74609 178.95898,30.705078 A 104.83116,104.83117 0 0 0 104.51367,0 Z m 27.39844,57.390625 c 8.02592,0 14.42713,2.00657 19.20117,6.019531 4.77404,4.012961 7.16016,9.374608 7.16016,16.085938 0,3.182692 -0.6056,6.210686 -1.81641,9.082031 -1.17621,2.836747 -3.33823,6.191824 -6.48633,10.066406 -0.86486,1.003241 -3.61434,3.908169 -8.25,8.716799 -4.63566,4.77404 -11.17418,11.468 -19.61523,20.08203 h 36.58398 v 8.82226 h -49.19336 v -8.82226 c 3.97837,-4.11675 9.39248,-9.63383 16.24219,-16.55274 6.8843,-6.95349 11.20834,-11.432968 12.97266,-13.439448 3.35566,-3.770799 5.69127,-6.954243 7.00586,-9.548828 1.34918,-2.629183 2.02343,-5.207025 2.02343,-7.732422 0,-4.116745 -1.45343,-7.471821 -4.35937,-10.066406 -2.87134,-2.594588 -6.62411,-3.892578 -11.25977,-3.892578 -3.28647,-10e-7 -6.76462,0.571271 -10.43164,1.71289 -3.63242,1.141619 -7.52444,2.871623 -11.67578,5.189453 V 62.527344 c 4.22053,-1.695131 8.16502,-2.974982 11.83203,-3.839844 3.66702,-0.864862 7.0221,-1.296875 10.06641,-1.296875 z m -78.978516,1.400391 h 10.482422 v 68.652344 h 37.724604 v 8.82226 H 52.933594 Z"
|
||||
transform="scale(0.26458334)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 2.1 KiB |
36
assets/controls/l3.svg
Normal file
|
@ -0,0 +1,36 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
id="svg8"
|
||||
version="1.1"
|
||||
viewBox="0 0 67.733332 67.733336"
|
||||
height="256"
|
||||
width="256">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
style="display:inline"
|
||||
id="layer1">
|
||||
<path
|
||||
id="path1554"
|
||||
style="fill:#ffffff;stroke-width:11.0688;stroke-linecap:round;stroke-linejoin:round;paint-order:stroke markers fill"
|
||||
d="M 0,0 -158.50977,385.86328 256,256 C 256,114.61511 141.38489,0 0,0 Z m 127.02734,118.39453 c 7.95674,0 14.25301,1.8168 18.88868,5.44922 4.63566,3.59783 6.95312,8.47499 6.95312,14.63281 0,4.28972 -1.22934,7.92331 -3.68555,10.89844 -2.4562,2.94053 -5.94857,4.98143 -10.48047,6.12305 5.01622,1.07243 8.92441,3.30309 11.72657,6.69336 2.83674,3.39026 4.25586,7.57698 4.25586,12.55859 0,7.64538 -2.63031,13.56016 -7.88867,17.74609 -5.25838,4.18594 -12.72957,6.2793 -22.41602,6.2793 -3.25188,0 -6.60891,-0.32903 -10.06836,-0.98633 -3.42485,-0.6227 -6.9697,-1.57352 -10.63672,-2.85351 v -10.11914 c 2.90594,1.69512 6.08743,2.97498 9.54688,3.83984 3.45945,0.86486 7.0749,1.29689 10.8457,1.29687 6.57295,10e-6 11.57319,-1.29799 14.99805,-3.89257 3.45945,-2.59459 5.1875,-6.36354 5.1875,-11.31055 0,-4.56647 -1.60693,-8.13141 -4.82422,-10.69141 -3.18269,-2.59458 -7.6298,-3.89062 -13.33789,-3.89062 h -9.02735 v -8.61524 h 9.44336 c 5.15458,0 9.09907,-1.01947 11.83203,-3.06054 2.73297,-2.07567 4.09961,-5.0512 4.09961,-8.92578 0,-3.97837 -1.41911,-7.02255 -4.25586,-9.13282 -2.80215,-2.14486 -6.83343,-3.21679 -12.09179,-3.21679 -2.87135,0 -5.94986,0.31089 -9.23633,0.93359 -3.28648,0.6227 -6.90193,1.59166 -10.8457,2.90625 v -9.3418 c 3.97836,-1.10702 7.69875,-1.93672 11.1582,-2.49023 3.49404,-0.55351 6.78046,-0.83008 9.85937,-0.83008 z m -80.224606,1.40039 h 10.482422 v 68.6543 h 37.72461 v 8.82031 H 46.802734 Z"
|
||||
transform="scale(0.26458334)" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.3 KiB |
44
assets/controls/l3_raw.svg
Normal file
|
@ -0,0 +1,44 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
id="svg8"
|
||||
version="1.1"
|
||||
viewBox="0 0 67.733332 67.733336"
|
||||
height="256"
|
||||
width="256">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
style="display:inline"
|
||||
id="layer1">
|
||||
<path
|
||||
id="path1554"
|
||||
style="fill:#ffffff;stroke-width:2.92862;stroke-linecap:round;stroke-linejoin:round;paint-order:stroke markers fill"
|
||||
d="M 0,0 C 37.408085,0 67.73333,30.325245 67.73333,67.73333 L -41.939116,102.09299 Z" />
|
||||
<text
|
||||
id="text1404"
|
||||
y="25.830172"
|
||||
x="-3.9868231"
|
||||
style="font-style:normal;font-weight:normal;font-size:28.1184px;line-height:1.25;font-family:sans-serif;text-align:start;letter-spacing:0px;word-spacing:0px;text-anchor:start;inline-size:75.2671;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.70296"
|
||||
xml:space="preserve"
|
||||
transform="translate(13.609727,26.364208)"><tspan
|
||||
x="-3.9868231"
|
||||
y="25.830172"><tspan>L3</tspan></tspan></text>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.5 KiB |
124
assets/controls/lr12.svg
Normal file
|
@ -0,0 +1,124 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
id="svg8"
|
||||
version="1.1"
|
||||
viewBox="0 0 67.733332 67.733336"
|
||||
height="256"
|
||||
width="256"
|
||||
sodipodi:docname="lr12.svg"
|
||||
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)">
|
||||
<sodipodi:namedview
|
||||
pagecolor="#000000"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1916"
|
||||
inkscape:window-height="1031"
|
||||
id="namedview1468"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.79980469"
|
||||
inkscape:cx="101.38147"
|
||||
inkscape:cy="95.943219"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg8" />
|
||||
<defs
|
||||
id="defs2" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="g2115"
|
||||
inkscape:label="l1"
|
||||
style="display:inline">
|
||||
<path
|
||||
id="path2031"
|
||||
style="fill:#ffffff;stroke-width:1.46608;stroke-linecap:round;stroke-linejoin:round;paint-order:stroke markers fill"
|
||||
d="M 39.225383,0 0,39.225383 20.383723,59.609106 a 27.736579,27.73658 0 0 0 39.225787,4.04e-4 27.736579,27.73658 0 0 0 -4.04e-4,-39.225787 z" />
|
||||
<text
|
||||
id="text1404-4"
|
||||
y="25.830172"
|
||||
x="-3.9868231"
|
||||
style="font-style:normal;font-weight:normal;font-size:28.1184px;line-height:1.25;font-family:sans-serif;text-align:start;letter-spacing:0px;word-spacing:0px;text-anchor:start;inline-size:75.2671;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.70296"
|
||||
xml:space="preserve"
|
||||
transform="translate(26.639768,24.096855)"><tspan
|
||||
x="-3.9868231"
|
||||
y="25.830172"><tspan>L1</tspan></tspan></text>
|
||||
</g>
|
||||
<g
|
||||
id="g2125"
|
||||
inkscape:label="r1"
|
||||
style="display:inline">
|
||||
<path
|
||||
id="path2117"
|
||||
style="fill:#ffffff;stroke-width:1.46608;stroke-linecap:round;stroke-linejoin:round;paint-order:stroke markers fill"
|
||||
d="M 28.507951,0 67.733334,39.225383 47.349611,59.609106 a 27.736579,27.73658 0 0 1 -39.2257874,4.04e-4 27.736579,27.73658 0 0 1 4.04e-4,-39.225787 z" />
|
||||
<text
|
||||
id="text2123"
|
||||
y="25.830172"
|
||||
x="-3.9868231"
|
||||
style="font-style:normal;font-weight:normal;font-size:28.1184px;line-height:1.25;font-family:sans-serif;text-align:start;letter-spacing:0px;word-spacing:0px;text-anchor:start;inline-size:75.2671;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.70296"
|
||||
xml:space="preserve"
|
||||
transform="translate(13.644494,24.096798)"><tspan
|
||||
x="-3.9868231"
|
||||
y="25.830172"><tspan>R1</tspan></tspan></text>
|
||||
</g>
|
||||
<g
|
||||
id="g2135"
|
||||
inkscape:label="l2"
|
||||
style="display:inline">
|
||||
<path
|
||||
id="path2127"
|
||||
style="fill:#ffffff;stroke-width:1.46608;stroke-linecap:round;stroke-linejoin:round;paint-order:stroke markers fill"
|
||||
d="M 28.507951,67.733335 67.733334,28.507952 47.349611,8.1242288 a 27.736579,27.73658 0 0 0 -39.2257874,-4.04e-4 27.736579,27.73658 0 0 0 4.04e-4,39.2257872 z" />
|
||||
<text
|
||||
id="text2133"
|
||||
y="25.830172"
|
||||
x="-3.9868231"
|
||||
style="font-style:normal;font-weight:normal;font-size:28.1184px;line-height:1.25;font-family:sans-serif;text-align:start;letter-spacing:0px;word-spacing:0px;text-anchor:start;inline-size:75.2671;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.70296"
|
||||
xml:space="preserve"
|
||||
transform="translate(15.231995,10.223453)"><tspan
|
||||
x="-3.9868231"
|
||||
y="25.830172"><tspan>L2</tspan></tspan></text>
|
||||
</g>
|
||||
<g
|
||||
id="g2145"
|
||||
inkscape:label="r2"
|
||||
style="display:inline"
|
||||
transform="matrix(-1,0,0,1,67.733334,0)">
|
||||
<path
|
||||
id="path2137"
|
||||
style="fill:#ffffff;stroke-width:1.46608;stroke-linecap:round;stroke-linejoin:round;paint-order:stroke markers fill"
|
||||
d="M 28.507951,67.733335 67.733334,28.507952 47.349611,8.1242288 a 27.736579,27.73658 0 0 0 -39.2257874,-4.04e-4 27.736579,27.73658 0 0 0 4.04e-4,39.2257872 z" />
|
||||
<text
|
||||
id="text2143"
|
||||
y="25.830172"
|
||||
x="-3.9868231"
|
||||
style="font-style:normal;font-weight:normal;font-size:28.1184px;line-height:1.25;font-family:sans-serif;text-align:start;letter-spacing:0px;word-spacing:0px;text-anchor:start;inline-size:75.2671;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.70296"
|
||||
xml:space="preserve"
|
||||
transform="matrix(-1,0,0,1,42.347278,10.223453)"><tspan
|
||||
x="-3.9868231"
|
||||
y="25.830172"><tspan>R2</tspan></tspan></text>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 5.1 KiB |
|
@ -5,37 +5,13 @@
|
|||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
sodipodi:docname="r1.svg"
|
||||
inkscape:version="1.0beta1 (5c3063637d, 2019-10-15)"
|
||||
id="svg8"
|
||||
version="1.1"
|
||||
viewBox="0 0 67.733332 33.866668"
|
||||
height="128"
|
||||
viewBox="0 0 67.733332 67.733336"
|
||||
height="256"
|
||||
width="256">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:window-y="15"
|
||||
inkscape:window-x="1920"
|
||||
inkscape:window-height="1048"
|
||||
inkscape:window-width="1918"
|
||||
units="px"
|
||||
showgrid="false"
|
||||
inkscape:document-rotation="0"
|
||||
inkscape:current-layer="layer1"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:cy="56.825844"
|
||||
inkscape:cx="96.071037"
|
||||
inkscape:zoom="2.8"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0"
|
||||
borderopacity="1.0"
|
||||
bordercolor="#666666"
|
||||
pagecolor="#000000"
|
||||
id="base" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
|
@ -49,28 +25,12 @@
|
|||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
style="display:inline"
|
||||
id="layer1"
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="Ebene 1">
|
||||
<rect
|
||||
y="0"
|
||||
x="0"
|
||||
height="33.866665"
|
||||
width="67.73333"
|
||||
id="rect1406"
|
||||
style="display:none;fill:#ffffff;stroke:none;stroke-width:6.28119;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;paint-order:stroke markers fill" />
|
||||
<text
|
||||
id="text1404"
|
||||
y="25.830172"
|
||||
x="-3.9868231"
|
||||
style="font-style:normal;font-weight:normal;font-size:28.1184px;line-height:1.25;font-family:sans-serif;text-align:start;letter-spacing:0px;word-spacing:0px;text-anchor:start;inline-size:75.2671;display:none;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.70296"
|
||||
xml:space="preserve" />
|
||||
id="g2125"
|
||||
style="display:inline">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
transform="scale(0.26458333)"
|
||||
d="M 0,0 V 128 H 256 V 0 Z M 80.675781,31.205078 H 103.7168 c 5.77728,0 10.15378,1.330365 13.1289,3.994141 3.00972,2.663775 4.51367,7.110882 4.51368,13.33789 -1e-5,8.510244 -3.90821,13.871891 -11.72657,16.085938 L 123.84961,97.625 H 114.25 L 100.60352,65.919922 H 89.498047 V 97.625 h -8.822266 z m 73.064449,0 h 8.82227 V 97.625 h -8.82227 V 43.658203 l -12.03906,12.039063 -6.22656,-6.226563 z m -64.242183,8.146484 v 18.421876 h 8.822265 c 4.635658,0 8.164328,-0.710533 10.585938,-2.128907 2.42161,-1.418373 3.63086,-3.786351 3.63086,-7.107422 0,-3.286475 -0.76105,-5.640217 -2.2832,-7.058593 -1.48757,-1.418374 -3.66577,-2.126954 -6.53711,-2.126954 z"
|
||||
style="display:inline;fill:#ffffff;stroke:none;stroke-width:23.7399;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;paint-order:stroke markers fill"
|
||||
id="rect1556" />
|
||||
id="path2117"
|
||||
style="fill:#ffffff;stroke-width:5.54109;stroke-linecap:round;stroke-linejoin:round;paint-order:stroke markers fill"
|
||||
d="M 107.74609,0 30.705078,77.041016 a 104.83116,104.83117 0 0 0 0,148.253904 104.83116,104.83117 0 0 0 148.253902,0 L 256,148.25391 Z M 46.933594,111.22656 h 23.662109 c 8.856189,0 15.463362,1.85113 19.822266,5.55274 4.358906,3.70161 6.539062,9.28735 6.539062,16.75976 0,4.87783 -1.140593,8.92529 -3.423828,12.14258 -2.248642,3.21729 -5.535064,5.44991 -9.859375,6.69531 2.248643,0.76108 4.426845,2.38615 6.53711,4.87696 2.144856,2.4908 4.290687,5.91648 6.435546,10.27539 L 107.2832,188.70117 H 96.023438 l -9.91211,-19.875 C 83.551336,163.637 81.060286,160.19513 78.638672,158.5 c -2.387019,-1.69513 -5.655301,-2.54297 -9.806641,-2.54297 H 57.416016 v 32.74414 H 46.933594 Z m 93.613286,0 h 10.48242 v 68.65235 h 17.12304 v 8.82226 h -44.62695 v -8.82226 h 17.125 v -59.10547 l -18.62891,3.73633 v -9.54688 z m -83.130864,8.61328 v 27.50196 h 13.179687 c 5.050794,0 8.856023,-1.15874 11.416016,-3.47657 2.594587,-2.35242 3.892578,-5.79429 3.892578,-10.32617 0,-4.53188 -1.297991,-7.93942 -3.892578,-10.22265 -2.559993,-2.31783 -6.365222,-3.47657 -11.416016,-3.47657 z"
|
||||
transform="scale(0.26458334)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 2 KiB |
|
@ -5,37 +5,13 @@
|
|||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
sodipodi:docname="r2.svg"
|
||||
inkscape:version="1.0beta1 (5c3063637d, 2019-10-15)"
|
||||
id="svg8"
|
||||
version="1.1"
|
||||
viewBox="0 0 67.733332 33.866668"
|
||||
height="128"
|
||||
viewBox="0 0 67.733332 67.733336"
|
||||
height="256"
|
||||
width="256">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:window-y="15"
|
||||
inkscape:window-x="1920"
|
||||
inkscape:window-height="1048"
|
||||
inkscape:window-width="1918"
|
||||
units="px"
|
||||
showgrid="false"
|
||||
inkscape:document-rotation="0"
|
||||
inkscape:current-layer="layer1"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:cy="56.825844"
|
||||
inkscape:cx="96.071037"
|
||||
inkscape:zoom="2.8"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0"
|
||||
borderopacity="1.0"
|
||||
bordercolor="#666666"
|
||||
pagecolor="#000000"
|
||||
id="base" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
|
@ -49,28 +25,13 @@
|
|||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="g2145"
|
||||
style="display:inline"
|
||||
id="layer1"
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="Ebene 1">
|
||||
<rect
|
||||
y="0"
|
||||
x="0"
|
||||
height="33.866665"
|
||||
width="67.73333"
|
||||
id="rect1406"
|
||||
style="display:none;fill:#ffffff;stroke:none;stroke-width:6.28119;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;paint-order:stroke markers fill" />
|
||||
<text
|
||||
id="text1404"
|
||||
y="25.830172"
|
||||
x="-3.9868231"
|
||||
style="font-style:normal;font-weight:normal;font-size:28.1184px;line-height:1.25;font-family:sans-serif;text-align:start;letter-spacing:0px;word-spacing:0px;text-anchor:start;inline-size:75.2671;display:none;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.70296"
|
||||
xml:space="preserve" />
|
||||
transform="matrix(-1,0,0,1,67.733334,0)">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
transform="scale(0.26458333)"
|
||||
d="M 0,0 V 128 H 256 V 0 Z m 153.74023,30.375 c 5.88107,0 10.53413,1.382832 13.95899,4.150391 3.42485,2.767558 5.13672,6.556599 5.13672,11.365234 0,1.522157 -0.0525,2.697075 -0.15625,3.527344 -0.0692,0.795671 -0.32762,1.88575 -0.77735,3.269531 -0.41513,1.349186 -1.14185,2.83695 -2.17968,4.462891 -1.03784,1.591347 -2.43881,3.492984 -4.20313,5.707031 l -21.27539,26.621094 h 29.42188 V 97.625 h -39.85157 v -8.146484 l 25.32227,-31.705078 c 1.55675,-1.937291 2.6993,-3.632969 3.42578,-5.085938 0.72648,-1.487564 1.14035,-2.611968 1.24414,-3.373047 0.13843,-0.795674 0.20703,-1.936266 0.20703,-3.423828 0,-2.283238 -0.91649,-4.083848 -2.75,-5.398437 -1.83351,-1.314591 -4.34074,-1.970704 -7.52344,-1.970704 -3.18269,0 -5.69188,0.656113 -7.52539,1.970704 -1.8335,1.314589 -2.75,3.115199 -2.75,5.398437 l -8.82031,-1.402344 c 0,-4.358904 1.71187,-7.800773 5.13672,-10.326172 C 143.2061,31.636712 147.85917,30.375 153.74023,30.375 Z M 80.675781,31.205078 H 103.7168 c 5.77728,0 10.15378,1.330365 13.1289,3.994141 3.00972,2.663775 4.51367,7.110882 4.51368,13.33789 -1e-5,8.510244 -3.90821,13.871891 -11.72657,16.085938 L 123.84961,97.625 H 114.25 L 100.60352,65.919922 H 89.498047 V 97.625 h -8.822266 z m 8.822266,8.146484 v 18.421876 h 8.822265 c 4.635658,0 8.164328,-0.710533 10.585938,-2.128907 2.42161,-1.418373 3.63086,-3.786351 3.63086,-7.107422 0,-3.286475 -0.76105,-5.640217 -2.2832,-7.058593 -1.48757,-1.418374 -3.66577,-2.126954 -6.53711,-2.126954 z"
|
||||
style="display:inline;fill:#ffffff;stroke:none;stroke-width:23.7399;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;paint-order:stroke markers fill"
|
||||
id="rect1556" />
|
||||
id="path2137"
|
||||
style="fill:#ffffff;stroke-width:5.54109;stroke-linecap:round;stroke-linejoin:round;paint-order:stroke markers fill"
|
||||
d="M 77.041016,30.705078 0,107.74609 148.25391,256 225.29492,178.95898 a 104.83116,104.83117 0 0 0 0,-148.253902 104.83116,104.83117 0 0 0 -148.253904,0 z M 184.92383,57.390625 c 8.02592,0 14.42518,2.00657 19.19922,6.019531 4.77403,4.012961 7.16211,9.374608 7.16211,16.085938 0,3.182692 -0.6056,6.210686 -1.81641,9.082031 -1.17621,2.836747 -3.33823,6.191824 -6.48633,10.066406 -0.86486,1.003241 -3.61629,3.908169 -8.25195,8.716799 -4.63566,4.77404 -11.17223,11.468 -19.61328,20.08203 h 36.58203 v 8.82226 h -49.19336 v -8.82226 c 3.97837,-4.11675 9.39248,-9.63383 16.24219,-16.55274 6.8843,-6.95349 11.20833,-11.432968 12.97265,-13.439448 3.35567,-3.770799 5.69127,-6.954243 7.00586,-9.548828 1.34919,-2.629183 2.02344,-5.207025 2.02344,-7.732422 0,-4.116745 -1.45148,-7.471821 -4.35742,-10.066406 -2.87134,-2.594588 -6.62606,-3.892578 -11.26172,-3.892578 -3.28648,-10e-7 -6.76267,0.571271 -10.42969,1.71289 -3.63242,1.141619 -7.52444,2.871623 -11.67578,5.189453 V 62.527344 c 4.22053,-1.695131 8.16502,-2.974982 11.83203,-3.839844 3.66702,-0.864862 7.02209,-1.296875 10.06641,-1.296875 z m -93.613283,1.400391 h 23.664063 c 8.85619,0 15.46335,1.851125 19.82227,5.552734 4.3589,3.701611 6.5371,9.289311 6.5371,16.761719 0,4.877823 -1.14059,8.92529 -3.42382,12.142578 -2.24865,3.217287 -5.53507,5.447957 -9.85938,6.693359 2.24864,0.761074 4.42685,2.386144 6.53711,4.876954 2.14486,2.4908 4.29069,5.91648 6.43555,10.27539 l 10.63867,21.17187 h -11.26172 l -9.91016,-19.875 c -2.55999,-5.18917 -5.05104,-8.63104 -7.47265,-10.32617 -2.38702,-1.69513 -5.65726,-2.54297 -9.8086,-2.54297 h -11.41601 v 32.74414 H 91.310547 Z m 10.482423,8.615234 v 27.501953 h 13.18164 c 5.05079,0 8.85602,-1.158732 11.41601,-3.476562 2.5946,-2.352424 3.89063,-5.794292 3.89063,-10.326172 0,-4.531878 -1.29603,-7.93942 -3.89063,-10.222657 -2.55999,-2.31783 -6.36522,-3.476562 -11.41601,-3.476562 z"
|
||||
transform="matrix(-0.26458334,0,0,0.26458334,67.733334,0)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 4 KiB After Width: | Height: | Size: 2.9 KiB |
36
assets/controls/r3.svg
Normal file
|
@ -0,0 +1,36 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
id="svg8"
|
||||
version="1.1"
|
||||
viewBox="0 0 67.733332 67.733336"
|
||||
height="256"
|
||||
width="256">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
style="display:inline"
|
||||
id="layer1">
|
||||
<path
|
||||
id="path1554"
|
||||
style="fill:#ffffff;stroke-width:11.0688;stroke-linecap:round;stroke-linejoin:round;paint-order:stroke markers fill"
|
||||
d="M 256,0 C 114.61511,0 0,114.61511 0,256 l 414.50977,129.86328 z m -65.89648,118.39453 c 7.95673,0 14.25301,1.8168 18.88867,5.44922 4.63566,3.59783 6.95508,8.47499 6.95508,14.63281 0,4.28972 -1.22934,7.92331 -3.68555,10.89844 -2.45621,2.94053 -5.95055,4.98143 -10.48242,6.12305 5.0162,1.07243 8.92636,3.30309 11.72851,6.69336 2.83675,3.39026 4.25391,7.57698 4.25391,12.55859 0,7.64538 -2.62836,13.56016 -7.88672,17.74609 -5.25836,4.18594 -12.73151,6.2793 -22.41797,6.2793 -3.25188,0 -6.60695,-0.32903 -10.06641,-0.98633 -3.42484,-0.6227 -6.9697,-1.57352 -10.63671,-2.85351 v -10.11914 c 2.90592,1.69512 6.08742,2.97498 9.54687,3.83984 3.45945,0.86486 7.07492,1.29689 10.8457,1.29687 6.57297,2e-5 11.57124,-1.29799 14.9961,-3.89257 3.45945,-2.59459 5.18945,-6.36354 5.18945,-11.31055 0,-4.56647 -1.60888,-8.13141 -4.82617,-10.69141 -3.18269,-2.59458 -7.62785,-3.89062 -13.33594,-3.89062 h -9.0293 v -8.61524 h 9.44532 c 5.15458,0 9.09711,-1.01947 11.83008,-3.06054 2.73296,-2.07567 4.0996,-5.0512 4.0996,-8.92578 2e-5,-3.97838 -1.41715,-7.02255 -4.2539,-9.13282 -2.80215,-2.14485 -6.83343,-3.21679 -12.0918,-3.21679 -2.87134,0 -5.94985,0.31089 -9.23633,0.93359 -3.28647,0.6227 -6.90193,1.59166 -10.8457,2.90625 v -9.3418 c 3.97837,-1.10702 7.6968,-1.93672 11.15625,-2.49023 3.49404,-0.55349 6.78046,-0.83008 9.85938,-0.83008 z m -94.857426,1.40039 H 118.9082 c 8.85619,0 15.46336,1.85113 19.82227,5.55274 4.35891,3.70161 6.53906,9.28931 6.53906,16.76172 0,4.87782 -1.14059,8.92529 -3.42383,12.14257 -2.24864,3.21729 -5.53506,5.44796 -9.85937,6.69336 2.24864,0.76108 4.42684,2.3881 6.53711,4.87891 2.14485,2.4908 4.29069,5.91453 6.43554,10.27344 l 10.63672,21.17187 h -11.25976 l -9.91211,-19.87305 c -2.55999,-5.18916 -5.05104,-8.63299 -7.47266,-10.32812 -2.38702,-1.69513 -5.6553,-2.54102 -9.80664,-2.54102 h -11.41601 v 32.74219 H 95.246094 Z m 10.482426,8.61524 v 27.50195 h 13.17968 c 5.0508,0 8.85603,-1.15873 11.41602,-3.47656 2.59459,-2.35243 3.89258,-5.79429 3.89258,-10.32617 0,-4.53189 -1.29799,-7.93942 -3.89258,-10.22266 -2.55999,-2.31783 -6.36522,-3.47656 -11.41602,-3.47656 z"
|
||||
transform="scale(0.26458333)" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3 KiB |
44
assets/controls/r3_raw.svg
Normal file
|
@ -0,0 +1,44 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
id="svg8"
|
||||
version="1.1"
|
||||
viewBox="0 0 67.733332 67.733336"
|
||||
height="256"
|
||||
width="256">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
style="display:inline"
|
||||
id="layer1">
|
||||
<path
|
||||
id="path1554"
|
||||
style="fill:#ffffff;stroke-width:2.92862;stroke-linecap:round;stroke-linejoin:round;paint-order:stroke markers fill"
|
||||
d="M 67.733333,0 C 30.325248,0 3.2333333e-6,30.325245 3.2333333e-6,67.73333 L 109.67245,102.09299 Z" />
|
||||
<text
|
||||
id="text1404"
|
||||
y="25.830172"
|
||||
x="-3.9868231"
|
||||
style="font-style:normal;font-weight:normal;font-size:28.1184px;line-height:1.25;font-family:sans-serif;text-align:start;letter-spacing:0px;word-spacing:0px;text-anchor:start;inline-size:75.2671;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.70296"
|
||||
xml:space="preserve"
|
||||
transform="translate(26.427202,26.364208)"><tspan
|
||||
x="-3.9868231"
|
||||
y="25.830172"><tspan>R3</tspan></tspan></text>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.5 KiB |
65
assets/controls/touchpad_surface.svg
Normal file
|
@ -0,0 +1,65 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="1920"
|
||||
height="942"
|
||||
viewBox="0 0 507.99999 249.23751"
|
||||
version="1.1"
|
||||
id="svg981"
|
||||
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)"
|
||||
sodipodi:docname="touchpad_surface.svg">
|
||||
<defs
|
||||
id="defs975" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#000000"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.24748737"
|
||||
inkscape:cx="876.84187"
|
||||
inkscape:cy="725.61319"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
inkscape:document-rotation="0"
|
||||
showgrid="false"
|
||||
units="px"
|
||||
inkscape:window-width="1916"
|
||||
inkscape:window-height="1031"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata978">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<rect
|
||||
style="fill:#ffffff;stroke-width:1.59637;stroke-linecap:round;stroke-linejoin:round;paint-order:stroke markers fill"
|
||||
id="rect1544"
|
||||
width="508"
|
||||
height="249.2375"
|
||||
x="-1.7763568e-15"
|
||||
y="0"
|
||||
rx="32"
|
||||
ry="32" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.8 KiB |
|
@ -15,3 +15,4 @@ endif()
|
|||
|
||||
add_executable(chiaki-cli src/main.c)
|
||||
target_link_libraries(chiaki-cli chiaki-cli-lib)
|
||||
install(TARGETS chiaki-cli)
|
||||
|
|
|
@ -142,13 +142,19 @@ CHIAKI_EXPORT int chiaki_cli_cmd_discover(ChiakiLog *log, int argc, char *argv[]
|
|||
return 1;
|
||||
}
|
||||
|
||||
((struct sockaddr_in *)host_addr)->sin_port = htons(CHIAKI_DISCOVERY_PORT_PS4); // TODO: IPv6, PS5, should probably use the service
|
||||
|
||||
ChiakiDiscoveryPacket packet;
|
||||
memset(&packet, 0, sizeof(packet));
|
||||
packet.cmd = CHIAKI_DISCOVERY_CMD_SRCH;
|
||||
|
||||
chiaki_discovery_send(&discovery, &packet, host_addr, host_addr_len);
|
||||
packet.protocol_version = CHIAKI_DISCOVERY_PROTOCOL_VERSION_PS4;
|
||||
((struct sockaddr_in *)host_addr)->sin_port = htons(CHIAKI_DISCOVERY_PORT_PS4);
|
||||
err = chiaki_discovery_send(&discovery, &packet, host_addr, host_addr_len);
|
||||
if(err != CHIAKI_ERR_SUCCESS)
|
||||
CHIAKI_LOGE(log, "Failed to send discovery packet for PS4: %s", chiaki_error_string(err));
|
||||
packet.protocol_version = CHIAKI_DISCOVERY_PROTOCOL_VERSION_PS5;
|
||||
((struct sockaddr_in *)host_addr)->sin_port = htons(CHIAKI_DISCOVERY_PORT_PS5);
|
||||
err = chiaki_discovery_send(&discovery, &packet, host_addr, host_addr_len);
|
||||
if(err != CHIAKI_ERR_SUCCESS)
|
||||
CHIAKI_LOGE(log, "Failed to send discovery packet for PS5: %s", chiaki_error_string(err));
|
||||
|
||||
while(1)
|
||||
sleep(1); // TODO: wtf
|
||||
|
|
|
@ -11,10 +11,14 @@ static char doc[] = "Send a PS4 wakeup packet.";
|
|||
|
||||
#define ARG_KEY_HOST 'h'
|
||||
#define ARG_KEY_REGISTKEY 'r'
|
||||
#define ARG_KEY_PS4 '4'
|
||||
#define ARG_KEY_PS5 '5'
|
||||
|
||||
static struct argp_option options[] = {
|
||||
{ "host", ARG_KEY_HOST, "Host", 0, "Host to send wakeup packet to", 0 },
|
||||
{ "registkey", ARG_KEY_REGISTKEY, "RegistKey", 0, "PS4 registration key", 0 },
|
||||
{ "registkey", ARG_KEY_REGISTKEY, "RegistKey", 0, "Remote Play registration key (plaintext)", 0 },
|
||||
{ "ps4", ARG_KEY_PS4, NULL, 0, "PlayStation 4", 0 },
|
||||
{ "ps5", ARG_KEY_PS5, NULL, 0, "PlayStation 5 (default)", 0 },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
|
@ -22,6 +26,7 @@ typedef struct arguments
|
|||
{
|
||||
const char *host;
|
||||
const char *registkey;
|
||||
bool ps5;
|
||||
} Arguments;
|
||||
|
||||
static int parse_opt(int key, char *arg, struct argp_state *state)
|
||||
|
@ -39,6 +44,12 @@ static int parse_opt(int key, char *arg, struct argp_state *state)
|
|||
case ARGP_KEY_ARG:
|
||||
argp_usage(state);
|
||||
break;
|
||||
case ARG_KEY_PS4:
|
||||
arguments->ps5 = false;
|
||||
break;
|
||||
case ARG_KEY_PS5:
|
||||
arguments->ps5 = true;
|
||||
break;
|
||||
default:
|
||||
return ARGP_ERR_UNKNOWN;
|
||||
}
|
||||
|
@ -51,6 +62,7 @@ static struct argp argp = { options, parse_opt, 0, doc, 0, 0, 0 };
|
|||
CHIAKI_EXPORT int chiaki_cli_cmd_wakeup(ChiakiLog *log, int argc, char *argv[])
|
||||
{
|
||||
Arguments arguments = { 0 };
|
||||
arguments.ps5 = true;
|
||||
error_t argp_r = argp_parse(&argp, argc, argv, ARGP_IN_ORDER, NULL, &arguments);
|
||||
if(argp_r != 0)
|
||||
return 1;
|
||||
|
@ -73,5 +85,5 @@ CHIAKI_EXPORT int chiaki_cli_cmd_wakeup(ChiakiLog *log, int argc, char *argv[])
|
|||
|
||||
uint64_t credential = (uint64_t)strtoull(arguments.registkey, NULL, 16);
|
||||
|
||||
return chiaki_discovery_wakeup(log, NULL, arguments.host, credential, false);
|
||||
return chiaki_discovery_wakeup(log, NULL, arguments.host, credential, arguments.ps5);
|
||||
}
|
||||
|
|
|
@ -49,7 +49,11 @@ function (_ffmpeg_find component headername)
|
|||
|
||||
# Try pkg-config first
|
||||
if(PKG_CONFIG_FOUND)
|
||||
pkg_check_modules(FFMPEG_${component} lib${component} IMPORTED_TARGET)
|
||||
if(CMAKE_VERSION VERSION_LESS "3.6")
|
||||
pkg_check_modules(FFMPEG_${component} lib${component})
|
||||
else()
|
||||
pkg_check_modules(FFMPEG_${component} lib${component} IMPORTED_TARGET)
|
||||
endif()
|
||||
if(FFMPEG_${component}_FOUND)
|
||||
if((TARGET PkgConfig::FFMPEG_${component}) AND (NOT CMAKE_VERSION VERSION_LESS "3.11.0"))
|
||||
if(APPLE)
|
||||
|
@ -69,6 +73,9 @@ function (_ffmpeg_find component headername)
|
|||
add_library(FFMPEG::${component} ALIAS PkgConfig::FFMPEG_${component})
|
||||
else()
|
||||
add_library("FFMPEG::${component}" INTERFACE IMPORTED)
|
||||
if(CMAKE_VERSION VERSION_LESS "3.6")
|
||||
link_directories("${FFMPEG_${component}_LIBRARY_DIRS}")
|
||||
endif()
|
||||
set_target_properties("FFMPEG::${component}" PROPERTIES
|
||||
INTERFACE_LINK_DIRECTORIES "${FFMPEG_${component}_LIBRARY_DIRS}"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${FFMPEG_${component}_INCLUDE_DIRS}"
|
||||
|
@ -224,10 +231,14 @@ foreach (_ffmpeg_component IN LISTS FFMPEG_FIND_COMPONENTS)
|
|||
list(APPEND _ffmpeg_required_vars
|
||||
"FFMPEG_${_ffmpeg_component}_LIBRARIES")
|
||||
else()
|
||||
set(FFMPEG_${_ffmpeg_component}_INCLUDE_DIRS
|
||||
"${FFMPEG_${_ffmpeg_component}_INCLUDE_DIR}")
|
||||
set(FFMPEG_${_ffmpeg_component}_LIBRARIES
|
||||
"${FFMPEG_${_ffmpeg_component}_LIBRARY}")
|
||||
if(NOT FFMPEG_${_ffmpeg_component}_INCLUDE_DIRS)
|
||||
set(FFMPEG_${_ffmpeg_component}_INCLUDE_DIRS
|
||||
"${FFMPEG_${_ffmpeg_component}_INCLUDE_DIR}")
|
||||
endif()
|
||||
if(NOT FFMPEG_${_ffmpeg_component}_LIBRARIES)
|
||||
set(FFMPEG_${_ffmpeg_component}_LIBRARIES
|
||||
"${FFMPEG_${_ffmpeg_component}_LIBRARY}")
|
||||
endif()
|
||||
list(APPEND FFMPEG_INCLUDE_DIRS
|
||||
"${FFMPEG_${_ffmpeg_component}_INCLUDE_DIRS}")
|
||||
list(APPEND FFMPEG_LIBRARIES
|
||||
|
|
|
@ -1,6 +1,26 @@
|
|||
|
||||
find_package(SDL2 NO_MODULE QUIET)
|
||||
|
||||
# Adapted from libsdl-org/SDL_ttf: https://github.com/libsdl-org/SDL_ttf/blob/main/cmake/FindPrivateSDL2.cmake#L19-L31
|
||||
# Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
# Licensed under the zlib license (https://github.com/libsdl-org/SDL_ttf/blob/main/LICENSE.txt)
|
||||
set(SDL2_VERSION_MAJOR)
|
||||
set(SDL2_VERSION_MINOR)
|
||||
set(SDL2_VERSION_PATCH)
|
||||
set(SDL2_VERSION)
|
||||
if(SDL2_INCLUDE_DIR)
|
||||
file(READ "${SDL2_INCLUDE_DIR}/SDL_version.h" _sdl_version_h)
|
||||
string(REGEX MATCH "#define[ \t]+SDL_MAJOR_VERSION[ \t]+([0-9]+)" _sdl2_major_re "${_sdl_version_h}")
|
||||
set(SDL2_VERSION_MAJOR "${CMAKE_MATCH_1}")
|
||||
string(REGEX MATCH "#define[ \t]+SDL_MINOR_VERSION[ \t]+([0-9]+)" _sdl2_minor_re "${_sdl_version_h}")
|
||||
set(SDL2_VERSION_MINOR "${CMAKE_MATCH_1}")
|
||||
string(REGEX MATCH "#define[ \t]+SDL_PATCHLEVEL[ \t]+([0-9]+)" _sdl2_patch_re "${_sdl_version_h}")
|
||||
set(SDL2_VERSION_PATCH "${CMAKE_MATCH_1}")
|
||||
if(_sdl2_major_re AND _sdl2_minor_re AND _sdl2_patch_re)
|
||||
set(SDL2_VERSION "${SDL2_VERSION_MAJOR}.${SDL2_VERSION_MINOR}.${SDL2_VERSION_PATCH}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(SDL2_FOUND AND (NOT TARGET SDL2::SDL2))
|
||||
add_library(SDL2::SDL2 UNKNOWN IMPORTED GLOBAL)
|
||||
if(NOT SDL2_LIBDIR)
|
||||
|
|
|
@ -33,8 +33,8 @@ endif()
|
|||
|
||||
find_program(MAKE_EXE NAMES gmake make)
|
||||
ExternalProject_Add(OpenSSL-ExternalProject
|
||||
URL https://www.openssl.org/source/openssl-1.1.1d.tar.gz
|
||||
URL_HASH SHA256=1e3a91bc1f9dfce01af26026f856e064eab4c8ee0a8f457b5ae30b40b8b711f2
|
||||
URL https://www.openssl.org/source/openssl-1.1.1s.tar.gz
|
||||
URL_HASH SHA256=c5ac01e760ee6ff0dab61d6b2bbd30146724d063eb322180c6f18a6f74e4b6aa
|
||||
INSTALL_DIR "${OPENSSL_INSTALL_DIR}"
|
||||
CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env ${OPENSSL_BUILD_ENV}
|
||||
"<SOURCE_DIR>/Configure" "--prefix=<INSTALL_DIR>" no-shared ${OPENSSL_CONFIG_EXTRA_ARGS} "${OPENSSL_OS_COMPILER}"
|
||||
|
|
|
@ -1,34 +1,15 @@
|
|||
|
||||
# Find DEVKITPRO
|
||||
set(DEVKITPRO "$ENV{DEVKITPRO}" CACHE PATH "Path to DevKitPro")
|
||||
set(PORTLIBS_PREFIX "$ENV{PORTLIBS_PREFIX}" CACHE PATH "Path to portlibs inside DevKitPro")
|
||||
if(NOT DEVKITPRO OR NOT PORTLIBS_PREFIX)
|
||||
message(FATAL_ERROR "Please set DEVKITPRO & PORTLIBS_PREFIX env before calling cmake. https://devkitpro.org/wiki/Getting_Started")
|
||||
if(NOT DEVKITPRO)
|
||||
message(FATAL_ERROR "Please set DEVKITPRO env before calling cmake. https://devkitpro.org/wiki/Getting_Started")
|
||||
endif()
|
||||
|
||||
# include devkitpro toolchain
|
||||
include("${DEVKITPRO}/switch.cmake")
|
||||
include("${DEVKITPRO}/cmake/Switch.cmake")
|
||||
|
||||
set(NSWITCH TRUE)
|
||||
|
||||
# Enable gcc -g, to use
|
||||
# /opt/devkitpro/devkitA64/bin/aarch64-none-elf-addr2line -e build_switch/switch/chiaki -f -p -C -a 0xCCB5C
|
||||
# set(CMAKE_BUILD_TYPE Debug)
|
||||
# set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
# set(BUILD_SHARED_LIBS OFF CACHE INTERNAL "Shared libs not available" )
|
||||
|
||||
# FIXME rework this file to use the toolchain only
|
||||
# https://github.com/diasurgical/devilutionX/pull/764
|
||||
set(ARCH "-march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -ftls-model=local-exec")
|
||||
# set(CMAKE_C_FLAGS "-O2 -ffunction-sections ${ARCH}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}")
|
||||
# workaroud force -fPIE to avoid
|
||||
# aarch64-none-elf/bin/ld: read-only segment has dynamic relocations
|
||||
set(CMAKE_EXE_LINKER_FLAGS "-specs=${DEVKITPRO}/libnx/switch.specs ${ARCH} -fPIE -Wl,-Map,Output.map")
|
||||
|
||||
# add portlibs to the list of include dir
|
||||
include_directories("${PORTLIBS_PREFIX}/include")
|
||||
|
||||
# troubleshoot
|
||||
message(STATUS "CMAKE_FIND_ROOT_PATH = ${CMAKE_FIND_ROOT_PATH}")
|
||||
message(STATUS "PKG_CONFIG_EXECUTABLE = ${PKG_CONFIG_EXECUTABLE}")
|
||||
|
@ -79,4 +60,3 @@ function(add_nro_target output_name target title author version icon romfs)
|
|||
endfunction()
|
||||
|
||||
set(CMAKE_USE_SYSTEM_ENVIRONMENT_PATH OFF)
|
||||
set(CMAKE_PREFIX_PATH "/")
|
||||
|
|
|
@ -6,9 +6,6 @@ find_package(Qt5 REQUIRED COMPONENTS Core Widgets Gui Concurrent Multimedia Open
|
|||
if(APPLE)
|
||||
find_package(Qt5 REQUIRED COMPONENTS MacExtras)
|
||||
endif()
|
||||
if(CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER)
|
||||
find_package(SDL2 MODULE REQUIRED)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
add_definitions(-DWIN32_LEAN_AND_MEAN)
|
||||
|
@ -70,12 +67,12 @@ if(CHIAKI_ENABLE_CLI)
|
|||
endif()
|
||||
|
||||
target_link_libraries(chiaki Qt5::Core Qt5::Widgets Qt5::Gui Qt5::Concurrent Qt5::Multimedia Qt5::OpenGL Qt5::Svg)
|
||||
target_link_libraries(chiaki SDL2::SDL2)
|
||||
if(APPLE)
|
||||
target_link_libraries(chiaki Qt5::MacExtras)
|
||||
target_compile_definitions(chiaki PRIVATE CHIAKI_GUI_ENABLE_QT_MACEXTRAS)
|
||||
endif()
|
||||
if(CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER)
|
||||
target_link_libraries(chiaki SDL2::SDL2)
|
||||
target_compile_definitions(chiaki PRIVATE CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER)
|
||||
endif()
|
||||
if(CHIAKI_ENABLE_SETSU)
|
||||
|
|
BIN
gui/chiaki.icns
|
@ -3,6 +3,8 @@
|
|||
#ifndef CHIAKI_AVOPENGLWIDGET_H
|
||||
#define CHIAKI_AVOPENGLWIDGET_H
|
||||
|
||||
#include "transformmode.h"
|
||||
|
||||
#include <chiaki/log.h>
|
||||
|
||||
#include <QOpenGLWidget>
|
||||
|
@ -74,21 +76,24 @@ class AVOpenGLWidget: public QOpenGLWidget
|
|||
public:
|
||||
static QSurfaceFormat CreateSurfaceFormat();
|
||||
|
||||
explicit AVOpenGLWidget(StreamSession *session, QWidget *parent = nullptr);
|
||||
explicit AVOpenGLWidget(StreamSession *session, QWidget *parent = nullptr, TransformMode transform_mode = TransformMode::Fit);
|
||||
~AVOpenGLWidget() override;
|
||||
|
||||
void SwapFrames();
|
||||
AVOpenGLFrame *GetBackgroundFrame() { return &frames[1 - frame_fg]; }
|
||||
|
||||
void SetTransformMode(TransformMode mode) { transform_mode = mode; }
|
||||
TransformMode GetTransformMode() const { return transform_mode; }
|
||||
|
||||
protected:
|
||||
TransformMode transform_mode;
|
||||
void mouseMoveEvent(QMouseEvent *event) override;
|
||||
|
||||
void initializeGL() override;
|
||||
void paintGL() override;
|
||||
|
||||
private slots:
|
||||
void ResetMouseTimeout();
|
||||
public slots:
|
||||
void ResetMouseTimeout();
|
||||
void HideMouse();
|
||||
};
|
||||
|
||||
|
|
|
@ -12,8 +12,12 @@
|
|||
|
||||
#ifdef CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER
|
||||
#include <SDL.h>
|
||||
#include <chiaki/orientation.h>
|
||||
#endif
|
||||
|
||||
#define PS_TOUCHPAD_MAX_X 1920
|
||||
#define PS_TOUCHPAD_MAX_Y 1079
|
||||
|
||||
class Controller;
|
||||
|
||||
class ControllerManager : public QObject
|
||||
|
@ -33,7 +37,9 @@ class ControllerManager : public QObject
|
|||
private slots:
|
||||
void UpdateAvailableControllers();
|
||||
void HandleEvents();
|
||||
void ControllerEvent(int device_id);
|
||||
#ifdef CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER
|
||||
void ControllerEvent(SDL_Event evt);
|
||||
#endif
|
||||
|
||||
public:
|
||||
static ControllerManager *GetInstance();
|
||||
|
@ -57,12 +63,24 @@ class Controller : public QObject
|
|||
private:
|
||||
Controller(int device_id, ControllerManager *manager);
|
||||
|
||||
void UpdateState();
|
||||
#ifdef CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER
|
||||
void UpdateState(SDL_Event event);
|
||||
bool HandleButtonEvent(SDL_ControllerButtonEvent event);
|
||||
bool HandleAxisEvent(SDL_ControllerAxisEvent event);
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 14)
|
||||
bool HandleSensorEvent(SDL_ControllerSensorEvent event);
|
||||
bool HandleTouchpadEvent(SDL_ControllerTouchpadEvent event);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
ControllerManager *manager;
|
||||
int id;
|
||||
ChiakiOrientationTracker orientation_tracker;
|
||||
ChiakiControllerState state;
|
||||
bool is_dualsense;
|
||||
|
||||
#ifdef CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER
|
||||
QMap<QPair<Sint64, Sint64>, uint8_t> touch_ids;
|
||||
SDL_GameController *controller;
|
||||
#endif
|
||||
|
||||
|
@ -73,9 +91,44 @@ class Controller : public QObject
|
|||
int GetDeviceID();
|
||||
QString GetName();
|
||||
ChiakiControllerState GetState();
|
||||
void SetRumble(uint8_t left, uint8_t right);
|
||||
void SetTriggerEffects(uint8_t type_left, const uint8_t *data_left, uint8_t type_right, const uint8_t *data_right);
|
||||
bool IsDualSense();
|
||||
|
||||
signals:
|
||||
void StateChanged();
|
||||
};
|
||||
|
||||
/* PS5 trigger effect documentation:
|
||||
https://controllers.fandom.com/wiki/Sony_DualSense#FFB_Trigger_Modes
|
||||
|
||||
Taken from SDL2, licensed under the zlib license,
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
https://github.com/libsdl-org/SDL/blob/release-2.24.1/test/testgamecontroller.c#L263-L289
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
Uint8 ucEnableBits1; /* 0 */
|
||||
Uint8 ucEnableBits2; /* 1 */
|
||||
Uint8 ucRumbleRight; /* 2 */
|
||||
Uint8 ucRumbleLeft; /* 3 */
|
||||
Uint8 ucHeadphoneVolume; /* 4 */
|
||||
Uint8 ucSpeakerVolume; /* 5 */
|
||||
Uint8 ucMicrophoneVolume; /* 6 */
|
||||
Uint8 ucAudioEnableBits; /* 7 */
|
||||
Uint8 ucMicLightMode; /* 8 */
|
||||
Uint8 ucAudioMuteBits; /* 9 */
|
||||
Uint8 rgucRightTriggerEffect[11]; /* 10 */
|
||||
Uint8 rgucLeftTriggerEffect[11]; /* 21 */
|
||||
Uint8 rgucUnknown1[6]; /* 32 */
|
||||
Uint8 ucLedFlags; /* 38 */
|
||||
Uint8 rgucUnknown2[2]; /* 39 */
|
||||
Uint8 ucLedAnim; /* 41 */
|
||||
Uint8 ucLedBrightness; /* 42 */
|
||||
Uint8 ucPadLights; /* 43 */
|
||||
Uint8 ucLedRed; /* 44 */
|
||||
Uint8 ucLedGreen; /* 45 */
|
||||
Uint8 ucLedBlue; /* 46 */
|
||||
} DS5EffectsState_t;
|
||||
|
||||
#endif // CHIAKI_CONTROLLERMANAGER_H
|
||||
|
|
|
@ -55,6 +55,7 @@ class MainWindow : public QMainWindow
|
|||
|
||||
void UpdateDiscoveryEnabled();
|
||||
void ShowSettings();
|
||||
void Quit();
|
||||
|
||||
void UpdateDisplayServers();
|
||||
void UpdateServerWidgets();
|
||||
|
|
|
@ -63,6 +63,9 @@ class Settings : public QObject
|
|||
void SetLogVerbose(bool enabled) { settings.setValue("settings/log_verbose", enabled); }
|
||||
uint32_t GetLogLevelMask();
|
||||
|
||||
bool GetDualSenseEnabled() const { return settings.value("settings/dualsense_enabled", false).toBool(); }
|
||||
void SetDualSenseEnabled(bool enabled) { settings.setValue("settings/dualsense_enabled", enabled); }
|
||||
|
||||
ChiakiVideoResolutionPreset GetResolution() const;
|
||||
void SetResolution(ChiakiVideoResolutionPreset resolution);
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ class SettingsDialog : public QDialog
|
|||
|
||||
QCheckBox *log_verbose_check_box;
|
||||
QComboBox *disconnect_action_combo_box;
|
||||
QCheckBox *dualsense_check_box;
|
||||
|
||||
QComboBox *resolution_combo_box;
|
||||
QComboBox *fps_combo_box;
|
||||
|
@ -37,6 +38,7 @@ class SettingsDialog : public QDialog
|
|||
|
||||
private slots:
|
||||
void LogVerboseChanged();
|
||||
void DualSenseChanged();
|
||||
void DisconnectActionSelected();
|
||||
|
||||
void ResolutionSelected();
|
||||
|
|
|
@ -13,12 +13,14 @@
|
|||
|
||||
#if CHIAKI_GUI_ENABLE_SETSU
|
||||
#include <setsu.h>
|
||||
#include <chiaki/orientation.h>
|
||||
#endif
|
||||
|
||||
#include "exception.h"
|
||||
#include "sessionlog.h"
|
||||
#include "controllermanager.h"
|
||||
#include "settings.h"
|
||||
#include "transformmode.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QImage>
|
||||
|
@ -52,9 +54,18 @@ struct StreamSessionConnectInfo
|
|||
ChiakiConnectVideoProfile video_profile;
|
||||
unsigned int audio_buffer_size;
|
||||
bool fullscreen;
|
||||
TransformMode transform_mode;
|
||||
bool enable_keyboard;
|
||||
bool enable_dualsense;
|
||||
|
||||
StreamSessionConnectInfo(Settings *settings, ChiakiTarget target, QString host, QByteArray regist_key, QByteArray morning, bool fullscreen);
|
||||
StreamSessionConnectInfo(
|
||||
Settings *settings,
|
||||
ChiakiTarget target,
|
||||
QString host,
|
||||
QByteArray regist_key,
|
||||
QByteArray morning,
|
||||
bool fullscreen,
|
||||
TransformMode transform_mode);
|
||||
};
|
||||
|
||||
class StreamSession : public QObject
|
||||
|
@ -74,6 +85,9 @@ class StreamSession : public QObject
|
|||
Setsu *setsu;
|
||||
QMap<QPair<QString, SetsuTrackingId>, uint8_t> setsu_ids;
|
||||
ChiakiControllerState setsu_state;
|
||||
SetsuDevice *setsu_motion_device;
|
||||
ChiakiOrientationTracker orient_tracker;
|
||||
bool orient_dirty;
|
||||
#endif
|
||||
|
||||
ChiakiControllerState keyboard_state;
|
||||
|
@ -88,17 +102,23 @@ class StreamSession : public QObject
|
|||
unsigned int audio_buffer_size;
|
||||
QAudioOutput *audio_output;
|
||||
QIODevice *audio_io;
|
||||
SDL_AudioDeviceID haptics_output;
|
||||
uint8_t *haptics_resampler_buf;
|
||||
|
||||
QMap<Qt::Key, int> key_map;
|
||||
|
||||
void PushAudioFrame(int16_t *buf, size_t samples_count);
|
||||
void Event(ChiakiEvent *event);
|
||||
void PushHapticsFrame(uint8_t *buf, size_t buf_size);
|
||||
#if CHIAKI_GUI_ENABLE_SETSU
|
||||
void HandleSetsuEvent(SetsuEvent *event);
|
||||
#endif
|
||||
|
||||
private slots:
|
||||
void InitAudio(unsigned int channels, unsigned int rate);
|
||||
void InitHaptics();
|
||||
void Event(ChiakiEvent *event);
|
||||
void DisconnectHaptics();
|
||||
void ConnectHaptics();
|
||||
|
||||
public:
|
||||
explicit StreamSession(const StreamSessionConnectInfo &connect_info, QObject *parent = nullptr);
|
||||
|
@ -120,7 +140,7 @@ class StreamSession : public QObject
|
|||
#endif
|
||||
|
||||
void HandleKeyboardEvent(QKeyEvent *event);
|
||||
void HandleMouseEvent(QMouseEvent *event);
|
||||
bool HandleMouseEvent(QMouseEvent *event);
|
||||
|
||||
signals:
|
||||
void FfmpegFrameAvailable();
|
||||
|
|
|
@ -22,10 +22,14 @@ class StreamWindow: public QMainWindow
|
|||
const StreamSessionConnectInfo connect_info;
|
||||
StreamSession *session;
|
||||
|
||||
QAction *fullscreen_action;
|
||||
QAction *stretch_action;
|
||||
QAction *zoom_action;
|
||||
AVOpenGLWidget *av_widget;
|
||||
|
||||
void Init();
|
||||
void UpdateVideoTransform();
|
||||
void UpdateTransformModeActions();
|
||||
|
||||
protected:
|
||||
void keyPressEvent(QKeyEvent *event) override;
|
||||
|
@ -42,6 +46,9 @@ class StreamWindow: public QMainWindow
|
|||
void SessionQuit(ChiakiQuitReason reason, const QString &reason_str);
|
||||
void LoginPINRequested(bool incorrect);
|
||||
void ToggleFullscreen();
|
||||
void ToggleStretch();
|
||||
void ToggleZoom();
|
||||
void Quit();
|
||||
};
|
||||
|
||||
#endif // CHIAKI_GUI_STREAMWINDOW_H
|
||||
|
|