Merge branch 'cooker' into feat/steam-rom-manager

This commit is contained in:
XargonWan 2024-10-18 14:56:51 +09:00
commit 8ec67359de
69 changed files with 21246 additions and 1695 deletions

View file

@ -24,3 +24,4 @@ hash^RETRODECKMELONDSLATEST^https://github.com/RetroDECK/net.kuribo64.melonDS/re
hash^RETRODECKSOLARUSLATEST^https://github.com/RetroDECK/org.solarus_games.solarus.Launcher/releases/latest/download/RetroDECK-solarus-Artifact.tar.gz
hash^RETRODECKGZDOOMLATEST^https://github.com/RetroDECK/org.zdoom.GZDoom/releases/latest/download/RetroDECK-gzdoom-Artifact.tar.gz
hash^RETRODECKMAMELATEST^https://github.com/RetroDECK/MAME/releases/latest/download/RetroDECK-MAME-Artifact.tar.gz
hash^PORTMASTERLATESTSHA^https://github.com/PortsMaster/PortMaster-GUI/releases/latest/download/retrodeck.portmaster.zip

View file

@ -0,0 +1,19 @@
<?xml version="1.0"?>
<!--
This is an example of a custom system, you can add as many as you want by following this template.
More info on the official ES-DE Documentation:
https://gitlab.com/es-de/emulationstation-de/-/blob/master/USERGUIDE.md#game-system-customizations
-->
<systemList>
<!--
<system>
<name>mysystem</name>
<fullname>An example fake system</fullname>
<path>%ROMPATH%/mysystem</path>
<extension>.bin .BIN .chd .CHD .cue .CUE .iso .ISO .7z .7Z .zip .ZIP</extension>
<command label="MyEmulator">%EMULATOR_SOMETHING% %ROM%</command>
<platform>mysystem</platform>
<theme>mysystem</theme>
</system>
-->
</systemList>

View file

@ -736,15 +736,28 @@
"path": "dc"
},
"airlbios.zip": {
"md5": "09ef4b8dea6cd8db2de1c13d510a6a87",
"system": "dreamcast",
"md5": [
"09ef4b8dea6cd8db2de1c13d510a6a87",
"7a11bfe0cc72886d032e386db68f890c",
],
"system": [
"dreamcast",
"arcade",
],
"description": "Naomi Airline Pilots Deluxe BIOS",
"path": "dc"
},
"awbios.zip": {
"md5": "b2f122e091da223beb824efafc3d6a36",
"system": "arcade",
"description": "Naomi Atomiswave BIOS"
"md5": [
"b2f122e091da223beb824efafc3d6a36",
"85254fbe320ca82a768ec2c26bb08def",
],
"system": [
"dreamcast",
"arcade",
],
"description": "Naomi Atomiswave BIOS",
"path": "dc"
},
"bios.sms": {
"md5": "840481177270d5642a14ca71ee72844c",

View file

@ -168,6 +168,10 @@
"ryujinx_firmware": {
"filename": "Install-firmware-through-Ryujinx.txt",
"location": "$bios_folder/switch/firmware"
},
"custom_systems": {
"filename": "es_systems.xml",
"location": "$rdhome/ES-DE/custom_systems/es_systems.xml"
}
},
"compression_targets": {
@ -620,6 +624,9 @@
"pokemini": {
"name": "Nintendo Pokémon Mini"
},
"portmaster": {
"name": "PortMaster"
},
"ports": {
"name": "Ports"
},
@ -1129,6 +1136,13 @@
"description": "Steam ROM Manager (used to sync RetroDECK favorites with Steam)",
"name": "Steam ROM Manager",
"launch": "steam-rom-manager"
},
"portmaster": {
"description": "PortMaster",
"name": "PortMaster",
"url": "https://retrodeck.readthedocs.io/en/latest/wiki_about/what-is-retrodeck/",
"system": "portmaster",
"launch": "PortMaster"
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,31 +1,31 @@
The Team
Those that make RetroDECK happen
---
XargonWan
RetroDECK project founder and also one of the founding members of AmberELEC.
Grand General of the IPL (Italian Pizza Legion) in the internal pizza war.
---
Lazorne
Community management/outreach, testing, documentation, emulator configurations, Steam Input and feature request / issue management.
Meme Lord of the Wiki and also the cult leader of the NPC (The Nordic Pizza Cult) also called by the others as "The Pizza Heresy Cult" or "Harbingers of Pizza Chaos". Instigator of the internal pizza war.
---
jiannazzone
Web Development, Community management/outreach, testing, documentation. Have not choosen a side yet in the Pizza War.
Web Development, Community management/outreach, testing, documentation.
---
IceNine451
Creator of the RetroDECK configurator, the RetroDECK Framework and various cool things.
Freedom loving leader of the MCCP (Murican Cheese Crust Patriots) in the internal pizza war.
Creator of the OG RetroDECK configurator, the RetroDECK Framework and bash god.
---
@ -33,27 +33,27 @@ Lx32
Develops various new features, functions and tools.
1st Commander of the IPL (Italian Pizza Legion) nicknamed Paladin al Taglio in the internal pizza war.
---
WallK
Checks GODOT and other things.
Pizza Mercenary
Godot and scipting!
---
MonkeyX
Godot, Emulators and more things!
---
dottormac
Does bleeding edge cooker testing (lives in the danger zone), some feature suggestions and design.
Help with testing
---
MonkeyX
Jack of all trades: mainly working on GODOT and Manifest
---
We want give our special thanks to:
@ -70,3 +70,13 @@ We want give our special thanks to:
- All the community creators who creates various art and assets for the community.
You are all the ones that makes this project possible.
---
RetroDECK Alumni
Former members of the RetroDECK team have contributed to the project
---

View file

@ -16,6 +16,7 @@ borders_folder=/home/deck/retrodeck/borders
sdcard=/run/media/mmcblk0p1
[options]
power_user_warning=true
desktop_mode_warning=true
low_space_warning=true
@ -31,6 +32,10 @@ developer_options=false
kiroi_ponzu=false
akai_ponzu=false
steam_sync=false
sound_effects=true
volume_effects=10
font=1
cheevos_login=false
[cheevos]
duckstation=false

View file

@ -0,0 +1,36 @@
#!/bin/bash
# List of branches to pull and merge
branches=(
"cooker"
"feat/shadps4"
"feat/PortMaster"
"feat/steam-rom-manager"
)
# Get the current branch name
current_branch=$(git branch --show-current)
# Check if the current branch contains 'feat/' and 'okonomiyaki'
if [[ $current_branch == feat/* && $current_branch == *okonomiyaki* ]]; then
echo "Current branch is $current_branch, proceeding with fetch, pull, and merge."
# Iterate through the list of branches
for branch in "${branches[@]}"; do
echo "Fetching $branch..."
git fetch origin $branch
echo "Pulling $branch..."
git pull origin $branch
echo "Merging $branch into $current_branch..."
if ! git merge origin/$branch; then
echo "Merge conflict detected while merging $branch!"
echo "Please resolve the conflict, then run 'git merge --continue' to finish the merge."
exit 1 # Exit the script due to conflict
fi
done
else
echo "Current branch is not an okonomiyaki branch, quitting."
exit 1
fi

View file

@ -775,6 +775,15 @@ ponzu_remove() {
}
release_selector() {
# Show a progress bar
(
while true; do
echo "# Fetching all available releases from GitHub repositories... Please wait. This may take some time." ; sleep 1
done
) | zenity --progress --title="Fetching Releases" --text="Fetching releases..." --pulsate --no-cancel --auto-close --width=500 --height=150 &
progress_pid=$! # save process PID to kill it later
log d "Fetching releases from GitHub API for repository $cooker_repository_name"
# Fetch the main release from the RetroDECK repository
@ -783,6 +792,7 @@ release_selector() {
if [[ -z "$main_release" ]]; then
log e "Failed to fetch the main release"
kill $progress_pid # kill the progress bar
configurator_generic_dialog "Error" "Unable to fetch the main release. Please check your network connection or try again later."
return 1
fi
@ -796,11 +806,12 @@ release_selector() {
# Add the main release as the first entry in the release array
local release_array=("Main Release" "$main_tag_name" "$main_human_readable_date")
# Fetch all releases from the Cooker repository
local releases=$(curl -s https://api.github.com/repos/$git_organization_name/$cooker_repository_name/releases)
# Fetch all releases (including draft and pre-release) from the Cooker repository
local releases=$(curl -s https://api.github.com/repos/$git_organization_name/$cooker_repository_name/releases?per_page=100)
if [[ -z "$releases" ]]; then
log e "Failed to fetch releases or no releases available"
kill $progress_pid # kill the progress bar
configurator_generic_dialog "Error" "Unable to fetch releases. Please check your network connection or try again later."
return 1
fi
@ -809,15 +820,37 @@ release_selector() {
while IFS= read -r release; do
tag_name=$(echo "$release" | jq -r '.tag_name')
published_at=$(echo "$release" | jq -r '.published_at')
draft=$(echo "$release" | jq -r '.draft')
prerelease=$(echo "$release" | jq -r '.prerelease')
# Convert published_at to human-readable format
# Classifying releases
if echo "$tag_name" | grep -q "PR"; then
status="Pull Request"
elif [[ "$draft" == "true" ]]; then
status="Draft"
elif [[ "$prerelease" == "true" ]]; then
status="Pre-release"
elif [[ "$cooker_repository_name" == *"Cooker"* ]]; then
status="Cooker"
else
status="Main"
fi
# Convert published_at to human-readable format, if available
if [[ "$published_at" != "null" ]]; then
human_readable_date=$(date -d "$published_at" +"%d %B %Y %H:%M")
else
human_readable_date="Not published"
fi
# Ensure fields are properly aligned for Zenity
release_array+=("Cooker Channel" "$tag_name" "$human_readable_date")
release_array+=("$status" "$tag_name" "$human_readable_date")
done < <(echo "$releases" | jq -c '.[]' | sort -t: -k3,3r)
# kill the progress bar before opening the release list window
kill $progress_pid
if [[ ${#release_array[@]} -eq 0 ]]; then
configurator_generic_dialog "RetroDECK Updater" "No available releases found, exiting."
log d "No available releases found"

View file

@ -433,6 +433,9 @@ post_update() {
# Placeholder for version 0.9.0b
set_setting_value "$raconf" "libretro_info_path" "/var/config/retroarch/cores" "retroarch"
# TODO: Configurator dialog: Hey, we need to reset ES-DE! (because again ES-DE folders, new theme and such)
prepare_component "reset" "es-de"
prepare_component "reset" "portmaster"
prepare_component "reset" "ruffle"
log d "Steam Rom Manager was added, we need to prepare it"

View file

@ -66,6 +66,7 @@ prepare_component() {
set_setting_value "$es_settings" "UserThemeDirectory" "$themes_folder" "es_settings"
dir_prep "$rdhome/ES-DE/gamelists" "/var/config/ES-DE/gamelists"
dir_prep "$rdhome/ES-DE/collections" "/var/config/ES-DE/collections"
dir_prep "$rdhome/ES-DE/custom_systems" "/var/config/ES-DE/custom_systems"
dir_prep "$rd_logs_folder/ES-DE" "$es_source_logs"
log d "Generating roms system folders"
#es-de --home /var/config/ES-DE --create-system-dirs
@ -873,6 +874,21 @@ prepare_component() {
sed -i 's#RETRODECKSAVESDIR#'$saves_folder'#g' "/var/config/gzdoom/gzdoom.ini" # This is an unfortunate one-off because set_setting_value does not currently support JSON
fi
if [[ "$component" =~ ^(portmaster|all)$ ]]; then
component_found="true"
# TODO: MultiUser
log i "----------------------"
log i "Prepearing PortMaster"
log i "----------------------"
rm -rf "/var/data/PortMaster"
unzip "/app/retrodeck/PortMaster.zip" -d "/var/data/"
cp -f "/var/data/PortMaster/retrodeck/PortMaster.txt" "/var/data/PortMaster/PortMaster.sh"
chmod +x "/var/data/PortMaster/PortMaster.sh"
rm -f "$roms_folder/portmaster/PortMaster.sh"
install -Dm755 "/var/data/PortMaster/PortMaster.sh" "$roms_folder/portmaster/PortMaster.sh"
fi
if [[ "$component" =~ ^(ruffle|all)$ ]]; then
component_found="true"
log i "----------------------"

View file

@ -168,6 +168,7 @@ find_system_commands() {
substitute_placeholders() {
local cmd="$1"
log d "Substitute placeholder: working on $cmd"
game=$(echo "$game" | sed "s/'/'\\\\''/g") # escaping internal '
local rom_path="$game"
local rom_dir=$(dirname "$rom_path")
@ -193,6 +194,8 @@ substitute_placeholders() {
cmd="${cmd//"%FILENAME%"/"'$file_name'"}"
cmd="${cmd//"%ROMRAW%"/"'$rom_raw'"}"
cmd="${cmd//"%ROMPATH%"/"'$rom_dir'"}"
cmd="${cmd//"%ENABLESHORTCUTS%"/""}"
cmd="${cmd//"%EMULATOR_OS-SHELL%"/"/bin/sh"}"
# Ensure paths are quoted correctly
cmd="${cmd//"%ROM%"/"'$rom_path'"}"

View file

@ -535,21 +535,22 @@ modules:
url: https://github.com/RetroDECK/org.zdoom.GZDoom/releases/latest/download/RetroDECK-gzdoom-Artifact.tar.gz
sha256: RETRODECKGZDOOMLATEST
# TEMPORARLY DISABLED
# Ryujinx Appimage
# https://ryujinx.org/download
# This version was reported as working with symlinks: https://discord.com/channels/951662718102962256/951715885968654418/1264882000658169866
- name: Ryujinx-reported-working-version
buildsystem: simple
build-commands:
- |
tar -zxvf *.tar.gz
mv -v publish ${FLATPAK_DEST}/ryujinx
ln -sv ${FLATPAK_DEST}/ryujinx/Ryujinx ${FLATPAK_DEST}/bin/Ryujinx.sh
sources:
- type: file
url: https://github.com/Ryujinx/release-channel-master/releases/download/1.1.1297/ryujinx-1.1.1297-linux_x64.tar.gz
sha256: 28b38754e7d2e92083b313b23278c180ae54ac025edbbd0276ec03baec0cec0f
# - name: Ryujinx-reported-working-version
# buildsystem: simple
# build-commands:
# - |
# tar -zxvf *.tar.gz
# mv -v publish ${FLATPAK_DEST}/ryujinx
# ln -sv ${FLATPAK_DEST}/ryujinx/Ryujinx ${FLATPAK_DEST}/bin/Ryujinx.sh
# sources:
# - type: file
# url: https://github.com/Ryujinx/release-channel-master/releases/download/1.1.1297/ryujinx-1.1.1297-linux_x64.tar.gz
# sha256: 28b38754e7d2e92083b313b23278c180ae54ac025edbbd0276ec03baec0cec0f
# XEMU
# https://xemu.app/docs/download/#download-for-linux
@ -589,6 +590,33 @@ modules:
url: https://github.com/RetroDECK/MAME/releases/latest/download/RetroDECK-MAME-Artifact.tar.gz
sha256: RETRODECKMAMELATEST
# PortMaster
- name: PortMaster
buildsystem: simple
build-commands:
- mkdir -p "${FLATPAK_DEST}/retrodeck/PortMaster/"
- install -Dm755 "PortMaster" "${FLATPAK_DEST}/bin/PortMaster"
- install -Dm755 "harbourmaster" "${FLATPAK_DEST}/bin/harbourmaster"
- cp PortMaster.zip "${FLATPAK_DEST}/retrodeck/PortMaster.zip"
sources:
- type: file
url: https://github.com/PortsMaster/PortMaster-GUI/releases/latest/download/retrodeck.portmaster.zip
sha256: PORTMASTERLATESTSHA
dest-filename: PortMaster.zip
- type: script
commands:
- |
#!/bin/bash
"/var/data/PortMaster/PortMaster.sh" "$@"
dest-filename: PortMaster
- type: script
commands:
- |
#!/bin/bash
"/var/data/PortMaster/harbourmaster" "$@"
dest-filename: harbourmaster
# ES-DE
- name: ES-DE
@ -600,6 +628,7 @@ modules:
- cp -r files/* "${FLATPAK_DEST}"
- chmod +x "${FLATPAK_DEST}/bin/"*
sources:
# Testing the new feat/update-3.1.0
- type: archive
url: https://github.com/RetroDECK/ES-DE/releases/latest/download/RetroDECK-ES-DE-Artifact.tar.gz
sha256: RETRODECKESDELATEST

File diff suppressed because it is too large Load diff

View file

@ -1,15 +0,0 @@
extends Control
var rekku_state = false
func _input(event):
if event.is_action_released("rekku_hide"):
#self.visible = !self.visible
if rekku_state == false:
self.visible = true
rekku_state = true
%SplitContainer.split_offset=-300
elif event.is_action_released("rekku_hide") and rekku_state == true:
rekku_state = false
self.visible = false
%SplitContainer.split_offset=0

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://hh6yudttgfu4"
path="res://.godot/imported/RetroAchievements_logo_square_color.png-64abefe06c0579c28b1065af81a0acca.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/icons/home_made/RetroAchievements_logo_square_color.png"
dest_files=["res://.godot/imported/RetroAchievements_logo_square_color.png-64abefe06c0579c28b1065af81a0acca.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 797 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bl404iew0kt24"
path="res://.godot/imported/floorp.png-6d277ff687514a2a4d95956bdebe8f48.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/icons/pixelitos/128/floorp.png"
dest_files=["res://.godot/imported/floorp.png-6d277ff687514a2a4d95956bdebe8f48.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 637 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bgvrhhcyb3oav"
path="res://.godot/imported/retroachievements.png-c4b29821ae12837e3710e30d4646ea39.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/icons/pixelitos/128/retroachievements.png"
dest_files=["res://.godot/imported/retroachievements.png-c4b29821ae12837e3710e30d4646ea39.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 763 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://b4r1xk6ubwkmd"
path="res://.godot/imported/retroachievements_r.png-30093fcb234d7cc500450fe7b2bae8aa.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/icons/pixelitos/128/retroachievements_r.png"
dest_files=["res://.godot/imported/retroachievements_r.png-30093fcb234d7cc500450fe7b2bae8aa.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 761 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://syrfbhy5ov58"
path="res://.godot/imported/steam-rom-manager.png-8310109093f97cffa920822f53cc6704.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/icons/pixelitos/128/steam-rom-manager.png"
dest_files=["res://.godot/imported/steam-rom-manager.png-8310109093f97cffa920822f53cc6704.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 402 B

View file

@ -2,16 +2,16 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://n6ust3bdr2b7"
path="res://.godot/imported/tilemap_packed.png-7b301e6705a57389d2cd02d385b33920.ctex"
uid="uid://drxlki00ju7bc"
path="res://.godot/imported/floorp.png-ef66355fd6ca8ec96f4935c6c07e5541.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://tilemap_packed.png"
dest_files=["res://.godot/imported/tilemap_packed.png-7b301e6705a57389d2cd02d385b33920.ctex"]
source_file="res://assets/icons/pixelitos/16/floorp.png"
dest_files=["res://.godot/imported/floorp.png-ef66355fd6ca8ec96f4935c6c07e5541.ctex"]
[params]

Binary file not shown.

After

Width:  |  Height:  |  Size: 348 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://jpdccqpel2o0"
path="res://.godot/imported/retroachievements.png-7a6c7b94e38d9727ffd6620ed532a005.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/icons/pixelitos/16/retroachievements.png"
dest_files=["res://.godot/imported/retroachievements.png-7a6c7b94e38d9727ffd6620ed532a005.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 343 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bkgfwkkcn8m0c"
path="res://.godot/imported/retroachievements_r.png-32b929affa6aadc597b386f15a806086.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/icons/pixelitos/16/retroachievements_r.png"
dest_files=["res://.godot/imported/retroachievements_r.png-32b929affa6aadc597b386f15a806086.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 383 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://c8bluiipss6s7"
path="res://.godot/imported/steam-rom-manager.png-9c953bde1dcce1ed1cdd1f6b63483d8f.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/icons/pixelitos/16/steam-rom-manager.png"
dest_files=["res://.godot/imported/steam-rom-manager.png-9c953bde1dcce1ed1cdd1f6b63483d8f.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View file

@ -1,16 +0,0 @@
[gd_resource type="Theme" load_steps=5 format=3 uid="uid://co27jgr76wvcl"]
[ext_resource type="FontFile" uid="uid://c8lbo5ljgtaaa" path="res://assets/fonts/OpenDyslexic3/OpenDyslexic3-Regular.ttf" id="1_d8f12"]
[ext_resource type="Texture2D" uid="uid://buod4n6hw4i2m" path="res://assets/icons/pixelitos/vcs-normal.svg" id="1_pvl23"]
[ext_resource type="Texture2D" uid="uid://cn0tfnnihjvy7" path="res://assets/icons/pixelitos/vcs-grey.svg" id="2_ud3yg"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ghisc"]
bg_color = Color(0.6, 0.168627, 0.6, 0.372549)
[resource]
default_font = ExtResource("1_d8f12")
Button/styles/focus = SubResource("StyleBoxFlat_ghisc")
CheckBox/constants/check_v_offset = 0
CheckBox/constants/h_separation = 0
CheckBox/icons/checked = ExtResource("1_pvl23")
CheckBox/icons/unchecked = ExtResource("2_ud3yg")

View file

@ -1,14 +1,65 @@
[gd_resource type="Theme" load_steps=4 format=3 uid="uid://hhc60cllcg47"]
[gd_resource type="Theme" load_steps=7 format=3 uid="uid://hhc60cllcg47"]
[ext_resource type="Texture2D" uid="uid://buod4n6hw4i2m" path="res://assets/icons/pixelitos/vcs-normal.svg" id="1_pvl23"]
[ext_resource type="Texture2D" uid="uid://cn0tfnnihjvy7" path="res://assets/icons/pixelitos/vcs-grey.svg" id="2_ud3yg"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ghisc"]
bg_color = Color(0.6, 0.168627, 0.6, 0.372549)
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_md22p"]
bg_color = Color(0.580392, 0.419608, 0.921569, 1)
border_width_left = 15
border_width_top = 15
border_width_right = 15
border_width_bottom = 15
border_color = Color(0.843137, 0.137255, 0.909804, 1)
border_blend = true
corner_radius_top_left = 25
corner_radius_top_right = 25
corner_radius_bottom_right = 25
corner_radius_bottom_left = 25
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_kr58o"]
bg_color = Color(0.580392, 0.419608, 0.921569, 1)
border_width_left = 15
border_width_top = 15
border_width_right = 15
border_width_bottom = 15
border_color = Color(0.136826, 0.136826, 0.136826, 1)
border_blend = true
corner_radius_top_left = 25
corner_radius_top_right = 25
corner_radius_bottom_right = 25
corner_radius_bottom_left = 25
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_0ahfc"]
bg_color = Color(0.454524, 0.454524, 0.454524, 1)
border_width_left = 10
border_width_top = 10
border_width_right = 10
border_width_bottom = 10
border_color = Color(0.101961, 0.623529, 1, 1)
border_blend = true
corner_radius_top_left = 25
corner_radius_top_right = 25
corner_radius_bottom_right = 25
corner_radius_bottom_left = 25
corner_detail = 7
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_o8sf1"]
bg_color = Color(0.101961, 0.623529, 1, 1)
border_width_left = 15
border_width_top = 14
border_width_right = 15
border_width_bottom = 15
border_blend = true
corner_radius_top_left = 25
corner_radius_top_right = 25
corner_radius_bottom_right = 25
corner_radius_bottom_left = 25
[resource]
Button/styles/focus = SubResource("StyleBoxFlat_ghisc")
CheckBox/constants/check_v_offset = 0
CheckBox/constants/h_separation = 0
Button/constants/align_to_largest_stylebox = 1
Button/styles/focus = SubResource("StyleBoxFlat_md22p")
Button/styles/hover = SubResource("StyleBoxFlat_kr58o")
Button/styles/normal = SubResource("StyleBoxFlat_0ahfc")
Button/styles/pressed = SubResource("StyleBoxFlat_o8sf1")
CheckBox/icons/checked = ExtResource("1_pvl23")
CheckBox/icons/unchecked = ExtResource("2_ud3yg")

View file

@ -1,16 +0,0 @@
[gd_resource type="Theme" load_steps=5 format=3 uid="uid://dcyix4kssqal2"]
[ext_resource type="Texture2D" uid="uid://buod4n6hw4i2m" path="res://assets/icons/pixelitos/vcs-normal.svg" id="1_pvl23"]
[ext_resource type="FontFile" uid="uid://1x3s2oon2g64" path="res://assets/fonts/akrobat/Akrobat-Regular.otf" id="1_qs1qb"]
[ext_resource type="Texture2D" uid="uid://cn0tfnnihjvy7" path="res://assets/icons/pixelitos/vcs-grey.svg" id="2_ud3yg"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ghisc"]
bg_color = Color(0.6, 0.168627, 0.6, 0.372549)
[resource]
default_font = ExtResource("1_qs1qb")
Button/styles/focus = SubResource("StyleBoxFlat_ghisc")
CheckBox/constants/check_v_offset = 0
CheckBox/constants/h_separation = 0
CheckBox/icons/checked = ExtResource("1_pvl23")
CheckBox/icons/unchecked = ExtResource("2_ud3yg")

View file

@ -1,16 +0,0 @@
[gd_resource type="Theme" load_steps=5 format=3 uid="uid://3ljv5xgd4c1u"]
[ext_resource type="FontFile" uid="uid://q405aelgnmvo" path="res://assets/fonts/munro/munro.ttf" id="1_kirwi"]
[ext_resource type="Texture2D" uid="uid://buod4n6hw4i2m" path="res://assets/icons/pixelitos/vcs-normal.svg" id="1_pvl23"]
[ext_resource type="Texture2D" uid="uid://cn0tfnnihjvy7" path="res://assets/icons/pixelitos/vcs-grey.svg" id="2_ud3yg"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ghisc"]
bg_color = Color(0.6, 0.168627, 0.6, 0.372549)
[resource]
default_font = ExtResource("1_kirwi")
Button/styles/focus = SubResource("StyleBoxFlat_ghisc")
CheckBox/constants/check_v_offset = 0
CheckBox/constants/h_separation = 0
CheckBox/icons/checked = ExtResource("1_pvl23")
CheckBox/icons/unchecked = ExtResource("2_ud3yg")

View file

@ -0,0 +1,171 @@
# The RetroDECK Configurator
**Please note that we are going to rebuild the Configurator into a controller friendly GODOT application and that the current version is not the final design.**
<img src="../../wiki_images/graphics/configurator/configurator.png" width="500">
The `RetroDECK Configurator` is a unique multi-use utility that exists within RetroDECK to manage many aspects of the application and exposes functions from the `RetroDECK Framework` to the user.
The `RetroDECK Configurator` can be opened from:
- The main menu inside the ES-DE interface and choose `RetroDECK Configurator`.
<img src="../../wiki_images/graphics/configurator/configurator-esde.png" width="500">
* From the `RetroDECK Configurator.desktop` desktop shortcut, available in your application menu.
<img src="../../wiki_images/graphics/configurator/configurator-kde.png" width="500">
* From CLI by calling `flatpak run net.retrodeck.retrodeck --configurator`
What follows are the commands you can use inside the Configurator (more commands will be added during development).
## Presets & Settings
In this menu you can set various presets.
#### Widescreen: Enable/Disable
Enables or disables Widescreen in all supported emulators and cores.
#### Ask to Exit prompt: Enable/Disable
Enables or disables ask to exit prompts in all supported emulators and cores.
Note: If you disable this, the emulators will directly exit.
### Global: Presets & Settings
In this menu you will find presets and settings that span over multiple emulators.
#### RetroAchivements: Login
Login to RetroAchievements in all supported emulators and cores.
#### RetroAchivements: Logut
Logut from RetroAchievements in all supported emulators and cores.
#### RetroAchivements: Hardcore Mode
Enables `Hardcore Mode` from RetroAchievements in all supported emulators and cores.
#### Swap A/B and X/Y: Enable/Disable
Swaps `A/B` `X/Y` in supported emulators and cores.
#### Quick Resume: Enable/Disable
Enables `Quick Resume` aka `Auto Save` + `Auto Load` on exit in supported emulators and cores.
### RetroArch: Presets & Settings
In this menu you will find presets and settings for RetroArch.
#### Borders: Enable/Disable
Enable / Disable borders across the RetroArch cores you choose.
#### Rewind: Enable/Disable
Enable / Disable rewind across all of RetroArch (this may impact performance on some more demanding systems).
### Wii & Gamecube: Presets & Settings
In this menu you will find presets and settings for Dolphin and Primehack.
#### Dolphin Textures: Universal Dynamic Input
Enable / Disable Venomalias's Universal Dynamic Input Texture for Dolphin.
#### Primehack Textures: Universal Dynamic Input
Enable / Disable Venomalias's Universal Dynamic Input Texture for Primehack.
## Open Emulator
Here you launch and configure each emulator's settings, the option you choose will open that emulators GUI. For documentation on how to change the settings of each emulator's settings please check the website of each emulator.
(Please note that most of the emulator interfaces where not designed with controller input in mind for handling the applications GUI, just the games. You might need to use other inputs like the Steam Decks touchscreen or a mouse and keyboard to navigate properly).
## RetroDECK: Tools
### Tool: Remove empty ROM folders
This tool removes all the roms folders under retrodeck/roms/ that are empty to only leave those that are populated with content.
### Tool: Rebuild all ROM folders
This tool rebuilds rom folders you have accidentally removed or used the `Remove empty ROM folders` tool.
### Tool: Move files
This option lets you choose the installation path of the RetroDECK folder that handles ROMS, Saves, BIOS, etc... to a new location.
You get the following three options.
`Internal Storage` - Moves the folder to the internal storage.
`SD CARD` - Moves the folder to the SD CARD
`Custom Location` - Choose where you want the RetroDECK folder to be.
### Tool: Compress games
This option enables you to compress disc-based game image files `.gdi` `.iso` `.bin` `.cue` to the less space demanding `.chd` format.
You can choose either a single game or many.
### Install: RetroDECK SD Controller Profile
This option installs the Steam controller profiles that RetroDECK into Steam.
### Install: PS3 Firmware
This option downloads and installs the latest PS3 firmware. At the end of the download, RPCS3 will open requesting the user to install it (just press OK).
### RetroDECK: Change update settings (cooker only)
This option lets you turn on or off automatic updates on launch.
## RetroDECK: Troubleshooting
Various troubleshooting options.
### Backup: RetroDECK Userdata
Creates backups of the user data folders
### Check & Verify: Multi-file structure
Verifies the structure of multi disc/file games that uses `.m3u` files.
### Check & Verify: BIOS
Shows a detailed BIOS list of missing and current BIOS.
### RetroDECK: Reset
The reset menu resets various features
#### Reset Specific Emulator
Opens a menu where you can reset a specific emulator
#### Reset All Emulators
Resets all the emulators at once
#### Reset RetroDECK
Resets the entirety of RetroDECK.
`⚠️ WARNING! BACK UP YOUR DATA BEFORE RUNNING THIS! ⚠️`
## RetroDECK: About
This menu contains information about RetroDECK
### Version history
Displays the changelogs
### Credits
Displays the credits

View file

@ -2,44 +2,53 @@ extends Control
var bios_result: Dictionary
var console: bool = false
var BIOS_COLUMNS_BASIC := ["BIOS File Name", "System", "Found", "Hash Match", "Description"]
var BIOS_COLUMNS_EXPERT := ["BIOS File Name", "System", "Found", "Hash Match", "Description", "Subdirectory", "Hash"]
var BIOS_COLUMNS_BASIC := ["BIOS File Name", "System", "Found", "Hash\nMatch", "Description"]
var BIOS_COLUMNS_EXPERT := ["BIOS File Name", "System", "Found", "Hash\nMatch", "Description", "Sub\nFolder", "Hash"]
@onready var bios_type:int = get_tree().current_scene.bios_type
@onready var custom_theme: Theme = get_tree().current_scene.custom_theme
func _ready():
#var font_size = get_theme_font_size("font")
#custom_theme.default_font_size = 16
$".".theme = custom_theme
var table := $Table
var table: Tree = %Table
if bios_type == 1: #Basic BIOS button pressed
table.columns = BIOS_COLUMNS_BASIC.size()
for i in BIOS_COLUMNS_BASIC.size():
table.set_column_custom_minimum_width(0, 150)
table.set_column_custom_minimum_width(1, 200)
table.set_column_custom_minimum_width(4, 350)
table.set_column_title(i, BIOS_COLUMNS_BASIC[i])
else: #Assume advanced BIOS button pressed
table.columns = BIOS_COLUMNS_EXPERT.size()
for i in BIOS_COLUMNS_EXPERT.size():
table.set_column_custom_minimum_width(0, 170)
table.set_column_custom_minimum_width(1, 200)
table.set_column_custom_minimum_width(4, 325)
table.set_column_custom_minimum_width(6, 225)
table.set_column_title(i, BIOS_COLUMNS_EXPERT[i])
var root = table.create_item()
table.hide_root = true
if bios_type == 1: #Basic BIOS button pressed
var parameters = ["check_bios_files","basic"]
await run_thread_command(class_functions.wrapper_command, parameters, console)
class_functions.log_parameters[2] = class_functions.log_text + "Exit code: " + str(bios_result["exit_code"])
class_functions.execute_command(class_functions.wrapper_command,class_functions.log_parameters, false)
bios_result = await class_functions.run_thread_command(class_functions.wrapper_command, parameters, console)
else: #Assume advanced BIOS button pressed
var parameters = ["check_bios_files"]
class_functions.execute_command(class_functions.wrapper_command, parameters, false)
await run_thread_command(class_functions.wrapper_command, parameters, console)
bios_result = await class_functions.run_thread_command(class_functions.wrapper_command, parameters, console)
var bios_list = bios_result["output"]
var bios_lines = bios_list.split("\n")
var bios_lines: Array = bios_list.split("\n")
for line in bios_lines:
var bios_line = line.split("^")
var bios_line: Array = line.split("^")
var table_line: TreeItem = table.create_item(root)
for i in bios_line.size():
if bios_line.size() >= 5:
if bios_line[2] == "No":
table_line.set_custom_bg_color(i,Color(1,0,0,0.15))
elif bios_line[2] == "Yes":
table_line.set_custom_bg_color(i,Color(0,1,0,0.15))
elif bios_line[2] == "Yes" and bios_line[3] == "No":
table_line.set_custom_bg_color(i,Color(1,0.6,0,0.15))
table_line.set_text(i, bios_line[i])
if table_line.get_index() % 2 == 1:
table_line.set_custom_bg_color(i,Color(0.15, 0.15, 0.15, 1),false)
table_line.set_custom_color(i,Color(1,1,1,1))
func run_thread_command(command: String, parameters: Array, console: bool) -> void:
bios_result = await class_functions.run_command_in_thread(command, parameters, console)
#if table_line.get_index() % 2 == 1:
#table_line.set_custom_bg_color(i,Color(0.15, 0.15, 0.15, 1),false)
#table_line.set_custom_color(i,Color(1,1,1,1))

View file

@ -1,26 +1,41 @@
[gd_scene load_steps=2 format=3 uid="uid://bihon3xtx45y7"]
[gd_scene load_steps=3 format=3 uid="uid://bihon3xtx45y7"]
[ext_resource type="Script" path="res://components/bios_check/bios_check.gd" id="1_qrkee"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_8e2dh"]
bg_color = Color(0.133, 0.133, 0.133, 1)
border_width_left = 25
border_width_top = 25
border_width_right = 25
border_width_bottom = 25
border_color = Color(0.505882, 0.505882, 0.505882, 0.647059)
border_blend = true
[node name="PopupContent" type="Control"]
top_level = true
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
offset_right = -355.0
offset_right = -1.0
offset_bottom = -71.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_qrkee")
[node name="Table" type="Tree" parent="."]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
unique_name_in_owner = true
clip_contents = false
layout_mode = 2
offset_right = 1277.0
offset_bottom = 723.0
grow_horizontal = 2
grow_vertical = 2
size_flags_horizontal = 3
size_flags_vertical = 3
theme_override_font_sizes/font_size = 16
theme_override_font_sizes/title_button_font_size = 18
theme_override_styles/panel = SubResource("StyleBoxFlat_8e2dh")
columns = 5
column_titles_visible = true
allow_reselect = true

View file

@ -1,21 +0,0 @@
[gd_scene format=3 uid="uid://b0ts52bsu7cpb"]
[node name="PopupContent" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="RichTextLabel" type="RichTextLabel" parent="."]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
focus_mode = 2
scroll_following = true
context_menu_enabled = true
selection_enabled = true

View file

@ -1,21 +1,21 @@
extends Control
var content = null
@onready var custom_theme: Theme = get_tree().current_scene.custom_theme
#@onready var button_off = get_node(current_scene.%l1_button)# .current_scene.l1_button
@onready var lbhide: TextureButton = get_tree().current_scene.get_node("%l1_button")
@onready var rbhide: TextureButton = get_tree().current_scene.get_node("%r1_button")
@onready var lbhide: Panel = get_tree().current_scene.get_node("%l1_box")
@onready var rbhide: Panel = get_tree().current_scene.get_node("%r1_box")
@onready var bios_type:int = get_tree().current_scene.bios_type
@onready var custom_theme: Theme = get_tree().current_scene.custom_theme
func _ready():
$".".theme = custom_theme
lbhide.visible=false
rbhide.visible=false
$".".theme = custom_theme
# TODO this alowes copy and paste from RTB in logs?
if (content != null and bios_type > 0):
$Panel/MarginContainer/VBoxContainer/ContentContainer/MarginContainer.add_child(content)
func _process(delta):
func _process(_delta):
if Input.is_action_pressed("back_button"):
lbhide.visible=true
rbhide.visible=true
@ -27,6 +27,6 @@ func set_content(new_content):
func set_title(new_title):
$Panel/MarginContainer/VBoxContainer/MarginContainer/HBoxContainer/Label.text = new_title
func set_display_text(new_display_text):
$Panel/MarginContainer/VBoxContainer/ContentContainer/MarginContainer/RichTextLabel.text=new_display_text
$Panel/MarginContainer/VBoxContainer/ContentContainer/MarginContainer/LineEdit.text=new_display_text
func _on_back_pressed():
queue_free()

View file

@ -63,10 +63,7 @@ theme_override_constants/margin_top = 6
theme_override_constants/margin_right = 10
theme_override_constants/margin_bottom = 6
[node name="RichTextLabel" type="RichTextLabel" parent="Panel/MarginContainer/VBoxContainer/ContentContainer/MarginContainer"]
[node name="LineEdit" type="TextEdit" parent="Panel/MarginContainer/VBoxContainer/ContentContainer/MarginContainer"]
layout_mode = 2
focus_mode = 2
scroll_following = true
context_menu_enabled = true
editable = false
shortcut_keys_enabled = false
selection_enabled = true

View file

@ -1,8 +1,8 @@
extends Control
@onready var custom_theme: Theme = get_tree().current_scene.custom_theme
var command: String
var parameters: Array
@onready var custom_theme: Theme = get_tree().current_scene.custom_theme
func _ready():
$".".theme = custom_theme

View file

@ -3,7 +3,7 @@
name="Linux/X11 64-bit"
platform="Linux"
runnable=true
advanced_options=false
advanced_options=true
dedicated_server=false
custom_features=""
export_filter="all_resources"
@ -20,7 +20,7 @@ script_export_mode=2
custom_template/debug=""
custom_template/release=""
debug/export_console_wrapper=1
debug/export_console_wrapper=0
binary_format/embed_pck=true
texture_format/s3tc_bptc=true
texture_format/etc2_astc=false

View file

@ -1,14 +0,0 @@
extends RichTextLabel
@onready var helper_text_node = self
func _ready():
# Connect the signal that gets fired on every focus change
get_viewport().connect("gui_focus_changed", _on_focus_changed)
func _on_focus_changed(selected_element:Control) -> void:
if selected_element != null and selected_element.has_meta("description"):
helper_text_node.text = selected_element.get_meta("description")
else:
helper_text_node.text = "Hey, there's no description"
#helper_text_node.text = "That stupid Monkey almost deleted me.\n\n\nPlease save me!!!!!!!!"

View file

@ -1,81 +0,0 @@
keys,en,it,de,sv,ua,ja,zh
TK_SYSTEM,"System","Sistema","System","System","Cистема","システム","系统"
TK_GAME_SETTINGS,"Game Settings","Impostazioni di Gioco","Spieleinstellungen","Spelinställningar","Ігрові Налаштування","ゲーム設定","游戏设定"
TK_QRESUME,"Quick Resume","Quick Resume","Schnellfortsetzung","Snabb Återupptagning","Швидкий Запуск","クイックリジューム","快速恢复"
TK_ADVANCED,"Advanced","Avanzate","Erweitert","Avancerat","Розширені","アドバンスド","高级/进阶"
TK_REWIND,"Rewind","Riavvolgimento","Zurückspulen","Tillbakaspolning","Перемотка","巻き戻し","倒带"
TK_CONFIRMEXIT,"Quit Confirmation","Conferma per Uscire","Beenden Bestätigen","Avlutningsbekräftelse","Підтвердження Виходу","確認終了","退出确认"
TK_CHEATS,"Cheats","Trucchi","Cheats","Fusk","Чіти","チート","作弊"
TK_SOON,"(coming soon)","(in arrivo)","(bald verfügbar)","(kommer snart)","(незабаром)","(近日公開)","(即将到来)"
TK_GRAPHICS,"Graphics","Grafica","Grafik","Grafik","Графіка","グラフィック","画质"
TK_CONTROLS,"Controls","Controlli","Steuerung","Kontroller","Управління","コントロール","控制"
TK_TOOLS,"Tools","Strumenti","Werkzeuge","Verktyg","Інструменти","ツール","工具"
TK_NETWORK,"Network","Rete","Netzwerk","Nätverk","Мережа","ネットワーク","kai qi"
TK_TROUBLESHOOT,"Troubleshoot","Risoluzione Problemi","Fehlerbehebung","Felsökning","Несправності","トラブルシューティング","排错"
TK_TROUBLESHOOTLBL,"Troubleshoot","Risoluzione Problemi","Fehlerbehebung","Felsökning","Усунення Несправностей","トラブルシューティング","排错"
TK_CONFIGURATOR,"Configurator","Configurator","Configurator","Configurator","Конфігуратор","確認","设置"
TK_ABOUT,"About","Informazioni","Über","Om","Про Нас","アバウト","关于"
TK_DECORATIONS,"Decorations","Decorazioni","Dekorationen","Dekorationer","Декорації","装飾","装饰"
TK_BORDERS,"Borders","Bordi","Ränder","Ramar","Фони","ボーダー","边框"
TK_WSCREEN,"Widescreen","Widescreen","Breitbild","Bredbild","Широкий Екран","ワイドスクリーン","宽屏"
TK_SHADERS,"Shaders","Shader","Shaders","Shaders","Шейдери","シェーダ","着色器"
TK_EXTRA,"Extra","Extra","Extra","Extra","Додатково","エクストラ","额外"
TK_MODS,"Mods","Mod","Mods","Moddar","Модифікації","改造","游戏模组"
TK_TATE,"TATE Mode","TATE Mode","TATE-Mode","TATE Läge","Режим TATE","垂直スクリーンモード","垂屏模式"
TK_STEAMCONTEMP,"Steam: Controller Templates","Template dei Controller di Steam","Steam: Controller-Vorlagen","Steam: Kontroller Mallar","Steam: Шаблони Контролерів","Steamコントローラーテンプレート","Steam控制器模板"
TK_INSTALL,"Install","Installa","Installieren","Installera","Встановити","インストール","安装"
TK_BTNLAYOUT,"Button Layout","Layout Pulsanti","Tastenbelegung","Knapp Layout","Розташування Кнопок","ボタンのレイアウト","按键布局"
TK_BTNCLASSIC,"Classic","Classico","Klassik","Klassisk","Класичний","クラッシク","经典"
TK_BTNNINTENDO,"Nintendo","Nintendo","Nintendo","Nintendo","Nintendo","ニンテンドー","任天堂"
TK_HOTKEYSOUND,"Hotkey Activation Sound","Suono su Attivazione Hotkey","Hotkey Aktivierungssound","Hotkey Aktiveringsljud","Звук Гарячих Клавіш","ホットキー起動音","热键激活音效"
TK_SCAN,"Scan","Scansiona","Scan","Skanna","Сканувати","スキャン","扫描"
TK_PS3SCAN,"PlayStation 3 Games","Giochi PlayStation 3","PlayStation 3 Spiele","PlayStation 3 Spel","Ігри для PlayStation 3","プレステ3ゲーム","PlayStation3游戏"
TK_SCUMMVMSCAN,"ScummVM Games","Giochi ScummVM","ScummVM Spiele","ScummVM Spel","Ігри ScummVM","ScummVMゲーム","ScummVM游戏"
TK_MULTIFILE,"Multi-File Structure","Struttura Multi-File","Mehrfachdateistruktur","Flerfilsstruktur","Багатофайлова Структура","マルチファイル構造","多文件结构"
TK_3DSDECRYPT,"3DS Game Decrypter","Decrittatore Giochi 3DS","3DS Spielentcrypter","3DS Spelavkrypterare","Дешифратор Ігор 3DS","3DS ゲームデクリプタ","3DS游戏解密"
TK_BIOS,"BIOS","BIOS","BIOS","BIOS","BIOS","BIOS","BIOS"
TK_GENTOOLS,"General Tools","Strumenti Generali","Allgemeine Werkzeuge","Allmänt","Загальні Інструменти","一般的なツール","一般工具"
TK_EMUOPEN,"Open Emulator...","Apri Emulatore...","Öffne Emulator...","Öppna Emulator...","Відкрити Емулятор...","エミュレータを開く...","打开模拟器..."
TK_GRIDINSTALL,"Install RetroDECK Steam Grids","Installa le Steam Grids di RetroDECK","RetroDECK Steam Grids Installieren","Installera RetroDECK Steam Grids","Встановити RetroDECK Steam Grids","RetroDECK Steam Gridsをインストール","安装RetroDECK Steam Grids"
TK_PS3FWINSTALL,"Install PS3 Firmware","Installa il Firmware PS3","Installiere PS3 Firmware","Installera PS3 Firmware","Встановити Прошивку PS3","PS3ファームウェアをインストール","安装PS3固件"
TK_FAVSTEAM,"Show Favorites as Steam Games","Mostra Giochi Preferiti su Steam","Favoriten als Steam-Spiele anzeigen","Visa Favoriter som Spel i Steam","Показати Улюблені як Ігри в Steam","お気に入りを Steam ゲームとして表示","显示收藏夹为Steam游戏"
TK_FILETOOLS,"File Maniuplation","Manipolazione File","Datei Werkzeuge","Filhantering","Маніпуляції з Файлами","ファイル操作","文件操作"
TK_USBTOOL,"USB Transfer Tool","Strumento di Trasferimento USB","USB Transfer Tool","USB Överföringsverktyg","Інструмент для Передачі Даних USB","USB転送ツール","USB传输工具"
TK_BACKUPBTN,"Backup User Data","Backup Dati Utente","Benutzerdaten Sichern","Backup av Användardata","Резервне Копіювання Даних Користувача","ユーザデータバックアップ","备份用户数据"
TK_COMPRESSGAMES,"Compress Games","Comprimi Giochi","Spiele Komprimieren","Komprimera Spel","Стиснути Ігри","ゲームを圧縮","压缩游戏"
TK_MOVEFILES,"Move User Files","Sposta File Utente","Benutzerdateien Verschieben","Flytta Användarfiler","Перемістити Файли Користувача","ユーザーファイルを移動","移动用户文件"
TK_CHEEVOS,"Retro Achievements","Retro Achievements","Retro Achievements","Retro Achievements","Retro Achievements","レトロ実績","Retro成就"
TK_CHEEVOSUNAME,"Username:","Nome Utente:","Benutzername:","Användarnamn:","Ім'я користувача:","ユーザー名:","用户名:"
TK_CHEEVOSPWD,"Password:","Password:","Passwort:","Lösenord:","Пароль:","パスワード:","密码:"
TK_CHEEVOSHARDCORE,"Hardcore Mode","Modalità Hardcore","Hardcore Modus","Hardcore Läge","Хардкорний Режим","ハードコアモード","硬核模式"
TK_CHEEVOSTROPHYBTN,"Show Throphies","Mostra Trofei","Trophäen Anzeigen","Visa Troféer","Показати Трофеї","トロフィーを表示","显示奖杯"
TK_LOGIN,"Login","Login","Login","Logga In","Увійти","ログイン","登录"
TK_NETPLAY,"Netplay","Netplay","Netplay","Netplay","Netplay","ネットプレイ","网战"
TK_NETPLAYID,"Netplay ID:","ID Netplay:","Netplay ID:","Netplay ID:","Netplay ID:","ネットプレイID","网战ID"
TK_NETPLAYADDRESS,"Address:","Indirizzo:","Adresse:","Address:","Адреса:","アドレス:","地址:"
TK_NETPLAYCONNECT,"Connect","Connetti","Verbinden","Anslut","Підключитися","接続","连接"
TK_DATAMNG,"Data Management","Gestione Dati","Datenverwaltung","Datahantering","Управління Даними","データ管理","数据管理"
TK_SAVESSYNC,"Synchronize Saves","Sincronizzazione Salvataggi","Spielstände Synchronisieren","Synkronisera Sparfiler","Синхронізувати Збереження","保存データを同期","同步存档"
TK_FTPBTN,"Start sFTP Server","Avvia Server sFTP","Starte sFTP Server","Starta sFTP Server","Запустити Сервер sFTP","sFTPサーバーを起動","开启sFTP服务器"
TK_CHECKCONN,"Check Connection","Controllo Connessione","Verbindung Überprüfen","Kontrollera Anslutning","Перевірити Підключення","接続を確認","检查连接"
TK_LOGSBTN,"Show Logs","Mostra Log","Logs Anzeigen","Visa Loggar","Показати Логи","ログを表示","显示日志"
TK_RESET,"Reset","Reset","Reset","Återställ","Скинути","リセット","重置"
TK_RESETSINGLE,"Single Emulator...","Emulatore Singolo...","Einzelner Emulator...","En Emulator...","Один Емулятор...","単一エミュレータ...","单独模拟器..."
TK_RESETALL,"All Emulators","Tutti gli Emulatori","Alle Emulatoren","Alla Emulatorer","Всі Емулятори","全エミュレータ","所有模拟器"
TK_RESETFULL,"Full RetroDECK Reset","Reset RetroDECK Completo","Vollständiges Zurücksetzen von RetroDECK","Återställ Hela RetroDECK","Повне Скидання RetroDECK","RetroDECKを完全リセット","完全重置RetroDECK"
TK_UPDATENOTIF,"Update Notification","Notifica gli Aggiornamenti","Update-Benachrichtigung","Uppdaterings-notifikation","Сповіщення про Оновлення","アップデート通知","更新通知"
TK_EASTEREGGS,"Show Easter Eggs","Mostra Easter Eggs","Easter Eggs anzeigen","Visa Easter Eggs","Показувати Пасхальні Яйця","イースターエッグを表示","显示彩蛋"
TK_MULTIUSR,"Multi-User Mode","Modalità Multi-Utente","Multi-User Mode","Flerspelarläge","Багатокористувацький Режим","マルチユーザーモード","多用户模式"
TK_OFF,"Off","Off","Aus","Av","Вимк","オフ","关闭"
TK_STEAMUSR,"Steam Users","Utenti Steam","Steam Benutzer","Steam Användare","Користувачі Steam","Steamユーザー","Steam用户"
TK_CUSTOMUSR,"Custom Users","Utenti Personalizzati","Benutzerdefinierte Benutzer","Anpassade Användare","Кастомні Користувачі","カスタムユーザー","自定义用户"
TK_MUSIC,"Menu Music","Musica del Menu","Menu Hintergrundmusik","Meny Musik","Музика Меню","メニュー音楽","菜单音乐"
TK_ABOUTHEADER,"About RetroDECK","A Proposito di RetroDECK","Über RetroDECK","Om RetroDECK","Про RetroDECK","RetroDECKについて","关于RetroDECK"
TK_WEBSITE,"Website","Sito Web","Website","Hemsida","Веб-сайт","公式サイト","网站"
TK_CHANGELOG,"Version History","Storico Versioni","Versions History","Versionshistorik","Історія Версій","バージョン履歴","版本历史"
TK_WIKI,"Wiki","Wiki","Wiki","Wiki","Wiki","Wiki","维基"
TK_CREDITS,"Credits","Crediti","Credits","Tillskrivningar","Автори","クレジット","鸣谢"
TK_DONATE,"Donate","Donazione","Spenden","Donera","Пожертвувати","寄付","捐赠"
TK_CONTACTUS,"Reach Us","Contattaci","Kontakiere Uns","Kontakta Oss","Зв'язатися з Нами","連絡","联系我们"
TK_LICENSES,"Licenses","Licenze","Lizenzen","Licenser","Ліцензії","ライセンス","许可"
TK_ON,"On","On","An","På","Увімк","オン","开启"
1 keys en it de sv ua ja zh
2 TK_SYSTEM System Sistema System System Cистема システム 系统
3 TK_GAME_SETTINGS Game Settings Impostazioni di Gioco Spieleinstellungen Spelinställningar Ігрові Налаштування ゲーム設定 游戏设定
4 TK_QRESUME Quick Resume Quick Resume Schnellfortsetzung Snabb Återupptagning Швидкий Запуск クイックリジューム 快速恢复
5 TK_ADVANCED Advanced Avanzate Erweitert Avancerat Розширені アドバンスド 高级/进阶
6 TK_REWIND Rewind Riavvolgimento Zurückspulen Tillbakaspolning Перемотка 巻き戻し 倒带
7 TK_CONFIRMEXIT Quit Confirmation Conferma per Uscire Beenden Bestätigen Avlutningsbekräftelse Підтвердження Виходу 確認終了 退出确认
8 TK_CHEATS Cheats Trucchi Cheats Fusk Чіти チート 作弊
9 TK_SOON (coming soon) (in arrivo) (bald verfügbar) (kommer snart) (незабаром) (近日公開) (即将到来)
10 TK_GRAPHICS Graphics Grafica Grafik Grafik Графіка グラフィック 画质
11 TK_CONTROLS Controls Controlli Steuerung Kontroller Управління コントロール 控制
12 TK_TOOLS Tools Strumenti Werkzeuge Verktyg Інструменти ツール 工具
13 TK_NETWORK Network Rete Netzwerk Nätverk Мережа ネットワーク kai qi
14 TK_TROUBLESHOOT Troubleshoot Risoluzione Problemi Fehlerbehebung Felsökning Несправності トラブルシューティング 排错
15 TK_TROUBLESHOOTLBL Troubleshoot Risoluzione Problemi Fehlerbehebung Felsökning Усунення Несправностей トラブルシューティング 排错
16 TK_CONFIGURATOR Configurator Configurator Configurator Configurator Конфігуратор 確認 设置
17 TK_ABOUT About Informazioni Über Om Про Нас アバウト 关于
18 TK_DECORATIONS Decorations Decorazioni Dekorationen Dekorationer Декорації 装飾 装饰
19 TK_BORDERS Borders Bordi Ränder Ramar Фони ボーダー 边框
20 TK_WSCREEN Widescreen Widescreen Breitbild Bredbild Широкий Екран ワイドスクリーン 宽屏
21 TK_SHADERS Shaders Shader Shaders Shaders Шейдери シェーダ 着色器
22 TK_EXTRA Extra Extra Extra Extra Додатково エクストラ 额外
23 TK_MODS Mods Mod Mods Moddar Модифікації 改造 游戏模组
24 TK_TATE TATE Mode TATE Mode TATE-Mode TATE Läge Режим TATE 垂直スクリーンモード 垂屏模式
25 TK_STEAMCONTEMP Steam: Controller Templates Template dei Controller di Steam Steam: Controller-Vorlagen Steam: Kontroller Mallar Steam: Шаблони Контролерів Steam:コントローラーテンプレート Steam:控制器模板
26 TK_INSTALL Install Installa Installieren Installera Встановити インストール 安装
27 TK_BTNLAYOUT Button Layout Layout Pulsanti Tastenbelegung Knapp Layout Розташування Кнопок ボタンのレイアウト 按键布局
28 TK_BTNCLASSIC Classic Classico Klassik Klassisk Класичний クラッシク 经典
29 TK_BTNNINTENDO Nintendo Nintendo Nintendo Nintendo Nintendo ニンテンドー 任天堂
30 TK_HOTKEYSOUND Hotkey Activation Sound Suono su Attivazione Hotkey Hotkey Aktivierungssound Hotkey Aktiveringsljud Звук Гарячих Клавіш ホットキー起動音 热键激活音效
31 TK_SCAN Scan Scansiona Scan Skanna Сканувати スキャン 扫描
32 TK_PS3SCAN PlayStation 3 Games Giochi PlayStation 3 PlayStation 3 Spiele PlayStation 3 Spel Ігри для PlayStation 3 プレステ3ゲーム PlayStation3游戏
33 TK_SCUMMVMSCAN ScummVM Games Giochi ScummVM ScummVM Spiele ScummVM Spel Ігри ScummVM ScummVMゲーム ScummVM游戏
34 TK_MULTIFILE Multi-File Structure Struttura Multi-File Mehrfachdateistruktur Flerfilsstruktur Багатофайлова Структура マルチファイル構造 多文件结构
35 TK_3DSDECRYPT 3DS Game Decrypter Decrittatore Giochi 3DS 3DS Spielentcrypter 3DS Spelavkrypterare Дешифратор Ігор 3DS 3DS ゲームデクリプタ 3DS游戏解密
36 TK_BIOS BIOS BIOS BIOS BIOS BIOS BIOS BIOS
37 TK_GENTOOLS General Tools Strumenti Generali Allgemeine Werkzeuge Allmänt Загальні Інструменти 一般的なツール 一般工具
38 TK_EMUOPEN Open Emulator... Apri Emulatore... Öffne Emulator... Öppna Emulator... Відкрити Емулятор... エミュレータを開く... 打开模拟器...
39 TK_GRIDINSTALL Install RetroDECK Steam Grids Installa le Steam Grids di RetroDECK RetroDECK Steam Grids Installieren Installera RetroDECK Steam Grids Встановити RetroDECK Steam Grids RetroDECK Steam Gridsをインストール 安装RetroDECK Steam Grids
40 TK_PS3FWINSTALL Install PS3 Firmware Installa il Firmware PS3 Installiere PS3 Firmware Installera PS3 Firmware Встановити Прошивку PS3 PS3ファームウェアをインストール 安装PS3固件
41 TK_FAVSTEAM Show Favorites as Steam Games Mostra Giochi Preferiti su Steam Favoriten als Steam-Spiele anzeigen Visa Favoriter som Spel i Steam Показати Улюблені як Ігри в Steam お気に入りを Steam ゲームとして表示 显示收藏夹为Steam游戏
42 TK_FILETOOLS File Maniuplation Manipolazione File Datei Werkzeuge Filhantering Маніпуляції з Файлами ファイル操作 文件操作
43 TK_USBTOOL USB Transfer Tool Strumento di Trasferimento USB USB Transfer Tool USB Överföringsverktyg Інструмент для Передачі Даних USB USB転送ツール USB传输工具
44 TK_BACKUPBTN Backup User Data Backup Dati Utente Benutzerdaten Sichern Backup av Användardata Резервне Копіювання Даних Користувача ユーザデータバックアップ 备份用户数据
45 TK_COMPRESSGAMES Compress Games Comprimi Giochi Spiele Komprimieren Komprimera Spel Стиснути Ігри ゲームを圧縮 压缩游戏
46 TK_MOVEFILES Move User Files Sposta File Utente Benutzerdateien Verschieben Flytta Användarfiler Перемістити Файли Користувача ユーザーファイルを移動 移动用户文件
47 TK_CHEEVOS Retro Achievements Retro Achievements Retro Achievements Retro Achievements Retro Achievements レトロ実績 Retro成就
48 TK_CHEEVOSUNAME Username: Nome Utente: Benutzername: Användarnamn: Ім'я користувача: ユーザー名: 用户名:
49 TK_CHEEVOSPWD Password: Password: Passwort: Lösenord: Пароль: パスワード: 密码:
50 TK_CHEEVOSHARDCORE Hardcore Mode Modalità Hardcore Hardcore Modus Hardcore Läge Хардкорний Режим ハードコアモード 硬核模式
51 TK_CHEEVOSTROPHYBTN Show Throphies Mostra Trofei Trophäen Anzeigen Visa Troféer Показати Трофеї トロフィーを表示 显示奖杯
52 TK_LOGIN Login Login Login Logga In Увійти ログイン 登录
53 TK_NETPLAY Netplay Netplay Netplay Netplay Netplay ネットプレイ 网战
54 TK_NETPLAYID Netplay ID: ID Netplay: Netplay ID: Netplay ID: Netplay ID: ネットプレイID: 网战ID:
55 TK_NETPLAYADDRESS Address: Indirizzo: Adresse: Address: Адреса: アドレス: 地址:
56 TK_NETPLAYCONNECT Connect Connetti Verbinden Anslut Підключитися 接続 连接
57 TK_DATAMNG Data Management Gestione Dati Datenverwaltung Datahantering Управління Даними データ管理 数据管理
58 TK_SAVESSYNC Synchronize Saves Sincronizzazione Salvataggi Spielstände Synchronisieren Synkronisera Sparfiler Синхронізувати Збереження 保存データを同期 同步存档
59 TK_FTPBTN Start sFTP Server Avvia Server sFTP Starte sFTP Server Starta sFTP Server Запустити Сервер sFTP sFTPサーバーを起動 开启sFTP服务器
60 TK_CHECKCONN Check Connection Controllo Connessione Verbindung Überprüfen Kontrollera Anslutning Перевірити Підключення 接続を確認 检查连接
61 TK_LOGSBTN Show Logs Mostra Log Logs Anzeigen Visa Loggar Показати Логи ログを表示 显示日志
62 TK_RESET Reset Reset Reset Återställ Скинути リセット 重置
63 TK_RESETSINGLE Single Emulator... Emulatore Singolo... Einzelner Emulator... En Emulator... Один Емулятор... 単一エミュレータ... 单独模拟器...
64 TK_RESETALL All Emulators Tutti gli Emulatori Alle Emulatoren Alla Emulatorer Всі Емулятори 全エミュレータ 所有模拟器
65 TK_RESETFULL Full RetroDECK Reset Reset RetroDECK Completo Vollständiges Zurücksetzen von RetroDECK Återställ Hela RetroDECK Повне Скидання RetroDECK RetroDECKを完全リセット 完全重置RetroDECK
66 TK_UPDATENOTIF Update Notification Notifica gli Aggiornamenti Update-Benachrichtigung Uppdaterings-notifikation Сповіщення про Оновлення アップデート通知 更新通知
67 TK_EASTEREGGS Show Easter Eggs Mostra Easter Eggs Easter Eggs anzeigen Visa Easter Eggs Показувати Пасхальні Яйця イースターエッグを表示 显示彩蛋
68 TK_MULTIUSR Multi-User Mode Modalità Multi-Utente Multi-User Mode Flerspelarläge Багатокористувацький Режим マルチユーザーモード 多用户模式
69 TK_OFF Off Off Aus Av Вимк オフ 关闭
70 TK_STEAMUSR Steam Users Utenti Steam Steam Benutzer Steam Användare Користувачі Steam Steamユーザー Steam用户
71 TK_CUSTOMUSR Custom Users Utenti Personalizzati Benutzerdefinierte Benutzer Anpassade Användare Кастомні Користувачі カスタムユーザー 自定义用户
72 TK_MUSIC Menu Music Musica del Menu Menu Hintergrundmusik Meny Musik Музика Меню メニュー音楽 菜单音乐
73 TK_ABOUTHEADER About RetroDECK A Proposito di RetroDECK Über RetroDECK Om RetroDECK Про RetroDECK RetroDECKについて 关于RetroDECK
74 TK_WEBSITE Website Sito Web Website Hemsida Веб-сайт 公式サイト 网站
75 TK_CHANGELOG Version History Storico Versioni Versions History Versionshistorik Історія Версій バージョン履歴 版本历史
76 TK_WIKI Wiki Wiki Wiki Wiki Wiki Wiki 维基
77 TK_CREDITS Credits Crediti Credits Tillskrivningar Автори クレジット 鸣谢
78 TK_DONATE Donate Donazione Spenden Donera Пожертвувати 寄付 捐赠
79 TK_CONTACTUS Reach Us Contattaci Kontakiere Uns Kontakta Oss Зв'язатися з Нами 連絡 联系我们
80 TK_LICENSES Licenses Licenze Lizenzen Licenser Ліцензії ライセンス 许可
81 TK_ON On On An Увімк オン 开启

View file

@ -1,17 +0,0 @@
[remap]
importer="csv_translation"
type="Translation"
uid="uid://cwb782o5jh5lx"
[deps]
files=["res://locales/interface.en.translation", "res://locales/interface.it.translation", "res://locales/interface.de.translation", "res://locales/interface.sv.translation", "res://locales/interface.ua.translation", "res://locales/interface.ja.translation", "res://locales/interface.zh.translation"]
source_file="res://locales/interface.csv"
dest_files=["res://locales/interface.en.translation", "res://locales/interface.it.translation", "res://locales/interface.de.translation", "res://locales/interface.sv.translation", "res://locales/interface.ua.translation", "res://locales/interface.ja.translation", "res://locales/interface.zh.translation"]
[params]
compress=true
delimiter=0

View file

@ -1,281 +0,0 @@
#todo
# add cores as class/ Like eumlator but one level lower
extends Control
@onready var bios_type:int
var log_results: Dictionary
var theme_option: OptionButton
#signal signal_theme_changed
var custom_theme: Theme = $".".theme
var log_option: OptionButton
var tab_container: TabContainer
var anim_logo: AnimatedSprite2D
var a_button_texture: Texture2D = load("res://assets/icons/kenney_input-prompts-pixel-16/Tiles/tile_0042.png")
var b_button_texture: Texture2D = load("res://assets/icons/kenney_input-prompts-pixel-16/Tiles/tile_0043.png")
var app_data := AppData.new()
func _ready():
_get_nodes()
_connect_signals()
_play_main_animations()
#%locale_option.selected = class_functions.map_locale_id(OS.get_locale_language())
#class_functions.logger()
%rd_title.text += class_functions.read_cfg()
class_functions.log_parameters[2] = class_functions.log_text + "started configurator"
class_functions.execute_command(class_functions.wrapper_command,class_functions.log_parameters, false)
print (class_functions.rd_log)
#var log_file = class_functions.import_text_file(rd_logs +"/retrodeck.log")
#for id in config.paths:
# var path_data = config.paths[id]
# print (id)
# set current startup tab to match IDE
tab_container.current_tab = 0
#add_child(class_functions) # Needed for threaded results Not need autoload?
var children = findElements(self, "Control")
for n: Control in children: #iterate the children
if (n.focus_mode == FOCUS_ALL):
n.mouse_entered.connect(_on_control_mouse_entered.bind(n)) #grab focus on mouse hover
if (n.is_class("BaseButton") and n.disabled == true): #if button-like control and disabled
n.self_modulate.a = 0.5 #make it half transparent
combine_tkeys()
func _input(event):
if Input.is_action_pressed("quit1") and Input.is_action_pressed("quit2"):
_exit()
if Input.is_action_pressed("back_button"):
%b_button.texture_normal = %b_button.texture_pressed
elif Input.is_action_pressed("action_button"):
%a_button.texture_normal = %a_button.texture_pressed
else:
%a_button.texture_normal = a_button_texture
%b_button.texture_normal = b_button_texture
if event.is_action_pressed("quit"):
_exit()
func _exit():
class_functions.log_parameters[2] = class_functions.log_text + "exited configurator"
class_functions.execute_command(class_functions.wrapper_command,class_functions.log_parameters, false)
get_tree().root.propagate_notification(NOTIFICATION_WM_CLOSE_REQUEST)
get_tree().quit()
func _get_nodes() -> void:
theme_option = get_node("%theme_optionbutton")
tab_container = get_node("%TabContainer")
anim_logo = get_node("%logo_animated")
log_option = get_node("%logs_button")
func _connect_signals() -> void:
#signal_theme_changed.connect(_conf_theme)
theme_option.item_selected.connect(_conf_theme)
#signal_theme_changed.emit(theme_option.item_selected)
log_option.item_selected.connect(_load_log)
%borders_button.pressed.connect(_hide_show_buttons.bind(%borders_button,%borders_gridcontainer,%decorations_gridcontainer))
%button_layout.pressed.connect(_hide_show_buttons.bind(%button_layout,%borders_gridcontainer,%decorations_gridcontainer))
%decorations_save.pressed.connect(_hide_show_buttons.bind(%decorations_save,%decorations_save.get_parent(),null))
%decorations_button.pressed.connect(_hide_show_containers.bind(%decorations_button, %decorations_gridcontainer))
%systems_button.pressed.connect(_hide_show_containers.bind(%systems_button, %systems_gridcontainer))
%save_resume_button.pressed.connect(_hide_show_containers.bind(%decorations_button,%systems_gridcontainer))
func _load_log(index: int) -> void:
var log_content:String
match index:
1:
class_functions.log_parameters[2] = class_functions.log_text + "Loading RetroDeck log"
class_functions.execute_command(class_functions.wrapper_command,class_functions.log_parameters, false)
log_content = class_functions.import_text_file(class_functions.rd_log_folder +"/retrodeck.log")
load_popup("RetroDeck Log", "res://components/logs_view/logs_popup_content.tscn", log_content)
2:
class_functions.log_parameters[2] = class_functions.log_text + "Loading ES-DE log"
class_functions.execute_command(class_functions.wrapper_command,class_functions.log_parameters, false)
log_content = class_functions.import_text_file(class_functions.rd_log_folder +"/ES-DE/es_log.txt")
load_popup("ES-DE Log", "res://components/logs_view/logs_popup_content.tscn",log_content)
3:
class_functions.log_parameters[2] = class_functions.log_text + "Loading RetroArch log"
class_functions.execute_command(class_functions.wrapper_command,class_functions.log_parameters, false)
log_content = class_functions.import_text_file(class_functions.rd_log_folder +"/retroarch/logs/log.txt")
load_popup("Retroarch Log", "res://components/logs_view/logs_popup_content.tscn",log_content)
func _play_main_animations() -> void:
anim_logo.play()
func _hide_show_containers(button: Button, grid_container: GridContainer) -> void:
match button.name:
"decorations_button", "systems_button":
grid_container.visible = true
if button.toggle_mode:
button.toggle_mode=false
grid_container.visible = false
else:
button.toggle_mode=true
# TODO Pass GridContainer(might need 2?) as above
# TODO load existing settings or default to enable all
func _hide_show_buttons(button: Button, buttons_gridcontainer: GridContainer, hidden_gridcontainer: GridContainer) -> void:
match button.name:
"borders_button", "button_layout":
buttons_gridcontainer.visible = true
if button.toggle_mode == false:
for i in range(buttons_gridcontainer.get_child_count()):
var child = buttons_gridcontainer.get_child(i)
child.button_pressed=true
for i in range(hidden_gridcontainer.get_child_count()):
var child = hidden_gridcontainer.get_child(i)
if child is Button and child != button:
child.visible=false
elif button.toggle_mode == true and %borders_gridcontainer.visible == true:
print (button.name, "SAVE NOW? TODO") # TODO SHOW ALL AGAIN?
buttons_gridcontainer.visible = false
#button.toggle_mode = false
for i in range(hidden_gridcontainer.get_child_count()):
var child = hidden_gridcontainer.get_child(i)
if child is Button:
child.visible=true
child.toggle_mode = false
button.toggle_mode = true
func _conf_theme(index: int) -> void:
match index:
1:
class_functions.log_parameters[2] = class_functions.log_text + "Set theme to index " + str(index)
class_functions.execute_command(class_functions.wrapper_command,class_functions.log_parameters, false)
custom_theme = preload("res://res/pixel_ui_theme/RetroDECKTheme.tres")
2:
class_functions.log_parameters[2] = class_functions.log_text + "Set theme to index " + str(index)
class_functions.execute_command(class_functions.wrapper_command,class_functions.log_parameters, false)
custom_theme = preload("res://assets/themes/retro_theme.tres")
3:
class_functions.log_parameters[2] = class_functions.log_text + "Set theme to index " + str(index)
class_functions.execute_command(class_functions.wrapper_command,class_functions.log_parameters, false)
custom_theme = preload("res://assets/themes/modern_theme.tres")
4:
class_functions.log_parameters[2] = class_functions.log_text + "Set theme to index " + str(index)
class_functions.execute_command(class_functions.wrapper_command,class_functions.log_parameters, false)
custom_theme = preload("res://assets/themes/accesible_theme.tres")
$".".theme = custom_theme
_play_main_animations()
func findElements(node: Node, className: String, result: Array = []) -> Array:
if node.is_class(className):
result.push_back(node)
for child in node.get_children():
result = findElements(child, className, result)
return result
func _on_control_mouse_entered(control: Node):
control.grab_focus()
func load_popup(title:String, content_path:String, display_text: String):
var popup = load("res://components/popup.tscn").instantiate() as Control
popup.set_title(title)
popup.set_content(content_path)
popup.set_display_text(display_text)
$Background.add_child(popup)
func _on_quickresume_advanced_pressed():
load_popup("Quick Resume Advanced", "res://components/popups_content/popup_content_test.tscn","")
func _on_bios_button_pressed():
_play_main_animations()
bios_type = 1
class_functions.log_parameters[2] = class_functions.log_text + "Bios_Check"
log_results = class_functions.execute_command(class_functions.wrapper_command, class_functions.log_parameters, false)
load_popup("BIOS File Check", "res://components/bios_check/bios_popup_content.tscn","")
bios_type = 0
func _on_bios_button_expert_pressed():
_play_main_animations()
bios_type = 2
class_functions.log_parameters[2] = class_functions.log_text + "Advanced_Bios_Check"
log_results = class_functions.execute_command(class_functions.wrapper_command, class_functions.log_parameters, false)
class_functions.log_parameters[2] = class_functions.log_text + "Exit code: " + str(log_results["exit_code"])
load_popup("BIOS File Check", "res://components/bios_check/bios_popup_content.tscn","")
bios_type = 0
func _on_exit_button_pressed():
_play_main_animations()
_exit()
func _on_locale_selected(index):
match index:
0:
TranslationServer.set_locale("en")
_:
TranslationServer.set_locale("en")
combine_tkeys()
"""
1:
TranslationServer.set_locale("it")
2:
TranslationServer.set_locale("de")
3:
TranslationServer.set_locale("sv")
4:
TranslationServer.set_locale("ua")
5:
TranslationServer.set_locale("ja")
6:
TranslationServer.set_locale("zh")
"""
func combine_tkeys(): #More as a test
pass
#%cheats.text = tr("TK_CHEATS") + " " + tr("TK_SOON") # switched to access as a unique name as easier to refactor
#$Background/MarginContainer/TabContainer/TK_SYSTEM/ScrollContainer/VBoxContainer/HBoxContainer/GridContainer/cheats.text = tr("TK_CHEATS") + " " + tr("TK_SOON")
#%tate_mode.text = tr("TK_TATE") + " " + tr("TK_SOON")
#%hotkey_sound.text = tr("TK_HOTKEYSOUND") + " " + tr("TK_SOON")
#$Background/MarginContainer/TabContainer/TK_NETWORK/ScrollContainer/VBoxContainer/cheevos_container/cheevos_advanced_container/cheevos_hardcore.text = tr("TK_CHEEVOSHARDCORE") + " " + tr("TK_SOON")
#$Background/MarginContainer/TabContainer/TK_NETWORK/ScrollContainer/VBoxContainer/data_mng_container/saves_sync.text = tr("TK_SAVESSYNC") + " " + tr("TK_SOON")
#$Background/MarginContainer/TabContainer/TK_CONFIGURATOR/ScrollContainer/VBoxContainer/system_container/easter_eggs.text = tr("TK_EASTEREGGS") + " " + tr("TK_SOON")
func display_json_data() -> void:
app_data = data_handler.app_data
#data_handler.add_emulator()
#data_handler.modify_emulator_test()
if app_data:
var website_data: Link = app_data.about_links["rd_web"]
print (website_data.name,"-",website_data.url,"-",website_data.description,"-",website_data.url)
#print (app_data.about_links["rd_web"]["name"])
var core_data: Core = app_data.cores["gambatte_libetro"]
print (core_data.name)
for property: CoreProperty in core_data.properties:
print("Cheevos: ", property.cheevos)
print("Cheevos Hardcore: ", property.cheevos_hardcore)
print("Quick Resume: ", property.quick_resume)
print("Rewind: ", property.rewind)
print("Borders: ", property.borders)
print("Widescreen: ", property.widescreen)
print("ABXY_button:", property.abxy_button)
for key in app_data.emulators.keys():
var emulator = app_data.emulators[key]
# Display the properties of each emulator
print("System Name: ", emulator.name)
print("Description: ", emulator.description)
#print("System: ", emulator.systen)
print("Help URL: ", emulator.url)
print("Properties:")
for property: EmulatorProperty in emulator.properties:
print("Cheevos: ", property.cheevos)
print("Borders: ", property.borders)
print("ABXY_button:", property.abxy_button)
print("multi_user_config_dir: ", property.multi_user_config_dir)
for key in app_data.cores.keys():
var core = app_data.cores[key]
print("Core Name: ", core.name)
print("Description: ", core.description)
print("Properties:")
for property: CoreProperty in core.properties:
print("Cheevos: ", property.cheevos)
print("Cheevos Hardcore: ", property.cheevos_hardcore)
print("Quick Resume: ", property.quick_resume)
print("Rewind: ", property.rewind)
print("Borders: ", property.borders)
print("Widescreen: ", property.widescreen)
print("ABXY_button:", property.abxy_button)
else:
print ("No emulators")

File diff suppressed because it is too large Load diff

View file

@ -27,9 +27,7 @@ data_handler="*res://scripts/data_handler.gd"
window/size/viewport_width=1280
window/size/viewport_height=800
window/size/transparent=true
window/stretch/mode="canvas_items"
window/per_pixel_transparency/allowed=true
[filesystem]
@ -66,6 +64,11 @@ rekku_hide={
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":true,"meta_pressed":false,"pressed":false,"keycode":72,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
]
}
info={
"deadzone": 0.5,
"events": [Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":2,"pressure":0.0,"pressed":true,"script":null)
]
}
quit={
"deadzone": 0.5,
"events": [Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":15,"pressure":0.0,"pressed":false,"script":null)
@ -75,15 +78,15 @@ quit={
next_tab={
"deadzone": 0.5,
"events": [Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":10,"pressure":0.0,"pressed":false,"script":null)
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":69,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":5,"pressure":0.0,"pressed":true,"script":null)
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194328,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
]
}
previous_tab={
"deadzone": 0.5,
"events": [Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":9,"pressure":0.0,"pressed":false,"script":null)
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":81,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":4,"pressure":0.0,"pressed":true,"script":null)
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194326,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
]
}
back_button={
@ -100,22 +103,20 @@ action_button={
quit1={
"deadzone": 0.5,
"events": [Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":6,"pressure":0.0,"pressed":true,"script":null)
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194306,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
]
}
quit2={
"deadzone": 0.5,
"events": [Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":7,"pressure":0.0,"pressed":true,"script":null)
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":4,"pressure":0.0,"pressed":true,"script":null)
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194305,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
]
}
[internationalization]
locale/translation_remaps={
"res://res/pixel_ui_theme/8x8_ui_elements.png": PackedStringArray("res://res/pixel_ui_theme/8x8_ui_elements_de.png:de", "res://res/pixel_ui_theme/8x8_ui_elements_sv.png:sv"),
"res://res/pixel_ui_theme/8x8_ui_elements2x.png": PackedStringArray("res://res/pixel_ui_theme/8x8_ui_elements2x_de.png:de", "res://res/pixel_ui_theme/8x8_ui_elements2x_sv.png:sv")
}
locale/translations=PackedStringArray("res://locales/interface.en.translation", "res://locales/interface.it.translation", "res://locales/interface.de.translation", "res://locales/interface.sv.translation", "res://locales/interface.ua.translation", "res://locales/interface.zh.translation", "res://locales/interface.ja.translation")
locale/translation_remaps={}
[rendering]

View file

@ -1,4 +1,4 @@
[gd_resource type="Theme" load_steps=132 format=4 uid="uid://bq8dsxeo34sl"]
[gd_resource type="Theme" load_steps=129 format=4 uid="uid://bq8dsxeo34sl"]
[ext_resource type="Texture2D" uid="uid://dx0u5hiwxfgu5" path="res://res/pixel_ui_theme/8x8_ui_elements.png" id="1_ak8qr"]
[ext_resource type="Texture2D" uid="uid://c4vntk8yri4yw" path="res://res/pixel_ui_theme/8x8_ui_elements2x.png" id="2_jrpaj"]
@ -1087,7 +1087,7 @@ cache/0/16/0/glyphs/95/uv_rect = Rect2(92, 148, 6, 1)
cache/0/16/0/glyphs/95/texture_idx = 0
cache/0/16/0/kerning_overrides/16/0 = Vector2(0, 0)
[sub_resource type="Image" id="Image_62emc"]
[sub_resource type="Image" id="Image_rprbs"]
data = {
"data": PackedByteArray("4ODg4ODg4OD//////////+Dg4ODg4ODg///////////g4ODg4ODg4P//////////4ODg4ODg4OD//////////+Dg4ODg4ODg///////////g4ODg4ODg4P//////////4ODg4ODg4OD//////////+Dg4ODg4ODg/////////////////////+Dg4ODg4ODg///////////g4ODg4ODg4P//////////4ODg4ODg4OD//////////+Dg4ODg4ODg///////////g4ODg4ODg4P//////////4ODg4ODg4OD//////////+Dg4ODg4ODg///////////g4ODg4ODg4A=="),
"format": "Lum8",
@ -1097,9 +1097,9 @@ data = {
}
[sub_resource type="ImageTexture" id="447"]
image = SubResource("Image_62emc")
image = SubResource("Image_rprbs")
[sub_resource type="Image" id="Image_43yh4"]
[sub_resource type="Image" id="Image_cf6bc"]
data = {
"data": PackedByteArray("AAQACgARABkAHwAiACQAJAAkACQAIgAfABkAEQAKAAQACgAVACUANAA/AEYARwBIAEgARwBGAD8ANAAlABUACgARACU/d1rvVv9W/1b/Vv9W/1b/Vv9W/1rvP3cAJQARABkANFnvSP9E/0P/Q/9D/0P/Q/9D/0T/SP9Z7wA0ABkAHwA/VP9D/0P/Q/9D/0P/Q/9D/0P/Q/9D/1T/AD8AHwAiAEZS/0L/Qv9C/0L/Qv9C/0L/Qv9C/0L/Uv8ARgAiACQAR1H/QP9A/0D/QP9A/0D/QP9A/0D/QP9R/wBHACQAJABIT/8//z//P/8//z//P/8//z//P/8//0//AEgAJAAkAEhN/z7/Pv8+/z7/Pv8+/z7/Pv8+/z7/Tf8ASAAkACQAR0z/Pf89/z3/Pf89/z3/Pf89/z3/Pf9M/wBHACQAIgBGSv87/zv/O/87/zv/O/87/zv/O/87/0r/AEYAIgAfAD9J/zr/Ov86/zr/Ov86/zr/Ov86/zr/Sf8APwAfABkANEvvPf85/zn/Of85/zn/Of85/zn/Pf9L7wA0ABkAEQAlNXdK70f/Rv9G/0b/Rv9G/0b/R/9K7TV3ACUAEQAKABUAJQA0AD8ARgBHAEgASABHAEYAPwA0ACUAFQAKAAQACgARABkAHwAiACQAJAAkACQAIgAfABkAEQAKAAQ="),
"format": "LumAlpha8",
@ -1109,7 +1109,7 @@ data = {
}
[sub_resource type="ImageTexture" id="53"]
image = SubResource("Image_43yh4")
image = SubResource("Image_cf6bc")
[sub_resource type="StyleBoxTexture" id="54"]
content_margin_left = 6.0
@ -1123,7 +1123,7 @@ expand_margin_right = 2.0
expand_margin_bottom = 2.0
region_rect = Rect2(0, 0, 16, 16)
[sub_resource type="Image" id="Image_g8qbb"]
[sub_resource type="Image" id="Image_1cy53"]
data = {
"data": PackedByteArray("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEeMvw5HjL85R4y/aEeMv3pHjL97R4y/e0eMv3tHjL97R4y/ekeMv2hHjL85R4y/DgAAAAAAAAAAAAAAAAAAAABHjL86R4y/dEeMvxBHjL8IR4y/CEeMvwhHjL8IR4y/CEeMvwhHjL8QR4y/dEeMvzoAAAAAAAAAAAAAAAAAAAAAR4y/aUeMvw8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEeMvw9HjL9pAAAAAAAAAAAAAAAAAAAAAEeMv3tHjL8GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABHjL8GR4y/ewAAAAAAAAAAAAAAAAAAAABHjL97R4y/CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAR4y/CEeMv3sAAAAAAAAAAAAAAAAAAAAAR4y/e0eMvwgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEeMvwhHjL97AAAAAAAAAAAAAAAAAAAAAEeMv3tHjL8IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABHjL8IR4y/ewAAAAAAAAAAAAAAAAAAAABHjL97R4y/CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAR4y/CEeMv3sAAAAAAAAAAAAAAAAAAAAAR4y/e0eMvwYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEeMvwZHjL97AAAAAAAAAAAAAAAAAAAAAEeMv2lHjL8PAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABHjL8OR4y/aQAAAAAAAAAAAAAAAAAAAABHjL86R4y/dUeMvw9HjL8IR4y/CEeMvwhHjL8IR4y/CEeMvwhHjL8RR4y/dEeMvzoAAAAAAAAAAAAAAAAAAAAAR4y/DkeMvzpHjL9oR4y/ekeMv3tHjL97R4y/e0eMv3tHjL96R4y/aEeMvzlHjL8OAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="),
"format": "RGBA8",
@ -1133,7 +1133,7 @@ data = {
}
[sub_resource type="ImageTexture" id="56"]
image = SubResource("Image_g8qbb")
image = SubResource("Image_1cy53")
[sub_resource type="StyleBoxTexture" id="57"]
content_margin_left = 6.0
@ -1147,7 +1147,7 @@ expand_margin_right = 2.0
expand_margin_bottom = 2.0
region_rect = Rect2(0, 0, 16, 16)
[sub_resource type="Image" id="Image_8hsq5"]
[sub_resource type="Image" id="Image_b3ady"]
data = {
"data": PackedByteArray("AAAABAAAAAoAAAARAAAAGQAAAB8AAAAiAAAAJAAAACQAAAAkAAAAJAAAACIAAAAfAAAAGQAAABEAAAAKAAAABAAAAAoAAAAVAAAAJQAAADQAAAA/AAAARgAAAEcAAABIAAAASAAAAEcAAABGAAAAPwAAADQAAAAlAAAAFQAAAAoAAAARAAAAJUJAS3dfWmzvW1do/1pWZ/9aVmf/WlZn/1pWZ/9aVmf/WlZn/1tXaP9fWmzvQkBLdwAAACUAAAARAAAAGQAAADRfWmvvTUpX/0lGUv9IRVH/SEVR/0hFUf9IRVH/SEVR/0hFUf9JRlL/TUpX/19aa+8AAAA0AAAAGQAAAB8AAAA/W1dm/0lGUv9IRVH/SEVR/0hFUf9IRVH/SEVR/0hFUf9IRVH/SEVR/0lGUv9bV2b/AAAAPwAAAB8AAAAiAAAARllVZP9HRFD/R0RQ/0dEUP9HRFD/R0RQ/0dEUP9HRFD/R0RQ/0dEUP9HRFD/WVVk/wAAAEYAAAAiAAAAJAAAAEdYVGT/RkNQ/0ZDUP9GQ1D/RkNQ/0ZDUP9GQ1D/RkNQ/0ZDUP9GQ1D/RkNQ/1hUZP8AAABHAAAAJAAAACQAAABIVlNj/0VCT/9FQk//RUJP/0VCT/9FQk//RUJP/0VCT/9FQk//RUJP/0VCT/9WU2P/AAAASAAAACQAAAAkAAAASFZTYv9FQk7/RUJO/0VCTv9FQk7/RUJO/0VCTv9FQk7/RUJO/0VCTv9FQk7/VlNi/wAAAEgAAAAkAAAAJAAAAEdVUWL/REFO/0RBTv9EQU7/REFO/0RBTv9EQU7/REFO/0RBTv9EQU7/REFO/1VRYv8AAABHAAAAJAAAACIAAABGVVFg/0RBTf9EQU3/REFN/0RBTf9EQU3/REFN/0RBTf9EQU3/REFN/0RBTf9VUWD/AAAARgAAACIAAAAfAAAAP1VRYP9EQU3/Q0BM/0NATP9DQEz/Q0BM/0NATP9DQEz/Q0BM/0NATP9EQU3/VVFg/wAAAD8AAAAfAAAAGQAAADRWU2TvR0NR/0M/Tf9CP0z/Qj9M/0I/TP9CP0z/Qj9M/0I/TP9DP03/R0NR/1dTZO8AAAA0AAAAGQAAABEAAAAlPjtGd1dTY+9TUF//U09e/1NPXv9TT17/U09e/1NPXv9TT17/U1Bf/1dTY+0+O0Z3AAAAJQAAABEAAAAKAAAAFQAAACUAAAA0AAAAPwAAAEYAAABHAAAASAAAAEgAAABHAAAARgAAAD8AAAA0AAAAJQAAABUAAAAKAAAABAAAAAoAAAARAAAAGQAAAB8AAAAiAAAAJAAAACQAAAAkAAAAJAAAACIAAAAfAAAAGQAAABEAAAAKAAAABA=="),
"format": "RGBA8",
@ -1157,7 +1157,7 @@ data = {
}
[sub_resource type="ImageTexture" id="59"]
image = SubResource("Image_8hsq5")
image = SubResource("Image_b3ady")
[sub_resource type="StyleBoxTexture" id="60"]
content_margin_left = 6.0
@ -1175,7 +1175,7 @@ expand_margin_right = 2.0
expand_margin_bottom = 2.0
region_rect = Rect2(0, 0, 16, 16)
[sub_resource type="Image" id="Image_xq8h4"]
[sub_resource type="Image" id="Image_7hmcg"]
data = {
"data": PackedByteArray("AAAABAAAAAoAAAARAAAAGQAAAB8AAAAiAAAAJAAAACQAAAAkAAAAJAAAACIAAAAfAAAAGQAAABEAAAAKAAAABAAAAAoAAAAVAAAAJQAAADQAAAA/AAAARgAAAEcAAABIAAAASAAAAEcAAABGAAAAPwAAADQAAAAlAAAAFQAAAAoAAAARAAAAJTw6RHdWU2HvUlBd/1FPXf9RT13/UU9d/1FPXf9RT13/UU9d/1JQXf9WU2HvPDpEdwAAACUAAAARAAAAGQAAADRWUmDvRkJO/0I+Sv9BPkn/QT5J/0E+Sf9BPkn/QT5J/0E+Sf9CPkr/RkJO/1ZSYO8AAAA0AAAAGQAAAB8AAAA/UU5b/0E+Sf9APkj/QD5I/0A+SP9APkj/QD5I/0A+SP9APkj/QD5I/0E+Sf9RTlv/AAAAPwAAAB8AAAAiAAAARk9MWf8/PUf/Pz1H/z89R/8/PUf/Pz1H/z89R/8/PUf/Pz1H/z89R/8/PUf/T0xZ/wAAAEYAAAAiAAAAJAAAAEdOSlj/PjtG/z47Rv8+O0b/PjtG/z47Rv8+O0b/PjtG/z47Rv8+O0b/PjtG/05KWP8AAABHAAAAJAAAACQAAABIS0lV/zw6RP88OkT/PDpE/zw6RP88OkT/PDpE/zw6RP88OkT/PDpE/zw6RP9LSVX/AAAASAAAACQAAAAkAAAASEpHVP87OUP/OzlD/zs5Q/87OUP/OzlD/zs5Q/87OUP/OzlD/zs5Q/87OUP/SkdU/wAAAEgAAAAkAAAAJAAAAEdJRlP/OjhC/zo4Qv86OEL/OjhC/zo4Qv86OEL/OjhC/zo4Qv86OEL/OjhC/0lGU/8AAABHAAAAJAAAACIAAABGR0VQ/zk3QP85N0D/OTdA/zk3QP85N0D/OTdA/zk3QP85N0D/OTdA/zk3QP9HRVD/AAAARgAAACIAAAAfAAAAP0dDUP84NT//ODU//zg1P/84NT//ODU//zg1P/84NT//ODU//zg1P/84NT//R0NQ/wAAAD8AAAAfAAAAGQAAADRHRFLvOjhC/zY0Pv82ND7/NjQ+/zY0Pv82ND7/NjQ+/zY0Pv82ND7/OjhC/0dEUu8AAAA0AAAAGQAAABEAAAAlMzE5d0dEUO9EQk3/REFM/0RBTP9EQUz/REFM/0RBTP9EQUz/REJN/0dEUe0zMTl3AAAAJQAAABEAAAAKAAAAFQAAACUAAAA0AAAAPwAAAEYAAABHAAAASAAAAEgAAABHAAAARgAAAD8AAAA0AAAAJQAAABUAAAAKAAAABAAAAAoAAAARAAAAGQAAAB8AAAAiAAAAJAAAACQAAAAkAAAAJAAAACIAAAAfAAAAGQAAABEAAAAKAAAABA=="),
"format": "RGBA8",
@ -1185,7 +1185,7 @@ data = {
}
[sub_resource type="ImageTexture" id="62"]
image = SubResource("Image_xq8h4")
image = SubResource("Image_7hmcg")
[sub_resource type="StyleBoxTexture" id="63"]
content_margin_left = 6.0
@ -1199,7 +1199,7 @@ expand_margin_right = 2.0
expand_margin_bottom = 2.0
region_rect = Rect2(0, 0, 16, 16)
[sub_resource type="Image" id="Image_33w4k"]
[sub_resource type="Image" id="Image_cg8le"]
data = {
"data": PackedByteArray("AAAABAAAAAoAAAARAAAAGQAAAB8AAAAiAAAAJAAAACQAAAAkAAAAJAAAACIAAAAfAAAAGQAAABEAAAAKAAAABAAAAAsAAAAWAAAAJwAAADYAAABBAAAASQAAAEoAAABLAAAASwAAAEoAAABJAAAAQQAAADYAAAAnAAAAFgAAAAsAAAATAAAAKTEvN4BGQ0/xQ0BM/0JAS/9CQEv/QkBL/0JAS/9CQEv/QkBL/0NATP9GQ0/xMS83fwAAACkAAAATAAAAHgAAAD1HRFDyOjhB/wsLDP8LCgz/CwoM/wsKDP8LCgz/CwsM/wsLDP8LCwz/OjhB/0dEUPIAAAA9AAAAHgAAACcAAABNREJO/w8OEf8PDhH/Dw4R/w8OEf8PDhH/Dw4R/w8OEf8PDhH/Dw4R/w8OEf9EQk7/AAAATQAAACcAAAAsAAAAWEZCT/8UExb/ExIW/xMSFv8UExb/ExIW/xQTFv8UExb/FBMW/xQTFv8TEhb/RkJP/wAAAFgAAAAsAAAAMgAAAF1HRVD/GBcb/xgXG/8YFxv/GBcb/xgXG/8YFxv/GBcb/xkYHP8YFxv/GBcb/0dFUP8AAABdAAAAMgAAADMAAABjSUZT/x0cIf8dHCH/HRwh/x0cIf8dHCH/HRwh/x0cIf8dHCH/HRwh/x0cIf9JRlP/AAAAYwAAADMAAAA2AAAAZkpHVP8iISf/IiEn/yIhJ/8iISf/IiEn/yIhJ/8iISf/IiEn/yIhJ/8iISf/SkdU/wAAAGYAAAA2AAAAOQAAAGlLSVX/JyYt/ycmLf8nJi3/JyYt/ycmLf8nJi3/JyYt/ygmLf8nJi3/KCYt/0tJVf8AAABpAAAAOQAAADgAAABsTkpY/y0rM/8tKzP/LSsz/y0rM/8tKzP/LSsz/y0rM/8tKzP/LSsz/y0rM/9OSlj/AAAAbAAAADgAAAA1AAAAZVBNWv8zMTr/MzE5/zMxOf8zMTn/MzE5/zMxOf8zMTn/MzE5/zMxOf8zMTr/UE1a/wAAAGUAAAA1AAAALQAAAFlVUl/8RUJN/zk3QP84N0D/OTdA/zg3QP84N0D/ODdA/zg3QP86N0H/RUJN/1VSYPwAAABZAAAALQAAACAAAABEPTpFtFZSYP1STlz/UU5b/1FOW/9RTlv/UU5b/1FOW/9RTlv/Uk5c/1ZSYP09OkW0AAAARAAAACAAAAAUAAAAKAAAAEUAAABdAAAAbgAAAHkAAAB6AAAAfAAAAHwAAAB6AAAAeQAAAG4AAABdAAAARQAAACgAAAAUAAAACAAAABQAAAAhAAAAMAAAADoAAAA/AAAAQwAAAEMAAABDAAAAQwAAAD8AAAA6AAAAMAAAACEAAAAUAAAACA=="),
"format": "RGBA8",
@ -1209,7 +1209,7 @@ data = {
}
[sub_resource type="ImageTexture" id="65"]
image = SubResource("Image_33w4k")
image = SubResource("Image_cg8le")
[sub_resource type="StyleBoxTexture" id="66"]
content_margin_left = 6.0
@ -1223,7 +1223,7 @@ expand_margin_right = 2.0
expand_margin_bottom = 2.0
region_rect = Rect2(0, 0, 16, 16)
[sub_resource type="Image" id="Image_dg6qs"]
[sub_resource type="Image" id="Image_tpkot"]
data = {
"data": PackedByteArray("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/wAAAADf39+IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAODg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P8AAAAA4ODg/9/f34gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADg4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/AAAAAODg4P/g4OD/39/fiAAAAAAAAAAAAAAAAAAAAAAAAAAA4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/wAAAADg4OD/4ODg/+Dg4P/f39+IAAAAAAAAAAAAAAAAAAAAAODg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADg4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P8AAAAAAAAAAAAAAAAAAAAA4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/AAAAAAAAAAAAAAAAAAAAAODg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/wAAAAAAAAAAAAAAAAAAAADg4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P8AAAAAAAAAAAAAAAAAAAAA4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/AAAAAAAAAAAAAAAAAAAAAODg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/wAAAAAAAAAAAAAAAAAAAADg4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P8AAAAAAAAAAAAAAAAAAAAA4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/AAAAAAAAAAAAAAAAAAAAAODg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="),
"format": "RGBA8",
@ -1233,9 +1233,9 @@ data = {
}
[sub_resource type="ImageTexture" id="425"]
image = SubResource("Image_dg6qs")
image = SubResource("Image_tpkot")
[sub_resource type="Image" id="Image_d8gug"]
[sub_resource type="Image" id="Image_8d7tv"]
data = {
"data": PackedByteArray("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4MXg/+D/4P/g/+D/4P/gwwAAAAAAAAAAAAAAAAAAAADg/+D/4P/g/+D/4P/g/+D/AAAAAAAAAAAAAAAAAAAAAOD/4P/g/+D/4P/g/+D/4P/hPAAAAAAAAAAAAAAAAAAA4P/g/+D/4P/g/+D/4P/g/+D/4P/g/+D/4P/gwwAAAADg/+D/4P/g/+D/4P/g/+D/4P/g/+D/4P/g/+D/AAAAAOD/4P/g/+D/4P/g/+D/4P/g/+D/4P/g/+D/4P8AAAAA4P/g/+D/4P/g/+D/4P/g/+D/4P/g/+D/4P/g/wAAAADg/+D/4P/g/+D/4P/g/+D/4P/g/+D/4P/g/+D/AAAAAOD/4P/g/+D/4P/g/+D/4P/g/+D/4P/g/+D/4P8AAAAA4P/g/+D/4P/g/+D/4P/g/+D/4P/g/+D/4P/g/wAAAADg/+D/4P/g/+D/4P/g/+D/4P/g/+D/4P/g/+D/AAAAAODD4P/g/+D/4P/g/+D/4P/g/+D/4P/g/+D/38IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"format": "LumAlpha8",
@ -1245,9 +1245,9 @@ data = {
}
[sub_resource type="ImageTexture" id="427"]
image = SubResource("Image_d8gug")
image = SubResource("Image_8d7tv")
[sub_resource type="Image" id="Image_r7rto"]
[sub_resource type="Image" id="Image_bwfne"]
data = {
"data": PackedByteArray("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3hfgz+DO3hcAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3Bbh0uD+4P7g1+AZAAAAAAAAAAAAAAAAAAAAAAAA3Bbh0uD+4P7g/uD+4NfgGQAAAAAAAAAAAAAAAAAA3hfg1OD+4NHg/uD94dLg/uDU3hcAAAAAAAAAAAAAAADgzeD+4NDcFuD+4P3bFeDR4P7gzAAAAAAAAAAAAAAAAOC+4MXZFP8B4P7g/QAA2xXhyeDFAAAAAAAAAAAAAAAAAAAAAAAA/wHg/uD9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AeD+4P0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4MThwQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"format": "LumAlpha8",
@ -1257,9 +1257,9 @@ data = {
}
[sub_resource type="ImageTexture" id="429"]
image = SubResource("Image_r7rto")
image = SubResource("Image_bwfne")
[sub_resource type="Image" id="Image_emksd"]
[sub_resource type="Image" id="Image_r6mai"]
data = {
"data": PackedByteArray("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADbB99u4Mfg8+Dz4MfebdsHAAAAAAAAAAAAAAAAAADjG+DP4P7g/uD+4P7g/uD+4M7jGwAAAAAAAAAAAADbB+DP4P7g4eBT2A3YDd9Q4Nfg/uDO2wcAAAAAAAAAAN9u4P7g4eMSAAAAAAAAAADhEeDh4P7ebAAAAAAAAAAA4Mjg/uBTAAAAAAAAAAAAAAAA3lXg/uDGAAAAAAAAAADg8uD+2A0AAAAAAAAAAAAAAADbDuD+4PEAAAAA4J7g/uD+4P7g/uCeAAAAAAAAAAAAAN0P4P7g8QAAAADoC+DU4P7g/uDU6AsAAAAAAAAAAAAA3lbg/uDGAAAAAAAA4Svg8+Dz4SsAAAAAAAAAAAAA5BPh4uD+3mwAAAAAAAAAAN9g32AAAAAAAAAAANsO3lbh4uD+4M7VBgAAAAAAAAAAAAAAAAAAAAAAAAAA4P7g/uD+4M7jGwAAAAAAAAAAAAAAAAAAAAAAAAAAAADg8uDF3mzVBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"format": "LumAlpha8",
@ -1269,9 +1269,9 @@ data = {
}
[sub_resource type="ImageTexture" id="431"]
image = SubResource("Image_emksd")
image = SubResource("Image_r6mai")
[sub_resource type="Image" id="Image_kxpah"]
[sub_resource type="Image" id="Image_ikos2"]
data = {
"data": PackedByteArray("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA39/fCN7e3mzg4ODF4ODg9ODg4PPg4ODF3t7ebePj4wkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3t7eLuDg4Njg4OD+4ODg/uDg4P7g4OD+4ODg/uDg4P7h4eHa4ODgMgAAAAAAAAAAAAAAAAAAAAAAAAAA3t7eL+Dg4PDg4OD+4ODg4eDg4FPY2NgN2NjYDd/f31Dg4ODX4ODg/uDg4PLh4eEzAAAAAAAAAAAAAAAA4+PjCeDg4Nzg4OD+4ODg4ePj4xIAAAAAAAAAAAAAAAAAAAAA4eHhEeDg4OHg4OD+4ODg3+bm5goAAAAAAAAAAN/f33fg4OD+4ODg/uDg4FMAAAAA4ODgS+Dg4OPh4eHi4ODgSQAAAADe3t5V4ODg/uDg4P7f3995AAAAAAAAAADh4eHa4ODg/uDg4P7Y2NgNAAAAAOHh4eLg4OD+4ODg/uDg4OEAAAAA29vbDuDg4P7g4OD+4eHh2gAAAAAAAAAA4ODg2+Dg4P7g4OD+2NjYDQAAAADh4eHi4ODg/uDg4P7g4ODhAAAAAN3d3Q/g4OD+4ODg/uDg4NsAAAAAAAAAAN7e3nzg4OD+4ODg/t/f31AAAAAA4ODgSeHh4eLg4ODh39/fSAAAAADe3t5W4ODg/uDg4P7g4OB7AAAAAAAAAADV1dUM4ODg4+Dg4P7g4ODX4eHhEQAAAAAAAAAAAAAAAAAAAADk5OQT4eHh4uDg4P7g4ODh1dXVDAAAAAAAAAAAAAAAAN/f3zjg4OD04ODg/uDg4OHe3t5V29vbDtvb2w7e3t5W4eHh4uDg4P7g4OD03t7eNgAAAAAAAAAAAAAAAAAAAAAAAAAA39/fN+Dg4N7g4OD+4ODg/uDg4P7g4OD+4ODg/uDg4P7g4ODd3t7eNgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADm5uYK39/fcODg4MXg4ODz4ODg8+Dg4MXf399u5ubmCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="),
"format": "RGBA8",
@ -1281,7 +1281,7 @@ data = {
}
[sub_resource type="ImageTexture" id="433"]
image = SubResource("Image_kxpah")
image = SubResource("Image_ikos2")
[sub_resource type="StyleBoxTexture" id="StyleBoxTexture_g6bu4"]
texture = ExtResource("1_ak8qr")
@ -1347,69 +1347,6 @@ border_width_top = 1
border_color = Color(0.2, 0.2, 0.2, 1)
anti_aliasing = false
[sub_resource type="AtlasTexture" id="250"]
atlas = ExtResource("1_ak8qr")
region = Rect2(96, 64, 16, 16)
[sub_resource type="AtlasTexture" id="251"]
atlas = ExtResource("1_ak8qr")
region = Rect2(96, 96, 16, 16)
[sub_resource type="AtlasTexture" id="252"]
atlas = ExtResource("1_ak8qr")
region = Rect2(96, 80, 16, 16)
[sub_resource type="Image" id="Image_nr33g"]
data = {
"data": PackedByteArray("AAAAAJiYmHlOTk4xAAAAAAAAAACNjY15Tk5OMQAAAAAAAAAAgoKCeU5OTjEAAAAAAAAAAE5OTjFOTk4cAAAAAAAAAAA4VV8AOFVfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjKy4ADhVXwAAAAAAAAAAAIGirQA4VV8AAAAAAAAAAACYmJh5Tk5OMQAAAAAAAAAAjY2NeU5OTjEAAAAAAAAAAIKCgnlOTk4xAAAAAA=="),
"format": "RGBA8",
"height": 16,
"mipmaps": false,
"width": 4
}
[sub_resource type="ImageTexture" id="29"]
image = SubResource("Image_nr33g")
[sub_resource type="StyleBoxTexture" id="4"]
content_margin_left = 6.0
content_margin_top = 3.0
content_margin_right = 6.0
content_margin_bottom = 3.0
texture = ExtResource("1_ak8qr")
texture_margin_left = 2.0
texture_margin_top = 2.0
texture_margin_right = 2.0
texture_margin_bottom = 2.0
axis_stretch_horizontal = 2
region_rect = Rect2(0, 40, 8, 8)
[sub_resource type="StyleBoxTexture" id="248"]
content_margin_left = 6.0
content_margin_top = 3.0
content_margin_right = 6.0
content_margin_bottom = 3.0
texture = ExtResource("1_ak8qr")
texture_margin_left = 2.0
texture_margin_top = 2.0
texture_margin_right = 2.0
texture_margin_bottom = 2.0
axis_stretch_horizontal = 2
region_rect = Rect2(32, 40, 8, 8)
[sub_resource type="StyleBoxTexture" id="249"]
content_margin_left = 6.0
content_margin_top = 3.0
content_margin_right = 6.0
content_margin_bottom = 3.0
texture = ExtResource("1_ak8qr")
texture_margin_left = 2.0
texture_margin_top = 2.0
texture_margin_right = 2.0
texture_margin_bottom = 2.0
axis_stretch_horizontal = 2
region_rect = Rect2(16, 40, 8, 8)
[sub_resource type="StyleBoxTexture" id="461"]
texture = ExtResource("1_ak8qr")
texture_margin_left = 2.0
@ -1440,7 +1377,7 @@ bg_color = Color(0.490196, 0.490196, 0.490196, 1)
corner_detail = 1
anti_aliasing = false
[sub_resource type="Image" id="Image_67hak"]
[sub_resource type="Image" id="Image_h6a0p"]
data = {
"data": PackedByteArray("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN9Y3BYAAAAAAAAAAAAAAADcFt9YAAAAAAAAAAAAAN9Y4P7g09wWAAAAAAAAAADcFuDT4P7fWAAAAAAAAAAA2xXf0uD/4NfgGQAAAADbFd/S4P/g198YAAAAAAAAAAAAANsV39Lg/+DX4BnbFd/S4P/g198YAAAAAAAAAAAAAAAAAADbFd/S4P/h2uDW4P/g198YAAAAAAAAAAAAAAAAAAAAAAAA2xXf1uD/4P/g298YAAAAAAAAAAAAAAAAAAAAAAAAAADbFd/W4P/g/+Db4BkAAAAAAAAAAAAAAAAAAAAAAADbFd/S4P/f2uDW4P/g1+AZAAAAAAAAAAAAAAAAAADbFd/S4P/g198Y2xXf0uD/4NfgGQAAAAAAAAAAAADbFd/S4P/g198YAAAAANsV39Lg/+DX4BkAAAAAAAAAAN9Y4P7g09wWAAAAAAAAAADcFuDT4P7fWAAAAAAAAAAAAADfWNwWAAAAAAAAAAAAAAAA3BbfWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"format": "LumAlpha8",
@ -1450,7 +1387,7 @@ data = {
}
[sub_resource type="ImageTexture" id="49"]
image = SubResource("Image_67hak")
image = SubResource("Image_h6a0p")
[sub_resource type="StyleBoxTexture" id="127"]
content_margin_left = 4.0
@ -2271,7 +2208,7 @@ texture_margin_right = 2.0
texture_margin_bottom = 2.0
region_rect = Rect2(72, 64, 8, 8)
[sub_resource type="Image" id="Image_22qm6"]
[sub_resource type="Image" id="Image_8nh6x"]
data = {
"data": PackedByteArray("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAc5uqs87c4bPO3OGzztzhs87c4bPO3OGzztzhs3ObqrMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="),
"format": "RGBA8",
@ -2281,7 +2218,7 @@ data = {
}
[sub_resource type="ImageTexture" id="199"]
image = SubResource("Image_22qm6")
image = SubResource("Image_8nh6x")
[sub_resource type="StyleBoxTexture" id="200"]
texture = SubResource("199")
@ -2305,7 +2242,7 @@ texture_margin_right = 2.0
texture_margin_bottom = 2.0
region_rect = Rect2(64, 64, 8, 8)
[sub_resource type="Image" id="Image_mwlj8"]
[sub_resource type="Image" id="Image_hk701"]
data = {
"data": PackedByteArray("/wD//wD//wD//wD/Z3qFZnqGaHuGaHuGaHuGaHuGZnqGZ3qF/wD//wD//wD//wD//wD//wD/Z3qFZnqGV1FRTEJATUNBTUNBTUNBTUNBTEJAV1FRZnqGZ3qF/wD//wD//wD/Z3qFVkxLTEJATURBTUNBTkRCTkRCTkRCTkRCTUNBTURBTEJAV1FRZ3qF/wD//wD/ZnqGTEJATEJATUNBT0VDT0VDT0VDT0VDT0VDT0VDTUNBTEJATEJAZ3uH/wD/Z3qFV1FRTEJATEJATkRCT0RDUEVEUkZEUkZEUUZFT0RDTkRCTEJATEJAV1FRZ3qFZnqGS0A/TEJATUNBT0RDUUdFUkhGU0hHU0hHUkhGUUdFT0RDTkRCTEJAS0E/Z3uHZ3uHS0E/TEJATUNBT0RDUUdFVElGVUpHVUlHVUpHUkhGUEVETUNBTEJAS0E/aHyIZ3uHSkA+S0E/TUNBT0VDUUdFVElGVUtJVk1LVElGU0lHUEZETkRCTEJAS0E/aHyIZ3uHSkE+S0E/TEJAT0VDUUdFVElGVUtJVUtJVUpHUkhGUEZETkRCTEJASkA+aHyIZ3uHSD48S0I/S0E/TkRCUEVEUUZFU0lHU0lHUkhGUEVETkRCTEJAS0E/ST89aHyIZ3uHRj08SD48SkA+TEJATkRCT0RDUEVEUEVEUEZET0VDTEJAS0A/ST89Rz07Z3uHZ3qFV1FRRz47SUA9S0E/TEJATUNBTkRCTkRCTUNBTEJAS0E/ST89Rz07V1FRaHuG/wD/Z3uHRj08Rz07SD48ST89SkA+S0E/S0E/S0A/SkA+SD48Rz47Rz07Z3uH/wD//wD/Z3qFV1FRRTw7Rz07Rz07Rz07SD48SD48Rz07Rz07Rz47Rj08V1FRZnqG/wD//wD//wD/Z3qFZ3uHV1FRRjw6Rjw6Rz47Rz47Rjw6Rjw6V1FRZ3uHaHuG/wD//wD//wD//wD//wD//wD/ZnqGZ3uHaHyIaHyIaHyIaHyIZ3uHaHuG/wD//wD//wD//wD/"),
"format": "RGB8",
@ -2315,7 +2252,7 @@ data = {
}
[sub_resource type="ImageTexture" id="204"]
image = SubResource("Image_mwlj8")
image = SubResource("Image_hk701")
[sub_resource type="StyleBoxTexture" id="205"]
texture = SubResource("204")
@ -2428,7 +2365,7 @@ axis_stretch_horizontal = 2
axis_stretch_vertical = 2
region_rect = Rect2(80, 0, 16, 8)
[sub_resource type="Image" id="Image_k0gxe"]
[sub_resource type="Image" id="Image_ll126"]
data = {
"data": PackedByteArray("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOD/4P/g/+D/4P/g/+D/4P8AAAAAAAAAAOD/4P/g/+D/4P/g/+D/4P8AAAAAAAAAAOD/4P/g/+D/4P/g/+D/4P8AAAAAAAAAAOFe4PTg/+D/4P/g/+D24WYAAAAAAAAAAAAA3yjf0uD/4P/g1+MtAAAAAAAAAAAAAAAAAADoC+Gf4Z/oCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"),
"format": "LumAlpha8",
@ -2438,9 +2375,9 @@ data = {
}
[sub_resource type="ImageTexture" id="306"]
image = SubResource("Image_k0gxe")
image = SubResource("Image_ll126")
[sub_resource type="Image" id="Image_x5o30"]
[sub_resource type="Image" id="Image_jfrub"]
data = {
"data": PackedByteArray("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4P/g/+D/32AAAAAAAAAAAAAAAAAAAAAA4P/g/+D/4PThKwAAAAAAAAAAAAAAAAAA4P/g/+D/4P/g1egLAAAAAAAAAAAAAAAA4P/g/+D/4P/g/+GfAAAAAAAAAAAAAAAA4P/g/+D/4P/g/+GfAAAAAAAAAAAAAAAA4P/g/+D/4P/g1egLAAAAAAAAAAAAAAAA4P/g/+D/4PThKwAAAAAAAAAAAAAAAAAA4P/g/+D/32AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"),
"format": "LumAlpha8",
@ -2450,9 +2387,9 @@ data = {
}
[sub_resource type="ImageTexture" id="308"]
image = SubResource("Image_x5o30")
image = SubResource("Image_jfrub")
[sub_resource type="Image" id="Image_r2uaw"]
[sub_resource type="Image" id="Image_d7wny"]
data = {
"data": PackedByteArray("AAAAAAAAAAAAAAAAAAAAAAAA/1n/FP8U/1kAAAAAAAAAAAAA/1n/FP8U/1kAAAAAAAAAAAAA/1n/FP8U/1kAAAAAAAAAAP9Z/xT/FP9ZAAAAAAAA/1n/FP8U/1kAAAAAAAD/Wf8U/xT/WQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"format": "LumAlpha8",
@ -2462,9 +2399,9 @@ data = {
}
[sub_resource type="ImageTexture" id="292"]
image = SubResource("Image_r2uaw")
image = SubResource("Image_d7wny")
[sub_resource type="Image" id="Image_mmk83"]
[sub_resource type="Image" id="Image_jacs1"]
data = {
"data": PackedByteArray("FxYabx0cIe8gHiT3IR8l9yEfJfchHyX3IR8l9yAeJPcdHCHvFxYabx0cIfAkIin/KCYt/ygmLv8oJi7/KCYu/ygmLv8oJi3/JCIp/x0cIfAgHiT5KCYt/ysqMf8sKjL/LCoy/ywqMv8sKjL/Kyox/ygmLf8gHiT5IR8l9ygmLv8sKjL/LCoy/ywqMv8sKjL/LCoy/ywqMv8oJi7/IR8l9yEfJfcoJi7/LCoy/ywqMv8sKjL/LCoy/ywqMv8sKjL/KCYu/yEfJfchHyX3KCYu/ywqMv8sKjL/LCoy/ywqMv8sKjL/LCoy/ygmLv8hHyX3IR8l9ygmLv8sKjL/LCoy/ywqMv8sKjL/LCoy/ywqMv8oJi7/IR8l9yAeJPkoJi3/Kyox/ywqMv8sKjL/LCoy/ywqMv8rKjH/KCYt/yAeJPkdHCHwJCIp/ygmLf8oJi7/KCYu/ygmLv8oJi7/KCYt/yQiKf8dHCHxFxYabx0cIfAgHiT3IR8l9yEfJfchHyX3IR8l9yAeJPcdHCHuFxYabw=="),
"format": "RGBA8",
@ -2474,7 +2411,7 @@ data = {
}
[sub_resource type="ImageTexture" id="39"]
image = SubResource("Image_mmk83")
image = SubResource("Image_jacs1")
[sub_resource type="StyleBoxTexture" id="272"]
content_margin_left = 0.0
@ -2534,7 +2471,7 @@ axis_stretch_horizontal = 2
axis_stretch_vertical = 2
region_rect = Rect2(24, 40, 8, 8)
[sub_resource type="Image" id="Image_kak1t"]
[sub_resource type="Image" id="Image_nk8py"]
data = {
"data": PackedByteArray("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABNS1kHTUtZJ01LWVBNS1lmTUtZaE1LWWhNS1loTUtZaE1LWWhNS1loWFZjarCvtYFNS1knTUtZBwAAAAAAAAAATUtZJzg3QLQgICT6Hh4i/x8fI/8fHyP/Hx8j/x8fI/8fHyP/Hx8j/4uLjf//////tra53U1LWScAAAAAAAAAAE1LWVAgICT6ICAk/yIiJ/8jIyj/IyMo/yMjKP8jIyj/IyMo/0JCR//4+Pj//v7+/1dXWvtNS1lQAAAAAAAAAABNS1lmHh4i/yIiJ/8lJSr/JSUq/05OUv8mJiv/JSUq/yUlKv/Fxcf//////6qqq/8eHiL/TUtZZgAAAAAAAAAATUtZaB8fI/8jIyj/JSUq/7i4uv//////X19j/yUlKv90dHf//////+3t7f8zMzj/Hx8j/01LWWgAAAAAAAAAAE1LWWgfHyP/IyMo/yUlKv+NjY///////7i4uf81NTn/7e3t//////90dHf/IyMo/x8fI/9NS1loAAAAAAAAAABNS1loHx8j/yMjKP8lJSr/Ojo+//v7+//6+vr/srK0///////Fxcf/JSUq/yMjKP8fHyP/TUtZaAAAAAAAAAAATUtZaB8fI/8jIyj/JSUq/yUlKv+4uLr///////7+/v/4+Pj/RUVJ/yUlKv8jIyj/Hx8j/01LWWgAAAAAAAAAAE1LWWgfHyP/IyMo/yUlKv8lJSr/YWFl////////////j4+S/yUlKv8lJSr/IyMo/x8fI/9NS1loAAAAAAAAAABNS1loHx8j/yMjKP8lJSr/JSUq/yYmK/9OTlL/Y2Nm/yoqL/8lJSr/JSUq/yMjKP8fHyP/TUtZaAAAAAAAAAAATUtZZh4eIv8iIif/JSUq/yUlKv8lJSr/JSUq/yUlKv8lJSr/JSUq/yUlKv8iIif/Hh4i/01LWWYAAAAAAAAAAE1LWVAgICT6ICAk/yIiJ/8jIyj/IyMo/yMjKP8jIyj/IyMo/yMjKP8iIif/ICAk/yAgJPtNS1lQAAAAAAAAAABNS1knODZAtCAgJPseHiL/Hx8j/x8fI/8fHyP/Hx8j/x8fI/8fHyP/Hh4i/yAgJfo4NkC0TUtZJwAAAAAAAAAATUtZB01LWSdNS1lQTUtZZk1LWWhNS1loTUtZaE1LWWhNS1loTUtZaE1LWWZNS1lQTUtZJ01LWQcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="),
"format": "RGBA8",
@ -2544,9 +2481,9 @@ data = {
}
[sub_resource type="ImageTexture" id="334"]
image = SubResource("Image_kak1t")
image = SubResource("Image_nk8py")
[sub_resource type="Image" id="Image_ds41u"]
[sub_resource type="Image" id="Image_iduya"]
data = {
"data": PackedByteArray("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABNS1kHTUtZJ01LWVBNS1lmTUtZaE1LWWhNS1loTUtZaE1LWWhNS1loTUtZZk1LWVBNS1knTUtZBwAAAAAAAAAATUtZJzg3QLQgICT6Hh4i/x8fI/8fHyP/Hx8j/x8fI/8fHyP/Hx8j/x4eIv8gICT6ODdAtE1LWScAAAAAAAAAAE1LWVAgICT6ICAk/yIiJ/8jIyj/IyMo/yMjKP8jIyj/IyMo/yMjKP8iIif/ICAk/yAgJPpNS1lQAAAAAAAAAABNS1lmHh4i/yIiJ/8lJSr/JSUq/yUlKv8lJSr/JSUq/yUlKv8lJSr/JSUq/yIiJ/8eHiL/TUtZZgAAAAAAAAAATUtZaB8fI/8jIyj/JSUq/yUlKv8lJSr/JSUq/yUlKv8lJSr/JSUq/yUlKv8jIyj/Hx8j/01LWWgAAAAAAAAAAE1LWWgfHyP/IyMo/yUlKv8lJSr/JSUq/yUlKv8lJSr/JSUq/yUlKv8lJSr/IyMo/x8fI/9NS1loAAAAAAAAAABNS1loHx8j/yMjKP8lJSr/JSUq/yUlKv8lJSr/JSUq/yUlKv8lJSr/JSUq/yMjKP8fHyP/TUtZaAAAAAAAAAAATUtZaB8fI/8jIyj/JSUq/yUlKv8lJSr/JSUq/yUlKv8lJSr/JSUq/yUlKv8jIyj/Hx8j/01LWWgAAAAAAAAAAE1LWWgfHyP/IyMo/yUlKv8lJSr/JSUq/yUlKv8lJSr/JSUq/yUlKv8lJSr/IyMo/x8fI/9NS1loAAAAAAAAAABNS1loHx8j/yMjKP8lJSr/JSUq/yUlKv8lJSr/JSUq/yUlKv8lJSr/JSUq/yMjKP8fHyP/TUtZaAAAAAAAAAAATUtZZh4eIv8iIif/JSUq/yUlKv8lJSr/JSUq/yUlKv8lJSr/JSUq/yUlKv8iIif/Hh4i/01LWWYAAAAAAAAAAE1LWVAgICT6ICAk/yIiJ/8jIyj/IyMo/yMjKP8jIyj/IyMo/yMjKP8iIif/ICAk/yAgJPtNS1lQAAAAAAAAAABNS1knODZAtCAgJPseHiL/Hx8j/x8fI/8fHyP/Hx8j/x8fI/8fHyP/Hh4i/yAgJfo4NkC0TUtZJwAAAAAAAAAATUtZB01LWSdNS1lQTUtZZk1LWWhNS1loTUtZaE1LWWhNS1loTUtZaE1LWWZNS1lQTUtZJ01LWQcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="),
"format": "RGBA8",
@ -2556,7 +2493,7 @@ data = {
}
[sub_resource type="ImageTexture" id="336"]
image = SubResource("Image_ds41u")
image = SubResource("Image_iduya")
[sub_resource type="AtlasTexture" id="359"]
atlas = ExtResource("1_ak8qr")
@ -2632,7 +2569,19 @@ border_width_left = 1
border_color = Color(0.2, 0.2, 0.2, 1)
anti_aliasing = false
[sub_resource type="Image" id="Image_1e2s7"]
[sub_resource type="AtlasTexture" id="250"]
atlas = ExtResource("1_ak8qr")
region = Rect2(96, 64, 16, 16)
[sub_resource type="AtlasTexture" id="251"]
atlas = ExtResource("1_ak8qr")
region = Rect2(96, 96, 16, 16)
[sub_resource type="AtlasTexture" id="252"]
atlas = ExtResource("1_ak8qr")
region = Rect2(96, 80, 16, 16)
[sub_resource type="Image" id="Image_a5v57"]
data = {
"data": PackedByteArray("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIKCgnmNjY15mJiYeYGirQCMrLgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOFVfAE5OTjGCgoJ5jY2NeZiYmHlOTk4xTk5OMU5OTjE4VV8AOFVfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADhVXwBOTk4cTk5OMU5OTjFOTk4xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="),
"format": "RGBA8",
@ -2642,7 +2591,33 @@ data = {
}
[sub_resource type="ImageTexture" id="111"]
image = SubResource("Image_1e2s7")
image = SubResource("Image_a5v57")
[sub_resource type="StyleBoxTexture" id="4"]
content_margin_left = 6.0
content_margin_top = 3.0
content_margin_right = 6.0
content_margin_bottom = 3.0
texture = ExtResource("1_ak8qr")
texture_margin_left = 2.0
texture_margin_top = 2.0
texture_margin_right = 2.0
texture_margin_bottom = 2.0
axis_stretch_horizontal = 2
region_rect = Rect2(0, 40, 8, 8)
[sub_resource type="StyleBoxTexture" id="249"]
content_margin_left = 6.0
content_margin_top = 3.0
content_margin_right = 6.0
content_margin_bottom = 3.0
texture = ExtResource("1_ak8qr")
texture_margin_left = 2.0
texture_margin_top = 2.0
texture_margin_right = 2.0
texture_margin_bottom = 2.0
axis_stretch_horizontal = 2
region_rect = Rect2(16, 40, 8, 8)
[sub_resource type="AtlasTexture" id="20"]
atlas = ExtResource("3_0m6kw")
@ -2734,13 +2709,6 @@ HScrollBar/styles/grabber_pressed = SubResource("StyleBoxTexture_bfd3g")
HScrollBar/styles/scroll = SubResource("StyleBoxTexture_lsn07")
HScrollBar/styles/scroll_focus = SubResource("StyleBoxTexture_8681i")
HSeparator/styles/separator = SubResource("576")
HSlider/icons/grabber = SubResource("250")
HSlider/icons/grabber_disabled = SubResource("251")
HSlider/icons/grabber_highlight = SubResource("252")
HSlider/icons/tick = SubResource("29")
HSlider/styles/grabber_area = SubResource("4")
HSlider/styles/grabber_area_highlight = SubResource("248")
HSlider/styles/slider = SubResource("249")
ItemList/colors/font_color = Color(0.866667, 0.866667, 0.866667, 1)
ItemList/colors/font_color_selected = Color(1, 1, 1, 1)
ItemList/colors/guide_color = Color(0.266667, 0.266667, 0.266667, 1)
@ -2823,12 +2791,7 @@ TabContainer/constants/label_valign_bg = 0
TabContainer/constants/label_valign_fg = 0
TabContainer/constants/side_margin = 0
TabContainer/constants/top_margin = 0
TabContainer/icons/decrement = null
TabContainer/icons/decrement_highlight = null
TabContainer/icons/increment = null
TabContainer/icons/increment_highlight = null
TabContainer/icons/menu = null
TabContainer/icons/menu_highlight = null
TabContainer/styles/panel = SubResource("420")
TabContainer/styles/tab_bg = SubResource("525")
TabContainer/styles/tab_disabled = SubResource("422")

View file

@ -0,0 +1,33 @@
extends Control
var split_max: int = 1280
var split_min: int = 925
var step_value: int = -7
var split_speed: float = 0.001/100
func _input(event):
if event.is_action_released("rekku_hide"):
#self.visible = !self.visible
if class_functions.rekku_state == false:
self.visible = true
class_functions.rekku_state = true
for n in range (split_max, split_min,step_value):
await class_functions.wait(split_speed)
%SplitContainer.split_offset=n
%pop_rtl.visible = false
%TabContainer.set_tab_title(0, "GLOBALS")
%TabContainer.set_tab_title(1, "SYSTEMS")
%TabContainer.set_tab_title(2, "TOOLS")
%TabContainer.set_tab_title(3, "SETTINGS")
%TabContainer.set_tab_title(4, "ABOUT")
elif event.is_action_released("rekku_hide") and class_functions.rekku_state == true:
%TabContainer.set_tab_title(0, " GLOBALS ")
%TabContainer.set_tab_title(1, " SYSTEMS ")
%TabContainer.set_tab_title(2, " TOOLS ")
%TabContainer.set_tab_title(3, " SETTINGS ")
%TabContainer.set_tab_title(4, " ABOUT ")
%pop_rtl.visible = false
for n in range (split_min, split_max,abs(step_value)):
await class_functions.wait(split_speed)
%SplitContainer.split_offset=n
class_functions.rekku_state = false
self.visible = false

View file

@ -1,103 +0,0 @@
extends Control
var app_data := AppData.new()
var current_system := Emulator.new()
var press_time: float = 0.0
var is_reset_pressed: bool = false
var reset_result: Dictionary
@export var PRESS_DURATION: float = 3.0
func _ready():
app_data = data_handler.app_data
_connect_signals()
func _process(delta: float) -> void:
if is_reset_pressed:
press_time += delta
%reset_progress.value = press_time / PRESS_DURATION * 100.0
if press_time >= PRESS_DURATION:
_do_complete()
press_time = 0.0
is_reset_pressed = false
%reset_progress.value = 0.0
func _connect_signals() -> void:
%retroarch_button.pressed.connect(_hide_show_buttons.bind(%retroarch_button,%system_gridcontainer, %action_gridcontainer))
%mame_button.pressed.connect(_hide_show_buttons.bind(%mame_button,%system_gridcontainer, %action_gridcontainer))
%ruffle_button.pressed.connect(_hide_show_buttons.bind(%ruffle_button,%system_gridcontainer, %action_gridcontainer))
%melonds_button.pressed.connect(_hide_show_buttons.bind(%melonds_button,%system_gridcontainer, %action_gridcontainer))
%pcsx2_button.pressed.connect(_hide_show_buttons.bind(%pcsx2_button,%system_gridcontainer, %action_gridcontainer))
%duckstation_button.pressed.connect(_hide_show_buttons.bind(%duckstation_button,%system_gridcontainer, %action_gridcontainer))
%ppsspp_button.pressed.connect(_hide_show_buttons.bind(%ppsspp_button,%system_gridcontainer, %action_gridcontainer))
%vita3k_button.pressed.connect(_hide_show_buttons.bind(%vita3k_button,%system_gridcontainer, %action_gridcontainer))
%rpcs3_button.pressed.connect(_hide_show_buttons.bind(%rpcs3_button,%system_gridcontainer, %action_gridcontainer))
%ryujinx_button.pressed.connect(_hide_show_buttons.bind(%ryujinx_button,%system_gridcontainer, %action_gridcontainer))
%dolphin_button.pressed.connect(_hide_show_buttons.bind(%dolphin_button,%system_gridcontainer, %action_gridcontainer))
%primehack_button.pressed.connect(_hide_show_buttons.bind(%primehack_button,%system_gridcontainer, %action_gridcontainer))
%cemu_button.pressed.connect(_hide_show_buttons.bind(%cemu_button,%system_gridcontainer, %action_gridcontainer))
%xemu_button.pressed.connect(_hide_show_buttons.bind(%xemu_button,%system_gridcontainer, %action_gridcontainer))
%esde_button.pressed.connect(_hide_show_buttons.bind(%esde_button,%system_gridcontainer, %action_gridcontainer))
%help_button.pressed.connect(_do_action.bind(%help_button))
#%launch_button.pressed.connect(_do_action.bind(%launch_button))
%launch_button.pressed.connect(_do_action.bind(%launch_button))
%reset_button.button_down.connect(_do_action.bind(%reset_button))
%reset_button.button_up.connect(_on_Button_released.bind(%reset_progress))
func _hide_show_buttons(button: Button, buttons_gridcontainer: GridContainer, hidden_gridcontainer: GridContainer) -> void:
current_system = app_data.emulators[button.text.to_lower()]
match button.name:
"retroarch_button", "mame_button", "ruffle_button", "melonds_button", "pcsx2_button", "duckstation_button", \
"ppsspp_button", "vita3k_button", "rpcs3_button", "ryujinx_button", "dolphin_button", "primehack_button", \
"cemu_button", "xemu_button", "esde_button":
%reset_button.text="RESET"
hidden_gridcontainer.visible = true
if button.toggle_mode == false:
for i in range(buttons_gridcontainer.get_child_count()):
var child = buttons_gridcontainer.get_child(i)
if child is Button and child != button:
child.visible=false
elif button.toggle_mode == true and hidden_gridcontainer.visible == true:
hidden_gridcontainer.visible = false
for i in range(buttons_gridcontainer.get_child_count()):
var child = buttons_gridcontainer.get_child(i)
if child is Button:
child.visible=true
child.toggle_mode = false
if hidden_gridcontainer.visible == true:
button.toggle_mode = true
func _on_Button_released(progress: ProgressBar) -> void:
is_reset_pressed = false
%reset_progress.visible = false
press_time = 0.0
progress.value = 0.0
func _do_action(button: Button) -> void:
match [button.name, current_system.name]:
["help_button", current_system.name]:
class_functions.log_parameters[2] = class_functions.log_text + "Launching " + current_system.name + " Help"
class_functions.execute_command(class_functions.wrapper_command,class_functions.log_parameters, false)
class_functions.launch_help(current_system.url)
["launch_button", current_system.name]:
class_functions.log_parameters[2] = class_functions.log_text + "Launching " + current_system.name
class_functions.execute_command(class_functions.wrapper_command,class_functions.log_parameters, false)
var launch = class_functions.execute_command(current_system.launch,[], false)
class_functions.log_parameters[2] = class_functions.log_text + "Exit Code: " + str(launch["exit_code"])
class_functions.execute_command(class_functions.wrapper_command,class_functions.log_parameters, false)
["reset_button", current_system.name]:
is_reset_pressed = true
%reset_progress.visible = true
func _do_complete() ->void:
if is_reset_pressed:
var parameters = ["prepare_component","reset",current_system.name]
%reset_button.text = "RESETTING-NOW"
class_functions.log_parameters[2] = class_functions.log_text + "Resetting " + current_system.name
class_functions.execute_command(class_functions.wrapper_command,class_functions.log_parameters, false)
await run_thread_command(class_functions.wrapper_command,parameters, false)
class_functions.log_parameters[2] = class_functions.log_text + "Exit Code: " + str(reset_result["exit_code"])
class_functions.execute_command(class_functions.wrapper_command,class_functions.log_parameters, false)
%reset_button.text = "RESET COMPLETED"
func run_thread_command(command: String, parameters: Array, console: bool) -> void:
reset_result = await class_functions.run_command_in_thread(command, parameters, console)

View file

@ -0,0 +1,58 @@
extends MarginContainer
var rd_web_button:= Button.new()
var rd_changelog_button:= Button.new()
var rd_wiki_button:= Button.new()
var rd_credits_button:= Button.new()
var rd_donate_button:= Button.new()
var rd_contactus_button:= Button.new()
var rd_licenses_button:= Button.new()
var app_data:= AppData.new()
var button_array: Array = [rd_web_button, rd_changelog_button, rd_wiki_button, rd_credits_button, rd_donate_button, rd_contactus_button, rd_licenses_button]
var web_id: Array = ["rd_web", "rd_changelog", "rd_wiki", "rd_credits", "rd_donate", "rd_contactus", "rd_licenses"]
func _ready():
#tk_about = class_functions.import_csv_data("res://tk_about.txt")
app_data = data_handler.app_data
_connect_signals()
create_buttons()
func _connect_signals() -> void:
for i in button_array.size():
button_array[i].pressed.connect(_about_button_pressed.bind(web_id[i], button_array[i]))
func _about_button_pressed(id: String, button: Button) -> void:
var tmp_txt = button.text
if class_functions.desktop_mode != "gamescope":
class_functions.logger("i","Loading website for " + id)
class_functions.launch_help(button.get_meta("url"))
else:
button.text = "Help only in Desktop Mode"
await class_functions.wait(3.0)
button.text = tmp_txt
func create_buttons() -> void:
for i in button_array.size():
var button = button_array[i]
%GridContainer.add_child(button)
var id = web_id[i]
if id in app_data.about_links:
var web_data: Link = app_data.about_links[id]
_setup_button(button, web_data)
func _setup_button(button: Button, web_data: Link) -> void:
button.size_flags_horizontal = Control.SIZE_EXPAND_FILL
button.size_flags_vertical = Control.SIZE_EXPAND_FILL
button.text = web_data.name
var vect2 = Vector2(200,100)
button.custom_minimum_size = vect2
#button.tooltip_text = web_data.description
button.icon = ResourceLoader.load(web_data.icon)
button.set_meta("url", web_data.url)
button.set_meta("description", web_data.description)
button.icon_alignment = HORIZONTAL_ALIGNMENT_LEFT
button.vertical_icon_alignment = VERTICAL_ALIGNMENT_CENTER
button.add_theme_constant_override("icon_max_width", 64)
button.icon_alignment = HORIZONTAL_ALIGNMENT_CENTER
button.alignment = HORIZONTAL_ALIGNMENT_CENTER
button.vertical_icon_alignment = VERTICAL_ALIGNMENT_TOP

View file

@ -1,10 +1,7 @@
extends TabContainer
var icon_width: int = 32
@onready var tcount: int = get_tab_count()-1
var l1_button_texture: Texture2D = load("res://assets/icons/kenney_input-prompts-pixel-16/Tiles/tile_0797.png")
var r1_button_texture: Texture2D = load("res://assets/icons/kenney_input-prompts-pixel-16/Tiles/tile_0798.png")
@onready var tcount: int = get_tab_count()-2
func _ready():
focusFirstFocusableChild() #grab focus on first element to enable controller focusing
@ -12,6 +9,18 @@ func _ready():
%TabContainer.add_theme_icon_override("decrement_highlight",ResourceLoader.load("res://assets/icons/kenney_input-prompts-pixel-16/Tiles/tile_0763.png"))
%TabContainer.add_theme_icon_override("increment",ResourceLoader.load("res://assets/icons/kenney_input-prompts-pixel-16/Tiles/tile_0798.png"))
%TabContainer.add_theme_icon_override("increment_highlight",ResourceLoader.load("res://assets/icons/kenney_input-prompts-pixel-16/Tiles/tile_0764.png"))
if class_functions.font_select !=3:
%TabContainer.add_theme_font_size_override("font_size", class_functions.font_tab_size)
elif class_functions.font_select == 3:
%TabContainer.add_theme_font_size_override("font_size", 15)
else:
%TabContainer.add_theme_font_size_override("font_size", class_functions.font_tab_size)
set_tab_title(0, " GLOBALS ")
set_tab_title(1, " SYSTEMS ")
set_tab_title(2, " TOOLS ")
set_tab_title(3, " SETTINGS ")
set_tab_title(4, " ABOUT ")
set_tab_hidden(5, true)
set_tab_icon(0, ResourceLoader.load("res://assets/icons/pixelitos/128/map-globe.png"))
set_tab_icon_max_width(0,icon_width)
set_tab_icon(1, ResourceLoader.load("res://assets/icons/pixelitos/128/preferences-system-windows.png"))
@ -22,39 +31,44 @@ func _ready():
set_tab_icon_max_width(3,icon_width)
set_tab_icon(4, ResourceLoader.load("res://assets/icons/pixelitos/128/help-about.png"))
set_tab_icon_max_width(4,icon_width)
#%TK_GRAPHICS.name="BOB"
connect_focus_signals(self)
%volume_effects_slider.value = class_functions.volume_effects
func connect_focus_signals(node):
for child in node.get_children():
if child is Button:
child.focus_entered.connect(_on_Button_focus_entered.bind(child))
child.focus_entered.connect(_on_button_focus_entered.bind(child))
child.focus_exited.connect(_on_button_focus_exited.bind())
elif child is Control:
connect_focus_signals(child)
func _on_Button_focus_entered(button: Button):
if button:
func _on_button_focus_exited() -> void:
%pop_rtl.visible = false
func _on_button_focus_entered(button: Button):
if button and class_functions.sound_effects:
%AudioStreamPlayer2D.volume_db = class_functions.volume_effects
%AudioStreamPlayer2D.play()
#if button and class_functions.rekku_state == false and button.has_meta("description"):
#%pop_rtl.visible = true
#%pop_rtl.text = button.get_meta("description")
elif class_functions.rekku_state == false:
%pop_rtl.visible = true
%pop_rtl.text = "Hey, there's no description"
func _input(event):
if (event.is_action_pressed("next_tab")):
%r1_button.texture_normal = %r1_button.texture_pressed
if current_tab == tcount:
current_tab = 0
else:
self.select_next_available()
focusFirstFocusableChild()
else:
%r1_button.texture_normal = r1_button_texture
if (event.is_action_pressed("previous_tab")):
%l1_button.texture_normal = %l1_button.texture_pressed
if current_tab == 0:
current_tab = tcount
else:
self.select_previous_available()
focusFirstFocusableChild()
else:
%l1_button.texture_normal = l1_button_texture
func focusFirstFocusableChild():
var children = findElements(get_current_tab_control(), "Control")

View file

@ -0,0 +1,35 @@
extends Control
func _ready():
_connect_signals()
func _process(delta: float) -> void:
if class_functions.current_button != null:
update_progress(delta, class_functions.current_progress)
func update_progress(delta: float, progress: ProgressBar) -> void:
if class_functions.press_time >= class_functions.PRESS_DURATION:
class_functions._do_complete(class_functions.current_button)
class_functions.is_state_pressed = false
#print ("Progress Bar: %s Button: %s" % [progress.name, current_button.name])
elif class_functions.is_state_pressed and class_functions.current_state == "mixed":
class_functions.press_time += delta
progress.value = class_functions.press_time / class_functions.PRESS_DURATION * 100.0
func _connect_signals():
%quick_resume_button.pressed.connect(class_functions.run_function.bind(%quick_resume_button, "quick_resume"))
%button_swap_button.button_down.connect(class_functions._do_action.bind(%button_swap_progress, %button_swap_button, class_functions.abxy_state))
%button_swap_button.button_up.connect(class_functions._on_button_released.bind(%button_swap_progress))
%button_swap_button.pressed.connect(class_functions.run_function.bind(%button_swap_button, "abxy_button_swap"))
%ask_to_exit_button.button_down.connect(class_functions._do_action.bind(%ask_to_exit_progress, %ask_to_exit_button, class_functions.ask_to_exit_state))
%ask_to_exit_button.button_up.connect(class_functions._on_button_released.bind(%ask_to_exit_progress))
%ask_to_exit_button.pressed.connect(class_functions.run_function.bind(%ask_to_exit_button, "ask_to_exit"))
%border_button.button_down.connect(class_functions._do_action.bind(%border_progress, %border_button, class_functions.border_state))
%border_button.button_up.connect(class_functions._on_button_released.bind(%border_progress))
%border_button.pressed.connect(class_functions.run_function.bind(%border_button, "borders"))
%widescreen_button.button_down.connect(class_functions._do_action.bind(%widescreen_progress, %widescreen_button, class_functions.widescreen_state))
%widescreen_button.button_up.connect(class_functions._on_button_released.bind(%widescreen_progress))
%widescreen_button.pressed.connect(class_functions.run_function.bind(%widescreen_button, "widescreen"))
%quick_rewind_button.button_down.connect(class_functions._do_action.bind(%quick_rewind_progress, %quick_rewind_button, class_functions.quick_rewind_state))
%quick_rewind_button.button_up.connect(class_functions._on_button_released.bind(%quick_rewind_progress))
%quick_rewind_button.pressed.connect(class_functions.run_function.bind(%quick_rewind_button, "rewind"))

View file

@ -0,0 +1,65 @@
extends Control
var responses: Array
func _ready():
_connect_signals()
if class_functions.cheevos_token_state == "true":
#%cheevos_label.add_theme_stylebox_override()
%cheevos_label.add_theme_color_override("font_color", Color(0.941, 0.502, 1, 1))
%cheevos_label.text = "ALREADY LOGGED IN"
#%cheevos_connect_button.text = "LOGOUT"
else:
%cheevos_label.text = "NOT LOGGED IN"
func _connect_signals() -> void:
%sound_button.pressed.connect(class_functions.run_function.bind(%sound_button, "sound_effects"))
%update_notification_button.pressed.connect(class_functions.run_function.bind(%update_notification_button, "update_check"))
%volume_effects_slider.drag_ended.connect(class_functions.slider_function.bind(%volume_effects_slider))
%cheevos_connect_button.pressed.connect(cheevos.bind(%cheevos_connect_button))
%cheevos_button.button_down.connect(class_functions._do_action.bind(%cheevos_progress, %cheevos_button, class_functions.cheevos_state))
%cheevos_button.button_up.connect(class_functions._on_button_released.bind(%cheevos_progress))
%cheevos_button.pressed.connect(class_functions.run_function.bind(%cheevos_button, "cheevos"))
%cheevos_hardcore_button.button_down.connect(class_functions._do_action.bind(%cheevos_hardcore_progress, %cheevos_hardcore_button, class_functions.cheevos_hardcore_state))
%cheevos_hardcore_button.button_up.connect(class_functions._on_button_released.bind(%cheevos_hardcore_progress))
%cheevos_hardcore_button.pressed.connect(class_functions.run_function.bind(%cheevos_hardcore_button, "cheevos_hardcore"))
%reset_retrodeck_button.button_down.connect(class_functions._do_action.bind(%reset_retrodeck_progress, %reset_retrodeck_button, "mixed"))
%reset_retrodeck_button.button_up.connect(class_functions._on_button_released.bind(%reset_retrodeck_progress))
%reset_all_emulators_button.button_down.connect(class_functions._do_action.bind(%reset_all_emulators_progress, %reset_all_emulators_button, "mixed"))
%reset_all_emulators_button.button_up.connect(class_functions._on_button_released.bind(%reset_all_emulators_progress))
%system_button.pressed.connect(class_functions._hide_show_containers.bind(%system_button, %system_gridcontainer2))
%cheevos_collapse_button.pressed.connect(class_functions._hide_show_containers.bind(%cheevos_collapse_button, %cheevos_gridcontainer))
%future_button.pressed.connect(class_functions._hide_show_containers.bind(%future_button, %future_gridcontainer))
func _on_request_completed(_result, response_code, _headers, body) -> Array:
var response_text = JSON.parse_string(body.get_string_from_utf8())
var cheevos_token: String = ""
#print("Response Code: ", response_code)
#print("Response Body: ", response_text)
#print ("Response Success: ", response_text.Success)
#print("Response Token: ", response_text.Token)
if response_text.Success:
cheevos_token = response_text.Token
if response_code == 200:
responses = [response_code, response_text.Success, cheevos_token]
return responses
return responses
func cheevos(button: Button):
class_functions.logger("d","Attempting RA connection")
var ra_url = "https://retroachievements.org/dorequest.php?r=login&u="+%cheevos_username.text+"&p="+%cheevos_password.text
button.disabled = true
%cheevos_label.text = "ATTEMPTING LOGIN"
var http_request = HTTPRequest.new()
add_child(http_request)
http_request.request_completed.connect(self._on_request_completed)
http_request.request(ra_url)
responses = await wait_to_complete(http_request)
%cheevos_label.text = "LOGIN SUCCESS = %s" % str(responses[1]).to_upper()
button.disabled = false
# need to create missing fields/keys too ie chhevos token duckstation? Possibly not But do need timestamp
#data_handler.read_change_regex(class_functions.config_folder_path + "retroarch/retroarch.cfg", "cheevos_username", "bob12")
data_handler.read_change_regex(class_functions.config_folder_path + "duckstation/settings.ini", "Username", "monkeyx", false)
func wait_to_complete(http_request: HTTPRequest) -> Array:
await http_request.request_completed
return responses

View file

@ -0,0 +1,125 @@
extends Control
var app_data := AppData.new()
var current_system := Emulator.new()
var press_time: float = 0.0
var is_reset_pressed: bool = false
var reset_result: Dictionary
@export var PRESS_DURATION: float = 3.0
func _ready():
app_data = data_handler.app_data
_connect_signals()
func _process(delta: float) -> void:
if is_reset_pressed:
press_time += delta
%reset_progress.value = press_time / PRESS_DURATION * 100.0
if press_time >= PRESS_DURATION:
_do_complete()
press_time = 0.0
is_reset_pressed = false
%reset_progress.value = 0.0
func _connect_signals() -> void:
#TODO make for loops for each function linked to button function call
# Change to follow hoe TabGlobals Works
%retroarch_button.pressed.connect(standard_buttons.bind(%retroarch_button,%system_gridcontainer, %action_gridcontainer))
%mame_button.pressed.connect(standard_buttons.bind(%mame_button,%system_gridcontainer, %action_gridcontainer))
%ruffle_button.pressed.connect(standard_buttons.bind(%ruffle_button,%system_gridcontainer, %action_gridcontainer))
%melonds_button.pressed.connect(standard_buttons.bind(%melonds_button,%system_gridcontainer, %action_gridcontainer))
%pcsx2_button.pressed.connect(standard_buttons.bind(%pcsx2_button,%system_gridcontainer, %action_gridcontainer))
%duckstation_button.pressed.connect(standard_buttons.bind(%duckstation_button,%system_gridcontainer, %action_gridcontainer))
%ppsspp_button.pressed.connect(standard_buttons.bind(%ppsspp_button,%system_gridcontainer, %action_gridcontainer))
%vita3k_button.pressed.connect(standard_buttons.bind(%vita3k_button,%system_gridcontainer, %action_gridcontainer))
%rpcs3_button.pressed.connect(standard_buttons.bind(%rpcs3_button,%system_gridcontainer, %action_gridcontainer))
%ryujinx_button.pressed.connect(standard_buttons.bind(%ryujinx_button,%system_gridcontainer, %action_gridcontainer))
%dolphin_button.pressed.connect(standard_buttons.bind(%dolphin_button,%system_gridcontainer, %action_gridcontainer))
%primehack_button.pressed.connect(standard_buttons.bind(%primehack_button,%system_gridcontainer, %action_gridcontainer))
%cemu_button.pressed.connect(standard_buttons.bind(%cemu_button,%system_gridcontainer, %action_gridcontainer))
%xemu_button.pressed.connect(standard_buttons.bind(%xemu_button,%system_gridcontainer, %action_gridcontainer))
%esde_button.pressed.connect(standard_buttons.bind(%esde_button,%system_gridcontainer, %action_gridcontainer))
%help_button.pressed.connect(_do_action.bind(%help_button))
#%launch_button.pressed.connect(_do_action.bind(%launch_button))
%launch_button.pressed.connect(_do_action.bind(%launch_button))
%reset_button.button_down.connect(_do_action.bind(%reset_button))
%reset_button.button_up.connect(_on_Button_released.bind(%reset_progress))
%rpcs3_firmware_button.pressed.connect(_do_action.bind(%rpcs3_firmware_button))
%vita3k_firmware_button.pressed.connect(_do_action.bind(%vita3k_firmware_button))
%retroarch_quick_resume_button.pressed.connect(class_functions.run_function.bind(%retroarch_quick_resume_button, "quick_resume"))
func standard_buttons(button: Button, buttons_gridcontainer: GridContainer, hidden_gridcontainer: GridContainer) -> void:
current_system = app_data.emulators[button.text.to_lower()]
%reset_button.text="RESET"
match button.name:
"vita3k_button":
%vita3k_firmware_button.visible = true
"rpcs3_button":
%rpcs3_firmware_button.visible = true
"retroarch_button":
%retroarch_quick_resume_button.visible = true
_:
%vita3k_firmware_button.visible = false
%rpcs3_firmware_button.visible = false
%retroarch_quick_resume_button.visible = false
hidden_gridcontainer.visible = true
if button.toggle_mode == false:
for i in range(buttons_gridcontainer.get_child_count()):
var child = buttons_gridcontainer.get_child(i)
if child is Button and child != button:
child.visible=false
elif button.toggle_mode == true and hidden_gridcontainer.visible == true:
hidden_gridcontainer.visible = false
for i in range(buttons_gridcontainer.get_child_count()):
var child = buttons_gridcontainer.get_child(i)
if child is Button:
child.visible=true
child.toggle_mode = false
if hidden_gridcontainer.visible == true:
button.toggle_mode = true
func _on_Button_released(progress: ProgressBar) -> void:
is_reset_pressed = false
%reset_progress.visible = false
press_time = 0.0
progress.value = 0.0
func _do_action(button: Button) -> void:
var original_txt = button.text
match [button.name, current_system.name]:
["help_button", current_system.name]:
if class_functions.desktop_mode != "gamescope":
print ("URL %s" %current_system.url)
class_functions.logger("i", "Launching " + current_system.name + " Help")
class_functions.launch_help(current_system.url)
else:
button.text = "Help only works in Desktop Mode"
await class_functions.wait(3.0)
button.text = original_txt
["launch_button", current_system.name]:
class_functions.logger("i", "Launching " + current_system.name)
var launch = class_functions.execute_command(current_system.launch,[], false)
class_functions.logger("d", "Exit Code: " + str(launch["exit_code"]))
["reset_button", current_system.name]:
is_reset_pressed = true
%reset_progress.visible = true
["rpcs3_firmware_button", current_system.name]:
class_functions.logger("i", "Firmware install " + current_system.name)
var launch = class_functions.execute_command(class_functions.wrapper_command,["update_rpcs3_firmware"], false)
class_functions.logger("d", "Exit Code: " + str(launch["exit_code"]))
["vita3k_firmware_button", current_system.name]:
class_functions.logger("i", "Firmware install " + current_system.name)
var launch = class_functions.execute_command(class_functions.wrapper_command,["update_vita3k_firmware"], false)
class_functions.logger("d", "Exit Code: " + str(launch["exit_code"]))
func _do_complete() ->void:
if is_reset_pressed:
var tmp_txt = %reset_button.text
%reset_button.text = "RESETTING-NOW"
class_functions.logger("i", "Resetting " + current_system.name)
var parameters = ["prepare_component","reset",current_system.name]
reset_result = await class_functions.run_thread_command(class_functions.wrapper_command,parameters, false)
class_functions.logger("d", "Exit Code: " + str(reset_result["exit_code"]))
%reset_button.text = "RESET COMPLETED"
await class_functions.wait(3.0)
%reset_button.text = tmp_txt

View file

@ -0,0 +1,51 @@
extends Control
@onready var http_request: HTTPRequest = HTTPRequest.new()
func _ready():
add_child(http_request)
http_request.request_completed.connect(_on_request_completed)
_connect_signals()
#%backup_user_button.text += " - " + class_functions.rdhome + "/backup"
func _connect_signals() -> void:
%check_conn_button.pressed.connect(check_internet_connection)
%backup_user_button.pressed.connect(run_function.bind(%backup_user_button, "Start User Backup"))
func run_function(button: Button, message: String) -> void:
class_functions.logger("d",message)
match button.name:
"backup_user_button":
_run_backup(button)
func _run_backup(button: Button) -> void:
var original_txt = button.text
%progress_bar_backup.visible = true
button.text = "Backup Running"
var parameters = ["backup_retrodeck_userdata"]
var run_result = await class_functions.run_thread_command(class_functions.wrapper_command, parameters, true)
if run_result["exit_code"] == 0:
button.text = "Backup Complete - " + class_functions.rdhome + "/backup"
class_functions.logger("d","User Backup Completed")
await class_functions.wait(3.0)
button.text = original_txt
%progress_bar_backup.visible = false
else:
button.text = "Backup Failed"
class_functions.logger("e","User Backup Failed. " + run_result["exit_code"])
%progress_bar_backup.visible = false
func check_internet_connection():
class_functions.logger("i","Check Internet Connection")
%check_conn_button.text = "CHECK CONNECTION"
http_request.request("https://retrodeck.net/")
func _on_request_completed(_result, response_code, _headers, _body):
if response_code == 200:
class_functions.logger("i","Internet Connection Succesful")
%check_conn_button.button_pressed = true
%check_conn_button.text += " - CONNECTED"
else:
class_functions.logger("d","Internet Connection Failed")
%check_conn_button.button_pressed = false
%check_conn_button.text += " - NOT CONNECTED: " + str(response_code)

View file

@ -1,63 +1,145 @@
class_name ClassFunctions
extends Control
var log_text = "gdc_"
var log_result: Dictionary
var log_parameters: Array
var wrapper_command: String = "/app/tools/retrodeck_function_wrapper.sh"
const globals_sh_file_path: String = "/app/libexec/global.sh"
const wrapper_command: String = "/app/tools/retrodeck_function_wrapper.sh"
const config_file_path = "/var/config/retrodeck/retrodeck.cfg"
const json_file_path = "/var/config/retrodeck/retrodeck.json"
var config_folder_path = "/var/config/"
const esde_file_path = "/var/config/ES-DE/settings/es_settings.xml"
var desktop_mode: String = OS.get_environment("XDG_CURRENT_DESKTOP")
var rd_conf: String
var lockfile: String
var rdhome: String
var roms_folder: String
var saves_folder: String
var states_folder: String
var bios_folder: String
var rd_log: String
var rd_log_folder: String
var rd_version: String
var gc_version: String
var sound_effects: bool
var volume_effects: int
var title: String
var quick_resume_status: bool
var update_check: bool
var abxy_state: String
var ask_to_exit_state: String
var border_state: String
var widescreen_state: String
var quick_rewind_state: String
var cheevos_state: String
var cheevos_hardcore_state: String
var cheevos_token_state: String
var font_select: int
var font_tab_size: int = 35
var font_size: int = 20
var locale: String
var button_list: Array = ["button_swap_button", "ask_to_exit_button", "border_button", "widescreen_button", "quick_rewind_button", "reset_retrodeck_button", "reset_all_emulators_button", "cheevos_button", "cheevos_hardcore_button"]
signal update_global_signal
var rekku_state: bool = false
var press_time: float = 0.0
var is_state_pressed: bool = false
var PRESS_DURATION: float = 3.0
var current_button: Button = null
var current_progress: ProgressBar = null
var current_state: String = ""
func read_cfg() -> String:
var title: String
var config_file_path = "/var/config/retrodeck/retrodeck.cfg"
var json_file_path = "/var/config/retrodeck/retrodeck.json"
func _ready():
read_values_states()
func read_values_states() -> void:
var config = data_handler.parse_config_to_json(config_file_path)
data_handler.config_save_json(config, json_file_path)
rd_log_folder = config["paths"]["logs_folder"]
rd_log = rd_log_folder + "/retrodeck.log"
#rd_log = "/var/config/retrodeck/logs/retrodeck.log"
log_parameters = ["log", "i", log_text, rd_log]
rdhome = config["paths"]["rdhome"]
roms_folder = config["paths"]["roms_folder"]
saves_folder = config["paths"]["saves_folder"]
states_folder = config["paths"]["states_folder"]
bios_folder = config["paths"]["bios_folder"]
rd_version = config["version"]
rd_conf = extract_text(globals_sh_file_path, "rd_conf")
lockfile = extract_text(globals_sh_file_path, "lockfile")
locale = extract_text(esde_file_path, "esde")
gc_version = ProjectSettings.get_setting("application/config/version")
title = "\n " + rd_version + "\nConfigurator\n " + gc_version
print ("Make logging a function\nAlso add d,i,e,w: ", rd_log)
return title
quick_resume_status = config["quick_resume"]["retroarch"]
update_check = config["options"]["update_check"]
abxy_state = multi_state("abxy_button_swap", abxy_state)
ask_to_exit_state = multi_state("ask_to_exit", ask_to_exit_state)
border_state = multi_state("borders", border_state)
widescreen_state = multi_state("widescreen", widescreen_state)
quick_rewind_state = multi_state("rewind", quick_rewind_state)
sound_effects = config["options"]["sound_effects"]
volume_effects = int(config["options"]["volume_effects"])
font_select = int(config["options"]["font"])
cheevos_token_state = str(config["options"]["cheevos_login"])
cheevos_state = multi_state("cheevos", cheevos_state)
cheevos_hardcore_state = multi_state("cheevos_hardcore", cheevos_hardcore_state)
func logger() -> void:
pass
func multi_state(section: String, state: String) -> String:
var config_section:Dictionary = data_handler.get_elements_in_section(config_file_path, section)
var true_count: int = 0
var false_count: int = 0
for value in config_section.values():
if value == "true":
true_count += 1
else:
false_count += 1
if true_count == config_section.size():
state = "true"
elif false_count == config_section.size():
state = "false"
else:
state = "mixed"
return state
func logger(log_type: String, log_text: String) -> void:
# Type of log messages:
# log d - debug message: maybe in the future we can decide to hide them in main builds or if an option is toggled
# log i - normal informational message
# log w - waring: something is not expected but it's not a big deal
# log e - error: something broke
var log_header_text = "gdc_"
log_header_text+=log_text
log_parameters = ["log", log_type, log_header_text]
log_result = await run_thread_command(wrapper_command,log_parameters, false)
#log_result = await run_thread_command("find",["$HOME", "-name", "*.xml","-print"], false)
#print (log_result["exit_code"])
#print (log_result["output"])
func array_to_string(arr: Array) -> String:
var text: String
for line in arr:
#text += line + "\n"
text = line.strip_edges() + "\n"
return text
func wait (seconds: float) -> void:
await get_tree().create_timer(seconds).timeout
# TODO This should be looked at again when GoDot 4.3 ships as has new OS.execute_with_pipe
func execute_command(command: String, parameters: Array, console: bool) -> Dictionary:
var result = {}
var output = []
var exit_code = OS.execute(command, parameters, output, console) ## add if exit == 0 etc
result["output"] = array_to_string(output)
result["output"] = class_functions.array_to_string(output)
result["exit_code"] = exit_code
#print (array_to_string(output))
#print (result["exit_code"])
return result
func run_command_in_thread(command: String, paramaters: Array, _console: bool) -> Dictionary:
var thread = Thread.new()
thread.start(execute_command.bind(command,paramaters,false))
thread.start(execute_command.bind(command,paramaters,true))
while thread.is_alive():
await get_tree().process_frame
var result = thread.wait_to_finish()
thread = null
return result
return thread.wait_to_finish()
func _threaded_command_execution(command: String, parameters: Array, console: bool) -> Dictionary:
var result = execute_command(command, parameters, console)
return result
func run_thread_command(command: String, parameters: Array, console: bool) -> Dictionary:
log_result = await run_command_in_thread(command, parameters, console)
return log_result
func process_url_image(body) -> Texture:
var image = Image.new()
@ -66,6 +148,10 @@ func process_url_image(body) -> Texture:
return texture
func launch_help(url: String) -> void:
#OS.unset_environment("LD_PRELOAD")
#OS.set_environment("XDG_CURRENT_DESKTOP", "KDE")
#var launch = class_functions.execute_command("xdg-open",[url], false)
#var launch = class_functions.execute_command("org.mozilla.firefox",[url], false)
OS.shell_open(url)
func import_csv_data(file_path: String) -> Dictionary:
@ -102,11 +188,11 @@ func import_text_file(file_path: String) -> String:
var content: String = ""
var file = FileAccess.open(file_path, FileAccess.READ)
if file == null:
print("Failed to open file")
logger("e","Failed to open file %s" % file_path)
return content
while not file.eof_reached():
content += file.get_line() + "\n"
file.close
#file.close
return content
func map_locale_id(current_locale: String) -> int:
@ -127,3 +213,250 @@ func map_locale_id(current_locale: String) -> int:
"cn":
int_locale = 6
return int_locale
func environment_data() -> void:
var env_result = execute_command("printenv",[], true)
var file = FileAccess.open(OS.get_environment("HOME") + "/sdenv.txt",FileAccess.WRITE)
if file != null:
file.store_string(env_result["output"])
file.close()
func display_json_data() -> void:
var app_data := AppData.new()
app_data = data_handler.app_data
#data_handler.add_emulator()
#data_handler.modify_emulator_test()
if app_data:
#var website_data: Link = app_data.about_links["rd_web"]
#print (website_data.name,"-",website_data.url,"-",website_data.description,"-",website_data.url)
##print (app_data.about_links["rd_web"]["name"])
#var core_data: Core = app_data.cores["gambatte_libetro"]
#print (core_data.name)
#for property: CoreProperty in core_data.properties:
#print("Cheevos: ", property.cheevos)
#print("Cheevos Hardcore: ", property.cheevos_hardcore)
#print("Quick Resume: ", property.quick_resume)
#print("Rewind: ", property.rewind)
#print("Borders: ", property.borders)
#print("Widescreen: ", property.widescreen)
#print("ABXY_button:", property.abxy_button)
for key in app_data.emulators.keys():
var emulator = app_data.emulators[key]
# Display the properties of each emulator
print("System Name: ", emulator.name)
#print("Description: ", emulator.description)
#print("System: ", emulator.systen)
#print("Help URL: ", emulator.url)
#print("Properties:")
for property: EmulatorProperty in emulator.properties:
#print("Cheevos: ", property.cheevos)
#print("Borders: ", property.borders)
print("ABXY_button:", property.abxy_button)
#print("multi_user_config_dir: ", property.multi_user_config_dir)
for key in app_data.cores.keys():
var core = app_data.cores[key]
print("Core Name: ", core.name)
#print("Description: ", core.description)
#print("Properties:")
for property: CoreProperty in core.properties:
#print("Cheevos: ", property.cheevos)
#print("Cheevos Hardcore: ", property.cheevos_hardcore)
#print("Quick Resume: ", property.quick_resume)
#print("Rewind: ", property.rewind)
#print("Borders: ", property.borders)
#print("Widescreen: ", property.widescreen)
print("ABXY_button:", property.abxy_button)
else:
print ("No emulators")
func slider_function(value: float, slide: HSlider) -> void:
volume_effects = int(slide.value)
data_handler.change_cfg_value(config_file_path, "volume_effects", "options", str(slide.value))
func run_function(button: Button, preset: String) -> void:
if button.button_pressed:
update_global(button, preset, true)
else:
update_global(button, preset, false)
func update_global(button: Button, preset: String, state: bool) -> void:
#TODO pass state as an object in future version
var result: Array
result.append("build_preset_config")
var config_section:Dictionary = data_handler.get_elements_in_section(config_file_path, preset)
match button.name:
"quick_resume_button", "retroarch_quick_resume_button":
quick_resume_status = state
result.append_array(data_handler.change_cfg_value(config_file_path, "retroarch", preset, str(state)))
change_global(result, button, str(quick_resume_status))
"update_notification_button":
update_check = state
result.append_array(data_handler.change_cfg_value(config_file_path, preset, "options", str(state)))
change_global(result, button, str(result))
"sound_button":
sound_effects = state
result.append_array(data_handler.change_cfg_value(config_file_path, preset, "options", str(state)))
logger("i", "Enabled: %s" % (button.name))
update_global_signal.emit([button.name])
"cheevos_connect_button":
cheevos_token_state = str(state)
result.append_array(data_handler.change_cfg_value(config_file_path, preset, "options", str(state)))
logger("i", "Enabled: %s" % (button.name))
update_global_signal.emit([button.name])
"button_swap_button":
if abxy_state != "mixed":
abxy_state = str(state)
result.append_array(data_handler.change_all_cfg_values(config_file_path, config_section, preset, str(state)))
change_global(result, button, abxy_state)
"ask_to_exit_button":
if ask_to_exit_state != "mixed":
ask_to_exit_state = str(state)
result.append_array(data_handler.change_all_cfg_values(config_file_path, config_section, preset, str(state)))
change_global(result, button, ask_to_exit_state)
"border_button":
if border_state != "mixed":
border_state = str(state)
result.append_array(data_handler.change_all_cfg_values(config_file_path, config_section, preset, str(state)))
change_global(result, button, border_state)
if widescreen_state == "true" or widescreen_state == "mixed":
config_section = data_handler.get_elements_in_section(config_file_path, "widescreen")
widescreen_state = "false"
result.append_array(data_handler.change_all_cfg_values(config_file_path, config_section, "widescreen", widescreen_state))
change_global(result, button, widescreen_state)
"widescreen_button":
if widescreen_state != "mixed":
widescreen_state = str(state)
result.append_array(data_handler.change_all_cfg_values(config_file_path, config_section, preset, str(state)))
change_global(result, button, widescreen_state)
if border_state == "true" or border_state == "mixed":
config_section = data_handler.get_elements_in_section(config_file_path, "borders")
border_state = "false"
result.append_array(data_handler.change_all_cfg_values(config_file_path, config_section, "borders", border_state))
change_global(result, button, border_state)
"quick_rewind_button":
if quick_rewind_state != "mixed":
quick_rewind_state = str(state)
result.append_array(data_handler.change_all_cfg_values(config_file_path, config_section, preset, str(state)))
change_global(result, button, quick_rewind_state)
"cheevos_button":
if cheevos_state != "mixed":
cheevos_state = str(state)
result.append_array(data_handler.change_all_cfg_values(config_file_path, config_section, preset, str(state)))
change_global(result, button, cheevos_state)
if cheevos_state == "false":
cheevos_hardcore_state = "false"
result.append_array(data_handler.change_all_cfg_values(config_file_path, config_section, "cheevos_hardcore", class_functions.cheevos_hardcore_state))
change_global(result, button, cheevos_hardcore_state)
"cheevos_hardcore_button":
if cheevos_hardcore_state != "mixed":
cheevos_hardcore_state = str(state)
result.append_array(data_handler.change_all_cfg_values(config_file_path, config_section, preset, str(state)))
change_global(result, button, cheevos_hardcore_state)
func change_global(parameters: Array, button: Button, state: String) -> void:
#print (str(parameters))
match parameters[2]:
"abxy_button_swap", "ask_to_exit", "borders", "widescreen", "rewind", "cheevos", "cheevos_hardcore":
for system in parameters[1].keys():
var command_parameter: Array = [parameters[0],system, parameters[2]]
logger("d", "Change Global Multi: %s " % str(command_parameter))
var result: Dictionary = await run_thread_command(wrapper_command, command_parameter, false)
#var result = OS.execute_with_pipe(wrapper_command, command_parameter)
logger("d", "Exit code: %s" % result["exit_code"])
_:
logger("d", "Change Global Single: %s" % str(parameters))
var result: Dictionary = await run_thread_command(wrapper_command, parameters, false)
#var result = OS.execute_with_pipe(wrapper_command, parameter)
#var result = OS.create_process(wrapper_command, cparameter)
logger("d", "Exit code: %s" % result["exit_code"])
parameters.append(button)
parameters.append(state)
update_global_signal.emit(parameters)
func extract_text(file_path: String, extract: String) -> String:
var file = FileAccess.open(file_path, FileAccess.ModeFlags.READ)
var pattern: String
if file:
var regex = RegEx.new()
if extract != "esde":
pattern = extract + '="([^"]+)"'
else:
pattern = '<string name="ApplicationLanguage" value="([^"]+)" />'
regex.compile(pattern)
while not file.eof_reached():
var line: String = file.get_line().strip_edges()
var result: RegExMatch = regex.search(line)
if result:
return result.get_string(1)
file.close()
else:
logger("e", "Could not open file: %s" % file_path)
return ""
func _on_button_released(progress: ProgressBar) -> void:
is_state_pressed = false
progress.visible = false
press_time = 0.0
progress.value = 0.0
current_button = null
current_progress = null
current_state == null
func _do_action(progress: ProgressBar, button: Button, state: String) -> void:
match [class_functions.button_list]:
[class_functions.button_list]:
current_state = state
current_button = button
current_progress = progress
current_progress.visible = true
is_state_pressed = true
func _do_complete(button: Button) ->void:
#TODO use object for state
if is_state_pressed and button == current_button:
match button.name:
"button_swap_button":
class_functions.abxy_state = "false"
"ask_to_exit_button":
class_functions.ask_to_exit_state = "false"
"border_button":
class_functions.border_state = "false"
"widescreen_button":
class_functions.widescreen_state = "false"
"quick_rewind_button":
class_functions.quick_rewind_state = "false"
"cheevos_button":
class_functions.cheevos_state = "false"
"cheevos_hardcore_button":
class_functions.cheevos_hardcore_state = "false"
"reset_retrodeck_button":
var dir = DirAccess.open(class_functions.rd_conf.get_base_dir())
if dir is DirAccess:
dir.rename(class_functions.rd_conf, class_functions.rd_conf.get_base_dir() + "/retrodeck.bak")
dir.remove(class_functions.lockfile)
class_functions.change_global(["prepare_component", "reset", "retrodeck"], button, "")
button.text = "RESETTING-NOW"
await class_functions.wait(2.0)
button.text = "CONFIGURATOR WILL NOW CLOSE"
await class_functions.wait(1.0)
get_tree().quit()
"reset_all_emulators_button":
var tmp_txt = button.text
button.text = "RESETTING-NOW"
class_functions.change_global(["prepare_component", "reset", "all"], button, "")
await class_functions.wait(2.0)
button.text = "RESET COMPLETED"
await class_functions.wait(3.0)
button.text = tmp_txt
button.toggle_mode = true
func _hide_show_containers(button: Button, grid_container: GridContainer) -> void:
match button.name:
"decorations_button", "systems_button", "system_button", "cheevos_collapse_button", "future_button":
grid_container.visible = true
if button.toggle_mode:
button.toggle_mode=false
grid_container.visible = false
else:
button.toggle_mode=true

View file

@ -1,6 +1,6 @@
extends PanelContainer
func _process(delta):
func _process(_delta):
# TODO hack. Use state machine?
if %action_gridcontainer.visible == true:
if Input.is_action_pressed("back_button"):

View file

@ -61,6 +61,7 @@ func load_base_data() -> AppData:
if core_data.has("properties"):
for property_data in core_data["properties"]:
#print (core.name,"----",property_data)
# inherit from RetroArch
var property = CoreProperty.new()
property.cheevos = true
property.cheevos_hardcore = true
@ -82,9 +83,9 @@ func load_base_data() -> AppData:
app_dict.cores = cores
return app_dict
else:
print("Error parsing JSON")
class_functions.logger("d","Error parsing JSON ")
else:
print("Error opening file")
class_functions.logger("d","Error opening file: " + file)
get_tree().quit()
return null
@ -157,7 +158,6 @@ func save_base_data(app_dict: AppData):
file = FileAccess.open(data_file_path, FileAccess.WRITE)
file.store_string(json_text)
file.close()
print("Data appended successfully")
# Function to modify an existing link
func modify_link(key: String, new_name: String, new_url: String, new_description: String):
@ -231,27 +231,22 @@ func parse_config_to_json(file_path: String) -> Dictionary:
var current_section = ""
var file = FileAccess.open(file_path, FileAccess.READ)
if file == null:
print("Failed to open file")
class_functions.logger("e","Failed to open file: " + file_path)
return config
while not file.eof_reached():
var line = file.get_line().strip_edges()
if line.begins_with("[") and line.ends_with("]"):
# Start a new section
current_section = line.substr(1, line.length() - 2)
config[current_section] = {}
elif line != "" and not line.begins_with("#"):
# Add key-value pair to the current section
var parts = line.split("=")
if parts.size() == 2:
var key = parts[0].strip_edges()
var value = parts[1].strip_edges()
# Convert value to proper type
if value == "true":
value = true
elif value == "false":
value = false
if key == "version":
config[key] = value
else:
@ -271,4 +266,126 @@ func config_save_json(config: Dictionary, json_file_path: String) -> void:
file.store_string(json_string)
file.close()
else:
print("Failed to open JSON file for writing")
class_functions.logger("e", "File not found: %s" % json_file_path)
func read_cfg_file(file_path: String) -> Array:
var lines: Array = []
var file: FileAccess = FileAccess.open(file_path, FileAccess.ModeFlags.READ)
if file:
while not file.eof_reached():
var line: String = file.get_line()
lines.append(line)
file.close()
else:
class_functions.logger("e", "File not found: %s" % file_path)
return lines
func write_cfg_file(file_path: String, lines: Array, changes: Dictionary) -> void:
var file: FileAccess = FileAccess.open(file_path, FileAccess.ModeFlags.WRITE)
var current_section: String = ""
var line_count: int = lines.size()
for i in line_count:
var line: String = lines[i]
var trimmed_line: String = line.strip_edges()
if trimmed_line.begins_with("[") and trimmed_line.ends_with("]"):
current_section = trimmed_line.trim_prefix("[").trim_suffix("]")# trimmed_line.trim_prefix("["].trim_suffix("]")
file.store_line(line)
elif "=" in trimmed_line and current_section in changes:
var parts: Array = trimmed_line.split("=", false)
if parts.size() == 2:
var key: String = parts[0].strip_edges()
var original_value: String = parts[1].strip_edges()
if key in changes[current_section]:
var new_value: String = changes[current_section][key]
if new_value != original_value:
file.store_line("%s=%s" % [key, new_value])
class_functions.logger("i", "Changed %s in section [%s] from %s to %s" % [key, current_section, original_value, new_value])
else:
file.store_line(line)
else:
file.store_line(line)
else:
file.store_line(line)
else:
file.store_line(line)
if i == line_count - 2:
break
file.close()
func change_cfg_value(file_path: String, system: String, section: String, new_value: String) -> Array:
var lines: Array = read_cfg_file(file_path)
var parameters: Array =[system, section]
var changes: Dictionary = {}
changes[section] = {system: new_value}
class_functions.logger("i", "Change: System: %s Section %s New Value: %s" % [system, section, new_value])
write_cfg_file(file_path, lines, changes)
return parameters
func change_all_cfg_values(file_path: String, systems: Dictionary, section: String, new_value: String) -> Array:
var lines: Array = read_cfg_file(file_path)
var parameters: Array =[systems, section]
var changes: Dictionary = {}
var current_section: String
for line in lines:
var trimmed_line: String = line.strip_edges()
if trimmed_line.begins_with("[") and trimmed_line.ends_with("]"):
current_section = trimmed_line.trim_prefix("[").trim_suffix("]")
if current_section == section:
changes[current_section] = {}
elif "=" in trimmed_line and current_section == section:
var parts: Array = trimmed_line.split("=", false)
if parts.size() >= 2:
var key: String = parts[0].strip_edges()
changes[section][key] = new_value
class_functions.logger("i", "Change: Systems: %s Section %s New Value: %s" % [systems, section, new_value])
write_cfg_file(file_path, lines, changes)
return parameters
func get_elements_in_section(file_path: String, section: String) -> Dictionary:
var lines: Array = read_cfg_file(file_path)
var elements: Dictionary = {}
var current_section: String = ""
for line in lines:
var trimmed_line: String = line.strip_edges()
if trimmed_line.begins_with("[") and trimmed_line.ends_with("]"):
current_section = trimmed_line.trim_prefix("[").trim_suffix("]")
elif "=" in trimmed_line and current_section == section:
var parts: Array = trimmed_line.split("=", false)
if parts.size() >= 2:
var key: String = parts[0].strip_edges()
var value: String = parts[1].strip_edges()
elements[key] = value
return elements
func read_change_regex(file_path: String, key: String, new_value: String, use_quotes: bool = true) -> String:
var file := FileAccess.open(file_path, FileAccess.READ_WRITE)
if file == null:
print("Error: Could not open the file - %s" % file_path)
return ""
var content := file.get_as_text()
file.close()
var pattern := ""
if use_quotes:
pattern = '%s\\s*=\\s*"(.*?)"' % key
else:
pattern = '%s\\s*=\\s*(.*)' % key # For keys without quotes
var regex := RegEx.new()
regex.compile(pattern)
var match := regex.search(content)
if match == null:
print("Key %s not found for match - %s" % [key, match])
return ""
var current_value := match.get_string(1)
if new_value == current_value:
print (current_value)
return current_value
var updated_content := ""
if use_quotes:
updated_content = regex.sub(content, '%s = "%s"' % [key, new_value])
else:
updated_content = regex.sub(content, '%s = %s' % [key, new_value])
file = FileAccess.open(file_path, FileAccess.WRITE)
file.store_string(updated_content)
file.close()
print("File updated successfully")
return new_value

View file

@ -0,0 +1,21 @@
extends Label
@onready var helper_text_node = self
func _ready():
# Connect the signal that gets fired on every focus change
get_viewport().connect("gui_focus_changed", _on_focus_changed)
func _on_focus_changed(selected_element:Control) -> void:
if selected_element != null and selected_element.has_meta("rekku") and class_functions.rekku_state == true:
#helper_text_node.text = selected_element.get_meta("rekku")
%pop_rtl.visible = true
%pop_rtl.text = selected_element.get_meta("rekku")
elif selected_element != null and selected_element.has_meta("description") and class_functions.rekku_state == false:
%pop_rtl.visible = true
var text_newline : String = selected_element.get_meta("description") as String
text_newline = text_newline.replace("\\n", "\n")
%pop_rtl.text = text_newline
#func replace_newline(text: String) -> String:
#return text.replace("\n", "\n")

View file

@ -0,0 +1,246 @@
extends Control
@onready var bios_type:int
var custom_theme: Theme
var log_option: OptionButton
var tab_container: TabContainer
var anim_logo: AnimatedSprite2D
var a_button_texture: Texture2D = load("res://assets/icons/kenney_input-prompts-pixel-16/Tiles/tile_0042.png")
var b_button_texture: Texture2D = load("res://assets/icons/kenney_input-prompts-pixel-16/Tiles/tile_0043.png")
var l1_button_texture: Texture2D = load("res://assets/icons/kenney_input-prompts-pixel-16/Tiles/tile_0797.png")
var r1_button_texture: Texture2D = load("res://assets/icons/kenney_input-prompts-pixel-16/Tiles/tile_0798.png")
var style_box_original: StyleBox = preload("res://assets/themes/default_theme.tres::StyleBoxFlat_0ahfc")
var font_size: int = 20
func _ready():
_get_nodes()
_connect_signals()
_play_main_animations()
_set_up_globals([])
custom_theme = get_tree().current_scene.custom_theme
$".".theme = custom_theme
if class_functions.locale == "automatic":
%locale_option.selected = class_functions.map_locale_id(OS.get_locale_language())
%rd_title.text += class_functions.title
class_functions.logger("i","Started Godot configurator")
#class_functions.display_json_data()
# set current startup tab to match IDE
tab_container.current_tab = 0
#add_child(class_functions) # Needed for threaded results Not need autoload?
var children = findElements(self, "Control")
for n: Control in children: #iterate the children
if (n.focus_mode == FOCUS_ALL):
n.mouse_entered.connect(_on_control_mouse_entered.bind(n)) #grab focus on mouse hover
#if (n.is_class("BaseButton") and n.disabled == true): #if button-like control and disabled
#n.self_modulate.a = 0.5 #make it half transparent
#combine_tkeys()
change_font(class_functions.font_select)
func _input(event):
if Input.is_action_pressed("quit1") and Input.is_action_pressed("quit2"):
_exit()
if Input.is_action_pressed("next_tab"):
%r1_button.texture_normal = %r1_button.texture_pressed
elif Input.is_action_pressed("previous_tab"):
%l1_button.texture_normal = %l1_button.texture_pressed
elif Input.is_action_pressed("back_button"):
%b_button.texture_normal = %b_button.texture_pressed
elif Input.is_action_pressed("action_button"):
%a_button.texture_normal = %a_button.texture_pressed
else:
%r1_button.texture_normal = r1_button_texture
%l1_button.texture_normal = l1_button_texture
%a_button.texture_normal = a_button_texture
%b_button.texture_normal = b_button_texture
if event.is_action_pressed("quit"):
_exit()
func _exit():
class_functions.logger("i","Exited Godot configurator")
get_tree().root.propagate_notification(NOTIFICATION_WM_CLOSE_REQUEST)
get_tree().quit()
func _get_nodes() -> void:
tab_container = get_node("%TabContainer")
anim_logo = get_node("%logo_animated")
log_option = get_node("%logs_button")
func _connect_signals() -> void:
#signal_theme_changed.connect(_conf_theme)
%font_optionbutton.item_selected.connect(change_font)
log_option.item_selected.connect(_load_log)
%borders_button.pressed.connect(_hide_show_buttons.bind(%borders_button,%borders_gridcontainer,%decorations_gridcontainer))
%button_layout.pressed.connect(_hide_show_buttons.bind(%button_layout,%borders_gridcontainer,%decorations_gridcontainer))
%decorations_save.pressed.connect(_hide_show_buttons.bind(%decorations_save,%decorations_save.get_parent(),null))
%decorations_button.pressed.connect(class_functions._hide_show_containers.bind(%decorations_button, %decorations_gridcontainer))
%systems_button.pressed.connect(class_functions._hide_show_containers.bind(%systems_button, %systems_gridcontainer))
class_functions.update_global_signal.connect(_set_up_globals)
func _load_log(index: int) -> void:
var log_content:String
match index:
1:
class_functions.logger("i","Loading RetroDeck log")
log_content = class_functions.import_text_file(class_functions.rd_log_folder +"/retrodeck.log")
load_popup("RetroDeck Log", "res://components/popup.tscn", log_content)
2:
class_functions.logger("i","Loading ES-DE log")
log_content = class_functions.import_text_file(class_functions.rd_log_folder +"/ES-DE/es_log.txt")
load_popup("ES-DE Log", "res://components/popup.tscn",log_content)
3:
class_functions.logger("i","Loading RetroArch log")
log_content = class_functions.import_text_file(class_functions.rd_log_folder +"/retroarch/logs/log.txt")
load_popup("Retroarch Log", "res://components/popup.tscn",log_content)
func _play_main_animations() -> void:
anim_logo.play()
# TODO Pass GridContainer(might need 2?) as above
# TODO load existing settings or default to enable all
func _hide_show_buttons(button: Button, buttons_gridcontainer: GridContainer, hidden_gridcontainer: GridContainer) -> void:
match button.name:
"borders_button", "button_layout":
buttons_gridcontainer.visible = true
if button.toggle_mode == false:
for i in range(buttons_gridcontainer.get_child_count()):
var child = buttons_gridcontainer.get_child(i)
child.button_pressed=true
for i in range(hidden_gridcontainer.get_child_count()):
var child = hidden_gridcontainer.get_child(i)
if child is Button and child != button:
child.visible=false
elif button.toggle_mode == true and %borders_gridcontainer.visible == true:
buttons_gridcontainer.visible = false
#button.toggle_mode = false
for i in range(hidden_gridcontainer.get_child_count()):
var child = hidden_gridcontainer.get_child(i)
if child is Button:
child.visible=true
child.toggle_mode = false
button.toggle_mode = true
func findElements(node: Node, className: String, result: Array = []) -> Array:
if node.is_class(className):
result.push_back(node)
for child in node.get_children():
result = findElements(child, className, result)
return result
func _on_control_mouse_entered(control: Node):
control.grab_focus()
func load_popup(title:String, content_path:String, display_text: String):
var popup = load("res://components/popup.tscn").instantiate() as Control
popup.set_title(title)
popup.set_content(content_path)
popup.set_display_text(display_text)
$Background.add_child(popup)
func _on_bios_button_pressed():
_play_main_animations()
bios_type = 1
class_functions.logger("i","Bios Check")
load_popup("BIOS File Check", "res://components/bios_check/bios_popup_content.tscn","")
bios_type = 0
func _on_bios_button_expert_pressed():
_play_main_animations()
bios_type = 2
class_functions.logger("i","Advanced Bios Check")
load_popup("BIOS File Check", "res://components/bios_check/bios_popup_content.tscn","")
bios_type = 0
func _on_exit_button_pressed():
_play_main_animations()
_exit()
_exit()
#func _on_locale_selected(index):
#match index:
#0:
#TranslationServer.set_locale("en")
#_:
#TranslationServer.set_locale("en")
#combine_tkeys()
#func combine_tkeys(): #More as a test
#pass
#%cheats.text = tr("TK_CHEATS") + " " + tr("TK_SOON") # switched to access as a unique name as easier to refactor
#$Background/MarginContainer/TabContainer/TK_SYSTEM/ScrollContainer/VBoxContainer/HBoxContainer/GridContainer/cheats.text = tr("TK_CHEATS") + " " + tr("TK_SOON")
#%tate_mode.text = tr("TK_TATE") + " " + tr("TK_SOON")
#%hotkey_sound.text = tr("TK_HOTKEYSOUND") + " " + tr("TK_SOON")
#$Background/MarginContainer/TabContainer/TK_NETWORK/ScrollContainer/VBoxContainer/cheevos_container/cheevos_advanced_container/cheevos_hardcore.text = tr("TK_CHEEVOSHARDCORE") + " " + tr("TK_SOON")
#$Background/MarginContainer/TabContainer/TK_NETWORK/ScrollContainer/VBoxContainer/data_mng_container/saves_sync.text = tr("TK_SAVESSYNC") + " " + tr("TK_SOON")
#$Background/MarginContainer/TabContainer/TK_CONFIGURATOR/ScrollContainer/VBoxContainer/system_container/easter_eggs.text = tr("TK_EASTEREGGS") + " " + tr("TK_SOON")
func _set_up_globals(state: Array) -> void:
#TODO on initial run pass array date?
#print (state)
%update_notification_button.button_pressed = class_functions.update_check
%quick_resume_button.button_pressed = class_functions.quick_resume_status
%retroarch_quick_resume_button.button_pressed = class_functions.quick_resume_status
%sound_button.button_pressed = class_functions.sound_effects
%volume_effects_slider.visible = class_functions.sound_effects
mixed_mode(%button_swap_button, class_functions.abxy_state)
mixed_mode(%ask_to_exit_button, class_functions.ask_to_exit_state)
mixed_mode(%border_button, class_functions.border_state)
mixed_mode(%widescreen_button, class_functions.widescreen_state)
mixed_mode(%quick_rewind_button, class_functions.quick_rewind_state)
mixed_mode(%cheevos_button, class_functions.cheevos_state)
mixed_mode(%cheevos_hardcore_button, class_functions.cheevos_hardcore_state)
#if class_functions.cheevos_state == "true":
#%cheevos_enabled_container.visible = true
#elif class_functions.cheevos_state == "false":
#%cheevos_enabled_container.visible = false
func mixed_mode (button: Button, state: String) -> void:
match [class_functions.button_list]:
[class_functions.button_list]:
if state == "true":
button.button_pressed = true
button.add_theme_stylebox_override("normal", style_box_original)
elif state == "false":
button.button_pressed = false
button.add_theme_stylebox_override("normal", style_box_original)
elif state == "mixed":
mixed_status(button)
func mixed_status (button: Button) -> void:
button.button_pressed = false
button.toggle_mode = false
var style_box = StyleBoxFlat.new()
style_box.bg_color = Color(0.941, 0.502, 0, 1)
style_box.border_color = Color(0.102, 0.624, 1, 1)
style_box.border_blend = true
style_box.corner_radius_top_left = 25
style_box.corner_radius_top_right = 25
style_box.corner_radius_bottom_right = 25
style_box.corner_radius_bottom_left = 25
style_box.border_width_left = 15
style_box.border_width_top = 15
style_box.border_width_right = 15
style_box.border_width_bottom = 15
button.add_theme_stylebox_override("normal", style_box)
func change_font(index: int) -> void:
var font_file: FontFile
match index:
1:
font_file = load("res://assets/fonts/munro/munro.ttf")
%TabContainer.add_theme_font_size_override("font_size", class_functions.font_tab_size)
font_size = 25
2:
font_file = load("res://assets/fonts/akrobat/Akrobat-Regular.otf")
%TabContainer.add_theme_font_size_override("font_size", class_functions.font_tab_size)
font_size = 25
3:
font_file = load("res://assets/fonts/OpenDyslexic3/OpenDyslexic3-Regular.ttf")
%TabContainer.add_theme_font_size_override("font_size", 15)
font_size = 16
custom_theme = load("res://assets/themes/default_theme.tres")
custom_theme.set_font("font", "Control", font_file)
custom_theme.default_font_size = font_size
$".".theme = custom_theme
data_handler.change_cfg_value(class_functions.config_file_path, "font", "options", str(index))

View file

@ -0,0 +1,17 @@
extends Sprite2D
@export var rotation_speed: float = 45.0
@export var speed = 400
const SCALE_MIN = 0.01
const SCALE_MAX = 0.35
const SCALE_SPEED = 0.5
var scale_direction = 1.0
func _process(delta) -> void:
# Rotate the sprite
rotation_degrees += rotation_speed * delta
var new_scale = scale + Vector2(scale_direction, scale_direction) * SCALE_SPEED * delta
if new_scale.x < SCALE_MIN or new_scale.x > SCALE_MAX:
scale_direction *= -1 # Reverse direction if scale limit is reached
else:
scale = new_scale

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

View file

@ -1,94 +0,0 @@
extends MarginContainer
var rd_web_button := Button.new()
var rd_changelog_button := Button.new()
var rd_wiki_button := Button.new()
var rd_credits_button := Button.new()
var rd_donate_button := Button.new()
var rd_contactus_button := Button.new()
var rd_licenses_button := Button.new()
var app_data := AppData.new()
var bArray :Array = [rd_web_button,rd_changelog_button,rd_wiki_button,
rd_credits_button,rd_donate_button,rd_contactus_button,rd_licenses_button]
func _ready():
#tk_about = class_functions.import_csv_data("res://tk_about.txt")
_connect_signals()
create_buttons()
func _connect_signals() -> void:
rd_web_button.pressed.connect(_about_button_pressed.bind("rd_web", rd_web_button))
rd_changelog_button.pressed.connect(_about_button_pressed.bind("rd_changelog", rd_changelog_button))
rd_wiki_button.pressed.connect(_about_button_pressed.bind("rd_wiki",rd_wiki_button))
rd_credits_button.pressed.connect(_about_button_pressed.bind("rd_credits", rd_credits_button))
rd_donate_button.pressed.connect(_about_button_pressed.bind("rd_donate", rd_donate_button))
rd_contactus_button.pressed.connect(_about_button_pressed.bind("rd_contactus", rd_contactus_button))
rd_licenses_button.pressed.connect(_about_button_pressed.bind("rd_licenses", rd_licenses_button))
func _about_button_pressed(id: String, button: Button) -> void:
match id:
"rd_web", "rd_changelog", "rd_wiki", "rd_credits", "rd_donate", "rd_contactus", "rd_licenses":
class_functions.log_parameters[2] = class_functions.log_text + "Loading website for " + id
class_functions.execute_command(class_functions.wrapper_command,class_functions.log_parameters, false)
OS.shell_open(button.editor_description)
_:
class_functions.log_parameters[2] = class_functions.log_text + "Loading website - no matching ID found"
class_functions.execute_command(class_functions.wrapper_command,class_functions.log_parameters, false)
print ("Website ID/Link not found")
func create_buttons() -> void:
app_data = data_handler.app_data
for button in bArray:
%GridContainer.add_child(button)
for id in app_data.about_links:
var web_data: Link = app_data.about_links[id]
match id:
"rd_web":
rd_web_button.text = web_data.name
rd_web_button.tooltip_text = web_data.description
rd_web_button.icon = ResourceLoader.load(web_data.icon)
rd_web_button.editor_description = web_data.url
rd_web_button.icon_alignment = HORIZONTAL_ALIGNMENT_CENTER
rd_web_button.vertical_icon_alignment = VERTICAL_ALIGNMENT_TOP
"rd_changelog":
rd_changelog_button.text = web_data.name
rd_changelog_button.tooltip_text = web_data.description
rd_changelog_button.icon = ResourceLoader.load(web_data.icon)
rd_changelog_button.editor_description = web_data.url
rd_changelog_button.icon_alignment = HORIZONTAL_ALIGNMENT_CENTER
rd_changelog_button.vertical_icon_alignment = VERTICAL_ALIGNMENT_TOP
"rd_wiki":
rd_wiki_button.text = web_data.name
rd_wiki_button.tooltip_text = web_data.description
rd_wiki_button.icon = ResourceLoader.load(web_data.icon)
rd_wiki_button.editor_description = web_data.url
rd_wiki_button.icon_alignment = HORIZONTAL_ALIGNMENT_CENTER
rd_wiki_button.vertical_icon_alignment = VERTICAL_ALIGNMENT_TOP
"rd_credits":
rd_credits_button.text = web_data.name
rd_credits_button.tooltip_text = web_data.description
rd_credits_button.icon = ResourceLoader.load(web_data.icon)
rd_credits_button.editor_description = web_data.url
rd_credits_button.icon_alignment = HORIZONTAL_ALIGNMENT_CENTER
rd_credits_button.vertical_icon_alignment = VERTICAL_ALIGNMENT_TOP
"rd_donate":
rd_donate_button.text = web_data.name
rd_donate_button.tooltip_text = web_data.description
rd_donate_button.icon = ResourceLoader.load(web_data.icon)
rd_donate_button.editor_description = web_data.url
rd_donate_button.icon_alignment = HORIZONTAL_ALIGNMENT_CENTER
rd_donate_button.vertical_icon_alignment = VERTICAL_ALIGNMENT_TOP
"rd_contactus":
rd_contactus_button.text = web_data.name
rd_contactus_button.tooltip_text = web_data.description
rd_contactus_button.icon = ResourceLoader.load(web_data.icon)
rd_contactus_button.editor_description = web_data.url
rd_contactus_button.icon_alignment = HORIZONTAL_ALIGNMENT_CENTER
rd_contactus_button.vertical_icon_alignment = VERTICAL_ALIGNMENT_TOP
"rd_licenses":
rd_licenses_button.text = web_data.name
rd_licenses_button.tooltip_text = web_data.description
rd_licenses_button.icon = ResourceLoader.load(web_data.icon)
rd_licenses_button.editor_description = web_data.url
rd_licenses_button.icon_alignment = HORIZONTAL_ALIGNMENT_CENTER
rd_licenses_button.vertical_icon_alignment = VERTICAL_ALIGNMENT_TOP