diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml
index ef417e375..ec5ceb642 100644
--- a/.github/workflows/test.yaml
+++ b/.github/workflows/test.yaml
@@ -14,4 +14,4 @@ jobs:
steps:
- uses: actions/checkout@v3
- run: |
- make in-docker IMAGE_TAG=4.2.1 TARGET='import test GAMESCOPE_CMD='
+ make in-docker IMAGE_TAG=4.3 TARGET='import test GAMESCOPE_CMD='
diff --git a/.releaserc.yaml b/.releaserc.yaml
index b87566048..5724888e0 100644
--- a/.releaserc.yaml
+++ b/.releaserc.yaml
@@ -43,7 +43,7 @@ plugins:
# Execute commands to build the project
- - "@semantic-release/exec"
- shell: true
- prepareCmd: "make in-docker IMAGE_TAG=4.2.2 TARGET='force-import dist'"
+ prepareCmd: "make in-docker IMAGE_TAG=4.3 TARGET='force-import dist'"
# Publish artifacts as a GitHub release
- - "@semantic-release/github"
diff --git a/Makefile b/Makefile
index 51c7784e2..aa70289c1 100644
--- a/Makefile
+++ b/Makefile
@@ -15,18 +15,16 @@ EXPORT_TEMPLATE ?= $(HOME)/.local/share/godot/export_templates/$(GODOT_REVISION)
#EXPORT_TEMPLATE_URL ?= https://downloads.tuxfamily.org/godotengine/$(GODOT_VERSION)/Godot_v$(GODOT_VERSION)-$(GODOT_RELEASE)_export_templates.tpz
EXPORT_TEMPLATE_URL ?= https://github.com/godotengine/godot/releases/download/$(GODOT_VERSION)-$(GODOT_RELEASE)/Godot_v$(GODOT_VERSION)-$(GODOT_RELEASE)_export_templates.tpz
-ALL_ADDONS := ./addons/dbus/bin/libdbus.linux.template_$(BUILD_TYPE).x86_64.so ./addons/linuxthread/bin/liblinuxthread.linux.template_$(BUILD_TYPE).x86_64.so ./addons/pty/bin/libpty.linux.template_$(BUILD_TYPE).x86_64.so ./addons/unixsock/bin/libunixsock.linux.template_$(BUILD_TYPE).x86_64.so ./addons/xlib/bin/libxlib.linux.template_$(BUILD_TYPE).x86_64.so
-ALL_ADDON_FILES := $(shell find ./addons -regex '.*\(\.cpp\|\.h\|\.hpp\)$$')
+ALL_EXTENSIONS := ./addons/core/bin/libopengamepadui-core.linux.template_$(BUILD_TYPE).x86_64.so
+ALL_EXTENSION_FILES := $(shell find ./extensions/ -regex '.*\(\.rs|\.toml\|\.lock\)$$')
ALL_GDSCRIPT := $(shell find ./ -name '*.gd')
ALL_SCENES := $(shell find ./ -name '*.tscn')
ALL_RESOURCES := $(shell find ./ -regex '.*\(\.tres\|\.svg\|\.png\)$$')
-PROJECT_FILES := $(ALL_ADDONS) $(ALL_GDSCRIPT) $(ALL_SCENES) $(ALL_RESOURCES)
+PROJECT_FILES := $(ALL_EXTENSIONS) $(ALL_GDSCRIPT) $(ALL_SCENES) $(ALL_RESOURCES)
# Docker image variables
IMAGE_NAME ?= ghcr.io/shadowblip/opengamepadui-builder
IMAGE_TAG ?= latest
-ADDONS_IMAGE_NAME ?= ghcr.io/shadowblip/opengamepadui-addons-builder
-ADDONS_IMAGE_TAG ?= latest
# Remote debugging variables
SSH_USER ?= deck
@@ -37,6 +35,8 @@ SSH_DATA_PATH ?= /home/$(SSH_USER)/Projects
# systemd-sysext variables
SYSEXT_ID ?= steamos
SYSEXT_VERSION_ID ?= 3.6.3
+SYSEXT_LIBIIO_VERSION ?= 0.26-1
+SYSEXT_LIBSERIALPORT_VERSION ?= 0.1.2-1
# Include any user defined settings
-include settings.mk
@@ -144,37 +144,40 @@ build/metadata.json: build/opengamepad-ui.x86_64 assets/crypto/keys/opengamepadu
.PHONY: import
import: $(IMPORT_DIR) ## Import project assets
-$(IMPORT_DIR): $(ALL_ADDONS)
+$(IMPORT_DIR): $(ALL_EXTENSIONS)
@echo "Importing project assets. This will take some time..."
command -v $(GODOT) > /dev/null 2>&1
timeout --foreground 40 $(GODOT) --headless --editor . > /dev/null 2>&1 || echo "Finished"
touch $(IMPORT_DIR)
.PHONY: force-import
-force-import: $(ALL_ADDONS)
+force-import: $(ALL_EXTENSIONS)
@echo "Force importing project assets. This will take some time..."
command -v $(GODOT) > /dev/null 2>&1
timeout --foreground 40 $(GODOT) --headless --editor . > /dev/null 2>&1 || echo "Finished"
timeout --foreground 40 $(GODOT) --headless --editor . > /dev/null 2>&1 || echo "Finished"
-.PHONY: addons
-addons: $(ALL_ADDONS) ## Build GDExtension addons
-$(ALL_ADDONS) &: $(ALL_ADDON_FILES)
- @echo "Building native GDExtension addons..."
- cd ./gdext && $(MAKE) build
+.PHONY: extensions
+extensions: $(ALL_EXTENSIONS) ## Build engine extensions
+$(ALL_EXTENSIONS) &: $(ALL_EXTENSION_FILES)
+ @echo "Building engine extensions..."
+ cd ./extensions && $(MAKE) build
.PHONY: edit
edit: $(IMPORT_DIR) ## Open the project in the Godot editor
$(GODOT) --editor .
+.PHONY: purge
+purge: clean ## Remove all build artifacts including engine extensions
+ rm -rf $(ROOTFS)
+ cd ./extensions && $(MAKE) clean
+
.PHONY: clean
-clean: ## Remove build artifacts
+clean: ## Remove Godot build artifacts
rm -rf build
- rm -rf $(ROOTFS)
rm -rf $(CACHE_DIR)
rm -rf dist
rm -rf $(IMPORT_DIR)
- cd ./gdext && $(MAKE) clean
.PHONY: run run-force
run: build/opengamepad-ui.x86_64 run-force ## Run the project in gamescope
@@ -193,7 +196,7 @@ $(EXPORT_TEMPLATE):
.PHONY: debug
debug: $(IMPORT_DIR) ## Run the project in debug mode in gamescope
- $(GAMESCOPE) -e --xwayland-count 2 -- \
+ $(GAMESCOPE) -e --xwayland-count 2 --expose-wayland -- \
$(GODOT) --path $(PWD) --remote-debug tcp://127.0.0.1:6007 \
--position 320,140 res://entrypoint.tscn
@@ -237,9 +240,8 @@ assets/crypto/keys/opengamepadui.pub: assets/crypto/keys/opengamepadui.key
##@ Remote Debugging
.PHONY: deploy
-deploy: dist-archive $(SSH_MOUNT_PATH)/.mounted ## Build, deploy, and tunnel to a remote device
- cp dist/opengamepadui.tar.gz $(SSH_MOUNT_PATH)
- cd $(SSH_MOUNT_PATH) #&& tar xvfz opengamepadui.tar.gz
+deploy: dist-archive ## Build and deploy to a remote device
+ scp dist/opengamepadui.tar.gz $(SSH_USER)@$(SSH_HOST):$(SSH_DATA_PATH)
ssh -t $(SSH_USER)@$(SSH_HOST) tar xvfz "$(SSH_DATA_PATH)/opengamepadui.tar.gz"
@@ -274,14 +276,6 @@ tunnel: ## Create an SSH tunnel to allow remote debugging
ssh $(SSH_USER)@$(SSH_HOST) -N -f -R 6007:localhost:6007
-# Mounts the remote device and creates an SSH tunnel for remote debugging
-$(SSH_MOUNT_PATH)/.mounted:
- mkdir -p $(SSH_MOUNT_PATH)
- sshfs -o default_permissions $(SSH_USER)@$(SSH_HOST):$(SSH_DATA_PATH) $(SSH_MOUNT_PATH)
- $(MAKE) tunnel
- touch $(SSH_MOUNT_PATH)/.mounted
-
-
##@ Distribution
.PHONY: rootfs
@@ -293,6 +287,7 @@ rootfs: build/opengamepad-ui.x86_64
cp -r build/*.so $(ROOTFS)/usr/share/opengamepadui
cp -r build/opengamepad-ui.x86_64 $(ROOTFS)/usr/share/opengamepadui
cp -r build/opengamepad-ui.pck $(ROOTFS)/usr/share/opengamepadui
+ cp ./extensions/target/release/reaper $(ROOTFS)/usr/share/opengamepadui
touch $(ROOTFS)/.gdignore
@@ -393,7 +388,7 @@ $(CACHE_DIR)/inputplumber.tar.gz: $(CACHE_DIR)/libiio $(CACHE_DIR)/libserialport
wget -O $@ https://github.com/ShadowBlip/InputPlumber/releases/download/$${IP_VERSION}/inputplumber.tar.gz
-LIBIIO_URL ?= https://mirror.rackspace.com/archlinux/extra/os/x86_64/libiio-0.25-3-x86_64.pkg.tar.zst
+LIBIIO_URL ?= https://mirror.rackspace.com/archlinux/extra/os/x86_64/libiio-$(SYSEXT_LIBIIO_VERSION)-x86_64.pkg.tar.zst
$(CACHE_DIR)/libiio:
rm -rf $(CACHE_DIR)/libiio*
wget $(LIBIIO_URL) \
@@ -403,7 +398,7 @@ $(CACHE_DIR)/libiio:
tar xvf $(CACHE_DIR)/libiio.tar -C $(CACHE_DIR)/libiio
-LIBSERIALPORT_URL ?= https://mirror.rackspace.com/archlinux/extra/os/x86_64/libserialport-0.1.1-5-x86_64.pkg.tar.zst
+LIBSERIALPORT_URL ?= https://mirror.rackspace.com/archlinux/extra/os/x86_64/libserialport-$(SYSEXT_LIBSERIALPORT_VERSION)-x86_64.pkg.tar.zst
$(CACHE_DIR)/libserialport:
rm -rf $(CACHE_DIR)/libserialport*
wget $(LIBSERIALPORT_URL) \
@@ -421,14 +416,6 @@ release: ## Publish a release with semantic release
# E.g. make in-docker TARGET=build
.PHONY: in-docker
in-docker:
- @# Build addons in a seperate container for glibc compatibility
- docker run --rm \
- -v $(PWD):/src \
- --workdir /src \
- -e PWD=/src \
- --user $(shell id -u):$(shell id -g) \
- $(ADDONS_IMAGE_NAME):$(ADDONS_IMAGE_TAG) \
- make addons
@# Run the given make target inside Docker
docker run --rm \
-v $(PWD):/src \
@@ -449,14 +436,3 @@ docker-builder:
.PHONY: docker-builder-push
docker-builder-push: docker-builder
docker push $(IMAGE_NAME):$(IMAGE_TAG)
-
-.PHONY: docker-builder-addons
-docker-builder-addons:
- @# Pull any existing image to cache it
- docker pull $(ADDONS_IMAGE_NAME):$(ADDONS_IMAGE_TAG) || echo "No remote image to pull"
- @# Build the Docker image that will build the project
- docker build -t $(ADDONS_IMAGE_NAME):$(ADDONS_IMAGE_TAG) -f docker/Dockerfile.addons ./docker
-
-.PHONY: docker-builder-addons-push
-docker-builder-addons-push: docker-builder-addons
- docker push $(ADDONS_IMAGE_NAME):$(ADDONS_IMAGE_TAG)
diff --git a/addons/.gitignore b/addons/.gitignore
index 99eef491d..140f8cf80 100644
--- a/addons/.gitignore
+++ b/addons/.gitignore
@@ -1,5 +1 @@
-dbus/
-linuxthread/
-pty/
-unixsock/
-xlib/
+*.so
diff --git a/addons/core/assets/icons/carbon--cloud-registry.svg b/addons/core/assets/icons/carbon--cloud-registry.svg
new file mode 100644
index 000000000..67dd643ec
--- /dev/null
+++ b/addons/core/assets/icons/carbon--cloud-registry.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/core/assets/icons/carbon--cloud-registry.svg.import b/addons/core/assets/icons/carbon--cloud-registry.svg.import
new file mode 100644
index 000000000..094131c98
--- /dev/null
+++ b/addons/core/assets/icons/carbon--cloud-registry.svg.import
@@ -0,0 +1,37 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://bghk66u2c0kq"
+path="res://.godot/imported/carbon--cloud-registry.svg-1e050ab4a509bcd0338010b635012822.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/core/assets/icons/carbon--cloud-registry.svg"
+dest_files=["res://.godot/imported/carbon--cloud-registry.svg-1e050ab4a509bcd0338010b635012822.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
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/addons/core/assets/icons/clarity--process-on-vm-line.svg b/addons/core/assets/icons/clarity--process-on-vm-line.svg
new file mode 100644
index 000000000..308adfad9
--- /dev/null
+++ b/addons/core/assets/icons/clarity--process-on-vm-line.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/core/assets/icons/clarity--process-on-vm-line.svg.import b/addons/core/assets/icons/clarity--process-on-vm-line.svg.import
new file mode 100644
index 000000000..11ef486b9
--- /dev/null
+++ b/addons/core/assets/icons/clarity--process-on-vm-line.svg.import
@@ -0,0 +1,37 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://b1e1er0exm6u4"
+path="res://.godot/imported/clarity--process-on-vm-line.svg-283d9963c91ea54966f3276a32a96346.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/core/assets/icons/clarity--process-on-vm-line.svg"
+dest_files=["res://.godot/imported/clarity--process-on-vm-line.svg-283d9963c91ea54966f3276a32a96346.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
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/addons/core/assets/icons/inputplumber.svg b/addons/core/assets/icons/inputplumber.svg
new file mode 100644
index 000000000..4ea3ae1e5
--- /dev/null
+++ b/addons/core/assets/icons/inputplumber.svg
@@ -0,0 +1,76 @@
+
+
diff --git a/addons/core/assets/icons/inputplumber.svg.import b/addons/core/assets/icons/inputplumber.svg.import
new file mode 100644
index 000000000..b11985071
--- /dev/null
+++ b/addons/core/assets/icons/inputplumber.svg.import
@@ -0,0 +1,37 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://dbdyxgqmyeg1f"
+path="res://.godot/imported/inputplumber.svg-930e8ab4c0d3c4d458c32ef96742bdaf.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/core/assets/icons/inputplumber.svg"
+dest_files=["res://.godot/imported/inputplumber.svg-930e8ab4c0d3c4d458c32ef96742bdaf.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
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/addons/core/assets/icons/library.svg b/addons/core/assets/icons/library.svg
new file mode 100644
index 000000000..a4c3cef4f
--- /dev/null
+++ b/addons/core/assets/icons/library.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/core/assets/icons/library.svg.import b/addons/core/assets/icons/library.svg.import
new file mode 100644
index 000000000..36d12ed4b
--- /dev/null
+++ b/addons/core/assets/icons/library.svg.import
@@ -0,0 +1,37 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://bn4jiyx7afl3b"
+path="res://.godot/imported/library.svg-8fcfe8437951fa126b5ab9f50dba6f13.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/core/assets/icons/library.svg"
+dest_files=["res://.godot/imported/library.svg-8fcfe8437951fa126b5ab9f50dba6f13.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
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/addons/core/assets/icons/material-symbols-light--valve.svg b/addons/core/assets/icons/material-symbols-light--valve.svg
new file mode 100644
index 000000000..8881ab392
--- /dev/null
+++ b/addons/core/assets/icons/material-symbols-light--valve.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/core/assets/icons/material-symbols-light--valve.svg.import b/addons/core/assets/icons/material-symbols-light--valve.svg.import
new file mode 100644
index 000000000..bf831ce91
--- /dev/null
+++ b/addons/core/assets/icons/material-symbols-light--valve.svg.import
@@ -0,0 +1,37 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://d0pv3m8ld8ess"
+path="res://.godot/imported/material-symbols-light--valve.svg-c7c5e30f16c31ebbbe32f0986c258ed1.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/core/assets/icons/material-symbols-light--valve.svg"
+dest_files=["res://.godot/imported/material-symbols-light--valve.svg-c7c5e30f16c31ebbbe32f0986c258ed1.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
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/addons/core/core.gdextension b/addons/core/core.gdextension
new file mode 100644
index 000000000..c47219866
--- /dev/null
+++ b/addons/core/core.gdextension
@@ -0,0 +1,20 @@
+[configuration]
+entry_symbol = "gdext_rust_init"
+compatibility_minimum = 4.3
+reloadable = false
+
+[libraries]
+linux.debug.x86_64 = "res://addons/core/bin/libopengamepadui-core.linux.template_debug.x86_64.so"
+linux.release.x86_64 = "res://addons/core/bin/libopengamepadui-core.linux.template_release.x86_64.so"
+
+[icons]
+BluezInstance = "res://assets/editor-icons/bluetooth.svg"
+GamescopeInstance = "res://assets/editor-icons/streamline--desktop-game-solid.svg"
+InputPlumberInstance = "res://addons/core/assets/icons/inputplumber.svg"
+NetworkManagerInstance = "res://assets/ui/icons/iconoir--network-solid.svg"
+PowerStationInstance = "res://assets/editor-icons/game-icons--power-generator.svg"
+Pty = "res://assets/editor-icons/devicon-plain--bash.svg"
+ResourceProcessor = "res://addons/core/assets/icons/clarity--process-on-vm-line.svg"
+ResourceRegistry = "res://addons/core/assets/icons/carbon--cloud-registry.svg"
+UPowerInstance = "res://assets/editor-icons/material-symbols--battery-profile-sharp.svg"
+Vdf = "res://addons/core/assets/icons/material-symbols-light--valve.svg"
diff --git a/addons/gut/fonts/AnonymousPro-Bold.ttf.import b/addons/gut/fonts/AnonymousPro-Bold.ttf.import
index a3eb4791f..de1351f60 100644
--- a/addons/gut/fonts/AnonymousPro-Bold.ttf.import
+++ b/addons/gut/fonts/AnonymousPro-Bold.ttf.import
@@ -15,6 +15,7 @@ dest_files=["res://.godot/imported/AnonymousPro-Bold.ttf-9d8fef4d357af5b52cd60af
Rendering=null
antialiasing=1
generate_mipmaps=false
+disable_embedded_bitmaps=true
multichannel_signed_distance_field=false
msdf_pixel_range=8
msdf_size=48
diff --git a/addons/gut/fonts/AnonymousPro-BoldItalic.ttf.import b/addons/gut/fonts/AnonymousPro-BoldItalic.ttf.import
index ef28dd805..bdde20728 100644
--- a/addons/gut/fonts/AnonymousPro-BoldItalic.ttf.import
+++ b/addons/gut/fonts/AnonymousPro-BoldItalic.ttf.import
@@ -15,6 +15,7 @@ dest_files=["res://.godot/imported/AnonymousPro-BoldItalic.ttf-4274bf704d3d6b9cd
Rendering=null
antialiasing=1
generate_mipmaps=false
+disable_embedded_bitmaps=true
multichannel_signed_distance_field=false
msdf_pixel_range=8
msdf_size=48
diff --git a/addons/gut/fonts/AnonymousPro-Italic.ttf.import b/addons/gut/fonts/AnonymousPro-Italic.ttf.import
index 1779af172..ce3e5b918 100644
--- a/addons/gut/fonts/AnonymousPro-Italic.ttf.import
+++ b/addons/gut/fonts/AnonymousPro-Italic.ttf.import
@@ -15,6 +15,7 @@ dest_files=["res://.godot/imported/AnonymousPro-Italic.ttf-9989590b02137b799e13d
Rendering=null
antialiasing=1
generate_mipmaps=false
+disable_embedded_bitmaps=true
multichannel_signed_distance_field=false
msdf_pixel_range=8
msdf_size=48
diff --git a/addons/gut/fonts/AnonymousPro-Regular.ttf.import b/addons/gut/fonts/AnonymousPro-Regular.ttf.import
index 1e2975b15..a567498cd 100644
--- a/addons/gut/fonts/AnonymousPro-Regular.ttf.import
+++ b/addons/gut/fonts/AnonymousPro-Regular.ttf.import
@@ -15,6 +15,7 @@ dest_files=["res://.godot/imported/AnonymousPro-Regular.ttf-856c843fd6f89964d2ca
Rendering=null
antialiasing=1
generate_mipmaps=false
+disable_embedded_bitmaps=true
multichannel_signed_distance_field=false
msdf_pixel_range=8
msdf_size=48
diff --git a/addons/gut/fonts/CourierPrime-Bold.ttf.import b/addons/gut/fonts/CourierPrime-Bold.ttf.import
index 7d60fb0a2..cb05171da 100644
--- a/addons/gut/fonts/CourierPrime-Bold.ttf.import
+++ b/addons/gut/fonts/CourierPrime-Bold.ttf.import
@@ -15,6 +15,7 @@ dest_files=["res://.godot/imported/CourierPrime-Bold.ttf-1f003c66d63ebed70964e77
Rendering=null
antialiasing=1
generate_mipmaps=false
+disable_embedded_bitmaps=true
multichannel_signed_distance_field=false
msdf_pixel_range=8
msdf_size=48
diff --git a/addons/gut/fonts/CourierPrime-BoldItalic.ttf.import b/addons/gut/fonts/CourierPrime-BoldItalic.ttf.import
index 4678c9ebb..0a9a7b770 100644
--- a/addons/gut/fonts/CourierPrime-BoldItalic.ttf.import
+++ b/addons/gut/fonts/CourierPrime-BoldItalic.ttf.import
@@ -15,6 +15,7 @@ dest_files=["res://.godot/imported/CourierPrime-BoldItalic.ttf-65ebcc61dd5e1dfa8
Rendering=null
antialiasing=1
generate_mipmaps=false
+disable_embedded_bitmaps=true
multichannel_signed_distance_field=false
msdf_pixel_range=8
msdf_size=48
diff --git a/addons/gut/fonts/CourierPrime-Italic.ttf.import b/addons/gut/fonts/CourierPrime-Italic.ttf.import
index 522e2950c..89412fc98 100644
--- a/addons/gut/fonts/CourierPrime-Italic.ttf.import
+++ b/addons/gut/fonts/CourierPrime-Italic.ttf.import
@@ -15,6 +15,7 @@ dest_files=["res://.godot/imported/CourierPrime-Italic.ttf-baa9156a73770735a0f72
Rendering=null
antialiasing=1
generate_mipmaps=false
+disable_embedded_bitmaps=true
multichannel_signed_distance_field=false
msdf_pixel_range=8
msdf_size=48
diff --git a/addons/gut/fonts/CourierPrime-Regular.ttf.import b/addons/gut/fonts/CourierPrime-Regular.ttf.import
index 38174660f..9fde40b1b 100644
--- a/addons/gut/fonts/CourierPrime-Regular.ttf.import
+++ b/addons/gut/fonts/CourierPrime-Regular.ttf.import
@@ -15,6 +15,7 @@ dest_files=["res://.godot/imported/CourierPrime-Regular.ttf-3babe7e4a7a588dfc9a8
Rendering=null
antialiasing=1
generate_mipmaps=false
+disable_embedded_bitmaps=true
multichannel_signed_distance_field=false
msdf_pixel_range=8
msdf_size=48
diff --git a/addons/gut/fonts/LobsterTwo-Bold.ttf.import b/addons/gut/fonts/LobsterTwo-Bold.ttf.import
index 7548ad04d..673d15155 100644
--- a/addons/gut/fonts/LobsterTwo-Bold.ttf.import
+++ b/addons/gut/fonts/LobsterTwo-Bold.ttf.import
@@ -15,6 +15,7 @@ dest_files=["res://.godot/imported/LobsterTwo-Bold.ttf-7c7f734103b58a32491a47881
Rendering=null
antialiasing=1
generate_mipmaps=false
+disable_embedded_bitmaps=true
multichannel_signed_distance_field=false
msdf_pixel_range=8
msdf_size=48
diff --git a/addons/gut/fonts/LobsterTwo-BoldItalic.ttf.import b/addons/gut/fonts/LobsterTwo-BoldItalic.ttf.import
index 4b609e80b..62048b0ef 100644
--- a/addons/gut/fonts/LobsterTwo-BoldItalic.ttf.import
+++ b/addons/gut/fonts/LobsterTwo-BoldItalic.ttf.import
@@ -15,6 +15,7 @@ dest_files=["res://.godot/imported/LobsterTwo-BoldItalic.ttf-227406a33e84448e6aa
Rendering=null
antialiasing=1
generate_mipmaps=false
+disable_embedded_bitmaps=true
multichannel_signed_distance_field=false
msdf_pixel_range=8
msdf_size=48
diff --git a/addons/gut/fonts/LobsterTwo-Italic.ttf.import b/addons/gut/fonts/LobsterTwo-Italic.ttf.import
index 5899b7977..d3ca27281 100644
--- a/addons/gut/fonts/LobsterTwo-Italic.ttf.import
+++ b/addons/gut/fonts/LobsterTwo-Italic.ttf.import
@@ -15,6 +15,7 @@ dest_files=["res://.godot/imported/LobsterTwo-Italic.ttf-f93abf6c25390c85ad5fb6c
Rendering=null
antialiasing=1
generate_mipmaps=false
+disable_embedded_bitmaps=true
multichannel_signed_distance_field=false
msdf_pixel_range=8
msdf_size=48
diff --git a/addons/gut/fonts/LobsterTwo-Regular.ttf.import b/addons/gut/fonts/LobsterTwo-Regular.ttf.import
index 45a12c8a5..9cc754218 100644
--- a/addons/gut/fonts/LobsterTwo-Regular.ttf.import
+++ b/addons/gut/fonts/LobsterTwo-Regular.ttf.import
@@ -15,6 +15,7 @@ dest_files=["res://.godot/imported/LobsterTwo-Regular.ttf-f3fcfa01cd671c8da433dd
Rendering=null
antialiasing=1
generate_mipmaps=false
+disable_embedded_bitmaps=true
multichannel_signed_distance_field=false
msdf_pixel_range=8
msdf_size=48
diff --git a/assets/editor-icons/devicon-plain--bash.svg b/assets/editor-icons/devicon-plain--bash.svg
new file mode 100644
index 000000000..50a9294b3
--- /dev/null
+++ b/assets/editor-icons/devicon-plain--bash.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/editor-icons/devicon-plain--bash.svg.import b/assets/editor-icons/devicon-plain--bash.svg.import
new file mode 100644
index 000000000..c58992fe6
--- /dev/null
+++ b/assets/editor-icons/devicon-plain--bash.svg.import
@@ -0,0 +1,37 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://byyen2xkltwti"
+path="res://.godot/imported/devicon-plain--bash.svg-6240f7f0c8c8d59a2493575f1290b4da.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://assets/editor-icons/devicon-plain--bash.svg"
+dest_files=["res://.godot/imported/devicon-plain--bash.svg-6240f7f0c8c8d59a2493575f1290b4da.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
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/assets/editor-icons/game-icons--power-generator.svg b/assets/editor-icons/game-icons--power-generator.svg
new file mode 100644
index 000000000..b6590b544
--- /dev/null
+++ b/assets/editor-icons/game-icons--power-generator.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/editor-icons/game-icons--power-generator.svg.import b/assets/editor-icons/game-icons--power-generator.svg.import
new file mode 100644
index 000000000..4e7a4ee49
--- /dev/null
+++ b/assets/editor-icons/game-icons--power-generator.svg.import
@@ -0,0 +1,37 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://sgo62iku8hra"
+path="res://.godot/imported/game-icons--power-generator.svg-c4c65834b21ee0abccaa30749630027a.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://assets/editor-icons/game-icons--power-generator.svg"
+dest_files=["res://.godot/imported/game-icons--power-generator.svg-c4c65834b21ee0abccaa30749630027a.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
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/assets/editor-icons/inputplumber.svg b/assets/editor-icons/inputplumber.svg
new file mode 100644
index 000000000..4e63ef665
--- /dev/null
+++ b/assets/editor-icons/inputplumber.svg
@@ -0,0 +1,50 @@
+
+
diff --git a/assets/editor-icons/inputplumber.svg.import b/assets/editor-icons/inputplumber.svg.import
new file mode 100644
index 000000000..4f82c89c4
--- /dev/null
+++ b/assets/editor-icons/inputplumber.svg.import
@@ -0,0 +1,37 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://dhwvdnbmrvqu4"
+path="res://.godot/imported/inputplumber.svg-f9a02e1ec85cdf7dc3601d7003f9de2a.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://assets/editor-icons/inputplumber.svg"
+dest_files=["res://.godot/imported/inputplumber.svg-f9a02e1ec85cdf7dc3601d7003f9de2a.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
+svg/scale=0.063
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/assets/editor-icons/material-symbols--battery-profile-sharp.svg b/assets/editor-icons/material-symbols--battery-profile-sharp.svg
new file mode 100644
index 000000000..5dfdb58a1
--- /dev/null
+++ b/assets/editor-icons/material-symbols--battery-profile-sharp.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/editor-icons/material-symbols--battery-profile-sharp.svg.import b/assets/editor-icons/material-symbols--battery-profile-sharp.svg.import
new file mode 100644
index 000000000..6e2b2d68b
--- /dev/null
+++ b/assets/editor-icons/material-symbols--battery-profile-sharp.svg.import
@@ -0,0 +1,37 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://cl50s5usbx8nv"
+path="res://.godot/imported/material-symbols--battery-profile-sharp.svg-87e7d7a90b8036cca4150ec1137bd618.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://assets/editor-icons/material-symbols--battery-profile-sharp.svg"
+dest_files=["res://.godot/imported/material-symbols--battery-profile-sharp.svg-87e7d7a90b8036cca4150ec1137bd618.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
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/assets/editor-icons/solar--dialog-2-bold.svg b/assets/editor-icons/solar--dialog-2-bold.svg
new file mode 100644
index 000000000..c4799ee46
--- /dev/null
+++ b/assets/editor-icons/solar--dialog-2-bold.svg
@@ -0,0 +1,46 @@
+
+
diff --git a/assets/editor-icons/solar--dialog-2-bold.svg.import b/assets/editor-icons/solar--dialog-2-bold.svg.import
new file mode 100644
index 000000000..ed2c0a288
--- /dev/null
+++ b/assets/editor-icons/solar--dialog-2-bold.svg.import
@@ -0,0 +1,37 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://dkxlstqr7f8oo"
+path="res://.godot/imported/solar--dialog-2-bold.svg-da68fed2d0a8c7337ff4134355b0d904.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://assets/editor-icons/solar--dialog-2-bold.svg"
+dest_files=["res://.godot/imported/solar--dialog-2-bold.svg-da68fed2d0a8c7337ff4134355b0d904.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
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/assets/editor-icons/streamline--desktop-game-solid.svg b/assets/editor-icons/streamline--desktop-game-solid.svg
new file mode 100644
index 000000000..d8ebec7e1
--- /dev/null
+++ b/assets/editor-icons/streamline--desktop-game-solid.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/editor-icons/streamline--desktop-game-solid.svg.import b/assets/editor-icons/streamline--desktop-game-solid.svg.import
new file mode 100644
index 000000000..b575a2729
--- /dev/null
+++ b/assets/editor-icons/streamline--desktop-game-solid.svg.import
@@ -0,0 +1,37 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://cav2x6q8apups"
+path="res://.godot/imported/streamline--desktop-game-solid.svg-ff379b75f0c49d1fc9be24f364b571c9.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://assets/editor-icons/streamline--desktop-game-solid.svg"
+dest_files=["res://.godot/imported/streamline--desktop-game-solid.svg-ff379b75f0c49d1fc9be24f364b571c9.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
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/assets/gamepad/icon_mappings/joycon.tres b/assets/gamepad/icon_mappings/joycon.tres
index 786c95ba8..fb6793f2d 100644
--- a/assets/gamepad/icon_mappings/joycon.tres
+++ b/assets/gamepad/icon_mappings/joycon.tres
@@ -1,36 +1,36 @@
[gd_resource type="Resource" script_class="InputIconMapping" load_steps=32 format=3 uid="uid://dukk7rqq5cgma"]
[ext_resource type="Script" path="res://core/systems/input/input_icon_mapping.gd" id="1_a16bb"]
-[ext_resource type="Texture2D" uid="uid://dec8wg71j58h1" path="res://assets/images/gamepad/switch/switch_button_a.svg" id="1_bwo1l"]
-[ext_resource type="Texture2D" uid="uid://b1qcl62witrrt" path="res://assets/images/gamepad/switch/switch_buttons.svg" id="1_ww2e7"]
-[ext_resource type="Texture2D" uid="uid://c3hr6ecnhdtg2" path="res://assets/images/gamepad/switch/switch_buttons_down.svg" id="2_gavjx"]
-[ext_resource type="Texture2D" uid="uid://b3v8gbuc0knsr" path="res://assets/images/gamepad/switch/switch_button_home.svg" id="2_o4j1j"]
-[ext_resource type="Texture2D" uid="uid://b6wkct2qwo0ul" path="res://assets/images/gamepad/switch/switch_button_x.svg" id="3_ae6nc"]
-[ext_resource type="Texture2D" uid="uid://dykfvnb0v687h" path="res://assets/images/gamepad/switch/switch_buttons_left.svg" id="3_k02em"]
-[ext_resource type="Texture2D" uid="uid://bcthc11uwae6n" path="res://assets/images/gamepad/switch/switch_buttons_right.svg" id="4_w4xps"]
-[ext_resource type="Texture2D" uid="uid://bo07ay1vxneo1" path="res://assets/images/gamepad/switch/switch_buttons_up.svg" id="5_e3bby"]
-[ext_resource type="Texture2D" uid="uid://8o3g4dcunk87" path="res://assets/images/gamepad/switch/switch_button_b.svg" id="5_jpu3i"]
-[ext_resource type="Texture2D" uid="uid://dugmdwvujsrk4" path="res://assets/images/gamepad/switch/switch_button_plus.svg" id="6_q5ufv"]
-[ext_resource type="Texture2D" uid="uid://djvoe5nud1i0w" path="res://assets/images/gamepad/switch/switch_button_y.svg" id="7_e24lf"]
-[ext_resource type="Texture2D" uid="uid://by4xd4qq5dspy" path="res://assets/images/gamepad/switch/switch_joycon_left_rotate.svg" id="8_5ade5"]
-[ext_resource type="Texture2D" uid="uid://b57k4ko26lm6" path="res://assets/images/gamepad/switch/switch_button_l.svg" id="9_y7sje"]
-[ext_resource type="Texture2D" uid="uid://bgkt5t7mmbhts" path="res://assets/images/gamepad/switch/switch_stick_l.svg" id="10_7ixoo"]
-[ext_resource type="Texture2D" uid="uid://ca4fcl2jsx62k" path="res://assets/images/gamepad/switch/switch_stick_l_press.svg" id="11_sc443"]
-[ext_resource type="Texture2D" uid="uid://bvnpkij77axxu" path="res://assets/images/gamepad/switch/switch_stick_l_down.svg" id="12_xl772"]
-[ext_resource type="Texture2D" uid="uid://bbad7xmuveel8" path="res://assets/images/gamepad/switch/switch_stick_l_left.svg" id="13_21edv"]
-[ext_resource type="Texture2D" uid="uid://lpy6n3raxq2" path="res://assets/images/gamepad/switch/switch_stick_l_right.svg" id="14_t7a81"]
-[ext_resource type="Texture2D" uid="uid://btrirhorp6y57" path="res://assets/images/gamepad/switch/switch_stick_l_up.svg" id="15_c886y"]
-[ext_resource type="Texture2D" uid="uid://dsa8m2vfvtx0q" path="res://assets/images/gamepad/switch/switch_button_zl.svg" id="16_xvg34"]
-[ext_resource type="Texture2D" uid="uid://bu2naacuis8k8" path="res://assets/images/gamepad/switch/switch_button_r.svg" id="18_rb1n1"]
-[ext_resource type="Texture2D" uid="uid://c1fas8o38r02p" path="res://assets/images/gamepad/switch/switch_stick_r.svg" id="19_royjt"]
-[ext_resource type="Texture2D" uid="uid://dop088ppjtx7r" path="res://assets/images/gamepad/switch/switch_stick_r_press.svg" id="20_o8e1o"]
-[ext_resource type="Texture2D" uid="uid://dqrqw3lv3kl3e" path="res://assets/images/gamepad/switch/switch_stick_r_down.svg" id="21_m6t1r"]
-[ext_resource type="Texture2D" uid="uid://bcstmmysk3e1" path="res://assets/images/gamepad/switch/switch_stick_r_left.svg" id="22_4onjx"]
-[ext_resource type="Texture2D" uid="uid://domi3pblhpgqy" path="res://assets/images/gamepad/switch/switch_stick_r_right.svg" id="23_rh7dk"]
-[ext_resource type="Texture2D" uid="uid://dtkumw37qfis8" path="res://assets/images/gamepad/switch/switch_stick_r_up.svg" id="24_jvrdt"]
-[ext_resource type="Texture2D" uid="uid://cutjyk72c0d1" path="res://assets/images/gamepad/switch/switch_button_zr.svg" id="25_pawt1"]
-[ext_resource type="Texture2D" uid="uid://baeygxurw7dn1" path="res://assets/images/gamepad/switch/switch_button_sync.svg" id="26_3hoym"]
-[ext_resource type="Texture2D" uid="uid://crl6hqey1xqfd" path="res://assets/images/gamepad/switch/switch_button_minus.svg" id="28_wn71f"]
+[ext_resource type="Texture2D" uid="uid://dsnnac0xk0tfl" path="res://assets/images/gamepad/switch/switch_button_a.svg" id="1_bwo1l"]
+[ext_resource type="Texture2D" uid="uid://bvjmsnstaoq2v" path="res://assets/images/gamepad/switch/switch_buttons.svg" id="1_ww2e7"]
+[ext_resource type="Texture2D" uid="uid://cdvcck1mbmt87" path="res://assets/images/gamepad/switch/switch_buttons_down.svg" id="2_gavjx"]
+[ext_resource type="Texture2D" uid="uid://dicj4tpxknqai" path="res://assets/images/gamepad/switch/switch_button_home.svg" id="2_o4j1j"]
+[ext_resource type="Texture2D" uid="uid://d0nkpy8tk3f28" path="res://assets/images/gamepad/switch/switch_button_x.svg" id="3_ae6nc"]
+[ext_resource type="Texture2D" uid="uid://b4j53xuo8rosw" path="res://assets/images/gamepad/switch/switch_buttons_left.svg" id="3_k02em"]
+[ext_resource type="Texture2D" uid="uid://bnbk3lkeaqwfa" path="res://assets/images/gamepad/switch/switch_buttons_right.svg" id="4_w4xps"]
+[ext_resource type="Texture2D" uid="uid://ducpt6w14ol4i" path="res://assets/images/gamepad/switch/switch_buttons_up.svg" id="5_e3bby"]
+[ext_resource type="Texture2D" uid="uid://b21ssea6yir56" path="res://assets/images/gamepad/switch/switch_button_b.svg" id="5_jpu3i"]
+[ext_resource type="Texture2D" uid="uid://rgpis0qqwyn3" path="res://assets/images/gamepad/switch/switch_button_plus.svg" id="6_q5ufv"]
+[ext_resource type="Texture2D" uid="uid://ckwf0ko1ch08t" path="res://assets/images/gamepad/switch/switch_button_y.svg" id="7_e24lf"]
+[ext_resource type="Texture2D" uid="uid://cda8etpu56yjn" path="res://assets/images/gamepad/switch/switch_joycon_left_rotate.svg" id="8_5ade5"]
+[ext_resource type="Texture2D" uid="uid://d2ho4b7w2mdlb" path="res://assets/images/gamepad/switch/switch_button_l.svg" id="9_y7sje"]
+[ext_resource type="Texture2D" uid="uid://ruhfjlhtlik3" path="res://assets/images/gamepad/switch/switch_stick_l.svg" id="10_7ixoo"]
+[ext_resource type="Texture2D" uid="uid://d1xnwfo4kwgwe" path="res://assets/images/gamepad/switch/switch_stick_l_press.svg" id="11_sc443"]
+[ext_resource type="Texture2D" uid="uid://ri6vpuerb2jn" path="res://assets/images/gamepad/switch/switch_stick_l_down.svg" id="12_xl772"]
+[ext_resource type="Texture2D" uid="uid://dvdwtqdrgcx55" path="res://assets/images/gamepad/switch/switch_stick_l_left.svg" id="13_21edv"]
+[ext_resource type="Texture2D" uid="uid://ckdjvbxmun3hk" path="res://assets/images/gamepad/switch/switch_stick_l_right.svg" id="14_t7a81"]
+[ext_resource type="Texture2D" uid="uid://c54734rwsvi5y" path="res://assets/images/gamepad/switch/switch_stick_l_up.svg" id="15_c886y"]
+[ext_resource type="Texture2D" uid="uid://ysw3f4s0wckl" path="res://assets/images/gamepad/switch/switch_button_zl.svg" id="16_xvg34"]
+[ext_resource type="Texture2D" uid="uid://dh8gskvlf1y4n" path="res://assets/images/gamepad/switch/switch_button_r.svg" id="18_rb1n1"]
+[ext_resource type="Texture2D" uid="uid://bnr0q7kupfac8" path="res://assets/images/gamepad/switch/switch_stick_r.svg" id="19_royjt"]
+[ext_resource type="Texture2D" uid="uid://dalb0538ux4qy" path="res://assets/images/gamepad/switch/switch_stick_r_press.svg" id="20_o8e1o"]
+[ext_resource type="Texture2D" uid="uid://c37v6pn2p4pa7" path="res://assets/images/gamepad/switch/switch_stick_r_down.svg" id="21_m6t1r"]
+[ext_resource type="Texture2D" uid="uid://d0s0cx6bqiovg" path="res://assets/images/gamepad/switch/switch_stick_r_left.svg" id="22_4onjx"]
+[ext_resource type="Texture2D" uid="uid://dxycp3mj54mwc" path="res://assets/images/gamepad/switch/switch_stick_r_right.svg" id="23_rh7dk"]
+[ext_resource type="Texture2D" uid="uid://be6s7r6y3ndty" path="res://assets/images/gamepad/switch/switch_stick_r_up.svg" id="24_jvrdt"]
+[ext_resource type="Texture2D" uid="uid://cwkd4oyqs445d" path="res://assets/images/gamepad/switch/switch_button_zr.svg" id="25_pawt1"]
+[ext_resource type="Texture2D" uid="uid://brwy28sjw2pe8" path="res://assets/images/gamepad/switch/switch_button_sync.svg" id="26_3hoym"]
+[ext_resource type="Texture2D" uid="uid://f3dabljd057e" path="res://assets/images/gamepad/switch/switch_button_minus.svg" id="28_wn71f"]
[resource]
script = ExtResource("1_a16bb")
diff --git a/assets/gamepad/icon_mappings/oxp.tres b/assets/gamepad/icon_mappings/oxp.tres
index 540ca3cf9..f213f9e6c 100644
--- a/assets/gamepad/icon_mappings/oxp.tres
+++ b/assets/gamepad/icon_mappings/oxp.tres
@@ -1,36 +1,36 @@
[gd_resource type="Resource" script_class="InputIconMapping" load_steps=32 format=3 uid="uid://d0xd340cjsp72"]
-[ext_resource type="Texture2D" uid="uid://hmebqgl4qfmc" path="res://assets/images/gamepad/oxp/oxp-mini-a07.png" id="1_2cbux"]
-[ext_resource type="Texture2D" uid="uid://cdhd2pnbunvy3" path="res://assets/images/gamepad/xbox/xbox_dpad.svg" id="2_fdy21"]
-[ext_resource type="Texture2D" uid="uid://bju6gytlq2div" path="res://assets/images/gamepad/xbox/xbox_dpad_down.svg" id="3_imsyj"]
-[ext_resource type="Texture2D" uid="uid://candjw8elkekp" path="res://assets/images/gamepad/xbox/xbox_dpad_left.svg" id="4_tgha8"]
-[ext_resource type="Texture2D" uid="uid://dcpsb03pvu0vb" path="res://assets/images/gamepad/xbox/xbox_dpad_right.svg" id="5_m1y8h"]
-[ext_resource type="Texture2D" uid="uid://c6w5exkfdkkrr" path="res://assets/images/gamepad/xbox/xbox_dpad_up.svg" id="6_rp82k"]
-[ext_resource type="Texture2D" uid="uid://b3ofivkj5cwdd" path="res://assets/images/gamepad/oxp/b.png" id="7_5e6yx"]
-[ext_resource type="Texture2D" uid="uid://cu0fgwxtupy5y" path="res://assets/images/gamepad/oxp/home.png" id="8_s3lvh"]
-[ext_resource type="Texture2D" uid="uid://mtd8tfnbotgc" path="res://assets/images/gamepad/xbox/xbox_lb.svg" id="9_eiwti"]
-[ext_resource type="Texture2D" uid="uid://bdqfg27h5o836" path="res://assets/images/gamepad/xbox/xbox_stick_l.svg" id="10_6wqop"]
-[ext_resource type="Texture2D" uid="uid://dvv5grt45cows" path="res://assets/images/gamepad/xbox/xbox_stick_l_press.svg" id="11_0fasu"]
-[ext_resource type="Texture2D" uid="uid://dcumk3oqkyy7g" path="res://assets/images/gamepad/xbox/xbox_stick_l_down.svg" id="12_5ksa6"]
-[ext_resource type="Texture2D" uid="uid://dooej262t4g0x" path="res://assets/images/gamepad/xbox/xbox_stick_l_left.svg" id="13_g2uyl"]
-[ext_resource type="Texture2D" uid="uid://coltjh07der5" path="res://assets/images/gamepad/xbox/xbox_stick_l_right.svg" id="14_8dpbw"]
-[ext_resource type="Texture2D" uid="uid://b3xxbnyo2h20l" path="res://assets/images/gamepad/xbox/xbox_stick_l_up.svg" id="15_p3f62"]
-[ext_resource type="Texture2D" uid="uid://u3jonqoafyg6" path="res://assets/images/gamepad/xbox/xbox_lt.svg" id="16_ly5ym"]
-[ext_resource type="Texture2D" uid="uid://cfeud3gaq056l" path="res://assets/images/gamepad/oxp/y.png" id="17_io5hp"]
-[ext_resource type="Texture2D" uid="uid://55kdld1mn8sh" path="res://assets/images/gamepad/oxp/dots.png" id="18_2rhb4"]
-[ext_resource type="Texture2D" uid="uid://co3kg331knfu7" path="res://assets/images/gamepad/xbox/xbox_rb.svg" id="18_riyhh"]
-[ext_resource type="Texture2D" uid="uid://dw15y6xiuthpe" path="res://assets/images/gamepad/xbox/xbox_stick_r.svg" id="19_u0e7h"]
-[ext_resource type="Texture2D" uid="uid://de2kcqeakp3q0" path="res://assets/images/gamepad/xbox/xbox_stick_r_press.svg" id="20_6oyto"]
-[ext_resource type="Texture2D" uid="uid://d4iq63eypbf2s" path="res://assets/images/gamepad/xbox/xbox_stick_r_down.svg" id="21_x8g1e"]
-[ext_resource type="Texture2D" uid="uid://bus2l2lmd844f" path="res://assets/images/gamepad/xbox/xbox_stick_r_left.svg" id="22_kp76m"]
-[ext_resource type="Texture2D" uid="uid://cokparjjmwy8c" path="res://assets/images/gamepad/xbox/xbox_stick_r_right.svg" id="23_lsal5"]
-[ext_resource type="Texture2D" uid="uid://jn543ff1ak1c" path="res://assets/images/gamepad/xbox/xbox_stick_r_up.svg" id="24_5n5ek"]
-[ext_resource type="Texture2D" uid="uid://da8ojjv5vttou" path="res://assets/images/gamepad/xbox/xbox_rt.svg" id="25_pdf5n"]
+[ext_resource type="Texture2D" uid="uid://d224crt7h1b8l" path="res://assets/images/gamepad/oxp/oxp-mini-a07.png" id="1_2cbux"]
+[ext_resource type="Texture2D" uid="uid://di87v7xnlu4hd" path="res://assets/images/gamepad/xbox/xbox_dpad.svg" id="2_fdy21"]
+[ext_resource type="Texture2D" uid="uid://brqqse0hid6ki" path="res://assets/images/gamepad/xbox/xbox_dpad_down.svg" id="3_imsyj"]
+[ext_resource type="Texture2D" uid="uid://caqnkbu5b0u2q" path="res://assets/images/gamepad/xbox/xbox_dpad_left.svg" id="4_tgha8"]
+[ext_resource type="Texture2D" uid="uid://b5gektw3mgp1a" path="res://assets/images/gamepad/xbox/xbox_dpad_right.svg" id="5_m1y8h"]
+[ext_resource type="Texture2D" uid="uid://cjwqn3wttist" path="res://assets/images/gamepad/xbox/xbox_dpad_up.svg" id="6_rp82k"]
+[ext_resource type="Texture2D" uid="uid://c8cjp8mh52xh2" path="res://assets/images/gamepad/oxp/b.png" id="7_5e6yx"]
+[ext_resource type="Texture2D" uid="uid://c00vtor5dsj8n" path="res://assets/images/gamepad/oxp/home.png" id="8_s3lvh"]
+[ext_resource type="Texture2D" uid="uid://cwyi3if752xh6" path="res://assets/images/gamepad/xbox/xbox_lb.svg" id="9_eiwti"]
+[ext_resource type="Texture2D" uid="uid://dqx7njocf1aok" path="res://assets/images/gamepad/xbox/xbox_stick_l.svg" id="10_6wqop"]
+[ext_resource type="Texture2D" uid="uid://ckqaven4xmk16" path="res://assets/images/gamepad/xbox/xbox_stick_l_press.svg" id="11_0fasu"]
+[ext_resource type="Texture2D" uid="uid://c1bfw2axbcg1q" path="res://assets/images/gamepad/xbox/xbox_stick_l_down.svg" id="12_5ksa6"]
+[ext_resource type="Texture2D" uid="uid://c4iwtbyehtps2" path="res://assets/images/gamepad/xbox/xbox_stick_l_left.svg" id="13_g2uyl"]
+[ext_resource type="Texture2D" uid="uid://d4bfok8606fmv" path="res://assets/images/gamepad/xbox/xbox_stick_l_right.svg" id="14_8dpbw"]
+[ext_resource type="Texture2D" uid="uid://c7p0nhy4sh5wf" path="res://assets/images/gamepad/xbox/xbox_stick_l_up.svg" id="15_p3f62"]
+[ext_resource type="Texture2D" uid="uid://cg8r4ijx7641s" path="res://assets/images/gamepad/xbox/xbox_lt.svg" id="16_ly5ym"]
+[ext_resource type="Texture2D" uid="uid://dqhw0phvf3tre" path="res://assets/images/gamepad/oxp/y.png" id="17_io5hp"]
+[ext_resource type="Texture2D" uid="uid://wmris721srn5" path="res://assets/images/gamepad/oxp/dots.png" id="18_2rhb4"]
+[ext_resource type="Texture2D" uid="uid://ceiru5s4y3ghy" path="res://assets/images/gamepad/xbox/xbox_rb.svg" id="18_riyhh"]
+[ext_resource type="Texture2D" uid="uid://bjq76f76quyry" path="res://assets/images/gamepad/xbox/xbox_stick_r.svg" id="19_u0e7h"]
+[ext_resource type="Texture2D" uid="uid://5q4tjwvf7b8a" path="res://assets/images/gamepad/xbox/xbox_stick_r_press.svg" id="20_6oyto"]
+[ext_resource type="Texture2D" uid="uid://cu3ptt3kea56h" path="res://assets/images/gamepad/xbox/xbox_stick_r_down.svg" id="21_x8g1e"]
+[ext_resource type="Texture2D" uid="uid://s4x7rp50eub5" path="res://assets/images/gamepad/xbox/xbox_stick_r_left.svg" id="22_kp76m"]
+[ext_resource type="Texture2D" uid="uid://kfqb1dr0735v" path="res://assets/images/gamepad/xbox/xbox_stick_r_right.svg" id="23_lsal5"]
+[ext_resource type="Texture2D" uid="uid://o0xrox1l5sae" path="res://assets/images/gamepad/xbox/xbox_stick_r_up.svg" id="24_5n5ek"]
+[ext_resource type="Texture2D" uid="uid://brt5gm71iv3u4" path="res://assets/images/gamepad/xbox/xbox_rt.svg" id="25_pdf5n"]
[ext_resource type="Script" path="res://core/systems/input/input_icon_mapping.gd" id="26_iuti6"]
-[ext_resource type="Texture2D" uid="uid://ce732ysw0pjo1" path="res://assets/images/gamepad/xbox/xbox_button_view.svg" id="27_7206a"]
-[ext_resource type="Texture2D" uid="uid://ddj7iydr5c04r" path="res://assets/images/gamepad/oxp/a.png" id="28_1faky"]
-[ext_resource type="Texture2D" uid="uid://dagfma4wnmvw8" path="res://assets/images/gamepad/xbox/xbox_button_menu.svg" id="29_vuglh"]
-[ext_resource type="Texture2D" uid="uid://ddma44dieeu0c" path="res://assets/images/gamepad/oxp/x.png" id="30_sjmia"]
+[ext_resource type="Texture2D" uid="uid://cws272by4n8r7" path="res://assets/images/gamepad/xbox/xbox_button_view.svg" id="27_7206a"]
+[ext_resource type="Texture2D" uid="uid://vmqhe01e4iit" path="res://assets/images/gamepad/oxp/a.png" id="28_1faky"]
+[ext_resource type="Texture2D" uid="uid://ckk2my0j71i3r" path="res://assets/images/gamepad/xbox/xbox_button_menu.svg" id="29_vuglh"]
+[ext_resource type="Texture2D" uid="uid://cgsn52xbh5g7n" path="res://assets/images/gamepad/oxp/x.png" id="30_sjmia"]
[resource]
script = ExtResource("26_iuti6")
diff --git a/assets/gamepad/icon_mappings/ps4.tres b/assets/gamepad/icon_mappings/ps4.tres
index b9ec01048..578a82a08 100644
--- a/assets/gamepad/icon_mappings/ps4.tres
+++ b/assets/gamepad/icon_mappings/ps4.tres
@@ -1,37 +1,37 @@
[gd_resource type="Resource" script_class="InputIconMapping" load_steps=33 format=3 uid="uid://d1wwvmphhodm0"]
[ext_resource type="Script" path="res://core/systems/input/input_icon_mapping.gd" id="1_6dodo"]
-[ext_resource type="Texture2D" uid="uid://cgt42jlee1t3" path="res://assets/images/gamepad/playstation/playstation4_touchpad_touch.svg" id="1_dgojl"]
-[ext_resource type="Texture2D" uid="uid://brf1l7pyedsg6" path="res://assets/images/gamepad/playstation/PS4_Diagram_Simple.png" id="1_xfnbr"]
-[ext_resource type="Texture2D" uid="uid://dcysxvygs0t0b" path="res://assets/images/gamepad/playstation/playstation_button_color_circle.svg" id="2_boi0e"]
-[ext_resource type="Texture2D" uid="uid://d1bn7vfymb8h7" path="res://assets/images/gamepad/playstation/playstation_dpad.svg" id="2_ksv3d"]
-[ext_resource type="Texture2D" uid="uid://b8t8udyk7f2sy" path="res://assets/images/gamepad/playstation/playstation_dpad_down.svg" id="3_lbw7u"]
-[ext_resource type="Texture2D" uid="uid://dt6pmeivafjuh" path="res://assets/images/gamepad/playstation/guide.svg" id="3_tihua"]
-[ext_resource type="Texture2D" uid="uid://bucd4u3xhdkn5" path="res://assets/images/gamepad/playstation/playstation_dpad_left.svg" id="4_43xit"]
-[ext_resource type="Texture2D" uid="uid://crv4tl33mg881" path="res://assets/images/gamepad/playstation/playstation_button_color_triangle.svg" id="4_t0rx5"]
-[ext_resource type="Texture2D" uid="uid://nva4um5gnp46" path="res://assets/images/gamepad/playstation/playstation_dpad_right.svg" id="5_bxvhl"]
-[ext_resource type="Texture2D" uid="uid://dvckjbn44kqh4" path="res://assets/images/gamepad/playstation/playstation_dpad_up.svg" id="6_01cs4"]
-[ext_resource type="Texture2D" uid="uid://cvx6k287vtlda" path="res://assets/images/gamepad/playstation/playstation4_button_share.svg" id="6_eb1f1"]
-[ext_resource type="Texture2D" uid="uid://d3b15ae2w8u04" path="res://assets/images/gamepad/playstation/playstation_button_color_cross.svg" id="7_1eaue"]
-[ext_resource type="Texture2D" uid="uid://bbekpvxt1viwr" path="res://assets/images/gamepad/playstation/playstation4_button_options.svg" id="8_is2y1"]
-[ext_resource type="Texture2D" uid="uid://ce50wyq1ctdg3" path="res://assets/images/gamepad/playstation/playstation_trigger_l1.svg" id="9_2i8h4"]
-[ext_resource type="Texture2D" uid="uid://cwmll8jpe01x1" path="res://assets/images/gamepad/playstation/playstation_button_color_square.svg" id="9_41xra"]
-[ext_resource type="Texture2D" uid="uid://bq64rpsb1usfh" path="res://assets/images/gamepad/playstation/playstation_stick_l.svg" id="10_sg1b0"]
-[ext_resource type="Texture2D" uid="uid://bi2887g54x4ym" path="res://assets/images/gamepad/generic/gyro.png" id="10_tdin3"]
-[ext_resource type="Texture2D" uid="uid://dbf2kolrjqlsk" path="res://assets/images/gamepad/playstation/playstation_stick_l_press.svg" id="11_j8ffx"]
-[ext_resource type="Texture2D" uid="uid://cv1gammxiedb" path="res://assets/images/gamepad/playstation/playstation_stick_l_down.svg" id="12_vf35o"]
-[ext_resource type="Texture2D" uid="uid://d22o4cxlcni3q" path="res://assets/images/gamepad/playstation/playstation_stick_l_left.svg" id="13_civhm"]
-[ext_resource type="Texture2D" uid="uid://0bomms2ipyct" path="res://assets/images/gamepad/playstation/playstation_stick_l_right.svg" id="14_vpg31"]
-[ext_resource type="Texture2D" uid="uid://ds60ucempaqtc" path="res://assets/images/gamepad/playstation/playstation_stick_l_up.svg" id="15_obvm1"]
-[ext_resource type="Texture2D" uid="uid://d0pbaqstutkli" path="res://assets/images/gamepad/playstation/playstation_trigger_l2.svg" id="16_0u2wr"]
-[ext_resource type="Texture2D" uid="uid://drbydhj23dk4v" path="res://assets/images/gamepad/playstation/playstation_trigger_r1.svg" id="18_mt27f"]
-[ext_resource type="Texture2D" uid="uid://byrtduc2ys2gd" path="res://assets/images/gamepad/playstation/playstation_stick_r.svg" id="19_cv760"]
-[ext_resource type="Texture2D" uid="uid://dnc8ia8fbc72f" path="res://assets/images/gamepad/playstation/playstation_stick_r_press.svg" id="20_wv7w2"]
-[ext_resource type="Texture2D" uid="uid://b0hdbw4qo4nl2" path="res://assets/images/gamepad/playstation/playstation_stick_r_down.svg" id="21_64cn1"]
-[ext_resource type="Texture2D" uid="uid://dedewmjipppck" path="res://assets/images/gamepad/playstation/playstation_stick_r_left.svg" id="22_6k3lc"]
-[ext_resource type="Texture2D" uid="uid://d2f87ubl8ut4t" path="res://assets/images/gamepad/playstation/playstation_stick_r_right.svg" id="23_a3gna"]
-[ext_resource type="Texture2D" uid="uid://cvjxqt1lsfp1t" path="res://assets/images/gamepad/playstation/playstation_stick_r_up.svg" id="24_hoi2y"]
-[ext_resource type="Texture2D" uid="uid://botqou7j5tw5i" path="res://assets/images/gamepad/playstation/playstation_trigger_r2.svg" id="25_t4gxs"]
+[ext_resource type="Texture2D" uid="uid://clihwqudrnv5k" path="res://assets/images/gamepad/playstation/playstation4_touchpad_touch.svg" id="1_dgojl"]
+[ext_resource type="Texture2D" uid="uid://b6ebettxxbmu1" path="res://assets/images/gamepad/playstation/PS4_Diagram_Simple.png" id="1_xfnbr"]
+[ext_resource type="Texture2D" uid="uid://b1wo28cyd80ov" path="res://assets/images/gamepad/playstation/playstation_button_color_circle.svg" id="2_boi0e"]
+[ext_resource type="Texture2D" uid="uid://ua3iri55e4go" path="res://assets/images/gamepad/playstation/playstation_dpad.svg" id="2_ksv3d"]
+[ext_resource type="Texture2D" uid="uid://byblaf3dx4by6" path="res://assets/images/gamepad/playstation/playstation_dpad_down.svg" id="3_lbw7u"]
+[ext_resource type="Texture2D" uid="uid://b6qllts4hg3my" path="res://assets/images/gamepad/playstation/guide.svg" id="3_tihua"]
+[ext_resource type="Texture2D" uid="uid://bmuqx6jxetdp1" path="res://assets/images/gamepad/playstation/playstation_dpad_left.svg" id="4_43xit"]
+[ext_resource type="Texture2D" uid="uid://2rjhdg632n1f" path="res://assets/images/gamepad/playstation/playstation_button_color_triangle.svg" id="4_t0rx5"]
+[ext_resource type="Texture2D" uid="uid://cxhc0rxkyqf2g" path="res://assets/images/gamepad/playstation/playstation_dpad_right.svg" id="5_bxvhl"]
+[ext_resource type="Texture2D" uid="uid://da1vcs31c68sx" path="res://assets/images/gamepad/playstation/playstation_dpad_up.svg" id="6_01cs4"]
+[ext_resource type="Texture2D" uid="uid://bb0cv3hsg3y0v" path="res://assets/images/gamepad/playstation/playstation4_button_share.svg" id="6_eb1f1"]
+[ext_resource type="Texture2D" uid="uid://dwv1scwq0mlr2" path="res://assets/images/gamepad/playstation/playstation_button_color_cross.svg" id="7_1eaue"]
+[ext_resource type="Texture2D" uid="uid://ci7bqueqpt20u" path="res://assets/images/gamepad/playstation/playstation4_button_options.svg" id="8_is2y1"]
+[ext_resource type="Texture2D" uid="uid://bkya1ndod3v1j" path="res://assets/images/gamepad/playstation/playstation_trigger_l1.svg" id="9_2i8h4"]
+[ext_resource type="Texture2D" uid="uid://brniycjajdi03" path="res://assets/images/gamepad/playstation/playstation_button_color_square.svg" id="9_41xra"]
+[ext_resource type="Texture2D" uid="uid://d0hn6un6byklr" path="res://assets/images/gamepad/playstation/playstation_stick_l.svg" id="10_sg1b0"]
+[ext_resource type="Texture2D" uid="uid://do8ip0e6vs5h5" path="res://assets/images/gamepad/generic/gyro.png" id="10_tdin3"]
+[ext_resource type="Texture2D" uid="uid://cmijt22flcpda" path="res://assets/images/gamepad/playstation/playstation_stick_l_press.svg" id="11_j8ffx"]
+[ext_resource type="Texture2D" uid="uid://od86dbeeirmp" path="res://assets/images/gamepad/playstation/playstation_stick_l_down.svg" id="12_vf35o"]
+[ext_resource type="Texture2D" uid="uid://bufyl7xm4mcij" path="res://assets/images/gamepad/playstation/playstation_stick_l_left.svg" id="13_civhm"]
+[ext_resource type="Texture2D" uid="uid://bj8fx1k8ectnx" path="res://assets/images/gamepad/playstation/playstation_stick_l_right.svg" id="14_vpg31"]
+[ext_resource type="Texture2D" uid="uid://c8uwdhedkaonn" path="res://assets/images/gamepad/playstation/playstation_stick_l_up.svg" id="15_obvm1"]
+[ext_resource type="Texture2D" uid="uid://dcnvqtiuawl0c" path="res://assets/images/gamepad/playstation/playstation_trigger_l2.svg" id="16_0u2wr"]
+[ext_resource type="Texture2D" uid="uid://f2ge3igc0h6g" path="res://assets/images/gamepad/playstation/playstation_trigger_r1.svg" id="18_mt27f"]
+[ext_resource type="Texture2D" uid="uid://dlh3o8lhabxmv" path="res://assets/images/gamepad/playstation/playstation_stick_r.svg" id="19_cv760"]
+[ext_resource type="Texture2D" uid="uid://ctsqjuqhj0soc" path="res://assets/images/gamepad/playstation/playstation_stick_r_press.svg" id="20_wv7w2"]
+[ext_resource type="Texture2D" uid="uid://do6olohpve0fm" path="res://assets/images/gamepad/playstation/playstation_stick_r_down.svg" id="21_64cn1"]
+[ext_resource type="Texture2D" uid="uid://7uwvswwxu8u5" path="res://assets/images/gamepad/playstation/playstation_stick_r_left.svg" id="22_6k3lc"]
+[ext_resource type="Texture2D" uid="uid://d2t2wxh6fduon" path="res://assets/images/gamepad/playstation/playstation_stick_r_right.svg" id="23_a3gna"]
+[ext_resource type="Texture2D" uid="uid://csve53s1buixo" path="res://assets/images/gamepad/playstation/playstation_stick_r_up.svg" id="24_hoi2y"]
+[ext_resource type="Texture2D" uid="uid://doeikq8t8xfny" path="res://assets/images/gamepad/playstation/playstation_trigger_r2.svg" id="25_t4gxs"]
[resource]
script = ExtResource("1_6dodo")
diff --git a/assets/gamepad/icon_mappings/ps5.tres b/assets/gamepad/icon_mappings/ps5.tres
index ee3ce2d20..65458bd08 100644
--- a/assets/gamepad/icon_mappings/ps5.tres
+++ b/assets/gamepad/icon_mappings/ps5.tres
@@ -1,27 +1,27 @@
[gd_resource type="Resource" script_class="InputIconMapping" load_steps=23 format=3 uid="uid://bmquv6m1c6ba1"]
[ext_resource type="Script" path="res://core/systems/input/input_icon_mapping.gd" id="1_ba5rj"]
-[ext_resource type="Texture2D" uid="uid://biu5qfv6e1mq8" path="res://assets/images/gamepad/playstation/PS5_Diagram_Simple.png" id="1_brns1"]
-[ext_resource type="Texture2D" uid="uid://bj0qk2s5mxkkd" path="res://assets/images/gamepad/playstation/playstation5_touchpad_touch.svg" id="1_l1iq3"]
-[ext_resource type="Texture2D" uid="uid://dcysxvygs0t0b" path="res://assets/images/gamepad/playstation/playstation_button_color_circle.svg" id="2_6ey1f"]
-[ext_resource type="Texture2D" uid="uid://dt6pmeivafjuh" path="res://assets/images/gamepad/playstation/guide.svg" id="3_3ltu8"]
-[ext_resource type="Texture2D" uid="uid://crv4tl33mg881" path="res://assets/images/gamepad/playstation/playstation_button_color_triangle.svg" id="3_c5wlt"]
-[ext_resource type="Texture2D" uid="uid://d1bn7vfymb8h7" path="res://assets/images/gamepad/playstation/playstation_dpad.svg" id="3_yh60b"]
-[ext_resource type="Texture2D" uid="uid://b8t8udyk7f2sy" path="res://assets/images/gamepad/playstation/playstation_dpad_down.svg" id="4_wgvj5"]
-[ext_resource type="Texture2D" uid="uid://d3b15ae2w8u04" path="res://assets/images/gamepad/playstation/playstation_button_color_cross.svg" id="5_bn8cu"]
-[ext_resource type="Texture2D" uid="uid://bucd4u3xhdkn5" path="res://assets/images/gamepad/playstation/playstation_dpad_left.svg" id="5_k05x8"]
-[ext_resource type="Texture2D" uid="uid://cwmll8jpe01x1" path="res://assets/images/gamepad/playstation/playstation_button_color_square.svg" id="6_ed18o"]
-[ext_resource type="Texture2D" uid="uid://nva4um5gnp46" path="res://assets/images/gamepad/playstation/playstation_dpad_right.svg" id="6_vgnrb"]
-[ext_resource type="Texture2D" uid="uid://y4ntbxk5qrpo" path="res://assets/images/gamepad/playstation/playstation5_button_create.svg" id="7_klhod"]
-[ext_resource type="Texture2D" uid="uid://dvckjbn44kqh4" path="res://assets/images/gamepad/playstation/playstation_dpad_up.svg" id="7_paptw"]
-[ext_resource type="Texture2D" uid="uid://8vgoicywpflx" path="res://assets/images/gamepad/playstation/playstation5_button_options.svg" id="9_sj432"]
-[ext_resource type="Texture2D" uid="uid://bi2887g54x4ym" path="res://assets/images/gamepad/generic/gyro.png" id="10_ctm85"]
-[ext_resource type="Texture2D" uid="uid://ce50wyq1ctdg3" path="res://assets/images/gamepad/playstation/playstation_trigger_l1.svg" id="10_gaqt5"]
-[ext_resource type="Texture2D" uid="uid://bq64rpsb1usfh" path="res://assets/images/gamepad/playstation/playstation_stick_l.svg" id="11_mlyq1"]
-[ext_resource type="Texture2D" uid="uid://d0pbaqstutkli" path="res://assets/images/gamepad/playstation/playstation_trigger_l2.svg" id="12_0m5i4"]
-[ext_resource type="Texture2D" uid="uid://drbydhj23dk4v" path="res://assets/images/gamepad/playstation/playstation_trigger_r1.svg" id="14_6vcxa"]
-[ext_resource type="Texture2D" uid="uid://byrtduc2ys2gd" path="res://assets/images/gamepad/playstation/playstation_stick_r.svg" id="15_chusf"]
-[ext_resource type="Texture2D" uid="uid://botqou7j5tw5i" path="res://assets/images/gamepad/playstation/playstation_trigger_r2.svg" id="16_5vbcf"]
+[ext_resource type="Texture2D" uid="uid://devahu3vo6pdj" path="res://assets/images/gamepad/playstation/PS5_Diagram_Simple.png" id="1_brns1"]
+[ext_resource type="Texture2D" uid="uid://do6nap60p4cs6" path="res://assets/images/gamepad/playstation/playstation5_touchpad_touch.svg" id="1_l1iq3"]
+[ext_resource type="Texture2D" uid="uid://b1wo28cyd80ov" path="res://assets/images/gamepad/playstation/playstation_button_color_circle.svg" id="2_6ey1f"]
+[ext_resource type="Texture2D" uid="uid://b6qllts4hg3my" path="res://assets/images/gamepad/playstation/guide.svg" id="3_3ltu8"]
+[ext_resource type="Texture2D" uid="uid://2rjhdg632n1f" path="res://assets/images/gamepad/playstation/playstation_button_color_triangle.svg" id="3_c5wlt"]
+[ext_resource type="Texture2D" uid="uid://ua3iri55e4go" path="res://assets/images/gamepad/playstation/playstation_dpad.svg" id="3_yh60b"]
+[ext_resource type="Texture2D" uid="uid://byblaf3dx4by6" path="res://assets/images/gamepad/playstation/playstation_dpad_down.svg" id="4_wgvj5"]
+[ext_resource type="Texture2D" uid="uid://dwv1scwq0mlr2" path="res://assets/images/gamepad/playstation/playstation_button_color_cross.svg" id="5_bn8cu"]
+[ext_resource type="Texture2D" uid="uid://bmuqx6jxetdp1" path="res://assets/images/gamepad/playstation/playstation_dpad_left.svg" id="5_k05x8"]
+[ext_resource type="Texture2D" uid="uid://brniycjajdi03" path="res://assets/images/gamepad/playstation/playstation_button_color_square.svg" id="6_ed18o"]
+[ext_resource type="Texture2D" uid="uid://cxhc0rxkyqf2g" path="res://assets/images/gamepad/playstation/playstation_dpad_right.svg" id="6_vgnrb"]
+[ext_resource type="Texture2D" uid="uid://lsf27o58vimw" path="res://assets/images/gamepad/playstation/playstation5_button_create.svg" id="7_klhod"]
+[ext_resource type="Texture2D" uid="uid://da1vcs31c68sx" path="res://assets/images/gamepad/playstation/playstation_dpad_up.svg" id="7_paptw"]
+[ext_resource type="Texture2D" uid="uid://bn6oh5im6dg0t" path="res://assets/images/gamepad/playstation/playstation5_button_options.svg" id="9_sj432"]
+[ext_resource type="Texture2D" uid="uid://do8ip0e6vs5h5" path="res://assets/images/gamepad/generic/gyro.png" id="10_ctm85"]
+[ext_resource type="Texture2D" uid="uid://bkya1ndod3v1j" path="res://assets/images/gamepad/playstation/playstation_trigger_l1.svg" id="10_gaqt5"]
+[ext_resource type="Texture2D" uid="uid://d0hn6un6byklr" path="res://assets/images/gamepad/playstation/playstation_stick_l.svg" id="11_mlyq1"]
+[ext_resource type="Texture2D" uid="uid://dcnvqtiuawl0c" path="res://assets/images/gamepad/playstation/playstation_trigger_l2.svg" id="12_0m5i4"]
+[ext_resource type="Texture2D" uid="uid://f2ge3igc0h6g" path="res://assets/images/gamepad/playstation/playstation_trigger_r1.svg" id="14_6vcxa"]
+[ext_resource type="Texture2D" uid="uid://dlh3o8lhabxmv" path="res://assets/images/gamepad/playstation/playstation_stick_r.svg" id="15_chusf"]
+[ext_resource type="Texture2D" uid="uid://doeikq8t8xfny" path="res://assets/images/gamepad/playstation/playstation_trigger_r2.svg" id="16_5vbcf"]
[resource]
script = ExtResource("1_ba5rj")
diff --git a/assets/gamepad/icon_mappings/rog_ally.tres b/assets/gamepad/icon_mappings/rog_ally.tres
index b4de5ac23..c176eba6d 100644
--- a/assets/gamepad/icon_mappings/rog_ally.tres
+++ b/assets/gamepad/icon_mappings/rog_ally.tres
@@ -1,39 +1,39 @@
[gd_resource type="Resource" script_class="InputIconMapping" load_steps=35 format=3 uid="uid://b1nd8y2yx8yq6"]
-[ext_resource type="Texture2D" uid="uid://xm6mg1kykt88" path="res://assets/images/gamepad/rog-ally/diagram.png" id="1_01w5b"]
-[ext_resource type="Texture2D" uid="uid://dn8i3gpeijgu1" path="res://assets/images/gamepad/xbox/xbox_dpad_round.svg" id="2_ujiwl"]
-[ext_resource type="Texture2D" uid="uid://dwv3f88h7uaq7" path="res://assets/images/gamepad/xbox/xbox_dpad_round_down.svg" id="3_fu5eu"]
-[ext_resource type="Texture2D" uid="uid://fmnwuu2ym0m8" path="res://assets/images/gamepad/xbox/xbox_dpad_round_left.svg" id="4_vlt4b"]
-[ext_resource type="Texture2D" uid="uid://cboy1enwvdeoy" path="res://assets/images/gamepad/xbox/xbox_dpad_round_right.svg" id="5_rd21s"]
-[ext_resource type="Texture2D" uid="uid://ba64eulr61afh" path="res://assets/images/gamepad/xbox/xbox_dpad_round_up.svg" id="6_e3vuo"]
-[ext_resource type="Texture2D" uid="uid://bqho0a0sr6u1j" path="res://assets/images/gamepad/xbox/xbox_button_color_b.svg" id="7_5kd38"]
-[ext_resource type="Texture2D" uid="uid://brctkdj250hpv" path="res://assets/images/gamepad/rog-ally/ally_button_guide.svg" id="8_3soja"]
-[ext_resource type="Texture2D" uid="uid://mtd8tfnbotgc" path="res://assets/images/gamepad/xbox/xbox_lb.svg" id="9_ex1hq"]
-[ext_resource type="Texture2D" uid="uid://bi2887g54x4ym" path="res://assets/images/gamepad/generic/gyro.png" id="9_vvq27"]
-[ext_resource type="Texture2D" uid="uid://bdqfg27h5o836" path="res://assets/images/gamepad/xbox/xbox_stick_l.svg" id="10_e71eg"]
-[ext_resource type="Texture2D" uid="uid://d3nga7v4ldmap" path="res://assets/images/gamepad/rog-ally/ally_button_m2.svg" id="10_t6mry"]
-[ext_resource type="Texture2D" uid="uid://dvv5grt45cows" path="res://assets/images/gamepad/xbox/xbox_stick_l_press.svg" id="11_iyaus"]
-[ext_resource type="Texture2D" uid="uid://dcumk3oqkyy7g" path="res://assets/images/gamepad/xbox/xbox_stick_l_down.svg" id="12_c3tu1"]
-[ext_resource type="Texture2D" uid="uid://dooej262t4g0x" path="res://assets/images/gamepad/xbox/xbox_stick_l_left.svg" id="13_edtti"]
-[ext_resource type="Texture2D" uid="uid://coltjh07der5" path="res://assets/images/gamepad/xbox/xbox_stick_l_right.svg" id="14_efnr7"]
-[ext_resource type="Texture2D" uid="uid://b3xxbnyo2h20l" path="res://assets/images/gamepad/xbox/xbox_stick_l_up.svg" id="15_i2tmb"]
-[ext_resource type="Texture2D" uid="uid://u3jonqoafyg6" path="res://assets/images/gamepad/xbox/xbox_lt.svg" id="16_isy1r"]
-[ext_resource type="Texture2D" uid="uid://ddpudi00yulrx" path="res://assets/images/gamepad/xbox/xbox_button_color_y.svg" id="17_jr7kr"]
-[ext_resource type="Texture2D" uid="uid://co3kg331knfu7" path="res://assets/images/gamepad/xbox/xbox_rb.svg" id="18_4llry"]
-[ext_resource type="Texture2D" uid="uid://srjhf8dp2cpg" path="res://assets/images/gamepad/rog-ally/ally_button_quick.svg" id="18_gra38"]
-[ext_resource type="Texture2D" uid="uid://dw15y6xiuthpe" path="res://assets/images/gamepad/xbox/xbox_stick_r.svg" id="19_rgqul"]
-[ext_resource type="Texture2D" uid="uid://de2kcqeakp3q0" path="res://assets/images/gamepad/xbox/xbox_stick_r_press.svg" id="20_sg7ew"]
-[ext_resource type="Texture2D" uid="uid://obqv3ikblrmx" path="res://assets/images/gamepad/rog-ally/ally_button_m1.svg" id="21_4aapa"]
-[ext_resource type="Texture2D" uid="uid://d4iq63eypbf2s" path="res://assets/images/gamepad/xbox/xbox_stick_r_down.svg" id="21_rfair"]
-[ext_resource type="Texture2D" uid="uid://bus2l2lmd844f" path="res://assets/images/gamepad/xbox/xbox_stick_r_left.svg" id="22_fvge1"]
-[ext_resource type="Texture2D" uid="uid://cokparjjmwy8c" path="res://assets/images/gamepad/xbox/xbox_stick_r_right.svg" id="23_p32gu"]
-[ext_resource type="Texture2D" uid="uid://jn543ff1ak1c" path="res://assets/images/gamepad/xbox/xbox_stick_r_up.svg" id="24_2bmwh"]
-[ext_resource type="Texture2D" uid="uid://da8ojjv5vttou" path="res://assets/images/gamepad/xbox/xbox_rt.svg" id="25_1q8wd"]
+[ext_resource type="Texture2D" uid="uid://c5tmyp3bdtksr" path="res://assets/images/gamepad/rog-ally/diagram.png" id="1_01w5b"]
+[ext_resource type="Texture2D" uid="uid://n4t36xrl15ux" path="res://assets/images/gamepad/xbox/xbox_dpad_round.svg" id="2_ujiwl"]
+[ext_resource type="Texture2D" uid="uid://bxovdah6vnpsn" path="res://assets/images/gamepad/xbox/xbox_dpad_round_down.svg" id="3_fu5eu"]
+[ext_resource type="Texture2D" uid="uid://qhwj81sv67l4" path="res://assets/images/gamepad/xbox/xbox_dpad_round_left.svg" id="4_vlt4b"]
+[ext_resource type="Texture2D" uid="uid://b1uo5130s6gfw" path="res://assets/images/gamepad/xbox/xbox_dpad_round_right.svg" id="5_rd21s"]
+[ext_resource type="Texture2D" uid="uid://dqk82r4up56mh" path="res://assets/images/gamepad/xbox/xbox_dpad_round_up.svg" id="6_e3vuo"]
+[ext_resource type="Texture2D" uid="uid://dfby3iiksln2e" path="res://assets/images/gamepad/xbox/xbox_button_color_b.svg" id="7_5kd38"]
+[ext_resource type="Texture2D" uid="uid://cl1gl3j47wds5" path="res://assets/images/gamepad/rog-ally/ally_button_guide.svg" id="8_3soja"]
+[ext_resource type="Texture2D" uid="uid://cwyi3if752xh6" path="res://assets/images/gamepad/xbox/xbox_lb.svg" id="9_ex1hq"]
+[ext_resource type="Texture2D" uid="uid://do8ip0e6vs5h5" path="res://assets/images/gamepad/generic/gyro.png" id="9_vvq27"]
+[ext_resource type="Texture2D" uid="uid://dqx7njocf1aok" path="res://assets/images/gamepad/xbox/xbox_stick_l.svg" id="10_e71eg"]
+[ext_resource type="Texture2D" uid="uid://74k3jdksgydd" path="res://assets/images/gamepad/rog-ally/ally_button_m2.svg" id="10_t6mry"]
+[ext_resource type="Texture2D" uid="uid://ckqaven4xmk16" path="res://assets/images/gamepad/xbox/xbox_stick_l_press.svg" id="11_iyaus"]
+[ext_resource type="Texture2D" uid="uid://c1bfw2axbcg1q" path="res://assets/images/gamepad/xbox/xbox_stick_l_down.svg" id="12_c3tu1"]
+[ext_resource type="Texture2D" uid="uid://c4iwtbyehtps2" path="res://assets/images/gamepad/xbox/xbox_stick_l_left.svg" id="13_edtti"]
+[ext_resource type="Texture2D" uid="uid://d4bfok8606fmv" path="res://assets/images/gamepad/xbox/xbox_stick_l_right.svg" id="14_efnr7"]
+[ext_resource type="Texture2D" uid="uid://c7p0nhy4sh5wf" path="res://assets/images/gamepad/xbox/xbox_stick_l_up.svg" id="15_i2tmb"]
+[ext_resource type="Texture2D" uid="uid://cg8r4ijx7641s" path="res://assets/images/gamepad/xbox/xbox_lt.svg" id="16_isy1r"]
+[ext_resource type="Texture2D" uid="uid://b81pjmldtt10s" path="res://assets/images/gamepad/xbox/xbox_button_color_y.svg" id="17_jr7kr"]
+[ext_resource type="Texture2D" uid="uid://ceiru5s4y3ghy" path="res://assets/images/gamepad/xbox/xbox_rb.svg" id="18_4llry"]
+[ext_resource type="Texture2D" uid="uid://dg7xaotlsxoix" path="res://assets/images/gamepad/rog-ally/ally_button_quick.svg" id="18_gra38"]
+[ext_resource type="Texture2D" uid="uid://bjq76f76quyry" path="res://assets/images/gamepad/xbox/xbox_stick_r.svg" id="19_rgqul"]
+[ext_resource type="Texture2D" uid="uid://5q4tjwvf7b8a" path="res://assets/images/gamepad/xbox/xbox_stick_r_press.svg" id="20_sg7ew"]
+[ext_resource type="Texture2D" uid="uid://bwqadttdisdkl" path="res://assets/images/gamepad/rog-ally/ally_button_m1.svg" id="21_4aapa"]
+[ext_resource type="Texture2D" uid="uid://cu3ptt3kea56h" path="res://assets/images/gamepad/xbox/xbox_stick_r_down.svg" id="21_rfair"]
+[ext_resource type="Texture2D" uid="uid://s4x7rp50eub5" path="res://assets/images/gamepad/xbox/xbox_stick_r_left.svg" id="22_fvge1"]
+[ext_resource type="Texture2D" uid="uid://kfqb1dr0735v" path="res://assets/images/gamepad/xbox/xbox_stick_r_right.svg" id="23_p32gu"]
+[ext_resource type="Texture2D" uid="uid://o0xrox1l5sae" path="res://assets/images/gamepad/xbox/xbox_stick_r_up.svg" id="24_2bmwh"]
+[ext_resource type="Texture2D" uid="uid://brt5gm71iv3u4" path="res://assets/images/gamepad/xbox/xbox_rt.svg" id="25_1q8wd"]
[ext_resource type="Script" path="res://core/systems/input/input_icon_mapping.gd" id="26_3rfes"]
-[ext_resource type="Texture2D" uid="uid://dyemqkvdtk43e" path="res://assets/images/gamepad/xbox/xbox_button_color_a.svg" id="29_10lmq"]
-[ext_resource type="Texture2D" uid="uid://cu0vttshpc7ui" path="res://assets/images/gamepad/rog-ally/ally_button_view.svg" id="29_ecr88"]
-[ext_resource type="Texture2D" uid="uid://csxxwf7pgahkb" path="res://assets/images/gamepad/rog-ally/ally_button_menu.svg" id="31_d6bvl"]
-[ext_resource type="Texture2D" uid="uid://cuvx61nakiaoi" path="res://assets/images/gamepad/xbox/xbox_button_color_x.svg" id="31_dqvdl"]
+[ext_resource type="Texture2D" uid="uid://cxvxwgt1vox0" path="res://assets/images/gamepad/xbox/xbox_button_color_a.svg" id="29_10lmq"]
+[ext_resource type="Texture2D" uid="uid://bcrthlw3xno0p" path="res://assets/images/gamepad/rog-ally/ally_button_view.svg" id="29_ecr88"]
+[ext_resource type="Texture2D" uid="uid://d4gi4bucbgyhv" path="res://assets/images/gamepad/rog-ally/ally_button_menu.svg" id="31_d6bvl"]
+[ext_resource type="Texture2D" uid="uid://ojrh7msglai0" path="res://assets/images/gamepad/xbox/xbox_button_color_x.svg" id="31_dqvdl"]
[resource]
script = ExtResource("26_3rfes")
diff --git a/assets/gamepad/icon_mappings/steam.tres b/assets/gamepad/icon_mappings/steam.tres
index 1afab2899..ce078b01b 100644
--- a/assets/gamepad/icon_mappings/steam.tres
+++ b/assets/gamepad/icon_mappings/steam.tres
@@ -1,29 +1,29 @@
[gd_resource type="Resource" script_class="InputIconMapping" load_steps=25 format=3 uid="uid://bgm0ymdturbr6"]
-[ext_resource type="Texture2D" uid="uid://c8b8706k0iryj" path="res://assets/images/gamepad/steam/controller_steam.svg" id="1_6gggn"]
+[ext_resource type="Texture2D" uid="uid://cst2i5us0vdjy" path="res://assets/images/gamepad/steam/controller_steam.svg" id="1_6gggn"]
[ext_resource type="Script" path="res://core/systems/input/input_icon_mapping.gd" id="1_vsxmp"]
-[ext_resource type="Texture2D" uid="uid://dnia1n0cogcvv" path="res://assets/images/gamepad/steam/steam_dpad.svg" id="2_dr285"]
-[ext_resource type="Texture2D" uid="uid://b36ese18p42qf" path="res://assets/images/gamepad/steam/steam_dpad_down.svg" id="3_614i2"]
-[ext_resource type="Texture2D" uid="uid://curpocxiiytm1" path="res://assets/images/gamepad/steam/steam_dpad_left.svg" id="4_joten"]
-[ext_resource type="Texture2D" uid="uid://bpws8otkr23ss" path="res://assets/images/gamepad/steam/steam_dpad_right.svg" id="5_iyjxe"]
-[ext_resource type="Texture2D" uid="uid://cmlvutjr6mn8r" path="res://assets/images/gamepad/steam/steam_dpad_up.svg" id="6_khnqq"]
-[ext_resource type="Texture2D" uid="uid://c435jhogs3n8o" path="res://assets/images/gamepad/steam/steam_button_color_b.svg" id="7_g8gma"]
-[ext_resource type="Texture2D" uid="uid://com8m05m2uqco" path="res://assets/images/gamepad/steam/steam_button_lp.svg" id="8_6hxdr"]
-[ext_resource type="Texture2D" uid="uid://b8kll7wj3mpw5" path="res://assets/images/gamepad/steamdeck/steamdeck_button_guide.svg" id="8_qwegv"]
-[ext_resource type="Texture2D" uid="uid://b251los4ey64w" path="res://assets/images/gamepad/steam/steam_stick.svg" id="9_0stxd"]
-[ext_resource type="Texture2D" uid="uid://01a6rkyglcse" path="res://assets/images/gamepad/steam/steam_button_color_y.svg" id="9_tbfyw"]
-[ext_resource type="Texture2D" uid="uid://cer0ys0nbh0no" path="res://assets/images/gamepad/steam/steam_button_rp.svg" id="10_c0nl7"]
-[ext_resource type="Texture2D" uid="uid://dipbfvbdnieqv" path="res://assets/images/gamepad/steam/steam_stick_down.svg" id="10_emyma"]
-[ext_resource type="Texture2D" uid="uid://7jx3hwdcd28t" path="res://assets/images/gamepad/steam/steam_lg.svg" id="10_lb40s"]
-[ext_resource type="Texture2D" uid="uid://cc3la68tqkeu7" path="res://assets/images/gamepad/steam/steam_stick_l_press.svg" id="10_uvdib"]
-[ext_resource type="Texture2D" uid="uid://b7vfsacm21uvc" path="res://assets/images/gamepad/steam/steam_stick_left.svg" id="11_bq8g3"]
-[ext_resource type="Texture2D" uid="uid://jfjsyxvyctbk" path="res://assets/images/gamepad/steam/steam_stick_right.svg" id="12_8u65p"]
-[ext_resource type="Texture2D" uid="uid://dpgjaie64o2j7" path="res://assets/images/gamepad/steam/steam_button_back_icon.svg" id="12_gac83"]
-[ext_resource type="Texture2D" uid="uid://bpkm2swtktdf0" path="res://assets/images/gamepad/steam/steam_button_color_a.svg" id="13_vysxh"]
-[ext_resource type="Texture2D" uid="uid://c10buq0dndeb8" path="res://assets/images/gamepad/steam/steam_stick_up.svg" id="13_yhcf0"]
-[ext_resource type="Texture2D" uid="uid://gm2fk8y4xrig" path="res://assets/images/gamepad/steam/steam_button_color_x.svg" id="14_l277p"]
-[ext_resource type="Texture2D" uid="uid://bsxofaj5ietuc" path="res://assets/images/gamepad/steam/steam_rg.svg" id="19_dvgk4"]
-[ext_resource type="Texture2D" uid="uid://drhbwe1m16fx7" path="res://assets/images/gamepad/steam/steam_button_start_icon.svg" id="19_mlqpj"]
+[ext_resource type="Texture2D" uid="uid://dr4giue83b7ly" path="res://assets/images/gamepad/steam/steam_dpad.svg" id="2_dr285"]
+[ext_resource type="Texture2D" uid="uid://hjxtuq87i2s8" path="res://assets/images/gamepad/steam/steam_dpad_down.svg" id="3_614i2"]
+[ext_resource type="Texture2D" uid="uid://dlt00cmdhrufc" path="res://assets/images/gamepad/steam/steam_dpad_left.svg" id="4_joten"]
+[ext_resource type="Texture2D" uid="uid://dwopaos8mykma" path="res://assets/images/gamepad/steam/steam_dpad_right.svg" id="5_iyjxe"]
+[ext_resource type="Texture2D" uid="uid://u6ehkqpdr5dn" path="res://assets/images/gamepad/steam/steam_dpad_up.svg" id="6_khnqq"]
+[ext_resource type="Texture2D" uid="uid://b730xukgcsh2k" path="res://assets/images/gamepad/steam/steam_button_color_b.svg" id="7_g8gma"]
+[ext_resource type="Texture2D" uid="uid://mphqdrq0v6nv" path="res://assets/images/gamepad/steam/steam_button_lp.svg" id="8_6hxdr"]
+[ext_resource type="Texture2D" uid="uid://7obnebcrnike" path="res://assets/images/gamepad/steamdeck/steamdeck_button_guide.svg" id="8_qwegv"]
+[ext_resource type="Texture2D" uid="uid://bm0b6klr4s4me" path="res://assets/images/gamepad/steam/steam_stick.svg" id="9_0stxd"]
+[ext_resource type="Texture2D" uid="uid://dl6mkuxwnau6c" path="res://assets/images/gamepad/steam/steam_button_color_y.svg" id="9_tbfyw"]
+[ext_resource type="Texture2D" uid="uid://djidib24hy7sf" path="res://assets/images/gamepad/steam/steam_button_rp.svg" id="10_c0nl7"]
+[ext_resource type="Texture2D" uid="uid://b38225lpoxnad" path="res://assets/images/gamepad/steam/steam_stick_down.svg" id="10_emyma"]
+[ext_resource type="Texture2D" uid="uid://bxjvcfty4u5tr" path="res://assets/images/gamepad/steam/steam_lg.svg" id="10_lb40s"]
+[ext_resource type="Texture2D" uid="uid://bp3y2i8nclwov" path="res://assets/images/gamepad/steam/steam_stick_l_press.svg" id="10_uvdib"]
+[ext_resource type="Texture2D" uid="uid://cwe6414vhvsbm" path="res://assets/images/gamepad/steam/steam_stick_left.svg" id="11_bq8g3"]
+[ext_resource type="Texture2D" uid="uid://c5c5rvhs8260" path="res://assets/images/gamepad/steam/steam_stick_right.svg" id="12_8u65p"]
+[ext_resource type="Texture2D" uid="uid://cmnjax5k8juxb" path="res://assets/images/gamepad/steam/steam_button_back_icon.svg" id="12_gac83"]
+[ext_resource type="Texture2D" uid="uid://1q1vr24dkc26" path="res://assets/images/gamepad/steam/steam_button_color_a.svg" id="13_vysxh"]
+[ext_resource type="Texture2D" uid="uid://h0lyv05rajef" path="res://assets/images/gamepad/steam/steam_stick_up.svg" id="13_yhcf0"]
+[ext_resource type="Texture2D" uid="uid://ctvb5ylheu2nm" path="res://assets/images/gamepad/steam/steam_button_color_x.svg" id="14_l277p"]
+[ext_resource type="Texture2D" uid="uid://otfjb4w8k4vh" path="res://assets/images/gamepad/steam/steam_rg.svg" id="19_dvgk4"]
+[ext_resource type="Texture2D" uid="uid://4lase2m3005j" path="res://assets/images/gamepad/steam/steam_button_start_icon.svg" id="19_mlqpj"]
[resource]
script = ExtResource("1_vsxmp")
diff --git a/assets/gamepad/icon_mappings/steamdeck.tres b/assets/gamepad/icon_mappings/steamdeck.tres
index fdaeeb7c9..652b94404 100644
--- a/assets/gamepad/icon_mappings/steamdeck.tres
+++ b/assets/gamepad/icon_mappings/steamdeck.tres
@@ -1,42 +1,42 @@
[gd_resource type="Resource" script_class="InputIconMapping" load_steps=38 format=3 uid="uid://dmck8es3nhbqt"]
[ext_resource type="Script" path="res://core/systems/input/input_icon_mapping.gd" id="1_xffj2"]
-[ext_resource type="Texture2D" uid="uid://cvyo2q5qjpamv" path="res://assets/images/gamepad/steamdeck/diagram.png" id="1_xtoy0"]
-[ext_resource type="Texture2D" uid="uid://bdijnj7q510fb" path="res://assets/images/gamepad/steamdeck/steamdeck_button_b.svg" id="2_8eg7f"]
-[ext_resource type="Texture2D" uid="uid://d1vwjidwwl6g6" path="res://assets/images/gamepad/steamdeck/steamdeck_dpad.svg" id="2_8t15o"]
-[ext_resource type="Texture2D" uid="uid://ck0gwj0t1nlnb" path="res://assets/images/gamepad/steamdeck/steamdeck_dpad_down.svg" id="3_d8lqu"]
-[ext_resource type="Texture2D" uid="uid://b8kll7wj3mpw5" path="res://assets/images/gamepad/steamdeck/steamdeck_button_guide.svg" id="3_nvde6"]
-[ext_resource type="Texture2D" uid="uid://2hvt2s10h4oh" path="res://assets/images/gamepad/steamdeck/steamdeck_button_l4.svg" id="4_dvvlm"]
-[ext_resource type="Texture2D" uid="uid://bw3o757gon60n" path="res://assets/images/gamepad/steamdeck/steamdeck_dpad_left.svg" id="4_vffs6"]
-[ext_resource type="Texture2D" uid="uid://bsqe51ljqa1wl" path="res://assets/images/gamepad/steamdeck/steamdeck_button_l5.svg" id="5_qlfxn"]
-[ext_resource type="Texture2D" uid="uid://cxe85qvlcxt8k" path="res://assets/images/gamepad/steamdeck/steamdeck_dpad_right.svg" id="5_v1qd7"]
-[ext_resource type="Texture2D" uid="uid://iuf1gwubgrkr" path="res://assets/images/gamepad/steamdeck/steamdeck_button_l1.svg" id="6_4nclm"]
-[ext_resource type="Texture2D" uid="uid://d3bk0otxo2u0t" path="res://assets/images/gamepad/steamdeck/steamdeck_dpad_up.svg" id="6_dpf6l"]
-[ext_resource type="Texture2D" uid="uid://dxpamvls1wtr4" path="res://assets/images/gamepad/steamdeck/steamdeck_button_l2.svg" id="7_j67qe"]
-[ext_resource type="Texture2D" uid="uid://b14twfve0lmf6" path="res://assets/images/gamepad/steamdeck/steamdeck_button_y.svg" id="8_0rfpr"]
-[ext_resource type="Texture2D" uid="uid://byy323swr1naa" path="res://assets/images/gamepad/steamdeck/steamdeck_button_quickaccess.svg" id="8_owjyj"]
-[ext_resource type="Texture2D" uid="uid://dmfw87xx6phhc" path="res://assets/images/gamepad/steamdeck/steamdeck_button_r4.svg" id="9_2ijj3"]
-[ext_resource type="Texture2D" uid="uid://d3ocywhdiyjvk" path="res://assets/images/gamepad/steamdeck/steamdeck_trackpad_l_all.svg" id="9_3q0xs"]
-[ext_resource type="Texture2D" uid="uid://bre5c38fo7hn5" path="res://assets/images/gamepad/steamdeck/steamdeck_button_r5.svg" id="10_sihsr"]
-[ext_resource type="Texture2D" uid="uid://cvm6un7wher3" path="res://assets/images/gamepad/steamdeck/steamdeck_button_r1.svg" id="11_sg6p3"]
-[ext_resource type="Texture2D" uid="uid://coaaq1r1uiyx2" path="res://assets/images/gamepad/steamdeck/steamdeck_button_r2.svg" id="12_kfdop"]
-[ext_resource type="Texture2D" uid="uid://c6holuruhn6gs" path="res://assets/images/gamepad/steamdeck/steamdeck_stick_l.svg" id="12_w0n16"]
-[ext_resource type="Texture2D" uid="uid://dcqhk1jgepeq0" path="res://assets/images/gamepad/steamdeck/steamdeck_stick_l_press.svg" id="13_f2qfl"]
-[ext_resource type="Texture2D" uid="uid://2ymxt6fjxgbg" path="res://assets/images/gamepad/steamdeck/steamdeck_button_a.svg" id="14_hcyjc"]
-[ext_resource type="Texture2D" uid="uid://bkuoy3851ps81" path="res://assets/images/gamepad/steamdeck/steamdeck_stick_l_down.svg" id="14_nkcal"]
-[ext_resource type="Texture2D" uid="uid://c3tfburs4gc2e" path="res://assets/images/gamepad/steamdeck/steamdeck_button_view.svg" id="15_1fovd"]
-[ext_resource type="Texture2D" uid="uid://dfreqwma7axjm" path="res://assets/images/gamepad/steamdeck/steamdeck_stick_l_left.svg" id="15_1p0bb"]
-[ext_resource type="Texture2D" uid="uid://dhwuj34jww33w" path="res://assets/images/gamepad/steamdeck/steamdeck_button_options.svg" id="15_m6xmt"]
-[ext_resource type="Texture2D" uid="uid://dpxu821a7oj4s" path="res://assets/images/gamepad/steamdeck/steamdeck_stick_l_right.svg" id="16_tmt1u"]
-[ext_resource type="Texture2D" uid="uid://dgpc6aewueu74" path="res://assets/images/gamepad/steamdeck/steamdeck_stick_l_up.svg" id="17_j3c4l"]
-[ext_resource type="Texture2D" uid="uid://dedkcpdkjkfgi" path="res://assets/images/gamepad/steamdeck/steamdeck_button_x.svg" id="18_ekemo"]
-[ext_resource type="Texture2D" uid="uid://b5smg46hvo3en" path="res://assets/images/gamepad/steamdeck/steamdeck_trackpad_r_all.svg" id="22_4kkvh"]
-[ext_resource type="Texture2D" uid="uid://c0vodcvwmd4mq" path="res://assets/images/gamepad/steamdeck/steamdeck_stick_r.svg" id="24_4sn7m"]
-[ext_resource type="Texture2D" uid="uid://bflve4wmy5l7p" path="res://assets/images/gamepad/steamdeck/steamdeck_stick_r_press.svg" id="25_jya3g"]
-[ext_resource type="Texture2D" uid="uid://drhc3nti5y4v2" path="res://assets/images/gamepad/steamdeck/steamdeck_stick_r_down.svg" id="26_koslu"]
-[ext_resource type="Texture2D" uid="uid://bf050ow2fqwl5" path="res://assets/images/gamepad/steamdeck/steamdeck_stick_r_left.svg" id="27_56oh1"]
-[ext_resource type="Texture2D" uid="uid://deujxqeovbjs8" path="res://assets/images/gamepad/steamdeck/steamdeck_stick_r_right.svg" id="28_r81kg"]
-[ext_resource type="Texture2D" uid="uid://c23ukiudnt5vx" path="res://assets/images/gamepad/steamdeck/steamdeck_stick_r_up.svg" id="29_x2rgv"]
+[ext_resource type="Texture2D" uid="uid://b4w5tmfci1toh" path="res://assets/images/gamepad/steamdeck/diagram.png" id="1_xtoy0"]
+[ext_resource type="Texture2D" uid="uid://bi6jcsdcp4e77" path="res://assets/images/gamepad/steamdeck/steamdeck_button_b.svg" id="2_8eg7f"]
+[ext_resource type="Texture2D" uid="uid://dprhshnof4mpt" path="res://assets/images/gamepad/steamdeck/steamdeck_dpad.svg" id="2_8t15o"]
+[ext_resource type="Texture2D" uid="uid://bc1anbo6va8c2" path="res://assets/images/gamepad/steamdeck/steamdeck_dpad_down.svg" id="3_d8lqu"]
+[ext_resource type="Texture2D" uid="uid://7obnebcrnike" path="res://assets/images/gamepad/steamdeck/steamdeck_button_guide.svg" id="3_nvde6"]
+[ext_resource type="Texture2D" uid="uid://cru5rdx15j4ts" path="res://assets/images/gamepad/steamdeck/steamdeck_button_l4.svg" id="4_dvvlm"]
+[ext_resource type="Texture2D" uid="uid://ggcsc810x7ri" path="res://assets/images/gamepad/steamdeck/steamdeck_dpad_left.svg" id="4_vffs6"]
+[ext_resource type="Texture2D" uid="uid://iby8tq0amo8b" path="res://assets/images/gamepad/steamdeck/steamdeck_button_l5.svg" id="5_qlfxn"]
+[ext_resource type="Texture2D" uid="uid://tc7bgm3gcyqd" path="res://assets/images/gamepad/steamdeck/steamdeck_dpad_right.svg" id="5_v1qd7"]
+[ext_resource type="Texture2D" uid="uid://scfbg0yygqka" path="res://assets/images/gamepad/steamdeck/steamdeck_button_l1.svg" id="6_4nclm"]
+[ext_resource type="Texture2D" uid="uid://dfqvij0d87gq8" path="res://assets/images/gamepad/steamdeck/steamdeck_dpad_up.svg" id="6_dpf6l"]
+[ext_resource type="Texture2D" uid="uid://k5ca2xyvchl2" path="res://assets/images/gamepad/steamdeck/steamdeck_button_l2.svg" id="7_j67qe"]
+[ext_resource type="Texture2D" uid="uid://d238yav03b5tk" path="res://assets/images/gamepad/steamdeck/steamdeck_button_y.svg" id="8_0rfpr"]
+[ext_resource type="Texture2D" uid="uid://c8huhb14jh1ba" path="res://assets/images/gamepad/steamdeck/steamdeck_button_quickaccess.svg" id="8_owjyj"]
+[ext_resource type="Texture2D" uid="uid://duirfrp1swep8" path="res://assets/images/gamepad/steamdeck/steamdeck_button_r4.svg" id="9_2ijj3"]
+[ext_resource type="Texture2D" uid="uid://dvioogs1h44wj" path="res://assets/images/gamepad/steamdeck/steamdeck_trackpad_l_all.svg" id="9_3q0xs"]
+[ext_resource type="Texture2D" uid="uid://b5dvxnn2ddhar" path="res://assets/images/gamepad/steamdeck/steamdeck_button_r5.svg" id="10_sihsr"]
+[ext_resource type="Texture2D" uid="uid://cdx74dhosgpi1" path="res://assets/images/gamepad/steamdeck/steamdeck_button_r1.svg" id="11_sg6p3"]
+[ext_resource type="Texture2D" uid="uid://dw7hjtcfaepx" path="res://assets/images/gamepad/steamdeck/steamdeck_button_r2.svg" id="12_kfdop"]
+[ext_resource type="Texture2D" uid="uid://cljgsi6rwed5y" path="res://assets/images/gamepad/steamdeck/steamdeck_stick_l.svg" id="12_w0n16"]
+[ext_resource type="Texture2D" uid="uid://fk70akhspjqw" path="res://assets/images/gamepad/steamdeck/steamdeck_stick_l_press.svg" id="13_f2qfl"]
+[ext_resource type="Texture2D" uid="uid://glixduifqfyc" path="res://assets/images/gamepad/steamdeck/steamdeck_button_a.svg" id="14_hcyjc"]
+[ext_resource type="Texture2D" uid="uid://b4t2lfdlk8v1l" path="res://assets/images/gamepad/steamdeck/steamdeck_stick_l_down.svg" id="14_nkcal"]
+[ext_resource type="Texture2D" uid="uid://b3g1sl3gxac3l" path="res://assets/images/gamepad/steamdeck/steamdeck_button_view.svg" id="15_1fovd"]
+[ext_resource type="Texture2D" uid="uid://dgq0pu6stgp0n" path="res://assets/images/gamepad/steamdeck/steamdeck_stick_l_left.svg" id="15_1p0bb"]
+[ext_resource type="Texture2D" uid="uid://i37o7qma5l0m" path="res://assets/images/gamepad/steamdeck/steamdeck_button_options.svg" id="15_m6xmt"]
+[ext_resource type="Texture2D" uid="uid://cg673id36yufn" path="res://assets/images/gamepad/steamdeck/steamdeck_stick_l_right.svg" id="16_tmt1u"]
+[ext_resource type="Texture2D" uid="uid://clerkwh0rv4qm" path="res://assets/images/gamepad/steamdeck/steamdeck_stick_l_up.svg" id="17_j3c4l"]
+[ext_resource type="Texture2D" uid="uid://du2ljto5eauh5" path="res://assets/images/gamepad/steamdeck/steamdeck_button_x.svg" id="18_ekemo"]
+[ext_resource type="Texture2D" uid="uid://b006fo2wqcu8w" path="res://assets/images/gamepad/steamdeck/steamdeck_trackpad_r_all.svg" id="22_4kkvh"]
+[ext_resource type="Texture2D" uid="uid://dm1cw0o0kpajg" path="res://assets/images/gamepad/steamdeck/steamdeck_stick_r.svg" id="24_4sn7m"]
+[ext_resource type="Texture2D" uid="uid://vb6n5l5ajq0t" path="res://assets/images/gamepad/steamdeck/steamdeck_stick_r_press.svg" id="25_jya3g"]
+[ext_resource type="Texture2D" uid="uid://dcyao1pr3jtls" path="res://assets/images/gamepad/steamdeck/steamdeck_stick_r_down.svg" id="26_koslu"]
+[ext_resource type="Texture2D" uid="uid://dk34rpf2xmwpp" path="res://assets/images/gamepad/steamdeck/steamdeck_stick_r_left.svg" id="27_56oh1"]
+[ext_resource type="Texture2D" uid="uid://jpl2xe1upygm" path="res://assets/images/gamepad/steamdeck/steamdeck_stick_r_right.svg" id="28_r81kg"]
+[ext_resource type="Texture2D" uid="uid://8ioc8gidakfr" path="res://assets/images/gamepad/steamdeck/steamdeck_stick_r_up.svg" id="29_x2rgv"]
[resource]
script = ExtResource("1_xffj2")
diff --git a/assets/gamepad/icon_mappings/switch.tres b/assets/gamepad/icon_mappings/switch.tres
index 0a9f5b012..116235c6e 100644
--- a/assets/gamepad/icon_mappings/switch.tres
+++ b/assets/gamepad/icon_mappings/switch.tres
@@ -1,36 +1,36 @@
[gd_resource type="Resource" script_class="InputIconMapping" load_steps=32 format=3 uid="uid://behwrymqjqtvv"]
[ext_resource type="Script" path="res://core/systems/input/input_icon_mapping.gd" id="1_s4hvo"]
-[ext_resource type="Texture2D" uid="uid://jv2vbh18muy8" path="res://assets/images/gamepad/switch/switch_dpad.svg" id="1_ydeli"]
-[ext_resource type="Texture2D" uid="uid://beb058tm84w5j" path="res://assets/images/gamepad/switch/switch_dpad_down.svg" id="2_tw4ge"]
-[ext_resource type="Texture2D" uid="uid://dnp6tc41r8xi3" path="res://assets/images/gamepad/switch/switch_dpad_left.svg" id="3_8rr1p"]
-[ext_resource type="Texture2D" uid="uid://u7ity54x4vx3" path="res://assets/images/gamepad/switch/switch_dpad_right.svg" id="4_pppsw"]
-[ext_resource type="Texture2D" uid="uid://bi8viiuisfuxh" path="res://assets/images/gamepad/switch/switch_dpad_up.svg" id="5_c4oby"]
-[ext_resource type="Texture2D" uid="uid://dec8wg71j58h1" path="res://assets/images/gamepad/switch/switch_button_a.svg" id="6_riih2"]
-[ext_resource type="Texture2D" uid="uid://b3v8gbuc0knsr" path="res://assets/images/gamepad/switch/switch_button_home.svg" id="7_v8spc"]
-[ext_resource type="Texture2D" uid="uid://by4xd4qq5dspy" path="res://assets/images/gamepad/switch/switch_joycon_left_rotate.svg" id="8_mj4ae"]
-[ext_resource type="Texture2D" uid="uid://b57k4ko26lm6" path="res://assets/images/gamepad/switch/switch_button_l.svg" id="9_ryb7o"]
-[ext_resource type="Texture2D" uid="uid://bgkt5t7mmbhts" path="res://assets/images/gamepad/switch/switch_stick_l.svg" id="10_jcwsc"]
-[ext_resource type="Texture2D" uid="uid://ca4fcl2jsx62k" path="res://assets/images/gamepad/switch/switch_stick_l_press.svg" id="11_tcwua"]
-[ext_resource type="Texture2D" uid="uid://bvnpkij77axxu" path="res://assets/images/gamepad/switch/switch_stick_l_down.svg" id="12_dmidv"]
-[ext_resource type="Texture2D" uid="uid://bbad7xmuveel8" path="res://assets/images/gamepad/switch/switch_stick_l_left.svg" id="13_g56k4"]
-[ext_resource type="Texture2D" uid="uid://lpy6n3raxq2" path="res://assets/images/gamepad/switch/switch_stick_l_right.svg" id="14_0ydal"]
-[ext_resource type="Texture2D" uid="uid://btrirhorp6y57" path="res://assets/images/gamepad/switch/switch_stick_l_up.svg" id="15_5vsxb"]
-[ext_resource type="Texture2D" uid="uid://dsa8m2vfvtx0q" path="res://assets/images/gamepad/switch/switch_button_zl.svg" id="16_4pllh"]
-[ext_resource type="Texture2D" uid="uid://b6wkct2qwo0ul" path="res://assets/images/gamepad/switch/switch_button_x.svg" id="17_n3inh"]
-[ext_resource type="Texture2D" uid="uid://bu2naacuis8k8" path="res://assets/images/gamepad/switch/switch_button_r.svg" id="18_45ryk"]
-[ext_resource type="Texture2D" uid="uid://c1fas8o38r02p" path="res://assets/images/gamepad/switch/switch_stick_r.svg" id="19_gqh2w"]
-[ext_resource type="Texture2D" uid="uid://dop088ppjtx7r" path="res://assets/images/gamepad/switch/switch_stick_r_press.svg" id="20_rugaw"]
-[ext_resource type="Texture2D" uid="uid://dqrqw3lv3kl3e" path="res://assets/images/gamepad/switch/switch_stick_r_down.svg" id="21_susn6"]
-[ext_resource type="Texture2D" uid="uid://bcstmmysk3e1" path="res://assets/images/gamepad/switch/switch_stick_r_left.svg" id="22_xgn3r"]
-[ext_resource type="Texture2D" uid="uid://domi3pblhpgqy" path="res://assets/images/gamepad/switch/switch_stick_r_right.svg" id="23_stpgt"]
-[ext_resource type="Texture2D" uid="uid://dtkumw37qfis8" path="res://assets/images/gamepad/switch/switch_stick_r_up.svg" id="24_ranay"]
-[ext_resource type="Texture2D" uid="uid://cutjyk72c0d1" path="res://assets/images/gamepad/switch/switch_button_zr.svg" id="25_4bdkg"]
-[ext_resource type="Texture2D" uid="uid://baeygxurw7dn1" path="res://assets/images/gamepad/switch/switch_button_sync.svg" id="26_ppthb"]
-[ext_resource type="Texture2D" uid="uid://crl6hqey1xqfd" path="res://assets/images/gamepad/switch/switch_button_minus.svg" id="28_i4oi2"]
-[ext_resource type="Texture2D" uid="uid://8o3g4dcunk87" path="res://assets/images/gamepad/switch/switch_button_b.svg" id="29_qxbwx"]
-[ext_resource type="Texture2D" uid="uid://dugmdwvujsrk4" path="res://assets/images/gamepad/switch/switch_button_plus.svg" id="30_gmsl2"]
-[ext_resource type="Texture2D" uid="uid://djvoe5nud1i0w" path="res://assets/images/gamepad/switch/switch_button_y.svg" id="31_7qfqf"]
+[ext_resource type="Texture2D" uid="uid://b735i56yjhict" path="res://assets/images/gamepad/switch/switch_dpad.svg" id="1_ydeli"]
+[ext_resource type="Texture2D" uid="uid://drfroynux1b3f" path="res://assets/images/gamepad/switch/switch_dpad_down.svg" id="2_tw4ge"]
+[ext_resource type="Texture2D" uid="uid://e3db7ixs8tjk" path="res://assets/images/gamepad/switch/switch_dpad_left.svg" id="3_8rr1p"]
+[ext_resource type="Texture2D" uid="uid://vdro02bqhoxn" path="res://assets/images/gamepad/switch/switch_dpad_right.svg" id="4_pppsw"]
+[ext_resource type="Texture2D" uid="uid://hwsqjx3falhf" path="res://assets/images/gamepad/switch/switch_dpad_up.svg" id="5_c4oby"]
+[ext_resource type="Texture2D" uid="uid://dsnnac0xk0tfl" path="res://assets/images/gamepad/switch/switch_button_a.svg" id="6_riih2"]
+[ext_resource type="Texture2D" uid="uid://dicj4tpxknqai" path="res://assets/images/gamepad/switch/switch_button_home.svg" id="7_v8spc"]
+[ext_resource type="Texture2D" uid="uid://cda8etpu56yjn" path="res://assets/images/gamepad/switch/switch_joycon_left_rotate.svg" id="8_mj4ae"]
+[ext_resource type="Texture2D" uid="uid://d2ho4b7w2mdlb" path="res://assets/images/gamepad/switch/switch_button_l.svg" id="9_ryb7o"]
+[ext_resource type="Texture2D" uid="uid://ruhfjlhtlik3" path="res://assets/images/gamepad/switch/switch_stick_l.svg" id="10_jcwsc"]
+[ext_resource type="Texture2D" uid="uid://d1xnwfo4kwgwe" path="res://assets/images/gamepad/switch/switch_stick_l_press.svg" id="11_tcwua"]
+[ext_resource type="Texture2D" uid="uid://ri6vpuerb2jn" path="res://assets/images/gamepad/switch/switch_stick_l_down.svg" id="12_dmidv"]
+[ext_resource type="Texture2D" uid="uid://dvdwtqdrgcx55" path="res://assets/images/gamepad/switch/switch_stick_l_left.svg" id="13_g56k4"]
+[ext_resource type="Texture2D" uid="uid://ckdjvbxmun3hk" path="res://assets/images/gamepad/switch/switch_stick_l_right.svg" id="14_0ydal"]
+[ext_resource type="Texture2D" uid="uid://c54734rwsvi5y" path="res://assets/images/gamepad/switch/switch_stick_l_up.svg" id="15_5vsxb"]
+[ext_resource type="Texture2D" uid="uid://ysw3f4s0wckl" path="res://assets/images/gamepad/switch/switch_button_zl.svg" id="16_4pllh"]
+[ext_resource type="Texture2D" uid="uid://d0nkpy8tk3f28" path="res://assets/images/gamepad/switch/switch_button_x.svg" id="17_n3inh"]
+[ext_resource type="Texture2D" uid="uid://dh8gskvlf1y4n" path="res://assets/images/gamepad/switch/switch_button_r.svg" id="18_45ryk"]
+[ext_resource type="Texture2D" uid="uid://bnr0q7kupfac8" path="res://assets/images/gamepad/switch/switch_stick_r.svg" id="19_gqh2w"]
+[ext_resource type="Texture2D" uid="uid://dalb0538ux4qy" path="res://assets/images/gamepad/switch/switch_stick_r_press.svg" id="20_rugaw"]
+[ext_resource type="Texture2D" uid="uid://c37v6pn2p4pa7" path="res://assets/images/gamepad/switch/switch_stick_r_down.svg" id="21_susn6"]
+[ext_resource type="Texture2D" uid="uid://d0s0cx6bqiovg" path="res://assets/images/gamepad/switch/switch_stick_r_left.svg" id="22_xgn3r"]
+[ext_resource type="Texture2D" uid="uid://dxycp3mj54mwc" path="res://assets/images/gamepad/switch/switch_stick_r_right.svg" id="23_stpgt"]
+[ext_resource type="Texture2D" uid="uid://be6s7r6y3ndty" path="res://assets/images/gamepad/switch/switch_stick_r_up.svg" id="24_ranay"]
+[ext_resource type="Texture2D" uid="uid://cwkd4oyqs445d" path="res://assets/images/gamepad/switch/switch_button_zr.svg" id="25_4bdkg"]
+[ext_resource type="Texture2D" uid="uid://brwy28sjw2pe8" path="res://assets/images/gamepad/switch/switch_button_sync.svg" id="26_ppthb"]
+[ext_resource type="Texture2D" uid="uid://f3dabljd057e" path="res://assets/images/gamepad/switch/switch_button_minus.svg" id="28_i4oi2"]
+[ext_resource type="Texture2D" uid="uid://b21ssea6yir56" path="res://assets/images/gamepad/switch/switch_button_b.svg" id="29_qxbwx"]
+[ext_resource type="Texture2D" uid="uid://rgpis0qqwyn3" path="res://assets/images/gamepad/switch/switch_button_plus.svg" id="30_gmsl2"]
+[ext_resource type="Texture2D" uid="uid://ckwf0ko1ch08t" path="res://assets/images/gamepad/switch/switch_button_y.svg" id="31_7qfqf"]
[resource]
script = ExtResource("1_s4hvo")
diff --git a/assets/gamepad/icon_mappings/xbox360.tres b/assets/gamepad/icon_mappings/xbox360.tres
index e99683802..20672899c 100644
--- a/assets/gamepad/icon_mappings/xbox360.tres
+++ b/assets/gamepad/icon_mappings/xbox360.tres
@@ -1,41 +1,41 @@
[gd_resource type="Resource" script_class="InputIconMapping" load_steps=31 format=3 uid="uid://bx1o03i6woyis"]
-[ext_resource type="Texture2D" uid="uid://bie2sf8kjawr" path="res://assets/images/gamepad/xbox/XboxOne_Diagram.png" id="1_ivcim"]
-[ext_resource type="Texture2D" uid="uid://dn8i3gpeijgu1" path="res://assets/images/gamepad/xbox/xbox_dpad_round.svg" id="2_2qico"]
-[ext_resource type="Texture2D" uid="uid://bqho0a0sr6u1j" path="res://assets/images/gamepad/xbox/xbox_button_color_b.svg" id="2_scm2e"]
-[ext_resource type="Texture2D" uid="uid://bcoajyq8st62e" path="res://assets/images/gamepad/xbox/xbox_guide.svg" id="3_rcstt"]
-[ext_resource type="Texture2D" uid="uid://dwv3f88h7uaq7" path="res://assets/images/gamepad/xbox/xbox_dpad_round_down.svg" id="3_x7c5e"]
-[ext_resource type="Texture2D" uid="uid://fmnwuu2ym0m8" path="res://assets/images/gamepad/xbox/xbox_dpad_round_left.svg" id="4_dtqoy"]
-[ext_resource type="Texture2D" uid="uid://ddpudi00yulrx" path="res://assets/images/gamepad/xbox/xbox_button_color_y.svg" id="4_yf7fg"]
-[ext_resource type="Texture2D" uid="uid://cboy1enwvdeoy" path="res://assets/images/gamepad/xbox/xbox_dpad_round_right.svg" id="5_l43jp"]
+[ext_resource type="Texture2D" uid="uid://cibfy4ssigmqm" path="res://assets/images/gamepad/xbox/XboxOne_Diagram_Simple.png" id="1_vdrwh"]
+[ext_resource type="Texture2D" uid="uid://n4t36xrl15ux" path="res://assets/images/gamepad/xbox/xbox_dpad_round.svg" id="2_2qico"]
+[ext_resource type="Texture2D" uid="uid://dfby3iiksln2e" path="res://assets/images/gamepad/xbox/xbox_button_color_b.svg" id="2_scm2e"]
+[ext_resource type="Texture2D" uid="uid://dq7kibukggise" path="res://assets/images/gamepad/xbox/xbox_guide.svg" id="3_rcstt"]
+[ext_resource type="Texture2D" uid="uid://bxovdah6vnpsn" path="res://assets/images/gamepad/xbox/xbox_dpad_round_down.svg" id="3_x7c5e"]
+[ext_resource type="Texture2D" uid="uid://qhwj81sv67l4" path="res://assets/images/gamepad/xbox/xbox_dpad_round_left.svg" id="4_dtqoy"]
+[ext_resource type="Texture2D" uid="uid://b81pjmldtt10s" path="res://assets/images/gamepad/xbox/xbox_button_color_y.svg" id="4_yf7fg"]
+[ext_resource type="Texture2D" uid="uid://b1uo5130s6gfw" path="res://assets/images/gamepad/xbox/xbox_dpad_round_right.svg" id="5_l43jp"]
[ext_resource type="Script" path="res://core/systems/input/input_icon_mapping.gd" id="5_qsuka"]
-[ext_resource type="Texture2D" uid="uid://ba64eulr61afh" path="res://assets/images/gamepad/xbox/xbox_dpad_round_up.svg" id="6_hdxil"]
-[ext_resource type="Texture2D" uid="uid://dyemqkvdtk43e" path="res://assets/images/gamepad/xbox/xbox_button_color_a.svg" id="6_kekiu"]
-[ext_resource type="Texture2D" uid="uid://cuvx61nakiaoi" path="res://assets/images/gamepad/xbox/xbox_button_color_x.svg" id="7_5gtvm"]
-[ext_resource type="Texture2D" uid="uid://mtd8tfnbotgc" path="res://assets/images/gamepad/xbox/xbox_lb.svg" id="9_5mjlo"]
-[ext_resource type="Texture2D" uid="uid://bdqfg27h5o836" path="res://assets/images/gamepad/xbox/xbox_stick_l.svg" id="10_h038p"]
-[ext_resource type="Texture2D" uid="uid://dvv5grt45cows" path="res://assets/images/gamepad/xbox/xbox_stick_l_press.svg" id="11_87ajn"]
-[ext_resource type="Texture2D" uid="uid://u3jonqoafyg6" path="res://assets/images/gamepad/xbox/xbox_lt.svg" id="12_2l3bb"]
-[ext_resource type="Texture2D" uid="uid://dcumk3oqkyy7g" path="res://assets/images/gamepad/xbox/xbox_stick_l_down.svg" id="12_kp3w4"]
-[ext_resource type="Texture2D" uid="uid://dooej262t4g0x" path="res://assets/images/gamepad/xbox/xbox_stick_l_left.svg" id="13_8wccm"]
-[ext_resource type="Texture2D" uid="uid://co3kg331knfu7" path="res://assets/images/gamepad/xbox/xbox_rb.svg" id="14_106m0"]
-[ext_resource type="Texture2D" uid="uid://coltjh07der5" path="res://assets/images/gamepad/xbox/xbox_stick_l_right.svg" id="14_m6oqd"]
-[ext_resource type="Texture2D" uid="uid://da8ojjv5vttou" path="res://assets/images/gamepad/xbox/xbox_rt.svg" id="15_1ae1p"]
-[ext_resource type="Texture2D" uid="uid://b3xxbnyo2h20l" path="res://assets/images/gamepad/xbox/xbox_stick_l_up.svg" id="15_wqxdi"]
-[ext_resource type="Texture2D" uid="uid://worovimrqapy" path="res://assets/images/gamepad/xbox/xbox_button_back_icon.svg" id="17_ewr7o"]
-[ext_resource type="Texture2D" uid="uid://lyo4d0hfj4ut" path="res://assets/images/gamepad/xbox/xbox_button_start_icon.svg" id="19_5p4eh"]
-[ext_resource type="Texture2D" uid="uid://dw15y6xiuthpe" path="res://assets/images/gamepad/xbox/xbox_stick_r.svg" id="19_p4shy"]
-[ext_resource type="Texture2D" uid="uid://de2kcqeakp3q0" path="res://assets/images/gamepad/xbox/xbox_stick_r_press.svg" id="20_4oewr"]
-[ext_resource type="Texture2D" uid="uid://d4iq63eypbf2s" path="res://assets/images/gamepad/xbox/xbox_stick_r_down.svg" id="21_r84kb"]
-[ext_resource type="Texture2D" uid="uid://bus2l2lmd844f" path="res://assets/images/gamepad/xbox/xbox_stick_r_left.svg" id="22_s82sf"]
-[ext_resource type="Texture2D" uid="uid://cokparjjmwy8c" path="res://assets/images/gamepad/xbox/xbox_stick_r_right.svg" id="23_nd0cx"]
-[ext_resource type="Texture2D" uid="uid://jn543ff1ak1c" path="res://assets/images/gamepad/xbox/xbox_stick_r_up.svg" id="24_go4xp"]
+[ext_resource type="Texture2D" uid="uid://dqk82r4up56mh" path="res://assets/images/gamepad/xbox/xbox_dpad_round_up.svg" id="6_hdxil"]
+[ext_resource type="Texture2D" uid="uid://cxvxwgt1vox0" path="res://assets/images/gamepad/xbox/xbox_button_color_a.svg" id="6_kekiu"]
+[ext_resource type="Texture2D" uid="uid://ojrh7msglai0" path="res://assets/images/gamepad/xbox/xbox_button_color_x.svg" id="7_5gtvm"]
+[ext_resource type="Texture2D" uid="uid://cwyi3if752xh6" path="res://assets/images/gamepad/xbox/xbox_lb.svg" id="9_5mjlo"]
+[ext_resource type="Texture2D" uid="uid://dqx7njocf1aok" path="res://assets/images/gamepad/xbox/xbox_stick_l.svg" id="10_h038p"]
+[ext_resource type="Texture2D" uid="uid://ckqaven4xmk16" path="res://assets/images/gamepad/xbox/xbox_stick_l_press.svg" id="11_87ajn"]
+[ext_resource type="Texture2D" uid="uid://cg8r4ijx7641s" path="res://assets/images/gamepad/xbox/xbox_lt.svg" id="12_2l3bb"]
+[ext_resource type="Texture2D" uid="uid://c1bfw2axbcg1q" path="res://assets/images/gamepad/xbox/xbox_stick_l_down.svg" id="12_kp3w4"]
+[ext_resource type="Texture2D" uid="uid://c4iwtbyehtps2" path="res://assets/images/gamepad/xbox/xbox_stick_l_left.svg" id="13_8wccm"]
+[ext_resource type="Texture2D" uid="uid://ceiru5s4y3ghy" path="res://assets/images/gamepad/xbox/xbox_rb.svg" id="14_106m0"]
+[ext_resource type="Texture2D" uid="uid://d4bfok8606fmv" path="res://assets/images/gamepad/xbox/xbox_stick_l_right.svg" id="14_m6oqd"]
+[ext_resource type="Texture2D" uid="uid://brt5gm71iv3u4" path="res://assets/images/gamepad/xbox/xbox_rt.svg" id="15_1ae1p"]
+[ext_resource type="Texture2D" uid="uid://c7p0nhy4sh5wf" path="res://assets/images/gamepad/xbox/xbox_stick_l_up.svg" id="15_wqxdi"]
+[ext_resource type="Texture2D" uid="uid://cwxfxkby7fk2a" path="res://assets/images/gamepad/xbox/xbox_button_back_icon.svg" id="17_ewr7o"]
+[ext_resource type="Texture2D" uid="uid://c3v2ch2hw3mhm" path="res://assets/images/gamepad/xbox/xbox_button_start_icon.svg" id="19_5p4eh"]
+[ext_resource type="Texture2D" uid="uid://bjq76f76quyry" path="res://assets/images/gamepad/xbox/xbox_stick_r.svg" id="19_p4shy"]
+[ext_resource type="Texture2D" uid="uid://5q4tjwvf7b8a" path="res://assets/images/gamepad/xbox/xbox_stick_r_press.svg" id="20_4oewr"]
+[ext_resource type="Texture2D" uid="uid://cu3ptt3kea56h" path="res://assets/images/gamepad/xbox/xbox_stick_r_down.svg" id="21_r84kb"]
+[ext_resource type="Texture2D" uid="uid://s4x7rp50eub5" path="res://assets/images/gamepad/xbox/xbox_stick_r_left.svg" id="22_s82sf"]
+[ext_resource type="Texture2D" uid="uid://kfqb1dr0735v" path="res://assets/images/gamepad/xbox/xbox_stick_r_right.svg" id="23_nd0cx"]
+[ext_resource type="Texture2D" uid="uid://o0xrox1l5sae" path="res://assets/images/gamepad/xbox/xbox_stick_r_up.svg" id="24_go4xp"]
[resource]
script = ExtResource("5_qsuka")
name = "XBox 360"
device_names = PackedStringArray("Xbox 360 Controller", "Microsoft X-Box 360 pad")
-diagram = ExtResource("1_ivcim")
+diagram = ExtResource("1_vdrwh")
north = ExtResource("4_yf7fg")
south = ExtResource("6_kekiu")
east = ExtResource("2_scm2e")
diff --git a/assets/gamepad/icon_mappings/xboxone.tres b/assets/gamepad/icon_mappings/xboxone.tres
index 99bd09f8e..d26d14e96 100644
--- a/assets/gamepad/icon_mappings/xboxone.tres
+++ b/assets/gamepad/icon_mappings/xboxone.tres
@@ -1,35 +1,35 @@
[gd_resource type="Resource" script_class="InputIconMapping" load_steps=31 format=3 uid="uid://005wjp70lsdu"]
-[ext_resource type="Texture2D" uid="uid://bie2sf8kjawr" path="res://assets/images/gamepad/xbox/XboxOne_Diagram.png" id="1_7rqq5"]
+[ext_resource type="Texture2D" uid="uid://ceyt88pt5sogo" path="res://assets/images/gamepad/xbox/XboxOne_Diagram.png" id="1_7rqq5"]
[ext_resource type="Script" path="res://core/systems/input/input_icon_mapping.gd" id="1_lckpp"]
-[ext_resource type="Texture2D" uid="uid://cdhd2pnbunvy3" path="res://assets/images/gamepad/xbox/xbox_dpad.svg" id="2_7tdao"]
-[ext_resource type="Texture2D" uid="uid://bju6gytlq2div" path="res://assets/images/gamepad/xbox/xbox_dpad_down.svg" id="3_b76jf"]
-[ext_resource type="Texture2D" uid="uid://candjw8elkekp" path="res://assets/images/gamepad/xbox/xbox_dpad_left.svg" id="4_3pall"]
-[ext_resource type="Texture2D" uid="uid://dcpsb03pvu0vb" path="res://assets/images/gamepad/xbox/xbox_dpad_right.svg" id="5_g2nkq"]
-[ext_resource type="Texture2D" uid="uid://c6w5exkfdkkrr" path="res://assets/images/gamepad/xbox/xbox_dpad_up.svg" id="6_tm6is"]
-[ext_resource type="Texture2D" uid="uid://bqho0a0sr6u1j" path="res://assets/images/gamepad/xbox/xbox_button_color_b.svg" id="7_g13ut"]
-[ext_resource type="Texture2D" uid="uid://bcoajyq8st62e" path="res://assets/images/gamepad/xbox/xbox_guide.svg" id="8_2xbuh"]
-[ext_resource type="Texture2D" uid="uid://mtd8tfnbotgc" path="res://assets/images/gamepad/xbox/xbox_lb.svg" id="9_hg4fs"]
-[ext_resource type="Texture2D" uid="uid://bdqfg27h5o836" path="res://assets/images/gamepad/xbox/xbox_stick_l.svg" id="10_6y3yw"]
-[ext_resource type="Texture2D" uid="uid://dvv5grt45cows" path="res://assets/images/gamepad/xbox/xbox_stick_l_press.svg" id="11_u8jcq"]
-[ext_resource type="Texture2D" uid="uid://dcumk3oqkyy7g" path="res://assets/images/gamepad/xbox/xbox_stick_l_down.svg" id="12_o47r8"]
-[ext_resource type="Texture2D" uid="uid://dooej262t4g0x" path="res://assets/images/gamepad/xbox/xbox_stick_l_left.svg" id="13_k3o80"]
-[ext_resource type="Texture2D" uid="uid://coltjh07der5" path="res://assets/images/gamepad/xbox/xbox_stick_l_right.svg" id="14_5mj40"]
-[ext_resource type="Texture2D" uid="uid://b3xxbnyo2h20l" path="res://assets/images/gamepad/xbox/xbox_stick_l_up.svg" id="15_k4fks"]
-[ext_resource type="Texture2D" uid="uid://u3jonqoafyg6" path="res://assets/images/gamepad/xbox/xbox_lt.svg" id="16_ld8s8"]
-[ext_resource type="Texture2D" uid="uid://ddpudi00yulrx" path="res://assets/images/gamepad/xbox/xbox_button_color_y.svg" id="17_wbg38"]
-[ext_resource type="Texture2D" uid="uid://co3kg331knfu7" path="res://assets/images/gamepad/xbox/xbox_rb.svg" id="18_dqiaq"]
-[ext_resource type="Texture2D" uid="uid://dw15y6xiuthpe" path="res://assets/images/gamepad/xbox/xbox_stick_r.svg" id="19_tfh6l"]
-[ext_resource type="Texture2D" uid="uid://de2kcqeakp3q0" path="res://assets/images/gamepad/xbox/xbox_stick_r_press.svg" id="20_qquah"]
-[ext_resource type="Texture2D" uid="uid://d4iq63eypbf2s" path="res://assets/images/gamepad/xbox/xbox_stick_r_down.svg" id="21_5sudg"]
-[ext_resource type="Texture2D" uid="uid://bus2l2lmd844f" path="res://assets/images/gamepad/xbox/xbox_stick_r_left.svg" id="22_y2dmg"]
-[ext_resource type="Texture2D" uid="uid://cokparjjmwy8c" path="res://assets/images/gamepad/xbox/xbox_stick_r_right.svg" id="23_tnsia"]
-[ext_resource type="Texture2D" uid="uid://jn543ff1ak1c" path="res://assets/images/gamepad/xbox/xbox_stick_r_up.svg" id="24_u3tot"]
-[ext_resource type="Texture2D" uid="uid://da8ojjv5vttou" path="res://assets/images/gamepad/xbox/xbox_rt.svg" id="25_h8btq"]
-[ext_resource type="Texture2D" uid="uid://ce732ysw0pjo1" path="res://assets/images/gamepad/xbox/xbox_button_view.svg" id="27_we8jk"]
-[ext_resource type="Texture2D" uid="uid://dyemqkvdtk43e" path="res://assets/images/gamepad/xbox/xbox_button_color_a.svg" id="28_e6a35"]
-[ext_resource type="Texture2D" uid="uid://dagfma4wnmvw8" path="res://assets/images/gamepad/xbox/xbox_button_menu.svg" id="29_r5b3p"]
-[ext_resource type="Texture2D" uid="uid://cuvx61nakiaoi" path="res://assets/images/gamepad/xbox/xbox_button_color_x.svg" id="30_2but5"]
+[ext_resource type="Texture2D" uid="uid://di87v7xnlu4hd" path="res://assets/images/gamepad/xbox/xbox_dpad.svg" id="2_7tdao"]
+[ext_resource type="Texture2D" uid="uid://brqqse0hid6ki" path="res://assets/images/gamepad/xbox/xbox_dpad_down.svg" id="3_b76jf"]
+[ext_resource type="Texture2D" uid="uid://caqnkbu5b0u2q" path="res://assets/images/gamepad/xbox/xbox_dpad_left.svg" id="4_3pall"]
+[ext_resource type="Texture2D" uid="uid://b5gektw3mgp1a" path="res://assets/images/gamepad/xbox/xbox_dpad_right.svg" id="5_g2nkq"]
+[ext_resource type="Texture2D" uid="uid://cjwqn3wttist" path="res://assets/images/gamepad/xbox/xbox_dpad_up.svg" id="6_tm6is"]
+[ext_resource type="Texture2D" uid="uid://dfby3iiksln2e" path="res://assets/images/gamepad/xbox/xbox_button_color_b.svg" id="7_g13ut"]
+[ext_resource type="Texture2D" uid="uid://dq7kibukggise" path="res://assets/images/gamepad/xbox/xbox_guide.svg" id="8_2xbuh"]
+[ext_resource type="Texture2D" uid="uid://cwyi3if752xh6" path="res://assets/images/gamepad/xbox/xbox_lb.svg" id="9_hg4fs"]
+[ext_resource type="Texture2D" uid="uid://dqx7njocf1aok" path="res://assets/images/gamepad/xbox/xbox_stick_l.svg" id="10_6y3yw"]
+[ext_resource type="Texture2D" uid="uid://ckqaven4xmk16" path="res://assets/images/gamepad/xbox/xbox_stick_l_press.svg" id="11_u8jcq"]
+[ext_resource type="Texture2D" uid="uid://c1bfw2axbcg1q" path="res://assets/images/gamepad/xbox/xbox_stick_l_down.svg" id="12_o47r8"]
+[ext_resource type="Texture2D" uid="uid://c4iwtbyehtps2" path="res://assets/images/gamepad/xbox/xbox_stick_l_left.svg" id="13_k3o80"]
+[ext_resource type="Texture2D" uid="uid://d4bfok8606fmv" path="res://assets/images/gamepad/xbox/xbox_stick_l_right.svg" id="14_5mj40"]
+[ext_resource type="Texture2D" uid="uid://c7p0nhy4sh5wf" path="res://assets/images/gamepad/xbox/xbox_stick_l_up.svg" id="15_k4fks"]
+[ext_resource type="Texture2D" uid="uid://cg8r4ijx7641s" path="res://assets/images/gamepad/xbox/xbox_lt.svg" id="16_ld8s8"]
+[ext_resource type="Texture2D" uid="uid://b81pjmldtt10s" path="res://assets/images/gamepad/xbox/xbox_button_color_y.svg" id="17_wbg38"]
+[ext_resource type="Texture2D" uid="uid://ceiru5s4y3ghy" path="res://assets/images/gamepad/xbox/xbox_rb.svg" id="18_dqiaq"]
+[ext_resource type="Texture2D" uid="uid://bjq76f76quyry" path="res://assets/images/gamepad/xbox/xbox_stick_r.svg" id="19_tfh6l"]
+[ext_resource type="Texture2D" uid="uid://5q4tjwvf7b8a" path="res://assets/images/gamepad/xbox/xbox_stick_r_press.svg" id="20_qquah"]
+[ext_resource type="Texture2D" uid="uid://cu3ptt3kea56h" path="res://assets/images/gamepad/xbox/xbox_stick_r_down.svg" id="21_5sudg"]
+[ext_resource type="Texture2D" uid="uid://s4x7rp50eub5" path="res://assets/images/gamepad/xbox/xbox_stick_r_left.svg" id="22_y2dmg"]
+[ext_resource type="Texture2D" uid="uid://kfqb1dr0735v" path="res://assets/images/gamepad/xbox/xbox_stick_r_right.svg" id="23_tnsia"]
+[ext_resource type="Texture2D" uid="uid://o0xrox1l5sae" path="res://assets/images/gamepad/xbox/xbox_stick_r_up.svg" id="24_u3tot"]
+[ext_resource type="Texture2D" uid="uid://brt5gm71iv3u4" path="res://assets/images/gamepad/xbox/xbox_rt.svg" id="25_h8btq"]
+[ext_resource type="Texture2D" uid="uid://cws272by4n8r7" path="res://assets/images/gamepad/xbox/xbox_button_view.svg" id="27_we8jk"]
+[ext_resource type="Texture2D" uid="uid://cxvxwgt1vox0" path="res://assets/images/gamepad/xbox/xbox_button_color_a.svg" id="28_e6a35"]
+[ext_resource type="Texture2D" uid="uid://ckk2my0j71i3r" path="res://assets/images/gamepad/xbox/xbox_button_menu.svg" id="29_r5b3p"]
+[ext_resource type="Texture2D" uid="uid://ojrh7msglai0" path="res://assets/images/gamepad/xbox/xbox_button_color_x.svg" id="30_2but5"]
[resource]
script = ExtResource("1_lckpp")
diff --git a/assets/gamepad/icon_mappings/xboxseries.tres b/assets/gamepad/icon_mappings/xboxseries.tres
index dcae369b8..68d461b2b 100644
--- a/assets/gamepad/icon_mappings/xboxseries.tres
+++ b/assets/gamepad/icon_mappings/xboxseries.tres
@@ -1,36 +1,36 @@
[gd_resource type="Resource" script_class="InputIconMapping" load_steps=32 format=3 uid="uid://bpu8kbwkjlcdf"]
[ext_resource type="Script" path="res://core/systems/input/input_icon_mapping.gd" id="1_b6rct"]
-[ext_resource type="Texture2D" uid="uid://bie2sf8kjawr" path="res://assets/images/gamepad/xbox/XboxOne_Diagram.png" id="1_ev5wy"]
-[ext_resource type="Texture2D" uid="uid://dn8i3gpeijgu1" path="res://assets/images/gamepad/xbox/xbox_dpad_round.svg" id="2_6ynjl"]
-[ext_resource type="Texture2D" uid="uid://dwv3f88h7uaq7" path="res://assets/images/gamepad/xbox/xbox_dpad_round_down.svg" id="3_xm811"]
-[ext_resource type="Texture2D" uid="uid://fmnwuu2ym0m8" path="res://assets/images/gamepad/xbox/xbox_dpad_round_left.svg" id="4_uybyb"]
-[ext_resource type="Texture2D" uid="uid://cboy1enwvdeoy" path="res://assets/images/gamepad/xbox/xbox_dpad_round_right.svg" id="5_tp8q3"]
-[ext_resource type="Texture2D" uid="uid://ba64eulr61afh" path="res://assets/images/gamepad/xbox/xbox_dpad_round_up.svg" id="6_1xdjq"]
-[ext_resource type="Texture2D" uid="uid://bqho0a0sr6u1j" path="res://assets/images/gamepad/xbox/xbox_button_color_b.svg" id="7_hobo3"]
-[ext_resource type="Texture2D" uid="uid://bcoajyq8st62e" path="res://assets/images/gamepad/xbox/xbox_guide.svg" id="8_auhb1"]
-[ext_resource type="Texture2D" uid="uid://mtd8tfnbotgc" path="res://assets/images/gamepad/xbox/xbox_lb.svg" id="9_hctac"]
-[ext_resource type="Texture2D" uid="uid://bdqfg27h5o836" path="res://assets/images/gamepad/xbox/xbox_stick_l.svg" id="10_xwigx"]
-[ext_resource type="Texture2D" uid="uid://dvv5grt45cows" path="res://assets/images/gamepad/xbox/xbox_stick_l_press.svg" id="11_xcmc2"]
-[ext_resource type="Texture2D" uid="uid://dcumk3oqkyy7g" path="res://assets/images/gamepad/xbox/xbox_stick_l_down.svg" id="12_nxi2e"]
-[ext_resource type="Texture2D" uid="uid://dooej262t4g0x" path="res://assets/images/gamepad/xbox/xbox_stick_l_left.svg" id="13_p1oy0"]
-[ext_resource type="Texture2D" uid="uid://coltjh07der5" path="res://assets/images/gamepad/xbox/xbox_stick_l_right.svg" id="14_8q8uu"]
-[ext_resource type="Texture2D" uid="uid://b3xxbnyo2h20l" path="res://assets/images/gamepad/xbox/xbox_stick_l_up.svg" id="15_cswmi"]
-[ext_resource type="Texture2D" uid="uid://u3jonqoafyg6" path="res://assets/images/gamepad/xbox/xbox_lt.svg" id="16_uewt6"]
-[ext_resource type="Texture2D" uid="uid://ddpudi00yulrx" path="res://assets/images/gamepad/xbox/xbox_button_color_y.svg" id="17_sgpdy"]
-[ext_resource type="Texture2D" uid="uid://co3kg331knfu7" path="res://assets/images/gamepad/xbox/xbox_rb.svg" id="18_1nrje"]
-[ext_resource type="Texture2D" uid="uid://dw15y6xiuthpe" path="res://assets/images/gamepad/xbox/xbox_stick_r.svg" id="19_a20m1"]
-[ext_resource type="Texture2D" uid="uid://de2kcqeakp3q0" path="res://assets/images/gamepad/xbox/xbox_stick_r_press.svg" id="20_4odka"]
-[ext_resource type="Texture2D" uid="uid://d4iq63eypbf2s" path="res://assets/images/gamepad/xbox/xbox_stick_r_down.svg" id="21_dg0kt"]
-[ext_resource type="Texture2D" uid="uid://bus2l2lmd844f" path="res://assets/images/gamepad/xbox/xbox_stick_r_left.svg" id="22_2ed5x"]
-[ext_resource type="Texture2D" uid="uid://cokparjjmwy8c" path="res://assets/images/gamepad/xbox/xbox_stick_r_right.svg" id="23_vchpt"]
-[ext_resource type="Texture2D" uid="uid://jn543ff1ak1c" path="res://assets/images/gamepad/xbox/xbox_stick_r_up.svg" id="24_3b4ji"]
-[ext_resource type="Texture2D" uid="uid://da8ojjv5vttou" path="res://assets/images/gamepad/xbox/xbox_rt.svg" id="25_1f2e0"]
-[ext_resource type="Texture2D" uid="uid://ce732ysw0pjo1" path="res://assets/images/gamepad/xbox/xbox_button_view.svg" id="27_yvhvb"]
-[ext_resource type="Texture2D" uid="uid://dasqdy0fqn33r" path="res://assets/images/gamepad/xbox/xbox_button_share.svg" id="28_kfx4h"]
-[ext_resource type="Texture2D" uid="uid://dyemqkvdtk43e" path="res://assets/images/gamepad/xbox/xbox_button_color_a.svg" id="28_wmep3"]
-[ext_resource type="Texture2D" uid="uid://dagfma4wnmvw8" path="res://assets/images/gamepad/xbox/xbox_button_menu.svg" id="30_0yia7"]
-[ext_resource type="Texture2D" uid="uid://cuvx61nakiaoi" path="res://assets/images/gamepad/xbox/xbox_button_color_x.svg" id="30_ubo18"]
+[ext_resource type="Texture2D" uid="uid://ceyt88pt5sogo" path="res://assets/images/gamepad/xbox/XboxOne_Diagram.png" id="1_ev5wy"]
+[ext_resource type="Texture2D" uid="uid://n4t36xrl15ux" path="res://assets/images/gamepad/xbox/xbox_dpad_round.svg" id="2_6ynjl"]
+[ext_resource type="Texture2D" uid="uid://bxovdah6vnpsn" path="res://assets/images/gamepad/xbox/xbox_dpad_round_down.svg" id="3_xm811"]
+[ext_resource type="Texture2D" uid="uid://qhwj81sv67l4" path="res://assets/images/gamepad/xbox/xbox_dpad_round_left.svg" id="4_uybyb"]
+[ext_resource type="Texture2D" uid="uid://b1uo5130s6gfw" path="res://assets/images/gamepad/xbox/xbox_dpad_round_right.svg" id="5_tp8q3"]
+[ext_resource type="Texture2D" uid="uid://dqk82r4up56mh" path="res://assets/images/gamepad/xbox/xbox_dpad_round_up.svg" id="6_1xdjq"]
+[ext_resource type="Texture2D" uid="uid://dfby3iiksln2e" path="res://assets/images/gamepad/xbox/xbox_button_color_b.svg" id="7_hobo3"]
+[ext_resource type="Texture2D" uid="uid://dq7kibukggise" path="res://assets/images/gamepad/xbox/xbox_guide.svg" id="8_auhb1"]
+[ext_resource type="Texture2D" uid="uid://cwyi3if752xh6" path="res://assets/images/gamepad/xbox/xbox_lb.svg" id="9_hctac"]
+[ext_resource type="Texture2D" uid="uid://dqx7njocf1aok" path="res://assets/images/gamepad/xbox/xbox_stick_l.svg" id="10_xwigx"]
+[ext_resource type="Texture2D" uid="uid://ckqaven4xmk16" path="res://assets/images/gamepad/xbox/xbox_stick_l_press.svg" id="11_xcmc2"]
+[ext_resource type="Texture2D" uid="uid://c1bfw2axbcg1q" path="res://assets/images/gamepad/xbox/xbox_stick_l_down.svg" id="12_nxi2e"]
+[ext_resource type="Texture2D" uid="uid://c4iwtbyehtps2" path="res://assets/images/gamepad/xbox/xbox_stick_l_left.svg" id="13_p1oy0"]
+[ext_resource type="Texture2D" uid="uid://d4bfok8606fmv" path="res://assets/images/gamepad/xbox/xbox_stick_l_right.svg" id="14_8q8uu"]
+[ext_resource type="Texture2D" uid="uid://c7p0nhy4sh5wf" path="res://assets/images/gamepad/xbox/xbox_stick_l_up.svg" id="15_cswmi"]
+[ext_resource type="Texture2D" uid="uid://cg8r4ijx7641s" path="res://assets/images/gamepad/xbox/xbox_lt.svg" id="16_uewt6"]
+[ext_resource type="Texture2D" uid="uid://b81pjmldtt10s" path="res://assets/images/gamepad/xbox/xbox_button_color_y.svg" id="17_sgpdy"]
+[ext_resource type="Texture2D" uid="uid://ceiru5s4y3ghy" path="res://assets/images/gamepad/xbox/xbox_rb.svg" id="18_1nrje"]
+[ext_resource type="Texture2D" uid="uid://bjq76f76quyry" path="res://assets/images/gamepad/xbox/xbox_stick_r.svg" id="19_a20m1"]
+[ext_resource type="Texture2D" uid="uid://5q4tjwvf7b8a" path="res://assets/images/gamepad/xbox/xbox_stick_r_press.svg" id="20_4odka"]
+[ext_resource type="Texture2D" uid="uid://cu3ptt3kea56h" path="res://assets/images/gamepad/xbox/xbox_stick_r_down.svg" id="21_dg0kt"]
+[ext_resource type="Texture2D" uid="uid://s4x7rp50eub5" path="res://assets/images/gamepad/xbox/xbox_stick_r_left.svg" id="22_2ed5x"]
+[ext_resource type="Texture2D" uid="uid://kfqb1dr0735v" path="res://assets/images/gamepad/xbox/xbox_stick_r_right.svg" id="23_vchpt"]
+[ext_resource type="Texture2D" uid="uid://o0xrox1l5sae" path="res://assets/images/gamepad/xbox/xbox_stick_r_up.svg" id="24_3b4ji"]
+[ext_resource type="Texture2D" uid="uid://brt5gm71iv3u4" path="res://assets/images/gamepad/xbox/xbox_rt.svg" id="25_1f2e0"]
+[ext_resource type="Texture2D" uid="uid://cws272by4n8r7" path="res://assets/images/gamepad/xbox/xbox_button_view.svg" id="27_yvhvb"]
+[ext_resource type="Texture2D" uid="uid://crda44th28ovn" path="res://assets/images/gamepad/xbox/xbox_button_share.svg" id="28_kfx4h"]
+[ext_resource type="Texture2D" uid="uid://cxvxwgt1vox0" path="res://assets/images/gamepad/xbox/xbox_button_color_a.svg" id="28_wmep3"]
+[ext_resource type="Texture2D" uid="uid://ckk2my0j71i3r" path="res://assets/images/gamepad/xbox/xbox_button_menu.svg" id="30_0yia7"]
+[ext_resource type="Texture2D" uid="uid://ojrh7msglai0" path="res://assets/images/gamepad/xbox/xbox_button_color_x.svg" id="30_ubo18"]
[resource]
script = ExtResource("1_b6rct")
diff --git a/assets/gamepad/profiles/default.json b/assets/gamepad/profiles/default.json
index cbed2a772..4517be37a 100644
--- a/assets/gamepad/profiles/default.json
+++ b/assets/gamepad/profiles/default.json
@@ -1,7 +1,7 @@
{
"version": 1,
"kind": "DeviceProfile",
- "name": "Default",
+ "name": "OpenGamepadUI Default",
"mapping": [
{
"name": "LeftTop",
@@ -52,14 +52,7 @@
},
"target_events": [
{
- "gamepad": {
- "button": "Guide"
- }
- },
- {
- "gamepad": {
- "button": "North"
- }
+ "dbus": "ui_osk"
}
]
},
@@ -82,6 +75,19 @@
}
}
]
+ },
+ {
+ "name": "QuickAccess",
+ "source_event": {
+ "gamepad": {
+ "button": "QuickAccess"
+ }
+ },
+ "target_events": [
+ {
+ "dbus": "ui_quick"
+ }
+ ]
}
]
}
diff --git a/assets/images/gamepad/ayaneo-2/diagram.png.import b/assets/images/gamepad/ayaneo-2/diagram.png.import
index 9c835f44f..c677728e7 100644
--- a/assets/images/gamepad/ayaneo-2/diagram.png.import
+++ b/assets/images/gamepad/ayaneo-2/diagram.png.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cutkhw5cn00t1"
+uid="uid://0ks0l6lrjisb"
path="res://.godot/imported/diagram.png-f50e7f3c087f705f9d78ceca7847be41.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/ayaneo-2021/diagram.png.png.import b/assets/images/gamepad/ayaneo-2021/diagram.png.png.import
index 9fd83ecf9..24a4ad23e 100644
--- a/assets/images/gamepad/ayaneo-2021/diagram.png.png.import
+++ b/assets/images/gamepad/ayaneo-2021/diagram.png.png.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bju0qdfa1agbx"
+uid="uid://bycwbaq43ecps"
path="res://.godot/imported/diagram.png.png-a9db9f2667b0184a3fe15017167f42a7.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/ayaneo-air/diagram.png.import b/assets/images/gamepad/ayaneo-air/diagram.png.import
index b16952dc1..9349fe36e 100644
--- a/assets/images/gamepad/ayaneo-air/diagram.png.import
+++ b/assets/images/gamepad/ayaneo-air/diagram.png.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bkmukuppf8aga"
+uid="uid://ol30ae8sw3j"
path="res://.godot/imported/diagram.png-78a360acd3fc560b6d6e676e7bf7c1f3.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/ayaneo-next/diagram.png.import b/assets/images/gamepad/ayaneo-next/diagram.png.import
index 41f790c5b..a8d05221b 100644
--- a/assets/images/gamepad/ayaneo-next/diagram.png.import
+++ b/assets/images/gamepad/ayaneo-next/diagram.png.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://by00fwcpvklck"
+uid="uid://f8no2jrnw4qq"
path="res://.godot/imported/diagram.png-98af58cfaf32d93ba4eb60fc0c58fa92.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/generic/generic_button_circle.svg.import b/assets/images/gamepad/generic/generic_button_circle.svg.import
index 1e5d55b08..61465dfb2 100644
--- a/assets/images/gamepad/generic/generic_button_circle.svg.import
+++ b/assets/images/gamepad/generic/generic_button_circle.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://c5oweso4md55c"
+uid="uid://ytg4and6kiyc"
path="res://.godot/imported/generic_button_circle.svg-f9f0a7d2857249866da78c46a084e942.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/generic/gyro.png.import b/assets/images/gamepad/generic/gyro.png.import
index 40331ea7a..3a8554280 100644
--- a/assets/images/gamepad/generic/gyro.png.import
+++ b/assets/images/gamepad/generic/gyro.png.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bi2887g54x4ym"
+uid="uid://do8ip0e6vs5h5"
path="res://.godot/imported/gyro.png-8d4572ae245f576c2f8b62cdee4d47a0.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/luna/Luna_Diagram_Simple.png.import b/assets/images/gamepad/luna/Luna_Diagram_Simple.png.import
index a134c31c4..856690e6e 100644
--- a/assets/images/gamepad/luna/Luna_Diagram_Simple.png.import
+++ b/assets/images/gamepad/luna/Luna_Diagram_Simple.png.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://ct1wx8gqcmp2x"
+uid="uid://b6o0kbjxrsmef"
path="res://.godot/imported/Luna_Diagram_Simple.png-c5bfecf21132287f0b480f6e101196f0.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/oxp/a.png.import b/assets/images/gamepad/oxp/a.png.import
index 67acfba0d..5fba563c8 100644
--- a/assets/images/gamepad/oxp/a.png.import
+++ b/assets/images/gamepad/oxp/a.png.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://ddj7iydr5c04r"
+uid="uid://vmqhe01e4iit"
path="res://.godot/imported/a.png-adb7e9f43d4988d915e3c2cced5e214c.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/oxp/b.png.import b/assets/images/gamepad/oxp/b.png.import
index 319acdf0e..3aceb3f22 100644
--- a/assets/images/gamepad/oxp/b.png.import
+++ b/assets/images/gamepad/oxp/b.png.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b3ofivkj5cwdd"
+uid="uid://c8cjp8mh52xh2"
path="res://.godot/imported/b.png-ccadb030652ec36982b4edf9756cd5c6.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/oxp/dots.png.import b/assets/images/gamepad/oxp/dots.png.import
index 0ffe9eaf0..90d2c591e 100644
--- a/assets/images/gamepad/oxp/dots.png.import
+++ b/assets/images/gamepad/oxp/dots.png.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://55kdld1mn8sh"
+uid="uid://wmris721srn5"
path="res://.godot/imported/dots.png-aa558f692310d0b6110a9f5cd1200254.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/oxp/gyro.png.import b/assets/images/gamepad/oxp/gyro.png.import
index f8483af57..60d49d3fe 100644
--- a/assets/images/gamepad/oxp/gyro.png.import
+++ b/assets/images/gamepad/oxp/gyro.png.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bicbp0it5onk"
+uid="uid://b156x3h81b827"
path="res://.godot/imported/gyro.png-bd99b5512fb99777e2b958e5b4fe065d.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/oxp/home.png.import b/assets/images/gamepad/oxp/home.png.import
index d6bdefeef..ee68c73e0 100644
--- a/assets/images/gamepad/oxp/home.png.import
+++ b/assets/images/gamepad/oxp/home.png.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cu0fgwxtupy5y"
+uid="uid://c00vtor5dsj8n"
path="res://.godot/imported/home.png-a880cdd0ca077c0f417c531781309c23.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/oxp/l_stick.png.import b/assets/images/gamepad/oxp/l_stick.png.import
index 050eae854..9d4a31d98 100644
--- a/assets/images/gamepad/oxp/l_stick.png.import
+++ b/assets/images/gamepad/oxp/l_stick.png.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://1grh7tb8l2ev"
+uid="uid://do2o0rko3dl8q"
path="res://.godot/imported/l_stick.png-e6268b4a4b2a52faf165716609590ea1.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/oxp/l_stick_click.png.import b/assets/images/gamepad/oxp/l_stick_click.png.import
index 72177a168..19ae815c0 100644
--- a/assets/images/gamepad/oxp/l_stick_click.png.import
+++ b/assets/images/gamepad/oxp/l_stick_click.png.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cxrw6ik2qxvjv"
+uid="uid://d1nbyq2klq1o3"
path="res://.godot/imported/l_stick_click.png-61804b5213d32b45fe69d3f2785613aa.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/oxp/menu.png.import b/assets/images/gamepad/oxp/menu.png.import
index 1ea3c3a3c..3e565fc7c 100644
--- a/assets/images/gamepad/oxp/menu.png.import
+++ b/assets/images/gamepad/oxp/menu.png.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://8bjdmpmjwbrh"
+uid="uid://dyfisopofd1ml"
path="res://.godot/imported/menu.png-3f32e1e8fb1b69686806894f351a3c13.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/oxp/oxp-mini-a07.png.import b/assets/images/gamepad/oxp/oxp-mini-a07.png.import
index cb4f74bf6..2614b11be 100644
--- a/assets/images/gamepad/oxp/oxp-mini-a07.png.import
+++ b/assets/images/gamepad/oxp/oxp-mini-a07.png.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://hmebqgl4qfmc"
+uid="uid://d224crt7h1b8l"
path="res://.godot/imported/oxp-mini-a07.png-47d2e27d7da4015b7fb2c32e4a3ec788.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/oxp/r_stick.png.import b/assets/images/gamepad/oxp/r_stick.png.import
index b45211131..5e385ad20 100644
--- a/assets/images/gamepad/oxp/r_stick.png.import
+++ b/assets/images/gamepad/oxp/r_stick.png.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://c12df6tk1yof7"
+uid="uid://2efop4m33tk3"
path="res://.godot/imported/r_stick.png-b0146314735f965f9130034d6d7630fc.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/oxp/r_stick_click.png.import b/assets/images/gamepad/oxp/r_stick_click.png.import
index 8fb0cf49e..5ce52c25c 100644
--- a/assets/images/gamepad/oxp/r_stick_click.png.import
+++ b/assets/images/gamepad/oxp/r_stick_click.png.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://mxd2r3jqn10"
+uid="uid://csfqtx1sfw3kn"
path="res://.godot/imported/r_stick_click.png-557e77aa943c46c2a0d17ebf192978f7.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/oxp/square.png.import b/assets/images/gamepad/oxp/square.png.import
index 9f7ba1773..46ac18886 100644
--- a/assets/images/gamepad/oxp/square.png.import
+++ b/assets/images/gamepad/oxp/square.png.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://xarlsdq5yd4l"
+uid="uid://ob0fpdvy6aya"
path="res://.godot/imported/square.png-d8270a92bf98e3fb174fc7fbe2426fef.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/oxp/x.png.import b/assets/images/gamepad/oxp/x.png.import
index f3b3f72ba..8c748d6d2 100644
--- a/assets/images/gamepad/oxp/x.png.import
+++ b/assets/images/gamepad/oxp/x.png.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://ddma44dieeu0c"
+uid="uid://cgsn52xbh5g7n"
path="res://.godot/imported/x.png-ffd94bc4c243f828262a0e08def527fa.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/oxp/y.png.import b/assets/images/gamepad/oxp/y.png.import
index 916ea9ed0..bae4118fc 100644
--- a/assets/images/gamepad/oxp/y.png.import
+++ b/assets/images/gamepad/oxp/y.png.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cfeud3gaq056l"
+uid="uid://dqhw0phvf3tre"
path="res://.godot/imported/y.png-659c755ba143af92e8840bf905b0ba06.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/PS4_Diagram_Simple.png.import b/assets/images/gamepad/playstation/PS4_Diagram_Simple.png.import
index 77d53a3c6..fed3ff5ab 100644
--- a/assets/images/gamepad/playstation/PS4_Diagram_Simple.png.import
+++ b/assets/images/gamepad/playstation/PS4_Diagram_Simple.png.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://brf1l7pyedsg6"
+uid="uid://b6ebettxxbmu1"
path="res://.godot/imported/PS4_Diagram_Simple.png-9de8a8def0da5353241716fed618be6c.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/PS5_Diagram_Simple.png.import b/assets/images/gamepad/playstation/PS5_Diagram_Simple.png.import
index a6d4562b3..8dbb9bd35 100644
--- a/assets/images/gamepad/playstation/PS5_Diagram_Simple.png.import
+++ b/assets/images/gamepad/playstation/PS5_Diagram_Simple.png.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://biu5qfv6e1mq8"
+uid="uid://devahu3vo6pdj"
path="res://.godot/imported/PS5_Diagram_Simple.png-7a455e97137ffa78f17bc447a3926f67.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/controller_playstation1.svg.import b/assets/images/gamepad/playstation/controller_playstation1.svg.import
index 7e7adb191..6cfae665e 100644
--- a/assets/images/gamepad/playstation/controller_playstation1.svg.import
+++ b/assets/images/gamepad/playstation/controller_playstation1.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cs6ubfgvplwfp"
+uid="uid://byh1x35alqdq7"
path="res://.godot/imported/controller_playstation1.svg-c3bec59d35d7f0b9cf561ebd3ac4669c.ctex"
metadata={
"vram_texture": false
@@ -32,6 +32,6 @@ process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
-svg/scale=15.0
+svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false
diff --git a/assets/images/gamepad/playstation/controller_playstation2.svg.import b/assets/images/gamepad/playstation/controller_playstation2.svg.import
index 7709120f5..ed1c4fd09 100644
--- a/assets/images/gamepad/playstation/controller_playstation2.svg.import
+++ b/assets/images/gamepad/playstation/controller_playstation2.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://ix4y28aaadi5"
+uid="uid://cpavuyofh1t5b"
path="res://.godot/imported/controller_playstation2.svg-0a490338d7897aa8ddd715fc3576fe4d.ctex"
metadata={
"vram_texture": false
@@ -32,6 +32,6 @@ process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
-svg/scale=15.0
+svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false
diff --git a/assets/images/gamepad/playstation/controller_playstation3.svg.import b/assets/images/gamepad/playstation/controller_playstation3.svg.import
index db6a04088..a90c8c884 100644
--- a/assets/images/gamepad/playstation/controller_playstation3.svg.import
+++ b/assets/images/gamepad/playstation/controller_playstation3.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://uopdu8w1sjci"
+uid="uid://gr1o4cqn6m22"
path="res://.godot/imported/controller_playstation3.svg-08fa9901d1d1775542e7bcdf7c601d1c.ctex"
metadata={
"vram_texture": false
@@ -32,6 +32,6 @@ process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
-svg/scale=15.0
+svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false
diff --git a/assets/images/gamepad/playstation/controller_playstation4.svg.import b/assets/images/gamepad/playstation/controller_playstation4.svg.import
index 22e962c79..0aeea0540 100644
--- a/assets/images/gamepad/playstation/controller_playstation4.svg.import
+++ b/assets/images/gamepad/playstation/controller_playstation4.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dq281njbgcpjs"
+uid="uid://kj50pj05684x"
path="res://.godot/imported/controller_playstation4.svg-ea4196e59dca750d0d60766e88bc9587.ctex"
metadata={
"vram_texture": false
@@ -32,6 +32,6 @@ process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
-svg/scale=15.0
+svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false
diff --git a/assets/images/gamepad/playstation/controller_playstation5.svg.import b/assets/images/gamepad/playstation/controller_playstation5.svg.import
index eed12a74b..dd13f386f 100644
--- a/assets/images/gamepad/playstation/controller_playstation5.svg.import
+++ b/assets/images/gamepad/playstation/controller_playstation5.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://guwve61cbjpj"
+uid="uid://cv4w2wqlkt341"
path="res://.godot/imported/controller_playstation5.svg-cc6541a198815a9e4d2d6fe7cf5e23d6.ctex"
metadata={
"vram_texture": false
@@ -32,6 +32,6 @@ process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
-svg/scale=15.0
+svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false
diff --git a/assets/images/gamepad/playstation/guide.svg.import b/assets/images/gamepad/playstation/guide.svg.import
index e4d2203d3..081b77ea1 100644
--- a/assets/images/gamepad/playstation/guide.svg.import
+++ b/assets/images/gamepad/playstation/guide.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dt6pmeivafjuh"
+uid="uid://b6qllts4hg3my"
path="res://.godot/imported/guide.svg-ce9434d207a41e6efefcb450d49d0b19.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation3_button_select.svg.import b/assets/images/gamepad/playstation/playstation3_button_select.svg.import
index c9257fa7e..dd5b542e5 100644
--- a/assets/images/gamepad/playstation/playstation3_button_select.svg.import
+++ b/assets/images/gamepad/playstation/playstation3_button_select.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://btcpbcj64i6w3"
+uid="uid://duedso6l7wcd3"
path="res://.godot/imported/playstation3_button_select.svg-20e8bc106a233146c77984cfc95fdc86.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation3_button_select_outline.svg.import b/assets/images/gamepad/playstation/playstation3_button_select_outline.svg.import
index ff1405fae..f669dab9a 100644
--- a/assets/images/gamepad/playstation/playstation3_button_select_outline.svg.import
+++ b/assets/images/gamepad/playstation/playstation3_button_select_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dx6m1lx0lq23s"
+uid="uid://c1mptm48tj211"
path="res://.godot/imported/playstation3_button_select_outline.svg-54416d6a0fcd2eb4ef6219f80fd46689.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation3_button_start.svg.import b/assets/images/gamepad/playstation/playstation3_button_start.svg.import
index 39a37725c..c20f23f03 100644
--- a/assets/images/gamepad/playstation/playstation3_button_start.svg.import
+++ b/assets/images/gamepad/playstation/playstation3_button_start.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://c42k3k486kupj"
+uid="uid://dyy835yt85d1h"
path="res://.godot/imported/playstation3_button_start.svg-52212432baef095e029d7cc27bad1e4b.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation3_button_start_outline.svg.import b/assets/images/gamepad/playstation/playstation3_button_start_outline.svg.import
index 6329e352c..a1fd5ea57 100644
--- a/assets/images/gamepad/playstation/playstation3_button_start_outline.svg.import
+++ b/assets/images/gamepad/playstation/playstation3_button_start_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b2aavhjxo2k1c"
+uid="uid://dmx0c7u4ov8uv"
path="res://.godot/imported/playstation3_button_start_outline.svg-7272ebeebbac0b97d5c2a0ddac0b6bea.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation4_button_options.svg.import b/assets/images/gamepad/playstation/playstation4_button_options.svg.import
index 42ea2a8e0..a57fc466a 100644
--- a/assets/images/gamepad/playstation/playstation4_button_options.svg.import
+++ b/assets/images/gamepad/playstation/playstation4_button_options.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bbekpvxt1viwr"
+uid="uid://ci7bqueqpt20u"
path="res://.godot/imported/playstation4_button_options.svg-c9fd31a00b2d775038c55898004be7d1.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation4_button_options_outline.svg.import b/assets/images/gamepad/playstation/playstation4_button_options_outline.svg.import
index 6e42089f8..96161342d 100644
--- a/assets/images/gamepad/playstation/playstation4_button_options_outline.svg.import
+++ b/assets/images/gamepad/playstation/playstation4_button_options_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://625c0wogf48s"
+uid="uid://bmg02xcx2rbus"
path="res://.godot/imported/playstation4_button_options_outline.svg-9a7ca97c9da69171b5f8531af6131ebe.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation4_button_share.svg.import b/assets/images/gamepad/playstation/playstation4_button_share.svg.import
index 5eec9550d..4cc22dd3c 100644
--- a/assets/images/gamepad/playstation/playstation4_button_share.svg.import
+++ b/assets/images/gamepad/playstation/playstation4_button_share.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cvx6k287vtlda"
+uid="uid://bb0cv3hsg3y0v"
path="res://.godot/imported/playstation4_button_share.svg-79b64357e6d64c26651cfb08560f5988.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation4_button_share_outline.svg.import b/assets/images/gamepad/playstation/playstation4_button_share_outline.svg.import
index 14cd1677c..b0be3a540 100644
--- a/assets/images/gamepad/playstation/playstation4_button_share_outline.svg.import
+++ b/assets/images/gamepad/playstation/playstation4_button_share_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cqp7tf0yr3ac6"
+uid="uid://b3qq5f7s37yx6"
path="res://.godot/imported/playstation4_button_share_outline.svg-218d0fd990e503ace50b48ff8d8bb1fa.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation4_touchpad.svg.import b/assets/images/gamepad/playstation/playstation4_touchpad.svg.import
index b0c49200e..8a59e8594 100644
--- a/assets/images/gamepad/playstation/playstation4_touchpad.svg.import
+++ b/assets/images/gamepad/playstation/playstation4_touchpad.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b7w1bs67uogco"
+uid="uid://h0mg7dksau38"
path="res://.godot/imported/playstation4_touchpad.svg-0f48b732be68289ac7488f137537a381.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation4_touchpad_outline.svg.import b/assets/images/gamepad/playstation/playstation4_touchpad_outline.svg.import
index dc33a3348..fcda17a27 100644
--- a/assets/images/gamepad/playstation/playstation4_touchpad_outline.svg.import
+++ b/assets/images/gamepad/playstation/playstation4_touchpad_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bxoilijemljux"
+uid="uid://cwc5kohjy5k2f"
path="res://.godot/imported/playstation4_touchpad_outline.svg-7648d6b6826d06b07af9aad68a2a707c.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation4_touchpad_touch.svg.import b/assets/images/gamepad/playstation/playstation4_touchpad_touch.svg.import
index c3af57467..f5eedf1e2 100644
--- a/assets/images/gamepad/playstation/playstation4_touchpad_touch.svg.import
+++ b/assets/images/gamepad/playstation/playstation4_touchpad_touch.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cgt42jlee1t3"
+uid="uid://clihwqudrnv5k"
path="res://.godot/imported/playstation4_touchpad_touch.svg-3183d886f32b32c8210d5b5d1a4739d1.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation4_touchpad_touch_outline.svg.import b/assets/images/gamepad/playstation/playstation4_touchpad_touch_outline.svg.import
index 776316ae4..5b869e9e9 100644
--- a/assets/images/gamepad/playstation/playstation4_touchpad_touch_outline.svg.import
+++ b/assets/images/gamepad/playstation/playstation4_touchpad_touch_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://010wt5wrk1s3"
+uid="uid://br3r6oqplp8xc"
path="res://.godot/imported/playstation4_touchpad_touch_outline.svg-44c0823bf709e7c3981a12b76997b01c.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation5_button_create.svg.import b/assets/images/gamepad/playstation/playstation5_button_create.svg.import
index 85920a871..08fa2b92c 100644
--- a/assets/images/gamepad/playstation/playstation5_button_create.svg.import
+++ b/assets/images/gamepad/playstation/playstation5_button_create.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://y4ntbxk5qrpo"
+uid="uid://lsf27o58vimw"
path="res://.godot/imported/playstation5_button_create.svg-b4c0ab4d921557e6a1f1ba33e528e069.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation5_button_create_alternative.svg.import b/assets/images/gamepad/playstation/playstation5_button_create_alternative.svg.import
index a8733fa0a..4989964f6 100644
--- a/assets/images/gamepad/playstation/playstation5_button_create_alternative.svg.import
+++ b/assets/images/gamepad/playstation/playstation5_button_create_alternative.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://eodm14jnxebi"
+uid="uid://c5p5xci8yhfpg"
path="res://.godot/imported/playstation5_button_create_alternative.svg-33fa5cd83f6e73d025864830b4c7fb91.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation5_button_create_alternative_outline.svg.import b/assets/images/gamepad/playstation/playstation5_button_create_alternative_outline.svg.import
index df5f71ada..0ce7138ca 100644
--- a/assets/images/gamepad/playstation/playstation5_button_create_alternative_outline.svg.import
+++ b/assets/images/gamepad/playstation/playstation5_button_create_alternative_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://ccmc1i7c51jjq"
+uid="uid://c2gtebn7w8g34"
path="res://.godot/imported/playstation5_button_create_alternative_outline.svg-a5c8fa8b8bf8a1d63732b1a94ec34321.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation5_button_create_outline.svg.import b/assets/images/gamepad/playstation/playstation5_button_create_outline.svg.import
index 31eba448c..0cbc731cf 100644
--- a/assets/images/gamepad/playstation/playstation5_button_create_outline.svg.import
+++ b/assets/images/gamepad/playstation/playstation5_button_create_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://doh64jvkhxcyb"
+uid="uid://djvtv3cof0fag"
path="res://.godot/imported/playstation5_button_create_outline.svg-291a261c3cb412f706675548cb537339.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation5_button_mute.svg.import b/assets/images/gamepad/playstation/playstation5_button_mute.svg.import
index 748575c5f..a5e4f93b1 100644
--- a/assets/images/gamepad/playstation/playstation5_button_mute.svg.import
+++ b/assets/images/gamepad/playstation/playstation5_button_mute.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dwfcqp030lm7i"
+uid="uid://doee34h2f5sui"
path="res://.godot/imported/playstation5_button_mute.svg-dbf082d66e2af7204d36ccd546bdceaa.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation5_button_mute_outline.svg.import b/assets/images/gamepad/playstation/playstation5_button_mute_outline.svg.import
index ef49cfcd6..7139a6532 100644
--- a/assets/images/gamepad/playstation/playstation5_button_mute_outline.svg.import
+++ b/assets/images/gamepad/playstation/playstation5_button_mute_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://hhihq8nrhjod"
+uid="uid://47f8kbpm037m"
path="res://.godot/imported/playstation5_button_mute_outline.svg-0918eab049a68cf2ae1591ff0d89a17d.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation5_button_options.svg.import b/assets/images/gamepad/playstation/playstation5_button_options.svg.import
index 68c3f5924..25e5674bb 100644
--- a/assets/images/gamepad/playstation/playstation5_button_options.svg.import
+++ b/assets/images/gamepad/playstation/playstation5_button_options.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://8vgoicywpflx"
+uid="uid://bn6oh5im6dg0t"
path="res://.godot/imported/playstation5_button_options.svg-598e27fe351f4ae0dec9ee6463857a2d.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation5_button_options_alternative.svg.import b/assets/images/gamepad/playstation/playstation5_button_options_alternative.svg.import
index 01eb1b26f..778e29375 100644
--- a/assets/images/gamepad/playstation/playstation5_button_options_alternative.svg.import
+++ b/assets/images/gamepad/playstation/playstation5_button_options_alternative.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dwobavrwqg52h"
+uid="uid://b7tp2oavf30vb"
path="res://.godot/imported/playstation5_button_options_alternative.svg-0e61ef71b5db0fda48dcbb6d8b08ff76.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation5_button_options_alternative_outline.svg.import b/assets/images/gamepad/playstation/playstation5_button_options_alternative_outline.svg.import
index e6020469a..14d20c260 100644
--- a/assets/images/gamepad/playstation/playstation5_button_options_alternative_outline.svg.import
+++ b/assets/images/gamepad/playstation/playstation5_button_options_alternative_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bs8jdl7iiwrnv"
+uid="uid://5hbc4imd22fh"
path="res://.godot/imported/playstation5_button_options_alternative_outline.svg-c391ab346436c3e24692a3c935505d16.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation5_button_options_outline.svg.import b/assets/images/gamepad/playstation/playstation5_button_options_outline.svg.import
index 6e1493848..a4147671d 100644
--- a/assets/images/gamepad/playstation/playstation5_button_options_outline.svg.import
+++ b/assets/images/gamepad/playstation/playstation5_button_options_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://obf61hdejues"
+uid="uid://bqqqfcf7olcbd"
path="res://.godot/imported/playstation5_button_options_outline.svg-e9639bf2dedfebfcc5795643ae8efeb9.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation5_touchpad.svg.import b/assets/images/gamepad/playstation/playstation5_touchpad.svg.import
index ce0ac7a52..495f42f1c 100644
--- a/assets/images/gamepad/playstation/playstation5_touchpad.svg.import
+++ b/assets/images/gamepad/playstation/playstation5_touchpad.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://xdrolp3nr15b"
+uid="uid://b268gvlnbb2d8"
path="res://.godot/imported/playstation5_touchpad.svg-61e1a8482c48ae5288d6f8ebbf85309a.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation5_touchpad_outline.svg.import b/assets/images/gamepad/playstation/playstation5_touchpad_outline.svg.import
index 6024ce755..f499f0ca4 100644
--- a/assets/images/gamepad/playstation/playstation5_touchpad_outline.svg.import
+++ b/assets/images/gamepad/playstation/playstation5_touchpad_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://3j4v7uom7l8"
+uid="uid://8v6fi3c7ixd0"
path="res://.godot/imported/playstation5_touchpad_outline.svg-17ed64d94abbb21afe1c3abeb2afef5a.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation5_touchpad_touch.svg.import b/assets/images/gamepad/playstation/playstation5_touchpad_touch.svg.import
index 0d750db19..1eb1c0825 100644
--- a/assets/images/gamepad/playstation/playstation5_touchpad_touch.svg.import
+++ b/assets/images/gamepad/playstation/playstation5_touchpad_touch.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bj0qk2s5mxkkd"
+uid="uid://do6nap60p4cs6"
path="res://.godot/imported/playstation5_touchpad_touch.svg-5c134d924a1c9103687f0ea27aaac82a.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation5_touchpad_touch_outline.svg.import b/assets/images/gamepad/playstation/playstation5_touchpad_touch_outline.svg.import
index 74ecdb64c..fba4d9940 100644
--- a/assets/images/gamepad/playstation/playstation5_touchpad_touch_outline.svg.import
+++ b/assets/images/gamepad/playstation/playstation5_touchpad_touch_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bc6dc888584pl"
+uid="uid://cmsfcvp3ax5i6"
path="res://.godot/imported/playstation5_touchpad_touch_outline.svg-837235ff299445b9798fac883ddba273.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_button_analog.svg.import b/assets/images/gamepad/playstation/playstation_button_analog.svg.import
index d24d45b75..4bb508abd 100644
--- a/assets/images/gamepad/playstation/playstation_button_analog.svg.import
+++ b/assets/images/gamepad/playstation/playstation_button_analog.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://k85f16j46gc3"
+uid="uid://bvx1w0km6ix13"
path="res://.godot/imported/playstation_button_analog.svg-aa87cfcd0c57d013851404246a4ee4e6.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_button_analog_outline.svg.import b/assets/images/gamepad/playstation/playstation_button_analog_outline.svg.import
index c3dca7689..0ed43e0c6 100644
--- a/assets/images/gamepad/playstation/playstation_button_analog_outline.svg.import
+++ b/assets/images/gamepad/playstation/playstation_button_analog_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://drlke4b038a2i"
+uid="uid://c0eml8c4xxg2s"
path="res://.godot/imported/playstation_button_analog_outline.svg-f8be9b46e53e4afb801daf1fd39dc451.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_button_circle.svg.import b/assets/images/gamepad/playstation/playstation_button_circle.svg.import
index 35d2904aa..9f9d0d67b 100644
--- a/assets/images/gamepad/playstation/playstation_button_circle.svg.import
+++ b/assets/images/gamepad/playstation/playstation_button_circle.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://hq2enjjkuc2x"
+uid="uid://dfb1egyjgak2x"
path="res://.godot/imported/playstation_button_circle.svg-58673e6f941d624c21fcc3b38bec5d6d.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_button_circle_outline.svg.import b/assets/images/gamepad/playstation/playstation_button_circle_outline.svg.import
index 31d94f1a3..7c2390418 100644
--- a/assets/images/gamepad/playstation/playstation_button_circle_outline.svg.import
+++ b/assets/images/gamepad/playstation/playstation_button_circle_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://gvk81uyivjtx"
+uid="uid://71yrtx1tfrog"
path="res://.godot/imported/playstation_button_circle_outline.svg-5139e2a4253a14eecfd6784d5d634414.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_button_color_circle.svg.import b/assets/images/gamepad/playstation/playstation_button_color_circle.svg.import
index bdee01180..a89435409 100644
--- a/assets/images/gamepad/playstation/playstation_button_color_circle.svg.import
+++ b/assets/images/gamepad/playstation/playstation_button_color_circle.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dcysxvygs0t0b"
+uid="uid://b1wo28cyd80ov"
path="res://.godot/imported/playstation_button_color_circle.svg-5cfa673e7782bd07526a9ee32057bee9.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_button_color_circle_outline.svg.import b/assets/images/gamepad/playstation/playstation_button_color_circle_outline.svg.import
index 996a5073d..cde64d3a6 100644
--- a/assets/images/gamepad/playstation/playstation_button_color_circle_outline.svg.import
+++ b/assets/images/gamepad/playstation/playstation_button_color_circle_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bdlrfek4gpwlu"
+uid="uid://kxhrmgkt4j6l"
path="res://.godot/imported/playstation_button_color_circle_outline.svg-f3809e44ca1cf8e2f7720a8d02be68e7.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_button_color_cross.svg.import b/assets/images/gamepad/playstation/playstation_button_color_cross.svg.import
index ac0097347..b05d2eec8 100644
--- a/assets/images/gamepad/playstation/playstation_button_color_cross.svg.import
+++ b/assets/images/gamepad/playstation/playstation_button_color_cross.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://d3b15ae2w8u04"
+uid="uid://dwv1scwq0mlr2"
path="res://.godot/imported/playstation_button_color_cross.svg-a1810f0f7282ce4d1a185fd05ee2b1ca.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_button_color_cross_outline.svg.import b/assets/images/gamepad/playstation/playstation_button_color_cross_outline.svg.import
index 6565d96f9..5d1bee5eb 100644
--- a/assets/images/gamepad/playstation/playstation_button_color_cross_outline.svg.import
+++ b/assets/images/gamepad/playstation/playstation_button_color_cross_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cxncdc1y8w3sp"
+uid="uid://cidksduldvx2v"
path="res://.godot/imported/playstation_button_color_cross_outline.svg-b9e78af561976a35c989f516564d45fa.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_button_color_square.svg.import b/assets/images/gamepad/playstation/playstation_button_color_square.svg.import
index 1495fd1f2..35380fcd9 100644
--- a/assets/images/gamepad/playstation/playstation_button_color_square.svg.import
+++ b/assets/images/gamepad/playstation/playstation_button_color_square.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cwmll8jpe01x1"
+uid="uid://brniycjajdi03"
path="res://.godot/imported/playstation_button_color_square.svg-98c319316dd27cdf59df8db384252907.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_button_color_square_outline.svg.import b/assets/images/gamepad/playstation/playstation_button_color_square_outline.svg.import
index ebfa9379b..b5637ff8c 100644
--- a/assets/images/gamepad/playstation/playstation_button_color_square_outline.svg.import
+++ b/assets/images/gamepad/playstation/playstation_button_color_square_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bq7hfbip35326"
+uid="uid://576uohl166eg"
path="res://.godot/imported/playstation_button_color_square_outline.svg-c3aa6104ea2be5ce6fa5c530465ce1a6.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_button_color_triangle.svg.import b/assets/images/gamepad/playstation/playstation_button_color_triangle.svg.import
index aea34ac4e..0781023c7 100644
--- a/assets/images/gamepad/playstation/playstation_button_color_triangle.svg.import
+++ b/assets/images/gamepad/playstation/playstation_button_color_triangle.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://crv4tl33mg881"
+uid="uid://2rjhdg632n1f"
path="res://.godot/imported/playstation_button_color_triangle.svg-173eb7e14a9eec2b2e16e6e0e4d1dfa4.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_button_color_triangle_outline.svg.import b/assets/images/gamepad/playstation/playstation_button_color_triangle_outline.svg.import
index 77bc40a71..6ecf3d017 100644
--- a/assets/images/gamepad/playstation/playstation_button_color_triangle_outline.svg.import
+++ b/assets/images/gamepad/playstation/playstation_button_color_triangle_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bhl7luffti3jx"
+uid="uid://ch0n2tmnawppg"
path="res://.godot/imported/playstation_button_color_triangle_outline.svg-42541db9911f67abcf25dcd8d26455bb.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_button_cross.svg.import b/assets/images/gamepad/playstation/playstation_button_cross.svg.import
index dbff995b2..e99b87209 100644
--- a/assets/images/gamepad/playstation/playstation_button_cross.svg.import
+++ b/assets/images/gamepad/playstation/playstation_button_cross.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://chby0sf0s01da"
+uid="uid://cwkuwr1n1edp3"
path="res://.godot/imported/playstation_button_cross.svg-ef60b331443a31ca0df0f6c291bcbd26.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_button_cross_outline.svg.import b/assets/images/gamepad/playstation/playstation_button_cross_outline.svg.import
index f15c5a570..5acb777b6 100644
--- a/assets/images/gamepad/playstation/playstation_button_cross_outline.svg.import
+++ b/assets/images/gamepad/playstation/playstation_button_cross_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://38mlnyg8jteh"
+uid="uid://bip6t1lpm0g70"
path="res://.godot/imported/playstation_button_cross_outline.svg-1c0c614f11f543eb8b021a7fc3c14665.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_button_l3.svg.import b/assets/images/gamepad/playstation/playstation_button_l3.svg.import
index ed8131839..b70a21e58 100644
--- a/assets/images/gamepad/playstation/playstation_button_l3.svg.import
+++ b/assets/images/gamepad/playstation/playstation_button_l3.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dmii4b6k52scj"
+uid="uid://davo1atqgb71c"
path="res://.godot/imported/playstation_button_l3.svg-1bf8269547f4a53d084be922e7f964a0.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_button_l3_outline.svg.import b/assets/images/gamepad/playstation/playstation_button_l3_outline.svg.import
index 89e55082f..f6762dd1d 100644
--- a/assets/images/gamepad/playstation/playstation_button_l3_outline.svg.import
+++ b/assets/images/gamepad/playstation/playstation_button_l3_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bswoa6047q5ut"
+uid="uid://crq5ldbo061bu"
path="res://.godot/imported/playstation_button_l3_outline.svg-2950a518a6fb860a34ef16b24aea4742.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_button_r3.svg.import b/assets/images/gamepad/playstation/playstation_button_r3.svg.import
index c0b9e559d..38c835962 100644
--- a/assets/images/gamepad/playstation/playstation_button_r3.svg.import
+++ b/assets/images/gamepad/playstation/playstation_button_r3.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cdaevyher8pd1"
+uid="uid://bel7cl5p3pocr"
path="res://.godot/imported/playstation_button_r3.svg-b7d9339b6c2c3d27ef240ec640aa2d6f.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_button_r3_outline.svg.import b/assets/images/gamepad/playstation/playstation_button_r3_outline.svg.import
index c475fd1bb..425b1f8ce 100644
--- a/assets/images/gamepad/playstation/playstation_button_r3_outline.svg.import
+++ b/assets/images/gamepad/playstation/playstation_button_r3_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://k8vngthu5ovm"
+uid="uid://ccohtptghs0tm"
path="res://.godot/imported/playstation_button_r3_outline.svg-f32dc99f4b77f5d5fa4d28bd0dea14a5.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_button_square.svg.import b/assets/images/gamepad/playstation/playstation_button_square.svg.import
index 6a5a7d68e..a23eca6e0 100644
--- a/assets/images/gamepad/playstation/playstation_button_square.svg.import
+++ b/assets/images/gamepad/playstation/playstation_button_square.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b76tygr2qcdao"
+uid="uid://6so8a6c4hfk2"
path="res://.godot/imported/playstation_button_square.svg-52371029f4e22483e007e6736baa04d3.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_button_square_outline.svg.import b/assets/images/gamepad/playstation/playstation_button_square_outline.svg.import
index 527870013..4a5e015cb 100644
--- a/assets/images/gamepad/playstation/playstation_button_square_outline.svg.import
+++ b/assets/images/gamepad/playstation/playstation_button_square_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://ds3two3o2kdm6"
+uid="uid://bgwp26djot28g"
path="res://.godot/imported/playstation_button_square_outline.svg-d9df9280b219a7fa7cb6ed206852a3c4.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_button_triangle.svg.import b/assets/images/gamepad/playstation/playstation_button_triangle.svg.import
index 258c3eff4..9a2f0f269 100644
--- a/assets/images/gamepad/playstation/playstation_button_triangle.svg.import
+++ b/assets/images/gamepad/playstation/playstation_button_triangle.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bc0hqr1fg775q"
+uid="uid://dhx2g6brifdl1"
path="res://.godot/imported/playstation_button_triangle.svg-7ced16e5b24906d44b5bb4e5ad89545c.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_button_triangle_outline.svg.import b/assets/images/gamepad/playstation/playstation_button_triangle_outline.svg.import
index 819338f0e..b2af92eaf 100644
--- a/assets/images/gamepad/playstation/playstation_button_triangle_outline.svg.import
+++ b/assets/images/gamepad/playstation/playstation_button_triangle_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dutgbovpwfag3"
+uid="uid://bpagdu7f64ajc"
path="res://.godot/imported/playstation_button_triangle_outline.svg-2dc559fb78b5da14027b3a08cc3f07e5.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_dpad.svg.import b/assets/images/gamepad/playstation/playstation_dpad.svg.import
index d38ea9d83..fe3658682 100644
--- a/assets/images/gamepad/playstation/playstation_dpad.svg.import
+++ b/assets/images/gamepad/playstation/playstation_dpad.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://d1bn7vfymb8h7"
+uid="uid://ua3iri55e4go"
path="res://.godot/imported/playstation_dpad.svg-86b907dbc9f02dc055128492cb189ea1.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_dpad_all.svg.import b/assets/images/gamepad/playstation/playstation_dpad_all.svg.import
index 80121eb65..676748069 100644
--- a/assets/images/gamepad/playstation/playstation_dpad_all.svg.import
+++ b/assets/images/gamepad/playstation/playstation_dpad_all.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://iuepe8j3hcm7"
+uid="uid://cpq3b5bvlki8e"
path="res://.godot/imported/playstation_dpad_all.svg-926ae0a7da8a52f9ca2ecf7ff74ee2cd.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_dpad_down.svg.import b/assets/images/gamepad/playstation/playstation_dpad_down.svg.import
index cfe256a6d..446eb0f19 100644
--- a/assets/images/gamepad/playstation/playstation_dpad_down.svg.import
+++ b/assets/images/gamepad/playstation/playstation_dpad_down.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b8t8udyk7f2sy"
+uid="uid://byblaf3dx4by6"
path="res://.godot/imported/playstation_dpad_down.svg-4889c43a9fb288f096ba98f364685725.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_dpad_down_outline.svg.import b/assets/images/gamepad/playstation/playstation_dpad_down_outline.svg.import
index 678e21b9e..afa09387f 100644
--- a/assets/images/gamepad/playstation/playstation_dpad_down_outline.svg.import
+++ b/assets/images/gamepad/playstation/playstation_dpad_down_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bu520uchod3el"
+uid="uid://1xrhh3mr2nel"
path="res://.godot/imported/playstation_dpad_down_outline.svg-625aa856f9a1beb9bd1ae462ef8af1b5.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_dpad_horizontal.svg.import b/assets/images/gamepad/playstation/playstation_dpad_horizontal.svg.import
index a666cb478..db1f5cde9 100644
--- a/assets/images/gamepad/playstation/playstation_dpad_horizontal.svg.import
+++ b/assets/images/gamepad/playstation/playstation_dpad_horizontal.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bfc6pgyss6r64"
+uid="uid://cs5bo16yewi0q"
path="res://.godot/imported/playstation_dpad_horizontal.svg-91161b3369636347e4325053c8cc1db3.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_dpad_horizontal_outline.svg.import b/assets/images/gamepad/playstation/playstation_dpad_horizontal_outline.svg.import
index 8f2716f9b..0e44d28e0 100644
--- a/assets/images/gamepad/playstation/playstation_dpad_horizontal_outline.svg.import
+++ b/assets/images/gamepad/playstation/playstation_dpad_horizontal_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cnmiwfmopy33d"
+uid="uid://erwu6qfidj1q"
path="res://.godot/imported/playstation_dpad_horizontal_outline.svg-875ab67c538e81ab39fb1359b3dcc0a0.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_dpad_left.svg.import b/assets/images/gamepad/playstation/playstation_dpad_left.svg.import
index 188759a5a..faf5a85b7 100644
--- a/assets/images/gamepad/playstation/playstation_dpad_left.svg.import
+++ b/assets/images/gamepad/playstation/playstation_dpad_left.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bucd4u3xhdkn5"
+uid="uid://bmuqx6jxetdp1"
path="res://.godot/imported/playstation_dpad_left.svg-a1e233bda16263cfee2ec0e8de35360c.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_dpad_left_outline.svg.import b/assets/images/gamepad/playstation/playstation_dpad_left_outline.svg.import
index 2435a5888..5558fe766 100644
--- a/assets/images/gamepad/playstation/playstation_dpad_left_outline.svg.import
+++ b/assets/images/gamepad/playstation/playstation_dpad_left_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dghs30vx834ax"
+uid="uid://bskdor86prw3q"
path="res://.godot/imported/playstation_dpad_left_outline.svg-26d9e6764000e0dcc8c514bb647eb660.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_dpad_none.svg.import b/assets/images/gamepad/playstation/playstation_dpad_none.svg.import
index a6a43dc8e..ec8d629ce 100644
--- a/assets/images/gamepad/playstation/playstation_dpad_none.svg.import
+++ b/assets/images/gamepad/playstation/playstation_dpad_none.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://ejy52tbaldjq"
+uid="uid://44ap65odhxm"
path="res://.godot/imported/playstation_dpad_none.svg-cfbd352ab93c81e86b48e7bd99c27298.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_dpad_right.svg.import b/assets/images/gamepad/playstation/playstation_dpad_right.svg.import
index 7822ca26b..29ef59d7e 100644
--- a/assets/images/gamepad/playstation/playstation_dpad_right.svg.import
+++ b/assets/images/gamepad/playstation/playstation_dpad_right.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://nva4um5gnp46"
+uid="uid://cxhc0rxkyqf2g"
path="res://.godot/imported/playstation_dpad_right.svg-135b5076d9e4d84e264d437f96ad5044.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_dpad_right_outline.svg.import b/assets/images/gamepad/playstation/playstation_dpad_right_outline.svg.import
index 61df3cd5b..ba08d03c5 100644
--- a/assets/images/gamepad/playstation/playstation_dpad_right_outline.svg.import
+++ b/assets/images/gamepad/playstation/playstation_dpad_right_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://ba4r6538gbgwm"
+uid="uid://bb7wo613rvkoj"
path="res://.godot/imported/playstation_dpad_right_outline.svg-d9713bf03043834ed1c1a64dbba5f020.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_dpad_up.svg.import b/assets/images/gamepad/playstation/playstation_dpad_up.svg.import
index a03bd74df..9934db16d 100644
--- a/assets/images/gamepad/playstation/playstation_dpad_up.svg.import
+++ b/assets/images/gamepad/playstation/playstation_dpad_up.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dvckjbn44kqh4"
+uid="uid://da1vcs31c68sx"
path="res://.godot/imported/playstation_dpad_up.svg-def95acecdef794dfc14c4de9eacd85a.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_dpad_up_outline.svg.import b/assets/images/gamepad/playstation/playstation_dpad_up_outline.svg.import
index b423c97c2..d63c4e86c 100644
--- a/assets/images/gamepad/playstation/playstation_dpad_up_outline.svg.import
+++ b/assets/images/gamepad/playstation/playstation_dpad_up_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cu2xh15ccdt0m"
+uid="uid://c745ykeqdi8v"
path="res://.godot/imported/playstation_dpad_up_outline.svg-395f31d79e66ae06c55fdcb09e1c4afc.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_dpad_vertical.svg.import b/assets/images/gamepad/playstation/playstation_dpad_vertical.svg.import
index 7a474ad3b..0be8ddfa3 100644
--- a/assets/images/gamepad/playstation/playstation_dpad_vertical.svg.import
+++ b/assets/images/gamepad/playstation/playstation_dpad_vertical.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://7efn74unxey0"
+uid="uid://dkl4tiwec0s3r"
path="res://.godot/imported/playstation_dpad_vertical.svg-aac1e207d1fd459caa1c6a52e4f1dd7f.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_dpad_vertical_outline.svg.import b/assets/images/gamepad/playstation/playstation_dpad_vertical_outline.svg.import
index f4e68e085..b61c88b6a 100644
--- a/assets/images/gamepad/playstation/playstation_dpad_vertical_outline.svg.import
+++ b/assets/images/gamepad/playstation/playstation_dpad_vertical_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://c525mej5lvygi"
+uid="uid://ddm45gl40aoa1"
path="res://.godot/imported/playstation_dpad_vertical_outline.svg-590fe1643f5ddb3ee600c7cef1d7d932.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_stick_l.svg.import b/assets/images/gamepad/playstation/playstation_stick_l.svg.import
index 978cd70a4..224436e64 100644
--- a/assets/images/gamepad/playstation/playstation_stick_l.svg.import
+++ b/assets/images/gamepad/playstation/playstation_stick_l.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bq64rpsb1usfh"
+uid="uid://d0hn6un6byklr"
path="res://.godot/imported/playstation_stick_l.svg-78771de1cc4486570e8ee7f4ba8f10a3.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_stick_l_down.svg.import b/assets/images/gamepad/playstation/playstation_stick_l_down.svg.import
index c067dd00b..d2b6f359a 100644
--- a/assets/images/gamepad/playstation/playstation_stick_l_down.svg.import
+++ b/assets/images/gamepad/playstation/playstation_stick_l_down.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cv1gammxiedb"
+uid="uid://od86dbeeirmp"
path="res://.godot/imported/playstation_stick_l_down.svg-0a9bcfec30b1217ec41bae800564a666.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_stick_l_horizontal.svg.import b/assets/images/gamepad/playstation/playstation_stick_l_horizontal.svg.import
index c5e5b659d..599bda249 100644
--- a/assets/images/gamepad/playstation/playstation_stick_l_horizontal.svg.import
+++ b/assets/images/gamepad/playstation/playstation_stick_l_horizontal.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://2vnyidlvl542"
+uid="uid://c2ynlxwt4h4kp"
path="res://.godot/imported/playstation_stick_l_horizontal.svg-05799650ff3c647f3da4d6f395d81859.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_stick_l_left.svg.import b/assets/images/gamepad/playstation/playstation_stick_l_left.svg.import
index 70dc9e7a7..fc5895fa7 100644
--- a/assets/images/gamepad/playstation/playstation_stick_l_left.svg.import
+++ b/assets/images/gamepad/playstation/playstation_stick_l_left.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://d22o4cxlcni3q"
+uid="uid://bufyl7xm4mcij"
path="res://.godot/imported/playstation_stick_l_left.svg-f5f49c466ce685378f701c1173edb9f5.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_stick_l_press.svg.import b/assets/images/gamepad/playstation/playstation_stick_l_press.svg.import
index afeada187..fc764af1a 100644
--- a/assets/images/gamepad/playstation/playstation_stick_l_press.svg.import
+++ b/assets/images/gamepad/playstation/playstation_stick_l_press.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dbf2kolrjqlsk"
+uid="uid://cmijt22flcpda"
path="res://.godot/imported/playstation_stick_l_press.svg-6198ab93afcc5042573cd8c40074db46.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_stick_l_right.svg.import b/assets/images/gamepad/playstation/playstation_stick_l_right.svg.import
index 21c588b1a..3fac935a7 100644
--- a/assets/images/gamepad/playstation/playstation_stick_l_right.svg.import
+++ b/assets/images/gamepad/playstation/playstation_stick_l_right.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://0bomms2ipyct"
+uid="uid://bj8fx1k8ectnx"
path="res://.godot/imported/playstation_stick_l_right.svg-96fbddfa8f7e4235d145fa8b98efa2a3.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_stick_l_up.svg.import b/assets/images/gamepad/playstation/playstation_stick_l_up.svg.import
index 50deaa3f6..31a0a6206 100644
--- a/assets/images/gamepad/playstation/playstation_stick_l_up.svg.import
+++ b/assets/images/gamepad/playstation/playstation_stick_l_up.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://ds60ucempaqtc"
+uid="uid://c8uwdhedkaonn"
path="res://.godot/imported/playstation_stick_l_up.svg-84c17c66b9e0a056bada8c06d9c6a1b0.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_stick_l_vertical.svg.import b/assets/images/gamepad/playstation/playstation_stick_l_vertical.svg.import
index fad950c52..aa0245d99 100644
--- a/assets/images/gamepad/playstation/playstation_stick_l_vertical.svg.import
+++ b/assets/images/gamepad/playstation/playstation_stick_l_vertical.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bapyv15bfbax0"
+uid="uid://bfgooboa5sf22"
path="res://.godot/imported/playstation_stick_l_vertical.svg-013d3c28e5b3783b611056738e685711.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_stick_r.svg.import b/assets/images/gamepad/playstation/playstation_stick_r.svg.import
index 62fe18c18..2118a991e 100644
--- a/assets/images/gamepad/playstation/playstation_stick_r.svg.import
+++ b/assets/images/gamepad/playstation/playstation_stick_r.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://byrtduc2ys2gd"
+uid="uid://dlh3o8lhabxmv"
path="res://.godot/imported/playstation_stick_r.svg-21eb25318ffa23b186e9a7aad20f1a54.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_stick_r_down.svg.import b/assets/images/gamepad/playstation/playstation_stick_r_down.svg.import
index 5267a9b10..3f09a79bf 100644
--- a/assets/images/gamepad/playstation/playstation_stick_r_down.svg.import
+++ b/assets/images/gamepad/playstation/playstation_stick_r_down.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b0hdbw4qo4nl2"
+uid="uid://do6olohpve0fm"
path="res://.godot/imported/playstation_stick_r_down.svg-d6136347d7764141309e1a27582c4ace.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_stick_r_horizontal.svg.import b/assets/images/gamepad/playstation/playstation_stick_r_horizontal.svg.import
index 35076143c..9d338bf42 100644
--- a/assets/images/gamepad/playstation/playstation_stick_r_horizontal.svg.import
+++ b/assets/images/gamepad/playstation/playstation_stick_r_horizontal.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://c4ia0why4c72a"
+uid="uid://bcfgvh21ubjop"
path="res://.godot/imported/playstation_stick_r_horizontal.svg-98948b806f38efdb17315a06592ca911.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_stick_r_left.svg.import b/assets/images/gamepad/playstation/playstation_stick_r_left.svg.import
index 4871a2b59..fba52aec3 100644
--- a/assets/images/gamepad/playstation/playstation_stick_r_left.svg.import
+++ b/assets/images/gamepad/playstation/playstation_stick_r_left.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dedewmjipppck"
+uid="uid://7uwvswwxu8u5"
path="res://.godot/imported/playstation_stick_r_left.svg-0fe661862efaf4c979ab634970041f50.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_stick_r_press.svg.import b/assets/images/gamepad/playstation/playstation_stick_r_press.svg.import
index 637bb0928..70ea624d7 100644
--- a/assets/images/gamepad/playstation/playstation_stick_r_press.svg.import
+++ b/assets/images/gamepad/playstation/playstation_stick_r_press.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dnc8ia8fbc72f"
+uid="uid://ctsqjuqhj0soc"
path="res://.godot/imported/playstation_stick_r_press.svg-b2a99765532bf7c6f9d63b280174ddee.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_stick_r_right.svg.import b/assets/images/gamepad/playstation/playstation_stick_r_right.svg.import
index ffc7cd8c7..3eb06a09d 100644
--- a/assets/images/gamepad/playstation/playstation_stick_r_right.svg.import
+++ b/assets/images/gamepad/playstation/playstation_stick_r_right.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://d2f87ubl8ut4t"
+uid="uid://d2t2wxh6fduon"
path="res://.godot/imported/playstation_stick_r_right.svg-b70ec3d6dab7f3901ffa9e2dc6c1089d.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_stick_r_up.svg.import b/assets/images/gamepad/playstation/playstation_stick_r_up.svg.import
index ff50ecbab..0502dd876 100644
--- a/assets/images/gamepad/playstation/playstation_stick_r_up.svg.import
+++ b/assets/images/gamepad/playstation/playstation_stick_r_up.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cvjxqt1lsfp1t"
+uid="uid://csve53s1buixo"
path="res://.godot/imported/playstation_stick_r_up.svg-33ed81f8863b64e5b1c3e2cda0bbd3c1.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_stick_r_vertical.svg.import b/assets/images/gamepad/playstation/playstation_stick_r_vertical.svg.import
index c8ee96683..061532e82 100644
--- a/assets/images/gamepad/playstation/playstation_stick_r_vertical.svg.import
+++ b/assets/images/gamepad/playstation/playstation_stick_r_vertical.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b7xquxe1drevm"
+uid="uid://mmdrtvbfqgwp"
path="res://.godot/imported/playstation_stick_r_vertical.svg-412416e1a8d54bc81ba3247ac5c343df.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_stick_side_l.svg.import b/assets/images/gamepad/playstation/playstation_stick_side_l.svg.import
index abaa27890..6c223363a 100644
--- a/assets/images/gamepad/playstation/playstation_stick_side_l.svg.import
+++ b/assets/images/gamepad/playstation/playstation_stick_side_l.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://43gjagfbavpy"
+uid="uid://dyvp38qrpane7"
path="res://.godot/imported/playstation_stick_side_l.svg-537935c59a0fdcbe14b06e4047bad67c.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_stick_side_r.svg.import b/assets/images/gamepad/playstation/playstation_stick_side_r.svg.import
index 8fda4683e..6def22aa1 100644
--- a/assets/images/gamepad/playstation/playstation_stick_side_r.svg.import
+++ b/assets/images/gamepad/playstation/playstation_stick_side_r.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bl8cbv7k17etp"
+uid="uid://dkotgp8doeykf"
path="res://.godot/imported/playstation_stick_side_r.svg-4bf0ddcb5182bf926f23b36a21fa93bd.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_stick_top_l.svg.import b/assets/images/gamepad/playstation/playstation_stick_top_l.svg.import
index ad43d9743..f017a6458 100644
--- a/assets/images/gamepad/playstation/playstation_stick_top_l.svg.import
+++ b/assets/images/gamepad/playstation/playstation_stick_top_l.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bgpfotacv32ph"
+uid="uid://dup0tccpfm6rj"
path="res://.godot/imported/playstation_stick_top_l.svg-417cbe94b020bd679dfaaeedced0a5c0.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_stick_top_r.svg.import b/assets/images/gamepad/playstation/playstation_stick_top_r.svg.import
index de256bcff..83281db87 100644
--- a/assets/images/gamepad/playstation/playstation_stick_top_r.svg.import
+++ b/assets/images/gamepad/playstation/playstation_stick_top_r.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bgkj3lsr5rfwp"
+uid="uid://dt5hlmc48at3x"
path="res://.godot/imported/playstation_stick_top_r.svg-a44a7853e0bfcb189d8b2c91e8056598.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_trigger_l1.svg.import b/assets/images/gamepad/playstation/playstation_trigger_l1.svg.import
index f31ed442b..cc83fe4a1 100644
--- a/assets/images/gamepad/playstation/playstation_trigger_l1.svg.import
+++ b/assets/images/gamepad/playstation/playstation_trigger_l1.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://ce50wyq1ctdg3"
+uid="uid://bkya1ndod3v1j"
path="res://.godot/imported/playstation_trigger_l1.svg-1a7f953a755b39a459d1afbf2d7d2d9d.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_trigger_l1_alternative.svg.import b/assets/images/gamepad/playstation/playstation_trigger_l1_alternative.svg.import
index 010003044..be75e5c9f 100644
--- a/assets/images/gamepad/playstation/playstation_trigger_l1_alternative.svg.import
+++ b/assets/images/gamepad/playstation/playstation_trigger_l1_alternative.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dxbqk8u10kwig"
+uid="uid://ch70gfvca2q1m"
path="res://.godot/imported/playstation_trigger_l1_alternative.svg-5cb68c8b0e5c5ff08c63409265883401.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_trigger_l1_alternative_outline.svg.import b/assets/images/gamepad/playstation/playstation_trigger_l1_alternative_outline.svg.import
index 21910f811..de33bc9e3 100644
--- a/assets/images/gamepad/playstation/playstation_trigger_l1_alternative_outline.svg.import
+++ b/assets/images/gamepad/playstation/playstation_trigger_l1_alternative_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://g3e7jhclqs71"
+uid="uid://dri3xldq3kdmo"
path="res://.godot/imported/playstation_trigger_l1_alternative_outline.svg-97dc03ec737b5ecf31b755449e52c455.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_trigger_l1_outline.svg.import b/assets/images/gamepad/playstation/playstation_trigger_l1_outline.svg.import
index f0fa38c10..acc57c6d8 100644
--- a/assets/images/gamepad/playstation/playstation_trigger_l1_outline.svg.import
+++ b/assets/images/gamepad/playstation/playstation_trigger_l1_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://460hvpu6xeu7"
+uid="uid://qkv44ew2xt7w"
path="res://.godot/imported/playstation_trigger_l1_outline.svg-5aaa1ea5fe4f6ae2ba2294cb5c3efb80.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_trigger_l2.svg.import b/assets/images/gamepad/playstation/playstation_trigger_l2.svg.import
index d61b36430..9dee0da12 100644
--- a/assets/images/gamepad/playstation/playstation_trigger_l2.svg.import
+++ b/assets/images/gamepad/playstation/playstation_trigger_l2.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://d0pbaqstutkli"
+uid="uid://dcnvqtiuawl0c"
path="res://.godot/imported/playstation_trigger_l2.svg-2a8f6aabbb3e4f3fc1e7b9ced3f9415d.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_trigger_l2_alternative.svg.import b/assets/images/gamepad/playstation/playstation_trigger_l2_alternative.svg.import
index 1cc64cae6..1119973ac 100644
--- a/assets/images/gamepad/playstation/playstation_trigger_l2_alternative.svg.import
+++ b/assets/images/gamepad/playstation/playstation_trigger_l2_alternative.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://2kni34s7n11k"
+uid="uid://1ic45xwvjvd6"
path="res://.godot/imported/playstation_trigger_l2_alternative.svg-62d4698a2b264205d33e077ac964fc88.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_trigger_l2_alternative_outline.svg.import b/assets/images/gamepad/playstation/playstation_trigger_l2_alternative_outline.svg.import
index 7c5094cbc..e221c2c9c 100644
--- a/assets/images/gamepad/playstation/playstation_trigger_l2_alternative_outline.svg.import
+++ b/assets/images/gamepad/playstation/playstation_trigger_l2_alternative_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bhdhfpi3vye80"
+uid="uid://d3y536qvsu1bq"
path="res://.godot/imported/playstation_trigger_l2_alternative_outline.svg-83ee2242d0024a0e67467305556bfb23.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_trigger_l2_outline.svg.import b/assets/images/gamepad/playstation/playstation_trigger_l2_outline.svg.import
index 9b9593426..f5a47759c 100644
--- a/assets/images/gamepad/playstation/playstation_trigger_l2_outline.svg.import
+++ b/assets/images/gamepad/playstation/playstation_trigger_l2_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dhanoxbu76h6m"
+uid="uid://bupb1c0xpsta"
path="res://.godot/imported/playstation_trigger_l2_outline.svg-db5c82e5fc75e2497088f296395666c3.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_trigger_r1.svg.import b/assets/images/gamepad/playstation/playstation_trigger_r1.svg.import
index 70c24a795..928c29943 100644
--- a/assets/images/gamepad/playstation/playstation_trigger_r1.svg.import
+++ b/assets/images/gamepad/playstation/playstation_trigger_r1.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://drbydhj23dk4v"
+uid="uid://f2ge3igc0h6g"
path="res://.godot/imported/playstation_trigger_r1.svg-c3a2982f1ed177c78e338ff739e1bd5a.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_trigger_r1_alternative.svg.import b/assets/images/gamepad/playstation/playstation_trigger_r1_alternative.svg.import
index 3bf7cfde6..a59352b18 100644
--- a/assets/images/gamepad/playstation/playstation_trigger_r1_alternative.svg.import
+++ b/assets/images/gamepad/playstation/playstation_trigger_r1_alternative.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cw1l4imye15u2"
+uid="uid://1he8y6gxecgc"
path="res://.godot/imported/playstation_trigger_r1_alternative.svg-22278c7f3a77b8ab38074e3ba6d3c4f5.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_trigger_r1_alternative_outline.svg.import b/assets/images/gamepad/playstation/playstation_trigger_r1_alternative_outline.svg.import
index 25b853886..850b118a6 100644
--- a/assets/images/gamepad/playstation/playstation_trigger_r1_alternative_outline.svg.import
+++ b/assets/images/gamepad/playstation/playstation_trigger_r1_alternative_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://qlitalglh3us"
+uid="uid://civko3bru1bnc"
path="res://.godot/imported/playstation_trigger_r1_alternative_outline.svg-44ef2e153afdababeba17288d04b4d08.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_trigger_r1_outline.svg.import b/assets/images/gamepad/playstation/playstation_trigger_r1_outline.svg.import
index 064c4bf86..2a31988df 100644
--- a/assets/images/gamepad/playstation/playstation_trigger_r1_outline.svg.import
+++ b/assets/images/gamepad/playstation/playstation_trigger_r1_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://d430lpfy8dws"
+uid="uid://bowphl0vp8xuy"
path="res://.godot/imported/playstation_trigger_r1_outline.svg-2aa389fa1fbb610b0a7fd41f0cb60322.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_trigger_r2.svg.import b/assets/images/gamepad/playstation/playstation_trigger_r2.svg.import
index 5c9878a8e..df06ef4d2 100644
--- a/assets/images/gamepad/playstation/playstation_trigger_r2.svg.import
+++ b/assets/images/gamepad/playstation/playstation_trigger_r2.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://botqou7j5tw5i"
+uid="uid://doeikq8t8xfny"
path="res://.godot/imported/playstation_trigger_r2.svg-c94d5ef5ced1efe3106d760cf3b47154.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_trigger_r2_alternative.svg.import b/assets/images/gamepad/playstation/playstation_trigger_r2_alternative.svg.import
index 91faa340c..4b7dae97b 100644
--- a/assets/images/gamepad/playstation/playstation_trigger_r2_alternative.svg.import
+++ b/assets/images/gamepad/playstation/playstation_trigger_r2_alternative.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bk8wdjsgrtcb8"
+uid="uid://c8fiv430upxks"
path="res://.godot/imported/playstation_trigger_r2_alternative.svg-e1f88b83548eeae507f33ab0760e0785.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_trigger_r2_alternative_outline.svg.import b/assets/images/gamepad/playstation/playstation_trigger_r2_alternative_outline.svg.import
index 30999e791..1d5732007 100644
--- a/assets/images/gamepad/playstation/playstation_trigger_r2_alternative_outline.svg.import
+++ b/assets/images/gamepad/playstation/playstation_trigger_r2_alternative_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dg64rtw5ya867"
+uid="uid://b63uyotxfiq0r"
path="res://.godot/imported/playstation_trigger_r2_alternative_outline.svg-ce4b4e24e971d4554a2c1dfdc4380ab3.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/playstation/playstation_trigger_r2_outline.svg.import b/assets/images/gamepad/playstation/playstation_trigger_r2_outline.svg.import
index 9a91908a8..e95883fbd 100644
--- a/assets/images/gamepad/playstation/playstation_trigger_r2_outline.svg.import
+++ b/assets/images/gamepad/playstation/playstation_trigger_r2_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://c8m3knpevw1mj"
+uid="uid://d0rkwq62acgjo"
path="res://.godot/imported/playstation_trigger_r2_outline.svg-e34198810f385ed653d0099366eb3af6.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/rog-ally/ally_button_guide.svg.import b/assets/images/gamepad/rog-ally/ally_button_guide.svg.import
index b240eb9c9..697bd365f 100644
--- a/assets/images/gamepad/rog-ally/ally_button_guide.svg.import
+++ b/assets/images/gamepad/rog-ally/ally_button_guide.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://brctkdj250hpv"
+uid="uid://cl1gl3j47wds5"
path="res://.godot/imported/ally_button_guide.svg-4dea71f5533fa80bed794218bac702d3.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/rog-ally/ally_button_m1.svg.import b/assets/images/gamepad/rog-ally/ally_button_m1.svg.import
index 2e5407b07..be52a0cf8 100644
--- a/assets/images/gamepad/rog-ally/ally_button_m1.svg.import
+++ b/assets/images/gamepad/rog-ally/ally_button_m1.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://obqv3ikblrmx"
+uid="uid://bwqadttdisdkl"
path="res://.godot/imported/ally_button_m1.svg-2209cf215426742e59419468852c7f76.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/rog-ally/ally_button_m2.svg.import b/assets/images/gamepad/rog-ally/ally_button_m2.svg.import
index e26d957c8..6cd4db3dd 100644
--- a/assets/images/gamepad/rog-ally/ally_button_m2.svg.import
+++ b/assets/images/gamepad/rog-ally/ally_button_m2.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://d3nga7v4ldmap"
+uid="uid://74k3jdksgydd"
path="res://.godot/imported/ally_button_m2.svg-fb574cb511a98a7db85a8542a4eeba16.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/rog-ally/ally_button_menu.svg.import b/assets/images/gamepad/rog-ally/ally_button_menu.svg.import
index d35e6c0fc..ed299fe60 100644
--- a/assets/images/gamepad/rog-ally/ally_button_menu.svg.import
+++ b/assets/images/gamepad/rog-ally/ally_button_menu.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://csxxwf7pgahkb"
+uid="uid://d4gi4bucbgyhv"
path="res://.godot/imported/ally_button_menu.svg-5bc275dc6fe1008aaba7812362c79d13.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/rog-ally/ally_button_quick.svg.import b/assets/images/gamepad/rog-ally/ally_button_quick.svg.import
index 24658736b..1f80dc2cd 100644
--- a/assets/images/gamepad/rog-ally/ally_button_quick.svg.import
+++ b/assets/images/gamepad/rog-ally/ally_button_quick.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://srjhf8dp2cpg"
+uid="uid://dg7xaotlsxoix"
path="res://.godot/imported/ally_button_quick.svg-ff312a6b5a60c8bd3b1277ae2f6f750f.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/rog-ally/ally_button_view.svg.import b/assets/images/gamepad/rog-ally/ally_button_view.svg.import
index c96420504..3af054767 100644
--- a/assets/images/gamepad/rog-ally/ally_button_view.svg.import
+++ b/assets/images/gamepad/rog-ally/ally_button_view.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cu0vttshpc7ui"
+uid="uid://bcrthlw3xno0p"
path="res://.godot/imported/ally_button_view.svg-e9edf14585505f3aeb57f7909fcfa542.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/rog-ally/diagram.png.import b/assets/images/gamepad/rog-ally/diagram.png.import
index 676907366..5f3446ea7 100644
--- a/assets/images/gamepad/rog-ally/diagram.png.import
+++ b/assets/images/gamepad/rog-ally/diagram.png.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://xm6mg1kykt88"
+uid="uid://c5tmyp3bdtksr"
path="res://.godot/imported/diagram.png-f99b5efd3297c6be62f3cd7c6032cbe7.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/controller_steam.svg.import b/assets/images/gamepad/steam/controller_steam.svg.import
index 02b08ec1f..6ea02a5a3 100644
--- a/assets/images/gamepad/steam/controller_steam.svg.import
+++ b/assets/images/gamepad/steam/controller_steam.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://c8b8706k0iryj"
+uid="uid://cst2i5us0vdjy"
path="res://.godot/imported/controller_steam.svg-62c5680d992df27a89be5b43451be65d.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_button_a.svg.import b/assets/images/gamepad/steam/steam_button_a.svg.import
index bad7917c5..5d228ffb6 100644
--- a/assets/images/gamepad/steam/steam_button_a.svg.import
+++ b/assets/images/gamepad/steam/steam_button_a.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://d1wgo1ahf04x2"
+uid="uid://m7frkhqu2tch"
path="res://.godot/imported/steam_button_a.svg-d2022bdec8581dec2a4f53c219b80d20.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_button_a_outline.svg.import b/assets/images/gamepad/steam/steam_button_a_outline.svg.import
index f5f7b3f3d..66f7c2c44 100644
--- a/assets/images/gamepad/steam/steam_button_a_outline.svg.import
+++ b/assets/images/gamepad/steam/steam_button_a_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b0d21hv13mxg8"
+uid="uid://bg0xisuykiukf"
path="res://.godot/imported/steam_button_a_outline.svg-a2011c3d2a870ce3b74802549bb3e376.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_button_b.svg.import b/assets/images/gamepad/steam/steam_button_b.svg.import
index a7cbfcc86..ffce38f76 100644
--- a/assets/images/gamepad/steam/steam_button_b.svg.import
+++ b/assets/images/gamepad/steam/steam_button_b.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b0unrfy7gwj1p"
+uid="uid://btth5l4hrc7gt"
path="res://.godot/imported/steam_button_b.svg-98263f03935b05edbd6dda5a5bba99b9.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_button_b_outline.svg.import b/assets/images/gamepad/steam/steam_button_b_outline.svg.import
index fe949974b..58ec93c93 100644
--- a/assets/images/gamepad/steam/steam_button_b_outline.svg.import
+++ b/assets/images/gamepad/steam/steam_button_b_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bmqdohrxqoeom"
+uid="uid://btg8nwed8br7a"
path="res://.godot/imported/steam_button_b_outline.svg-e2f15b2dd4bff4950ec24bfd138bc584.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_button_back_icon.svg.import b/assets/images/gamepad/steam/steam_button_back_icon.svg.import
index c965a03f2..4ff0735b1 100644
--- a/assets/images/gamepad/steam/steam_button_back_icon.svg.import
+++ b/assets/images/gamepad/steam/steam_button_back_icon.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dpgjaie64o2j7"
+uid="uid://cmnjax5k8juxb"
path="res://.godot/imported/steam_button_back_icon.svg-8c7b3e3d12fbe79c9b07a90a0b16d8bd.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_button_back_icon_outline.svg.import b/assets/images/gamepad/steam/steam_button_back_icon_outline.svg.import
index aa5fa8a25..4be10ca3a 100644
--- a/assets/images/gamepad/steam/steam_button_back_icon_outline.svg.import
+++ b/assets/images/gamepad/steam/steam_button_back_icon_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://hcl376g1xwbp"
+uid="uid://cv6674gwc2efo"
path="res://.godot/imported/steam_button_back_icon_outline.svg-55310bfad7faa509e99bef8366f3ffe6.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_button_color_a.svg.import b/assets/images/gamepad/steam/steam_button_color_a.svg.import
index 71f9f85d5..bb6049247 100644
--- a/assets/images/gamepad/steam/steam_button_color_a.svg.import
+++ b/assets/images/gamepad/steam/steam_button_color_a.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bpkm2swtktdf0"
+uid="uid://1q1vr24dkc26"
path="res://.godot/imported/steam_button_color_a.svg-e57c6075a8ae2d4698eb9074f7a01f6c.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_button_color_a_outline.svg.import b/assets/images/gamepad/steam/steam_button_color_a_outline.svg.import
index 1bfe9f581..83fe9a247 100644
--- a/assets/images/gamepad/steam/steam_button_color_a_outline.svg.import
+++ b/assets/images/gamepad/steam/steam_button_color_a_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dkrl63y6pkf64"
+uid="uid://bwgr3ta8sao1i"
path="res://.godot/imported/steam_button_color_a_outline.svg-f2baa759d2b97b064666c297d774b008.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_button_color_b.svg.import b/assets/images/gamepad/steam/steam_button_color_b.svg.import
index 60d086cec..fef3ecf9b 100644
--- a/assets/images/gamepad/steam/steam_button_color_b.svg.import
+++ b/assets/images/gamepad/steam/steam_button_color_b.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://c435jhogs3n8o"
+uid="uid://b730xukgcsh2k"
path="res://.godot/imported/steam_button_color_b.svg-504c889ae1df23c8606bb98ae339f224.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_button_color_b_outline.svg.import b/assets/images/gamepad/steam/steam_button_color_b_outline.svg.import
index 4b7ecf5c2..d4a110d9d 100644
--- a/assets/images/gamepad/steam/steam_button_color_b_outline.svg.import
+++ b/assets/images/gamepad/steam/steam_button_color_b_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b611xwsk4jd8g"
+uid="uid://dm3wn6k4gdhxv"
path="res://.godot/imported/steam_button_color_b_outline.svg-0e1fb99cb2b144bab056a34805fcbd17.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_button_color_x.svg.import b/assets/images/gamepad/steam/steam_button_color_x.svg.import
index f184da81b..bb000ccca 100644
--- a/assets/images/gamepad/steam/steam_button_color_x.svg.import
+++ b/assets/images/gamepad/steam/steam_button_color_x.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://gm2fk8y4xrig"
+uid="uid://ctvb5ylheu2nm"
path="res://.godot/imported/steam_button_color_x.svg-8d6c4bbc64b2fc71f30a8373d0780939.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_button_color_x_outline.svg.import b/assets/images/gamepad/steam/steam_button_color_x_outline.svg.import
index 9ac254522..1ea45fd46 100644
--- a/assets/images/gamepad/steam/steam_button_color_x_outline.svg.import
+++ b/assets/images/gamepad/steam/steam_button_color_x_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://gr1h0bths2hq"
+uid="uid://b6rc56egbak4k"
path="res://.godot/imported/steam_button_color_x_outline.svg-7bff64d6fa59c13267e6b969b3ac90c2.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_button_color_y.svg.import b/assets/images/gamepad/steam/steam_button_color_y.svg.import
index cedd2d0bf..96c2bff08 100644
--- a/assets/images/gamepad/steam/steam_button_color_y.svg.import
+++ b/assets/images/gamepad/steam/steam_button_color_y.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://01a6rkyglcse"
+uid="uid://dl6mkuxwnau6c"
path="res://.godot/imported/steam_button_color_y.svg-cdd12d662f695aa12321a0edc59476d2.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_button_color_y_outline.svg.import b/assets/images/gamepad/steam/steam_button_color_y_outline.svg.import
index 151b27909..ab65f0227 100644
--- a/assets/images/gamepad/steam/steam_button_color_y_outline.svg.import
+++ b/assets/images/gamepad/steam/steam_button_color_y_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://d10m4l7a4ka84"
+uid="uid://6tnv6sfkkph5"
path="res://.godot/imported/steam_button_color_y_outline.svg-80eca862bfbd50dc574394e812306f1e.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_button_lp.svg.import b/assets/images/gamepad/steam/steam_button_lp.svg.import
index 0e9488a3f..3fe326186 100644
--- a/assets/images/gamepad/steam/steam_button_lp.svg.import
+++ b/assets/images/gamepad/steam/steam_button_lp.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://com8m05m2uqco"
+uid="uid://mphqdrq0v6nv"
path="res://.godot/imported/steam_button_lp.svg-f44d6df7cc16ef1c3fe7ac4513d5f5f5.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_button_lp_outline.svg.import b/assets/images/gamepad/steam/steam_button_lp_outline.svg.import
index 42b680de3..6496d9cf7 100644
--- a/assets/images/gamepad/steam/steam_button_lp_outline.svg.import
+++ b/assets/images/gamepad/steam/steam_button_lp_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b3w6ihl1r6saj"
+uid="uid://co68m1fx51rnp"
path="res://.godot/imported/steam_button_lp_outline.svg-a9673ce26d4d1879535b7da9d7cad6e2.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_button_rp.svg.import b/assets/images/gamepad/steam/steam_button_rp.svg.import
index c68ace787..b7133e5a9 100644
--- a/assets/images/gamepad/steam/steam_button_rp.svg.import
+++ b/assets/images/gamepad/steam/steam_button_rp.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cer0ys0nbh0no"
+uid="uid://djidib24hy7sf"
path="res://.godot/imported/steam_button_rp.svg-3048616445b39be3b96594953c16172a.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_button_rp_outline.svg.import b/assets/images/gamepad/steam/steam_button_rp_outline.svg.import
index 246a36594..bdadf715f 100644
--- a/assets/images/gamepad/steam/steam_button_rp_outline.svg.import
+++ b/assets/images/gamepad/steam/steam_button_rp_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://ylpv7gaw5qo5"
+uid="uid://77ss42pw0tl7"
path="res://.godot/imported/steam_button_rp_outline.svg-5b10b3e460186307a7f9a27db60c304b.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_button_start_icon.svg.import b/assets/images/gamepad/steam/steam_button_start_icon.svg.import
index d2409c6c6..d6e858d56 100644
--- a/assets/images/gamepad/steam/steam_button_start_icon.svg.import
+++ b/assets/images/gamepad/steam/steam_button_start_icon.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://drhbwe1m16fx7"
+uid="uid://4lase2m3005j"
path="res://.godot/imported/steam_button_start_icon.svg-82778ba4170b4455744b14ddb4669092.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_button_start_icon_outline.svg.import b/assets/images/gamepad/steam/steam_button_start_icon_outline.svg.import
index 87c9f9048..19a19b342 100644
--- a/assets/images/gamepad/steam/steam_button_start_icon_outline.svg.import
+++ b/assets/images/gamepad/steam/steam_button_start_icon_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bximbxuv2c214"
+uid="uid://brwod1hqn3pow"
path="res://.godot/imported/steam_button_start_icon_outline.svg-6fd7ca17c9705b4a525b2331c792da95.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_button_x.svg.import b/assets/images/gamepad/steam/steam_button_x.svg.import
index 170a6e218..f234ff888 100644
--- a/assets/images/gamepad/steam/steam_button_x.svg.import
+++ b/assets/images/gamepad/steam/steam_button_x.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cbhyatwdtbboq"
+uid="uid://d0e7vl3u4pv2i"
path="res://.godot/imported/steam_button_x.svg-9cd005dab1d0b3e91c6feaa39834442d.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_button_x_outline.svg.import b/assets/images/gamepad/steam/steam_button_x_outline.svg.import
index c4b190315..c2ca841f3 100644
--- a/assets/images/gamepad/steam/steam_button_x_outline.svg.import
+++ b/assets/images/gamepad/steam/steam_button_x_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dr6pj7dkcci8d"
+uid="uid://d4ctfdb13smyb"
path="res://.godot/imported/steam_button_x_outline.svg-1c1031f09ff40b7b336c61601c495bf6.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_button_y.svg.import b/assets/images/gamepad/steam/steam_button_y.svg.import
index 3da1f4498..b6cb17b62 100644
--- a/assets/images/gamepad/steam/steam_button_y.svg.import
+++ b/assets/images/gamepad/steam/steam_button_y.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://7auey4qjw3cw"
+uid="uid://btisptq5v3eeu"
path="res://.godot/imported/steam_button_y.svg-685f1d4a78e54a1f823cc5b2264777f4.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_button_y_outline.svg.import b/assets/images/gamepad/steam/steam_button_y_outline.svg.import
index c952fc10e..4ac592370 100644
--- a/assets/images/gamepad/steam/steam_button_y_outline.svg.import
+++ b/assets/images/gamepad/steam/steam_button_y_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://1bfwtcexppnp"
+uid="uid://c7ymjfhrpetd1"
path="res://.godot/imported/steam_button_y_outline.svg-22cdaaaf10fedddd95fdcf7723d9cbfc.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_dpad.svg.import b/assets/images/gamepad/steam/steam_dpad.svg.import
index bc36aacda..185ab2d3a 100644
--- a/assets/images/gamepad/steam/steam_dpad.svg.import
+++ b/assets/images/gamepad/steam/steam_dpad.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dnia1n0cogcvv"
+uid="uid://dr4giue83b7ly"
path="res://.godot/imported/steam_dpad.svg-20f150b454300110333909ef7d33c6f9.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_dpad_all.svg.import b/assets/images/gamepad/steam/steam_dpad_all.svg.import
index 2c2e6729b..62bc06d30 100644
--- a/assets/images/gamepad/steam/steam_dpad_all.svg.import
+++ b/assets/images/gamepad/steam/steam_dpad_all.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://tlt8jgn42cbr"
+uid="uid://hskiho52kmev"
path="res://.godot/imported/steam_dpad_all.svg-57fe97eec128a7e743182074184937dd.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_dpad_down.svg.import b/assets/images/gamepad/steam/steam_dpad_down.svg.import
index 4adf9bf91..748051af3 100644
--- a/assets/images/gamepad/steam/steam_dpad_down.svg.import
+++ b/assets/images/gamepad/steam/steam_dpad_down.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b36ese18p42qf"
+uid="uid://hjxtuq87i2s8"
path="res://.godot/imported/steam_dpad_down.svg-6195a0e733febce2ebcfaa2317835c84.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_dpad_down_outline.svg.import b/assets/images/gamepad/steam/steam_dpad_down_outline.svg.import
index 3c45be9e7..cb0ec2854 100644
--- a/assets/images/gamepad/steam/steam_dpad_down_outline.svg.import
+++ b/assets/images/gamepad/steam/steam_dpad_down_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cwmtqdi0hbsu5"
+uid="uid://hyubwe6uq6ix"
path="res://.godot/imported/steam_dpad_down_outline.svg-5ecec87eb41a657ae5d3920d8fc16eb6.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_dpad_horizontal.svg.import b/assets/images/gamepad/steam/steam_dpad_horizontal.svg.import
index 7bda8bbc8..c5d266188 100644
--- a/assets/images/gamepad/steam/steam_dpad_horizontal.svg.import
+++ b/assets/images/gamepad/steam/steam_dpad_horizontal.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cnwse2l7xhl26"
+uid="uid://ce8plfafnl4ds"
path="res://.godot/imported/steam_dpad_horizontal.svg-a3318b8ea5525e416d28b70b7d29c7fa.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_dpad_horizontal_outline.svg.import b/assets/images/gamepad/steam/steam_dpad_horizontal_outline.svg.import
index c6b895f18..a697d6bdb 100644
--- a/assets/images/gamepad/steam/steam_dpad_horizontal_outline.svg.import
+++ b/assets/images/gamepad/steam/steam_dpad_horizontal_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://i7q0vemc5kug"
+uid="uid://c3sm6y4gi7jry"
path="res://.godot/imported/steam_dpad_horizontal_outline.svg-3a72fde31146bb1d9eb4c0a570eeaa45.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_dpad_left.svg.import b/assets/images/gamepad/steam/steam_dpad_left.svg.import
index 6a47b2ec8..b8ae9e821 100644
--- a/assets/images/gamepad/steam/steam_dpad_left.svg.import
+++ b/assets/images/gamepad/steam/steam_dpad_left.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://curpocxiiytm1"
+uid="uid://dlt00cmdhrufc"
path="res://.godot/imported/steam_dpad_left.svg-f02c48628a55c5667b171cdb6e10ec61.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_dpad_left_outline.svg.import b/assets/images/gamepad/steam/steam_dpad_left_outline.svg.import
index 6f08ab756..2e5d422ad 100644
--- a/assets/images/gamepad/steam/steam_dpad_left_outline.svg.import
+++ b/assets/images/gamepad/steam/steam_dpad_left_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dvw6oeujbypqi"
+uid="uid://dx75o4inwpu7"
path="res://.godot/imported/steam_dpad_left_outline.svg-5434e37d868495d5c6c8ddc847b0b8c7.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_dpad_none.svg.import b/assets/images/gamepad/steam/steam_dpad_none.svg.import
index 344d19fe6..edca55095 100644
--- a/assets/images/gamepad/steam/steam_dpad_none.svg.import
+++ b/assets/images/gamepad/steam/steam_dpad_none.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://eatx11haoxew"
+uid="uid://du76byhoab751"
path="res://.godot/imported/steam_dpad_none.svg-2d8476e7eeef3df1bc4bf9cc9d1494b3.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_dpad_right.svg.import b/assets/images/gamepad/steam/steam_dpad_right.svg.import
index 84905f5d2..7a48664d0 100644
--- a/assets/images/gamepad/steam/steam_dpad_right.svg.import
+++ b/assets/images/gamepad/steam/steam_dpad_right.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bpws8otkr23ss"
+uid="uid://dwopaos8mykma"
path="res://.godot/imported/steam_dpad_right.svg-08180a7ed815f68bb4f114ff4ee1e3ea.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_dpad_right_outline.svg.import b/assets/images/gamepad/steam/steam_dpad_right_outline.svg.import
index 15172598a..75d1ff575 100644
--- a/assets/images/gamepad/steam/steam_dpad_right_outline.svg.import
+++ b/assets/images/gamepad/steam/steam_dpad_right_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://ipy1kflhf03t"
+uid="uid://bxtngwdstx1sc"
path="res://.godot/imported/steam_dpad_right_outline.svg-eabbc0656426185bf685e06dcca3d1d6.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_dpad_up.svg.import b/assets/images/gamepad/steam/steam_dpad_up.svg.import
index 3bb1a4770..0fabafa08 100644
--- a/assets/images/gamepad/steam/steam_dpad_up.svg.import
+++ b/assets/images/gamepad/steam/steam_dpad_up.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cmlvutjr6mn8r"
+uid="uid://u6ehkqpdr5dn"
path="res://.godot/imported/steam_dpad_up.svg-34c15774c5b8e0667e482957cc589931.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_dpad_up_outline.svg.import b/assets/images/gamepad/steam/steam_dpad_up_outline.svg.import
index 21326766a..1f3f0ad77 100644
--- a/assets/images/gamepad/steam/steam_dpad_up_outline.svg.import
+++ b/assets/images/gamepad/steam/steam_dpad_up_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b5xsiltlb0era"
+uid="uid://cjwbnerecy2gf"
path="res://.godot/imported/steam_dpad_up_outline.svg-be5f6c67ba9c2c82ebda8b73f3b31d91.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_dpad_vertical.svg.import b/assets/images/gamepad/steam/steam_dpad_vertical.svg.import
index 752a7df37..c06315f4c 100644
--- a/assets/images/gamepad/steam/steam_dpad_vertical.svg.import
+++ b/assets/images/gamepad/steam/steam_dpad_vertical.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cxysy67ne3dvn"
+uid="uid://d2fj6mripsovk"
path="res://.godot/imported/steam_dpad_vertical.svg-31b4e5461fde01da04ecedbf6d63ba9f.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_dpad_vertical_outline.svg.import b/assets/images/gamepad/steam/steam_dpad_vertical_outline.svg.import
index f7bae40f0..7f7ce3126 100644
--- a/assets/images/gamepad/steam/steam_dpad_vertical_outline.svg.import
+++ b/assets/images/gamepad/steam/steam_dpad_vertical_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cmr0lnbcsq6bf"
+uid="uid://mu3mwpq1o12c"
path="res://.godot/imported/steam_dpad_vertical_outline.svg-6e1865793d97cafa03f690b211cc5a88.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_lb.svg.import b/assets/images/gamepad/steam/steam_lb.svg.import
index cc3cf39ad..c6d95c1a3 100644
--- a/assets/images/gamepad/steam/steam_lb.svg.import
+++ b/assets/images/gamepad/steam/steam_lb.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://o5y7nyyxy31y"
+uid="uid://b501gsjclnmu1"
path="res://.godot/imported/steam_lb.svg-ebdaaa7816cc3b103231afd349e36652.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_lb_outline.svg.import b/assets/images/gamepad/steam/steam_lb_outline.svg.import
index d72845de9..6b01c5cb8 100644
--- a/assets/images/gamepad/steam/steam_lb_outline.svg.import
+++ b/assets/images/gamepad/steam/steam_lb_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://c8l4akyxxy163"
+uid="uid://bgeesij5jtsp4"
path="res://.godot/imported/steam_lb_outline.svg-8a2d3960a576a1b32b34fc03e78d364d.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_lg.svg.import b/assets/images/gamepad/steam/steam_lg.svg.import
index 0349e071c..56cdc0441 100644
--- a/assets/images/gamepad/steam/steam_lg.svg.import
+++ b/assets/images/gamepad/steam/steam_lg.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://7jx3hwdcd28t"
+uid="uid://bxjvcfty4u5tr"
path="res://.godot/imported/steam_lg.svg-3f6e5c7e14aa2f55df576fc20a5d9ba9.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_lg_outline.svg.import b/assets/images/gamepad/steam/steam_lg_outline.svg.import
index 17b68d249..5a8348e0d 100644
--- a/assets/images/gamepad/steam/steam_lg_outline.svg.import
+++ b/assets/images/gamepad/steam/steam_lg_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://u5xyyrbtuv4g"
+uid="uid://bvn4v3wqwqs5i"
path="res://.godot/imported/steam_lg_outline.svg-062c444b53b06310ba4aef86a028cfda.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_lt.svg.import b/assets/images/gamepad/steam/steam_lt.svg.import
index 301645940..7d4d52a36 100644
--- a/assets/images/gamepad/steam/steam_lt.svg.import
+++ b/assets/images/gamepad/steam/steam_lt.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dampk4csvkjsw"
+uid="uid://bbrwngtk0wmmj"
path="res://.godot/imported/steam_lt.svg-b01bfd27622635950e396e6bc9c7928b.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_lt_outline.svg.import b/assets/images/gamepad/steam/steam_lt_outline.svg.import
index fa6e6242a..ec10a47ad 100644
--- a/assets/images/gamepad/steam/steam_lt_outline.svg.import
+++ b/assets/images/gamepad/steam/steam_lt_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://7f2dmsr0hn0d"
+uid="uid://culhebtu5jfv2"
path="res://.godot/imported/steam_lt_outline.svg-302e340d0c033abfd2a6d05faf49e086.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_pad.svg.import b/assets/images/gamepad/steam/steam_pad.svg.import
index a428af493..588ff4fb0 100644
--- a/assets/images/gamepad/steam/steam_pad.svg.import
+++ b/assets/images/gamepad/steam/steam_pad.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dy5uvti4f81vs"
+uid="uid://bb1iks7hcb0ld"
path="res://.godot/imported/steam_pad.svg-df48b374b61757ac941ec062b7f496c0.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_pad_center.svg.import b/assets/images/gamepad/steam/steam_pad_center.svg.import
index b94fd236c..32a63470f 100644
--- a/assets/images/gamepad/steam/steam_pad_center.svg.import
+++ b/assets/images/gamepad/steam/steam_pad_center.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cfmikv08xxrfo"
+uid="uid://b240xfdmiqrgp"
path="res://.godot/imported/steam_pad_center.svg-2e7a602bbe80de1f3e095c3b9c1e5e28.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_pad_down.svg.import b/assets/images/gamepad/steam/steam_pad_down.svg.import
index f2d8d3052..056a816cc 100644
--- a/assets/images/gamepad/steam/steam_pad_down.svg.import
+++ b/assets/images/gamepad/steam/steam_pad_down.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cburq6bpwwckm"
+uid="uid://fsgwkm8wjffx"
path="res://.godot/imported/steam_pad_down.svg-e86db49bb06475315e8751f20a55a7e1.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_pad_left.svg.import b/assets/images/gamepad/steam/steam_pad_left.svg.import
index 2e3b6ffd3..303d2ee04 100644
--- a/assets/images/gamepad/steam/steam_pad_left.svg.import
+++ b/assets/images/gamepad/steam/steam_pad_left.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bkj2m4623hqw5"
+uid="uid://qc384y4f6w8w"
path="res://.godot/imported/steam_pad_left.svg-0e071ed0a5c088ebaaf46cbd900dceed.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_pad_right.svg.import b/assets/images/gamepad/steam/steam_pad_right.svg.import
index 43faba3aa..6cda40ede 100644
--- a/assets/images/gamepad/steam/steam_pad_right.svg.import
+++ b/assets/images/gamepad/steam/steam_pad_right.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://yp42bh1b0erl"
+uid="uid://cuu4f18c7detj"
path="res://.godot/imported/steam_pad_right.svg-47fdf1c0bae4c0d252cf407f0b1f5865.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_pad_up.svg.import b/assets/images/gamepad/steam/steam_pad_up.svg.import
index fa09a677b..8df253903 100644
--- a/assets/images/gamepad/steam/steam_pad_up.svg.import
+++ b/assets/images/gamepad/steam/steam_pad_up.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bfgog4n4ytv7u"
+uid="uid://dp11cg0bc0kd2"
path="res://.godot/imported/steam_pad_up.svg-59f45a7ba048802096ed36a7684e9f18.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_rb.svg.import b/assets/images/gamepad/steam/steam_rb.svg.import
index f955d97cb..e6c79a396 100644
--- a/assets/images/gamepad/steam/steam_rb.svg.import
+++ b/assets/images/gamepad/steam/steam_rb.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://xydy2h52e35y"
+uid="uid://cvx88kxapa0xi"
path="res://.godot/imported/steam_rb.svg-9318cab37b297594f6297f3c52e60dda.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_rb_outline.svg.import b/assets/images/gamepad/steam/steam_rb_outline.svg.import
index baba1a908..e1d7af587 100644
--- a/assets/images/gamepad/steam/steam_rb_outline.svg.import
+++ b/assets/images/gamepad/steam/steam_rb_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dkkfgph1iyqym"
+uid="uid://cvqy5x4nlwvu7"
path="res://.godot/imported/steam_rb_outline.svg-54720a810d4e0ed1cf9b532e414dcd64.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_rg.svg.import b/assets/images/gamepad/steam/steam_rg.svg.import
index 269162119..0e4ddec1d 100644
--- a/assets/images/gamepad/steam/steam_rg.svg.import
+++ b/assets/images/gamepad/steam/steam_rg.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bsxofaj5ietuc"
+uid="uid://otfjb4w8k4vh"
path="res://.godot/imported/steam_rg.svg-9d969ea629ebc8f79d977f507af8231f.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_rg_outline.svg.import b/assets/images/gamepad/steam/steam_rg_outline.svg.import
index a85c44b84..01a14cf6e 100644
--- a/assets/images/gamepad/steam/steam_rg_outline.svg.import
+++ b/assets/images/gamepad/steam/steam_rg_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b7jrp7gupco21"
+uid="uid://tyafjwljcoj5"
path="res://.godot/imported/steam_rg_outline.svg-481fcdf5ceba8b3048c550792abb7468.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_rt.svg.import b/assets/images/gamepad/steam/steam_rt.svg.import
index 7e8abfbc8..0755704c7 100644
--- a/assets/images/gamepad/steam/steam_rt.svg.import
+++ b/assets/images/gamepad/steam/steam_rt.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dcdbjs574x67u"
+uid="uid://dyq1bux1exh7u"
path="res://.godot/imported/steam_rt.svg-4a43cc6d50aee24f70346df5a38e1e7d.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_rt_outline.svg.import b/assets/images/gamepad/steam/steam_rt_outline.svg.import
index d5043b891..ce6a68148 100644
--- a/assets/images/gamepad/steam/steam_rt_outline.svg.import
+++ b/assets/images/gamepad/steam/steam_rt_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bliwxrb2col5v"
+uid="uid://b4833q7cdgvdp"
path="res://.godot/imported/steam_rt_outline.svg-812befdf3249ea36dd8c20073482120c.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_stick.svg.import b/assets/images/gamepad/steam/steam_stick.svg.import
index f7172ac98..e568c326f 100644
--- a/assets/images/gamepad/steam/steam_stick.svg.import
+++ b/assets/images/gamepad/steam/steam_stick.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b251los4ey64w"
+uid="uid://bm0b6klr4s4me"
path="res://.godot/imported/steam_stick.svg-c39de154d15fe02103cb42db87a977e2.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_stick_down.svg.import b/assets/images/gamepad/steam/steam_stick_down.svg.import
index e121297aa..1204fca07 100644
--- a/assets/images/gamepad/steam/steam_stick_down.svg.import
+++ b/assets/images/gamepad/steam/steam_stick_down.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dipbfvbdnieqv"
+uid="uid://b38225lpoxnad"
path="res://.godot/imported/steam_stick_down.svg-b9bdcb37ca243c9bf3a9c1344c932c97.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_stick_horizontal.svg.import b/assets/images/gamepad/steam/steam_stick_horizontal.svg.import
index 16d85f0df..e0c9f1547 100644
--- a/assets/images/gamepad/steam/steam_stick_horizontal.svg.import
+++ b/assets/images/gamepad/steam/steam_stick_horizontal.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://2dlvoe02t0xj"
+uid="uid://lr5cgsbsdue5"
path="res://.godot/imported/steam_stick_horizontal.svg-ce74baee539630d6117416b33e77de36.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_stick_l_press.svg.import b/assets/images/gamepad/steam/steam_stick_l_press.svg.import
index 6b230bf9a..1e9f4abea 100644
--- a/assets/images/gamepad/steam/steam_stick_l_press.svg.import
+++ b/assets/images/gamepad/steam/steam_stick_l_press.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cc3la68tqkeu7"
+uid="uid://bp3y2i8nclwov"
path="res://.godot/imported/steam_stick_l_press.svg-345633f8e0fae22795871cdae118d9d5.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_stick_left.svg.import b/assets/images/gamepad/steam/steam_stick_left.svg.import
index 0c6522db6..4714d1d02 100644
--- a/assets/images/gamepad/steam/steam_stick_left.svg.import
+++ b/assets/images/gamepad/steam/steam_stick_left.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b7vfsacm21uvc"
+uid="uid://cwe6414vhvsbm"
path="res://.godot/imported/steam_stick_left.svg-cba212938eec57f543e0924a399de692.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_stick_right.svg.import b/assets/images/gamepad/steam/steam_stick_right.svg.import
index 71c017a04..b60f337a7 100644
--- a/assets/images/gamepad/steam/steam_stick_right.svg.import
+++ b/assets/images/gamepad/steam/steam_stick_right.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://jfjsyxvyctbk"
+uid="uid://c5c5rvhs8260"
path="res://.godot/imported/steam_stick_right.svg-965841e5f4831da187ca9f10a6bc3a7a.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_stick_side_l.svg.import b/assets/images/gamepad/steam/steam_stick_side_l.svg.import
index 28f68b741..ada507d91 100644
--- a/assets/images/gamepad/steam/steam_stick_side_l.svg.import
+++ b/assets/images/gamepad/steam/steam_stick_side_l.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://tp838k62c4h"
+uid="uid://ccyqd0aswcuis"
path="res://.godot/imported/steam_stick_side_l.svg-a9fc7d0551ff234c0ed21ddabeaa1363.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_stick_up.svg.import b/assets/images/gamepad/steam/steam_stick_up.svg.import
index 7a8658d16..765b30719 100644
--- a/assets/images/gamepad/steam/steam_stick_up.svg.import
+++ b/assets/images/gamepad/steam/steam_stick_up.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://c10buq0dndeb8"
+uid="uid://h0lyv05rajef"
path="res://.godot/imported/steam_stick_up.svg-c95a45250883ac3a3cadc13f7e19f3a5.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steam/steam_stick_vertical.svg.import b/assets/images/gamepad/steam/steam_stick_vertical.svg.import
index 0c54e426b..683a9f7ca 100644
--- a/assets/images/gamepad/steam/steam_stick_vertical.svg.import
+++ b/assets/images/gamepad/steam/steam_stick_vertical.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bqabcjwil5a60"
+uid="uid://dqn8y6dtrtaj"
path="res://.godot/imported/steam_stick_vertical.svg-c5c996b8de39ae68ec73252f3952df05.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/controller_steamdeck.svg.import b/assets/images/gamepad/steamdeck/controller_steamdeck.svg.import
index 0406047c8..c753d65b1 100644
--- a/assets/images/gamepad/steamdeck/controller_steamdeck.svg.import
+++ b/assets/images/gamepad/steamdeck/controller_steamdeck.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://c8v7tlasra7pf"
+uid="uid://bbkn14ei6gvyy"
path="res://.godot/imported/controller_steamdeck.svg-b380028662e4389bcaad12bcd2c1457f.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/diagram.png.import b/assets/images/gamepad/steamdeck/diagram.png.import
index 906156d78..201984e1e 100644
--- a/assets/images/gamepad/steamdeck/diagram.png.import
+++ b/assets/images/gamepad/steamdeck/diagram.png.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cvyo2q5qjpamv"
+uid="uid://b4w5tmfci1toh"
path="res://.godot/imported/diagram.png-d1aa2aa0cc56822aa0de1b6eae6efe02.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_button_a.svg.import b/assets/images/gamepad/steamdeck/steamdeck_button_a.svg.import
index 2ad8edfca..300d7279d 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_button_a.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_button_a.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://2ymxt6fjxgbg"
+uid="uid://glixduifqfyc"
path="res://.godot/imported/steamdeck_button_a.svg-3c96f372767139bc6a7947b6024d4c33.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_button_a_outline.svg.import b/assets/images/gamepad/steamdeck/steamdeck_button_a_outline.svg.import
index f31ee1d91..5844a7bbf 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_button_a_outline.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_button_a_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://2nutdoeeqfs6"
+uid="uid://buct6isrdlqfl"
path="res://.godot/imported/steamdeck_button_a_outline.svg-862d22fe6a348292e059eb24fe5fd408.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_button_b.svg.import b/assets/images/gamepad/steamdeck/steamdeck_button_b.svg.import
index 0c1d84fff..a6840a325 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_button_b.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_button_b.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bdijnj7q510fb"
+uid="uid://bi6jcsdcp4e77"
path="res://.godot/imported/steamdeck_button_b.svg-e4e5608d890fbee317682689863cb7da.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_button_b_outline.svg.import b/assets/images/gamepad/steamdeck/steamdeck_button_b_outline.svg.import
index c4fc09c2b..b5d3c0ffa 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_button_b_outline.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_button_b_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cxnabiia426t5"
+uid="uid://g8ygs37lvqqk"
path="res://.godot/imported/steamdeck_button_b_outline.svg-8c421f861f790b857b05d52982c66ff2.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_button_guide.svg.import b/assets/images/gamepad/steamdeck/steamdeck_button_guide.svg.import
index eb335313d..c0a6ec975 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_button_guide.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_button_guide.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b8kll7wj3mpw5"
+uid="uid://7obnebcrnike"
path="res://.godot/imported/steamdeck_button_guide.svg-88570b881601d872403131bf0a893641.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_button_guide_outline.svg.import b/assets/images/gamepad/steamdeck/steamdeck_button_guide_outline.svg.import
index 57531a92d..0a07fa24a 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_button_guide_outline.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_button_guide_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dt7lcs2caoj1f"
+uid="uid://blkb53i8h572k"
path="res://.godot/imported/steamdeck_button_guide_outline.svg-d45f44227db018837f5aecf8ae628036.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_button_l1.svg.import b/assets/images/gamepad/steamdeck/steamdeck_button_l1.svg.import
index 3727ec339..f58f56665 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_button_l1.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_button_l1.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://iuf1gwubgrkr"
+uid="uid://scfbg0yygqka"
path="res://.godot/imported/steamdeck_button_l1.svg-37c5dfe953290523d7a0870f5ec4920d.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_button_l1_outline.svg.import b/assets/images/gamepad/steamdeck/steamdeck_button_l1_outline.svg.import
index b543a2ee1..906f26b05 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_button_l1_outline.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_button_l1_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b6s7og36abb72"
+uid="uid://bkevsp88so0qo"
path="res://.godot/imported/steamdeck_button_l1_outline.svg-e16d27872d60c49e588a305342949519.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_button_l2.svg.import b/assets/images/gamepad/steamdeck/steamdeck_button_l2.svg.import
index 0dbd03bcc..09355841f 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_button_l2.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_button_l2.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dxpamvls1wtr4"
+uid="uid://k5ca2xyvchl2"
path="res://.godot/imported/steamdeck_button_l2.svg-aceca1274115db593d8ecb8243d34e49.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_button_l2_outline.svg.import b/assets/images/gamepad/steamdeck/steamdeck_button_l2_outline.svg.import
index 1f1b556e6..b5fb96a66 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_button_l2_outline.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_button_l2_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://djq3ruhk5qvcw"
+uid="uid://sroh0o3qwlhy"
path="res://.godot/imported/steamdeck_button_l2_outline.svg-7a898280a759f7f328095fc1fddc1172.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_button_l4.svg.import b/assets/images/gamepad/steamdeck/steamdeck_button_l4.svg.import
index 0b46107f7..78d2017c0 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_button_l4.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_button_l4.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://2hvt2s10h4oh"
+uid="uid://cru5rdx15j4ts"
path="res://.godot/imported/steamdeck_button_l4.svg-17eb0171ee9f951a043e00f5d2d799b0.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_button_l4_outline.svg.import b/assets/images/gamepad/steamdeck/steamdeck_button_l4_outline.svg.import
index d8bae0458..09c07fc49 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_button_l4_outline.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_button_l4_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cvgsjmmmxhj27"
+uid="uid://drw1e1taneo26"
path="res://.godot/imported/steamdeck_button_l4_outline.svg-5b983c6aa05e41693534c6d8842a1441.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_button_l5.svg.import b/assets/images/gamepad/steamdeck/steamdeck_button_l5.svg.import
index 70ea4caac..f1d93c1af 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_button_l5.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_button_l5.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bsqe51ljqa1wl"
+uid="uid://iby8tq0amo8b"
path="res://.godot/imported/steamdeck_button_l5.svg-fb46ead322627794a308ab7a4fd40f1f.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_button_l5_outline.svg.import b/assets/images/gamepad/steamdeck/steamdeck_button_l5_outline.svg.import
index 269cc0dc5..d307d3815 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_button_l5_outline.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_button_l5_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cdtfvv4xetm05"
+uid="uid://l6866l67en71"
path="res://.godot/imported/steamdeck_button_l5_outline.svg-9e67363a6a1cdeaf708bdc2260720a17.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_button_options.svg.import b/assets/images/gamepad/steamdeck/steamdeck_button_options.svg.import
index ad0c2e3ea..1cf3fa2fe 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_button_options.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_button_options.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dhwuj34jww33w"
+uid="uid://i37o7qma5l0m"
path="res://.godot/imported/steamdeck_button_options.svg-fe436a11d931edc617b188532486d3f3.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_button_options_outline.svg.import b/assets/images/gamepad/steamdeck/steamdeck_button_options_outline.svg.import
index 2a07d5f91..f0207c550 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_button_options_outline.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_button_options_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://5lgrd7ygl855"
+uid="uid://ba3th3xag5j4f"
path="res://.godot/imported/steamdeck_button_options_outline.svg-d1f39f0fd37fa6a44333a87cdb873050.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_button_quickaccess.svg.import b/assets/images/gamepad/steamdeck/steamdeck_button_quickaccess.svg.import
index 31ee89548..28333b305 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_button_quickaccess.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_button_quickaccess.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://byy323swr1naa"
+uid="uid://c8huhb14jh1ba"
path="res://.godot/imported/steamdeck_button_quickaccess.svg-267fcd44a36ca9cde7bdfa67733ac61d.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_button_quickaccess_outline.svg.import b/assets/images/gamepad/steamdeck/steamdeck_button_quickaccess_outline.svg.import
index a8ba11c24..e34b8fdd6 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_button_quickaccess_outline.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_button_quickaccess_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b684m5kw5iest"
+uid="uid://bnsm37uh6a0cd"
path="res://.godot/imported/steamdeck_button_quickaccess_outline.svg-fe28bfacd46a07040d742e33a4efcadd.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_button_r1.svg.import b/assets/images/gamepad/steamdeck/steamdeck_button_r1.svg.import
index fe8b95922..953ca5a4f 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_button_r1.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_button_r1.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cvm6un7wher3"
+uid="uid://cdx74dhosgpi1"
path="res://.godot/imported/steamdeck_button_r1.svg-ea73b538a66919b66e7401df05c8d53f.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_button_r1_outline.svg.import b/assets/images/gamepad/steamdeck/steamdeck_button_r1_outline.svg.import
index f07034861..a2c62d6cf 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_button_r1_outline.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_button_r1_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dytmy0gt1x26k"
+uid="uid://lys7vscbqlhv"
path="res://.godot/imported/steamdeck_button_r1_outline.svg-cd54cc6217e365f3672d391ceb3b42a4.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_button_r2.svg.import b/assets/images/gamepad/steamdeck/steamdeck_button_r2.svg.import
index c127c7bf1..0abf2480e 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_button_r2.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_button_r2.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://coaaq1r1uiyx2"
+uid="uid://dw7hjtcfaepx"
path="res://.godot/imported/steamdeck_button_r2.svg-57f7f438c382adb35a10239bd22ac1d3.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_button_r2_outline.svg.import b/assets/images/gamepad/steamdeck/steamdeck_button_r2_outline.svg.import
index 5cec3c73f..1257c3e00 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_button_r2_outline.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_button_r2_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://nxyikcse40tf"
+uid="uid://dbl6ggekqybxm"
path="res://.godot/imported/steamdeck_button_r2_outline.svg-84baf69025cc9ce4619170e1f55c338b.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_button_r4.svg.import b/assets/images/gamepad/steamdeck/steamdeck_button_r4.svg.import
index cf0b4b6b9..53e8d4f17 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_button_r4.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_button_r4.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dmfw87xx6phhc"
+uid="uid://duirfrp1swep8"
path="res://.godot/imported/steamdeck_button_r4.svg-d12e3f86a5ac3e1f45129b859ea0a2d7.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_button_r4_outline.svg.import b/assets/images/gamepad/steamdeck/steamdeck_button_r4_outline.svg.import
index 323d4cf95..054723e51 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_button_r4_outline.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_button_r4_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bsv3tlxuhgena"
+uid="uid://b05ajk2yqm804"
path="res://.godot/imported/steamdeck_button_r4_outline.svg-ec7e1fb5a8ed988b1374be9c34228fcb.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_button_r5.svg.import b/assets/images/gamepad/steamdeck/steamdeck_button_r5.svg.import
index 570f68e0c..b98fbfa78 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_button_r5.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_button_r5.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bre5c38fo7hn5"
+uid="uid://b5dvxnn2ddhar"
path="res://.godot/imported/steamdeck_button_r5.svg-1983f11c413a72b91022c926e08fc027.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_button_r5_outline.svg.import b/assets/images/gamepad/steamdeck/steamdeck_button_r5_outline.svg.import
index 4655262df..1ba19e797 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_button_r5_outline.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_button_r5_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cpdr8qkxeo5ju"
+uid="uid://b33wq5mcv46tp"
path="res://.godot/imported/steamdeck_button_r5_outline.svg-5b3f434144f60c0bcbbba463711c0d3e.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_button_view.svg.import b/assets/images/gamepad/steamdeck/steamdeck_button_view.svg.import
index 98e2505ab..ce3dd3c79 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_button_view.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_button_view.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://c3tfburs4gc2e"
+uid="uid://b3g1sl3gxac3l"
path="res://.godot/imported/steamdeck_button_view.svg-df5e705a2ae746d8f893dc4c49b7062f.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_button_view_outline.svg.import b/assets/images/gamepad/steamdeck/steamdeck_button_view_outline.svg.import
index 3b6556ce5..d4f33cf8a 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_button_view_outline.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_button_view_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b1086fd7g6tor"
+uid="uid://4lvqtp435icx"
path="res://.godot/imported/steamdeck_button_view_outline.svg-59748db8aa7141f9866d8e1574315527.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_button_x.svg.import b/assets/images/gamepad/steamdeck/steamdeck_button_x.svg.import
index 27efa79fa..a563f3d9e 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_button_x.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_button_x.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dedkcpdkjkfgi"
+uid="uid://du2ljto5eauh5"
path="res://.godot/imported/steamdeck_button_x.svg-335cf3f8e08c9ca9a5d8df07a0ab3341.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_button_x_outline.svg.import b/assets/images/gamepad/steamdeck/steamdeck_button_x_outline.svg.import
index f17dc45a5..00128ae9b 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_button_x_outline.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_button_x_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://datmi41jrwsul"
+uid="uid://d358hwoxc2vq7"
path="res://.godot/imported/steamdeck_button_x_outline.svg-d37a7e3f6e334568860831bf9a78e3bc.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_button_y.svg.import b/assets/images/gamepad/steamdeck/steamdeck_button_y.svg.import
index 217bfc759..4d3414b40 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_button_y.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_button_y.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b14twfve0lmf6"
+uid="uid://d238yav03b5tk"
path="res://.godot/imported/steamdeck_button_y.svg-491ec7b2f613d73aed5951adb98883c1.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_button_y_outline.svg.import b/assets/images/gamepad/steamdeck/steamdeck_button_y_outline.svg.import
index 9b5eafd24..98c217db6 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_button_y_outline.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_button_y_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dd101tqt3ta7g"
+uid="uid://mgwkcxa4o7y6"
path="res://.godot/imported/steamdeck_button_y_outline.svg-913defeea6af577570b1c575750854b4.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_dpad.svg.import b/assets/images/gamepad/steamdeck/steamdeck_dpad.svg.import
index 6caa82bda..6720bc362 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_dpad.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_dpad.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://d1vwjidwwl6g6"
+uid="uid://dprhshnof4mpt"
path="res://.godot/imported/steamdeck_dpad.svg-753b7ebe2856b88604fc7b17c8209d87.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_dpad_all.svg.import b/assets/images/gamepad/steamdeck/steamdeck_dpad_all.svg.import
index f4db29955..b8c9e57e1 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_dpad_all.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_dpad_all.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dcud65iy6s5sl"
+uid="uid://cph7qr17caho5"
path="res://.godot/imported/steamdeck_dpad_all.svg-a4cdcb6fac9af5eaad366f8d3ddfe692.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_dpad_down.svg.import b/assets/images/gamepad/steamdeck/steamdeck_dpad_down.svg.import
index 169331b5e..8e54826ae 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_dpad_down.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_dpad_down.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://ck0gwj0t1nlnb"
+uid="uid://bc1anbo6va8c2"
path="res://.godot/imported/steamdeck_dpad_down.svg-ed18ec862cec822779d95a5c4bd7cea4.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_dpad_down_outline.svg.import b/assets/images/gamepad/steamdeck/steamdeck_dpad_down_outline.svg.import
index 11ad59ab3..39a155582 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_dpad_down_outline.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_dpad_down_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://2uwp5b8cw7gi"
+uid="uid://gi2hxifsgish"
path="res://.godot/imported/steamdeck_dpad_down_outline.svg-e35d85bd00e08ab760c254d9ecf8c468.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_dpad_horizontal.svg.import b/assets/images/gamepad/steamdeck/steamdeck_dpad_horizontal.svg.import
index 002dfdddc..9983050b7 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_dpad_horizontal.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_dpad_horizontal.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bu1c432lg87jt"
+uid="uid://vm3u83b0rcwi"
path="res://.godot/imported/steamdeck_dpad_horizontal.svg-5a9c4f7f6c49bece425ca169d0c1b8f7.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_dpad_horizontal_outline.svg.import b/assets/images/gamepad/steamdeck/steamdeck_dpad_horizontal_outline.svg.import
index 682fa2017..2ee984293 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_dpad_horizontal_outline.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_dpad_horizontal_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://7mwu1mw50mfb"
+uid="uid://drehqhi4k2cww"
path="res://.godot/imported/steamdeck_dpad_horizontal_outline.svg-d3797b43452b5450c512878f738711f6.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_dpad_left.svg.import b/assets/images/gamepad/steamdeck/steamdeck_dpad_left.svg.import
index f55cfeb7e..c90762e2b 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_dpad_left.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_dpad_left.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bw3o757gon60n"
+uid="uid://ggcsc810x7ri"
path="res://.godot/imported/steamdeck_dpad_left.svg-39c443fbe819af802f0f3eddc3213231.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_dpad_left_outline.svg.import b/assets/images/gamepad/steamdeck/steamdeck_dpad_left_outline.svg.import
index 9163af2b5..40b8a5bc2 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_dpad_left_outline.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_dpad_left_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://trep17b27in5"
+uid="uid://cv41uec8jor18"
path="res://.godot/imported/steamdeck_dpad_left_outline.svg-0cc5532c63959465a335c431cdd399a5.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_dpad_none.svg.import b/assets/images/gamepad/steamdeck/steamdeck_dpad_none.svg.import
index c512034ca..be6a744bd 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_dpad_none.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_dpad_none.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dt06u2aunvd6d"
+uid="uid://irdbms6j8s81"
path="res://.godot/imported/steamdeck_dpad_none.svg-6a4d7648c61970861acc15131f306998.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_dpad_right.svg.import b/assets/images/gamepad/steamdeck/steamdeck_dpad_right.svg.import
index b768b15dc..1f897c465 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_dpad_right.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_dpad_right.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cxe85qvlcxt8k"
+uid="uid://tc7bgm3gcyqd"
path="res://.godot/imported/steamdeck_dpad_right.svg-24b9aced2fb9e18c763d60190fdc3df6.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_dpad_right_outline.svg.import b/assets/images/gamepad/steamdeck/steamdeck_dpad_right_outline.svg.import
index 25251ee06..cb5fe4c71 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_dpad_right_outline.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_dpad_right_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bl2oq66bq55bx"
+uid="uid://c2agy2hadglv4"
path="res://.godot/imported/steamdeck_dpad_right_outline.svg-7def502e7977f3b3619939ea74c91745.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_dpad_up.svg.import b/assets/images/gamepad/steamdeck/steamdeck_dpad_up.svg.import
index fa1b1466c..76720ba97 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_dpad_up.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_dpad_up.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://d3bk0otxo2u0t"
+uid="uid://dfqvij0d87gq8"
path="res://.godot/imported/steamdeck_dpad_up.svg-5f3805a998fa474a44c8ba2a0fb5affe.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_dpad_up_outline.svg.import b/assets/images/gamepad/steamdeck/steamdeck_dpad_up_outline.svg.import
index ba8136eec..3af78d729 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_dpad_up_outline.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_dpad_up_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://8vo7daip3bwa"
+uid="uid://b2i2bd4ppnynk"
path="res://.godot/imported/steamdeck_dpad_up_outline.svg-282a6e353faf1f6650c531c24d26f618.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_dpad_vertical.svg.import b/assets/images/gamepad/steamdeck/steamdeck_dpad_vertical.svg.import
index 2e204ea5f..51e544c7a 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_dpad_vertical.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_dpad_vertical.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b5rdkewtqva3g"
+uid="uid://d051eubmxe0i5"
path="res://.godot/imported/steamdeck_dpad_vertical.svg-b2baad11b7e2c66f06a95a9cffcf860a.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_dpad_vertical_outline.svg.import b/assets/images/gamepad/steamdeck/steamdeck_dpad_vertical_outline.svg.import
index ecb49087d..ae15c8436 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_dpad_vertical_outline.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_dpad_vertical_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://gjgojrbivjk0"
+uid="uid://cqylecsj4twwa"
path="res://.godot/imported/steamdeck_dpad_vertical_outline.svg-4c4fc011882ecfda0ca0dfef32b18244.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_stick_l.svg.import b/assets/images/gamepad/steamdeck/steamdeck_stick_l.svg.import
index 744922744..cc483ccfa 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_stick_l.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_stick_l.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://c6holuruhn6gs"
+uid="uid://cljgsi6rwed5y"
path="res://.godot/imported/steamdeck_stick_l.svg-e57d296ff43284680adfdfb347d107d7.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_stick_l_down.svg.import b/assets/images/gamepad/steamdeck/steamdeck_stick_l_down.svg.import
index 2ace9c19b..e495232e3 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_stick_l_down.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_stick_l_down.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bkuoy3851ps81"
+uid="uid://b4t2lfdlk8v1l"
path="res://.godot/imported/steamdeck_stick_l_down.svg-7a0e27ed40f5448139f22f448d55a591.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_stick_l_horizontal.svg.import b/assets/images/gamepad/steamdeck/steamdeck_stick_l_horizontal.svg.import
index e2e300be0..5eb19d7b5 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_stick_l_horizontal.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_stick_l_horizontal.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bdvotsbpgqfdh"
+uid="uid://2pi8ywk01h7l"
path="res://.godot/imported/steamdeck_stick_l_horizontal.svg-acad8a6786e459ff92731fe6815e2f28.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_stick_l_left.svg.import b/assets/images/gamepad/steamdeck/steamdeck_stick_l_left.svg.import
index 8bf9e7fe8..796f270e8 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_stick_l_left.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_stick_l_left.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dfreqwma7axjm"
+uid="uid://dgq0pu6stgp0n"
path="res://.godot/imported/steamdeck_stick_l_left.svg-a2746b63364a319880bd47d9af14c185.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_stick_l_press.svg.import b/assets/images/gamepad/steamdeck/steamdeck_stick_l_press.svg.import
index 541cf0c54..d432e65bc 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_stick_l_press.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_stick_l_press.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dcqhk1jgepeq0"
+uid="uid://fk70akhspjqw"
path="res://.godot/imported/steamdeck_stick_l_press.svg-a1e9ca79e30ef553e717bec6a0ec0276.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_stick_l_right.svg.import b/assets/images/gamepad/steamdeck/steamdeck_stick_l_right.svg.import
index 72f145a6e..054f8e4bf 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_stick_l_right.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_stick_l_right.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dpxu821a7oj4s"
+uid="uid://cg673id36yufn"
path="res://.godot/imported/steamdeck_stick_l_right.svg-e94e889b8467541c329b1f6106501ce5.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_stick_l_up.svg.import b/assets/images/gamepad/steamdeck/steamdeck_stick_l_up.svg.import
index 7f8cf6c62..7fb1a7a19 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_stick_l_up.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_stick_l_up.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dgpc6aewueu74"
+uid="uid://clerkwh0rv4qm"
path="res://.godot/imported/steamdeck_stick_l_up.svg-a9025e3fa7239eb9a249cfb7c4645379.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_stick_l_vertical.svg.import b/assets/images/gamepad/steamdeck/steamdeck_stick_l_vertical.svg.import
index 1d9839dac..3a61fe3f3 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_stick_l_vertical.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_stick_l_vertical.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://d3dxqs8yjn466"
+uid="uid://bk3imcmp86kgc"
path="res://.godot/imported/steamdeck_stick_l_vertical.svg-463a0006ec6805b46dc4119a66ebcd2e.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_stick_r.svg.import b/assets/images/gamepad/steamdeck/steamdeck_stick_r.svg.import
index 19cdc61d6..f87f7c65b 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_stick_r.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_stick_r.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://c0vodcvwmd4mq"
+uid="uid://dm1cw0o0kpajg"
path="res://.godot/imported/steamdeck_stick_r.svg-40fce2614f30b40f063b130b06363d2e.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_stick_r_down.svg.import b/assets/images/gamepad/steamdeck/steamdeck_stick_r_down.svg.import
index 8ddbb8cf4..356769f07 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_stick_r_down.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_stick_r_down.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://drhc3nti5y4v2"
+uid="uid://dcyao1pr3jtls"
path="res://.godot/imported/steamdeck_stick_r_down.svg-fc725e715647ca133ea27b8f22e2f9dc.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_stick_r_horizontal.svg.import b/assets/images/gamepad/steamdeck/steamdeck_stick_r_horizontal.svg.import
index 309490bb2..38049bed5 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_stick_r_horizontal.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_stick_r_horizontal.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://g2l2c7s5w5g8"
+uid="uid://b4ek5ijusyt1x"
path="res://.godot/imported/steamdeck_stick_r_horizontal.svg-e843d1815a1b03129b431815caef58ff.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_stick_r_left.svg.import b/assets/images/gamepad/steamdeck/steamdeck_stick_r_left.svg.import
index 28c2e03aa..3797d3b9c 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_stick_r_left.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_stick_r_left.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bf050ow2fqwl5"
+uid="uid://dk34rpf2xmwpp"
path="res://.godot/imported/steamdeck_stick_r_left.svg-74f89d5ab1621bb0ebaee0c4f6f4f9a1.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_stick_r_press.svg.import b/assets/images/gamepad/steamdeck/steamdeck_stick_r_press.svg.import
index f8c68426a..bd08e8fcf 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_stick_r_press.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_stick_r_press.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bflve4wmy5l7p"
+uid="uid://vb6n5l5ajq0t"
path="res://.godot/imported/steamdeck_stick_r_press.svg-628771ef06c6e6b796cf8d399987e99d.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_stick_r_right.svg.import b/assets/images/gamepad/steamdeck/steamdeck_stick_r_right.svg.import
index 96332a2cd..3dda1d769 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_stick_r_right.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_stick_r_right.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://deujxqeovbjs8"
+uid="uid://jpl2xe1upygm"
path="res://.godot/imported/steamdeck_stick_r_right.svg-ec7052bbe9148d012957a93bed6869ac.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_stick_r_up.svg.import b/assets/images/gamepad/steamdeck/steamdeck_stick_r_up.svg.import
index 2bd2e6a45..a3858cfd5 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_stick_r_up.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_stick_r_up.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://c23ukiudnt5vx"
+uid="uid://8ioc8gidakfr"
path="res://.godot/imported/steamdeck_stick_r_up.svg-d7c53925775ebad53f0dd406e3f9ce4f.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_stick_r_vertical.svg.import b/assets/images/gamepad/steamdeck/steamdeck_stick_r_vertical.svg.import
index 1d828dd5b..80b5409d2 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_stick_r_vertical.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_stick_r_vertical.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dgwnxs2mculkc"
+uid="uid://bs274ebd2cikg"
path="res://.godot/imported/steamdeck_stick_r_vertical.svg-be8bce72238e6acf6272015ba2e4d9ae.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_stick_side_l.svg.import b/assets/images/gamepad/steamdeck/steamdeck_stick_side_l.svg.import
index 5cfebff32..4e94a435a 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_stick_side_l.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_stick_side_l.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://co0py5tmila8a"
+uid="uid://dmjx70fjf5ysy"
path="res://.godot/imported/steamdeck_stick_side_l.svg-81dbe8c04f53654c901e85c6a96eacba.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_stick_side_r.svg.import b/assets/images/gamepad/steamdeck/steamdeck_stick_side_r.svg.import
index ab3255ac7..0ce8ced96 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_stick_side_r.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_stick_side_r.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://qqbosx352dwi"
+uid="uid://cnat1bi7c1iy1"
path="res://.godot/imported/steamdeck_stick_side_r.svg-10667782bb7cc9e65006687d639eab05.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_stick_top_l.svg.import b/assets/images/gamepad/steamdeck/steamdeck_stick_top_l.svg.import
index 08bfc2828..db7efdf4c 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_stick_top_l.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_stick_top_l.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dg7sruj1cp03x"
+uid="uid://byd0ivhix7vwl"
path="res://.godot/imported/steamdeck_stick_top_l.svg-08c6d79693c31cf1a6246b6dcbd2b9bb.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_stick_top_r.svg.import b/assets/images/gamepad/steamdeck/steamdeck_stick_top_r.svg.import
index ce7447621..2f3ff3892 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_stick_top_r.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_stick_top_r.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cvh811d6hb5xi"
+uid="uid://dlhdb57l8offw"
path="res://.godot/imported/steamdeck_stick_top_r.svg-4c7f3d1d6992cd87aaef06f8e0dc62ed.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_trackpad.svg.import b/assets/images/gamepad/steamdeck/steamdeck_trackpad.svg.import
index 07e4e1537..53c6b8c69 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_trackpad.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_trackpad.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cps7dui0d3oae"
+uid="uid://sycfdml1m5ex"
path="res://.godot/imported/steamdeck_trackpad.svg-4bd8afdd7ac21a0997b342400e515994.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_trackpad_all.svg.import b/assets/images/gamepad/steamdeck/steamdeck_trackpad_all.svg.import
index a5a95f41f..22435a434 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_trackpad_all.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_trackpad_all.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://ce8tc0w3e3hsu"
+uid="uid://c5xcaecaki0hr"
path="res://.godot/imported/steamdeck_trackpad_all.svg-74d3c4f60ea641065ad9c16147dfa6fe.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_trackpad_all_outline.svg.import b/assets/images/gamepad/steamdeck/steamdeck_trackpad_all_outline.svg.import
index 1329fbac0..d9b02cb92 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_trackpad_all_outline.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_trackpad_all_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cvca275bt0sx0"
+uid="uid://csejgvv8wqtc8"
path="res://.godot/imported/steamdeck_trackpad_all_outline.svg-e2643ceada3a81c22d1f09be6475a9ff.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_trackpad_down.svg.import b/assets/images/gamepad/steamdeck/steamdeck_trackpad_down.svg.import
index cbe20e069..7d560f016 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_trackpad_down.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_trackpad_down.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://c7ly06enxm5jq"
+uid="uid://bnbkfkp463ugy"
path="res://.godot/imported/steamdeck_trackpad_down.svg-e5b0e2a72ecc2fad3b64337ab389461a.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_trackpad_down_outline.svg.import b/assets/images/gamepad/steamdeck/steamdeck_trackpad_down_outline.svg.import
index 3d60a46a3..bbdef7e2b 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_trackpad_down_outline.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_trackpad_down_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dr1jdrodtji8u"
+uid="uid://dvxroqm3ri4ni"
path="res://.godot/imported/steamdeck_trackpad_down_outline.svg-fb01c14e76955085f3421428d15fc027.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_trackpad_horizontal.svg.import b/assets/images/gamepad/steamdeck/steamdeck_trackpad_horizontal.svg.import
index d490276b1..28659b52b 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_trackpad_horizontal.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_trackpad_horizontal.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cwefuotasq164"
+uid="uid://bfcyyblbhxmhl"
path="res://.godot/imported/steamdeck_trackpad_horizontal.svg-59190bd913cbc5efd8d01d04d275cb2b.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_trackpad_horizontal_outline.svg.import b/assets/images/gamepad/steamdeck/steamdeck_trackpad_horizontal_outline.svg.import
index bf55c4111..cf6ed002f 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_trackpad_horizontal_outline.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_trackpad_horizontal_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b5jt466sn03jo"
+uid="uid://bul2avxinhktc"
path="res://.godot/imported/steamdeck_trackpad_horizontal_outline.svg-4a558bfd480aac89183bac74deac9e66.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_trackpad_l.svg.import b/assets/images/gamepad/steamdeck/steamdeck_trackpad_l.svg.import
index 3c170d6ce..3aa4b46cb 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_trackpad_l.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_trackpad_l.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://fpsxow3w684w"
+uid="uid://bs0jtx81eplgt"
path="res://.godot/imported/steamdeck_trackpad_l.svg-0907662361c9e790d82b03f453102b0c.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_all.svg.import b/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_all.svg.import
index a3d49d1a9..86d5396db 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_all.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_all.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://d3ocywhdiyjvk"
+uid="uid://dvioogs1h44wj"
path="res://.godot/imported/steamdeck_trackpad_l_all.svg-5c9d7615db66a57fe276acd76abd3aca.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_all_outline.svg.import b/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_all_outline.svg.import
index 9fdd74bff..8997c81cb 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_all_outline.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_all_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://tq36f51n68ku"
+uid="uid://oak22878aalc"
path="res://.godot/imported/steamdeck_trackpad_l_all_outline.svg-fa23b59ea3fa8b7d2fd258f711d15996.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_down.svg.import b/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_down.svg.import
index bb5964e4e..5602f20a8 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_down.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_down.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dqgafsu3l3uj0"
+uid="uid://bb5ti5dmaalrw"
path="res://.godot/imported/steamdeck_trackpad_l_down.svg-fc1afbad1bc5f01ea0f6c3d3170cddc8.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_down_outline.svg.import b/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_down_outline.svg.import
index 5f33f1894..5fe4e4b2d 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_down_outline.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_down_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dnomrtfwget4x"
+uid="uid://cekvrmhd1ot3m"
path="res://.godot/imported/steamdeck_trackpad_l_down_outline.svg-f8787a9ea51ad5b764f77d08c9a4ce8e.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_horizontal.svg.import b/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_horizontal.svg.import
index 47af7dc06..29423c634 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_horizontal.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_horizontal.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://rlhy688f6ojc"
+uid="uid://dkv4ktx3l5dal"
path="res://.godot/imported/steamdeck_trackpad_l_horizontal.svg-31128938b6860937b2366f53391922a8.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_horizontal_outline.svg.import b/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_horizontal_outline.svg.import
index 889c841f9..bfb8f6981 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_horizontal_outline.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_horizontal_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cd4vbh0hotird"
+uid="uid://bs8hat4ofxowp"
path="res://.godot/imported/steamdeck_trackpad_l_horizontal_outline.svg-62fca701d78f63489fb4f3eaca573383.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_left.svg.import b/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_left.svg.import
index acbbb0c13..59ba29bfd 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_left.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_left.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://jh64ow81otuu"
+uid="uid://47w0743681wo"
path="res://.godot/imported/steamdeck_trackpad_l_left.svg-c103bb7a15626f83f476aa75c1b973d7.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_left_outline.svg.import b/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_left_outline.svg.import
index 8639dbce3..88ac15a49 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_left_outline.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_left_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://byp0vq1liutf"
+uid="uid://k0nanb3qcfi6"
path="res://.godot/imported/steamdeck_trackpad_l_left_outline.svg-f7b4cda7af1d8a43cf433c1fdc3b3625.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_outline.svg.import b/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_outline.svg.import
index 409091d5e..10e078131 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_outline.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://d3yledpl4vkjo"
+uid="uid://8klud0p6amw3"
path="res://.godot/imported/steamdeck_trackpad_l_outline.svg-276439bd5b946a262802792e6629b626.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_right.svg.import b/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_right.svg.import
index e77890669..ec0582d1f 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_right.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_right.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cp37an4l8wte6"
+uid="uid://c1we48r6l0yqi"
path="res://.godot/imported/steamdeck_trackpad_l_right.svg-51aeddf18637cd83e587dbd7bbf2496e.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_right_outline.svg.import b/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_right_outline.svg.import
index 35ce137af..fd9110898 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_right_outline.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_right_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bdjf1f6ki0mmq"
+uid="uid://dwidwmuandijw"
path="res://.godot/imported/steamdeck_trackpad_l_right_outline.svg-b98e27a5d160a3023524ac3d1ca91276.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_up.svg.import b/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_up.svg.import
index 075d286c6..617e730d6 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_up.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_up.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://clmhcfgwrj6gb"
+uid="uid://cjqx116cvounh"
path="res://.godot/imported/steamdeck_trackpad_l_up.svg-601b7f2d3d0b71266cd0064f44cfb41b.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_up_outline.svg.import b/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_up_outline.svg.import
index 3b16284f2..bb67f32af 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_up_outline.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_up_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cbynxgsakuer4"
+uid="uid://bqnq5ev80pwtv"
path="res://.godot/imported/steamdeck_trackpad_l_up_outline.svg-6bec7a04fef0bf31d167e9b6e1819bbd.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_vertical.svg.import b/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_vertical.svg.import
index ab40d0d84..92bc7bf51 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_vertical.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_vertical.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bj3gaowwpk7xm"
+uid="uid://bynex2dpngxsl"
path="res://.godot/imported/steamdeck_trackpad_l_vertical.svg-74de1926732e10e8508c87bc9cc26ee1.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_vertical_outline.svg.import b/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_vertical_outline.svg.import
index ad532df36..09bea1a20 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_vertical_outline.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_trackpad_l_vertical_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://lyecfnrnd6b7"
+uid="uid://cxu3sk0qiy004"
path="res://.godot/imported/steamdeck_trackpad_l_vertical_outline.svg-10cbc8bdb739fd0856a45c34603e86c8.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_trackpad_left.svg.import b/assets/images/gamepad/steamdeck/steamdeck_trackpad_left.svg.import
index 77db359fc..f8e5efc7e 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_trackpad_left.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_trackpad_left.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://06xriwqdq5t5"
+uid="uid://dtcbp5hqiltr0"
path="res://.godot/imported/steamdeck_trackpad_left.svg-ee90096cfd6aeb339994399b7a75b13a.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_trackpad_left_outline.svg.import b/assets/images/gamepad/steamdeck/steamdeck_trackpad_left_outline.svg.import
index 258e5186f..e2efcd055 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_trackpad_left_outline.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_trackpad_left_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://mqccljqtruyj"
+uid="uid://cpffkd800su26"
path="res://.godot/imported/steamdeck_trackpad_left_outline.svg-3ebe2d1c8cb8cae481de1f22b4b55892.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_trackpad_outline.svg.import b/assets/images/gamepad/steamdeck/steamdeck_trackpad_outline.svg.import
index 68855b7fc..ab6f11271 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_trackpad_outline.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_trackpad_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bu3cgxorfcnop"
+uid="uid://bvs22agcyremo"
path="res://.godot/imported/steamdeck_trackpad_outline.svg-d9c932ce678c6cdf03095e2dc2f8ac6f.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_trackpad_r.svg.import b/assets/images/gamepad/steamdeck/steamdeck_trackpad_r.svg.import
index 9c25f3b9b..8df90c6a8 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_trackpad_r.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_trackpad_r.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://da5ds5ps218cu"
+uid="uid://bwobw44drvuo"
path="res://.godot/imported/steamdeck_trackpad_r.svg-7ea5bddd757dde3d7093598e2dc87821.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_all.svg.import b/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_all.svg.import
index 29d89f3c8..18b5b9510 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_all.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_all.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b5smg46hvo3en"
+uid="uid://b006fo2wqcu8w"
path="res://.godot/imported/steamdeck_trackpad_r_all.svg-706cbed575120d7f67f1e77300afeda4.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_all_outline.svg.import b/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_all_outline.svg.import
index 5bebbc92e..158edcef5 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_all_outline.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_all_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://1b81jqa04fd8"
+uid="uid://b47l5gbfjbaf3"
path="res://.godot/imported/steamdeck_trackpad_r_all_outline.svg-157a71c4c4a8be87a50237337422c735.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_down.svg.import b/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_down.svg.import
index 32b7dad68..64ae5dc39 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_down.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_down.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://ue2g0egd4ph7"
+uid="uid://du6v2pbduxbau"
path="res://.godot/imported/steamdeck_trackpad_r_down.svg-005d41abe0baaefa300be710fad26b28.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_down_outline.svg.import b/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_down_outline.svg.import
index 93972d0bb..8fb3aaa6a 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_down_outline.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_down_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://d8tmauoecosv"
+uid="uid://bnuba0jvd384a"
path="res://.godot/imported/steamdeck_trackpad_r_down_outline.svg-10ef1daf7ecf5335f59f7f5cfdb0c450.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_horizontal.svg.import b/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_horizontal.svg.import
index a8bbab84c..8b7434dee 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_horizontal.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_horizontal.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bbsc1kwoxas20"
+uid="uid://bylxo8d1ky083"
path="res://.godot/imported/steamdeck_trackpad_r_horizontal.svg-bacb5d65043d055a8e762d3ea4f6691e.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_horizontal_outline.svg.import b/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_horizontal_outline.svg.import
index c63c6d8d7..0c9978727 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_horizontal_outline.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_horizontal_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dj184i0dohlwq"
+uid="uid://g6b6mtq6h12q"
path="res://.godot/imported/steamdeck_trackpad_r_horizontal_outline.svg-74d5afb9fdb692a5985770f9820a94ac.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_left.svg.import b/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_left.svg.import
index 473072d02..bc9afe3b3 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_left.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_left.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bvonexp8ilgdj"
+uid="uid://bh0xmnvxuqvsa"
path="res://.godot/imported/steamdeck_trackpad_r_left.svg-5f7013136716c28612dfd31391363091.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_left_outline.svg.import b/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_left_outline.svg.import
index ed0c75098..830ef2c6d 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_left_outline.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_left_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://ou5jo5c7nh1h"
+uid="uid://imitg6gbgbmb"
path="res://.godot/imported/steamdeck_trackpad_r_left_outline.svg-d839001e76ee62f176ad537746e5b070.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_outline.svg.import b/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_outline.svg.import
index d067c5185..5f82c1ce7 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_outline.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://c0ve1624rr4xp"
+uid="uid://bpk2bbvq7nc16"
path="res://.godot/imported/steamdeck_trackpad_r_outline.svg-a376b97064c661130d85b080c9226cc1.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_right.svg.import b/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_right.svg.import
index 56eeb81e5..565a9b52c 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_right.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_right.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cia6uq06g65yv"
+uid="uid://cfrvptfw4wgal"
path="res://.godot/imported/steamdeck_trackpad_r_right.svg-6f69f7ffaa9c7d08e204fda45afd632f.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_right_outline.svg.import b/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_right_outline.svg.import
index 8c656baa2..ae3bd7d57 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_right_outline.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_right_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://d0phlopeumfb7"
+uid="uid://be66sf5wpj2fs"
path="res://.godot/imported/steamdeck_trackpad_r_right_outline.svg-3383aeb43bb3567a77a98f4006e8d51c.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_up.svg.import b/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_up.svg.import
index a09d2bda1..d38367476 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_up.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_up.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://t5eugo5st8l7"
+uid="uid://dbof7iv20i3d1"
path="res://.godot/imported/steamdeck_trackpad_r_up.svg-8620dc7c0eb7b71921167e478bd6d2c8.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_up_outline.svg.import b/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_up_outline.svg.import
index 1b124a00b..a73ec909a 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_up_outline.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_up_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cvpfdo10uu6m4"
+uid="uid://c8o73nshepu6f"
path="res://.godot/imported/steamdeck_trackpad_r_up_outline.svg-851dc842ad2b2ca0cf2eff655c5dfd40.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_vertical.svg.import b/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_vertical.svg.import
index 1c52596f8..438fc612b 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_vertical.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_vertical.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dnk1kwbb21xq7"
+uid="uid://wv0f584p3hy3"
path="res://.godot/imported/steamdeck_trackpad_r_vertical.svg-3bf40a8215e02210b3404982fc423bd3.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_vertical_outline.svg.import b/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_vertical_outline.svg.import
index a8316dad5..dd83714f2 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_vertical_outline.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_trackpad_r_vertical_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://yru8t1ixe67j"
+uid="uid://5cfmuat6okme"
path="res://.godot/imported/steamdeck_trackpad_r_vertical_outline.svg-2a306bdb1e27d693a4a5eeb0f8a6fd0d.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_trackpad_right.svg.import b/assets/images/gamepad/steamdeck/steamdeck_trackpad_right.svg.import
index 3d7671e35..81f0f8581 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_trackpad_right.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_trackpad_right.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cbm4urp4onu2"
+uid="uid://nsy8kr7gweas"
path="res://.godot/imported/steamdeck_trackpad_right.svg-928419d42824ab4f8e5452b1cc0a52be.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_trackpad_right_outline.svg.import b/assets/images/gamepad/steamdeck/steamdeck_trackpad_right_outline.svg.import
index 4874be756..aefa9b4a0 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_trackpad_right_outline.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_trackpad_right_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://3lvu2n0ius6s"
+uid="uid://bsfmfl1kbt3d6"
path="res://.godot/imported/steamdeck_trackpad_right_outline.svg-90513269646d5dd9fd80b8b9ff8d6d54.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_trackpad_up.svg.import b/assets/images/gamepad/steamdeck/steamdeck_trackpad_up.svg.import
index 8752cba54..b96baa715 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_trackpad_up.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_trackpad_up.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://c816h08164py6"
+uid="uid://di52a0h4esc6e"
path="res://.godot/imported/steamdeck_trackpad_up.svg-7115dbc5330efcd07dcd2866173bf2dc.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_trackpad_up_outline.svg.import b/assets/images/gamepad/steamdeck/steamdeck_trackpad_up_outline.svg.import
index 4328fd354..f9964f10c 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_trackpad_up_outline.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_trackpad_up_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://yy1fphtrtw1e"
+uid="uid://imjfaos3vgf"
path="res://.godot/imported/steamdeck_trackpad_up_outline.svg-bc698b1451d1d003a71b103a61a37755.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_trackpad_vertical.svg.import b/assets/images/gamepad/steamdeck/steamdeck_trackpad_vertical.svg.import
index ce4841cbc..327348765 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_trackpad_vertical.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_trackpad_vertical.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b4m3wd5cjm40w"
+uid="uid://y332cxmoaws0"
path="res://.godot/imported/steamdeck_trackpad_vertical.svg-c2e0be831bd618002d2420a69e5906bd.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/steamdeck/steamdeck_trackpad_vertical_outline.svg.import b/assets/images/gamepad/steamdeck/steamdeck_trackpad_vertical_outline.svg.import
index 9cfc90c36..802bc2382 100644
--- a/assets/images/gamepad/steamdeck/steamdeck_trackpad_vertical_outline.svg.import
+++ b/assets/images/gamepad/steamdeck/steamdeck_trackpad_vertical_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bgb4g5i1fa23n"
+uid="uid://caq1dit7xl8ha"
path="res://.godot/imported/steamdeck_trackpad_vertical_outline.svg-2ddd6f3da1ed8d8260b0cd949d96cc9e.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/controller_switch.svg.import b/assets/images/gamepad/switch/controller_switch.svg.import
index 5b6735bc7..aa05f0749 100644
--- a/assets/images/gamepad/switch/controller_switch.svg.import
+++ b/assets/images/gamepad/switch/controller_switch.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://sqnr774q3mvp"
+uid="uid://cxugsmqkyjfgb"
path="res://.godot/imported/controller_switch.svg-88690e3c69c3169fba3e8459c87a9d2c.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/controller_switch_joycon_down.svg.import b/assets/images/gamepad/switch/controller_switch_joycon_down.svg.import
index 9b82f90a9..5e6fa768b 100644
--- a/assets/images/gamepad/switch/controller_switch_joycon_down.svg.import
+++ b/assets/images/gamepad/switch/controller_switch_joycon_down.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://gkjuhpveilje"
+uid="uid://b6jmf3g838xag"
path="res://.godot/imported/controller_switch_joycon_down.svg-d9b8276ac1c082c46f2382f1bbcd0a3b.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/controller_switch_joycon_up.svg.import b/assets/images/gamepad/switch/controller_switch_joycon_up.svg.import
index 167341853..1dc48d0fb 100644
--- a/assets/images/gamepad/switch/controller_switch_joycon_up.svg.import
+++ b/assets/images/gamepad/switch/controller_switch_joycon_up.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cxa840aaxrl64"
+uid="uid://v1fjunjxpvm4"
path="res://.godot/imported/controller_switch_joycon_up.svg-fbfc4472b0e57eba29c932d1b6480f3f.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/controller_switch_pro.svg.import b/assets/images/gamepad/switch/controller_switch_pro.svg.import
index 464ddf996..b8c4bee50 100644
--- a/assets/images/gamepad/switch/controller_switch_pro.svg.import
+++ b/assets/images/gamepad/switch/controller_switch_pro.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bcngxgq2hojum"
+uid="uid://hm8ubklvtb4u"
path="res://.godot/imported/controller_switch_pro.svg-e85f378a45cfeea7a4374fd18837c7ec.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_button_a.svg.import b/assets/images/gamepad/switch/switch_button_a.svg.import
index 2fc98f0ef..6004903cb 100644
--- a/assets/images/gamepad/switch/switch_button_a.svg.import
+++ b/assets/images/gamepad/switch/switch_button_a.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dec8wg71j58h1"
+uid="uid://dsnnac0xk0tfl"
path="res://.godot/imported/switch_button_a.svg-b7c2fc428a8939039f1db6d1de5e558b.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_button_a_outline.svg.import b/assets/images/gamepad/switch/switch_button_a_outline.svg.import
index f7fbbfce6..dcbdf91b2 100644
--- a/assets/images/gamepad/switch/switch_button_a_outline.svg.import
+++ b/assets/images/gamepad/switch/switch_button_a_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://ba7ddjqpe6c58"
+uid="uid://d133qfc5ei021"
path="res://.godot/imported/switch_button_a_outline.svg-9270fa0490025f245f1104632cf36de6.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_button_b.svg.import b/assets/images/gamepad/switch/switch_button_b.svg.import
index c7ba08375..6f2682b7f 100644
--- a/assets/images/gamepad/switch/switch_button_b.svg.import
+++ b/assets/images/gamepad/switch/switch_button_b.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://8o3g4dcunk87"
+uid="uid://b21ssea6yir56"
path="res://.godot/imported/switch_button_b.svg-fa79e7674743feebb9be572c435c7eea.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_button_b_outline.svg.import b/assets/images/gamepad/switch/switch_button_b_outline.svg.import
index 5f777aadf..769abf721 100644
--- a/assets/images/gamepad/switch/switch_button_b_outline.svg.import
+++ b/assets/images/gamepad/switch/switch_button_b_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b3f4wxhhr68ej"
+uid="uid://bebyeav5jc5vo"
path="res://.godot/imported/switch_button_b_outline.svg-d4f745a5cd8a943271aae57a35922e10.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_button_home.svg.import b/assets/images/gamepad/switch/switch_button_home.svg.import
index 5e0b15ae8..a6064eb91 100644
--- a/assets/images/gamepad/switch/switch_button_home.svg.import
+++ b/assets/images/gamepad/switch/switch_button_home.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b3v8gbuc0knsr"
+uid="uid://dicj4tpxknqai"
path="res://.godot/imported/switch_button_home.svg-c31466b79eec07495096085bbf7f1770.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_button_home_outline.svg.import b/assets/images/gamepad/switch/switch_button_home_outline.svg.import
index 4d00b32b5..277656d8d 100644
--- a/assets/images/gamepad/switch/switch_button_home_outline.svg.import
+++ b/assets/images/gamepad/switch/switch_button_home_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://chx626dpbwwa3"
+uid="uid://bwmxkbqp3i083"
path="res://.godot/imported/switch_button_home_outline.svg-75d8c08d81ca6bb46efa60945414e065.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_button_l.svg.import b/assets/images/gamepad/switch/switch_button_l.svg.import
index 0bd5bb203..18e0c4956 100644
--- a/assets/images/gamepad/switch/switch_button_l.svg.import
+++ b/assets/images/gamepad/switch/switch_button_l.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b57k4ko26lm6"
+uid="uid://d2ho4b7w2mdlb"
path="res://.godot/imported/switch_button_l.svg-427a83ab83f20c13a321edf8de67a6dc.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_button_l_outline.svg.import b/assets/images/gamepad/switch/switch_button_l_outline.svg.import
index f2fe10a54..9afe36dcd 100644
--- a/assets/images/gamepad/switch/switch_button_l_outline.svg.import
+++ b/assets/images/gamepad/switch/switch_button_l_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://xr3r0gaebxa3"
+uid="uid://b3lpl1fc7lsfs"
path="res://.godot/imported/switch_button_l_outline.svg-6c6c4b5a8f1430b1e4484ec72bdb7bff.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_button_minus.svg.import b/assets/images/gamepad/switch/switch_button_minus.svg.import
index d0d01764a..f52fc27ac 100644
--- a/assets/images/gamepad/switch/switch_button_minus.svg.import
+++ b/assets/images/gamepad/switch/switch_button_minus.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://crl6hqey1xqfd"
+uid="uid://f3dabljd057e"
path="res://.godot/imported/switch_button_minus.svg-71ba1bfca6601620e6dba96b0faae9e9.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_button_minus_outline.svg.import b/assets/images/gamepad/switch/switch_button_minus_outline.svg.import
index 1f2ef4fa2..2336a2811 100644
--- a/assets/images/gamepad/switch/switch_button_minus_outline.svg.import
+++ b/assets/images/gamepad/switch/switch_button_minus_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://jcbnrbsvbs64"
+uid="uid://xercor0xim78"
path="res://.godot/imported/switch_button_minus_outline.svg-28fb1c7663dc11a8b2bcd6b23d517749.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_button_plus.svg.import b/assets/images/gamepad/switch/switch_button_plus.svg.import
index 13060b6bd..6646c55b3 100644
--- a/assets/images/gamepad/switch/switch_button_plus.svg.import
+++ b/assets/images/gamepad/switch/switch_button_plus.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dugmdwvujsrk4"
+uid="uid://rgpis0qqwyn3"
path="res://.godot/imported/switch_button_plus.svg-17c97b6ab5721a68d2bdaa8c61e9ec2a.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_button_plus_outline.svg.import b/assets/images/gamepad/switch/switch_button_plus_outline.svg.import
index fec41fa41..34dcdb6fa 100644
--- a/assets/images/gamepad/switch/switch_button_plus_outline.svg.import
+++ b/assets/images/gamepad/switch/switch_button_plus_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b7clxv4skg0wl"
+uid="uid://dg01m1prbcqj5"
path="res://.godot/imported/switch_button_plus_outline.svg-4fdda2a4e04568c0ce4794e749ae7ee0.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_button_r.svg.import b/assets/images/gamepad/switch/switch_button_r.svg.import
index 10311a82d..7939ebb17 100644
--- a/assets/images/gamepad/switch/switch_button_r.svg.import
+++ b/assets/images/gamepad/switch/switch_button_r.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bu2naacuis8k8"
+uid="uid://dh8gskvlf1y4n"
path="res://.godot/imported/switch_button_r.svg-0a9b6ce35f686f9403a26351249e46dd.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_button_r_outline.svg.import b/assets/images/gamepad/switch/switch_button_r_outline.svg.import
index b4e37f85a..e2c081bb0 100644
--- a/assets/images/gamepad/switch/switch_button_r_outline.svg.import
+++ b/assets/images/gamepad/switch/switch_button_r_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://pwvdheaes81a"
+uid="uid://d3p3bsnovkeos"
path="res://.godot/imported/switch_button_r_outline.svg-d44b1c9d6654d18d83905c29bea95452.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_button_sl.svg.import b/assets/images/gamepad/switch/switch_button_sl.svg.import
index 9b2cf09e1..95da2836b 100644
--- a/assets/images/gamepad/switch/switch_button_sl.svg.import
+++ b/assets/images/gamepad/switch/switch_button_sl.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bqp0l3x30ojqa"
+uid="uid://cej023qrdtqg5"
path="res://.godot/imported/switch_button_sl.svg-effb40acd820d539db9ac77ed3dd57ae.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_button_sl_outline.svg.import b/assets/images/gamepad/switch/switch_button_sl_outline.svg.import
index 89030eeb7..de59ebf5e 100644
--- a/assets/images/gamepad/switch/switch_button_sl_outline.svg.import
+++ b/assets/images/gamepad/switch/switch_button_sl_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dj1gfqdc2v8c2"
+uid="uid://cet8fp0burrjp"
path="res://.godot/imported/switch_button_sl_outline.svg-2bfa80c9138bfa659d07a29bae74724d.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_button_sr.svg.import b/assets/images/gamepad/switch/switch_button_sr.svg.import
index b358ec4dc..8c166e47b 100644
--- a/assets/images/gamepad/switch/switch_button_sr.svg.import
+++ b/assets/images/gamepad/switch/switch_button_sr.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dikclv36p7ai0"
+uid="uid://d366wyqoknqtc"
path="res://.godot/imported/switch_button_sr.svg-d87714c326169e4347c9ecb0db0c3030.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_button_sr_outline.svg.import b/assets/images/gamepad/switch/switch_button_sr_outline.svg.import
index fd9f5f60b..3895faaa4 100644
--- a/assets/images/gamepad/switch/switch_button_sr_outline.svg.import
+++ b/assets/images/gamepad/switch/switch_button_sr_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://c0f2ufrp4fivj"
+uid="uid://qf5oi850m8al"
path="res://.godot/imported/switch_button_sr_outline.svg-62a0f3c5b8f7b594a05933bdc01747d8.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_button_sync.svg.import b/assets/images/gamepad/switch/switch_button_sync.svg.import
index 65bc4428a..e57c7d717 100644
--- a/assets/images/gamepad/switch/switch_button_sync.svg.import
+++ b/assets/images/gamepad/switch/switch_button_sync.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://baeygxurw7dn1"
+uid="uid://brwy28sjw2pe8"
path="res://.godot/imported/switch_button_sync.svg-3a6d3a3eb26b161d0dec26aa8eccad58.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_button_sync_outline.svg.import b/assets/images/gamepad/switch/switch_button_sync_outline.svg.import
index 7809983fc..1dfd1d050 100644
--- a/assets/images/gamepad/switch/switch_button_sync_outline.svg.import
+++ b/assets/images/gamepad/switch/switch_button_sync_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://ccwn7n7ycbw80"
+uid="uid://dby6hm0625wja"
path="res://.godot/imported/switch_button_sync_outline.svg-e44753a7ccc2de0a3a6dd19c147ed8b4.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_button_x.svg.import b/assets/images/gamepad/switch/switch_button_x.svg.import
index 1a46b4c8e..36535f9e5 100644
--- a/assets/images/gamepad/switch/switch_button_x.svg.import
+++ b/assets/images/gamepad/switch/switch_button_x.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b6wkct2qwo0ul"
+uid="uid://d0nkpy8tk3f28"
path="res://.godot/imported/switch_button_x.svg-ac793655b62238b26cad4619513c2308.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_button_x_outline.svg.import b/assets/images/gamepad/switch/switch_button_x_outline.svg.import
index ff383a3fd..9cb438f02 100644
--- a/assets/images/gamepad/switch/switch_button_x_outline.svg.import
+++ b/assets/images/gamepad/switch/switch_button_x_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dwy6l0iflgddw"
+uid="uid://bnag8d0gpab8s"
path="res://.godot/imported/switch_button_x_outline.svg-775b19ef72714d64d717d6c05a699f6e.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_button_y.svg.import b/assets/images/gamepad/switch/switch_button_y.svg.import
index 6cece60b4..26e302b78 100644
--- a/assets/images/gamepad/switch/switch_button_y.svg.import
+++ b/assets/images/gamepad/switch/switch_button_y.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://djvoe5nud1i0w"
+uid="uid://ckwf0ko1ch08t"
path="res://.godot/imported/switch_button_y.svg-a9757befa8d96e5aafd17afe3e36b6e3.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_button_y_outline.svg.import b/assets/images/gamepad/switch/switch_button_y_outline.svg.import
index d5bd519f8..be4c8be87 100644
--- a/assets/images/gamepad/switch/switch_button_y_outline.svg.import
+++ b/assets/images/gamepad/switch/switch_button_y_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://tcuixxkr0285"
+uid="uid://bqb647h8tg10v"
path="res://.godot/imported/switch_button_y_outline.svg-aa05c1b6d91ae1386ec13b09f9662066.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_button_zl.svg.import b/assets/images/gamepad/switch/switch_button_zl.svg.import
index 93dcddf24..e01c2d25b 100644
--- a/assets/images/gamepad/switch/switch_button_zl.svg.import
+++ b/assets/images/gamepad/switch/switch_button_zl.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dsa8m2vfvtx0q"
+uid="uid://ysw3f4s0wckl"
path="res://.godot/imported/switch_button_zl.svg-4a5c362a583098d738445dedaa2972b3.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_button_zl_outline.svg.import b/assets/images/gamepad/switch/switch_button_zl_outline.svg.import
index 3a1c5d94c..6c5802827 100644
--- a/assets/images/gamepad/switch/switch_button_zl_outline.svg.import
+++ b/assets/images/gamepad/switch/switch_button_zl_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://q76rrwbter2d"
+uid="uid://uac20no0b2dj"
path="res://.godot/imported/switch_button_zl_outline.svg-f476743e054446a59fdc9d355cfeb3a4.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_button_zr.svg.import b/assets/images/gamepad/switch/switch_button_zr.svg.import
index 968031f11..a6dd5e680 100644
--- a/assets/images/gamepad/switch/switch_button_zr.svg.import
+++ b/assets/images/gamepad/switch/switch_button_zr.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cutjyk72c0d1"
+uid="uid://cwkd4oyqs445d"
path="res://.godot/imported/switch_button_zr.svg-9be3343c2bc958e2c1b734bd56b7a326.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_button_zr_outline.svg.import b/assets/images/gamepad/switch/switch_button_zr_outline.svg.import
index d28c9d465..aa2ca082d 100644
--- a/assets/images/gamepad/switch/switch_button_zr_outline.svg.import
+++ b/assets/images/gamepad/switch/switch_button_zr_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://c5e4j4mufbkfj"
+uid="uid://1p3ejwpd1ia4"
path="res://.godot/imported/switch_button_zr_outline.svg-47403d21b19d1178a4d74d02463a90b2.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_buttons.svg.import b/assets/images/gamepad/switch/switch_buttons.svg.import
index 0a4eecfdc..928b3a978 100644
--- a/assets/images/gamepad/switch/switch_buttons.svg.import
+++ b/assets/images/gamepad/switch/switch_buttons.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b1qcl62witrrt"
+uid="uid://bvjmsnstaoq2v"
path="res://.godot/imported/switch_buttons.svg-3ed28df4fd427a3a0a7cfa0879cec9d3.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_buttons_all.svg.import b/assets/images/gamepad/switch/switch_buttons_all.svg.import
index c4be38648..ab08851fd 100644
--- a/assets/images/gamepad/switch/switch_buttons_all.svg.import
+++ b/assets/images/gamepad/switch/switch_buttons_all.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bsjoo254uaytt"
+uid="uid://cub78cesb05r7"
path="res://.godot/imported/switch_buttons_all.svg-e88654adf145effe30bbaa1654069b2c.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_buttons_down.svg.import b/assets/images/gamepad/switch/switch_buttons_down.svg.import
index 315e6e091..fb6665ee7 100644
--- a/assets/images/gamepad/switch/switch_buttons_down.svg.import
+++ b/assets/images/gamepad/switch/switch_buttons_down.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://c3hr6ecnhdtg2"
+uid="uid://cdvcck1mbmt87"
path="res://.godot/imported/switch_buttons_down.svg-13fd102ec320f9f6f249aab7e628cade.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_buttons_down_outline.svg.import b/assets/images/gamepad/switch/switch_buttons_down_outline.svg.import
index bfce3b080..b5c5a2adc 100644
--- a/assets/images/gamepad/switch/switch_buttons_down_outline.svg.import
+++ b/assets/images/gamepad/switch/switch_buttons_down_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bmqlk4rxwclr3"
+uid="uid://q0u4lji8k55t"
path="res://.godot/imported/switch_buttons_down_outline.svg-e818c6999a9fc5acdbbb4ac2bada593c.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_buttons_horizontal.svg.import b/assets/images/gamepad/switch/switch_buttons_horizontal.svg.import
index 76489f670..61a1df71f 100644
--- a/assets/images/gamepad/switch/switch_buttons_horizontal.svg.import
+++ b/assets/images/gamepad/switch/switch_buttons_horizontal.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cnfktwcoxpqrs"
+uid="uid://bji4c5ie7r81i"
path="res://.godot/imported/switch_buttons_horizontal.svg-665a43c7d2f510df0a2590e40e8ba971.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_buttons_horizontal_outline.svg.import b/assets/images/gamepad/switch/switch_buttons_horizontal_outline.svg.import
index 5e8f82b2d..15282f696 100644
--- a/assets/images/gamepad/switch/switch_buttons_horizontal_outline.svg.import
+++ b/assets/images/gamepad/switch/switch_buttons_horizontal_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://beyhw2dnujq8p"
+uid="uid://ceu3kuwhc3wtm"
path="res://.godot/imported/switch_buttons_horizontal_outline.svg-f347387cf151e0066db42734c0bf6a9c.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_buttons_left.svg.import b/assets/images/gamepad/switch/switch_buttons_left.svg.import
index 47f8fc582..df94d542d 100644
--- a/assets/images/gamepad/switch/switch_buttons_left.svg.import
+++ b/assets/images/gamepad/switch/switch_buttons_left.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dykfvnb0v687h"
+uid="uid://b4j53xuo8rosw"
path="res://.godot/imported/switch_buttons_left.svg-c1b18e363ee56fbfc413d2c13c5c95bc.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_buttons_left_outline.svg.import b/assets/images/gamepad/switch/switch_buttons_left_outline.svg.import
index 6af83fdf5..4ae206407 100644
--- a/assets/images/gamepad/switch/switch_buttons_left_outline.svg.import
+++ b/assets/images/gamepad/switch/switch_buttons_left_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://74j5mtle3kdm"
+uid="uid://rgk8j0hf5vlr"
path="res://.godot/imported/switch_buttons_left_outline.svg-118459ac3b923ecca44523ae9fa70567.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_buttons_none.svg.import b/assets/images/gamepad/switch/switch_buttons_none.svg.import
index c3d772836..3eedf2c2a 100644
--- a/assets/images/gamepad/switch/switch_buttons_none.svg.import
+++ b/assets/images/gamepad/switch/switch_buttons_none.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cb2gnj26b21xw"
+uid="uid://dnsiav286rdds"
path="res://.godot/imported/switch_buttons_none.svg-6a2811f7e8932df09cbe1a635cb9f599.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_buttons_right.svg.import b/assets/images/gamepad/switch/switch_buttons_right.svg.import
index da82bff3b..36cf2075d 100644
--- a/assets/images/gamepad/switch/switch_buttons_right.svg.import
+++ b/assets/images/gamepad/switch/switch_buttons_right.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bcthc11uwae6n"
+uid="uid://bnbk3lkeaqwfa"
path="res://.godot/imported/switch_buttons_right.svg-77b67acfd767e572f57d2b0a612e0c6e.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_buttons_right_outline.svg.import b/assets/images/gamepad/switch/switch_buttons_right_outline.svg.import
index b35c39c77..0941ad0f0 100644
--- a/assets/images/gamepad/switch/switch_buttons_right_outline.svg.import
+++ b/assets/images/gamepad/switch/switch_buttons_right_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://daeysxerxps5w"
+uid="uid://bpk81q4kpeaoo"
path="res://.godot/imported/switch_buttons_right_outline.svg-3a02639270ce574170d60f749bb8f6b3.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_buttons_up.svg.import b/assets/images/gamepad/switch/switch_buttons_up.svg.import
index 0ec56706f..689170ba0 100644
--- a/assets/images/gamepad/switch/switch_buttons_up.svg.import
+++ b/assets/images/gamepad/switch/switch_buttons_up.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bo07ay1vxneo1"
+uid="uid://ducpt6w14ol4i"
path="res://.godot/imported/switch_buttons_up.svg-83a91b61f01d7a98db5367af6fde26bb.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_buttons_up_outline.svg.import b/assets/images/gamepad/switch/switch_buttons_up_outline.svg.import
index 03f7f6a01..a2d7a6744 100644
--- a/assets/images/gamepad/switch/switch_buttons_up_outline.svg.import
+++ b/assets/images/gamepad/switch/switch_buttons_up_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://fgojvl2uagek"
+uid="uid://d0xpybdv7ghc0"
path="res://.godot/imported/switch_buttons_up_outline.svg-2c6a706edc84e816c816a328500bd9d4.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_buttons_vertical.svg.import b/assets/images/gamepad/switch/switch_buttons_vertical.svg.import
index 0af48932e..ce74a21ee 100644
--- a/assets/images/gamepad/switch/switch_buttons_vertical.svg.import
+++ b/assets/images/gamepad/switch/switch_buttons_vertical.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bhk3nkfw0wcf5"
+uid="uid://bdaj6q5kxfki6"
path="res://.godot/imported/switch_buttons_vertical.svg-116cdb0a1a7091a1ff6acf55b63c188a.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_buttons_vertical_outline.svg.import b/assets/images/gamepad/switch/switch_buttons_vertical_outline.svg.import
index 541c2d916..12a69482d 100644
--- a/assets/images/gamepad/switch/switch_buttons_vertical_outline.svg.import
+++ b/assets/images/gamepad/switch/switch_buttons_vertical_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://c68sl1ds8mwif"
+uid="uid://tocbmfxy0u7m"
path="res://.godot/imported/switch_buttons_vertical_outline.svg-68d6627f06f8dd0623c33edcb97f55c5.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_down.svg.import b/assets/images/gamepad/switch/switch_down.svg.import
index 1caadb71a..22b4b8930 100644
--- a/assets/images/gamepad/switch/switch_down.svg.import
+++ b/assets/images/gamepad/switch/switch_down.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://fvoo46vkt8b7"
+uid="uid://c3ub75gme530f"
path="res://.godot/imported/switch_down.svg-61d08bf369236097d0f22cce525a5c38.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_down_outline.svg.import b/assets/images/gamepad/switch/switch_down_outline.svg.import
index cf8b7aa18..6aa80defd 100644
--- a/assets/images/gamepad/switch/switch_down_outline.svg.import
+++ b/assets/images/gamepad/switch/switch_down_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://r0ibcb2juk06"
+uid="uid://cw03pa7jrwxgj"
path="res://.godot/imported/switch_down_outline.svg-fbcfc8cec1d6a38af097d77261126689.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_dpad.svg.import b/assets/images/gamepad/switch/switch_dpad.svg.import
index befcfdf9e..e3c3404eb 100644
--- a/assets/images/gamepad/switch/switch_dpad.svg.import
+++ b/assets/images/gamepad/switch/switch_dpad.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://jv2vbh18muy8"
+uid="uid://b735i56yjhict"
path="res://.godot/imported/switch_dpad.svg-7807cb4ee6e43bb5229c8adeea45711a.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_dpad_all.svg.import b/assets/images/gamepad/switch/switch_dpad_all.svg.import
index c7cbf3bb9..0a481b0c5 100644
--- a/assets/images/gamepad/switch/switch_dpad_all.svg.import
+++ b/assets/images/gamepad/switch/switch_dpad_all.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://c5s007gtnials"
+uid="uid://bjvnio2bp1fre"
path="res://.godot/imported/switch_dpad_all.svg-c76aff9dbb1cd187d2157a2e8b58e2cb.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_dpad_down.svg.import b/assets/images/gamepad/switch/switch_dpad_down.svg.import
index 724288069..563e95301 100644
--- a/assets/images/gamepad/switch/switch_dpad_down.svg.import
+++ b/assets/images/gamepad/switch/switch_dpad_down.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://beb058tm84w5j"
+uid="uid://drfroynux1b3f"
path="res://.godot/imported/switch_dpad_down.svg-0ef2179131eb4be2a0e4adebac4ac50c.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_dpad_down_outline.svg.import b/assets/images/gamepad/switch/switch_dpad_down_outline.svg.import
index 4c5fd8e8b..c99c097fd 100644
--- a/assets/images/gamepad/switch/switch_dpad_down_outline.svg.import
+++ b/assets/images/gamepad/switch/switch_dpad_down_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://47hflntjho5b"
+uid="uid://h6ejds5wp0dh"
path="res://.godot/imported/switch_dpad_down_outline.svg-10d37f00d3450563ee74f2f94bf36e59.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_dpad_horizontal.svg.import b/assets/images/gamepad/switch/switch_dpad_horizontal.svg.import
index 1bd361249..7cee29f10 100644
--- a/assets/images/gamepad/switch/switch_dpad_horizontal.svg.import
+++ b/assets/images/gamepad/switch/switch_dpad_horizontal.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bef43efnn06xj"
+uid="uid://4ggtvi2mmku4"
path="res://.godot/imported/switch_dpad_horizontal.svg-fcc9456c9b31a5069934e1a43a8c131e.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_dpad_horizontal_outline.svg.import b/assets/images/gamepad/switch/switch_dpad_horizontal_outline.svg.import
index aba5ad75f..842ac1ce2 100644
--- a/assets/images/gamepad/switch/switch_dpad_horizontal_outline.svg.import
+++ b/assets/images/gamepad/switch/switch_dpad_horizontal_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dywek0kaad7v5"
+uid="uid://ciny67jr2mun7"
path="res://.godot/imported/switch_dpad_horizontal_outline.svg-96d5ee9475602a88b92a8801639b1fe3.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_dpad_left.svg.import b/assets/images/gamepad/switch/switch_dpad_left.svg.import
index 6184c2f0a..11cb5f796 100644
--- a/assets/images/gamepad/switch/switch_dpad_left.svg.import
+++ b/assets/images/gamepad/switch/switch_dpad_left.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dnp6tc41r8xi3"
+uid="uid://e3db7ixs8tjk"
path="res://.godot/imported/switch_dpad_left.svg-05c896c13318854a72359da288ae2bb8.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_dpad_left_outline.svg.import b/assets/images/gamepad/switch/switch_dpad_left_outline.svg.import
index 21c0e248d..545d6d47f 100644
--- a/assets/images/gamepad/switch/switch_dpad_left_outline.svg.import
+++ b/assets/images/gamepad/switch/switch_dpad_left_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://csa323ms64r2f"
+uid="uid://b3qhsmna1ha82"
path="res://.godot/imported/switch_dpad_left_outline.svg-70e11ee38114bb00d2190752646e1749.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_dpad_none.svg.import b/assets/images/gamepad/switch/switch_dpad_none.svg.import
index c395314e3..b2c4f40aa 100644
--- a/assets/images/gamepad/switch/switch_dpad_none.svg.import
+++ b/assets/images/gamepad/switch/switch_dpad_none.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://24ehq8ht56tj"
+uid="uid://b7p4n2y8qaedr"
path="res://.godot/imported/switch_dpad_none.svg-f9665f20d992e21ae6b38f27360f2832.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_dpad_right.svg.import b/assets/images/gamepad/switch/switch_dpad_right.svg.import
index 15fabb6d0..f4e9472e8 100644
--- a/assets/images/gamepad/switch/switch_dpad_right.svg.import
+++ b/assets/images/gamepad/switch/switch_dpad_right.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://u7ity54x4vx3"
+uid="uid://vdro02bqhoxn"
path="res://.godot/imported/switch_dpad_right.svg-4cd732b19a61281fb7fe387ab4572bf2.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_dpad_right_outline.svg.import b/assets/images/gamepad/switch/switch_dpad_right_outline.svg.import
index 34e9a945b..126c2af6c 100644
--- a/assets/images/gamepad/switch/switch_dpad_right_outline.svg.import
+++ b/assets/images/gamepad/switch/switch_dpad_right_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bqj684mnvtudu"
+uid="uid://cpkc6kydivw6u"
path="res://.godot/imported/switch_dpad_right_outline.svg-bde5b57e68848cbbebf47fbe2c7bdd9f.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_dpad_up.svg.import b/assets/images/gamepad/switch/switch_dpad_up.svg.import
index 5a4f3281a..34fd75ace 100644
--- a/assets/images/gamepad/switch/switch_dpad_up.svg.import
+++ b/assets/images/gamepad/switch/switch_dpad_up.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bi8viiuisfuxh"
+uid="uid://hwsqjx3falhf"
path="res://.godot/imported/switch_dpad_up.svg-954d4772f896299df4ab2a8a9b7f736d.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_dpad_up_outline.svg.import b/assets/images/gamepad/switch/switch_dpad_up_outline.svg.import
index e0313033b..7470c9bca 100644
--- a/assets/images/gamepad/switch/switch_dpad_up_outline.svg.import
+++ b/assets/images/gamepad/switch/switch_dpad_up_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://qblns8wu6gho"
+uid="uid://b821cjw2446qb"
path="res://.godot/imported/switch_dpad_up_outline.svg-7301585ac4bfce54f037d97a85bc5987.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_dpad_vertical.svg.import b/assets/images/gamepad/switch/switch_dpad_vertical.svg.import
index 59afd28ac..145846bc9 100644
--- a/assets/images/gamepad/switch/switch_dpad_vertical.svg.import
+++ b/assets/images/gamepad/switch/switch_dpad_vertical.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://iafkrydlew02"
+uid="uid://c8br7hyx2d3b4"
path="res://.godot/imported/switch_dpad_vertical.svg-dad4d987caf73c3e0cf76970514a9013.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_dpad_vertical_outline.svg.import b/assets/images/gamepad/switch/switch_dpad_vertical_outline.svg.import
index 7fde8cc7d..235a26ee5 100644
--- a/assets/images/gamepad/switch/switch_dpad_vertical_outline.svg.import
+++ b/assets/images/gamepad/switch/switch_dpad_vertical_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b20xc4gi43jml"
+uid="uid://8mchw4pq6eqj"
path="res://.godot/imported/switch_dpad_vertical_outline.svg-275370e91928314bb10aae9037162cf8.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_joycon.svg.import b/assets/images/gamepad/switch/switch_joycon.svg.import
index 6bcdae595..406c1d2e4 100644
--- a/assets/images/gamepad/switch/switch_joycon.svg.import
+++ b/assets/images/gamepad/switch/switch_joycon.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://wjwxqmerud6"
+uid="uid://do7ujgwkwb5vj"
path="res://.godot/imported/switch_joycon.svg-99630983d8d21523e280793a0ba42727.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_joycon_left.svg.import b/assets/images/gamepad/switch/switch_joycon_left.svg.import
index 6d968690a..3fa700beb 100644
--- a/assets/images/gamepad/switch/switch_joycon_left.svg.import
+++ b/assets/images/gamepad/switch/switch_joycon_left.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://c08u1m8o4kswm"
+uid="uid://bnfjymekps4r4"
path="res://.godot/imported/switch_joycon_left.svg-94f983c6b9b9f9da0a1e76f4f73cf558.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_joycon_left_diagonal.svg.import b/assets/images/gamepad/switch/switch_joycon_left_diagonal.svg.import
index eeea8a66b..ec478a744 100644
--- a/assets/images/gamepad/switch/switch_joycon_left_diagonal.svg.import
+++ b/assets/images/gamepad/switch/switch_joycon_left_diagonal.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://ddkwutbwswgtg"
+uid="uid://be2l53k0ry6tp"
path="res://.godot/imported/switch_joycon_left_diagonal.svg-21f51c8d27047fb130b970c22ee818c9.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_joycon_left_diagonal_outline.svg.import b/assets/images/gamepad/switch/switch_joycon_left_diagonal_outline.svg.import
index 745436526..35d7251b8 100644
--- a/assets/images/gamepad/switch/switch_joycon_left_diagonal_outline.svg.import
+++ b/assets/images/gamepad/switch/switch_joycon_left_diagonal_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://da2m56sqfbnt7"
+uid="uid://bkxj6kxkou5gy"
path="res://.godot/imported/switch_joycon_left_diagonal_outline.svg-d789357e25c9c1e6b98f3df559b01824.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_joycon_left_horizontal.svg.import b/assets/images/gamepad/switch/switch_joycon_left_horizontal.svg.import
index 02df16a86..9adc06e63 100644
--- a/assets/images/gamepad/switch/switch_joycon_left_horizontal.svg.import
+++ b/assets/images/gamepad/switch/switch_joycon_left_horizontal.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://becf7dkmrt720"
+uid="uid://c4gr80dvc4xc"
path="res://.godot/imported/switch_joycon_left_horizontal.svg-706712efeeb38e67a4b0d2fc321fabf0.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_joycon_left_horizontal_outline.svg.import b/assets/images/gamepad/switch/switch_joycon_left_horizontal_outline.svg.import
index 299430806..e88036d2f 100644
--- a/assets/images/gamepad/switch/switch_joycon_left_horizontal_outline.svg.import
+++ b/assets/images/gamepad/switch/switch_joycon_left_horizontal_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bm4ltpk3tysjp"
+uid="uid://bdgwitxguooyb"
path="res://.godot/imported/switch_joycon_left_horizontal_outline.svg-2a5ba48e8c9646c039e96b549d07ed3d.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_joycon_left_outline.svg.import b/assets/images/gamepad/switch/switch_joycon_left_outline.svg.import
index f7f363599..06272d0f4 100644
--- a/assets/images/gamepad/switch/switch_joycon_left_outline.svg.import
+++ b/assets/images/gamepad/switch/switch_joycon_left_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://80hrmjlfhdk7"
+uid="uid://csmi83v2epni4"
path="res://.godot/imported/switch_joycon_left_outline.svg-1b27cd759582719a0e01020e77e4e552.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_joycon_left_rotate.svg.import b/assets/images/gamepad/switch/switch_joycon_left_rotate.svg.import
index 457a3e6ce..8df3ff1a1 100644
--- a/assets/images/gamepad/switch/switch_joycon_left_rotate.svg.import
+++ b/assets/images/gamepad/switch/switch_joycon_left_rotate.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://by4xd4qq5dspy"
+uid="uid://cda8etpu56yjn"
path="res://.godot/imported/switch_joycon_left_rotate.svg-944c087dc0aefb6bda31d7f3dd5ad357.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_joycon_left_rotate_outline.svg.import b/assets/images/gamepad/switch/switch_joycon_left_rotate_outline.svg.import
index 8adf0d8a8..3c109db14 100644
--- a/assets/images/gamepad/switch/switch_joycon_left_rotate_outline.svg.import
+++ b/assets/images/gamepad/switch/switch_joycon_left_rotate_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://d4mgd3ang8xv"
+uid="uid://cef02qkdnf5w3"
path="res://.godot/imported/switch_joycon_left_rotate_outline.svg-36cc63c32af2ad6da749f7600177a363.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_joycon_left_vertical.svg.import b/assets/images/gamepad/switch/switch_joycon_left_vertical.svg.import
index 5d1b76bde..845015960 100644
--- a/assets/images/gamepad/switch/switch_joycon_left_vertical.svg.import
+++ b/assets/images/gamepad/switch/switch_joycon_left_vertical.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bcptlybmhqpdn"
+uid="uid://os8sumlnqj8n"
path="res://.godot/imported/switch_joycon_left_vertical.svg-ea0d7edee10c9f6aa1194e2a5cb0b6ee.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_joycon_left_vertical_outline.svg.import b/assets/images/gamepad/switch/switch_joycon_left_vertical_outline.svg.import
index e5a0c677f..683646b20 100644
--- a/assets/images/gamepad/switch/switch_joycon_left_vertical_outline.svg.import
+++ b/assets/images/gamepad/switch/switch_joycon_left_vertical_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cqk8lkc0njdt4"
+uid="uid://fnkkivip7r3j"
path="res://.godot/imported/switch_joycon_left_vertical_outline.svg-7341150781697f5fde961db943dd8d14.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_joycon_outline.svg.import b/assets/images/gamepad/switch/switch_joycon_outline.svg.import
index 8a463cf8c..f1e1e7470 100644
--- a/assets/images/gamepad/switch/switch_joycon_outline.svg.import
+++ b/assets/images/gamepad/switch/switch_joycon_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bgms863mn70t0"
+uid="uid://c0qvwfvx2n4pm"
path="res://.godot/imported/switch_joycon_outline.svg-4c0db1382cdb8427d69fb63a3c203715.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_joycon_right.svg.import b/assets/images/gamepad/switch/switch_joycon_right.svg.import
index 785494238..00f3106fe 100644
--- a/assets/images/gamepad/switch/switch_joycon_right.svg.import
+++ b/assets/images/gamepad/switch/switch_joycon_right.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dbyiyxa814wdx"
+uid="uid://71s1fkcvihco"
path="res://.godot/imported/switch_joycon_right.svg-6826bf80e5c192664d7c67517db6d812.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_joycon_right_diagonal.svg.import b/assets/images/gamepad/switch/switch_joycon_right_diagonal.svg.import
index c35ff86f0..16a29ad17 100644
--- a/assets/images/gamepad/switch/switch_joycon_right_diagonal.svg.import
+++ b/assets/images/gamepad/switch/switch_joycon_right_diagonal.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dt8l32jey6r56"
+uid="uid://dmsy2w7mnm2c4"
path="res://.godot/imported/switch_joycon_right_diagonal.svg-00a3f01eca458a52372dfef04c9eac3d.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_joycon_right_diagonal_outline.svg.import b/assets/images/gamepad/switch/switch_joycon_right_diagonal_outline.svg.import
index cf08364c2..6c6f3ac4a 100644
--- a/assets/images/gamepad/switch/switch_joycon_right_diagonal_outline.svg.import
+++ b/assets/images/gamepad/switch/switch_joycon_right_diagonal_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cu250actmithx"
+uid="uid://rohtiop6glol"
path="res://.godot/imported/switch_joycon_right_diagonal_outline.svg-7b81b2b30e1d1b6e045b2a75ac5e1632.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_joycon_right_horizontal.svg.import b/assets/images/gamepad/switch/switch_joycon_right_horizontal.svg.import
index 5526a380e..4ebdfdcc2 100644
--- a/assets/images/gamepad/switch/switch_joycon_right_horizontal.svg.import
+++ b/assets/images/gamepad/switch/switch_joycon_right_horizontal.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://btxhhdt177nb1"
+uid="uid://b5yxtlxfblwo6"
path="res://.godot/imported/switch_joycon_right_horizontal.svg-886a5a2bd5511d4a635b73c4c8993459.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_joycon_right_horizontal_outline.svg.import b/assets/images/gamepad/switch/switch_joycon_right_horizontal_outline.svg.import
index 9342678bd..7c28b5a60 100644
--- a/assets/images/gamepad/switch/switch_joycon_right_horizontal_outline.svg.import
+++ b/assets/images/gamepad/switch/switch_joycon_right_horizontal_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://c7yoljyn13w7v"
+uid="uid://dk7b1dgsgmkx5"
path="res://.godot/imported/switch_joycon_right_horizontal_outline.svg-0f3bf20cde47b289a347a8ce9789447d.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_joycon_right_outline.svg.import b/assets/images/gamepad/switch/switch_joycon_right_outline.svg.import
index cd9064df4..521fb5953 100644
--- a/assets/images/gamepad/switch/switch_joycon_right_outline.svg.import
+++ b/assets/images/gamepad/switch/switch_joycon_right_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://hy4gu3gggx0g"
+uid="uid://ciehfb12nue5v"
path="res://.godot/imported/switch_joycon_right_outline.svg-df7dcdee297c267ee8883cb0f3d67255.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_joycon_right_rotate.svg.import b/assets/images/gamepad/switch/switch_joycon_right_rotate.svg.import
index dfcb20514..44f4f3ac7 100644
--- a/assets/images/gamepad/switch/switch_joycon_right_rotate.svg.import
+++ b/assets/images/gamepad/switch/switch_joycon_right_rotate.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dvog60nf0kt5s"
+uid="uid://rsofb7ugkkyy"
path="res://.godot/imported/switch_joycon_right_rotate.svg-75b82eab6a389f044d7b7ba20fafd2b6.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_joycon_right_rotate_outline.svg.import b/assets/images/gamepad/switch/switch_joycon_right_rotate_outline.svg.import
index d847a9a85..de0cd5036 100644
--- a/assets/images/gamepad/switch/switch_joycon_right_rotate_outline.svg.import
+++ b/assets/images/gamepad/switch/switch_joycon_right_rotate_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://6hpdc0rkrgba"
+uid="uid://c2yalpuhsrbbb"
path="res://.godot/imported/switch_joycon_right_rotate_outline.svg-abbe3cb88bcf15930da81ddf7558ec14.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_joycon_right_vertical.svg.import b/assets/images/gamepad/switch/switch_joycon_right_vertical.svg.import
index d0c8b0559..b3c4a193a 100644
--- a/assets/images/gamepad/switch/switch_joycon_right_vertical.svg.import
+++ b/assets/images/gamepad/switch/switch_joycon_right_vertical.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://rb5ecc7g4kb2"
+uid="uid://c1msoefnvve7s"
path="res://.godot/imported/switch_joycon_right_vertical.svg-c9d4df26e43a2e80c0a1fc0bb9c82f2c.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_joycon_right_vertical_outline.svg.import b/assets/images/gamepad/switch/switch_joycon_right_vertical_outline.svg.import
index 93eab4cab..95994228f 100644
--- a/assets/images/gamepad/switch/switch_joycon_right_vertical_outline.svg.import
+++ b/assets/images/gamepad/switch/switch_joycon_right_vertical_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b26di7327d50c"
+uid="uid://cafbe34hfdgrt"
path="res://.godot/imported/switch_joycon_right_vertical_outline.svg-bcb5132be16c9ef14104546786ca9b6e.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_left.svg.import b/assets/images/gamepad/switch/switch_left.svg.import
index 14a123c58..fd0e5a313 100644
--- a/assets/images/gamepad/switch/switch_left.svg.import
+++ b/assets/images/gamepad/switch/switch_left.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://ck1hpi2g0iprq"
+uid="uid://btfnrwxhv1hqm"
path="res://.godot/imported/switch_left.svg-c7bab108015a169efe10a56ac6b51b0b.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_left_outline.svg.import b/assets/images/gamepad/switch/switch_left_outline.svg.import
index eee17ff2f..651c4dcc8 100644
--- a/assets/images/gamepad/switch/switch_left_outline.svg.import
+++ b/assets/images/gamepad/switch/switch_left_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://ci3kxstltykfw"
+uid="uid://bdg0cg6f0ms1b"
path="res://.godot/imported/switch_left_outline.svg-dff174aeb5d10c31520c2edd059fbd84.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_right.svg.import b/assets/images/gamepad/switch/switch_right.svg.import
index 1761ba56b..d7eb140f0 100644
--- a/assets/images/gamepad/switch/switch_right.svg.import
+++ b/assets/images/gamepad/switch/switch_right.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://duaf8xdncqrlo"
+uid="uid://bwcjsvfcryoyv"
path="res://.godot/imported/switch_right.svg-0d9b55b2f31ae028dca22757697d6a7b.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_right_outline.svg.import b/assets/images/gamepad/switch/switch_right_outline.svg.import
index da1677270..d3011b3b3 100644
--- a/assets/images/gamepad/switch/switch_right_outline.svg.import
+++ b/assets/images/gamepad/switch/switch_right_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dt3gdq87voy2x"
+uid="uid://nsys24svmvg5"
path="res://.godot/imported/switch_right_outline.svg-f470d7fd258fc993c7b61017d1013f87.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_stick_l.svg.import b/assets/images/gamepad/switch/switch_stick_l.svg.import
index 1b164a72f..18b948043 100644
--- a/assets/images/gamepad/switch/switch_stick_l.svg.import
+++ b/assets/images/gamepad/switch/switch_stick_l.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bgkt5t7mmbhts"
+uid="uid://ruhfjlhtlik3"
path="res://.godot/imported/switch_stick_l.svg-aae382f05f8e763d7ef1c2fc250541db.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_stick_l_down.svg.import b/assets/images/gamepad/switch/switch_stick_l_down.svg.import
index 562df6f15..2fe8e019e 100644
--- a/assets/images/gamepad/switch/switch_stick_l_down.svg.import
+++ b/assets/images/gamepad/switch/switch_stick_l_down.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bvnpkij77axxu"
+uid="uid://ri6vpuerb2jn"
path="res://.godot/imported/switch_stick_l_down.svg-4acd6f3cbdcb3b3bf61ba920a3b60179.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_stick_l_horizontal.svg.import b/assets/images/gamepad/switch/switch_stick_l_horizontal.svg.import
index 46d6c8f0b..4523e3b4f 100644
--- a/assets/images/gamepad/switch/switch_stick_l_horizontal.svg.import
+++ b/assets/images/gamepad/switch/switch_stick_l_horizontal.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cisoss8hfkibx"
+uid="uid://dn4ao7qj2r7iq"
path="res://.godot/imported/switch_stick_l_horizontal.svg-cc9f66eb7cbea3b6415a31bd80039f78.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_stick_l_left.svg.import b/assets/images/gamepad/switch/switch_stick_l_left.svg.import
index e1b799692..021cd9821 100644
--- a/assets/images/gamepad/switch/switch_stick_l_left.svg.import
+++ b/assets/images/gamepad/switch/switch_stick_l_left.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bbad7xmuveel8"
+uid="uid://dvdwtqdrgcx55"
path="res://.godot/imported/switch_stick_l_left.svg-77c801aca888a97a967cfca83860300c.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_stick_l_press.svg.import b/assets/images/gamepad/switch/switch_stick_l_press.svg.import
index 389181a6f..006e2b7e2 100644
--- a/assets/images/gamepad/switch/switch_stick_l_press.svg.import
+++ b/assets/images/gamepad/switch/switch_stick_l_press.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://ca4fcl2jsx62k"
+uid="uid://d1xnwfo4kwgwe"
path="res://.godot/imported/switch_stick_l_press.svg-c5dcc6fd5751f66ea51a7e110553bb1c.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_stick_l_right.svg.import b/assets/images/gamepad/switch/switch_stick_l_right.svg.import
index 731b2577c..94ceacd10 100644
--- a/assets/images/gamepad/switch/switch_stick_l_right.svg.import
+++ b/assets/images/gamepad/switch/switch_stick_l_right.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://lpy6n3raxq2"
+uid="uid://ckdjvbxmun3hk"
path="res://.godot/imported/switch_stick_l_right.svg-de601db1d53058711973f52e5d6c6a20.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_stick_l_up.svg.import b/assets/images/gamepad/switch/switch_stick_l_up.svg.import
index 52d559c4d..447147009 100644
--- a/assets/images/gamepad/switch/switch_stick_l_up.svg.import
+++ b/assets/images/gamepad/switch/switch_stick_l_up.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://btrirhorp6y57"
+uid="uid://c54734rwsvi5y"
path="res://.godot/imported/switch_stick_l_up.svg-7ec61c14ae2f7c598dd6b2f74b871769.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_stick_l_vertical.svg.import b/assets/images/gamepad/switch/switch_stick_l_vertical.svg.import
index 03b6c12fc..3fc2ad998 100644
--- a/assets/images/gamepad/switch/switch_stick_l_vertical.svg.import
+++ b/assets/images/gamepad/switch/switch_stick_l_vertical.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bhos74bdthcxj"
+uid="uid://wjqj6c2wcyry"
path="res://.godot/imported/switch_stick_l_vertical.svg-8996d30495edbd4880713f90220989c2.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_stick_r.svg.import b/assets/images/gamepad/switch/switch_stick_r.svg.import
index 32d479dec..66cdff5c0 100644
--- a/assets/images/gamepad/switch/switch_stick_r.svg.import
+++ b/assets/images/gamepad/switch/switch_stick_r.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://c1fas8o38r02p"
+uid="uid://bnr0q7kupfac8"
path="res://.godot/imported/switch_stick_r.svg-6e256a5f8d4a4fc03b463997f820cd35.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_stick_r_down.svg.import b/assets/images/gamepad/switch/switch_stick_r_down.svg.import
index fa5fcefda..3d47f4ab4 100644
--- a/assets/images/gamepad/switch/switch_stick_r_down.svg.import
+++ b/assets/images/gamepad/switch/switch_stick_r_down.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dqrqw3lv3kl3e"
+uid="uid://c37v6pn2p4pa7"
path="res://.godot/imported/switch_stick_r_down.svg-d521a00541e87de24830d67369f603c0.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_stick_r_horizontal.svg.import b/assets/images/gamepad/switch/switch_stick_r_horizontal.svg.import
index 43fb60dac..857b667f2 100644
--- a/assets/images/gamepad/switch/switch_stick_r_horizontal.svg.import
+++ b/assets/images/gamepad/switch/switch_stick_r_horizontal.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bp82itprpqi44"
+uid="uid://kyn53m0q0o60"
path="res://.godot/imported/switch_stick_r_horizontal.svg-ca8fab810667df12b86832050d3122a6.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_stick_r_left.svg.import b/assets/images/gamepad/switch/switch_stick_r_left.svg.import
index 6b4aa9933..3591e459a 100644
--- a/assets/images/gamepad/switch/switch_stick_r_left.svg.import
+++ b/assets/images/gamepad/switch/switch_stick_r_left.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bcstmmysk3e1"
+uid="uid://d0s0cx6bqiovg"
path="res://.godot/imported/switch_stick_r_left.svg-67ebb0066735a4763b14d2a4736f8abd.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_stick_r_press.svg.import b/assets/images/gamepad/switch/switch_stick_r_press.svg.import
index f23c17068..7fa271e6e 100644
--- a/assets/images/gamepad/switch/switch_stick_r_press.svg.import
+++ b/assets/images/gamepad/switch/switch_stick_r_press.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dop088ppjtx7r"
+uid="uid://dalb0538ux4qy"
path="res://.godot/imported/switch_stick_r_press.svg-a7afce4c88b1f9ebb43bed3d6f998e63.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_stick_r_right.svg.import b/assets/images/gamepad/switch/switch_stick_r_right.svg.import
index 60b335544..1672ea07b 100644
--- a/assets/images/gamepad/switch/switch_stick_r_right.svg.import
+++ b/assets/images/gamepad/switch/switch_stick_r_right.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://domi3pblhpgqy"
+uid="uid://dxycp3mj54mwc"
path="res://.godot/imported/switch_stick_r_right.svg-c8a8ea34f91cb8ac27b1b8dbc35ec2dc.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_stick_r_up.svg.import b/assets/images/gamepad/switch/switch_stick_r_up.svg.import
index 1d4954c7b..fbfe87ed8 100644
--- a/assets/images/gamepad/switch/switch_stick_r_up.svg.import
+++ b/assets/images/gamepad/switch/switch_stick_r_up.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dtkumw37qfis8"
+uid="uid://be6s7r6y3ndty"
path="res://.godot/imported/switch_stick_r_up.svg-f63e9b2a667b9ff07adefcb25e446532.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_stick_r_vertical.svg.import b/assets/images/gamepad/switch/switch_stick_r_vertical.svg.import
index b284a777c..d07402125 100644
--- a/assets/images/gamepad/switch/switch_stick_r_vertical.svg.import
+++ b/assets/images/gamepad/switch/switch_stick_r_vertical.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bk1cmphnkacdo"
+uid="uid://djlj5v8c0fiho"
path="res://.godot/imported/switch_stick_r_vertical.svg-daf25366dd8c5fb5b47709470d853b99.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_stick_side_l.svg.import b/assets/images/gamepad/switch/switch_stick_side_l.svg.import
index 5542be985..3d60b754d 100644
--- a/assets/images/gamepad/switch/switch_stick_side_l.svg.import
+++ b/assets/images/gamepad/switch/switch_stick_side_l.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dpwy5hc8fo0dl"
+uid="uid://dm7aknxom21r7"
path="res://.godot/imported/switch_stick_side_l.svg-726e57c646f64ead20cecca407755d36.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_stick_side_r.svg.import b/assets/images/gamepad/switch/switch_stick_side_r.svg.import
index 183cb2719..9707a83cd 100644
--- a/assets/images/gamepad/switch/switch_stick_side_r.svg.import
+++ b/assets/images/gamepad/switch/switch_stick_side_r.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cxqi3b27jc5ya"
+uid="uid://uu7ejty8j7se"
path="res://.godot/imported/switch_stick_side_r.svg-f5c98e6b9a5fda0ac1413b4e26c81e57.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_stick_top_l.svg.import b/assets/images/gamepad/switch/switch_stick_top_l.svg.import
index 29f302f6e..1c2430d2b 100644
--- a/assets/images/gamepad/switch/switch_stick_top_l.svg.import
+++ b/assets/images/gamepad/switch/switch_stick_top_l.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bac30sashnbxg"
+uid="uid://dp5audyyanttc"
path="res://.godot/imported/switch_stick_top_l.svg-29532a2bd9b1c20e1b2e0d001196bf77.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_stick_top_r.svg.import b/assets/images/gamepad/switch/switch_stick_top_r.svg.import
index 539b049ed..232f05200 100644
--- a/assets/images/gamepad/switch/switch_stick_top_r.svg.import
+++ b/assets/images/gamepad/switch/switch_stick_top_r.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cr1spi2ofv3eh"
+uid="uid://dl8a0auf0ql2d"
path="res://.godot/imported/switch_stick_top_r.svg-eef0efc5598b99da72fd2941b2e3b792.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_up.svg.import b/assets/images/gamepad/switch/switch_up.svg.import
index 4037f7d05..51f39b65b 100644
--- a/assets/images/gamepad/switch/switch_up.svg.import
+++ b/assets/images/gamepad/switch/switch_up.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dx6cbkmaquu0i"
+uid="uid://sboeqnr1sdod"
path="res://.godot/imported/switch_up.svg-a5ba228a57134357f57102bc90fb5990.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/switch/switch_up_outline.svg.import b/assets/images/gamepad/switch/switch_up_outline.svg.import
index 901a85a15..25139d299 100644
--- a/assets/images/gamepad/switch/switch_up_outline.svg.import
+++ b/assets/images/gamepad/switch/switch_up_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://yrros5e0ffvr"
+uid="uid://rl6xjmy7brub"
path="res://.godot/imported/switch_up_outline.svg-9e3a14a4bc0345ded4e75b1f08cfb511.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/controller_wii_classic.svg.import b/assets/images/gamepad/wii/controller_wii_classic.svg.import
index e8fc4e45e..a8a2679b4 100644
--- a/assets/images/gamepad/wii/controller_wii_classic.svg.import
+++ b/assets/images/gamepad/wii/controller_wii_classic.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b4suct4lxd2o5"
+uid="uid://ei2kbd7bns55"
path="res://.godot/imported/controller_wii_classic.svg-dc1bf5a78ba834b5eec7afb117f4137b.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/controller_wii_classic_pro.svg.import b/assets/images/gamepad/wii/controller_wii_classic_pro.svg.import
index 7046bdf97..12203e329 100644
--- a/assets/images/gamepad/wii/controller_wii_classic_pro.svg.import
+++ b/assets/images/gamepad/wii/controller_wii_classic_pro.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://3ljlvycfy0ks"
+uid="uid://bcxmqua8k8ejy"
path="res://.godot/imported/controller_wii_classic_pro.svg-f8d0beec497dfc798b1f5490367a3d92.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_button_1.svg.import b/assets/images/gamepad/wii/wii_button_1.svg.import
index a96c9ebd0..3b353053b 100644
--- a/assets/images/gamepad/wii/wii_button_1.svg.import
+++ b/assets/images/gamepad/wii/wii_button_1.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dcoic7xprw3s7"
+uid="uid://cjxhg5l6ubkd0"
path="res://.godot/imported/wii_button_1.svg-f3971dfa4194a9225bd416449e3d61e2.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_button_1_outline.svg.import b/assets/images/gamepad/wii/wii_button_1_outline.svg.import
index 55611bfe5..12216e56a 100644
--- a/assets/images/gamepad/wii/wii_button_1_outline.svg.import
+++ b/assets/images/gamepad/wii/wii_button_1_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cfeyd5ywwf1v3"
+uid="uid://caylm6q24ldpn"
path="res://.godot/imported/wii_button_1_outline.svg-3b5502e8a7320e252362bb7d78e426ef.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_button_2.svg.import b/assets/images/gamepad/wii/wii_button_2.svg.import
index 747117b90..39e976403 100644
--- a/assets/images/gamepad/wii/wii_button_2.svg.import
+++ b/assets/images/gamepad/wii/wii_button_2.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bkcd4by7vgbic"
+uid="uid://bwnjv1hmqeenc"
path="res://.godot/imported/wii_button_2.svg-b4f862ed7c7db7792341ba5bde88ad21.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_button_2_outline.svg.import b/assets/images/gamepad/wii/wii_button_2_outline.svg.import
index fba301901..5ac55daae 100644
--- a/assets/images/gamepad/wii/wii_button_2_outline.svg.import
+++ b/assets/images/gamepad/wii/wii_button_2_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://ctoaykmpm6a8c"
+uid="uid://cmtbbb0bgfsql"
path="res://.godot/imported/wii_button_2_outline.svg-cfe121ccf8884cf6a3879b2dcd03be56.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_button_a.svg.import b/assets/images/gamepad/wii/wii_button_a.svg.import
index 9aff7052e..83681614b 100644
--- a/assets/images/gamepad/wii/wii_button_a.svg.import
+++ b/assets/images/gamepad/wii/wii_button_a.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://6x7wk7qqt0qy"
+uid="uid://b7xm48eehmmnd"
path="res://.godot/imported/wii_button_a.svg-5f20ec3dde54a51fe6e3ae5eaa16be13.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_button_a_outline.svg.import b/assets/images/gamepad/wii/wii_button_a_outline.svg.import
index a0d691671..272a78e47 100644
--- a/assets/images/gamepad/wii/wii_button_a_outline.svg.import
+++ b/assets/images/gamepad/wii/wii_button_a_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cxola65t655fr"
+uid="uid://i5dukvf56vj8"
path="res://.godot/imported/wii_button_a_outline.svg-4402ad471557eecc824df6da919008d4.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_button_b.svg.import b/assets/images/gamepad/wii/wii_button_b.svg.import
index 18f872af4..f15620f78 100644
--- a/assets/images/gamepad/wii/wii_button_b.svg.import
+++ b/assets/images/gamepad/wii/wii_button_b.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dp2k3akttnjqd"
+uid="uid://xfx8mk42yvv4"
path="res://.godot/imported/wii_button_b.svg-634186bb96a5f08cc9fa35ceff9b49c2.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_button_b_outline.svg.import b/assets/images/gamepad/wii/wii_button_b_outline.svg.import
index 02618f7c3..957def9f6 100644
--- a/assets/images/gamepad/wii/wii_button_b_outline.svg.import
+++ b/assets/images/gamepad/wii/wii_button_b_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://75u34yhw6ks7"
+uid="uid://yfsqhb2372dc"
path="res://.godot/imported/wii_button_b_outline.svg-d37cc5bd2dff758524e27b3f09ae962b.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_button_c.svg.import b/assets/images/gamepad/wii/wii_button_c.svg.import
index 0f30fb67f..d0974083c 100644
--- a/assets/images/gamepad/wii/wii_button_c.svg.import
+++ b/assets/images/gamepad/wii/wii_button_c.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://ca65lbp3d7jt3"
+uid="uid://brcl5b3d7nl0x"
path="res://.godot/imported/wii_button_c.svg-31c8b68f736647fd87dbbd3a71ef4a32.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_button_c_outline.svg.import b/assets/images/gamepad/wii/wii_button_c_outline.svg.import
index f7f13329a..9163c0a12 100644
--- a/assets/images/gamepad/wii/wii_button_c_outline.svg.import
+++ b/assets/images/gamepad/wii/wii_button_c_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://83w8k2mfsbgr"
+uid="uid://dt6yfi01r71h2"
path="res://.godot/imported/wii_button_c_outline.svg-0dfbda2c9082cff0d6216b3bfe6e5ae2.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_button_home.svg.import b/assets/images/gamepad/wii/wii_button_home.svg.import
index 7c2e7d778..638e32adb 100644
--- a/assets/images/gamepad/wii/wii_button_home.svg.import
+++ b/assets/images/gamepad/wii/wii_button_home.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dsfxlgf6phk2q"
+uid="uid://df82wcu8iklpg"
path="res://.godot/imported/wii_button_home.svg-39a2942a06e2f4fbb61cd7379e16ea2b.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_button_home_outline.svg.import b/assets/images/gamepad/wii/wii_button_home_outline.svg.import
index adcef55fe..d48a13290 100644
--- a/assets/images/gamepad/wii/wii_button_home_outline.svg.import
+++ b/assets/images/gamepad/wii/wii_button_home_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b8o78v36eggpj"
+uid="uid://bvi2knm4a0kvt"
path="res://.godot/imported/wii_button_home_outline.svg-69d0e8774c6ceef72cc548f66a8c12f0.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_button_l.svg.import b/assets/images/gamepad/wii/wii_button_l.svg.import
index 483da952f..d60391ce9 100644
--- a/assets/images/gamepad/wii/wii_button_l.svg.import
+++ b/assets/images/gamepad/wii/wii_button_l.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://duu0x4agtufwg"
+uid="uid://jv0f2kumegn6"
path="res://.godot/imported/wii_button_l.svg-912503ea1c7e2365be31bd6f699e5066.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_button_l_outline.svg.import b/assets/images/gamepad/wii/wii_button_l_outline.svg.import
index 779c1a924..6a884ff7f 100644
--- a/assets/images/gamepad/wii/wii_button_l_outline.svg.import
+++ b/assets/images/gamepad/wii/wii_button_l_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cjc4chwhtvj3b"
+uid="uid://cjs2sdqbumhsg"
path="res://.godot/imported/wii_button_l_outline.svg-85b264b627126990528575d0a9dd47fe.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_button_minus.svg.import b/assets/images/gamepad/wii/wii_button_minus.svg.import
index 8f2830c58..85f7310cb 100644
--- a/assets/images/gamepad/wii/wii_button_minus.svg.import
+++ b/assets/images/gamepad/wii/wii_button_minus.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bd5oq6dvv5rhw"
+uid="uid://dvuc3xpvgl7g4"
path="res://.godot/imported/wii_button_minus.svg-860a76d15f06501803c4c1ef2104a643.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_button_minus_outline.svg.import b/assets/images/gamepad/wii/wii_button_minus_outline.svg.import
index a004d888f..bfe19db8c 100644
--- a/assets/images/gamepad/wii/wii_button_minus_outline.svg.import
+++ b/assets/images/gamepad/wii/wii_button_minus_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://c7qxk1ailjtm6"
+uid="uid://byjprmsf4j5f0"
path="res://.godot/imported/wii_button_minus_outline.svg-4398c3b614db97c270ab3e7e7806e277.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_button_plus.svg.import b/assets/images/gamepad/wii/wii_button_plus.svg.import
index 13c25ada4..0fee5cd91 100644
--- a/assets/images/gamepad/wii/wii_button_plus.svg.import
+++ b/assets/images/gamepad/wii/wii_button_plus.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://f52q2dj84otl"
+uid="uid://c3eujt77bspur"
path="res://.godot/imported/wii_button_plus.svg-c12882fb49167f9dc00b7d14e1170589.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_button_plus_outline.svg.import b/assets/images/gamepad/wii/wii_button_plus_outline.svg.import
index 969b1f99b..98bf13393 100644
--- a/assets/images/gamepad/wii/wii_button_plus_outline.svg.import
+++ b/assets/images/gamepad/wii/wii_button_plus_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://j546dwnx2s34"
+uid="uid://d0oe8dsggbu1y"
path="res://.godot/imported/wii_button_plus_outline.svg-ff9294805c33c642a0171789cfea8113.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_button_power.svg.import b/assets/images/gamepad/wii/wii_button_power.svg.import
index 277d264cd..ddaaba1a2 100644
--- a/assets/images/gamepad/wii/wii_button_power.svg.import
+++ b/assets/images/gamepad/wii/wii_button_power.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bxolmk00ra2q7"
+uid="uid://cks6quaniwkcy"
path="res://.godot/imported/wii_button_power.svg-435396daaeb61eed63539d4af5888db8.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_button_power_outline.svg.import b/assets/images/gamepad/wii/wii_button_power_outline.svg.import
index 0e0cdffc5..219f0e6e1 100644
--- a/assets/images/gamepad/wii/wii_button_power_outline.svg.import
+++ b/assets/images/gamepad/wii/wii_button_power_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://co200ljfffs2i"
+uid="uid://dn7402t0c60f"
path="res://.godot/imported/wii_button_power_outline.svg-1c6888491ec4c3b86e8f3a308981bc70.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_button_r.svg.import b/assets/images/gamepad/wii/wii_button_r.svg.import
index fc981f69f..33f03bba3 100644
--- a/assets/images/gamepad/wii/wii_button_r.svg.import
+++ b/assets/images/gamepad/wii/wii_button_r.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b4rnow0ar3tqm"
+uid="uid://cc7h86ctk20wd"
path="res://.godot/imported/wii_button_r.svg-b505c40405df7d9ddd0d4123932661aa.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_button_r_outline.svg.import b/assets/images/gamepad/wii/wii_button_r_outline.svg.import
index fdef564d7..dd44b5209 100644
--- a/assets/images/gamepad/wii/wii_button_r_outline.svg.import
+++ b/assets/images/gamepad/wii/wii_button_r_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dnrl5lg3bji20"
+uid="uid://b86y01kmbhycv"
path="res://.godot/imported/wii_button_r_outline.svg-ad820ab0a92dbc3f6f1d16b91c6cd6ae.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_button_x.svg.import b/assets/images/gamepad/wii/wii_button_x.svg.import
index 212080902..4da31657e 100644
--- a/assets/images/gamepad/wii/wii_button_x.svg.import
+++ b/assets/images/gamepad/wii/wii_button_x.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://d3di23ekl3lmx"
+uid="uid://df7ytg83oxf72"
path="res://.godot/imported/wii_button_x.svg-1a063d73a38b3f77292ba7e4a1949288.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_button_x_outline.svg.import b/assets/images/gamepad/wii/wii_button_x_outline.svg.import
index 6895f3201..46d5f0d83 100644
--- a/assets/images/gamepad/wii/wii_button_x_outline.svg.import
+++ b/assets/images/gamepad/wii/wii_button_x_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://0vb1fxtd43v5"
+uid="uid://5tl4y6636hy7"
path="res://.godot/imported/wii_button_x_outline.svg-483dfc6b8d0398678dd56d1606a1ad38.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_button_y.svg.import b/assets/images/gamepad/wii/wii_button_y.svg.import
index 1e367a91d..302922be3 100644
--- a/assets/images/gamepad/wii/wii_button_y.svg.import
+++ b/assets/images/gamepad/wii/wii_button_y.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bpotw335akb8t"
+uid="uid://cdf7rxayfascb"
path="res://.godot/imported/wii_button_y.svg-7564833f4f7b6b8744e922f68565213c.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_button_y_outline.svg.import b/assets/images/gamepad/wii/wii_button_y_outline.svg.import
index e5b147968..4f61fd2d9 100644
--- a/assets/images/gamepad/wii/wii_button_y_outline.svg.import
+++ b/assets/images/gamepad/wii/wii_button_y_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bssbg0unve36t"
+uid="uid://dnr5lobxfg4e3"
path="res://.godot/imported/wii_button_y_outline.svg-edef6503d35ae3b32b12bf7e5265a384.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_button_z.svg.import b/assets/images/gamepad/wii/wii_button_z.svg.import
index e56bb485d..3bd5e8c36 100644
--- a/assets/images/gamepad/wii/wii_button_z.svg.import
+++ b/assets/images/gamepad/wii/wii_button_z.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://1v2vwdc62uv1"
+uid="uid://b66hmbh5td3xb"
path="res://.godot/imported/wii_button_z.svg-3e6e537a0ff751e16d141a6af24af82b.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_button_z_outline.svg.import b/assets/images/gamepad/wii/wii_button_z_outline.svg.import
index 5a89085b2..14b52ae33 100644
--- a/assets/images/gamepad/wii/wii_button_z_outline.svg.import
+++ b/assets/images/gamepad/wii/wii_button_z_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dftgua4j3vw1v"
+uid="uid://bjl54ftvfhbod"
path="res://.godot/imported/wii_button_z_outline.svg-f1bae1443d801015a68c25df3253182f.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_button_zl.svg.import b/assets/images/gamepad/wii/wii_button_zl.svg.import
index 61fe6f543..21eae4049 100644
--- a/assets/images/gamepad/wii/wii_button_zl.svg.import
+++ b/assets/images/gamepad/wii/wii_button_zl.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://c53i2connw6hq"
+uid="uid://jwoi6r8v0aeu"
path="res://.godot/imported/wii_button_zl.svg-33b67456438af78986d72bc8cf4fc430.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_button_zl_outline.svg.import b/assets/images/gamepad/wii/wii_button_zl_outline.svg.import
index 026b2b31d..63cb8e04e 100644
--- a/assets/images/gamepad/wii/wii_button_zl_outline.svg.import
+++ b/assets/images/gamepad/wii/wii_button_zl_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bihrnvma1guc7"
+uid="uid://yqlvxk8ggchu"
path="res://.godot/imported/wii_button_zl_outline.svg-db207d8a2160d4011dc7d03c89a6f9d4.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_button_zr.svg.import b/assets/images/gamepad/wii/wii_button_zr.svg.import
index d00f4bf27..80790a5a6 100644
--- a/assets/images/gamepad/wii/wii_button_zr.svg.import
+++ b/assets/images/gamepad/wii/wii_button_zr.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cemhw310oy5wu"
+uid="uid://bhti7edlek6mt"
path="res://.godot/imported/wii_button_zr.svg-cc820b66bfad2013da9264e62c792902.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_button_zr_outline.svg.import b/assets/images/gamepad/wii/wii_button_zr_outline.svg.import
index 69c75e0fe..fd0a3ccc0 100644
--- a/assets/images/gamepad/wii/wii_button_zr_outline.svg.import
+++ b/assets/images/gamepad/wii/wii_button_zr_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://c8c8e20m7i04p"
+uid="uid://dwlupjiaoniul"
path="res://.godot/imported/wii_button_zr_outline.svg-2e2f67d64bfb7f0687e2503a50e85fdc.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_controller.svg.import b/assets/images/gamepad/wii/wii_controller.svg.import
index cbbd41582..eb19f1cc7 100644
--- a/assets/images/gamepad/wii/wii_controller.svg.import
+++ b/assets/images/gamepad/wii/wii_controller.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cfp8balkqg7qk"
+uid="uid://b4v3acclylug2"
path="res://.godot/imported/wii_controller.svg-e0f576be4e6214f56f10891c4354aa0b.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_controller_diagonal.svg.import b/assets/images/gamepad/wii/wii_controller_diagonal.svg.import
index 8457429f1..1cd8e268f 100644
--- a/assets/images/gamepad/wii/wii_controller_diagonal.svg.import
+++ b/assets/images/gamepad/wii/wii_controller_diagonal.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://c15m18opca6al"
+uid="uid://b8tnhfti5v0of"
path="res://.godot/imported/wii_controller_diagonal.svg-7118a665b9990f09b67cf43eff86e33f.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_controller_diagonal_outline.svg.import b/assets/images/gamepad/wii/wii_controller_diagonal_outline.svg.import
index be657d510..51ec8ff57 100644
--- a/assets/images/gamepad/wii/wii_controller_diagonal_outline.svg.import
+++ b/assets/images/gamepad/wii/wii_controller_diagonal_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://3edtfj4ygfn3"
+uid="uid://b6ueqo8iokc7"
path="res://.godot/imported/wii_controller_diagonal_outline.svg-5f2593408426aecdaf47cb7a95bdb8ae.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_controller_horizontal.svg.import b/assets/images/gamepad/wii/wii_controller_horizontal.svg.import
index 87f25acb5..08fb31a4c 100644
--- a/assets/images/gamepad/wii/wii_controller_horizontal.svg.import
+++ b/assets/images/gamepad/wii/wii_controller_horizontal.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bs6pp8e14k4o6"
+uid="uid://r8mop0r6qyb8"
path="res://.godot/imported/wii_controller_horizontal.svg-0a9a3682bceb873593b8d42efc2fb9cd.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_controller_horizontal_outline.svg.import b/assets/images/gamepad/wii/wii_controller_horizontal_outline.svg.import
index dbe6bb7e7..eaf060508 100644
--- a/assets/images/gamepad/wii/wii_controller_horizontal_outline.svg.import
+++ b/assets/images/gamepad/wii/wii_controller_horizontal_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://d0ua8p1d0if3o"
+uid="uid://dc8mxciok1wjp"
path="res://.godot/imported/wii_controller_horizontal_outline.svg-1f407578800bce47a5f13e344d3507b1.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_controller_nunchuk.svg.import b/assets/images/gamepad/wii/wii_controller_nunchuk.svg.import
index b839ecd9e..bc7eeb163 100644
--- a/assets/images/gamepad/wii/wii_controller_nunchuk.svg.import
+++ b/assets/images/gamepad/wii/wii_controller_nunchuk.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://curc4goqj1g5f"
+uid="uid://bm1qtwckkhj27"
path="res://.godot/imported/wii_controller_nunchuk.svg-cb51f3e0118b6c7df3473dd431d72bd3.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_controller_nunchuk_wire.svg.import b/assets/images/gamepad/wii/wii_controller_nunchuk_wire.svg.import
index 66aae118f..9bd8cbf85 100644
--- a/assets/images/gamepad/wii/wii_controller_nunchuk_wire.svg.import
+++ b/assets/images/gamepad/wii/wii_controller_nunchuk_wire.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dtqfknuw14csy"
+uid="uid://dpwe15m58b588"
path="res://.godot/imported/wii_controller_nunchuk_wire.svg-351f1aa3d70f0f335ce2cc9fadfd1588.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_controller_outline.svg.import b/assets/images/gamepad/wii/wii_controller_outline.svg.import
index c00e1032d..c7f09cb53 100644
--- a/assets/images/gamepad/wii/wii_controller_outline.svg.import
+++ b/assets/images/gamepad/wii/wii_controller_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bh21a5f588v8f"
+uid="uid://bx3v504x4hdh8"
path="res://.godot/imported/wii_controller_outline.svg-471483e247b136c434695e68c2e93481.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_controller_rotate.svg.import b/assets/images/gamepad/wii/wii_controller_rotate.svg.import
index 9823550f3..d82a07c28 100644
--- a/assets/images/gamepad/wii/wii_controller_rotate.svg.import
+++ b/assets/images/gamepad/wii/wii_controller_rotate.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://c14kfcscy2d7k"
+uid="uid://bb1l6j3ablgv8"
path="res://.godot/imported/wii_controller_rotate.svg-df11ad5a2ddbe45c2fbe75e315f9c7b5.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_controller_rotate_outline.svg.import b/assets/images/gamepad/wii/wii_controller_rotate_outline.svg.import
index 349dcd14e..9d3006d4e 100644
--- a/assets/images/gamepad/wii/wii_controller_rotate_outline.svg.import
+++ b/assets/images/gamepad/wii/wii_controller_rotate_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://i5l41k7eklva"
+uid="uid://b6mll70inm1ht"
path="res://.godot/imported/wii_controller_rotate_outline.svg-3937f3c575637192eb0d6244580122ae.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_controller_vertical.svg.import b/assets/images/gamepad/wii/wii_controller_vertical.svg.import
index a442169ca..689464333 100644
--- a/assets/images/gamepad/wii/wii_controller_vertical.svg.import
+++ b/assets/images/gamepad/wii/wii_controller_vertical.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://we2qa5i8d6f8"
+uid="uid://dopema7nkbl5n"
path="res://.godot/imported/wii_controller_vertical.svg-ea6f5448200b26577d51d7f833240b91.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_controller_vertical_outline.svg.import b/assets/images/gamepad/wii/wii_controller_vertical_outline.svg.import
index 92dd7aed0..e0179b5d0 100644
--- a/assets/images/gamepad/wii/wii_controller_vertical_outline.svg.import
+++ b/assets/images/gamepad/wii/wii_controller_vertical_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cc06bdslokvu4"
+uid="uid://bjf4geurelffk"
path="res://.godot/imported/wii_controller_vertical_outline.svg-e07ae70b6c11cfe021f9ab4ab7881966.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_dpad.svg.import b/assets/images/gamepad/wii/wii_dpad.svg.import
index 00e4dcda6..91c9eca2b 100644
--- a/assets/images/gamepad/wii/wii_dpad.svg.import
+++ b/assets/images/gamepad/wii/wii_dpad.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://n3xg588juoe5"
+uid="uid://dh7gm6mnxis68"
path="res://.godot/imported/wii_dpad.svg-4fb5b0b90bbefe77fe17c4ecae222273.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_dpad_all.svg.import b/assets/images/gamepad/wii/wii_dpad_all.svg.import
index 05b27c19b..c3f50caf9 100644
--- a/assets/images/gamepad/wii/wii_dpad_all.svg.import
+++ b/assets/images/gamepad/wii/wii_dpad_all.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dj3i4yljcxef4"
+uid="uid://hsh53klk8kep"
path="res://.godot/imported/wii_dpad_all.svg-b572646c4291f5f7ef2a7dadda7e9c3e.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_dpad_down.svg.import b/assets/images/gamepad/wii/wii_dpad_down.svg.import
index 04d15cf4d..663820a75 100644
--- a/assets/images/gamepad/wii/wii_dpad_down.svg.import
+++ b/assets/images/gamepad/wii/wii_dpad_down.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://drhsjhalwcb0p"
+uid="uid://14lpwxruj5f2"
path="res://.godot/imported/wii_dpad_down.svg-b51b622985429f7e34ab58bad7bcab45.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_dpad_down_outline.svg.import b/assets/images/gamepad/wii/wii_dpad_down_outline.svg.import
index 6e73c1288..d016e04bd 100644
--- a/assets/images/gamepad/wii/wii_dpad_down_outline.svg.import
+++ b/assets/images/gamepad/wii/wii_dpad_down_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dyepvuf3v60cr"
+uid="uid://3n2slhg0yjdc"
path="res://.godot/imported/wii_dpad_down_outline.svg-922080eece2ca41000f590edac255f4d.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_dpad_horizontal.svg.import b/assets/images/gamepad/wii/wii_dpad_horizontal.svg.import
index bad5f90c3..10f215709 100644
--- a/assets/images/gamepad/wii/wii_dpad_horizontal.svg.import
+++ b/assets/images/gamepad/wii/wii_dpad_horizontal.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b0y1ldkgunfp8"
+uid="uid://cp5tjtd0inbif"
path="res://.godot/imported/wii_dpad_horizontal.svg-d52e9fa42190433f3e28d0bacb969824.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_dpad_horizontal_outline.svg.import b/assets/images/gamepad/wii/wii_dpad_horizontal_outline.svg.import
index 838d7d5c2..853b48993 100644
--- a/assets/images/gamepad/wii/wii_dpad_horizontal_outline.svg.import
+++ b/assets/images/gamepad/wii/wii_dpad_horizontal_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://ddnggnmibiouq"
+uid="uid://bq00llqb4m5lf"
path="res://.godot/imported/wii_dpad_horizontal_outline.svg-401b2ffa62040f3b471c3b0625f2fa66.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_dpad_left.svg.import b/assets/images/gamepad/wii/wii_dpad_left.svg.import
index 27b4bfa60..2e8acafe2 100644
--- a/assets/images/gamepad/wii/wii_dpad_left.svg.import
+++ b/assets/images/gamepad/wii/wii_dpad_left.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://c5sxbuul3e8jt"
+uid="uid://cbvdeo4q1do0u"
path="res://.godot/imported/wii_dpad_left.svg-44bbfd0d9e89a5075cfb7b59e1a8b14f.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_dpad_left_outline.svg.import b/assets/images/gamepad/wii/wii_dpad_left_outline.svg.import
index ecaf6f73d..6ffb7aa22 100644
--- a/assets/images/gamepad/wii/wii_dpad_left_outline.svg.import
+++ b/assets/images/gamepad/wii/wii_dpad_left_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cwbie6fxsapvh"
+uid="uid://dmo0nkxs3g6jd"
path="res://.godot/imported/wii_dpad_left_outline.svg-05e2fbc62cc8a58436651d50e69d1d2a.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_dpad_none.svg.import b/assets/images/gamepad/wii/wii_dpad_none.svg.import
index 7fb800ab4..bafa2e15c 100644
--- a/assets/images/gamepad/wii/wii_dpad_none.svg.import
+++ b/assets/images/gamepad/wii/wii_dpad_none.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dpl3s1qpws0si"
+uid="uid://bcggdc4awm8fe"
path="res://.godot/imported/wii_dpad_none.svg-d875b89299cdd20c760f4bdab6f6fcb8.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_dpad_right.svg.import b/assets/images/gamepad/wii/wii_dpad_right.svg.import
index 1ae6f5ab3..5243ffdd4 100644
--- a/assets/images/gamepad/wii/wii_dpad_right.svg.import
+++ b/assets/images/gamepad/wii/wii_dpad_right.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bpyq17k74erhn"
+uid="uid://de22wvyfphorq"
path="res://.godot/imported/wii_dpad_right.svg-19bf50599836d669a24fa4098e5f1cbf.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_dpad_right_outline.svg.import b/assets/images/gamepad/wii/wii_dpad_right_outline.svg.import
index baf895708..1c76952ab 100644
--- a/assets/images/gamepad/wii/wii_dpad_right_outline.svg.import
+++ b/assets/images/gamepad/wii/wii_dpad_right_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://r1sbcvftihte"
+uid="uid://rlehfgm7tu8n"
path="res://.godot/imported/wii_dpad_right_outline.svg-65667971788b78ade0accd165140264a.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_dpad_up.svg.import b/assets/images/gamepad/wii/wii_dpad_up.svg.import
index fb9771552..f8414526a 100644
--- a/assets/images/gamepad/wii/wii_dpad_up.svg.import
+++ b/assets/images/gamepad/wii/wii_dpad_up.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b2hwfvnmkh2vr"
+uid="uid://jbjm4a7nes2"
path="res://.godot/imported/wii_dpad_up.svg-3b748550a5075659ce4a751d2324cdff.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_dpad_up_outline.svg.import b/assets/images/gamepad/wii/wii_dpad_up_outline.svg.import
index 1a3766d76..883c13e9d 100644
--- a/assets/images/gamepad/wii/wii_dpad_up_outline.svg.import
+++ b/assets/images/gamepad/wii/wii_dpad_up_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dwtlhkc36j2a5"
+uid="uid://bb7saw75xx2ko"
path="res://.godot/imported/wii_dpad_up_outline.svg-07668bdc84f56707f73eeb2a3f0a6bd1.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_dpad_vertical.svg.import b/assets/images/gamepad/wii/wii_dpad_vertical.svg.import
index 917ef79ff..f9d3d7ef6 100644
--- a/assets/images/gamepad/wii/wii_dpad_vertical.svg.import
+++ b/assets/images/gamepad/wii/wii_dpad_vertical.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://ccpjxb6n8il6p"
+uid="uid://dgd68irvine1k"
path="res://.godot/imported/wii_dpad_vertical.svg-ef00d582883ab72593a0cc97abbccce7.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_dpad_vertical_outline.svg.import b/assets/images/gamepad/wii/wii_dpad_vertical_outline.svg.import
index aa2dd3e43..1713f13b8 100644
--- a/assets/images/gamepad/wii/wii_dpad_vertical_outline.svg.import
+++ b/assets/images/gamepad/wii/wii_dpad_vertical_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://f0sxwhs7v57e"
+uid="uid://cnvpwsclbvmc"
path="res://.godot/imported/wii_dpad_vertical_outline.svg-358ead95c3668b7d6eb3816d927ac548.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_stick.svg.import b/assets/images/gamepad/wii/wii_stick.svg.import
index 82923c8c5..59e5f94da 100644
--- a/assets/images/gamepad/wii/wii_stick.svg.import
+++ b/assets/images/gamepad/wii/wii_stick.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://lrvbqjy5628j"
+uid="uid://cw0vbsxgb8tu4"
path="res://.godot/imported/wii_stick.svg-656b9ab24d6bb7a53bd43e36664ed282.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_stick_down.svg.import b/assets/images/gamepad/wii/wii_stick_down.svg.import
index 51fead1ee..efa1217af 100644
--- a/assets/images/gamepad/wii/wii_stick_down.svg.import
+++ b/assets/images/gamepad/wii/wii_stick_down.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cupr1886nqj3j"
+uid="uid://8rr2m346sp5f"
path="res://.godot/imported/wii_stick_down.svg-c42c14a0486d97ce39a3d05183a782a8.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_stick_horizontal.svg.import b/assets/images/gamepad/wii/wii_stick_horizontal.svg.import
index a549324cb..1ff9c2da4 100644
--- a/assets/images/gamepad/wii/wii_stick_horizontal.svg.import
+++ b/assets/images/gamepad/wii/wii_stick_horizontal.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dkdy5fucs4arc"
+uid="uid://dx3f113p2raoa"
path="res://.godot/imported/wii_stick_horizontal.svg-d40e99f38848a37375b43a41a43cd302.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_stick_l.svg.import b/assets/images/gamepad/wii/wii_stick_l.svg.import
index 534f6382c..d3de29d44 100644
--- a/assets/images/gamepad/wii/wii_stick_l.svg.import
+++ b/assets/images/gamepad/wii/wii_stick_l.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bely1hxf8ye66"
+uid="uid://be2oop0pkkrfr"
path="res://.godot/imported/wii_stick_l.svg-3c790a5a9cd8acfd3e5ff45bd400ff1a.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_stick_l_down.svg.import b/assets/images/gamepad/wii/wii_stick_l_down.svg.import
index 57802c314..7fec52a94 100644
--- a/assets/images/gamepad/wii/wii_stick_l_down.svg.import
+++ b/assets/images/gamepad/wii/wii_stick_l_down.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://ckxfscck63s5f"
+uid="uid://b62hrhqt3u6aq"
path="res://.godot/imported/wii_stick_l_down.svg-cafd36e791319f35361d36245121246f.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_stick_l_horizontal.svg.import b/assets/images/gamepad/wii/wii_stick_l_horizontal.svg.import
index 69bebd17d..e483d1e6c 100644
--- a/assets/images/gamepad/wii/wii_stick_l_horizontal.svg.import
+++ b/assets/images/gamepad/wii/wii_stick_l_horizontal.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://de40hwwgj4pyg"
+uid="uid://bdnh7cietk6ry"
path="res://.godot/imported/wii_stick_l_horizontal.svg-d216f3a521363660a7d6eb66bba8290a.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_stick_l_left.svg.import b/assets/images/gamepad/wii/wii_stick_l_left.svg.import
index c063f5fa0..2bdf89529 100644
--- a/assets/images/gamepad/wii/wii_stick_l_left.svg.import
+++ b/assets/images/gamepad/wii/wii_stick_l_left.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cys7i0bdjrj8o"
+uid="uid://cayyt75fsa6bt"
path="res://.godot/imported/wii_stick_l_left.svg-fe2b5a51394d14548875f9854d1794e7.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_stick_l_right.svg.import b/assets/images/gamepad/wii/wii_stick_l_right.svg.import
index 4ab1b26e5..8de6792be 100644
--- a/assets/images/gamepad/wii/wii_stick_l_right.svg.import
+++ b/assets/images/gamepad/wii/wii_stick_l_right.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://d1wpua221rg0d"
+uid="uid://c6nsxqqqhlnfl"
path="res://.godot/imported/wii_stick_l_right.svg-9685ed83275ba4ddc47818057a37f5d5.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_stick_l_up.svg.import b/assets/images/gamepad/wii/wii_stick_l_up.svg.import
index a803a092a..7ea9a4e99 100644
--- a/assets/images/gamepad/wii/wii_stick_l_up.svg.import
+++ b/assets/images/gamepad/wii/wii_stick_l_up.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b83a1mvgp4e1d"
+uid="uid://d1xtkprhbogn6"
path="res://.godot/imported/wii_stick_l_up.svg-4259065159b4e4526b5189199d47c02a.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_stick_l_vertical.svg.import b/assets/images/gamepad/wii/wii_stick_l_vertical.svg.import
index 6a49b376b..708847885 100644
--- a/assets/images/gamepad/wii/wii_stick_l_vertical.svg.import
+++ b/assets/images/gamepad/wii/wii_stick_l_vertical.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://d4j4xhngd5k6a"
+uid="uid://cw7s3xgc0dlnm"
path="res://.godot/imported/wii_stick_l_vertical.svg-b1635b9fea322026ac7d800a0ed3be03.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_stick_left.svg.import b/assets/images/gamepad/wii/wii_stick_left.svg.import
index e3ce64cf1..4d276090e 100644
--- a/assets/images/gamepad/wii/wii_stick_left.svg.import
+++ b/assets/images/gamepad/wii/wii_stick_left.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cig74ev1kcwik"
+uid="uid://byqki84xmkgdj"
path="res://.godot/imported/wii_stick_left.svg-efde037995799ab72512631e42091c45.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_stick_r.svg.import b/assets/images/gamepad/wii/wii_stick_r.svg.import
index 7b24cb876..08953ec57 100644
--- a/assets/images/gamepad/wii/wii_stick_r.svg.import
+++ b/assets/images/gamepad/wii/wii_stick_r.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://1ulk2ip48xbb"
+uid="uid://b66t42cwr1l0a"
path="res://.godot/imported/wii_stick_r.svg-d5630162a8c3340f85877784f95078a3.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_stick_r_down.svg.import b/assets/images/gamepad/wii/wii_stick_r_down.svg.import
index 728201fff..d3cd7e3ec 100644
--- a/assets/images/gamepad/wii/wii_stick_r_down.svg.import
+++ b/assets/images/gamepad/wii/wii_stick_r_down.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://kiiav02uwggo"
+uid="uid://chinkv4vury2k"
path="res://.godot/imported/wii_stick_r_down.svg-39269d81a6327ae5844820c7aa51b233.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_stick_r_horizontal.svg.import b/assets/images/gamepad/wii/wii_stick_r_horizontal.svg.import
index b1354391a..bbb1bd679 100644
--- a/assets/images/gamepad/wii/wii_stick_r_horizontal.svg.import
+++ b/assets/images/gamepad/wii/wii_stick_r_horizontal.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dyc0gl7h8rvos"
+uid="uid://cacctfx7ycs38"
path="res://.godot/imported/wii_stick_r_horizontal.svg-477399d6e9fe3a34a0530cfdfd4b79bb.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_stick_r_left.svg.import b/assets/images/gamepad/wii/wii_stick_r_left.svg.import
index ae2d08551..f1debd3f4 100644
--- a/assets/images/gamepad/wii/wii_stick_r_left.svg.import
+++ b/assets/images/gamepad/wii/wii_stick_r_left.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://1wsl7nfb0mgq"
+uid="uid://b6iw7hrjmsdjb"
path="res://.godot/imported/wii_stick_r_left.svg-dbdfa0e18a4325ff7b2ca5036c510440.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_stick_r_right.svg.import b/assets/images/gamepad/wii/wii_stick_r_right.svg.import
index 67eb475ad..9229a25a2 100644
--- a/assets/images/gamepad/wii/wii_stick_r_right.svg.import
+++ b/assets/images/gamepad/wii/wii_stick_r_right.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://da6rm2k5k3qw1"
+uid="uid://0b7h08ywmk7k"
path="res://.godot/imported/wii_stick_r_right.svg-a24d810dd88d67d60e0260cc7ec51c6e.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_stick_r_up.svg.import b/assets/images/gamepad/wii/wii_stick_r_up.svg.import
index ebd0173d5..bcab70177 100644
--- a/assets/images/gamepad/wii/wii_stick_r_up.svg.import
+++ b/assets/images/gamepad/wii/wii_stick_r_up.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://crtooonvlnwhy"
+uid="uid://bmegwrr3mn70f"
path="res://.godot/imported/wii_stick_r_up.svg-1b2c48383d6bf2b549de04181e4bc73c.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_stick_r_vertical.svg.import b/assets/images/gamepad/wii/wii_stick_r_vertical.svg.import
index 32c1871e8..90323756c 100644
--- a/assets/images/gamepad/wii/wii_stick_r_vertical.svg.import
+++ b/assets/images/gamepad/wii/wii_stick_r_vertical.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dw6waqj1aj5mn"
+uid="uid://c6hnyqorwu4wf"
path="res://.godot/imported/wii_stick_r_vertical.svg-f845e8f103906a7ce358b75d77f997f1.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_stick_right.svg.import b/assets/images/gamepad/wii/wii_stick_right.svg.import
index a8541ec75..9faeb0c4a 100644
--- a/assets/images/gamepad/wii/wii_stick_right.svg.import
+++ b/assets/images/gamepad/wii/wii_stick_right.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dbnrcg1768db8"
+uid="uid://d1iutll6165h2"
path="res://.godot/imported/wii_stick_right.svg-41870e98be3d50788fcb3da9a9c8265e.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_stick_top_l.svg.import b/assets/images/gamepad/wii/wii_stick_top_l.svg.import
index 938367b23..2e6064a55 100644
--- a/assets/images/gamepad/wii/wii_stick_top_l.svg.import
+++ b/assets/images/gamepad/wii/wii_stick_top_l.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dkk0t8j8m05e5"
+uid="uid://bguehceyrfnhv"
path="res://.godot/imported/wii_stick_top_l.svg-e83c6ce225e9f5013948bea59477d964.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_stick_top_r.svg.import b/assets/images/gamepad/wii/wii_stick_top_r.svg.import
index 9455bc4d5..b63e212bd 100644
--- a/assets/images/gamepad/wii/wii_stick_top_r.svg.import
+++ b/assets/images/gamepad/wii/wii_stick_top_r.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://ynvb08ar0rgk"
+uid="uid://40xbsh4571vs"
path="res://.godot/imported/wii_stick_top_r.svg-8e8678fe1959755506985023a50da2c9.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_stick_up.svg.import b/assets/images/gamepad/wii/wii_stick_up.svg.import
index b748330f6..2d6325672 100644
--- a/assets/images/gamepad/wii/wii_stick_up.svg.import
+++ b/assets/images/gamepad/wii/wii_stick_up.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://c6yx2n3hyyb8r"
+uid="uid://ct1ktqpeouk7a"
path="res://.godot/imported/wii_stick_up.svg-b77b47134f8f313e593e96dca0389ec9.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wii/wii_stick_vertical.svg.import b/assets/images/gamepad/wii/wii_stick_vertical.svg.import
index e0d5bd6ef..5d087004b 100644
--- a/assets/images/gamepad/wii/wii_stick_vertical.svg.import
+++ b/assets/images/gamepad/wii/wii_stick_vertical.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://gorv65b1ahqs"
+uid="uid://ceobf3dmi8aq3"
path="res://.godot/imported/wii_stick_vertical.svg-4ba3650bc28bf58edd614f042288dcd5.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/controller_wiiu_pro.svg.import b/assets/images/gamepad/wiiu/controller_wiiu_pro.svg.import
index d606a41d2..4bc243ab4 100644
--- a/assets/images/gamepad/wiiu/controller_wiiu_pro.svg.import
+++ b/assets/images/gamepad/wiiu/controller_wiiu_pro.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://yf77an3r1cdn"
+uid="uid://dfw226f6el2uf"
path="res://.godot/imported/controller_wiiu_pro.svg-78a3268c1a861555f3d383c33852f853.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_button_1.svg.import b/assets/images/gamepad/wiiu/wiiu_button_1.svg.import
index 0e836f56a..fdbe52cfb 100644
--- a/assets/images/gamepad/wiiu/wiiu_button_1.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_button_1.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://df75x0thccllb"
+uid="uid://dwgioia8g50jh"
path="res://.godot/imported/wiiu_button_1.svg-5ec5865e13e326b30c4152a6fa4f224e.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_button_1_outline.svg.import b/assets/images/gamepad/wiiu/wiiu_button_1_outline.svg.import
index 851d96e00..5a3973e20 100644
--- a/assets/images/gamepad/wiiu/wiiu_button_1_outline.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_button_1_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bbfnaw7hh8qe5"
+uid="uid://c533xywvwcydb"
path="res://.godot/imported/wiiu_button_1_outline.svg-c6b36e891d1ea47056bbf438e5c0dd7d.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_button_2.svg.import b/assets/images/gamepad/wiiu/wiiu_button_2.svg.import
index a47023a42..7150bdf68 100644
--- a/assets/images/gamepad/wiiu/wiiu_button_2.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_button_2.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b8wnfacjshkhq"
+uid="uid://dahlvx4nsc8g3"
path="res://.godot/imported/wiiu_button_2.svg-151c311b19a1945370285562791b1984.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_button_2_outline.svg.import b/assets/images/gamepad/wiiu/wiiu_button_2_outline.svg.import
index 50482632f..95f0b43d9 100644
--- a/assets/images/gamepad/wiiu/wiiu_button_2_outline.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_button_2_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dywbnqhf77i2c"
+uid="uid://cmt0t6egk47ag"
path="res://.godot/imported/wiiu_button_2_outline.svg-9a4d605d99d0b95c9d607db1536e9c1c.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_button_a.svg.import b/assets/images/gamepad/wiiu/wiiu_button_a.svg.import
index 3cad62af3..64d4d507f 100644
--- a/assets/images/gamepad/wiiu/wiiu_button_a.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_button_a.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dip43m6hyqkk1"
+uid="uid://crtwqn7qlxgpx"
path="res://.godot/imported/wiiu_button_a.svg-dc5253a0d9e9654dd4846000dacad345.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_button_a_outline.svg.import b/assets/images/gamepad/wiiu/wiiu_button_a_outline.svg.import
index 3cd021914..0de584cf0 100644
--- a/assets/images/gamepad/wiiu/wiiu_button_a_outline.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_button_a_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dgogoqks4w234"
+uid="uid://dbaumq746yl48"
path="res://.godot/imported/wiiu_button_a_outline.svg-19838785d2158a14ed7a777f19bca626.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_button_b.svg.import b/assets/images/gamepad/wiiu/wiiu_button_b.svg.import
index ee706ec69..1cae2a4cd 100644
--- a/assets/images/gamepad/wiiu/wiiu_button_b.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_button_b.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://gy5pspnwa2gd"
+uid="uid://wm54l6h6moc6"
path="res://.godot/imported/wiiu_button_b.svg-9899435b3db638d531c06d554c021e61.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_button_b_outline.svg.import b/assets/images/gamepad/wiiu/wiiu_button_b_outline.svg.import
index 84cf10862..7073180ea 100644
--- a/assets/images/gamepad/wiiu/wiiu_button_b_outline.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_button_b_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://c3avmb3v5li84"
+uid="uid://2w0q401cvioo"
path="res://.godot/imported/wiiu_button_b_outline.svg-f69d6eee07fc94b811f4eb47672ee5dc.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_button_home.svg.import b/assets/images/gamepad/wiiu/wiiu_button_home.svg.import
index 47897b7cb..81b1df2e1 100644
--- a/assets/images/gamepad/wiiu/wiiu_button_home.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_button_home.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cvc4p2u5xulri"
+uid="uid://byt2y2jf63dp8"
path="res://.godot/imported/wiiu_button_home.svg-b0c37b499db55db18c20b214d31ba2db.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_button_home_outline.svg.import b/assets/images/gamepad/wiiu/wiiu_button_home_outline.svg.import
index d1ea0bda3..2326cdb9d 100644
--- a/assets/images/gamepad/wiiu/wiiu_button_home_outline.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_button_home_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bydix7rhocxnp"
+uid="uid://b2hx0mp4v5oha"
path="res://.godot/imported/wiiu_button_home_outline.svg-07cd6c192e2619f405adc431f06e53f8.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_button_l.svg.import b/assets/images/gamepad/wiiu/wiiu_button_l.svg.import
index 8c22dcbfe..2618a4d9f 100644
--- a/assets/images/gamepad/wiiu/wiiu_button_l.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_button_l.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://k1i0rxhfmi1y"
+uid="uid://dg5d67wp1j076"
path="res://.godot/imported/wiiu_button_l.svg-e8ce66b52e084e3b3bbc26e3cd6861c9.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_button_l_outline.svg.import b/assets/images/gamepad/wiiu/wiiu_button_l_outline.svg.import
index c777ec220..9f74b9d80 100644
--- a/assets/images/gamepad/wiiu/wiiu_button_l_outline.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_button_l_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bup8vd3ofol7b"
+uid="uid://c1lu66fawak0o"
path="res://.godot/imported/wiiu_button_l_outline.svg-819d08825063c8337b2f4328a087ab0e.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_button_minus.svg.import b/assets/images/gamepad/wiiu/wiiu_button_minus.svg.import
index 07e9f89bd..fa69c6cd2 100644
--- a/assets/images/gamepad/wiiu/wiiu_button_minus.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_button_minus.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dwr4yd5ayosvx"
+uid="uid://bju5kflh4sjr6"
path="res://.godot/imported/wiiu_button_minus.svg-0f0bac401f0eab03018c71d6235538f4.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_button_minus_outline.svg.import b/assets/images/gamepad/wiiu/wiiu_button_minus_outline.svg.import
index b48f3ede3..2a97a3ba4 100644
--- a/assets/images/gamepad/wiiu/wiiu_button_minus_outline.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_button_minus_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://c8h7gh5v56cyc"
+uid="uid://cenndgiblg7q0"
path="res://.godot/imported/wiiu_button_minus_outline.svg-ddb7b6291194709db2583c789a2d4cb3.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_button_plus.svg.import b/assets/images/gamepad/wiiu/wiiu_button_plus.svg.import
index 464ed064a..43012f0ff 100644
--- a/assets/images/gamepad/wiiu/wiiu_button_plus.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_button_plus.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bc05a5u1fyu7x"
+uid="uid://b03cesqenwbl4"
path="res://.godot/imported/wiiu_button_plus.svg-75058bfa797da2dee7227c18fe8a79fd.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_button_plus_outline.svg.import b/assets/images/gamepad/wiiu/wiiu_button_plus_outline.svg.import
index a25a7746d..fa308faf7 100644
--- a/assets/images/gamepad/wiiu/wiiu_button_plus_outline.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_button_plus_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://qdr1vhpp5y5l"
+uid="uid://dwa4pfoqdw40y"
path="res://.godot/imported/wiiu_button_plus_outline.svg-46db7f53b2292e789d188b0c92795bc6.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_button_power.svg.import b/assets/images/gamepad/wiiu/wiiu_button_power.svg.import
index 0628e1c8a..e2b5f5a02 100644
--- a/assets/images/gamepad/wiiu/wiiu_button_power.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_button_power.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b5884480qhqd8"
+uid="uid://cy203nju4qp7f"
path="res://.godot/imported/wiiu_button_power.svg-1d981fb732728e6b380a8da9f103dea3.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_button_power_outline.svg.import b/assets/images/gamepad/wiiu/wiiu_button_power_outline.svg.import
index edd313116..eb798873d 100644
--- a/assets/images/gamepad/wiiu/wiiu_button_power_outline.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_button_power_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dj1yx2icni1ny"
+uid="uid://btsa7lj3qxp36"
path="res://.godot/imported/wiiu_button_power_outline.svg-a82860715b59e45e458cb5fe71978a74.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_button_r.svg.import b/assets/images/gamepad/wiiu/wiiu_button_r.svg.import
index e11e2fdb7..2106b749a 100644
--- a/assets/images/gamepad/wiiu/wiiu_button_r.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_button_r.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://d00jbvyklnc50"
+uid="uid://bs2rn6xjkn5bt"
path="res://.godot/imported/wiiu_button_r.svg-8b4f9aad7545f1a8d3a135f43d1d8d14.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_button_r_outline.svg.import b/assets/images/gamepad/wiiu/wiiu_button_r_outline.svg.import
index c4f7d8202..c14b8c333 100644
--- a/assets/images/gamepad/wiiu/wiiu_button_r_outline.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_button_r_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bngnbdyvit2tv"
+uid="uid://qj3b6hpwikow"
path="res://.godot/imported/wiiu_button_r_outline.svg-0330e27457a4a78e7486fd719a3e8af9.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_button_tv.svg.import b/assets/images/gamepad/wiiu/wiiu_button_tv.svg.import
index f2b5c28d5..6404d08a9 100644
--- a/assets/images/gamepad/wiiu/wiiu_button_tv.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_button_tv.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dw1x1emip8y30"
+uid="uid://csyjs5lwjwnu6"
path="res://.godot/imported/wiiu_button_tv.svg-29cace85ff8a35e7157d406635e4ec2c.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_button_tv_outline.svg.import b/assets/images/gamepad/wiiu/wiiu_button_tv_outline.svg.import
index 8d5f280c8..60fc66088 100644
--- a/assets/images/gamepad/wiiu/wiiu_button_tv_outline.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_button_tv_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://gobm4m0sn4wk"
+uid="uid://c5pkpa6n7ytxu"
path="res://.godot/imported/wiiu_button_tv_outline.svg-dcea5d7d9107df22e89ead6ee2df8278.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_button_x.svg.import b/assets/images/gamepad/wiiu/wiiu_button_x.svg.import
index d3510718a..aa28f51ba 100644
--- a/assets/images/gamepad/wiiu/wiiu_button_x.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_button_x.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b50n645eq3huj"
+uid="uid://dnfqug1or5qp6"
path="res://.godot/imported/wiiu_button_x.svg-008cc99e8c0da1904a23f90cd275b25e.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_button_x_outline.svg.import b/assets/images/gamepad/wiiu/wiiu_button_x_outline.svg.import
index c4a0522e3..f62fbe6d9 100644
--- a/assets/images/gamepad/wiiu/wiiu_button_x_outline.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_button_x_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bsg32vurc33ed"
+uid="uid://bg83erlbwmj3k"
path="res://.godot/imported/wiiu_button_x_outline.svg-a3577f4d3c26b9cf3f41d34c0f1be3dc.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_button_y.svg.import b/assets/images/gamepad/wiiu/wiiu_button_y.svg.import
index 5e78ae459..2540f4ffc 100644
--- a/assets/images/gamepad/wiiu/wiiu_button_y.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_button_y.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bjgq3bmrsh3fv"
+uid="uid://bxvct1cyrogov"
path="res://.godot/imported/wiiu_button_y.svg-e7a51e33c6a0a7354c8fefdb71227f78.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_button_y_outline.svg.import b/assets/images/gamepad/wiiu/wiiu_button_y_outline.svg.import
index 2bb0f39c0..41f5e75a6 100644
--- a/assets/images/gamepad/wiiu/wiiu_button_y_outline.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_button_y_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b4c3nb05jv11d"
+uid="uid://bvbei87ttm6v3"
path="res://.godot/imported/wiiu_button_y_outline.svg-36d1935f7e2502c64a5220cbdf0f6409.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_button_zl.svg.import b/assets/images/gamepad/wiiu/wiiu_button_zl.svg.import
index 57b841c4e..14e499841 100644
--- a/assets/images/gamepad/wiiu/wiiu_button_zl.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_button_zl.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bgp0kk656kp3j"
+uid="uid://bq82fclhupln8"
path="res://.godot/imported/wiiu_button_zl.svg-979de8055e9bc26530754eb97e160445.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_button_zl_outline.svg.import b/assets/images/gamepad/wiiu/wiiu_button_zl_outline.svg.import
index 5d39f1f17..6f6ea4dc1 100644
--- a/assets/images/gamepad/wiiu/wiiu_button_zl_outline.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_button_zl_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://chxhfi1eipp5x"
+uid="uid://rgbq886q84ot"
path="res://.godot/imported/wiiu_button_zl_outline.svg-3d5742a6688b848781afc44f5009c5ba.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_button_zr.svg.import b/assets/images/gamepad/wiiu/wiiu_button_zr.svg.import
index 6cf4b7b5e..d2cea66f6 100644
--- a/assets/images/gamepad/wiiu/wiiu_button_zr.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_button_zr.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://1rj547t8hqmj"
+uid="uid://dqh3lmvu4sm21"
path="res://.godot/imported/wiiu_button_zr.svg-cdce4ca396b5ffe162f7a0a8821c963e.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_button_zr_outline.svg.import b/assets/images/gamepad/wiiu/wiiu_button_zr_outline.svg.import
index 283659f82..522525281 100644
--- a/assets/images/gamepad/wiiu/wiiu_button_zr_outline.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_button_zr_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cgee110krbkjt"
+uid="uid://b03i71uoh443h"
path="res://.godot/imported/wiiu_button_zr_outline.svg-23f6e76e9ca0be26447d8863f767fa49.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_controller.svg.import b/assets/images/gamepad/wiiu/wiiu_controller.svg.import
index 4d5b006a1..75b49c3bb 100644
--- a/assets/images/gamepad/wiiu/wiiu_controller.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_controller.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://byfgrcpjy2wcx"
+uid="uid://dy312mcan4x4s"
path="res://.godot/imported/wiiu_controller.svg-eacb2e68cb1f394d26f127163c4d6f6d.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_controller_down.svg.import b/assets/images/gamepad/wiiu/wiiu_controller_down.svg.import
index f97518f9d..0e4a62958 100644
--- a/assets/images/gamepad/wiiu/wiiu_controller_down.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_controller_down.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bhw4cndgm6eqq"
+uid="uid://cghi3e64bd6em"
path="res://.godot/imported/wiiu_controller_down.svg-cd64f5fb2e3704377e43adfb6c66698a.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_controller_down_outline.svg.import b/assets/images/gamepad/wiiu/wiiu_controller_down_outline.svg.import
index 966d1297a..b12dfb9c1 100644
--- a/assets/images/gamepad/wiiu/wiiu_controller_down_outline.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_controller_down_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://co6333a2apljn"
+uid="uid://dvn1n8yle23tn"
path="res://.godot/imported/wiiu_controller_down_outline.svg-d395c2c337671334dd8a7a288e185114.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_controller_outline.svg.import b/assets/images/gamepad/wiiu/wiiu_controller_outline.svg.import
index 352d7503d..472aef601 100644
--- a/assets/images/gamepad/wiiu/wiiu_controller_outline.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_controller_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dg5xmwgdfjo7l"
+uid="uid://cdk3uo4ce5vhb"
path="res://.godot/imported/wiiu_controller_outline.svg-79e0d672e143dcc612e81607777178a0.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_controller_up.svg.import b/assets/images/gamepad/wiiu/wiiu_controller_up.svg.import
index e42024c5f..fdb2106e6 100644
--- a/assets/images/gamepad/wiiu/wiiu_controller_up.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_controller_up.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bcqrkeomfttgw"
+uid="uid://blgxhcsc3nbdy"
path="res://.godot/imported/wiiu_controller_up.svg-c2bb69fe329d0b72088ebf118c9ced4b.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_controller_up_outlnie.svg.import b/assets/images/gamepad/wiiu/wiiu_controller_up_outlnie.svg.import
index c663a0740..0680eefaf 100644
--- a/assets/images/gamepad/wiiu/wiiu_controller_up_outlnie.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_controller_up_outlnie.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bmkcpgjywd4gc"
+uid="uid://drtd8ma0w7apy"
path="res://.godot/imported/wiiu_controller_up_outlnie.svg-b3486e1be69af6b8188962dfd855dd6d.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_dpad.svg.import b/assets/images/gamepad/wiiu/wiiu_dpad.svg.import
index 2dc8a5bba..192729116 100644
--- a/assets/images/gamepad/wiiu/wiiu_dpad.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_dpad.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bcuj12tfwvvy3"
+uid="uid://d4k2nl1j2h2pa"
path="res://.godot/imported/wiiu_dpad.svg-a3fbd5c1c765f029dc5059aaf0572066.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_dpad_all.svg.import b/assets/images/gamepad/wiiu/wiiu_dpad_all.svg.import
index 8d4525789..5b7b89cab 100644
--- a/assets/images/gamepad/wiiu/wiiu_dpad_all.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_dpad_all.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://beu1j3jwadr22"
+uid="uid://uk3y1pp2bq15"
path="res://.godot/imported/wiiu_dpad_all.svg-57c5314bedc7962d643febfd9ff66c24.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_dpad_down.svg.import b/assets/images/gamepad/wiiu/wiiu_dpad_down.svg.import
index b6ea3db02..7225648c5 100644
--- a/assets/images/gamepad/wiiu/wiiu_dpad_down.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_dpad_down.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bkb50jtr4pxba"
+uid="uid://d0lb1vuu1bd0m"
path="res://.godot/imported/wiiu_dpad_down.svg-567c9eb58e77d044c09d43276a5dc816.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_dpad_down_outline.svg.import b/assets/images/gamepad/wiiu/wiiu_dpad_down_outline.svg.import
index 60f6f23b9..b7f85adb9 100644
--- a/assets/images/gamepad/wiiu/wiiu_dpad_down_outline.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_dpad_down_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://ch1px7uro83y2"
+uid="uid://bkn5fhd1iv45c"
path="res://.godot/imported/wiiu_dpad_down_outline.svg-21e1e1e4bf7fa446c4fb8159673378d8.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_dpad_horizontal.svg.import b/assets/images/gamepad/wiiu/wiiu_dpad_horizontal.svg.import
index 348012f1e..59d002f3b 100644
--- a/assets/images/gamepad/wiiu/wiiu_dpad_horizontal.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_dpad_horizontal.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://c0dc3u6pc5w55"
+uid="uid://codxov8eqeayr"
path="res://.godot/imported/wiiu_dpad_horizontal.svg-4d50cfd610469c38d5a15db1d705f4f6.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_dpad_horizontal_outline.svg.import b/assets/images/gamepad/wiiu/wiiu_dpad_horizontal_outline.svg.import
index f5b4b8f3b..4d45273ad 100644
--- a/assets/images/gamepad/wiiu/wiiu_dpad_horizontal_outline.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_dpad_horizontal_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cepsbve4qaklr"
+uid="uid://cr6u4jphttwcy"
path="res://.godot/imported/wiiu_dpad_horizontal_outline.svg-20791e2ca03ac76ceb2ff2afc0967c02.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_dpad_left.svg.import b/assets/images/gamepad/wiiu/wiiu_dpad_left.svg.import
index 7018cedd1..ce09015d1 100644
--- a/assets/images/gamepad/wiiu/wiiu_dpad_left.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_dpad_left.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bvh6rsmubn4d4"
+uid="uid://bku4fkvbmd68y"
path="res://.godot/imported/wiiu_dpad_left.svg-e6cb13df4f6ca61bd7250b45837d3bdc.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_dpad_left_outline.svg.import b/assets/images/gamepad/wiiu/wiiu_dpad_left_outline.svg.import
index 14aab6a29..8a77b9848 100644
--- a/assets/images/gamepad/wiiu/wiiu_dpad_left_outline.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_dpad_left_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://s4vb187yjudt"
+uid="uid://c0iorpod5q0gl"
path="res://.godot/imported/wiiu_dpad_left_outline.svg-a2146bcf2c202c767046bb70f7ea8f22.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_dpad_none.svg.import b/assets/images/gamepad/wiiu/wiiu_dpad_none.svg.import
index 043d19e0f..d0a695966 100644
--- a/assets/images/gamepad/wiiu/wiiu_dpad_none.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_dpad_none.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bgvhkex7wco03"
+uid="uid://dp6jrl45siaku"
path="res://.godot/imported/wiiu_dpad_none.svg-394322d348eae7ff5684e1f7240a295c.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_dpad_right.svg.import b/assets/images/gamepad/wiiu/wiiu_dpad_right.svg.import
index d49ea66ab..10a171fe9 100644
--- a/assets/images/gamepad/wiiu/wiiu_dpad_right.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_dpad_right.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://djy25p3v12033"
+uid="uid://d0iplpc4ni6dc"
path="res://.godot/imported/wiiu_dpad_right.svg-1ff4846823a94d7624aaa35c0773b229.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_dpad_right_outline.svg.import b/assets/images/gamepad/wiiu/wiiu_dpad_right_outline.svg.import
index 13b8784bc..6ddafe32c 100644
--- a/assets/images/gamepad/wiiu/wiiu_dpad_right_outline.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_dpad_right_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://mg0kayawmdne"
+uid="uid://ctco0tv7h6bec"
path="res://.godot/imported/wiiu_dpad_right_outline.svg-94d66b73b22550e8d043d4e5f5b3cf97.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_dpad_up.svg.import b/assets/images/gamepad/wiiu/wiiu_dpad_up.svg.import
index 0c45e1bb2..12aae8e88 100644
--- a/assets/images/gamepad/wiiu/wiiu_dpad_up.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_dpad_up.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cp5ovhb3qrm0m"
+uid="uid://bg8ecant07gfr"
path="res://.godot/imported/wiiu_dpad_up.svg-a0f3ef05a04dec5123fb95133769d2e0.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_dpad_up_outline.svg.import b/assets/images/gamepad/wiiu/wiiu_dpad_up_outline.svg.import
index 32687407c..122399341 100644
--- a/assets/images/gamepad/wiiu/wiiu_dpad_up_outline.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_dpad_up_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://be4ccsanl6w5r"
+uid="uid://cxdkv8wmor1px"
path="res://.godot/imported/wiiu_dpad_up_outline.svg-9ecc2cc2fdc6f18f599fc1711aed5e9d.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_dpad_vertical.svg.import b/assets/images/gamepad/wiiu/wiiu_dpad_vertical.svg.import
index 364326bcb..862e63bf7 100644
--- a/assets/images/gamepad/wiiu/wiiu_dpad_vertical.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_dpad_vertical.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://sf2eaq4ddbth"
+uid="uid://dnoson8ys2rb2"
path="res://.godot/imported/wiiu_dpad_vertical.svg-f011156bbde3833344cb012660e44b23.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_dpad_vertical_outline.svg.import b/assets/images/gamepad/wiiu/wiiu_dpad_vertical_outline.svg.import
index 5e1f2b621..7d9ec329f 100644
--- a/assets/images/gamepad/wiiu/wiiu_dpad_vertical_outline.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_dpad_vertical_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://uokqhslfubmg"
+uid="uid://d2d05nbwg4p37"
path="res://.godot/imported/wiiu_dpad_vertical_outline.svg-2b5c2149ee0b3094a0ea111ef06216a3.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_stick_l.svg.import b/assets/images/gamepad/wiiu/wiiu_stick_l.svg.import
index 2936f9229..e157dae94 100644
--- a/assets/images/gamepad/wiiu/wiiu_stick_l.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_stick_l.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://e8i108stbu7v"
+uid="uid://cjcrdudsu7dsx"
path="res://.godot/imported/wiiu_stick_l.svg-04f1f9da4dcfed3968cda6ec1d4bcb0a.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_stick_l_down.svg.import b/assets/images/gamepad/wiiu/wiiu_stick_l_down.svg.import
index 53bcb5ca5..8a17aa3cf 100644
--- a/assets/images/gamepad/wiiu/wiiu_stick_l_down.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_stick_l_down.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://c0bfex67ty7e3"
+uid="uid://cjq5x0mhdt8mh"
path="res://.godot/imported/wiiu_stick_l_down.svg-7bcfd8625b9d89d87d0df0564cc0e29c.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_stick_l_horizontal.svg.import b/assets/images/gamepad/wiiu/wiiu_stick_l_horizontal.svg.import
index 0d8eb13ec..f7ef8f98f 100644
--- a/assets/images/gamepad/wiiu/wiiu_stick_l_horizontal.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_stick_l_horizontal.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bnnbr484ph6gi"
+uid="uid://cfs0l1cpsaur5"
path="res://.godot/imported/wiiu_stick_l_horizontal.svg-01e0d7483d6df2559bc91c913836b20f.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_stick_l_left.svg.import b/assets/images/gamepad/wiiu/wiiu_stick_l_left.svg.import
index 4e04bb94a..675d6ac00 100644
--- a/assets/images/gamepad/wiiu/wiiu_stick_l_left.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_stick_l_left.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dcl6aqrxeh2or"
+uid="uid://bjj75d7d2m3th"
path="res://.godot/imported/wiiu_stick_l_left.svg-9745e48ab58ba201e4fcbdf63a62de42.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_stick_l_right.svg.import b/assets/images/gamepad/wiiu/wiiu_stick_l_right.svg.import
index 784960a7b..f84043777 100644
--- a/assets/images/gamepad/wiiu/wiiu_stick_l_right.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_stick_l_right.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bcc3s7yr1taaf"
+uid="uid://cg5na4cj11g8i"
path="res://.godot/imported/wiiu_stick_l_right.svg-6bc93a0e21fc7529a08da0df4f5a0915.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_stick_l_up.svg.import b/assets/images/gamepad/wiiu/wiiu_stick_l_up.svg.import
index c19f869ab..3379d7c01 100644
--- a/assets/images/gamepad/wiiu/wiiu_stick_l_up.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_stick_l_up.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cj53jm83ttpey"
+uid="uid://bx1ejne0hf32e"
path="res://.godot/imported/wiiu_stick_l_up.svg-02e3c39280acd6d39f036d3752c3422c.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_stick_l_vertical.svg.import b/assets/images/gamepad/wiiu/wiiu_stick_l_vertical.svg.import
index 4d73a5c44..b2a732a48 100644
--- a/assets/images/gamepad/wiiu/wiiu_stick_l_vertical.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_stick_l_vertical.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cmcjco6h3mly5"
+uid="uid://11h1m6jx4bhy"
path="res://.godot/imported/wiiu_stick_l_vertical.svg-55e56d9cf079f40f0425c9c06b9fe3b1.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_stick_r.svg.import b/assets/images/gamepad/wiiu/wiiu_stick_r.svg.import
index 70972d874..cbdc8be25 100644
--- a/assets/images/gamepad/wiiu/wiiu_stick_r.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_stick_r.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://d3sxs8lvy2jpi"
+uid="uid://ds66flubaekdw"
path="res://.godot/imported/wiiu_stick_r.svg-d9deb19522a756574e2e4dadf04c6e34.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_stick_r_down.svg.import b/assets/images/gamepad/wiiu/wiiu_stick_r_down.svg.import
index 777a08cea..5ae788e7d 100644
--- a/assets/images/gamepad/wiiu/wiiu_stick_r_down.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_stick_r_down.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://c1lyv4u6w7jhj"
+uid="uid://b6d2emjvdsgjd"
path="res://.godot/imported/wiiu_stick_r_down.svg-b1f01bd0fe0b941dadc4325e05513ad7.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_stick_r_horizontal.svg.import b/assets/images/gamepad/wiiu/wiiu_stick_r_horizontal.svg.import
index 0e7797025..eed3fe1ab 100644
--- a/assets/images/gamepad/wiiu/wiiu_stick_r_horizontal.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_stick_r_horizontal.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://c1pynyuwsswh4"
+uid="uid://cwmi2kaapq55b"
path="res://.godot/imported/wiiu_stick_r_horizontal.svg-9bfda2ab53bbb34acfbc0ede27275483.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_stick_r_left.svg.import b/assets/images/gamepad/wiiu/wiiu_stick_r_left.svg.import
index 347289321..773ac676c 100644
--- a/assets/images/gamepad/wiiu/wiiu_stick_r_left.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_stick_r_left.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://ddvuo0uqv2wo2"
+uid="uid://tjp5ctarwubn"
path="res://.godot/imported/wiiu_stick_r_left.svg-2b214a8bce9746d60ba7dfaaad59b90b.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_stick_r_right.svg.import b/assets/images/gamepad/wiiu/wiiu_stick_r_right.svg.import
index 2c6ac2aeb..2576b689d 100644
--- a/assets/images/gamepad/wiiu/wiiu_stick_r_right.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_stick_r_right.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cpx4vmnilefas"
+uid="uid://btsmc4eytrxe3"
path="res://.godot/imported/wiiu_stick_r_right.svg-d7c14941ef1c3293766688dddbc380a2.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_stick_r_up.svg.import b/assets/images/gamepad/wiiu/wiiu_stick_r_up.svg.import
index a6d95b045..aa8e5933c 100644
--- a/assets/images/gamepad/wiiu/wiiu_stick_r_up.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_stick_r_up.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://chgkwr206vyqu"
+uid="uid://bsymx5elr5qxt"
path="res://.godot/imported/wiiu_stick_r_up.svg-d48f29d5870c1143f41d3b5f78e3344a.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_stick_r_vertical.svg.import b/assets/images/gamepad/wiiu/wiiu_stick_r_vertical.svg.import
index ce578f277..b893fc3b6 100644
--- a/assets/images/gamepad/wiiu/wiiu_stick_r_vertical.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_stick_r_vertical.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://djm337j48c7yy"
+uid="uid://dttvnhmt43h3p"
path="res://.godot/imported/wiiu_stick_r_vertical.svg-1ca5cdabbc3aaace31cd54c68c4c98d0.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_stick_top_l.svg.import b/assets/images/gamepad/wiiu/wiiu_stick_top_l.svg.import
index 5ffd0c4e8..efe5345c7 100644
--- a/assets/images/gamepad/wiiu/wiiu_stick_top_l.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_stick_top_l.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cuv4fji0r5ggp"
+uid="uid://byto6orxyr3ug"
path="res://.godot/imported/wiiu_stick_top_l.svg-12177c0858355d1aa8c9638f8eaa4268.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/wiiu/wiiu_stick_top_r.svg.import b/assets/images/gamepad/wiiu/wiiu_stick_top_r.svg.import
index 7085f5fd6..699ca803f 100644
--- a/assets/images/gamepad/wiiu/wiiu_stick_top_r.svg.import
+++ b/assets/images/gamepad/wiiu/wiiu_stick_top_r.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://c0wk5l1n6ddam"
+uid="uid://sxqlbjkpontl"
path="res://.godot/imported/wiiu_stick_top_r.svg-12cb9a95a85c9e5e02df52fd754f89ce.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/win4/diagram.png.import b/assets/images/gamepad/win4/diagram.png.import
index 7039b8953..56d420af0 100644
--- a/assets/images/gamepad/win4/diagram.png.import
+++ b/assets/images/gamepad/win4/diagram.png.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b57nsqeawh8pm"
+uid="uid://ct7bo3dulbx0o"
path="res://.godot/imported/diagram.png-03c26c29ce498ea10cb8055b51000e4c.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/XboxOne_Diagram.png.import b/assets/images/gamepad/xbox/XboxOne_Diagram.png.import
index 42b746a43..788c64067 100644
--- a/assets/images/gamepad/xbox/XboxOne_Diagram.png.import
+++ b/assets/images/gamepad/xbox/XboxOne_Diagram.png.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bie2sf8kjawr"
+uid="uid://ceyt88pt5sogo"
path="res://.godot/imported/XboxOne_Diagram.png-528d1d386d471d3f0a4e3d004b209880.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/XboxOne_Diagram_Simple.png.import b/assets/images/gamepad/xbox/XboxOne_Diagram_Simple.png.import
index 2e8470cc0..1caa94b69 100644
--- a/assets/images/gamepad/xbox/XboxOne_Diagram_Simple.png.import
+++ b/assets/images/gamepad/xbox/XboxOne_Diagram_Simple.png.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://d0jq2ge68564v"
+uid="uid://cibfy4ssigmqm"
path="res://.godot/imported/XboxOne_Diagram_Simple.png-ee0e86525f057d115010c33ed9921fa5.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/controller_xbox360.svg.import b/assets/images/gamepad/xbox/controller_xbox360.svg.import
index d4cc2ea1f..c25a1421e 100644
--- a/assets/images/gamepad/xbox/controller_xbox360.svg.import
+++ b/assets/images/gamepad/xbox/controller_xbox360.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://rmvytw8m2h2r"
+uid="uid://cf05gacxjxdi"
path="res://.godot/imported/controller_xbox360.svg-e770ea87e1e53f27f102b9afb4da2f88.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/controller_xbox_adaptive.svg.import b/assets/images/gamepad/xbox/controller_xbox_adaptive.svg.import
index b15e2f706..ed7a702e1 100644
--- a/assets/images/gamepad/xbox/controller_xbox_adaptive.svg.import
+++ b/assets/images/gamepad/xbox/controller_xbox_adaptive.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cjou21a3nlwl7"
+uid="uid://dt3l6lhk0mdr3"
path="res://.godot/imported/controller_xbox_adaptive.svg-777c94e728519a7d798e0a7a896f11e2.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/controller_xboxone.svg.import b/assets/images/gamepad/xbox/controller_xboxone.svg.import
index 043a661b9..f08c01c6a 100644
--- a/assets/images/gamepad/xbox/controller_xboxone.svg.import
+++ b/assets/images/gamepad/xbox/controller_xboxone.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bmlowbm4srsyr"
+uid="uid://eijkgk4rk31l"
path="res://.godot/imported/controller_xboxone.svg-474b0e15e22b5b156866a964b9b3221d.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/controller_xboxseries.svg.import b/assets/images/gamepad/xbox/controller_xboxseries.svg.import
index d0a6dbcd3..df9e58059 100644
--- a/assets/images/gamepad/xbox/controller_xboxseries.svg.import
+++ b/assets/images/gamepad/xbox/controller_xboxseries.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://c16tv621e0ft3"
+uid="uid://o5yjthrf58su"
path="res://.godot/imported/controller_xboxseries.svg-afdcdb96b3c4ece83adb6b5ba0efc1ca.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_button_a.svg.import b/assets/images/gamepad/xbox/xbox_button_a.svg.import
index 7932d83c0..bbc8a910c 100644
--- a/assets/images/gamepad/xbox/xbox_button_a.svg.import
+++ b/assets/images/gamepad/xbox/xbox_button_a.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bdkrtl0k6qpie"
+uid="uid://cl4d11t0kv11a"
path="res://.godot/imported/xbox_button_a.svg-bb80ea3db87776ddc205fc0ce310ca2c.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_button_a_outline.svg.import b/assets/images/gamepad/xbox/xbox_button_a_outline.svg.import
index 55fd3467c..bf900112a 100644
--- a/assets/images/gamepad/xbox/xbox_button_a_outline.svg.import
+++ b/assets/images/gamepad/xbox/xbox_button_a_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bb0glmi2lyf1b"
+uid="uid://daqukh8da0skq"
path="res://.godot/imported/xbox_button_a_outline.svg-5c72c6c8bcb7bfe8106ed236329efc04.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_button_b.svg.import b/assets/images/gamepad/xbox/xbox_button_b.svg.import
index 1eab330e5..a1a9ddc37 100644
--- a/assets/images/gamepad/xbox/xbox_button_b.svg.import
+++ b/assets/images/gamepad/xbox/xbox_button_b.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b4fxi5irku3fp"
+uid="uid://dcucdnmw0q0ov"
path="res://.godot/imported/xbox_button_b.svg-c37f9ec87569772305819768f8b366c2.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_button_b_outline.svg.import b/assets/images/gamepad/xbox/xbox_button_b_outline.svg.import
index 8fa9f5a6b..086e213fa 100644
--- a/assets/images/gamepad/xbox/xbox_button_b_outline.svg.import
+++ b/assets/images/gamepad/xbox/xbox_button_b_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dq86lnsd771mx"
+uid="uid://b1rmsrpeo4uh"
path="res://.godot/imported/xbox_button_b_outline.svg-da48aefccd1b0e6ae5d9c0b00ad0c9a7.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_button_back.svg.import b/assets/images/gamepad/xbox/xbox_button_back.svg.import
index 49be7a6a2..16c551c4a 100644
--- a/assets/images/gamepad/xbox/xbox_button_back.svg.import
+++ b/assets/images/gamepad/xbox/xbox_button_back.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://wgefpgg5qcn4"
+uid="uid://c6tj74yf7gsxb"
path="res://.godot/imported/xbox_button_back.svg-63ec1ebb30674cb42d369ce45e17eea3.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_button_back_icon.svg.import b/assets/images/gamepad/xbox/xbox_button_back_icon.svg.import
index 62e0297a9..023e48c48 100644
--- a/assets/images/gamepad/xbox/xbox_button_back_icon.svg.import
+++ b/assets/images/gamepad/xbox/xbox_button_back_icon.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://worovimrqapy"
+uid="uid://cwxfxkby7fk2a"
path="res://.godot/imported/xbox_button_back_icon.svg-84cd4236d7f672c6a4c3ca81fd60e331.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_button_back_icon_outline.svg.import b/assets/images/gamepad/xbox/xbox_button_back_icon_outline.svg.import
index d9c5e9be7..fed8d5697 100644
--- a/assets/images/gamepad/xbox/xbox_button_back_icon_outline.svg.import
+++ b/assets/images/gamepad/xbox/xbox_button_back_icon_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bl062vt1l8m5t"
+uid="uid://bhrpqano2lehn"
path="res://.godot/imported/xbox_button_back_icon_outline.svg-7f0353c398f5d24a4610a4e6df396df1.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_button_back_outline.svg.import b/assets/images/gamepad/xbox/xbox_button_back_outline.svg.import
index 162ad080d..956c10555 100644
--- a/assets/images/gamepad/xbox/xbox_button_back_outline.svg.import
+++ b/assets/images/gamepad/xbox/xbox_button_back_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://brjy7qkptl404"
+uid="uid://ctpq56o4hvsd4"
path="res://.godot/imported/xbox_button_back_outline.svg-761f914c3a1066c09c04d9250585cf26.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_button_color_a.svg.import b/assets/images/gamepad/xbox/xbox_button_color_a.svg.import
index 9b2b45a6c..85c4ed4a1 100644
--- a/assets/images/gamepad/xbox/xbox_button_color_a.svg.import
+++ b/assets/images/gamepad/xbox/xbox_button_color_a.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dyemqkvdtk43e"
+uid="uid://cxvxwgt1vox0"
path="res://.godot/imported/xbox_button_color_a.svg-2f8eba8e6261ffeaa861e615a8c5091a.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_button_color_a_outline.svg.import b/assets/images/gamepad/xbox/xbox_button_color_a_outline.svg.import
index 18bf47a82..981f26267 100644
--- a/assets/images/gamepad/xbox/xbox_button_color_a_outline.svg.import
+++ b/assets/images/gamepad/xbox/xbox_button_color_a_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dbdplieoh63mw"
+uid="uid://bp11mma26v2gb"
path="res://.godot/imported/xbox_button_color_a_outline.svg-f60c5338bf5d411669a95b9a9d9e94af.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_button_color_b.svg.import b/assets/images/gamepad/xbox/xbox_button_color_b.svg.import
index 3980eb967..c02956317 100644
--- a/assets/images/gamepad/xbox/xbox_button_color_b.svg.import
+++ b/assets/images/gamepad/xbox/xbox_button_color_b.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bqho0a0sr6u1j"
+uid="uid://dfby3iiksln2e"
path="res://.godot/imported/xbox_button_color_b.svg-12f75c505369b364244635a0d0ac0fcf.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_button_color_b_outline.svg.import b/assets/images/gamepad/xbox/xbox_button_color_b_outline.svg.import
index 26e4d6305..5395e3332 100644
--- a/assets/images/gamepad/xbox/xbox_button_color_b_outline.svg.import
+++ b/assets/images/gamepad/xbox/xbox_button_color_b_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://jbqugaw65tjn"
+uid="uid://c66tk68snyvkp"
path="res://.godot/imported/xbox_button_color_b_outline.svg-bddbdac1738aa51d70c7b074d1232969.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_button_color_x.svg.import b/assets/images/gamepad/xbox/xbox_button_color_x.svg.import
index 9a2340c75..14bed7691 100644
--- a/assets/images/gamepad/xbox/xbox_button_color_x.svg.import
+++ b/assets/images/gamepad/xbox/xbox_button_color_x.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cuvx61nakiaoi"
+uid="uid://ojrh7msglai0"
path="res://.godot/imported/xbox_button_color_x.svg-68cb4450be80b17c17fc0274bcac944e.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_button_color_x_outline.svg.import b/assets/images/gamepad/xbox/xbox_button_color_x_outline.svg.import
index 15f06205f..098472d67 100644
--- a/assets/images/gamepad/xbox/xbox_button_color_x_outline.svg.import
+++ b/assets/images/gamepad/xbox/xbox_button_color_x_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://domfr16n5e0eq"
+uid="uid://cn7857u3ah7nc"
path="res://.godot/imported/xbox_button_color_x_outline.svg-3a762e20b5ad4d2077b6bf65d70eaf09.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_button_color_y.svg.import b/assets/images/gamepad/xbox/xbox_button_color_y.svg.import
index 58a415521..e2d4c0223 100644
--- a/assets/images/gamepad/xbox/xbox_button_color_y.svg.import
+++ b/assets/images/gamepad/xbox/xbox_button_color_y.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://ddpudi00yulrx"
+uid="uid://b81pjmldtt10s"
path="res://.godot/imported/xbox_button_color_y.svg-1d248820d20c6ef050937701e498556f.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_button_color_y_outline.svg.import b/assets/images/gamepad/xbox/xbox_button_color_y_outline.svg.import
index b17615089..38f67255b 100644
--- a/assets/images/gamepad/xbox/xbox_button_color_y_outline.svg.import
+++ b/assets/images/gamepad/xbox/xbox_button_color_y_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cn3280t4gjd8l"
+uid="uid://c2tdumulmgljk"
path="res://.godot/imported/xbox_button_color_y_outline.svg-a019af67b765f1d1eb8e74c35d8adbfd.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_button_menu.svg.import b/assets/images/gamepad/xbox/xbox_button_menu.svg.import
index 715d55ccd..2ac398eff 100644
--- a/assets/images/gamepad/xbox/xbox_button_menu.svg.import
+++ b/assets/images/gamepad/xbox/xbox_button_menu.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dagfma4wnmvw8"
+uid="uid://ckk2my0j71i3r"
path="res://.godot/imported/xbox_button_menu.svg-b58c6fabc452de1668514256375ee4bd.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_button_menu_outline.svg.import b/assets/images/gamepad/xbox/xbox_button_menu_outline.svg.import
index bf40510fe..216a6ecad 100644
--- a/assets/images/gamepad/xbox/xbox_button_menu_outline.svg.import
+++ b/assets/images/gamepad/xbox/xbox_button_menu_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dnj5fsxv46yqb"
+uid="uid://c7u3y2kb6qcr3"
path="res://.godot/imported/xbox_button_menu_outline.svg-7efbfa23f42cbcb6fed792ad892cd118.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_button_share.svg.import b/assets/images/gamepad/xbox/xbox_button_share.svg.import
index 17fd221bf..3ecefe258 100644
--- a/assets/images/gamepad/xbox/xbox_button_share.svg.import
+++ b/assets/images/gamepad/xbox/xbox_button_share.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dasqdy0fqn33r"
+uid="uid://crda44th28ovn"
path="res://.godot/imported/xbox_button_share.svg-dce1bf9ccda415346ad3deb379372594.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_button_share_outline.svg.import b/assets/images/gamepad/xbox/xbox_button_share_outline.svg.import
index 17171d1c6..332d3431e 100644
--- a/assets/images/gamepad/xbox/xbox_button_share_outline.svg.import
+++ b/assets/images/gamepad/xbox/xbox_button_share_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b4tqkf40tdq5f"
+uid="uid://ctea5mghu44vu"
path="res://.godot/imported/xbox_button_share_outline.svg-a784f1f956b9c0dae069a6bb6e0be3c8.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_button_start.svg.import b/assets/images/gamepad/xbox/xbox_button_start.svg.import
index 117491713..530fb5f79 100644
--- a/assets/images/gamepad/xbox/xbox_button_start.svg.import
+++ b/assets/images/gamepad/xbox/xbox_button_start.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dvpdtmjv4mjhh"
+uid="uid://dm4aqhsm8bo7m"
path="res://.godot/imported/xbox_button_start.svg-675d1c3d2310a53b97db1fa351891baa.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_button_start_icon.svg.import b/assets/images/gamepad/xbox/xbox_button_start_icon.svg.import
index 22122db30..144a05c3d 100644
--- a/assets/images/gamepad/xbox/xbox_button_start_icon.svg.import
+++ b/assets/images/gamepad/xbox/xbox_button_start_icon.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://lyo4d0hfj4ut"
+uid="uid://c3v2ch2hw3mhm"
path="res://.godot/imported/xbox_button_start_icon.svg-c60ef4d394b5cc1e496eaf88984b8c91.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_button_start_icon_outline.svg.import b/assets/images/gamepad/xbox/xbox_button_start_icon_outline.svg.import
index b5f27bab9..3757f659e 100644
--- a/assets/images/gamepad/xbox/xbox_button_start_icon_outline.svg.import
+++ b/assets/images/gamepad/xbox/xbox_button_start_icon_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://clgtdnaufqi7"
+uid="uid://o4ylq5slkt7y"
path="res://.godot/imported/xbox_button_start_icon_outline.svg-75e89531003513fa0a4a35cfa5d8746a.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_button_start_outline.svg.import b/assets/images/gamepad/xbox/xbox_button_start_outline.svg.import
index 855b800d0..31eea8bf5 100644
--- a/assets/images/gamepad/xbox/xbox_button_start_outline.svg.import
+++ b/assets/images/gamepad/xbox/xbox_button_start_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bc3yg3ljfduac"
+uid="uid://de8qmlbhec0ux"
path="res://.godot/imported/xbox_button_start_outline.svg-a105c21baddb3824554b1aa27f9dab78.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_button_view.svg.import b/assets/images/gamepad/xbox/xbox_button_view.svg.import
index f2ce31f3a..8e1564b29 100644
--- a/assets/images/gamepad/xbox/xbox_button_view.svg.import
+++ b/assets/images/gamepad/xbox/xbox_button_view.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://ce732ysw0pjo1"
+uid="uid://cws272by4n8r7"
path="res://.godot/imported/xbox_button_view.svg-457e98b18fe3550217eaa8b628bb7a19.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_button_view_outline.svg.import b/assets/images/gamepad/xbox/xbox_button_view_outline.svg.import
index c4c0d217d..d84bf245b 100644
--- a/assets/images/gamepad/xbox/xbox_button_view_outline.svg.import
+++ b/assets/images/gamepad/xbox/xbox_button_view_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://n1ijurfdighb"
+uid="uid://ciwwbm2xvghg3"
path="res://.godot/imported/xbox_button_view_outline.svg-e18c011fabdce4434bd073f3366b662a.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_button_x.svg.import b/assets/images/gamepad/xbox/xbox_button_x.svg.import
index 102ac9084..5973a3f04 100644
--- a/assets/images/gamepad/xbox/xbox_button_x.svg.import
+++ b/assets/images/gamepad/xbox/xbox_button_x.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://6gch2u81rmff"
+uid="uid://cjnbox2d87ta7"
path="res://.godot/imported/xbox_button_x.svg-1eccbfafb5da4b6b7b000b062c9bd219.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_button_x_outline.svg.import b/assets/images/gamepad/xbox/xbox_button_x_outline.svg.import
index 7cd5679c9..87b962f87 100644
--- a/assets/images/gamepad/xbox/xbox_button_x_outline.svg.import
+++ b/assets/images/gamepad/xbox/xbox_button_x_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dkyx3l8xmwnhh"
+uid="uid://cwhgcx6vbtqe4"
path="res://.godot/imported/xbox_button_x_outline.svg-20f267c3c0398b229f2a37aa4445e09c.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_button_y.svg.import b/assets/images/gamepad/xbox/xbox_button_y.svg.import
index 24b07d47e..aae7679e5 100644
--- a/assets/images/gamepad/xbox/xbox_button_y.svg.import
+++ b/assets/images/gamepad/xbox/xbox_button_y.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bn4hgmp4f7gr4"
+uid="uid://0jg4cw548nty"
path="res://.godot/imported/xbox_button_y.svg-7afd378b26ca7dff1a09678d75befd28.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_button_y_outline.svg.import b/assets/images/gamepad/xbox/xbox_button_y_outline.svg.import
index 2771d01c1..1e4501131 100644
--- a/assets/images/gamepad/xbox/xbox_button_y_outline.svg.import
+++ b/assets/images/gamepad/xbox/xbox_button_y_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dta0d363mjp56"
+uid="uid://vf04qhyffom3"
path="res://.godot/imported/xbox_button_y_outline.svg-db834979656473a43c55bffd35c230a3.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_dpad.svg.import b/assets/images/gamepad/xbox/xbox_dpad.svg.import
index dc84f2979..ff122f393 100644
--- a/assets/images/gamepad/xbox/xbox_dpad.svg.import
+++ b/assets/images/gamepad/xbox/xbox_dpad.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cdhd2pnbunvy3"
+uid="uid://di87v7xnlu4hd"
path="res://.godot/imported/xbox_dpad.svg-ea138d2676c93dd668df2f4dd175692c.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_dpad_all.svg.import b/assets/images/gamepad/xbox/xbox_dpad_all.svg.import
index 9907b7b9f..2c6a14449 100644
--- a/assets/images/gamepad/xbox/xbox_dpad_all.svg.import
+++ b/assets/images/gamepad/xbox/xbox_dpad_all.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://d33ypa2inoshf"
+uid="uid://52414c1rvldf"
path="res://.godot/imported/xbox_dpad_all.svg-169a5712da050446105241c1235e6010.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_dpad_down.svg.import b/assets/images/gamepad/xbox/xbox_dpad_down.svg.import
index 5080d3db8..4d87dce3c 100644
--- a/assets/images/gamepad/xbox/xbox_dpad_down.svg.import
+++ b/assets/images/gamepad/xbox/xbox_dpad_down.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bju6gytlq2div"
+uid="uid://brqqse0hid6ki"
path="res://.godot/imported/xbox_dpad_down.svg-67715dcb6a010f6eddc14e0a5d9bdbdb.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_dpad_down_outline.svg.import b/assets/images/gamepad/xbox/xbox_dpad_down_outline.svg.import
index aaae7f338..0fea2617d 100644
--- a/assets/images/gamepad/xbox/xbox_dpad_down_outline.svg.import
+++ b/assets/images/gamepad/xbox/xbox_dpad_down_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cy42kh58lpan4"
+uid="uid://ct47mctn1skhr"
path="res://.godot/imported/xbox_dpad_down_outline.svg-3768dd03bbda427ffbedd7ef6bebfa80.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_dpad_horizontal.svg.import b/assets/images/gamepad/xbox/xbox_dpad_horizontal.svg.import
index bdb1d66bf..9519384cd 100644
--- a/assets/images/gamepad/xbox/xbox_dpad_horizontal.svg.import
+++ b/assets/images/gamepad/xbox/xbox_dpad_horizontal.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://homu12tujxbw"
+uid="uid://wb6p8cij2tr5"
path="res://.godot/imported/xbox_dpad_horizontal.svg-0798a6e371de7a7e91ba63014c25807c.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_dpad_horizontal_outline.svg.import b/assets/images/gamepad/xbox/xbox_dpad_horizontal_outline.svg.import
index ff627f2a1..dc44dab89 100644
--- a/assets/images/gamepad/xbox/xbox_dpad_horizontal_outline.svg.import
+++ b/assets/images/gamepad/xbox/xbox_dpad_horizontal_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://blpl5n5beus6c"
+uid="uid://cisy02l5y4n7a"
path="res://.godot/imported/xbox_dpad_horizontal_outline.svg-8afa7c864944d4c94a30e44ab371bce3.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_dpad_left.svg.import b/assets/images/gamepad/xbox/xbox_dpad_left.svg.import
index 701f55819..46bbb3e2f 100644
--- a/assets/images/gamepad/xbox/xbox_dpad_left.svg.import
+++ b/assets/images/gamepad/xbox/xbox_dpad_left.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://candjw8elkekp"
+uid="uid://caqnkbu5b0u2q"
path="res://.godot/imported/xbox_dpad_left.svg-de98007623838331d669244a5974e011.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_dpad_left_outline.svg.import b/assets/images/gamepad/xbox/xbox_dpad_left_outline.svg.import
index 9420eb252..cf223d48b 100644
--- a/assets/images/gamepad/xbox/xbox_dpad_left_outline.svg.import
+++ b/assets/images/gamepad/xbox/xbox_dpad_left_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dtttrdlt8omtf"
+uid="uid://cxve1m3gq2fws"
path="res://.godot/imported/xbox_dpad_left_outline.svg-39483817ce2f6a7dd646f6426bfd9b87.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_dpad_none.svg.import b/assets/images/gamepad/xbox/xbox_dpad_none.svg.import
index 919f00f5f..753908fd3 100644
--- a/assets/images/gamepad/xbox/xbox_dpad_none.svg.import
+++ b/assets/images/gamepad/xbox/xbox_dpad_none.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cat1ov3iuseru"
+uid="uid://c6fbdql365x7"
path="res://.godot/imported/xbox_dpad_none.svg-448844b96111f5ead0db14d578a0a915.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_dpad_right.svg.import b/assets/images/gamepad/xbox/xbox_dpad_right.svg.import
index 12bb0de23..d779485e1 100644
--- a/assets/images/gamepad/xbox/xbox_dpad_right.svg.import
+++ b/assets/images/gamepad/xbox/xbox_dpad_right.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dcpsb03pvu0vb"
+uid="uid://b5gektw3mgp1a"
path="res://.godot/imported/xbox_dpad_right.svg-af4a893b5dc17ac86d681470cefb81e0.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_dpad_right_outline.svg.import b/assets/images/gamepad/xbox/xbox_dpad_right_outline.svg.import
index 8fbe9f141..3478c445b 100644
--- a/assets/images/gamepad/xbox/xbox_dpad_right_outline.svg.import
+++ b/assets/images/gamepad/xbox/xbox_dpad_right_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dqmbqhg1oc661"
+uid="uid://pkhdwfawpfcc"
path="res://.godot/imported/xbox_dpad_right_outline.svg-7a8a7d1b9cda40379332c7096886ece5.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_dpad_round.svg.import b/assets/images/gamepad/xbox/xbox_dpad_round.svg.import
index c90ae74ed..65940f9d6 100644
--- a/assets/images/gamepad/xbox/xbox_dpad_round.svg.import
+++ b/assets/images/gamepad/xbox/xbox_dpad_round.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dn8i3gpeijgu1"
+uid="uid://n4t36xrl15ux"
path="res://.godot/imported/xbox_dpad_round.svg-40c467bd7af68c5e122c6c75bec0135a.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_dpad_round_all.svg.import b/assets/images/gamepad/xbox/xbox_dpad_round_all.svg.import
index bfb57241f..264d07bcc 100644
--- a/assets/images/gamepad/xbox/xbox_dpad_round_all.svg.import
+++ b/assets/images/gamepad/xbox/xbox_dpad_round_all.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bbj8ampn6hgct"
+uid="uid://so0la23m3pb"
path="res://.godot/imported/xbox_dpad_round_all.svg-1ed2bc5259b0b482d639b5f250f29d57.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_dpad_round_down.svg.import b/assets/images/gamepad/xbox/xbox_dpad_round_down.svg.import
index 926a8d6c5..c8ad21468 100644
--- a/assets/images/gamepad/xbox/xbox_dpad_round_down.svg.import
+++ b/assets/images/gamepad/xbox/xbox_dpad_round_down.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dwv3f88h7uaq7"
+uid="uid://bxovdah6vnpsn"
path="res://.godot/imported/xbox_dpad_round_down.svg-59a36379fca801af7f991132a1e8949b.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_dpad_round_horizontal.svg.import b/assets/images/gamepad/xbox/xbox_dpad_round_horizontal.svg.import
index 77e241248..13bc68f74 100644
--- a/assets/images/gamepad/xbox/xbox_dpad_round_horizontal.svg.import
+++ b/assets/images/gamepad/xbox/xbox_dpad_round_horizontal.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b6gqg2b6pcrby"
+uid="uid://pdiueqpnssea"
path="res://.godot/imported/xbox_dpad_round_horizontal.svg-4fde19342e5570eb0693b48a8017b211.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_dpad_round_left.svg.import b/assets/images/gamepad/xbox/xbox_dpad_round_left.svg.import
index 460439dea..ab3cb173f 100644
--- a/assets/images/gamepad/xbox/xbox_dpad_round_left.svg.import
+++ b/assets/images/gamepad/xbox/xbox_dpad_round_left.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://fmnwuu2ym0m8"
+uid="uid://qhwj81sv67l4"
path="res://.godot/imported/xbox_dpad_round_left.svg-502a7266adee947974e86d838ca520cb.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_dpad_round_right.svg.import b/assets/images/gamepad/xbox/xbox_dpad_round_right.svg.import
index e570cad5f..bdc1abd2e 100644
--- a/assets/images/gamepad/xbox/xbox_dpad_round_right.svg.import
+++ b/assets/images/gamepad/xbox/xbox_dpad_round_right.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cboy1enwvdeoy"
+uid="uid://b1uo5130s6gfw"
path="res://.godot/imported/xbox_dpad_round_right.svg-1114dc82cc3b1482e6e611adaab921c5.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_dpad_round_up.svg.import b/assets/images/gamepad/xbox/xbox_dpad_round_up.svg.import
index 2f94888c8..1510c3ce8 100644
--- a/assets/images/gamepad/xbox/xbox_dpad_round_up.svg.import
+++ b/assets/images/gamepad/xbox/xbox_dpad_round_up.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://ba64eulr61afh"
+uid="uid://dqk82r4up56mh"
path="res://.godot/imported/xbox_dpad_round_up.svg-41de4ad553b53f470c7a3fe7efaf902b.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_dpad_round_vertical.svg.import b/assets/images/gamepad/xbox/xbox_dpad_round_vertical.svg.import
index d363bbe77..432b4fd1f 100644
--- a/assets/images/gamepad/xbox/xbox_dpad_round_vertical.svg.import
+++ b/assets/images/gamepad/xbox/xbox_dpad_round_vertical.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dmhky2baxwheu"
+uid="uid://ccs5txc1px4a3"
path="res://.godot/imported/xbox_dpad_round_vertical.svg-04a43b32d5655eabae549267fc17610d.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_dpad_up.svg.import b/assets/images/gamepad/xbox/xbox_dpad_up.svg.import
index 9936038de..489c35f62 100644
--- a/assets/images/gamepad/xbox/xbox_dpad_up.svg.import
+++ b/assets/images/gamepad/xbox/xbox_dpad_up.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://c6w5exkfdkkrr"
+uid="uid://cjwqn3wttist"
path="res://.godot/imported/xbox_dpad_up.svg-5186fc3cc4f9679288a83d1d012cf73a.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_dpad_up_outline.svg.import b/assets/images/gamepad/xbox/xbox_dpad_up_outline.svg.import
index e36ca77c6..4a239a467 100644
--- a/assets/images/gamepad/xbox/xbox_dpad_up_outline.svg.import
+++ b/assets/images/gamepad/xbox/xbox_dpad_up_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bbo6fbusni1cc"
+uid="uid://ch0kyfjpkcmtx"
path="res://.godot/imported/xbox_dpad_up_outline.svg-ade502dd63188e5695c779711b2406b1.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_dpad_vertical.svg.import b/assets/images/gamepad/xbox/xbox_dpad_vertical.svg.import
index 749b19c91..66b80589a 100644
--- a/assets/images/gamepad/xbox/xbox_dpad_vertical.svg.import
+++ b/assets/images/gamepad/xbox/xbox_dpad_vertical.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bnndaco52g6gj"
+uid="uid://ckswrlv6m834h"
path="res://.godot/imported/xbox_dpad_vertical.svg-2bf59d2adeea0bf7ecbd4e9e187e5411.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_dpad_vertical_outline.svg.import b/assets/images/gamepad/xbox/xbox_dpad_vertical_outline.svg.import
index c1dedcec3..09b7d3a7c 100644
--- a/assets/images/gamepad/xbox/xbox_dpad_vertical_outline.svg.import
+++ b/assets/images/gamepad/xbox/xbox_dpad_vertical_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://10a2ky5156xj"
+uid="uid://xsdkqw0waaax"
path="res://.godot/imported/xbox_dpad_vertical_outline.svg-2afc52ca78de863b322db67e79d8f062.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_guide.svg.import b/assets/images/gamepad/xbox/xbox_guide.svg.import
index 9153c52ad..35c192004 100644
--- a/assets/images/gamepad/xbox/xbox_guide.svg.import
+++ b/assets/images/gamepad/xbox/xbox_guide.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bcoajyq8st62e"
+uid="uid://dq7kibukggise"
path="res://.godot/imported/xbox_guide.svg-7e127b7a22c3b066dc5699856d0c797f.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_guide_outline.svg.import b/assets/images/gamepad/xbox/xbox_guide_outline.svg.import
index 8eb54873c..382922ee4 100644
--- a/assets/images/gamepad/xbox/xbox_guide_outline.svg.import
+++ b/assets/images/gamepad/xbox/xbox_guide_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://wpkboh1kyedm"
+uid="uid://g73lou0pj88w"
path="res://.godot/imported/xbox_guide_outline.svg-17e63c770bb3ddf95772a98313c857f7.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_lb.svg.import b/assets/images/gamepad/xbox/xbox_lb.svg.import
index 76b6d5e16..e445afd06 100644
--- a/assets/images/gamepad/xbox/xbox_lb.svg.import
+++ b/assets/images/gamepad/xbox/xbox_lb.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://mtd8tfnbotgc"
+uid="uid://cwyi3if752xh6"
path="res://.godot/imported/xbox_lb.svg-398dff58e13f71ff0f7430230c58d7f2.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_lb_outline.svg.import b/assets/images/gamepad/xbox/xbox_lb_outline.svg.import
index 32e1665c9..a3c38d88f 100644
--- a/assets/images/gamepad/xbox/xbox_lb_outline.svg.import
+++ b/assets/images/gamepad/xbox/xbox_lb_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://c42xikfrkkr1v"
+uid="uid://do34qfhrq5x41"
path="res://.godot/imported/xbox_lb_outline.svg-2bfbaf6d828ff79113bd9e003e828e9a.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_ls.svg.import b/assets/images/gamepad/xbox/xbox_ls.svg.import
index 20e82a5ec..2abd31281 100644
--- a/assets/images/gamepad/xbox/xbox_ls.svg.import
+++ b/assets/images/gamepad/xbox/xbox_ls.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://qs6heuf6tn1i"
+uid="uid://dmybf5rjebq5j"
path="res://.godot/imported/xbox_ls.svg-a14e134edf2ff040f151e9d80c01fcb2.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_ls_outline.svg.import b/assets/images/gamepad/xbox/xbox_ls_outline.svg.import
index 3ac2650a0..c10467f9e 100644
--- a/assets/images/gamepad/xbox/xbox_ls_outline.svg.import
+++ b/assets/images/gamepad/xbox/xbox_ls_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bwcpk1ld2p5j5"
+uid="uid://clhscg5hh4jat"
path="res://.godot/imported/xbox_ls_outline.svg-b8a715b74389de55dadb1aa57df26ff8.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_lt.svg.import b/assets/images/gamepad/xbox/xbox_lt.svg.import
index 1d6a10c69..8b3993186 100644
--- a/assets/images/gamepad/xbox/xbox_lt.svg.import
+++ b/assets/images/gamepad/xbox/xbox_lt.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://u3jonqoafyg6"
+uid="uid://cg8r4ijx7641s"
path="res://.godot/imported/xbox_lt.svg-d30dc6b47cdba60b77fe84b9e3041a43.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_lt_outline.svg.import b/assets/images/gamepad/xbox/xbox_lt_outline.svg.import
index 5e1670178..df7444976 100644
--- a/assets/images/gamepad/xbox/xbox_lt_outline.svg.import
+++ b/assets/images/gamepad/xbox/xbox_lt_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://66buwdk71388"
+uid="uid://crs7kjqof8lgf"
path="res://.godot/imported/xbox_lt_outline.svg-ed40a819eb7fc8a09708bd0424289916.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_rb.svg.import b/assets/images/gamepad/xbox/xbox_rb.svg.import
index 2ce0f34d6..28772768b 100644
--- a/assets/images/gamepad/xbox/xbox_rb.svg.import
+++ b/assets/images/gamepad/xbox/xbox_rb.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://co3kg331knfu7"
+uid="uid://ceiru5s4y3ghy"
path="res://.godot/imported/xbox_rb.svg-a88f851439045fbc24b8fdd22e99412b.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_rb_outline.svg.import b/assets/images/gamepad/xbox/xbox_rb_outline.svg.import
index bac700efc..9466eedcc 100644
--- a/assets/images/gamepad/xbox/xbox_rb_outline.svg.import
+++ b/assets/images/gamepad/xbox/xbox_rb_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bu5l7hyvthqer"
+uid="uid://bwhh6fbprgryt"
path="res://.godot/imported/xbox_rb_outline.svg-024fc9413f393d610b3e382983354e72.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_rs.svg.import b/assets/images/gamepad/xbox/xbox_rs.svg.import
index a5147cf90..a930f3878 100644
--- a/assets/images/gamepad/xbox/xbox_rs.svg.import
+++ b/assets/images/gamepad/xbox/xbox_rs.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bt1cwcrqvujvn"
+uid="uid://bwr086x6ga5ay"
path="res://.godot/imported/xbox_rs.svg-78ab1580fc2d20ab704d0879618ea576.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_rs_outline.svg.import b/assets/images/gamepad/xbox/xbox_rs_outline.svg.import
index f8b88c226..c0c96c630 100644
--- a/assets/images/gamepad/xbox/xbox_rs_outline.svg.import
+++ b/assets/images/gamepad/xbox/xbox_rs_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dpcxinh1uthrf"
+uid="uid://bsh0ua7hu50uf"
path="res://.godot/imported/xbox_rs_outline.svg-a903d4c4e479d433c86ca716b83ebbb2.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_rt.svg.import b/assets/images/gamepad/xbox/xbox_rt.svg.import
index 4e4c6173c..0f4abcf65 100644
--- a/assets/images/gamepad/xbox/xbox_rt.svg.import
+++ b/assets/images/gamepad/xbox/xbox_rt.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://da8ojjv5vttou"
+uid="uid://brt5gm71iv3u4"
path="res://.godot/imported/xbox_rt.svg-698d5c2013b4a3c8f0dcc4c446bd55f5.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_rt_outline.svg.import b/assets/images/gamepad/xbox/xbox_rt_outline.svg.import
index 8f0394ad5..1a8da3f89 100644
--- a/assets/images/gamepad/xbox/xbox_rt_outline.svg.import
+++ b/assets/images/gamepad/xbox/xbox_rt_outline.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cil1xigmkb71c"
+uid="uid://carrmxn87xhtb"
path="res://.godot/imported/xbox_rt_outline.svg-58c19f710c4a3c1ae25059e1943b2939.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_stick_l.svg.import b/assets/images/gamepad/xbox/xbox_stick_l.svg.import
index 01c3a1d97..ed1e52b76 100644
--- a/assets/images/gamepad/xbox/xbox_stick_l.svg.import
+++ b/assets/images/gamepad/xbox/xbox_stick_l.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bdqfg27h5o836"
+uid="uid://dqx7njocf1aok"
path="res://.godot/imported/xbox_stick_l.svg-2c0ef8a05925eee7d7d471ba1671bf9e.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_stick_l_down.svg.import b/assets/images/gamepad/xbox/xbox_stick_l_down.svg.import
index c812305b9..6da04077c 100644
--- a/assets/images/gamepad/xbox/xbox_stick_l_down.svg.import
+++ b/assets/images/gamepad/xbox/xbox_stick_l_down.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dcumk3oqkyy7g"
+uid="uid://c1bfw2axbcg1q"
path="res://.godot/imported/xbox_stick_l_down.svg-2871ec99e71cd38b3dbae0847ab9317a.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_stick_l_horizontal.svg.import b/assets/images/gamepad/xbox/xbox_stick_l_horizontal.svg.import
index 47b9749a8..88231ca6a 100644
--- a/assets/images/gamepad/xbox/xbox_stick_l_horizontal.svg.import
+++ b/assets/images/gamepad/xbox/xbox_stick_l_horizontal.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://drcwmg5hpjyo0"
+uid="uid://xtwxoob18mw8"
path="res://.godot/imported/xbox_stick_l_horizontal.svg-f85d175ed4d43011f3fefb5e5b29334f.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_stick_l_left.svg.import b/assets/images/gamepad/xbox/xbox_stick_l_left.svg.import
index 4185bc00d..bf3255dc3 100644
--- a/assets/images/gamepad/xbox/xbox_stick_l_left.svg.import
+++ b/assets/images/gamepad/xbox/xbox_stick_l_left.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dooej262t4g0x"
+uid="uid://c4iwtbyehtps2"
path="res://.godot/imported/xbox_stick_l_left.svg-670f38737f59de4a65d5eb0d47729b4c.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_stick_l_press.svg.import b/assets/images/gamepad/xbox/xbox_stick_l_press.svg.import
index 300946edf..1d7f8ba5a 100644
--- a/assets/images/gamepad/xbox/xbox_stick_l_press.svg.import
+++ b/assets/images/gamepad/xbox/xbox_stick_l_press.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dvv5grt45cows"
+uid="uid://ckqaven4xmk16"
path="res://.godot/imported/xbox_stick_l_press.svg-c76f558e3498373b82265363d91f1bc8.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_stick_l_right.svg.import b/assets/images/gamepad/xbox/xbox_stick_l_right.svg.import
index 23438f790..71ba56d9a 100644
--- a/assets/images/gamepad/xbox/xbox_stick_l_right.svg.import
+++ b/assets/images/gamepad/xbox/xbox_stick_l_right.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://coltjh07der5"
+uid="uid://d4bfok8606fmv"
path="res://.godot/imported/xbox_stick_l_right.svg-9d5fb5ee9de7d1bf371d57141ac51d9f.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_stick_l_up.svg.import b/assets/images/gamepad/xbox/xbox_stick_l_up.svg.import
index f57a125c6..ad8db0016 100644
--- a/assets/images/gamepad/xbox/xbox_stick_l_up.svg.import
+++ b/assets/images/gamepad/xbox/xbox_stick_l_up.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b3xxbnyo2h20l"
+uid="uid://c7p0nhy4sh5wf"
path="res://.godot/imported/xbox_stick_l_up.svg-b8052c88e206210677dbefa76e6f9716.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_stick_l_vertical.svg.import b/assets/images/gamepad/xbox/xbox_stick_l_vertical.svg.import
index 5079e36f0..6c91fcb44 100644
--- a/assets/images/gamepad/xbox/xbox_stick_l_vertical.svg.import
+++ b/assets/images/gamepad/xbox/xbox_stick_l_vertical.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bs16gcmgm2ice"
+uid="uid://5rtbypusev2a"
path="res://.godot/imported/xbox_stick_l_vertical.svg-60bb43e09e4845355ebff48f8e99fca9.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_stick_r.svg.import b/assets/images/gamepad/xbox/xbox_stick_r.svg.import
index bdab31876..14fecf779 100644
--- a/assets/images/gamepad/xbox/xbox_stick_r.svg.import
+++ b/assets/images/gamepad/xbox/xbox_stick_r.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dw15y6xiuthpe"
+uid="uid://bjq76f76quyry"
path="res://.godot/imported/xbox_stick_r.svg-b6b0a563aad875ae5baad0fef90e1b5c.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_stick_r_down.svg.import b/assets/images/gamepad/xbox/xbox_stick_r_down.svg.import
index d08318436..cbbff7e62 100644
--- a/assets/images/gamepad/xbox/xbox_stick_r_down.svg.import
+++ b/assets/images/gamepad/xbox/xbox_stick_r_down.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://d4iq63eypbf2s"
+uid="uid://cu3ptt3kea56h"
path="res://.godot/imported/xbox_stick_r_down.svg-729218646a9ef8658f5fb344747dfcb6.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_stick_r_horizontal.svg.import b/assets/images/gamepad/xbox/xbox_stick_r_horizontal.svg.import
index e4563c035..06361aa5a 100644
--- a/assets/images/gamepad/xbox/xbox_stick_r_horizontal.svg.import
+++ b/assets/images/gamepad/xbox/xbox_stick_r_horizontal.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://60v0iyqxwm65"
+uid="uid://d4ihs7jvxb56h"
path="res://.godot/imported/xbox_stick_r_horizontal.svg-d5c67dba97d5fd690e64fade1fc24c98.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_stick_r_left.svg.import b/assets/images/gamepad/xbox/xbox_stick_r_left.svg.import
index 70f3670d6..90c6d0f31 100644
--- a/assets/images/gamepad/xbox/xbox_stick_r_left.svg.import
+++ b/assets/images/gamepad/xbox/xbox_stick_r_left.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bus2l2lmd844f"
+uid="uid://s4x7rp50eub5"
path="res://.godot/imported/xbox_stick_r_left.svg-75748f934fb270dcc712766fc9e05344.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_stick_r_press.svg.import b/assets/images/gamepad/xbox/xbox_stick_r_press.svg.import
index 4915364cb..ab6feeefb 100644
--- a/assets/images/gamepad/xbox/xbox_stick_r_press.svg.import
+++ b/assets/images/gamepad/xbox/xbox_stick_r_press.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://de2kcqeakp3q0"
+uid="uid://5q4tjwvf7b8a"
path="res://.godot/imported/xbox_stick_r_press.svg-ddd86906998c0f8d808ffb0a28a37658.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_stick_r_right.svg.import b/assets/images/gamepad/xbox/xbox_stick_r_right.svg.import
index 9ce045918..709e0a843 100644
--- a/assets/images/gamepad/xbox/xbox_stick_r_right.svg.import
+++ b/assets/images/gamepad/xbox/xbox_stick_r_right.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cokparjjmwy8c"
+uid="uid://kfqb1dr0735v"
path="res://.godot/imported/xbox_stick_r_right.svg-50e70773301ab1ce1d333d783cbffd23.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_stick_r_up.svg.import b/assets/images/gamepad/xbox/xbox_stick_r_up.svg.import
index 38d38ac32..7dbcce947 100644
--- a/assets/images/gamepad/xbox/xbox_stick_r_up.svg.import
+++ b/assets/images/gamepad/xbox/xbox_stick_r_up.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://jn543ff1ak1c"
+uid="uid://o0xrox1l5sae"
path="res://.godot/imported/xbox_stick_r_up.svg-5e2522d5822c9d7bb7aa51e28602facf.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_stick_r_vertical.svg.import b/assets/images/gamepad/xbox/xbox_stick_r_vertical.svg.import
index bc89ef847..5f3ec986a 100644
--- a/assets/images/gamepad/xbox/xbox_stick_r_vertical.svg.import
+++ b/assets/images/gamepad/xbox/xbox_stick_r_vertical.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cb87vvgyfr3cd"
+uid="uid://b5xybuy7txmro"
path="res://.godot/imported/xbox_stick_r_vertical.svg-1fc29f0194e1d1b5bd3ac55e4215f953.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_stick_side_l.svg.import b/assets/images/gamepad/xbox/xbox_stick_side_l.svg.import
index 8f6e48ba7..9fdbebe3d 100644
--- a/assets/images/gamepad/xbox/xbox_stick_side_l.svg.import
+++ b/assets/images/gamepad/xbox/xbox_stick_side_l.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://pp4tpvdxcw06"
+uid="uid://jyjr6jeest60"
path="res://.godot/imported/xbox_stick_side_l.svg-bb0a65e7b78b9c1e45b7347398cb21ea.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_stick_side_r.svg.import b/assets/images/gamepad/xbox/xbox_stick_side_r.svg.import
index 61473ffcf..cf43855e8 100644
--- a/assets/images/gamepad/xbox/xbox_stick_side_r.svg.import
+++ b/assets/images/gamepad/xbox/xbox_stick_side_r.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dpp5vgspiqd45"
+uid="uid://ccgy64wgba2vg"
path="res://.godot/imported/xbox_stick_side_r.svg-47000d6b9e86f11f14be4872c61921bd.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_stick_top_l.svg.import b/assets/images/gamepad/xbox/xbox_stick_top_l.svg.import
index 291b44ae1..941557da1 100644
--- a/assets/images/gamepad/xbox/xbox_stick_top_l.svg.import
+++ b/assets/images/gamepad/xbox/xbox_stick_top_l.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b2r8gh8p7equd"
+uid="uid://dqs8jabjytp1h"
path="res://.godot/imported/xbox_stick_top_l.svg-116826ec220fb2927e609042115300c7.ctex"
metadata={
"vram_texture": false
diff --git a/assets/images/gamepad/xbox/xbox_stick_top_r.svg.import b/assets/images/gamepad/xbox/xbox_stick_top_r.svg.import
index 3d4e32f29..d4c1d55ed 100644
--- a/assets/images/gamepad/xbox/xbox_stick_top_r.svg.import
+++ b/assets/images/gamepad/xbox/xbox_stick_top_r.svg.import
@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://b4h18p23lg15j"
+uid="uid://dm552sfjigl8o"
path="res://.godot/imported/xbox_stick_top_r.svg-aa85ffee187ac1c15ab213a993dde263.ctex"
metadata={
"vram_texture": false
diff --git a/assets/shaders/god_rays.gdshader b/assets/shaders/god_rays.gdshader
new file mode 100644
index 000000000..7b35c9c4b
--- /dev/null
+++ b/assets/shaders/god_rays.gdshader
@@ -0,0 +1,108 @@
+/*
+Shader from Godot Shaders - the free shader library.
+godotshaders.com/shader/god-rays
+
+Feel free to use, improve and change this shader according to your needs
+and consider sharing the modified result on godotshaders.com.
+*/
+
+shader_type canvas_item;
+
+uniform sampler2D SCREEN_TEXTURE : hint_screen_texture, filter_linear_mipmap;
+uniform float angle = -0.3;
+uniform float position = -0.2;
+uniform float spread : hint_range(0.0, 1.0) = 0.5;
+uniform float cutoff : hint_range(-1.0, 1.0) = 0.1;
+uniform float falloff : hint_range(0.0, 1.0) = 0.2;
+uniform float edge_fade : hint_range(0.0, 1.0) = 0.15;
+
+uniform float speed = 1.0;
+uniform float ray1_density = 8.0;
+uniform float ray2_density = 30.0;
+uniform float ray2_intensity : hint_range(0.0, 1.0) = 0.3;
+
+uniform vec4 color : source_color = vec4(1.0, 0.9, 0.65, 0.8);
+
+uniform bool hdr = false;
+uniform float seed = 5.0;
+
+// Random and noise functions from Book of Shader's chapter on Noise.
+float random(vec2 _uv) {
+ return fract(sin(dot(_uv.xy,
+ vec2(12.9898, 78.233))) *
+ 43758.5453123);
+}
+
+float noise (in vec2 uv) {
+ vec2 i = floor(uv);
+ vec2 f = fract(uv);
+
+ // Four corners in 2D of a tile
+ float a = random(i);
+ float b = random(i + vec2(1.0, 0.0));
+ float c = random(i + vec2(0.0, 1.0));
+ float d = random(i + vec2(1.0, 1.0));
+
+
+ // Smooth Interpolation
+
+ // Cubic Hermine Curve. Same as SmoothStep()
+ vec2 u = f * f * (3.0-2.0 * f);
+
+ // Mix 4 coorners percentages
+ return mix(a, b, u.x) +
+ (c - a)* u.y * (1.0 - u.x) +
+ (d - b) * u.x * u.y;
+}
+
+mat2 rotate(float _angle){
+ return mat2(vec2(cos(_angle), -sin(_angle)),
+ vec2(sin(_angle), cos(_angle)));
+}
+
+vec4 screen(vec4 base, vec4 blend){
+ return 1.0 - (1.0 - base) * (1.0 - blend);
+}
+
+void fragment()
+{
+
+ // Rotate, skew and move the UVs
+ vec2 transformed_uv = ( rotate(angle) * (UV - position) ) / ( (UV.y + spread) - (UV.y * spread) );
+
+ // Animate the ray according the the new transformed UVs
+ vec2 ray1 = vec2(transformed_uv.x * ray1_density + sin(TIME * 0.1 * speed) * (ray1_density * 0.2) + seed, 1.0);
+ vec2 ray2 = vec2(transformed_uv.x * ray2_density + sin(TIME * 0.2 * speed) * (ray1_density * 0.2) + seed, 1.0);
+
+ // Cut off the ray's edges
+ float cut = step(cutoff, transformed_uv.x) * step(cutoff, 1.0 - transformed_uv.x);
+ ray1 *= cut;
+ ray2 *= cut;
+
+ // Apply the noise pattern (i.e. create the rays)
+ float rays;
+
+ if (hdr){
+ // This is not really HDR, but check this to not clamp the two merged rays making
+ // their values go over 1.0. Can make for some nice effect
+ rays = noise(ray1) + (noise(ray2) * ray2_intensity);
+ }
+ else{
+ rays = clamp(noise(ray1) + (noise(ray2) * ray2_intensity), 0., 1.);
+ }
+
+ // Fade out edges
+ rays *= smoothstep(0.0, falloff, (1.0 - UV.y)); // Bottom
+ rays *= smoothstep(0.0 + cutoff, edge_fade + cutoff, transformed_uv.x); // Left
+ rays *= smoothstep(0.0 + cutoff, edge_fade + cutoff, 1.0 - transformed_uv.x); // Right
+
+ // Color to the rays
+ vec3 shine = vec3(rays) * color.rgb;
+
+ // Try different blending modes for a nicer effect. "Screen" is included in the code,
+ // but take a look at https://godotshaders.com/snippet/blending-modes/ for more.
+ // With "Screen" blend mode:
+ shine = screen(texture(SCREEN_TEXTURE, SCREEN_UV), vec4(color)).rgb;
+
+ COLOR = vec4(shine, rays * color.a);
+}
\ No newline at end of file
diff --git a/assets/shaders/highlight_shine.gdshader b/assets/shaders/highlight_shine.gdshader
new file mode 100644
index 000000000..bb2922f1f
--- /dev/null
+++ b/assets/shaders/highlight_shine.gdshader
@@ -0,0 +1,69 @@
+shader_type canvas_item;
+render_mode blend_premul_alpha;
+
+uniform float Line_Smoothness : hint_range(0, 0.1) = 0.045;
+uniform float Line_Width : hint_range(0, 0.2) = 0.09;
+uniform float Brightness = 3.0;
+uniform float Rotation_deg : hint_range(-90, 90) = 30;
+uniform float Distortion : hint_range(1, 2) = 1.8;
+uniform float Speed = 0.7;
+uniform float Position : hint_range(0, 1) = 0;
+uniform float Position_Min = 0.25;
+uniform float Position_Max = 0.5;
+uniform float Alpha : hint_range(0, 1) = 1;
+
+vec2 rotate_uv(vec2 uv, vec2 center, float rotation, bool use_degrees){
+ float _angle = rotation;
+ if(use_degrees){
+ _angle = rotation * (3.1415926/180.0);
+ }
+ mat2 _rotation = mat2(
+ vec2(cos(_angle), -sin(_angle)),
+ vec2(sin(_angle), cos(_angle))
+ );
+ vec2 _delta = uv - center;
+ _delta = _rotation * _delta;
+ return _delta + center;
+ }
+
+void fragment() {
+
+ vec2 center_uv = UV - vec2(0.5, 0.5);
+ float gradient_to_edge = max(abs(center_uv.x), abs(center_uv.y));
+ gradient_to_edge = gradient_to_edge * Distortion;
+ gradient_to_edge = 1.0 - gradient_to_edge;
+ vec2 rotaded_uv = rotate_uv(UV, vec2(0.5, 0.5), Rotation_deg, true);
+
+ float remapped_position;
+ {
+ float output_range = Position_Max - Position_Min;
+ remapped_position = Position_Min + output_range * Position;
+ }
+
+ float remapped_time = TIME * Speed + remapped_position;
+ remapped_time = fract(remapped_time);
+ {
+ float output_range = 2.0 - (-2.0);
+ remapped_time = -2.0 + output_range * remapped_time;
+ }
+
+ vec2 offset_uv = vec2(rotaded_uv.xy) + vec2(remapped_time, 0.0);
+ float line = vec3(offset_uv, 0.0).x;
+ line = abs(line);
+ line = gradient_to_edge * line;
+ line = sqrt(line);
+
+ float line_smoothness = clamp(Line_Smoothness, 0.001, 1.0);
+ float offset_plus = Line_Width + line_smoothness;
+ float offset_minus = Line_Width - line_smoothness;
+
+ float remapped_line;
+ {
+ float input_range = offset_minus - offset_plus;
+ remapped_line = (line - offset_plus) / input_range;
+ }
+ remapped_line = remapped_line * Brightness;
+ remapped_line = min(remapped_line, Alpha);
+ COLOR.rgb = vec3(COLOR.xyz) * vec3(remapped_line);
+ COLOR.a = remapped_line;
+}
diff --git a/assets/state/states/quick_bar_performance.tres b/assets/state/states/quick_bar_performance.tres
index 345f38ce6..811d09c6c 100644
--- a/assets/state/states/quick_bar_performance.tres
+++ b/assets/state/states/quick_bar_performance.tres
@@ -1,8 +1,8 @@
-[gd_resource type="Resource" load_steps=2 format=3 uid="uid://xw3l4h1vt0oa"]
+[gd_resource type="Resource" script_class="State" load_steps=2 format=3 uid="uid://b2ruoxboq5k6e"]
-[ext_resource type="Script" path="res://core/systems/state/state.gd" id="1_pmemp"]
+[ext_resource type="Script" path="res://core/systems/state/state.gd" id="1_3a3in"]
[resource]
-script = ExtResource("1_pmemp")
-name = "performance"
+script = ExtResource("1_3a3in")
+name = "powertools"
data = null
diff --git a/assets/state/states/quick_bar_powertools.tres b/assets/state/states/quick_bar_powertools.tres
deleted file mode 100644
index 811d09c6c..000000000
--- a/assets/state/states/quick_bar_powertools.tres
+++ /dev/null
@@ -1,8 +0,0 @@
-[gd_resource type="Resource" script_class="State" load_steps=2 format=3 uid="uid://b2ruoxboq5k6e"]
-
-[ext_resource type="Script" path="res://core/systems/state/state.gd" id="1_3a3in"]
-
-[resource]
-script = ExtResource("1_3a3in")
-name = "powertools"
-data = null
diff --git a/assets/ui/icons/iconoir--network-solid.svg b/assets/ui/icons/iconoir--network-solid.svg
new file mode 100644
index 000000000..9105a08bc
--- /dev/null
+++ b/assets/ui/icons/iconoir--network-solid.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/ui/icons/iconoir--network-solid.svg.import b/assets/ui/icons/iconoir--network-solid.svg.import
new file mode 100644
index 000000000..de593f58d
--- /dev/null
+++ b/assets/ui/icons/iconoir--network-solid.svg.import
@@ -0,0 +1,37 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://cxcn8w1t87qm1"
+path="res://.godot/imported/iconoir--network-solid.svg-668a1b8254e7d06c708068562df9cd81.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://assets/ui/icons/iconoir--network-solid.svg"
+dest_files=["res://.godot/imported/iconoir--network-solid.svg-668a1b8254e7d06c708068562df9cd81.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
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/assets/ui/icons/material-symbols--lock.svg b/assets/ui/icons/material-symbols--lock.svg
new file mode 100644
index 000000000..e32009064
--- /dev/null
+++ b/assets/ui/icons/material-symbols--lock.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/ui/icons/material-symbols--lock.svg.import b/assets/ui/icons/material-symbols--lock.svg.import
new file mode 100644
index 000000000..b5bc892e8
--- /dev/null
+++ b/assets/ui/icons/material-symbols--lock.svg.import
@@ -0,0 +1,37 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://ctnsy07oi3jks"
+path="res://.godot/imported/material-symbols--lock.svg-ec8320f21f9adbbbebcfe8c41ada06a5.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://assets/ui/icons/material-symbols--lock.svg"
+dest_files=["res://.godot/imported/material-symbols--lock.svg-ec8320f21f9adbbbebcfe8c41ada06a5.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
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/assets/ui/icons/mdi--ethernet.svg b/assets/ui/icons/mdi--ethernet.svg
new file mode 100644
index 000000000..4620dd816
--- /dev/null
+++ b/assets/ui/icons/mdi--ethernet.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/ui/icons/mdi--ethernet.svg.import b/assets/ui/icons/mdi--ethernet.svg.import
new file mode 100644
index 000000000..be57c422c
--- /dev/null
+++ b/assets/ui/icons/mdi--ethernet.svg.import
@@ -0,0 +1,37 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://caygvo6umqvln"
+path="res://.godot/imported/mdi--ethernet.svg-c3832d5dc20f540b8d177a4e083b844b.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://assets/ui/icons/mdi--ethernet.svg"
+dest_files=["res://.godot/imported/mdi--ethernet.svg-c3832d5dc20f540b8d177a4e083b844b.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
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/assets/ui/icons/powertools_icon.svg b/assets/ui/icons/performance_icon.svg
similarity index 100%
rename from assets/ui/icons/powertools_icon.svg
rename to assets/ui/icons/performance_icon.svg
diff --git a/assets/ui/icons/powertools_icon.svg.import b/assets/ui/icons/performance_icon.svg.import
similarity index 73%
rename from assets/ui/icons/powertools_icon.svg.import
rename to assets/ui/icons/performance_icon.svg.import
index 360126d2b..2dd445a6f 100644
--- a/assets/ui/icons/powertools_icon.svg.import
+++ b/assets/ui/icons/performance_icon.svg.import
@@ -3,15 +3,15 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://cqy34r7oni6d4"
-path="res://.godot/imported/powertools_icon.svg-652cf7833e5f111e096aaec7055e1d3a.ctex"
+path="res://.godot/imported/performance_icon.svg-5082e7fb3c41a1711d81bab95097ecfa.ctex"
metadata={
"vram_texture": false
}
[deps]
-source_file="res://assets/ui/icons/powertools_icon.svg"
-dest_files=["res://.godot/imported/powertools_icon.svg-652cf7833e5f111e096aaec7055e1d3a.ctex"]
+source_file="res://assets/ui/icons/performance_icon.svg"
+dest_files=["res://.godot/imported/performance_icon.svg-5082e7fb3c41a1711d81bab95097ecfa.ctex"]
[params]
diff --git a/assets/ui/icons/tabler--network-off.svg b/assets/ui/icons/tabler--network-off.svg
new file mode 100644
index 000000000..dba2e1c13
--- /dev/null
+++ b/assets/ui/icons/tabler--network-off.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/ui/icons/tabler--network-off.svg.import b/assets/ui/icons/tabler--network-off.svg.import
new file mode 100644
index 000000000..a83fce09b
--- /dev/null
+++ b/assets/ui/icons/tabler--network-off.svg.import
@@ -0,0 +1,37 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://dghihbwuwab1y"
+path="res://.godot/imported/tabler--network-off.svg-191244c146ebb11979e737f2add2c042.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://assets/ui/icons/tabler--network-off.svg"
+dest_files=["res://.godot/imported/tabler--network-off.svg-191244c146ebb11979e737f2add2c042.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
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/core/global/audio_manager.gd b/core/global/audio_manager.gd
index c90969061..20be7fd0e 100644
--- a/core/global/audio_manager.gd
+++ b/core/global/audio_manager.gd
@@ -18,9 +18,6 @@ enum VOLUME {
## Limit the maximum volume to 200%
const volume_limit := "2.0"
-## Thread to run audio changes on
-var thread := load("res://core/systems/threading/thread_pool.tres")
-
## Current volume
var current_volume := await _get_current_volume()
var _muted := false
@@ -29,7 +26,6 @@ var _current_output := ""
func _init() -> void:
- thread.start()
current_volume = await _get_current_volume()
_output_devices = await _get_output_devices()
@@ -80,8 +76,11 @@ func set_volume(value: float, type: VOLUME = VOLUME.ABSOLUTE) -> int:
suffix = "%+"
var percent := value * 100
- var args := ["set-volume", "--limit", volume_limit, "@DEFAULT_AUDIO_SINK@", str(percent) + suffix]
- var code := await thread.exec(OS.execute.bind("wpctl", args)) as int
+ var args: Array[String] = ["set-volume", "--limit", volume_limit, "@DEFAULT_AUDIO_SINK@", str(percent) + suffix]
+ var cmd := Command.create("wpctl", args)
+ cmd.timeout = 5.0
+ cmd.execute()
+ var code := await cmd.finished as int
return code
@@ -90,7 +89,10 @@ func set_volume(value: float, type: VOLUME = VOLUME.ABSOLUTE) -> int:
func toggle_mute() -> int:
_muted = !_muted
volume_mute_toggled.emit()
- var code := await thread.exec(OS.execute.bind("wpctl", ["set-mute", "@DEFAULT_AUDIO_SINK@", "toggle"])) as int
+ var cmd := Command.create("wpctl", ["set-mute", "@DEFAULT_AUDIO_SINK@", "toggle"])
+ cmd.timeout = 5.0
+ cmd.execute()
+ var code := await cmd.finished as int
return code
@@ -116,7 +118,11 @@ func set_output_device(device: String) -> int:
var i := devices.find(device)
var device_id := ids[i]
- return await thread.exec(OS.execute.bind("wpctl", ["set-default", device_id]))
+ var cmd := Command.create("wpctl", ["set-default", device_id])
+ cmd.timeout = 5.0
+ cmd.execute()
+
+ return await cmd.finished as int
## Returns the currently set output device
@@ -135,16 +141,16 @@ func get_current_volume() -> float:
## Fetch the volume for the current output device
func _get_current_volume() -> float:
- var output := []
- var code := await thread.exec(OS.execute.bind("wpctl", ["get-volume", "@DEFAULT_AUDIO_SINK@"], output)) as int
- if code != 0:
- return -1
- if output.size() == 0:
+ var cmd := Command.create("wpctl", ["get-volume", "@DEFAULT_AUDIO_SINK@"])
+ cmd.timeout = 5.0
+ cmd.execute()
+ var code := await cmd.finished as int
+ if code != OK:
return -1
# Parse the output of wpctl
# Example: Volume: 0.52
- var text := output[0] as String
+ var text := cmd.stdout
var parts := text.split(" ")
if parts.size() < 2:
return -1
@@ -178,28 +184,26 @@ func _get_output_devices() -> PackedStringArray:
# Inspects the given wirepipe object
func _wpctl_inspect(id: String) -> PackedStringArray:
- var out := PackedStringArray()
- var output := []
- var code := await thread.exec(OS.execute.bind("wpctl", ["inspect", id], output)) as int
- if code != 0:
- return out
- if output.size() == 0:
- return out
- var text := output[0] as String
- return text.split("\n")
+ var cmd := Command.create("wpctl", ["inspect", id])
+ cmd.timeout = 5.0
+ cmd.execute()
+ var code := await cmd.finished as int
+ if code != OK:
+ return PackedStringArray()
+ return cmd.stdout.split("\n")
# Returns an array of discovered Wirepipe object IDs
func _get_wpctl_object_ids() -> PackedStringArray:
var ids := PackedStringArray()
- var output := []
- var code := await thread.exec(OS.execute.bind("wpctl", ["status"], output)) as int
- if code != 0:
- return ids
- if output.size() == 0:
+ var cmd := Command.create("wpctl", ["status"])
+ cmd.timeout = 5.0
+ cmd.execute()
+ var code := await cmd.finished as int
+ if code != OK:
return ids
- var text := output[0] as String
+ var text := cmd.stdout
var parts := text.split(" ")
if parts.size() < 2:
return ids
diff --git a/core/global/battery_manager.gd b/core/global/battery_manager.gd
deleted file mode 100644
index 56e8f37ad..000000000
--- a/core/global/battery_manager.gd
+++ /dev/null
@@ -1,91 +0,0 @@
-@icon("res://assets/ui/icons/battery-charging.svg")
-extends Resource
-class_name BatteryManager
-
-
-const power_supply_dir = "/sys/class/power_supply"
-
-@export var icon_charging: Texture = preload("res://assets/ui/icons/battery-charging.svg")
-@export var icon_full: Texture = preload("res://assets/ui/icons/battery-full.svg")
-@export var icon_high: Texture = preload("res://assets/ui/icons/battery-75.svg")
-@export var icon_half: Texture = preload("res://assets/ui/icons/battery-half.svg")
-@export var icon_low: Texture = preload("res://assets/ui/icons/battery-low.svg")
-@export var icon_empty: Texture = preload("res://assets/ui/icons/battery-empty.svg")
-
-enum STATUS {
- NONE,
- DISCHARGING,
- NOT_CHARGING,
- CHARGING,
- FULL,
-}
-
-var battery_path: String = find_battery_path()
-var logger := Log.get_logger("BatteryManager")
-
-## Finds the battery path. If none is found, returns an empty string.
-static func find_battery_path() -> Variant:
- var power_dir: DirAccess = DirAccess.open(power_supply_dir)
- var devices: PackedStringArray = power_dir.get_directories()
- var battery_dir: String = ""
- for folder in devices:
- if folder.begins_with("BAT"):
- battery_dir = folder
- break
- if battery_dir == "":
- return ""
-
- return "/".join([power_supply_dir, battery_dir])
-
-
-## Returns the current battery capacity as a percentage. Returns -1 if no battery
-## was discovered.
-func get_capacity() -> int:
- if battery_path == "":
- return -1
- var capacity_file: String = "/".join([battery_path, "capacity"])
- var file: FileAccess = FileAccess.open(capacity_file, FileAccess.READ)
- var bytes: PackedByteArray = file.get_buffer(100)
- var str: String = bytes.get_string_from_ascii().strip_edges()
- if not str.is_valid_int():
- return -1
- return str.to_int()
-
-
-## Returns the status of the given battery
-func get_status() -> STATUS:
- if battery_path == "":
- return STATUS.NONE
- var status_file: String = "/".join([battery_path, "status"])
-
- var output := []
- var code := OS.execute("cat", [status_file], output)
- if code != OK:
- return STATUS.NONE
- var status := (output[0] as String).strip_edges()
-
- match status:
- "Discharging":
- return STATUS.DISCHARGING
- "Not charging":
- return STATUS.NOT_CHARGING
- "Charging":
- return STATUS.CHARGING
- "Full":
- return STATUS.FULL
- return STATUS.NONE
-
-
-## Returns the texture reflecting the given battery capacity
-func get_capacity_texture(capacity: int, status: STATUS = STATUS.NONE) -> Texture2D:
- if status > STATUS.NOT_CHARGING:
- return icon_charging
- if capacity >= 90:
- return icon_full
- if capacity >= 65:
- return icon_high
- if capacity >= 40:
- return icon_half
- if capacity >= 20:
- return icon_low
- return icon_empty
diff --git a/core/global/battery_manager.tres b/core/global/battery_manager.tres
deleted file mode 100644
index 4cec2e356..000000000
--- a/core/global/battery_manager.tres
+++ /dev/null
@@ -1,18 +0,0 @@
-[gd_resource type="Resource" script_class="BatteryManager" load_steps=8 format=3 uid="uid://bn5vhnowoo3dl"]
-
-[ext_resource type="Texture2D" uid="uid://000r1wyog2d1" path="res://assets/ui/icons/battery-charging.svg" id="1_lk1dm"]
-[ext_resource type="Script" path="res://core/global/battery_manager.gd" id="2_mxapa"]
-[ext_resource type="Texture2D" uid="uid://ck3r7wbbb6lj7" path="res://assets/ui/icons/battery-empty.svg" id="2_qbtqx"]
-[ext_resource type="Texture2D" uid="uid://icnhb750o8ma" path="res://assets/ui/icons/battery-full.svg" id="3_v7nrv"]
-[ext_resource type="Texture2D" uid="uid://c61mthg68r41g" path="res://assets/ui/icons/battery-half.svg" id="4_j7gj6"]
-[ext_resource type="Texture2D" uid="uid://b3amqx05ikddx" path="res://assets/ui/icons/battery-75.svg" id="5_ick7m"]
-[ext_resource type="Texture2D" uid="uid://ywcnlki2k06u" path="res://assets/ui/icons/battery-low.svg" id="6_6fi5u"]
-
-[resource]
-script = ExtResource("2_mxapa")
-icon_charging = ExtResource("1_lk1dm")
-icon_full = ExtResource("3_v7nrv")
-icon_high = ExtResource("5_ick7m")
-icon_half = ExtResource("4_j7gj6")
-icon_low = ExtResource("6_6fi5u")
-icon_empty = ExtResource("2_qbtqx")
diff --git a/core/global/boxart_manager.gd b/core/global/boxart_manager.gd
index 0d97d33f7..361fe17fd 100644
--- a/core/global/boxart_manager.gd
+++ b/core/global/boxart_manager.gd
@@ -55,6 +55,9 @@ func get_boxart(item: LibraryItem, kind: BoxArtProvider.LAYOUT) -> Texture2D:
func _get_boxart_sync(item: LibraryItem, kind: BoxArtProvider.LAYOUT) -> Texture2D:
+ if not item:
+ return null
+
if _providers.is_empty():
logger.error("No box art providers were found!")
return null
diff --git a/core/global/dbus_manager.gd b/core/global/dbus_manager.gd
deleted file mode 100644
index 4786b3bd3..000000000
--- a/core/global/dbus_manager.gd
+++ /dev/null
@@ -1,311 +0,0 @@
-extends Resource
-class_name DBusManager
-
-## DBusManager is a helper class for using DBus
-##
-## Use this class to interface with DBus.
-
-enum BUS_TYPE {
- SYSTEM = dbus.DBUS_BUS_SYSTEM,
- SESSION = dbus.DBUS_BUS_SESSION,
- STARTER = dbus.DBUS_BUS_STARTER,
-}
-
-const DBUS_BUS := "org.freedesktop.DBus"
-const DBUS_PATH := "/org/freedesktop/DBus"
-
-const IFACE_DBUS := "org.freedesktop.DBus"
-const IFACE_PROPERTIES := "org.freedesktop.DBus.Properties"
-const IFACE_OBJECT_MANAGER := "org.freedesktop.DBus.ObjectManager"
-
-## Type of bus to connect to
-@export var bus_type := BUS_TYPE.SYSTEM
-## Shared thread to process DBus messages on
-@export var thread: SharedThread = load("res://core/systems/threading/system_thread.tres")
-
-var logger := Log.get_logger("DBusManager")
-var well_known_names := []
-var dbus := DBus.new()
-var dbus_proxy := DBusProxy.new(create_proxy(DBUS_BUS, DBUS_PATH))
-
-
-func _init() -> void:
- if dbus.connect(bus_type) != OK:
- logger.warn("Unable to connect to dbus")
- return
- thread.add_process(_process)
- thread.start()
-
-
-## Process messages on the bus that are being watched and dispatch them.
-func _process(_delta: float):
- var messages: Array[DBusMessage] = []
- var msg := dbus.pop_message()
- while msg != null:
- logger.debug("Received DBus message on " + msg.get_sender() + " from " + msg.get_path() + ": " + str(msg.get_args()))
- messages.append(msg)
- msg = dbus.pop_message()
-
- for message in messages:
- _process_message(message)
-
-
-## Dispatch the given message to any proxy objects
-func _process_message(msg: DBusMessage) -> void:
- # Try looking up the well-known name of the message sender
- var known_names := get_names_for_owner(msg.get_sender())
-
- # Try constructing the resource path to the proxy and see if it exists
- for known_name in known_names:
- var res_path := "dbus://" + known_name + msg.get_path()
- if not ResourceLoader.exists(res_path):
- logger.debug("No proxy resource found to send message to at: " + res_path)
- continue
- logger.debug("Found proxy to send message signal to at: " + res_path)
- var proxy := load(res_path) as Proxy
- if not proxy:
- logger.warn("Failed to load proxy from resource cache: " + res_path)
- continue
- var send_signal := func(message: DBusMessage) -> void:
- proxy.message_received.emit(message)
- send_signal.call_deferred(msg)
- break
-
-
-## Creates a reference to a DBus object on the given bus at the given path.
-## E.g. create_proxy("org.bluez", "/org/bluez/hci0")
-func create_proxy(bus: String, path: String) -> Proxy:
- # Try to load the proxy if it already exists
- var res_path := "dbus://" + bus + path
- logger.debug("Creating proxy with resource path: " + res_path)
- var proxy: Proxy
- if ResourceLoader.exists(res_path):
- logger.debug("Resource already exists. Returning existing instance.")
- proxy = load(res_path)
- return proxy
-
- proxy = Proxy.new(dbus, bus, path)
- proxy.take_over_path(res_path)
-
- # Keep track of bus names so they can be referenced later
- if not bus in well_known_names:
- well_known_names.append(bus)
-
- return proxy
-
-
-## Returns true if the given well-known name has an owner.
-func bus_exists(name: String) -> bool:
- return dbus.name_has_owner(name)
-
-# TODO: This is deprecated. Remove this and all refrences to it.
-## Returns a dictionary of manages objects for the given bus and path
-func get_managed_objects(bus: String, path: String) -> Array[ManagedObject]:
- var obj := create_proxy(bus, path)
- var result := obj.call_method(IFACE_OBJECT_MANAGER, "GetManagedObjects", [], "")
- if not result:
- return []
- var args := result.get_args()
- if args.size() != 1:
- return []
- if not args[0] is Dictionary:
- return []
-
- var objs_dict := args[0] as Dictionary
- var objects: Array[ManagedObject] = []
-
- # Convert the objects dictionary into an array of objects
- for obj_path in objs_dict.keys():
- var obj_data := objs_dict[obj_path] as Dictionary
- var object := ManagedObject.new(obj_path as String, obj_data)
- objects.append(object)
-
- return objects
-
-
-## Tries to resolve well-known names (e.g. "org.bluez") from the given owner (e.g. ":1.5").
-## This will return an array of well-known names.
-func get_names_for_owner(owner: String) -> PackedStringArray:
- var names := PackedStringArray()
- for name in well_known_names:
- var name_owner := dbus_proxy.get_name_owner(name as String)
- if name_owner == owner:
- names.append(name as String)
-
- return names
-
-
-func _to_string() -> String:
- var bus_string := "System" if bus_type == BUS_TYPE.SYSTEM else "Session"
- return "".format([bus_string])
-
-
-class ObjectManager extends Resource:
- signal interfaces_added(dbus_path: String)
- signal interfaces_removed(dbus_path: String)
-
- var _proxy: Proxy
-
- func _init(proxy: Proxy) -> void:
- _proxy = proxy
- _proxy.message_received.connect(_on_message_received)
- _proxy.thread.exec(_proxy.watch.bind(IFACE_OBJECT_MANAGER, "InterfacesAdded"))
- _proxy.thread.exec(_proxy.watch.bind(IFACE_OBJECT_MANAGER, "InterfacesRemoved"))
-
- ## Returns a dictionary of manages objects for the given bus and path
- func get_managed_objects(_bus: String, _path: String) -> Array[ManagedObject]:
- var result := _proxy.call_method(IFACE_OBJECT_MANAGER, "GetManagedObjects", [], "")
- if not result:
- return []
- var args := result.get_args()
- if args.size() != 1:
- return []
- if not args[0] is Dictionary:
- return []
-
- var objs_dict := args[0] as Dictionary
- var objects: Array[ManagedObject] = []
-
- # Convert the objects dictionary into an array of objects
- for obj_path in objs_dict.keys():
- var obj_data := objs_dict[obj_path] as Dictionary
- var object := ManagedObject.new(obj_path as String, obj_data)
- objects.append(object)
-
- return objects
-
- func _on_message_received(msg: DBusMessage) -> void:
- #print("Got message: " + str(msg))
- if not msg:
- return
- var args := msg.get_args()
- #print("Got args: " + str(args))
- if args.size() != 2:
- return
- #print("Got args big enough")
- if msg.get_member() == "InterfacesAdded":
- #print("Got InterfacesAdded")
- interfaces_added.emit(args[0])
-
- if msg.get_member() == "InterfacesRemoved":
- #print("Got InterfacesRemoved")
- interfaces_removed.emit(args[0])
-
-
-## A Proxy provides an interface to call methods on a DBus object.
-class Proxy extends Resource:
- signal message_received(msg: DBusMessage)
- signal properties_changed(iface: String, props: Dictionary)
- var _dbus: DBus
- var bus_name: String
- var path: String
- var rules := PackedStringArray()
- var logger := Log.get_logger("DBusProxy")
- var thread: SharedThread = load("res://core/systems/threading/system_thread.tres")
-
- func _init(conn: DBus, bus: String, obj_path: String) -> void:
- _dbus = conn
- bus_name = bus
- path = obj_path
- message_received.connect(_on_property_changed)
- thread.exec(watch.bind(IFACE_PROPERTIES, "PropertiesChanged"))
-
- func _on_property_changed(msg: DBusMessage) -> void:
- if not msg:
- return
- if msg.get_member() != "PropertiesChanged":
- return
- var args := msg.get_args()
- if args.size() < 2:
- return
- properties_changed.emit(args[0], args[1])
-
- func _notification(what: int) -> void:
- if what != NOTIFICATION_PREDELETE:
- return
- for rule in rules:
- logger.debug("Removing watch rule: " + rule)
- _dbus.remove_match(rule)
-
- ## Call the given method
- func call_method(iface: String, method: String, args: Array = [], signature: String = "") -> DBusMessage:
- logger.debug("Calling method: " + iface + "::" + method + "(" + str(args) + ")")
- return _dbus.send_with_reply_and_block(bus_name, path, iface, method, args, signature)
-
- ## Set the given property
- func set_property(iface: String, property: String, value: Variant) -> void:
- logger.debug("Set property " + property + " to " + str(value) + " for interface " + iface)
- call_method(IFACE_PROPERTIES, "Set", [iface, property, value], "ssv")
-
- ## Get the given property
- func get_property(iface: String, property: String) -> Variant:
- var response := call_method(IFACE_PROPERTIES, "Get", [iface, property], "ss")
- if not response:
- return null
- var args := response.get_args()
- if args.size() == 0:
- return null
-
- return args[0]
-
- ## Get all properties for the given interface
- func get_properties(iface: String) -> Dictionary:
- var response := call_method(IFACE_PROPERTIES, "GetAll", [iface], "s")
- if not response:
- return {}
- var args := response.get_args()
- if args.size() == 0:
- return {}
-
- return args[0]
-
- ## Watch the bus for particular signals
- func watch(iface: String, member: String = "PropertiesChanged") -> int:
- var rule := "type='signal',interface='{0}',path='{1}',member='{2}'".format(
- [iface, path, member]
- )
- rules.append(rule)
- logger.debug("Adding watch rule: " + rule)
- var err := _dbus.add_match(rule)
- if err != OK:
- logger.error("Unable to watch " + path)
- return err
-
-
-## A ManagedObject is a simple structure used with GetManagedObjects
-class ManagedObject:
- var path: String
- var data: Dictionary
-
- func _init(obj_path: String, obj_data: Dictionary) -> void:
- path = obj_path
- data = obj_data
-
- func has_interface(name: String) -> bool:
- return name in data
-
- func has_interface_attr(iface: String, name: String) -> bool:
- if not iface in data:
- return false
- if not name in data[iface]:
- return false
- return true
-
-
-## Proxy to manage /org/freedesktop/DBus on the org.freedesktop.DBus bus.
-class DBusProxy:
- var _proxy: Proxy
-
- func _init(proxy: Proxy) -> void:
- _proxy = proxy
-
- ## Return the connection name (e.g. ":1.1270") from the given well-known name
- func get_name_owner(name: String) -> String:
- var msg := _proxy.call_method(IFACE_DBUS, "GetNameOwner", [name], "s")
- if not msg:
- return ""
- var args := msg.get_args()
- if args.size() != 1:
- return ""
-
- return args[0]
diff --git a/core/global/dbus_system.tres b/core/global/dbus_system.tres
deleted file mode 100644
index 95c70f0d1..000000000
--- a/core/global/dbus_system.tres
+++ /dev/null
@@ -1,9 +0,0 @@
-[gd_resource type="Resource" script_class="DBusManager" load_steps=3 format=3 uid="uid://dskqww1130rb2"]
-
-[ext_resource type="Script" path="res://core/global/dbus_manager.gd" id="1_6xf1o"]
-[ext_resource type="Resource" uid="uid://ct7pi0cx0r832" path="res://core/systems/threading/system_thread.tres" id="2_p3brt"]
-
-[resource]
-script = ExtResource("1_6xf1o")
-bus_type = 1
-thread = ExtResource("2_p3brt")
diff --git a/core/global/gamescope.gd b/core/global/gamescope.gd
deleted file mode 100644
index d8ae55f73..000000000
--- a/core/global/gamescope.gd
+++ /dev/null
@@ -1,751 +0,0 @@
-extends Resource
-class_name Gamescope
-
-## Interact with Gamescope windows and properties
-##
-## The Gamescope class is responsible for interacting with Gamescope, usually
-## via the means of setting gamescope-specific window properties. It can be
-## used to discover Gamescope displays, list windows and their children, and set
-## gamescope-specific window atoms to switch windows, set blur, limit FPS, etc.
-## [br][br]
-## For example, to limit the FPS, you can do the following:
-## [codeblock]
-## Gamescope.set_fps_limit(display, 30)
-## [/codeblock]
-## [br][br]
-## Most of the core functionality of this class is provided by the [Xlib]
-## module, which is a GDExtension that exposes Xlib methods to Godot.
-
-signal blur_mode_updated(from: int, to: int)
-signal display_is_external_updated(from: int, to: int)
-signal focused_window_updated(from: int, to: int)
-signal focusable_windows_updated(from: PackedInt32Array, to: PackedInt32Array)
-signal focused_app_updated(from: int, to: int)
-signal focused_app_gfx_updated(from: int, to: int)
-signal focusable_apps_updated(from: PackedInt32Array, to: PackedInt32Array)
-
-## Gamescope Blur modes
-enum BLUR_MODE {
- OFF = 0, ## Turns off blur of running games
- COND = 1, ## Conditionally blurs running games
- ALWAYS = 2, ## Turns blurring of running games on
-}
-
-## Specifies which Gamescope xwayland server to perform an operation on.
-enum XWAYLAND {
- PRIMARY, ## Primary Gamescope xwayland instance
- OGUI, ## Xwayland instance that OpenGamepadUI is running on
- GAME, ## Xwayland instance where games run
-}
-
-## Gamescope is hard-coded to look for STEAM_GAME=769 to determine if it is the
-## overlay app.
-const OVERLAY_GAME_ID := 769
-
-@export var log_level := Log.LEVEL.INFO
-## The primary xwayland is the primary Gamescope xwayland session that contains
-## Gamescope properties on the root window.
-var xwayland_primary: Xlib
-## The OGUI xwayland is the xwayland instance that OGUI is running under.
-var xwayland_ogui: Xlib
-## The Game xwayland is the xwayland instance that games are launched under.
-var xwayland_game: Xlib
-## Array of all discovered xwayland instances
-var xwaylands: Array[Xlib] = []
-var logger := Log.get_logger("Gamescope", log_level)
-
-# Gamescope properties
-## Blur mode (read-only)
-var blur_mode: int:
- set(v):
- var prev_value := blur_mode
- blur_mode = v
- if prev_value != v:
- blur_mode_updated.emit(prev_value, v)
-var baselayer_window: int
-var input_counter: int
-var display_is_external: int
-var vrr_enabled: int
-var vrr_feedback: int
-var vrr_capable: int
-var keyboard_focus_display: PackedInt32Array
-var mouse_focus_display: PackedInt32Array
-var focus_display: PackedInt32Array
-var focused_window: int:
- set(v):
- var prev_value := focused_window
- focused_window = v
- if prev_value != v:
- focused_window_updated.emit(prev_value, v)
-var focused_app_gfx: int:
- set(v):
- var prev_value := focused_app_gfx
- focused_app_gfx = v
- if prev_value != v:
- focused_app_gfx_updated.emit(prev_value, v)
-var focused_app: int:
- set(v):
- var prev_value := focused_app
- focused_app = v
- if prev_value != v:
- focused_app_updated.emit(prev_value, v)
-var focusable_windows: PackedInt32Array:
- set(v):
- var prev_value := focusable_windows
- focusable_windows = v
- if prev_value != v:
- focusable_windows_updated.emit(prev_value, v)
-var focusable_apps: PackedInt32Array:
- set(v):
- var prev_value := focusable_apps
- focusable_apps = v
- if prev_value != v:
- focusable_apps_updated.emit(prev_value, v)
-var cursor_visible_feedback: int
-
-
-# Connects to all gamescope xwayland instances
-func _init() -> void:
- # Don't initialize if run from the editor (during doc generation)
- if Engine.is_editor_hint():
- logger.info("Not initializing. Ran from editor.")
- return
-
- # Connect to the xwayland instance that OGUI is running on
- var ogui_display := OS.get_environment("DISPLAY")
- xwayland_ogui = Xlib.new()
- if xwayland_ogui.open(ogui_display) != OK:
- logger.error("Failed to open OGUI X server: " + ogui_display)
- return
- if _is_gamescope_xwayland(xwayland_ogui):
- logger.debug("OpenGamepadUI is running in Gamescope")
- xwayland_game = xwayland_ogui
- if _is_gamescope_xwayland_primary(xwayland_ogui):
- logger.debug("OpenGamepadUI is running on the primary Gamescope xwayland")
- xwayland_primary = xwayland_ogui
- xwaylands.push_front(xwayland_ogui)
-
- # Discover all other xwayland displays
- var displays := discover_gamescope_displays()
- for display in displays:
- if _has_xwayland(display):
- logger.debug("Already discovered xwayland: " + display)
- continue
- var xwayland := Xlib.new()
- if xwayland.open(display) != OK:
- logger.debug("Failed to open X server: " + display)
- continue
- if _is_gamescope_xwayland_primary(xwayland):
- logger.debug("Display " + display + " is the primary gamescope instance")
- xwayland_primary = xwayland
- if xwayland_primary != xwayland:
- xwayland_game = xwayland
- xwaylands.append(xwayland)
-
- # If we haven't discovered any gamescope displays, set everything to use
- # the OGUI xwayland instance
- if not xwayland_primary:
- logger.warn("OpenGamepadUI is not running in Gamescope. Unexpected behavior expected.")
- xwayland_primary = xwayland_ogui
- if not xwayland_game:
- xwayland_game = xwayland_ogui
-
- logger.debug("Primary xwayland is " + xwayland_primary.get_name())
- logger.debug("OGUI xwayland is " + xwayland_ogui.get_name())
- logger.debug("Game xwayland is " + xwayland_game.get_name())
-
-
-## Returns all gamescope xwayland names (E.g. [":0", ":1"])
-# TODO: This seems brittle. Is there any other way we can discover Gamescope displays?
-func discover_gamescope_displays() -> PackedStringArray:
- logger.debug("Discovering xwaylands!")
-
- # X11 displays have a corresponding socket in /tmp/.X11-unix
- # The sockets are named like: X0, X1, X2, etc.
- var dir := DirAccess.open("/tmp/.X11-unix")
- var sockets := dir.get_files()
-
- # Loop through each socket file and derrive the display number.
- var display_names: PackedInt32Array = []
- for socket in sockets:
- var suffix := (socket as String).trim_prefix("X")
- if not suffix.is_valid_int():
- logger.warn("Skipping X11 socket with a weird name: " + socket)
- continue
- display_names.append(suffix.to_int())
-
- # Check to see if the root window of these displays has gamescope-specific properties
- var gamescope_displays := PackedStringArray()
- for display_num in display_names:
- var display := ":{0}".format([display_num])
- var xwayland := Xlib.new()
- if xwayland.open(display) != OK:
- logger.debug("Failed to open X server: " + display)
- continue
- if _is_gamescope_xwayland(xwayland):
- gamescope_displays.append(display)
- logger.debug("Discovered X server display: " + display)
- xwayland.close()
- return gamescope_displays
-
-
-## Updates the Gamescope state. Should be called in a loop to keep the Gamescope
-## state up-to-date.
-func update() -> void:
- blur_mode = get_blur_mode()
- focused_window = get_focused_window()
- focused_app = get_focused_app()
- focused_app_gfx = get_focused_app_gfx()
- focusable_windows = get_focusable_windows()
- focusable_apps = get_focusable_apps()
- baselayer_window = get_baselayer_window()
- if not baselayer_window in get_focusable_windows():
- baselayer_window = -1
- remove_baselayer_window()
-
-
-## Returns the name of the given xwayland display (e.g. ":1")
-func get_display_name(display: XWAYLAND) -> String:
- var xwayland := get_xwayland(display)
- if not xwayland:
- return ""
- return xwayland.get_name()
-
-
-## Returns true if the given X property exists on the given window.
-func has_xprop(window_id: int, key: String, display: XWAYLAND) -> bool:
- var xwayland := get_xwayland(display)
- if not xwayland:
- return false
- return xwayland.has_xprop(window_id, key)
-
-
-## Returns a list of X properties on the given window
-func list_xprops(window_id: int, display: XWAYLAND) -> PackedStringArray:
- var xwayland := get_xwayland(display)
- if not xwayland:
- return []
- return xwayland.list_xprops(window_id)
-
-
-## Returns the name of the given window.
-func get_window_name(window_id: int, display: XWAYLAND = XWAYLAND.GAME) -> String:
- var xwayland := get_xwayland(display)
- if not xwayland:
- return ""
- return xwayland.get_window_name(window_id)
-
-
-## Returns the PID of the given window. Returns -1 if no PID was found.
-func get_window_pid(window_id: int, display: XWAYLAND) -> int:
- var xwayland := get_xwayland(display)
- if not xwayland:
- return -1
- return xwayland.get_window_pid(window_id)
-
-
-## Returns the xwayland window ID for the given process. Returns -1 if no
-## window was found.
-func get_window_id(pid: int, display: XWAYLAND) -> int:
- var display_name := get_display_name(display)
- logger.trace("Getting Window ID for {0} on display {1}".format([pid, display_name]))
- var xwayland := get_xwayland(display)
- if not xwayland:
- return -1
- var root_id := xwayland.get_root_window_id()
- var all_windows := get_all_windows(root_id, display)
- for window_id in all_windows:
- var window_pid := xwayland.get_window_pid(window_id)
- if pid == window_pid:
- return window_id
- window_pid = xwayland.get_xprop(window_id, "_NET_WM_PID")
- if pid == window_pid:
- return window_id
-
- return -1
-
-
-## Returns the xwayland window ID(s) for the given process using multiple methods
-## to try and discover.
-func get_window_ids(pid: int, display: XWAYLAND) -> PackedInt32Array:
- var window_ids := PackedInt32Array()
- var display_name := get_display_name(display)
- logger.trace("Getting Window ID for {0} on display {1}".format([pid, display_name]))
- var xwayland := get_xwayland(display)
- if not xwayland:
- return window_ids
- var root_id := xwayland.get_root_window_id()
- var all_windows := get_all_windows(root_id, display)
- for window_id in all_windows:
- var window_pid := xwayland.get_window_pid(window_id)
- if pid == window_pid and not window_id in window_ids:
- window_ids.append(window_id)
- var net_window_pid := xwayland.get_xprop(window_id, "_NET_WM_PID")
- if pid == net_window_pid and not net_window_pid in window_ids:
- window_ids.append(net_window_pid)
-
- return window_ids
-
-
-## Returns the child window ids of the given window
-func get_window_children(window_id: int, display: XWAYLAND) -> PackedInt32Array:
- var xwayland := get_xwayland(display)
- if not xwayland:
- return PackedInt32Array()
- var children := xwayland.get_window_children(window_id)
- if len(children) == 0:
- return PackedInt32Array()
- return children
-
-
-## Recursively returns all child windows of the given window id
-func get_all_windows(window_id: int, display: XWAYLAND) -> PackedInt32Array:
- var xwayland := get_xwayland(display)
- if not xwayland:
- return PackedInt32Array()
- var children := xwayland.get_window_children(window_id)
- if len(children) == 0:
- return PackedInt32Array([])
-
- var leaves := PackedInt32Array()
- for child in children:
- leaves.append(child)
- leaves.append_array(get_all_windows(child, display))
-
- return leaves
-
-
-## Returns true if the window with the given window ID exists
-func is_focusable_app(window_id: int, display: XWAYLAND = XWAYLAND.PRIMARY) -> bool:
- var focusable := get_focusable_apps(display)
- if window_id in focusable:
- return true
- return false
-
-
-## Returns the root window ID of the given display
-func get_root_window_id(display: XWAYLAND) -> int:
- var xwayland := get_xwayland(display)
- if not xwayland:
- return -1
- return xwayland.get_root_window_id()
-
-
-## Returns a list of focusable app window ids
-func get_focusable_apps(display: XWAYLAND = XWAYLAND.PRIMARY) -> PackedInt32Array:
- var xwayland := get_xwayland(display)
- if not xwayland:
- return PackedInt32Array()
- var root_id := xwayland.get_root_window_id()
- return _get_xprop_array(xwayland, root_id, "GAMESCOPE_FOCUSABLE_APPS")
-
-
-## Returns a list of focusable window ids
-func get_focusable_windows(display: XWAYLAND = XWAYLAND.PRIMARY) -> PackedInt32Array:
- var xwayland := get_xwayland(display)
- if not xwayland:
- return PackedInt32Array()
- var root_id := xwayland.get_root_window_id()
- return _get_xprop_array(xwayland, root_id, "GAMESCOPE_FOCUSABLE_WINDOWS")
-
-
-## Returns a list of focusable window names
-func get_focusable_window_names(display: XWAYLAND = XWAYLAND.PRIMARY) -> PackedStringArray:
- var focusable := get_focusable_windows(display)
- var results := PackedStringArray()
- for window_id in focusable:
- var name := get_window_name(window_id, display)
- results.append(name)
- return results
-
-
-## Return the currently focused window id.
-func get_focused_window(display: XWAYLAND = XWAYLAND.PRIMARY) -> int:
- var xwayland := get_xwayland(display)
- if not xwayland:
- return -1
- var root_id := xwayland.get_root_window_id()
- var results := _get_xprop_array(xwayland, root_id, "GAMESCOPE_FOCUSED_WINDOW")
- if results.size() == 0:
- return 0
- return results[0]
-
-
-## Return the currently focused app id.
-func get_focused_app(display: XWAYLAND = XWAYLAND.PRIMARY) -> int:
- var xwayland := get_xwayland(display)
- if not xwayland:
- return -1
- var root_id := xwayland.get_root_window_id()
- var results := _get_xprop_array(xwayland, root_id, "GAMESCOPE_FOCUSED_APP")
- if results.size() == 0:
- return 0
- return results[0]
-
-
-## Return the currently focused gfx app id.
-func get_focused_app_gfx(display: XWAYLAND = XWAYLAND.PRIMARY) -> int:
- var xwayland := get_xwayland(display)
- if not xwayland:
- return -1
- var root_id := xwayland.get_root_window_id()
- var results := _get_xprop_array(xwayland, root_id, "GAMESCOPE_FOCUSED_APP_GFX")
- if results.size() == 0:
- return 0
- return results[0]
-
-
-## Sets the given window as the main launcher app.
-## Gamescope is hard-coded to look for appId 769
-func set_main_app(window_id: int, display: XWAYLAND = XWAYLAND.OGUI) -> int:
- var xwayland := get_xwayland(display)
- if not xwayland:
- return -1
- return _set_xprop(xwayland, window_id, "STEAM_GAME", OVERLAY_GAME_ID)
-
-
-## Set the given window as the primary overlay input focus. This should be set to
-## "1" whenever the overlay wants to intercept input from a game.
-func set_input_focus(window_id: int, value: int, display: XWAYLAND = XWAYLAND.OGUI) -> int:
- var xwayland := get_xwayland(display)
- if not xwayland:
- return -1
- return _set_xprop(xwayland, window_id, "STEAM_INPUT_FOCUS", value)
-
-
-## Returns whether or not the overlay window is currently focused
-func is_overlay_focused(display: XWAYLAND = XWAYLAND.OGUI) -> bool:
- return get_focused_app(display) == OVERLAY_GAME_ID
-
-
-## Get the overlay status for the given window
-func get_overlay(window_id: int, display: XWAYLAND = XWAYLAND.OGUI) -> int:
- var xwayland := get_xwayland(display)
- if not xwayland:
- return -1
- return _get_xprop(xwayland, window_id, "STEAM_OVERLAY")
-
-
-## Set the given window as an overlay
-func set_overlay(window_id: int, value: int, display: XWAYLAND = XWAYLAND.OGUI) -> int:
- var xwayland := get_xwayland(display)
- if not xwayland:
- return -1
- return _set_xprop(xwayland, window_id, "STEAM_OVERLAY", value)
-
-
-## Set the given window as a notification. This should be set to "1" when some
-## UI wants to be shown but not intercept input.
-func set_notification(window_id: int, value: int, display: XWAYLAND = XWAYLAND.OGUI) -> int:
- var xwayland := get_xwayland(display)
- if not xwayland:
- return -1
- return _set_xprop(xwayland, window_id, "STEAM_NOTIFICATION", value)
-
-
-## Set the given window as an external overlay
-func set_external_overlay(window_id: int, value: int, display: XWAYLAND = XWAYLAND.OGUI) -> int:
- var xwayland := get_xwayland(display)
- if not xwayland:
- return -1
- return _set_xprop(xwayland, window_id, "GAMESCOPE_EXTERNAL_OVERLAY", value)
-
-
-## Returns the currently set app ID on the given window
-func get_app_id(window_id: int, display: XWAYLAND = XWAYLAND.GAME) -> int:
- var xwayland := get_xwayland(display)
- if not xwayland:
- return -1
- return _get_xprop(xwayland, window_id, "STEAM_GAME")
-
-
-## Sets the app ID on the given window
-func set_app_id(window_id: int, app_id: int, display: XWAYLAND = XWAYLAND.GAME) -> int:
- var xwayland := get_xwayland(display)
- if not xwayland:
- return -1
- return _set_xprop(xwayland, window_id, "STEAM_GAME", app_id)
-
-
-## Returns whether or not the given window has an app ID set
-func has_app_id(window_id: int, display: XWAYLAND = XWAYLAND.GAME) -> bool:
- return has_xprop(window_id, "STEAM_GAME", display)
-
-
-## Sets the Gamescope FPS limit
-func set_fps_limit(fps: int = 60, display: XWAYLAND = XWAYLAND.PRIMARY) -> int:
- logger.debug("Setting FPS to: {0}".format([fps]))
- var xwayland := get_xwayland(display)
- if not xwayland:
- return -1
- var root_id := xwayland.get_root_window_id()
- return _set_xprop(xwayland, root_id, "GAMESCOPE_FPS_LIMIT", fps)
-
-
-## Returns the Gamescope FPS limit
-func get_fps_limit(display: XWAYLAND = XWAYLAND.PRIMARY) -> int:
- var xwayland := get_xwayland(display)
- if not xwayland:
- return -1
- var root_id := xwayland.get_root_window_id()
- return _get_xprop(xwayland, root_id, "GAMESCOPE_FPS_LIMIT")
-
-
-## Returns the current Gamescope blur mode
-func get_blur_mode(display: XWAYLAND = XWAYLAND.PRIMARY) -> int:
- var xwayland := get_xwayland(display)
- if not xwayland:
- return -1
- var root_id := xwayland.get_root_window_id()
- return _get_xprop(xwayland, root_id, "GAMESCOPE_BLUR_MODE")
-
-
-## Sets the Gamescope blur mode
-func set_blur_mode(mode: BLUR_MODE = BLUR_MODE.OFF, display: XWAYLAND = XWAYLAND.PRIMARY) -> int:
- logger.debug("Setting blur mode to: {0}".format([mode]))
- var xwayland := get_xwayland(display)
- if not xwayland:
- return -1
- var root_id := xwayland.get_root_window_id()
- var err := _set_xprop(xwayland, root_id, "GAMESCOPE_BLUR_MODE", mode)
- blur_mode = mode
- return err
-
-
-## Sets the Gamescope blur radius when blur is active
-func set_blur_radius(radius: int, display: XWAYLAND = XWAYLAND.PRIMARY) -> int:
- logger.debug("Setting blur radius to: {0}".format([radius]))
- var xwayland := get_xwayland(display)
- if not xwayland:
- return -1
- var root_id := xwayland.get_root_window_id()
- return _set_xprop(xwayland, root_id, "GAMESCOPE_BLUR_RADIUS", radius)
-
-
-## Configures Gamescope to allow tearing or not
-func set_allow_tearing(allow: bool, display: XWAYLAND = XWAYLAND.PRIMARY) -> int:
- logger.debug("Setting tearing to: {0}".format([allow]))
- var xwayland := get_xwayland(display)
- if not xwayland:
- return -1
- var value := 1 if allow else 0
- var root_id := xwayland.get_root_window_id()
- return _set_xprop(xwayland, root_id, "GAMESCOPE_ALLOW_TEARING", value)
-
-
-## Returns the currently set manual focus
-func get_baselayer_window(display: XWAYLAND = XWAYLAND.PRIMARY) -> int:
- var xwayland := get_xwayland(display)
- if not xwayland:
- return -1
- var root_id := xwayland.get_root_window_id()
- return _get_xprop(xwayland, root_id, "GAMESCOPECTRL_BASELAYER_WINDOW")
-
-
-## Focuses the given window
-func set_baselayer_window(window_id: int, display: XWAYLAND = XWAYLAND.PRIMARY) -> int:
- var xwayland := get_xwayland(display)
- if not xwayland:
- return -1
- var root_id := xwayland.get_root_window_id()
- return _set_xprop(xwayland, root_id, "GAMESCOPECTRL_BASELAYER_WINDOW", window_id)
-
-
-## Removes the baselayer property to un-focus windows
-func remove_baselayer_window(display: XWAYLAND = XWAYLAND.PRIMARY) -> int:
- var xwayland := get_xwayland(display)
- if not xwayland:
- return -1
- var root_id := xwayland.get_root_window_id()
- return _remove_xprop(xwayland, root_id, "GAMESCOPECTRL_BASELAYER_WINDOW")
-
-
-## Request a screenshot from gamescope
-func request_screenshot(display: XWAYLAND = XWAYLAND.PRIMARY) -> int:
- var xwayland := get_xwayland(display)
- if not xwayland:
- return -1
- var root_id := xwayland.get_root_window_id()
- return _set_xprop(xwayland, root_id, "GAMESCOPECTRL_REQUEST_SCREENSHOT", 1)
-
-
-## Sets the xwayland mode resolution on the given xwayland display
-## number (default: XWAYLAND.GAME).
-func set_resolution(resolution: Vector2i, allow_super: bool = false, display: XWAYLAND = XWAYLAND.GAME) -> int:
- var xwayland := get_xwayland(XWAYLAND.PRIMARY)
- if not xwayland:
- return -1
-
- var target_display := get_display_number(display)
- var root_id := xwayland.get_root_window_id()
- var allow_super_value := 1 if allow_super else 0
- var args := PackedInt32Array([target_display, resolution.x, resolution.y, allow_super_value])
- return _set_xprop_array(xwayland, root_id, "GAMESCOPE_XWAYLAND_MODE_CONTROL", args)
-
-
-## Returns the currently set gamescope saturation
-# Based on vibrantDeck by Scrumplex
-func get_saturation(display: XWAYLAND = XWAYLAND.PRIMARY) -> float:
- var xwayland := get_xwayland(display)
- if not xwayland:
- return -1
- var root_id := xwayland.get_root_window_id()
-
- var matrix := _get_xprop_array(xwayland, root_id, "GAMESCOPE_COLOR_MATRIX")
- if matrix.size() < 2:
- return -1
-
- # [1065353216, 0, 0, 0, 1065353216, 0, 0, 0, 1065353216]
- var matrix_arr: Array[int] = Array(matrix)
- # Convert the array of longs to floats
- # [1.0, 0, 0, 0, 1.0, 0, 0, 0, 1.0]
- var coeffs := matrix_arr.map(_long_to_float)
- var saturation := snappedf(coeffs[0] - coeffs[1], 0.01)
-
- return saturation
-
-
-## Set the gamescope saturation
-# Based on vibrantDeck by Scrumplex
-func set_saturation(saturation: float, display: XWAYLAND = XWAYLAND.PRIMARY) -> int:
- saturation = maxf(saturation, 0.0)
- saturation = minf(saturation, 4.0)
- logger.debug("Setting saturation to: " + str(saturation))
-
- # Generate color transformation matrix
- var coeffs := _saturation_to_coeffs(saturation)
-
- # Represent floats as integars (long)
- var long_coeffs := coeffs.map(_float_to_long)
-
- # Get the xwayland to set the property on
- var xwayland := get_xwayland(display)
- if not xwayland:
- return -1
- var root_id := xwayland.get_root_window_id()
-
- logger.debug("Setting color matrix coeffs: " + str(long_coeffs))
- return _set_xprop_array(xwayland, root_id, "GAMESCOPE_COLOR_MATRIX", long_coeffs)
-
-
-func _saturation_to_coeffs(saturation: float) -> Array[float]:
- var coeff := (1.0 - saturation) / 3.0
-
- var coeffs: Array[float] = []
- coeffs.resize(9)
- coeffs.fill(coeff)
- coeffs[0] += saturation
- coeffs[4] += saturation
- coeffs[8] += saturation
-
- return coeffs
-
-
-func _float_to_long(x: float) -> int:
- var bytes := PackedByteArray()
- bytes.resize(4)
- bytes.encode_float(0, x)
- return bytes.decode_u32(0)
-
-
-func _long_to_float(x: int) -> float:
- var bytes := PackedByteArray()
- bytes.resize(4)
- bytes.encode_u32(0, x)
- return bytes.decode_float(0)
-
-
-## Returns the display type for the given display name
-func get_display_type(name: String) -> XWAYLAND:
- if xwayland_primary.get_name() == name:
- return XWAYLAND.PRIMARY
- if xwayland_ogui.get_name() == name:
- return XWAYLAND.OGUI
- return XWAYLAND.GAME
-
-
-## Returns the name of the given xwayland display
-func get_display_number(display: XWAYLAND) -> int:
- var name := get_display_name(display)
- var clean_name := name.replace(":", "")
- if clean_name.is_valid_int():
- return clean_name.to_int()
- logger.error("Unable to determine display number from name: " + name)
- return 0
-
-
-## Returns the xwayland instance for the given display type
-func get_xwayland(display: XWAYLAND) -> Xlib:
- if xwaylands.size() == 0:
- return null
- if display == XWAYLAND.PRIMARY:
- return xwayland_primary
- if display == XWAYLAND.OGUI:
- return xwayland_ogui
- return xwayland_game
-
-
-## Returns true if Gamescope is tracking the given display
-func _has_xwayland(display: String) -> bool:
- for xwayland in xwaylands:
- if xwayland.get_name() == display:
- return true
- return false
-
-
-## Returns true if the given xwayland instance is the primary gamescope instance
-func _is_gamescope_xwayland_primary(xwayland: Xlib) -> bool:
- var root_id := xwayland.get_root_window_id()
- if xwayland.has_xprop(root_id, "GAMESCOPE_FOCUSED_WINDOW"):
- return true
- return false
-
-
-## Returns true if the given xwayland instance is a gamescope instance
-func _is_gamescope_xwayland(xwayland: Xlib) -> bool:
- var root_id := xwayland.get_root_window_id()
- if xwayland.has_xprop(root_id, "GAMESCOPE_CURSOR_VISIBLE_FEEDBACK"):
- return true
- return false
-
-
-## Sets the given X property on the given window.
-## Example:
-## [codeblock]
-## Gamescope._set_xprop(":0", 1234, "STEAM_INPUT", 1)
-## [/codeblock]
-func _set_xprop(xwayland: Xlib, window_id: int, key: String, value: int) -> int:
- var msg_args := [window_id, key, value, xwayland.get_name()]
- logger.debug("Setting window {0} key {1} to {2} on display {3}".format(msg_args))
- return xwayland.set_xprop(window_id, key, value)
-
-
-## Sets the given X property with the given array of values
-func _set_xprop_array(xwayland: Xlib, window_id: int, key: String, values: PackedInt32Array) -> int:
- var msg_args := [window_id, key, str(values), xwayland.get_name()]
- logger.debug("Setting window {0} key {1} to {2} on display {3}".format(msg_args))
- # TODO: Fix set_xprop_array and use that instead of xprop
- var values_str_arr := []
- for value in values:
- values_str_arr.append(str(value))
- var values_str := ",".join(values_str_arr)
- var cmd := "env"
- var args := ["DISPLAY="+xwayland.get_name(), "xprop", "-id", str(window_id), "-f", key, "32c", "-set", key, values_str]
- return OS.execute(cmd, args)
-
-
-## Returns the value of the given X property for the given window. Returns
-## [member Xlib.ERR_XPROP_NOT_FOUND] if property doesn't exist.
-func _get_xprop(xwayland: Xlib, window_id: int, key: String) -> int:
- return xwayland.get_xprop(window_id, key)
-
-
-## Removes the given X property for the given window.
-func _remove_xprop(xwayland: Xlib, window_id: int, key: String) -> int:
- return xwayland.remove_xprop(window_id, key)
-
-
-## Returns an array of values for the given X property for the given window.
-## Returns an empty array if property was not found.
-func _get_xprop_array(xwayland: Xlib, window_id: int, key: String) -> PackedInt32Array:
- return xwayland.get_xprop_array(window_id, key)
diff --git a/core/global/gamescope.tres b/core/global/gamescope.tres
deleted file mode 100644
index f394fbb12..000000000
--- a/core/global/gamescope.tres
+++ /dev/null
@@ -1,7 +0,0 @@
-[gd_resource type="Resource" script_class="Gamescope" load_steps=2 format=3 uid="uid://blr55dcwc05m1"]
-
-[ext_resource type="Script" path="res://core/global/gamescope.gd" id="1_ipl5o"]
-
-[resource]
-script = ExtResource("1_ipl5o")
-log_level = 4
diff --git a/core/global/gamescope_test.gd b/core/global/gamescope_test.gd
deleted file mode 100644
index e64b41dd3..000000000
--- a/core/global/gamescope_test.gd
+++ /dev/null
@@ -1,15 +0,0 @@
-extends GutTest
-
-var gamescope := Gamescope.new()
-
-
-func test_float_to_long() -> void:
- var to_int := gamescope._float_to_long(1.3)
- gut.p(to_int)
- assert_eq(to_int, 1067869798, "should be converted to a long")
-
-
-func test_long_to_float() -> void:
- var to_float := gamescope._long_to_float(1067869798)
- gut.p(to_float)
- assert_almost_eq(to_float, 1.3, 0.01, "should be approximately 1.3")
diff --git a/core/global/keyboard_instance.gd b/core/global/keyboard_instance.gd
index 172ba67f0..d0f9caa9c 100644
--- a/core/global/keyboard_instance.gd
+++ b/core/global/keyboard_instance.gd
@@ -58,4 +58,3 @@ func set_context(ctx: KeyboardContext) -> void:
context = ctx
context_changed.emit(ctx)
ctx.entered.emit()
-
diff --git a/core/global/launch_manager.gd b/core/global/launch_manager.gd
index 7d65adffc..d753d43cc 100644
--- a/core/global/launch_manager.gd
+++ b/core/global/launch_manager.gd
@@ -12,82 +12,135 @@ class_name LaunchManager
## periodically check on launched games to see if they have exited, or are
## opening new windows that might need attention. Example:
## [codeblock]
-## const LaunchManager := preload("res://core/global/launch_manager.tres")
+## var launch_manager := load("res://core/global/launch_manager.tres") as LaunchManager
## ...
## # Create a LibraryLaunchItem to run something
## var item := LibraryLaunchItem.new()
## item.command = "vkcube"
##
## # Launch the app with LaunchManager
-## var running_app := LaunchManager.launch(item)
+## var running_app := launch_manager.launch(item)
##
## # Get a list of running apps
-## var running := LaunchManager.get_running()
+## var running := launch_manager.get_running()
## print(running)
##
## # Stop an app with LaunchManager
-## LaunchManager.stop(running_app)
+## launch_manager.stop(running_app)
## [/codeblock]
+signal all_apps_stopped()
signal app_launched(app: RunningApp)
signal app_stopped(app: RunningApp)
signal app_switched(from: RunningApp, to: RunningApp)
signal recent_apps_changed()
const settings_manager := preload("res://core/global/settings_manager.tres")
-const NotificationManager := preload("res://core/global/notification_manager.tres")
+const notification_manager := preload("res://core/global/notification_manager.tres")
-var gamescope := preload("res://core/global/gamescope.tres") as Gamescope
-var input_plumber := load("res://core/systems/input/input_plumber.tres") as InputPlumber
+var gamescope := preload("res://core/systems/gamescope/gamescope.tres") as GamescopeInstance
+var input_plumber := load("res://core/systems/input/input_plumber.tres") as InputPlumberInstance
var state_machine := preload("res://assets/state/state_machines/global_state_machine.tres") as StateMachine
var in_game_state := preload("res://assets/state/states/in_game.tres") as State
var in_game_menu_state := preload("res://assets/state/states/in_game_menu.tres") as State
var PID: int = OS.get_process_id()
+var _xwayland_primary := gamescope.get_xwayland(gamescope.XWAYLAND_TYPE_PRIMARY)
+var _xwayland_ogui := gamescope.get_xwayland(gamescope.XWAYLAND_TYPE_OGUI)
+var _xwayland_game := gamescope.get_xwayland(gamescope.XWAYLAND_TYPE_GAME)
var _sandbox := Sandbox.get_sandbox()
var _current_app: RunningApp
var _pid_to_windows := {}
var _running: Array[RunningApp] = []
-var _stopping: Array[RunningApp] = []
+var _running_background: Array[RunningApp] = []
var _apps_by_pid: Dictionary = {}
var _apps_by_name: Dictionary = {}
var _data_dir: String = ProjectSettings.get_setting("OpenGamepadUI/data/directory")
var _persist_path: String = "/".join([_data_dir, "launcher.json"])
var _persist_data: Dictionary = {"version": 1}
-var _ogui_window_id := gamescope.get_window_id(PID, gamescope.XWAYLAND.OGUI)
+var _ogui_window_id := 0
var should_manage_overlay := true
var logger := Log.get_logger("LaunchManager", Log.LEVEL.INFO)
+var _focused_app_id := 0
# Connect to Gamescope signals
func _init() -> void:
- # When window focus changes, update the current app and gamepad profile
- var on_focus_changed := func(from: int, to: int):
- logger.info("Window focus changed from " + str(from) + " to: " + str(to))
- var last_app := _current_app
- _current_app = _detect_running_app(to)
-
- logger.debug("Last app: " + str(last_app) + " current_app: " + str(_current_app))
- app_switched.emit(last_app, _current_app)
-
- # If the app has a gamepad profile, set it
- if to != _ogui_window_id and _current_app:
- set_app_gamepad_profile(_current_app)
+ _load_persist_data()
+
+ # Get the window ID of OpenGamepadUI
+ if _xwayland_ogui:
+ var ogui_windows := _xwayland_ogui.get_windows_for_pid(PID)
+ if not ogui_windows.is_empty():
+ _ogui_window_id = ogui_windows[0]
+
+ # Listen for signals from the primary Gamescope XWayland
+ if _xwayland_primary:
+ # Debug print when the focused window changes
+ var on_focus_changed := func(from: int, to: int):
+ if from == to:
+ return
+ logger.info("Window focus changed from " + str(from) + " to: " + str(to))
+ self.check_running.call_deferred()
+ _xwayland_primary.focused_window_updated.connect(on_focus_changed)
- # If we don't want LaunchManager to manage overlay (I.E. overlay mode), return false always.
- if not should_manage_overlay:
+ # When focused app changes, update the current app and gamepad profile
+ var on_focused_app_changed := func(_from: int, to: int) -> void:
+ if _focused_app_id == to:
return
+ logger.debug("Focused app changed from " + str(_focused_app_id) + " to " + str(to))
+ _focused_app_id = to
- gamescope.focused_window_updated.connect(on_focus_changed)
+ # If OGUI was focused, set the global gamepad profile
+ if to in [gamescope.OVERLAY_GAME_ID, 0, 1]:
+ set_gamepad_profile("")
+ return
- # Debug print when the focused app changed
- var on_focused_app_changed := func(from: int, to: int) -> void:
- logger.debug("Focused app changed from " + str(from) + " to " + str(to))
- gamescope.focused_app_updated.connect(on_focused_app_changed)
+ # Find the running app for the given app id
+ var last_app := self._current_app
+ var detected_app: RunningApp
+ for app in _running:
+ if app.app_id == to:
+ detected_app = app
+
+ # If the running app was not launched by OpenGamepadUI, then detect it.
+ if not detected_app:
+ detected_app = _detect_running_app(to)
+ self._current_app = detected_app
+
+ logger.debug("Last app: " + str(last_app) + " current_app: " + str(self._current_app))
+ app_switched.emit(last_app, self._current_app)
+
+ # If the app has a gamepad profile, set it
+ if self._current_app:
+ set_app_gamepad_profile(self._current_app)
+ _xwayland_primary.focused_app_updated.connect(on_focused_app_changed)
+
+ # Listen for when focusable apps change
+ var on_focusable_apps_changed := func(from: PackedInt64Array, to: PackedInt64Array):
+ if from == to:
+ return
+ logger.debug("Focusable apps changed from", from, "to", to)
+ self.check_running.call_deferred()
+ # If focusable apps has changed and the currently focused app no longer exists,
+ # remove the manual focus
+ var baselayer_app := _xwayland_primary.baselayer_app
+ to.append(_xwayland_primary.focused_app)
+ if baselayer_app > 0 and not baselayer_app in to:
+ _xwayland_primary.remove_baselayer_app()
+ _xwayland_primary.focusable_apps_updated.connect(on_focusable_apps_changed)
+
+ # Listen for signals from the secondary Gamescope XWayland
+ if _xwayland_game:
+ # Listen for window created/destroyed events
+ var on_window_created := func(window_id: int):
+ logger.debug("Window created:", window_id)
+ self.check_running.call_deferred()
+ _xwayland_game.window_created.connect(on_window_created)
# Whenever the in-game state is entered, set the gamepad profile
- var on_game_state_entered := func(from: State):
+ var on_game_state_entered := func(_from: State):
if _current_app:
set_app_gamepad_profile(_current_app)
@@ -95,8 +148,9 @@ func _init() -> void:
if not should_manage_overlay:
return
- logger.debug("Enabling STEAM_OVERLAY atom")
- gamescope.set_overlay(_ogui_window_id, 0)
+ if _xwayland_ogui:
+ logger.debug("Enabling STEAM_OVERLAY atom")
+ _xwayland_ogui.set_overlay(_ogui_window_id, 0)
var on_game_state_exited := func(_to: State):
# Set the gamepad profile to the global profile
@@ -106,11 +160,13 @@ func _init() -> void:
if not should_manage_overlay:
return
- logger.debug("Disabling STEAM_OVERLAY atom")
- gamescope.set_overlay(_ogui_window_id, 1)
+ if _xwayland_ogui:
+ logger.debug("Disabling STEAM_OVERLAY atom")
+ _xwayland_ogui.set_overlay(_ogui_window_id, 1)
in_game_state.state_entered.connect(on_game_state_entered)
in_game_state.state_exited.connect(on_game_state_exited)
+ set_gamepad_profile("")
# Loads persistent data like recent games launched, etc.
@@ -137,9 +193,39 @@ func _save_persist_data():
file.flush()
-## Launches the given command on the target xwayland display. Returns a PID
-## of the launched process.
+## Launches the given application and switches to the in-game state. Returns a
+## [RunningApp] instance of the application.
func launch(app: LibraryLaunchItem) -> RunningApp:
+ var running_app := _launch(app)
+
+ # Add the running app to our list and change to the IN_GAME state
+ _add_running(running_app)
+ state_machine.set_state([in_game_state])
+ _update_recent_apps(app)
+
+ return running_app
+
+
+## Launches the given app in the background. Returns the [RunningApp] instance.
+func launch_in_background(app: LibraryLaunchItem) -> RunningApp:
+ # Start the application
+ var running_app := _launch(app)
+
+ # Listen for app state changes
+ var on_app_state_changed := func(from: RunningApp.STATE, to: RunningApp.STATE):
+ if to != RunningApp.STATE.STOPPED:
+ return
+ logger.debug("Cleaning up pid {0}".format([running_app.pid]))
+ _running_background.erase(running_app)
+ logger.debug("Currently running background apps:", _running_background)
+ running_app.state_changed.connect(on_app_state_changed)
+ _running_background.append(running_app)
+
+ return running_app
+
+
+## Launches the given app
+func _launch(app: LibraryLaunchItem) -> RunningApp:
var cmd: String = app.command
var args: PackedStringArray = app.args
var env: Dictionary = app.env.duplicate()
@@ -150,28 +236,30 @@ func launch(app: LibraryLaunchItem) -> RunningApp:
# Override any parameters that may be in the user's config for this game
var section := ".".join(["game", app.name.to_lower()])
var cmd_key := ".".join(["command", app._provider_id])
- var user_cmd = settings_manager.get_value(section, cmd_key)
- if user_cmd and user_cmd is String:
+ var user_cmd = settings_manager.get_value(section, cmd_key, "")
+ if user_cmd and user_cmd is String and not (user_cmd as String).is_empty():
cmd = user_cmd
var args_key := ".".join(["args", app._provider_id])
- var user_args = settings_manager.get_value(section, args_key)
- if user_args and user_args is PackedStringArray:
+ var user_args = settings_manager.get_value(section, args_key, PackedStringArray())
+ if user_args and user_args is PackedStringArray and not (user_args as PackedStringArray).is_empty():
args = user_args
var cwd_key := ".".join(["cwd", app._provider_id])
- var user_cwd = settings_manager.get_value(section, cwd_key)
- if user_cwd and user_cwd is String:
+ var user_cwd = settings_manager.get_value(section, cwd_key, "")
+ if user_cwd and user_cwd is String and not (user_cwd as String).is_empty():
cwd = user_cwd
var env_key := ".".join(["env", app._provider_id])
- var user_env = settings_manager.get_value(section, env_key)
- if user_env and user_env is Dictionary:
+ var user_env = settings_manager.get_value(section, env_key, {})
+ if user_env and user_env is Dictionary and not (user_env as Dictionary).is_empty():
env = user_env
var sandboxing_key := ".".join(["use_sandboxing", app._provider_id])
- var use_sandboxing := settings_manager.get_value(section, sandboxing_key, true) as bool
+ var use_sandboxing := settings_manager.get_value(section, sandboxing_key, false) as bool
# Set the display environment if one was not set.
if not "DISPLAY" in env:
- env["DISPLAY"] = gamescope.get_display_name(Gamescope.XWAYLAND.GAME)
- var display := env["DISPLAY"] as String
+ if _xwayland_game:
+ env["DISPLAY"] = _xwayland_game.name
+ else:
+ env["DISPLAY"] = ""
# Set the OGUI ID environment variable
env["OGUI_ID"] = app.name
@@ -196,18 +284,9 @@ func launch(app: LibraryLaunchItem) -> RunningApp:
logger.info("Launching game with command: {0} {1}".format([exec, str(command)]))
# Launch the application process
- var pid = Reaper.create_process(exec, command)
- logger.info("Launched with PID: {0}".format([pid]))
-
- # Create a running app instance
- var running_app := _make_running_app(app, pid, display)
- running_app.command = command
- running_app.environment = env
-
- # Add the running app to our list and change to the IN_GAME state
- _add_running(running_app)
- state_machine.set_state([in_game_state])
- _update_recent_apps(app)
+ var running_app := RunningApp.spawn(app, env, exec, command)
+ logger.info("Launched with PID: {0}".format([running_app.pid]))
+
return running_app
@@ -254,6 +333,11 @@ func get_running() -> Array[RunningApp]:
return _running.duplicate()
+## Returns a list of currently running background apps
+func get_running_background() -> Array[RunningApp]:
+ return _running_background.duplicate()
+
+
## Returns the running app from the given window id
func get_running_from_window_id(window_id: int) -> RunningApp:
for app in _running:
@@ -289,9 +373,12 @@ func set_app_gamepad_profile(app: RunningApp) -> void:
# Check to see if this game has any gamepad profiles. If so, set our
# gamepads to use them.
var section := ".".join(["game", app.launch_item.name.to_lower()])
- var profile_path = settings_manager.get_value(section, "gamepad_profile", "")
+ var profile_path := settings_manager.get_value(section, "gamepad_profile", "") as String
var profile_gamepad := settings_manager.get_value(section, "gamepad_profile_target", "") as String
- logger.debug("Using profile '" + profile_path + "' with gamepad type '" + profile_gamepad + "'")
+ if profile_path.is_empty():
+ logger.debug("Using global gamepad profile")
+ else:
+ logger.debug("Using profile '" + profile_path + "' with gamepad type '" + profile_gamepad + "'")
set_gamepad_profile(profile_path, profile_gamepad)
@@ -305,26 +392,10 @@ func set_gamepad_profile(path: String, target_gamepad: String = "") -> void:
# If no profile was specified, unset the gamepad profiles
if path == "":
# Try check to see if there is a global gamepad setting
- var profile_path := settings_manager.get_value("input", "gamepad_profile", InputPlumber.DEFAULT_GLOBAL_PROFILE) as String
- if not profile_path.ends_with(".json") or not FileAccess.file_exists(profile_path):
- profile_path = InputPlumber.DEFAULT_GLOBAL_PROFILE
- logger.info("Loading global gamepad profile: " + profile_path)
-
- for gamepad in input_plumber.composite_devices:
- gamepad.target_modify_profile(profile_path, profile_modifier)
-
- # Set the target gamepad if one was specified
- if not target_gamepad.is_empty():
- var target_devices := [target_gamepad, "keyboard", "mouse"]
- match target_gamepad:
- "xb360", "xbox-series", "xbox-elite", "gamepad":
- target_devices.append("touchpad")
- _:
- logger.debug(target_gamepad, "needs no additional target devices.")
- logger.info("Setting target devices to: ", target_devices)
- gamepad.set_target_devices(target_devices)
-
- return
+ path = settings_manager.get_value("input", "gamepad_profile", InputPlumber.DEFAULT_GLOBAL_PROFILE) as String
+ # Verify we loaded a valid profile, or fallback.
+ if not path.ends_with(".json") or not FileAccess.file_exists(path):
+ path = InputPlumber.DEFAULT_GLOBAL_PROFILE
logger.info("Loading gamepad profile: " + path)
if not FileAccess.file_exists(path):
@@ -338,12 +409,12 @@ func set_gamepad_profile(path: String, target_gamepad: String = "") -> void:
return
# TODO: Save profiles for individual controllers?
- for gamepad in input_plumber.composite_devices:
- gamepad.target_modify_profile(path, profile_modifier)
+ for gamepad in input_plumber.get_composite_devices():
+ InputPlumber.load_target_modified_profile(gamepad, path, profile_modifier)
# Set the target gamepad if one was specified
if not target_gamepad.is_empty():
- var target_devices := [target_gamepad, "keyboard", "mouse"]
+ var target_devices := PackedStringArray([target_gamepad, "keyboard", "mouse"])
match target_gamepad:
"xb360", "xbox-series", "xbox-elite", "gamepad":
target_devices.append("touchpad")
@@ -352,12 +423,12 @@ func set_gamepad_profile(path: String, target_gamepad: String = "") -> void:
logger.info("Setting target devices to: ", target_devices)
gamepad.set_target_devices(target_devices)
- var notify := Notification.new("Using gamepad profile: " + profile.name)
- NotificationManager.show(notify)
+ #var notify := Notification.new("Using gamepad profile: " + profile.name)
+ #notification_manager.show(notify)
## Sets the given running app as the current app
-func set_current_app(app: RunningApp, switch_baselayer: bool = true) -> void:
+func set_current_app(app: RunningApp, _switch_baselayer: bool = true) -> void:
if app == null:
return
app.grab_focus()
@@ -386,71 +457,79 @@ func _add_running(app: RunningApp):
## Called when a running app's state changes
-func _on_app_state_changed(_from: RunningApp.STATE, to: RunningApp.STATE, app: RunningApp) -> void:
+func _on_app_state_changed(from: RunningApp.STATE, to: RunningApp.STATE, app: RunningApp) -> void:
+ logger.debug("App state changed from", from, "to", to, "for app:", app)
if to != RunningApp.STATE.STOPPED:
return
+ logger.debug("Cleaning up pid {0}".format([app.pid]))
_remove_running(app)
+ logger.debug("Currently running apps:", _running)
if state_machine.has_state(in_game_state) and _running.size() == 0:
logger.info("No more apps are running. Removing in-game state.")
- gamescope.remove_baselayer_window()
+ _xwayland_primary.remove_baselayer_window()
state_machine.remove_state(in_game_state)
state_machine.remove_state(in_game_menu_state)
+ all_apps_stopped.emit()
# Removes the given PID from our list of running apps
func _remove_running(app: RunningApp):
- logger.info("Cleaning up pid {0}".format([app.pid]))
+ logger.info("Removing app", app, "from running apps.")
_running.erase(app)
_apps_by_name.erase(app.launch_item.name)
_apps_by_pid.erase(app.pid)
-
app_stopped.emit(app)
# Checks for running apps and updates our state accordingly
func check_running() -> void:
# Find the root window
- var root_id := gamescope.get_root_window_id(Gamescope.XWAYLAND.GAME)
+ if not _xwayland_game:
+ return
+ var root_id := _xwayland_game.root_window_id
if root_id < 0:
return
-
- # Update the Gamescope state
- gamescope.update()
-
+
# Update our view of running processes and what windows they have
_update_pids(root_id)
-
+
# Update the state of all running apps
for app in _running:
app.update()
+ for app in _running_background:
+ app.update()
# Updates our mapping of PIDs to Windows. This gives us a good view of what
# processes are running, and what windows they have.
func _update_pids(root_id: int):
+ if not _xwayland_game:
+ return
var pids := {}
- var all_windows := gamescope.get_all_windows(root_id, Gamescope.XWAYLAND.GAME)
+ var all_windows := _xwayland_game.get_all_windows(root_id)
for window in all_windows:
- var pid := gamescope.get_window_pid(window, Gamescope.XWAYLAND.GAME)
- if not pid in pids:
- pids[pid] = []
- pids[pid].append(window)
+ var window_pids := _xwayland_game.get_pids_for_window(window)
+ for window_pid in window_pids:
+ if not window_pid in pids:
+ pids[window_pid] = []
+ pids[window_pid].append(window)
_pid_to_windows = pids
# Below functions detect launched game from other processes
# Returns the process ID
func _get_pid_from_focused_window(window_id: int) -> int:
- var pid := -1
- logger.debug(str(gamescope.get_xwayland(Gamescope.XWAYLAND.GAME).list_xprops(window_id)))
- pid = gamescope.get_xwayland(Gamescope.XWAYLAND.GAME).get_xprop(window_id, "_NET_WM_PID")
- logger.debug("PID: " + str(pid))
- return pid
+ if not _xwayland_game:
+ return -1
+ var window_pids := _xwayland_game.get_pids_for_window(window_id)
+ if window_pids.is_empty():
+ return -1
+ return window_pids[0]
# First method, try to get the name from the window_id using gamescope.
func _get_app_name_from_window_id(window_id: int) -> String:
- return gamescope.get_window_name(window_id)
+ return _xwayland_game.get_window_name(window_id)
# Last resort, try to use the parent dir of the executable from /proc/pid/cwd to return
@@ -459,22 +538,26 @@ func _get_app_name_from_proc(pid: int) -> String:
var process_name: String
var path := "/proc/" + str(pid) + "/cwd"
var output := []
- var exit_code := OS.execute("ls", ["-l", path], output)
+ var _exit_code := OS.execute("ls", ["-l", path], output)
var process_path: PackedStringArray = output[0].strip_edges().split("/")
process_name = process_path[process_path.size()-1]
return process_name
-# Primary nw app ID method. Identifies the running app from steam's library.vdf
+# Primary new app ID method. Identifies the running app from steam's library.vdf
# and appmanifest_.acf files.
func _get_name_from_steam_library() -> String:
- var missing_app_id := gamescope.get_focused_app()
+ var missing_app_id := -1
+ if _xwayland_primary:
+ missing_app_id = _xwayland_primary.focused_app
logger.debug("Found unclaimed app id: " +str(missing_app_id))
var steam_library_path := OS.get_environment("HOME") +"/.steam/steam"
var library_data := _parse_data_from_steam_file(steam_library_path + "/steamapps/libraryfolders.vdf")
for library in library_data:
logger.debug("Library: " + library + " : " + str(library_data[library]))
+ if not "apps" in library_data[library]:
+ continue
if library_data[library]["apps"].has(str(missing_app_id)):
var app_path : String = library_data[library]["path"] +"/steamapps/appmanifest_" + str(missing_app_id) + ".acf"
logger.debug("Found app ID in a steam library:" + app_path)
@@ -494,8 +577,14 @@ func _is_app_id_running(app_id) -> bool:
# Identifies the running app from the given window_id. If none is found,
# creates a new RunningApp instance.
-func _detect_running_app(window_id: int) -> RunningApp:
+func _detect_running_app(app_id: int) -> RunningApp:
logger.debug("No known running app in focused window. Attempting to detect the running app.")
+
+ # Get the currently focused window id
+ var window_id := _xwayland_primary.focused_window
+ if window_id == _ogui_window_id:
+ return null
+
var app_name: String
# Check if this window ID is a child of an existing RunningApp
@@ -531,16 +620,16 @@ func _detect_running_app(window_id: int) -> RunningApp:
return null
logger.debug("Found app name : " + app_name)
- return _make_running_app_from_process(app_name, pid, window_id)
+ return _make_running_app_from_process(app_name, pid, window_id, app_id)
# Creates a new RunningApp instance from a given name, PID, and window_id. Used
# when an app launch is detcted that wasn't launched by an OGUI library.
-func _make_running_app_from_process(name: String, pid: int, window_id: int) -> RunningApp:
+func _make_running_app_from_process(name: String, pid: int, window_id: int, app_id: int) -> RunningApp:
logger.debug("Creating running app from process")
# Create a dummy LibraryLaunchItem to make our RunningApp.
- var lauch_dict = {
+ var lauch_dict := {
"_id": "",
"_provider_id": "",
"provider_app_id": "",
@@ -553,8 +642,11 @@ func _make_running_app_from_process(name: String, pid: int, window_id: int) -> R
}
var launch_item: LibraryLaunchItem = LibraryLaunchItem.from_dict(lauch_dict)
- var display:= gamescope.get_display_name(Gamescope.XWAYLAND.GAME)
+ var display := ""
+ if _xwayland_game:
+ display = _xwayland_game.name
var running_app: RunningApp = _make_running_app(launch_item, pid, display)
+ running_app.app_id = app_id
running_app.window_id = window_id
running_app.state = RunningApp.STATE.RUNNING
running_app.is_ogui_managed = false
diff --git a/core/global/library_manager.gd b/core/global/library_manager.gd
index 42845f05a..38975b3c1 100644
--- a/core/global/library_manager.gd
+++ b/core/global/library_manager.gd
@@ -198,6 +198,7 @@ func remove_library_launch_item(library_id: String, name: String) -> void:
## Loads the launch items from the given library
func load_library(library_id: String) -> void:
+ logger.debug("Loading library from provider:", library_id)
var library := get_library_by_id(library_id)
var items: Array = await library.get_library_launch_items()
for i in items:
diff --git a/core/global/platform.gd b/core/global/platform.gd
index 84af60c25..beab13ec1 100644
--- a/core/global/platform.gd
+++ b/core/global/platform.gd
@@ -44,6 +44,7 @@ enum PLATFORM {
STEAMOS,
MANJARO,
ARCH_LIKE,
+ NIXOS,
}
var hardware_manager := load("res://core/systems/hardware/hardware_manager.tres") as HardwareManager
@@ -51,7 +52,7 @@ var hardware_manager := load("res://core/systems/hardware/hardware_manager.tres"
## Detected Operating System information
var os_info := _detect_os()
## The OS platform provider detected
-var os: PlatformProvider
+var os: OSPlatform
## The hardware platform provider detected
var platform: PlatformProvider
var logger := Log.get_logger("Platform", Log.LEVEL.INFO)
@@ -127,6 +128,8 @@ func _init() -> void:
os = load("res://core/platform/os/chimeraos.tres")
if PLATFORM.MANJARO in flags:
os = load("res://core/platform/os/manjaro.tres")
+ if PLATFORM.NIXOS in flags:
+ os = load("res://core/platform/os/nixos.tres")
if os:
for action in os.startup_actions:
@@ -286,6 +289,8 @@ func _read_os() -> Array[PLATFORM]:
flags.append(PLATFORM.MANJARO)
if os_info.id_like == "arch":
flags.append(PLATFORM.ARCH_LIKE)
+ if os_info.id == "nixos":
+ flags.append(PLATFORM.NIXOS)
return flags
diff --git a/core/global/plugin_loader.gd b/core/global/plugin_loader.gd
index 6b244c791..2da34a3fa 100644
--- a/core/global/plugin_loader.gd
+++ b/core/global/plugin_loader.gd
@@ -18,7 +18,7 @@ class_name PluginLoader
## pack.
const PLUGIN_STORE_URL = "https://raw.githubusercontent.com/ShadowBlip/OpenGamepadUI-plugins/main/plugins.json"
-const PLUGIN_API_VERSION = "1.0.0"
+const PLUGIN_API_VERSION = "1.1.0"
const PLUGINS_DIR = "user://plugins"
const LOADED_PLUGINS_DIR = "res://plugins"
const REQUIRED_META = ["plugin.name", "plugin.version", "plugin.min-api-version", "entrypoint"]
@@ -545,14 +545,34 @@ func _is_plugin_upgradable(plugin_id: String, store_db: Dictionary) -> bool:
# Check if we've already found this is upgradable
if plugin_id in plugins_upgradable:
return false
- var current_version = plugins[plugin_id]["plugin.version"]
- var new_version = store_db[plugin_id]["plugin.version"]
- if SemanticVersion.is_greater(new_version, current_version):
- logger.info("Plugin update available: {0}.".format([plugin_id]))
- plugin_upgradable.emit(plugin_id, update_type.UPDATE)
- plugins_upgradable.append(plugin_id)
- return true
- return false
+ # Validate the correct data exists
+ if not plugin_id in plugins or not "plugin.version" in plugins[plugin_id]:
+ return false
+ if not plugin_id in store_db or not "plugin.version" in store_db[plugin_id]:
+ return false
+ var current_version := plugins[plugin_id]["plugin.version"] as String
+ var new_version := store_db[plugin_id]["plugin.version"] as String
+
+ # If the plugin version in the store is not greater than the currently
+ # installed version, then this plugin is not upgradable.
+ if not SemanticVersion.is_greater(new_version, current_version):
+ logger.debug("Plugin", plugin_id, "with version", current_version, "is not greater than", new_version)
+ return false
+
+ # Check to see if the new plugin is compatible with the OpenGamepadUI's current
+ # plugin API.
+ if not "plugin.min-api-version" in store_db[plugin_id]:
+ logger.error("No minimum api version specified in store for plugin:", plugin_id)
+ return false
+ var plugin_min_api_version := store_db[plugin_id]["plugin.min-api-version"] as String
+ if not SemanticVersion.is_feature_compatible(plugin_min_api_version, PLUGIN_API_VERSION):
+ logger.info("Plugin", plugin_id, "requires plugin API version", plugin_min_api_version, "but current plugin API version is", PLUGIN_API_VERSION)
+ return false
+
+ logger.info("Plugin update available: {0}.".format([plugin_id]))
+ plugin_upgradable.emit(plugin_id, update_type.UPDATE)
+ plugins_upgradable.append(plugin_id)
+ return true
# Checks if a given plugin is already in the plugin database
@@ -580,6 +600,7 @@ func filter_by_tag(plugins: Dictionary, tag: String) -> Array[String]:
logger.debug(plugin["plugin.id"] + " will not be loaded. " + str(tags))
return filtered_ids
+
# Sets the filters for the plugin list
func set_plugin_filters(filters: Array[Callable]) -> void:
logger.debug("Setting plugin filters.")
diff --git a/core/global/settings_manager.gd b/core/global/settings_manager.gd
index bd4cdcdd1..6f456b628 100644
--- a/core/global/settings_manager.gd
+++ b/core/global/settings_manager.gd
@@ -39,6 +39,8 @@ func get_value(section: String, key: String, default: Variant = null) -> Variant
func get_library_value(item: LibraryItem, key: String, default: Variant = null) -> Variant:
+ if not item:
+ return null
var section := ".".join(["game", item.name.to_lower()])
return get_value(section, key, default)
diff --git a/core/platform/actions/start_inputplumber.gd b/core/platform/actions/start_inputplumber.gd
index 1cb668911..ca54626b1 100644
--- a/core/platform/actions/start_inputplumber.gd
+++ b/core/platform/actions/start_inputplumber.gd
@@ -6,6 +6,6 @@ const INPUT_PLUMBER_PATH := "/usr/share/opengamepadui/scripts/manage_input"
func execute() -> void:
logger.info("Starting InputPlumber")
- var cmd := CommandSync.new(INPUT_PLUMBER_PATH, ["startInputPlumber"])
- if cmd.execute() != OK:
+ var cmd := Command.create(INPUT_PLUMBER_PATH, ["startInputPlumber"])
+ if cmd.execute_blocking() != OK:
logger.warn("Failed to start InputPlumber: " + cmd.stdout)
diff --git a/core/platform/actions/start_powerstation.gd b/core/platform/actions/start_powerstation.gd
index 18ee2e9ac..19e05aa23 100644
--- a/core/platform/actions/start_powerstation.gd
+++ b/core/platform/actions/start_powerstation.gd
@@ -6,6 +6,6 @@ const POWERTOOLS_PATH := "/usr/share/opengamepadui/scripts/manage_input"
func execute() -> void:
logger.info("Starting PowerStation")
- var cmd := CommandSync.new(POWERTOOLS_PATH, ["startPowerStation"])
- if cmd.execute() != OK:
+ var cmd := Command.create(POWERTOOLS_PATH, ["startPowerStation"])
+ if cmd.execute_blocking() != OK:
logger.warn("Failed to start PowerStation: " + cmd.stdout)
diff --git a/core/platform/actions/turbo_takeover.gd b/core/platform/actions/turbo_takeover.gd
index 0c9594d6d..761444dd9 100644
--- a/core/platform/actions/turbo_takeover.gd
+++ b/core/platform/actions/turbo_takeover.gd
@@ -3,7 +3,8 @@ class_name ActionTurboTakeover
func execute() -> void:
- var cmd := Command.new("/usr/share/opengamepadui/scripts/manage_input", ["turbo_takeover", "1"])
- var code := await cmd.execute() as int
+ var cmd := Command.create("/usr/share/opengamepadui/scripts/manage_input", ["turbo_takeover", "1"])
+ cmd.execute()
+ var code := await cmd.finished as int
if code != OK:
- logger.warn("Unable to take over turbo button: " + cmd.stdout)
+ logger.warn("Unable to take over turbo button: " + cmd.stdout + " " + cmd.stderr)
diff --git a/core/platform/handheld/handheld_platform.gd b/core/platform/handheld/handheld_platform.gd
index 03dc639b4..b0740adc6 100644
--- a/core/platform/handheld/handheld_platform.gd
+++ b/core/platform/handheld/handheld_platform.gd
@@ -11,6 +11,6 @@ class_name HandheldPlatform
@export_category("Controller Icons")
## Image of the device as a diagram to show in the gamepad configuration menus.
-@export var diagram: Texture2D = load("res://addons/controller_icons/assets/xboxone/diagram_simple.png")
+@export var diagram: Texture2D = load("res://assets/images/gamepad/xbox/XboxOne_Diagram_Simple.png")
## Custom icon images to use when displaying buttons/joysticks in the interface
@export var icon_mappings: Array[HandheldIconMapping]
diff --git a/core/platform/os/nixos.gd b/core/platform/os/nixos.gd
new file mode 100644
index 000000000..f76e9b934
--- /dev/null
+++ b/core/platform/os/nixos.gd
@@ -0,0 +1,23 @@
+extends OSPlatform
+class_name PlatformNixOS
+
+
+func _init() -> void:
+ logger.set_name("PlatformNixOS")
+ logger.set_level(Log.LEVEL.INFO)
+ logger.info("Detected NixOS platform")
+
+
+## NixOS typically cannot execute regular binaries, so downloaded binaries will
+## be run with 'steam-run'.
+func get_binary_compatibility_cmd(cmd: String, args: PackedStringArray) -> Array[String]:
+ # Hack for steam plugin running steamcmd on NixOS
+ var command: Array[String] = []
+ if not cmd.ends_with("steamcmd.sh"):
+ return command
+
+ command.push_back("steam-run")
+ command.push_back(cmd)
+ command.append_array(args)
+
+ return command
diff --git a/core/platform/os/nixos.tres b/core/platform/os/nixos.tres
new file mode 100644
index 000000000..cc237b6e4
--- /dev/null
+++ b/core/platform/os/nixos.tres
@@ -0,0 +1,10 @@
+[gd_resource type="Resource" script_class="PlatformNixOS" load_steps=3 format=3 uid="uid://byxeetkb11b3e"]
+
+[ext_resource type="Script" path="res://core/platform/os/nixos.gd" id="1_h88kc"]
+[ext_resource type="Script" path="res://core/platform/actions/platform_action.gd" id="2_tc12v"]
+
+[resource]
+script = ExtResource("1_h88kc")
+name = ""
+startup_actions = Array[ExtResource("2_tc12v")]([])
+shutdown_actions = Array[ExtResource("2_tc12v")]([])
diff --git a/core/platform/os/os_platform.gd b/core/platform/os/os_platform.gd
index 7901ac126..17b66f330 100644
--- a/core/platform/os/os_platform.gd
+++ b/core/platform/os/os_platform.gd
@@ -4,3 +4,11 @@ class_name OSPlatform
@export_category("Images")
@export var logo: Texture2D ## Logo of the OS
+
+
+## If the OS requires running regular binaries through a compatibility tool,
+## this method should return the given command/args prepended with the compatibility
+## tool to use.
+func get_binary_compatibility_cmd(cmd: String, args: PackedStringArray) -> Array[String]:
+ var result: Array[String] = []
+ return result
diff --git a/core/systems/battery.gd b/core/systems/battery.gd
deleted file mode 100644
index 70c4e7a90..000000000
--- a/core/systems/battery.gd
+++ /dev/null
@@ -1,87 +0,0 @@
-@icon("res://assets/icons/battery-charging.svg")
-extends RefCounted
-class_name Battery
-
-const power_supply_dir = "/sys/class/power_supply"
-const icon_charging = preload("res://assets/ui/icons/battery-charging.svg")
-const icon_full = preload("res://assets/ui/icons/battery-full.svg")
-const icon_high = preload("res://assets/ui/icons/battery-75.svg")
-const icon_half = preload("res://assets/ui/icons/battery-half.svg")
-const icon_low = preload("res://assets/ui/icons/battery-low.svg")
-const icon_empty = preload("res://assets/ui/icons/battery-empty.svg")
-
-enum STATUS {
- NONE,
- DISCHARGING,
- NOT_CHARGING,
- CHARGING,
- FULL,
-}
-
-var logger := Log.get_logger("Battery")
-
-# Finds the battery path. If none is found, returns null.
-static func find_battery_path() -> Variant:
- var power_dir: DirAccess = DirAccess.open(power_supply_dir)
- var devices: PackedStringArray = power_dir.get_directories()
- var battery_dir: String = ""
- for folder in devices:
- if folder.begins_with("BAT"):
- battery_dir = folder
- break
- if battery_dir == "":
- return ""
-
- return "/".join([power_supply_dir, battery_dir])
-
-
-# Returns the current battery capacity as a percentage
-static func get_capacity(battery: String) -> int:
- if battery == "":
- return -1
- var capacity_file: String = "/".join([battery, "capacity"])
- var file: FileAccess = FileAccess.open(capacity_file, FileAccess.READ)
- var bytes: PackedByteArray = file.get_buffer(100)
- var str: String = bytes.get_string_from_ascii().strip_edges()
- if not str.is_valid_int():
- return -1
- return str.to_int()
-
-
-## Returns the status of the given battery
-static func get_status(battery: String) -> STATUS:
- if battery == "":
- return STATUS.NONE
- var status_file: String = "/".join([battery, "status"])
-
- var output := []
- var code := OS.execute("cat", [status_file], output)
- if code != OK:
- return STATUS.NONE
- var status := (output[0] as String).strip_edges()
-
- match status:
- "Discharging":
- return STATUS.DISCHARGING
- "Not charging":
- return STATUS.NOT_CHARGING
- "Charging":
- return STATUS.CHARGING
- "Full":
- return STATUS.FULL
- return STATUS.NONE
-
-
-## Returns the texture reflecting the given battery capacity
-static func get_capacity_texture(capacity: int, status: STATUS = STATUS.NONE) -> Texture2D:
- if status > STATUS.NOT_CHARGING:
- return icon_charging
- if capacity >= 90:
- return icon_full
- if capacity >= 65:
- return icon_high
- if capacity >= 40:
- return icon_half
- if capacity >= 20:
- return icon_low
- return icon_empty
diff --git a/core/systems/bluetooth/bluetooth_manager.gd b/core/systems/bluetooth/bluetooth_manager.gd
index 28cd21ae7..b4561eb58 100644
--- a/core/systems/bluetooth/bluetooth_manager.gd
+++ b/core/systems/bluetooth/bluetooth_manager.gd
@@ -1,188 +1,16 @@
@icon("res://assets/editor-icons/bluetooth.svg")
-extends Resource
+extends Node
class_name BluetoothManager
## BluetoothManager interfaces with the bluetooth system
##
-## This class uses [DBusManager] to communicate with the bluetooth service
-## over DBus.
+## This node is used to drive the bluetooth instance forward by calling its
+## 'process()' method every frame to dispatch signals.
-const BLUEZ_BUS := "org.bluez"
-const BLUES_PREFIX := "/org/bluez"
+@export var instance: BluezInstance = load("res://core/systems/bluetooth/bluetooth_manager.tres")
-const IFACE_ADAPTER := "org.bluez.Adapter1"
-const IFACE_DEVICE := "org.bluez.Device1"
-var dbus := load("res://core/global/dbus_system.tres") as DBusManager
-
-
-## Returns true if bluetooth can be used on this system
-func supports_bluetooth() -> bool:
- return dbus.bus_exists(BLUEZ_BUS)
-
-
-## Returns the bluetooth adapter with the given name.
-func get_adapter(adapter_name: String = "hci0") -> Adapter:
- var adapter_path := "/".join([BLUES_PREFIX, adapter_name])
- var proxy := dbus.create_proxy(BLUEZ_BUS, adapter_path)
- var adapter := Adapter.new(proxy)
-
- return adapter
-
-
-## Return a list of currently discovered devices
-func get_discovered_devices() -> Array[Device]:
- var devices: Array[Device] = []
- var objects := dbus.get_managed_objects(BLUEZ_BUS, "/")
-
- # Loop through all objects on the bus
- for obj in objects:
- # Skip any DBus objects that aren't devices
- if not obj.has_interface_attr(IFACE_DEVICE, "Address"):
- continue
-
- # Create a bluetooth Device from this object
- var proxy := dbus.create_proxy(BLUEZ_BUS, obj.path)
- var device := Device.new(proxy)
-
- devices.append(device)
-
- return devices
-
-
-## Container for a bluetooth adapter
-## https://github.com/luetzel/bluez/blob/master/doc/adapter-api.txt
-class Adapter:
- signal updated
- var _proxy: DBusManager.Proxy
- var address: String:
- get:
- var property = _proxy.get_property(IFACE_ADAPTER, "Address")
- if not property is String:
- return ""
- return property
- var name: String:
- get:
- var property = _proxy.get_property(IFACE_ADAPTER, "Name")
- if not property is String:
- return ""
- return property
- var powered: bool:
- set(v):
- _proxy.set_property(IFACE_ADAPTER, "Powered", v)
- get:
- var property = _proxy.get_property(IFACE_ADAPTER, "Powered")
- if not property is bool:
- return false
- return property
- var discovering: bool:
- get:
- var property = _proxy.get_property(IFACE_ADAPTER, "Discovering")
- if not property is bool:
- return false
- return property
-
- func _init(proxy: DBusManager.Proxy) -> void:
- _proxy = proxy
- _proxy.properties_changed.connect(_on_properties_changed)
-
- func _on_properties_changed(iface: String, props: Dictionary) -> void:
- updated.emit()
-
- func start_discovery() -> void:
- _proxy.call_method(IFACE_ADAPTER, "StartDiscovery")
-
- func stop_discovery() -> void:
- _proxy.call_method(IFACE_ADAPTER, "StopDiscovery")
-
-
-## Container for a bluetooth device
-## https://github.com/luetzel/bluez/blob/master/doc/device-api.txt
-class Device:
- signal connection_changed(is_connected: bool)
- signal paired_changed(is_paired: bool)
- signal updated
- var _proxy: DBusManager.Proxy
- var adapter: String:
- get:
- var property = _proxy.get_property(IFACE_DEVICE, "Adapter")
- if not property is String:
- return ""
- return property
- var address: String:
- get:
- var property = _proxy.get_property(IFACE_DEVICE, "Address")
- if not property is String:
- return ""
- return property
- var alias: String:
- get:
- var property = _proxy.get_property(IFACE_DEVICE, "Alias")
- if not property is String:
- return ""
- return property
- var name: String:
- get:
- var property = _proxy.get_property(IFACE_DEVICE, "Name")
- if not property is String:
- return ""
- return property
- var icon: String:
- get:
- var property = _proxy.get_property(IFACE_DEVICE, "Icon")
- if not property is String:
- return ""
- return property
- var paired: bool:
- get:
- var property = _proxy.get_property(IFACE_DEVICE, "Paired")
- if not property is bool:
- return false
- return property
- var connected: bool:
- get:
- var property = _proxy.get_property(IFACE_DEVICE, "Connected")
- if not property is bool:
- return false
- return property
- var trusted: bool:
- get:
- var property = _proxy.get_property(IFACE_DEVICE, "Trusted")
- if not property is bool:
- return false
- return property
- var blocked: bool:
- get:
- var property = _proxy.get_property(IFACE_DEVICE, "Blocked")
- if not property is bool:
- return false
- return property
-
- func _init(proxy: DBusManager.Proxy) -> void:
- _proxy = proxy
- _proxy.properties_changed.connect(_on_properties_changed)
-
- func _on_properties_changed(iface: String, props: Dictionary) -> void:
- updated.emit()
- if "Connected" in props:
- connection_changed.emit(props["Connected"])
- if "Paired" in props:
- paired_changed.emit(props["Paired"])
-
- func connect_to() -> void:
- _proxy.call_method(IFACE_DEVICE, "Connect")
-
- func disconnect_from() -> void:
- _proxy.call_method(IFACE_DEVICE, "Disconnect")
-
- func connect_profile(uuid: String) -> void:
- _proxy.call_method(IFACE_DEVICE, "ConnectProfile", [uuid], "s")
-
- func disconnect_profile(uuid: String) -> void:
- _proxy.call_method(IFACE_DEVICE, "DisconnectProfile", [uuid], "s")
-
- func pair() -> void:
- _proxy.call_method(IFACE_DEVICE, "Pair")
-
- func cancel_pairing() -> void:
- _proxy.call_method(IFACE_DEVICE, "CancelPairing")
+func _process(_delta: float) -> void:
+ if not instance:
+ return
+ instance.process()
diff --git a/core/systems/bluetooth/bluetooth_manager.tres b/core/systems/bluetooth/bluetooth_manager.tres
index 3481770fc..f7b63bfc6 100644
--- a/core/systems/bluetooth/bluetooth_manager.tres
+++ b/core/systems/bluetooth/bluetooth_manager.tres
@@ -1,6 +1,3 @@
-[gd_resource type="Resource" script_class="BluetoothManager" load_steps=2 format=3 uid="uid://cyra53o28hppt"]
-
-[ext_resource type="Script" path="res://core/systems/bluetooth/bluetooth_manager.gd" id="1_q2n5i"]
+[gd_resource type="BluezInstance" format=3 uid="uid://peeajgfcx2fw"]
[resource]
-script = ExtResource("1_q2n5i")
diff --git a/core/systems/bluetooth/bluetooth_manager_test.gd b/core/systems/bluetooth/bluetooth_manager_test.gd
index 8d692916f..da46b3768 100644
--- a/core/systems/bluetooth/bluetooth_manager_test.gd
+++ b/core/systems/bluetooth/bluetooth_manager_test.gd
@@ -1,32 +1,33 @@
extends GutTest
-var bluetooth := load("res://core/systems/bluetooth/bluetooth_manager.tres") as BluetoothManager
+var bluetooth := load("res://core/systems/bluetooth/bluetooth_manager.tres") as BluezInstance
func before_all() -> void:
- if not bluetooth.supports_bluetooth():
+ if not bluetooth.is_running():
@warning_ignore("unsafe_method_access")
gut.p("Bluetooth is not supported")
return
func test_get_adapter() -> void:
- if not bluetooth.supports_bluetooth():
+ if not bluetooth.is_running():
pass_test("Bluetooth not supported, skipping")
return
- var adapter := bluetooth.get_adapter()
- if not adapter:
+ var adapters := bluetooth.get_adapters()
+ if adapters.is_empty():
pass_test("No bluetooth adapter found, skipping")
pass_test("Skipping")
func test_discovery() -> void:
- if not bluetooth.supports_bluetooth():
+ if not bluetooth.is_running():
pass_test("Bluetooth not supported, skipping")
return
- var adapter := bluetooth.get_adapter()
- if not adapter:
+ var adapters := bluetooth.get_adapters()
+ if adapters.is_empty():
pass_test("No bluetooth adapter found, skipping")
+ var adapter := adapters[0] as BluetoothAdapter
adapter.start_discovery()
await wait_seconds(3, "waiting for discovery")
diff --git a/core/systems/debug/log_manager.gd b/core/systems/debug/log_manager.gd
index 944a0935e..386bc94f9 100644
--- a/core/systems/debug/log_manager.gd
+++ b/core/systems/debug/log_manager.gd
@@ -88,4 +88,3 @@ func get_available_loggers() -> PackedStringArray:
var logger_names := loggers_by_name.keys()
mutex.unlock()
return logger_names
-
diff --git a/core/systems/disks/disk_manager.gd b/core/systems/disks/disk_manager.gd
new file mode 100644
index 000000000..281f00395
--- /dev/null
+++ b/core/systems/disks/disk_manager.gd
@@ -0,0 +1,11 @@
+extends Node
+class_name DiskManager
+
+
+@export var instance: UDisks2Instance = load("res://core/systems/disks/disk_manager.tres") as UDisks2Instance
+
+
+func _process(_delta: float) -> void:
+ if not instance:
+ return
+ instance.process()
diff --git a/core/systems/disks/disk_manager.tres b/core/systems/disks/disk_manager.tres
new file mode 100644
index 000000000..2856e2ff1
--- /dev/null
+++ b/core/systems/disks/disk_manager.tres
@@ -0,0 +1,3 @@
+[gd_resource type="UDisks2Instance" format=3 uid="uid://dhmtkhokrb8pu"]
+
+[resource]
diff --git a/core/systems/disks/steam_removable_media_manager.gd b/core/systems/disks/steam_removable_media_manager.gd
index ffe1b525f..78f1da935 100644
--- a/core/systems/disks/steam_removable_media_manager.gd
+++ b/core/systems/disks/steam_removable_media_manager.gd
@@ -1,7 +1,7 @@
extends Resource
class_name SteamRemovableMediaManager
-var udisks2 := load("res://core/systems/disks/udisks2.tres") as UDisks2
+var udisks2 := load("res://core/systems/disks/disk_manager.tres") as UDisks2Instance
var logger := Log.get_logger("SteamRemovableMediaManager", Log.LEVEL.INFO)
@@ -26,7 +26,7 @@ var trim_capable: bool = false
func _init() -> void:
- if not udisks2.supports_disk_management():
+ if not udisks2.is_running():
return
# Check the required system files exist for steam_removable_media
@@ -58,12 +58,6 @@ func format_drive(device: BlockDevice) -> Error:
logger.error("System is not format capable")
return ERR_UNAVAILABLE
- # This should never hit if using our device tree, but the method is public so
- # make sure.
- if udisks2.block_device_has_protected_mount(device):
- logger.error("Attempted to format device with protected mount. Illegal Operation.")
- return ERR_UNAUTHORIZED
-
var drive = "/dev" + device.dbus_path.trim_prefix(BLOCK_PREFIX)
logger.debug("Formatting drive:", drive)
var args := ["--full", "--device", drive]
@@ -83,12 +77,6 @@ func init_steam_lib(partition: PartitionDevice) -> Error:
logger.error("System cannot initialize steam libraries")
return ERR_UNAVAILABLE
- # This should never hit if using our device tree, but the method is public so
- # make sure.
- if udisks2.partition_has_protected_mount(partition):
- logger.error("Attempted to initialize steam library on device with protected mount. Illegal Operation.")
- return ERR_UNAUTHORIZED
-
var drive := "/dev" + partition.dbus_path.trim_prefix(BLOCK_PREFIX)
logger.debug("Intitializing partition as Steam Library: " + drive)
var args := [drive]
@@ -173,13 +161,11 @@ func trim_sd_card() -> Error:
return ERR_SCRIPT_FAILED
-func _execute_in_thread(path: String, args: Array = []) -> Array:
+func _execute_in_thread(path: String, args: Array[String] = []) -> Array:
block_operations = true
- var thread_options := SharedThread.Option.NONE
- var thread := SharedThread.new(thread_options)
- thread.start()
- var cmd := Command.new(path, args, thread)
- var code := await cmd.execute() as int
- thread.stop()
+ var cmd := Command.create(path, args)
+ if cmd.execute() != OK:
+ return ["", -1]
+ var code := await cmd.finished as int
block_operations = false
return [cmd.stdout, code]
diff --git a/core/systems/disks/udisks2.gd b/core/systems/disks/udisks2.gd
deleted file mode 100644
index 1fa780e9e..000000000
--- a/core/systems/disks/udisks2.gd
+++ /dev/null
@@ -1,182 +0,0 @@
-extends Resource
-class_name UDisks2
-
-## Manages disk discovery.
-##
-## The UDisks2 class is responsible for handling dbus messages to and
-## from the UDisks2 daemon for disk management.
-
-# Paths
-const UDISKS2_PATH := "/org/freedesktop/UDisks2"
-const BLOCK_DEVICES_PATH := UDISKS2_PATH + "/block_devices"
-const DRIVES_PATH := UDISKS2_PATH + "/drives"
-const UDISKS2_MANAGER_PATH := UDISKS2_PATH + "/Manager"
-# Interfaces
-const UDISKS2_BUS := "org.freedesktop.UDisks2"
-const IFACE_MANAGER := UDISKS2_BUS + ".Manager"
-const IFACE_BLOCK := UDISKS2_BUS + ".Block"
-const IFACE_FILESYSTEM := UDISKS2_BUS + ".Filesystem"
-const IFACE_PARTITION := UDISKS2_BUS + ".Partition"
-const IFACE_PARTITION_TABLE := UDISKS2_BUS + ".PartitionTable"
-const IFACE_DRIVE := UDISKS2_BUS + ".Drive"
-const IFACE_NVME_CONTROLLER := UDISKS2_BUS + ".NVMe.Controller"
-
-const protected_mounts = [
- "/",
- "/boot",
- "/boot/efi",
- "/efi",
- "/frzr_root",
- "/frzr_root/boot",
- "/home",
- "/var",
- "/var/cache",
- "/var/log",
- ]
-
-var dbus := load("res://core/global/dbus_system.tres") as DBusManager
-var manager := Manager.new(dbus.create_proxy(UDISKS2_BUS, UDISKS2_MANAGER_PATH))
-var object_manager := dbus.ObjectManager.new(dbus.create_proxy(UDISKS2_BUS, UDISKS2_PATH))
-
-signal devices_updated(devices: Array[BlockDevice])
-signal unprotected_devices_updated(unprotected_devices: Array[BlockDevice])
-
-var logger := Log.get_logger("UDisks2", Log.LEVEL.INFO)
-
-
-## Returns true if UDisks2 can be used on this system
-func supports_disk_management() -> bool:
- return true
- return dbus.bus_exists(UDISKS2_BUS)
-
-
-func _init() -> void:
- logger.debug("Initalizing UDisks2 Dbus interface.")
- object_manager.interfaces_added.connect(_drives_updated)
- object_manager.interfaces_removed.connect(_drives_updated)
-
-
-## Signals when a changes to drives are detected
-func _drives_updated(iface: String) -> void:
- logger.trace("Update from interface:", iface)
- var devices = get_devices()
- devices_updated.emit(devices)
- var unprotected_devices = get_unprotected_devices(devices)
- unprotected_devices_updated.emit(unprotected_devices)
-
-
-## Returns all the current block devices detected by UDisks2
-func get_devices() -> Array[BlockDevice]:
- var block_array: Array[BlockDevice] = []
- var partition_array: Array[PartitionDevice] = []
- var drive_array: Array[DriveDevice] = []
- var device_paths := dbus.get_managed_objects(UDISKS2_BUS, UDISKS2_PATH)
- logger.trace("Searching for UDisks2 DBus objects.")
-
- # Loop through all objects on the bus
- for obj in device_paths:
- var object := obj as DBusManager.ManagedObject
- var path := object.path
- var proxy := dbus.create_proxy(UDISKS2_BUS, path)
- logger.trace("Found object: " + str(object) + " with path " + path)
- logger.trace("Object data: " + str(object.data))
-
- if path.contains("block_devices"):
- if object.has_interface(IFACE_PARTITION):
- logger.trace("Found Partition Device:", path)
- var device := PartitionDevice.new(proxy)
- if object.has_interface(IFACE_FILESYSTEM):
- logger.trace(path + " has Filesystem")
- device.has_filesystem = true
- partition_array.append(device)
- continue
- logger.trace("Found Block Device:", path)
- var device := BlockDevice.new(proxy)
- block_array.append(device)
-
- if path.contains("drives"):
- var res_path := "drive://" + path
- logger.trace("Found Drive Device:", path)
- var device := DriveDevice.new(proxy)
- device.take_over_path(res_path)
- device.interface_type = _id_type(device)
- drive_array.append(device)
- continue
-
- for block in block_array:
- for partition in partition_array:
- if partition.partition_table == block.dbus_path:
- block.partitions.append(partition)
- for drive in drive_array:
- if block.drive_path == drive.dbus_path:
- block.drive = drive
-
- return block_array
-
-
-## Returns all current devices that don't have protected mounts
-func get_unprotected_devices(devices: Array[BlockDevice] = []):
- var device_tree: Array[BlockDevice]
- if devices == []:
- logger.debug("Got empty array, grabbing devices from udisks2")
- devices = get_devices()
- for block in devices:
- if not block_device_has_protected_mount(block):
- logger.debug(block.dbus_path, "has no protected mounts.")
- device_tree.append(block)
- return device_tree
-
-
-## Finds all partitions of the given block device and returns true if any of
-## them have mounts in the protected_mounts list.
-func block_device_has_protected_mount(device: BlockDevice) -> bool:
- logger.debug("Checking block device", device.dbus_path, "for protected mounts.")
- # Get all the partition dbus paths of this block device
- for partition in device.partitions:
- if partition_has_protected_mount(partition):
- return true
- return false
-
-
-## Loops through all mount points of the given partition and returns true if any of
-## them have mounts in the protected_mounts list.
-func partition_has_protected_mount(device: PartitionDevice) -> bool:
- logger.debug("Checking partition", device.dbus_path, "for protected mounts.")
- for mount_point in device.fs_mount_points:
- logger.debug("Checking mount point", mount_point, "for protected mounts.")
- if mount_point in protected_mounts:
- logger.debug("Found a protected mount point on drive: " + device.dbus_path)
- return true
- return false
-
-
-func _id_type(device: DriveDevice) -> DriveDevice.INTERFACE_TYPE:
- if device.connection_bus == "usb":
- return DriveDevice.INTERFACE_TYPE.USB
- elif device.connection_bus == "sdio":
- return DriveDevice.INTERFACE_TYPE.SD
- elif device.connection_bus == "":
- if device.sort_key.contains("hotplug"):
- return DriveDevice.INTERFACE_TYPE.USB
- elif device.sort_key.contains("removable"):
- return DriveDevice.INTERFACE_TYPE.USB
- elif device.sort_key.contains("nvme"):
- return DriveDevice.INTERFACE_TYPE.NVME
- elif device.sort_key.contains("sd_"):
- if device.rotation_rate > 0:
- return DriveDevice.INTERFACE_TYPE.HDD
- return DriveDevice.INTERFACE_TYPE.SSD
- return DriveDevice.INTERFACE_TYPE.UNKNOWN
-
-# Unused. Usefull?
-class Manager extends Resource:
- signal updated
- var _proxy: DBusManager.Proxy
-
- func _init(proxy: DBusManager.Proxy) -> void:
- _proxy = proxy
- _proxy.properties_changed.connect(_on_properties_changed)
-
- func _on_properties_changed(_iface: String, _props: Dictionary) -> void:
- updated.emit()
-
diff --git a/core/systems/disks/udisks2.tres b/core/systems/disks/udisks2.tres
deleted file mode 100644
index 9b223797c..000000000
--- a/core/systems/disks/udisks2.tres
+++ /dev/null
@@ -1,6 +0,0 @@
-[gd_resource type="Resource" load_steps=2 format=3 uid="uid://d4k3rpacw1yn1"]
-
-[ext_resource type="Script" path="res://core/systems/disks/udisks2.gd" id="1_flkf8"]
-
-[resource]
-script = ExtResource("1_flkf8")
diff --git a/core/systems/disks/udisks2_block_device.gd b/core/systems/disks/udisks2_block_device.gd
deleted file mode 100644
index ba34d9923..000000000
--- a/core/systems/disks/udisks2_block_device.gd
+++ /dev/null
@@ -1,271 +0,0 @@
-extends UDisks2
-class_name BlockDevice
-
-## Methods and properties of a UDisks2 Block Device dbus interface.
-##
-## The BlockDevice class is responsible for handling dbus messages to and
-## from the UDisks2 daemon for block device management, including filesystems
-## and partitions.
-
-signal updated
-
-var _proxy: DBusManager.Proxy
-var dbus_path: String
-var partitions: Array[PartitionDevice]
-
-
-func _init(proxy: DBusManager.Proxy) -> void:
- var dbus := load("res://core/global/dbus_system.tres") as DBusManager
- _proxy = proxy
- _proxy.properties_changed.connect(_on_properties_changed)
- dbus_path = _proxy.path
-
-func _on_properties_changed(_iface: String, _props: Dictionary) -> void:
- updated.emit()
-
-
-## Returns the human readable string equivalent of the given number of bytes.
-func get_readable_size() -> String:
- if block_size <= 0:
- return "0 B"
- var block_size_f: float = float(block_size)
- var length = str(block_size).length()
- var size_simple: float
-
- match length:
- 1, 2, 3:
- return str(block_size) + " B"
- 4, 5, 6:
- size_simple = block_size_f/1024.0
- if size_simple < 1:
- size_simple *= 1000
- return str(snappedf(size_simple, 0.01)) + " B"
- return str(snappedf(size_simple, 0.01)) + " KB"
- 7, 8, 9:
- size_simple = block_size_f/1024.0/1024.0
- if size_simple < 1:
- size_simple *= 1000
- return str(snappedf(size_simple, 0.01)) + " KB"
- return str(snappedf(size_simple, 0.01)) + " MB"
- 10, 11, 12:
- size_simple = block_size_f/1024.0/1024.0/1024.0
- if size_simple < 1:
- size_simple *= 1000
- return str(snappedf(size_simple, 0.01)) + " MB"
- return str(snappedf(size_simple, 0.01)) + " GB"
- 13, 14, 15:
- size_simple = block_size_f/1024.0/1024.0/1024.0/1024.0
- if size_simple < 1:
- size_simple *= 1000
- return str(snappedf(size_simple, 0.01)) + " GB"
- return str(snappedf(size_simple, 0.01)) + " TB"
- 16, 17, 18:
- size_simple = block_size_f/1024.0/1024.0/1024.0/1024.0/1024.0
- if size_simple < 1:
- size_simple *= 1000
- return str(snappedf(size_simple, 0.01)) + " TB"
- return str(snappedf(size_simple, 0.01)) + " PB"
- _:
- return "Undefined"
-
-
-# Block
-#func block_add_configuration_item() -> void: #(sa{sv})a{sv}
- #pass
-
-#func block_format() -> void: #sa{sv}
- #pass
-
-#func block_get_secret_configuration() -> void: #a{sv} -> a(sa{sv})
- #pass
-
-#func block_open_device() -> void: #sa{sv} -> h
- #pass
-
-#func block_open_for_backup() -> void: #a{sv} -> h
- #pass
-
-#func block_open_for_benchmark() -> void: #a{sv} -> h
- #pass
-
-#func block_open_for_restore() -> void: #a{sv} -> h
- #pass
-
-#func block_remove_configuration_item() -> void: #a{sv} -> a(sa{sv})
- #pass
-
-#func block_rescan() -> void: #a{sv}
- #pass
-
-#func block_update_configuration_item() -> void: # (sa{sv})(sa{sv})a{sv}
- #pass
-
-var block_configuration: Dictionary: #a(sa{sv})
- get:
- var property = _proxy.get_property(IFACE_BLOCK, "Configuration")
- if not property is Dictionary:
- return {}
- return property
-
-var block_crypto_backing_device: String: #o
- get:
- var property = _proxy.get_property(IFACE_BLOCK, "CryptoBackingDevice")
- if not property is String:
- return ""
- return property
-
-var block_device: String: #ay
- get:
- var property = _proxy.get_property(IFACE_BLOCK, "Device")
- if not property is String:
- return ""
- return property
-
-var block_device_number: int: #t
- get:
- var property = _proxy.get_property(IFACE_BLOCK, "DeviceNumber")
- if not property is int:
- return -1
- return property
-
-var drive: DriveDevice
-
-var drive_path: String: #o
- get:
- var property = _proxy.get_property(IFACE_BLOCK, "Drive")
- if not property is String:
- return ""
- return property
-
-var block_hint_auto: bool:
- get:
- var property = _proxy.get_property(IFACE_BLOCK, "HintAuto")
- if not property is bool:
- return false
- return property
-
-var block_hint_icon_name: String: #s
- get:
- var property = _proxy.get_property(IFACE_BLOCK, "HintIconName")
- if not property is String:
- return ""
- return property
-
-var block_hint_ignore: bool:
- get:
- var property = _proxy.get_property(IFACE_BLOCK, "HintIgnore")
- if not property is bool:
- return false
- return property
-
-var block_hint_name: String: #s
- get:
- var property = _proxy.get_property(IFACE_BLOCK, "HintName")
- if not property is String:
- return ""
- return property
-
-var block_hint_partitionable: bool:
- get:
- var property = _proxy.get_property(IFACE_BLOCK, "HintPartitionable")
- if not property is bool:
- return false
- return property
-
-var block_hint_symbolic_icon_name: String: #s
- get:
- var property = _proxy.get_property(IFACE_BLOCK, "HintSymbolicIconName")
- if not property is String:
- return ""
- return property
-
-var block_hint_system: bool:
- get:
- var property = _proxy.get_property(IFACE_BLOCK, "HintSystem")
- if not property is bool:
- return false
- return property
-
-var block_id: String: #s
- get:
- var property = _proxy.get_property(IFACE_BLOCK, "Id")
- if not property is String:
- return ""
- return property
-
-var block_id_label: String: #s
- get:
- var property = _proxy.get_property(IFACE_BLOCK, "IdLabel")
- if not property is String:
- return ""
- return property
-
-var block_id_type: String: #s
- get:
- var property = _proxy.get_property(IFACE_BLOCK, "IdType")
- if not property is String:
- return ""
- return property
-
-var block_id_uuid: String: #s
- get:
- var property = _proxy.get_property(IFACE_BLOCK, "IdUUID")
- if not property is String:
- return ""
- return property
-
-var block_id_usage: String: #s
- get:
- var property = _proxy.get_property(IFACE_BLOCK, "IdUsage")
- if not property is String:
- return ""
- return property
-
-var block_id_version: String: #s
- get:
- var property = _proxy.get_property(IFACE_BLOCK, "IdVersion")
- if not property is String:
- return ""
- return property
-
-var block_md_raid: String: #o
- get:
- var property = _proxy.get_property(IFACE_BLOCK, "MDRaid")
- if not property is String:
- return ""
- return property
-
-var block_md_raid_member: String: #o
- get:
- var property = _proxy.get_property(IFACE_BLOCK, "MDRaidMember")
- if not property is String:
- return ""
- return property
-
-var block_preferred_device: String: #ay
- get:
- var property = _proxy.get_property(IFACE_BLOCK, "PreferredDevice")
- if not property is String:
- return ""
- return property
-
-var block_read_only: bool:
- get:
- var property = _proxy.get_property(IFACE_BLOCK, "ReadOnly")
- if not property is bool:
- return false
- return property
-
-var block_size: int: #t
- get:
- var property = _proxy.get_property(IFACE_BLOCK, "Size")
- if not property is int:
- return -1
- return property
-
-var block_userspace_mount_options: PackedStringArray: #as
- get:
- var property = _proxy.get_property(IFACE_BLOCK, "UserspaceMountOptions")
- if not property is Array:
- return []
- return property
diff --git a/core/systems/disks/udisks2_block_device.tres b/core/systems/disks/udisks2_block_device.tres
deleted file mode 100644
index fcf724f5c..000000000
--- a/core/systems/disks/udisks2_block_device.tres
+++ /dev/null
@@ -1,6 +0,0 @@
-[gd_resource type="Resource" load_steps=2 format=3 uid="uid://bqa1oyg8j861h"]
-
-[ext_resource type="Script" path="res://core/systems/disks/udisks2_block_device.gd" id="1_q6b6m"]
-
-[resource]
-script = ExtResource("1_q6b6m")
diff --git a/core/systems/disks/udisks2_drive_device.gd b/core/systems/disks/udisks2_drive_device.gd
deleted file mode 100644
index 7a6865ca5..000000000
--- a/core/systems/disks/udisks2_drive_device.gd
+++ /dev/null
@@ -1,360 +0,0 @@
-extends UDisks2
-class_name DriveDevice
-
-## Methods and properties of a UDisks2 Drive Device dbus interface.
-##
-## The DriveDevice class is responsible for handling dbus messages to and
-## from the UDisks2 daemon for drive device management, including drive
-## controllers.
-
-signal updated
-
-var _proxy: DBusManager.Proxy
-var dbus_path: String
-var interface_type:= INTERFACE_TYPE.UNKNOWN
-
-enum INTERFACE_TYPE {
- UNKNOWN,
- HDD,
- NVME,
- SD,
- SSD,
- USB,
-}
-
-
-func _init(proxy: DBusManager.Proxy) -> void:
- var dbus := load("res://core/global/dbus_system.tres") as DBusManager
- _proxy = proxy
- _proxy.properties_changed.connect(_on_properties_changed)
- dbus_path = _proxy.path
-
-func _on_properties_changed(_iface: String, props: Dictionary) -> void:
- updated.emit()
-
-# Drive
-#func eject() -> void: #a{sv}
- #pass
-
-#func power_off() -> void: #a{sv}
- #pass
-
-#func set_configuration() -> void: #a{sv}a{sv}
- #pass
-
-var can_power_off: bool:
- get:
- var property = _proxy.get_property(IFACE_DRIVE, "Ejectable")
- if not property is bool:
- return false
- return property
-
-var configuration: Array: #a{sv}
- get:
- var property = _proxy.get_property(IFACE_DRIVE, "Configuration")
- if not property is Array:
- return []
- return property
-
-var connection_bus: String: #s
- get:
- var property = _proxy.get_property(IFACE_DRIVE, "ConnectionBus")
- if not property is String:
- return ""
- return property
-
-var ejectable: bool:
- get:
- var property = _proxy.get_property(IFACE_DRIVE, "Ejectable")
- if not property is bool:
- return false
- return property
-
-var id: String: #s
- get:
- var property = _proxy.get_property(IFACE_DRIVE, "Id")
- if not property is String:
- return ""
- return property
-
-var media: String: #s
- get:
- var property = _proxy.get_property(IFACE_DRIVE, "Media")
- if not property is String:
- return ""
- return property
-
-var media_available: bool:
- get:
- var property = _proxy.get_property(IFACE_DRIVE, "MediaAvailable")
- if not property is bool:
- return false
- return property
-
-var media_change_detected: bool:
- get:
- var property = _proxy.get_property(IFACE_DRIVE, "MediaChangeDetected")
- if not property is bool:
- return false
- return property
-
-var media_compatibility: PackedStringArray: #as
- get:
- var property = _proxy.get_property(IFACE_DRIVE, "MediaCompatibility")
- if not property is PackedStringArray:
- return []
- return property
-
-var media_removable: bool:
- get:
- var property = _proxy.get_property(IFACE_DRIVE, "MediaRemovable")
- if not property is bool:
- return false
- return property
-
-var model: String: #s
- get:
- var property = _proxy.get_property(IFACE_DRIVE, "Model")
- if not property is String:
- return ""
- return property
-
-var optical: bool:
- get:
- var property = _proxy.get_property(IFACE_DRIVE, "Optical")
- if not property is bool:
- return false
- return property
-
-var optical_blank: bool:
- get:
- var property = _proxy.get_property(IFACE_DRIVE, "OpticalBlank")
- if not property is bool:
- return false
- return property
-
-var optical_num_audio_tracks: int: #u
- get:
- var property = _proxy.get_property(IFACE_DRIVE, "OpticalNumAudioTracks")
- if not property is int:
- return -1
- return property
-
-var optical_num_data_tracks: int: #u
- get:
- var property = _proxy.get_property(IFACE_DRIVE, "OpticalNumDataTracks")
- if not property is int:
- return -1
- return property
-
-var optical_num_sessions: int: #u
- get:
- var property = _proxy.get_property(IFACE_DRIVE, "OpticalNumSessions")
- if not property is int:
- return -1
- return property
-
-var optical_num_tracks: int: #u
- get:
- var property = _proxy.get_property(IFACE_DRIVE, "OpticalNumTracks")
- if not property is int:
- return -1
- return property
-
-var removable: bool:
- get:
- var property = _proxy.get_property(IFACE_DRIVE, "Removable")
- if not property is bool:
- return false
- return property
-
-var revision: String: #s
- get:
- var property = _proxy.get_property(IFACE_DRIVE, "Revision")
- if not property is String:
- return ""
- return property
-
-var rotation_rate: int: #i
- get:
- var property = _proxy.get_property(IFACE_DRIVE, "RotationRate")
- if not property is int:
- return -1
- return property
-
-var seat: String: #s
- get:
- var property = _proxy.get_property(IFACE_DRIVE, "Seat")
- if not property is String:
- return ""
- return property
-
-var serial: String: #s
- get:
- var property = _proxy.get_property(IFACE_DRIVE, "Serial")
- if not property is String:
- return ""
- return property
-
-var sibling_id: String: #s
- get:
- var property = _proxy.get_property(IFACE_DRIVE, "SiblingId")
- if not property is String:
- return ""
- return property
-
-var size: int: #t
- get:
- var property = _proxy.get_property(IFACE_DRIVE, "Size")
- if not property is int:
- return -1
- return property
-
-var sort_key: String: #s
- get:
- var property = _proxy.get_property(IFACE_DRIVE, "SortKey")
- if not property is String:
- return ""
- return property
-
-var time_detected: int: #t
- get:
- var property = _proxy.get_property(IFACE_DRIVE, "TimeDetected")
- if not property is int:
- return -1
- return property
-
-var time_media_detected: int: #t
- get:
- var property = _proxy.get_property(IFACE_DRIVE, "TimeMediaDetected")
- if not property is int:
- return -1
- return property
-
-var vendor: String: #s
- get:
- var property = _proxy.get_property(IFACE_DRIVE, "Vendor")
- if not property is String:
- return ""
- return property
-
-var wwn: String: #s
- get:
- var property = _proxy.get_property(IFACE_DRIVE, "WWN")
- if not property is String:
- return ""
- return property
-
-# NVME Controller
-#func sanitize_start() -> void: #sa{sv}
- #pass
-
-#func smart_get_attributes() -> void: #a{sv} -> a{sv}
- #pass
-
-#func smart_selftest_abort() -> void: #a{sv}
- #pass
-
-#func smart_selftest_start() -> void: #sa{sv}
- #pass
-
-#func smart_update() -> void: #a{sv}
- #pass
-
-#var controller_id: int: #q
- #get:
- #var property = _proxy.get_property(IFACE_NVME_CONTROLLER, "ControllerID")
- #if not property is int:
- #return -1
- #return property #uint16
-
-#var fguid: String: #s
- #get:
- #var property = _proxy.get_property(IFACE_NVME_CONTROLLER, "FGUID")
- #if not property is String:
- #return ""
- #return property
-
-#var nvme_revision: String: #s
- #get:
- #var property = _proxy.get_property(IFACE_NVME_CONTROLLER, "NVMERevision")
- #if not property is String:
- #return ""
- #return property
-
-#var sanitize_percent_remaining: int: #i
- #get:
- #var property = _proxy.get_property(IFACE_NVME_CONTROLLER, "SanitizePercentRemaining")
- #if not property is int:
- #return -1
- #return property
-
-#var sanitize_status: String: #s
- #get:
- #var property = _proxy.get_property(IFACE_NVME_CONTROLLER, "SanitizeStatus")
- #if not property is String:
- #return ""
- #return property
-
-#var smart_critical_warning: PackedStringArray: #as
- #get:
- #var property = _proxy.get_property(IFACE_NVME_CONTROLLER, "SmartCriticalWarning")
- #if not property is PackedStringArray:
- #return []
- #return property
-
-#var smart_power_on_hours: int: #t
- #get:
- #var property = _proxy.get_property(IFACE_NVME_CONTROLLER, "SmartPowerOnHours")
- #if not property is int:
- #return -1
- #return property
-
-#var smart_selftest_percent_remaining: int: #i
- #get:
- #var property = _proxy.get_property(IFACE_NVME_CONTROLLER, "SmartSelftestPercentRemaining")
- #if not property is int:
- #return -1
- #return property
-
-#var smart_selftest_status: String: #s
- #get:
- #var property = _proxy.get_property(IFACE_NVME_CONTROLLER, "SmartSelftestStatus")
- #if not property is String:
- #return ""
- #return property
-
-#var smart_temperature: int: #q
- #get:
- #var property = _proxy.get_property(IFACE_NVME_CONTROLLER, "SmartTemperature")
- #if not property is int:
- #return -1
- #return property
-
-#var smart_updated: int: #t
- #get:
- #var property = _proxy.get_property(IFACE_NVME_CONTROLLER, "SmartUpdated")
- #if not property is int:
- #return -1
- #return property
-
-#var state: String: #s
- #get:
- #var property = _proxy.get_property(IFACE_NVME_CONTROLLER, "State")
- #if not property is String:
- #return ""
- #return property
-
-#var subsystem_nqn: String: #ay
- #get:
- #var property = _proxy.get_property(IFACE_NVME_CONTROLLER, "SubsystemNQN")
- #if not property is String:
- #return ""
- #return property
-
-#var unallocated_capacity: int: #t
- #get:
- #var property = _proxy.get_property(IFACE_NVME_CONTROLLER, "unallocatedCapacity")
- #if not property is int:
- #return -1
- #return property
diff --git a/core/systems/disks/udisks2_drive_device.tres b/core/systems/disks/udisks2_drive_device.tres
deleted file mode 100644
index b69c04ef0..000000000
--- a/core/systems/disks/udisks2_drive_device.tres
+++ /dev/null
@@ -1,6 +0,0 @@
-[gd_resource type="Resource" load_steps=2 format=3 uid="uid://biqlkubechqgc"]
-
-[ext_resource type="Script" path="res://core/systems/disks/udisks2_drive_device.gd" id="1_1kb7p"]
-
-[resource]
-script = ExtResource("1_1kb7p")
diff --git a/core/systems/disks/udisks2_partition_device.gd b/core/systems/disks/udisks2_partition_device.gd
deleted file mode 100644
index ff31ea4a1..000000000
--- a/core/systems/disks/udisks2_partition_device.gd
+++ /dev/null
@@ -1,172 +0,0 @@
-extends BlockDevice
-class_name PartitionDevice
-
-## Methods and properties of a UDisks2 Block Device's Partition and Filesystem
-## dbus interface.
-##
-## The PartitionDevice class is responsible for handling dbus messages to and
-## from the UDisks2 daemon for filesystems and partition BLock devices.
-
-var has_filesystem: bool = false
-
-# Partition
-#func partition_delete() -> void: #a{sv}
- #pass
-
-#func partition_resize_partition() -> void: #ta{sv}
- #pass
-
-#func partition_set_flags() -> void: #ta{sv}
- #pass
-
-#func partition_set_partition_name() -> void: #sa{sv} .SetName, set_name is a reserved Godot method
- #pass
-
-#func partition_set_type() -> void: #sa{sv}
- #pass
-
-#func partition_set_partition_uuid() -> void: #sa{sv}
- #pass
-
-
-var partition_flags: int: #t
- get:
- var property = _proxy.get_property(IFACE_PARTITION, "Flags")
- if not property is int:
- return -1
- return property
-
-var partition_is_contained: bool:
- get:
- var property = _proxy.get_property(IFACE_PARTITION, "IsContained")
- if not property is bool:
- return false
- return property
-
-var partition_is_container: bool:
- get:
- var property = _proxy.get_property(IFACE_PARTITION, "IsContainer")
- if not property is bool:
- return false
- return property
-
-var partition_name: String: #s
- get:
- var property = _proxy.get_property(IFACE_PARTITION, "Name")
- if not property is String:
- return ""
- return property
-
-var partition_number: int: #u
- get:
- var property = _proxy.get_property(IFACE_PARTITION, "Number")
- if not property is int:
- return -1
- return property
-
-var partition_offset: int: #t
- get:
- var property = _proxy.get_property(IFACE_PARTITION, "Offset")
- if not property is int:
- return -1
- return property
-
-var partition_size: int: #t
- get:
- var property = _proxy.get_property(IFACE_PARTITION, "Size")
- if not property is int:
- return -1
- return property
-
-var partition_table: String: #o
- get:
- var property = _proxy.get_property(IFACE_PARTITION, "Table")
- if not property is String:
- return ""
- return property
-
-var partition_type: String: #s
- get:
- var property = _proxy.get_property(IFACE_PARTITION, "Type")
- if not property is String:
- return ""
- return property
-
-var partition_uuid: String: #s
- get:
- var property = _proxy.get_property(IFACE_PARTITION, "UUID")
- if not property is String:
- return ""
- return property
-
-# Filesystem
-#func fs_check() -> void: #a{sv} -> b
- #pass
-
-#func fs_mount() -> void: #a{sv} -> s
- #pass
-
-#func fs_repair() -> void: #a{sv} -> b
- #pass
-
-#func fs_resize_filesystem() -> void: #ta{sv}
- #pass
-
-#func fs_set_label() -> void: #sa{sv}
- #pass
-
-#func fs_set_filesystem_uuid() -> void: #sa{sv}
- #pass
-
-#func fs_take_ownership() -> void: #a{sv}
- #pass
-
-#func fs_unmount() -> void: #a{sv}
- #pass
-
-var fs_mount_points: PackedStringArray: #aay
- get:
- if not has_filesystem:
- return []
-
- var mount_points: PackedStringArray = []
- var property = _proxy.get_property(IFACE_FILESYSTEM, "MountPoints")
-
- if not property is Array:
- return []
-
- for raw_array in property:
- var char_array: PackedByteArray = []
- char_array.append_array(raw_array as PackedByteArray)
- var mount_point = char_array.get_string_from_ascii()
- mount_points.append(mount_point as String)
-
- return mount_points
-
-var fs_size: int: #t
- get:
- if not has_filesystem:
- return -1
- var property = _proxy.get_property(IFACE_FILESYSTEM, "Size")
- if not property is int:
- return -1
- return property
-
-var fs_symlinks: PackedStringArray: #aay
- get:
- if not has_filesystem:
- return []
-
- var symlinks: PackedStringArray = []
- var property = _proxy.get_property(IFACE_FILESYSTEM, "MountPoints")
-
- if not property is Array:
- return []
-
- for raw_array in property:
- var char_array: PackedByteArray = []
- char_array.append_array(raw_array as PackedByteArray)
- var symlink = char_array.get_string_from_ascii()
- symlinks.append(symlink as String)
-
- return symlinks
diff --git a/core/systems/disks/udisks2_partition_device.tres b/core/systems/disks/udisks2_partition_device.tres
deleted file mode 100644
index 97950d54b..000000000
--- a/core/systems/disks/udisks2_partition_device.tres
+++ /dev/null
@@ -1,6 +0,0 @@
-[gd_resource type="Resource" script_class="PartitionDevice" load_steps=2 format=3 uid="uid://df7pk5qc4ppt4"]
-
-[ext_resource type="Script" path="res://core/systems/disks/udisks2_partition_device.gd" id="1_rv37n"]
-
-[resource]
-script = ExtResource("1_rv37n")
diff --git a/core/systems/gamescope/gamescope.gd b/core/systems/gamescope/gamescope.gd
new file mode 100644
index 000000000..185d62df9
--- /dev/null
+++ b/core/systems/gamescope/gamescope.gd
@@ -0,0 +1,26 @@
+@icon("res://assets/editor-icons/streamline--desktop-game-solid.svg")
+extends Node
+class_name Gamescope
+
+## Manages gamescope.
+##
+## The [Gamescope] class is responsible for loading a [GamescopeInstance] and
+## calling its 'process()' method each frame.
+
+@export var instance: GamescopeInstance = load("res://core/systems/gamescope/gamescope.tres") as GamescopeInstance
+
+# Keep a reference to xwayland instances so they are not cleaned up automatically
+var _xwaylands: Array[GamescopeXWayland]
+var logger := Log.get_logger("Gamescope")
+
+
+func _ready() -> void:
+ _xwaylands = instance.get_xwaylands()
+ if _xwaylands.is_empty():
+ logger.warn("Gamescope not detected. Unexpected behavior expected.")
+
+
+func _process(_delta: float) -> void:
+ if not instance:
+ return
+ instance.process()
diff --git a/core/systems/gamescope/gamescope.tres b/core/systems/gamescope/gamescope.tres
new file mode 100644
index 000000000..1e22d2c3b
--- /dev/null
+++ b/core/systems/gamescope/gamescope.tres
@@ -0,0 +1,3 @@
+[gd_resource type="GamescopeInstance" format=3 uid="uid://chd0nc6gbfnw0"]
+
+[resource]
diff --git a/core/systems/gamescope/gamescope_test.gd b/core/systems/gamescope/gamescope_test.gd
new file mode 100644
index 000000000..96fd0b73d
--- /dev/null
+++ b/core/systems/gamescope/gamescope_test.gd
@@ -0,0 +1,21 @@
+extends Node2D
+
+var gamescope := load("res://core/systems/gamescope/gamescope.tres") as GamescopeInstance
+
+var PID := OS.get_process_id()
+
+# Called when the node enters the scene tree for the first time.
+func _ready() -> void:
+ print(gamescope.get_xwaylands())
+ var xwayland := gamescope.get_xwayland(gamescope.XWAYLAND_TYPE_OGUI)
+ if not xwayland:
+ print("XWayland not found")
+ return
+
+ var ogui_window_ids := xwayland.get_windows_for_pid(PID)
+ if ogui_window_ids.is_empty():
+ print("Unable to find window id for OGUI")
+ return
+ var ogui_window_id := ogui_window_ids[0]
+ xwayland.set_main_app(ogui_window_id)
+ print("Found window ids for OGUI: ", ogui_window_ids)
diff --git a/core/systems/gamescope/gamescope_test.tscn b/core/systems/gamescope/gamescope_test.tscn
new file mode 100644
index 000000000..73d96e768
--- /dev/null
+++ b/core/systems/gamescope/gamescope_test.tscn
@@ -0,0 +1,17 @@
+[gd_scene load_steps=5 format=3 uid="uid://83606lflpyo5"]
+
+[ext_resource type="Script" path="res://core/systems/gamescope/gamescope_test.gd" id="1_e433b"]
+[ext_resource type="Script" path="res://core/systems/gamescope/gamescope.gd" id="1_ukgov"]
+[ext_resource type="GamescopeInstance" uid="uid://chd0nc6gbfnw0" path="res://core/systems/gamescope/gamescope.tres" id="2_fbm81"]
+[ext_resource type="Texture2D" uid="uid://djy4rejy21s6g" path="res://icon.svg" id="4_j1wlf"]
+
+[node name="GamescopeTest" type="Node2D"]
+script = ExtResource("1_e433b")
+
+[node name="Gamescope" type="Node" parent="."]
+script = ExtResource("1_ukgov")
+instance = ExtResource("2_fbm81")
+
+[node name="Icon" type="Sprite2D" parent="."]
+position = Vector2(609, 401)
+texture = ExtResource("4_j1wlf")
diff --git a/core/systems/hardware/cpu.gd b/core/systems/hardware/cpu.gd
index 259a6167a..efba6168d 100644
--- a/core/systems/hardware/cpu.gd
+++ b/core/systems/hardware/cpu.gd
@@ -99,8 +99,8 @@ func _get_property(prop_path: String) -> String:
## Provides info on the GPU vendor, model, and capabilities.
func _get_lscpu_info() -> PackedStringArray:
- var cmd := CommandSync.new("lscpu")
- if cmd.execute() != OK:
+ var cmd := Command.create("lscpu", [])
+ if cmd.execute_blocking() != OK:
return []
return cmd.stdout.split("\n")
@@ -111,4 +111,3 @@ func _to_string() -> String:
+ ") Model: (" + str(model) \
+ ") Core count: (" + str(core_count) \
+ ")>"
-
diff --git a/core/systems/hardware/hardware_manager.gd b/core/systems/hardware/hardware_manager.gd
index e006376e9..c24f5edd9 100644
--- a/core/systems/hardware/hardware_manager.gd
+++ b/core/systems/hardware/hardware_manager.gd
@@ -71,7 +71,8 @@ func get_gpu_info() -> GPUInfo:
# to look into vulkaninfo as this can only gather the data
# for the currently active GPU. Vulkaninfo can provide data
# on all detected GPU devices.
- match RenderingServer.get_video_adapter_vendor():
+ gpu_info.vendor = RenderingServer.get_video_adapter_vendor()
+ match gpu_info.vendor:
"AMD", "AuthenticAMD", 'AuthenticAMD Advanced Micro Devices, Inc.', "Advanced Micro Devices, Inc. [AMD/ATI]":
gpu_info.vendor = "AMD"
"Intel", "GenuineIntel", "Intel Corporation":
@@ -160,11 +161,11 @@ func get_kernel_version() -> String:
## (e.g. get_gpu_card("card1"))
func get_gpu_card(card_dir: String) -> DRMCardInfo:
var file_prefix := "/".join(["/sys/class/drm", card_dir, "device"])
- var vendor_id := _get_card_property_from_path("/".join([file_prefix, "vendor"]))
- var device_id := _get_card_property_from_path("/".join([file_prefix, "device"]))
- var revision_id := _get_card_property_from_path("/".join([file_prefix, "revision"]))
- var subvendor_id := _get_card_property_from_path("/".join([file_prefix, "subsystem_vendor"]))
- var subdevice_id := _get_card_property_from_path("/".join([file_prefix, "subsystem_device"]))
+ var vendor_id := _get_card_property_from_cat("/".join([file_prefix, "vendor"]))
+ var device_id := _get_card_property_from_cat("/".join([file_prefix, "device"]))
+ var revision_id := _get_card_property_from_cat("/".join([file_prefix, "revision"]))
+ var subvendor_id := _get_card_property_from_cat("/".join([file_prefix, "subsystem_vendor"]))
+ var subdevice_id := _get_card_property_from_cat("/".join([file_prefix, "subsystem_device"]))
# Try to load the card info if it already exists
var res_path := "/".join(["drmcardinfo://", vendor_id, device_id, subvendor_id, subdevice_id])
@@ -272,7 +273,7 @@ func get_gpu_cards() -> Array[DRMCardInfo]:
var card_info := get_gpu_card(card_name)
if not card_info:
continue
-
+
found_cards.append(card_info)
var vulkan_info := _get_cards_from_vulkan()
@@ -378,6 +379,16 @@ func _get_card_property_from_path(path: String) -> String:
return FileAccess.get_file_as_string(path).lstrip("0x").to_lower().strip_escapes()
+func _get_card_property_from_cat(path: String) -> String:
+ var output := []
+ OS.execute("cat", [path], output)
+ if output.is_empty():
+ return ""
+ var value := output[0] as String
+ logger.debug("Got cat output:", value)
+ return value.lstrip("0x").to_lower().strip_escapes()
+
+
## Returns a an array of PackedStringArray's that each represent a sing GPU
## identified in vulkaninfo.
func _get_cards_from_vulkan() ->Array[PackedStringArray]:
diff --git a/core/systems/input/events/event.gd b/core/systems/input/events/event.gd
index 632602be1..c996fe2c4 100644
--- a/core/systems/input/events/event.gd
+++ b/core/systems/input/events/event.gd
@@ -740,3 +740,266 @@ static func capability_from_keycode(scancode: int) -> String:
return "Keyboard:KeyF24"
_:
return ""
+
+
+## Convert the given key scancode into a target keyboard event string
+static func virtual_key_from_keycode(scancode: int) -> String:
+ match scancode:
+ KEY_ESCAPE:
+ return "KEY_ESC"
+ KEY_1:
+ return "KEY_1"
+ KEY_2:
+ return "KEY_2"
+ KEY_3:
+ return "KEY_3"
+ KEY_4:
+ return "KEY_4"
+ KEY_5:
+ return "KEY_5"
+ KEY_6:
+ return "KEY_6"
+ KEY_7:
+ return "KEY_7"
+ KEY_8:
+ return "KEY_8"
+ KEY_9:
+ return "KEY_9"
+ KEY_0:
+ return "KEY_0"
+ KEY_MINUS:
+ return "KEY_MINUS"
+ KEY_EQUAL:
+ return "KEY_EQUAL"
+ KEY_BACKSPACE:
+ return "KEY_BACKSPACE"
+ KEY_TAB:
+ return "KEY_TAB"
+ KEY_Q:
+ return "KEY_Q"
+ KEY_W:
+ return "KEY_W"
+ KEY_E:
+ return "KEY_E"
+ KEY_R:
+ return "KEY_R"
+ KEY_T:
+ return "KEY_T"
+ KEY_Y:
+ return "KEY_Y"
+ KEY_U:
+ return "KEY_U"
+ KEY_I:
+ return "KEY_I"
+ KEY_O:
+ return "KEY_O"
+ KEY_P:
+ return "KEY_P"
+ KEY_BRACELEFT:
+ return "KEY_LEFTBRACE"
+ KEY_BRACERIGHT:
+ return "KEY_RIGHTBRACE"
+ KEY_ENTER:
+ return "KEY_ENTER"
+ KEY_CTRL:
+ return "KEY_LEFTCTRL"
+ KEY_A:
+ return "KEY_A"
+ KEY_S:
+ return "KEY_S"
+ KEY_D:
+ return "KEY_D"
+ KEY_F:
+ return "KEY_F"
+ KEY_G:
+ return "KEY_G"
+ KEY_H:
+ return "KEY_H"
+ KEY_J:
+ return "KEY_J"
+ KEY_K:
+ return "KEY_K"
+ KEY_L:
+ return "KEY_L"
+ KEY_SEMICOLON:
+ return "KEY_SEMICOLON"
+ KEY_APOSTROPHE:
+ return "KEY_APOSTROPHE"
+ KEY_ASCIITILDE:
+ return "KEY_GRAVE"
+ KEY_SHIFT:
+ return "KEY_LEFTSHIFT"
+ KEY_BACKSLASH:
+ return "KEY_BACKSLASH"
+ KEY_Z:
+ return "KEY_Z"
+ KEY_X:
+ return "KEY_X"
+ KEY_C:
+ return "KEY_C"
+ KEY_V:
+ return "KEY_V"
+ KEY_B:
+ return "KEY_B"
+ KEY_N:
+ return "KEY_N"
+ KEY_M:
+ return "KEY_M"
+ KEY_COMMA:
+ return "KEY_COMMA"
+ KEY_PERIOD:
+ return "KEY_DOT"
+ KEY_SLASH:
+ return "KEY_SLASH"
+ KEY_SHIFT:
+ return "KEY_SHIFT"
+ KEY_ASTERISK:
+ return "KEY_ASTERISK"
+ KEY_ALT:
+ return "KEY_ALT"
+ KEY_SPACE:
+ return "KEY_SPACE"
+ KEY_CAPSLOCK:
+ return "KEY_CAPSLOCK"
+ KEY_F1:
+ return "KEY_F1"
+ KEY_F2:
+ return "KEY_F2"
+ KEY_F3:
+ return "KEY_F3"
+ KEY_F4:
+ return "KEY_F4"
+ KEY_F5:
+ return "KEY_F5"
+ KEY_F6:
+ return "KEY_F6"
+ KEY_F7:
+ return "KEY_F7"
+ KEY_F8:
+ return "KEY_F8"
+ KEY_F9:
+ return "KEY_F9"
+ KEY_F10:
+ return "KEY_F10"
+ KEY_NUMLOCK:
+ return "KEY_NUMLOCK"
+ KEY_SCROLLLOCK:
+ return "KEY_SCROLLLOCK"
+ KEY_KP_7:
+ return "KEY_KP7"
+ KEY_KP_8:
+ return "KEY_KP8"
+ KEY_KP_9:
+ return "KEY_KP9"
+ KEY_KP_SUBTRACT:
+ return "KEY_KPMINUS"
+ KEY_KP_4:
+ return "KEY_KP4"
+ KEY_KP_5:
+ return "KEY_KP5"
+ KEY_KP_6:
+ return "KEY_KP6"
+ KEY_KP_ADD:
+ return "KEY_KPPLUS"
+ KEY_KP_1:
+ return "KEY_KP1"
+ KEY_KP_2:
+ return "KEY_KP2"
+ KEY_KP_3:
+ return "KEY_KP3"
+ KEY_KP_0:
+ return "KEY_KP0"
+ KEY_KP_PERIOD:
+ return "KEY_KPDOT"
+ KEY_F11:
+ return "KEY_F11"
+ KEY_F12:
+ return "KEY_F12"
+ KEY_JIS_KANA:
+ return "KEY_KATAKANAHIRAGANA"
+ KEY_KP_ENTER:
+ return "KEY_KPENTER"
+ KEY_CTRL:
+ return "KEY_CTRL"
+ KEY_KP_DIVIDE:
+ return "KEY_KPSLASH"
+ KEY_SYSREQ:
+ return "KEY_SYSREQ"
+ KEY_ALT:
+ return "KEY_ALT"
+ KEY_HOME:
+ return "KEY_HOME"
+ KEY_UP:
+ return "KEY_UP"
+ KEY_PAGEUP:
+ return "KEY_PAGEUP"
+ KEY_LEFT:
+ return "KEY_LEFT"
+ KEY_RIGHT:
+ return "KEY_RIGHT"
+ KEY_END:
+ return "KEY_END"
+ KEY_DOWN:
+ return "KEY_DOWN"
+ KEY_PAGEDOWN:
+ return "KEY_PAGEDOWN"
+ KEY_INSERT:
+ return "KEY_INSERT"
+ KEY_DELETE:
+ return "KEY_DELETE"
+ KEY_VOLUMEMUTE:
+ return "KEY_VOLUMEMUTE"
+ KEY_VOLUMEDOWN:
+ return "KEY_VOLUMEDOWN"
+ KEY_VOLUMEUP:
+ return "KEY_VOLUMEUP"
+ KEY_PAUSE:
+ return "KEY_PAUSE"
+ KEY_YEN:
+ return "KEY_YEN"
+ KEY_META:
+ return "KEY_LEFTMETA"
+ KEY_STOP:
+ return "KEY_STOP"
+ KEY_HELP:
+ return "KEY_HELP"
+ KEY_BACK:
+ return "KEY_BACK"
+ KEY_FORWARD:
+ return "KEY_FORWARD"
+ KEY_MEDIANEXT:
+ return "KEY_MEDIANEXT"
+ KEY_MEDIAPLAY:
+ return "KEY_MEDIAPLAY"
+ KEY_MEDIAPREVIOUS:
+ return "KEY_MEDIAPREVIOUS"
+ KEY_MEDIASTOP:
+ return "KEY_MEDIASTOP"
+ KEY_REFRESH:
+ return "KEY_REFRESH"
+ KEY_F13:
+ return "KEY_F13"
+ KEY_F14:
+ return "KEY_F14"
+ KEY_F15:
+ return "KEY_F15"
+ KEY_F16:
+ return "KEY_F16"
+ KEY_F17:
+ return "KEY_F17"
+ KEY_F18:
+ return "KEY_F18"
+ KEY_F19:
+ return "KEY_F19"
+ KEY_F20:
+ return "KEY_F20"
+ KEY_F21:
+ return "KEY_F21"
+ KEY_F22:
+ return "KEY_F22"
+ KEY_F23:
+ return "KEY_F23"
+ KEY_F24:
+ return "KEY_F24"
+ _:
+ return ""
diff --git a/core/systems/input/input_icon_manager.gd b/core/systems/input/input_icon_manager.gd
index f60d1b40e..e0cb5c177 100644
--- a/core/systems/input/input_icon_manager.gd
+++ b/core/systems/input/input_icon_manager.gd
@@ -20,7 +20,7 @@ enum InputType {
}
var in_game_state := load("res://assets/state/states/in_game.tres") as State
-var input_plumber := load("res://core/systems/input/input_plumber.tres") as InputPlumber
+var input_plumber := load("res://core/systems/input/input_plumber.tres") as InputPlumberInstance
var logger := Log.get_logger("InputIconManager", Log.LEVEL.INFO)
## Disable/Enable signaling on input type changes
@@ -154,7 +154,7 @@ func _init():
in_game_state.state_exited.connect(on_in_game_exited)
# Listen for InputPlumber device change events
- var on_comp_device_added := func(_device: InputPlumber.CompositeDevice):
+ var on_comp_device_added := func(_device: CompositeDevice):
_on_joy_connection_changed(true)
input_plumber.composite_device_added.connect(on_comp_device_added)
var on_comp_device_removed := func(_path: String):
@@ -402,8 +402,6 @@ func _get_matching_event(path: String, input_type: InputType) -> Array[InputEven
## Set the last input type to the given value and emit a signal
func set_last_input_type(_last_input_type: InputType):
last_input_type = _last_input_type
- if not self.disabled:
- input_type_changed.emit(_last_input_type)
## Signal whenever a gamepad is connected/disconnected
diff --git a/core/systems/input/input_icon_processor.gd b/core/systems/input/input_icon_processor.gd
index 767f57f9a..2acdd3072 100644
--- a/core/systems/input/input_icon_processor.gd
+++ b/core/systems/input/input_icon_processor.gd
@@ -6,7 +6,7 @@ class_name InputIconProcessor
const DEADZONE := 0.4
-var input_plumber := load("res://core/systems/input/input_plumber.tres") as InputPlumber
+var input_plumber := load("res://core/systems/input/input_plumber.tres") as InputPlumberInstance
var icon_manager := load("res://core/systems/input/input_icon_manager.tres") as InputIconManager
@@ -23,16 +23,21 @@ func _input(event: InputEvent) -> void:
# If this is an InputPlumber event, use the name from the device
if event.has_meta("dbus_path") and not event.get_meta("dbus_path", "").is_empty():
var dbus_path := event.get_meta("dbus_path") as String
- var device := input_plumber.get_device(dbus_path)
- device_name = device.name
+ var device := input_plumber.get_composite_device(dbus_path)
+ if device:
+ device_name = device.name
# Otherwise, use the detected device name
else:
device_name = Input.get_joy_name(event.device)
"InputEventJoypadMotion":
if abs(event.axis_value) > DEADZONE:
input_type = InputIconManager.InputType.GAMEPAD
+ var refresh := false
if input_type != icon_manager.last_input_type:
icon_manager.set_last_input_type(input_type)
+ refresh = true
if device_name != icon_manager.last_input_device:
icon_manager.last_input_device = device_name
+ refresh = true
+ if refresh:
icon_manager.refresh()
diff --git a/core/systems/input/input_manager.gd b/core/systems/input/input_manager.gd
index 7925a935e..174b1405e 100644
--- a/core/systems/input/input_manager.gd
+++ b/core/systems/input/input_manager.gd
@@ -18,7 +18,7 @@ var osk := load("res://core/global/keyboard_instance.tres") as KeyboardInstance
## The audio manager to use to adjust the audio when audio input events happen.
var audio_manager := load("res://core/global/audio_manager.tres") as AudioManager
## InputPlumber receives and sends DBus input events.
-var input_plumber := load("res://core/systems/input/input_plumber.tres") as InputPlumber
+var input_plumber := load("res://core/systems/input/input_plumber.tres") as InputPlumberInstance
## LaunchManager provides context on the currently running app so we can switch profiles
var launch_manager := load("res://core/global/launch_manager.tres") as LaunchManager
## The Global State Machine
@@ -36,6 +36,9 @@ var popup_state := preload("res://assets/state/states/popup.tres") as State
## Map of pressed actions to prevent double inputs
var actions_pressed := {}
+## Number of currently pressed touches
+var current_touches := 0
+
## Will show logger events with the prefix InputManager
var logger := Log.get_logger("InputManager", Log.LEVEL.INFO)
@@ -44,11 +47,20 @@ var logger := Log.get_logger("InputManager", Log.LEVEL.INFO)
func _ready() -> void:
add_to_group("InputManager")
input_plumber.composite_device_added.connect(_watch_dbus_device)
+ input_plumber.started.connect(_init_inputplumber)
+ _init_inputplumber()
+
- for device in input_plumber.composite_devices:
+func _init_inputplumber() -> void:
+ for device in input_plumber.get_composite_devices():
_watch_dbus_device(device)
+## Returns true if the given event is an InputPlumber event
+static func is_inputplumber_event(event: InputEvent) -> bool:
+ return event.has_meta("dbus_path")
+
+
## Queue a release event for the given action
func action_release(dbus_path: String, action: String, strength: float = 1.0) -> void:
Input.action_release(action)
@@ -72,10 +84,26 @@ func _send_input(dbus_path: String, action: String, pressed: bool, strength: flo
Input.parse_input_event(input_action)
-## Process all unhandled input, possibly preventing the input from propagating further.
-## https://docs.godotengine.org/en/latest/tutorials/inputs/inputevent.html#how-does-it-work
+## Process all window input. Window input is processed before all _input and
+## _gui_input node methods.
+## @tutorial https://docs.godotengine.org/en/latest/tutorials/inputs/inputevent.html#how-does-it-work
func _input(event: InputEvent) -> void:
logger.debug("Got input event to handle: " + str(event))
+
+ # Keep track of the current number of touch inputs
+ if event is InputEventScreenTouch:
+ if event.is_pressed():
+ self.current_touches += 1
+ else:
+ self.current_touches -= 1
+
+ # Don't process Godot events if InputPlumber is running
+ if input_plumber.is_running() and not is_inputplumber_event(event):
+ if event is InputEventJoypadButton or event is InputEventJoypadMotion:
+ logger.debug("Skipping Godot event while InputPlumber is running:", event)
+ get_viewport().set_input_as_handled()
+ return
+
var dbus_path := event.get_meta("dbus_path", "") as String
# Consume double inputs for controllers with DPads that have TRIGGER_HAPPY events
@@ -175,7 +203,7 @@ func _guide_input(event: InputEvent) -> void:
var dbus_path := event.get_meta("dbus_path", "") as String
# Only act on release events
if event.is_pressed():
- logger.warn("Guide pressed. Waiting for additional events.")
+ logger.debug("Guide pressed. Waiting for additional events.")
# Set the gamepad profile to the global default so we can capture button events.
# This ensures that we use the global profile and not the game's input profile for
# processing guide button combos and navigating the menu.
@@ -270,17 +298,19 @@ func _audio_input(event: InputEvent) -> void:
return
-func _watch_dbus_device(device: InputPlumber.CompositeDevice) -> void:
- for target in device.dbus_targets:
- logger.debug("Adding watch for " + device.name + " " + target.name)
- logger.debug(str(target.get_instance_id()))
- logger.debug(str(target.get_rid()))
- target.input_event.connect(_on_dbus_input_event.bind(device.dbus_path))
+func _watch_dbus_device(device: CompositeDevice) -> void:
+ for target in device.dbus_devices:
+ if target.input_event.is_connected(_on_dbus_input_event.bind(device.dbus_path)):
+ continue
+ logger.debug("Adding watch for " + device.name + " " + target.dbus_path)
+ logger.debug(str(target.get_instance_id()))
+ logger.debug(str(target.get_rid()))
+ target.input_event.connect(_on_dbus_input_event.bind(device.dbus_path))
func _on_dbus_input_event(event: String, value: float, dbus_path: String) -> void:
var pressed := value == 1.0
- logger.debug("Handling dbus input event from" + dbus_path + ": " + event + " pressed: " + str(pressed))
+ logger.debug("Handling dbus input event from '" + dbus_path + "': " + event + " pressed: " + str(pressed))
var action := event
match event:
diff --git a/core/systems/input/input_manager.tscn b/core/systems/input/input_manager.tscn
index a32585d55..000a852e8 100644
--- a/core/systems/input/input_manager.tscn
+++ b/core/systems/input/input_manager.tscn
@@ -1,6 +1,12 @@
-[gd_scene load_steps=2 format=3 uid="uid://n83wlhmmsu3j"]
+[gd_scene load_steps=4 format=3 uid="uid://n83wlhmmsu3j"]
[ext_resource type="Script" path="res://core/systems/input/input_manager.gd" id="1_3s67x"]
+[ext_resource type="Script" path="res://core/systems/input/input_plumber.gd" id="2_v1kl3"]
+[ext_resource type="InputPlumberInstance" uid="uid://e2bevy4j4rx2" path="res://core/systems/input/input_plumber.tres" id="3_eclcy"]
[node name="InputManager" type="Node"]
script = ExtResource("1_3s67x")
+
+[node name="InputPlumber" type="Node" parent="."]
+script = ExtResource("2_v1kl3")
+instance = ExtResource("3_eclcy")
diff --git a/core/systems/input/input_plumber.gd b/core/systems/input/input_plumber.gd
index f21c8e0ad..446a1a625 100644
--- a/core/systems/input/input_plumber.gd
+++ b/core/systems/input/input_plumber.gd
@@ -1,5 +1,5 @@
-@icon("res://assets/icons/game-controller.svg")
-extends Resource
+@icon("res://addons/core/assets/icons/inputplumber.svg")
+extends Node
class_name InputPlumber
## Manages routing input to and from InputPlumber.
@@ -7,690 +7,118 @@ class_name InputPlumber
## The InputPlumberManager class is responsible for handling dbus messages to and
## from the InputPlumber input manager daemon.
-const INPUT_PLUMBER_BUS := "org.shadowblip.InputPlumber"
-const INPUT_PLUMBER_PATH := "/org/shadowblip/InputPlumber"
-const INPUT_PLUMBER_PREFIX := INPUT_PLUMBER_PATH + "/devices"
-const INPUT_PLUMBER_MANAGER_PATH := "/org/shadowblip/InputPlumber/Manager"
-const IFACE_MANAGER := "org.shadowblip.InputManager"
-const IFACE_COMPOSITE_DEVICE := "org.shadowblip.Input.CompositeDevice"
-const IFACE_EVENT_DEVICE := "org.shadowblip.Input.Source.EventDevice"
-const IFACE_HIDRAW_DEVICE := "org.shadowblip.Input.Source.HIDRawDevice"
-const IFACE_IIO_DEVICE := "org.shadowblip.Input.Source.IIODevice"
-const IFACE_DBUS_DEVICE := "org.shadowblip.Input.DBusDevice"
-const IFACE_GAMEPAD_DEVICE := "org.shadowblip.Input.Gamepad"
-const IFACE_KEYBOARD_DEVICE := "org.shadowblip.Input.Keyboard"
-const IFACE_MOUSE_DEVICE := "org.shadowblip.Input.Mouse"
-
const DEFAULT_PROFILE := "res://assets/gamepad/profiles/default.json"
const DEFAULT_GLOBAL_PROFILE := "user://data/gamepad/profiles/global_default.json"
const PROFILES_DIR := "user://data/gamepad/profiles"
-enum INTERCEPT_MODE {
- NONE,
- PASS,
- ALL,
-}
-
-var logger := Log.get_logger("InputPlumber", Log.LEVEL.INFO)
-
-var dbus := load("res://core/global/dbus_system.tres") as DBusManager
-var manager := Manager.new(dbus.create_proxy(INPUT_PLUMBER_BUS, INPUT_PLUMBER_MANAGER_PATH))
-var object_manager := dbus.ObjectManager.new(dbus.create_proxy(INPUT_PLUMBER_BUS, INPUT_PLUMBER_PATH))
-var system_thread := load("res://core/systems/threading/system_thread.tres") as SharedThread
-
-var is_running := false
-var composite_devices: Array[CompositeDevice] = []
-var composite_devices_map: Dictionary = {}
-var intercept_mode_current: INTERCEPT_MODE = INTERCEPT_MODE.NONE
-var intercept_triggers_current: PackedStringArray = ["Gamepad:Button:Guide"]
-var intercept_target_current: String = "Gamepad:Button:Guide"
+@export var instance: InputPlumberInstance = load("res://core/systems/input/input_plumber.tres")
-## Emitted when InputPlumber is detected as running
-signal started
-## Emitted when InputPlumber is detected as stopped
-signal stopped
-## Emitted when a CompositeDevice is dicovered and identified as a new device
-signal composite_device_added(device: CompositeDevice)
-## Emitted when a CompositeDevice is dicovered over dbus but already exists in
-## the local map
-signal composite_device_changed(device: CompositeDevice)
-## Emitted when a CompositeDevice is removed
-signal composite_device_removed(dbus_path: String)
+# Keep a reference to dbus devices so they are not cleaned up automatically
+var _dbus_devices := {}
func _init() -> void:
- logger.debug("Initalizing InputPlumber. Found composite devices: " + str(composite_devices))
- object_manager.interfaces_added.connect(_on_interfaces_added)
- object_manager.interfaces_removed.connect(_on_interfaces_removed)
- composite_devices = get_devices()
- for device in composite_devices:
- composite_devices_map[device.dbus_path] = device
-
- # Ensure the global default config is created
- var profiles_dir := ProjectSettings.globalize_path(PROFILES_DIR)
- if DirAccess.make_dir_recursive_absolute(profiles_dir) != OK:
- logger.error("Failed to create user profiles directory: " + profiles_dir)
- return
- var default_profile := FileAccess.open(DEFAULT_PROFILE, FileAccess.READ)
- var default_profile_data := default_profile.get_as_text()
- logger.debug("Writing default global profile to: " + DEFAULT_GLOBAL_PROFILE)
- var global_default_profile := FileAccess.open(DEFAULT_GLOBAL_PROFILE, FileAccess.WRITE)
- global_default_profile.store_string(default_profile_data)
-
- # Start a task that monitors whether or not InputPlumber is started or stopped,
- # and emits signals when its running state changes.
- started.connect(_on_inputplumber_started)
- stopped.connect(_on_inputplumber_stopped)
- var running_check := func():
- var update_running := func():
- var running := dbus.bus_exists(INPUT_PLUMBER_BUS)
- if running == self.is_running:
- return
- self.is_running = running
- if running:
- started.emit()
- else:
- stopped.emit()
- update_running.call_deferred()
- system_thread.exec(running_check)
- system_thread.scheduled_exec(running_check, 5000, SharedThread.ScheduledTaskType.RECURRING)
-
-
-func _on_inputplumber_started() -> void:
- logger.info("InputPlumber started")
+ # Ensure the default global profile exists in the user directory.
+ if not FileAccess.file_exists(DEFAULT_GLOBAL_PROFILE):
+ var file := FileAccess.open(DEFAULT_PROFILE, FileAccess.READ)
+ var content := file.get_as_text()
+ file.close()
+ if DirAccess.make_dir_recursive_absolute(PROFILES_DIR) != OK:
+ var logger := Log.get_logger("InputPlumber", Log.LEVEL.DEBUG)
+ logger.error("Failed to create gamepad profiles directory")
+ var new_file := FileAccess.open(DEFAULT_GLOBAL_PROFILE, FileAccess.WRITE)
+ new_file.store_string(content)
+ new_file.close()
+
+
+func _ready() -> void:
+ # Add listeners for any new devices
+ var on_device_added := func(device: CompositeDevice):
+ var dbus_devices := device.dbus_devices
+ if dbus_devices.is_empty():
+ return
+ var dbus_device := dbus_devices[0]
+ var dbus_path := device.dbus_path
+ _dbus_devices[dbus_path] = dbus_device
+ instance.composite_device_added.connect(on_device_added)
- # Remove any Godot gamepad input maps and rely completely on InputPlumber for
- # gamepad input
- var actions := InputMap.get_actions()
- var to_erase: Array[InputEvent] = []
- for action in actions:
- var events := InputMap.action_get_events(action)
- for event in events:
- if event is InputEventJoypadButton or event is InputEventJoypadMotion:
- logger.debug("Erasing mapping for", action, ":", event)
- InputMap.action_erase_event(action, event)
-
+ # Add listeners when devices are removed
+ var on_device_removed := func(dbus_path: String):
+ if not _dbus_devices.has(dbus_path):
+ return
+ _dbus_devices.erase(dbus_path)
+ instance.composite_device_removed.connect(on_device_removed)
-func _on_inputplumber_stopped() -> void:
- logger.warn("InputPlumber stopped")
-
- # Reload Godot input mappings if InputPlumber shuts down
- logger.debug("Restoring input mappings from project settings")
- InputMap.load_from_project_settings()
+ # Find all composite devices
+ var devices := instance.get_composite_devices()
+ for device in devices:
+ on_device_added.call(device)
-func _on_interfaces_added(dbus_path: String) -> void:
- logger.debug("Interfaces Added: " + str(dbus_path))
- if not "CompositeDevice" in dbus_path:
+func _process(_delta: float) -> void:
+ if not instance:
return
- composite_devices = get_devices(dbus_path)
- composite_devices_map.clear()
- for device in composite_devices:
- composite_devices_map[device.dbus_path] = device
-
-
-func _on_interfaces_removed(dbus_path: String) -> void:
- logger.debug("Interfaces Removed: " + str(dbus_path))
- if not "CompositeDevice" in dbus_path:
+ instance.process()
+
+
+ ## Load the given profile on the composite device, optionally specifying a profile
+## modifier, which is a target device string (e.g. "deck", "ds5-edge", etc.) to
+## adapt the profile for. This will update the profile with target-specific
+## defaults, like mapping left/right pads to the DualSense center pad if no
+## other mappings are defined.
+static func load_target_modified_profile(device: CompositeDevice, path: String, profile_modifier: String = "") -> void:
+ var logger := Log.get_logger("InputPlumber", Log.LEVEL.DEBUG)
+ logger.debug("Loading Profile:", path)
+ if path == "" or not path.ends_with(".json") or not FileAccess.file_exists(path):
+ logger.error("Profile path:", path," is not a valid profile path.")
+ return
+ if profile_modifier.is_empty():
+ device.load_profile_path(path)
return
- composite_devices = get_devices()
- composite_devices_map.clear()
- for device in composite_devices:
- composite_devices_map[device.dbus_path] = device
- if dbus_path.contains("CompositeDevice"):
- composite_device_removed.emit(dbus_path)
-
-
-## Returns true if InputPlumber can be used on this system
-func supports_input_plumber() -> bool:
- return dbus.bus_exists(INPUT_PLUMBER_BUS)
-
-
-func get_objects_of(pattern: String) -> Array:
- var devices: Array = []
- var device_paths := dbus.get_managed_objects(INPUT_PLUMBER_BUS, INPUT_PLUMBER_PATH)
- logger.debug("Searching for " + pattern + " objects.")
- # Loop through all objects on the bus
- for obj in device_paths:
-
- var object := obj as DBusManager.ManagedObject
- var path := object.path
- var proxy := dbus.create_proxy(INPUT_PLUMBER_BUS, path)
- #logger.debug("Found object: " + str(object) + " with path " + path)
- if path.contains(pattern) and pattern == "CompositeDevice":
- logger.debug("Found " + pattern + " in " + path)
- var device := CompositeDevice.new(proxy)
- devices.append(device)
- continue
-
- if path.contains(pattern) and pattern == "event":
- var device := EventDevice.new(proxy)
- devices.append(device)
- continue
-
- if path.contains(pattern) and pattern == "hidraw":
- var device := HIDRawDevice.new(proxy)
- devices.append(device)
- continue
-
- if path.contains(pattern) and pattern == "iio":
- var device := IIODevice.new(proxy)
- devices.append(device)
- continue
-
- if path.contains(pattern) and pattern == "dbus":
- var device := DBusDevice.new(proxy)
- devices.append(device)
- continue
-
- if path.contains(pattern) and pattern == "gamepad":
- var device := GamepadDevice.new(proxy)
- devices.append(device)
- continue
-
- if path.contains(pattern) and pattern == "keyboard":
- var device := KeyboardDevice.new(proxy)
- devices.append(device)
- continue
-
- if path.contains(pattern) and pattern == "mouse":
- var device := MouseDevice.new(proxy)
- devices.append(device)
- continue
- logger.debug("Returning devices: " + str(devices))
- return devices
-
-
-## Retrieves all CompositeDevices currently on the InputPlumber DBus interface. Will
-## emit composite_device_added if the given dbus path is a new device, or
-## composite_device_changed if it already existed
-func get_devices(dbus_path: String = "") -> Array[CompositeDevice]:
- logger.debug("Getting all composite devices.")
- var new_device_list: Array[CompositeDevice]
- new_device_list.assign(get_objects_of("CompositeDevice"))
- var existing_devices: Array[CompositeDevice]
-
- # Only return new devices. Overriding devices breaks signaling.
- for device in new_device_list:
- var found: bool = false
- for old_dev in composite_devices:
- if old_dev.dbus_path == device.dbus_path:
- existing_devices.append(old_dev)
- found = true
- if dbus_path == device.dbus_path:
- composite_device_changed.emit(device)
- break
-
- # New device found
- if not found:
- existing_devices.append(device)
- set_intercept_mode_single(intercept_mode_current, device)
- set_intercept_activation_single(intercept_triggers_current, \
- intercept_target_current, device)
- composite_device_added.emit(device)
-
- return existing_devices
-
-
-## Returns the [CompositeDevice] with the given DBus path
-func get_device(dbus_path: String) -> CompositeDevice:
- if dbus_path in composite_devices_map:
- return composite_devices_map[dbus_path]
- return null
-
-
-## Sets all composite devices to the specified intercept mode.
-func set_intercept_mode(mode: INTERCEPT_MODE) -> void:
- logger.debug("Setting all composite devices to mode: " + str(mode))
- intercept_mode_current = mode
- for d in composite_devices:
- var device := d as CompositeDevice
- set_intercept_mode_single(mode, device)
-
-
-func set_intercept_mode_single(mode: INTERCEPT_MODE, device: CompositeDevice) -> void:
- logger.debug("Setting composite device "+ device.dbus_path + " to mode: " + str(mode))
- match mode:
- INTERCEPT_MODE.NONE:
- device.intercept_mode = 0
- INTERCEPT_MODE.PASS:
- device.intercept_mode = 1
- INTERCEPT_MODE.ALL:
- device.intercept_mode = 2
-
-
-## Sets all composite devices to use the specified intercept actions.
-func set_intercept_activation(triggers: PackedStringArray, target: String) -> void:
- logger.debug("Setting all composite devices to intercept triggers: " + str(triggers) + " and target event: " + target)
- intercept_triggers_current = triggers
- intercept_target_current = target
- for d in composite_devices:
- var device := d as CompositeDevice
- set_intercept_activation_single(triggers, target, device)
-
-
-func set_intercept_activation_single(triggers: PackedStringArray, target: String, device: CompositeDevice) -> void:
- logger.debug("Setting composite device "+ device.dbus_path + " intercept triggers: " + str(triggers) + " and target event: " + target)
- device.set_intercept_activation(triggers, target)
-
-
-class Manager extends Resource:
- signal updated
- var _proxy: DBusManager.Proxy
-
- func _init(proxy: DBusManager.Proxy) -> void:
- _proxy = proxy
- _proxy.properties_changed.connect(_on_properties_changed)
-
- func _on_properties_changed(iface: String, props: Dictionary) -> void:
- updated.emit()
-
- func create_composite_device(config_path: String) -> String:
- var result := _proxy.call_method(IFACE_MANAGER, "CreateCompositeDevice", [config_path])
- if not result:
- return ""
- var args := result.get_args()
- if args.size() != 1:
- return ""
- if not args[0] is String:
- return ""
- return args[0]
-
-
-class CompositeDevice extends Resource:
- signal updated
-
- var _proxy: DBusManager.Proxy
- var dbus_targets: Array[DBusDevice]
- var dbus_path: String
- var logger := Log.get_logger("InputPlumber CompositeDevice", Log.LEVEL.INFO)
-
- func _init(proxy: DBusManager.Proxy) -> void:
- var dbus := load("res://core/global/dbus_system.tres") as DBusManager
- _proxy = proxy
- _proxy.properties_changed.connect(_on_properties_changed)
- for path in self.dbus_devices:
- var device := DBusDevice.new(dbus.create_proxy(INPUT_PLUMBER_BUS, path))
- dbus_targets.append(device)
- dbus_path = _proxy.path
-
- func _on_properties_changed(iface: String, props: Dictionary) -> void:
- updated.emit()
-
- var name: String:
- get:
- var property = _proxy.get_property(IFACE_COMPOSITE_DEVICE, "Name")
- if not property is String:
- return ""
- return property
-
- var profile_name: String:
- get:
- var property = _proxy.get_property(IFACE_COMPOSITE_DEVICE, "ProfileName")
- if not property is String:
- return ""
- return property
-
- var intercept_mode: int:
- set(v):
- #print("Setting mode " + str(v) + " on " + self.dbus_path)
- _proxy.set_property(IFACE_COMPOSITE_DEVICE, "InterceptMode", DBus.uint32(v))
- get:
- var property = _proxy.get_property(IFACE_COMPOSITE_DEVICE, "InterceptMode")
- if not property is int:
- return -1
- return property
-
- var capabilities: PackedStringArray:
- get:
- var property = _proxy.get_property(IFACE_COMPOSITE_DEVICE, "Capabilities")
- if not property is Array:
- return []
- return property
-
- var target_capabilities: PackedStringArray:
- get:
- var property = _proxy.get_property(IFACE_COMPOSITE_DEVICE, "TargetCapabilities")
- if not property is Array:
- return []
- return property
-
- var dbus_devices: PackedStringArray:
- get:
- var property = _proxy.get_property(IFACE_COMPOSITE_DEVICE, "DbusDevices")
- if not property is Array:
- return []
- return property
-
- var source_device_paths: PackedStringArray:
- get:
- var property = _proxy.get_property(IFACE_COMPOSITE_DEVICE, "SourceDevicePaths")
- if not property is Array:
- return []
- return property
-
- var target_devices: PackedStringArray:
- get:
- var property = _proxy.get_property(IFACE_COMPOSITE_DEVICE, "TargetDevices")
- if not property is Array:
- return []
- return property
-
- func set_target_devices(devices: PackedStringArray) -> void:
- _proxy.call_method( IFACE_COMPOSITE_DEVICE, "SetTargetDevices", [devices], "as")
-
- ## Load the given profile on the composite device, optionally specifying a profile
- ## modifier, which is a target device string (e.g. "deck", "ds5-edge", etc.) to
- ## adapt the profile for. This will update the profile with target-specific
- ## defaults, like mapping left/right pads to the DualSense center pad if no
- ## other mappings are defined.
- func target_modify_profile(path: String, profile_modifier: String = "") -> void:
- logger.debug("Loading Profile:", path)
- if path == "" or not path.ends_with(".json") or not FileAccess.file_exists(path):
- logger.error("Profile path:", path," is not a valid profile path.")
- return
- if profile_modifier.is_empty():
- load_profile_path(path)
- return
-
- var profile := InputPlumberProfile.load(path)
-
- var c_pad_cap = "Touchpad:CenterPad:Motion"
- var l_pad_cap = "Touchpad:LeftPad:Motion"
- var r_pad_cap = "Touchpad:RightPad:Motion"
- var mouse_cap = "Mouse:Motion"
-
- if !profile_modifier.is_empty():
- var mapped_capabilities := profile.to_json()
- logger.debug("Mapped Capabilities (before):", mapped_capabilities)
- match profile_modifier:
- "deck":
- logger.debug("Steam Deck Profile")
- if c_pad_cap not in mapped_capabilities:
- logger.debug("Map", c_pad_cap)
- var c_pad_map := InputPlumberMapping.from_source_capability(c_pad_cap)
- var r_pad_event := InputPlumberEvent.from_capability(r_pad_cap)
- c_pad_map.target_events = [r_pad_event]
- profile.mapping.append(c_pad_map)
-
- "ds5", "ds5-edge":
- logger.debug("Dualsense Profile")
- if l_pad_cap not in mapped_capabilities:
- logger.debug("Map", l_pad_cap)
- var l_pad_map := InputPlumberMapping.from_source_capability(l_pad_cap)
- var c_pad_event := InputPlumberEvent.from_capability(c_pad_cap)
- l_pad_map.target_events = [c_pad_event]
- profile.mapping.append(l_pad_map)
- if r_pad_cap not in mapped_capabilities:
- logger.debug("Map", r_pad_cap)
- var r_pad_map := InputPlumberMapping.from_source_capability(r_pad_cap)
- var c_pad_event := InputPlumberEvent.from_capability(c_pad_cap)
- r_pad_map.target_events = [c_pad_event]
- profile.mapping.append(r_pad_map)
-
- _:
- logger.debug("Target device needs no modifications:", profile_modifier)
-
- mapped_capabilities = profile.to_json()
- logger.debug("Mapped Capabilities (after):", mapped_capabilities)
-
- path = path.rstrip(".json") + profile_modifier + ".json"
- if profile.save(path) != OK:
- logger.error("Failed to save", profile.name, "to", path)
- return
- load_profile_path(path)
-
- func load_profile_path(path: String) -> void:
- # Get the absolute path if this is a resource path
- var absolute_path := path
- if path.begins_with("res://") or path.begins_with("user://"):
- absolute_path = ProjectSettings.globalize_path(path)
- _proxy.call_method(IFACE_COMPOSITE_DEVICE, "LoadProfilePath", [absolute_path], "s")
-
- func send_event(action: String, value: Variant) -> void:
- _proxy.call_method( IFACE_COMPOSITE_DEVICE, "SendEvent", [action, value], "sv")
-
- func send_button_chord(actions: PackedStringArray) -> void:
- _proxy.call_method( IFACE_COMPOSITE_DEVICE, "SendButtonChord", [actions], "as")
-
- func set_intercept_activation(triggers: PackedStringArray, target_event: String) -> void:
- _proxy.call_method( IFACE_COMPOSITE_DEVICE, "SetInterceptActivation", [triggers, target_event], "ass")
-
-
-class EventDevice extends Resource:
- signal updated
- var _proxy: DBusManager.Proxy
-
- func _init(proxy: DBusManager.Proxy) -> void:
- _proxy = proxy
- _proxy.properties_changed.connect(_on_properties_changed)
-
- func _on_properties_changed(iface: String, props: Dictionary) -> void:
- updated.emit()
-
- var name: String:
- get:
- var property = _proxy.get_property(IFACE_EVENT_DEVICE, "Name")
- if not property is String:
- return ""
- return property
-
- var device_path: String:
- get:
- var property = _proxy.get_property(IFACE_EVENT_DEVICE, "DevicePath")
- if not property is String:
- return ""
- return property
-
- var phys_path: String:
- get:
- var property = _proxy.get_property(IFACE_EVENT_DEVICE, "PhysPath")
- if not property is String:
- return ""
- return property
-
- var sysfs_path: String:
- get:
- var property = _proxy.get_property(IFACE_EVENT_DEVICE, "SysfsPath")
- if not property is String:
- return ""
- return property
-
- var unique_id: String:
- get:
- var property = _proxy.get_property(IFACE_EVENT_DEVICE, "UniqueId")
- if not property is String:
- return ""
- return property
-
- var handlers: PackedStringArray:
- get:
- var property = _proxy.get_property(IFACE_EVENT_DEVICE, "Handlers")
- if not property is Array:
- return []
- return property
-
-
-class HIDRawDevice extends Resource:
- signal updated
- var _proxy: DBusManager.Proxy
-
- func _init(proxy: DBusManager.Proxy) -> void:
- _proxy = proxy
- _proxy.properties_changed.connect(_on_properties_changed)
-
- func _on_properties_changed(iface: String, props: Dictionary) -> void:
- updated.emit()
-
- var interface_number: int:
- get:
- var property = _proxy.get_property(IFACE_HIDRAW_DEVICE, "InterfaceNumber")
- if not property is int:
- return -1
- return property
-
- var manufacturer: String:
- get:
- var property = _proxy.get_property(IFACE_HIDRAW_DEVICE, "Manufacturer")
- if not property is String:
- return ""
- return property
-
- var path: String:
- get:
- var property = _proxy.get_property(IFACE_HIDRAW_DEVICE, "Path")
- if not property is String:
- return ""
- return property
-
- var product: String:
- get:
- var property = _proxy.get_property(IFACE_HIDRAW_DEVICE, "Product")
- if not property is String:
- return ""
- return property
-
- var product_id: String:
- get:
- var property = _proxy.get_property(IFACE_HIDRAW_DEVICE, "ProductId")
- if not property is String:
- return ""
- return property
-
- var release_number: String:
- get:
- var property = _proxy.get_property(IFACE_HIDRAW_DEVICE, "ReleaseNumber")
- if not property is String:
- return ""
- return property
-
- var serial_number: String:
- get:
- var property = _proxy.get_property(IFACE_HIDRAW_DEVICE, "SerialNumber")
- if not property is String:
- return ""
- return property
-
- var vendor_id: String:
- get:
- var property = _proxy.get_property(IFACE_HIDRAW_DEVICE, "VendorId")
- if not property is String:
- return ""
- return property
-
-
-class IIODevice extends Resource:
- signal updated
- var _proxy: DBusManager.Proxy
-
- func _init(proxy: DBusManager.Proxy) -> void:
- _proxy = proxy
- _proxy.properties_changed.connect(_on_properties_changed)
-
- func _on_properties_changed(iface: String, props: Dictionary) -> void:
- updated.emit()
-
- var id: String:
- get:
- var property = _proxy.get_property(IFACE_IIO_DEVICE, "Id")
- if not property is int:
- return ""
- return property
-
- var name: String:
- get:
- var property = _proxy.get_property(IFACE_IIO_DEVICE, "Name")
- if not property is String:
- return ""
- return property
-
-
-class KeyboardDevice extends Resource:
- signal updated
- var _proxy: DBusManager.Proxy
-
- func _init(proxy: DBusManager.Proxy) -> void:
- _proxy = proxy
- _proxy.properties_changed.connect(_on_properties_changed)
-
- func _on_properties_changed(iface: String, props: Dictionary) -> void:
- updated.emit()
-
- var name: String:
- get:
- var property = _proxy.get_property(IFACE_KEYBOARD_DEVICE, "Name")
- if not property is String:
- return ""
- return property
-
- func send_key(key: String, pressed: bool) -> void:
- _proxy.call_method(IFACE_KEYBOARD_DEVICE, "SendKey", [key, pressed])
-
-
-class MouseDevice extends Resource:
- signal updated
- var _proxy: DBusManager.Proxy
-
- func _init(proxy: DBusManager.Proxy) -> void:
- _proxy = proxy
- _proxy.properties_changed.connect(_on_properties_changed)
-
- func _on_properties_changed(iface: String, props: Dictionary) -> void:
- updated.emit()
-
- var name: String:
- get:
- var property = _proxy.get_property(IFACE_MOUSE_DEVICE, "Name")
- if not property is String:
- return ""
- return property
-
-
-class GamepadDevice extends Resource:
- signal updated
- var _proxy: DBusManager.Proxy
-
- func _init(proxy: DBusManager.Proxy) -> void:
- _proxy = proxy
- _proxy.properties_changed.connect(_on_properties_changed)
-
- func _on_properties_changed(iface: String, props: Dictionary) -> void:
- updated.emit()
-
- var name: String:
- get:
- var property = _proxy.get_property(IFACE_GAMEPAD_DEVICE, "Name")
- if not property is String:
- return ""
- return property
-
-
-class DBusDevice extends Resource:
- signal input_event(type_code: String, value: float)
- var _proxy: DBusManager.Proxy
-
- func _init(proxy: DBusManager.Proxy) -> void:
- #print("Creating DBusDevice!")
- _proxy = proxy
- _proxy.message_received.connect(_on_message_received)
- _proxy.thread.exec(_proxy.watch.bind(IFACE_DBUS_DEVICE, "InputEvent"))
-
- func _on_message_received(msg: DBusMessage) -> void:
- if not msg:
- return
- if msg.get_member() != "InputEvent":
- return
- var args := msg.get_args()
- if args.size() < 2:
- return
- #print("Got InputEvent " + str(args))
- #print(str(self.get_instance_id()))
- #print(str(self.get_rid()))
- input_event.emit(args[0], args[1])
- var name: String:
- get:
- var property = _proxy.get_property(IFACE_DBUS_DEVICE, "Name")
- if not property is String:
- return ""
- return property
+ var profile := InputPlumberProfile.load(path)
+
+ var c_pad_cap = "Touchpad:CenterPad:Motion"
+ var l_pad_cap = "Touchpad:LeftPad:Motion"
+ var r_pad_cap = "Touchpad:RightPad:Motion"
+ var mouse_cap = "Mouse:Motion"
+
+ if !profile_modifier.is_empty():
+ var mapped_capabilities := profile.to_json()
+ logger.debug("Mapped Capabilities (before):", mapped_capabilities)
+ match profile_modifier:
+ "deck":
+ logger.debug("Steam Deck Profile")
+ if c_pad_cap not in mapped_capabilities:
+ logger.debug("Map", c_pad_cap)
+ var c_pad_map := InputPlumberMapping.from_source_capability(c_pad_cap)
+ var r_pad_event := InputPlumberEvent.from_capability(r_pad_cap)
+ c_pad_map.target_events = [r_pad_event]
+ profile.mapping.append(c_pad_map)
+
+ "ds5", "ds5-edge":
+ logger.debug("Dualsense Profile")
+ if l_pad_cap not in mapped_capabilities:
+ logger.debug("Map", l_pad_cap)
+ var l_pad_map := InputPlumberMapping.from_source_capability(l_pad_cap)
+ var c_pad_event := InputPlumberEvent.from_capability(c_pad_cap)
+ l_pad_map.target_events = [c_pad_event]
+ profile.mapping.append(l_pad_map)
+ if r_pad_cap not in mapped_capabilities:
+ logger.debug("Map", r_pad_cap)
+ var r_pad_map := InputPlumberMapping.from_source_capability(r_pad_cap)
+ var c_pad_event := InputPlumberEvent.from_capability(c_pad_cap)
+ r_pad_map.target_events = [c_pad_event]
+ profile.mapping.append(r_pad_map)
+
+ _:
+ logger.debug("Target device needs no modifications:", profile_modifier)
+
+ mapped_capabilities = profile.to_json()
+ logger.debug("Mapped Capabilities (after):", mapped_capabilities)
+
+ path = path.rstrip(".json") + profile_modifier + ".json"
+ if profile.save(path) != OK:
+ logger.error("Failed to save", profile.name, "to", path)
+ return
+ device.load_profile_path(path)
diff --git a/core/systems/input/input_plumber.tres b/core/systems/input/input_plumber.tres
index 60a89d180..64f50b4ab 100644
--- a/core/systems/input/input_plumber.tres
+++ b/core/systems/input/input_plumber.tres
@@ -1,6 +1,3 @@
-[gd_resource type="Resource" script_class="InputPlumber" load_steps=2 format=3 uid="uid://ct1hxnffwtqvl"]
-
-[ext_resource type="Script" path="res://core/systems/input/input_plumber.gd" id="1_0njvc"]
+[gd_resource type="InputPlumberInstance" format=3 uid="uid://e2bevy4j4rx2"]
[resource]
-script = ExtResource("1_0njvc")
diff --git a/core/systems/input/input_plumber_profile_test.gd b/core/systems/input/input_plumber_profile_test.gd
index 0d523d670..ed9c33000 100644
--- a/core/systems/input/input_plumber_profile_test.gd
+++ b/core/systems/input/input_plumber_profile_test.gd
@@ -3,7 +3,7 @@ extends GutTest
func test_load() -> void:
var profile := InputPlumberProfile.load("res://assets/gamepad/profiles/default.json")
- assert_eq(profile.name, "Default")
+ assert_eq(profile.name, "OpenGamepadUI Default")
func test_save() -> void:
diff --git a/core/systems/input/input_plumber_test.gd b/core/systems/input/input_plumber_test.gd
index 336420591..238dd6b09 100644
--- a/core/systems/input/input_plumber_test.gd
+++ b/core/systems/input/input_plumber_test.gd
@@ -1,45 +1,51 @@
-extends Node2D
-
-var input_plumber := load("res://core/systems/input/input_plumber.tres") as InputPlumber
-
-
-# Called when the node enters the scene tree for the first time.
-func _ready():
- for compo in input_plumber.composite_devices:
- print(compo.dbus_targets)
- for dt in compo.dbus_targets:
- dt.input_event.connect(_on_input_event)
-
- input_plumber.composite_device_added.connect(_on_dev_add)
- input_plumber.composite_device_removed.connect(_on_dev_rm)
- input_plumber.set_intercept_mode(InputPlumber.INTERCEPT_MODE.ALL)
- get_tree().root.mode = Window.MODE_MINIMIZED
-
-
-# Called every frame. 'delta' is the elapsed time since the previous frame.
-func _process(delta):
- pass
-
-
-func _on_input_event(event: String, value: float) -> void:
- print("Got input event " + event + " with value " + str(value))
- if event == "ui_guide":
- var pressed = value == 1.0
- for device in input_plumber.composite_devices:
- device.intercept_mode = 0
- device.send_event("Gamepad:Button:Guide", pressed)
- device.intercept_mode = InputPlumber.INTERCEPT_MODE.ALL as int
-
- if event == "ui_accept":
- for device in input_plumber.composite_devices:
- var intercept_mode = device.intercept_mode
- device.intercept_mode = 0
- device.send_button_chord(["Gamepad:Button:Guide", "Gamepad:Button:South"])
- device.intercept_mode = InputPlumber.INTERCEPT_MODE.ALL as int
-
-
-func _on_dev_add() -> void:
- print("Newbie doobie")
-
-func _on_dev_rm() -> void:
- print("bubye")
+extends GutTest
+
+
+# Configure the given composite device to set intercept mode and print input
+# events
+func _watch_device(device: CompositeDevice) -> void:
+ gut.p(" Found device " + str(device) + " at " + device.dbus_path)
+ device.intercept_mode = InputPlumberInstance.INTERCEPT_MODE_ALL
+ assert_eq(device.intercept_mode, InputPlumberInstance.INTERCEPT_MODE_ALL)
+ var dbus_devices := device.dbus_devices
+ if dbus_devices.is_empty():
+ gut.p(" No dbus devices found for device")
+ return
+ var dbus_device := dbus_devices[0]
+ gut.p(" Found DBus device: " + str(dbus_device) + " at " + dbus_device.dbus_path)
+ var on_input_event := func(event: String, value: float):
+ gut.p("[DBus Event] " + event + ": " + str(value))
+ dbus_device.input_event.connect(on_input_event)
+
+
+func test_inputplumber() -> void:
+ var inputplumber := InputPlumber.new()
+ inputplumber.instance = load("res://core/systems/input/input_plumber.tres")
+ add_child_autoqfree(inputplumber)
+
+ if not inputplumber.instance.is_running():
+ pass_test("InputPlumber is not running. Skipping tests.")
+ return
+
+ # Set intercept mode
+ gut.p("Setting intercept mode to ALL")
+ inputplumber.instance.intercept_mode = InputPlumberInstance.INTERCEPT_MODE_ALL
+ assert_eq(inputplumber.instance.intercept_mode, InputPlumberInstance.INTERCEPT_MODE_ALL)
+
+ # Find all composite devices
+ gut.p("Discovering all composite devices")
+ var devices := inputplumber.instance.get_composite_devices()
+ for device in devices:
+ _watch_device(device)
+
+ # Add listeners for any new devices
+ inputplumber.instance.composite_device_added.connect(_watch_device)
+
+ # Add listeners when devices are removed
+ var on_device_removed := func(dbus_path: String):
+ gut.p("Device was removed: " + dbus_path)
+ inputplumber.instance.composite_device_removed.connect(on_device_removed)
+
+ await wait_seconds(30, "Waiting 30s... Press buttons to test")
+
+ inputplumber.instance.intercept_mode = InputPlumberInstance.INTERCEPT_MODE_NONE
diff --git a/core/systems/input/input_plumber_test.tscn b/core/systems/input/input_plumber_test.tscn
deleted file mode 100644
index 659851bfd..000000000
--- a/core/systems/input/input_plumber_test.tscn
+++ /dev/null
@@ -1,6 +0,0 @@
-[gd_scene load_steps=2 format=3 uid="uid://djylrf6b7nxyx"]
-
-[ext_resource type="Script" path="res://core/systems/input/input_plumber_test.gd" id="1_x2aky"]
-
-[node name="InputPlumberTest" type="Node2D"]
-script = ExtResource("1_x2aky")
diff --git a/core/systems/input/input_plumber_test_old.tscn b/core/systems/input/input_plumber_test_old.tscn
new file mode 100644
index 000000000..88349a4ef
--- /dev/null
+++ b/core/systems/input/input_plumber_test_old.tscn
@@ -0,0 +1,52 @@
+[gd_scene load_steps=2 format=3 uid="uid://b401m3qcqa8yd"]
+
+[sub_resource type="GDScript" id="GDScript_k2tux"]
+script/source = "extends Node2D
+
+var input_plumber := load(\"res://core/systems/input/input_plumber.tres\") as InputPlumber
+
+
+# Called when the node enters the scene tree for the first time.
+func _ready():
+ for compo in input_plumber.composite_devices:
+ print(compo.dbus_targets)
+ for dt in compo.dbus_targets:
+ dt.input_event.connect(_on_input_event)
+
+ input_plumber.composite_device_added.connect(_on_dev_add)
+ input_plumber.composite_device_removed.connect(_on_dev_rm)
+ input_plumber.set_intercept_mode(InputPlumber.INTERCEPT_MODE.ALL)
+ get_tree().root.mode = Window.MODE_MINIMIZED
+
+
+# Called every frame. 'delta' is the elapsed time since the previous frame.
+func _process(delta):
+ pass
+
+
+func _on_input_event(event: String, value: float) -> void:
+ print(\"Got input event \" + event + \" with value \" + str(value))
+ if event == \"ui_guide\":
+ var pressed = value == 1.0
+ for device in input_plumber.composite_devices:
+ device.intercept_mode = 0
+ device.send_event(\"Gamepad:Button:Guide\", pressed)
+ device.intercept_mode = InputPlumber.INTERCEPT_MODE.ALL as int
+
+ if event == \"ui_accept\":
+ for device in input_plumber.composite_devices:
+ var intercept_mode = device.intercept_mode
+ device.intercept_mode = 0
+ device.send_button_chord([\"Gamepad:Button:Guide\", \"Gamepad:Button:South\"])
+ device.intercept_mode = InputPlumber.INTERCEPT_MODE.ALL as int
+
+
+func _on_dev_add() -> void:
+ print(\"Newbie doobie\")
+
+func _on_dev_rm() -> void:
+ print(\"bubye\")
+"
+
+[node name="InputPlumberTest" type="Node2D"]
+script = SubResource("GDScript_k2tux")
diff --git a/core/systems/input/keyboard_opener.gd b/core/systems/input/keyboard_opener.gd
new file mode 100644
index 000000000..372a5e6e2
--- /dev/null
+++ b/core/systems/input/keyboard_opener.gd
@@ -0,0 +1,106 @@
+@tool
+@icon("res://assets/ui/icons/keyboard-rounded.svg")
+extends Node
+class_name KeyboardOpener
+
+## Node that can open the on-screen keyboard in response to a signal firing
+
+## Reference to the on-screen keyboard instance to open when the OSK action is
+## pressed.
+var osk := load("res://core/global/keyboard_instance.tres") as KeyboardInstance
+## The Global State Machine
+var state_machine := load("res://assets/state/state_machines/global_state_machine.tres") as StateMachine
+## Popup state machine to show the OSK popup.
+var popup_state_machine := (
+ preload("res://assets/state/state_machines/popup_state_machine.tres") as StateMachine
+)
+var in_game_menu_state := preload("res://assets/state/states/in_game_menu.tres") as State
+var main_menu_state := preload("res://assets/state/states/main_menu.tres") as State
+var quick_bar_state := preload("res://assets/state/states/quick_bar_menu.tres") as State
+var osk_state := preload("res://assets/state/states/osk.tres") as State
+var popup_state := preload("res://assets/state/states/popup.tres") as State
+
+## Signal on our parent node to connect to
+var on_signal: String
+## Target control node to send keyboard input to.
+var target: Control
+
+## The type of keyboard behavior. An "X11" keyboard will send keyboard events
+## to a running game. A "Godot" keyboard will send text input to a control node.
+@export var type: KeyboardContext.TYPE = KeyboardContext.TYPE.X11:
+ set(v):
+ type = v
+ notify_property_list_changed()
+
+
+func _init() -> void:
+ ready.connect(_on_ready)
+
+
+func _on_ready() -> void:
+ notify_property_list_changed()
+ # Do nothing if running in the editor
+ if Engine.is_editor_hint():
+ return
+ if on_signal != "":
+ get_parent().connect(on_signal, _on_signal)
+
+
+## Fires when the given signal is emitted.
+func _on_signal(_arg1: Variant = null, _arg2: Variant = null, _arg3: Variant = null, _arg4: Variant = null):
+ var state := popup_state_machine.current_state()
+ if state == osk_state:
+ osk.close()
+ popup_state_machine.pop_state()
+ return
+
+ if state in [main_menu_state, in_game_menu_state, quick_bar_state]:
+ popup_state_machine.replace_state(osk_state)
+ else:
+ popup_state_machine.push_state(osk_state)
+ state_machine.push_state(popup_state)
+
+ var context := KeyboardContext.new()
+ context.type = type
+ if type == KeyboardContext.TYPE.GODOT:
+ context.target = target
+ osk.open(context)
+
+
+# Customize editor properties that we expose. Here we dynamically look up
+# the parent node's signals so we can display them in a list.
+func _get_property_list():
+ # By default, `on_signal` is not visible in the editor.
+ var property_usage := PROPERTY_USAGE_NO_EDITOR
+
+ var parent_signals := []
+ if get_parent() != null:
+ property_usage = PROPERTY_USAGE_DEFAULT
+ for sig in get_parent().get_signal_list():
+ parent_signals.push_back(sig["name"])
+
+ # Build the exported node properties
+ var properties := []
+ properties.append(
+ {
+ "name": "on_signal",
+ "type": TYPE_STRING,
+ "usage": property_usage, # See above assignment.
+ "hint": PROPERTY_HINT_ENUM,
+ "hint_string": ",".join(parent_signals)
+ }
+ )
+
+ # Only show the control node target property if "Godot" type is selected
+ if self.type == KeyboardContext.TYPE.GODOT:
+ properties.append(
+ {
+ "name": "target",
+ "type": TYPE_OBJECT,
+ "usage": property_usage,
+ "hint": PROPERTY_HINT_NODE_TYPE,
+ "hint_string": "Control",
+ }
+ )
+
+ return properties
diff --git a/core/systems/input/overlay_mode_input_manager.gd b/core/systems/input/overlay_mode_input_manager.gd
index f060c8fe3..13594c4fd 100644
--- a/core/systems/input/overlay_mode_input_manager.gd
+++ b/core/systems/input/overlay_mode_input_manager.gd
@@ -1,4 +1,4 @@
-@icon("res://assets/icons/navigation.svg")
+@icon("res://assets/editor-icons/material-symbols-joystick.svg")
extends Node
class_name OverlayInputManager
@@ -14,7 +14,7 @@ class_name OverlayInputManager
## The audio manager to use to adjust the audio when audio input events happen.
var audio_manager := load("res://core/global/audio_manager.tres") as AudioManager
## InputPlumber receives and sends DBus input events.
-var input_plumber := load("res://core/systems/input/input_plumber.tres") as InputPlumber
+var input_plumber := load("res://core/systems/input/input_plumber.tres") as InputPlumberInstance
## LaunchManager provides context on the currently running app so we can switch profiles
var launch_manager := load("res://core/global/launch_manager.tres") as LaunchManager
## The Global State Machine
@@ -39,8 +39,12 @@ var logger := Log.get_logger("InputManager(Overlay Mode)", Log.LEVEL.INFO)
func _ready() -> void:
add_to_group("InputManager")
input_plumber.composite_device_added.connect(_watch_dbus_device)
+ input_plumber.started.connect(_init_inputplumber)
+ _init_inputplumber()
- for device in input_plumber.composite_devices:
+
+func _init_inputplumber() -> void:
+ for device in input_plumber.get_composite_devices():
_watch_dbus_device(device)
@@ -71,6 +75,13 @@ func _send_input(dbus_path: String, action: String, pressed: bool, strength: flo
## https://docs.godotengine.org/en/latest/tutorials/inputs/inputevent.html#how-does-it-work
func _input(event: InputEvent) -> void:
logger.debug("Got input event to handle: " + str(event))
+ # Don't process Godot events if InputPlumber is running
+ if input_plumber.is_running() and not InputManager.is_inputplumber_event(event):
+ if event is InputEventJoypadButton or event is InputEventJoypadMotion:
+ logger.debug("Skipping Godot event while InputPlumber is running:", event)
+ get_viewport().set_input_as_handled()
+ return
+
var dbus_path := event.get_meta("dbus_path", "") as String
# Consume double inputs for controllers with DPads that have TRIGGER_HAPPY events
@@ -295,7 +306,7 @@ func _send_steam_chord(event: InputEvent) -> bool:
# Steam On-Screen Keyboard
elif event.is_action_pressed("ogui_osk_ov"):
logger.debug("Trigger Steam OSK")
- chord.append("Gamepad:Button:East")
+ chord.append("Gamepad:Button:North")
# Steam Video-Capture
elif event.is_action_pressed("ogui_vc_ov"):
@@ -320,8 +331,8 @@ func _return_chord(actions: PackedStringArray) -> void:
# TODO: Figure out a way to get the device who sent the event through
# Input.parse_input_event so we don't do this terrible loop. This is awful.
logger.debug("Return events to InputPlumber: " + str(actions))
- for device in input_plumber.composite_devices:
- device.intercept_mode = InputPlumber.INTERCEPT_MODE.PASS
+ for device in input_plumber.get_composite_devices():
+ device.intercept_mode = InputPlumberInstance.INTERCEPT_MODE_PASS
device.send_button_chord(actions)
@@ -347,9 +358,11 @@ func _audio_input(event: InputEvent) -> void:
return
-func _watch_dbus_device(device: InputPlumber.CompositeDevice) -> void:
- for target in device.dbus_targets:
- logger.debug("Adding watch for " + device.name + " " + target.name)
+func _watch_dbus_device(device: CompositeDevice) -> void:
+ for target in device.dbus_devices:
+ if target.input_event.is_connected(_on_dbus_input_event.bind(device.dbus_path)):
+ continue
+ logger.debug("Adding watch for " + device.name + " " + target.dbus_path)
logger.debug(str(target.get_instance_id()))
logger.debug(str(target.get_rid()))
target.input_event.connect(_on_dbus_input_event.bind(device.dbus_path))
@@ -357,8 +370,9 @@ func _watch_dbus_device(device: InputPlumber.CompositeDevice) -> void:
func _on_dbus_input_event(event: String, value: float, dbus_path: String) -> void:
var pressed := value == 1.0
- logger.debug("Handling dbus input event: " + event + " pressed: " + str(pressed))
- var action = event
+ logger.debug("Handling dbus input event from" + dbus_path + ": " + event + " pressed: " + str(pressed))
+
+ var action := event
match event:
"ui_accept":
action = "ogui_south_ov"
diff --git a/core/systems/input/overlay_mode_input_manager.tscn b/core/systems/input/overlay_mode_input_manager.tscn
index 61b5aed19..e3973446b 100644
--- a/core/systems/input/overlay_mode_input_manager.tscn
+++ b/core/systems/input/overlay_mode_input_manager.tscn
@@ -1,6 +1,10 @@
-[gd_scene load_steps=2 format=3 uid="uid://bxnb8t7i08vma"]
+[gd_scene load_steps=3 format=3 uid="uid://bxnb8t7i08vma"]
[ext_resource type="Script" path="res://core/systems/input/overlay_mode_input_manager.gd" id="1_fvwoc"]
+[ext_resource type="Script" path="res://core/systems/input/input_plumber.gd" id="2_vf8uv"]
[node name="InputManager" type="Node"]
script = ExtResource("1_fvwoc")
+
+[node name="InputPlumber" type="Node" parent="."]
+script = ExtResource("2_vf8uv")
diff --git a/core/systems/launcher/app_lifecycle_hook.gd b/core/systems/launcher/app_lifecycle_hook.gd
new file mode 100644
index 000000000..3ea085a49
--- /dev/null
+++ b/core/systems/launcher/app_lifecycle_hook.gd
@@ -0,0 +1,39 @@
+extends RefCounted
+class_name AppLifecycleHook
+
+## Base class for executing callbacks at certain points of an app's lifecycle.
+##
+## This class provides an interface for executing arbitrary callbacks at certain
+## points of an application's lifecycle. This can allow [Library] implementations
+## the ability to execute actions when apps are about to start, have started,
+## or have exited.
+
+## The type of hook determines where in the application's lifecycle this hook
+## should be executed.
+enum TYPE {
+ ## Executes right before an app is launched
+ PRE_LAUNCH,
+ ## Executes right after an app is launched
+ LAUNCH,
+ ## Executed after app exit
+ EXIT,
+}
+
+var _hook_type: TYPE
+
+
+func _init(hook_type: TYPE) -> void:
+ _hook_type = hook_type
+
+
+## Executes whenever an app from this library reaches the stage in its lifecycle
+## designated by the hook type. E.g. a `PRE_LAUNCH` hook will have this method
+## called whenever an app is about to launch.
+func execute(item: LibraryLaunchItem) -> void:
+ pass
+
+
+## Returns the hook type, which designates where in the application's lifecycle
+## the hook should be executed.
+func get_type() -> TYPE:
+ return _hook_type
diff --git a/core/systems/launcher/interactive_process.gd b/core/systems/launcher/interactive_process.gd
index 778c0f30b..18a8baf05 100644
--- a/core/systems/launcher/interactive_process.gd
+++ b/core/systems/launcher/interactive_process.gd
@@ -1,75 +1,100 @@
+@icon("res://assets/editor-icons/devicon-plain--bash.svg")
extends Resource
class_name InteractiveProcess
+# DEPRECATED: Use the [Pty] node instead
+
## Class for starting an interacting with a process through a psuedo terminal
##
## Starts an interactive session
-var pty: PTY
+var pty: Pty
var cmd: String
var args: PackedStringArray = []
var pid: int
+var platform := load("res://core/global/platform.tres") as Platform
+var registry := load("res://core/systems/resource/resource_registry.tres") as ResourceRegistry
+var lines_mutex := Mutex.new()
+var lines_buffer := PackedStringArray()
var logger := Log.get_logger("InteractiveProcess", Log.LEVEL.INFO)
func _init(command: String, cmd_args: PackedStringArray = []) -> void:
- cmd = command
- args = cmd_args
+ # Check to see if this OS requires running the command through a binary
+ # compatibility tool.
+ if platform and platform.os:
+ var compatibility_cmd := platform.os.get_binary_compatibility_cmd(command, cmd_args)
+ if not compatibility_cmd.is_empty():
+ logger.debug("Using binary compatibility tool")
+ self.cmd = compatibility_cmd.pop_front()
+ self.args = PackedStringArray(compatibility_cmd)
+ return
+
+ self.cmd = command
+ self.args = cmd_args
## Start the interactive process
func start() -> int:
- pty = PTY.new()
- if pty.open() != OK:
- pty = null
- return ERR_CANT_CREATE
+ # Create a new PTY instance and start the process
+ self.pty = Pty.new()
+ self.pty.exec(self.cmd, self.args)
+ self.pty.line_written.connect(_on_line_written)
+
+ # The new [Pty] is a node, so it must be added to the scene tree
+ self.registry.add_child(self.pty)
+
+ return OK
- pid = pty.create_process(cmd, args)
- if pid < 0:
- pty = null
- return ERR_CANT_FORK
- return OK
+func _on_line_written(line: String):
+ logger.trace("PTY:", line)
+ self.lines_mutex.lock()
+ self.lines_buffer.append(line)
+ self.lines_mutex.unlock()
## Send the given input to the running process
func send(input: String) -> void:
if not pty:
return
- logger.debug("Writing input: " + input)
+ #if pty.write_line(input) < 0:
if pty.write(input.to_utf8_buffer()) < 0:
logger.debug("Unable to write to PTY")
## Read from the stdout of the running process
-func read(chunk_size: int = 1024) -> String:
+func read(_chunk_size: int = 1024) -> String:
if not pty:
logger.debug("Unable to read from closed PTY")
return ""
# Keep reading from the process until the buffer is empty
- var output := ""
- var buffer := pty.read(chunk_size)
- while buffer.size() != 0:
- output += buffer.get_string_from_utf8()
- buffer = pty.read(chunk_size)
+ self.lines_mutex.lock()
+ var output := "\n".join(self.lines_buffer)
+ self.lines_buffer = PackedStringArray()
+ self.lines_mutex.unlock()
return output
## Stop the given process
func stop() -> void:
- logger.debug("Stopping pid: " + str(pid))
- OS.kill(pid)
- pty = null
+ logger.debug("Stopping pid: " + str(self.pid))
+ self.pty.kill()
+ self.registry.remove_child(self.pty)
+ self.pty = null
## Returns whether or not the interactive process is still running
func is_running() -> bool:
- return OS.is_process_running(pid)
+ if not pty:
+ return false
+ return pty.running
-func output_to_log_file(log_file: FileAccess, chunk_size: int = 1024) -> int:
+# TODO: Fixme
+func output_to_log_file(log_file: FileAccess, _chunk_size: int = 1024) -> int:
if not log_file:
logger.warn("Unable to log output. Log file has not been opened.")
return ERR_FILE_CANT_OPEN
@@ -79,10 +104,6 @@ func output_to_log_file(log_file: FileAccess, chunk_size: int = 1024) -> int:
return ERR_DOES_NOT_EXIST
# Keep reading from the process until the buffer is empty
- var buffer := pty.read(chunk_size)
- while buffer.size() != 0:
- log_file.store_buffer(buffer)
- buffer = pty.read(chunk_size)
log_file.flush()
return OK
diff --git a/core/systems/launcher/launch_manager.gd b/core/systems/launcher/launch_manager.gd
deleted file mode 100644
index b7e36fa9e..000000000
--- a/core/systems/launcher/launch_manager.gd
+++ /dev/null
@@ -1,15 +0,0 @@
-@icon("res://assets/editor-icons/ph-rocket-launch-fill.svg")
-extends Node
-
-@export var launch_manager := preload("res://core/global/launch_manager.tres") as LaunchManager
-
-@onready var overlay_display = OS.get_environment("DISPLAY")
-
-
-func _init() -> void:
- launch_manager._load_persist_data()
-
-
-# TODO: Replace this with dbus signaling. This is super shitty.
-func _process(delta) -> void:
- launch_manager.check_running()
diff --git a/core/systems/launcher/launch_manager.tscn b/core/systems/launcher/launch_manager.tscn
deleted file mode 100644
index 134a43c7a..000000000
--- a/core/systems/launcher/launch_manager.tscn
+++ /dev/null
@@ -1,6 +0,0 @@
-[gd_scene load_steps=2 format=3 uid="uid://cbboox5bujlx1"]
-
-[ext_resource type="Script" path="res://core/systems/launcher/launch_manager.gd" id="1_h73xp"]
-
-[node name="LaunchManager" type="Node"]
-script = ExtResource("1_h73xp")
diff --git a/core/systems/launcher/launcher.gd b/core/systems/launcher/launcher.gd
index 38971ffa5..11271ebe9 100644
--- a/core/systems/launcher/launcher.gd
+++ b/core/systems/launcher/launcher.gd
@@ -1,54 +1,20 @@
-@icon("res://assets/icons/loader.svg")
+@icon("res://assets/editor-icons/ph-rocket-launch-fill.svg")
extends Node
class_name Launcher
-const LaunchManager := preload("res://core/global/launch_manager.tres")
-var LibraryManager := preload("res://core/global/library_manager.tres")
-const NotificationManager := preload("res://core/global/notification_manager.tres")
+@export var launch_manager := preload("res://core/global/launch_manager.tres") as LaunchManager
-var state_machine := (
- preload("res://assets/state/state_machines/global_state_machine.tres") as StateMachine
-)
-var in_game_state := preload("res://assets/state/states/in_game.tres") as State
-var installing := {}
+@onready var overlay_display = OS.get_environment("DISPLAY")
-# The library item to launch
-@export var launch_item: LibraryLaunchItem
-# Signal on our parent to connect to
-@export var signal_name: String = "button_up"
-@onready var parent: Node = get_parent()
+func _init() -> void:
+ launch_manager._load_persist_data()
func _ready() -> void:
- parent.connect(signal_name, _on_launch)
-
-
-func _on_launch():
- # Resume if the game is running already
- if LaunchManager.is_running(launch_item.name):
- state_machine.set_state([in_game_state])
- return
-
- # If the app isn't installed, install it.
- if not launch_item.installed:
- if launch_item.name in installing and installing[launch_item.name]:
- return
- var notify := Notification.new("Installing " + launch_item.name)
- NotificationManager.show(notify)
- LibraryManager.install(launch_item)
- LibraryManager.item_installed.connect(_on_installed)
- installing[launch_item.name] = true
- return
-
- # Launch the game using launch manager
- LaunchManager.launch(launch_item)
-
-
-func _on_installed(item: LibraryLaunchItem, success: bool) -> void:
- var verb := "failed"
- if success:
- verb = "completed"
- var notify := Notification.new("Install " + verb + " for " + item.name)
- NotificationManager.show(notify)
- installing[launch_item.name] = false
+ var timer := Timer.new()
+ timer.autostart = true
+ timer.one_shot = false
+ timer.wait_time = 1
+ timer.timeout.connect(launch_manager.check_running)
+ add_child(timer)
diff --git a/core/systems/launcher/launcher.tscn b/core/systems/launcher/launcher.tscn
index 2cac63ce8..e69de29bb 100644
--- a/core/systems/launcher/launcher.tscn
+++ b/core/systems/launcher/launcher.tscn
@@ -1,6 +0,0 @@
-[gd_scene load_steps=2 format=3 uid="uid://bargrxdqbu3gl"]
-
-[ext_resource type="Script" path="res://core/systems/launcher/launcher.gd" id="1_cd3hc"]
-
-[node name="Launcher" type="Node"]
-script = ExtResource("1_cd3hc")
diff --git a/core/systems/launcher/reaper.gd b/core/systems/launcher/reaper.gd
index fb05d0d53..597a92b2e 100644
--- a/core/systems/launcher/reaper.gd
+++ b/core/systems/launcher/reaper.gd
@@ -11,9 +11,54 @@ enum SIG {
## Spawn a process with PR_SET_CHILD_SUBREAPER set so child processes will
## reparent themselves to OpenGamepadUI. Returns the PID of the spawned process.
-static func create_process(cmd: String, args: PackedStringArray) -> int:
- #return OS.create_process(cmd, args)
- return LinuxThread.subreaper_create_process(cmd, args)
+static func create_process(cmd: String, args: PackedStringArray, app_id: int = -1) -> int:
+ var logger := Log.get_logger("Reaper")
+ logger.debug("Got command to execute:", cmd, args)
+ var reaper_cmd := get_reaper_command()
+ logger.debug("Got reaper command:", reaper_cmd)
+ if reaper_cmd.is_empty():
+ logger.warn("'reaper' binary not found, launching without reaper")
+ logger.info("Executing OS command:", cmd, args)
+ return OS.create_process(cmd, args)
+
+ # Build the arguments for reaper.
+ var reaper_args := PackedStringArray()
+ if app_id >= 0:
+ reaper_args.append("SteamLaunch")
+ reaper_args.append("AppId={0}".format([app_id]))
+ reaper_args.append("--")
+ reaper_args.append(cmd)
+ reaper_args.append_array(args)
+ logger.info("Executing REAPER command:", reaper_cmd, reaper_args)
+ return OS.create_process(reaper_cmd, reaper_args)
+
+## Discovers the 'reaper' binary to execute commands with PR_SET_CHILD_SUBREAPER.
+static func get_reaper_command() -> String:
+ var logger := Log.get_logger("Reaper")
+ var home := OS.get_environment("HOME")
+ var search_paths := [
+ "./extensions/target/release",
+ "/usr/share/opengamepadui",
+ "{0}/.local/share/opengamepadui".format([home]),
+ "/run/current-system/sw/share/opengamepadui"
+ ]
+
+ for path in search_paths:
+ logger.debug("Checking for reaper in path:", path)
+ # Check if the path exists, its the responsible thing to do.
+ if not DirAccess.dir_exists_absolute(path):
+ logger.debug("Path does not exists!")
+ continue
+ logger.debug("Path does exists!")
+ var directory := DirAccess.open(path)
+ if not directory:
+ logger.warn("Failed to open path:", path)
+ continue
+ if directory.file_exists("reaper"):
+ var reaper_path := "{0}/reaper".format([path])
+ return reaper_path
+
+ return ""
# Kills the given PID and all its descendants
@@ -26,6 +71,11 @@ static func reap(pid: int, sig: SIG = SIG.TERM) -> void:
pids.reverse()
var logger := Log.get_logger("Reaper")
for p in pids:
+ # Don't kill the actual reaper PID
+ if p == pid:
+ logger.debug("Skipping killing reaper pid:", pid)
+ continue
+
# Kill PGID
var cmd := "kill"
var args := [sig_arg, "--", "-{0}".format([p])]
@@ -72,9 +122,7 @@ static func get_pid_group(pid: int) -> int:
static func get_pid_state(pid: int) -> String:
var status: Dictionary = get_pid_status(pid)
if not "State" in status:
- var logger := Log.get_logger("Reaper")
- logger.warn("Unable to check state of PID " + str(pid))
- return ""
+ return "D (dead)"
return status["State"]
@@ -104,7 +152,7 @@ static func get_pid_status(pid: int) -> Dictionary:
var status_file: FileAccess = FileAccess.open(status_path, FileAccess.READ)
if not status_file:
var logger := Log.get_logger("Reaper")
- logger.error("Unable to check status for pid: {0}".format([pid]))
+ logger.debug("Unable to check status for pid: {0}".format([pid]))
return {}
# Parse the status output
@@ -172,7 +220,7 @@ static func is_gamescope_pid(pid: int) -> bool:
var status: Dictionary = get_pid_status(pid)
if not "Name" in status:
var logger := Log.get_logger("Reaper")
- logger.error("No name was found in pid status!")
+ logger.debug("No name was found in pid status!")
return false
if status["Name"] == "gamescope-wl":
return true
diff --git a/core/systems/launcher/running_app.gd b/core/systems/launcher/running_app.gd
index 145feffff..974a1ea14 100644
--- a/core/systems/launcher/running_app.gd
+++ b/core/systems/launcher/running_app.gd
@@ -5,13 +5,15 @@ class_name RunningApp
##
## RunningApp contains details and methods around running applications
-const Gamescope := preload("res://core/global/gamescope.tres")
+var gamescope := load("res://core/systems/gamescope/gamescope.tres") as GamescopeInstance
## Emitted when all child processes of the app are no longer running
signal app_killed
## Emitted when the given app is gracefully stopped
signal app_stopped
+## Emitted when the app type is detected
+signal app_type_detected
## Emitted when the window id of the given app has changed
signal window_id_changed
## Emitted whenever the windows change for the app
@@ -36,6 +38,12 @@ enum STATE {
STOPPED, ## App is no longer running
}
+enum APP_TYPE {
+ UNKNOWN,
+ X11,
+ WAYLAND,
+}
+
## The LibraryLaunchItem associated with the running application
var launch_item: LibraryLaunchItem
## The PID of the launched application
@@ -79,6 +87,8 @@ var app_id: int:
set(v):
app_id = v
app_id_changed.emit()
+## The type of app
+var app_type: APP_TYPE = APP_TYPE.UNKNOWN
## Whether or not the app is currently focused
var focused: bool = false:
set(v):
@@ -111,10 +121,105 @@ func _init(item: LibraryLaunchItem, process_id: int, dsp: String) -> void:
display = dsp
+## Run the given command and return it as a [RunningApp]
+static func spawn(app: LibraryLaunchItem, env: Dictionary, cmd: String, args: PackedStringArray) -> RunningApp:
+ # Generate an app id for the running application based on its name
+ var app_id := app.get_app_id()
+
+ # Launch the application process
+ var pid := Reaper.create_process(cmd, args, app_id)
+ var display := env["DISPLAY"] as String
+ var command := PackedStringArray([cmd])
+ command.append_array(args)
+
+ # Create a running app instance
+ var running_app := RunningApp.new(app, pid, display)
+ running_app.command = command
+ running_app.environment = env
+ running_app.app_id = app_id
+
+ return running_app
+
+
+# TODO: Only call this on window creation/deletion
## Updates the running app and fires signals
func update() -> void:
+ match self.app_type:
+ APP_TYPE.UNKNOWN:
+ self.app_type = discover_app_type()
+ if self.app_type != APP_TYPE.UNKNOWN:
+ app_type_detected.emit()
+ self.update()
+ APP_TYPE.X11:
+ update_xwayland_app()
+ APP_TYPE.WAYLAND:
+ update_wayland_app()
+
+
+## Tries to discover if the launched app is an X11 or Wayland application
+func discover_app_type() -> APP_TYPE:
+ # Update all the windows
+ self.window_ids = get_all_window_ids()
+
+ # Check to see if running app's app_id exists in focusable_apps
+ var xwayland_primary := gamescope.get_xwayland(gamescope.XWAYLAND_TYPE_PRIMARY)
+ var focused_app := xwayland_primary.focused_app
+ var focusable_apps := xwayland_primary.focusable_apps
+ if (self.app_id == focused_app or self.app_id in focusable_apps) and self.window_ids.is_empty():
+ logger.debug("Discovered app type: Wayland")
+ return APP_TYPE.WAYLAND
+
+ if self.app_id in focusable_apps and not self.window_ids.is_empty():
+ logger.debug("Discovered app type: X11")
+ return APP_TYPE.X11
+
+ return APP_TYPE.UNKNOWN
+
+
+func update_wayland_app() -> void:
+ # Check if the app, or any of its children, are still running
+ var running := is_running()
+ if not running:
+ self.not_running_count += 1
+
+ # Update the running app's state
+ if not_running_count > 3:
+ state = STATE.STOPPED
+ app_killed.emit()
+ elif state == STATE.STARTED:
+ state = STATE.RUNNING
+ #grab_focus() # How can we grab wayland window focus?
+
+ # Update the focus state of the app
+ focused = is_focused()
+
+ var state_str := {
+ STATE.STARTED: "started",
+ STATE.RUNNING: "running",
+ STATE.MISSING_WINDOW: "no window",
+ STATE.STOPPING: "stopping",
+ STATE.STOPPED: "stopped"
+ }
+ logger.trace(launch_item.name + " current state: " + state_str[state])
+
+ # If this was launched by Steam, try and detect if the game closed
+ # so we can kill Steam gracefully
+ if is_steam_app() and state == STATE.STOPPED and is_ogui_managed:
+ logger.trace(launch_item.name + " is a Steam game and has no valid window ID. It may have closed.")
+ # Don't try closing Steam immediately. Wait a few more ticks before attempting
+ # to close Steam.
+ if steam_close_tries < 4:
+ steam_close_tries += 1
+ return
+ var steam_pid := find_steam()
+ if steam_pid > 0:
+ logger.info("Trying to stop steam with pid: " + str(steam_pid))
+ OS.execute("kill", ["-15", str(steam_pid)])
+
+
+func update_xwayland_app() -> void:
# Update all windows related to the app's PID
- window_ids = get_all_window_ids()
+ self.window_ids = get_all_window_ids()
# Ensure that all windows related to the app have an app ID set
_ensure_app_id()
@@ -127,6 +232,7 @@ func update() -> void:
if id > 0 and window_id != id:
logger.trace("Setting window ID " + str(id) + " for " + launch_item.name)
window_id = id
+ has_valid_window = true
else:
has_valid_window = true
@@ -187,33 +293,47 @@ func suspend(enable: bool) -> void:
func get_window_title(win_id: int) -> String:
if not win_id in window_ids:
return ""
- return Gamescope.get_window_name(win_id)
+ var xwayland := gamescope.get_xwayland_by_name(display)
+ if not xwayland:
+ return ""
+ var title := xwayland.get_window_name(win_id)
+ return title
## Attempt to discover the window ID from the PID of the given application
func get_window_id_from_pid() -> int:
- var display_type := Gamescope.get_display_type(display)
- return Gamescope.get_window_id(pid, display_type)
+ var xwayland := gamescope.get_xwayland_by_name(display)
+ if not xwayland:
+ return -1
+ var windows := xwayland.get_windows_for_pid(pid)
+ if windows.is_empty():
+ return -1
+ return windows[0]
## Attempt to discover all window IDs from the PID of the given application and
## the PIDs of all processes in the same process group.
func get_all_window_ids() -> PackedInt32Array:
var app_name := launch_item.name
- var display_type := Gamescope.get_display_type(display)
var window_ids := PackedInt32Array()
var pids := get_child_pids()
+ var xwayland := gamescope.get_xwayland_by_name(display)
pids.append(pid)
logger.trace(app_name + " found related PIDs: " + str(pids))
- for process_id in pids:
- var windows := Gamescope.get_window_ids(process_id, display_type)
- for window in windows:
- if window < 0:
- continue
- if window in window_ids:
- continue
- window_ids.append(window)
+ # Loop through all windows and check if the window belongs to one of our
+ # processes
+ var all_windows := xwayland.get_all_windows(xwayland.root_window_id)
+ for window_id in all_windows:
+ if xwayland.has_app_id(window_id) and xwayland.get_app_id(window_id) == self.app_id:
+ window_ids.append(window_id)
+ continue
+ var window_pids := xwayland.get_pids_for_window(window_id)
+ for window_pid in window_pids:
+ if window_pid in pids:
+ #logger.trace("Found window for pid", window_pid, ":", window_id)
+ window_ids.append(window_id)
+
logger.trace(app_name + " found related window IDs: " + str(window_ids))
return window_ids
@@ -222,25 +342,7 @@ func get_all_window_ids() -> PackedInt32Array:
## Returns true if the app's PID is running or any decendents with the same
## process group.
func is_running() -> bool:
- # If the app is still running, great!
- if OS.is_process_running(pid):
- return true
-
- # If that failed, check if reaper can get the status.
- logger.trace("Reaper pid State: " + Reaper.get_pid_state(pid))
- if Reaper.get_pid_state(pid) in ["R (running)", "S (sleeping)"]:
- return true
-
- logger.trace("Original process not running. Checking child PID's...")
- # If it's not running, let's check to make sure it's REALLY not running
- # and hasn't re-parented itself
- var children := get_child_pids()
- if children.size() > 0:
- var pids := Array(children)
- logger.trace("{0} is not running, but lives on in {1}".format([pid, ",".join(pids)]))
- return true
- logger.trace("Process " + str(pid) + " has died and no child PID's could be found.")
- return false
+ return OS.is_process_running(pid)
## Return a list of child PIDs. When launching apps with [Reaper], PR_SET_CHILD_SUBREAPER
@@ -280,22 +382,28 @@ func get_child_pids() -> PackedInt32Array:
## Returns whether or not the app can be switched to/focused
func can_focus() -> bool:
- return window_id > 0
+ return self.app_id > 0
## Return true if the currently running app is focused
func is_focused() -> bool:
if not can_focus():
return false
- var focused_window := Gamescope.get_focused_window()
- return window_id == focused_window or focused_window in window_ids
+ var xwayland_primary := gamescope.get_xwayland(gamescope.XWAYLAND_TYPE_PRIMARY)
+ if not xwayland_primary:
+ return false
+ var focused_app := xwayland_primary.focused_app
+ return self.app_id == focused_app
## Focuses to the app's window
func grab_focus() -> void:
if not can_focus():
return
- Gamescope.set_baselayer_window(window_id)
+ var xwayland_primary := gamescope.get_xwayland(gamescope.XWAYLAND_TYPE_PRIMARY)
+ if not xwayland_primary:
+ return
+ xwayland_primary.baselayer_app = self.app_id
focused = true
@@ -303,17 +411,24 @@ func grab_focus() -> void:
## to switch to the window
func switch_window(win_id: int, focus: bool = true) -> int:
# Error if the window does not belong to the running app
+ # TODO: Look into how window switching can work with Wayland windows
if not win_id in window_ids:
return ERR_DOES_NOT_EXIST
-
+
+ # Get the primary XWayland instance
+ var xwayland_primary := gamescope.get_xwayland(gamescope.XWAYLAND_TYPE_PRIMARY)
+ if not xwayland_primary:
+ return ERR_UNAVAILABLE
+
# Check if this app is a focusable window.
- if not win_id in Gamescope.get_focusable_windows():
+ if not win_id in xwayland_primary.focusable_windows:
return ERR_UNAVAILABLE
# Update the window ID and optionally grab focus
window_id = win_id
if focus:
grab_focus()
+ xwayland_primary.baselayer_window = win_id
return OK
@@ -332,32 +447,48 @@ func _ensure_app_id() -> void:
if is_steam_app() or not is_ogui_managed:
return
+ # Get the xwayland instance this app is running on
+ var xwayland := gamescope.get_xwayland_by_name(display)
+ if not xwayland:
+ return
+
# Get all windows associated with the running app
var possible_windows := window_ids.duplicate()
# Try setting the app ID on each possible Window. If they are valid windows,
# gamescope will make these windows available as focusable windows.
- var app_name := launch_item.name
for window in possible_windows:
- var display_type := Gamescope.get_display_type(display)
- if Gamescope.has_app_id(window, display_type):
+ if xwayland.has_app_id(window):
continue
- Gamescope.set_app_id(window, window, display_type)
+ xwayland.set_app_id(window, self.app_id)
## Returns whether or not the window id of the running app needs to be discovered
func needs_window_id() -> bool:
+ var xwayland_primary := gamescope.get_xwayland(gamescope.XWAYLAND_TYPE_PRIMARY)
+ if not xwayland_primary:
+ return false
+
if window_id <= 0:
logger.trace(launch_item.name + " has a bad window ID: " + str(window_id))
return true
- var focusable_windows := Gamescope.get_focusable_windows()
+ # If this is a Steam app and the current window id is a Steam window, don't
+ # consider this a valid window id. TODO: We might not need this since we also
+ # check this in _discover_window_id()
+ if is_steam_app() and is_steam_window(window_id):
+ return true
+ var focusable_windows := xwayland_primary.focusable_windows
if not window_id in focusable_windows:
logger.trace(str(window_id) + " is not in the list of focusable windows")
return true
+ var xwayland := gamescope.get_xwayland_by_name(display)
+ if not xwayland:
+ return false
+
# Check if the current window ID exists in the list of open windows
- var root_window := Gamescope.get_root_window_id(Gamescope.XWAYLAND.GAME)
- var all_windows := Gamescope.get_all_windows(root_window, Gamescope.XWAYLAND.GAME)
+ var root_window := xwayland.root_window_id
+ var all_windows := xwayland.get_all_windows(root_window)
if not window_id in all_windows:
logger.trace(str(window_id) + " is not in the list of all windows")
return true
@@ -365,12 +496,11 @@ func needs_window_id() -> bool:
# If this is a Steam app, the only acceptable window will have its STEAM_GAME
# property set.
if is_steam_app():
- var display_type := Gamescope.get_display_type(display)
var steam_app_id := get_meta("steam_app_id") as int
- if not Gamescope.has_app_id(window_id, display_type):
+ if not xwayland.has_app_id(window_id):
logger.trace(str(window_id) + " does not have an app ID already set by Steam")
return true
- if Gamescope.get_app_id(window_id) != steam_app_id:
+ if xwayland.get_app_id(window_id) != steam_app_id:
logger.trace(str(window_id) + " has an app ID but it does not match " + str(steam_app_id))
return true
@@ -392,11 +522,21 @@ func _discover_window_id() -> int:
# Get all windows associated with the running app
var possible_windows := window_ids.duplicate()
-
+
+ # Get the primary XWayland instance
+ var xwayland_primary := gamescope.get_xwayland(gamescope.XWAYLAND_TYPE_PRIMARY)
+ if not xwayland_primary:
+ return -1
+
# Look for the app window in the list of focusable windows
- var focusable := Gamescope.get_focusable_windows()
+ var focusable := xwayland_primary.focusable_windows
for window in possible_windows:
if window in focusable:
+ # If this is a steam app, don't consider any Steam windows as valid
+ # discovered window ids for this app.
+ if is_steam_app() and is_steam_window(window):
+ logger.debug("Window", window, "is a Steam window")
+ continue
return window
return -1
@@ -418,6 +558,25 @@ func is_steam_app() -> bool:
return false
+## Returns true if the given window id is detected as a Steam window
+func is_steam_window(window_id: int) -> bool:
+ var xwayland := gamescope.get_xwayland_by_name(display)
+ if not xwayland:
+ return false
+
+ var window_pids := xwayland.get_pids_for_window(window_id)
+ for window_pid in window_pids:
+ var pid_info := Reaper.get_pid_status(window_pid)
+ if not "Name" in pid_info:
+ continue
+ var process_name := pid_info["Name"] as String
+ if process_name in ["steam", "steamwebhelper"]:
+ return true
+ print(process_name)
+
+ return false
+
+
## Finds the steam process so it can be killed when a game closes
func find_steam() -> int:
var child_pids := get_child_pids()
@@ -431,3 +590,9 @@ func find_steam() -> int:
return child_pid
return -1
+
+
+func _to_string() -> String:
+ if not self.launch_item:
+ return ""
+ return "".format([self.launch_item.name, self.app_id])
diff --git a/core/systems/library/library.gd b/core/systems/library/library.gd
index 718bc7088..2e8c9c02d 100644
--- a/core/systems/library/library.gd
+++ b/core/systems/library/library.gd
@@ -94,5 +94,13 @@ func has_update(item: LibraryLaunchItem) -> bool:
return false
+## This method should be overridden if the library requires executing callbacks
+## at certain points in an app's lifecycle, such as when an app is starting or
+## stopping.
+func get_app_lifecycle_hooks() -> Array[AppLifecycleHook]:
+ var hooks: Array[AppLifecycleHook]
+ return hooks
+
+
func _exit_tree() -> void:
LibraryManager.unregister_library(self)
diff --git a/core/systems/library/library_desktop.gd b/core/systems/library/library_desktop.gd
index d98235c88..a9b551c69 100644
--- a/core/systems/library/library_desktop.gd
+++ b/core/systems/library/library_desktop.gd
@@ -80,7 +80,8 @@ func _apply_quirks(launch_item: LibraryLaunchItem) -> void:
# If the desktop shortcut is for Steam, add the '-silent' argument so it
# doesn't launch into the Steam interface
- var args := PackedStringArray(["-gamepadui", "-steamos3", "-steampal", "-steamdeck", "-silent"])
+ #var args := PackedStringArray(["-gamepadui", "-steamos3", "-steampal", "-steamdeck", "-silent"])
+ var args := PackedStringArray(["-silent"])
args.append_array(launch_item.args)
launch_item.args = args
diff --git a/core/systems/library/library_launch_item.gd b/core/systems/library/library_launch_item.gd
index d3cbadcc6..fc4949c2d 100644
--- a/core/systems/library/library_launch_item.gd
+++ b/core/systems/library/library_launch_item.gd
@@ -65,3 +65,24 @@ static func from_dict(d: Dictionary) -> LibraryLaunchItem:
if "metadata" in d:
item.metadata = d["metadata"]
return item
+
+
+## Returns a numerical app ID associated with the launch item
+func get_app_id() -> int:
+ # If this launch item launches a Steam game, use the Steam app id instead
+ for arg in self.args:
+ if not arg.contains("steam://rungameid/"):
+ continue
+ var parts := arg.split("/", false)
+ if parts.is_empty():
+ continue
+ var id := parts[-1] as String
+ if not id.is_valid_int():
+ continue
+ return int(id)
+
+ # In all other cases, use the hash of the app name for its app id
+ var app_id := hash(self.name)
+ const MAX_APP_ID := 800483647
+
+ return app_id % MAX_APP_ID
diff --git a/core/systems/library/library_refresher.gd b/core/systems/library/library_refresher.gd
new file mode 100644
index 000000000..711dc2eaf
--- /dev/null
+++ b/core/systems/library/library_refresher.gd
@@ -0,0 +1,55 @@
+@icon("res://assets/editor-icons/library.svg")
+@tool
+extends Node
+class_name LibraryRefresher
+
+## Refreshes the library when the given parent signal is fired
+
+var library_manager := load("res://core/global/library_manager.tres") as LibraryManager
+
+## Signal on our parent node to connect to
+var on_signal: String
+
+
+func _init() -> void:
+ ready.connect(_on_ready)
+
+
+func _on_ready() -> void:
+ notify_property_list_changed()
+ # Do nothing if running in the editor
+ if Engine.is_editor_hint():
+ return
+ if on_signal != "":
+ get_parent().connect(on_signal, _on_signal)
+
+
+## Fires when the given signal is emitted.
+func _on_signal():
+ library_manager.reload_library()
+
+
+# Customize editor properties that we expose. Here we dynamically look up
+# the parent node's signals so we can display them in a list.
+func _get_property_list():
+ # By default, `on_signal` is not visible in the editor.
+ var property_usage := PROPERTY_USAGE_NO_EDITOR
+
+ var parent_signals := []
+ if get_parent() != null:
+ property_usage = PROPERTY_USAGE_DEFAULT
+ for sig in get_parent().get_signal_list():
+ parent_signals.push_back(sig["name"])
+
+ var properties := []
+ properties.append(
+ {
+ "name": "on_signal",
+ "type": TYPE_STRING,
+ "usage": property_usage, # See above assignment.
+ "hint": PROPERTY_HINT_ENUM,
+ "hint_string": ",".join(parent_signals)
+ }
+ )
+
+ return properties
diff --git a/core/systems/library/library_refresher.tscn b/core/systems/library/library_refresher.tscn
new file mode 100644
index 000000000..c3514f640
--- /dev/null
+++ b/core/systems/library/library_refresher.tscn
@@ -0,0 +1,6 @@
+[gd_scene load_steps=2 format=3 uid="uid://buwdabfwboyn0"]
+
+[ext_resource type="Script" path="res://core/systems/library/library_refresher.gd" id="1_ttjxh"]
+
+[node name="LibraryRefresher" type="Node"]
+script = ExtResource("1_ttjxh")
diff --git a/core/systems/network/network_manager.gd b/core/systems/network/network_manager.gd
index 3b7dc0f64..6dab85bce 100644
--- a/core/systems/network/network_manager.gd
+++ b/core/systems/network/network_manager.gd
@@ -1,106 +1,20 @@
-extends RefCounted
+@icon("res://assets/ui/icons/iconoir--network-solid.svg")
+extends Node
class_name NetworkManager
-## Manage and interact with the system network settings
+## Manages NetworkManager.
##
-## Allows network management through nmcli
-## Reference: https://developer-old.gnome.org/NetworkManager/stable/nmcli.html
+## The [NetworkManager] class is responsible for loading a [NetworkManagerInstance] and
+## calling its 'process()' method each frame.
const bar_0 := preload("res://assets/ui/icons/wifi-none.svg")
const bar_1 := preload("res://assets/ui/icons/wifi-low.svg")
const bar_2 := preload("res://assets/ui/icons/wifi-medium.svg")
const bar_3 := preload("res://assets/ui/icons/wifi-high.svg")
+const no_network := preload("res://assets/ui/icons/tabler--network-off.svg")
+const ethernet := preload("res://assets/ui/icons/mdi--ethernet.svg")
-const common_args := ["--terse", "--color", "no"]
-
-
-## Wireless Access Point
-class WifiAP:
- var in_use: bool
- var bssid: String
- var ssid: String
- var mode: String
- var channel: int
- var rate: String
- var strength: int
- var security: String
-
-
-## Network device
-class NetworkDevice:
- var device: String
- var type: String
- var state: String
- var connection: String
-
-
-## Returns true if the system has network controls we support
-static func supports_network() -> bool:
- var code := OS.execute("which", ["nmcli"])
- return code == 0
-
-
-## Returns a list of network devices
-#$nmcli --terse --color no device
-#enp5s0:ethernet:connected:Wired connection 1
-#wlp4s0:wifi:connected:Chonenberg
-#lo:loopback:connected (externally):lo
-#p2p-dev-wlp4s0:wifi-p2p:disconnected:
-static func get_devices() -> Array[NetworkDevice]:
- var result: Array[NetworkDevice] = []
- var output := _run_nmcli(["device"])
- for line in output:
- var device := NetworkDevice.new()
- device.device = line[0]
- device.type = line[1]
- device.state = line[2]
- device.connection = line[3]
- result.append(device)
-
- return result
-
-
-## Returns a list of available wifi access points
-#$ nmcli --terse --color no dev wifi
-# :AA\:BB\:CC\:83\:82\:FF:Chronenberg 5GHz:Infra:120:405 Mbit/s:94:▂▄▆█:WPA2
-#*:AA\:BB\:CC\:83\:82\:FB:Chonenberg:Infra:11:195 Mbit/s:83:▂▄▆█:WPA2
-static func get_access_points() -> Array[WifiAP]:
- var result: Array[WifiAP] = []
- var output := _run_nmcli(["dev", "wifi"])
- for line in output:
- var ap := WifiAP.new()
- ap.in_use = line[0] == "*"
- ap.bssid = line[1]
- ap.ssid = line[2]
- ap.mode = line[3]
- ap.channel = line[4].to_int()
- ap.rate = line[5]
- ap.strength = line[6].to_int()
- ap.security = line[8]
- result.append(ap)
-
- return result
-
-
-## Returns the currently connected access point
-static func get_current_access_point() -> WifiAP:
- var access_points := get_access_points()
- for ap in access_points:
- if ap.in_use:
- return ap
- return null
-
-
-## Connect to the given wifi access point
-static func connect_access_point(ssid: String, password: String = "") -> int:
- var args := ["dev", "wifi", "connect", ssid]
- if password != "":
- args.append_array(["password", password])
- var output := []
- var code := OS.execute("nmcli", args, output)
- if code != OK:
- push_warning("Unable to connect to ", ssid, ": ", output[0])
- return code
+@export var instance: NetworkManagerInstance = load("res://core/systems/network/network_manager.tres") as NetworkManagerInstance
## Returns the texture reflecting the given wifi strength
@@ -114,34 +28,7 @@ static func get_strength_texture(strength: int) -> Texture2D:
return bar_0
-# Run nmcli with the given arguments. Returns the parsed output.
-static func _run_nmcli(args: PackedStringArray) -> Array[PackedStringArray]:
- var output := []
- var cmd_args := common_args.duplicate()
- cmd_args.append_array(args)
- var code := OS.execute("nmcli", cmd_args, output)
- if code != OK:
- return []
-
- return _parse_nmcli(output[0])
-
-
-# Parses the terse output of nmcli, which is separated by ':'
-#$ nmcli --terse --color no dev wifi
-# :AA\:BB\:CC\:83\:82\:FF:Chronenberg 5GHz:Infra:120:405 Mbit/s:94:▂▄▆█:WPA2
-#*:AA\:BB\:CC\:83\:82\:FB:Chonenberg:Infra:11:195 Mbit/s:83:▂▄▆█:WPA2
-static func _parse_nmcli(output: String) -> Array[PackedStringArray]:
- var parsed: Array[PackedStringArray] = []
- var lines := output.split("\n")
- for line in lines:
- var parsed_line := PackedStringArray()
- if line == "":
- continue
- line = line.replace("\\:", "%COLON%")
- var columns := line.split(":")
- for column in columns:
- column = column.replace("%COLON%", ":")
- parsed_line.append(column)
- parsed.append(parsed_line)
-
- return parsed
+func _process(_delta: float) -> void:
+ if not instance:
+ return
+ instance.process()
diff --git a/core/systems/network/network_manager.tres b/core/systems/network/network_manager.tres
new file mode 100644
index 000000000..319aa7c1f
--- /dev/null
+++ b/core/systems/network/network_manager.tres
@@ -0,0 +1,3 @@
+[gd_resource type="NetworkManagerInstance" format=3 uid="uid://cmwavccnjwpr0"]
+
+[resource]
diff --git a/core/systems/network/network_manager_test.gd b/core/systems/network/network_manager_test.gd
index ccb0ab893..14c0d44ac 100644
--- a/core/systems/network/network_manager_test.gd
+++ b/core/systems/network/network_manager_test.gd
@@ -1,14 +1,95 @@
extends GutTest
+var network_manager := load("res://core/systems/network/network_manager.tres") as NetworkManagerInstance
-func test_get_access_points() -> void:
- if not NetworkManager.supports_network():
+const SSID := "SomeSSID"
+const PSK := "SomePassword"
+
+
+func before_all() -> void:
+ if not network_manager.is_running():
+ @warning_ignore("unsafe_method_access")
+ gut.p("Networking is not supported")
+ return
+
+
+func test_connect() -> void:
+ if not network_manager.is_running():
pass_test("Networking not supported, skipping")
return
+ var devices := network_manager.get_devices()
+ if devices.is_empty():
+ pass_test("No network adapters found, skipping")
+ return
+ var wireless_devices := devices.filter(func(device: NetworkDevice): return device.wireless != null)
+ if wireless_devices.is_empty():
+ pass_test("No wireless adapters found, skipping")
+ return
+ gut.p("Found wireless devices: " + str(wireless_devices))
+ var device := wireless_devices[0] as NetworkDevice
+ var access_point: NetworkAccessPoint
+ for ap in device.wireless.access_points:
+ if ap.ssid != SSID:
+ continue
+ access_point = ap
+ break
+
+ if not access_point:
+ pass_test("No valid wireless networks found, skipping")
+ return
+
+ var connection := access_point.connect(device, PSK)
+
+ for i in range(50):
+ var state := connection.state
+ gut.p("Device state: " + str(device.state))
+ gut.p("Connection state: " + str(state))
+ match device.state:
+ device.NM_DEVICE_STATE_CONFIG:
+ gut.p("Connecting...")
+ device.NM_DEVICE_STATE_NEED_AUTH:
+ gut.p("Authentication required")
+ break
+ device.NM_DEVICE_STATE_ACTIVATED:
+ gut.p("Successfully connected!")
+ break
+ device.NM_DEVICE_STATE_IP_CONFIG:
+ gut.p("Aquiring IP address...")
+ device.NM_DEVICE_STATE_DEACTIVATING:
+ gut.p("Deactivation connection...")
+
+ await wait_seconds(1, "waiting for connection")
+
+ pass_test("Skipping")
- for ap in NetworkManager.get_access_points():
- gut.p("Found AP: " + str(ap.ssid))
- for device in NetworkManager.get_devices():
- gut.p("Found device: " + device.device + " " + device.type + " " + device.state)
+func test_get_devices() -> void:
+ if not network_manager.is_running():
+ pass_test("Networking not supported, skipping")
+ return
+ var devices := network_manager.get_devices()
+ if devices.is_empty():
+ pass_test("No network adapters found, skipping")
+ for device in devices:
+ @warning_ignore("unsafe_method_access")
+ gut.p("discovered device: " + device.dbus_path)
+
+ if device.ip4_config:
+ gut.p(" found address: " + str(device.ip4_config.addresses))
+
+ if device.device_type == device.NM_DEVICE_TYPE_ETHERNET:
+ assert_null(device.wireless)
+ @warning_ignore("unsafe_method_access")
+ gut.p(" discovered ethernet device")
+ if device.device_type == device.NM_DEVICE_TYPE_WIFI:
+ assert_not_null(device.wireless)
+ @warning_ignore("unsafe_method_access")
+ gut.p(" discovered wireless device: " + device.wireless.dbus_path)
+ if device.wireless.active_access_point:
+ gut.p(" active access point: " + device.wireless.active_access_point.ssid)
+ for ap in device.wireless.access_points:
+ gut.p(" discovered access point: " + ap.ssid)
+ gut.p(" strength: " + str(ap.strength))
+ gut.p(" freq: " + str(ap.frequency))
+ gut.p(" max bitrate: " + str(ap.max_bitrate))
pass_test("Skipping")
diff --git a/core/systems/network/unix_socket_client.gd b/core/systems/network/unix_socket_client.gd
deleted file mode 100644
index 19ac3e480..000000000
--- a/core/systems/network/unix_socket_client.gd
+++ /dev/null
@@ -1,59 +0,0 @@
-@icon("res://assets/editor-icons/socket-bold.svg")
-extends Node
-class_name UnixSocketClient
-
-signal connected
-signal data
-signal disconnected
-signal error
-
-var _is_open: bool = false
-var _stream := StreamPeerUnix.new()
-var _logger := Log.get_logger("UnixSocketClient")
-
-
-func _ready() -> void:
- _is_open = _stream.is_open()
-
-
-func _process(_delta: float) -> void:
- var new_status := _stream.is_open()
- if new_status != _is_open:
- var prev_status := _is_open
- _is_open = new_status
- if prev_status and not new_status:
- _logger.info("Disconnected from socket.")
- disconnected.emit()
- if new_status:
- _logger.info("Connected to socket.")
- connected.emit()
-
- if _is_open:
- var available_bytes: int = _stream.get_available_bytes()
- if available_bytes > 0:
- _logger.debug("available bytes: " + str(available_bytes))
- var parts := _stream.get_partial_data(available_bytes)
- # Check for read error.
- if parts[0] != OK:
- _logger.error("Error getting data from stream: " + str(parts[0]))
- error.emit()
- else:
- data.emit(parts[1])
-
-
-func open(path: String) -> void:
- # Reset status so we can tell if it changes to error again.
- _is_open = false
- if _stream.open(path) != OK:
- error.emit()
-
-
-func send(data: PackedByteArray) -> bool:
- if not _is_open:
- _logger.error("Error: Stream is not currently connected.")
- return false
- var err: int = _stream.put_data(data)
- if err != OK:
- _logger.error("Error writing to stream: " + str(err))
- return false
- return true
diff --git a/core/systems/performance/performance_manager.gd b/core/systems/performance/performance_manager.gd
index b7166f76b..590e4af72 100644
--- a/core/systems/performance/performance_manager.gd
+++ b/core/systems/performance/performance_manager.gd
@@ -11,7 +11,7 @@ signal profile_loaded(profile: PerformanceProfile)
signal profile_saved(profile: PerformanceProfile, path: String)
const USER_PROFILES := "user://data/performance/profiles"
-const DOCKED_STATES := [PowerManager.DEVICE_STATE.CHARGING, PowerManager.DEVICE_STATE.FULLY_CHARGED, PowerManager.DEVICE_STATE.PENDING_CHARGE]
+const DOCKED_STATES := [UPowerDevice.STATE_CHARGING, UPowerDevice.STATE_FULLY_CHARGED, UPowerDevice.STATE_PENDING_CHARGE]
## Performance profiles are separated into these states, so users can have different
## performance depending on whether or not they are plugged in to an external power
@@ -22,11 +22,12 @@ enum PROFILE_STATE {
}
var _hardware_manager := load("res://core/systems/hardware/hardware_manager.tres") as HardwareManager
-var _power_manager := load("res://core/systems/power/power_manager.tres") as PowerManager
+var _power_manager := load("res://core/systems/power/power_manager.tres") as UPowerInstance
var _settings_manager := load("res://core/global/settings_manager.tres") as SettingsManager
-var _power_station := load("res://core/systems/performance/power_station.tres") as PowerStation
+var _power_station := load("res://core/systems/performance/power_station.tres") as PowerStationInstance
var _launch_manager := load("res://core/global/launch_manager.tres") as LaunchManager
+var display_device := _power_manager.get_display_device()
var current_profile: PerformanceProfile
var current_profile_state: PROFILE_STATE # docked or undocked
var logger := Log.get_logger("PerformanceManager", Log.LEVEL.INFO)
@@ -36,18 +37,17 @@ func _init() -> void:
# Listen for signals when the current app switches so we can update the profile
# accordingly.
_launch_manager.app_switched.connect(_on_app_switched)
+ _launch_manager.all_apps_stopped.connect(_on_all_apps_stopped)
# Connect to battery state changes to switch between "docked" and "undocked"
# performance profiles.
- var batteries := _power_manager.get_devices_by_type(PowerManager.DEVICE_TYPE.BATTERY)
- if batteries.size() > 1:
- logger.warn("You somehow have more than one battery. We don't know what to do with that.")
- if batteries.size() > 0:
- var battery := batteries[0]
- battery.updated.connect(_on_battery_updated.bind(battery))
-
+ if display_device:
+ display_device.updated.connect(_on_battery_updated.bind(display_device))
+
+ # TODO: Listen for signals if PowerStation starts/stops
+
# Do nothing if PowerStation is not detected
- if not _power_station.supports_power_station():
+ if not _power_station.is_running():
return
# Load and apply the default profile
@@ -109,22 +109,25 @@ func create_profile(library_item: LibraryLaunchItem = null) -> PerformanceProfil
profile.cpu_smt_enabled = _power_station.cpu.smt_enabled
# Detect all GPU cards
- var cards: Array[PowerStation.GPUCard] = []
+ var cards: Array[GpuCard] = []
if _power_station.gpu:
cards = _power_station.gpu.get_cards()
# Configure GPU settings
# TODO: Support multiple GPUs?
for card in cards:
- if card.class_type != "integrated":
+ if card.class != "integrated":
continue
-
- profile.tdp_current = card.tdp
- profile.tdp_boost_current = card.boost
+ if _hardware_manager.gpu:
+ profile.tdp_current = round(_hardware_manager.gpu.tdp_max)
+ profile.tdp_boost_current = round(_hardware_manager.gpu.max_boost)
+ else:
+ profile.tdp_current = card.tdp
+ profile.tdp_boost_current = card.boost
profile.gpu_freq_min_current = card.clock_value_mhz_min
profile.gpu_freq_max_current = card.clock_value_mhz_max
profile.gpu_manual_enabled = card.manual_clock
- #profile.gpu_power_profile = card.power_profile # TODO: Fix this
+ profile.gpu_power_profile = card.power_profile
profile.gpu_temp_current = card.thermal_throttle_limit_c
logger.debug("Created performance profile: " + profile.name)
@@ -152,7 +155,7 @@ func load_or_create_profile(profile_path: String, library_item: LibraryLaunchIte
if profile:
logger.debug("Found profile at: " + profile_path)
return profile
-
+
# If the profile does not exist, create one with the currently applied
# performance settings.
logger.debug("No profile found. Creating one.")
@@ -161,60 +164,58 @@ func load_or_create_profile(profile_path: String, library_item: LibraryLaunchIte
## Applies the given performance profile to the system
func apply_profile(profile: PerformanceProfile) -> void:
- if not _power_station.supports_power_station():
+ if not _power_station.is_running():
logger.info("Unable to apply performance profile. PowerStation not detected.")
return
-
- logger.info("Applying performance profile: " + profile.name)
- # Apply CPU settings from the given profile
- if _power_station.cpu:
- logger.debug("Applying CPU performance settings from profile")
- if _power_station.cpu.boost_enabled != profile.cpu_boost_enabled:
- _power_station.cpu.boost_enabled = profile.cpu_boost_enabled
- if _power_station.cpu.smt_enabled != profile.cpu_smt_enabled:
- _power_station.cpu.smt_enabled = profile.cpu_smt_enabled
- if profile.cpu_core_count_current > 0 and _power_station.cpu.cores_enabled != profile.cpu_core_count_current:
- _power_station.cpu.cores_enabled = profile.cpu_core_count_current
+ logger.info("Applying performance profile: " + profile.name)
# Detect all GPU cards
- var cards: Array[PowerStation.GPUCard] = []
+ var cards: Array[GpuCard] = []
if _power_station.gpu:
cards = _power_station.gpu.get_cards()
# Configure GPU settings
# TODO: Support mutliple GPUs?
for card in cards:
- if card.class_type != "integrated":
+ if card.class != "integrated":
continue
logger.debug("Applying GPU performance settings from profile")
+ if card.power_profile != profile.gpu_power_profile:
+ logger.debug("Applying Power Profile: " + profile.gpu_power_profile)
+ card.power_profile = profile.gpu_power_profile
if card.manual_clock != profile.gpu_manual_enabled:
+ logger.debug("Applying Manual Clock Enabled: " + str(profile.gpu_manual_enabled))
card.manual_clock = profile.gpu_manual_enabled
- if profile.tdp_current > 0 and card.tdp != profile.tdp_current:
- logger.debug("Applying TDP: " + str(profile.tdp_current))
- card.tdp = profile.tdp_current
- if profile.tdp_boost_current > 0 and card.boost != profile.tdp_boost_current:
- logger.debug("Applying TDP Boost: " + str(profile.tdp_boost_current))
- card.boost = profile.tdp_boost_current
if profile.gpu_freq_min_current > 0 and card.clock_value_mhz_min != profile.gpu_freq_min_current:
logger.debug("Applying Clock Freq Min: " + str(profile.gpu_freq_min_current))
card.clock_value_mhz_min = profile.gpu_freq_min_current
if profile.gpu_freq_max_current > 0 and card.clock_value_mhz_max != profile.gpu_freq_max_current:
logger.debug("Applying Clock Freq Max: " + str(profile.gpu_freq_max_current))
card.clock_value_mhz_max = profile.gpu_freq_max_current
- if profile.gpu_power_profile >= 0:
- var power_profile := "max-performance"
- if profile.gpu_power_profile == 0:
- power_profile = "max-performance"
- if profile.gpu_power_profile == 1:
- power_profile = "power-saving"
- if card.power_profile != power_profile:
- logger.debug("Applying Power Profile: " + power_profile)
- card.power_profile = power_profile
if profile.gpu_temp_current > 0 and card.thermal_throttle_limit_c != profile.gpu_temp_current:
logger.debug("Applying Thermal Throttle Limit: " + str(profile.gpu_temp_current))
card.thermal_throttle_limit_c = profile.gpu_temp_current
+ # Only apply GPU TDP settings from the given profile if we're in a mode that supports it
+ if profile.advanced_mode or "max-performance" in get_power_profiles_available():
+ if profile.tdp_current > 0 and card.tdp != profile.tdp_current:
+ logger.debug("Applying TDP: " + str(profile.tdp_current))
+ card.tdp = profile.tdp_current
+ if profile.tdp_boost_current > 0 and card.boost != profile.tdp_boost_current:
+ logger.debug("Applying TDP Boost: " + str(profile.tdp_boost_current))
+ card.boost = profile.tdp_boost_current
+
+ # Apply CPU settings from the given profile
+ if _power_station.cpu:
+ logger.debug("Applying CPU performance settings from profile")
+ if _power_station.cpu.boost_enabled != profile.cpu_boost_enabled:
+ _power_station.cpu.boost_enabled = profile.cpu_boost_enabled
+ if _power_station.cpu.smt_enabled != profile.cpu_smt_enabled:
+ _power_station.cpu.smt_enabled = profile.cpu_smt_enabled
+ if profile.cpu_core_count_current > 0 and _power_station.cpu.cores_enabled != profile.cpu_core_count_current:
+ _power_station.cpu.cores_enabled = profile.cpu_core_count_current
+
logger.info("Applied Performance Profile: " + profile.name)
profile_applied.emit(profile)
@@ -242,26 +243,22 @@ func apply_and_save_profile(profile: PerformanceProfile) -> void:
## Returns the current profile state. I.e. whether or not the "docked" or "undocked"
## performance profiles should be used.
func get_profile_state() -> PROFILE_STATE:
- var batteries := _power_manager.get_devices_by_type(PowerManager.DEVICE_TYPE.BATTERY)
- if batteries.size() > 1:
- logger.warn("You somehow have more than one battery. We don't know what to do with that.")
- if batteries.size() > 0:
- var battery := batteries[0]
- return get_profile_state_from_battery(battery)
+ if display_device:
+ return get_profile_state_from_battery(display_device)
return PROFILE_STATE.DOCKED
## Returns the current profile state. I.e. whether or not the "docked" or "undocked"
## performance profiles should be used.
-func get_profile_state_from_battery(battery: PowerManager.Device) -> PROFILE_STATE:
+func get_profile_state_from_battery(battery: UPowerDevice) -> PROFILE_STATE:
if battery.state not in DOCKED_STATES:
return PROFILE_STATE.UNDOCKED
return PROFILE_STATE.DOCKED
## Called whenever a battery is updated
-func _on_battery_updated(battery: PowerManager.Device) -> void:
+func _on_battery_updated(battery: UPowerDevice) -> void:
# Get the current profile state to see if we need to load the docked or
# undocked profile.
var profile_state := get_profile_state_from_battery(battery)
@@ -287,6 +284,23 @@ func _on_battery_updated(battery: PowerManager.Device) -> void:
apply_profile(profile)
+## Sets the default performance profile when all running apps have stopped
+func _on_all_apps_stopped() -> void:
+ logger.debug("Detected all apps stopped")
+
+ # Get the current profile state to see if we need to load the docked or
+ # undocked profile.
+ var profile_state := get_profile_state()
+
+ # Load the performance profile based on the running game
+ var profile_path := get_profile_filename(profile_state)
+ profile_path = "/".join([USER_PROFILES, profile_path])
+ var profile := load_or_create_profile(profile_path)
+ current_profile = profile
+ profile_loaded.emit(profile)
+ apply_profile(profile)
+
+
## Called whenever an app is switched. E.g. when a game is launched
func _on_app_switched(_from: RunningApp, to: RunningApp) -> void:
logger.debug("Detected app switch")
@@ -304,3 +318,18 @@ func _on_app_switched(_from: RunningApp, to: RunningApp) -> void:
current_profile = profile
profile_loaded.emit(profile)
apply_profile(profile)
+
+
+# Get the currently available power profiles
+func get_power_profiles_available() -> PackedStringArray:
+ # Detect all GPU cards
+ var cards: Array[GpuCard] = []
+ if _power_station.gpu:
+ cards = _power_station.gpu.get_cards()
+
+ for card in cards:
+ if card.class != "integrated":
+ continue
+
+ return card.power_profiles_available
+ return []
diff --git a/core/systems/performance/performance_profile.gd b/core/systems/performance/performance_profile.gd
index 9fe0d4448..76e80c796 100644
--- a/core/systems/performance/performance_profile.gd
+++ b/core/systems/performance/performance_profile.gd
@@ -10,11 +10,12 @@ class_name PerformanceProfile
@export var gpu_freq_max_current: float
@export var gpu_freq_min_current: float
@export var gpu_manual_enabled: bool
-@export var gpu_power_profile: int
+@export var gpu_power_profile: String
@export var gpu_temp_current: float
@export var tdp_boost_current: float
@export var tdp_current: float
@export var thermal_profile: int
+@export var advanced_mode: bool = false
func _to_string() -> String:
@@ -25,8 +26,9 @@ func _to_string() -> String:
+ "gpu_freq_max_current: " + str(gpu_freq_max_current) + ", " \
+ "gpu_freq_min_current: " + str(gpu_freq_min_current) + ", " \
+ "gpu_manual_enabled: " + str(gpu_manual_enabled) + ", " \
- + "gpu_power_profile: " + str(gpu_power_profile) + ", " \
+ + "gpu_power_profile: " + gpu_power_profile + ", " \
+ "gpu_temp_current: " + str(gpu_temp_current) + ", " \
+ "tdp_boost_current: " + str(tdp_boost_current) + ", " \
+ "tdp_current: " + str(tdp_current) + ", " \
- + "thermal_profile: " + str(thermal_profile) + ">"
+ + "thermal_profile: " + str(thermal_profile) + ", " \
+ + "advanced_mode:" + str(advanced_mode) + ">"
diff --git a/core/systems/performance/power_station.gd b/core/systems/performance/power_station.gd
index 2c9127791..e714a78b9 100644
--- a/core/systems/performance/power_station.gd
+++ b/core/systems/performance/power_station.gd
@@ -1,4 +1,5 @@
-extends Resource
+@icon("res://assets/editor-icons/game-icons--power-generator.svg")
+extends Node
class_name PowerStation
## Proxy interface to PowerStation over DBus
@@ -6,404 +7,20 @@ class_name PowerStation
## Provides wrapper classes and methods for interacting with PowerStation over
## DBus to control CPU and GPU performance.
-const POWERSTATION_BUS := "org.shadowblip.PowerStation"
-const PERFORMANCE_PATH := "/org/shadowblip/Performance"
-const CPU_PATH := "/org/shadowblip/Performance/CPU"
-const GPU_PATH := "/org/shadowblip/Performance/GPU"
-const IFACE_CPU := "org.shadowblip.CPU"
-const IFACE_CPU_CORE := "org.shadowblip.CPU.Core"
-const IFACE_GPU := "org.shadowblip.GPU"
-const IFACE_GPU_CARD := "org.shadowblip.GPU.Card"
-const IFACE_GPU_TDP := "org.shadowblip.GPU.Card.TDP"
-const IFACE_GPU_CONNECTOR := "org.shadowblip.GPU.Card.Connector"
+@export var instance: PowerStationInstance = load("res://core/systems/performance/power_station.tres") as PowerStationInstance
+# Keep a reference to instances so they are not cleaned up automatically
+var _cpu: Cpu
+var _gpu: Gpu
var logger := Log.get_logger("PowerStation")
-var dbus := load("res://core/global/dbus_system.tres") as DBusManager
-var cpu := CPUBus.new(dbus.create_proxy(POWERSTATION_BUS, CPU_PATH))
-var gpu := GPUBus.new(dbus.create_proxy(POWERSTATION_BUS, GPU_PATH))
-## Returns true if PowerStation can be used on this system
-func supports_power_station() -> bool:
- return dbus.bus_exists(POWERSTATION_BUS)
+func _ready() -> void:
+ _cpu = instance.get_cpu()
+ _gpu = instance.get_gpu()
-## CPUBus provides a DBus connection to the CPU bus for CPU controls
-class CPUBus extends Resource:
- signal properties_changed
- signal updated
- var _proxy: DBusManager.Proxy
-
- func _init(proxy: DBusManager.Proxy) -> void:
- _proxy = proxy
- _proxy.properties_changed.connect(_on_properties_changed)
-
- func _on_properties_changed(iface: String, props: Dictionary) -> void:
- updated.emit()
-
- ## Returns a list of DBus object paths to every detected core
- func enumerate_cores() -> PackedStringArray:
- var result := _proxy.call_method(IFACE_CPU, "EnumerateCores")
- if not result:
- return []
- var args := result.get_args()
- if args.size() != 1:
- return []
- if not args[0] is Array:
- return []
- return args[0]
-
- ## Returns true if the CPU has the given feature
- func has_feature(feature: String) -> bool:
- var result := _proxy.call_method(IFACE_CPU, "HasFeature", [feature], "s")
- if not result:
- return false
- var args := result.get_args()
- if args.size() != 1:
- return false
- if not args[0] is bool:
- return false
- return args[0]
-
- var boost_enabled: bool:
- set(v):
- _proxy.set_property(IFACE_CPU, "BoostEnabled", v)
- get:
- var property = _proxy.get_property(IFACE_CPU, "BoostEnabled")
- if not property is bool:
- return false
- return property
-
- var cores_count: int:
- get:
- var property = _proxy.get_property(IFACE_CPU, "CoresCount")
- if not property is int:
- return -1
- return property
-
- var cores_enabled: int:
- set(v):
- _proxy.set_property(IFACE_CPU, "CoresEnabled", DBus.uint32(v))
- get:
- var property = _proxy.get_property(IFACE_CPU, "CoresEnabled")
- if not property is int:
- return -1
- return property
-
- var features: PackedStringArray:
- get:
- var property = _proxy.get_property(IFACE_CPU, "Features")
- if not property is Array:
- return []
- return property
-
- var smt_enabled: bool:
- set(v):
- _proxy.set_property(IFACE_CPU, "SmtEnabled", v)
- get:
- var property = _proxy.get_property(IFACE_CPU, "SmtEnabled")
- if not property is bool:
- return false
- return property
-
-
-## Provides an interface to enumerate all detected GPU cards
-class GPUBus extends Resource:
- signal properties_changed
- signal updated
- var _proxy: DBusManager.Proxy
-
- func _init(proxy: DBusManager.Proxy) -> void:
- _proxy = proxy
- _proxy.properties_changed.connect(_on_properties_changed)
-
- func _on_properties_changed(iface: String, props: Dictionary) -> void:
- updated.emit()
-
- ## Returns a list of DBus object paths to every detected GPU card
- func enumerate_cards() -> PackedStringArray:
- var result := _proxy.call_method(IFACE_GPU, "EnumerateCards")
- if not result:
- return []
- var args := result.get_args()
- if args.size() != 1:
- return []
- if not args[0] is Array:
- return []
- return args[0]
-
- ## Returns a list of all GPUCard objects
- func get_cards() -> Array[GPUCard]:
- var dbus := load("res://core/global/dbus_system.tres") as DBusManager
- var cards: Array[GPUCard] = []
- var paths := self.enumerate_cards()
- for path in paths:
- var card = GPUCard.new(dbus.create_proxy(POWERSTATION_BUS, path))
- cards.append(card)
-
- return cards
-
-
-## GPUCard provides a DBus connection to the GPU for GPU control
-class GPUCard extends Resource:
- signal properties_changed
- signal updated
- var _proxy: DBusManager.Proxy
-
- func _init(proxy: DBusManager.Proxy) -> void:
- _proxy = proxy
- _proxy.properties_changed.connect(_on_properties_changed)
-
- func _on_properties_changed(iface: String, props: Dictionary) -> void:
- updated.emit()
-
- ## Returns true if the card supports TDP control
- func supports_tdp() -> bool:
- return self.tdp > 1
-
- ## Returns a list of DBus object paths to every detected GPU connector
- func enumerate_connectors() -> PackedStringArray:
- var result := _proxy.call_method(IFACE_GPU_CARD, "EnumerateConnectors")
- if not result:
- return []
- var args := result.get_args()
- if args.size() != 1:
- return []
- if not args[0] is Array:
- return []
- return args[0]
-
- ## Returns a list of all GPUConnector objects
- func get_connectors() -> Array[GPUConnector]:
- var dbus := load("res://core/global/dbus_system.tres") as DBusManager
- var connectors: Array[GPUConnector] = []
- var paths := self.enumerate_connectors()
- for path in paths:
- var card = GPUConnector.new(dbus.create_proxy(POWERSTATION_BUS, path))
- connectors.append(card)
-
- return connectors
-
- var class_type: String:
- get:
- var property = _proxy.get_property(IFACE_GPU_CARD, "Class")
- if not property is String:
- return ""
- return property
-
- var class_id: String:
- get:
- var property = _proxy.get_property(IFACE_GPU_CARD, "ClassId")
- if not property is String:
- return ""
- return property
-
- var clock_limit_mhz_max: float:
- get:
- var property = _proxy.get_property(IFACE_GPU_CARD, "ClockLimitMhzMax")
- if not property is float:
- return -1
- return property
-
- var clock_limit_mhz_min: float:
- get:
- var property = _proxy.get_property(IFACE_GPU_CARD, "ClockLimitMhzMin")
- if not property is float:
- return -1
- return property
-
- var clock_value_mhz_max: float:
- set(v):
- _proxy.set_property(IFACE_GPU_CARD, "ClockValueMhzMax", float(v))
- get:
- var property = _proxy.get_property(IFACE_GPU_CARD, "ClockValueMhzMax")
- if not property is float:
- return -1
- return property
-
- var clock_value_mhz_min: float:
- set(v):
- _proxy.set_property(IFACE_GPU_CARD, "ClockValueMhzMin", float(v))
- get:
- var property = _proxy.get_property(IFACE_GPU_CARD, "ClockValueMhzMin")
- if not property is float:
- return -1
- return property
-
- var device: String:
- get:
- var property = _proxy.get_property(IFACE_GPU_CARD, "Device")
- if not property is String:
- return ""
- return property
-
- var device_id: String:
- get:
- var property = _proxy.get_property(IFACE_GPU_CARD, "DeviceId")
- if not property is String:
- return ""
- return property
-
- var manual_clock: bool:
- set(v):
- _proxy.set_property(IFACE_GPU_CARD, "ManualClock", v)
- get:
- var property = _proxy.get_property(IFACE_GPU_CARD, "ManualClock")
- if not property is bool:
- return false
- return property
-
- var name: String:
- get:
- var property = _proxy.get_property(IFACE_GPU_CARD, "Name")
- if not property is String:
- return ""
- return property
-
- var path: String:
- get:
- var property = _proxy.get_property(IFACE_GPU_CARD, "Path")
- if not property is String:
- return ""
- return property
-
- var revision_id: String:
- get:
- var property = _proxy.get_property(IFACE_GPU_CARD, "RevisionId")
- if not property is String:
- return ""
- return property
-
- var subdevice: String:
- get:
- var property = _proxy.get_property(IFACE_GPU_CARD, "Subdevice")
- if not property is String:
- return ""
- return property
-
- var subdevice_id: String:
- get:
- var property = _proxy.get_property(IFACE_GPU_CARD, "SubdeviceId")
- if not property is String:
- return ""
- return property
-
- var subvendor_id: String:
- get:
- var property = _proxy.get_property(IFACE_GPU_CARD, "SubvendorId")
- if not property is String:
- return ""
- return property
-
- var vendor: String:
- get:
- var property = _proxy.get_property(IFACE_GPU_CARD, "Vendor")
- if not property is String:
- return ""
- return property
-
- var vendor_id: String:
- get:
- var property = _proxy.get_property(IFACE_GPU_CARD, "VendorId")
- if not property is String:
- return ""
- return property
-
- var boost: float:
- set(v):
- _proxy.set_property(IFACE_GPU_TDP, "Boost", float(v))
- get:
- var property = _proxy.get_property(IFACE_GPU_TDP, "Boost")
- if not property is float:
- return -1
- return property
-
- var power_profile: String:
- set(v):
- _proxy.set_property(IFACE_GPU_TDP, "PowerProfile", v)
- get:
- var property = _proxy.get_property(IFACE_GPU_TDP, "PowerProfile")
- if not property is String:
- return ""
- return property
-
- var tdp: float:
- set(v):
- _proxy.set_property(IFACE_GPU_TDP, "TDP", float(v))
- get:
- var property = _proxy.get_property(IFACE_GPU_TDP, "TDP")
- if not property is float:
- return -1
- return property
-
- var thermal_throttle_limit_c: float:
- set(v):
- _proxy.set_property(IFACE_GPU_TDP, "ThermalThrottleLimitC", float(v))
- get:
- var property = _proxy.get_property(IFACE_GPU_TDP, "ThermalThrottleLimitC")
- if not property is float:
- return -1
- return property
-
-
-## GPUConnector provides a DBus connection to a GPU connector
-class GPUConnector extends Resource:
- signal properties_changed
- signal updated
- var _proxy: DBusManager.Proxy
-
- func _init(proxy: DBusManager.Proxy) -> void:
- _proxy = proxy
- _proxy.properties_changed.connect(_on_properties_changed)
-
- func _on_properties_changed(iface: String, props: Dictionary) -> void:
- updated.emit()
-
- var dpms: bool:
- get:
- var property = _proxy.get_property(IFACE_GPU_CONNECTOR, "DPMS")
- if not property is bool:
- return false
- return property
-
- var enabled: bool:
- get:
- var property = _proxy.get_property(IFACE_GPU_CONNECTOR, "Enabled")
- if not property is bool:
- return false
- return property
-
- var id: int:
- get:
- var property = _proxy.get_property(IFACE_GPU_CONNECTOR, "Id")
- if not property is int:
- return -1
- return property
-
- var modes: PackedStringArray:
- get:
- var property = _proxy.get_property(IFACE_GPU_CONNECTOR, "Modes")
- if not property is Array:
- return []
- return property
-
- var name: String:
- get:
- var property = _proxy.get_property(IFACE_GPU_CONNECTOR, "Name")
- if not property is String:
- return ""
- return property
-
- var path: String:
- get:
- var property = _proxy.get_property(IFACE_GPU_CONNECTOR, "Path")
- if not property is String:
- return ""
- return property
-
- var status: String:
- get:
- var property = _proxy.get_property(IFACE_GPU_CONNECTOR, "Status")
- if not property is String:
- return ""
- return property
+func _process(_delta: float) -> void:
+ if not instance:
+ return
+ instance.process()
diff --git a/core/systems/performance/power_station.tres b/core/systems/performance/power_station.tres
index 20b696118..14a601808 100644
--- a/core/systems/performance/power_station.tres
+++ b/core/systems/performance/power_station.tres
@@ -1,6 +1,3 @@
-[gd_resource type="Resource" script_class="PowerStation" load_steps=2 format=3 uid="uid://cdyeux8mdf6l6"]
-
-[ext_resource type="Script" path="res://core/systems/performance/power_station.gd" id="1_bdrpq"]
+[gd_resource type="PowerStationInstance" format=3 uid="uid://c2mmrnh3rcs58"]
[resource]
-script = ExtResource("1_bdrpq")
diff --git a/core/systems/performance/power_station_test.gd b/core/systems/performance/power_station_test.gd
index d20f159e3..1444dcac5 100644
--- a/core/systems/performance/power_station_test.gd
+++ b/core/systems/performance/power_station_test.gd
@@ -1,39 +1,43 @@
extends GutTest
-var power_station := load("res://core/systems/performance/power_station.tres") as PowerStation
-
func test_cpu() -> void:
- if not power_station.supports_power_station():
+ var powerstation := PowerStation.new()
+ powerstation.instance = load("res://core/systems/performance/power_station.tres") as PowerStationInstance
+ add_child_autoqfree(powerstation)
+
+ if not powerstation.instance.is_running():
pass_test("PowerStation is not running, skipping")
return
- var cpu := power_station.cpu
+ var cpu := powerstation.instance.get_cpu()
assert_not_null(cpu, "should return CPU instance")
# Test getting total number of cpu cores
- var num_cores = cpu.cores_count
+ var num_cores := cpu.cores_count
+ gut.p("Total CPU cores: " + str(num_cores))
assert_ne(num_cores, -1, "should have returned total core count")
- # Test that CPU cores get set
- cpu.cores_enabled = num_cores - 1
- assert_eq(cpu.cores_enabled, num_cores - 1, "should have disabled cores")
-
- # Set the cores back
- cpu.cores_enabled = num_cores
- assert_eq(cpu.cores_enabled, num_cores, "should have re-enabled all cores")
-
- # Test enumerating cores
- var enumerated := cpu.enumerate_cores()
- assert_gt(enumerated.size(), 0, "should return at least 1 cpu core path")
-
# Test getting features
- var features = cpu.features
+ var features := cpu.features
+ gut.p("Found CPU features: " + str(features))
assert_gt(features.size(), 1, "should return CPU features")
if features.size() > 1:
var feature := features[0] as String
assert_true(cpu.has_feature(feature), "should have CPU feature")
assert_false(cpu.has_feature("IdontXsist!"), "should not have CPU feature")
+ # Test that CPU cores get set
+ gut.p("Disabling one CPU core")
+ cpu.cores_enabled = num_cores - 1
+ gut.p("Cores enabled: " + str(cpu.cores_enabled))
+ assert_eq(cpu.cores_enabled, num_cores - 1, "should have disabled cores")
+
+ # Set the cores back
+ gut.p("Re-enabling CPU core")
+ cpu.cores_enabled = num_cores
+ gut.p("Cores enabled: " + str(cpu.cores_enabled))
+ assert_eq(cpu.cores_enabled, num_cores, "should have re-enabled all cores")
+
# Test setting SMT
cpu.smt_enabled = false
assert_false(cpu.smt_enabled, "should have disabled SMT")
@@ -44,24 +48,32 @@ func test_cpu() -> void:
# Test setting boost
cpu.boost_enabled = false
- assert_false(cpu.boost_enabled, "should have disabled boost")
+ #assert_false(cpu.boost_enabled, "should have disabled boost")
await wait_frames(1, "wait for change")
cpu.boost_enabled = true
- assert_true(cpu.boost_enabled, "should have enabled boost")
+ #assert_true(cpu.boost_enabled, "should have enabled boost")
await wait_frames(1, "wait for change")
+ # Test enumerating cores
+ var cores := cpu.get_cores()
+ assert_gt(cores.size(), 0, "should return at least 1 cpu core")
+ for core in cores:
+ gut.p("CPU Core: " + str(core.number))
+ gut.p(" ID: " + str(core.core_id))
+ gut.p(" Online: " + str(core.online))
+
func test_gpu() -> void:
- if not power_station.supports_power_station():
+ var powerstation := PowerStation.new()
+ powerstation.instance = load("res://core/systems/performance/power_station.tres") as PowerStationInstance
+ add_child_autoqfree(powerstation)
+
+ if not powerstation.instance.is_running():
pass_test("PowerStation is not running, skipping")
return
- var gpu := power_station.gpu
+ var gpu := powerstation.instance.get_gpu()
assert_not_null(gpu, "should return GPU instance")
- # Test enumerating cards
- var card_paths := gpu.enumerate_cards()
- #assert_gt(cards.size(), 0, "should return at least 1 gpu")
-
# Test all GPU card methods
var cards := gpu.get_cards()
for card in cards:
diff --git a/core/systems/power/power_manager.gd b/core/systems/power/power_manager.gd
index 371ff69ae..72fccbe19 100644
--- a/core/systems/power/power_manager.gd
+++ b/core/systems/power/power_manager.gd
@@ -1,352 +1,27 @@
-extends Resource
+@icon("res://assets/editor-icons/material-symbols--battery-profile-sharp.svg")
+extends Node
class_name PowerManager
-const POWER_BUS := "org.freedesktop.UPower"
-const UPOWER_PATH := "/org/freedesktop/UPower"
-const POWER_PREFIX := "/org/freedesktop/UPower/devices"
-const IFACE_UPOWER := "org.freedesktop.UPower"
-const IFACE_DEVICE := "org.freedesktop.UPower.Device"
+## Manages power settings.
+##
+## The [PowerManager] class is responsible for loading a [UPowerInstance] and
+## calling its 'process()' method each frame.
-enum DEVICE_TYPE {
- UNKNOWN,
- LINE_POWER,
- BATTERY,
- UPS,
- MONITOR,
- MOUSE,
- KEYBOARD,
- PDA,
- PHONE,
-}
+@export var instance: UPowerInstance = load("res://core/systems/power/power_manager.tres") as UPowerInstance
-enum DEVICE_STATE {
- UNKNOWN,
- CHARGING,
- DISCHARGING,
- EMPTY,
- FULLY_CHARGED,
- PENDING_CHARGE,
- PENDING_DISCHARGE,
-}
+# Keep a reference to device instances so they are not cleaned up automatically
+var _devices: Array[UPowerDevice]
+var logger := Log.get_logger("PowerManager")
-enum DEVICE_WARNING_LEVEL {
- UNKNOWN,
- NONE,
- DISCHARGING,
- LOW,
- CRITICAL,
- ACTION,
-}
-enum DEVICE_BATTERY_LEVEL {
- UNKNOWN,
- NONE,
- LOW,
- CRITICAL,
- NORMAL,
- HIGH,
- FULL,Z
-}
+func _ready() -> void:
+ var display_device := instance.get_display_device()
+ _devices.push_back(display_device)
+ if _devices.is_empty():
+ logger.warn("UPower not detected.")
-enum DEVICE_TECHNOLOGY {
- UNKNOWN,
- LITHIUM_ION,
- LITHIUM_POLYMER,
- LITHIUM_IRON_PHOSPHATE,
- LEAD_ACID,
- NICKLE_CADMIUM,
- NICKLE_METAL_HYDRIDE,
-}
-var dbus := load("res://core/global/dbus_system.tres") as DBusManager
-var upower := UPower.new(dbus.create_proxy(POWER_BUS, UPOWER_PATH))
-
-
-func get_devices() -> Array[Device]:
- var devices: Array[Device] = []
- var device_paths := upower.enumerate_devices()
-
- # Loop through all objects on the bus
- for path in device_paths:
- # Create a power Device from this object
- var proxy := dbus.create_proxy(POWER_BUS, path)
- var device := Device.new(proxy)
-
- devices.append(device)
-
- return devices
-
-
-func get_devices_by_type(type: DEVICE_TYPE) -> Array[Device]:
- var all_devices := get_devices()
- var type_devices : Array[Device]
- for device in all_devices:
- if device.type == type:
- type_devices.append(device)
- return type_devices
-
-
-func get_device(device_name: String) -> Device:
- var device_path := "/".join([POWER_PREFIX, device_name])
- var proxy := dbus.create_proxy(POWER_BUS, device_path)
- var device := Device.new(proxy)
-
- return device
-
-
-## Returns true if bluetooth can be used on this system
-func supports_power() -> bool:
- return dbus.bus_exists(POWER_BUS)
-
-
-class UPower extends Resource:
- signal updated
- var _proxy: DBusManager.Proxy
- var on_battery: bool:
- get:
- var property = _proxy.get_property(IFACE_UPOWER, "OnBattery")
- if not property is bool:
- return false
- return property
-
- func _init(proxy: DBusManager.Proxy) -> void:
- _proxy = proxy
- _proxy.properties_changed.connect(_on_properties_changed)
-
- func _on_properties_changed(iface: String, props: Dictionary) -> void:
- updated.emit()
-
- func enumerate_devices() -> Array:
- var result := _proxy.call_method(IFACE_UPOWER, "EnumerateDevices")
- var args := result.get_args()
- if args.size() != 1:
- return []
- if not args[0] is Array:
- return []
- return args[0]
-
-
-class Device extends Resource:
- signal porperties_changed
- signal updated
- var _proxy: DBusManager.Proxy
-
- func _init(proxy: DBusManager.Proxy) -> void:
- _proxy = proxy
- _proxy.properties_changed.connect(_on_properties_changed)
-
- func _on_properties_changed(iface: String, props: Dictionary) -> void:
- updated.emit()
-
- func refresh() -> void:
- _proxy.call_method(IFACE_DEVICE, "Refresh")
-
- var native_path: String:
- get:
- var property = _proxy.get_property(IFACE_DEVICE, "NativePath")
- if not property is String:
- return ""
- return property
-
- var vendor: String:
- get:
- var property = _proxy.get_property(IFACE_DEVICE, "Vendor")
- if not property is String:
- return ""
- return property
-
- var model: String:
- get:
- var property = _proxy.get_property(IFACE_DEVICE, "Model")
- if not property is String:
- return ""
- return property
-
- var serial: String:
- get:
- var property = _proxy.get_property(IFACE_DEVICE, "Serial")
- if not property is String:
- return ""
- return property
-
- var update_time: int:
- get:
- var property = _proxy.get_property(IFACE_DEVICE, "UpdateTime")
- if not property is int:
- return 0
- return property
-
- var type: int:
- get:
- var property = _proxy.get_property(IFACE_DEVICE, "Type")
- if not property is int:
- return 0
- return property
-
- var power_supply: bool:
- get:
- var property = _proxy.get_property(IFACE_DEVICE, "PowerSupply")
- if not property is bool:
- return false
- return property
-
- var has_history: bool:
- get:
- var property = _proxy.get_property(IFACE_DEVICE, "HasHistory")
- if not property is bool:
- return false
- return property
-
- var has_statistics: bool:
- get:
- var property = _proxy.get_property(IFACE_DEVICE, "HasStatisics")
- if not property is bool:
- return false
- return property
-
- var online: bool:
- get:
- var property = _proxy.get_property(IFACE_DEVICE, "Online")
- if not property is bool:
- return false
- return property
-
- var energy: float:
- get:
- var property = _proxy.get_property(IFACE_DEVICE, "Energy")
- if not property is float:
- return 0.0
- return property
-
- var energy_empty: float:
- get:
- var property = _proxy.get_property(IFACE_DEVICE, "EnergyEmpty")
- if not property is float:
- return 0.0
- return property
-
- var energy_full: float:
- get:
- var property = _proxy.get_property(IFACE_DEVICE, "EnergyFull")
- if not property is float:
- return 0.0
- return property
-
- var energy_full_design: float:
- get:
- var property = _proxy.get_property(IFACE_DEVICE, "EnergyFullDesign")
- if not property is float:
- return 0.0
- return property
-
- var energy_rate: float:
- get:
- var property = _proxy.get_property(IFACE_DEVICE, "EnergyRate")
- if not property is float:
- return 0.0
- return property
-
- var voltage: float:
- get:
- var property = _proxy.get_property(IFACE_DEVICE, "Voltage")
- if not property is float:
- return 0.0
- return property
-
- var charge_cycles: int:
- get:
- var property = _proxy.get_property(IFACE_DEVICE, "ChargeCycles")
- if not property is int:
- return 0
- return property
-
- var luminosity: float:
- get:
- var property = _proxy.get_property(IFACE_DEVICE, "Luminosity")
- if not property is float:
- return 0.0
- return property
-
- var time_to_empty: int:
- get:
- var property = _proxy.get_property(IFACE_DEVICE, "TimeToEmpty")
- if not property is int:
- return 0
- return property
-
- var time_to_full: int:
- get:
- var property = _proxy.get_property(IFACE_DEVICE, "TimeToFull")
- if not property is int:
- return 0
- return property
-
- var percentage: float:
- get:
- var property = _proxy.get_property(IFACE_DEVICE, "Percentage")
- if not property is float:
- return 0.0
- return property
-
- var temperature: float:
- get:
- var property = _proxy.get_property(IFACE_DEVICE, "Temperature")
- if not property is float:
- return 0.0
- return property
-
- var is_present: bool:
- get:
- var property = _proxy.get_property(IFACE_DEVICE, "IsPresent")
- if not property is bool:
- return false
- return property
-
- var state: int:
- get:
- var property = _proxy.get_property(IFACE_DEVICE, "State")
- if not property is int:
- return 0
- return property
-
- var is_rechargable: bool:
- get:
- var property = _proxy.get_property(IFACE_DEVICE, "IsRechargeable")
- if not property is bool:
- return false
- return property
-
- var capacity: float:
- get:
- var property = _proxy.get_property(IFACE_DEVICE, "Capacity")
- if not property is float:
- return 0.0
- return property
-
- var technology: int:
- get:
- var property = _proxy.get_property(IFACE_DEVICE, "Technology")
- if not property is int:
- return 0
- return property
-
- var warning_level: int:
- get:
- var property = _proxy.get_property(IFACE_DEVICE, "WarningLevel")
- if not property is int:
- return 0
- return property
-
- var battery_level: int:
- get:
- var property = _proxy.get_property(IFACE_DEVICE, "BatteryLevel")
- if not property is int:
- return 0
- return property
-
- var icon_name: String:
- get:
- var property = _proxy.get_property(IFACE_DEVICE, "IconName")
- if not property is String:
- return ""
- return property
+func _process(_delta: float) -> void:
+ if not instance:
+ return
+ instance.process()
diff --git a/core/systems/power/power_manager.tres b/core/systems/power/power_manager.tres
index a13360eaa..79b53674a 100644
--- a/core/systems/power/power_manager.tres
+++ b/core/systems/power/power_manager.tres
@@ -1,6 +1,3 @@
-[gd_resource type="Resource" script_class="PowerManager" load_steps=2 format=3 uid="uid://dxa4156di7yk2"]
-
-[ext_resource type="Script" path="res://core/systems/power/power_manager.gd" id="1_57v16"]
+[gd_resource type="UPowerInstance" format=3 uid="uid://pgiv8yxro3n8"]
[resource]
-script = ExtResource("1_57v16")
diff --git a/core/systems/power/power_manager_test.gd b/core/systems/power/power_manager_test.gd
new file mode 100644
index 000000000..76ef3a8c1
--- /dev/null
+++ b/core/systems/power/power_manager_test.gd
@@ -0,0 +1,20 @@
+extends GutTest
+
+
+func test_upower() -> void:
+ var power_manager := PowerManager.new()
+ power_manager.instance = load("res://core/systems/power/power_manager.tres")
+ add_child_autoqfree(power_manager)
+
+ if not power_manager.instance.is_running():
+ gut.p("InputPlumber is not running. Skipping tests.")
+ return
+
+ # Get the display device
+ var display_device := power_manager.instance.get_display_device()
+ assert_eq(display_device.dbus_path, "/org/freedesktop/UPower/devices/DisplayDevice")
+ gut.p("DBus Path: " + str(display_device.dbus_path))
+ gut.p("Battery level: " + str(display_device.battery_level))
+ gut.p("Icon name: " + str(display_device.icon_name))
+ gut.p("Percentage: " + str(display_device.percentage))
+ gut.p("State: " + str(display_device.state))
diff --git a/core/systems/power/power_saver.gd b/core/systems/power/power_saver.gd
index a3a5a91b8..ba6dbdc26 100644
--- a/core/systems/power/power_saver.gd
+++ b/core/systems/power/power_saver.gd
@@ -6,7 +6,7 @@ class_name PowerSaver
var display := load("res://core/global/display_manager.tres") as DisplayManager
var settings := load("res://core/global/settings_manager.tres") as SettingsManager
-var power_manager := load("res://core/systems/power/power_manager.tres") as PowerManager
+var power_manager := load("res://core/systems/power/power_manager.tres") as UPowerInstance
const MINUTE := 60
@@ -27,14 +27,13 @@ var dimmed := false
var prev_brightness := {}
var supports_brightness := display.supports_brightness()
var has_battery := false
-var batteries : Array[PowerManager.Device]
+var display_device := power_manager.get_display_device()
var logger := Log.get_logger("PowerSaver")
func _ready() -> void:
- batteries = power_manager.get_devices_by_type(PowerManager.DEVICE_TYPE.BATTERY)
- if batteries.size() > 0:
- has_battery = true
+ if display_device:
+ has_battery = display_device.is_present
if dim_screen_enabled and supports_brightness:
dim_timer.timeout.connect(_on_dim_timer_timeout)
@@ -46,9 +45,9 @@ func _ready() -> void:
func _on_dim_timer_timeout() -> void:
# If dimming is disabled when charging, check the battery state
- if has_battery and not dim_when_charging:
- var status: int = batteries[0].state
- if status in [PowerManager.DEVICE_STATE.CHARGING, PowerManager.DEVICE_STATE.FULLY_CHARGED]:
+ if has_battery and display_device and not dim_when_charging:
+ var status := display_device.state
+ if status in [UPowerDevice.STATE_CHARGING, UPowerDevice.STATE_FULLY_CHARGED]:
logger.debug("Not dimming because battery is charging")
return
if not has_battery and not dim_when_charging:
@@ -71,9 +70,9 @@ func _on_dim_timer_timeout() -> void:
func _on_suspend_timer_timeout() -> void:
# If suspend is disabled when charging, check the battery state
- if has_battery and not suspend_when_charging:
- var status: int = batteries[0].state
- if status in [PowerManager.DEVICE_STATE.CHARGING, PowerManager.DEVICE_STATE.FULLY_CHARGED]:
+ if has_battery and display_device and not suspend_when_charging:
+ var status := display_device.state
+ if status in [UPowerDevice.STATE_CHARGING, UPowerDevice.STATE_FULLY_CHARGED]:
logger.debug("Not suspending because battery is charging")
return
if not has_battery and not suspend_when_charging:
diff --git a/core/systems/resource/resource_registry.tres b/core/systems/resource/resource_registry.tres
new file mode 100644
index 000000000..4c457a768
--- /dev/null
+++ b/core/systems/resource/resource_registry.tres
@@ -0,0 +1,3 @@
+[gd_resource type="ResourceRegistry" format=3 uid="uid://bsr58xihnpn1j"]
+
+[resource]
diff --git a/core/systems/sandbox/sandbox_bubblewrap.gd b/core/systems/sandbox/sandbox_bubblewrap.gd
index 96ab5677d..e42a28a3d 100644
--- a/core/systems/sandbox/sandbox_bubblewrap.gd
+++ b/core/systems/sandbox/sandbox_bubblewrap.gd
@@ -27,15 +27,16 @@ func is_available() -> bool:
# Applies additional blacklists depending on if we're launching a steam app
func _apply_quirks(app: LibraryLaunchItem) -> PackedStringArray:
var args := PackedStringArray()
- # Only block device access if this is a Steam app
- if app.command != "steam":
- return args
-
- # Block any hidraw devices
- var devices := DirAccess.get_files_at("/dev")
- for dev in devices:
- if not dev.begins_with("hidraw"):
- continue
- var path := "/".join(["/dev", dev])
- args.append_array(["--bind", "/dev/null", path])
return args
+# # Only block device access if this is a Steam app
+# if app.command != "steam":
+# return args
+#
+# # Block any hidraw devices
+# var devices := DirAccess.get_files_at("/dev")
+# for dev in devices:
+# if not dev.begins_with("hidraw"):
+# continue
+# var path := "/".join(["/dev", dev])
+# args.append_array(["--bind", "/dev/null", path])
+# return args
diff --git a/core/systems/state/state.gd b/core/systems/state/state.gd
index e76304ccc..bb3f323a5 100644
--- a/core/systems/state/state.gd
+++ b/core/systems/state/state.gd
@@ -36,4 +36,3 @@ func _to_string() -> String:
if not name.is_empty():
return "".format({"name": name})
return "".format({"rid": get_rid()})
-
diff --git a/core/systems/testing/pre_run.gd b/core/systems/testing/pre_run.gd
index b78c3f844..3732566c6 100644
--- a/core/systems/testing/pre_run.gd
+++ b/core/systems/testing/pre_run.gd
@@ -1,11 +1,19 @@
extends GutHookScript
-var PID: int = OS.get_process_id()
-var gamescope := load("res://core/global/gamescope.tres") as Gamescope
-var window_id = gamescope.get_window_id(PID, gamescope.XWAYLAND.OGUI)
+var PID: int
+var gamescope: GamescopeInstance
+var window_id: int
func run() -> void:
+ PID = OS.get_process_id()
+ gamescope = load("res://core/systems/gamescope/gamescope.tres") as GamescopeInstance
+ var xwayland := gamescope.get_xwayland(gamescope.XWAYLAND_TYPE_OGUI)
+ if not xwayland:
+ return
+ var window_ids := xwayland.get_windows_for_pid(PID)
+ if not window_ids.is_empty():
+ window_id = window_ids[0]
if window_id < 0:
return
diff --git a/core/systems/threading/command.gd b/core/systems/threading/command.gd
deleted file mode 100644
index af3ea375e..000000000
--- a/core/systems/threading/command.gd
+++ /dev/null
@@ -1,73 +0,0 @@
-extends RefCounted
-class_name Command
-
-## Execute an OS command in a thread
-##
-## The [Command] class allows you to asyncronously execute a command in a thread
-## that does not block the main thread. Optionally a [SharedThread] can be
-## passed if you do not wish for the command to execute in the [ThreadPool].[br]
-## Example:
-## [codeblock]
-## var cmd := Command.new("cat", ["/etc/issue"])
-## if cmd.execute() != OK:
-## print("Command failed with exit code: ", cmd.code)
-##
-## print(cmd.stdout)
-## [/codeblock]
-
-## The [ThreadPool] to execute the command in
-var thread_pool := load("res://core/systems/threading/thread_pool.tres") as ThreadPool
-## Optional [SharedThread] to execute the command in
-var shared_thread: SharedThread
-## Path to the command to execute
-var cmd: String
-## Array of arguments to pass to the command
-var args := PackedStringArray()
-## The command output after execution
-var stdout: String
-## The exit code of the command after execution
-var code := 0
-
-
-func _init(command: String = "", arguments: PackedStringArray = [], thread: SharedThread = null) -> void:
- cmd = command
- args = arguments
- if thread:
- shared_thread = thread
-
-
-## Execute the command in a thread and return the command's exit code.
-func execute() -> int:
- var ret: int
- if shared_thread:
- ret = await _shared_thread_exec()
- else:
- ret = await _thread_pool_exec()
-
- return ret
-
-
-func _shared_thread_exec() -> int:
- shared_thread.start()
-
- var output := []
- var ret := await shared_thread.exec(OS.execute.bind(cmd, args, output)) as int
- code = ret
- stdout = output[0]
-
- return ret
-
-
-func _thread_pool_exec() -> int:
- thread_pool.start()
-
- var output := []
- var ret := await thread_pool.exec(OS.execute.bind(cmd, args, output)) as int
- code = ret
- stdout = output[0]
-
- return ret
-
-
-func _to_string() -> String:
- return "Command<{0} {1}>".format([cmd, " ".join(args)])
diff --git a/core/systems/threading/command_sync.gd b/core/systems/threading/command_sync.gd
deleted file mode 100644
index 4a522cd84..000000000
--- a/core/systems/threading/command_sync.gd
+++ /dev/null
@@ -1,35 +0,0 @@
-extends RefCounted
-class_name CommandSync
-
-## Execute a blocking OS command
-##
-## The [CommandSync] class allows you to syncronously execute a command that
-## will block the executing thread.
-
-## Path to the command to execute
-var cmd: String
-## Array of arguments to pass to the command
-var args := PackedStringArray()
-## The command output after execution
-var stdout: String
-## The exit code of the command after execution
-var code := 0
-
-
-func _init(command: String = "", arguments: PackedStringArray = []) -> void:
- cmd = command
- args = arguments
-
-
-## Execute the command in a thread and return the command's exit code.
-func execute() -> int:
- var output := []
- var ret := OS.execute(cmd, args, output)
- code = ret
- stdout = output[0]
-
- return ret
-
-
-func _to_string() -> String:
- return "CommandSync<{0} {1}>".format([cmd, " ".join(args)])
diff --git a/core/systems/threading/command_test.gd b/core/systems/threading/command_test.gd
new file mode 100644
index 000000000..88634a4e0
--- /dev/null
+++ b/core/systems/threading/command_test.gd
@@ -0,0 +1,60 @@
+extends GutTest
+
+
+func test_command():
+ # Ensure the [ResourceProcessor] node is added to the scene tree
+ var resource_processor := ResourceProcessor.new()
+ resource_processor.registry = load("res://core/systems/resource/resource_registry.tres") as ResourceRegistry
+ add_child_autoqfree(resource_processor)
+
+ var command := Command.create("ls", ["/", "/idontexistforrealz"])
+ gut.p("Executing command: " + command.command + " " + str(command.args))
+ if command.execute() != OK:
+ gut.p(" Failed to start executing command")
+ var code := await command.finished as int
+ gut.p(" Command exited with code: " + str(code))
+ gut.p(command.stdout)
+ gut.p(command.stderr)
+ assert_false(command.stdout.is_empty(), "should return output")
+ assert_eq(command.stderr, "ls: cannot access '/idontexistforrealz': No such file or directory\n", "should produce error output")
+
+ command = Command.create("echo", ["-n", "one", "two", "three"])
+ gut.p("Executing command: " + command.command + " " + str(command.args))
+ if command.execute() != OK:
+ gut.p(" Failed to start executing command")
+ code = await command.finished as int
+ gut.p(" Command exited with code: " + str(code))
+ gut.p(command.stdout)
+ assert_eq(code, OK, "should return zero")
+ assert_eq(command.stdout, "one two three", "should have correct output")
+
+ command = Command.create("Id0NtEx1st", [])
+ gut.p("Executing command: " + command.command + " " + str(command.args))
+ if command.execute() != OK:
+ gut.p(" Failed to start executing command")
+ code = await command.finished as int
+ assert_ne(code, OK, "should fail to run")
+
+
+func test_command_cancel():
+ # Ensure the [ResourceProcessor] node is added to the scene tree
+ var resource_processor := ResourceProcessor.new()
+ resource_processor.registry = load("res://core/systems/resource/resource_registry.tres") as ResourceRegistry
+ add_child_autoqfree(resource_processor)
+
+ var command := Command.create("sleep", ["5"])
+ command.timeout = 1.0
+ gut.p("Executing command: " + command.command + " " + str(command.args))
+ if command.execute() != OK:
+ gut.p(" Failed to start executing command")
+ var code := await command.finished as int
+ gut.p(" Command exited with code: " + str(code))
+ assert_eq(code, command.EXIT_CODE_CANCEL, "should exit with code 130, indicating cancellation")
+
+
+func test_command_sync():
+ var command := Command.create("sleep", ["1"])
+ gut.p("Executing command: " + command.command + " " + str(command.args))
+ var code := command.execute_blocking()
+ gut.p(" Command exited with code: " + str(code))
+ assert_eq(code, 0, "should exit ok")
diff --git a/core/systems/threading/linuxthread_test.gd b/core/systems/threading/linuxthread_test.gd
index 9e1f19600..97396e3f2 100644
--- a/core/systems/threading/linuxthread_test.gd
+++ b/core/systems/threading/linuxthread_test.gd
@@ -2,9 +2,9 @@ extends GutTest
func test_subreaper_create_process() -> void:
- var pid := LinuxThread.subreaper_create_process("sleep", ["1"])
+ var pid := SubReaper.create_process("sleep", ["1"])
gut.p("Got reaper PID: " + str(pid))
-
+
assert_true(OS.is_process_running(pid), "reaper process should be running")
await wait_seconds(2)
assert_false(OS.is_process_running(pid), "reaper process should have exited")
diff --git a/core/systems/threading/pty_test.gd b/core/systems/threading/pty_test.gd
new file mode 100644
index 000000000..6386fa7d8
--- /dev/null
+++ b/core/systems/threading/pty_test.gd
@@ -0,0 +1,24 @@
+extends GutTest
+
+
+func test_pty() -> void:
+ var pty := Pty.new()
+ add_child_autoqfree(pty)
+
+ # Listen for output from the command
+ var on_line_written := func(line: String):
+ gut.p("Line: " + line)
+ if line.contains("Type something:"):
+ pty.write_line("Hello World")
+ pty.line_written.connect(on_line_written)
+
+ # Execute the command in the PTY
+ var result := pty.exec("bash", PackedStringArray(["-c", "read -p 'Type something: ' foo; echo 'You typed:' $foo"]))
+ assert_eq(result, OK)
+
+ # Wait for the command to exit
+ var exit_code = await pty.finished
+
+ gut.p("Command finished with exit code: " + str(exit_code))
+
+ await wait_seconds(5, "Waiting")
diff --git a/core/systems/threading/shared_thread.gd b/core/systems/threading/shared_thread.gd
index ffd820f1a..416021d94 100644
--- a/core/systems/threading/shared_thread.gd
+++ b/core/systems/threading/shared_thread.gd
@@ -94,17 +94,18 @@ func set_priority(value: int) -> int:
mutex.lock()
var thread_id := tid
mutex.unlock()
- if LinuxThread.get_tid() != thread_id:
- logger.debug("Set thread priority was called from another thread")
- return await exec(set_priority.bind(value))
+ # TODO: fixme
+ #if LinuxThread.get_tid() != thread_id:
+ # logger.debug("Set thread priority was called from another thread")
+ # return await exec(set_priority.bind(value))
# Set the thread priority if this function was called from the SharedThread
- var err := LinuxThread.set_thread_priority(value)
- if err == OK:
- niceness = value
- logger.info("Set thread niceness on {0} ({1}) to: {2}".format([name, thread_id, value]))
+ #var err := LinuxThread.set_thread_priority(value)
+ #if err == OK:
+ # niceness = value
+ # logger.info("Set thread niceness on {0} ({1}) to: {2}".format([name, thread_id, value]))
- return err
+ return OK
## Add the given [NodeThread] to the list of nodes to process. This should
@@ -204,9 +205,9 @@ func remove_process(method: Callable) -> void:
func _run() -> void:
# Update the thread ID
mutex.lock()
- tid = LinuxThread.get_tid()
+ #tid = LinuxThread.get_tid()
mutex.unlock()
- logger.info("Started thread with thread ID: " + str(LinuxThread.get_tid()))
+ #logger.info("Started thread with thread ID: " + str(LinuxThread.get_tid()))
# If the nice value isn't default, reassign the thread priority
if niceness != 0:
diff --git a/core/systems/threading/thread_pool.gd b/core/systems/threading/thread_pool.gd
index 7fa774cb3..0fe400f01 100644
--- a/core/systems/threading/thread_pool.gd
+++ b/core/systems/threading/thread_pool.gd
@@ -25,6 +25,7 @@ var logger := Log.get_logger("ThreadPool", Log.LEVEL.INFO)
## A queued task to run in the thread pool
class Task extends RefCounted:
+ var task_name: String
var method: Callable
var ret: Variant
@@ -75,10 +76,14 @@ func is_running() -> bool:
## method and awaits it to be called during the process loop. You should await
## this method if your method returns something.
## E.g. [code]var result = await thread_pool.exec(myfund.bind("myarg"))[/code]
-func exec(method: Callable) -> Variant:
+func exec(method: Callable, name: String = "") -> Variant:
if size == 0:
return method.call()
var task := Task.new()
+ if name.is_empty():
+ task.task_name = str(method)
+ else:
+ task.task_name = name
task.method = method
mutex.lock()
queue.append(task)
@@ -108,7 +113,7 @@ func _process(id: int) -> void:
var task := queue.pop_front() as Task
mutex.unlock()
- logger.debug("Processing task in thread " + str(id))
+ logger.debug("Processing task", task.task_name, "in thread " + str(id))
_async_call(task)
diff --git a/core/systems/utility/vdf_test.gd b/core/systems/utility/vdf_test.gd
new file mode 100644
index 000000000..89e665907
--- /dev/null
+++ b/core/systems/utility/vdf_test.gd
@@ -0,0 +1,80 @@
+extends GutTest
+
+const LOGIN_USERS_VDF: String = """"users"
+{
+ "12345678901234567"
+ {
+ "AccountName" "ACCOUNT_NAME"
+ "MostRecent" "1"
+ "RememberPassword" "1"
+ "PersonaName" "PERSONA_NAME"
+ "Timestamp" "1234567890"
+ }
+}
+"""
+
+const LOGIN_USERS_DICT: Dictionary = {
+ "users": {
+ "12345678901234567": {
+ "AccountName": "ACCOUNT_NAME",
+ "MostRecent": "1",
+ "PersonaName": "PERSONA_NAME",
+ "RememberPassword": "1",
+ "Timestamp": "1234567890"
+ }
+ }
+}
+
+const LOCAL_VDF: String = """"MachineUserConfigStore"
+{
+ "Software"
+ {
+ "valve"
+ {
+ "Steam"
+ {
+ "ConnectCache"
+ {
+ "1111a2222" "someverylongtext"
+ }
+ }
+ }
+ }
+}
+"""
+
+const LOCAL_DICT: Dictionary = {
+ "MachineUserConfigStore": {
+ "Software": {
+ "valve": {
+ "Steam": {
+ "ConnectCache": {
+ "1111a2222": "someverylongtext"
+ }
+ }
+ }
+ }
+ }
+}
+
+const vdf_content: Array[String] = [LOGIN_USERS_VDF, LOCAL_VDF]
+const dict_content: Array[Dictionary] = [LOGIN_USERS_DICT, LOCAL_DICT]
+
+func test_parse() -> void:
+ var i := 0
+ for vdf_data in vdf_content:
+ var vdf := Vdf.new()
+ var err := vdf.parse(vdf_data)
+ assert_eq(err, OK, "should successfully parse")
+ gut.p("Got result: " + str(vdf.data))
+ assert_eq(vdf.data, dict_content[i], "should deserialize the correct values")
+ i += 1
+
+
+func test_stringify() -> void:
+ var i := 0
+ for dict_data in dict_content:
+ var text := Vdf.stringify(dict_data)
+ gut.p("Got serialized result:\n" + text)
+ assert_false(text.is_empty(), "should serialize into text")
+ i += 1
diff --git a/core/ui/card_ui/card_ui.gd b/core/ui/card_ui/card_ui.gd
index 44327f30a..057c7f16d 100644
--- a/core/ui/card_ui/card_ui.gd
+++ b/core/ui/card_ui/card_ui.gd
@@ -1,10 +1,11 @@
extends Control
var platform := load("res://core/global/platform.tres") as Platform
-var gamescope := load("res://core/global/gamescope.tres") as Gamescope
+var gamescope := load("res://core/systems/gamescope/gamescope.tres") as GamescopeInstance
var library_manager := load("res://core/global/library_manager.tres") as LibraryManager
var settings_manager := load("res://core/global/settings_manager.tres") as SettingsManager
-var input_plumber := load("res://core/systems/input/input_plumber.tres") as InputPlumber
+var input_plumber := load("res://core/systems/input/input_plumber.tres") as InputPlumberInstance
+var launch_manager := load("res://core/global/launch_manager.tres") as LaunchManager
var state_machine := (
preload("res://assets/state/state_machines/global_state_machine.tres") as StateMachine
@@ -20,7 +21,10 @@ var osk_state := preload("res://assets/state/states/osk.tres") as State
var power_state := preload("res://assets/state/states/power_menu.tres") as State
var PID: int = OS.get_process_id()
-var overlay_window_id := gamescope.get_window_id(PID, gamescope.XWAYLAND.OGUI)
+var _xwayland_primary := gamescope.get_xwayland(gamescope.XWAYLAND_TYPE_PRIMARY)
+var _xwayland_ogui := gamescope.get_xwayland(gamescope.XWAYLAND_TYPE_OGUI)
+var _xwayland_game := gamescope.get_xwayland(gamescope.XWAYLAND_TYPE_GAME)
+var overlay_window_id := 0
@onready var panel := $%Panel as Panel
@onready var ui_container := $%MenuContent as MarginContainer
@@ -33,6 +37,12 @@ var overlay_window_id := gamescope.get_window_id(PID, gamescope.XWAYLAND.OGUI)
var logger = Log.get_logger("Main", Log.LEVEL.INFO)
func _init() -> void:
+ # Discover the window id of OpenGamepadUI
+ if _xwayland_ogui:
+ var ogui_windows := _xwayland_ogui.get_windows_for_pid(PID)
+ if not ogui_windows.is_empty():
+ overlay_window_id = ogui_windows[0]
+
# Tell gamescope that we're an overlay
if overlay_window_id <= 0:
logger.error("Unable to detect Window ID. Overlay is not going to work!")
@@ -47,12 +57,34 @@ func _setup(window_id: int) -> void:
return
# Pretend to be Steam
# Gamescope is hard-coded to look for appId 769
- if gamescope.set_main_app(window_id) != OK:
+ if _xwayland_primary.set_main_app(window_id) != OK:
logger.error("Unable to set STEAM_GAME atom!")
# Sets ourselves to the input focus
- if gamescope.set_input_focus(window_id, 1) != OK:
+ if _xwayland_primary.set_input_focus(window_id, 1) != OK:
logger.error("Unable to set STEAM_INPUT_FOCUS atom!")
+ # Override reserved app ids for any newly created windows
+ # Listen for window created/destroyed events
+ var on_window_created := func(window_id: int):
+ logger.debug("Window created:", window_id)
+ var try := 0
+ while try < 10:
+ if _xwayland_game.has_app_id(window_id):
+ break
+ try += 1
+ await get_tree().create_timer(0.2).timeout # wait a beat
+ var app_id := _xwayland_game.get_app_id(window_id)
+ if app_id == GamescopeInstance.OVERLAY_GAME_ID:
+ # Find the current running app and use that app id
+ var running := launch_manager.get_running()
+ running.reverse()
+ for app in running:
+ _xwayland_game.set_app_id(window_id, app.app_id)
+ return
+ logger.warn("Unable to find a running app to tie Steam to")
+ _xwayland_game.set_app_id(window_id, 7769)
+ _xwayland_game.window_created.connect(on_window_created)
+
# Called when the node enters the scene tree for the first time.
# gamescope --xwayland-count 2 -- build/opengamepad-ui.x86_64
@@ -111,19 +143,24 @@ func _ready() -> void:
get_viewport().gui_focus_changed.connect(_on_focus_changed)
library_manager.reload_library()
- # Set the initial intercept mode
- input_plumber.set_intercept_mode(InputPlumber.INTERCEPT_MODE.ALL)
- var on_device_changed := func(device: InputPlumber.CompositeDevice):
- var intercept_mode : InputPlumber.INTERCEPT_MODE = input_plumber.intercept_mode_current
+ # Setup inputplumber to receive guide presses.
+ input_plumber.set_intercept_mode(InputPlumberInstance.INTERCEPT_MODE_ALL)
+ input_plumber.set_intercept_activation(PackedStringArray(["Gamepad:Button:Guide"]), "Gamepad:Button:Guide")
+
+ # Sets the intercept mode and intercept activation keys to what overlay_mode expects.
+ var on_device_changed := func(device: CompositeDevice):
+ var intercept_mode := input_plumber.intercept_mode
logger.debug("Setting intercept mode to: " + str(intercept_mode))
- input_plumber.set_intercept_mode_single(intercept_mode, device)
- input_plumber.composite_device_changed.connect(on_device_changed)
+ device.intercept_mode = intercept_mode
+ device.set_intercept_activation(PackedStringArray(["Gamepad:Button:Guide"]), "Gamepad:Button:Guide")
+ input_plumber.composite_device_added.connect(on_device_changed)
# Set the theme if one was set
var theme_path := settings_manager.get_value("general", "theme", "res://assets/themes/card_ui-dracula.tres") as String
logger.debug("Setting theme to: " + theme_path)
var loaded_theme = load(theme_path)
if loaded_theme != null:
+ @warning_ignore("unsafe_call_argument")
set_theme(loaded_theme)
else:
logger.debug("Unable to load theme")
@@ -137,13 +174,13 @@ func _on_focus_changed(control: Control) -> void:
## Invoked when the in-game state was entered
func _on_game_state_entered(_from: State) -> void:
# Pass all gamepad input to the game
- input_plumber.set_intercept_mode(InputPlumber.INTERCEPT_MODE.PASS)
+ input_plumber.set_intercept_mode(InputPlumberInstance.INTERCEPT_MODE_PASS)
# Turn off gamescope blur effect
- _set_blur(gamescope.BLUR_MODE.OFF)
+ _set_blur(GamescopeXWayland.BLUR_MODE_OFF)
# Set gamescope input focus to off so the user can interact with the game
- if gamescope.set_input_focus(overlay_window_id, 0) != OK:
+ if _xwayland_ogui and _xwayland_ogui.set_input_focus(overlay_window_id, 0) != OK:
logger.error("Unable to set STEAM_INPUT_FOCUS atom!")
# Ensure panel is invisible
@@ -160,7 +197,7 @@ func _on_game_state_entered(_from: State) -> void:
## Invoked when the in-game state is exited
func _on_game_state_exited(to: State) -> void:
# Intercept all gamepad input when not in-game
- input_plumber.set_intercept_mode(InputPlumber.INTERCEPT_MODE.ALL)
+ input_plumber.set_intercept_mode(InputPlumberInstance.INTERCEPT_MODE_ALL)
# Revert back to the default gamepad profile
#gamepad_manager.set_gamepads_profile(null)
@@ -171,16 +208,18 @@ func _on_game_state_exited(to: State) -> void:
if current_popup == osk_state:
return
- if gamescope.set_input_focus(overlay_window_id, 1) != OK:
- logger.error("Unable to set STEAM_INPUT_FOCUS atom!")
+ if _xwayland_primary:
+ if _xwayland_primary.set_input_focus(overlay_window_id, 1) != OK:
+ logger.error("Unable to set STEAM_INPUT_FOCUS atom!")
# If the in-game state still exists in the stack, set the blur state.
if state_machine.has_state(in_game_state):
panel.visible = false
# Only blur if the focused GFX app is set
- var should_blur := settings_manager.get_value("display", "enable_overlay_blur", true) as bool
- if should_blur and gamescope.get_focused_app_gfx() != Gamescope.OVERLAY_GAME_ID:
- _set_blur(gamescope.BLUR_MODE.ALWAYS)
+ if _xwayland_primary:
+ var should_blur := settings_manager.get_value("display", "enable_overlay_blur", false) as bool
+ if should_blur and _xwayland_primary.get_focused_app_gfx() != gamescope.OVERLAY_GAME_ID:
+ _set_blur(GamescopeXWayland.BLUR_MODE_ALWAYS)
else:
_on_game_state_removed()
@@ -195,7 +234,7 @@ func _on_game_state_exited(to: State) -> void:
## Invoked when the in-game state is removed
func _on_game_state_removed() -> void:
# Turn off gamescope blur
- _set_blur(gamescope.BLUR_MODE.OFF)
+ _set_blur(GamescopeXWayland.BLUR_MODE_OFF)
# Un-hide the background panel
panel.visible = true
@@ -208,12 +247,14 @@ func _on_game_state_removed() -> void:
# Sets the blur mode in gamescope
-func _set_blur(mode: Gamescope.BLUR_MODE) -> void:
+func _set_blur(mode: int) -> void:
+ if not _xwayland_primary:
+ return
# Sometimes setting this may fail when Steam closes. Retry several times.
for try in range(10):
- if gamescope.set_blur_mode(mode) != OK:
- logger.warn("Unable to set blur mode atom!")
- var current := gamescope.get_blur_mode()
+ if _xwayland_primary:
+ _xwayland_primary.set_blur_mode(mode)
+ var current := _xwayland_primary.get_blur_mode()
if mode == current:
break
logger.warn("Retrying in " + str(try) + "ms")
@@ -255,7 +296,7 @@ func _input(event: InputEvent) -> void:
if not power_timer.is_stopped():
logger.info("Received suspend signal")
for connection in power_timer.timeout.get_connections():
- power_timer.timeout.disconnect(connection["callable"])
+ power_timer.timeout.disconnect(connection["callable"] as Callable)
power_timer.stop()
var output: Array = []
if OS.execute("systemctl", ["suspend"], output) != OK:
@@ -263,12 +304,12 @@ func _input(event: InputEvent) -> void:
# Removes specified child elements from the given Node.
-func _remove_children(remove_list: PackedStringArray, parent:Node) -> void:
+func _remove_children(remove_list: PackedStringArray, parent: Node) -> void:
var child_count := parent.get_child_count()
- var to_remove_list := []
+ var to_remove_list: Array[Node]
for child_idx in child_count:
- var child = parent.get_child(child_idx)
+ var child := parent.get_child(child_idx)
logger.trace("Checking if " + child.name + " in remove list...")
if child.name in remove_list:
logger.trace(child.name + " queued for removal!")
diff --git a/core/ui/card_ui/card_ui.tscn b/core/ui/card_ui/card_ui.tscn
index 80c61b45a..28e61d095 100644
--- a/core/ui/card_ui/card_ui.tscn
+++ b/core/ui/card_ui/card_ui.tscn
@@ -1,33 +1,42 @@
-[gd_scene load_steps=38 format=3 uid="uid://fhriwlhm0lcj"]
+[gd_scene load_steps=47 format=3 uid="uid://fhriwlhm0lcj"]
[ext_resource type="PackedScene" uid="uid://n83wlhmmsu3j" path="res://core/systems/input/input_manager.tscn" id="1_34t85"]
[ext_resource type="Script" path="res://core/ui/card_ui/card_ui.gd" id="1_f8851"]
[ext_resource type="PackedScene" uid="uid://dlegwm7jqfe2i" path="res://core/systems/boxart/boxart_local.tscn" id="2_600i0"]
[ext_resource type="PackedScene" uid="uid://ch6qw6obetalo" path="res://core/systems/library/library_desktop.tscn" id="3_68bes"]
[ext_resource type="Script" path="res://core/systems/input/input_icon_processor.gd" id="3_y116l"]
-[ext_resource type="PackedScene" uid="uid://cbboox5bujlx1" path="res://core/systems/launcher/launch_manager.tscn" id="4_tgw75"]
+[ext_resource type="Script" path="res://core/systems/gamescope/gamescope.gd" id="4_ksi1t"]
[ext_resource type="PackedScene" uid="uid://uam46dtvo2yh" path="res://core/systems/plugin/plugin_manager.tscn" id="5_dv70s"]
+[ext_resource type="GamescopeInstance" uid="uid://chd0nc6gbfnw0" path="res://core/systems/gamescope/gamescope.tres" id="5_wmkau"]
[ext_resource type="PackedScene" uid="uid://o70x5igrlq30" path="res://core/ui/card_ui/home/cardui_home.tscn" id="6_12lhu"]
[ext_resource type="PackedScene" uid="uid://dnq5j20fbcrwx" path="res://core/systems/power/power_saver.tscn" id="8_hyc1j"]
[ext_resource type="PackedScene" uid="uid://bcdk1lj6enq3l" path="res://core/ui/card_ui/launch/game_launch_menu.tscn" id="9_m34in"]
[ext_resource type="PackedScene" uid="uid://d2jiecrd5sw4s" path="res://core/ui/card_ui/settings/settings_menu.tscn" id="10_1ruvi"]
[ext_resource type="PackedScene" uid="uid://d4bmkauhrlhq0" path="res://core/ui/card_ui/navigation/search_bar_menu.tscn" id="10_7bl6b"]
[ext_resource type="PackedScene" uid="uid://58qlqqbh58im" path="res://core/ui/card_ui/launch/game_settings.tscn" id="10_7cj6o"]
+[ext_resource type="Script" path="res://core/systems/power/power_manager.gd" id="10_opsp8"]
[ext_resource type="PackedScene" uid="uid://uqkwpeq7f1o" path="res://core/ui/card_ui/library/library_menu.tscn" id="10_uqodp"]
+[ext_resource type="UPowerInstance" uid="uid://pgiv8yxro3n8" path="res://core/systems/power/power_manager.tres" id="11_nk5v7"]
[ext_resource type="PackedScene" uid="uid://by0i08fw1fwty" path="res://core/ui/card_ui/navigation/top_button_menu.tscn" id="11_x7ns7"]
[ext_resource type="PackedScene" uid="uid://cd2p3lu01aric" path="res://core/ui/card_ui/navigation/context_bar_menu.tscn" id="12_bstc8"]
[ext_resource type="PackedScene" uid="uid://jfacx7uys32r" path="res://core/ui/card_ui/main-menu/main_menu.tscn" id="13_46tck"]
[ext_resource type="PackedScene" uid="uid://cwarv58ju0sow" path="res://core/ui/card_ui/gamepad/gamepad_settings.tscn" id="13_n64ve"]
+[ext_resource type="Script" path="res://core/systems/performance/power_station.gd" id="13_tag7s"]
+[ext_resource type="PowerStationInstance" uid="uid://c2mmrnh3rcs58" path="res://core/systems/performance/power_station.tres" id="14_a5vk3"]
[ext_resource type="PackedScene" uid="uid://b30stcxjwk3od" path="res://core/ui/card_ui/ootbe/first_boot_menu.tscn" id="14_dpfu1"]
+[ext_resource type="Script" path="res://core/systems/launcher/launcher.gd" id="14_fs00k"]
[ext_resource type="PackedScene" uid="uid://hroo3ll4inrb" path="res://core/ui/card_ui/quick_bar/quick_bar_menu.tscn" id="14_lsaok"]
+[ext_resource type="Script" path="res://core/systems/network/network_manager.gd" id="14_rqu7s"]
+[ext_resource type="NetworkManagerInstance" uid="uid://cmwavccnjwpr0" path="res://core/systems/network/network_manager.tres" id="15_k47ua"]
[ext_resource type="PackedScene" uid="uid://dj1fooc3gh13l" path="res://core/ui/card_ui/help/help_menu.tscn" id="15_m1wp2"]
+[ext_resource type="ResourceRegistry" uid="uid://bsr58xihnpn1j" path="res://core/systems/resource/resource_registry.tres" id="15_ne50o"]
[ext_resource type="PackedScene" uid="uid://cu4l0d1joc37w" path="res://core/ui/card_ui/navigation/in-game_notification.tscn" id="16_bcudw"]
[ext_resource type="PackedScene" uid="uid://vf4sij64f82b" path="res://core/ui/common/osk/on_screen_keyboard.tscn" id="18_462u5"]
[ext_resource type="PackedScene" uid="uid://doft5r1y37j1" path="res://core/ui/components/volume_indicator.tscn" id="18_g4maw"]
[ext_resource type="PackedScene" uid="uid://bbcd5tclmp2ux" path="res://core/ui/card_ui/navigation/library_loading_notification.tscn" id="20_7tnsn"]
[ext_resource type="PackedScene" uid="uid://lfm3ps837gy5" path="res://core/ui/card_ui/power/power_menu.tscn" id="20_noim3"]
[ext_resource type="VideoStream" path="res://assets/videos/boot.ogv" id="21_s3peg"]
-[ext_resource type="PackedScene" path="res://core/ui/common/game/game_loading.tscn" id="22_morxu"]
+[ext_resource type="PackedScene" uid="uid://b1kist0rarpcy" path="res://core/ui/common/game/game_loading.tscn" id="22_morxu"]
[ext_resource type="PackedScene" uid="uid://ccwn4n40imfg8" path="res://core/ui/components/containers/overlay_container.tscn" id="23_h8glb"]
[ext_resource type="PackedScene" uid="uid://bw8113ocotx2r" path="res://core/systems/effects/fade_effect.tscn" id="27_jq430"]
[ext_resource type="PackedScene" uid="uid://ekhjpmat02f8" path="res://core/systems/effects/slide_effect.tscn" id="28_ex7w4"]
@@ -84,26 +93,48 @@ grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_f8851")
-[node name="InputManager" parent="." instance=ExtResource("1_34t85")]
-
[node name="InputIconProcessor" type="Node" parent="."]
script = ExtResource("3_y116l")
+[node name="Gamescope" type="Node" parent="."]
+script = ExtResource("4_ksi1t")
+instance = ExtResource("5_wmkau")
+
[node name="BoxArtLocal" parent="." instance=ExtResource("2_600i0")]
[node name="DesktopLibrary" parent="." instance=ExtResource("3_68bes")]
-[node name="LaunchManager" parent="." instance=ExtResource("4_tgw75")]
-
[node name="PluginManager" parent="." instance=ExtResource("5_dv70s")]
+[node name="PowerManager" type="Node" parent="."]
+script = ExtResource("10_opsp8")
+instance = ExtResource("11_nk5v7")
+
+[node name="Launcher" type="Node" parent="."]
+script = ExtResource("14_fs00k")
+
[node name="PowerSaver" parent="." instance=ExtResource("8_hyc1j")]
+[node name="PowerStation" type="Node" parent="."]
+script = ExtResource("13_tag7s")
+instance = ExtResource("14_a5vk3")
+
+[node name="NetworkManager" type="Node" parent="."]
+script = ExtResource("14_rqu7s")
+instance = ExtResource("15_k47ua")
+
+[node name="ResourceProcessor" type="ResourceProcessor" parent="."]
+registry = ExtResource("15_ne50o")
+
[node name="PowerTimer" type="Timer" parent="."]
unique_name_in_owner = true
wait_time = 1.5
one_shot = true
+[node name="GameLoading" parent="." instance=ExtResource("22_morxu")]
+visible = false
+layout_mode = 1
+
[node name="Panel" type="Panel" parent="."]
unique_name_in_owner = true
layout_mode = 1
@@ -219,10 +250,6 @@ layout_mode = 2
visible = false
layout_mode = 2
-[node name="GameLoading" parent="." instance=ExtResource("22_morxu")]
-visible = false
-layout_mode = 1
-
[node name="AlwaysVisibleContent" type="MarginContainer" parent="."]
editor_description = "Anything in this container will always be visible, even during in-game states.
"
@@ -339,4 +366,6 @@ grow_vertical = 2
stream = ExtResource("21_s3peg")
autoplay = true
+[node name="InputManager" parent="." instance=ExtResource("1_34t85")]
+
[editable path="AlwaysVisibleContent/OnScreenKeyboard"]
diff --git a/core/ui/card_ui/gamepad/gamepad_mapper.gd b/core/ui/card_ui/gamepad/gamepad_mapper.gd
index 1d0522375..2e5585d66 100644
--- a/core/ui/card_ui/gamepad/gamepad_mapper.gd
+++ b/core/ui/card_ui/gamepad/gamepad_mapper.gd
@@ -72,7 +72,7 @@ func _ready() -> void:
func _on_state_entered(_from: State) -> void:
var texture := change_input_state.get_meta("texture") as Texture2D
var mapping := change_input_state.get_meta("mappings") as InputPlumberMapping
- var gamepad := change_input_state.get_meta("gamepad") as InputPlumber.CompositeDevice
+ var gamepad := change_input_state.get_meta("gamepad") as CompositeDevice
var gamepad_type := change_input_state.get_meta("gamepad_type") as String
var gamepad_icons_type := change_input_state.get_meta("gamepad_type_icon_map") as String
diff --git a/core/ui/card_ui/gamepad/gamepad_mapper.tscn b/core/ui/card_ui/gamepad/gamepad_mapper.tscn
index a208cd533..de5bb95e5 100644
--- a/core/ui/card_ui/gamepad/gamepad_mapper.tscn
+++ b/core/ui/card_ui/gamepad/gamepad_mapper.tscn
@@ -8,7 +8,7 @@
[ext_resource type="PackedScene" uid="uid://bw8113ocotx2r" path="res://core/systems/effects/fade_effect.tscn" id="4_scwwv"]
[ext_resource type="Resource" uid="uid://46cu324n427u" path="res://assets/state/states/gamepad_change_input.tres" id="4_sv30y"]
[ext_resource type="PackedScene" uid="uid://uljtdvmuol3l" path="res://core/systems/input/focus_group_setter.tscn" id="5_i6uqd"]
-[ext_resource type="Texture2D" uid="uid://dyemqkvdtk43e" path="res://assets/images/gamepad/xbox/xbox_button_color_a.svg" id="8_5jaa6"]
+[ext_resource type="Texture2D" uid="uid://cxvxwgt1vox0" path="res://assets/images/gamepad/xbox/xbox_button_color_a.svg" id="8_5jaa6"]
[ext_resource type="PackedScene" uid="uid://cgmb4kr2ec4ha" path="res://core/ui/components/tabs_header.tscn" id="8_okgql"]
[ext_resource type="PackedScene" uid="uid://8m20p2s0v5gb" path="res://core/systems/input/focus_group.tscn" id="9_an8os"]
[ext_resource type="Resource" uid="uid://b58i2ue2qwe6f" path="res://core/ui/card_ui/gamepad/gamepad_mapper_tabs_state.tres" id="10_gr678"]
@@ -16,7 +16,7 @@
[ext_resource type="PackedScene" uid="uid://cr83fmlociwko" path="res://core/ui/components/card_icon_button.tscn" id="11_taofv"]
[ext_resource type="PackedScene" uid="uid://vf4sij64f82b" path="res://core/ui/common/osk/on_screen_keyboard.tscn" id="12_30f1c"]
[ext_resource type="Texture2D" uid="uid://dj1ohb74chydb" path="res://assets/ui/icons/round-delete-forever.svg" id="12_akkxd"]
-[ext_resource type="Texture2D" uid="uid://bie2sf8kjawr" path="res://assets/images/gamepad/xbox/XboxOne_Diagram.png" id="13_hvmil"]
+[ext_resource type="Texture2D" uid="uid://ceyt88pt5sogo" path="res://assets/images/gamepad/xbox/XboxOne_Diagram.png" id="13_hvmil"]
[ext_resource type="PackedScene" uid="uid://c71ayw7pcw6u6" path="res://core/ui/components/card_button.tscn" id="16_bkk3w"]
[ext_resource type="Texture2D" uid="uid://05mc8os4g5ax" path="res://assets/images/mouse/diagram.svg" id="18_lkxxd"]
[ext_resource type="Script" path="res://core/global/keyboard_instance.gd" id="18_u0i73"]
@@ -114,10 +114,12 @@ unique_name_in_owner = true
layout_mode = 2
size_flags_vertical = 3
theme_override_styles/panel = SubResource("StyleBoxEmpty_t62r6")
+current_tab = 0
tabs_visible = false
[node name="Gamepad" type="MarginContainer" parent="VBoxContainer/TabContainer"]
layout_mode = 2
+metadata/_tab_index = 0
[node name="MarginContainer" type="MarginContainer" parent="VBoxContainer/TabContainer/Gamepad"]
layout_mode = 2
@@ -219,6 +221,7 @@ text = "Touch Pads"
[node name="Keyboard" type="MarginContainer" parent="VBoxContainer/TabContainer"]
visible = false
layout_mode = 2
+metadata/_tab_index = 1
[node name="MarginContainer" type="MarginContainer" parent="VBoxContainer/TabContainer/Keyboard"]
layout_mode = 2
@@ -248,6 +251,7 @@ size_flags_vertical = 3
[node name="Mouse" type="MarginContainer" parent="VBoxContainer/TabContainer"]
visible = false
layout_mode = 2
+metadata/_tab_index = 2
[node name="MarginContainer" type="MarginContainer" parent="VBoxContainer/TabContainer/Mouse"]
layout_mode = 2
@@ -305,6 +309,7 @@ text = "Buttons"
[node name="System" type="MarginContainer" parent="VBoxContainer/TabContainer"]
visible = false
layout_mode = 2
+metadata/_tab_index = 3
[node name="MarginContainer" type="MarginContainer" parent="VBoxContainer/TabContainer/System"]
layout_mode = 2
diff --git a/core/ui/card_ui/gamepad/gamepad_settings.gd b/core/ui/card_ui/gamepad/gamepad_settings.gd
index d5dbdab00..bed2b5c04 100644
--- a/core/ui/card_ui/gamepad/gamepad_settings.gd
+++ b/core/ui/card_ui/gamepad/gamepad_settings.gd
@@ -12,13 +12,13 @@ var notification_manager := load("res://core/global/notification_manager.tres")
var settings_manager := load("res://core/global/settings_manager.tres") as SettingsManager
var global_state_machine := load("res://assets/state/state_machines/menu_state_machine.tres") as StateMachine
var state_machine := load("res://assets/state/state_machines/gamepad_settings_state_machine.tres") as StateMachine
-var input_plumber := load("res://core/systems/input/input_plumber.tres") as InputPlumber
+var input_plumber := load("res://core/systems/input/input_plumber.tres") as InputPlumberInstance
var input_icons := load("res://core/systems/input/input_icon_manager.tres") as InputIconManager
var button_scene := load("res://core/ui/components/card_mapping_button.tscn") as PackedScene
var container_scene := load("res://core/ui/components/card_mapping_button_group.tscn") as PackedScene
var expandable_scene := load("res://core/ui/card_ui/quick_bar/qb_card.tscn") as PackedScene
-var gamepad: InputPlumber.CompositeDevice
+var gamepad: CompositeDevice
var profile: InputPlumberProfile
var profile_gamepad: String
var library_item: LibraryItem
@@ -63,8 +63,8 @@ func _ready() -> void:
self.gamepad_type_selected = item_selected
if self.profile:
var gamepad_type := self.get_selected_target_gamepad()
- profile_gamepad = InputPlumberProfile.get_target_device_string(gamepad_type)
- logger.debug("Setting gamepad to " + profile_gamepad)
+ self.profile_gamepad = InputPlumberProfile.get_target_device_string(gamepad_type)
+ logger.debug("Setting gamepad to " + self.profile_gamepad)
else:
logger.debug("No profile, unable to set gamepad type.")
self._update_mapping_elements()
@@ -72,9 +72,9 @@ func _ready() -> void:
# Load the default profile
var profile_path = settings_manager.get_value("input", "gamepad_profile", "")
- profile_gamepad = settings_manager.get_value("input", "gamepad_profile_target", "")
- for gamepad in input_plumber.composite_devices:
- _set_gamepad_profile(gamepad, profile_path)
+ self.profile_gamepad = settings_manager.get_value("input", "gamepad_profile_target", "")
+ for composite_device in input_plumber.get_composite_devices():
+ _set_gamepad_profile(composite_device, profile_path)
# Grab focus when the mapper exits
var on_state_changed := func(_from: State, to: State):
@@ -85,7 +85,7 @@ func _ready() -> void:
# Ensure new devices are set to the correct profile when added
input_plumber.composite_device_added.connect(_set_gamepad_profile)
- input_plumber.composite_device_changed.connect(_set_gamepad_profile)
+ #input_plumber.composite_device_changed.connect(_set_gamepad_profile) #TODO: fixme?
## Called when the gamepad settings state is entered
@@ -94,7 +94,7 @@ func _on_state_entered(_from: State) -> void:
in_game_panel.visible = global_state_machine.has_state(in_game_state)
# Ensure that InputPlumber is running
- if not input_plumber.supports_input_plumber():
+ if not input_plumber.is_running():
not_available.visible = true
main_container.visible = false
$ServiceNotAvailableContainer/Label.text = "InputPlumber service not available"
@@ -103,7 +103,7 @@ func _on_state_entered(_from: State) -> void:
main_container.visible = true
# Read from the state to determine which gamepad is being configured
- gamepad = null
+ self.gamepad = null
if !gamepad_state.has_meta("dbus_path"):
logger.error("No gamepad was set to configure!")
# Make menu empty, unable to find gamepad to configure
@@ -114,58 +114,50 @@ func _on_state_entered(_from: State) -> void:
var dbus_path := gamepad_state.get_meta("dbus_path") as String
# Find the composite device to configure
- for device: InputPlumber.CompositeDevice in input_plumber.composite_devices:
+ for device: CompositeDevice in input_plumber.get_composite_devices():
if device.dbus_path == dbus_path:
- gamepad = device
+ self.gamepad = device
break
- if gamepad == null:
+
+ if self.gamepad == null:
logger.error("Unable to find CompositeDevice with path: " + dbus_path)
not_available.visible = true
main_container.visible = false
$ServiceNotAvailableContainer/Label.text = "No gamepad to configure"
return
- logger.debug("Configuring gamepad '" + gamepad.name + "': " + dbus_path)
+ logger.debug("Configuring gamepad '" + self.gamepad.name + "': " + dbus_path)
# Set the gamepad name label
- gamepad_label.text = gamepad.name
+ gamepad_label.text = self.gamepad.name
# Populate the menu with the source inputs for the given gamepad
- populate_mappings_for(gamepad)
+ populate_mappings_for(self.gamepad)
# Set the library item, if one exists
- library_item = null
- profile = null
+ self.library_item = null
+ self.profile = null
if gamepad_state.has_meta("item"):
- library_item = gamepad_state.get_meta("item") as LibraryItem
+ self.library_item = gamepad_state.get_meta("item") as LibraryItem
# If no library item was set, but there's a running app, try to see if
# there is a library item for it instead.
- if not library_item:
- library_item = launch_manager.get_current_app_library_item()
+ if not self.library_item:
+ self.library_item = launch_manager.get_current_app_library_item()
# If no library item was set with the state, then configure the OGUI profile
- if not library_item:
- profile_label.text = "Global"
- @warning_ignore("confusable_local_declaration")
- var profile_path := settings_manager.get_value("input", "gamepad_profile", InputPlumber.DEFAULT_GLOBAL_PROFILE) as String
- var profile_target_gamepad := settings_manager.get_value("input", "gamepad_profile_target", "") as String
- profile = _load_profile(profile_path)
- profile_gamepad = profile_target_gamepad
- _update_mapping_elements()
- return
-
- # Set the profile text to the game name
- profile_label.text = library_item.name
-
+ var profile_path: String
+ if not self.library_item:
+ self.profile_label.text = "Global"
+ profile_path = settings_manager.get_value("input", "gamepad_profile", InputPlumber.DEFAULT_GLOBAL_PROFILE) as String
+ else:
+ self.profile_label.text = self.library_item.name
+ profile_path = settings_manager.get_library_value(self.library_item, "gamepad_profile", "") as String
+ self.profile_gamepad = settings_manager.get_library_value(self.library_item, "gamepad_profile_target", "") as String
- # Check to see if the given game has a gamepad profile
- var profile_path := settings_manager.get_library_value(library_item, "gamepad_profile", "") as String
- var profile_target_gamepad := settings_manager.get_library_value(library_item, "gamepad_profile_target", "") as String
- profile = _load_profile(profile_path)
- profile_gamepad = profile_target_gamepad
+ self.profile = _load_profile(profile_path)
_update_mapping_elements()
-
+
# Clear focus
mapping_focus_group.current_focus = null
@@ -196,7 +188,7 @@ func _on_state_exited(_to: State) -> void:
## Populates the button mappings for the given gamepad
-func populate_mappings_for(gamepad: InputPlumber.CompositeDevice) -> void:
+func populate_mappings_for(gamepad: CompositeDevice) -> void:
var gamepad_name := gamepad.name
var capabilities := gamepad.capabilities
@@ -402,8 +394,8 @@ func _update_mapping_elements() -> void:
profile_label.text = profile.name
# Update the dropdown based on the profile's target gamepad type
- if not profile_gamepad.is_empty():
- var target_device := InputPlumberProfile.get_target_device(profile_gamepad)
+ if not self.profile_gamepad.is_empty():
+ var target_device := InputPlumberProfile.get_target_device(self.profile_gamepad)
var gamepad_text := self.get_target_gamepad_text(target_device)
var i := 0
var idx := 0
@@ -595,7 +587,7 @@ func get_target_gamepad_text(gamepad_type: InputPlumberProfile.TargetDevice) ->
# Set the given profile for the given composte device.
-func _set_gamepad_profile(gamepad: InputPlumber.CompositeDevice, profile_path: String = "") -> void:
+func _set_gamepad_profile(gamepad: CompositeDevice, profile_path: String = "") -> void:
if profile_path == "":
if gamepad_state.has_meta("item"):
library_item = gamepad_state.get_meta("item") as LibraryItem
@@ -612,16 +604,16 @@ func _set_gamepad_profile(gamepad: InputPlumber.CompositeDevice, profile_path: S
profile_path = settings_manager.get_library_value(library_item, "gamepad_profile", "")
logger.debug("Setting " + gamepad.name + " to profile: " + profile_path)
- gamepad.target_modify_profile(profile_path, profile_gamepad)
+ InputPlumber.load_target_modified_profile(gamepad, profile_path, self.profile_gamepad)
# Set the target gamepad if one was specified
- if not profile_gamepad.is_empty():
- var target_devices := [profile_gamepad, "keyboard", "mouse"]
- match profile_gamepad:
+ if not self.profile_gamepad.is_empty():
+ var target_devices := PackedStringArray([self.profile_gamepad, "keyboard", "mouse"])
+ match self.profile_gamepad:
"xb360", "xbox-series", "xbox-elite", "gamepad":
target_devices.append("touchpad")
_:
- logger.debug(profile_gamepad, "needs no additional target devices.")
+ logger.debug(self.profile_gamepad, "needs no additional target devices.")
logger.debug("Setting target devices to: ", target_devices)
gamepad.set_target_devices(target_devices)
@@ -645,10 +637,11 @@ func _save_profile() -> void:
return
# Update the game settings to use this global profile
+ self.logger.info("Saving gamepad profile at", path, "and gamepad target", self.profile_gamepad)
settings_manager.set_value("input", "gamepad_profile", path)
- settings_manager.set_value("input", "gamepad_profile_target", profile_gamepad)
+ settings_manager.set_value("input", "gamepad_profile_target", self.profile_gamepad)
- for gamepad in input_plumber.composite_devices:
+ for gamepad in input_plumber.get_composite_devices():
_set_gamepad_profile(gamepad, path)
logger.debug("Saved global gamepad profile to: " + path)
@@ -668,7 +661,7 @@ func _save_profile() -> void:
# Update the game settings to use this gamepad profile
var section := "game.{0}".format([library_item.name.to_lower()])
settings_manager.set_value(section, "gamepad_profile", path)
- settings_manager.set_value(section, "gamepad_profile_target", profile_gamepad)
+ settings_manager.set_value(section, "gamepad_profile_target", self.profile_gamepad)
logger.debug("Saved gamepad profile to: " + path)
notify.text = "Gamepad profile saved"
notification_manager.show(notify)
diff --git a/core/ui/card_ui/home/cardui_home.gd b/core/ui/card_ui/home/cardui_home.gd
index 41ba28098..1e4b668a4 100644
--- a/core/ui/card_ui/home/cardui_home.gd
+++ b/core/ui/card_ui/home/cardui_home.gd
@@ -201,6 +201,15 @@ func _on_card_focused(item: LibraryItem, card: Control) -> void:
player.play("fade_in")
banner.texture = await BoxArtManager.get_boxart_or_placeholder(item, BoxArtProvider.LAYOUT.BANNER)
library_banner.visible = false
+
+ # Don't scroll to the card if mouse or touch is being used
+ var input_manager := get_tree().get_first_node_in_group("InputManager")
+ if input_manager:
+ if (input_manager as InputManager).current_touches > 0:
+ return
+ if Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT):
+ return
+
_scroll_to(card)
diff --git a/core/ui/card_ui/home/cardui_home.tscn b/core/ui/card_ui/home/cardui_home.tscn
index eea547d86..7c2624ced 100644
--- a/core/ui/card_ui/home/cardui_home.tscn
+++ b/core/ui/card_ui/home/cardui_home.tscn
@@ -1,4 +1,4 @@
-[gd_scene load_steps=18 format=3 uid="uid://o70x5igrlq30"]
+[gd_scene load_steps=20 format=3 uid="uid://o70x5igrlq30"]
[ext_resource type="Script" path="res://core/ui/card_ui/home/cardui_home.gd" id="1_a4a3j"]
[ext_resource type="PackedScene" uid="uid://c6fg6uvng0ovi" path="res://core/systems/input/input_watcher.tscn" id="2_d1wwx"]
@@ -9,6 +9,7 @@
[ext_resource type="Resource" uid="uid://e7bbebwf7guj" path="res://assets/state/states/main_menu.tres" id="5_gbh30"]
[ext_resource type="Texture2D" uid="uid://d1mksukdkqorr" path="res://assets/images/placeholder-grid-banner.png" id="10_mmfgs"]
[ext_resource type="PackedScene" uid="uid://rosd00fxjrs8" path="res://core/ui/components/library_banner.tscn" id="11_16gcd"]
+[ext_resource type="Shader" path="res://assets/shaders/god_rays.gdshader" id="11_r5mwe"]
[ext_resource type="PackedScene" uid="uid://b0cyl6fdqxevn" path="res://core/systems/input/scroller_joystick.tscn" id="12_h5dxg"]
[ext_resource type="PackedScene" uid="uid://bkhrcemal7uxo" path="res://core/ui/components/card.tscn" id="12_m30ge"]
[ext_resource type="PackedScene" uid="uid://crsu0vpicq0vh" path="res://core/ui/components/library_deck.tscn" id="13_rxwf5"]
@@ -16,6 +17,22 @@
[ext_resource type="PackedScene" uid="uid://b76dvfuouhlwd" path="res://core/systems/state/state_updater.tscn" id="14_wdgux"]
[ext_resource type="Resource" uid="uid://boq501bigx8kl" path="res://assets/state/states/library.tres" id="16_6odlo"]
+[sub_resource type="ShaderMaterial" id="ShaderMaterial_bjg8e"]
+shader = ExtResource("11_r5mwe")
+shader_parameter/angle = 0.06
+shader_parameter/position = -0.1
+shader_parameter/spread = 0.674
+shader_parameter/cutoff = 0.1
+shader_parameter/falloff = 0.896
+shader_parameter/edge_fade = 0.15
+shader_parameter/speed = 6.995
+shader_parameter/ray1_density = 8.0
+shader_parameter/ray2_density = 30.0
+shader_parameter/ray2_intensity = 0.184
+shader_parameter/color = Color(0.888, 0.885, 1, 0.173)
+shader_parameter/hdr = true
+shader_parameter/seed = 1.505
+
[sub_resource type="Animation" id="Animation_638a6"]
resource_name = "fade_in"
length = 0.5
@@ -88,6 +105,15 @@ unique_name_in_owner = true
visible = false
layout_mode = 1
+[node name="GodRaysShader" type="ColorRect" parent="VBoxContainer/BannerTexture"]
+material = SubResource("ShaderMaterial_bjg8e")
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+
[node name="PanelContainer" type="PanelContainer" parent="VBoxContainer"]
layout_mode = 2
size_flags_vertical = 3
diff --git a/core/ui/card_ui/launch/game_launch_menu.tscn b/core/ui/card_ui/launch/game_launch_menu.tscn
index 430a0b745..1f201075b 100644
--- a/core/ui/card_ui/launch/game_launch_menu.tscn
+++ b/core/ui/card_ui/launch/game_launch_menu.tscn
@@ -1,4 +1,4 @@
-[gd_scene load_steps=20 format=3 uid="uid://bcdk1lj6enq3l"]
+[gd_scene load_steps=22 format=3 uid="uid://bcdk1lj6enq3l"]
[ext_resource type="Script" path="res://core/ui/card_ui/launch/game_launch_menu.gd" id="1_u3ehs"]
[ext_resource type="Texture2D" uid="uid://d1mksukdkqorr" path="res://assets/images/placeholder-grid-banner.png" id="2_oae7b"]
@@ -9,6 +9,7 @@
[ext_resource type="PackedScene" uid="uid://shvyhrv5sx3v" path="res://core/systems/state/state_watcher.tscn" id="5_4ja2v"]
[ext_resource type="Texture2D" uid="uid://bec6fhiswf6ve" path="res://assets/ui/icons/gamepad-bold.svg" id="5_ewj68"]
[ext_resource type="PackedScene" uid="uid://bw8113ocotx2r" path="res://core/systems/effects/fade_effect.tscn" id="7_ch3qu"]
+[ext_resource type="Shader" path="res://assets/shaders/god_rays.gdshader" id="10_l1dl8"]
[ext_resource type="Texture2D" uid="uid://d2ipfga47yjju" path="res://assets/images/empty-grid-logo.png" id="12_01uv6"]
[ext_resource type="PackedScene" uid="uid://c71ayw7pcw6u6" path="res://core/ui/components/card_button.tscn" id="14_3h1st"]
[ext_resource type="PackedScene" uid="uid://cr83fmlociwko" path="res://core/ui/components/card_icon_button.tscn" id="15_f3ktw"]
@@ -37,6 +38,22 @@ _data = {
"fade_in": SubResource("Animation_ou6f5")
}
+[sub_resource type="ShaderMaterial" id="ShaderMaterial_f0qty"]
+shader = ExtResource("10_l1dl8")
+shader_parameter/angle = 0.06
+shader_parameter/position = -0.1
+shader_parameter/spread = 0.674
+shader_parameter/cutoff = 0.1
+shader_parameter/falloff = 0.896
+shader_parameter/edge_fade = 0.15
+shader_parameter/speed = 6.995
+shader_parameter/ray1_density = 8.0
+shader_parameter/ray2_density = 30.0
+shader_parameter/ray2_intensity = 0.184
+shader_parameter/color = Color(0.888, 0.885, 1, 0.173)
+shader_parameter/hdr = true
+shader_parameter/seed = 1.505
+
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_7fb8y"]
bg_color = Color(1, 0.47451, 0.776471, 1)
corner_radius_top_left = 5
@@ -109,6 +126,15 @@ libraries = {
"": SubResource("AnimationLibrary_yfglc")
}
+[node name="GodRaysShader" type="ColorRect" parent="VBoxContainer/BannerTexture"]
+material = SubResource("ShaderMaterial_f0qty")
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+
[node name="PanelContainer" type="PanelContainer" parent="VBoxContainer"]
layout_mode = 2
size_flags_vertical = 3
diff --git a/core/ui/card_ui/library/library_menu.gd b/core/ui/card_ui/library/library_menu.gd
index b032739c1..03b553425 100644
--- a/core/ui/card_ui/library/library_menu.gd
+++ b/core/ui/card_ui/library/library_menu.gd
@@ -244,8 +244,17 @@ func _on_uninstalled(req: InstallManager.Request) -> void:
# Called when a library card is focused
func _on_focus_updated(card: Control, tab: int) -> void:
+ # Update the currently selected card
_current_selection[tab] = card
+ # Don't scroll to the card if mouse or touch is being used
+ var input_manager := get_tree().get_first_node_in_group("InputManager")
+ if input_manager:
+ if (input_manager as InputManager).current_touches > 0:
+ return
+ if Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT):
+ return
+
# Get the scroll container for this card
var scroll_container := tab_container.get_child(tab) as ScrollContainer
if not scroll_container:
diff --git a/core/ui/card_ui/library/library_menu.tscn b/core/ui/card_ui/library/library_menu.tscn
index e035c4bc8..f070b56cb 100644
--- a/core/ui/card_ui/library/library_menu.tscn
+++ b/core/ui/card_ui/library/library_menu.tscn
@@ -52,11 +52,13 @@ grow_horizontal = 2
grow_vertical = 2
size_flags_vertical = 3
theme_override_styles/panel = SubResource("StyleBoxFlat_xn2qp")
+current_tab = 0
tabs_visible = false
[node name="InstalledTab" type="ScrollContainer" parent="TabContainer"]
layout_mode = 2
horizontal_scroll_mode = 0
+metadata/_tab_index = 0
[node name="ScrollerJoystick" parent="TabContainer/InstalledTab" instance=ExtResource("11_27umd")]
@@ -113,6 +115,7 @@ layout_mode = 2
visible = false
layout_mode = 2
horizontal_scroll_mode = 0
+metadata/_tab_index = 1
[node name="ScrollerJoystick" parent="TabContainer/AllGamesTab" instance=ExtResource("11_27umd")]
diff --git a/core/ui/card_ui/navigation/context_bar_menu.gd b/core/ui/card_ui/navigation/context_bar_menu.gd
index 91689c9dc..e072a0aa6 100644
--- a/core/ui/card_ui/navigation/context_bar_menu.gd
+++ b/core/ui/card_ui/navigation/context_bar_menu.gd
@@ -1,12 +1,8 @@
extends PanelContainer
-const thread := preload("res://core/systems/threading/thread_pool.tres")
-
var state_machine := load("res://assets/state/state_machines/global_state_machine.tres") as StateMachine
-var battery_capacity := -1
var logger := Log.get_logger("ContextBar")
-@onready var battery: String = Battery.find_battery_path()
@onready var time_label: Label = $%TimeLabel
diff --git a/core/ui/card_ui/navigation/in-game_notification.gd b/core/ui/card_ui/navigation/in-game_notification.gd
index d53ab2a23..6b615fcd1 100644
--- a/core/ui/card_ui/navigation/in-game_notification.gd
+++ b/core/ui/card_ui/navigation/in-game_notification.gd
@@ -4,10 +4,10 @@ signal notification_received
signal notification_finished
var PID: int = OS.get_process_id()
-var gamescope := load("res://core/global/gamescope.tres") as Gamescope
+var gamescope := load("res://core/systems/gamescope/gamescope.tres") as GamescopeInstance
var notification_manager := load("res://core/global/notification_manager.tres") as NotificationManager
var default_icon := preload("res://icon.svg")
-var overlay_window_id := gamescope.get_window_id(PID, gamescope.XWAYLAND.OGUI)
+var overlay_window_id: int
@onready var panel := $%PanelContainer as PanelContainer
@onready var texture := $%TextureRect as TextureRect
@@ -18,6 +18,11 @@ var overlay_window_id := gamescope.get_window_id(PID, gamescope.XWAYLAND.OGUI)
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
+ var xwayland := gamescope.get_xwayland(gamescope.XWAYLAND_TYPE_OGUI)
+ if xwayland:
+ var overlay_window_ids := xwayland.get_windows_for_pid(PID)
+ if not overlay_window_ids.is_empty():
+ overlay_window_id = overlay_window_ids[0]
panel.visible = false
# Subscribe to any notifications
notification_manager.notification_queued.connect(_on_notification_queued)
@@ -25,7 +30,9 @@ func _ready() -> void:
# Continue showing any other queued messages
var on_finished := func():
- gamescope.set_notification(overlay_window_id, 0)
+ var xwland := gamescope.get_xwayland(gamescope.XWAYLAND_TYPE_OGUI)
+ if xwland:
+ xwland.set_notification(overlay_window_id, 0)
_on_notification_queued(null)
effect.slide_out_finished.connect(on_finished)
@@ -38,7 +45,9 @@ func _on_notification_queued(_notify: Notification) -> void:
var notify := notification_manager.next()
if not notify:
return
- gamescope.set_notification(overlay_window_id, 1)
+ var xwayland := gamescope.get_xwayland(gamescope.XWAYLAND_TYPE_OGUI)
+ if xwayland:
+ xwayland.set_notification(overlay_window_id, 1)
show_toast(notify.text, notify.icon, notify.timeout)
diff --git a/core/ui/card_ui/navigation/running_game_card.gd b/core/ui/card_ui/navigation/running_game_card.gd
index e5302252e..18860ae57 100644
--- a/core/ui/card_ui/navigation/running_game_card.gd
+++ b/core/ui/card_ui/navigation/running_game_card.gd
@@ -10,8 +10,7 @@ signal toggled_off
signal finished_growing
signal finished_shrinking
-const Gamescope := preload("res://core/global/gamescope.tres")
-
+var gamescope := load("res://core/systems/gamescope/gamescope.tres") as GamescopeInstance
var launch_manager := load("res://core/global/launch_manager.tres") as LaunchManager
var boxart_manager := load("res://core/global/boxart_manager.tres") as BoxArtManager
var library_manager := load("res://core/global/library_manager.tres") as LibraryManager
@@ -20,6 +19,7 @@ var menu_state_machine := load("res://assets/state/state_machines/menu_state_mac
var popup_state_machine := load("res://assets/state/state_machines/popup_state_machine.tres") as StateMachine
var in_game_state := load("res://assets/state/states/in_game.tres") as State
var button_scene := load("res://core/ui/components/card_button.tscn") as PackedScene
+var gamepad_state := load("res://assets/state/states/gamepad_settings.tres") as State
@export_category("Card")
@export var is_toggled := false:
@@ -31,14 +31,15 @@ var button_scene := load("res://core/ui/components/card_button.tscn") as PackedS
toggled_off.emit()
toggled.emit(is_toggled)
-@onready var content_container := $%ContentContainer
-@onready var game_logo := $%GameLogo
-@onready var game_label := $%GameLabel
+@onready var content_container := $%ContentContainer as Container
+@onready var game_logo := $%GameLogo as TextureRect
+@onready var game_label := $%GameLabel as Label
@onready var resume_button := $%ResumeButton as CardButton
@onready var pause_button := $%PauseButton as CardButton
@onready var exit_button := $%ExitButton as CardButton
@onready var highlight_rect := $%HighlightTextureRect
@onready var focus_group := $%FocusGroup as FocusGroup
+@onready var gamepad_button := $%GamepadButton
var tween: Tween
var running_app: RunningApp
@@ -55,6 +56,7 @@ func _ready() -> void:
focus_exited.connect(_on_unfocus)
button_up.connect(_on_button_up)
theme_changed.connect(_on_theme_changed)
+ gamepad_button.button_down.connect(_on_gampad_button_pressed)
# Find the parent theme and update if required
var effective_theme := ThemeUtils.get_effective_theme(self)
@@ -100,6 +102,9 @@ func set_running_app(app: RunningApp):
return
running_app = app
var item := library_manager.get_app_by_name(app.launch_item.name)
+ if not item:
+ logger.warn("App", app.app_id, "has no library item.")
+ return
game_logo.visible = false
game_label.visible = false
var logo := await boxart_manager.get_boxart(item, BoxArtProvider.LAYOUT.LOGO) as Texture2D
@@ -112,7 +117,9 @@ func set_running_app(app: RunningApp):
# Connect to app signals to allow switching between app windows
var on_windows_changed := func(_from: PackedInt32Array, to: PackedInt32Array):
- var focusable_windows := Gamescope.get_focusable_windows()
+ var xwayland := gamescope.get_xwayland(gamescope.XWAYLAND_TYPE_PRIMARY)
+ var xwayland_game := gamescope.get_xwayland(gamescope.XWAYLAND_TYPE_GAME)
+ var focusable_windows := xwayland.get_focusable_windows()
# Add a button to switch to a given window
for window_id in to:
# A button already exists for this window
@@ -120,9 +127,9 @@ func set_running_app(app: RunningApp):
continue
if not window_id in focusable_windows:
continue
- var window_name := app.get_window_title(window_id)
+ var window_name := xwayland_game.get_window_name(window_id)
if window_name == "":
- continue
+ window_name = "Window (" + str(window_id) + ")"
var button := button_scene.instantiate() as CardButton
button.text = window_name
button.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
@@ -207,3 +214,12 @@ func _input(event: InputEvent) -> void:
#logger.debug("Consuming input event '{action}' for node {n}".format({"action": action, "n": str(self)}))
get_viewport().set_input_as_handled()
self.grab_focus()
+
+
+## Ensure that the library item meta data is always set before opening the gamepad
+## settings menu
+func _on_gampad_button_pressed() -> void:
+ var library_item: LibraryItem = null
+ if running_app and running_app.launch_item:
+ library_item = LibraryItem.new_from_launch_item(running_app.launch_item)
+ gamepad_state.set_meta("item", library_item)
diff --git a/core/ui/card_ui/navigation/running_game_card.tscn b/core/ui/card_ui/navigation/running_game_card.tscn
index 279c8c8a2..e16a6254b 100644
--- a/core/ui/card_ui/navigation/running_game_card.tscn
+++ b/core/ui/card_ui/navigation/running_game_card.tscn
@@ -17,7 +17,7 @@
[ext_resource type="Resource" uid="uid://cr544el0cqjlm" path="res://assets/state/state_machines/global_state_machine.tres" id="15_p4kr0"]
[ext_resource type="Resource" uid="uid://cv3vduo0ojk1u" path="res://assets/state/states/menu.tres" id="16_vmedb"]
-[sub_resource type="Image" id="Image_2yqt6"]
+[sub_resource type="Image" id="Image_8fib7"]
data = {
"data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0),
"format": "RGBA8",
@@ -27,7 +27,7 @@ data = {
}
[sub_resource type="ImageTexture" id="ImageTexture_osglk"]
-image = SubResource("Image_2yqt6")
+image = SubResource("Image_8fib7")
[node name="RunningGameCard" type="PanelContainer"]
anchors_preset = 10
@@ -160,6 +160,7 @@ layout_mode = 2
text = "Pause"
[node name="GamepadButton" parent="MarginContainer/VBoxContainer/ContentContainer" instance=ExtResource("8_ixs6g")]
+unique_name_in_owner = true
layout_mode = 2
text = "Gamepad"
diff --git a/core/ui/card_ui/navigation/system_container.gd b/core/ui/card_ui/navigation/system_container.gd
index 58e642688..b71b27710 100644
--- a/core/ui/card_ui/navigation/system_container.gd
+++ b/core/ui/card_ui/navigation/system_container.gd
@@ -1,29 +1,59 @@
extends HBoxContainer
-const thread := preload("res://core/systems/threading/thread_pool.tres")
+var network_manager := load("res://core/systems/network/network_manager.tres") as NetworkManagerInstance
@onready var network_icon := $%NetworkIcon as TextureRect
+var current_access_point: NetworkAccessPoint
+
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
- thread.start()
-
- # Create a timer to check wifi signal strength and battery percent
- var wifi_timer := Timer.new()
- wifi_timer.timeout.connect(_on_wifi_update)
- wifi_timer.wait_time = 60
- wifi_timer.autostart = true
- add_child(wifi_timer)
- _on_wifi_update()
-
-
-# Updates the wifi signal strength on timer timeout
-func _on_wifi_update() -> void:
- var get_ap := func() -> NetworkManager.WifiAP:
- return NetworkManager.get_current_access_point()
- var current_ap := await thread.exec(get_ap) as NetworkManager.WifiAP
- var strength := 0
- if current_ap:
- strength = current_ap.strength
+ # Set the visibility of the network icon depending on if networking is available
+ network_manager.started.connect(_on_networking_available)
+ network_manager.stopped.connect(_on_networking_available)
+ _on_networking_available()
+
+ # Listen for active connection changes to determine what icon to display
+ network_manager.primary_connection_changed.connect(_on_primary_change)
+ _on_primary_change(network_manager.primary_connection)
+
+
+func _on_networking_available() -> void:
+ network_icon.visible = network_manager.is_running()
+
+
+func _on_primary_change(conn: NetworkActiveConnection) -> void:
+ if current_access_point:
+ current_access_point.strength_changed.disconnect(_on_wifi_strength_changed)
+ current_access_point = null
+ if not conn:
+ # No active connection
+ network_icon.texture = NetworkManager.no_network
+ return
+
+ var devices := conn.devices
+ if devices.is_empty():
+ # No devices associated with connection
+ network_icon.texture = NetworkManager.no_network
+ return
+
+ # Set the icon based on the type of device
+ var device := devices[0]
+ if not device.wireless:
+ network_icon.texture = NetworkManager.ethernet
+ return
+
+ # Set the texture based on wifi state
+ current_access_point = device.wireless.active_access_point
+ if not current_access_point:
+ network_icon.texture = NetworkManager.bar_0
+ return
+ network_icon.texture = NetworkManager.get_strength_texture(current_access_point.strength)
+
+ # Update the wifi strength
+ current_access_point.strength_changed.connect(_on_wifi_strength_changed)
+
+
+func _on_wifi_strength_changed(strength: int) -> void:
network_icon.texture = NetworkManager.get_strength_texture(strength)
diff --git a/core/ui/card_ui/ootbe/language_select.gd b/core/ui/card_ui/ootbe/language_select.gd
index 259eb9fc5..fead50c3c 100644
--- a/core/ui/card_ui/ootbe/language_select.gd
+++ b/core/ui/card_ui/ootbe/language_select.gd
@@ -1,6 +1,9 @@
extends MarginContainer
-var state_updater_scene := load("res://core/systems/state/state_updater.tscn") as PackedScene
+var settings_manager := load("res://core/global/settings_manager.tres") as SettingsManager
+var network_manager := load("res://core/systems/network/network_manager.tres") as NetworkManagerInstance
+var state_machine := load("res://assets/state/state_machines/first_boot_state_machine.tres") as StateMachine
+var no_networking_state := load("res://assets/state/states/first_boot_finished.tres") as State
var button_scene := load("res://core/ui/components/card_button.tscn") as PackedScene
@onready var button_container := %VBoxContainer
@@ -14,19 +17,29 @@ func _ready() -> void:
# Create a button for each locale
for locale in TranslationServer.get_loaded_locales():
var language := locale.split("_")[0]
- var language_name := TranslationServer.get_language_name(language)
-
- # Configure a state updater to change menu states when the button is pressed
- var state_updater := state_updater_scene.instantiate() as StateUpdater
- state_updater.state_machine = load("res://assets/state/state_machines/first_boot_state_machine.tres")
- state_updater.state = load("res://assets/state/states/first_boot_network.tres")
- state_updater.action = state_updater.ACTION.PUSH
- state_updater.on_signal = "button_up"
+ var language_name := tr(TranslationServer.get_language_name(language))
# Create the button and set the language name
var button := button_scene.instantiate() as CardButton
+ button.button_up.connect(_on_button_up.bind(locale))
button.text = language_name
- button.add_child(state_updater)
# Add the button to the scene
button_container.add_child(button)
+
+
+func _on_button_up(locale: String) -> void:
+ # Set and save locale
+ TranslationServer.set_locale(locale)
+ settings_manager.set_value("general", "locale", locale)
+
+ # Determine the next state to go to
+ if not network_manager.is_running():
+ state_machine.push_state(no_networking_state)
+ return
+ var next_state: State
+ if network_manager.state >= network_manager.NM_STATE_CONNECTED_GLOBAL:
+ next_state = load("res://assets/state/states/first_boot_plugin_select.tres") as State
+ else:
+ next_state = load("res://assets/state/states/first_boot_network.tres") as State
+ state_machine.push_state(next_state)
diff --git a/core/ui/card_ui/ootbe/network_select.gd b/core/ui/card_ui/ootbe/network_select.gd
index 8742261a3..c87c6bb88 100644
--- a/core/ui/card_ui/ootbe/network_select.gd
+++ b/core/ui/card_ui/ootbe/network_select.gd
@@ -1,14 +1,14 @@
extends MarginContainer
+var network_manager := load("res://core/systems/network/network_manager.tres") as NetworkManagerInstance
var state_machine := load("res://assets/state/state_machines/first_boot_state_machine.tres") as StateMachine
-var next_state := load("res://assets/state/states/first_boot_plugin_select.tres") as State
-var network_state := load("res://assets/state/states/first_boot_network.tres") as State
-
+var no_networking_state := load("res://assets/state/states/first_boot_finished.tres") as State
var network_state_machine := load("res://assets/state/state_machines/first_boot_network_state_machine.tres") as StateMachine
var password_popup_state := load("res://assets/state/states/first_boot_network_password.tres") as State
var logger := Log.get_logger("NetworkSelect")
+@onready var next_button := $%NextButton as CardButton
@onready var wifi_tree := $%WifiNetworkTree as WifiNetworkTree
@onready var wifi_pass_box := $%WifiPasswordTextInput
@onready var wifi_pass_button := $%WifiPasswordButton
@@ -16,17 +16,21 @@ var logger := Log.get_logger("NetworkSelect")
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
- network_state.state_entered.connect(_on_state_entered)
+ next_button.button_up.connect(_on_next_button)
wifi_tree.challenge_required.connect(_on_challenge_required)
-# When this menu is shown, check if networking is supported. If not,
-# proceed to the next OOBE menu.
-func _on_state_entered(_from: State) -> void:
- if NetworkManager.supports_network():
+func _on_next_button() -> void:
+ # Determine the next state to go to
+ if not network_manager.is_running():
+ state_machine.push_state(no_networking_state)
return
- logger.info("Networking is not supported. Skipping.")
- state_machine.replace_state(next_state)
+ var next_state: State
+ if network_manager.state >= network_manager.NM_STATE_CONNECTED_GLOBAL:
+ next_state = load("res://assets/state/states/first_boot_plugin_select.tres") as State
+ else:
+ next_state = load("res://assets/state/states/first_boot_finished.tres") as State
+ state_machine.push_state(next_state)
# If a wifi password is needed, this method will be called. The callback
diff --git a/core/ui/card_ui/ootbe/network_select.tscn b/core/ui/card_ui/ootbe/network_select.tscn
index 94ea7062c..9649e6e8b 100644
--- a/core/ui/card_ui/ootbe/network_select.tscn
+++ b/core/ui/card_ui/ootbe/network_select.tscn
@@ -1,4 +1,4 @@
-[gd_scene load_steps=22 format=3 uid="uid://b64v61ut4e1qv"]
+[gd_scene load_steps=21 format=3 uid="uid://b64v61ut4e1qv"]
[ext_resource type="PackedScene" uid="uid://d0u3rsa5qpj57" path="res://core/ui/components/subsection_label.tscn" id="1_isj2i"]
[ext_resource type="Script" path="res://core/ui/card_ui/ootbe/network_select.gd" id="1_lbpas"]
@@ -16,7 +16,6 @@
[ext_resource type="Theme" uid="uid://bko0q7gp1hwjp" path="res://assets/themes/dracula.tres" id="10_oxokr"]
[ext_resource type="PackedScene" uid="uid://btg3dylh0tqoi" path="res://core/systems/effects/smooth_scroll_effect.tscn" id="10_umeai"]
[ext_resource type="PackedScene" uid="uid://d1rjdfxxrdccf" path="res://core/ui/components/text_input.tscn" id="11_hldpx"]
-[ext_resource type="Resource" uid="uid://bpi21xakop5wy" path="res://assets/state/states/first_boot_plugin_select.tres" id="14_bvbb6"]
[ext_resource type="Resource" uid="uid://b5e8kjinft7rs" path="res://assets/state/state_machines/first_boot_network_state_machine.tres" id="16_ckd3v"]
[ext_resource type="Resource" uid="uid://bm3fu76wxxmnt" path="res://assets/state/states/first_boot_network_password.tres" id="17_mmuaj"]
[ext_resource type="Script" path="res://core/systems/state/state_watcher.gd" id="17_umvp2"]
@@ -60,11 +59,11 @@ fade_out_signal = "state_exited"
on_signal = "state_entered"
[node name="FocusGroupSetter" parent="StateWatcher/FadeEffect" node_paths=PackedStringArray("target") instance=ExtResource("4_y44we")]
-target = NodePath("../../../HBoxContainer/ScrollContainer/MarginContainer/VBoxContainer/FocusGroup")
+target = NodePath("../../../HBoxContainer/ScrollContainer/MarginContainer/VBoxContainer/NetworkSelectFocusGroup")
on_signal = "effect_finished"
[node name="FocusGroupSetter" parent="StateWatcher" node_paths=PackedStringArray("target") instance=ExtResource("4_y44we")]
-target = NodePath("../../HBoxContainer/ScrollContainer/MarginContainer/VBoxContainer/FocusGroup")
+target = NodePath("../../HBoxContainer/ScrollContainer/MarginContainer/VBoxContainer/NetworkSelectFocusGroup")
on_signal = "state_refreshed"
[node name="HBoxContainer" type="HBoxContainer" parent="."]
@@ -103,7 +102,7 @@ theme_override_constants/margin_bottom = 80
layout_mode = 2
theme_override_constants/separation = 40
-[node name="FocusGroup" parent="HBoxContainer/ScrollContainer/MarginContainer/VBoxContainer" node_paths=PackedStringArray("current_focus") instance=ExtResource("6_c8yx4")]
+[node name="NetworkSelectFocusGroup" parent="HBoxContainer/ScrollContainer/MarginContainer/VBoxContainer" node_paths=PackedStringArray("current_focus") instance=ExtResource("6_c8yx4")]
current_focus = NodePath("../WifiNetworkTree")
[node name="Spacer" type="Control" parent="HBoxContainer/ScrollContainer/MarginContainer/VBoxContainer"]
@@ -115,17 +114,13 @@ layout_mode = 2
size_flags_vertical = 3
[node name="NextButton" parent="HBoxContainer/ScrollContainer/MarginContainer/VBoxContainer" instance=ExtResource("3_nucyf")]
+unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 8
size_flags_vertical = 8
text = "Next"
click_focuses = false
-[node name="StateUpdater" parent="HBoxContainer/ScrollContainer/MarginContainer/VBoxContainer/NextButton" instance=ExtResource("9_d1uu0")]
-state_machine = ExtResource("2_0fb0p")
-state = ExtResource("14_bvbb6")
-on_signal = "button_up"
-
[node name="PopupContainer" type="CenterContainer" parent="."]
unique_name_in_owner = true
visible = false
@@ -145,14 +140,20 @@ on_signal = "input_released"
script = ExtResource("17_umvp2")
state = ExtResource("17_mmuaj")
-[node name="FocusOnPopupOpen" parent="PopupContainer/StateWatcher" node_paths=PackedStringArray("target") instance=ExtResource("4_y44we")]
-target = NodePath("../../PanelContainer/MarginContainer/VBoxContainer/FocusGroup")
-on_signal = "state_entered"
-
[node name="FocusOnPopupClose" parent="PopupContainer/StateWatcher" node_paths=PackedStringArray("target") instance=ExtResource("4_y44we")]
-target = NodePath("../../../HBoxContainer/ScrollContainer/MarginContainer/VBoxContainer/FocusGroup")
+target = NodePath("../../../HBoxContainer/ScrollContainer/MarginContainer/VBoxContainer/NetworkSelectFocusGroup")
on_signal = "state_exited"
+[node name="FadeEffect" parent="PopupContainer/StateWatcher" node_paths=PackedStringArray("target") instance=ExtResource("7_2d2el")]
+target = NodePath("../..")
+on_signal = "state_entered"
+fade_out_signal = "state_exited"
+on_signal = "state_entered"
+
+[node name="FocusOnPopupOpen" parent="PopupContainer/StateWatcher/FadeEffect" node_paths=PackedStringArray("target") instance=ExtResource("4_y44we")]
+target = NodePath("../../../PanelContainer/MarginContainer/VBoxContainer/PasswordFocusGroup")
+on_signal = "effect_finished"
+
[node name="PanelContainer" type="PanelContainer" parent="PopupContainer"]
layout_mode = 2
theme = ExtResource("10_oxokr")
@@ -169,7 +170,7 @@ theme_override_constants/margin_bottom = 20
layout_mode = 2
theme_override_constants/separation = 10
-[node name="FocusGroup" parent="PopupContainer/PanelContainer/MarginContainer/VBoxContainer" node_paths=PackedStringArray("current_focus") instance=ExtResource("6_c8yx4")]
+[node name="PasswordFocusGroup" parent="PopupContainer/PanelContainer/MarginContainer/VBoxContainer" node_paths=PackedStringArray("current_focus") instance=ExtResource("6_c8yx4")]
current_focus = NodePath("../WifiPasswordTextInput")
[node name="WifiPasswordTextInput" parent="PopupContainer/PanelContainer/MarginContainer/VBoxContainer" instance=ExtResource("11_hldpx")]
diff --git a/core/ui/card_ui/ootbe/plugin_select.gd b/core/ui/card_ui/ootbe/plugin_select.gd
new file mode 100644
index 000000000..89f019dfd
--- /dev/null
+++ b/core/ui/card_ui/ootbe/plugin_select.gd
@@ -0,0 +1,28 @@
+extends MarginContainer
+
+var network_manager := load("res://core/systems/network/network_manager.tres") as NetworkManagerInstance
+var state_machine := load("res://assets/state/state_machines/first_boot_state_machine.tres") as StateMachine
+var next_state := load("res://assets/state/states/first_boot_plugin_select.tres") as State
+var no_networking_state := load("res://assets/state/states/first_boot_finished.tres") as State
+var plugin_store_state := load("res://assets/state/states/settings_plugin_store.tres") as State
+var plugin_select_state := load("res://assets/state/states/first_boot_plugin_select.tres") as State
+
+
+var logger := Log.get_logger("PluginSelect")
+
+# Called when the node enters the scene tree for the first time.
+func _ready() -> void:
+ plugin_select_state.state_entered.connect(_on_state_entered)
+
+
+# When this menu is shown, check if networking is supported. If not,
+# proceed to the next OOBE menu.
+func _on_state_entered(_from: State) -> void:
+ if not network_manager.is_running():
+ logger.info("Networking is not supported. Skipping.")
+ state_machine.replace_state(no_networking_state)
+ return
+ if network_manager.state < network_manager.NM_STATE_CONNECTED_GLOBAL:
+ logger.info("Network is not available. Skipping.")
+ state_machine.replace_state(no_networking_state)
+ return
diff --git a/core/ui/card_ui/ootbe/plugin_select.tscn b/core/ui/card_ui/ootbe/plugin_select.tscn
index 904281072..145c634a7 100644
--- a/core/ui/card_ui/ootbe/plugin_select.tscn
+++ b/core/ui/card_ui/ootbe/plugin_select.tscn
@@ -1,13 +1,15 @@
-[gd_scene load_steps=12 format=3 uid="uid://cq5do4hbuevrd"]
+[gd_scene load_steps=14 format=3 uid="uid://cq5do4hbuevrd"]
-[ext_resource type="PackedScene" uid="uid://orey8uxm7v6v" path="res://core/systems/state/visibility_manager.tscn" id="1_glflu"]
+[ext_resource type="Script" path="res://core/ui/card_ui/ootbe/plugin_select.gd" id="1_v2m4r"]
[ext_resource type="Resource" uid="uid://bj8aa7rky3u36" path="res://assets/state/state_machines/first_boot_state_machine.tres" id="2_8r7jx"]
+[ext_resource type="PackedScene" uid="uid://c6fg6uvng0ovi" path="res://core/systems/input/input_watcher.tscn" id="2_lfjkx"]
[ext_resource type="Resource" uid="uid://bpi21xakop5wy" path="res://assets/state/states/first_boot_plugin_select.tres" id="3_r2fie"]
[ext_resource type="PackedScene" uid="uid://uljtdvmuol3l" path="res://core/systems/input/focus_group_setter.tscn" id="4_byts3"]
-[ext_resource type="PackedScene" uid="uid://bo077a5mwi7xl" path="res://core/ui/components/transition_fade_in.tscn" id="5_6lpmx"]
+[ext_resource type="PackedScene" uid="uid://shvyhrv5sx3v" path="res://core/systems/state/state_watcher.tscn" id="5_svc26"]
[ext_resource type="PackedScene" uid="uid://cf5bdr4sh2irb" path="res://core/ui/card_ui/settings/plugin_store_menu.tscn" id="6_cox3h"]
[ext_resource type="PackedScene" uid="uid://d0u3rsa5qpj57" path="res://core/ui/components/subsection_label.tscn" id="6_mn0iu"]
[ext_resource type="PackedScene" uid="uid://c71ayw7pcw6u6" path="res://core/ui/components/card_button.tscn" id="7_4pfh5"]
+[ext_resource type="PackedScene" uid="uid://bw8113ocotx2r" path="res://core/systems/effects/fade_effect.tscn" id="7_6yapm"]
[ext_resource type="PackedScene" uid="uid://b76dvfuouhlwd" path="res://core/systems/state/state_updater.tscn" id="8_7mmqh"]
[ext_resource type="PackedScene" uid="uid://8m20p2s0v5gb" path="res://core/systems/input/focus_group.tscn" id="9_di8uy"]
[ext_resource type="Resource" uid="uid://j1csnsnb672v" path="res://assets/state/states/first_boot_plugin_setup.tres" id="11_83y3o"]
@@ -20,16 +22,34 @@ grow_horizontal = 2
grow_vertical = 2
theme_override_constants/margin_left = 100
theme_override_constants/margin_right = 20
+script = ExtResource("1_v2m4r")
-[node name="VisibilityManager" parent="." instance=ExtResource("1_glflu")]
+[node name="InputWatcher" parent="." instance=ExtResource("2_lfjkx")]
+stop_propagation = true
+process_input_mode = 1
+action = "ogui_east"
+
+[node name="StateUpdater" parent="InputWatcher" instance=ExtResource("8_7mmqh")]
state_machine = ExtResource("2_8r7jx")
+action = 2
+on_signal = "input_released"
+
+[node name="StateWatcher" parent="." instance=ExtResource("5_svc26")]
state = ExtResource("3_r2fie")
-[node name="FocusGroupSetter" parent="VisibilityManager" node_paths=PackedStringArray("target") instance=ExtResource("4_byts3")]
-target = NodePath("../../HBoxContainer/MarginContainer/VBoxContainer/PluginStoreMenu/MarginContainer/HFlowContainer/FocusGroup")
-on_signal = "entered"
+[node name="FadeEffect" parent="StateWatcher" node_paths=PackedStringArray("target") instance=ExtResource("7_6yapm")]
+target = NodePath("../..")
+on_signal = "state_entered"
+fade_out_signal = "state_exited"
+on_signal = "state_entered"
-[node name="TransitionFadeIn" parent="VisibilityManager" instance=ExtResource("5_6lpmx")]
+[node name="FocusGroupSetter" parent="StateWatcher/FadeEffect" node_paths=PackedStringArray("target") instance=ExtResource("4_byts3")]
+target = NodePath("../../../HBoxContainer/MarginContainer/VBoxContainer/FocusGroup")
+on_signal = "effect_finished"
+
+[node name="FocusGroupSetter" parent="StateWatcher" node_paths=PackedStringArray("target") instance=ExtResource("4_byts3")]
+target = NodePath("../../HBoxContainer/MarginContainer/VBoxContainer/FocusGroup")
+on_signal = "state_refreshed"
[node name="HBoxContainer" type="HBoxContainer" parent="."]
layout_mode = 2
@@ -69,14 +89,11 @@ layout_mode = 2
size_flags_vertical = 3
[node name="InputWatcher" parent="HBoxContainer/MarginContainer/VBoxContainer/PluginStoreMenu" index="0"]
+stop_propagation = false
process_input_mode = 1
-[node name="StateUpdater" parent="HBoxContainer/MarginContainer/VBoxContainer/PluginStoreMenu/InputWatcher" index="0"]
-state_machine = ExtResource("2_8r7jx")
-
-[node name="FocusGroup" parent="HBoxContainer/MarginContainer/VBoxContainer/PluginStoreMenu/MarginContainer/HFlowContainer" index="0" node_paths=PackedStringArray("focus_neighbor_bottom", "focus_neighbor_top")]
+[node name="FocusGroup" parent="HBoxContainer/MarginContainer/VBoxContainer/PluginStoreMenu/MarginContainer/HFlowContainer" index="0" node_paths=PackedStringArray("focus_neighbor_bottom")]
focus_neighbor_bottom = NodePath("../../../../FocusGroup")
-focus_neighbor_top = NodePath("../../../../FocusGroup")
[node name="NextButton" parent="HBoxContainer/MarginContainer/VBoxContainer" instance=ExtResource("7_4pfh5")]
layout_mode = 2
diff --git a/core/ui/card_ui/power/power_menu.gd b/core/ui/card_ui/power/power_menu.gd
index 8e62e9542..7d51a6407 100644
--- a/core/ui/card_ui/power/power_menu.gd
+++ b/core/ui/card_ui/power/power_menu.gd
@@ -12,7 +12,6 @@ var logger := Log.get_logger("PowerMenu")
@onready var shutdown_button := $%ShutdownButton
@onready var exit_button := $%ExitButton
@onready var cancel_button := $%CancelButton
-@onready var blur := $BlurRect
# Called when the node enters the scene tree for the first time.
@@ -23,30 +22,11 @@ func _ready() -> void:
reboot_button.button_down.connect(_on_systemctl_cmd.bind("reboot"))
exit_button.button_down.connect(_on_exit)
cancel_button.button_up.connect(_on_cancel)
-
- # Set the blur background shader parameters
- blur.material.set_shader_parameter("blur_amount", 1.587)
- blur.material.set_shader_parameter("mix_amount", 0.402)
- blur.material.set_shader_parameter("color_over", Color(0, 0, 0, 1))
func _on_state_entered(_from: State) -> void:
if focus_group:
focus_group.grab_focus()
-
- # TODO: Fix this
- # HACK to prevent giant pink texture from flashing for a second on first run
- # in OpenGL renderer
- if blur.has_meta("first_run"):
- return
- blur.set_meta("first_run", true)
-
- # Move the blur rect out of view for a few frames
- blur.position = Vector2(get_tree().get_root().size)
-
- # Create a timer and wait for a bit before moving the rect back
- await get_tree().create_timer(0.2).timeout
- blur.position = Vector2.ZERO
func _on_systemctl_cmd(command: String) -> void:
diff --git a/core/ui/card_ui/power/power_menu.tscn b/core/ui/card_ui/power/power_menu.tscn
index b67c488e2..a27c2e1b8 100644
--- a/core/ui/card_ui/power/power_menu.tscn
+++ b/core/ui/card_ui/power/power_menu.tscn
@@ -1,8 +1,8 @@
-[gd_scene load_steps=17 format=3 uid="uid://lfm3ps837gy5"]
+[gd_scene load_steps=15 format=3 uid="uid://lfm3ps837gy5"]
[ext_resource type="Script" path="res://core/ui/card_ui/power/power_menu.gd" id="2_0vc46"]
+[ext_resource type="Shader" path="res://assets/shaders/simple_blur.gdshader" id="2_hkifr"]
[ext_resource type="PackedScene" uid="uid://c6fg6uvng0ovi" path="res://core/systems/input/input_watcher.tscn" id="3_1whtm"]
-[ext_resource type="Shader" path="res://assets/shaders/simple_blur.gdshader" id="3_oe8pc"]
[ext_resource type="PackedScene" uid="uid://b76dvfuouhlwd" path="res://core/systems/state/state_updater.tscn" id="4_4rhfl"]
[ext_resource type="Resource" uid="uid://cadriyl38ny5y" path="res://assets/state/state_machines/popup_state_machine.tres" id="5_kxixy"]
[ext_resource type="Resource" uid="uid://bw0mtk7sso8m2" path="res://assets/state/states/power_menu.tres" id="5_u1rly"]
@@ -13,17 +13,11 @@
[ext_resource type="PackedScene" uid="uid://dithv38oqgy58" path="res://core/ui/components/section_label.tscn" id="10_y3iyf"]
[ext_resource type="PackedScene" uid="uid://c71ayw7pcw6u6" path="res://core/ui/components/card_button.tscn" id="12_2pwjc"]
-[sub_resource type="ShaderMaterial" id="ShaderMaterial_bxm1k"]
-shader = ExtResource("3_oe8pc")
-shader_parameter/blur_amount = 1.587
-shader_parameter/mix_amount = 0.402
-shader_parameter/color_over = null
-
-[sub_resource type="Gradient" id="Gradient_bc3c0"]
-colors = PackedColorArray(0, 0, 0, 1, 0, 0, 0, 1)
-
-[sub_resource type="GradientTexture1D" id="GradientTexture1D_nu0jx"]
-gradient = SubResource("Gradient_bc3c0")
+[sub_resource type="ShaderMaterial" id="ShaderMaterial_v0ws8"]
+shader = ExtResource("2_hkifr")
+shader_parameter/blur_amount = 1.578
+shader_parameter/mix_amount = null
+shader_parameter/color_over = Color(0, 0, 0, 0)
[sub_resource type="Resource" id="Resource_fafkw"]
script = ExtResource("10_6ywv6")
@@ -38,16 +32,27 @@ grow_horizontal = 2
grow_vertical = 2
script = ExtResource("2_0vc46")
-[node name="BlurRect" type="TextureRect" parent="."]
-modulate = Color(1, 1, 1, 0.501961)
-material = SubResource("ShaderMaterial_bxm1k")
+[node name="BackBufferCopy" type="BackBufferCopy" parent="."]
+copy_mode = 2
+
+[node name="ColorRect" type="ColorRect" parent="."]
+material = SubResource("ShaderMaterial_v0ws8")
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+color = Color(0, 0, 0, 1)
+
+[node name="ColorRect2" type="ColorRect" parent="."]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
-texture = SubResource("GradientTexture1D_nu0jx")
+color = Color(0, 0, 0, 0.666667)
[node name="InputWatcher" parent="." instance=ExtResource("3_1whtm")]
stop_propagation = true
diff --git a/core/ui/card_ui/quick_bar/performance_card.tscn b/core/ui/card_ui/quick_bar/performance_card.tscn
index 2e3c31f40..10c2e8a44 100644
--- a/core/ui/card_ui/quick_bar/performance_card.tscn
+++ b/core/ui/card_ui/quick_bar/performance_card.tscn
@@ -1,28 +1,14 @@
-[gd_scene load_steps=5 format=3 uid="uid://dycb7m0oj13ly"]
+[gd_scene load_steps=3 format=3 uid="uid://dycb7m0oj13ly"]
[ext_resource type="PackedScene" uid="uid://b5xnora73yd8x" path="res://core/ui/card_ui/quick_bar/qb_card.tscn" id="1_77cql"]
-[ext_resource type="PackedScene" uid="uid://b7piua3snox4i" path="res://core/ui/common/quick_bar/performance_menu.tscn" id="2_k3j2r"]
-
-[sub_resource type="Image" id="Image_asnwl"]
-data = {
-"data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0),
-"format": "RGBA8",
-"height": 16,
-"mipmaps": false,
-"width": 16
-}
-
-[sub_resource type="ImageTexture" id="ImageTexture_adlkc"]
-image = SubResource("Image_asnwl")
+[ext_resource type="PackedScene" uid="uid://dv3dt0j3jketh" path="res://core/ui/common/quick_bar/performance_menu.tscn" id="3_e67l3"]
[node name="PerformanceCard" instance=ExtResource("1_77cql")]
title = "Performance"
-[node name="HighlightTexture" parent="." index="4"]
-texture = SubResource("ImageTexture_adlkc")
-
[node name="SectionLabel" parent="MarginContainer/CardVBoxContainer" index="0"]
text = "Performance"
-[node name="PerformanceMenu" parent="MarginContainer/CardVBoxContainer/ContentContainer" index="0" instance=ExtResource("2_k3j2r")]
+[node name="Performance" parent="MarginContainer/CardVBoxContainer/ContentContainer" index="0" instance=ExtResource("3_e67l3")]
layout_mode = 2
+size_flags_vertical = 0
diff --git a/core/ui/card_ui/quick_bar/power_tools_card.tscn b/core/ui/card_ui/quick_bar/power_tools_card.tscn
deleted file mode 100644
index 165465ad4..000000000
--- a/core/ui/card_ui/quick_bar/power_tools_card.tscn
+++ /dev/null
@@ -1,29 +0,0 @@
-[gd_scene load_steps=5 format=3 uid="uid://v751ima8r8vg"]
-
-[ext_resource type="PackedScene" uid="uid://b5xnora73yd8x" path="res://core/ui/card_ui/quick_bar/qb_card.tscn" id="1_6lv34"]
-[ext_resource type="PackedScene" uid="uid://dv3dt0j3jketh" path="res://core/ui/common/quick_bar/powertools_menu.tscn" id="2_votl1"]
-
-[sub_resource type="Image" id="Image_n6cge"]
-data = {
-"data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0),
-"format": "RGBA8",
-"height": 16,
-"mipmaps": false,
-"width": 16
-}
-
-[sub_resource type="ImageTexture" id="ImageTexture_ca0vc"]
-image = SubResource("Image_n6cge")
-
-[node name="PowerToolsCard" instance=ExtResource("1_6lv34")]
-title = "Power Tools"
-
-[node name="HighlightTexture" parent="PanelContainer" index="0"]
-texture = SubResource("ImageTexture_ca0vc")
-
-[node name="SectionLabel" parent="MarginContainer/CardVBoxContainer" index="0"]
-text = "Power Tools"
-
-[node name="PowerTools" parent="MarginContainer/CardVBoxContainer/ContentContainer" index="0" instance=ExtResource("2_votl1")]
-layout_mode = 2
-size_flags_vertical = 0
diff --git a/core/ui/card_ui/quick_bar/quick_bar_menu.gd b/core/ui/card_ui/quick_bar/quick_bar_menu.gd
index 26d94012e..be7452d46 100644
--- a/core/ui/card_ui/quick_bar/quick_bar_menu.gd
+++ b/core/ui/card_ui/quick_bar/quick_bar_menu.gd
@@ -9,6 +9,7 @@ const qb_card_scene := preload("res://core/ui/card_ui/quick_bar/qb_card.tscn")
var launch_manager := load("res://core/global/launch_manager.tres") as LaunchManager
var quick_bar_menu_state := preload("res://assets/state/states/quick_bar_menu.tres") as State
var qb_focus := preload("res://core/ui/card_ui/quick_bar/quick_bar_menu_focus.tres") as FocusStack
+var gamepad_state := load("res://assets/state/states/gamepad_settings.tres") as State
@onready var viewport: VBoxContainer = $%Viewport
@onready var focus_group := $%FocusGroup as FocusGroup
@@ -16,6 +17,7 @@ var qb_focus := preload("res://core/ui/card_ui/quick_bar/quick_bar_menu_focus.tr
@onready var game_label := $%GameNameLabel
@onready var notify_button := $%NotifyButton
@onready var notify_card := $%NotificationsCard
+@onready var gamepad_button := $%GamepadButton
# Called when the node enters the scene tree for the first time.
@@ -23,6 +25,9 @@ func _ready() -> void:
quick_bar_menu_state.state_entered.connect(_on_state_entered)
quick_bar_menu_state.state_exited.connect(_on_state_exited)
launch_manager.app_switched.connect(_on_app_switched)
+ launch_manager.app_stopped.connect(_on_app_stopped)
+ launch_manager.app_launched.connect(_on_app_focus_changed)
+ gamepad_button.button_down.connect(_on_gampad_button_pressed)
# Handle when the notifications button is pressed
var on_notify_pressed := func():
@@ -45,6 +50,10 @@ func _on_state_exited(_to: State) -> void:
func _on_app_switched(_from: RunningApp, to: RunningApp) -> void:
+ _on_app_focus_changed(to)
+
+
+func _on_app_focus_changed(to: RunningApp) -> void:
if to == null:
playing_container.visible = false
return
@@ -54,6 +63,11 @@ func _on_app_switched(_from: RunningApp, to: RunningApp) -> void:
# TODO: Implement fetching game icon and setting it
+func _on_app_stopped(app: RunningApp) -> void:
+ if launch_manager.get_running().is_empty():
+ playing_container.visible = false
+
+
# Adds the given Control menu to the quick bar. A focus node can be given which will
# be the first node to focus
func add_child_menu(qb_item: Control, icon: Texture2D, focus_node: Control = null, title: String = ""):
@@ -84,3 +98,10 @@ func add_child_menu(qb_item: Control, icon: Texture2D, focus_node: Control = nul
focus_parent.add_child(focus_group)
viewport.add_child(qb_card)
+
+
+## Ensure that the library item meta data is always set before opening the gamepad
+## settings menu
+func _on_gampad_button_pressed() -> void:
+ var library_item := launch_manager.get_current_app_library_item()
+ gamepad_state.set_meta("item", library_item)
diff --git a/core/ui/card_ui/quick_bar/quick_bar_menu.tscn b/core/ui/card_ui/quick_bar/quick_bar_menu.tscn
index c89442234..4978e0a00 100644
--- a/core/ui/card_ui/quick_bar/quick_bar_menu.tscn
+++ b/core/ui/card_ui/quick_bar/quick_bar_menu.tscn
@@ -1,4 +1,4 @@
-[gd_scene load_steps=29 format=3 uid="uid://hroo3ll4inrb"]
+[gd_scene load_steps=30 format=3 uid="uid://hroo3ll4inrb"]
[ext_resource type="Script" path="res://core/ui/card_ui/quick_bar/quick_bar_menu.gd" id="1_56jo7"]
[ext_resource type="PackedScene" uid="uid://shvyhrv5sx3v" path="res://core/systems/state/state_watcher.tscn" id="2_6rvrx"]
@@ -13,8 +13,10 @@
[ext_resource type="Texture2D" uid="uid://bjscvn2us6tal" path="res://assets/ui/icons/bell.svg" id="10_4yppf"]
[ext_resource type="Texture2D" uid="uid://dq32os2qn6atc" path="res://assets/ui/icons/help.svg" id="11_a0ma3"]
[ext_resource type="PackedScene" uid="uid://b76dvfuouhlwd" path="res://core/systems/state/state_updater.tscn" id="12_ldp5y"]
+[ext_resource type="Texture2D" uid="uid://p3lsljjgjnv7" path="res://assets/ui/icons/keyboard-rounded.svg" id="13_625jj"]
[ext_resource type="Resource" uid="uid://d3gp85f35oiw6" path="res://assets/state/states/settings.tres" id="14_didkb"]
[ext_resource type="Resource" uid="uid://db5gbdl3xgwlq" path="res://assets/state/states/help_menu.tres" id="14_gr3i0"]
+[ext_resource type="Script" path="res://core/systems/input/keyboard_opener.gd" id="14_vjul7"]
[ext_resource type="Texture2D" uid="uid://c8pq5h4uim4pj" path="res://assets/ui/icons/game-controller.svg" id="15_0l0p5"]
[ext_resource type="PackedScene" uid="uid://dithv38oqgy58" path="res://core/ui/components/section_label.tscn" id="15_ip4q6"]
[ext_resource type="Texture2D" uid="uid://djy4rejy21s6g" path="res://icon.svg" id="16_5eydp"]
@@ -27,7 +29,6 @@
[ext_resource type="PackedScene" uid="uid://bjy50kdrebgre" path="res://core/ui/card_ui/quick_bar/notifications_card.tscn" id="19_pppbi"]
[ext_resource type="PackedScene" uid="uid://dxaeufuk7ump2" path="res://core/ui/card_ui/quick_bar/quick_settings_card.tscn" id="20_17ks0"]
[ext_resource type="PackedScene" uid="uid://dycb7m0oj13ly" path="res://core/ui/card_ui/quick_bar/performance_card.tscn" id="21_uw510"]
-[ext_resource type="PackedScene" uid="uid://v751ima8r8vg" path="res://core/ui/card_ui/quick_bar/power_tools_card.tscn" id="22_dtanu"]
[node name="QuickBarMenu" type="Control" groups=["quick-bar"]]
z_index = 20
@@ -109,6 +110,16 @@ custom_minimum_size = Vector2(26, 26)
layout_mode = 2
texture = ExtResource("10_4yppf")
+[node name="KeyboardButton" parent="MarginContainer/PanelContainer/MarginContainer/VBoxContainer/ButtonContainer" instance=ExtResource("9_6qs1m")]
+unique_name_in_owner = true
+custom_minimum_size = Vector2(26, 26)
+layout_mode = 2
+texture = ExtResource("13_625jj")
+
+[node name="KeyboardOpener" type="Node" parent="MarginContainer/PanelContainer/MarginContainer/VBoxContainer/ButtonContainer/KeyboardButton"]
+script = ExtResource("14_vjul7")
+on_signal = "button_up"
+
[node name="HelpButton" parent="MarginContainer/PanelContainer/MarginContainer/VBoxContainer/ButtonContainer" instance=ExtResource("9_6qs1m")]
custom_minimum_size = Vector2(26, 26)
layout_mode = 2
@@ -120,6 +131,7 @@ state = ExtResource("14_gr3i0")
on_signal = "button_up"
[node name="GamepadButton" parent="MarginContainer/PanelContainer/MarginContainer/VBoxContainer/ButtonContainer" instance=ExtResource("9_6qs1m")]
+unique_name_in_owner = true
custom_minimum_size = Vector2(26, 26)
layout_mode = 2
texture = ExtResource("15_0l0p5")
@@ -223,6 +235,3 @@ layout_mode = 2
[node name="PerformanceCard" parent="MarginContainer/PanelContainer/MarginContainer/VBoxContainer/ScrollContainer/Viewport" instance=ExtResource("21_uw510")]
layout_mode = 2
-
-[node name="PowerToolsCard" parent="MarginContainer/PanelContainer/MarginContainer/VBoxContainer/ScrollContainer/Viewport" instance=ExtResource("22_dtanu")]
-layout_mode = 2
diff --git a/core/ui/card_ui/settings/bluetooth_settings_menu.gd b/core/ui/card_ui/settings/bluetooth_settings_menu.gd
index 0355c31b4..d4a6d829c 100644
--- a/core/ui/card_ui/settings/bluetooth_settings_menu.gd
+++ b/core/ui/card_ui/settings/bluetooth_settings_menu.gd
@@ -1,12 +1,16 @@
extends Control
-var thread_pool := load("res://core/systems/threading/thread_pool.tres") as ThreadPool
-var bluetooth := load("res://core/systems/bluetooth/bluetooth_manager.tres") as BluetoothManager
-var adapter := bluetooth.get_adapter() # TODO: allow choosing adapter
+## Reference to the bluetooth service instance
+var bluetooth := load("res://core/systems/bluetooth/bluetooth_manager.tres") as BluezInstance
+## List of discovered bluetooth adapters
+var adapters := bluetooth.get_adapters() # TODO: allow choosing adapter
+## Currently used bluetooth adapter
+var adapter: BluetoothAdapter
+## Map of DBus path of bluetooth device to its tree item.
+## E.g. {"/org/bluez/dev_XX_XX_XX_XX_XX": }
var tree_items := {}
var logger := Log.get_logger("BluetoothMenu")
-@onready var timer := $%DiscoverTimer as Timer
@onready var enabled_toggle := $%EnableToggle as Toggle
@onready var discover_toggle := $%DiscoverToggle as Toggle
@onready var tree := $%Tree as Tree
@@ -15,18 +19,7 @@ var logger := Log.get_logger("BluetoothMenu")
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
- # Set the initial toggled states
- enabled_toggle.button_pressed = adapter.powered
- discover_toggle.button_pressed = adapter.discovering
-
- # Connect signals
- visibility_changed.connect(_on_visibility_changed)
- enabled_toggle.toggled.connect(_on_enable)
- discover_toggle.toggled.connect(_on_discover)
- timer.timeout.connect(_on_timer_timeout)
- tree.item_activated.connect(_on_item_activated)
-
- # Configure the tree
+ # Configure the tree with a root node and column titles
tree.create_item()
tree.set_column_title_alignment(0, HORIZONTAL_ALIGNMENT_CENTER)
tree.set_column_title(1, "Name")
@@ -40,56 +33,115 @@ func _ready() -> void:
# tree.set_column_title(5, "Signal Strength")
# tree.set_column_title_alignment(5, HORIZONTAL_ALIGNMENT_CENTER)
+ # Configure menu when bluetooth starts up or stops
+ bluetooth.started.connect(_on_bluetooth_started)
+ bluetooth.stopped.connect(_on_bluetooth_stopped)
+
+ # Configure the initial menu state
+ if _supports_bluetooth():
+ _on_bluetooth_started()
+ else:
+ _on_bluetooth_stopped()
+
+ # Connect signals
+ visibility_changed.connect(_on_visibility_changed)
+ enabled_toggle.toggled.connect(_on_enable)
+ discover_toggle.toggled.connect(_on_discover)
+ tree.item_activated.connect(_on_item_activated)
+
+
+## Returns whether or not the bluez service is running and bluetooth adapters are found
+func _supports_bluetooth() -> bool:
+ if not bluetooth.is_running():
+ return false
+ if bluetooth.get_adapters().size() == 0:
+ return false
+ return true
+
+
+## Invoked whenever the bluetooth service has started
+func _on_bluetooth_started() -> void:
+ logger.info("Bluetooth started")
+ adapters = bluetooth.get_adapters()
+ if not adapters.is_empty():
+ adapter = adapters[0] as BluetoothAdapter
+
+ # Listen for devices being added/removed
+ bluetooth.device_added.connect(_on_device_added)
+ bluetooth.device_removed.connect(_on_device_removed)
+
+ # Set the initial toggled states
+ if adapter:
+ enabled_toggle.button_pressed = adapter.powered
+ discover_toggle.button_pressed = adapter.discovering
+ else:
+ enabled_toggle.button_pressed = false
+ discover_toggle.button_pressed = false
+
+ # Perform initial device discovery
+ var devices := bluetooth.get_discovered_devices()
+ for device in devices:
+ _on_device_added(device)
+
+ _on_visibility_changed()
+
+
+## Invoked whenever the bluetooth service has stopped
+func _on_bluetooth_stopped() -> void:
+ logger.info("Bluetooth stopped")
+ adapters.clear()
+ adapter = null
+ var root := tree.get_root()
+ for dbus_path in tree_items.keys():
+ var item := tree_items[dbus_path] as TreeItem
+ root.remove_child(item)
+ tree_items.clear()
+
+ # Disconnect signals
+ if bluetooth.device_added.is_connected(_on_device_added):
+ bluetooth.device_added.disconnect(_on_device_added)
+ if bluetooth.device_removed.is_connected(_on_device_removed):
+ bluetooth.device_removed.disconnect(_on_device_removed)
+
+ _on_visibility_changed()
+
## Invoked when the menu becomes visible
func _on_visibility_changed():
if not is_visible_in_tree():
# Disable discovery if not visible
- if discover_toggle.button_pressed:
+ if adapter and discover_toggle.button_pressed:
adapter.stop_discovery()
return
# Show/hide parts of the menu if bluetooth is available
- var supports_bluetooth := bluetooth.supports_bluetooth()
+ var supports_bluetooth := _supports_bluetooth()
container_unavail.visible = not supports_bluetooth
container_avail.visible = supports_bluetooth
if not supports_bluetooth:
return
- _on_timer_timeout()
- enabled_toggle.button_pressed = adapter.powered
- discover_toggle.button_pressed = adapter.discovering
+ if adapter:
+ enabled_toggle.button_pressed = adapter.powered
+ discover_toggle.button_pressed = adapter.discovering
## Invoked when the enabled toggle is toggled
func _on_enable(toggled: bool) -> void:
+ if not adapter:
+ return
adapter.powered = toggled
## Invoked when the discover toggle is toggled
func _on_discover(toggled: bool) -> void:
- if toggled:
- timer.start()
- thread_pool.exec(adapter.start_discovery)
+ if not adapter:
+ logger.warn("No bluetooth adapter found to start discovery")
return
- timer.stop()
- thread_pool.exec(adapter.stop_discovery)
-
-
-## Invoked when the user selects a bluetooth device from the tree view
-func _on_item_activated() -> void:
- var selected := tree.get_selected()
- var device := selected.get_metadata(0) as BluetoothManager.Device
-
- # Disconnect if already connected
- if device.connected:
- selected.set_text(4, "Disconnecting")
- thread_pool.exec(device.disconnect_from)
+ if toggled:
+ adapter.start_discovery()
return
-
- # Try connecting to the device
- selected.set_text(4, "Connecting")
- thread_pool.exec(device.connect_to)
+ adapter.stop_discovery()
## Invoked when the discovery timer times out
@@ -102,8 +154,6 @@ func _on_timer_timeout() -> void:
for device in discovered:
var device_name := device.name
var address := device.address
- var paired := device.paired
- var connected := device.connected
addresses.append(address)
logger.debug("Discovered device: " + address)
@@ -133,8 +183,44 @@ func _on_timer_timeout() -> void:
tree_items.erase(address)
+func _on_device_added(device: BluetoothDevice) -> void:
+ var device_name := device.name
+ var address := device.address
+ var dbus_path := device.dbus_path
+ logger.debug("Discovered device:", address)
+
+ # Skip this device if it was already discovered
+ if dbus_path in tree_items:
+ return
+
+ # Skip this device if it has no name
+ if device_name == "":
+ return
+
+ # Create a tree item for this device
+ var root := tree.get_root()
+ var item := root.create_child()
+ item.set_metadata(0, device)
+ _on_device_updated(item)
+ device.updated.connect(_on_device_updated.bind(item))
+
+ # Add the item
+ tree_items[dbus_path] = item
+
+
+## Invoked whenever a bluetooth device has been removed
+func _on_device_removed(dbus_path: String) -> void:
+ if not dbus_path in tree_items:
+ return
+ var item := tree_items[dbus_path] as TreeItem
+ var root := tree.get_root()
+ root.remove_child(item)
+ tree_items.erase(dbus_path)
+
+
+## Invoked whenever a bluetooth device has property changes
func _on_device_updated(item: TreeItem) -> void:
- var device := item.get_metadata(0) as BluetoothManager.Device
+ var device := item.get_metadata(0) as BluetoothDevice
var device_name := device.name
var address := device.address
var paired := device.paired
@@ -162,3 +248,19 @@ func _on_device_updated(item: TreeItem) -> void:
item.set_icon(0, texture)
item.set_icon_max_width(0, 24)
item.set_text_alignment(0, HORIZONTAL_ALIGNMENT_CENTER)
+
+
+## Invoked when the user selects a bluetooth device from the tree view
+func _on_item_activated() -> void:
+ var selected := tree.get_selected()
+ var device := selected.get_metadata(0) as BluetoothDevice
+
+ # Disconnect if already connected
+ if device.connected:
+ selected.set_text(4, "Disconnecting")
+ device.disconnect_from()
+ return
+
+ # Try connecting to the device
+ selected.set_text(4, "Connecting")
+ device.connect_to()
diff --git a/core/ui/card_ui/settings/bluetooth_settings_menu.tscn b/core/ui/card_ui/settings/bluetooth_settings_menu.tscn
index 92d5e7c4c..a53eb216d 100644
--- a/core/ui/card_ui/settings/bluetooth_settings_menu.tscn
+++ b/core/ui/card_ui/settings/bluetooth_settings_menu.tscn
@@ -1,9 +1,11 @@
-[gd_scene load_steps=10 format=3 uid="uid://6ygxdkvh1hib"]
+[gd_scene load_steps=12 format=3 uid="uid://6ygxdkvh1hib"]
[ext_resource type="Script" path="res://core/ui/card_ui/settings/bluetooth_settings_menu.gd" id="1_7sjpd"]
[ext_resource type="PackedScene" uid="uid://8m20p2s0v5gb" path="res://core/systems/input/focus_group.tscn" id="2_36ef6"]
[ext_resource type="PackedScene" uid="uid://c6fg6uvng0ovi" path="res://core/systems/input/input_watcher.tscn" id="2_p7et2"]
+[ext_resource type="Script" path="res://core/systems/bluetooth/bluetooth_manager.gd" id="2_yoi1n"]
[ext_resource type="PackedScene" uid="uid://b76dvfuouhlwd" path="res://core/systems/state/state_updater.tscn" id="3_2trn0"]
+[ext_resource type="BluezInstance" uid="uid://peeajgfcx2fw" path="res://core/systems/bluetooth/bluetooth_manager.tres" id="3_aju5k"]
[ext_resource type="PackedScene" uid="uid://d1qb7euwlu7bh" path="res://core/ui/components/toggle.tscn" id="4_isnhb"]
[ext_resource type="Resource" uid="uid://iqrotrmq62i6" path="res://assets/state/state_machines/settings_state_machine.tres" id="4_l428g"]
[ext_resource type="PackedScene" uid="uid://shvyhrv5sx3v" path="res://core/systems/state/state_watcher.tscn" id="5_ivwga"]
@@ -19,6 +21,10 @@ grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_7sjpd")
+[node name="BluetoothManager" type="Node" parent="."]
+script = ExtResource("2_yoi1n")
+instance = ExtResource("3_aju5k")
+
[node name="InputWatcher" parent="." instance=ExtResource("2_p7et2")]
stop_propagation = true
action = "ogui_east"
@@ -36,9 +42,6 @@ script = ExtResource("7_klxjh")
target = NodePath("../../MarginContainer/ScrollContainer/AvailableContainer/VBoxContainer/FocusGroup")
on_signal = "state_entered"
-[node name="DiscoverTimer" type="Timer" parent="."]
-unique_name_in_owner = true
-
[node name="MarginContainer" type="MarginContainer" parent="."]
layout_mode = 1
anchors_preset = 15
diff --git a/core/ui/card_ui/settings/disks_settings_menu.gd b/core/ui/card_ui/settings/disks_settings_menu.gd
index 3fe3439c2..a10e03005 100644
--- a/core/ui/card_ui/settings/disks_settings_menu.gd
+++ b/core/ui/card_ui/settings/disks_settings_menu.gd
@@ -1,6 +1,6 @@
extends ScrollContainer
-var udisks2 := load("res://core/systems/disks/udisks2.tres") as UDisks2
+var udisks2 := load("res://core/systems/disks/disk_manager.tres") as UDisks2Instance
var steam_disks := load("res://core/systems/disks/steam_removable_media_manager.tres") as SteamRemovableMediaManager
const drive_card_scene: PackedScene = preload("res://core/ui/components/drive_card.tscn")
@@ -11,10 +11,12 @@ var logger := Log.get_logger("DisksMenu", Log.LEVEL.INFO)
@onready var focus_group: FocusGroup = $%FocusGroup
@onready var no_drive_label: Label = $%NoDisksLabel
+
# Called when the node enters the scene tree for the first time.
func _ready():
- if not udisks2.supports_disk_management():
+ if not udisks2.is_running():
return
+
udisks2.unprotected_devices_updated.connect(_on_drives_updated)
_on_drives_updated(udisks2.get_unprotected_devices())
@@ -49,7 +51,7 @@ func _on_drives_updated(devices: Array[BlockDevice]) -> void:
continue
# Create Drive Card
- var drive_card := drive_card_scene.instantiate()
+ var drive_card := drive_card_scene.instantiate() as DriveCard
container.add_child(drive_card)
drive_card.setup(drive)
drive_card.visible = true
diff --git a/core/ui/card_ui/settings/disks_settings_menu.tscn b/core/ui/card_ui/settings/disks_settings_menu.tscn
index babb7c5b8..36c6adcff 100644
--- a/core/ui/card_ui/settings/disks_settings_menu.tscn
+++ b/core/ui/card_ui/settings/disks_settings_menu.tscn
@@ -1,9 +1,11 @@
-[gd_scene load_steps=11 format=3 uid="uid://clbapexwfoqtu"]
+[gd_scene load_steps=13 format=3 uid="uid://clbapexwfoqtu"]
[ext_resource type="Script" path="res://core/ui/card_ui/settings/disks_settings_menu.gd" id="1_ct0k3"]
+[ext_resource type="Script" path="res://core/systems/disks/disk_manager.gd" id="2_2gbtg"]
[ext_resource type="PackedScene" uid="uid://c6fg6uvng0ovi" path="res://core/systems/input/input_watcher.tscn" id="2_6shyw"]
[ext_resource type="PackedScene" uid="uid://8m20p2s0v5gb" path="res://core/systems/input/focus_group.tscn" id="2_8gros"]
[ext_resource type="PackedScene" uid="uid://b76dvfuouhlwd" path="res://core/systems/state/state_updater.tscn" id="3_lwwgd"]
+[ext_resource type="UDisks2Instance" uid="uid://dhmtkhokrb8pu" path="res://core/systems/disks/disk_manager.tres" id="3_v1ku5"]
[ext_resource type="PackedScene" uid="uid://caeaxm6st4a4u" path="res://core/ui/components/drive_card.tscn" id="4_brwek"]
[ext_resource type="Resource" uid="uid://iqrotrmq62i6" path="res://assets/state/state_machines/settings_state_machine.tres" id="4_vkilo"]
[ext_resource type="PackedScene" uid="uid://shvyhrv5sx3v" path="res://core/systems/state/state_watcher.tscn" id="5_hkv7e"]
@@ -19,6 +21,10 @@ grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_ct0k3")
+[node name="DiskManager" type="Node" parent="."]
+script = ExtResource("2_2gbtg")
+instance = ExtResource("3_v1ku5")
+
[node name="InputWatcher" parent="." instance=ExtResource("2_6shyw")]
stop_propagation = true
action = "ogui_east"
diff --git a/core/ui/card_ui/settings/general_settings_menu.gd b/core/ui/card_ui/settings/general_settings_menu.gd
index a115f57e6..abb0773db 100644
--- a/core/ui/card_ui/settings/general_settings_menu.gd
+++ b/core/ui/card_ui/settings/general_settings_menu.gd
@@ -114,7 +114,7 @@ func _ready() -> void:
var i := 0
for locale in TranslationServer.get_loaded_locales():
var language := locale.split("_")[0]
- var language_name := TranslationServer.get_language_name(language)
+ var language_name := tr(TranslationServer.get_language_name(language))
lang_dropdown.add_item(language_name)
lang_dropdown.option_button.set_item_metadata(i, locale)
if locale == current_locale:
@@ -123,6 +123,9 @@ func _ready() -> void:
# Update the locale when it is changed
var on_language_change := func(idx: int) -> void:
+ if idx < 0:
+ logger.warn("Invalid language index selected:", idx)
+ return
var locale := lang_dropdown.option_button.get_item_metadata(idx) as String
var language_name := lang_dropdown.option_button.get_item_text(idx)
logger.info("Setting language to: " + locale)
diff --git a/core/ui/card_ui/settings/general_settings_menu.tscn b/core/ui/card_ui/settings/general_settings_menu.tscn
index 83869bf03..30a07eeef 100644
--- a/core/ui/card_ui/settings/general_settings_menu.tscn
+++ b/core/ui/card_ui/settings/general_settings_menu.tscn
@@ -1,4 +1,4 @@
-[gd_scene load_steps=23 format=3 uid="uid://dsgrw1grwef4m"]
+[gd_scene load_steps=24 format=3 uid="uid://dsgrw1grwef4m"]
[ext_resource type="Script" path="res://core/ui/card_ui/settings/general_settings_menu.gd" id="1_if7xt"]
[ext_resource type="PackedScene" uid="uid://c6fg6uvng0ovi" path="res://core/systems/input/input_watcher.tscn" id="2_b5gbi"]
@@ -19,6 +19,7 @@
[ext_resource type="PackedScene" uid="uid://cmjjyqx1pl23d" path="res://core/ui/components/text.tscn" id="9_sq2rc"]
[ext_resource type="PackedScene" uid="uid://b0cyl6fdqxevn" path="res://core/systems/input/scroller_joystick.tscn" id="10_06mt3"]
[ext_resource type="Theme" uid="uid://ehplgpp70vxa" path="res://assets/themes/card_ui-dracula.tres" id="10_b386h"]
+[ext_resource type="PackedScene" uid="uid://bk5ld0h1jgd2t" path="res://core/ui/components/card_button_setting.tscn" id="12_3b8j5"]
[ext_resource type="Theme" uid="uid://ddqvfbno2i1n4" path="res://assets/themes/card_ui-darksoul.tres" id="12_m1lrx"]
[ext_resource type="Theme" uid="uid://de64j20kxm1k1" path="res://assets/themes/card_ui-water-vapor.tres" id="13_2j54j"]
[ext_resource type="Theme" uid="uid://cw7auu2ayqnp8" path="res://assets/themes/card_ui-mountain.tres" id="14_wt0wj"]
@@ -93,20 +94,19 @@ text = "Automatic Updates"
separator_visible = false
description = "Automatically download and apply updates in the background when they are available"
-[node name="CheckUpdateButton" parent="MarginContainer/VBoxContainer/VBoxContainer" instance=ExtResource("7_qenel")]
+[node name="CheckUpdateButton" parent="MarginContainer/VBoxContainer/VBoxContainer" instance=ExtResource("12_3b8j5")]
unique_name_in_owner = true
layout_mode = 2
-size_flags_horizontal = 4
-text = "Check for Updates"
-uppercase = false
+text = "Check for updates"
+button_text = "Check for updates"
+disabled = false
-[node name="UpdateButton" parent="MarginContainer/VBoxContainer/VBoxContainer" instance=ExtResource("7_qenel")]
+[node name="UpdateButton" parent="MarginContainer/VBoxContainer/VBoxContainer" instance=ExtResource("12_3b8j5")]
unique_name_in_owner = true
-custom_minimum_size = Vector2(158, 0)
layout_mode = 2
-size_flags_horizontal = 4
-text = "Install Update"
-uppercase = false
+text = "Install Updates"
+button_text = "Update"
+disabled = false
[node name="HSeparator2" type="HSeparator" parent="MarginContainer/VBoxContainer/VBoxContainer"]
layout_mode = 2
diff --git a/core/ui/card_ui/settings/library_settings_menu.gd b/core/ui/card_ui/settings/library_settings_menu.gd
index f33f84cd2..f51e2036e 100644
--- a/core/ui/card_ui/settings/library_settings_menu.gd
+++ b/core/ui/card_ui/settings/library_settings_menu.gd
@@ -2,7 +2,7 @@ extends ScrollContainer
var settings_manager := load("res://core/global/settings_manager.tres") as SettingsManager
var library_manager := load("res://core/global/library_manager.tres") as LibraryManager
-var state_machine := load("res://assets/state/state_machines/global_state_machine.tres") as StateMachine
+var state_machine := load("res://assets/state/state_machines/menu_state_machine.tres") as StateMachine
var settings_state := load("res://assets/state/states/settings.tres") as State
var game_settings_state := preload("res://assets/state/states/game_settings.tres") as State
var button_scene := load("res://core/ui/components/card_button.tscn") as PackedScene
@@ -27,6 +27,8 @@ func _on_state_entered(_from: State) -> void:
for child in container.get_children():
if not child is CardButton:
continue
+ if child.name == "RefreshButton":
+ continue
container.remove_child(child)
child.queue_free()
diff --git a/core/ui/card_ui/settings/library_settings_menu.tscn b/core/ui/card_ui/settings/library_settings_menu.tscn
index 39d3547d2..abb33b7f5 100644
--- a/core/ui/card_ui/settings/library_settings_menu.tscn
+++ b/core/ui/card_ui/settings/library_settings_menu.tscn
@@ -1,4 +1,4 @@
-[gd_scene load_steps=11 format=3 uid="uid://drbp6ec8646v3"]
+[gd_scene load_steps=13 format=3 uid="uid://drbp6ec8646v3"]
[ext_resource type="Script" path="res://core/ui/card_ui/settings/library_settings_menu.gd" id="1_0w1vu"]
[ext_resource type="PackedScene" uid="uid://cemxrvvjgm4g" path="res://core/ui/components/slider.tscn" id="1_obgkx"]
@@ -10,6 +10,8 @@
[ext_resource type="Resource" uid="uid://iqrotrmq62i6" path="res://assets/state/state_machines/settings_state_machine.tres" id="4_cd7pj"]
[ext_resource type="PackedScene" uid="uid://8m20p2s0v5gb" path="res://core/systems/input/focus_group.tscn" id="5_sh522"]
[ext_resource type="Script" path="res://core/systems/input/focus_group_setter.gd" id="7_5nxbl"]
+[ext_resource type="PackedScene" uid="uid://bk5ld0h1jgd2t" path="res://core/ui/components/card_button_setting.tscn" id="9_3ae07"]
+[ext_resource type="Script" path="res://core/systems/library/library_refresher.gd" id="10_xjg34"]
[node name="LibrarySettingsMenu" type="ScrollContainer"]
anchors_preset = 15
@@ -53,6 +55,21 @@ layout_mode = 2
[node name="FocusGroup" parent="MarginContainer/VBoxContainer" node_paths=PackedStringArray("current_focus") instance=ExtResource("5_sh522")]
current_focus = NodePath("../MaxRecentAppsSlider")
+[node name="GeneralLabel" parent="MarginContainer/VBoxContainer" instance=ExtResource("3_x5lfl")]
+layout_mode = 2
+text = "General"
+
+[node name="RefreshLibraryButton" parent="MarginContainer/VBoxContainer" instance=ExtResource("9_3ae07")]
+layout_mode = 2
+text = "Refresh Library"
+description = "Trigger reloading your library"
+button_text = "Refresh"
+disabled = false
+
+[node name="LibraryRefresher" type="Node" parent="MarginContainer/VBoxContainer/RefreshLibraryButton"]
+script = ExtResource("10_xjg34")
+on_signal = "button_up"
+
[node name="HomeLabel" parent="MarginContainer/VBoxContainer" instance=ExtResource("3_x5lfl")]
layout_mode = 2
text = "Home"
diff --git a/core/ui/card_ui/settings/settings_menu.tscn b/core/ui/card_ui/settings/settings_menu.tscn
index b6a2ff313..c6302ced3 100644
--- a/core/ui/card_ui/settings/settings_menu.tscn
+++ b/core/ui/card_ui/settings/settings_menu.tscn
@@ -522,51 +522,64 @@ theme_override_constants/margin_bottom = 5
layout_mode = 2
size_flags_horizontal = 3
theme_override_styles/panel = SubResource("StyleBoxEmpty_a60ci")
+current_tab = 0
tabs_visible = false
[node name="GeneralSettings" parent="MarginContainer/HBoxContainer/ContentContainer/VBoxContainer/ContentContainer/MarginContainer/TabContainer" instance=ExtResource("29_8hwjo")]
layout_mode = 2
+metadata/_tab_index = 0
[node name="LibrarySettingsMenu" parent="MarginContainer/HBoxContainer/ContentContainer/VBoxContainer/ContentContainer/MarginContainer/TabContainer" instance=ExtResource("34_lrrl0")]
visible = false
layout_mode = 2
+metadata/_tab_index = 1
[node name="DisplaySettings" parent="MarginContainer/HBoxContainer/ContentContainer/VBoxContainer/ContentContainer/MarginContainer/TabContainer" instance=ExtResource("30_22tgj")]
visible = false
layout_mode = 2
+metadata/_tab_index = 2
[node name="NetworkSettings" parent="MarginContainer/HBoxContainer/ContentContainer/VBoxContainer/ContentContainer/MarginContainer/TabContainer" instance=ExtResource("31_35x2h")]
visible = false
layout_mode = 2
+metadata/_tab_index = 3
[node name="BluetoothSettingsMenu" parent="MarginContainer/HBoxContainer/ContentContainer/VBoxContainer/ContentContainer/MarginContainer/TabContainer" instance=ExtResource("33_a7xb2")]
visible = false
layout_mode = 2
+metadata/_tab_index = 4
[node name="AudioSettingsMenu" parent="MarginContainer/HBoxContainer/ContentContainer/VBoxContainer/ContentContainer/MarginContainer/TabContainer" instance=ExtResource("32_dqi6v")]
visible = false
layout_mode = 2
+metadata/_tab_index = 5
[node name="DisksMenu" parent="MarginContainer/HBoxContainer/ContentContainer/VBoxContainer/ContentContainer/MarginContainer/TabContainer" instance=ExtResource("40_lyyu6")]
visible = false
layout_mode = 2
+metadata/_tab_index = 6
[node name="PluginSettingsMenu" parent="MarginContainer/HBoxContainer/ContentContainer/VBoxContainer/ContentContainer/MarginContainer/TabContainer" instance=ExtResource("35_dooq8")]
visible = false
layout_mode = 2
+metadata/_tab_index = 7
[node name="PluginStoreMenu" parent="MarginContainer/HBoxContainer/ContentContainer/VBoxContainer/ContentContainer/MarginContainer/TabContainer" instance=ExtResource("35_0u4bv")]
visible = false
layout_mode = 2
+metadata/_tab_index = 8
[node name="ProcessesMenu" parent="MarginContainer/HBoxContainer/ContentContainer/VBoxContainer/ContentContainer/MarginContainer/TabContainer" instance=ExtResource("36_hnokx")]
visible = false
layout_mode = 2
+metadata/_tab_index = 9
[node name="LoggingSettings" parent="MarginContainer/HBoxContainer/ContentContainer/VBoxContainer/ContentContainer/MarginContainer/TabContainer" instance=ExtResource("37_iwtxk")]
visible = false
layout_mode = 2
+metadata/_tab_index = 10
[node name="GeneralControllerSettings" parent="MarginContainer/HBoxContainer/ContentContainer/VBoxContainer/ContentContainer/MarginContainer/TabContainer" instance=ExtResource("40_uqw2r")]
visible = false
layout_mode = 2
+metadata/_tab_index = 11
diff --git a/core/ui/card_ui_overlay_mode/card_ui_overlay_mode.gd b/core/ui/card_ui_overlay_mode/card_ui_overlay_mode.gd
index c83c7c437..8b9133881 100644
--- a/core/ui/card_ui_overlay_mode/card_ui_overlay_mode.gd
+++ b/core/ui/card_ui_overlay_mode/card_ui_overlay_mode.gd
@@ -1,10 +1,13 @@
extends Control
-var platform := preload("res://core/global/platform.tres") as Platform
-var gamescope := preload("res://core/global/gamescope.tres") as Gamescope
-var launch_manager := preload("res://core/global/launch_manager.tres") as LaunchManager
-var settings_manager := preload("res://core/global/settings_manager.tres") as SettingsManager
-var input_plumber := preload("res://core/systems/input/input_plumber.tres") as InputPlumber
+# Managers
+var platform := load("res://core/global/platform.tres") as Platform
+var gamescope := load("res://core/systems/gamescope/gamescope.tres") as GamescopeInstance
+var launch_manager := load("res://core/global/launch_manager.tres") as LaunchManager
+var settings_manager := load("res://core/global/settings_manager.tres") as SettingsManager
+var input_plumber := load("res://core/systems/input/input_plumber.tres") as InputPlumberInstance
+
+# State
var state_machine := (
preload("res://assets/state/state_machines/global_state_machine.tres") as StateMachine
)
@@ -12,36 +15,65 @@ var menu_state_machine := preload("res://assets/state/state_machines/menu_state_
var popup_state_machine := preload("res://assets/state/state_machines/popup_state_machine.tres") as StateMachine
var menu_state := preload("res://assets/state/states/menu.tres") as State
var popup_state := preload("res://assets/state/states/popup.tres") as State
-var quick_bar_state = preload("res://assets/state/states/quick_bar_menu.tres") as State
-var settings_state = preload("res://assets/state/states/settings.tres") as State
-var gamepad_state = preload("res://assets/state/states/gamepad_settings.tres") as State
-var base_state = preload("res://assets/state/states/in_game.tres") as State
+var quick_bar_state := preload("res://assets/state/states/quick_bar_menu.tres") as State
+var settings_state := preload("res://assets/state/states/settings.tres") as State
+var gamepad_state := preload("res://assets/state/states/gamepad_settings.tres") as State
+var base_state := preload("res://assets/state/states/in_game.tres") as State
+# Xwayland
var managed_states: Array[State] = [quick_bar_state, settings_state, gamepad_state]
+var xwayland_primary := gamescope.get_xwayland(gamescope.XWAYLAND_TYPE_PRIMARY)
+var xwayland_ogui := gamescope.get_xwayland(gamescope.XWAYLAND_TYPE_OGUI)
+var overlay_window_id := 0
+var set_steam_overlay_focus := false
+
+# Process
var PID: int = OS.get_process_id()
-var args := OS.get_cmdline_user_args()
+var launch_args := OS.get_cmdline_user_args()
var cmdargs := OS.get_cmdline_args()
-var display := Gamescope.XWAYLAND.OGUI
-var overlay_window_id := gamescope.get_window_id(PID, display)
var underlay_log: FileAccess
var underlay_process: int
var underlay_window_id: int
+# UI References
@onready var quick_bar_menu := $%QuickBarMenu
@onready var settings_menu := $%SettingsMenu
+# Constants
+
+const remove_list: PackedStringArray = [
+ "KeyboardButton",
+ "NotifyButton",
+ "HelpButton",
+ "VolumeSlider",
+ "BrightnessSlider",
+ "PerGameToggle",
+ "MangoAppSlider",
+ "FramerateLimitSlider",
+ "RefreshRateSlider"
+ ]
+
+const settings_remove_list: PackedStringArray = [
+ "LibraryButton",
+ "NetworkButton",
+ "BluetoothButton",
+ "AudioButton"
+ ]
+
+# Logger
var logger := Log.get_logger("Main", Log.LEVEL.INFO)
## Sets up overlay mode.
func _init():
# Discover the OpenGamepadUI window ID
+ if xwayland_ogui:
+ var ogui_windows := xwayland_ogui.get_windows_for_pid(PID)
+ if not ogui_windows.is_empty():
+ overlay_window_id = ogui_windows[0]
if overlay_window_id <= 0:
logger.error("Unable to detect Window ID. Overlay is not going to work!")
logger.info("Found primary window id: {0}".format([overlay_window_id]))
- # Back button wont close windows without this. OverlayInputManager prevents poping the last state.
- state_machine.push_state(base_state)
-
# Ensure LaunchManager doesn't override our custom overlay management l
launch_manager.should_manage_overlay = false
@@ -58,9 +90,9 @@ func _init():
func _ready() -> void:
# Workaround old versions that don't pass launch args via update pack
# TODO: Parse the parent PID's CLI args and use those instead.
- if "--skip-update-pack" in cmdargs and args.size() == 0:
+ if "--skip-update-pack" in cmdargs and launch_args.size() == 0:
logger.warn("Launched via update pack without arguments! Falling back to default.")
- args = ["steam", "-gamepadui", "-steamos3", "-steampal", "-steamdeck"]
+ launch_args = PackedStringArray(["steam", "-gamepadui", "-steamos3", "-steampal", "-steamdeck"])
# Configure the locale
logger.debug("Setup Locale")
@@ -83,35 +115,33 @@ func _ready() -> void:
# Set up the session
logger.debug("Setup Overlay Mode")
- _setup_overlay_mode(args)
+ _setup_overlay_mode(launch_args)
# Set the theme if one was set
- logger.debug("Setup Theme")
- var theme_path := settings_manager.get_value("general", "theme", "") as String
- if theme_path == "":
- logger.debug("No theme set. Using default theme.")
-
- var current_theme = get_theme()
- if theme_path != "" && current_theme.resource_path != theme_path:
- logger.debug("Setting theme to: " + theme_path)
- var loaded_theme = load(theme_path)
- if loaded_theme != null:
- # TODO: This is a workaround, themes aren't properly set the first time.
- call_deferred("set_theme", loaded_theme)
- call_deferred("set_theme", current_theme)
- call_deferred("set_theme", loaded_theme)
- else:
- logger.debug("Unable to load theme")
+ var theme_path := settings_manager.get_value("general", "theme", "res://assets/themes/card_ui-dracula.tres") as String
+ if theme_path.is_empty():
+ logger.error("Failed to load theme from settings manager.")
+ return
+ logger.debug("Setting theme to: " + theme_path)
+ var loaded_theme = load(theme_path)
+ if loaded_theme != null:
+ @warning_ignore("unsafe_call_argument")
+ set_theme(loaded_theme)
+ else:
+ logger.debug("Unable to load theme")
## Finds needed PID's and global vars, Starts the user defined program as an
## underlay process.
-func _setup_overlay_mode(args: Array) -> void:
+func _setup_overlay_mode(args: PackedStringArray) -> void:
# Always push the base state if we end up with an empty stack.
var on_states_emptied := func():
state_machine.push_state.call_deferred(base_state)
state_machine.emptied.connect(on_states_emptied)
+ # Back button wont close windows without this. OverlayInputManager prevents poping the last state.
+ state_machine.push_state(base_state)
+
# Whenever the menu state is refreshed, refresh the menu state machine to
# re-grab focus.
var on_menu_refreshed := func():
@@ -143,42 +173,43 @@ func _setup_overlay_mode(args: Array) -> void:
base_state.state_exited.connect(_on_base_state_exited)
# Don't crash if we're not launching another program.
- if args == []:
+ if args.is_empty():
logger.warn("overlay mode started with no launcher arguments.")
return
if "steam" in args:
+ logger.info("Starting Steam with args:", args)
_start_steam_process(args)
else:
+ logger.info("Starting underlay process with args:", args)
var log_path := OS.get_environment("HOME") + "/.underlay-stdout.log"
_start_underlay_process(args, log_path)
# Remove unneeded/conflicting elements from default menues
- var remove_list: PackedStringArray = ["PerformanceCard", "NotifyButton", "HelpButton", "VolumeSlider", "BrightnessSlider", "PerGameToggle"]
+
_remove_children(remove_list, quick_bar_menu)
- var settings_remove_list: PackedStringArray = ["LibraryButton", "NetworkButton", "BluetoothButton", "AudioButton"]
_remove_children(settings_remove_list, settings_menu)
# Setup inputplumber to receive guide presses.
- input_plumber.set_intercept_mode(InputPlumber.INTERCEPT_MODE.PASS)
- input_plumber.set_intercept_activation(["Gamepad:Button:Guide", "Gamepad:Button:East"], "Gamepad:Button:QuickAccess2")
+ input_plumber.set_intercept_mode(InputPlumberInstance.INTERCEPT_MODE_PASS)
+ input_plumber.set_intercept_activation(PackedStringArray(["Gamepad:Button:Guide", "Gamepad:Button:East"]), "Gamepad:Button:QuickAccess2")
# Sets the intercept mode and intercept activation keys to what overlay_mode expects.
- var on_device_changed := func(device: InputPlumber.CompositeDevice):
- var intercept_mode : InputPlumber.INTERCEPT_MODE = input_plumber.intercept_mode_current
+ var on_device_changed := func(device: CompositeDevice):
+ var intercept_mode := input_plumber.intercept_mode
logger.debug("Setting intercept mode to: " + str(intercept_mode))
- input_plumber.set_intercept_mode_single(intercept_mode, device)
- input_plumber.set_intercept_activation_single(["Gamepad:Button:Guide", "Gamepad:Button:East"], "Gamepad:Button:QuickAccess2", device)
- input_plumber.composite_device_changed.connect(on_device_changed)
+ device.intercept_mode = intercept_mode
+ device.set_intercept_activation(PackedStringArray(["Gamepad:Button:Guide", "Gamepad:Button:East"]), "Gamepad:Button:QuickAccess2")
+ input_plumber.composite_device_added.connect(on_device_changed)
# Removes specified child elements from the given Node.
func _remove_children(remove_list: PackedStringArray, parent:Node) -> void:
var child_count := parent.get_child_count()
- var to_remove_list := []
+ var to_remove_list: Array[Node] = []
for child_idx in child_count:
- var child = parent.get_child(child_idx)
+ var child := parent.get_child(child_idx)
logger.trace("Checking if " + child.name + " in remove list...")
if child.name in remove_list:
logger.trace(child.name + " queued for removal!")
@@ -195,10 +226,11 @@ func _remove_children(remove_list: PackedStringArray, parent:Node) -> void:
logger.trace("Removing " + child.name)
child.queue_free()
+
## Starts Steam as an underlay process
-func _start_steam_process(args: Array) -> void:
+func _start_steam_process(args: PackedStringArray) -> void:
logger.debug("Starting steam: " + str(args))
- var underlay_log_path = OS.get_environment("HOME") + "/.steam-stdout.log"
+ var underlay_log_path := OS.get_environment("HOME") + "/.steam-stdout.log"
_start_underlay_process(args, underlay_log_path)
_find_underlay_window_id()
@@ -213,35 +245,36 @@ func _start_steam_process(args: Array) -> void:
## Called to start the specified underlay process and redirects logging to a
## seperate log file.
-func _start_underlay_process(args: Array, log_path: String) -> void:
+func _start_underlay_process(args: PackedStringArray, _log_path: String) -> void:
logger.debug("Starting underlay process: " + str(args))
- # Set up loggining in the new thread.
- args.append("2>&1")
- args.append(log_path)
+ ## TODO: Fix this so it works
+ ## Set up logging in the new thread.
+ #args.append("2>&1")
+ #args.append(log_path)
# Setup logging
- underlay_log = FileAccess.open(log_path, FileAccess.WRITE)
- var error := underlay_log.get_open_error()
- if error != OK:
- logger.warn("Got error opening log file.")
- else:
- logger.info("Started logging underlay process at " + log_path)
- var command: String = "bash"
- underlay_process = Reaper.create_process(command, ["-c", " ".join(args)])
+ #underlay_log = FileAccess.open(log_path, FileAccess.WRITE)
+ #var error := FileAccess.get_open_error()
+ #if error != OK:
+ #logger.warn("Got error opening log file.")
+ #else:
+ #logger.info("Started logging underlay process at " + log_path)
+ var command: String = args[0]
+ args.remove_at(0)
+ underlay_process = Reaper.create_process(command, args)
## Called to identify the xwayland window ID of the underlay process.
func _find_underlay_window_id() -> void:
# Find Steam in the display tree
- var root_win_id := gamescope.get_root_window_id(display)
- var all_windows := gamescope.get_all_windows(root_win_id, display)
+ var root_win_id := xwayland_ogui.root_window_id
+ var all_windows := xwayland_ogui.get_all_windows(root_win_id)
for window in all_windows:
if window == overlay_window_id:
continue
- if gamescope.has_xprop(window, "STEAM_NOTIFICATION", display):
+ if xwayland_ogui.has_notification(window):
underlay_window_id = window
logger.info("Found steam! " + str(underlay_window_id))
- gamescope.focused_app_updated.connect(_on_app_focus_changed)
break
# If we didn't find the window_id, set up a tiemr to loop back and try again.
@@ -256,49 +289,45 @@ func _find_underlay_window_id() -> void:
## Called when the base state is entered.
-func _on_base_state_entered(from: State) -> void:
+func _on_base_state_entered(_from: State) -> void:
+ logger.debug("Setting Underlay proccess window as overlay")
+
# Manage input focus
- input_plumber.set_intercept_mode(InputPlumber.INTERCEPT_MODE.PASS)
- if gamescope.set_input_focus(overlay_window_id, 0) != OK:
+ input_plumber.set_intercept_mode(InputPlumberInstance.INTERCEPT_MODE_PASS)
+ if xwayland_ogui.set_input_focus(overlay_window_id, 0) != OK:
+ logger.error("Unable to set STEAM_INPUT_FOCUS atom!")
+ if xwayland_ogui.set_input_focus(underlay_window_id, 1) != OK:
logger.error("Unable to set STEAM_INPUT_FOCUS atom!")
# Manage overlay
- gamescope.set_overlay(overlay_window_id, 0, display)
- gamescope.set_overlay(underlay_window_id, 1, display)
+ xwayland_ogui.set_overlay(overlay_window_id, 0)
+ if self.set_steam_overlay_focus:
+ xwayland_ogui.set_overlay(underlay_window_id, 1)
## Called when a the base state is exited.
-func _on_base_state_exited(to: State) -> void:
+func _on_base_state_exited(_to: State) -> void:
+ logger.debug("Setting OpenGamepadUI window as overlay")
+
# Manage input focus
- input_plumber.set_intercept_mode(InputPlumber.INTERCEPT_MODE.ALL)
- if gamescope.set_input_focus(overlay_window_id, 1) != OK:
+ input_plumber.set_intercept_mode(InputPlumberInstance.INTERCEPT_MODE_ALL)
+ if xwayland_ogui.set_input_focus(overlay_window_id, 1) != OK:
+ logger.error("Unable to set STEAM_INPUT_FOCUS atom!")
+ if xwayland_ogui.set_input_focus(underlay_window_id, 0) != OK:
logger.error("Unable to set STEAM_INPUT_FOCUS atom!")
# Manage overlay
- gamescope.set_overlay(overlay_window_id, 1, display)
- gamescope.set_overlay(underlay_window_id, 0, display)
+ self.set_steam_overlay_focus = xwayland_ogui.get_overlay(underlay_window_id) == 1
+ xwayland_ogui.set_overlay(overlay_window_id, 1)
+ if self.set_steam_overlay_focus:
+ xwayland_ogui.set_overlay(underlay_window_id, 0)
## Verifies steam is still running by checking for the steam overlay, closes otherwise.
func _check_exit() -> void:
if Reaper.get_pid_state(underlay_process) in ["R (running)", "S (sleeping)"]:
return
- if gamescope.has_xprop(underlay_window_id, "STEAM_OVERLAY", display):
+ if xwayland_ogui.has_overlay(underlay_window_id):
return
logger.debug("Steam closed. Shutting down.")
get_tree().quit()
-
-
-func _on_app_focus_changed(_from: int, to: int) -> void:
- # On focus to the steam overlay, ensure the default profile is used.
- logger.warn("Changed window focus to app ID:", to)
- if to in [Gamescope.OVERLAY_GAME_ID, 0]:
- launch_manager.set_gamepad_profile("")
- return
-
- # On focus back to the game, ensure the game profile is set
- var _current_app := launch_manager.get_current_app()
- if not _current_app:
- logger.error("Unable to set gamepad profile. Current app is NULL and we aren't focused")
- return
- launch_manager.set_app_gamepad_profile(_current_app)
diff --git a/core/ui/card_ui_overlay_mode/card_ui_overlay_mode.tscn b/core/ui/card_ui_overlay_mode/card_ui_overlay_mode.tscn
index b09a8af15..2a4ae00b2 100644
--- a/core/ui/card_ui_overlay_mode/card_ui_overlay_mode.tscn
+++ b/core/ui/card_ui_overlay_mode/card_ui_overlay_mode.tscn
@@ -1,13 +1,21 @@
-[gd_scene load_steps=9 format=3 uid="uid://b13lnfkjbafkj"]
+[gd_scene load_steps=17 format=3 uid="uid://b13lnfkjbafkj"]
[ext_resource type="Theme" uid="uid://ehplgpp70vxa" path="res://assets/themes/card_ui-dracula.tres" id="1_0qmlq"]
[ext_resource type="Script" path="res://core/ui/card_ui_overlay_mode/card_ui_overlay_mode.gd" id="2_3ptao"]
[ext_resource type="PackedScene" uid="uid://bxnb8t7i08vma" path="res://core/systems/input/overlay_mode_input_manager.tscn" id="3_klhmb"]
-[ext_resource type="PackedScene" uid="uid://cbboox5bujlx1" path="res://core/systems/launcher/launch_manager.tscn" id="4_b1ok4"]
+[ext_resource type="Script" path="res://core/systems/input/input_icon_processor.gd" id="4_6rltg"]
+[ext_resource type="Script" path="res://core/systems/launcher/launcher.gd" id="4_o0rva"]
[ext_resource type="PackedScene" uid="uid://d2jiecrd5sw4s" path="res://core/ui/card_ui/settings/settings_menu.tscn" id="5_4sdt1"]
+[ext_resource type="Script" path="res://core/systems/gamescope/gamescope.gd" id="5_sgddx"]
+[ext_resource type="GamescopeInstance" uid="uid://chd0nc6gbfnw0" path="res://core/systems/gamescope/gamescope.tres" id="6_jj3bv"]
[ext_resource type="PackedScene" uid="uid://cwarv58ju0sow" path="res://core/ui/card_ui/gamepad/gamepad_settings.tscn" id="6_oddte"]
[ext_resource type="PackedScene" uid="uid://hroo3ll4inrb" path="res://core/ui/card_ui/quick_bar/quick_bar_menu.tscn" id="7_e54f8"]
+[ext_resource type="Script" path="res://core/systems/plugin/plugin_manager.gd" id="7_qqh0e"]
+[ext_resource type="Script" path="res://core/systems/performance/power_station.gd" id="8_kxe4b"]
[ext_resource type="PackedScene" uid="uid://eqqk1uve143x" path="res://core/ui/components/dialog.tscn" id="8_otm5f"]
+[ext_resource type="ResourceRegistry" uid="uid://bsr58xihnpn1j" path="res://core/systems/resource/resource_registry.tres" id="9_4si0w"]
+[ext_resource type="PowerStationInstance" uid="uid://c2mmrnh3rcs58" path="res://core/systems/performance/power_station.tres" id="9_nw6s5"]
+[ext_resource type="Script" path="res://core/systems/network/network_manager.gd" id="10_atypa"]
[node name="CardUIOverlayMode" type="Control" groups=["main"]]
layout_mode = 3
@@ -19,9 +27,28 @@ grow_vertical = 2
theme = ExtResource("1_0qmlq")
script = ExtResource("2_3ptao")
-[node name="InputManager" parent="." instance=ExtResource("3_klhmb")]
+[node name="InputIconProcessor" type="Node" parent="."]
+script = ExtResource("4_6rltg")
+
+[node name="Gamescope" type="Node" parent="."]
+script = ExtResource("5_sgddx")
+instance = ExtResource("6_jj3bv")
+
+[node name="Launcher" type="Node" parent="."]
+script = ExtResource("4_o0rva")
+
+[node name="PluginManager" type="Node" parent="."]
+script = ExtResource("7_qqh0e")
-[node name="LaunchManager" parent="." instance=ExtResource("4_b1ok4")]
+[node name="PowerStation" type="Node" parent="."]
+script = ExtResource("8_kxe4b")
+instance = ExtResource("9_nw6s5")
+
+[node name="NetworkManager" type="Node" parent="."]
+script = ExtResource("10_atypa")
+
+[node name="ResourceProcessor" type="ResourceProcessor" parent="."]
+registry = ExtResource("9_4si0w")
[node name="MenuContent" type="MarginContainer" parent="."]
unique_name_in_owner = true
@@ -67,3 +94,5 @@ anchor_right = 0.5
anchor_bottom = 0.5
grow_horizontal = 2
grow_vertical = 2
+
+[node name="InputManager" parent="." instance=ExtResource("3_klhmb")]
diff --git a/core/ui/common/debug/processes_menu.gd b/core/ui/common/debug/processes_menu.gd
index 77a56ea99..7683cb8ab 100644
--- a/core/ui/common/debug/processes_menu.gd
+++ b/core/ui/common/debug/processes_menu.gd
@@ -1,19 +1,26 @@
extends Control
-const Gamescope := preload("res://core/global/gamescope.tres")
+var gamescope := load("res://core/systems/gamescope/gamescope.tres") as GamescopeInstance
-signal displays_updated
+## Currently selected PID
+var _selected_pid := -1
+## Map of gamescope displays to XWayland instance
+## E.g. {":0": , ":1": }
+var _xwaylands := {}
-var selected_pid := -1
-
-@onready var displays := Gamescope.discover_gamescope_displays()
-@onready var refresh_timer := $RefreshTimer
+@onready var refresh_timer := $RefreshTimer as Timer
@onready var pid_inspector := $%PIDInspector as Tree
@onready var kill_button := $%KillButton as Button
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
+ # Discover Gamescope displays
+ var xwaylands := gamescope.get_xwaylands()
+ for xwayland in xwaylands:
+ var xwayland_name := xwayland.name
+ _xwaylands[xwayland_name] = xwayland
+
# Pause refresh when the inspector is not visible
var on_visible_changed := func():
if visible:
@@ -21,7 +28,6 @@ func _ready() -> void:
return
refresh_timer.stop()
visibility_changed.connect(on_visible_changed)
- refresh_timer.timeout.connect(_update_displays)
refresh_timer.timeout.connect(_update_pid_tree)
# Configure the PID inspector
@@ -41,34 +47,26 @@ func _on_pid_selected() -> void:
var selected := pid_inspector.get_selected()
var metadata = selected.get_metadata(0)
if not metadata:
- selected_pid = -1
+ _selected_pid = -1
kill_button.disabled = true
return
var pid := metadata as int
- selected_pid = pid
+ _selected_pid = pid
kill_button.disabled = false
# Triggers when the kill button is pressed
func _on_kill_pressed() -> void:
- if selected_pid < 1:
+ if _selected_pid < 1:
return
- Reaper.reap(selected_pid)
- OS.kill(selected_pid)
+ Reaper.reap(_selected_pid)
+ OS.kill(_selected_pid)
kill_button.disabled = true
-# Looks for gamescope displays at refresh interval
-func _update_displays() -> void:
- if len(displays) != 0:
- return
- displays = Gamescope.discover_gamescope_displays()
- displays_updated.emit()
-
-
# Update the PID tree component
func _update_pid_tree() -> void:
- if len(displays) == 0:
+ if _xwaylands.size() == 0:
return
# Get the PID tree component and get the root element
@@ -76,10 +74,9 @@ func _update_pid_tree() -> void:
var root := tree.get_root()
# Loop through all displays and find any processes with windows
- for display in displays:
-
+ for xwayland_name: String in _xwaylands.keys():
# Create a display root element if it does not exist
- var display_str := "Display %s" % display
+ var display_str := "Display %s" % xwayland_name
var display_root: TreeItem
for child in root.get_children():
var text := child.get_text(0)
@@ -90,26 +87,30 @@ func _update_pid_tree() -> void:
display_root.set_text(0, display_str)
# Update the tree for the given display
- _update_tree_for_display(display, tree, display_root)
+ _update_tree_for_display(xwayland_name, tree, display_root)
# Updates the given tree for the given display
func _update_tree_for_display(display_name: String, tree: Tree, root: TreeItem) -> void:
- var display := Gamescope.get_display_type(display_name)
+ if not display_name in _xwaylands:
+ return
+ var xwayland := _xwaylands[display_name] as GamescopeXWayland
# Get all windows for the given Gamescope display
- var windows_root := Gamescope.get_root_window_id(display)
- var windows_all := Gamescope.get_all_windows(windows_root, display)
+ var windows_root := xwayland.root_window_id
+ var windows_all := xwayland.get_all_windows(windows_root)
var pids := {}
for window in windows_all:
- var pid := Gamescope.get_window_pid(window, display)
- if not pid in pids:
- pids[pid] = []
- pids[pid].append(window)
+ var window_pids := xwayland.get_windows_for_pid(window)
+ for pid in window_pids:
+ if not pid in pids:
+ pids[pid] = []
+ @warning_ignore("unsafe_method_access")
+ pids[pid].append(window)
# Create a list of tree nodes to add or remove
- var needs_creation := []
- var needs_removal := []
+ var needs_creation: Array[int] = []
+ var needs_removal: Array[TreeItem] = []
# Get a list of all the current children in the tree so we can reconcile
# it with what processes are currently running
@@ -140,9 +141,8 @@ func _update_tree_for_display(display_name: String, tree: Tree, root: TreeItem)
pid_child.set_metadata(0, pid)
# Create a tree node for each window associated with the PID
- for window in pids[pid]:
+ for window: int in pids[pid]:
var window_child := tree.create_item(pid_child)
- var window_name := Gamescope.get_window_name(window, display)
+ var window_name := xwayland.get_window_name(window)
window_child.set_text(0, "Window {0} ({1})".format([window, window_name]))
window_child.set_metadata(0, pid)
-
diff --git a/core/ui/common/game/game_loading.gd b/core/ui/common/game/game_loading.gd
index 5a0e09791..0865c0369 100644
--- a/core/ui/common/game/game_loading.gd
+++ b/core/ui/common/game/game_loading.gd
@@ -1,17 +1,33 @@
extends Control
var launch_manager := load("res://core/global/launch_manager.tres") as LaunchManager
-
+var state_machine := (
+ preload("res://assets/state/state_machines/global_state_machine.tres") as StateMachine
+)
+var menu_state := preload("res://assets/state/states/menu.tres") as State
+var popup_state := preload("res://assets/state/states/popup.tres") as State
+var in_game_state := preload("res://assets/state/states/in_game.tres") as State
+var game_launching := false
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
- var on_app_launched := func(app: RunningApp):
- visible = true
- app.window_id_changed.connect(_on_window_created, CONNECT_ONE_SHOT)
- app.app_killed.connect(_on_window_created, CONNECT_ONE_SHOT)
- launch_manager.app_launched.connect(on_app_launched)
+ launch_manager.app_launched.connect(_on_app_launched)
+
+ var on_state_changed := func(_from: State, to: State):
+ if not game_launching:
+ visible = false
+ return
+ visible = to in [in_game_state, popup_state]
+ state_machine.state_changed.connect(on_state_changed)
+
+
+func _on_app_launched(app: RunningApp):
+ game_launching = true
+ app.app_type_detected.connect(_on_window_created, CONNECT_ONE_SHOT)
+ app.app_killed.connect(_on_window_created, CONNECT_ONE_SHOT)
func _on_window_created() -> void:
+ game_launching = false
visible = false
diff --git a/core/ui/common/game/game_loading.tscn b/core/ui/common/game/game_loading.tscn
index 9016bc1d0..9eff4db55 100644
--- a/core/ui/common/game/game_loading.tscn
+++ b/core/ui/common/game/game_loading.tscn
@@ -1,4 +1,4 @@
-[gd_scene load_steps=3 format=3]
+[gd_scene load_steps=3 format=3 uid="uid://b1kist0rarpcy"]
[ext_resource type="Script" path="res://core/ui/common/game/game_loading.gd" id="1_1ucmh"]
[ext_resource type="PackedScene" uid="uid://2tdbi1v6qb6h" path="res://core/ui/components/loading02.tscn" id="1_jduoa"]
diff --git a/core/ui/common/osk/on_screen_keyboard.gd b/core/ui/common/osk/on_screen_keyboard.gd
index cfb549089..80ece6941 100644
--- a/core/ui/common/osk/on_screen_keyboard.gd
+++ b/core/ui/common/osk/on_screen_keyboard.gd
@@ -8,13 +8,16 @@ signal mode_shifted(mode: MODE_SHIFT)
signal opened
signal closed
-const Gamescope := preload("res://core/global/gamescope.tres")
const key_scene := preload("res://core/ui/components/button.tscn")
+var gamescope := load("res://core/systems/gamescope/gamescope.tres") as GamescopeInstance
+var inputplumber := load("res://core/systems/input/input_plumber.tres") as InputPlumberInstance
+var state_machine := load("res://assets/state/state_machines/global_state_machine.tres") as StateMachine
## State machine to use to switch menu states in response to input events.
var popup_state_machine := (
preload("res://assets/state/state_machines/popup_state_machine.tres") as StateMachine
)
+var in_game_state := load("res://assets/state/states/in_game.tres") as State
var osk_state := preload("res://assets/state/states/osk.tres") as State
var input_icons := load("res://core/systems/input/input_icon_manager.tres") as InputIconManager
@@ -28,6 +31,7 @@ enum MODE_SHIFT {
@export var layout: KeyboardLayout
@export var instance: KeyboardInstance = preload("res://core/global/keyboard_instance.tres")
var _mode_shift: MODE_SHIFT = MODE_SHIFT.OFF
+var _last_input_focus: int
var logger := Log.get_logger("OSK")
@onready var rows_container := $%KeyboardRowsContainer
@@ -193,12 +197,33 @@ func open() -> void:
timer.timeout.connect(on_timeout, CONNECT_ONE_SHOT)
timer.start()
+ # If the keyboard is configured to send input to the game, set gamescope accordinly
+ if instance.context.type == instance.context.TYPE.X11:
+ var xwayland := gamescope.get_xwayland(gamescope.XWAYLAND_TYPE_OGUI)
+ var pid := OS.get_process_id()
+ var ogui_windows := xwayland.get_windows_for_pid(pid)
+ if not ogui_windows.is_empty():
+ var overlay_window_id := ogui_windows[0]
+ xwayland.set_input_focus(overlay_window_id, 2)
+
opened.emit()
# Closes the OSK
func close() -> void:
popup_state_machine.remove_state(osk_state)
+
+ # If the keyboard is configured to send input to the game, set gamescope accordinly
+ var xwayland := gamescope.get_xwayland(gamescope.XWAYLAND_TYPE_OGUI)
+ var pid := OS.get_process_id()
+ var ogui_windows := xwayland.get_windows_for_pid(pid)
+ if not ogui_windows.is_empty():
+ var overlay_window_id := ogui_windows[0]
+ if state_machine.current_state() == in_game_state:
+ xwayland.set_input_focus(overlay_window_id, 0)
+ else:
+ xwayland.set_input_focus(overlay_window_id, 1)
+
closed.emit()
@@ -279,8 +304,6 @@ func _on_key_pressed(key: KeyboardKeyConfig) -> void:
# Handle sending key presses to an xwayland instance
func _handle_x11(key: KeyboardKeyConfig) -> void:
- var xwayland := Gamescope.get_xwayland(Gamescope.XWAYLAND.GAME)
-
# Check for shift or capslock inputs
if key.input.keycode in [KEY_SHIFT, KEY_CAPSLOCK]:
_handle_native_action(key)
@@ -291,15 +314,32 @@ func _handle_x11(key: KeyboardKeyConfig) -> void:
if _mode_shift > MODE_SHIFT.OFF and key.mode_shift_input:
event = key.mode_shift_input
+ # Convert the keycode into an InputPlumber virtual keyboard event
+ var virtual_key := InputPlumberEvent.virtual_key_from_keycode(event.keycode)
+
+ # Find an InputPlumber keyboard to send the event
+ var virtual_keyboard: KeyboardDevice
+ for device in inputplumber.get_composite_devices():
+ var target_devices := device.get_target_devices()
+ for target_device in target_devices:
+ if target_device is KeyboardDevice:
+ virtual_keyboard = target_device
+ break
+
+ # Check to see if a keyboard was found
+ if not virtual_keyboard:
+ logger.error("Unable to find virtual InputPlumber keyboard to send input")
+ return
+
# Send a shift keypress if mode shifted
if _mode_shift > MODE_SHIFT.OFF:
- xwayland.send_key(KEY_SHIFT, true)
+ virtual_keyboard.send_key("KEY_LEFTSHIFT", true)
- xwayland.send_key(event.keycode, true)
- xwayland.send_key(event.keycode, false)
+ virtual_keyboard.send_key(virtual_key, true)
+ virtual_keyboard.send_key(virtual_key, false)
if _mode_shift > MODE_SHIFT.OFF:
- xwayland.send_key(KEY_SHIFT, false)
+ virtual_keyboard.send_key("KEY_LEFTSHIFT", false)
# Reset the modeshift if this was a one shot
if _mode_shift == MODE_SHIFT.ONE_SHOT:
diff --git a/core/ui/common/quick_bar/performance_menu.gd b/core/ui/common/quick_bar/performance_menu.gd
index f05304784..211b324ed 100644
--- a/core/ui/common/quick_bar/performance_menu.gd
+++ b/core/ui/common/quick_bar/performance_menu.gd
@@ -1,13 +1,305 @@
-extends Control
+extends VBoxContainer
-var logger := Log.get_logger("PerformanceMenu", Log.LEVEL.INFO)
+var _hardware_manager := load("res://core/systems/hardware/hardware_manager.tres") as HardwareManager
+var _platform := load("res://core/global/platform.tres") as Platform
+var _performance_manager := load("res://core/systems/performance/performance_manager.tres") as PerformanceManager
+var _power_station := load("res://core/systems/performance/power_station.tres") as PowerStationInstance
+var _profiles_available: PackedStringArray
-@onready var mangoapp_slider := $%MangoAppSlider
+@onready var focus_group := $%FocusGroup as FocusGroup
+@onready var cpu_boost_button := $CPUBoostButton as Toggle
+@onready var cpu_cores_slider := $CPUCoresSlider as ValueSlider
+@onready var gpu_freq_enable := $GPUFreqButton as Toggle
+@onready var gpu_freq_max_slider := $GPUFreqMaxSlider as ValueSlider
+@onready var gpu_freq_min_slider := $GPUFreqMinSlider as ValueSlider
+@onready var gpu_temp_slider := $GPUTempSlider as ValueSlider
+@onready var power_profile_dropdown := $PowerProfileDropdown as Dropdown
+@onready var tdp_boost_slider := $TDPBoostSlider as ValueSlider
+@onready var tdp_slider := $TDPSlider as ValueSlider
+@onready var smt_button := $SMTButton as Toggle
+@onready var cpu_label := $CPUSectionLabel as Control
+@onready var gpu_label := $GPUSectionLabel as Control
+@onready var wait_label := $WaitLabel as Control
+@onready var service_timer := $ServiceTimer as Timer
+@onready var apply_timer := $ApplyTimer as Timer
+@onready var mangoapp_slider := $%MangoAppSlider as ValueSlider
+@onready var mode_toggle := $%ModeToggle as Toggle
+
+var _power_station_running := false
+var _profile_loading := false
+var _current_profile: PerformanceProfile
+var logger := Log.get_logger("Performance", Log.LEVEL.INFO)
# Called when the node enters the scene tree for the first time.
+# Finds default values and current settings of the hardware.
func _ready() -> void:
+ # Setup dropdowns
+ var i := 0
+ _get_available_profiles()
+ power_profile_dropdown.clear()
+ for profile in _profiles_available:
+ power_profile_dropdown.add_item(profile, i)
+ i += 1
+
+ # Configure the interface
+ _on_profile_loaded(_performance_manager.current_profile)
+
+ _performance_manager.profile_loaded.connect(_on_profile_loaded)
mangoapp_slider.value_changed.connect(_on_mangoapp_changed)
+ mode_toggle.toggled.connect(_on_mode_toggled)
+
+ service_timer.timeout.connect(_on_service_timer_timeout)
+ apply_timer.timeout.connect(_on_apply_timer_timeout)
+
+ # Re-start the apply timer when changes happen
+ var on_changed := func() -> void:
+ if _profile_loading:
+ return
+ apply_timer.start()
+ cpu_boost_button.pressed.connect(on_changed)
+ smt_button.pressed.connect(on_changed)
+ gpu_freq_enable.pressed.connect(on_changed)
+ mode_toggle.pressed.connect(on_changed)
+
+ # Set the total number of available cores if the SMT button is pressed
+ var on_smt_pressed := func() -> void:
+ if not _hardware_manager.cpu:
+ return
+ var cpu := _hardware_manager.cpu
+ if smt_button.button_pressed:
+ cpu_cores_slider.max_value = cpu.core_count
+ else:
+ var cores := cpu.core_count / 2
+ if cpu_cores_slider.value > cores:
+ cpu_cores_slider.value = cores
+ cpu_cores_slider.max_value = cores
+ smt_button.pressed.connect(on_smt_pressed)
+
+ # Restart the timer when any slider changes happen
+ var on_slider_changed := func(_value) -> void:
+ if _profile_loading:
+ return
+ apply_timer.start()
+ cpu_cores_slider.value_changed.connect(on_slider_changed)
+ tdp_slider.value_changed.connect(on_slider_changed)
+ tdp_boost_slider.value_changed.connect(on_slider_changed)
+ gpu_freq_min_slider.value_changed.connect(on_slider_changed)
+ gpu_freq_max_slider.value_changed.connect(on_slider_changed)
+ gpu_temp_slider.value_changed.connect(on_slider_changed)
+
+ # Configure GPU frequency timers so the minimum value can never go higher
+ # than the maximum value slider and the maximum value can never go lower
+ # than the minimum value slider.
+ var on_gpu_freq_changed := func(_value: float, kind: String) -> void:
+ if kind == "min" and gpu_freq_min_slider.value > gpu_freq_max_slider.value:
+ gpu_freq_max_slider.value = gpu_freq_min_slider.value
+ return
+ if kind == "max" and gpu_freq_max_slider.value < gpu_freq_min_slider.value:
+ gpu_freq_min_slider.value = gpu_freq_max_slider.value
+ return
+ gpu_freq_min_slider.value_changed.connect(on_gpu_freq_changed.bind("min"))
+ gpu_freq_max_slider.value_changed.connect(on_gpu_freq_changed.bind("max"))
+
+ # Also restart the apply timer when dropdown changes happen
+ var on_dropdown_changed := func(index) -> void:
+ if _profile_loading:
+ return
+
+ var new_profile: PerformanceProfile
+ if _profiles_available[index] == "power-saving":
+ new_profile = _create_powersaving_profile()
+ elif _profiles_available[index] == "max-performance":
+ new_profile = _create_performance_profile(false)
+
+ if new_profile:
+ _on_profile_loaded(new_profile)
+ _performance_manager.apply_and_save_profile(_current_profile)
+ else:
+ apply_timer.start()
+ power_profile_dropdown.item_selected.connect(on_dropdown_changed)
+
+ # Toggle visibility when the GPU freq manual toggle is on
+ var on_manual_freq := func() -> void:
+ # Immediately apply manual GPU frequency so we can read the min/max
+ # values for the sliders
+ var card := _get_integrated_card()
+ if not card:
+ logger.warn("No integrated GPU to set manual frequency on!")
+ return
+ card.manual_clock = gpu_freq_enable.button_pressed
+
+ # Update the slider values with the current values
+ gpu_freq_min_slider.visible = gpu_freq_enable.button_pressed
+ gpu_freq_min_slider.min_value = round(card.clock_limit_mhz_min)
+ gpu_freq_min_slider.max_value = round(card.clock_limit_mhz_max)
+ gpu_freq_min_slider.value = round(card.clock_value_mhz_min)
+ gpu_freq_max_slider.visible = gpu_freq_enable.button_pressed
+ gpu_freq_max_slider.min_value = round(card.clock_limit_mhz_min)
+ gpu_freq_max_slider.max_value = round(card.clock_limit_mhz_max)
+ gpu_freq_max_slider.value = round(card.clock_value_mhz_max)
+ gpu_freq_enable.pressed.connect(on_manual_freq)
+
+
+# Triggers when the apply timer times out. The apply timer will start/restart
+# whenever the user makes a change to any item. When the timer runs out, it will
+# call this to apply the current profile.
+func _on_apply_timer_timeout() -> void:
+ if not _current_profile:
+ logger.debug("No loaded profile to apply")
+ return
+ logger.debug("Applying and saving profile")
+
+ # Update the profile based on the currently set values
+ var power_profile := _profiles_available[power_profile_dropdown.selected]
+ _current_profile.gpu_power_profile = power_profile
+ _current_profile.cpu_boost_enabled = cpu_boost_button.button_pressed
+ _current_profile.cpu_smt_enabled = smt_button.button_pressed
+ _current_profile.cpu_core_count_current = int(cpu_cores_slider.value)
+ _current_profile.tdp_current = tdp_slider.value
+ _current_profile.tdp_boost_current = tdp_boost_slider.value
+ _current_profile.gpu_manual_enabled = gpu_freq_enable.button_pressed
+ _current_profile.gpu_freq_min_current = gpu_freq_min_slider.value
+ _current_profile.gpu_freq_max_current = gpu_freq_max_slider.value
+ _current_profile.gpu_temp_current = gpu_temp_slider.value
+ _current_profile.advanced_mode = mode_toggle.button_pressed
+
+ _performance_manager.apply_and_save_profile(_current_profile)
+
+
+# Triggers every timeout to monitor the PowerStation DBus
+func _on_service_timer_timeout() -> void:
+ var bus_running := _power_station.is_running()
+ if bus_running == _power_station_running:
+ return
+
+ # If the state of powerstation changes, update the interface accordingly
+ _power_station_running = bus_running
+ _setup_interface()
+
+
+## Called when a performance profile is loaded
+func _on_profile_loaded(profile: PerformanceProfile) -> void:
+ if not _power_station.is_running():
+ logger.info("Unable to load performance profile. PowerStation not detected.")
+ return
+ var core_count := 1
+ if _hardware_manager.cpu:
+ core_count = _hardware_manager.cpu.core_count
+
+ logger.debug("Updating UI with loaded performance profile")
+ # Keep track of the currently loaded profile
+ _current_profile = profile
+
+ # Update UI components based on the loaded profile
+ _profile_loading = true
+ var idx := _profiles_available.find(profile.gpu_power_profile)
+ if idx > -1:
+ power_profile_dropdown.select(idx)
+ _setup_interface()
+
+ cpu_boost_button.button_pressed = profile.cpu_boost_enabled
+ smt_button.button_pressed = profile.cpu_smt_enabled
+ if smt_button.button_pressed:
+ cpu_cores_slider.max_value = core_count
+ else:
+ var cores := core_count / 2
+ if cpu_cores_slider.value > cores:
+ cpu_cores_slider.value = cores
+ cpu_cores_slider.max_value = cores
+ cpu_cores_slider.value = round(profile.cpu_core_count_current)
+
+ # Update GPU UI components
+ tdp_slider.value = round(profile.tdp_current)
+ tdp_boost_slider.value = round(profile.tdp_boost_current)
+ gpu_freq_enable.button_pressed = profile.gpu_manual_enabled
+ gpu_freq_enable.pressed.emit()
+ gpu_freq_min_slider.value = round(profile.gpu_freq_min_current)
+ gpu_freq_max_slider.value = round(profile.gpu_freq_max_current)
+ gpu_temp_slider.value = round(profile.gpu_temp_current)
+
+ mode_toggle.button_pressed = profile.advanced_mode
+
+ _profile_loading = false
+
+
+# Configure the min/max values and visibility based on detected performance
+# features.
+func _setup_interface() -> void:
+ # If powerstation is not running, hide everything
+ if not _power_station.is_running():
+ wait_label.visible = true
+ for node in get_children():
+ if node == wait_label:
+ continue
+ if node == Control:
+ (node as Control).visible = false
+ return
+
+ # Configure visibility for all components
+ wait_label.visible = false
+
+ var is_advanced := false
+ if _current_profile:
+ is_advanced = _current_profile.advanced_mode
+ if mode_toggle.button_pressed != is_advanced:
+ mode_toggle.button_pressed = is_advanced
+ focus_group.current_focus = mode_toggle
+
+ # Configure CPU components
+ if _power_station.cpu:
+ var cpu := _power_station.cpu
+ cpu_label.visible = is_advanced
+ cpu_boost_button.visible = cpu.has_feature("cpb") and is_advanced
+ smt_button.visible = cpu.has_feature("ht") and is_advanced
+ if cpu.smt_enabled:
+ cpu_cores_slider.max_value = cpu.cores_count
+ else:
+ cpu_cores_slider.max_value = cpu.cores_count / 2
+ cpu_cores_slider.visible = is_advanced
+
+ # Configure GPU components
+ if not _power_station.gpu:
+ return
+ var card := _get_integrated_card()
+
+ # Configure based on integrated graphics card
+ if not card:
+ return
+
+ gpu_label.visible = is_advanced
+
+ tdp_slider.visible = is_advanced
+ tdp_slider.min_value = round(_hardware_manager.gpu.tdp_min)
+ tdp_slider.max_value = round(_hardware_manager.gpu.tdp_max)
+
+ tdp_boost_slider.visible = is_advanced
+ tdp_boost_slider.max_value = round(_hardware_manager.gpu.max_boost)
+
+ gpu_freq_enable.visible = is_advanced
+
+ power_profile_dropdown.visible = not is_advanced
+
+ gpu_freq_min_slider.visible = card.manual_clock and is_advanced
+ gpu_freq_min_slider.min_value = round(card.clock_limit_mhz_min)
+ gpu_freq_min_slider.max_value = round(card.clock_limit_mhz_max)
+
+ gpu_freq_max_slider.visible = card.manual_clock and is_advanced
+ gpu_freq_max_slider.min_value = round(card.clock_limit_mhz_min)
+ gpu_freq_max_slider.max_value = round(card.clock_limit_mhz_max)
+
+ gpu_temp_slider.visible = is_advanced
+
+
+## Returns the primary integrated GPU instance
+func _get_integrated_card() -> GpuCard:
+ var card: GpuCard
+ var cards := _power_station.gpu.get_cards()
+ for c in cards:
+ if c.class != "integrated":
+ continue
+ card = c
+ return card
# Set the mangoapp config on slider change
@@ -27,3 +319,87 @@ func _on_mangoapp_changed(value: float) -> void:
if value >= 4:
MangoApp.set_config(MangoApp.CONFIG_INSANE)
return
+
+
+func _create_performance_profile(is_advanced: bool) -> PerformanceProfile:
+ var new_profile := PerformanceProfile.new()
+
+ # CPU Settings
+ new_profile.cpu_boost_enabled = true
+ new_profile.cpu_core_count_current = cpu_cores_slider.max_value
+ new_profile.cpu_smt_enabled = true
+
+ # GPU Settings
+ var profiles := _performance_manager.get_power_profiles_available() as PackedStringArray
+ if profiles.is_empty():
+ logger.error("No _platform profiles available. Unable to assume sane performance defaults.")
+ return null
+ if "custom" in profiles:
+ profiles.remove_at(profiles.find("custom"))
+ if not "max-performance" in profiles and not "performance" in profiles:
+ logger.error("Performance profile not found. Unable to assume sane performance defaults.")
+ return null
+ var profile_idx := profiles.find("max-performance")
+ if profile_idx == -1:
+ profile_idx = profiles.find("performance")
+ if profile_idx == -1:
+ logger.error("Performance profile not found. Unable to assume sane performance defaults.")
+ return null
+ new_profile.gpu_power_profile = profiles[profile_idx]
+ new_profile.gpu_freq_max_current = gpu_freq_max_slider.max_value
+ new_profile.gpu_freq_min_current = gpu_freq_min_slider.min_value
+ new_profile.gpu_manual_enabled = false
+ new_profile.gpu_temp_current = 95
+ new_profile.tdp_boost_current = tdp_boost_slider.max_value
+ new_profile.tdp_current = tdp_slider.max_value
+ new_profile.advanced_mode = is_advanced
+ return new_profile
+
+
+func _create_powersaving_profile() -> PerformanceProfile:
+ var new_profile := PerformanceProfile.new()
+
+ # CPU Settings
+ new_profile.cpu_boost_enabled = true
+ new_profile.cpu_core_count_current = cpu_cores_slider.max_value
+ new_profile.cpu_smt_enabled = true
+
+ # GPU Settings
+ _get_available_profiles()
+
+ if _profiles_available.is_empty():
+ logger.error("No _platform profiles available. Unable to assume sane performance defaults.")
+ return null
+ if not "power-saving" in _profiles_available:
+ logger.error("Power Saving profile not found. Unable to assume sane performance defaults.")
+ return null
+ var profile_idx := _profiles_available.find("power-saving")
+ if profile_idx == -1:
+ logger.error("Performance profile not found. Unable to assume sane performance defaults.")
+ return null
+
+ new_profile.gpu_power_profile = _profiles_available[profile_idx]
+ new_profile.gpu_freq_max_current = gpu_freq_max_slider.max_value
+ new_profile.gpu_freq_min_current = gpu_freq_min_slider.min_value
+ new_profile.gpu_manual_enabled = false
+ new_profile.gpu_temp_current = 95
+ var tdp_boost_mid = ((tdp_boost_slider.max_value - tdp_boost_slider.min_value) / 2) + tdp_boost_slider.min_value
+ new_profile.tdp_boost_current = tdp_boost_mid
+ var tdp_mid = ((tdp_slider.max_value - tdp_slider.min_value) / 2) + tdp_slider.min_value
+ new_profile.tdp_current = tdp_mid
+ new_profile.advanced_mode = false
+ return new_profile
+
+
+# Get
+func _get_available_profiles() -> void:
+ _profiles_available = _performance_manager.get_power_profiles_available()
+ if "custom" in _profiles_available:
+ var idx = _profiles_available.find("custom")
+ _profiles_available.remove_at(idx)
+
+
+# Adjust the available options based on the mode toggle
+func _on_mode_toggled(pressed: bool) -> void:
+ var new_profile := _create_performance_profile(pressed)
+ _on_profile_loaded(new_profile)
diff --git a/core/ui/common/quick_bar/performance_menu.tscn b/core/ui/common/quick_bar/performance_menu.tscn
index cfa5e66da..dfb503614 100644
--- a/core/ui/common/quick_bar/performance_menu.tscn
+++ b/core/ui/common/quick_bar/performance_menu.tscn
@@ -1,46 +1,184 @@
-[gd_scene load_steps=5 format=3 uid="uid://b7piua3snox4i"]
+[gd_scene load_steps=9 format=3 uid="uid://dv3dt0j3jketh"]
[ext_resource type="Script" path="res://core/ui/common/quick_bar/performance_menu.gd" id="1_r31yj"]
[ext_resource type="PackedScene" uid="uid://cemxrvvjgm4g" path="res://core/ui/components/slider.tscn" id="1_yptsc"]
[ext_resource type="PackedScene" uid="uid://8m20p2s0v5gb" path="res://core/systems/input/focus_group.tscn" id="2_my16i"]
[ext_resource type="Resource" uid="uid://dpc1o781f43ef" path="res://core/ui/card_ui/quick_bar/quick_bar_menu_focus.tres" id="3_hsr7n"]
+[ext_resource type="PackedScene" uid="uid://d0u3rsa5qpj57" path="res://core/ui/components/subsection_label.tscn" id="5_hil7p"]
+[ext_resource type="PackedScene" uid="uid://dithv38oqgy58" path="res://core/ui/components/section_label.tscn" id="6_ycrnf"]
+[ext_resource type="PackedScene" uid="uid://d1qb7euwlu7bh" path="res://core/ui/components/toggle.tscn" id="7_j02ci"]
+[ext_resource type="PackedScene" uid="uid://xei5afwefxud" path="res://core/ui/components/dropdown.tscn" id="8_j2331"]
-[node name="PerformanceMenu" type="Control"]
-layout_mode = 3
-anchors_preset = 15
+[node name="Performance" type="VBoxContainer"]
+anchors_preset = 10
anchor_right = 1.0
-anchor_bottom = 1.0
+offset_bottom = 28.0
grow_horizontal = 2
-grow_vertical = 2
-size_flags_horizontal = 3
-size_flags_vertical = 3
script = ExtResource("1_r31yj")
-[node name="VBoxContainer" type="VBoxContainer" parent="."]
-layout_mode = 1
-anchors_preset = 15
-anchor_right = 1.0
-anchor_bottom = 1.0
-grow_horizontal = 2
-grow_vertical = 2
-
-[node name="FocusGroup" parent="VBoxContainer" node_paths=PackedStringArray("current_focus") instance=ExtResource("2_my16i")]
-current_focus = NodePath("../MangoAppSlider")
+[node name="FocusGroup" parent="." instance=ExtResource("2_my16i")]
+unique_name_in_owner = true
focus_stack = ExtResource("3_hsr7n")
-[node name="MangoAppSlider" parent="VBoxContainer" instance=ExtResource("1_yptsc")]
+[node name="ApplyTimer" type="Timer" parent="."]
+wait_time = 1.5
+one_shot = true
+
+[node name="ServiceTimer" type="Timer" parent="."]
+wait_time = 5.0
+autostart = true
+
+[node name="MangoAppSlider" parent="." instance=ExtResource("1_yptsc")]
unique_name_in_owner = true
layout_mode = 2
text = "Performance Overlay"
max_value = 4.0
tick_count = 5
-[node name="FramerateLimitSlider" parent="VBoxContainer" instance=ExtResource("1_yptsc")]
+[node name="FramerateLimitSlider" parent="." instance=ExtResource("1_yptsc")]
visible = false
layout_mode = 2
text = "FPS Limit"
-[node name="RefreshRateSlider" parent="VBoxContainer" instance=ExtResource("1_yptsc")]
+[node name="RefreshRateSlider" parent="." instance=ExtResource("1_yptsc")]
visible = false
layout_mode = 2
text = "Refresh Rate"
+
+[node name="ModeToggle" parent="." instance=ExtResource("7_j02ci")]
+unique_name_in_owner = true
+layout_mode = 2
+text = "Advanced Mode"
+button_pressed = true
+
+[node name="WaitLabel" parent="." instance=ExtResource("5_hil7p")]
+custom_minimum_size = Vector2(100, 0)
+layout_mode = 2
+text = "Waiting for PowerStation service..."
+horizontal_alignment = 1
+vertical_alignment = 1
+autowrap_mode = 3
+
+[node name="CPUSectionLabel" parent="." instance=ExtResource("6_ycrnf")]
+visible = false
+layout_mode = 2
+text = "CPU Settings"
+
+[node name="CPUBoostButton" parent="." instance=ExtResource("7_j02ci")]
+visible = false
+layout_mode = 2
+focus_neighbor_left = NodePath("../GPUTempSlider")
+focus_neighbor_top = NodePath("../GPUTempSlider")
+focus_neighbor_right = NodePath("../SMTButton")
+focus_neighbor_bottom = NodePath("../SMTButton")
+focus_next = NodePath("../SMTButton")
+focus_previous = NodePath("../GPUTempSlider")
+text = "CPU Boost"
+separator_visible = false
+
+[node name="SMTButton" parent="." instance=ExtResource("7_j02ci")]
+visible = false
+layout_mode = 2
+focus_neighbor_left = NodePath("../CPUBoostButton")
+focus_neighbor_top = NodePath("../CPUBoostButton")
+focus_neighbor_right = NodePath("../CPUCoresSlider")
+focus_neighbor_bottom = NodePath("../CPUCoresSlider")
+focus_next = NodePath("../CPUCoresSlider")
+focus_previous = NodePath("../CPUBoostButton")
+text = "SMT Enabled"
+separator_visible = false
+
+[node name="CPUCoresSlider" parent="." instance=ExtResource("1_yptsc")]
+visible = false
+layout_mode = 2
+focus_neighbor_left = NodePath("../SMTButton")
+focus_neighbor_top = NodePath("../SMTButton")
+focus_neighbor_right = NodePath("../TDPSlider")
+focus_neighbor_bottom = NodePath("../TDPSlider")
+focus_next = NodePath("../TDPSlider")
+focus_previous = NodePath("../SMTButton")
+text = "CPU Cores"
+value = 1.0
+max_value = 1.0
+min_value = 1.0
+
+[node name="GPUSectionLabel" parent="." instance=ExtResource("6_ycrnf")]
+visible = false
+layout_mode = 2
+text = "GPU Settings"
+
+[node name="TDPSlider" parent="." instance=ExtResource("1_yptsc")]
+visible = false
+layout_mode = 2
+focus_neighbor_left = NodePath("../CPUCoresSlider")
+focus_neighbor_top = NodePath("../CPUCoresSlider")
+focus_neighbor_right = NodePath("../TDPBoostSlider")
+focus_neighbor_bottom = NodePath("../TDPBoostSlider")
+focus_next = NodePath("../TDPBoostSlider")
+focus_previous = NodePath("../CPUCoresSlider")
+text = "TDP"
+max_value = 0.0
+
+[node name="TDPBoostSlider" parent="." instance=ExtResource("1_yptsc")]
+visible = false
+layout_mode = 2
+focus_neighbor_left = NodePath("../TDPSlider")
+focus_neighbor_top = NodePath("../TDPSlider")
+focus_previous = NodePath("../TDPSlider")
+text = "TDP Boost"
+max_value = 0.0
+
+[node name="GPUFreqButton" parent="." instance=ExtResource("7_j02ci")]
+visible = false
+layout_mode = 2
+focus_neighbor_left = NodePath("../TDPBoostSlider")
+focus_neighbor_top = NodePath("../TDPBoostSlider")
+focus_neighbor_right = NodePath("../GPUFreqMinSlider")
+focus_neighbor_bottom = NodePath("../GPUFreqMinSlider")
+focus_next = NodePath("../GPUFreqMinSlider")
+focus_previous = NodePath("../TDPBoostSlider")
+text = "Manual Freq"
+separator_visible = false
+
+[node name="GPUFreqMinSlider" parent="." instance=ExtResource("1_yptsc")]
+visible = false
+layout_mode = 2
+focus_neighbor_right = NodePath("../GPUFreqMaxSlider")
+focus_neighbor_bottom = NodePath("../GPUFreqMaxSlider")
+focus_next = NodePath("../GPUFreqMaxSlider")
+text = "Min Freq"
+max_value = 0.0
+step = 100.0
+
+[node name="GPUFreqMaxSlider" parent="." instance=ExtResource("1_yptsc")]
+visible = false
+layout_mode = 2
+focus_neighbor_left = NodePath("../GPUFreqMinSlider")
+focus_neighbor_top = NodePath("../GPUFreqMinSlider")
+focus_neighbor_right = NodePath("../GPUTempSlider")
+focus_neighbor_bottom = NodePath("../GPUTempSlider")
+focus_next = NodePath("../GPUTempSlider")
+focus_previous = NodePath("../GPUFreqMinSlider")
+text = "Max Freq"
+max_value = 0.0
+step = 100.0
+
+[node name="GPUTempSlider" parent="." instance=ExtResource("1_yptsc")]
+visible = false
+layout_mode = 2
+focus_neighbor_left = NodePath("../GPUFreqMaxSlider")
+focus_neighbor_top = NodePath("../GPUFreqMaxSlider")
+focus_neighbor_right = NodePath("../CPUBoostButton")
+focus_neighbor_bottom = NodePath("../CPUBoostButton")
+focus_next = NodePath("../CPUBoostButton")
+focus_previous = NodePath("../GPUFreqMaxSlider")
+text = "GPU Temp Limit"
+value = 70.0
+max_value = 105.0
+min_value = 70.0
+
+[node name="PowerProfileDropdown" parent="." instance=ExtResource("8_j2331")]
+visible = false
+layout_mode = 2
+title = "Power Profile"
+description = ""
diff --git a/core/ui/common/quick_bar/powertools_menu.gd b/core/ui/common/quick_bar/powertools_menu.gd
deleted file mode 100644
index 222a585fa..000000000
--- a/core/ui/common/quick_bar/powertools_menu.gd
+++ /dev/null
@@ -1,273 +0,0 @@
-extends VBoxContainer
-
-var hardware_manager := load("res://core/systems/hardware/hardware_manager.tres") as HardwareManager
-var platform := load("res://core/global/platform.tres") as Platform
-var performance_manager := load("res://core/systems/performance/performance_manager.tres") as PerformanceManager
-var power_station := load("res://core/systems/performance/power_station.tres") as PowerStation
-
-@onready var cpu_boost_button := $CPUBoostButton as Toggle
-@onready var cpu_cores_slider := $CPUCoresSlider as ValueSlider
-@onready var gpu_freq_enable := $GPUFreqButton as Toggle
-@onready var gpu_freq_max_slider := $GPUFreqMaxSlider as ValueSlider
-@onready var gpu_freq_min_slider := $GPUFreqMinSlider as ValueSlider
-@onready var gpu_temp_slider := $GPUTempSlider as ValueSlider
-@onready var power_profile_dropdown := $PowerProfileDropdown as Dropdown
-@onready var tdp_boost_slider := $TDPBoostSlider as ValueSlider
-@onready var tdp_slider := $TDPSlider as ValueSlider
-@onready var thermal_profile_dropdown := $ThermalProfileDropdown as Dropdown
-@onready var smt_button := $SMTButton as Toggle
-@onready var cpu_label := $CPUSectionLabel as Control
-@onready var gpu_label := $GPUSectionLabel as Control
-@onready var wait_label := $WaitLabel as Control
-@onready var service_timer := $ServiceTimer as Timer
-@onready var apply_timer := $ApplyTimer as Timer
-
-var power_station_running := false
-var profile_loading := false
-var current_profile: PerformanceProfile
-var logger := Log.get_logger("PowerTools", Log.LEVEL.INFO)
-
-
-# Called when the node enters the scene tree for the first time.
-# Finds default values and current settings of the hardware.
-func _ready() -> void:
- # Listen for signals from performance manager
- performance_manager.profile_loaded.connect(_on_profile_loaded)
-
- # Configure a timer that will monitor the PowerStation DBus service
- service_timer.timeout.connect(_on_service_timer_timeout)
- # Configure a timer that will apply and save the performance profile
- apply_timer.timeout.connect(_on_apply_timer_timeout)
-
- # Configure the interface
- _setup_interface()
-
- # Re-start the apply timer when changes happen
- var on_changed := func() -> void:
- if profile_loading:
- return
- apply_timer.start()
- cpu_boost_button.pressed.connect(on_changed)
- smt_button.pressed.connect(on_changed)
- gpu_freq_enable.pressed.connect(on_changed)
-
- # Set the total number of available cores if the SMT button is pressed
- var on_smt_pressed := func() -> void:
- if not hardware_manager.cpu:
- return
- var cpu := hardware_manager.cpu
- if smt_button.button_pressed:
- cpu_cores_slider.max_value = cpu.core_count
- else:
- var cores := cpu.core_count / 2
- if cpu_cores_slider.value > cores:
- cpu_cores_slider.value = cores
- cpu_cores_slider.max_value = cores
- smt_button.pressed.connect(on_smt_pressed)
-
- # Restart the timer when any slider changes happen
- var on_slider_changed := func(_value) -> void:
- if profile_loading:
- return
- apply_timer.start()
- cpu_cores_slider.value_changed.connect(on_slider_changed)
- tdp_slider.value_changed.connect(on_slider_changed)
- tdp_boost_slider.value_changed.connect(on_slider_changed)
- gpu_freq_min_slider.value_changed.connect(on_slider_changed)
- gpu_freq_max_slider.value_changed.connect(on_slider_changed)
- gpu_temp_slider.value_changed.connect(on_slider_changed)
-
- # Configure GPU frequency timers so the minimum value can never go higher
- # than the maximum value slider and the maximum value can never go lower
- # than the minimum value slider.
- var on_gpu_freq_changed := func(_value: float, kind: String) -> void:
- if kind == "min" and gpu_freq_min_slider.value > gpu_freq_max_slider.value:
- gpu_freq_max_slider.value = gpu_freq_min_slider.value
- return
- if kind == "max" and gpu_freq_max_slider.value < gpu_freq_min_slider.value:
- gpu_freq_min_slider.value = gpu_freq_max_slider.value
- return
- gpu_freq_min_slider.value_changed.connect(on_gpu_freq_changed.bind("min"))
- gpu_freq_max_slider.value_changed.connect(on_gpu_freq_changed.bind("max"))
-
- # Also restart the apply timer when dropdown changes happen
- var on_dropdown_changed := func(_index) -> void:
- if profile_loading:
- return
- apply_timer.start()
- power_profile_dropdown.item_selected.connect(on_dropdown_changed)
- thermal_profile_dropdown.item_selected.connect(on_dropdown_changed)
-
- # Toggle visibility when the GPU freq manual toggle is on
- var on_manual_freq := func() -> void:
- # Immediately apply manual GPU frequency so we can read the min/max
- # values for the sliders
- var card := _get_integrated_card()
- if not card:
- logger.warn("No integrated GPU to set manual frequency on!")
- return
- card.manual_clock = gpu_freq_enable.button_pressed
-
- # Update the slider values with the current values
- gpu_freq_min_slider.visible = gpu_freq_enable.button_pressed
- gpu_freq_min_slider.min_value = card.clock_limit_mhz_min
- gpu_freq_min_slider.max_value = card.clock_limit_mhz_max
- gpu_freq_min_slider.value = card.clock_value_mhz_min
- gpu_freq_max_slider.visible = gpu_freq_enable.button_pressed
- gpu_freq_max_slider.min_value = card.clock_limit_mhz_min
- gpu_freq_max_slider.max_value = card.clock_limit_mhz_max
- gpu_freq_max_slider.value = card.clock_value_mhz_max
-
- gpu_freq_enable.pressed.connect(on_manual_freq)
-
- # Setup dropdowns
- power_profile_dropdown.clear()
- power_profile_dropdown.add_item("Max Performance", 0)
- power_profile_dropdown.add_item("Power Saving", 1)
- thermal_profile_dropdown.clear()
- thermal_profile_dropdown.add_item("Balanced", 0)
- thermal_profile_dropdown.add_item("Performance", 1)
- thermal_profile_dropdown.add_item("Silent", 2)
-
- # Set the initial values
- _on_profile_loaded(performance_manager.current_profile)
-
-
-# Triggers when the apply timer times out. The apply timer will start/restart
-# whenever the user makes a change to any item. When the timer runs out, it will
-# call this to apply the current profile.
-func _on_apply_timer_timeout() -> void:
- if not current_profile:
- logger.debug("No loaded profile to apply")
- return
- logger.debug("Applying and saving profile")
-
- # Update the profile based on the currently set values
- current_profile.cpu_boost_enabled = cpu_boost_button.button_pressed
- current_profile.cpu_smt_enabled = smt_button.button_pressed
- current_profile.cpu_core_count_current = int(cpu_cores_slider.value)
- current_profile.tdp_current = tdp_slider.value
- current_profile.tdp_boost_current = tdp_boost_slider.value
- current_profile.gpu_manual_enabled = gpu_freq_enable.button_pressed
- current_profile.gpu_freq_min_current = gpu_freq_min_slider.value
- current_profile.gpu_freq_max_current = gpu_freq_max_slider.value
- current_profile.gpu_temp_current = gpu_temp_slider.value
- current_profile.gpu_power_profile = power_profile_dropdown.selected
-
- performance_manager.apply_and_save_profile(current_profile)
-
-
-# Triggers every timeout to monitor the PowerStation DBus
-func _on_service_timer_timeout() -> void:
- var bus_running := power_station.supports_power_station()
- if bus_running == power_station_running:
- return
-
- # If the state of powerstation changes, update the interface accordingly
- power_station_running = bus_running
- _setup_interface()
-
-
-## Called when a performance profile is loaded
-func _on_profile_loaded(profile: PerformanceProfile) -> void:
- if not power_station.supports_power_station():
- logger.info("Unable to load performance profile. PowerStation not detected.")
- return
- var core_count := 1
- if hardware_manager.cpu:
- core_count = hardware_manager.cpu.core_count
-
- logger.debug("Updating UI with loaded performance profile")
- # Keep track of the currently loaded profile
- current_profile = profile
-
- # Update CPU UI components based on the loaded profile
- profile_loading = true
- cpu_boost_button.button_pressed = profile.cpu_boost_enabled
- smt_button.button_pressed = profile.cpu_smt_enabled
- if smt_button.button_pressed:
- cpu_cores_slider.max_value = core_count
- else:
- var cores := core_count / 2
- if cpu_cores_slider.value > cores:
- cpu_cores_slider.value = cores
- cpu_cores_slider.max_value = cores
- cpu_cores_slider.value = round(profile.cpu_core_count_current)
-
- # Update GPU UI components
- tdp_slider.value = round(profile.tdp_current)
- tdp_boost_slider.value = round(profile.tdp_boost_current)
- gpu_freq_enable.button_pressed = profile.gpu_manual_enabled
- gpu_freq_enable.pressed.emit()
- gpu_freq_min_slider.value = round(profile.gpu_freq_min_current)
- gpu_freq_max_slider.value = round(profile.gpu_freq_max_current)
- gpu_temp_slider.value = round(profile.gpu_temp_current)
-
- power_profile_dropdown.select(profile.gpu_power_profile)
- thermal_profile_dropdown.select(profile.thermal_profile)
-
- profile_loading = false
-
-
-# Configure the min/max values and visibility based on detected performance
-# features.
-func _setup_interface() -> void:
- # If powerstation is not running, disable everything
- if not power_station.supports_power_station():
- wait_label.visible = true
- for node in get_children():
- if node == wait_label:
- continue
- if node == Control:
- (node as Control).visible = false
- return
-
- # Configure visibility for all components
- wait_label.visible = false
-
- # Configure CPU components
- if power_station.cpu:
- var cpu := power_station.cpu
- cpu_label.visible = true
- cpu_boost_button.visible = cpu.has_feature("cpb")
- smt_button.visible = cpu.has_feature("ht")
- if cpu.smt_enabled:
- cpu_cores_slider.max_value = cpu.cores_count
- else:
- cpu_cores_slider.max_value = cpu.cores_count / 2
- cpu_cores_slider.visible = true
-
- # Configure GPU components
- if power_station.gpu:
- var card := _get_integrated_card()
-
- # Configure based on integrated graphics card
- if card:
- gpu_label.visible = true
- tdp_slider.visible = true
- tdp_slider.min_value = hardware_manager.gpu.tdp_min
- tdp_slider.max_value = hardware_manager.gpu.tdp_max
- tdp_boost_slider.visible = true
- tdp_boost_slider.max_value = hardware_manager.gpu.max_boost
- gpu_freq_enable.visible = true
- power_profile_dropdown.visible = true
- if card.clock_limit_mhz_min > 0 and card.clock_limit_mhz_max > 0:
- gpu_freq_min_slider.visible = card.manual_clock
- gpu_freq_min_slider.min_value = card.clock_limit_mhz_min
- gpu_freq_min_slider.max_value = card.clock_limit_mhz_max
- gpu_freq_max_slider.visible = card.manual_clock
- gpu_freq_max_slider.min_value = card.clock_limit_mhz_min
- gpu_freq_max_slider.max_value = card.clock_limit_mhz_max
- if card.thermal_throttle_limit_c > 0:
- gpu_temp_slider.visible = true
-
-
-## Returns the primary integrated GPU instance
-func _get_integrated_card() -> PowerStation.GPUCard:
- var card: PowerStation.GPUCard
- var cards := power_station.gpu.get_cards()
- for c in cards:
- if c.class_type != "integrated":
- continue
- card = c
- return card
diff --git a/core/ui/common/quick_bar/powertools_menu.tscn b/core/ui/common/quick_bar/powertools_menu.tscn
deleted file mode 100644
index ee0cd9d52..000000000
--- a/core/ui/common/quick_bar/powertools_menu.tscn
+++ /dev/null
@@ -1,166 +0,0 @@
-[gd_scene load_steps=9 format=3 uid="uid://dv3dt0j3jketh"]
-
-[ext_resource type="Script" path="res://core/ui/common/quick_bar/powertools_menu.gd" id="1_qncpn"]
-[ext_resource type="PackedScene" uid="uid://8m20p2s0v5gb" path="res://core/systems/input/focus_group.tscn" id="2_h0jgv"]
-[ext_resource type="Resource" uid="uid://dpc1o781f43ef" path="res://core/ui/card_ui/quick_bar/quick_bar_menu_focus.tres" id="3_0iyf7"]
-[ext_resource type="PackedScene" uid="uid://dithv38oqgy58" path="res://core/ui/components/section_label.tscn" id="4_1pfjc"]
-[ext_resource type="PackedScene" uid="uid://d1qb7euwlu7bh" path="res://core/ui/components/toggle.tscn" id="5_xig3u"]
-[ext_resource type="PackedScene" uid="uid://d0u3rsa5qpj57" path="res://core/ui/components/subsection_label.tscn" id="5_yr563"]
-[ext_resource type="PackedScene" uid="uid://cemxrvvjgm4g" path="res://core/ui/components/slider.tscn" id="6_7aip6"]
-[ext_resource type="PackedScene" uid="uid://xei5afwefxud" path="res://core/ui/components/dropdown.tscn" id="7_0kvsa"]
-
-[node name="PowerTools" type="VBoxContainer"]
-anchors_preset = 10
-anchor_right = 1.0
-offset_bottom = 28.0
-grow_horizontal = 2
-script = ExtResource("1_qncpn")
-
-[node name="FocusGroup" parent="." instance=ExtResource("2_h0jgv")]
-focus_stack = ExtResource("3_0iyf7")
-
-[node name="ApplyTimer" type="Timer" parent="."]
-wait_time = 1.5
-one_shot = true
-
-[node name="ServiceTimer" type="Timer" parent="."]
-wait_time = 5.0
-autostart = true
-
-[node name="WaitLabel" parent="." instance=ExtResource("5_yr563")]
-custom_minimum_size = Vector2(100, 0)
-layout_mode = 2
-text = "Waiting for PowerStation service..."
-horizontal_alignment = 1
-vertical_alignment = 1
-autowrap_mode = 3
-
-[node name="CPUSectionLabel" parent="." instance=ExtResource("4_1pfjc")]
-visible = false
-layout_mode = 2
-text = "CPU Settings"
-
-[node name="CPUBoostButton" parent="." instance=ExtResource("5_xig3u")]
-visible = false
-layout_mode = 2
-focus_neighbor_left = NodePath("../GPUTempSlider")
-focus_neighbor_top = NodePath("../GPUTempSlider")
-focus_neighbor_right = NodePath("../SMTButton")
-focus_neighbor_bottom = NodePath("../SMTButton")
-focus_next = NodePath("../SMTButton")
-focus_previous = NodePath("../GPUTempSlider")
-text = "CPU Boost"
-separator_visible = false
-
-[node name="SMTButton" parent="." instance=ExtResource("5_xig3u")]
-visible = false
-layout_mode = 2
-focus_neighbor_left = NodePath("../CPUBoostButton")
-focus_neighbor_top = NodePath("../CPUBoostButton")
-focus_neighbor_right = NodePath("../CPUCoresSlider")
-focus_neighbor_bottom = NodePath("../CPUCoresSlider")
-focus_next = NodePath("../CPUCoresSlider")
-focus_previous = NodePath("../CPUBoostButton")
-text = "SMT Enabled"
-separator_visible = false
-
-[node name="CPUCoresSlider" parent="." instance=ExtResource("6_7aip6")]
-visible = false
-layout_mode = 2
-focus_neighbor_left = NodePath("../SMTButton")
-focus_neighbor_top = NodePath("../SMTButton")
-focus_neighbor_right = NodePath("../TDPSlider")
-focus_neighbor_bottom = NodePath("../TDPSlider")
-focus_next = NodePath("../TDPSlider")
-focus_previous = NodePath("../SMTButton")
-text = "CPU Cores"
-value = 1.0
-max_value = 1.0
-min_value = 1.0
-
-[node name="GPUSectionLabel" parent="." instance=ExtResource("4_1pfjc")]
-visible = false
-layout_mode = 2
-text = "GPU Settings"
-
-[node name="TDPSlider" parent="." instance=ExtResource("6_7aip6")]
-visible = false
-layout_mode = 2
-focus_neighbor_left = NodePath("../CPUCoresSlider")
-focus_neighbor_top = NodePath("../CPUCoresSlider")
-focus_neighbor_right = NodePath("../TDPBoostSlider")
-focus_neighbor_bottom = NodePath("../TDPBoostSlider")
-focus_next = NodePath("../TDPBoostSlider")
-focus_previous = NodePath("../CPUCoresSlider")
-text = "TDP"
-max_value = 0.0
-
-[node name="TDPBoostSlider" parent="." instance=ExtResource("6_7aip6")]
-visible = false
-layout_mode = 2
-focus_neighbor_left = NodePath("../TDPSlider")
-focus_neighbor_top = NodePath("../TDPSlider")
-focus_previous = NodePath("../TDPSlider")
-text = "TDP Boost"
-max_value = 0.0
-
-[node name="GPUFreqButton" parent="." instance=ExtResource("5_xig3u")]
-visible = false
-layout_mode = 2
-focus_neighbor_left = NodePath("../TDPBoostSlider")
-focus_neighbor_top = NodePath("../TDPBoostSlider")
-focus_neighbor_right = NodePath("../GPUFreqMinSlider")
-focus_neighbor_bottom = NodePath("../GPUFreqMinSlider")
-focus_next = NodePath("../GPUFreqMinSlider")
-focus_previous = NodePath("../TDPBoostSlider")
-text = "Manual Freq"
-separator_visible = false
-
-[node name="GPUFreqMinSlider" parent="." instance=ExtResource("6_7aip6")]
-visible = false
-layout_mode = 2
-focus_neighbor_right = NodePath("../GPUFreqMaxSlider")
-focus_neighbor_bottom = NodePath("../GPUFreqMaxSlider")
-focus_next = NodePath("../GPUFreqMaxSlider")
-text = "Min Freq"
-max_value = 0.0
-step = 100.0
-
-[node name="GPUFreqMaxSlider" parent="." instance=ExtResource("6_7aip6")]
-visible = false
-layout_mode = 2
-focus_neighbor_left = NodePath("../GPUFreqMinSlider")
-focus_neighbor_top = NodePath("../GPUFreqMinSlider")
-focus_neighbor_right = NodePath("../GPUTempSlider")
-focus_neighbor_bottom = NodePath("../GPUTempSlider")
-focus_next = NodePath("../GPUTempSlider")
-focus_previous = NodePath("../GPUFreqMinSlider")
-text = "Max Freq"
-max_value = 0.0
-step = 100.0
-
-[node name="GPUTempSlider" parent="." instance=ExtResource("6_7aip6")]
-visible = false
-layout_mode = 2
-focus_neighbor_left = NodePath("../GPUFreqMaxSlider")
-focus_neighbor_top = NodePath("../GPUFreqMaxSlider")
-focus_neighbor_right = NodePath("../CPUBoostButton")
-focus_neighbor_bottom = NodePath("../CPUBoostButton")
-focus_next = NodePath("../CPUBoostButton")
-focus_previous = NodePath("../GPUFreqMaxSlider")
-text = "GPU Temp Limit"
-value = 70.0
-max_value = 105.0
-min_value = 70.0
-
-[node name="PowerProfileDropdown" parent="." instance=ExtResource("7_0kvsa")]
-visible = false
-layout_mode = 2
-title = "Power Profile"
-description = ""
-
-[node name="ThermalProfileDropdown" parent="." instance=ExtResource("7_0kvsa")]
-visible = false
-layout_mode = 2
-title = "Thermal Throttle Profile"
-description = ""
diff --git a/core/ui/common/quick_bar/quick_settings_menu.gd b/core/ui/common/quick_bar/quick_settings_menu.gd
index 277207f0a..423d5453d 100644
--- a/core/ui/common/quick_bar/quick_settings_menu.gd
+++ b/core/ui/common/quick_bar/quick_settings_menu.gd
@@ -1,9 +1,9 @@
extends Control
-var Gamescope := preload("res://core/global/gamescope.tres") as Gamescope
var AudioManager := preload("res://core/global/audio_manager.tres") as AudioManager
var DisplayManager := preload("res://core/global/display_manager.tres") as DisplayManager
+var gamescope := load("res://core/systems/gamescope/gamescope.tres") as GamescopeInstance
var backlights := DisplayManager.get_backlight_paths()
var logger := Log.get_logger("QuickSettings", Log.LEVEL.INFO)
@@ -48,7 +48,10 @@ func _on_brightness_slider_changed(value: float) -> void:
DisplayManager.set_brightness(percent)
+# TODO: Deprecate
func _on_saturation_changed(value: float) -> void:
- var code := Gamescope.set_saturation(value / 100.0)
- if code != OK:
- logger.warn("Unable to set saturation. Code: " + str(code))
+ pass
+ #var xwayland := gamescope.get_xwayland(gamescope.XWAYLAND_TYPE_PRIMARY)
+ #var code := xwayland.set_saturation(value / 100.0)
+ #if code != OK:
+ # logger.warn("Unable to set saturation. Code: " + str(code))
diff --git a/core/ui/common/settings/display_settings_menu.gd b/core/ui/common/settings/display_settings_menu.gd
index 09f45a3b0..f7561947a 100644
--- a/core/ui/common/settings/display_settings_menu.gd
+++ b/core/ui/common/settings/display_settings_menu.gd
@@ -12,7 +12,7 @@ func _ready() -> void:
get_window().content_scale_factor = display_scale
scale_slider.value_changed.connect(_on_scale_changed)
- var blur_enabled := settings_manager.get_value("display", "enable_overlay_blur", true) as bool
+ var blur_enabled := settings_manager.get_value("display", "enable_overlay_blur", false) as bool
blur_toggle.button_pressed = blur_enabled
blur_toggle.toggled.connect(_on_blur_toggled)
diff --git a/core/ui/common/settings/network_settings_menu.gd b/core/ui/common/settings/network_settings_menu.gd
index 5ce877f3f..1788bd40d 100644
--- a/core/ui/common/settings/network_settings_menu.gd
+++ b/core/ui/common/settings/network_settings_menu.gd
@@ -1,31 +1,51 @@
extends Control
-const thread := preload("res://core/systems/threading/thread_pool.tres")
-const bar_0 := preload("res://assets/ui/icons/wifi-none.svg")
-const bar_1 := preload("res://assets/ui/icons/wifi-low.svg")
-const bar_2 := preload("res://assets/ui/icons/wifi-medium.svg")
-const bar_3 := preload("res://assets/ui/icons/wifi-high.svg")
+var network_manager := load("res://core/systems/network/network_manager.tres") as NetworkManagerInstance
var connecting := false
@onready var no_net_label := $%NoNetworkLabel
-@onready var wifi_tree := $%WifiNetworkTree as Tree
-@onready var refresh_button := $%RefreshButton as Button
+@onready var wifi_tree := $%WifiNetworkTree as WifiNetworkTree
+@onready var wireless_toggle := $%WirelessEnableToggle as Toggle
+@onready var wifi_label := $%WifiLabel
@onready var password_button := $%WifiPasswordButton
@onready var password_input := $%WifiPasswordTextInput
@onready var password_popup := $%PopupContainer
+@onready var ip_text := $%IPAddressText as SelectableText
+@onready var mask_text := $%SubnetText as SelectableText
+@onready var gateway_text := $%GatewayText as SelectableText
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
- if not NetworkManager.supports_network():
- no_net_label.visible = true
- return
-
- thread.start()
+ # Display label if no networking is available
+ var on_networking_available := func():
+ no_net_label.visible = not network_manager.is_running()
+ network_manager.started.connect(on_networking_available)
+ network_manager.stopped.connect(on_networking_available)
+ on_networking_available.call()
+
+ # Connect the wireless enable toggle
+ var wireless_enabled := network_manager.wireless_enabled
+ wireless_toggle.button_pressed = wireless_enabled
+ wifi_label.visible = wireless_enabled
+ wifi_tree.visible = wireless_enabled
+ var on_wireless_toggled := func(enabled: bool):
+ network_manager.wireless_enabled = enabled
+ wifi_label.visible = enabled
+ wifi_tree.visible = enabled
+ if enabled:
+ await get_tree().create_timer(4.0).timeout
+ wifi_tree.refresh_networks()
+ wireless_toggle.toggled.connect(on_wireless_toggled)
+
+ # Fill out the connection details
+ var connection := network_manager.primary_connection
+ _on_connection_changed(connection)
+ network_manager.primary_connection_changed.connect(_on_connection_changed)
+
+ # Connect visibility and challenge signals
visibility_changed.connect(_on_visible_changed)
- refresh_button.pressed.connect(_refresh_networks)
- wifi_tree.item_activated.connect(_on_wifi_selected)
- wifi_tree.create_item()
+ wifi_tree.challenge_required.connect(_on_wifi_challenge)
# Configure the OSK with the password input box
var password_context := password_input.keyboard_context as KeyboardContext
@@ -35,118 +55,61 @@ func _ready() -> void:
password_context.close_on_submit = true
-func _on_visible_changed() -> void:
- _refresh_networks()
- password_popup.visible = false
-
-
-func _on_wifi_selected() -> void:
- if connecting:
+func _on_connection_changed(connection: NetworkActiveConnection) -> void:
+ await get_tree().create_timer(3.0).timeout
+ if not connection:
+ ip_text.text = "0.0.0.0"
+ mask_text.text = "0"
+ gateway_text.text = "0.0.0.0"
+ return
+ var devices := connection.devices
+ if devices.is_empty():
+ ip_text.text = "0.0.0.0"
+ mask_text.text = "0"
+ gateway_text.text = "0.0.0.0"
return
- connecting = true
- refresh_button.disabled = true
-
- var item := wifi_tree.get_selected()
- var ssid := item.get_text(1)
- var connect_ap := func() -> int:
- return NetworkManager.connect_access_point(ssid)
- item.set_text(4, "Connecting")
- var code := await thread.exec(connect_ap) as int
-
- connecting = false
- refresh_button.disabled = false
- if code == OK:
- _refresh_networks()
+ var device := devices[0]
+ var ip := device.ip4_config
+ if not ip:
+ ip_text.text = "0.0.0.0"
+ mask_text.text = "0"
+ gateway_text.text = "0.0.0.0"
return
+ var gateway := ip.gateway
+ if not gateway.is_empty():
+ gateway_text.text = gateway
+ var addresses := ip.addresses
+ if addresses.is_empty():
+ ip_text.text = "0.0.0.0"
+ mask_text.text = "0"
+ gateway_text.text = "0.0.0.0"
+ return
+ var info := addresses[0]
+ if "prefix" in info:
+ mask_text.text = str(info["prefix"])
+ if "address" in info:
+ ip_text.text = info["address"]
- # If we fail to connect, open the wifi challenge
- _on_wifi_challenge(item, ssid)
+
+func _on_visible_changed() -> void:
+ _on_connection_changed(network_manager.primary_connection)
+ wifi_tree.refresh_networks()
+ password_popup.visible = false
-func _on_wifi_challenge(item: TreeItem, ssid: String) -> void:
+func _on_wifi_challenge(callback: Callable) -> void:
password_popup.visible = true
password_input.grab_focus.call_deferred()
var on_pass_submit := func():
connecting = true
- refresh_button.disabled = true
password_popup.visible = false
- refresh_button.grab_focus.call_deferred()
+ wifi_tree.grab_focus.call_deferred()
var password := password_input.text as String
-
- var connect_ap := func() -> int:
- return NetworkManager.connect_access_point(ssid, password)
- item.set_text(4, "Connecting")
- var code := await thread.exec(connect_ap) as int
-
- connecting = false
- refresh_button.disabled = false
- if code == OK:
- _refresh_networks()
- return
-
- item.set_text(4, "Failed to connect")
-
+ callback.call(password)
password_button.pressed.connect(on_pass_submit, CONNECT_ONE_SHOT)
-func _refresh_networks() -> void:
- # Disable the refresh button while refreshing
- refresh_button.disabled = true
-
- # Fetch all the available access points from NetworkManager
- var tree := wifi_tree as Tree
- var root := tree.get_root()
- var access_points: Array[NetworkManager.WifiAP]
- var get_aps := func() -> Array[NetworkManager.WifiAP]:
- return NetworkManager.get_access_points()
- access_points = await thread.exec(get_aps)
-
- # Create an array of BSSIDs from our access points
- var bssids := []
- for ap in access_points:
- bssids.append(ap.bssid)
-
- # Look at the current tree items to see if any need to be removed
- var tree_bssids := {}
- for item in root.get_children():
- var bssid := item.get_metadata(0) as String
- if bssid in bssids:
- tree_bssids[bssid] = item
- continue
- root.remove_child(item)
-
- # Look at the current APs to see if any tree items need to be created
- # or updated
- for ap in access_points:
- var item: TreeItem
- if ap.bssid in tree_bssids:
- item = tree_bssids[ap.bssid]
- else:
- item = tree.create_item(root)
- item.set_metadata(0, ap.bssid)
- item.set_icon(0, NetworkManager.get_strength_texture(ap.strength))
- item.set_text(1, ap.ssid)
- item.set_text(2, ap.security)
- item.set_text(3, ap.rate)
- if ap.in_use:
- item.set_text(4, "Connected")
- else:
- item.set_text(4, "")
-
- refresh_button.disabled = false
-
-
-func _get_strength_texture(strength: int) -> Texture2D:
- if strength >= 80:
- return bar_3
- if strength >= 60:
- return bar_2
- if strength >= 40:
- return bar_1
- return bar_0
-
-
# Intercept back input when the password dialog is open
func _input(event: InputEvent) -> void:
if not visible:
diff --git a/core/ui/common/settings/network_settings_menu.tscn b/core/ui/common/settings/network_settings_menu.tscn
index 8ea0ed6de..b37bfbe58 100644
--- a/core/ui/common/settings/network_settings_menu.tscn
+++ b/core/ui/common/settings/network_settings_menu.tscn
@@ -1,4 +1,4 @@
-[gd_scene load_steps=15 format=3 uid="uid://cpss2bhdwm8t7"]
+[gd_scene load_steps=17 format=3 uid="uid://cpss2bhdwm8t7"]
[ext_resource type="Script" path="res://core/ui/common/settings/network_settings_menu.gd" id="1_2qdps"]
[ext_resource type="PackedScene" uid="uid://8m20p2s0v5gb" path="res://core/systems/input/focus_group.tscn" id="2_8jmkq"]
@@ -8,12 +8,14 @@
[ext_resource type="PackedScene" uid="uid://d0u3rsa5qpj57" path="res://core/ui/components/subsection_label.tscn" id="4_t7br0"]
[ext_resource type="Resource" uid="uid://iqrotrmq62i6" path="res://assets/state/state_machines/settings_state_machine.tres" id="4_tf04q"]
[ext_resource type="PackedScene" uid="uid://shvyhrv5sx3v" path="res://core/systems/state/state_watcher.tscn" id="5_jobhc"]
-[ext_resource type="PackedScene" uid="uid://df5o1o2dsik84" path="res://core/ui/components/button.tscn" id="5_round"]
-[ext_resource type="Theme" uid="uid://bko0q7gp1hwjp" path="res://assets/themes/dracula.tres" id="6_i7u1a"]
[ext_resource type="Resource" uid="uid://2efht48q7i6v" path="res://assets/state/states/settings_network.tres" id="6_ke40f"]
[ext_resource type="Script" path="res://core/systems/input/focus_group_setter.gd" id="7_gnxgo"]
[ext_resource type="PackedScene" uid="uid://d1rjdfxxrdccf" path="res://core/ui/components/text_input.tscn" id="7_qx5i7"]
[ext_resource type="PackedScene" uid="uid://b0cyl6fdqxevn" path="res://core/systems/input/scroller_joystick.tscn" id="9_v6vet"]
+[ext_resource type="PackedScene" uid="uid://d1qb7euwlu7bh" path="res://core/ui/components/toggle.tscn" id="11_y8h23"]
+[ext_resource type="Script" path="res://core/ui/components/wifi_network_tree.gd" id="12_flshi"]
+[ext_resource type="PackedScene" uid="uid://c71ayw7pcw6u6" path="res://core/ui/components/card_button.tscn" id="13_p7bew"]
+[ext_resource type="PackedScene" uid="uid://cmjjyqx1pl23d" path="res://core/ui/components/text.tscn" id="13_wnqd6"]
[node name="NetworkSettings" type="ScrollContainer"]
anchors_preset = 15
@@ -54,39 +56,39 @@ layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
-[node name="FocusGroup" parent="MarginContainer/VBoxContainer" node_paths=PackedStringArray("current_focus") instance=ExtResource("2_8jmkq")]
-current_focus = NodePath("../RefreshButton")
+[node name="FocusGroup" parent="MarginContainer/VBoxContainer" instance=ExtResource("2_8jmkq")]
[node name="NoNetworkLabel" parent="MarginContainer/VBoxContainer" instance=ExtResource("4_t7br0")]
unique_name_in_owner = true
visible = false
layout_mode = 2
-text = "Network dependencies not found"
+text = "Networking not available"
horizontal_alignment = 1
-[node name="DisplayLabel" parent="MarginContainer/VBoxContainer" instance=ExtResource("3_ddyy1")]
+[node name="WirelessDisplayLabel" parent="MarginContainer/VBoxContainer" instance=ExtResource("3_ddyy1")]
layout_mode = 2
text = "Wireless Network"
[node name="HSeparator" type="HSeparator" parent="MarginContainer/VBoxContainer"]
layout_mode = 2
-[node name="WifiLabel" parent="MarginContainer/VBoxContainer" instance=ExtResource("4_t7br0")]
+[node name="WirelessEnableToggle" parent="MarginContainer/VBoxContainer" instance=ExtResource("11_y8h23")]
+unique_name_in_owner = true
layout_mode = 2
-text = "Visible Networks"
+text = "Enable Wireless"
+separator_visible = false
+button_pressed = true
-[node name="RefreshButton" parent="MarginContainer/VBoxContainer" instance=ExtResource("5_round")]
+[node name="WifiLabel" parent="MarginContainer/VBoxContainer" instance=ExtResource("4_t7br0")]
unique_name_in_owner = true
layout_mode = 2
-text = "Refresh Networks"
+text = "Visible Networks"
[node name="WifiNetworkTree" type="Tree" parent="MarginContainer/VBoxContainer"]
unique_name_in_owner = true
custom_minimum_size = Vector2(0, 300)
layout_mode = 2
-columns = 5
-hide_root = true
-select_mode = 1
+script = ExtResource("12_flshi")
[node name="Spacer" type="Control" parent="MarginContainer/VBoxContainer"]
custom_minimum_size = Vector2(0, 20)
@@ -101,15 +103,42 @@ text = "Wired Network"
visible = false
layout_mode = 2
+[node name="DetailsDisplayLabel" parent="MarginContainer/VBoxContainer" instance=ExtResource("3_ddyy1")]
+layout_mode = 2
+text = "Connection Details"
+
+[node name="HSeparator3" type="HSeparator" parent="MarginContainer/VBoxContainer"]
+layout_mode = 2
+
+[node name="IPAddressText" parent="MarginContainer/VBoxContainer" instance=ExtResource("13_wnqd6")]
+unique_name_in_owner = true
+layout_mode = 2
+title = "IP Address"
+description = ""
+text = "0.0.0.0"
+
+[node name="SubnetText" parent="MarginContainer/VBoxContainer" instance=ExtResource("13_wnqd6")]
+unique_name_in_owner = true
+layout_mode = 2
+title = "Subnet Prefix"
+description = ""
+text = "0"
+
+[node name="GatewayText" parent="MarginContainer/VBoxContainer" instance=ExtResource("13_wnqd6")]
+unique_name_in_owner = true
+layout_mode = 2
+title = "Gateway"
+description = ""
+text = "0.0.0.0"
+
[node name="PopupContainer" type="CenterContainer" parent="MarginContainer"]
unique_name_in_owner = true
visible = false
layout_mode = 2
[node name="PanelContainer" type="PanelContainer" parent="MarginContainer/PopupContainer"]
-custom_minimum_size = Vector2(300, 200)
+custom_minimum_size = Vector2(300, 0)
layout_mode = 2
-theme = ExtResource("6_i7u1a")
[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/PopupContainer/PanelContainer"]
layout_mode = 2
@@ -120,6 +149,7 @@ theme_override_constants/margin_bottom = 20
[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/PopupContainer/PanelContainer/MarginContainer"]
layout_mode = 2
+theme_override_constants/separation = 10
[node name="WifiPasswordTextInput" parent="MarginContainer/PopupContainer/PanelContainer/MarginContainer/VBoxContainer" instance=ExtResource("7_qx5i7")]
unique_name_in_owner = true
@@ -129,7 +159,7 @@ title = "Password"
description = "Enter the password for this network"
secret = true
-[node name="WifiPasswordButton" parent="MarginContainer/PopupContainer/PanelContainer/MarginContainer/VBoxContainer" instance=ExtResource("5_round")]
+[node name="WifiPasswordButton" parent="MarginContainer/PopupContainer/PanelContainer/MarginContainer/VBoxContainer" instance=ExtResource("13_p7bew")]
unique_name_in_owner = true
layout_mode = 2
text = "Submit"
diff --git a/core/ui/components/battery_container.gd b/core/ui/components/battery_container.gd
index 463bb8d06..b9d3063a1 100644
--- a/core/ui/components/battery_container.gd
+++ b/core/ui/components/battery_container.gd
@@ -7,8 +7,10 @@ const icon_half = preload("res://assets/ui/icons/battery-half.svg")
const icon_low = preload("res://assets/ui/icons/battery-low.svg")
const icon_empty = preload("res://assets/ui/icons/battery-empty.svg")
-var power_manager := load("res://core/systems/power/power_manager.tres") as PowerManager
-var batteries : Array[PowerManager.Device]
+const no_battery_names := ["battery-missing-symbolic"]
+
+var power_manager := load("res://core/systems/power/power_manager.tres") as UPowerInstance
+var display_device := power_manager.get_display_device()
var logger := Log.get_logger("BatteryContainer", Log.LEVEL.INFO)
@@ -17,20 +19,21 @@ var logger := Log.get_logger("BatteryContainer", Log.LEVEL.INFO)
func _ready():
- batteries = power_manager.get_devices_by_type(PowerManager.DEVICE_TYPE.BATTERY)
- if batteries.size() > 1:
- logger.warn("You somehow have more than one battery. We don't know what to do with that.")
- if batteries.size() == 0:
+ if not display_device:
+ logger.debug("No battery detected. nothing to do.")
+ visible = false
+ return
+
+ if display_device.icon_name in no_battery_names:
logger.debug("No battery detected. nothing to do.")
visible = false
return
- var battery := batteries[0]
- _on_update_device(battery)
- battery.updated.connect(_on_update_device.bind(battery))
+ _on_update_device(display_device)
+ display_device.updated.connect(_on_update_device.bind(display_device))
-func _on_update_device(item: PowerManager.Device):
+func _on_update_device(item: UPowerDevice):
var capacity := item.percentage
var state := item.state
battery_icon.texture = get_capacity_texture(capacity, state)
@@ -42,8 +45,8 @@ func _on_update_device(item: PowerManager.Device):
## Returns the texture reflecting the given battery capacity
-static func get_capacity_texture(capacity: int, state: PowerManager.DEVICE_STATE) -> Texture2D:
- if state in [PowerManager.DEVICE_STATE.CHARGING, PowerManager.DEVICE_STATE.FULLY_CHARGED]:
+static func get_capacity_texture(capacity: int, state: int) -> Texture2D:
+ if state in [UPowerDevice.STATE_CHARGING, UPowerDevice.STATE_FULLY_CHARGED]:
return icon_charging
if capacity >= 90:
return icon_full
diff --git a/core/ui/components/card.gd b/core/ui/components/card.gd
index dd5f27ebd..e2243c003 100644
--- a/core/ui/components/card.gd
+++ b/core/ui/components/card.gd
@@ -35,12 +35,16 @@ signal unhighlighted
progress.value = v
var library_item: LibraryItem
+var tapped_count := 0
var logger := Log.get_logger("GameCard")
@onready var texture := $%TextureRect
@onready var name_container := $%NameMargin
@onready var name_label := $%NameLabel
@onready var progress := $%ProgressBar as ProgressBar
+@onready var tap_timer := $%TapTimer as Timer
+@onready var shine_rect := $%ShineShader as ColorRect
+@onready var god_rays_rect := $%GodRaysShader as ColorRect
# Called when the node enters the scene tree for the first time.
@@ -53,7 +57,12 @@ func _ready() -> void:
focus_exited.connect(_on_unfocus)
texture.mouse_entered.connect(_on_focus)
texture.mouse_exited.connect(_on_unfocus)
-
+
+ # Setup a timer callback to clear number of taps on the card
+ var on_timeout := func():
+ tapped_count = 0
+ tap_timer.timeout.connect(on_timeout)
+
var parent := get_parent()
if parent and parent is Container:
parent.queue_sort()
@@ -91,16 +100,76 @@ func set_library_item(item: LibraryItem, free_on_remove: bool = true) -> void:
func _on_focus() -> void:
highlighted.emit()
+ _shader_godrays_fade_in()
+ _shader_shine_fade_in()
+
+
+func _shader_godrays_fade_in() -> void:
+ var tween := create_tween()
+ var shader := god_rays_rect.material as ShaderMaterial
+ var final_color := Color(0.961, 0.937, 1.0, 0.2)
+ var start_color := Color(0.961, 0.937, 1.0, 0.0)
+ shader.set_shader_parameter("color", start_color)
+ god_rays_rect.visible = true
+ var on_tween := func(value: Color):
+ shader.set_shader_parameter("color", value)
+ tween.tween_method(on_tween, start_color, final_color, 0.5)
+
+
+func _shader_shine_fade_in() -> void:
+ var tween := create_tween()
+ var shader := shine_rect.material as ShaderMaterial
+ var final_alpha := 0.02
+ var start_alpha := 0.0
+ shader.set_shader_parameter("Alpha", start_alpha)
+ shine_rect.visible = true
+ var on_tween := func(value: float):
+ shader.set_shader_parameter("Alpha", value)
+ tween.tween_method(on_tween, start_alpha, final_alpha, 0.8)
func _on_unfocus() -> void:
unhighlighted.emit()
+ _shader_godrays_fade_out()
+ _shader_shine_fade_out()
+
+
+func _shader_godrays_fade_out() -> void:
+ var tween := create_tween()
+ var shader := god_rays_rect.material as ShaderMaterial
+ var start_color := Color(0.961, 0.937, 1.0, 0.2)
+ var final_color := Color(0.961, 0.937, 1.0, 0.0)
+ shader.set_shader_parameter("color", start_color)
+ var on_tween := func(value: Color):
+ shader.set_shader_parameter("color", value)
+ tween.tween_method(on_tween, start_color, final_color, 0.5)
+ tween.tween_property(god_rays_rect, "visible", false, 0.0)
+
+
+func _shader_shine_fade_out() -> void:
+ var tween := create_tween()
+ var shader := shine_rect.material as ShaderMaterial
+ var start_alpha := 0.02
+ var final_alpha := 0.0
+ shader.set_shader_parameter("Alpha", start_alpha)
+ var on_tween := func(value: float):
+ shader.set_shader_parameter("Alpha", value)
+ tween.tween_method(on_tween, start_alpha, final_alpha, 0.1)
+ tween.tween_property(shine_rect, "visible", false, 0.0)
func _gui_input(event: InputEvent) -> void:
if event is InputEventMouseButton:
if event.is_pressed() and event.double_click:
button_up.emit()
+ if event is InputEventScreenTouch:
+ if event.is_pressed():
+ tapped_count += 1
+ if tapped_count > 1:
+ tapped_count = 0
+ button_up.emit()
+ else:
+ tap_timer.start()
if event.is_action("ui_accept"):
if event.is_pressed():
button_down.emit()
diff --git a/core/ui/components/card.tscn b/core/ui/components/card.tscn
index 1117e1468..eac5f657b 100644
--- a/core/ui/components/card.tscn
+++ b/core/ui/components/card.tscn
@@ -1,9 +1,11 @@
-[gd_scene load_steps=9 format=3 uid="uid://bkhrcemal7uxo"]
+[gd_scene load_steps=13 format=3 uid="uid://bkhrcemal7uxo"]
[ext_resource type="Script" path="res://core/ui/components/card.gd" id="1_aiin0"]
[ext_resource type="Texture2D" uid="uid://blc0qyvt1qhci" path="res://assets/images/placeholder-grid-portrait.png" id="2_2hlyj"]
[ext_resource type="PackedScene" uid="uid://c5sfkhrfbao71" path="res://core/systems/effects/play_audio_effect.tscn" id="2_701dj"]
[ext_resource type="PackedScene" uid="uid://bui0u88oe8jr" path="res://core/systems/effects/raise_effect.tscn" id="3_gyi80"]
+[ext_resource type="Shader" path="res://assets/shaders/highlight_shine.gdshader" id="5_0n631"]
+[ext_resource type="Shader" path="res://assets/shaders/god_rays.gdshader" id="7_8n7dp"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ygsnb"]
corner_radius_top_left = 26
@@ -21,6 +23,37 @@ corner_radius_top_right = 5
corner_radius_bottom_right = 5
corner_radius_bottom_left = 5
+[sub_resource type="ShaderMaterial" id="ShaderMaterial_1bdvx"]
+resource_local_to_scene = true
+shader = ExtResource("5_0n631")
+shader_parameter/Line_Smoothness = 0.045
+shader_parameter/Line_Width = 0.075
+shader_parameter/Brightness = 0.81
+shader_parameter/Rotation_deg = 35.0
+shader_parameter/Distortion = 1.67
+shader_parameter/Speed = 0.31
+shader_parameter/Position = 0.0
+shader_parameter/Position_Min = 0.25
+shader_parameter/Position_Max = 0.5
+shader_parameter/Alpha = 0.02
+
+[sub_resource type="ShaderMaterial" id="ShaderMaterial_1nde2"]
+resource_local_to_scene = true
+shader = ExtResource("7_8n7dp")
+shader_parameter/angle = 0.0
+shader_parameter/position = 0.0
+shader_parameter/spread = 1.0
+shader_parameter/cutoff = -1.0
+shader_parameter/falloff = 1.0
+shader_parameter/edge_fade = 0.904
+shader_parameter/speed = 20.0
+shader_parameter/ray1_density = 8.0
+shader_parameter/ray2_density = 30.0
+shader_parameter/ray2_intensity = 0.3
+shader_parameter/color = Color(0.960784, 0.937255, 1, 0.117647)
+shader_parameter/hdr = false
+shader_parameter/seed = 5.96
+
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_st1t5"]
resource_local_to_scene = true
bg_color = Color(0, 0, 0, 0)
@@ -63,8 +96,9 @@ on_signal = "highlighted"
[node name="PanelContainer" type="PanelContainer" parent="."]
clip_children = 1
layout_mode = 0
-offset_right = 40.0
-offset_bottom = 40.0
+offset_right = 200.0
+offset_bottom = 300.0
+mouse_filter = 1
theme_override_styles/panel = SubResource("StyleBoxFlat_ygsnb")
[node name="TextureRect" type="TextureRect" parent="PanelContainer"]
@@ -119,6 +153,20 @@ theme_override_styles/fill = SubResource("StyleBoxFlat_up8ek")
value = 50.0
rounded = true
+[node name="ShineShader" type="ColorRect" parent="PanelContainer"]
+unique_name_in_owner = true
+visible = false
+material = SubResource("ShaderMaterial_1bdvx")
+layout_mode = 2
+mouse_filter = 2
+
+[node name="GodRaysShader" type="ColorRect" parent="PanelContainer"]
+unique_name_in_owner = true
+visible = false
+material = SubResource("ShaderMaterial_1nde2")
+layout_mode = 2
+mouse_filter = 2
+
[node name="MarginContainer" type="MarginContainer" parent="."]
show_behind_parent = true
custom_minimum_size = Vector2(200, 300)
@@ -136,3 +184,8 @@ show_behind_parent = true
layout_mode = 2
mouse_filter = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_st1t5")
+
+[node name="TapTimer" type="Timer" parent="."]
+unique_name_in_owner = true
+wait_time = 0.5
+one_shot = true
diff --git a/core/ui/components/card_button_setting.gd b/core/ui/components/card_button_setting.gd
new file mode 100644
index 000000000..8b09e42e9
--- /dev/null
+++ b/core/ui/components/card_button_setting.gd
@@ -0,0 +1,89 @@
+@tool
+extends BoxContainer
+class_name CardButtonSetting
+
+signal pressed
+signal button_up
+signal player_button_up(metaname: String, dbus_path: String)
+signal button_down
+signal player_button_down(metaname: String, dbus_path: String)
+
+@export_category("Label Settings")
+@export var text: String = "Setting"
+@export var separator_visible: bool = false
+@export var show_label := true:
+ set(v):
+ show_label = v
+ if label:
+ label.visible = v
+ notify_property_list_changed()
+@export var description: String = "":
+ set(v):
+ description = v
+ if description_label:
+ description_label.text = v
+ description_label.visible = v != ""
+ notify_property_list_changed()
+
+@export_category("Button Settings")
+@export var button_text := "Button":
+ set(v):
+ button_text = v
+ if card_button:
+ card_button.text = v
+ notify_property_list_changed()
+
+@export var disabled := false:
+ set(v):
+ disabled = v
+ if card_button:
+ card_button.disabled = v
+ notify_property_list_changed()
+
+@onready var label := $%Label as Label
+@onready var description_label := $%DescriptionLabel as Label
+@onready var card_button := $%CardButton as CardButton
+@onready var hsep := $%HSeparator as HSeparator
+@onready var panel := $%PanelContainer as PanelContainer
+
+
+# Called when the node enters the scene tree for the first time.
+func _ready() -> void:
+ label.text = text
+ description_label.text = description
+ description_label.visible = description != ""
+ hsep.visible = separator_visible
+
+ if Engine.is_editor_hint():
+ return
+
+ # Update colors on focus
+ focus_entered.connect(_on_focus.bind(true))
+ focus_exited.connect(_on_focus.bind(false))
+ theme_changed.connect(_on_theme_changed)
+
+ # Connect button signals
+ card_button.text = button_text
+ card_button.pressed.connect(self.emit_signal.bind("pressed"))
+ card_button.button_up.connect(self.emit_signal.bind("button_up"))
+ card_button.button_down.connect(self.emit_signal.bind("button_down"))
+ var on_player_button := func(metaname: String, dbus_path: String, sig: String):
+ self.emit_signal(sig, metaname, dbus_path)
+ card_button.player_button_up.connect(on_player_button.bind("player_button_up"))
+ card_button.player_button_down.connect(on_player_button.bind("player_button_up"))
+
+ # Find the parent theme and update if required
+ var effective_theme := ThemeUtils.get_effective_theme(self)
+ if effective_theme:
+ _on_theme_changed()
+
+
+func _on_theme_changed() -> void:
+ # Get the style from the set theme so it can be set on the panel container
+ var normal_stylebox := get_theme_stylebox("panel", "SelectableText").duplicate()
+ panel.add_theme_stylebox_override("panel", normal_stylebox)
+
+
+func _on_focus(focused: bool) -> void:
+ if focused:
+ card_button.grab_focus()
diff --git a/core/ui/components/card_button_setting.tscn b/core/ui/components/card_button_setting.tscn
new file mode 100644
index 000000000..f1fa344f8
--- /dev/null
+++ b/core/ui/components/card_button_setting.tscn
@@ -0,0 +1,63 @@
+[gd_scene load_steps=5 format=3 uid="uid://bk5ld0h1jgd2t"]
+
+[ext_resource type="LabelSettings" uid="uid://bdx3xgfcaqhse" path="res://assets/label/title_label.tres" id="1_bah65"]
+[ext_resource type="Script" path="res://core/ui/components/card_button_setting.gd" id="1_vyqam"]
+[ext_resource type="LabelSettings" uid="uid://bv56n31s84bfn" path="res://assets/label/subheading_label.tres" id="2_m742p"]
+[ext_resource type="PackedScene" uid="uid://c71ayw7pcw6u6" path="res://core/ui/components/card_button.tscn" id="3_kep31"]
+
+[node name="CardButtonSetting" type="BoxContainer"]
+anchors_preset = 10
+anchor_right = 1.0
+offset_bottom = 47.0
+grow_horizontal = 2
+size_flags_horizontal = 3
+focus_mode = 2
+mouse_filter = 0
+vertical = true
+script = ExtResource("1_vyqam")
+button_text = null
+disabled = null
+
+[node name="VBoxContainer" type="VBoxContainer" parent="."]
+layout_mode = 2
+
+[node name="PanelContainer" type="PanelContainer" parent="VBoxContainer"]
+unique_name_in_owner = true
+layout_mode = 2
+
+[node name="MarginContainer" type="MarginContainer" parent="VBoxContainer/PanelContainer"]
+layout_mode = 2
+theme_override_constants/margin_left = 4
+theme_override_constants/margin_top = 4
+theme_override_constants/margin_right = 4
+theme_override_constants/margin_bottom = 4
+
+[node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer/PanelContainer/MarginContainer"]
+layout_mode = 2
+
+[node name="ToggleContainer" type="HBoxContainer" parent="VBoxContainer/PanelContainer/MarginContainer/VBoxContainer"]
+layout_mode = 2
+
+[node name="Label" type="Label" parent="VBoxContainer/PanelContainer/MarginContainer/VBoxContainer/ToggleContainer"]
+unique_name_in_owner = true
+layout_mode = 2
+size_flags_horizontal = 3
+text = "Setting"
+label_settings = ExtResource("1_bah65")
+
+[node name="CardButton" parent="VBoxContainer/PanelContainer/MarginContainer/VBoxContainer/ToggleContainer" instance=ExtResource("3_kep31")]
+unique_name_in_owner = true
+custom_minimum_size = Vector2(200, 0)
+layout_mode = 2
+
+[node name="DescriptionLabel" type="Label" parent="VBoxContainer/PanelContainer/MarginContainer/VBoxContainer"]
+unique_name_in_owner = true
+visible = false
+custom_minimum_size = Vector2(100, 0)
+layout_mode = 2
+label_settings = ExtResource("2_m742p")
+autowrap_mode = 3
+
+[node name="HSeparator" type="HSeparator" parent="VBoxContainer"]
+unique_name_in_owner = true
+layout_mode = 2
diff --git a/core/ui/components/dialog.gd b/core/ui/components/dialog.gd
index 55f499dfb..56bc4caf4 100644
--- a/core/ui/components/dialog.gd
+++ b/core/ui/components/dialog.gd
@@ -1,4 +1,4 @@
-@icon("res://assets/editor-icons/dialog-2-bold.svg")
+@icon("res://assets/editor-icons/solar--dialog-2-bold.svg")
@tool
extends Control
class_name Dialog
diff --git a/core/ui/components/drive_card.gd b/core/ui/components/drive_card.gd
index 12cce13f7..50a9792db 100644
--- a/core/ui/components/drive_card.gd
+++ b/core/ui/components/drive_card.gd
@@ -11,7 +11,7 @@ const sd_icon = preload("res://assets/icons/interface-sd.svg")
const ssd_icon = preload("res://assets/icons/interface-ssd.svg")
const usb_icon = preload("res://assets/icons/interface-usb.svg")
-var device: BlockDevice
+var block_device: BlockDevice
var device_path: String
var highlight_tween: Tween
@@ -39,8 +39,8 @@ var log_level:= Log.LEVEL.INFO
## Performs _ready fucntionality with the given BlockDevice
func setup(device: BlockDevice) -> void:
# Setup UDisks2 information
- self.device = device
- self.device_path = "/dev" + self.device.dbus_path.trim_prefix(steam_disks.BLOCK_PREFIX)
+ self.block_device = device
+ self.device_path = "/dev" + self.block_device.dbus_path.trim_prefix(steam_disks.BLOCK_PREFIX)
logger = Log.get_logger("DriveCard|"+self.device_path, log_level)
logger.debug("Setup Drive Card")
@@ -86,7 +86,7 @@ func _srm_format_drive() -> void:
_clear_partitions()
_on_format_started()
var note := Notification.new("Format Complete: " + self.device_path)
- if await steam_disks.format_drive(device) != OK:
+ if await steam_disks.format_drive(block_device) != OK:
note.text = "Failed to format " + self.device_path
_on_format_complete(note)
@@ -132,39 +132,49 @@ func _srm_init_drive(partition: PartitionDevice) -> void:
init_partition.emit(partition)
-func _clear_partitions() -> void:
- # Clear the current grid of items
- var keep_nodes := [partitions_focus_group]
- for child in partitions_container.get_children():
- if child in keep_nodes:
- continue
- partitions_container.remove_child(child)
- child.queue_free()
-
func _set_icon() -> void:
- if not device or not device.drive:
- logger.warn("Unable to detect drive to set icon for:", device)
+ if not block_device:
+ logger.warn("Unable to detect drive to set icon for something?")
drive_icon.texture = hdd_icon
return
- match device.drive.interface_type:
- DriveDevice.INTERFACE_TYPE.HDD:
+ var drive := block_device.get_drive() as DriveDevice
+ if not drive:
+ logger.warn("Unable to detect drive to set icon for:", block_device)
+ drive_icon.texture = hdd_icon
+ return
+
+ match drive.interface_type():
+ DriveDevice.INTERFACE_TYPE_HDD:
drive_icon.texture = hdd_icon
- DriveDevice.INTERFACE_TYPE.NVME:
+ DriveDevice.INTERFACE_TYPE_NVME:
drive_icon.texture = nvme_icon
- DriveDevice.INTERFACE_TYPE.SD:
+ DriveDevice.INTERFACE_TYPE_SD:
drive_icon.texture = sd_icon
- DriveDevice.INTERFACE_TYPE.SSD:
+ DriveDevice.INTERFACE_TYPE_SSD:
drive_icon.texture = ssd_icon
- DriveDevice.INTERFACE_TYPE.USB:
+ DriveDevice.INTERFACE_TYPE_USB:
drive_icon.texture = usb_icon
+ DriveDevice.INTERFACE_TYPE_UNKNOWN:
+ # TODO: Assign a unique texture for this
+ drive_icon.texture = hdd_icon
+
+
+func _clear_partitions() -> void:
+ # Clear the current grid of items
+ var keep_nodes := [partitions_focus_group]
+ for child in partitions_container.get_children():
+ if child in keep_nodes:
+ continue
+ partitions_container.remove_child(child)
+ child.queue_free()
## Populates the partition grid with an item for every PartitionDevice on this BlockDevice
func _populate_partitions() -> void:
_clear_partitions()
var last_focus: FocusGroup
- for partition in self.device.partitions:
+ for partition in self.block_device.get_partitions():
# Ignore loop devices
if partition.partition_name.contains("/dev/loop"):
diff --git a/core/ui/components/input_icon.gd b/core/ui/components/input_icon.gd
index 099ba1d36..1a6d56d1a 100644
--- a/core/ui/components/input_icon.gd
+++ b/core/ui/components/input_icon.gd
@@ -31,15 +31,15 @@ var internal_children: Array[Node] = []
self.textures = input_icons.parse_path(path, force_mapping, force_type - 1)
else:
self.textures = input_icons.parse_path(path, force_mapping)
-
+
# If no textures are found, become invisible
self.visible = !self.textures.is_empty()
-
+
# Remove old children
for child in internal_children.duplicate():
_remove_internal_child(child)
internal_children.clear()
-
+
# Add new children
var i := 0
for texture in self.textures:
@@ -123,8 +123,7 @@ func _on_input_type_changed(input_type: InputIconManager.InputType):
(show_only == 2 and input_type == InputIconManager.InputType.GAMEPAD):
self.visible = true
self.path = path
- var width := self.max_width
- self.max_width = width
+ self.max_width = max_width
else:
self.visible = false
diff --git a/core/ui/components/input_texture_rect.gd b/core/ui/components/input_texture_rect.gd
deleted file mode 100644
index c7e48c87d..000000000
--- a/core/ui/components/input_texture_rect.gd
+++ /dev/null
@@ -1,53 +0,0 @@
-@tool
-extends TextureRect
-class_name InputTextureRect
-
-
-@export var path : String = "":
- set(_path):
- path = _path
- if is_inside_tree():
- if force_type > 0:
- texture = ControllerIcons.parse_path(path, force_type - 1)
- else:
- texture = ControllerIcons.parse_path(path)
-
-@export_enum("Both", "Keyboard/Mouse", "Controller") var show_only : int = 0:
- set(_show_only):
- show_only = _show_only
- _on_input_type_changed(ControllerIcons._last_input_type)
-
-@export_enum("None", "Keyboard/Mouse", "Controller") var force_type : int = 0:
- set(_force_type):
- force_type = _force_type
- _on_input_type_changed(ControllerIcons._last_input_type)
-
-@export var max_width : int = 40:
- set(_max_width):
- max_width = _max_width
- if is_inside_tree():
- if max_width < 0:
- expand_mode = TextureRect.EXPAND_KEEP_SIZE
- else:
- expand_mode = TextureRect.EXPAND_IGNORE_SIZE
- custom_minimum_size.x = max_width
- if texture:
- custom_minimum_size.y = texture.get_height() * max_width / texture.get_width()
- else:
- custom_minimum_size.y = custom_minimum_size.x
-
-
-func _ready():
- ControllerIcons.input_type_changed.connect(_on_input_type_changed)
- self.path = path
- self.max_width = max_width
-
-
-func _on_input_type_changed(input_type):
- if show_only == 0 or \
- (show_only == 1 and input_type == ControllerIcons.InputType.KEYBOARD_MOUSE) or \
- (show_only == 2 and input_type == ControllerIcons.InputType.CONTROLLER):
- visible = true
- self.path = path
- else:
- visible = false
diff --git a/core/ui/components/loading02.gd b/core/ui/components/loading02.gd
index 8d0ce9ebb..c93369ddf 100644
--- a/core/ui/components/loading02.gd
+++ b/core/ui/components/loading02.gd
@@ -7,15 +7,19 @@ extends Control
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
- if visible:
+ if is_visible_in_tree():
+ set_process(true)
animation_player.play("play")
+ else:
+ set_process(false)
+ animation_player.stop()
visibility_changed.connect(_on_visibility_changed)
func _on_visibility_changed() -> void:
if not animation_player:
return
- if visible:
+ if is_visible_in_tree():
set_process(true)
animation_player.play("play")
return
@@ -26,5 +30,9 @@ func _on_visibility_changed() -> void:
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(_delta: float) -> void:
var sprite_scale := 1 / (sprite.texture.get_height() / size.y)
- sprite.offset = size / 2 / sprite_scale
- sprite.scale = Vector2(sprite_scale, sprite_scale)
+ var new_offset := size / 2 / sprite_scale
+ if new_offset != sprite.offset:
+ sprite.offset = new_offset
+ var new_scale := Vector2(sprite_scale, sprite_scale)
+ if new_scale != sprite.scale:
+ sprite.scale = new_scale
diff --git a/core/ui/components/loading02.tscn b/core/ui/components/loading02.tscn
index 4f1019b86..995fcecc3 100644
--- a/core/ui/components/loading02.tscn
+++ b/core/ui/components/loading02.tscn
@@ -45,7 +45,7 @@ script = ExtResource("1_1u2cn")
texture = ExtResource("1_jaecb")
offset = Vector2(128, 128)
hframes = 43
-frame = 20
+frame = 31
[node name="AnimationPlayer" type="AnimationPlayer" parent="Sprite2D"]
root_node = NodePath("../..")
diff --git a/core/ui/components/partition_card.gd b/core/ui/components/partition_card.gd
index 81e885cea..91cbf7ec8 100644
--- a/core/ui/components/partition_card.gd
+++ b/core/ui/components/partition_card.gd
@@ -4,8 +4,8 @@ class_name PartitionCard
var steam_disks := load("res://core/systems/disks/steam_removable_media_manager.tres") as SteamRemovableMediaManager
var notification_manager := load("res://core/global/notification_manager.tres") as NotificationManager
-var device: PartitionDevice
-var device_path: String
+var partition_device: PartitionDevice
+var partition_device_path: String
signal init_partition(device: PartitionDevice)
@@ -20,14 +20,14 @@ var log_level:= Log.LEVEL.INFO
## Performs _ready fucntionality with the given PartitionDevice
-func setup(partition_device: PartitionDevice) -> void:
+func setup(device: PartitionDevice) -> void:
# Setup UDisks2 information
- self.device = partition_device
- self.device_path = "/dev" + self.device.dbus_path.trim_prefix(steam_disks.BLOCK_PREFIX)
- logger = Log.get_logger("PartitionCard|"+self.device_path, log_level)
- logger.debug("Setup card for:", self.device.dbus_path)
- name_label.text = self.device_path
- filesystem_label.text = self.device.block_id_type
+ self.partition_device = device
+ self.partition_device_path = "/dev" + self.partition_device.dbus_path.trim_prefix(steam_disks.BLOCK_PREFIX)
+ logger = Log.get_logger("PartitionCard|"+self.partition_device_path, log_level)
+ logger.debug("Setup card for:", self.partition_device.dbus_path)
+ name_label.text = self.partition_device_path
+ filesystem_label.text = self.partition_device.get_filesystem_type()
size_label.text = partition_device.get_readable_size()
_populate_mounts()
@@ -39,7 +39,7 @@ func setup(partition_device: PartitionDevice) -> void:
func _srm_init_drive() -> void:
var dialog := get_tree().get_first_node_in_group("dialog") as Dialog
- var msg := "INFO: Adding " + device_path + " as a steam path will NOT cause data loss. " + \
+ var msg := "INFO: Adding " + self.partition_device_path + " as a steam path will NOT cause data loss. " + \
"The drive will be made available to Steam for installing games. Do you wish to continue?"
dialog.open(init_button, msg, "Cancel", "Continue")
var cancel := await dialog.choice_selected as bool
@@ -50,16 +50,16 @@ func _srm_init_drive() -> void:
logger.debug("Init operation blocked.")
return
- logger.debug("Init Partition", device_path)
+ logger.debug("Init Partition", self.partition_device_path)
_clear_mounts()
- var note := Notification.new("Started Initializing Steam Library on " + self.device_path)
+ var note := Notification.new("Started Initializing Steam Library on " + self.partition_device_path)
notification_manager.show(note)
init_button.text = "Adding to Steam..."
- note.text = "Initializing Complete: " + self.device_path
- if await steam_disks.init_steam_lib(device) != OK:
- note.text = "Failed to add drive to steam: " + self.device_path
+ note.text = "Initializing Complete: " + self.partition_device_path
+ if await steam_disks.init_steam_lib(self.partition_device) != OK:
+ note.text = "Failed to add drive to steam: " + self.partition_device_path
- logger.debug("Init Complete", device_path)
+ logger.debug("Init Complete", self.partition_device_path)
init_button.text = "Add to Steam"
notification_manager.show(note)
_populate_mounts()
@@ -75,8 +75,12 @@ func _clear_mounts() -> void:
## Populates the mount grid with an item for every mount point on this PartitionDevice
func _populate_mounts() -> void:
_clear_mounts()
- logger.debug("Mounts:", str(self.device.fs_mount_points))
- for mount in self.device.fs_mount_points:
+ var filesystem_device = self.partition_device.get_filesystem()
+ if not filesystem_device:
+ return
+ var mounts: PackedStringArray = filesystem_device.get_mounts()
+ logger.debug("Mounts:", str(mounts))
+ for mount in mounts:
var fs_label := Label.new()
fs_label.text = mount
mounts_container.add_child(fs_label)
diff --git a/core/ui/components/plugin_store_card.gd b/core/ui/components/plugin_store_card.gd
index 991eab306..31798ed91 100644
--- a/core/ui/components/plugin_store_card.gd
+++ b/core/ui/components/plugin_store_card.gd
@@ -120,13 +120,16 @@ func _on_update_button() -> void:
func _on_unfocus() -> void:
# Emit a signal if a non-child node grabs focus
- var focus_owner := get_viewport().gui_get_focus_owner()
+ var viewport := get_viewport()
+ if not viewport:
+ return
+ var focus_owner := viewport.gui_get_focus_owner()
if not self.is_ancestor_of(focus_owner):
nonchild_focused.emit()
return
# If a child has focus, listen for focus changes until a non-child has focus
- get_viewport().gui_focus_changed.connect(_on_focus_change)
+ viewport.gui_focus_changed.connect(_on_focus_change)
func _on_focus_change(focused: Control) -> void:
diff --git a/core/ui/components/progress_dialog.gd b/core/ui/components/progress_dialog.gd
index 4a023374b..d4c92c61e 100644
--- a/core/ui/components/progress_dialog.gd
+++ b/core/ui/components/progress_dialog.gd
@@ -1,4 +1,4 @@
-@icon("res://assets/editor-icons/dialog-2-bold.svg")
+@icon("res://assets/editor-icons/solar--dialog-2-bold.svg")
@tool
extends Control
class_name ProgressDialog
diff --git a/core/ui/components/toggle.tscn b/core/ui/components/toggle.tscn
index 4c68c13f3..55a8fd1f3 100644
--- a/core/ui/components/toggle.tscn
+++ b/core/ui/components/toggle.tscn
@@ -58,5 +58,4 @@ autowrap_mode = 3
[node name="HSeparator" type="HSeparator" parent="VBoxContainer"]
unique_name_in_owner = true
-visible = false
layout_mode = 2
diff --git a/core/ui/components/volume_indicator.gd b/core/ui/components/volume_indicator.gd
index e021fdb6c..c0c396c9d 100644
--- a/core/ui/components/volume_indicator.gd
+++ b/core/ui/components/volume_indicator.gd
@@ -2,8 +2,8 @@ extends Control
var audio_manager := load("res://core/global/audio_manager.tres") as AudioManager
var PID: int = OS.get_process_id()
-var gamescope := load("res://core/global/gamescope.tres") as Gamescope
-var overlay_window_id := gamescope.get_window_id(PID, gamescope.XWAYLAND.OGUI)
+var gamescope := load("res://core/systems/gamescope/gamescope.tres") as GamescopeInstance
+var overlay_window_id: int
@onready var timer := $%Timer as Timer
@onready var level_indicator := $%LevelIndicator
@@ -11,6 +11,11 @@ var overlay_window_id := gamescope.get_window_id(PID, gamescope.XWAYLAND.OGUI)
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
+ var xwayland := gamescope.get_xwayland(gamescope.XWAYLAND_TYPE_OGUI)
+ if xwayland:
+ var window_ids := xwayland.get_windows_for_pid(PID)
+ if not window_ids.is_empty():
+ overlay_window_id = window_ids[0]
audio_manager.volume_changed.connect(_on_volume_changed)
timer.timeout.connect(_on_timeout)
visible = false
@@ -20,9 +25,13 @@ func _on_volume_changed(value: float) -> void:
visible = true
level_indicator.value = value * 100
timer.start()
- gamescope.set_notification(overlay_window_id, 1)
+ var xwayland := gamescope.get_xwayland(gamescope.XWAYLAND_TYPE_OGUI)
+ if xwayland:
+ xwayland.set_notification(overlay_window_id, 1)
func _on_timeout() -> void:
visible = false
- gamescope.set_notification(overlay_window_id, 0)
+ var xwayland := gamescope.get_xwayland(gamescope.XWAYLAND_TYPE_OGUI)
+ if xwayland:
+ xwayland.set_notification(overlay_window_id, 0)
diff --git a/core/ui/components/wifi_network_tree.gd b/core/ui/components/wifi_network_tree.gd
index 1dcfc6ed3..a3a70d484 100644
--- a/core/ui/components/wifi_network_tree.gd
+++ b/core/ui/components/wifi_network_tree.gd
@@ -1,7 +1,7 @@
extends Tree
class_name WifiNetworkTree
-const thread := preload("res://core/systems/threading/thread_pool.tres")
+var network_manager := load("res://core/systems/network/network_manager.tres") as NetworkManagerInstance
## Emitted when a password is needed to connect. The given callable should be
## invoked by a listener with the password. E.g. callback.call(password)
@@ -15,11 +15,17 @@ var logger := Log.get_logger("WifiNetworkTree")
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
- if not NetworkManager.supports_network():
- logger.warn("Network management not supported")
- return
+ hide_root = true
+ columns = 5
+ select_mode = SELECT_ROW
+ scroll_horizontal_enabled = false
+ if not network_manager.is_running():
+ logger.warn("NetworkManager is not running")
+
+ # Adjust column sizes
+ set_column_expand(0, false)
+ set_column_expand(2, false)
- thread.start()
visibility_changed.connect(refresh_networks)
item_activated.connect(_on_wifi_selected)
create_item()
@@ -28,7 +34,11 @@ func _ready() -> void:
func _on_wifi_selected() -> void:
var item := get_selected()
- var ssid := item.get_text(1)
+ var ssid := item.get_metadata(0) as String
+ var has_security := item.get_metadata(2) as bool
+ if has_security:
+ challenge_required.emit(network_connect.bind(ssid))
+ return
network_connect("", ssid)
@@ -40,40 +50,100 @@ func network_connect(password: String, ssid: String) -> void:
logger.info("Connecting to SSID: " + ssid)
connecting = true
+ # Find the wireless device
+ var devices := network_manager.get_devices()
+ var wifi_devices := devices.filter(func(device: NetworkDevice): return device.wireless != null)
+ if wifi_devices.is_empty():
+ logger.warn("No wifi devices found")
+ connecting = false
+ return
+ var device := wifi_devices[0] as NetworkDevice
+
+ # Find the access point to connect to
+ var access_points := device.wireless.access_points
+ var valid_access_points := access_points.filter(func(ap: NetworkAccessPoint): return ap.ssid == ssid)
+ if valid_access_points.is_empty():
+ logger.warn("Unable to find access point with SSID:", ssid)
+ connecting = false
+ return
+ var access_point := valid_access_points[0] as NetworkAccessPoint
+
+ # Try to connect to the access point
+ access_point.connect(device, password)
+
+ # Update the tree item's status
var item := get_selected()
- var connect_ap := func() -> int:
- return NetworkManager.connect_access_point(ssid)
item.set_text(4, "Connecting")
- var code := await thread.exec(connect_ap) as int
- connecting = false
- if code == OK:
- logger.info("Successfully connected to " + ssid)
- refresh_networks()
- return
+ # Wait for the connection to be established
+ for i in range(60):
+ logger.info("Device state: " + str(device.state))
+ match device.state:
+ device.NM_DEVICE_STATE_ACTIVATED:
+ logger.info("Successfully connected to", ssid)
+ item.set_text(4, "Connected")
+ connecting = false
+ refresh_networks()
+ return
+ device.NM_DEVICE_STATE_NEED_AUTH:
+ logger.info("Authentication required")
+ item.set_text(4, "Authentication required")
+ connecting = false
+ challenge_required.emit(network_connect.bind(ssid))
+ return
+ device.NM_DEVICE_STATE_CONFIG:
+ logger.info("Connecting...")
+ item.set_text(4, "Connecting")
+ device.NM_DEVICE_STATE_IP_CONFIG:
+ logger.info("Acquiring IP address...")
+ item.set_text(4, "Acquiring IP address")
+ device.NM_DEVICE_STATE_DEACTIVATING:
+ logger.info("Deactivation connection...")
+ item.set_text(4, "Deactivating connection")
+ device.NM_DEVICE_STATE_DISCONNECTED:
+ logger.info("Disconnected")
+ item.set_text(4, "Disconnected")
+ connecting = false
+ return
+ device.NM_DEVICE_STATE_FAILED:
+ logger.info("Failed to connect")
+ item.set_text(4, "Failed to connect")
+ connecting = false
+ return
+ # Use a timer to wait between tries
+ await get_tree().create_timer(0.5).timeout
- # If we fail to connect, open a wifi challenge
- logger.info("Wifi challenge required")
- item.set_text(4, "Unable to connect")
- challenge_required.emit(network_connect.bind(ssid))
+ connecting = false
+ logger.info("Timed out waiting to connect")
+ item.set_text(4, "Failed to connect")
## Refreshes the available wifi networks
func refresh_networks() -> void:
logger.info("Refreshing wifi networks")
refresh_started.emit()
- # Fetch all the available access points from NetworkManager
+
+ # Find the wireless device
+ var devices := network_manager.get_devices()
+ var wifi_devices := devices.filter(func(device: NetworkDevice): return device.wireless != null)
+ if wifi_devices.is_empty():
+ logger.warn("No wifi devices found")
+ return
+ var device := wifi_devices[0] as NetworkDevice
+
+ # Request a scan
+ device.wireless.request_scan()
+ await get_tree().create_timer(0.5).timeout
+
+ # Fetch all the available access points
var tree := self as Tree
var root := tree.get_root()
- var access_points: Array[NetworkManager.WifiAP]
- var get_aps := func() -> Array[NetworkManager.WifiAP]:
- return NetworkManager.get_access_points()
- access_points = await thread.exec(get_aps)
+ var access_points := device.wireless.access_points
# Create an array of BSSIDs from our access points
var bssids := []
for ap in access_points:
- bssids.append(ap.bssid)
+ bssids.append(ap.ssid)
# Look at the current tree items to see if any need to be removed
var tree_bssids := {}
@@ -84,20 +154,36 @@ func refresh_networks() -> void:
continue
root.remove_child(item)
+ var active_ap := device.wireless.active_access_point
+
# Look at the current APs to see if any tree items need to be created
# or updated
for ap in access_points:
+ await get_tree().create_timer(0.1).timeout # help spread out sync data fetching
var item: TreeItem
- if ap.bssid in tree_bssids:
- item = tree_bssids[ap.bssid]
+ if ap.ssid in tree_bssids:
+ item = tree_bssids[ap.ssid]
else:
item = tree.create_item(root)
- item.set_metadata(0, ap.bssid)
+
+ # Determine the security used for the access point
+ var has_security := ap.flags > ap.NM_802_11_AP_SEC_NONE
+ var security_texture: Texture2D
+ if has_security:
+ security_texture = load("res://assets/ui/icons/material-symbols--lock.svg")
+
+ var bitrate = (ap.max_bitrate / 1024.0)
+ bitrate = int(round(bitrate))
+
+ item.set_metadata(0, ap.ssid)
item.set_icon(0, NetworkManager.get_strength_texture(ap.strength))
item.set_text(1, ap.ssid)
- item.set_text(2, ap.security)
- item.set_text(3, ap.rate)
- if ap.in_use:
+ item.set_icon(2, security_texture)
+ item.set_icon_max_width(2, 16)
+ item.set_expand_right(2, false)
+ item.set_metadata(2, has_security)
+ item.set_text(3, str(bitrate) + " Mb/s")
+ if active_ap and active_ap.ssid == ap.ssid:
item.set_text(4, "Connected")
else:
item.set_text(4, "")
diff --git a/docker/Dockerfile b/docker/Dockerfile
index 7cdb05b89..d416a8500 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -2,45 +2,27 @@ FROM archlinux:base-devel
LABEL org.opencontainers.image.title="OpenGamepadUI Builder"
LABEL org.opencontainers.image.description="Build container for OpenGamepadUI"
LABEL org.opencontainers.image.source="https://github.com/ShadowBlip/OpenGamepadUI"
-LABEL org.opencontainers.image.version="4.2.2"
+LABEL org.opencontainers.image.version="4.3"
RUN sed -i '/ParallelDownloads/s/^#//g' /etc/pacman.conf
# Install dependencies
RUN echo -e "[multilib]\nInclude = /etc/pacman.d/mirrorlist\n" >> /etc/pacman.conf
RUN pacman --noconfirm -Syyu && pacman -S --needed --noconfirm \
- scons \
pkgconf \
- gcc \
- gcc-libs \
- libxcursor \
- libxinerama \
- libxi \
- libxrandr \
- mesa \
- glu \
- libglvnd \
- alsa-lib \
make \
- cmake \
unzip \
wget \
git \
- libevdev \
- libxau \
- libxcb \
- libxdmcp \
- libxext \
- libxres \
- libxtst \
squashfs-tools \
rpm-tools \
+ rust \
fontconfig \
zip \
jq
# Download and install the appropriate version of Godot
-ARG GODOT_VERSION=4.2.2
+ARG GODOT_VERSION=4.3
ARG GODOT_RELEASE=stable
RUN mkdir /tmp/godot && \
wget -q https://github.com/godotengine/godot-builds/releases/download/${GODOT_VERSION}-${GODOT_RELEASE}/Godot_v${GODOT_VERSION}-${GODOT_RELEASE}_linux.x86_64.zip -O /tmp/godot/godot.zip && \
diff --git a/docker/Dockerfile.addons b/docker/Dockerfile.addons
deleted file mode 100644
index 70348ae89..000000000
--- a/docker/Dockerfile.addons
+++ /dev/null
@@ -1,33 +0,0 @@
-FROM ubuntu:22.04
-
-# Install GDExtension dependencies
-ENV DEBIAN_FRONTEND noninteractive
-RUN apt-get update && apt-get install -y \
- build-essential \
- python3-pip \
- pkg-config \
- libx11-dev \
- libxcursor-dev \
- libxinerama-dev \
- libgl1-mesa-dev \
- libglu-dev \
- libasound2-dev \
- libpulse-dev \
- libudev-dev \
- libxi-dev \
- libxrandr-dev \
- binutils \
- git
-
-# Install scons from pypi
-RUN pip3 install scons
-
-# Install DBus dependencies
-RUN apt-get install -y \
- libdbus-1-dev \
- libdbus-c++-dev
-
-# Install Xlib dependencies
-RUN apt-get install -y \
- libxres-dev \
- libxtst-dev
diff --git a/entrypoint.gd b/entrypoint.gd
index aab3f90d3..b244c3d43 100644
--- a/entrypoint.gd
+++ b/entrypoint.gd
@@ -9,6 +9,10 @@ var args := OS.get_cmdline_args()
var child_pid := -1
var logger := Log.get_logger("Entrypoint")
+# We don't need this here, except we do. For some reason it won't load properly
+# after the entrypoint anymore and I don't care why. Don't touch this.
+var settings_manager := load("res://core/global/settings_manager.tres") as SettingsManager
+var input_icons := load("res://core/systems/input/input_icon_manager.tres") as InputIconManager
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
diff --git a/gdext/.gdignore b/extensions/.gdignore
similarity index 100%
rename from gdext/.gdignore
rename to extensions/.gdignore
diff --git a/extensions/.gitignore b/extensions/.gitignore
new file mode 100644
index 000000000..54b02da46
--- /dev/null
+++ b/extensions/.gitignore
@@ -0,0 +1,2 @@
+/target
+*.so
diff --git a/extensions/Cargo.lock b/extensions/Cargo.lock
new file mode 100644
index 000000000..db4ee3af2
--- /dev/null
+++ b/extensions/Cargo.lock
@@ -0,0 +1,1934 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "addr2line"
+version = "0.24.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1"
+dependencies = [
+ "gimli",
+]
+
+[[package]]
+name = "adler2"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
+
+[[package]]
+name = "ahash"
+version = "0.7.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9"
+dependencies = [
+ "getrandom",
+ "once_cell",
+ "version_check",
+]
+
+[[package]]
+name = "aho-corasick"
+version = "1.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "arrayvec"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
+
+[[package]]
+name = "async-broadcast"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "20cd0e2e25ea8e5f7e9df04578dc6cf5c83577fd09b1a46aaf5c85e1c33f2a7e"
+dependencies = [
+ "event-listener",
+ "event-listener-strategy",
+ "futures-core",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "async-channel"
+version = "2.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a"
+dependencies = [
+ "concurrent-queue",
+ "event-listener-strategy",
+ "futures-core",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "async-executor"
+version = "1.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec"
+dependencies = [
+ "async-task",
+ "concurrent-queue",
+ "fastrand",
+ "futures-lite",
+ "slab",
+]
+
+[[package]]
+name = "async-fs"
+version = "2.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ebcd09b382f40fcd159c2d695175b2ae620ffa5f3bd6f664131efff4e8b9e04a"
+dependencies = [
+ "async-lock",
+ "blocking",
+ "futures-lite",
+]
+
+[[package]]
+name = "async-io"
+version = "2.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "43a2b323ccce0a1d90b449fd71f2a06ca7faa7c54c2751f06c9bd851fc061059"
+dependencies = [
+ "async-lock",
+ "cfg-if",
+ "concurrent-queue",
+ "futures-io",
+ "futures-lite",
+ "parking",
+ "polling",
+ "rustix",
+ "slab",
+ "tracing",
+ "windows-sys 0.59.0",
+]
+
+[[package]]
+name = "async-lock"
+version = "3.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18"
+dependencies = [
+ "event-listener",
+ "event-listener-strategy",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "async-process"
+version = "2.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "63255f1dc2381611000436537bbedfe83183faa303a5a0edaf191edef06526bb"
+dependencies = [
+ "async-channel",
+ "async-io",
+ "async-lock",
+ "async-signal",
+ "async-task",
+ "blocking",
+ "cfg-if",
+ "event-listener",
+ "futures-lite",
+ "rustix",
+ "tracing",
+]
+
+[[package]]
+name = "async-recursion"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.90",
+]
+
+[[package]]
+name = "async-signal"
+version = "0.2.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "637e00349800c0bdf8bfc21ebbc0b6524abea702b0da4168ac00d070d0c0b9f3"
+dependencies = [
+ "async-io",
+ "async-lock",
+ "atomic-waker",
+ "cfg-if",
+ "futures-core",
+ "futures-io",
+ "rustix",
+ "signal-hook-registry",
+ "slab",
+ "windows-sys 0.59.0",
+]
+
+[[package]]
+name = "async-task"
+version = "4.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de"
+
+[[package]]
+name = "async-trait"
+version = "0.1.83"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.90",
+]
+
+[[package]]
+name = "atomic-waker"
+version = "1.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
+
+[[package]]
+name = "autocfg"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
+
+[[package]]
+name = "backtrace"
+version = "0.3.74"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a"
+dependencies = [
+ "addr2line",
+ "cfg-if",
+ "libc",
+ "miniz_oxide",
+ "object",
+ "rustc-demangle",
+ "windows-targets 0.52.6",
+]
+
+[[package]]
+name = "bitflags"
+version = "2.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
+
+[[package]]
+name = "bitvec"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c"
+dependencies = [
+ "funty",
+ "radium",
+ "tap",
+ "wyz",
+]
+
+[[package]]
+name = "block-buffer"
+version = "0.10.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
+dependencies = [
+ "generic-array",
+]
+
+[[package]]
+name = "blocking"
+version = "1.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea"
+dependencies = [
+ "async-channel",
+ "async-task",
+ "futures-io",
+ "futures-lite",
+ "piper",
+]
+
+[[package]]
+name = "borsh"
+version = "1.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2506947f73ad44e344215ccd6403ac2ae18cd8e046e581a441bf8d199f257f03"
+dependencies = [
+ "borsh-derive",
+ "cfg_aliases",
+]
+
+[[package]]
+name = "borsh-derive"
+version = "1.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c2593a3b8b938bd68373196c9832f516be11fa487ef4ae745eb282e6a56a7244"
+dependencies = [
+ "once_cell",
+ "proc-macro-crate",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.90",
+]
+
+[[package]]
+name = "byte-unit"
+version = "5.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e1cd29c3c585209b0cbc7309bfe3ed7efd8c84c21b7af29c8bfae908f8777174"
+dependencies = [
+ "rust_decimal",
+ "serde",
+ "utf8-width",
+]
+
+[[package]]
+name = "bytecheck"
+version = "0.6.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "23cdc57ce23ac53c931e88a43d06d070a6fd142f2617be5855eb75efc9beb1c2"
+dependencies = [
+ "bytecheck_derive",
+ "ptr_meta",
+ "simdutf8",
+]
+
+[[package]]
+name = "bytecheck_derive"
+version = "0.6.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3db406d29fbcd95542e92559bed4d8ad92636d1ca8b3b72ede10b4bcc010e659"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "byteorder"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
+
+[[package]]
+name = "bytes"
+version = "1.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "cfg_aliases"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
+
+[[package]]
+name = "concurrent-queue"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973"
+dependencies = [
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "cpufeatures"
+version = "0.2.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "crossbeam-utils"
+version = "0.8.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
+
+[[package]]
+name = "crypto-common"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
+dependencies = [
+ "generic-array",
+ "typenum",
+]
+
+[[package]]
+name = "digest"
+version = "0.10.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
+dependencies = [
+ "block-buffer",
+ "crypto-common",
+]
+
+[[package]]
+name = "endi"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a3d8a32ae18130a3c84dd492d4215c3d913c3b07c6b63c2eb3eb7ff1101ab7bf"
+
+[[package]]
+name = "enumflags2"
+version = "0.7.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d232db7f5956f3f14313dc2f87985c58bd2c695ce124c8cdd984e08e15ac133d"
+dependencies = [
+ "enumflags2_derive",
+ "serde",
+]
+
+[[package]]
+name = "enumflags2_derive"
+version = "0.7.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.90",
+]
+
+[[package]]
+name = "equivalent"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
+
+[[package]]
+name = "errno"
+version = "0.3.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d"
+dependencies = [
+ "libc",
+ "windows-sys 0.59.0",
+]
+
+[[package]]
+name = "event-listener"
+version = "5.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba"
+dependencies = [
+ "concurrent-queue",
+ "parking",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "event-listener-strategy"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1"
+dependencies = [
+ "event-listener",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "fastrand"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4"
+
+[[package]]
+name = "funty"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
+
+[[package]]
+name = "futures-core"
+version = "0.3.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
+
+[[package]]
+name = "futures-io"
+version = "0.3.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
+
+[[package]]
+name = "futures-lite"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cef40d21ae2c515b51041df9ed313ed21e572df340ea58a922a0aefe7e8891a1"
+dependencies = [
+ "fastrand",
+ "futures-core",
+ "futures-io",
+ "parking",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "futures-macro"
+version = "0.3.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.90",
+]
+
+[[package]]
+name = "futures-sink"
+version = "0.3.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7"
+
+[[package]]
+name = "futures-task"
+version = "0.3.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
+
+[[package]]
+name = "futures-util"
+version = "0.3.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
+dependencies = [
+ "futures-core",
+ "futures-io",
+ "futures-macro",
+ "futures-sink",
+ "futures-task",
+ "memchr",
+ "pin-project-lite",
+ "pin-utils",
+ "slab",
+]
+
+[[package]]
+name = "gamescope-x11-client"
+version = "0.1.0"
+source = "git+https://github.com/ShadowBlip/gamescope-x11-client?branch=main#9526a6e0d684d9530e8705f7f1a53efa401350f3"
+dependencies = [
+ "log",
+ "strum",
+ "strum_macros",
+ "x11rb",
+]
+
+[[package]]
+name = "gdextension-api"
+version = "0.2.1"
+source = "git+https://github.com/godot-rust/godot4-prebuilt?branch=releases#53fa4a856d93ac01d87deb8f57c6851179dfacec"
+
+[[package]]
+name = "generic-array"
+version = "0.14.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
+dependencies = [
+ "typenum",
+ "version_check",
+]
+
+[[package]]
+name = "gensym"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "913dce4c5f06c2ea40fc178c06f777ac89fc6b1383e90c254fafb1abe4ba3c82"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.90",
+ "uuid",
+]
+
+[[package]]
+name = "gethostname"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0176e0459c2e4a1fe232f984bca6890e681076abb9934f6cea7c326f3fc47818"
+dependencies = [
+ "libc",
+ "windows-targets 0.48.5",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
+[[package]]
+name = "gimli"
+version = "0.31.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
+
+[[package]]
+name = "glam"
+version = "0.28.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "779ae4bf7e8421cf91c0b3b64e7e8b40b862fba4d393f59150042de7c4965a94"
+
+[[package]]
+name = "godot"
+version = "0.2.0"
+source = "git+https://github.com/godot-rust/gdext?branch=master#c6b8b0e12414a69eb29ec512a313b4f5817e37de"
+dependencies = [
+ "godot-core",
+ "godot-macros",
+]
+
+[[package]]
+name = "godot-bindings"
+version = "0.2.0"
+source = "git+https://github.com/godot-rust/gdext?branch=master#c6b8b0e12414a69eb29ec512a313b4f5817e37de"
+dependencies = [
+ "gdextension-api",
+]
+
+[[package]]
+name = "godot-cell"
+version = "0.2.0"
+source = "git+https://github.com/godot-rust/gdext?branch=master#c6b8b0e12414a69eb29ec512a313b4f5817e37de"
+
+[[package]]
+name = "godot-codegen"
+version = "0.2.0"
+source = "git+https://github.com/godot-rust/gdext?branch=master#c6b8b0e12414a69eb29ec512a313b4f5817e37de"
+dependencies = [
+ "godot-bindings",
+ "heck 0.5.0",
+ "nanoserde",
+ "proc-macro2",
+ "quote",
+ "regex",
+]
+
+[[package]]
+name = "godot-core"
+version = "0.2.0"
+source = "git+https://github.com/godot-rust/gdext?branch=master#c6b8b0e12414a69eb29ec512a313b4f5817e37de"
+dependencies = [
+ "glam",
+ "godot-bindings",
+ "godot-cell",
+ "godot-codegen",
+ "godot-ffi",
+]
+
+[[package]]
+name = "godot-ffi"
+version = "0.2.0"
+source = "git+https://github.com/godot-rust/gdext?branch=master#c6b8b0e12414a69eb29ec512a313b4f5817e37de"
+dependencies = [
+ "gensym",
+ "godot-bindings",
+ "godot-codegen",
+ "libc",
+ "paste",
+]
+
+[[package]]
+name = "godot-macros"
+version = "0.2.0"
+source = "git+https://github.com/godot-rust/gdext?branch=master#c6b8b0e12414a69eb29ec512a313b4f5817e37de"
+dependencies = [
+ "godot-bindings",
+ "markdown",
+ "proc-macro2",
+ "quote",
+ "venial",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
+dependencies = [
+ "ahash",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.15.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
+
+[[package]]
+name = "heck"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
+
+[[package]]
+name = "heck"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
+
+[[package]]
+name = "hermit-abi"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc"
+
+[[package]]
+name = "hex"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
+
+[[package]]
+name = "indexmap"
+version = "2.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da"
+dependencies = [
+ "equivalent",
+ "hashbrown 0.15.2",
+]
+
+[[package]]
+name = "inotify"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3"
+dependencies = [
+ "bitflags",
+ "futures-core",
+ "inotify-sys",
+ "libc",
+ "tokio",
+]
+
+[[package]]
+name = "inotify-sys"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "itoa"
+version = "1.0.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
+
+[[package]]
+name = "keyvalues-parser"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7e4c8354918309196302015ac9cae43362f1a13d0d5c5539a33b4c2fd2cd6d25"
+dependencies = [
+ "pest",
+ "pest_derive",
+ "thiserror",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.167"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc"
+
+[[package]]
+name = "linux-raw-sys"
+version = "0.4.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
+
+[[package]]
+name = "lock_api"
+version = "0.4.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
+dependencies = [
+ "autocfg",
+ "scopeguard",
+]
+
+[[package]]
+name = "log"
+version = "0.4.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
+
+[[package]]
+name = "markdown"
+version = "1.0.0-alpha.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a6491e6c702bf7e3b24e769d800746d5f2c06a6c6a2db7992612e0f429029e81"
+dependencies = [
+ "unicode-id",
+]
+
+[[package]]
+name = "memchr"
+version = "2.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
+
+[[package]]
+name = "memoffset"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "miniz_oxide"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1"
+dependencies = [
+ "adler2",
+]
+
+[[package]]
+name = "mio"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd"
+dependencies = [
+ "libc",
+ "wasi",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "nanoserde"
+version = "0.1.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5de9cf844ab1e25a0353525bd74cb889843a6215fa4a0d156fd446f4857a1b99"
+dependencies = [
+ "nanoserde-derive",
+]
+
+[[package]]
+name = "nanoserde-derive"
+version = "0.1.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e943b2c21337b7e3ec6678500687cdc741b7639ad457f234693352075c082204"
+
+[[package]]
+name = "nix"
+version = "0.29.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46"
+dependencies = [
+ "bitflags",
+ "cfg-if",
+ "cfg_aliases",
+ "libc",
+ "memoffset",
+]
+
+[[package]]
+name = "num-traits"
+version = "0.2.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "object"
+version = "0.36.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.20.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
+
+[[package]]
+name = "opengamepadui-core"
+version = "0.1.0"
+dependencies = [
+ "byte-unit",
+ "futures-util",
+ "gamescope-x11-client",
+ "godot",
+ "inotify",
+ "keyvalues-parser",
+ "log",
+ "nix",
+ "once_cell",
+ "tokio",
+ "zbus",
+ "zvariant",
+]
+
+[[package]]
+name = "ordered-stream"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50"
+dependencies = [
+ "futures-core",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "parking"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba"
+
+[[package]]
+name = "parking_lot"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
+dependencies = [
+ "lock_api",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.9.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "redox_syscall",
+ "smallvec",
+ "windows-targets 0.52.6",
+]
+
+[[package]]
+name = "paste"
+version = "1.0.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
+
+[[package]]
+name = "pest"
+version = "2.7.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "879952a81a83930934cbf1786752d6dedc3b1f29e8f8fb2ad1d0a36f377cf442"
+dependencies = [
+ "memchr",
+ "thiserror",
+ "ucd-trie",
+]
+
+[[package]]
+name = "pest_derive"
+version = "2.7.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d214365f632b123a47fd913301e14c946c61d1c183ee245fa76eb752e59a02dd"
+dependencies = [
+ "pest",
+ "pest_generator",
+]
+
+[[package]]
+name = "pest_generator"
+version = "2.7.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eb55586734301717aea2ac313f50b2eb8f60d2fc3dc01d190eefa2e625f60c4e"
+dependencies = [
+ "pest",
+ "pest_meta",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.90",
+]
+
+[[package]]
+name = "pest_meta"
+version = "2.7.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b75da2a70cf4d9cb76833c990ac9cd3923c9a8905a8929789ce347c84564d03d"
+dependencies = [
+ "once_cell",
+ "pest",
+ "sha2",
+]
+
+[[package]]
+name = "pin-project-lite"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff"
+
+[[package]]
+name = "pin-utils"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
+
+[[package]]
+name = "piper"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066"
+dependencies = [
+ "atomic-waker",
+ "fastrand",
+ "futures-io",
+]
+
+[[package]]
+name = "polling"
+version = "3.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f"
+dependencies = [
+ "cfg-if",
+ "concurrent-queue",
+ "hermit-abi",
+ "pin-project-lite",
+ "rustix",
+ "tracing",
+ "windows-sys 0.59.0",
+]
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
+dependencies = [
+ "zerocopy",
+]
+
+[[package]]
+name = "proc-macro-crate"
+version = "3.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b"
+dependencies = [
+ "toml_edit",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "ptr_meta"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1"
+dependencies = [
+ "ptr_meta_derive",
+]
+
+[[package]]
+name = "ptr_meta_derive"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "radium"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
+
+[[package]]
+name = "rand"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
+dependencies = [
+ "libc",
+ "rand_chacha",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "reaper"
+version = "0.1.0"
+dependencies = [
+ "nix",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.5.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "regex"
+version = "1.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-automata",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
+
+[[package]]
+name = "rend"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "71fe3824f5629716b1589be05dacd749f6aa084c87e00e016714a8cdfccc997c"
+dependencies = [
+ "bytecheck",
+]
+
+[[package]]
+name = "rkyv"
+version = "0.7.45"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9008cd6385b9e161d8229e1f6549dd23c3d022f132a2ea37ac3a10ac4935779b"
+dependencies = [
+ "bitvec",
+ "bytecheck",
+ "bytes",
+ "hashbrown 0.12.3",
+ "ptr_meta",
+ "rend",
+ "rkyv_derive",
+ "seahash",
+ "tinyvec",
+ "uuid",
+]
+
+[[package]]
+name = "rkyv_derive"
+version = "0.7.45"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "503d1d27590a2b0a3a4ca4c94755aa2875657196ecbf401a42eff41d7de532c0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "rust_decimal"
+version = "1.36.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b082d80e3e3cc52b2ed634388d436fe1f4de6af5786cc2de9ba9737527bdf555"
+dependencies = [
+ "arrayvec",
+ "borsh",
+ "bytes",
+ "num-traits",
+ "rand",
+ "rkyv",
+ "serde",
+ "serde_json",
+]
+
+[[package]]
+name = "rustc-demangle"
+version = "0.1.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
+
+[[package]]
+name = "rustix"
+version = "0.38.41"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6"
+dependencies = [
+ "bitflags",
+ "errno",
+ "libc",
+ "linux-raw-sys",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "rustversion"
+version = "1.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248"
+
+[[package]]
+name = "ryu"
+version = "1.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
+
+[[package]]
+name = "scopeguard"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
+
+[[package]]
+name = "seahash"
+version = "4.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
+
+[[package]]
+name = "serde"
+version = "1.0.215"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.215"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.90",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.133"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377"
+dependencies = [
+ "itoa",
+ "memchr",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "serde_repr"
+version = "0.1.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.90",
+]
+
+[[package]]
+name = "sha1"
+version = "0.10.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "digest",
+]
+
+[[package]]
+name = "sha2"
+version = "0.10.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "digest",
+]
+
+[[package]]
+name = "signal-hook-registry"
+version = "1.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "simdutf8"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
+
+[[package]]
+name = "slab"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "smallvec"
+version = "1.13.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
+
+[[package]]
+name = "socket2"
+version = "0.5.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8"
+dependencies = [
+ "libc",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "static_assertions"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
+
+[[package]]
+name = "strum"
+version = "0.25.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125"
+
+[[package]]
+name = "strum_macros"
+version = "0.25.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0"
+dependencies = [
+ "heck 0.4.1",
+ "proc-macro2",
+ "quote",
+ "rustversion",
+ "syn 2.0.90",
+]
+
+[[package]]
+name = "syn"
+version = "1.0.109"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.90"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "tap"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
+
+[[package]]
+name = "tempfile"
+version = "3.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c"
+dependencies = [
+ "cfg-if",
+ "fastrand",
+ "once_cell",
+ "rustix",
+ "windows-sys 0.59.0",
+]
+
+[[package]]
+name = "thiserror"
+version = "1.0.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.90",
+]
+
+[[package]]
+name = "tinyvec"
+version = "1.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938"
+dependencies = [
+ "tinyvec_macros",
+]
+
+[[package]]
+name = "tinyvec_macros"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
+
+[[package]]
+name = "tokio"
+version = "1.41.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33"
+dependencies = [
+ "backtrace",
+ "bytes",
+ "libc",
+ "mio",
+ "parking_lot",
+ "pin-project-lite",
+ "signal-hook-registry",
+ "socket2",
+ "tokio-macros",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "tokio-macros"
+version = "2.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.90",
+]
+
+[[package]]
+name = "toml_datetime"
+version = "0.6.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
+
+[[package]]
+name = "toml_edit"
+version = "0.22.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5"
+dependencies = [
+ "indexmap",
+ "toml_datetime",
+ "winnow",
+]
+
+[[package]]
+name = "tracing"
+version = "0.1.41"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0"
+dependencies = [
+ "pin-project-lite",
+ "tracing-attributes",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-attributes"
+version = "0.1.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.90",
+]
+
+[[package]]
+name = "tracing-core"
+version = "0.1.33"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c"
+dependencies = [
+ "once_cell",
+]
+
+[[package]]
+name = "typenum"
+version = "1.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
+
+[[package]]
+name = "ucd-trie"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971"
+
+[[package]]
+name = "uds_windows"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "89daebc3e6fd160ac4aa9fc8b3bf71e1f74fbf92367ae71fb83a037e8bf164b9"
+dependencies = [
+ "memoffset",
+ "tempfile",
+ "winapi",
+]
+
+[[package]]
+name = "unicode-id"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "10103c57044730945224467c09f71a4db0071c123a0648cc3e818913bde6b561"
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
+
+[[package]]
+name = "utf8-width"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "86bd8d4e895da8537e5315b8254664e6b769c4ff3db18321b297a1e7004392e3"
+
+[[package]]
+name = "uuid"
+version = "1.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "venial"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6816bc32f30bf8dd1b3adb04de8406c7bf187d2f923bd9e4c0b99365d012613f"
+dependencies = [
+ "proc-macro2",
+ "quote",
+]
+
+[[package]]
+name = "version_check"
+version = "0.9.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
+
+[[package]]
+name = "wasi"
+version = "0.11.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
+[[package]]
+name = "windows-sys"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
+dependencies = [
+ "windows-targets 0.52.6",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.59.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
+dependencies = [
+ "windows-targets 0.52.6",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
+dependencies = [
+ "windows_aarch64_gnullvm 0.48.5",
+ "windows_aarch64_msvc 0.48.5",
+ "windows_i686_gnu 0.48.5",
+ "windows_i686_msvc 0.48.5",
+ "windows_x86_64_gnu 0.48.5",
+ "windows_x86_64_gnullvm 0.48.5",
+ "windows_x86_64_msvc 0.48.5",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
+dependencies = [
+ "windows_aarch64_gnullvm 0.52.6",
+ "windows_aarch64_msvc 0.52.6",
+ "windows_i686_gnu 0.52.6",
+ "windows_i686_gnullvm",
+ "windows_i686_msvc 0.52.6",
+ "windows_x86_64_gnu 0.52.6",
+ "windows_x86_64_gnullvm 0.52.6",
+ "windows_x86_64_msvc 0.52.6",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
+
+[[package]]
+name = "winnow"
+version = "0.6.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "wyz"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed"
+dependencies = [
+ "tap",
+]
+
+[[package]]
+name = "x11rb"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5d91ffca73ee7f68ce055750bf9f6eca0780b8c85eff9bc046a3b0da41755e12"
+dependencies = [
+ "gethostname",
+ "rustix",
+ "x11rb-protocol",
+]
+
+[[package]]
+name = "x11rb-protocol"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec107c4503ea0b4a98ef47356329af139c0a4f7750e621cf2973cd3385ebcb3d"
+
+[[package]]
+name = "xdg-home"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec1cdab258fb55c0da61328dc52c8764709b249011b2cad0454c72f0bf10a1f6"
+dependencies = [
+ "libc",
+ "windows-sys 0.59.0",
+]
+
+[[package]]
+name = "zbus"
+version = "4.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bb97012beadd29e654708a0fdb4c84bc046f537aecfde2c3ee0a9e4b4d48c725"
+dependencies = [
+ "async-broadcast",
+ "async-executor",
+ "async-fs",
+ "async-io",
+ "async-lock",
+ "async-process",
+ "async-recursion",
+ "async-task",
+ "async-trait",
+ "blocking",
+ "enumflags2",
+ "event-listener",
+ "futures-core",
+ "futures-sink",
+ "futures-util",
+ "hex",
+ "nix",
+ "ordered-stream",
+ "rand",
+ "serde",
+ "serde_repr",
+ "sha1",
+ "static_assertions",
+ "tracing",
+ "uds_windows",
+ "windows-sys 0.52.0",
+ "xdg-home",
+ "zbus_macros",
+ "zbus_names",
+ "zvariant",
+]
+
+[[package]]
+name = "zbus_macros"
+version = "4.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "267db9407081e90bbfa46d841d3cbc60f59c0351838c4bc65199ecd79ab1983e"
+dependencies = [
+ "proc-macro-crate",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.90",
+ "zvariant_utils",
+]
+
+[[package]]
+name = "zbus_names"
+version = "3.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4b9b1fef7d021261cc16cba64c351d291b715febe0fa10dc3a443ac5a5022e6c"
+dependencies = [
+ "serde",
+ "static_assertions",
+ "zvariant",
+]
+
+[[package]]
+name = "zerocopy"
+version = "0.7.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
+dependencies = [
+ "byteorder",
+ "zerocopy-derive",
+]
+
+[[package]]
+name = "zerocopy-derive"
+version = "0.7.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.90",
+]
+
+[[package]]
+name = "zvariant"
+version = "4.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2084290ab9a1c471c38fc524945837734fbf124487e105daec2bb57fd48c81fe"
+dependencies = [
+ "endi",
+ "enumflags2",
+ "serde",
+ "static_assertions",
+ "zvariant_derive",
+]
+
+[[package]]
+name = "zvariant_derive"
+version = "4.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "73e2ba546bda683a90652bac4a279bc146adad1386f25379cf73200d2002c449"
+dependencies = [
+ "proc-macro-crate",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.90",
+ "zvariant_utils",
+]
+
+[[package]]
+name = "zvariant_utils"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c51bcff7cc3dbb5055396bcf774748c3dab426b4b8659046963523cee4808340"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.90",
+]
diff --git a/extensions/Cargo.toml b/extensions/Cargo.toml
new file mode 100644
index 000000000..2d2cbba14
--- /dev/null
+++ b/extensions/Cargo.toml
@@ -0,0 +1,3 @@
+[workspace]
+members = ["core", "reaper"]
+resolver = "2"
diff --git a/extensions/Makefile b/extensions/Makefile
new file mode 100644
index 000000000..6f355153f
--- /dev/null
+++ b/extensions/Makefile
@@ -0,0 +1,50 @@
+PREFIX ?= addons
+EXT_NAME := $(shell grep 'name =' core/Cargo.toml | head -n 1 | cut -d'"' -f2)
+LIB_NAME := $(shell grep 'name =' core/Cargo.toml | head -n 1 | cut -d'"' -f2 | sed 's/-/_/g')
+ALL_RS := $(shell find ./ -name '*.rs')
+ADDON_PATH := ../addons/core
+RELEASE_TARGET := $(ADDON_PATH)/bin/lib$(EXT_NAME).linux.template_release.x86_64.so
+DEBUG_TARGET := $(ADDON_PATH)/bin/lib$(EXT_NAME).linux.template_debug.x86_64.so
+
+##@ General
+
+# The help target prints out all targets with their descriptions organized
+# beneath their categories. The categories are represented by '##@' and the
+# target descriptions by '##'. The awk commands is responsible for reading the
+# entire set of makefiles included in this invocation, looking for lines of the
+# file as xyz: ## something, and then pretty-format the target and help. Then,
+# if there's a line with ##@ something, that gets pretty-printed as a category.
+# More info on the usage of ANSI control characters for terminal formatting:
+# https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters
+# More info on the awk command:
+# http://linuxcommand.org/lc3_adv_awk.php
+
+.PHONY: help
+help: ## Display this help.
+ @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)
+
+
+.PHONY: build
+build: $(RELEASE_TARGET) $(DEBUG_TARGET) ## Build release and debug binaries
+
+
+.PHONY: clean
+clean: ## Clean build artifacts
+ rm $(RELEASE_TARGET) $(DEBUG_TARGET)
+ rm -rf target
+
+
+.PHONY: release
+release: $(RELEASE_TARGET) ## Build release binary
+$(RELEASE_TARGET): $(ALL_RS)
+ cargo build --release
+ mkdir -p $(@D)
+ cp target/release/lib$(LIB_NAME).so $@
+
+
+.PHONY: debug
+debug: $(DEBUG_TARGET) ## Build binary with debug symbols
+$(DEBUG_TARGET): $(ALL_RS)
+ cargo build
+ mkdir -p $(@D)
+ cp target/debug/lib$(LIB_NAME).so $@
diff --git a/extensions/core/.gitignore b/extensions/core/.gitignore
new file mode 100644
index 000000000..54b02da46
--- /dev/null
+++ b/extensions/core/.gitignore
@@ -0,0 +1,2 @@
+/target
+*.so
diff --git a/extensions/core/Cargo.toml b/extensions/core/Cargo.toml
new file mode 100644
index 000000000..b8123ac73
--- /dev/null
+++ b/extensions/core/Cargo.toml
@@ -0,0 +1,24 @@
+[package]
+name = "opengamepadui-core"
+version = "0.1.0"
+edition = "2021"
+
+[lib]
+crate-type = ["cdylib"] # Compile this crate to a dynamic C library.
+
+[dependencies]
+futures-util = "0.3.30"
+godot = { git = "https://github.com/godot-rust/gdext", branch = "master", features = [
+ "experimental-threads",
+ "register-docs",
+] }
+nix = { version = "0.29.0", features = ["term", "process"] }
+once_cell = "1.20.1"
+tokio = { version = "1.39.3", features = ["full"] }
+zbus = "4.4.0"
+zvariant = "4.2.0"
+gamescope-x11-client = { git = "https://github.com/ShadowBlip/gamescope-x11-client", branch = "main" }
+inotify = "0.11.0"
+byte-unit = "5.1.4"
+log = "0.4.22"
+keyvalues-parser = "0.2.0"
diff --git a/extensions/core/src/bluetooth.rs b/extensions/core/src/bluetooth.rs
new file mode 100644
index 000000000..5447862b1
--- /dev/null
+++ b/extensions/core/src/bluetooth.rs
@@ -0,0 +1 @@
+pub mod bluez;
diff --git a/extensions/core/src/bluetooth/bluez.rs b/extensions/core/src/bluetooth/bluez.rs
new file mode 100644
index 000000000..9cab950d3
--- /dev/null
+++ b/extensions/core/src/bluetooth/bluez.rs
@@ -0,0 +1,386 @@
+pub mod adapter;
+pub mod device;
+
+use std::{
+ collections::HashMap,
+ sync::mpsc::{channel, Receiver, Sender, TryRecvError},
+ time::Duration,
+};
+
+use adapter::BluetoothAdapter;
+use device::BluetoothDevice;
+use futures_util::stream::StreamExt;
+use godot::{classes::Engine, obj::WithBaseField, prelude::*};
+use zbus::fdo::ObjectManagerProxy;
+use zbus::{fdo::ManagedObjects, names::BusName};
+
+use crate::{dbus::RunError, get_dbus_system, get_dbus_system_blocking, RUNTIME};
+
+pub const BLUEZ_BUS: &str = "org.bluez";
+const BLUEZ_MANAGER_PATH: &str = "/";
+
+/// Supported Bluez DBus objects
+#[derive(Debug)]
+enum ObjectType {
+ Unknown,
+ Adapter,
+ Device,
+}
+
+impl ObjectType {
+ /// Returns the object type from the list of implemented interfaces
+ fn from_ifaces(ifaces: Vec) -> Self {
+ if ifaces.contains(&"org.bluez.Device1".to_string()) {
+ Self::Device
+ } else if ifaces.contains(&"org.bluez.Adapter1".to_string()) {
+ Self::Adapter
+ } else {
+ Self::Unknown
+ }
+ }
+}
+
+/// Signals that can be emitted
+#[derive(Debug)]
+enum Signal {
+ Started,
+ Stopped,
+ ObjectAdded { path: String, ifaces: Vec },
+ ObjectRemoved { path: String, ifaces: Vec },
+}
+
+#[derive(GodotClass)]
+#[class(base=Resource)]
+pub struct BluezInstance {
+ base: Base,
+ rx: Receiver,
+ conn: Option,
+ adapters: HashMap>,
+ devices: HashMap>,
+}
+
+#[godot_api]
+impl BluezInstance {
+ /// Emitted when Bluez is detected as running
+ #[signal]
+ fn started();
+
+ /// Emitted when Bluez is detected as stopped
+ #[signal]
+ fn stopped();
+
+ /// Emitted when a new bluetooth adapter is discovered
+ #[signal]
+ fn adapter_added(device: Gd);
+
+ /// Emitted when a bluetooth adapter is removed
+ #[signal]
+ fn adapter_removed(path: GString);
+
+ /// Emitted when a new bluetooth device is discovered
+ #[signal]
+ fn device_added(device: Gd);
+
+ /// Emitted when a bluetooth device is removed
+ #[signal]
+ fn device_removed(path: GString);
+
+ /// Returns true if the Bluez service is currently running
+ #[func]
+ fn is_running(&self) -> bool {
+ let Some(conn) = self.conn.as_ref() else {
+ return false;
+ };
+ let bus = BusName::from_static_str(BLUEZ_BUS).unwrap();
+ let dbus = zbus::blocking::fdo::DBusProxy::new(conn).ok();
+ let Some(dbus) = dbus else {
+ return false;
+ };
+ dbus.name_has_owner(bus.clone()).unwrap_or_default()
+ }
+
+ /// Get managed objects
+ fn get_managed_objects(&self) -> Result {
+ let Some(conn) = self.conn.as_ref() else {
+ return Err(zbus::fdo::Error::Disconnected(
+ "No DBus connection found".into(),
+ ));
+ };
+
+ let bus = BusName::from_static_str(BLUEZ_BUS).unwrap();
+ let object_manager = zbus::blocking::fdo::ObjectManagerProxy::builder(conn)
+ .destination(bus)
+ .ok()
+ .and_then(|builder| builder.path(BLUEZ_MANAGER_PATH).ok())
+ .and_then(|builder| builder.build().ok());
+ let Some(object_manager) = object_manager else {
+ return Ok(ManagedObjects::new());
+ };
+
+ object_manager.get_managed_objects()
+ }
+
+ /// Return a list of currently discovered bluetooth adapters
+ #[func]
+ fn get_adapters(&self) -> Array> {
+ let mut adapters = array![];
+ for adapter in self.adapters.values() {
+ adapters.push(adapter);
+ }
+
+ adapters
+ }
+
+ /// Return a list of currently discovered devices
+ #[func]
+ fn get_discovered_devices(&self) -> Array> {
+ let mut devices = array![];
+ for device in self.devices.values() {
+ devices.push(device);
+ }
+
+ devices
+ }
+
+ /// Process Bluez signals and emit them as Godot signals. This method
+ /// should be called every frame in the "_process" loop of a node.
+ #[func]
+ fn process(&mut self) {
+ // Drain all messages from the channel to process them
+ loop {
+ let signal = match self.rx.try_recv() {
+ Ok(value) => value,
+ Err(e) => match e {
+ TryRecvError::Empty => break,
+ TryRecvError::Disconnected => {
+ log::error!("Backend thread is not running!");
+ return;
+ }
+ },
+ };
+ self.process_signal(signal);
+ }
+
+ // Process signals on child objects
+ for adapter in self.adapters.values_mut() {
+ adapter.bind_mut().process();
+ }
+ for device in self.devices.values_mut() {
+ device.bind_mut().process();
+ }
+ }
+
+ /// Process and dispatch the given signal
+ fn process_signal(&mut self, signal: Signal) {
+ match signal {
+ Signal::Started => {
+ self.base_mut().emit_signal("started", &[]);
+ }
+ Signal::Stopped => {
+ self.base_mut().emit_signal("stopped", &[]);
+ }
+ Signal::ObjectAdded { path, ifaces } => {
+ let obj_type = ObjectType::from_ifaces(ifaces);
+ match obj_type {
+ ObjectType::Unknown => (),
+ ObjectType::Adapter => {
+ let adapter = BluetoothAdapter::new(path.as_str());
+ self.adapters.insert(path, adapter.clone());
+ self.base_mut()
+ .emit_signal("adapter_added", &[adapter.to_variant()]);
+ }
+ ObjectType::Device => {
+ let device = BluetoothDevice::new(path.as_str());
+ self.devices.insert(path, device.clone());
+ self.base_mut()
+ .emit_signal("device_added", &[device.to_variant()]);
+ }
+ }
+ }
+ Signal::ObjectRemoved { path, ifaces } => {
+ let obj_type = ObjectType::from_ifaces(ifaces);
+ match obj_type {
+ ObjectType::Unknown => (),
+ ObjectType::Adapter => {
+ self.adapters.remove(&path);
+ self.base_mut()
+ .emit_signal("adapter_removed", &[path.to_variant()]);
+ }
+ ObjectType::Device => {
+ self.devices.remove(&path);
+ self.base_mut()
+ .emit_signal("device_removed", &[path.to_variant()]);
+ }
+ }
+ }
+ }
+ }
+}
+
+#[godot_api]
+impl IResource for BluezInstance {
+ /// Called upon object initialization in the engine
+ fn init(base: Base) -> Self {
+ log::debug!("Initializing Bluez instance");
+
+ // Create a channel to communicate with the service
+ let (tx, rx) = channel();
+ let conn = get_dbus_system_blocking().ok();
+
+ // Don't run in the editor
+ let engine = Engine::singleton();
+ if engine.is_editor_hint() {
+ return Self {
+ base,
+ rx,
+ conn,
+ adapters: Default::default(),
+ devices: Default::default(),
+ };
+ }
+
+ // Spawn a task using the shared tokio runtime to listen for signals
+ RUNTIME.spawn(async move {
+ if let Err(e) = run(tx).await {
+ log::error!("Failed to run Bluez task: ${e:?}");
+ }
+ });
+
+ // Create a new Bluez instance
+ let mut instance = Self {
+ base,
+ rx,
+ conn,
+ adapters: HashMap::new(),
+ devices: HashMap::new(),
+ };
+
+ // Perform initial object discovery
+ let mut adapters = HashMap::new();
+ let mut devices = HashMap::new();
+ let objects = instance.get_managed_objects().unwrap_or_default();
+ for (path, ifaces) in objects.into_iter() {
+ let path = path.to_string();
+ let ifaces: Vec = ifaces.into_keys().map(|v| v.to_string()).collect();
+ let obj_type = ObjectType::from_ifaces(ifaces);
+
+ match obj_type {
+ ObjectType::Unknown => (),
+ ObjectType::Adapter => {
+ let adapter = BluetoothAdapter::new(path.as_str());
+ adapters.insert(path, adapter);
+ }
+ ObjectType::Device => {
+ let device = BluetoothDevice::new(path.as_str());
+ devices.insert(path, device);
+ }
+ }
+ }
+
+ // Update the discovered objects
+ instance.adapters = adapters;
+ instance.devices = devices;
+
+ instance
+ }
+}
+
+/// Runs Bluez tasks in Tokio to listen for DBus signals and send them
+/// over the given channel so they can be processed during each engine frame.
+async fn run(tx: Sender) -> Result<(), RunError> {
+ log::debug!("Spawning Bluez tasks");
+ // Establish a connection to the system bus
+ let conn = get_dbus_system().await?;
+
+ // Spawn a task to listen for Bluez start/stop
+ let dbus_conn = conn.clone();
+ let signals_tx = tx.clone();
+ RUNTIME.spawn(async move {
+ let bus = BusName::from_static_str(BLUEZ_BUS).unwrap();
+ let mut is_running = {
+ let dbus = zbus::fdo::DBusProxy::new(&dbus_conn).await.ok();
+ let Some(dbus) = dbus else {
+ return;
+ };
+ dbus.name_has_owner(bus.clone()).await.unwrap_or_default()
+ };
+
+ loop {
+ let dbus = zbus::fdo::DBusProxy::new(&dbus_conn).await.ok();
+ let Some(dbus) = dbus else {
+ break;
+ };
+ let running = dbus.name_has_owner(bus.clone()).await.unwrap_or_default();
+ if running != is_running {
+ let signal = if running {
+ Signal::Started
+ } else {
+ Signal::Stopped
+ };
+ if signals_tx.send(signal).is_err() {
+ break;
+ }
+ }
+ is_running = running;
+ tokio::time::sleep(Duration::from_secs(5)).await;
+ }
+ });
+
+ // Get a proxy instance to ObjectManager
+ let bus = BusName::from_static_str(BLUEZ_BUS).unwrap();
+ let object_manager: ObjectManagerProxy = ObjectManagerProxy::builder(&conn)
+ .destination(bus)?
+ .path(BLUEZ_MANAGER_PATH)?
+ .build()
+ .await?;
+
+ // Spawn a task to listen for objects added
+ let mut ifaces_added = object_manager.receive_interfaces_added().await?;
+ let signals_tx = tx.clone();
+ RUNTIME.spawn(async move {
+ while let Some(signal) = ifaces_added.next().await {
+ let args = match signal.args() {
+ Ok(args) => args,
+ Err(e) => {
+ log::warn!("Failed to get signal args: ${e:?}");
+ continue;
+ }
+ };
+
+ let path = args.object_path.to_string();
+ let ifaces = args
+ .interfaces_and_properties
+ .keys()
+ .map(|v| v.to_string())
+ .collect();
+ let signal = Signal::ObjectAdded { path, ifaces };
+ if signals_tx.send(signal).is_err() {
+ break;
+ }
+ }
+ });
+
+ // Spawn a task to listen for objects removed
+ let mut ifaces_removed = object_manager.receive_interfaces_removed().await?;
+ let signals_tx = tx.clone();
+ RUNTIME.spawn(async move {
+ while let Some(signal) = ifaces_removed.next().await {
+ let args = match signal.args() {
+ Ok(args) => args,
+ Err(e) => {
+ log::warn!("Failed to get signal args: ${e:?}");
+ continue;
+ }
+ };
+
+ let path = args.object_path.to_string();
+ let ifaces = args.interfaces.iter().map(|v| v.to_string()).collect();
+ let signal = Signal::ObjectRemoved { path, ifaces };
+ if signals_tx.send(signal).is_err() {
+ break;
+ }
+ }
+ });
+
+ Ok(())
+}
diff --git a/extensions/core/src/bluetooth/bluez/adapter.rs b/extensions/core/src/bluetooth/bluez/adapter.rs
new file mode 100644
index 000000000..87babcedc
--- /dev/null
+++ b/extensions/core/src/bluetooth/bluez/adapter.rs
@@ -0,0 +1,570 @@
+use std::sync::mpsc::{channel, Receiver, Sender, TryRecvError};
+
+use futures_util::StreamExt;
+use godot::obj::WithBaseField;
+use godot::prelude::*;
+
+use godot::classes::{Resource, ResourceLoader};
+use zvariant::ObjectPath;
+
+use crate::dbus::bluez::adapter1::{Adapter1Proxy, Adapter1ProxyBlocking};
+use crate::dbus::RunError;
+use crate::{get_dbus_system, get_dbus_system_blocking, RUNTIME};
+
+use super::device::BluetoothDevice;
+use super::BLUEZ_BUS;
+
+/// Signals that can be emitted
+#[derive(Debug)]
+enum Signal {
+ Discoverable { value: bool },
+ Discovering { value: bool },
+ Pairable { value: bool },
+ Powered { value: bool },
+ PowerState { value: String },
+}
+
+#[derive(GodotClass)]
+#[class(no_init, base=Resource)]
+pub struct BluetoothAdapter {
+ base: Base,
+ rx: Receiver,
+ conn: Option,
+
+ #[allow(dead_code)]
+ #[var(get = get_dbus_path)]
+ dbus_path: GString,
+ #[allow(dead_code)]
+ #[var(get = get_address)]
+ address: GString,
+ #[allow(dead_code)]
+ #[var(get = get_address_type)]
+ address_type: GString,
+ #[allow(dead_code)]
+ #[var(get = get_alias, set = set_alias)]
+ alias: GString,
+ #[allow(dead_code)]
+ #[var(get = get_class)]
+ class: u32,
+ #[allow(dead_code)]
+ #[var(get = get_discoverable, set = set_discoverable)]
+ discoverable: bool,
+ #[allow(dead_code)]
+ #[var(get = get_discoverable_timeout, set = set_discoverable_timeout)]
+ discoverable_timeout: u32,
+ #[allow(dead_code)]
+ #[var(get = get_discovering)]
+ discovering: bool,
+ #[allow(dead_code)]
+ #[var(get = get_experimental_features)]
+ experimental_features: PackedStringArray,
+ #[allow(dead_code)]
+ #[var(get = get_manufacturer)]
+ manufacturer: u16,
+ #[allow(dead_code)]
+ #[var(get = get_modalias)]
+ modalias: GString,
+ #[allow(dead_code)]
+ #[var(get = get_name)]
+ name: GString,
+ #[allow(dead_code)]
+ #[var(get = get_pairable, set = set_pairable)]
+ pairable: bool,
+ #[allow(dead_code)]
+ #[var(get = get_pairable_timeout, set = set_pairable_timeout)]
+ pairable_timeout: u32,
+ #[allow(dead_code)]
+ #[var(get = get_power_state)]
+ power_state: GString,
+ #[allow(dead_code)]
+ #[var(get = get_powered, set = set_powered)]
+ powered: bool,
+ #[allow(dead_code)]
+ #[var(get = get_roles)]
+ roles: PackedStringArray,
+ #[allow(dead_code)]
+ #[var(get = get_uuids)]
+ uuids: PackedStringArray,
+ #[allow(dead_code)]
+ #[var(get = get_version)]
+ version: u8,
+}
+
+#[godot_api]
+impl BluetoothAdapter {
+ #[signal]
+ fn discoverable_changed(value: bool);
+
+ #[signal]
+ fn discovering_changed(value: bool);
+
+ #[signal]
+ fn pairable_changed(value: bool);
+
+ #[signal]
+ fn powered_changed(value: bool);
+
+ #[signal]
+ fn power_state_changed(value: GString);
+
+ /// Create a new [BluetoothAdapter] with the given DBus path
+ pub fn from_path(path: GString) -> Gd {
+ // Create a channel to communicate with the signals task
+ log::debug!("BluetoothAdapter created with path: {path}");
+ let (tx, rx) = channel();
+ let dbus_path = path.clone().into();
+
+ // Spawn a task using the shared tokio runtime to listen for signals
+ RUNTIME.spawn(async move {
+ if let Err(e) = run(tx, dbus_path).await {
+ log::error!("Failed to run DBusDevice task: ${e:?}");
+ }
+ });
+
+ Gd::from_init_fn(|base| {
+ // Create a connection to DBus
+ let conn = get_dbus_system_blocking().ok();
+
+ // Accept a base of type Base and directly forward it.
+ Self {
+ base,
+ rx,
+ conn,
+ dbus_path: path,
+ address: Default::default(),
+ address_type: Default::default(),
+ alias: Default::default(),
+ class: Default::default(),
+ discoverable: Default::default(),
+ discoverable_timeout: Default::default(),
+ discovering: Default::default(),
+ experimental_features: Default::default(),
+ manufacturer: Default::default(),
+ modalias: Default::default(),
+ name: Default::default(),
+ pairable: Default::default(),
+ pairable_timeout: Default::default(),
+ power_state: Default::default(),
+ powered: Default::default(),
+ roles: Default::default(),
+ uuids: Default::default(),
+ version: Default::default(),
+ }
+ })
+ }
+
+ /// Return a proxy instance to the adapter
+ fn get_proxy(&self) -> Option {
+ if let Some(conn) = self.conn.as_ref() {
+ let path: String = self.dbus_path.clone().into();
+ Adapter1ProxyBlocking::builder(conn)
+ .path(path)
+ .ok()
+ .and_then(|builder| builder.build().ok())
+ } else {
+ None
+ }
+ }
+
+ /// Get or create a [BluetoothAdapter] with the given DBus path. If an instance
+ /// already exists with the given path, then it will be loaded from the resource
+ /// cache.
+ pub fn new(path: &str) -> Gd {
+ let res_path = format!("dbus://{BLUEZ_BUS}{path}");
+
+ // Check to see if a resource already exists for this device
+ let mut resource_loader = ResourceLoader::singleton();
+ if resource_loader.exists(res_path.as_str()) {
+ if let Some(res) = resource_loader.load(res_path.as_str()) {
+ log::debug!("Resource already exists with path '{res_path}', loading that instead");
+ let device: Gd = res.cast();
+ device
+ } else {
+ let mut device = BluetoothAdapter::from_path(path.to_string().into());
+ device.take_over_path(res_path.as_str());
+ device
+ }
+ } else {
+ let mut device = BluetoothAdapter::from_path(path.to_string().into());
+ device.take_over_path(res_path.as_str());
+ device
+ }
+ }
+
+ /// Returns the DBus path to the [BluetoothAdapter]
+ #[func]
+ pub fn get_dbus_path(&self) -> GString {
+ self.dbus_path.clone()
+ }
+
+ #[func]
+ pub fn get_address(&self) -> GString {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ proxy.address().unwrap_or_default().into()
+ }
+
+ #[func]
+ pub fn get_address_type(&self) -> GString {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ proxy.address_type().unwrap_or_default().into()
+ }
+
+ #[func]
+ pub fn get_alias(&self) -> GString {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ proxy.alias().unwrap_or_default().into()
+ }
+
+ #[func]
+ pub fn set_alias(&self, value: GString) {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ proxy
+ .set_alias(value.to_string().as_str())
+ .unwrap_or_default()
+ }
+
+ #[func]
+ pub fn get_class(&self) -> u32 {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ proxy.class().unwrap_or_default()
+ }
+
+ #[func]
+ pub fn get_discoverable(&self) -> bool {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ proxy.discoverable().unwrap_or_default()
+ }
+
+ #[func]
+ pub fn set_discoverable(&self, value: bool) {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ proxy.set_discoverable(value).unwrap_or_default()
+ }
+
+ #[func]
+ pub fn get_discoverable_timeout(&self) -> u32 {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ proxy.discoverable_timeout().unwrap_or_default()
+ }
+
+ #[func]
+ pub fn set_discoverable_timeout(&self, value: u32) {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ proxy.set_discoverable_timeout(value).unwrap_or_default()
+ }
+
+ #[func]
+ pub fn get_discovering(&self) -> bool {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ proxy.discovering().unwrap_or_default()
+ }
+
+ #[func]
+ pub fn get_experimental_features(&self) -> PackedStringArray {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ let values: Vec = proxy
+ .experimental_features()
+ .unwrap_or_default()
+ .into_iter()
+ .map(|v| v.to_godot())
+ .collect();
+ values.into()
+ }
+
+ #[func]
+ pub fn get_manufacturer(&self) -> u16 {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ proxy.manufacturer().unwrap_or_default()
+ }
+
+ #[func]
+ pub fn get_modalias(&self) -> GString {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ proxy.modalias().unwrap_or_default().into()
+ }
+
+ #[func]
+ pub fn get_name(&self) -> GString {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ proxy.name().unwrap_or_default().into()
+ }
+
+ #[func]
+ pub fn get_pairable(&self) -> bool {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ proxy.pairable().unwrap_or_default()
+ }
+
+ #[func]
+ pub fn set_pairable(&self, value: bool) {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ proxy.set_pairable(value).unwrap_or_default()
+ }
+
+ #[func]
+ pub fn get_pairable_timeout(&self) -> u32 {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ proxy.pairable_timeout().unwrap_or_default()
+ }
+
+ #[func]
+ pub fn set_pairable_timeout(&self, value: u32) {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ proxy.set_pairable_timeout(value).unwrap_or_default()
+ }
+
+ #[func]
+ pub fn get_power_state(&self) -> GString {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ proxy.power_state().unwrap_or_default().into()
+ }
+
+ #[func]
+ pub fn get_powered(&self) -> bool {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ proxy.powered().unwrap_or_default()
+ }
+
+ #[func]
+ pub fn set_powered(&self, value: bool) {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ proxy.set_powered(value).unwrap_or_default()
+ }
+
+ #[func]
+ pub fn get_roles(&self) -> PackedStringArray {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ let values: Vec = proxy
+ .roles()
+ .unwrap_or_default()
+ .into_iter()
+ .map(|v| v.to_godot())
+ .collect();
+ values.into()
+ }
+
+ #[func]
+ pub fn get_uuids(&self) -> PackedStringArray {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ let values: Vec = proxy
+ .uuids()
+ .unwrap_or_default()
+ .into_iter()
+ .map(|v| v.to_godot())
+ .collect();
+ values.into()
+ }
+
+ #[func]
+ pub fn get_version(&self) -> u8 {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ proxy.version().unwrap_or_default()
+ }
+
+ #[func]
+ pub fn get_discovery_filters(&self) -> PackedStringArray {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ let filters: Vec = proxy
+ .get_discovery_filters()
+ .unwrap_or_default()
+ .into_iter()
+ .map(|v| v.to_godot())
+ .collect();
+ filters.into()
+ }
+
+ #[func]
+ pub fn remove_device(&self, device: Gd) {
+ let Some(proxy) = self.get_proxy() else {
+ return;
+ };
+ let path = device.bind().get_dbus_path().to_string();
+ let path = ObjectPath::try_from(path).unwrap_or_default();
+ proxy.remove_device(&path).unwrap_or_default()
+ }
+
+ #[func]
+ pub fn start_discovery(&self) {
+ let Some(proxy) = self.get_proxy() else {
+ return;
+ };
+ proxy.start_discovery().unwrap_or_default()
+ }
+
+ #[func]
+ pub fn stop_discovery(&self) {
+ let Some(proxy) = self.get_proxy() else {
+ return;
+ };
+ proxy.stop_discovery().unwrap_or_default()
+ }
+
+ /// Dispatches signals
+ pub fn process(&mut self) {
+ // Drain all messages from the channel to process them
+ loop {
+ let signal = match self.rx.try_recv() {
+ Ok(value) => value,
+ Err(e) => match e {
+ TryRecvError::Empty => break,
+ TryRecvError::Disconnected => {
+ log::error!("Backend thread is not running!");
+ return;
+ }
+ },
+ };
+ self.process_signal(signal);
+ }
+ }
+
+ /// Process and dispatch the given signal
+ fn process_signal(&mut self, signal: Signal) {
+ match signal {
+ Signal::Discoverable { value } => {
+ self.base_mut()
+ .emit_signal("discoverable_changed", &[value.to_variant()]);
+ }
+ Signal::Discovering { value } => {
+ self.base_mut()
+ .emit_signal("discovering_changed", &[value.to_variant()]);
+ }
+ Signal::Pairable { value } => {
+ self.base_mut()
+ .emit_signal("pairable_changed", &[value.to_variant()]);
+ }
+ Signal::Powered { value } => {
+ self.base_mut()
+ .emit_signal("powered_changed", &[value.to_variant()]);
+ }
+ Signal::PowerState { value } => {
+ self.base_mut()
+ .emit_signal("power_state_changed", &[value.to_variant()]);
+ }
+ }
+ }
+}
+
+impl Drop for BluetoothAdapter {
+ fn drop(&mut self) {
+ log::trace!("BluetoothAdapter '{}' is being destroyed!", self.dbus_path);
+ }
+}
+
+/// Run the signals task
+async fn run(tx: Sender, path: String) -> Result<(), RunError> {
+ // Establish a connection to the system bus
+ let conn = get_dbus_system().await?;
+ let proxy = Adapter1Proxy::builder(&conn).path(path)?.build().await?;
+
+ let signals_tx = tx.clone();
+ let mut events = proxy.receive_discoverable_changed().await;
+ RUNTIME.spawn(async move {
+ while let Some(event) = events.next().await {
+ let value = event.get().await.unwrap_or_default();
+ let signal = Signal::Discoverable { value };
+ if signals_tx.send(signal).is_err() {
+ break;
+ }
+ }
+ });
+
+ let signals_tx = tx.clone();
+ let mut events = proxy.receive_discovering_changed().await;
+ RUNTIME.spawn(async move {
+ while let Some(event) = events.next().await {
+ let value = event.get().await.unwrap_or_default();
+ let signal = Signal::Discovering { value };
+ if signals_tx.send(signal).is_err() {
+ break;
+ }
+ }
+ });
+
+ let signals_tx = tx.clone();
+ let mut events = proxy.receive_pairable_changed().await;
+ RUNTIME.spawn(async move {
+ while let Some(event) = events.next().await {
+ let value = event.get().await.unwrap_or_default();
+ let signal = Signal::Pairable { value };
+ if signals_tx.send(signal).is_err() {
+ break;
+ }
+ }
+ });
+
+ let signals_tx = tx.clone();
+ let mut events = proxy.receive_powered_changed().await;
+ RUNTIME.spawn(async move {
+ while let Some(event) = events.next().await {
+ let value = event.get().await.unwrap_or_default();
+ let signal = Signal::Powered { value };
+ if signals_tx.send(signal).is_err() {
+ break;
+ }
+ }
+ });
+
+ let signals_tx = tx.clone();
+ let mut events = proxy.receive_power_state_changed().await;
+ RUNTIME.spawn(async move {
+ while let Some(event) = events.next().await {
+ let value = event.get().await.unwrap_or_default();
+ let signal = Signal::PowerState { value };
+ if signals_tx.send(signal).is_err() {
+ break;
+ }
+ }
+ });
+
+ Ok(())
+}
diff --git a/extensions/core/src/bluetooth/bluez/device.rs b/extensions/core/src/bluetooth/bluez/device.rs
new file mode 100644
index 000000000..f317588ad
--- /dev/null
+++ b/extensions/core/src/bluetooth/bluez/device.rs
@@ -0,0 +1,529 @@
+use std::sync::mpsc::{channel, Receiver, Sender, TryRecvError};
+
+use futures_util::StreamExt;
+use godot::prelude::*;
+
+use godot::classes::{Resource, ResourceLoader};
+
+use crate::dbus::bluez::device1::{Device1Proxy, Device1ProxyBlocking};
+use crate::dbus::RunError;
+use crate::{get_dbus_system, get_dbus_system_blocking, RUNTIME};
+
+use super::BLUEZ_BUS;
+
+/// Signals that can be emitted
+#[derive(Debug)]
+enum Signal {
+ Updated,
+ ConnectedChanged { value: bool },
+ PairedChanged { value: bool },
+}
+
+#[derive(GodotClass)]
+#[class(no_init, base=Resource)]
+pub struct BluetoothDevice {
+ base: Base,
+ rx: Receiver,
+ conn: Option,
+
+ #[allow(dead_code)]
+ #[var(get = get_dbus_path)]
+ dbus_path: GString,
+ #[allow(dead_code)]
+ #[var(get = get_adapter)]
+ adapter: GString,
+ #[allow(dead_code)]
+ #[var(get = get_address)]
+ address: GString,
+ #[allow(dead_code)]
+ #[var(get = get_address_type)]
+ address_type: GString,
+ #[allow(dead_code)]
+ #[var(get = get_alias, set = set_alias)]
+ alias: GString,
+ #[allow(dead_code)]
+ #[var(get = get_appearance)]
+ appearance: u16,
+ #[allow(dead_code)]
+ #[var(get = get_blocked, set = set_blocked)]
+ blocked: bool,
+ #[allow(dead_code)]
+ #[var(get = get_bonded)]
+ bonded: bool,
+ #[allow(dead_code)]
+ #[var(get = get_class)]
+ class: u32,
+ #[allow(dead_code)]
+ #[var(get = get_connected)]
+ connected: bool,
+ #[allow(dead_code)]
+ #[var(get = get_icon)]
+ icon: GString,
+ #[allow(dead_code)]
+ #[var(get = get_legacy_pairing)]
+ legacy_pairing: bool,
+ #[allow(dead_code)]
+ #[var(get = get_modalias)]
+ modalias: GString,
+ #[allow(dead_code)]
+ #[var(get = get_name)]
+ name: GString,
+ #[allow(dead_code)]
+ #[var(get = get_paired)]
+ paired: bool,
+ #[allow(dead_code)]
+ #[var(get = get_rssi)]
+ rssi: i16,
+ #[allow(dead_code)]
+ #[var(get = get_services_resolved)]
+ services_resolved: bool,
+ #[allow(dead_code)]
+ #[var(get = get_trusted, set = set_trusted)]
+ trusted: bool,
+ #[allow(dead_code)]
+ #[var(get = get_tx_power)]
+ tx_power: i16,
+ #[allow(dead_code)]
+ #[var(get = get_uuids)]
+ uuids: PackedStringArray,
+ #[allow(dead_code)]
+ #[var(get = get_wake_allowed, set = set_wake_allowed)]
+ wake_allowed: bool,
+}
+
+#[godot_api]
+impl BluetoothDevice {
+ #[signal]
+ fn updated();
+
+ #[signal]
+ fn connected_changed(value: bool);
+
+ #[signal]
+ fn paired_changed(value: bool);
+
+ /// Create a new [BluetoothDevice] with the given DBus path
+ pub fn from_path(path: GString) -> Gd {
+ // Create a channel to communicate with the signals task
+ log::debug!("BluetoothDevice created with path: {path}");
+ let (tx, rx) = channel();
+ let dbus_path = path.clone().into();
+
+ // Spawn a task using the shared tokio runtime to listen for signals
+ RUNTIME.spawn(async move {
+ if let Err(e) = run(tx, dbus_path).await {
+ log::error!("Failed to run BluetoothDevice task: ${e:?}");
+ }
+ });
+
+ Gd::from_init_fn(|base| {
+ // Create a connection to DBus
+ let conn = get_dbus_system_blocking().ok();
+
+ // Accept a base of type Base and directly forward it.
+ Self {
+ base,
+ rx,
+ conn,
+ dbus_path: path,
+ adapter: Default::default(),
+ address: Default::default(),
+ address_type: Default::default(),
+ alias: Default::default(),
+ appearance: Default::default(),
+ blocked: Default::default(),
+ bonded: Default::default(),
+ class: Default::default(),
+ connected: Default::default(),
+ icon: Default::default(),
+ legacy_pairing: Default::default(),
+ modalias: Default::default(),
+ name: Default::default(),
+ paired: Default::default(),
+ rssi: Default::default(),
+ services_resolved: Default::default(),
+ trusted: Default::default(),
+ tx_power: Default::default(),
+ uuids: Default::default(),
+ wake_allowed: Default::default(),
+ }
+ })
+ }
+
+ /// Return a proxy instance to the device
+ fn get_proxy(&self) -> Option {
+ if let Some(conn) = self.conn.as_ref() {
+ let path: String = self.dbus_path.clone().into();
+ Device1ProxyBlocking::builder(conn)
+ .path(path)
+ .ok()
+ .and_then(|builder| builder.build().ok())
+ } else {
+ None
+ }
+ }
+
+ /// Get or create a [BluetoothDevice] with the given DBus path. If an instance
+ /// already exists with the given path, then it will be loaded from the resource
+ /// cache.
+ pub fn new(path: &str) -> Gd {
+ let res_path = format!("dbus://{BLUEZ_BUS}{path}");
+
+ // Check to see if a resource already exists for this device
+ let mut resource_loader = ResourceLoader::singleton();
+ if resource_loader.exists(res_path.as_str()) {
+ if let Some(res) = resource_loader.load(res_path.as_str()) {
+ log::debug!("Resource already exists with path '{res_path}', loading that instead");
+ let device: Gd = res.cast();
+ device
+ } else {
+ let mut device = BluetoothDevice::from_path(path.to_string().into());
+ device.take_over_path(res_path.as_str());
+ device
+ }
+ } else {
+ let mut device = BluetoothDevice::from_path(path.to_string().into());
+ device.take_over_path(res_path.as_str());
+ device
+ }
+ }
+
+ /// Return the DBus path to the device
+ #[func]
+ pub fn get_dbus_path(&self) -> GString {
+ self.dbus_path.clone()
+ }
+
+ #[func]
+ pub fn cancel_pairing(&self) {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ proxy.cancel_pairing().unwrap_or_default()
+ }
+
+ #[func]
+ pub fn connect_to(&self) {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ proxy.connect().unwrap_or_default()
+ }
+
+ #[func]
+ pub fn connect_to_profile(&self, uuid: GString) {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ let uuid = uuid.to_string();
+ proxy.connect_profile(uuid.as_str()).unwrap_or_default()
+ }
+
+ #[func]
+ pub fn disconnect_from(&self) {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ proxy.disconnect().unwrap_or_default()
+ }
+
+ #[func]
+ pub fn disconnect_from_profile(&self, uuid: GString) {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ let uuid = uuid.to_string();
+ proxy.disconnect_profile(uuid.as_str()).unwrap_or_default()
+ }
+
+ #[func]
+ pub fn pair(&self) {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ proxy.pair().unwrap_or_default()
+ }
+
+ #[func]
+ pub fn get_wake_allowed(&self) -> bool {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ proxy.wake_allowed().unwrap_or_default()
+ }
+
+ #[func]
+ pub fn set_wake_allowed(&self, allowed: bool) {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ proxy.set_wake_allowed(allowed).unwrap_or_default()
+ }
+
+ #[func]
+ pub fn get_uuids(&self) -> PackedStringArray {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ let values: Vec = proxy
+ .uuids()
+ .unwrap_or_default()
+ .into_iter()
+ .map(|v| v.to_godot())
+ .collect();
+ values.into()
+ }
+
+ #[func]
+ pub fn get_tx_power(&self) -> i16 {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ proxy.tx_power().unwrap_or_default()
+ }
+
+ #[func]
+ pub fn get_trusted(&self) -> bool {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ proxy.trusted().unwrap_or_default()
+ }
+
+ #[func]
+ pub fn set_trusted(&self, value: bool) {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ proxy.set_trusted(value).unwrap_or_default()
+ }
+
+ #[func]
+ pub fn get_services_resolved(&self) -> bool {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ proxy.services_resolved().unwrap_or_default()
+ }
+
+ #[func]
+ pub fn get_rssi(&self) -> i16 {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ proxy.rssi().unwrap_or_default()
+ }
+
+ #[func]
+ pub fn get_paired(&self) -> bool {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ proxy.paired().unwrap_or_default()
+ }
+
+ #[func]
+ pub fn get_name(&self) -> GString {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ proxy.name().unwrap_or_default().into()
+ }
+
+ #[func]
+ pub fn get_modalias(&self) -> GString {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ proxy.modalias().unwrap_or_default().into()
+ }
+
+ #[func]
+ pub fn get_legacy_pairing(&self) -> bool {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ proxy.legacy_pairing().unwrap_or_default()
+ }
+
+ #[func]
+ pub fn get_icon(&self) -> GString {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ proxy.icon().unwrap_or_default().into()
+ }
+
+ #[func]
+ pub fn get_connected(&self) -> bool {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ proxy.connected().unwrap_or_default()
+ }
+
+ #[func]
+ pub fn get_class(&self) -> u32 {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ proxy.class().unwrap_or_default()
+ }
+
+ #[func]
+ pub fn get_bonded(&self) -> bool {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ proxy.bonded().unwrap_or_default()
+ }
+
+ #[func]
+ pub fn get_blocked(&self) -> bool {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ proxy.blocked().unwrap_or_default()
+ }
+
+ #[func]
+ pub fn set_blocked(&self, value: bool) {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ proxy.set_blocked(value).unwrap_or_default()
+ }
+
+ #[func]
+ pub fn get_appearance(&self) -> u16 {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ proxy.appearance().unwrap_or_default()
+ }
+
+ #[func]
+ pub fn get_alias(&self) -> GString {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ proxy.alias().unwrap_or_default().into()
+ }
+
+ #[func]
+ pub fn set_alias(&self, value: GString) {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ proxy
+ .set_alias(value.to_string().as_str())
+ .unwrap_or_default()
+ }
+
+ #[func]
+ pub fn get_address_type(&self) -> GString {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ proxy.address_type().unwrap_or_default().into()
+ }
+
+ #[func]
+ pub fn get_address(&self) -> GString {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ proxy.address().unwrap_or_default().into()
+ }
+
+ #[func]
+ pub fn get_adapter(&self) -> GString {
+ let Some(proxy) = self.get_proxy() else {
+ return Default::default();
+ };
+ proxy.adapter().unwrap_or_default().to_string().into()
+ }
+
+ /// Dispatches signals
+ pub fn process(&mut self) {
+ // Drain all messages from the channel to process them
+ loop {
+ let signal = match self.rx.try_recv() {
+ Ok(value) => value,
+ Err(e) => match e {
+ TryRecvError::Empty => break,
+ TryRecvError::Disconnected => {
+ log::error!("Backend thread is not running!");
+ return;
+ }
+ },
+ };
+ self.process_signal(signal);
+ }
+ }
+
+ /// Process and dispatch the given signal
+ fn process_signal(&mut self, signal: Signal) {
+ log::trace!("Got signal: {signal:?}");
+ match signal {
+ Signal::Updated => {
+ self.base_mut().emit_signal("updated", &[]);
+ }
+ Signal::ConnectedChanged { value } => {
+ self.base_mut()
+ .emit_signal("connected_changed", &[value.to_variant()]);
+ }
+ Signal::PairedChanged { value } => {
+ self.base_mut()
+ .emit_signal("paired_changed", &[value.to_variant()]);
+ }
+ }
+ }
+}
+
+impl Drop for BluetoothDevice {
+ fn drop(&mut self) {
+ log::trace!("BluetoothDevice '{}' is being destroyed!", self.dbus_path);
+ }
+}
+
+/// Run the signals task
+async fn run(tx: Sender, path: String) -> Result<(), RunError> {
+ // Establish a connection to the system bus
+ let conn = get_dbus_system().await?;
+ let proxy = Device1Proxy::builder(&conn).path(path)?.build().await?;
+
+ let signals_tx = tx.clone();
+ let mut events = proxy.receive_connected_changed().await;
+ RUNTIME.spawn(async move {
+ while let Some(event) = events.next().await {
+ let value = event.get().await.unwrap_or_default();
+ let signal = Signal::ConnectedChanged { value };
+ if signals_tx.send(signal).is_err() {
+ break;
+ }
+ let signal = Signal::Updated;
+ if signals_tx.send(signal).is_err() {
+ break;
+ }
+ }
+ });
+
+ let signals_tx = tx.clone();
+ let mut events = proxy.receive_paired_changed().await;
+ RUNTIME.spawn(async move {
+ while let Some(event) = events.next().await {
+ let value = event.get().await.unwrap_or_default();
+ let signal = Signal::PairedChanged { value };
+ if signals_tx.send(signal).is_err() {
+ break;
+ }
+ let signal = Signal::Updated;
+ if signals_tx.send(signal).is_err() {
+ break;
+ }
+ }
+ });
+
+ Ok(())
+}
diff --git a/extensions/core/src/dbus.rs b/extensions/core/src/dbus.rs
new file mode 100644
index 000000000..900750538
--- /dev/null
+++ b/extensions/core/src/dbus.rs
@@ -0,0 +1,164 @@
+use godot::prelude::*;
+use zvariant::NoneValue;
+
+pub mod bluez;
+pub mod inputplumber;
+pub mod networkmanager;
+pub mod powerstation;
+pub mod udisks2;
+pub mod upower;
+
+/// Possible DBus runtime errors
+#[derive(Debug)]
+pub enum RunError {
+ Zbus(zbus::Error),
+ ZbusFdo(zbus::fdo::Error),
+}
+
+impl From for RunError {
+ fn from(value: zbus::Error) -> Self {
+ RunError::Zbus(value)
+ }
+}
+
+impl From for RunError {
+ fn from(value: zbus::fdo::Error) -> Self {
+ RunError::ZbusFdo(value)
+ }
+}
+
+/// Interface for converting DBus types -> Godot types
+pub trait GodotVariant {
+ fn as_godot_variant(&self) -> Option;
+}
+
+impl GodotVariant for zvariant::OwnedValue {
+ /// Convert the DBus variant type into a Godot variant type
+ fn as_godot_variant(&self) -> Option {
+ let value = zvariant::Value::try_from(self).ok()?;
+ value.as_godot_variant()
+ }
+}
+
+impl<'a> GodotVariant for zvariant::Value<'a> {
+ /// Convert the DBus variant type into a Godot variant type
+ fn as_godot_variant(&self) -> Option {
+ match self {
+ zvariant::Value::U8(value) => Some(value.to_variant()),
+ zvariant::Value::Bool(value) => Some(value.to_variant()),
+ zvariant::Value::I16(value) => Some(value.to_variant()),
+ zvariant::Value::U16(value) => Some(value.to_variant()),
+ zvariant::Value::I32(value) => Some(value.to_variant()),
+ zvariant::Value::U32(value) => Some(value.to_variant()),
+ zvariant::Value::I64(value) => Some(value.to_variant()),
+ zvariant::Value::U64(value) => Some(value.to_variant()),
+ zvariant::Value::F64(value) => Some(value.to_variant()),
+ zvariant::Value::Str(value) => Some(value.to_string().to_variant()),
+ zvariant::Value::Signature(_) => None,
+ zvariant::Value::ObjectPath(value) => Some(value.to_string().to_variant()),
+ zvariant::Value::Value(_) => None,
+ zvariant::Value::Array(value) => {
+ let mut arr = array![];
+ for item in value.iter() {
+ let Some(variant) = item.as_godot_variant() else {
+ continue;
+ };
+ arr.push(&variant);
+ }
+
+ Some(arr.to_variant())
+ }
+ zvariant::Value::Dict(value) => {
+ let mut dict = Dictionary::new();
+ for (key, val) in value.iter() {
+ let Some(key) = key.as_godot_variant() else {
+ continue;
+ };
+ let Some(val) = val.as_godot_variant() else {
+ continue;
+ };
+ dict.set(key, val);
+ }
+
+ Some(dict.to_variant())
+ }
+ zvariant::Value::Structure(_) => None,
+ zvariant::Value::Fd(_) => None,
+ }
+ }
+}
+
+/// Interface for converting Godot types -> DBus types
+pub trait DBusVariant {
+ fn as_zvariant(&self) -> Option;
+}
+
+impl DBusVariant for Variant {
+ /// Convert the Godot variant type into a DBus variant type
+ fn as_zvariant(&self) -> Option {
+ match self.get_type() {
+ VariantType::NIL => {
+ let value = zvariant::Optional::<&str>::null_value();
+ Some(zvariant::Value::new(value))
+ }
+ VariantType::BOOL => {
+ let value: bool = self.to();
+ Some(zvariant::Value::new(value))
+ }
+ VariantType::INT => {
+ let value: i64 = self.to();
+ Some(zvariant::Value::new(value))
+ }
+ VariantType::FLOAT => {
+ let value: f64 = self.to();
+ Some(zvariant::Value::new(value))
+ }
+ VariantType::STRING => {
+ let value: GString = self.to();
+ let value: String = value.into();
+ Some(zvariant::Value::new(value))
+ }
+ VariantType::VECTOR2 => None,
+ VariantType::VECTOR2I => None,
+ VariantType::RECT2 => None,
+ VariantType::RECT2I => None,
+ VariantType::VECTOR3 => None,
+ VariantType::VECTOR3I => None,
+ VariantType::TRANSFORM2D => None,
+ VariantType::VECTOR4 => None,
+ VariantType::VECTOR4I => None,
+ VariantType::PLANE => None,
+ VariantType::QUATERNION => None,
+ VariantType::AABB => None,
+ VariantType::BASIS => None,
+ VariantType::TRANSFORM3D => None,
+ VariantType::PROJECTION => None,
+ VariantType::COLOR => None,
+ VariantType::STRING_NAME => None,
+ VariantType::NODE_PATH => None,
+ VariantType::RID => {
+ let value: i64 = self.to();
+ Some(zvariant::Value::new(value))
+ }
+ VariantType::OBJECT => None,
+ VariantType::CALLABLE => None,
+ VariantType::SIGNAL => None,
+ VariantType::DICTIONARY => None,
+ VariantType::ARRAY => None,
+ VariantType::PACKED_BYTE_ARRAY => None,
+ VariantType::PACKED_INT32_ARRAY => None,
+ VariantType::PACKED_INT64_ARRAY => None,
+ VariantType::PACKED_FLOAT32_ARRAY => None,
+ VariantType::PACKED_FLOAT64_ARRAY => None,
+ VariantType::PACKED_STRING_ARRAY => None,
+ VariantType::PACKED_VECTOR2_ARRAY => None,
+ VariantType::PACKED_VECTOR3_ARRAY => None,
+ VariantType::PACKED_COLOR_ARRAY => None,
+ VariantType::PACKED_VECTOR4_ARRAY => None,
+ VariantType::MAX => None,
+
+ // Unsupported conversion
+ _ => None,
+ }
+ }
+}
diff --git a/extensions/core/src/dbus/bluez.rs b/extensions/core/src/dbus/bluez.rs
new file mode 100644
index 000000000..bce2e071b
--- /dev/null
+++ b/extensions/core/src/dbus/bluez.rs
@@ -0,0 +1,8 @@
+pub mod adapter1;
+pub mod battery_provider_manager1;
+pub mod device1;
+pub mod gatt_manager1;
+pub mod leadvertising_manager1;
+pub mod media1;
+pub mod media_control1;
+pub mod network_server1;
diff --git a/extensions/core/src/dbus/bluez/adapter1.rs b/extensions/core/src/dbus/bluez/adapter1.rs
new file mode 100644
index 000000000..79e76a192
--- /dev/null
+++ b/extensions/core/src/dbus/bluez/adapter1.rs
@@ -0,0 +1,129 @@
+//! # D-Bus interface proxy for: `org.bluez.Adapter1`
+//!
+//! This code was generated by `zbus-xmlgen` `4.1.0` from D-Bus introspection data.
+//! Source: `Interface '/org/bluez/hci0' from service 'org.bluez' on system bus`.
+//!
+//! You may prefer to adapt it, instead of using it verbatim.
+//!
+//! More information can be found in the [Writing a client proxy] section of the zbus
+//! documentation.
+//!
+//! This type implements the [D-Bus standard interfaces], (`org.freedesktop.DBus.*`) for which the
+//! following zbus API can be used:
+//!
+//! * [`zbus::fdo::IntrospectableProxy`]
+//! * [`zbus::fdo::PropertiesProxy`]
+//!
+//! Consequently `zbus-xmlgen` did not generate code for the above interfaces.
+//!
+//! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html
+//! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces,
+use zbus::proxy;
+#[proxy(
+ interface = "org.bluez.Adapter1",
+ default_service = "org.bluez",
+ default_path = "/org/bluez/hci0"
+)]
+trait Adapter1 {
+ /// GetDiscoveryFilters method
+ fn get_discovery_filters(&self) -> zbus::Result>;
+
+ /// RemoveDevice method
+ fn remove_device(&self, device: &zbus::zvariant::ObjectPath<'_>) -> zbus::Result<()>;
+
+ /// SetDiscoveryFilter method
+ fn set_discovery_filter(
+ &self,
+ properties: std::collections::HashMap<&str, &zbus::zvariant::Value<'_>>,
+ ) -> zbus::Result<()>;
+
+ /// StartDiscovery method
+ fn start_discovery(&self) -> zbus::Result<()>;
+
+ /// StopDiscovery method
+ fn stop_discovery(&self) -> zbus::Result<()>;
+
+ /// Address property
+ #[zbus(property)]
+ fn address(&self) -> zbus::Result;
+
+ /// AddressType property
+ #[zbus(property)]
+ fn address_type(&self) -> zbus::Result;
+
+ /// Alias property
+ #[zbus(property)]
+ fn alias(&self) -> zbus::Result;
+ #[zbus(property)]
+ fn set_alias(&self, value: &str) -> zbus::Result<()>;
+
+ /// Class property
+ #[zbus(property)]
+ fn class(&self) -> zbus::Result;
+
+ /// Discoverable property
+ #[zbus(property)]
+ fn discoverable(&self) -> zbus::Result;
+ #[zbus(property)]
+ fn set_discoverable(&self, value: bool) -> zbus::Result<()>;
+
+ /// DiscoverableTimeout property
+ #[zbus(property)]
+ fn discoverable_timeout(&self) -> zbus::Result;
+ #[zbus(property)]
+ fn set_discoverable_timeout(&self, value: u32) -> zbus::Result<()>;
+
+ /// Discovering property
+ #[zbus(property)]
+ fn discovering(&self) -> zbus::Result;
+
+ /// ExperimentalFeatures property
+ #[zbus(property)]
+ fn experimental_features(&self) -> zbus::Result>;
+
+ /// Manufacturer property
+ #[zbus(property)]
+ fn manufacturer(&self) -> zbus::Result;
+
+ /// Modalias property
+ #[zbus(property)]
+ fn modalias(&self) -> zbus::Result;
+
+ /// Name property
+ #[zbus(property)]
+ fn name(&self) -> zbus::Result;
+
+ /// Pairable property
+ #[zbus(property)]
+ fn pairable(&self) -> zbus::Result;
+ #[zbus(property)]
+ fn set_pairable(&self, value: bool) -> zbus::Result<()>;
+
+ /// PairableTimeout property
+ #[zbus(property)]
+ fn pairable_timeout(&self) -> zbus::Result;
+ #[zbus(property)]
+ fn set_pairable_timeout(&self, value: u32) -> zbus::Result<()>;
+
+ /// PowerState property
+ #[zbus(property)]
+ fn power_state(&self) -> zbus::Result;
+
+ /// Powered property
+ #[zbus(property)]
+ fn powered(&self) -> zbus::Result;
+ #[zbus(property)]
+ fn set_powered(&self, value: bool) -> zbus::Result<()>;
+
+ /// Roles property
+ #[zbus(property)]
+ fn roles(&self) -> zbus::Result>;
+
+ /// UUIDs property
+ #[zbus(property, name = "UUIDs")]
+ fn uuids(&self) -> zbus::Result>;
+
+ /// Version property
+ #[zbus(property)]
+ fn version(&self) -> zbus::Result;
+}
diff --git a/extensions/core/src/dbus/bluez/battery_provider_manager1.rs b/extensions/core/src/dbus/bluez/battery_provider_manager1.rs
new file mode 100644
index 000000000..c47ac8f73
--- /dev/null
+++ b/extensions/core/src/dbus/bluez/battery_provider_manager1.rs
@@ -0,0 +1,39 @@
+//! # D-Bus interface proxy for: `org.bluez.BatteryProviderManager1`
+//!
+//! This code was generated by `zbus-xmlgen` `4.1.0` from D-Bus introspection data.
+//! Source: `Interface '/org/bluez/hci0' from service 'org.bluez' on system bus`.
+//!
+//! You may prefer to adapt it, instead of using it verbatim.
+//!
+//! More information can be found in the [Writing a client proxy] section of the zbus
+//! documentation.
+//!
+//! This type implements the [D-Bus standard interfaces], (`org.freedesktop.DBus.*`) for which the
+//! following zbus API can be used:
+//!
+//! * [`zbus::fdo::IntrospectableProxy`]
+//! * [`zbus::fdo::PropertiesProxy`]
+//!
+//! Consequently `zbus-xmlgen` did not generate code for the above interfaces.
+//!
+//! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html
+//! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces,
+use zbus::proxy;
+#[proxy(
+ interface = "org.bluez.BatteryProviderManager1",
+ default_service = "org.bluez",
+ default_path = "/org/bluez/hci0"
+)]
+trait BatteryProviderManager1 {
+ /// RegisterBatteryProvider method
+ fn register_battery_provider(
+ &self,
+ provider: &zbus::zvariant::ObjectPath<'_>,
+ ) -> zbus::Result<()>;
+
+ /// UnregisterBatteryProvider method
+ fn unregister_battery_provider(
+ &self,
+ provider: &zbus::zvariant::ObjectPath<'_>,
+ ) -> zbus::Result<()>;
+}
diff --git a/extensions/core/src/dbus/bluez/device1.rs b/extensions/core/src/dbus/bluez/device1.rs
new file mode 100644
index 000000000..1006f9c64
--- /dev/null
+++ b/extensions/core/src/dbus/bluez/device1.rs
@@ -0,0 +1,154 @@
+//! # D-Bus interface proxy for: `org.bluez.Device1`
+//!
+//! This code was generated by `zbus-xmlgen` `4.1.0` from D-Bus introspection data.
+//! Source: `Interface '/org/bluez/hci0/dev_XX...' from service 'org.bluez' on system bus`.
+//!
+//! You may prefer to adapt it, instead of using it verbatim.
+//!
+//! More information can be found in the [Writing a client proxy] section of the zbus
+//! documentation.
+//!
+//! This type implements the [D-Bus standard interfaces], (`org.freedesktop.DBus.*`) for which the
+//! following zbus API can be used:
+//!
+//! * [`zbus::fdo::IntrospectableProxy`]
+//! * [`zbus::fdo::PropertiesProxy`]
+//!
+//! Consequently `zbus-xmlgen` did not generate code for the above interfaces.
+//!
+//! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html
+//! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces,
+use zbus::proxy;
+#[proxy(interface = "org.bluez.Device1", default_service = "org.bluez")]
+trait Device1 {
+ /// CancelPairing method
+ fn cancel_pairing(&self) -> zbus::Result<()>;
+
+ /// Connect method
+ fn connect(&self) -> zbus::Result<()>;
+
+ /// ConnectProfile method
+ #[allow(non_snake_case)]
+ fn connect_profile(&self, UUID: &str) -> zbus::Result<()>;
+
+ /// Disconnect method
+ fn disconnect(&self) -> zbus::Result<()>;
+
+ /// DisconnectProfile method
+ #[allow(non_snake_case)]
+ fn disconnect_profile(&self, UUID: &str) -> zbus::Result<()>;
+
+ /// Pair method
+ fn pair(&self) -> zbus::Result<()>;
+
+ /// Adapter property
+ #[zbus(property)]
+ fn adapter(&self) -> zbus::Result;
+
+ /// Address property
+ #[zbus(property)]
+ fn address(&self) -> zbus::Result;
+
+ /// AddressType property
+ #[zbus(property)]
+ fn address_type(&self) -> zbus::Result;
+
+ /// Alias property
+ #[zbus(property)]
+ fn alias(&self) -> zbus::Result;
+ #[zbus(property)]
+ fn set_alias(&self, value: &str) -> zbus::Result<()>;
+
+ /// Appearance property
+ #[zbus(property)]
+ fn appearance(&self) -> zbus::Result;
+
+ /// Blocked property
+ #[zbus(property)]
+ fn blocked(&self) -> zbus::Result;
+ #[zbus(property)]
+ fn set_blocked(&self, value: bool) -> zbus::Result<()>;
+
+ /// Bonded property
+ #[zbus(property)]
+ fn bonded(&self) -> zbus::Result;
+
+ /// Class property
+ #[zbus(property)]
+ fn class(&self) -> zbus::Result;
+
+ /// Connected property
+ #[zbus(property)]
+ fn connected(&self) -> zbus::Result;
+
+ /// Icon property
+ #[zbus(property)]
+ fn icon(&self) -> zbus::Result;
+
+ /// LegacyPairing property
+ #[zbus(property)]
+ fn legacy_pairing(&self) -> zbus::Result;
+
+ /// ManufacturerData property
+ #[zbus(property)]
+ fn manufacturer_data(
+ &self,
+ ) -> zbus::Result>;
+
+ /// Modalias property
+ #[zbus(property)]
+ fn modalias(&self) -> zbus::Result;
+
+ /// Name property
+ #[zbus(property)]
+ fn name(&self) -> zbus::Result;
+
+ /// Paired property
+ #[zbus(property)]
+ fn paired(&self) -> zbus::Result;
+
+ /// RSSI property
+ #[zbus(property, name = "RSSI")]
+ fn rssi(&self) -> zbus::Result;
+
+ /// ServiceData property
+ #[zbus(property)]
+ fn service_data(
+ &self,
+ ) -> zbus::Result>;
+
+ /// ServicesResolved property
+ #[zbus(property)]
+ fn services_resolved(&self) -> zbus::Result;
+
+ /// Sets property
+ #[zbus(property)]
+ fn sets(
+ &self,
+ ) -> zbus::Result<
+ std::collections::HashMap<
+ zbus::zvariant::OwnedObjectPath,
+ std::collections::HashMap,
+ >,
+ >;
+
+ /// Trusted property
+ #[zbus(property)]
+ fn trusted(&self) -> zbus::Result;
+ #[zbus(property)]
+ fn set_trusted(&self, value: bool) -> zbus::Result<()>;
+
+ /// TxPower property
+ #[zbus(property)]
+ fn tx_power(&self) -> zbus::Result;
+
+ /// UUIDs property
+ #[zbus(property, name = "UUIDs")]
+ fn uuids(&self) -> zbus::Result>;
+
+ /// WakeAllowed property
+ #[zbus(property)]
+ fn wake_allowed(&self) -> zbus::Result;
+ #[zbus(property)]
+ fn set_wake_allowed(&self, value: bool) -> zbus::Result<()>;
+}
diff --git a/extensions/core/src/dbus/bluez/gatt_manager1.rs b/extensions/core/src/dbus/bluez/gatt_manager1.rs
new file mode 100644
index 000000000..bf0153d70
--- /dev/null
+++ b/extensions/core/src/dbus/bluez/gatt_manager1.rs
@@ -0,0 +1,40 @@
+//! # D-Bus interface proxy for: `org.bluez.GattManager1`
+//!
+//! This code was generated by `zbus-xmlgen` `4.1.0` from D-Bus introspection data.
+//! Source: `Interface '/org/bluez/hci0' from service 'org.bluez' on system bus`.
+//!
+//! You may prefer to adapt it, instead of using it verbatim.
+//!
+//! More information can be found in the [Writing a client proxy] section of the zbus
+//! documentation.
+//!
+//! This type implements the [D-Bus standard interfaces], (`org.freedesktop.DBus.*`) for which the
+//! following zbus API can be used:
+//!
+//! * [`zbus::fdo::IntrospectableProxy`]
+//! * [`zbus::fdo::PropertiesProxy`]
+//!
+//! Consequently `zbus-xmlgen` did not generate code for the above interfaces.
+//!
+//! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html
+//! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces,
+use zbus::proxy;
+#[proxy(
+ interface = "org.bluez.GattManager1",
+ default_service = "org.bluez",
+ default_path = "/org/bluez/hci0"
+)]
+trait GattManager1 {
+ /// RegisterApplication method
+ fn register_application(
+ &self,
+ application: &zbus::zvariant::ObjectPath<'_>,
+ options: std::collections::HashMap<&str, &zbus::zvariant::Value<'_>>,
+ ) -> zbus::Result<()>;
+
+ /// UnregisterApplication method
+ fn unregister_application(
+ &self,
+ application: &zbus::zvariant::ObjectPath<'_>,
+ ) -> zbus::Result<()>;
+}
diff --git a/extensions/core/src/dbus/bluez/leadvertising_manager1.rs b/extensions/core/src/dbus/bluez/leadvertising_manager1.rs
new file mode 100644
index 000000000..da3ddbb64
--- /dev/null
+++ b/extensions/core/src/dbus/bluez/leadvertising_manager1.rs
@@ -0,0 +1,56 @@
+//! # D-Bus interface proxy for: `org.bluez.LEAdvertisingManager1`
+//!
+//! This code was generated by `zbus-xmlgen` `4.1.0` from D-Bus introspection data.
+//! Source: `Interface '/org/bluez/hci0' from service 'org.bluez' on system bus`.
+//!
+//! You may prefer to adapt it, instead of using it verbatim.
+//!
+//! More information can be found in the [Writing a client proxy] section of the zbus
+//! documentation.
+//!
+//! This type implements the [D-Bus standard interfaces], (`org.freedesktop.DBus.*`) for which the
+//! following zbus API can be used:
+//!
+//! * [`zbus::fdo::IntrospectableProxy`]
+//! * [`zbus::fdo::PropertiesProxy`]
+//!
+//! Consequently `zbus-xmlgen` did not generate code for the above interfaces.
+//!
+//! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html
+//! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces,
+use zbus::proxy;
+#[proxy(
+ interface = "org.bluez.LEAdvertisingManager1",
+ default_service = "org.bluez",
+ default_path = "/org/bluez/hci0"
+)]
+trait LEAdvertisingManager1 {
+ /// RegisterAdvertisement method
+ fn register_advertisement(
+ &self,
+ advertisement: &zbus::zvariant::ObjectPath<'_>,
+ options: std::collections::HashMap<&str, &zbus::zvariant::Value<'_>>,
+ ) -> zbus::Result<()>;
+
+ /// UnregisterAdvertisement method
+ fn unregister_advertisement(
+ &self,
+ service: &zbus::zvariant::ObjectPath<'_>,
+ ) -> zbus::Result<()>;
+
+ /// ActiveInstances property
+ #[zbus(property)]
+ fn active_instances(&self) -> zbus::Result;
+
+ /// SupportedIncludes property
+ #[zbus(property)]
+ fn supported_includes(&self) -> zbus::Result>;
+
+ /// SupportedInstances property
+ #[zbus(property)]
+ fn supported_instances(&self) -> zbus::Result;
+
+ /// SupportedSecondaryChannels property
+ #[zbus(property)]
+ fn supported_secondary_channels(&self) -> zbus::Result>;
+}
diff --git a/extensions/core/src/dbus/bluez/media1.rs b/extensions/core/src/dbus/bluez/media1.rs
new file mode 100644
index 000000000..ba0456865
--- /dev/null
+++ b/extensions/core/src/dbus/bluez/media1.rs
@@ -0,0 +1,64 @@
+//! # D-Bus interface proxy for: `org.bluez.Media1`
+//!
+//! This code was generated by `zbus-xmlgen` `4.1.0` from D-Bus introspection data.
+//! Source: `Interface '/org/bluez/hci0' from service 'org.bluez' on system bus`.
+//!
+//! You may prefer to adapt it, instead of using it verbatim.
+//!
+//! More information can be found in the [Writing a client proxy] section of the zbus
+//! documentation.
+//!
+//! This type implements the [D-Bus standard interfaces], (`org.freedesktop.DBus.*`) for which the
+//! following zbus API can be used:
+//!
+//! * [`zbus::fdo::IntrospectableProxy`]
+//! * [`zbus::fdo::PropertiesProxy`]
+//!
+//! Consequently `zbus-xmlgen` did not generate code for the above interfaces.
+//!
+//! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html
+//! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces,
+use zbus::proxy;
+#[proxy(
+ interface = "org.bluez.Media1",
+ default_service = "org.bluez",
+ default_path = "/org/bluez/hci0"
+)]
+trait Media1 {
+ /// RegisterApplication method
+ fn register_application(
+ &self,
+ application: &zbus::zvariant::ObjectPath<'_>,
+ options: std::collections::HashMap<&str, &zbus::zvariant::Value<'_>>,
+ ) -> zbus::Result<()>;
+
+ /// RegisterEndpoint method
+ fn register_endpoint(
+ &self,
+ endpoint: &zbus::zvariant::ObjectPath<'_>,
+ properties: std::collections::HashMap<&str, &zbus::zvariant::Value<'_>>,
+ ) -> zbus::Result<()>;
+
+ /// RegisterPlayer method
+ fn register_player(
+ &self,
+ player: &zbus::zvariant::ObjectPath<'_>,
+ properties: std::collections::HashMap<&str, &zbus::zvariant::Value<'_>>,
+ ) -> zbus::Result<()>;
+
+ /// UnregisterApplication method
+ fn unregister_application(
+ &self,
+ application: &zbus::zvariant::ObjectPath<'_>,
+ ) -> zbus::Result<()>;
+
+ /// UnregisterEndpoint method
+ fn unregister_endpoint(&self, endpoint: &zbus::zvariant::ObjectPath<'_>) -> zbus::Result<()>;
+
+ /// UnregisterPlayer method
+ fn unregister_player(&self, player: &zbus::zvariant::ObjectPath<'_>) -> zbus::Result<()>;
+
+ /// SupportedUUIDs property
+ #[zbus(property, name = "SupportedUUIDs")]
+ fn supported_uuids(&self) -> zbus::Result>;
+}
diff --git a/extensions/core/src/dbus/bluez/media_control1.rs b/extensions/core/src/dbus/bluez/media_control1.rs
new file mode 100644
index 000000000..77583bff7
--- /dev/null
+++ b/extensions/core/src/dbus/bluez/media_control1.rs
@@ -0,0 +1,58 @@
+//! # D-Bus interface proxy for: `org.bluez.MediaControl1`
+//!
+//! This code was generated by `zbus-xmlgen` `4.1.0` from D-Bus introspection data.
+//! Source: `Interface '/org/bluez/hci0/dev_XX...' from service 'org.bluez' on system bus`.
+//!
+//! You may prefer to adapt it, instead of using it verbatim.
+//!
+//! More information can be found in the [Writing a client proxy] section of the zbus
+//! documentation.
+//!
+//! This type implements the [D-Bus standard interfaces], (`org.freedesktop.DBus.*`) for which the
+//! following zbus API can be used:
+//!
+//! * [`zbus::fdo::IntrospectableProxy`]
+//! * [`zbus::fdo::PropertiesProxy`]
+//!
+//! Consequently `zbus-xmlgen` did not generate code for the above interfaces.
+//!
+//! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html
+//! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces,
+use zbus::proxy;
+#[proxy(interface = "org.bluez.MediaControl1", default_service = "org.bluez")]
+trait MediaControl1 {
+ /// FastForward method
+ fn fast_forward(&self) -> zbus::Result<()>;
+
+ /// Next method
+ fn next(&self) -> zbus::Result<()>;
+
+ /// Pause method
+ fn pause(&self) -> zbus::Result<()>;
+
+ /// Play method
+ fn play(&self) -> zbus::Result<()>;
+
+ /// Previous method
+ fn previous(&self) -> zbus::Result<()>;
+
+ /// Rewind method
+ fn rewind(&self) -> zbus::Result<()>;
+
+ /// Stop method
+ fn stop(&self) -> zbus::Result<()>;
+
+ /// VolumeDown method
+ fn volume_down(&self) -> zbus::Result<()>;
+
+ /// VolumeUp method
+ fn volume_up(&self) -> zbus::Result<()>;
+
+ /// Connected property
+ #[zbus(property)]
+ fn connected(&self) -> zbus::Result;
+
+ /// Player property
+ #[zbus(property)]
+ fn player(&self) -> zbus::Result;
+}
diff --git a/extensions/core/src/dbus/bluez/network_server1.rs b/extensions/core/src/dbus/bluez/network_server1.rs
new file mode 100644
index 000000000..22a9f13ab
--- /dev/null
+++ b/extensions/core/src/dbus/bluez/network_server1.rs
@@ -0,0 +1,33 @@
+//! # D-Bus interface proxy for: `org.bluez.NetworkServer1`
+//!
+//! This code was generated by `zbus-xmlgen` `4.1.0` from D-Bus introspection data.
+//! Source: `Interface '/org/bluez/hci0' from service 'org.bluez' on system bus`.
+//!
+//! You may prefer to adapt it, instead of using it verbatim.
+//!
+//! More information can be found in the [Writing a client proxy] section of the zbus
+//! documentation.
+//!
+//! This type implements the [D-Bus standard interfaces], (`org.freedesktop.DBus.*`) for which the
+//! following zbus API can be used:
+//!
+//! * [`zbus::fdo::IntrospectableProxy`]
+//! * [`zbus::fdo::PropertiesProxy`]
+//!
+//! Consequently `zbus-xmlgen` did not generate code for the above interfaces.
+//!
+//! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html
+//! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces,
+use zbus::proxy;
+#[proxy(
+ interface = "org.bluez.NetworkServer1",
+ default_service = "org.bluez",
+ default_path = "/org/bluez/hci0"
+)]
+trait NetworkServer1 {
+ /// Register method
+ fn register(&self, uuid: &str, bridge: &str) -> zbus::Result<()>;
+
+ /// Unregister method
+ fn unregister(&self, uuid: &str) -> zbus::Result<()>;
+}
diff --git a/extensions/core/src/dbus/inputplumber.rs b/extensions/core/src/dbus/inputplumber.rs
new file mode 100644
index 000000000..e722fce81
--- /dev/null
+++ b/extensions/core/src/dbus/inputplumber.rs
@@ -0,0 +1,6 @@
+pub mod composite_device;
+pub mod dbus_device;
+pub mod event_device;
+pub mod input_manager;
+pub mod keyboard;
+pub mod mouse;
diff --git a/extensions/core/src/dbus/inputplumber/composite_device.rs b/extensions/core/src/dbus/inputplumber/composite_device.rs
new file mode 100644
index 000000000..bfb9ea4b8
--- /dev/null
+++ b/extensions/core/src/dbus/inputplumber/composite_device.rs
@@ -0,0 +1,87 @@
+//! # D-Bus interface proxy for: `org.shadowblip.Input.CompositeDevice`
+//!
+//! This code was generated by `zbus-xmlgen` `4.1.0` from D-Bus introspection data.
+//! Source: `Interface '/org/shadowblip/InputPlumber/CompositeDevice0' from service 'org.shadowblip.InputPlumber' on system bus`.
+//!
+//! You may prefer to adapt it, instead of using it verbatim.
+//!
+//! More information can be found in the [Writing a client proxy] section of the zbus
+//! documentation.
+//!
+//! This type implements the [D-Bus standard interfaces], (`org.freedesktop.DBus.*`) for which the
+//! following zbus API can be used:
+//!
+//! * [`zbus::fdo::PeerProxy`]
+//! * [`zbus::fdo::PropertiesProxy`]
+//! * [`zbus::fdo::IntrospectableProxy`]
+//!
+//! Consequently `zbus-xmlgen` did not generate code for the above interfaces.
+//!
+//! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html
+//! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces,
+use zbus::proxy;
+#[proxy(
+ interface = "org.shadowblip.Input.CompositeDevice",
+ default_service = "org.shadowblip.InputPlumber",
+ default_path = "/org/shadowblip/InputPlumber/CompositeDevice0"
+)]
+trait CompositeDevice {
+ /// LoadProfileFromYaml method
+ fn load_profile_from_yaml(&self, profile: &str) -> zbus::Result<()>;
+
+ /// LoadProfilePath method
+ fn load_profile_path(&self, path: &str) -> zbus::Result<()>;
+
+ /// SendButtonChord method
+ fn send_button_chord(&self, events: &[&str]) -> zbus::Result<()>;
+
+ /// SendEvent method
+ fn send_event(&self, event: &str, value: &zbus::zvariant::Value<'_>) -> zbus::Result<()>;
+
+ /// SetInterceptActivation method
+ fn set_intercept_activation(
+ &self,
+ activation_events: &[&str],
+ target_event: &str,
+ ) -> zbus::Result<()>;
+
+ /// SetTargetDevices method
+ fn set_target_devices(&self, target_device_types: &[&str]) -> zbus::Result<()>;
+
+ /// Stop method
+ fn stop(&self) -> zbus::Result<()>;
+
+ /// Capabilities property
+ #[zbus(property)]
+ fn capabilities(&self) -> zbus::Result>;
+
+ /// DbusDevices property
+ #[zbus(property)]
+ fn dbus_devices(&self) -> zbus::Result>;
+
+ /// InterceptMode property
+ #[zbus(property)]
+ fn intercept_mode(&self) -> zbus::Result;
+ #[zbus(property)]
+ fn set_intercept_mode(&self, value: u32) -> zbus::Result<()>;
+
+ /// Name property
+ #[zbus(property)]
+ fn name(&self) -> zbus::Result;
+
+ /// ProfileName property
+ #[zbus(property)]
+ fn profile_name(&self) -> zbus::Result;
+
+ /// SourceDevicePaths property
+ #[zbus(property)]
+ fn source_device_paths(&self) -> zbus::Result>;
+
+ /// TargetCapabilities property
+ #[zbus(property)]
+ fn target_capabilities(&self) -> zbus::Result>;
+
+ /// TargetDevices property
+ #[zbus(property)]
+ fn target_devices(&self) -> zbus::Result>;
+}
diff --git a/extensions/core/src/dbus/inputplumber/dbus_device.rs b/extensions/core/src/dbus/inputplumber/dbus_device.rs
new file mode 100644
index 000000000..56f054508
--- /dev/null
+++ b/extensions/core/src/dbus/inputplumber/dbus_device.rs
@@ -0,0 +1,48 @@
+//! # D-Bus interface proxy for: `org.shadowblip.Input.DBusDevice`
+//!
+//! This code was generated by `zbus-xmlgen` `4.1.0` from D-Bus introspection data.
+//! Source: `Interface '/org/shadowblip/InputPlumber/devices/target/dbus0' from service 'org.shadowblip.InputPlumber' on system bus`.
+//!
+//! You may prefer to adapt it, instead of using it verbatim.
+//!
+//! More information can be found in the [Writing a client proxy] section of the zbus
+//! documentation.
+//!
+//! This type implements the [D-Bus standard interfaces], (`org.freedesktop.DBus.*`) for which the
+//! following zbus API can be used:
+//!
+//! * [`zbus::fdo::PeerProxy`]
+//! * [`zbus::fdo::PropertiesProxy`]
+//! * [`zbus::fdo::IntrospectableProxy`]
+//!
+//! Consequently `zbus-xmlgen` did not generate code for the above interfaces.
+//!
+//! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html
+//! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces,
+use zbus::proxy;
+#[proxy(
+ interface = "org.shadowblip.Input.DBusDevice",
+ default_service = "org.shadowblip.InputPlumber",
+ default_path = "/org/shadowblip/InputPlumber/devices/target/dbus0"
+)]
+trait DBusDevice {
+ /// InputEvent signal
+ #[zbus(signal)]
+ fn input_event(&self, event: &str, value: f64) -> zbus::Result<()>;
+
+ /// TouchEvent signal
+ #[zbus(signal)]
+ fn touch_event(
+ &self,
+ event: &str,
+ index: u32,
+ is_touching: bool,
+ pressure: f64,
+ x: f64,
+ y: f64,
+ ) -> zbus::Result<()>;
+
+ /// Name property
+ #[zbus(property)]
+ fn name(&self) -> zbus::Result;
+}
diff --git a/extensions/core/src/dbus/inputplumber/event_device.rs b/extensions/core/src/dbus/inputplumber/event_device.rs
new file mode 100644
index 000000000..5b435da77
--- /dev/null
+++ b/extensions/core/src/dbus/inputplumber/event_device.rs
@@ -0,0 +1,64 @@
+//! # D-Bus interface proxy for: `org.shadowblip.Input.Source.EventDevice`
+//!
+//! This code was generated by `zbus-xmlgen` `4.1.0` from D-Bus introspection data.
+//! Source: `Interface '/org/shadowblip/InputPlumber/devices/source/event9' from service 'org.shadowblip.InputPlumber' on system bus`.
+//!
+//! You may prefer to adapt it, instead of using it verbatim.
+//!
+//! More information can be found in the [Writing a client proxy] section of the zbus
+//! documentation.
+//!
+//! This type implements the [D-Bus standard interfaces], (`org.freedesktop.DBus.*`) for which the
+//! following zbus API can be used:
+//!
+//! * [`zbus::fdo::PeerProxy`]
+//! * [`zbus::fdo::IntrospectableProxy`]
+//! * [`zbus::fdo::PropertiesProxy`]
+//!
+//! Consequently `zbus-xmlgen` did not generate code for the above interfaces.
+//!
+//! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html
+//! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces,
+use zbus::proxy;
+#[proxy(
+ interface = "org.shadowblip.Input.Source.EventDevice",
+ default_service = "org.shadowblip.InputPlumber",
+ default_path = "/org/shadowblip/InputPlumber/devices/source/event9"
+)]
+trait EventDevice {
+ /// DevicePath property
+ #[zbus(property)]
+ fn device_path(&self) -> zbus::Result;
+
+ /// IdBustype property
+ #[zbus(property)]
+ fn id_bustype(&self) -> zbus::Result;
+
+ /// IdProduct property
+ #[zbus(property)]
+ fn id_product(&self) -> zbus::Result;
+
+ /// IdVendor property
+ #[zbus(property)]
+ fn id_vendor(&self) -> zbus::Result;
+
+ /// IdVersion property
+ #[zbus(property)]
+ fn id_version(&self) -> zbus::Result;
+
+ /// Name property
+ #[zbus(property)]
+ fn name(&self) -> zbus::Result;
+
+ /// PhysPath property
+ #[zbus(property)]
+ fn phys_path(&self) -> zbus::Result;
+
+ /// SysfsPath property
+ #[zbus(property)]
+ fn sysfs_path(&self) -> zbus::Result;
+
+ /// UniqueId property
+ #[zbus(property)]
+ fn unique_id(&self) -> zbus::Result;
+}
diff --git a/extensions/core/src/dbus/inputplumber/gamepad.rs b/extensions/core/src/dbus/inputplumber/gamepad.rs
new file mode 100644
index 000000000..207174b19
--- /dev/null
+++ b/extensions/core/src/dbus/inputplumber/gamepad.rs
@@ -0,0 +1,32 @@
+//! # D-Bus interface proxy for: `org.shadowblip.Input.Gamepad`
+//!
+//! This code was generated by `zbus-xmlgen` `4.1.0` from D-Bus introspection data.
+//! Source: `Interface '/org/shadowblip/InputPlumber/devices/target/gamepad0' from service 'org.shadowblip.InputPlumber' on system bus`.
+//!
+//! You may prefer to adapt it, instead of using it verbatim.
+//!
+//! More information can be found in the [Writing a client proxy] section of the zbus
+//! documentation.
+//!
+//! This type implements the [D-Bus standard interfaces], (`org.freedesktop.DBus.*`) for which the
+//! following zbus API can be used:
+//!
+//! * [`zbus::fdo::PeerProxy`]
+//! * [`zbus::fdo::PropertiesProxy`]
+//! * [`zbus::fdo::IntrospectableProxy`]
+//!
+//! Consequently `zbus-xmlgen` did not generate code for the above interfaces.
+//!
+//! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html
+//! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces,
+use zbus::proxy;
+#[proxy(
+ interface = "org.shadowblip.Input.Gamepad",
+ default_service = "org.shadowblip.InputPlumber",
+ default_path = "/org/shadowblip/InputPlumber/devices/target/gamepad0"
+)]
+trait Gamepad {
+ /// Name property
+ #[zbus(property)]
+ fn name(&self) -> zbus::Result;
+}
diff --git a/extensions/core/src/dbus/inputplumber/hidraw_device.rs b/extensions/core/src/dbus/inputplumber/hidraw_device.rs
new file mode 100644
index 000000000..f0a50da52
--- /dev/null
+++ b/extensions/core/src/dbus/inputplumber/hidraw_device.rs
@@ -0,0 +1,64 @@
+//! # D-Bus interface proxy for: `org.shadowblip.Input.Source.HIDRawDevice`
+//!
+//! This code was generated by `zbus-xmlgen` `4.1.0` from D-Bus introspection data.
+//! Source: `Interface '/org/shadowblip/InputPlumber/devices/source/hidraw0' from service 'org.shadowblip.InputPlumber' on system bus`.
+//!
+//! You may prefer to adapt it, instead of using it verbatim.
+//!
+//! More information can be found in the [Writing a client proxy] section of the zbus
+//! documentation.
+//!
+//! This type implements the [D-Bus standard interfaces], (`org.freedesktop.DBus.*`) for which the
+//! following zbus API can be used:
+//!
+//! * [`zbus::fdo::PropertiesProxy`]
+//! * [`zbus::fdo::PeerProxy`]
+//! * [`zbus::fdo::IntrospectableProxy`]
+//!
+//! Consequently `zbus-xmlgen` did not generate code for the above interfaces.
+//!
+//! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html
+//! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces,
+use zbus::proxy;
+#[proxy(
+ interface = "org.shadowblip.Input.Source.HIDRawDevice",
+ default_service = "org.shadowblip.InputPlumber",
+ default_path = "/org/shadowblip/InputPlumber/devices/source/hidraw0"
+)]
+trait HIDRawDevice {
+ /// DevPath property
+ #[zbus(property)]
+ fn dev_path(&self) -> zbus::Result;
+
+ /// IdProduct property
+ #[zbus(property)]
+ fn id_product(&self) -> zbus::Result;
+
+ /// IdVendor property
+ #[zbus(property)]
+ fn id_vendor(&self) -> zbus::Result;
+
+ /// InterfaceNumber property
+ #[zbus(property)]
+ fn interface_number(&self) -> zbus::Result;
+
+ /// Manufacturer property
+ #[zbus(property)]
+ fn manufacturer(&self) -> zbus::Result;
+
+ /// Name property
+ #[zbus(property)]
+ fn name(&self) -> zbus::Result;
+
+ /// Product property
+ #[zbus(property)]
+ fn product(&self) -> zbus::Result;
+
+ /// SerialNumber property
+ #[zbus(property)]
+ fn serial_number(&self) -> zbus::Result;
+
+ /// SysfsPath property
+ #[zbus(property)]
+ fn sysfs_path(&self) -> zbus::Result;
+}
diff --git a/extensions/core/src/dbus/inputplumber/iioimudevice.rs b/extensions/core/src/dbus/inputplumber/iioimudevice.rs
new file mode 100644
index 000000000..7dbfdfdf9
--- /dev/null
+++ b/extensions/core/src/dbus/inputplumber/iioimudevice.rs
@@ -0,0 +1,76 @@
+//! # D-Bus interface proxy for: `org.shadowblip.Input.Source.IIOIMUDevice`
+//!
+//! This code was generated by `zbus-xmlgen` `4.1.0` from D-Bus introspection data.
+//! Source: `Interface '/org/shadowblip/InputPlumber/devices/source/iio_device0' from service 'org.shadowblip.InputPlumber' on system bus`.
+//!
+//! You may prefer to adapt it, instead of using it verbatim.
+//!
+//! More information can be found in the [Writing a client proxy] section of the zbus
+//! documentation.
+//!
+//! This type implements the [D-Bus standard interfaces], (`org.freedesktop.DBus.*`) for which the
+//! following zbus API can be used:
+//!
+//! * [`zbus::fdo::PeerProxy`]
+//! * [`zbus::fdo::IntrospectableProxy`]
+//! * [`zbus::fdo::PropertiesProxy`]
+//!
+//! Consequently `zbus-xmlgen` did not generate code for the above interfaces.
+//!
+//! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html
+//! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces,
+use zbus::proxy;
+#[proxy(
+ interface = "org.shadowblip.Input.Source.IIOIMUDevice",
+ default_service = "org.shadowblip.InputPlumber",
+ default_path = "/org/shadowblip/InputPlumber/devices/source/iio_device0"
+)]
+trait IIOIMUDevice {
+ /// AccelSampleRate property
+ #[zbus(property)]
+ fn accel_sample_rate(&self) -> zbus::Result;
+ #[zbus(property)]
+ fn set_accel_sample_rate(&self, value: f64) -> zbus::Result<()>;
+
+ /// AccelSampleRatesAvail property
+ #[zbus(property)]
+ fn accel_sample_rates_avail(&self) -> zbus::Result>;
+
+ /// AccelScale property
+ #[zbus(property)]
+ fn accel_scale(&self) -> zbus::Result;
+ #[zbus(property)]
+ fn set_accel_scale(&self, value: f64) -> zbus::Result<()>;
+
+ /// AccelScalesAvail property
+ #[zbus(property)]
+ fn accel_scales_avail(&self) -> zbus::Result>;
+
+ /// AngvelSampleRate property
+ #[zbus(property)]
+ fn angvel_sample_rate(&self) -> zbus::Result;
+ #[zbus(property)]
+ fn set_angvel_sample_rate(&self, value: f64) -> zbus::Result<()>;
+
+ /// AngvelSampleRatesAvail property
+ #[zbus(property)]
+ fn angvel_sample_rates_avail(&self) -> zbus::Result>;
+
+ /// AngvelScale property
+ #[zbus(property)]
+ fn angvel_scale(&self) -> zbus::Result;
+ #[zbus(property)]
+ fn set_angvel_scale(&self, value: f64) -> zbus::Result<()>;
+
+ /// AngvelScalesAvail property
+ #[zbus(property)]
+ fn angvel_scales_avail(&self) -> zbus::Result>;
+
+ /// Id property
+ #[zbus(property)]
+ fn id(&self) -> zbus::Result;
+
+ /// Name property
+ #[zbus(property)]
+ fn name(&self) -> zbus::Result;
+}
diff --git a/extensions/core/src/dbus/inputplumber/input_manager.rs b/extensions/core/src/dbus/inputplumber/input_manager.rs
new file mode 100644
index 000000000..49b1c3837
--- /dev/null
+++ b/extensions/core/src/dbus/inputplumber/input_manager.rs
@@ -0,0 +1,52 @@
+//! # D-Bus interface proxy for: `org.shadowblip.InputManager`
+//!
+//! This code was generated by `zbus-xmlgen` `4.1.0` from D-Bus introspection data.
+//! Source: `Interface '/org/shadowblip/InputPlumber/Manager' from service 'org.shadowblip.InputPlumber' on system bus`.
+//!
+//! You may prefer to adapt it, instead of using it verbatim.
+//!
+//! More information can be found in the [Writing a client proxy] section of the zbus
+//! documentation.
+//!
+//! This type implements the [D-Bus standard interfaces], (`org.freedesktop.DBus.*`) for which the
+//! following zbus API can be used:
+//!
+//! * [`zbus::fdo::PropertiesProxy`]
+//! * [`zbus::fdo::PeerProxy`]
+//! * [`zbus::fdo::IntrospectableProxy`]
+//!
+//! Consequently `zbus-xmlgen` did not generate code for the above interfaces.
+//!
+//! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html
+//! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces,
+use zbus::proxy;
+#[proxy(
+ interface = "org.shadowblip.InputManager",
+ default_service = "org.shadowblip.InputPlumber",
+ default_path = "/org/shadowblip/InputPlumber/Manager"
+)]
+trait InputManager {
+ /// AttachTargetDevice method
+ fn attach_target_device(&self, target_path: &str, composite_path: &str) -> zbus::Result<()>;
+
+ /// CreateCompositeDevice method
+ fn create_composite_device(&self, config_path: &str) -> zbus::Result;
+
+ /// CreateTargetDevice method
+ fn create_target_device(&self, kind: &str) -> zbus::Result;
+
+ /// StopTargetDevice method
+ fn stop_target_device(&self, path: &str) -> zbus::Result<()>;
+
+ /// InterceptMode property
+ #[zbus(property)]
+ fn intercept_mode(&self) -> zbus::Result;
+
+ /// SupportedTargetDeviceIds property
+ #[zbus(property)]
+ fn supported_target_device_ids(&self) -> zbus::Result>;
+
+ /// SupportedTargetDevices property
+ #[zbus(property)]
+ fn supported_target_devices(&self) -> zbus::Result>;
+}
diff --git a/extensions/core/src/dbus/inputplumber/keyboard.rs b/extensions/core/src/dbus/inputplumber/keyboard.rs
new file mode 100644
index 000000000..3da27d524
--- /dev/null
+++ b/extensions/core/src/dbus/inputplumber/keyboard.rs
@@ -0,0 +1,35 @@
+//! # D-Bus interface proxy for: `org.shadowblip.Input.Keyboard`
+//!
+//! This code was generated by `zbus-xmlgen` `4.1.0` from D-Bus introspection data.
+//! Source: `Interface '/org/shadowblip/InputPlumber/devices/target/keyboard0' from service 'org.shadowblip.InputPlumber' on system bus`.
+//!
+//! You may prefer to adapt it, instead of using it verbatim.
+//!
+//! More information can be found in the [Writing a client proxy] section of the zbus
+//! documentation.
+//!
+//! This type implements the [D-Bus standard interfaces], (`org.freedesktop.DBus.*`) for which the
+//! following zbus API can be used:
+//!
+//! * [`zbus::fdo::IntrospectableProxy`]
+//! * [`zbus::fdo::PeerProxy`]
+//! * [`zbus::fdo::PropertiesProxy`]
+//!
+//! Consequently `zbus-xmlgen` did not generate code for the above interfaces.
+//!
+//! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html
+//! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces,
+use zbus::proxy;
+#[proxy(
+ interface = "org.shadowblip.Input.Keyboard",
+ default_service = "org.shadowblip.InputPlumber",
+ default_path = "/org/shadowblip/InputPlumber/devices/target/keyboard0"
+)]
+trait Keyboard {
+ /// SendKey method
+ fn send_key(&self, key: &str, value: bool) -> zbus::Result<()>;
+
+ /// Name property
+ #[zbus(property)]
+ fn name(&self) -> zbus::Result;
+}
diff --git a/extensions/core/src/dbus/inputplumber/mouse.rs b/extensions/core/src/dbus/inputplumber/mouse.rs
new file mode 100644
index 000000000..8ffe1b2dd
--- /dev/null
+++ b/extensions/core/src/dbus/inputplumber/mouse.rs
@@ -0,0 +1,35 @@
+//! # D-Bus interface proxy for: `org.shadowblip.Input.Mouse`
+//!
+//! This code was generated by `zbus-xmlgen` `4.1.0` from D-Bus introspection data.
+//! Source: `Interface '/org/shadowblip/InputPlumber/devices/target/mouse0' from service 'org.shadowblip.InputPlumber' on system bus`.
+//!
+//! You may prefer to adapt it, instead of using it verbatim.
+//!
+//! More information can be found in the [Writing a client proxy] section of the zbus
+//! documentation.
+//!
+//! This type implements the [D-Bus standard interfaces], (`org.freedesktop.DBus.*`) for which the
+//! following zbus API can be used:
+//!
+//! * [`zbus::fdo::IntrospectableProxy`]
+//! * [`zbus::fdo::PropertiesProxy`]
+//! * [`zbus::fdo::PeerProxy`]
+//!
+//! Consequently `zbus-xmlgen` did not generate code for the above interfaces.
+//!
+//! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html
+//! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces,
+use zbus::proxy;
+#[proxy(
+ interface = "org.shadowblip.Input.Mouse",
+ default_service = "org.shadowblip.InputPlumber",
+ default_path = "/org/shadowblip/InputPlumber/devices/target/mouse0"
+)]
+trait Mouse {
+ /// MoveCursor method
+ fn move_cursor(&self, x: i32, y: i32) -> zbus::Result<()>;
+
+ /// Name property
+ #[zbus(property)]
+ fn name(&self) -> zbus::Result;
+}
diff --git a/extensions/core/src/dbus/networkmanager.rs b/extensions/core/src/dbus/networkmanager.rs
new file mode 100644
index 000000000..f45e3ff28
--- /dev/null
+++ b/extensions/core/src/dbus/networkmanager.rs
@@ -0,0 +1,17 @@
+pub mod access_point;
+pub mod active;
+pub mod agent_manager;
+pub mod bridge;
+pub mod connection;
+pub mod device;
+pub mod dhcp4config;
+pub mod dns_manager;
+pub mod ip4config;
+pub mod ip6config;
+pub mod loopback;
+pub mod network_manager;
+pub mod settings;
+pub mod statistics;
+pub mod wifi_p2p;
+pub mod wired;
+pub mod wireless;
diff --git a/extensions/core/src/dbus/networkmanager/access_point.rs b/extensions/core/src/dbus/networkmanager/access_point.rs
new file mode 100644
index 000000000..ec64db903
--- /dev/null
+++ b/extensions/core/src/dbus/networkmanager/access_point.rs
@@ -0,0 +1,71 @@
+//! # D-Bus interface proxy for: `org.freedesktop.NetworkManager.AccessPoint`
+//!
+//! This code was generated by `zbus-xmlgen` `4.1.0` from D-Bus introspection data.
+//! Source: `Interface '/org/freedesktop/NetworkManager/AccessPoint/891' from service 'org.freedesktop.NetworkManager' on system bus`.
+//!
+//! You may prefer to adapt it, instead of using it verbatim.
+//!
+//! More information can be found in the [Writing a client proxy] section of the zbus
+//! documentation.
+//!
+//! This type implements the [D-Bus standard interfaces], (`org.freedesktop.DBus.*`) for which the
+//! following zbus API can be used:
+//!
+//! * [`zbus::fdo::PropertiesProxy`]
+//! * [`zbus::fdo::IntrospectableProxy`]
+//! * [`zbus::fdo::PeerProxy`]
+//!
+//! Consequently `zbus-xmlgen` did not generate code for the above interfaces.
+//!
+//! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html
+//! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces,
+use zbus::proxy;
+#[proxy(
+ interface = "org.freedesktop.NetworkManager.AccessPoint",
+ default_service = "org.freedesktop.NetworkManager"
+)]
+trait AccessPoint {
+ /// Bandwidth property
+ #[zbus(property)]
+ fn bandwidth(&self) -> zbus::Result;
+
+ /// Flags property
+ #[zbus(property)]
+ fn flags(&self) -> zbus::Result;
+
+ /// Frequency property
+ #[zbus(property)]
+ fn frequency(&self) -> zbus::Result;
+
+ /// HwAddress property
+ #[zbus(property)]
+ fn hw_address(&self) -> zbus::Result;
+
+ /// LastSeen property
+ #[zbus(property)]
+ fn last_seen(&self) -> zbus::Result;
+
+ /// MaxBitrate property
+ #[zbus(property)]
+ fn max_bitrate(&self) -> zbus::Result;
+
+ /// Mode property
+ #[zbus(property)]
+ fn mode(&self) -> zbus::Result;
+
+ /// RsnFlags property
+ #[zbus(property)]
+ fn rsn_flags(&self) -> zbus::Result;
+
+ /// Ssid property
+ #[zbus(property)]
+ fn ssid(&self) -> zbus::Result>;
+
+ /// Strength property
+ #[zbus(property)]
+ fn strength(&self) -> zbus::Result;
+
+ /// WpaFlags property
+ #[zbus(property)]
+ fn wpa_flags(&self) -> zbus::Result;
+}
diff --git a/extensions/core/src/dbus/networkmanager/active.rs b/extensions/core/src/dbus/networkmanager/active.rs
new file mode 100644
index 000000000..1b5900428
--- /dev/null
+++ b/extensions/core/src/dbus/networkmanager/active.rs
@@ -0,0 +1,99 @@
+//! # D-Bus interface proxy for: `org.freedesktop.NetworkManager.Connection.Active`
+//!
+//! This code was generated by `zbus-xmlgen` `4.1.0` from D-Bus introspection data.
+//! Source: `Interface '/org/freedesktop/NetworkManager/ActiveConnection/3' from service 'org.freedesktop.NetworkManager' on system bus`.
+//!
+//! You may prefer to adapt it, instead of using it verbatim.
+//!
+//! More information can be found in the [Writing a client proxy] section of the zbus
+//! documentation.
+//!
+//! This type implements the [D-Bus standard interfaces], (`org.freedesktop.DBus.*`) for which the
+//! following zbus API can be used:
+//!
+//! * [`zbus::fdo::PropertiesProxy`]
+//! * [`zbus::fdo::IntrospectableProxy`]
+//! * [`zbus::fdo::PeerProxy`]
+//!
+//! Consequently `zbus-xmlgen` did not generate code for the above interfaces.
+//!
+//! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html
+//! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces,
+use zbus::proxy;
+#[proxy(
+ interface = "org.freedesktop.NetworkManager.Connection.Active",
+ default_service = "org.freedesktop.NetworkManager"
+)]
+trait Active {
+ /// StateChanged signal
+ //#[zbus(signal)]
+ //fn state_changed(&self, state: u32, reason: u32) -> zbus::Result<()>;
+
+ /// Connection property
+ #[zbus(property)]
+ fn connection(&self) -> zbus::Result;
+
+ /// Controller property
+ #[zbus(property)]
+ fn controller(&self) -> zbus::Result;
+
+ /// Default property
+ #[zbus(property)]
+ fn default(&self) -> zbus::Result;
+
+ /// Default6 property
+ #[zbus(property)]
+ fn default6(&self) -> zbus::Result;
+
+ /// Devices property
+ #[zbus(property)]
+ fn devices(&self) -> zbus::Result>;
+
+ /// Dhcp4Config property
+ #[zbus(property)]
+ fn dhcp4_config(&self) -> zbus::Result;
+
+ /// Dhcp6Config property
+ #[zbus(property)]
+ fn dhcp6_config(&self) -> zbus::Result;
+
+ /// Id property
+ #[zbus(property)]
+ fn id(&self) -> zbus::Result;
+
+ /// Ip4Config property
+ #[zbus(property)]
+ fn ip4_config(&self) -> zbus::Result;
+
+ /// Ip6Config property
+ #[zbus(property)]
+ fn ip6_config(&self) -> zbus::Result;
+
+ /// Master property
+ #[zbus(property)]
+ fn master(&self) -> zbus::Result;
+
+ /// SpecificObject property
+ #[zbus(property)]
+ fn specific_object(&self) -> zbus::Result;
+
+ /// State property
+ #[zbus(property)]
+ fn state(&self) -> zbus::Result;
+
+ /// StateFlags property
+ #[zbus(property)]
+ fn state_flags(&self) -> zbus::Result;
+
+ /// Type property
+ #[zbus(property)]
+ fn type_(&self) -> zbus::Result;
+
+ /// Uuid property
+ #[zbus(property)]
+ fn uuid(&self) -> zbus::Result;
+
+ /// Vpn property
+ #[zbus(property)]
+ fn vpn(&self) -> zbus::Result;
+}
diff --git a/extensions/core/src/dbus/networkmanager/agent_manager.rs b/extensions/core/src/dbus/networkmanager/agent_manager.rs
new file mode 100644
index 000000000..8a0c281d6
--- /dev/null
+++ b/extensions/core/src/dbus/networkmanager/agent_manager.rs
@@ -0,0 +1,37 @@
+//! # D-Bus interface proxy for: `org.freedesktop.NetworkManager.AgentManager`
+//!
+//! This code was generated by `zbus-xmlgen` `4.1.0` from D-Bus introspection data.
+//! Source: `Interface '/org/freedesktop/NetworkManager/AgentManager' from service 'org.freedesktop.NetworkManager' on system bus`.
+//!
+//! You may prefer to adapt it, instead of using it verbatim.
+//!
+//! More information can be found in the [Writing a client proxy] section of the zbus
+//! documentation.
+//!
+//! This type implements the [D-Bus standard interfaces], (`org.freedesktop.DBus.*`) for which the
+//! following zbus API can be used:
+//!
+//! * [`zbus::fdo::PropertiesProxy`]
+//! * [`zbus::fdo::IntrospectableProxy`]
+//! * [`zbus::fdo::PeerProxy`]
+//!
+//! Consequently `zbus-xmlgen` did not generate code for the above interfaces.
+//!
+//! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html
+//! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces,
+use zbus::proxy;
+#[proxy(
+ interface = "org.freedesktop.NetworkManager.AgentManager",
+ default_service = "org.freedesktop.NetworkManager",
+ default_path = "/org/freedesktop/NetworkManager/AgentManager"
+)]
+trait AgentManager {
+ /// Register method
+ fn register(&self, identifier: &str) -> zbus::Result<()>;
+
+ /// RegisterWithCapabilities method
+ fn register_with_capabilities(&self, identifier: &str, capabilities: u32) -> zbus::Result<()>;
+
+ /// Unregister method
+ fn unregister(&self) -> zbus::Result<()>;
+}
diff --git a/extensions/core/src/dbus/networkmanager/bridge.rs b/extensions/core/src/dbus/networkmanager/bridge.rs
new file mode 100644
index 000000000..5608afa39
--- /dev/null
+++ b/extensions/core/src/dbus/networkmanager/bridge.rs
@@ -0,0 +1,39 @@
+//! # D-Bus interface proxy for: `org.freedesktop.NetworkManager.Device.Bridge`
+//!
+//! This code was generated by `zbus-xmlgen` `4.1.0` from D-Bus introspection data.
+//! Source: `Interface '/org/freedesktop/NetworkManager/Devices/5' from service 'org.freedesktop.NetworkManager' on system bus`.
+//!
+//! You may prefer to adapt it, instead of using it verbatim.
+//!
+//! More information can be found in the [Writing a client proxy] section of the zbus
+//! documentation.
+//!
+//! This type implements the [D-Bus standard interfaces], (`org.freedesktop.DBus.*`) for which the
+//! following zbus API can be used:
+//!
+//! * [`zbus::fdo::PropertiesProxy`]
+//! * [`zbus::fdo::IntrospectableProxy`]
+//! * [`zbus::fdo::PeerProxy`]
+//!
+//! Consequently `zbus-xmlgen` did not generate code for the above interfaces.
+//!
+//! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html
+//! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces,
+use zbus::proxy;
+#[proxy(
+ interface = "org.freedesktop.NetworkManager.Device.Bridge",
+ default_service = "org.freedesktop.NetworkManager"
+)]
+trait Bridge {
+ /// Carrier property
+ #[zbus(property)]
+ fn carrier(&self) -> zbus::Result;
+
+ /// HwAddress property
+ #[zbus(property)]
+ fn hw_address(&self) -> zbus::Result;
+
+ /// Slaves property
+ #[zbus(property)]
+ fn slaves(&self) -> zbus::Result>;
+}
diff --git a/extensions/core/src/dbus/networkmanager/connection.rs b/extensions/core/src/dbus/networkmanager/connection.rs
new file mode 100644
index 000000000..ddbdee10c
--- /dev/null
+++ b/extensions/core/src/dbus/networkmanager/connection.rs
@@ -0,0 +1,110 @@
+//! # D-Bus interface proxy for: `org.freedesktop.NetworkManager.Settings.Connection`
+//!
+//! This code was generated by `zbus-xmlgen` `4.1.0` from D-Bus introspection data.
+//! Source: `Interface '/org/freedesktop/NetworkManager/Settings/5' from service 'org.freedesktop.NetworkManager' on system bus`.
+//!
+//! You may prefer to adapt it, instead of using it verbatim.
+//!
+//! More information can be found in the [Writing a client proxy] section of the zbus
+//! documentation.
+//!
+//! This type implements the [D-Bus standard interfaces], (`org.freedesktop.DBus.*`) for which the
+//! following zbus API can be used:
+//!
+//! * [`zbus::fdo::PropertiesProxy`]
+//! * [`zbus::fdo::IntrospectableProxy`]
+//! * [`zbus::fdo::PeerProxy`]
+//!
+//! Consequently `zbus-xmlgen` did not generate code for the above interfaces.
+//!
+//! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html
+//! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces,
+use zbus::proxy;
+#[proxy(
+ interface = "org.freedesktop.NetworkManager.Settings.Connection",
+ default_service = "org.freedesktop.NetworkManager"
+)]
+trait Connection {
+ /// ClearSecrets method
+ fn clear_secrets(&self) -> zbus::Result<()>;
+
+ /// Delete method
+ fn delete(&self) -> zbus::Result<()>;
+
+ /// GetSecrets method
+ fn get_secrets(
+ &self,
+ setting_name: &str,
+ ) -> zbus::Result<
+ std::collections::HashMap<
+ String,
+ std::collections::HashMap,
+ >,
+ >;
+
+ /// GetSettings method
+ fn get_settings(
+ &self,
+ ) -> zbus::Result<
+ std::collections::HashMap<
+ String,
+ std::collections::HashMap,
+ >,
+ >;
+
+ /// Save method
+ fn save(&self) -> zbus::Result<()>;
+
+ /// Update method
+ fn update(
+ &self,
+ properties: std::collections::HashMap<
+ &str,
+ std::collections::HashMap<&str, &zbus::zvariant::Value<'_>>,
+ >,
+ ) -> zbus::Result<()>;
+
+ /// Update2 method
+ fn update2(
+ &self,
+ settings: std::collections::HashMap<
+ &str,
+ std::collections::HashMap<&str, &zbus::zvariant::Value<'_>>,
+ >,
+ flags: u32,
+ args: std::collections::HashMap<&str, &zbus::zvariant::Value<'_>>,
+ ) -> zbus::Result>;
+
+ /// UpdateUnsaved method
+ fn update_unsaved(
+ &self,
+ properties: std::collections::HashMap<
+ &str,
+ std::collections::HashMap<&str, &zbus::zvariant::Value<'_>>,
+ >,
+ ) -> zbus::Result<()>;
+
+ /// Removed signal
+ #[zbus(signal)]
+ fn removed(&self) -> zbus::Result<()>;
+
+ /// Updated signal
+ #[zbus(signal)]
+ fn updated(&self) -> zbus::Result<()>;
+
+ /// Filename property
+ #[zbus(property)]
+ fn filename(&self) -> zbus::Result;
+
+ /// Flags property
+ #[zbus(property)]
+ fn flags(&self) -> zbus::Result;
+
+ /// Unsaved property
+ #[zbus(property)]
+ fn unsaved(&self) -> zbus::Result;
+
+ /// VersionId property
+ #[zbus(property)]
+ fn version_id(&self) -> zbus::Result;
+}
diff --git a/extensions/core/src/dbus/networkmanager/device.rs b/extensions/core/src/dbus/networkmanager/device.rs
new file mode 100644
index 000000000..a2f6d84ad
--- /dev/null
+++ b/extensions/core/src/dbus/networkmanager/device.rs
@@ -0,0 +1,195 @@
+//! # D-Bus interface proxy for: `org.freedesktop.NetworkManager.Device`
+//!
+//! This code was generated by `zbus-xmlgen` `4.1.0` from D-Bus introspection data.
+//! Source: `Interface '/org/freedesktop/NetworkManager/Devices/5' from service 'org.freedesktop.NetworkManager' on system bus`.
+//!
+//! You may prefer to adapt it, instead of using it verbatim.
+//!
+//! More information can be found in the [Writing a client proxy] section of the zbus
+//! documentation.
+//!
+//! This type implements the [D-Bus standard interfaces], (`org.freedesktop.DBus.*`) for which the
+//! following zbus API can be used:
+//!
+//! * [`zbus::fdo::PropertiesProxy`]
+//! * [`zbus::fdo::IntrospectableProxy`]
+//! * [`zbus::fdo::PeerProxy`]
+//!
+//! Consequently `zbus-xmlgen` did not generate code for the above interfaces.
+//!
+//! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html
+//! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces,
+use zbus::proxy;
+#[proxy(
+ interface = "org.freedesktop.NetworkManager.Device",
+ default_service = "org.freedesktop.NetworkManager"
+)]
+trait Device {
+ /// Delete method
+ fn delete(&self) -> zbus::Result<()>;
+
+ /// Disconnect method
+ fn disconnect(&self) -> zbus::Result<()>;
+
+ /// GetAppliedConnection method
+ #[allow(clippy::type_complexity)]
+ fn get_applied_connection(
+ &self,
+ flags: u32,
+ ) -> zbus::Result<(
+ std::collections::HashMap<
+ String,
+ std::collections::HashMap,
+ >,
+ u64,
+ )>;
+
+ /// Reapply method
+ fn reapply(
+ &self,
+ connection: std::collections::HashMap<
+ &str,
+ std::collections::HashMap<&str, &zbus::zvariant::Value<'_>>,
+ >,
+ version_id: u64,
+ flags: u32,
+ ) -> zbus::Result<()>;
+
+ /// StateChanged signal
+ //#[zbus(signal)]
+ //fn state_changed(&self, new_state: u32, old_state: u32, reason: u32) -> zbus::Result<()>;
+
+ /// ActiveConnection property
+ #[zbus(property)]
+ fn active_connection(&self) -> zbus::Result;
+
+ /// Autoconnect property
+ #[zbus(property)]
+ fn autoconnect(&self) -> zbus::Result;
+ #[zbus(property)]
+ fn set_autoconnect(&self, value: bool) -> zbus::Result<()>;
+
+ /// AvailableConnections property
+ #[zbus(property)]
+ fn available_connections(&self) -> zbus::Result>;
+
+ /// Capabilities property
+ #[zbus(property)]
+ fn capabilities(&self) -> zbus::Result;
+
+ /// DeviceType property
+ #[zbus(property)]
+ fn device_type(&self) -> zbus::Result;
+
+ /// Dhcp4Config property
+ #[zbus(property)]
+ fn dhcp4_config(&self) -> zbus::Result;
+
+ /// Dhcp6Config property
+ #[zbus(property)]
+ fn dhcp6_config(&self) -> zbus::Result;
+
+ /// Driver property
+ #[zbus(property)]
+ fn driver(&self) -> zbus::Result;
+
+ /// DriverVersion property
+ #[zbus(property)]
+ fn driver_version(&self) -> zbus::Result;
+
+ /// FirmwareMissing property
+ #[zbus(property)]
+ fn firmware_missing(&self) -> zbus::Result;
+
+ /// FirmwareVersion property
+ #[zbus(property)]
+ fn firmware_version(&self) -> zbus::Result;
+
+ /// HwAddress property
+ #[zbus(property)]
+ fn hw_address(&self) -> zbus::Result;
+
+ /// Interface property
+ #[zbus(property)]
+ fn interface(&self) -> zbus::Result;
+
+ /// InterfaceFlags property
+ #[zbus(property)]
+ fn interface_flags(&self) -> zbus::Result;
+
+ /// Ip4Address property
+ #[zbus(property)]
+ fn ip4_address(&self) -> zbus::Result;
+
+ /// Ip4Config property
+ #[zbus(property)]
+ fn ip4_config(&self) -> zbus::Result;
+
+ /// Ip4Connectivity property
+ #[zbus(property)]
+ fn ip4_connectivity(&self) -> zbus::Result;
+
+ /// Ip6Config property
+ #[zbus(property)]
+ fn ip6_config(&self) -> zbus::Result;
+
+ /// Ip6Connectivity property
+ #[zbus(property)]
+ fn ip6_connectivity(&self) -> zbus::Result;
+
+ /// IpInterface property
+ #[zbus(property)]
+ fn ip_interface(&self) -> zbus::Result;
+
+ /// LldpNeighbors property
+ #[zbus(property)]
+ fn lldp_neighbors(
+ &self,
+ ) -> zbus::Result>>;
+
+ /// Managed property
+ #[zbus(property)]
+ fn managed(&self) -> zbus::Result;
+ #[zbus(property)]
+ fn set_managed(&self, value: bool) -> zbus::Result<()>;
+
+ /// Metered property
+ #[zbus(property)]
+ fn metered(&self) -> zbus::Result;
+
+ /// Mtu property
+ #[zbus(property)]
+ fn mtu(&self) -> zbus::Result;
+
+ /// NmPluginMissing property
+ #[zbus(property)]
+ fn nm_plugin_missing(&self) -> zbus::Result;
+
+ /// Path property
+ #[zbus(property)]
+ fn path(&self) -> zbus::Result;
+
+ /// PhysicalPortId property
+ #[zbus(property)]
+ fn physical_port_id(&self) -> zbus::Result;
+
+ /// Ports property
+ #[zbus(property)]
+ fn ports(&self) -> zbus::Result>;
+
+ /// Real property
+ #[zbus(property)]
+ fn real(&self) -> zbus::Result;
+
+ /// State property
+ #[zbus(property)]
+ fn state(&self) -> zbus::Result;
+
+ /// StateReason property
+ #[zbus(property)]
+ fn state_reason(&self) -> zbus::Result<(u32, u32)>;
+
+ /// Udi property
+ #[zbus(property)]
+ fn udi(&self) -> zbus::Result;
+}
diff --git a/extensions/core/src/dbus/networkmanager/dhcp4config.rs b/extensions/core/src/dbus/networkmanager/dhcp4config.rs
new file mode 100644
index 000000000..d1186bc1c
--- /dev/null
+++ b/extensions/core/src/dbus/networkmanager/dhcp4config.rs
@@ -0,0 +1,33 @@
+//! # D-Bus interface proxy for: `org.freedesktop.NetworkManager.DHCP4Config`
+//!
+//! This code was generated by `zbus-xmlgen` `4.1.0` from D-Bus introspection data.
+//! Source: `Interface '/org/freedesktop/NetworkManager/DHCP4Config/2' from service 'org.freedesktop.NetworkManager' on system bus`.
+//!
+//! You may prefer to adapt it, instead of using it verbatim.
+//!
+//! More information can be found in the [Writing a client proxy] section of the zbus
+//! documentation.
+//!
+//! This type implements the [D-Bus standard interfaces], (`org.freedesktop.DBus.*`) for which the
+//! following zbus API can be used:
+//!
+//! * [`zbus::fdo::PropertiesProxy`]
+//! * [`zbus::fdo::IntrospectableProxy`]
+//! * [`zbus::fdo::PeerProxy`]
+//!
+//! Consequently `zbus-xmlgen` did not generate code for the above interfaces.
+//!
+//! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html
+//! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces,
+use zbus::proxy;
+#[proxy(
+ interface = "org.freedesktop.NetworkManager.DHCP4Config",
+ default_service = "org.freedesktop.NetworkManager"
+)]
+trait DHCP4Config {
+ /// Options property
+ #[zbus(property)]
+ fn options(
+ &self,
+ ) -> zbus::Result>;
+}
diff --git a/extensions/core/src/dbus/networkmanager/dns_manager.rs b/extensions/core/src/dbus/networkmanager/dns_manager.rs
new file mode 100644
index 000000000..d3d32a0df
--- /dev/null
+++ b/extensions/core/src/dbus/networkmanager/dns_manager.rs
@@ -0,0 +1,42 @@
+//! # D-Bus interface proxy for: `org.freedesktop.NetworkManager.DnsManager`
+//!
+//! This code was generated by `zbus-xmlgen` `4.1.0` from D-Bus introspection data.
+//! Source: `Interface '/org/freedesktop/NetworkManager/DnsManager' from service 'org.freedesktop.NetworkManager' on system bus`.
+//!
+//! You may prefer to adapt it, instead of using it verbatim.
+//!
+//! More information can be found in the [Writing a client proxy] section of the zbus
+//! documentation.
+//!
+//! This type implements the [D-Bus standard interfaces], (`org.freedesktop.DBus.*`) for which the
+//! following zbus API can be used:
+//!
+//! * [`zbus::fdo::PropertiesProxy`]
+//! * [`zbus::fdo::IntrospectableProxy`]
+//! * [`zbus::fdo::PeerProxy`]
+//!
+//! Consequently `zbus-xmlgen` did not generate code for the above interfaces.
+//!
+//! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html
+//! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces,
+use zbus::proxy;
+#[proxy(
+ interface = "org.freedesktop.NetworkManager.DnsManager",
+ default_service = "org.freedesktop.NetworkManager",
+ default_path = "/org/freedesktop/NetworkManager/DnsManager"
+)]
+trait DnsManager {
+ /// Configuration property
+ #[zbus(property)]
+ fn configuration(
+ &self,
+ ) -> zbus::Result>>;
+
+ /// Mode property
+ #[zbus(property)]
+ fn mode(&self) -> zbus::Result;
+
+ /// RcManager property
+ #[zbus(property)]
+ fn rc_manager(&self) -> zbus::Result;
+}
diff --git a/extensions/core/src/dbus/networkmanager/ip4config.rs b/extensions/core/src/dbus/networkmanager/ip4config.rs
new file mode 100644
index 000000000..ea9fef85e
--- /dev/null
+++ b/extensions/core/src/dbus/networkmanager/ip4config.rs
@@ -0,0 +1,85 @@
+//! # D-Bus interface proxy for: `org.freedesktop.NetworkManager.IP4Config`
+//!
+//! This code was generated by `zbus-xmlgen` `4.1.0` from D-Bus introspection data.
+//! Source: `Interface '/org/freedesktop/NetworkManager/IP4Config/1' from service 'org.freedesktop.NetworkManager' on system bus`.
+//!
+//! You may prefer to adapt it, instead of using it verbatim.
+//!
+//! More information can be found in the [Writing a client proxy] section of the zbus
+//! documentation.
+//!
+//! This type implements the [D-Bus standard interfaces], (`org.freedesktop.DBus.*`) for which the
+//! following zbus API can be used:
+//!
+//! * [`zbus::fdo::PropertiesProxy`]
+//! * [`zbus::fdo::IntrospectableProxy`]
+//! * [`zbus::fdo::PeerProxy`]
+//!
+//! Consequently `zbus-xmlgen` did not generate code for the above interfaces.
+//!
+//! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html
+//! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces,
+use zbus::proxy;
+#[proxy(
+ interface = "org.freedesktop.NetworkManager.IP4Config",
+ default_service = "org.freedesktop.NetworkManager"
+)]
+trait IP4Config {
+ /// AddressData property
+ #[zbus(property)]
+ fn address_data(
+ &self,
+ ) -> zbus::Result>>;
+
+ /// Addresses property
+ #[zbus(property)]
+ fn addresses(&self) -> zbus::Result>>;
+
+ /// DnsOptions property
+ #[zbus(property)]
+ fn dns_options(&self) -> zbus::Result>;
+
+ /// DnsPriority property
+ #[zbus(property)]
+ fn dns_priority(&self) -> zbus::Result;
+
+ /// Domains property
+ #[zbus(property)]
+ fn domains(&self) -> zbus::Result>;
+
+ /// Gateway property
+ #[zbus(property)]
+ fn gateway(&self) -> zbus::Result;
+
+ /// NameserverData property
+ #[zbus(property)]
+ fn nameserver_data(
+ &self,
+ ) -> zbus::Result>>;
+
+ /// Nameservers property
+ #[zbus(property)]
+ fn nameservers(&self) -> zbus::Result>;
+
+ /// RouteData property
+ #[zbus(property)]
+ fn route_data(
+ &self,
+ ) -> zbus::Result>>;
+
+ /// Routes property
+ #[zbus(property)]
+ fn routes(&self) -> zbus::Result>>;
+
+ /// Searches property
+ #[zbus(property)]
+ fn searches(&self) -> zbus::Result>;
+
+ /// WinsServerData property
+ #[zbus(property)]
+ fn wins_server_data(&self) -> zbus::Result>;
+
+ /// WinsServers property
+ #[zbus(property)]
+ fn wins_servers(&self) -> zbus::Result>;
+}
diff --git a/extensions/core/src/dbus/networkmanager/ip6config.rs b/extensions/core/src/dbus/networkmanager/ip6config.rs
new file mode 100644
index 000000000..701976e4c
--- /dev/null
+++ b/extensions/core/src/dbus/networkmanager/ip6config.rs
@@ -0,0 +1,73 @@
+//! # D-Bus interface proxy for: `org.freedesktop.NetworkManager.IP6Config`
+//!
+//! This code was generated by `zbus-xmlgen` `4.1.0` from D-Bus introspection data.
+//! Source: `Interface '/org/freedesktop/NetworkManager/IP6Config/3' from service 'org.freedesktop.NetworkManager' on system bus`.
+//!
+//! You may prefer to adapt it, instead of using it verbatim.
+//!
+//! More information can be found in the [Writing a client proxy] section of the zbus
+//! documentation.
+//!
+//! This type implements the [D-Bus standard interfaces], (`org.freedesktop.DBus.*`) for which the
+//! following zbus API can be used:
+//!
+//! * [`zbus::fdo::PropertiesProxy`]
+//! * [`zbus::fdo::IntrospectableProxy`]
+//! * [`zbus::fdo::PeerProxy`]
+//!
+//! Consequently `zbus-xmlgen` did not generate code for the above interfaces.
+//!
+//! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html
+//! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces,
+use zbus::proxy;
+#[proxy(
+ interface = "org.freedesktop.NetworkManager.IP6Config",
+ default_service = "org.freedesktop.NetworkManager"
+)]
+trait IP6Config {
+ /// AddressData property
+ #[zbus(property)]
+ fn address_data(
+ &self,
+ ) -> zbus::Result>>;
+
+ /// Addresses property
+ #[allow(clippy::type_complexity)]
+ #[zbus(property)]
+ fn addresses(&self) -> zbus::Result, u32, Vec)>>;
+
+ /// DnsOptions property
+ #[zbus(property)]
+ fn dns_options(&self) -> zbus::Result>;
+
+ /// DnsPriority property
+ #[zbus(property)]
+ fn dns_priority(&self) -> zbus::Result;
+
+ /// Domains property
+ #[zbus(property)]
+ fn domains(&self) -> zbus::Result>;
+
+ /// Gateway property
+ #[zbus(property)]
+ fn gateway(&self) -> zbus::Result;
+
+ /// Nameservers property
+ #[zbus(property)]
+ fn nameservers(&self) -> zbus::Result>>;
+
+ /// RouteData property
+ #[zbus(property)]
+ fn route_data(
+ &self,
+ ) -> zbus::Result>>;
+
+ /// Routes property
+ #[allow(clippy::type_complexity)]
+ #[zbus(property)]
+ fn routes(&self) -> zbus::Result, u32, Vec, u32)>>;
+
+ /// Searches property
+ #[zbus(property)]
+ fn searches(&self) -> zbus::Result>;
+}
diff --git a/extensions/core/src/dbus/networkmanager/loopback.rs b/extensions/core/src/dbus/networkmanager/loopback.rs
new file mode 100644
index 000000000..f979a31a0
--- /dev/null
+++ b/extensions/core/src/dbus/networkmanager/loopback.rs
@@ -0,0 +1,27 @@
+//! # D-Bus interface proxy for: `org.freedesktop.NetworkManager.Device.Loopback`
+//!
+//! This code was generated by `zbus-xmlgen` `4.1.0` from D-Bus introspection data.
+//! Source: `Interface '/org/freedesktop/NetworkManager/Devices/1' from service 'org.freedesktop.NetworkManager' on system bus`.
+//!
+//! You may prefer to adapt it, instead of using it verbatim.
+//!
+//! More information can be found in the [Writing a client proxy] section of the zbus
+//! documentation.
+//!
+//! This type implements the [D-Bus standard interfaces], (`org.freedesktop.DBus.*`) for which the
+//! following zbus API can be used:
+//!
+//! * [`zbus::fdo::PropertiesProxy`]
+//! * [`zbus::fdo::IntrospectableProxy`]
+//! * [`zbus::fdo::PeerProxy`]
+//!
+//! Consequently `zbus-xmlgen` did not generate code for the above interfaces.
+//!
+//! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html
+//! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces,
+use zbus::proxy;
+#[proxy(
+ interface = "org.freedesktop.NetworkManager.Device.Loopback",
+ default_service = "org.freedesktop.NetworkManager"
+)]
+trait Loopback {}
diff --git a/extensions/core/src/dbus/networkmanager/network_manager.rs b/extensions/core/src/dbus/networkmanager/network_manager.rs
new file mode 100644
index 000000000..27c05c7d8
--- /dev/null
+++ b/extensions/core/src/dbus/networkmanager/network_manager.rs
@@ -0,0 +1,266 @@
+//! # D-Bus interface proxy for: `org.freedesktop.NetworkManager`
+//!
+//! This code was generated by `zbus-xmlgen` `4.1.0` from D-Bus introspection data.
+//! Source: `Interface '/org/freedesktop/NetworkManager' from service 'org.freedesktop.NetworkManager' on system bus`.
+//!
+//! You may prefer to adapt it, instead of using it verbatim.
+//!
+//! More information can be found in the [Writing a client proxy] section of the zbus
+//! documentation.
+//!
+//! This type implements the [D-Bus standard interfaces], (`org.freedesktop.DBus.*`) for which the
+//! following zbus API can be used:
+//!
+//! * [`zbus::fdo::PropertiesProxy`]
+//! * [`zbus::fdo::IntrospectableProxy`]
+//! * [`zbus::fdo::PeerProxy`]
+//!
+//! Consequently `zbus-xmlgen` did not generate code for the above interfaces.
+//!
+//! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html
+//! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces,
+use zbus::proxy;
+#[proxy(
+ interface = "org.freedesktop.NetworkManager",
+ default_service = "org.freedesktop.NetworkManager",
+ default_path = "/org/freedesktop/NetworkManager"
+)]
+trait NetworkManager {
+ /// ActivateConnection method
+ fn activate_connection(
+ &self,
+ connection: &zbus::zvariant::ObjectPath<'_>,
+ device: &zbus::zvariant::ObjectPath<'_>,
+ specific_object: &zbus::zvariant::ObjectPath<'_>,
+ ) -> zbus::Result;
+
+ /// AddAndActivateConnection method
+ fn add_and_activate_connection(
+ &self,
+ connection: std::collections::HashMap<
+ &str,
+ std::collections::HashMap<&str, &zbus::zvariant::Value<'_>>,
+ >,
+ device: &zbus::zvariant::ObjectPath<'_>,
+ specific_object: &zbus::zvariant::ObjectPath<'_>,
+ ) -> zbus::Result<(
+ zbus::zvariant::OwnedObjectPath,
+ zbus::zvariant::OwnedObjectPath,
+ )>;
+
+ /// AddAndActivateConnection2 method
+ #[allow(clippy::too_many_arguments)]
+ fn add_and_activate_connection2(
+ &self,
+ connection: std::collections::HashMap<
+ &str,
+ std::collections::HashMap<&str, &zbus::zvariant::Value<'_>>,
+ >,
+ device: &zbus::zvariant::ObjectPath<'_>,
+ specific_object: &zbus::zvariant::ObjectPath<'_>,
+ options: std::collections::HashMap<&str, &zbus::zvariant::Value<'_>>,
+ ) -> zbus::Result<(
+ zbus::zvariant::OwnedObjectPath,
+ zbus::zvariant::OwnedObjectPath,
+ std::collections::HashMap,
+ )>;
+
+ /// CheckConnectivity method
+ fn check_connectivity(&self) -> zbus::Result;
+
+ /// CheckpointAdjustRollbackTimeout method
+ fn checkpoint_adjust_rollback_timeout(
+ &self,
+ checkpoint: &zbus::zvariant::ObjectPath<'_>,
+ add_timeout: u32,
+ ) -> zbus::Result<()>;
+
+ /// CheckpointCreate method
+ fn checkpoint_create(
+ &self,
+ devices: &[&zbus::zvariant::ObjectPath<'_>],
+ rollback_timeout: u32,
+ flags: u32,
+ ) -> zbus::Result;
+
+ /// CheckpointDestroy method
+ fn checkpoint_destroy(&self, checkpoint: &zbus::zvariant::ObjectPath<'_>) -> zbus::Result<()>;
+
+ /// CheckpointRollback method
+ fn checkpoint_rollback(
+ &self,
+ checkpoint: &zbus::zvariant::ObjectPath<'_>,
+ ) -> zbus::Result