From 2d603cc1cd50cbbeef9ba0850360cef4f0ad87aa Mon Sep 17 00:00:00 2001 From: Bill Doyle Date: Thu, 18 Jan 2024 10:33:09 -0500 Subject: [PATCH] Godot 4.2+ compatibility and mingw build support - Update godot-cpp to track 4.2 - Update openvr to 2.0.10 - Remove bundled godot-xr-tools - Remove support for MacOS, never tested and long broken - Update gdextension interface for changes in godot 4.1 - Support finding system-installed libopenvr on platforms with pkg-config - Support for mingw in build using tunabrain-patched openvr header - Add autoload singleton to register XR interface with server - This works around godotengine/godot#64975 the same way as the reference XR and TiltFive extensions. - Default to static libc++ to match godot-cpp - Remove CRT debug flag to match godot and godot-cpp - Update CI to publish gdextension artifacts correctly --- .github/workflows/build-on-push.yml | 130 +-- .github/workflows/static_checks.yml | 2 +- .gitignore | 1 + .gitmodules | 1 + README.md | 203 ++-- SConstruct | 149 +-- demo/Main.gd | 8 +- demo/Main.tscn | 74 +- demo/addons/godot-openvr/EditorPlugin.gd | 17 + .../addons/godot-openvr/OpenVRExportPlugin.gd | 13 +- .../godot-openvr/godot_openvr.gdextension | 1 + demo/addons/godot-openvr/icon.png.import | 13 +- .../meshes/hands_albedo.png.import | 16 +- .../meshes/hands_normal.png.import | 16 +- .../vr_glove_left_model_slim.glb.import | 10 +- .../vr_glove_right_model_slim.glb.import | 10 +- demo/addons/godot-openvr/openvr_autoloader.gd | 33 + .../godot-openvr/scenes/ovr_render_model.gd | 2 +- demo/addons/godot-xr-tools/CONTRIBUTORS.md | 13 - demo/addons/godot-xr-tools/LICENSE | 21 - demo/addons/godot-xr-tools/VERSIONS.md | 34 - demo/addons/godot-xr-tools/assets/LeftHand.gd | 16 - .../addons/godot-xr-tools/assets/LeftHand.glb | Bin 153828 -> 0 bytes .../godot-xr-tools/assets/LeftHand.glb.import | 30 - .../godot-xr-tools/assets/LeftHand.tscn | 500 ---------- .../assets/LeftHandBlendTree.tres | 38 - .../addons/godot-xr-tools/assets/RightHand.gd | 17 - .../godot-xr-tools/assets/RightHand.glb | Bin 152704 -> 0 bytes .../assets/RightHand.glb.import | 30 - .../godot-xr-tools/assets/RightHand.tscn | 508 ---------- .../godot-xr-tools/assets/RightHandBlend.tres | 40 - .../functions/Function_Direct_movement.gd | 251 ----- .../functions/Function_Direct_movement.tscn | 24 - .../functions/Function_Pickup.gd | 150 --- .../functions/Function_Pickup.tscn | 19 - .../functions/Function_Teleport.gd | 311 ------ .../functions/Function_Teleport.tscn | 49 - .../functions/Function_pointer.gd | 195 ---- .../functions/Function_pointer.tscn | 38 - demo/addons/godot-xr-tools/images/icon.png | Bin 3498 -> 0 bytes .../godot-xr-tools/images/icon.png.import | 35 - .../godot-xr-tools/images/teleport_arrow.png | Bin 526 -> 0 bytes .../images/teleport_arrow.png.import | 37 - .../godot-xr-tools/images/teleport_target.png | Bin 6903 -> 0 bytes .../images/teleport_target.png.import | 37 - .../godot-xr-tools/materials/capule.tres | 7 - .../godot-xr-tools/materials/highlight.tres | 74 -- .../godot-xr-tools/materials/pointer.tres | 6 - .../godot-xr-tools/materials/target.tres | 11 - .../materials/teleport.gdshader | 39 - .../godot-xr-tools/materials/teleport.tres | 12 - .../misc/VR_Common_Shader_Cache.gd | 13 - .../misc/VR_Common_Shader_Cache.tscn | 39 - .../godot-xr-tools/objects/Object_pickable.gd | 125 --- .../objects/Object_pickable.tscn | 11 - .../objects/Viewport_2D_in_3D.gd | 98 -- .../objects/Viewport_2D_in_3D.tscn | 45 - .../objects/Viewport_2D_in_3D_body.gd | 72 -- .../wasteland_clouds_2k.hdr.import | 13 +- .../brown_planks_03_AO_1k.jpg.import | 13 +- .../brown_planks_03_Disp_1k.jpg.import | 13 +- .../brown_planks_03_Nor_1k.jpg.import | 16 +- .../brown_planks_03_bump_1k.jpg.import | 13 +- .../brown_planks_03_diff_1k.jpg.import | 16 +- .../brown_planks_03_rough_1k.jpg.import | 16 +- .../brown_planks_03_spec_1k.jpg.import | 16 +- .../green_metal_rust_AO_1k.jpg.import | 13 +- .../green_metal_rust_Disp_1k.jpg.import | 13 +- .../green_metal_rust_Nor_1k.jpg.import | 16 +- .../green_metal_rust_bump_1k.jpg.import | 13 +- .../green_metal_rust_diff_1k.jpg.import | 16 +- .../green_metal_rust_rough_1k.jpg.import | 16 +- .../green_metal_rust_spec_1k.jpg.import | 16 +- .../wahooney.itch.io/blue_grid.png.import | 16 +- .../wahooney.itch.io/brown_grid.png.import | 13 +- .../wahooney.itch.io/green_grid.png.import | 16 +- .../wahooney.itch.io/white_grid.png.import | 16 +- demo/environment.tres | 4 +- demo/icon.png.import | 15 +- demo/misc/Cup.tscn | 21 +- demo/openxr_action_map.tres | 885 ++++++++++++++++++ demo/player/ButtonStates.gd | 10 +- demo/player/HUD_Anchor.gd | 2 +- demo/player/left_hand_controller.gd | 9 - demo/player/right_controller.gd | 4 +- demo/project.godot | 47 +- godot-cpp | 2 +- openvr | 2 +- src/open_vr/OpenVROverlay.cpp | 4 + src/open_vr/OpenVROverlay.h | 6 +- src/open_vr/OpenVRSkeleton.cpp | 2 +- src/open_vr/openvr_data.cpp | 58 +- src/open_vr/openvr_data.h | 8 +- src/register_types.cpp | 44 +- src/xr_interface_openvr.cpp | 22 +- src/xr_interface_openvr.h | 13 +- 96 files changed, 1477 insertions(+), 3605 deletions(-) create mode 100644 demo/addons/godot-openvr/openvr_autoloader.gd delete mode 100644 demo/addons/godot-xr-tools/CONTRIBUTORS.md delete mode 100644 demo/addons/godot-xr-tools/LICENSE delete mode 100644 demo/addons/godot-xr-tools/VERSIONS.md delete mode 100644 demo/addons/godot-xr-tools/assets/LeftHand.gd delete mode 100644 demo/addons/godot-xr-tools/assets/LeftHand.glb delete mode 100644 demo/addons/godot-xr-tools/assets/LeftHand.glb.import delete mode 100644 demo/addons/godot-xr-tools/assets/LeftHand.tscn delete mode 100644 demo/addons/godot-xr-tools/assets/LeftHandBlendTree.tres delete mode 100644 demo/addons/godot-xr-tools/assets/RightHand.gd delete mode 100644 demo/addons/godot-xr-tools/assets/RightHand.glb delete mode 100644 demo/addons/godot-xr-tools/assets/RightHand.glb.import delete mode 100644 demo/addons/godot-xr-tools/assets/RightHand.tscn delete mode 100644 demo/addons/godot-xr-tools/assets/RightHandBlend.tres delete mode 100644 demo/addons/godot-xr-tools/functions/Function_Direct_movement.gd delete mode 100644 demo/addons/godot-xr-tools/functions/Function_Direct_movement.tscn delete mode 100644 demo/addons/godot-xr-tools/functions/Function_Pickup.gd delete mode 100644 demo/addons/godot-xr-tools/functions/Function_Pickup.tscn delete mode 100644 demo/addons/godot-xr-tools/functions/Function_Teleport.gd delete mode 100644 demo/addons/godot-xr-tools/functions/Function_Teleport.tscn delete mode 100644 demo/addons/godot-xr-tools/functions/Function_pointer.gd delete mode 100644 demo/addons/godot-xr-tools/functions/Function_pointer.tscn delete mode 100644 demo/addons/godot-xr-tools/images/icon.png delete mode 100644 demo/addons/godot-xr-tools/images/icon.png.import delete mode 100644 demo/addons/godot-xr-tools/images/teleport_arrow.png delete mode 100644 demo/addons/godot-xr-tools/images/teleport_arrow.png.import delete mode 100644 demo/addons/godot-xr-tools/images/teleport_target.png delete mode 100644 demo/addons/godot-xr-tools/images/teleport_target.png.import delete mode 100644 demo/addons/godot-xr-tools/materials/capule.tres delete mode 100644 demo/addons/godot-xr-tools/materials/highlight.tres delete mode 100644 demo/addons/godot-xr-tools/materials/pointer.tres delete mode 100644 demo/addons/godot-xr-tools/materials/target.tres delete mode 100644 demo/addons/godot-xr-tools/materials/teleport.gdshader delete mode 100644 demo/addons/godot-xr-tools/materials/teleport.tres delete mode 100644 demo/addons/godot-xr-tools/misc/VR_Common_Shader_Cache.gd delete mode 100644 demo/addons/godot-xr-tools/misc/VR_Common_Shader_Cache.tscn delete mode 100644 demo/addons/godot-xr-tools/objects/Object_pickable.gd delete mode 100644 demo/addons/godot-xr-tools/objects/Object_pickable.tscn delete mode 100644 demo/addons/godot-xr-tools/objects/Viewport_2D_in_3D.gd delete mode 100644 demo/addons/godot-xr-tools/objects/Viewport_2D_in_3D.tscn delete mode 100644 demo/addons/godot-xr-tools/objects/Viewport_2D_in_3D_body.gd create mode 100644 demo/openxr_action_map.tres delete mode 100644 demo/player/left_hand_controller.gd diff --git a/.github/workflows/build-on-push.yml b/.github/workflows/build-on-push.yml index 7bf7138..7dd7071 100644 --- a/.github/workflows/build-on-push.yml +++ b/.github/workflows/build-on-push.yml @@ -1,15 +1,12 @@ - -# Workflow to automatically compile a Linux/Windows/OSX library on commit/push name: Build on push +# TODO: Add mingw to matrix + # Controls when the action will run. Triggers the workflow on push or pull request # events, but only for the master branch we'll create .zip files -on: - [push, pull_request] +on: [push, pull_request] -# A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: - # This job builds the plugin for our target platforms build: name: Building for ${{ matrix.os }} runs-on: ${{ matrix.os }} @@ -21,107 +18,74 @@ jobs: platform: linux - os: windows-latest platform: windows - # - os: macOS-latest - # platform: osx - # Steps represent a sequence of tasks that will be executed as part of the job steps: - # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: - submodules: 'recursive' + submodules: 'recursive' - - name: Install scons (Ubuntu) + - name: Install dependencies (Ubuntu) run: | - sudo apt install scons - if: matrix.os == 'ubuntu-20.04' + sudo apt-get update -qq + sudo apt-get install -qqq build-essential pkg-config + if: matrix.platform == 'linux' - - name: Install scons (Windows) - run: | - pip install scons - if: matrix.os == 'windows-latest' + - name: Set up Python (for SCons) + uses: actions/setup-python@v5 + with: + python-version: '3.x' - # - name: Install scons (macOS) - # run: | - # brew install scons - # if: matrix.os == 'macos-latest' + - name: Install scons + run: | + python -m pip install scons~=4.0 - name: Run the build for godot-cpp run: | - cd $GITHUB_WORKSPACE/godot-cpp - scons platform=${{ matrix.platform }} -j2 target=release generate_bindings=yes bits=64 - if: matrix.os != 'windows-latest' + scons -C godot-cpp platform=${{ matrix.platform }} -j2 target=template_release generate_bindings=yes bits=64 - name: Run the build for godot_openvr run: | - cd $GITHUB_WORKSPACE scons platform=${{ matrix.platform }} -j2 target=release bits=64 - if: matrix.os != 'windows-latest' - - - name: Run the build for godot-cpp (Windows) - run: | - cd ${env:GITHUB_WORKSPACE}/godot-cpp - scons platform=${{ matrix.platform }} -j2 target=release generate_bindings=yes bits=64 - if: matrix.os == 'windows-latest' - - name: Run the build for godot_openvr (Windows) - run: | - cd ${env:GITHUB_WORKSPACE} - scons platform=${{ matrix.platform }} -j2 target=release bits=64 - if: matrix.os == 'windows-latest' - - - name: Upload build files (artifacts) (Linux) - uses: actions/upload-artifact@v2 + # There's no option to preserve the path structure on the upload action, so we just + # treat each asset as its respective bin/ subfolder and put it in the right place in + # the next job. The names are important, they become the platform names. + # https://github.com/actions/upload-artifact/issues/174 + - name: Upload Windows build results + uses: actions/upload-artifact@v4 with: - name: build-files-linux - path: | - demo/addons/godot-openvr/bin/x11/libgodot_openvr.so - openvr/bin/linux64/libopenvr_api.so - if: matrix.os == 'ubuntu-20.04' + name: x11 + path: demo/addons/godot-openvr/bin/x11/ + if: matrix.platform == 'linux' - # - name: Upload build files (artifacts) (macOS) - # uses: actions/upload-artifact@v2 - # with: - # name: build-files-macos - # path: | - # demo/addons/godot-openvr/bin/osx/libgodot_openvr.dylib - # openvr/bin/osx32/OpenVR.framework - # if: matrix.os == 'macos-latest' - - - name: Upload build files (artifacts) (Windows) - uses: actions/upload-artifact@v2 + - name: Upload Linux build results + uses: actions/upload-artifact@v4 with: - name: build-files-windows - path: | - demo/addons/godot-openvr/bin/win64/libgodot_openvr.dll - openvr/bin/win64/openvr_api.dll - if: matrix.os == 'windows-latest' + name: win64 + path: demo/addons/godot-openvr/bin/win64/ + if: matrix.platform == 'windows' + # This job collects the build output and assembles the final asset (artifact) asset: - name: Assembling the asset (artifact) + name: Assemble release bundle runs-on: ubuntu-20.04 needs: build if: github.event_name == 'push' && (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags')) # Steps represent a sequence of tasks that will be executed as part of the job steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: - repository: 'GodotVR/godot_openvr' + # Giving an explicit path prevents an automatic cd into the checkout. path: godot_openvr - - name: Download all workflow run artifacts - uses: actions/download-artifact@v2 - - name: Copy files to destination + - name: Create destination and populate addon resources run: | - mkdir godot_openvr_plugin - mkdir godot_openvr_plugin/addons - cp -r godot_openvr/demo/addons/godot-openvr godot_openvr_plugin/addons - cp build-files-linux/demo/addons/godot-openvr/bin/x11/libgodot_openvr.so godot_openvr_plugin/addons/godot-openvr/bin/x11/libgodot_openvr.so - cp build-files-linux/openvr/bin/linux64/libopenvr_api.so godot_openvr_plugin/addons/godot-openvr/bin/x11/libopenvr_api.so - # cp build-files-macos/demo/addons/godot-openvr/bin/osx/libgodot_openvr.dylib godot_openvr_plugin/addons/godot-openvr/bin/osx/libgodot_openvr.dylib - # cp -r build-files-macos/openvr/bin/osx32/OpenVR.framework godot_openvr_plugin/addons/godot-openvr/bin/osx/OpenVR.framework - cp build-files-windows/demo/addons/godot-openvr/bin/win64/libgodot_openvr.dll godot_openvr_plugin/addons/godot-openvr/bin/win64/libgodot_openvr.dll - cp build-files-windows/openvr/bin/win64/openvr_api.dll godot_openvr_plugin/addons/godot-openvr/bin/win64/openvr_api.dll + mkdir -p godot_openvr_plugin/addons + cp -r godot_openvr/demo/addons/godot-openvr godot_openvr_plugin/addons/ + - name: Download per-platform binaries into addon + uses: actions/download-artifact@v4 + with: + path: godot_openvr_plugin/addons/godot-openvr/bin/ - name: Calculate GIT short ref run: | cd godot_openvr @@ -134,9 +98,6 @@ jobs: if: startsWith(github.ref, 'refs/tags') - name: Clean up extracted files run: | - rm -rf build-files-linux - #rm -rf build-files-macos - rm -rf build-files-windows rm -rf godot_openvr mv godot_openvr_plugin godot_openvr_${{ env.GITHUB_SHA_SHORT }} - name: Zip asset @@ -151,6 +112,9 @@ jobs: prerelease: false token: ${{ secrets.GITHUB_TOKEN }} if: startsWith(github.ref, 'refs/tags') + + # TODO: Both create-release and upload-release-asset are abandonded, need to port to maintained replacements. Both suggest replacements in their README. + - name: Create release for asset id: create_release uses: actions/create-release@v1 @@ -165,12 +129,12 @@ jobs: prerelease: true if: github.ref == 'refs/heads/master' - name: Upload asset - id: upload-release-asset + id: upload-release-asset uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: - upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps + upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps asset_path: ./godot-openvr.zip asset_name: godot-openvr.zip asset_content_type: application/zip diff --git a/.github/workflows/static_checks.yml b/.github/workflows/static_checks.yml index be1cc40..969344a 100644 --- a/.github/workflows/static_checks.yml +++ b/.github/workflows/static_checks.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-20.04 steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Install dependencies run: | diff --git a/.gitignore b/.gitignore index 27dc1a1..5d4e298 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,4 @@ Thumbs.db *.idb *.ilk *.dll +demo/addons/godot-xr-tools diff --git a/.gitmodules b/.gitmodules index d03ec95..4ed9559 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,4 @@ [submodule "godot-cpp"] path = godot-cpp url = https://github.com/godotengine/godot-cpp + branch = 4.2 diff --git a/README.md b/README.md index 89cc0f6..aa405b2 100644 --- a/README.md +++ b/README.md @@ -9,76 +9,77 @@ https://github.com/GodotVR/godot_openvr >> While we have taken care to try and keep a measure of backwards compatibility there are structural differences in how OpenVR handles actions and once enabled the old method of button and axis handling is deactivated. >> Please read the [OpenVR Actions documentation](https://github.com/GodotVR/godot-openvr-asset/wiki/OpenVR-actions) for more information! -Branches --------- - +# Branches This repo currently maintains the following branches: - `master` is our main development in which we maintain our `1.x.y` version of this plugin. This version works with Godot 3.x. - `2.0-dev` is our 2.0 development branch, this is an unstable branch in which we're porting this plugin to work in Godot 4.x. -- `Godot-3.0.4-plugin` is a legacy branch that worked with Godot 3.0, probably defunct -- `Godot-3.0-plugin` is a legacy branch that worked with Godot 3.0, probably defunct -Submodules ----------- -This project references two submodules. -If you do not already have these repositories downloaded somewhere you can execute: -``` -git submodule init -git submodule update -``` -To download the required versions. +# Building -You may need to run these commands in the `godot-cpp` subfolder to obtain the correct version of `godot_headers` +## Submodules +After cloning this repo, you should run: -Godot_cpp is a git repository that implements C++ bindings to Godots internal classes. + git submodule update --init --recursive -OpenVR is a git repository maintained by Valve that contains the OpenVR SDK used to interact with the OpenVR/SteamVR platform. +We use the following submodules: -Alternatively you can use the switch openvr to the location where you have downloaded a copy of this SDK by adding `openvr_path=` when running scons. +* [godot-cpp](https://github.com/godotengine/godot-cpp): C++ bindings to Godot's internal classes. This has a submodule of its own, godot-headers. +* [OpenVR](https://github.com/ValveSoftware/openvr): the repository maintained by Valve that contains the OpenVR SDK used to interact with the OpenVR/SteamVR platform. -Updating extensions -------------------- +The godot-cpp module is pointed at the branch corresponding to the specific release of Godot that we're currently supporting. 2.x of this extension has only been tested with OpenVR 2.0+. -As extensions are still being worked on you may need to run the following command on your build of Godot: -`godot --dump-extension-api` -And then copy the extension_api.json file into `godot-cpp/godot-headers` before compiling godot-cpp. +OpenVR can also be stored elsewhere using the `openvr_path=` build argument, or discovered automatically from the system if you're using a mingw/linux build environment. See Build variables below. -Compiling ---------- -Scons is used for compiling this module. I made the assumption that scons is installed as it is also used as the build mechanism for Godot and if you are building from source you will likely need to build Godot as well. +## Compiling +SCons is used for compiling this module. This is also the build mechanism for Godot and information on installing it on various platforms can be found in [the Godot documentation](https://docs.godotengine.org/en/stable/contributing/development/compiling/introduction_to_the_buildsystem.html). -You must compile `godot-cpp` first by executing: -``` -cd godot-cpp -scons platform=windows target=release generate_bindings=yes bits=64 -cd .. -``` +You must compile the `godot-cpp` submodule first by executing: -You can compile this module by executing: -``` -scons platform=windows target=release -``` + cd godot-cpp + scons platform=windows target=template_release generate_bindings=yes arch=x86_64 + cd .. -Platform can be windows, linux or osx. OSX is untested. +You can then compile this extension by executing: -Note that for extensions the dll needs to be compiled with `target=release_debug` when used with the editor. + scons -Deploying ---------- -Note that besides compiling the GDNative module you must also include valves openvr_api.dll (windows), libopenvr_api.so (linux) or OpenVR.framework (Mac OS X). See platform notes for placement of these files. -The godot_openvr.dll or libgodot_openvr.so file should be placed in the location the godot_openvr.gdnlib file is pointing to (at the moment bin). +The results will be placed within the extension's addon hierarchy in the included demo. This entire hierarchy (demo/addons/godot-openvr on downward) is then distributable. -Also, depending on what version of Visual Studio that was used to compile the dlls, you will need to install the `Microsoft Visual C++ Redistributable for Visual Studio` on any machine that you deploy your dll on. Godot already needs one of these but if you compile with a newer version of Visual Studio you also need to install that version. It's dumb, I know. -https://support.microsoft.com/en-au/help/2977003/the-latest-supported-visual-c-downloads +### Build variables +There are many CLI flags that can be given to scons to manipulate how the extension is created: + +* `target`: `release` or `debug`. Controls whether debug symbols are built into the extension and also sets appropriate compiler optimization flags. +* `platform`: `windows` or `linux`. Controls whether we build a DLL or shared library. +* `target_path`: The path where the native library for the extension is placed after building, defaults to `demo/addons/godot-openvr/bin/`. +* `target_name`: Name of the native library, defaults to `libgodot_openvr`, +* `use_mingw`: Use the Mingw compiler, even if the Visual Studio compiler is available (mostly useful on Windows). +* `use_llvm`: Use the LLVM compiler (clang). +* `use_static_cpp`: Link MinGW/MSVC C++ runtime libraries statically. Defaults to `yes` to simplify distribution and match godot-cpp. +* `bits`: `32` or `64`. Target CPU architecture, defaults to 64. +* `builtin_openvr`: Use the OpenVR library from our submodule. Defaults to `yes`, see below for how to use a system OpenVR. +* `openvr_path`: The path where the OpenVR repo is located, if `builtin_openvr` is used. Defaults to `openvr/`. + +Setting `builtin_openvr=no` will cause pkg-config to be invoked to search for a `libopenvr_api` installed on your system. pkg-config normally only exists on Linux systems, but can be installed on Windows using the mingw toolchain. + +When overriding any of these flags, care should be taken to build godot-cpp with the same flags where they exist. We have attempted to make them match in most cases, though the targets are different and `bits` is instead `arch={x86_64,x86_32}`. + +**In particular, when building for use in the editor you should compile godot-cpp with `target=template_debug` and this extension with `target=debug`.** + +See the Windows platform-specific notes below for further info about mingw and potential pitfalls. + +## Deploying +The finished GDExtension must be shipped with Valve's `openvr_api.dll` (Windows) or `libopenvr_api.so` (Linux). This is handled automatically by the build system whenever possible. The expected res:// paths of the library can be found in godot\_openvr.gdextension. + +## Running the demo +To use the demo you will additionally need to install the godot-xr-tools addon, which is available in the asset library within the editor. For alternative installation methods, see [the documentation](https://godotvr.github.io/godot-xr-tools/docs/installation/). +After installing, you will need to make sure it is enabled and then restart the editor. + +If you are building yourself, the demo should now be runnable. If you want to test it out without building, you can download the package from the latest Github actions build, unzip it, and replace the addons/godot-openvr directory with the one from the zip. Note that the debug build is not currently included in the package. -Mac notes ---------- -Valve has dropped support for MacOS in the latest version of OpenVR/SteamVR. While a 32bit binary is still included we have not been able to get this to work. -If you have a Mac and are willing to investigate this issue we would welcome a PR with the required fixes but otherwise support of MacOS has been dropped. +# Platform-specific notes -Linux notes ------------ -On Linux, Steam will not automatically add the SteamVR libraries to your $LD_LIBRARY_PATH variable. As such, when starting Godot (for development) or your game outside of Steam, it will fail to load the required libraries. +## Linux +On Linux, Steam will not automatically add the SteamVR libraries to your `$LD_LIBRARY_PATH` variable. As such, when starting Godot (for development) or your game outside of Steam, it will fail to load the required libraries. There are a couple of ways to fix this: @@ -86,105 +87,84 @@ There are a couple of ways to fix this: 2) Run Godot or your game through the steam runtime manually (change the path to suit your Steam installation): -``` -/home//.steam/steam/ubuntu12_32/steam-runtime/run.sh -``` + /home/$USER/.steam/steam/ubuntu12_32/steam-runtime/run.sh -3) Adjust your $LD_LIBRARY_PATH variable accordingly: +3) Adjust your `$LD_LIBRARY_PATH` variable accordingly: -``` -export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:"/path/to/libgodot_openvr.so/dir/":"/home//.steam/steam/steamapps/common/SteamVR/bin/" -``` + export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:/path/to/libgodot_openvr.so/dir/:/home/$USER/.steam/steam/steamapps/common/SteamVR/bin/" -You can place the libopenvr_api.so file alongside the libgodot_openvr.so file in the bin folder. You can find this file in: openvr/bin/linux64 +## Windows +Windows generally works without any special needs. This has been compiled with MSVC 2019, and in the past has worked with 2017 and 2015. With 2017 and above be aware Microsoft now lets you pick and choose which components you install and by default it may not install the SDK you need. Make sure to install both the Windows SDK and build tools. To build using the MSVC compiler without needing to install the entire IDE, the build tools can be installed using winget: -Windows notes -------------- + winget install Microsoft.VisualStudio.2019.BuildTools --override "--quiet --add Microsoft.VisualStudio.Workload.NativeDesktop" -Windows generally works without any special needs. I've tested compiling with MSVC 2017, others have tested 2015. With 2017 be aware Microsoft now lets you pick and choose which components you install and by default it may not install the SDK you need. Make sure to install both the Windows SDK and build tools. +Building with scons should then work within the Developer Powershell it creates. -Also when deploying users may need to first install the correct redistributable you can find here: https://support.microsoft.com/en-au/help/2977003/the-latest-supported-visual-c-downloads -I am not 100% sure this is a requirement as it automatically installs this when installing MSVC but past experiences and such... :) +Also, depending on what version of Visual Studio that was used to compile the dlls, you will need to install the `Microsoft Visual C++ Redistributable for Visual Studio` on any machine that you deploy your dll on. Godot already needs one of these but if you compile with a newer version of Visual Studio you also need to install that version. It's dumb, I know. If you build statically (`use_static_cpp`), this is not necessary as the library is compiled into the extension. Note that mixing a statically included libc++ with other versions may cause unintended side effects. +https://support.microsoft.com/en-au/help/2977003/the-latest-supported-visual-c-downloads -For Windows you need to supply a copy of openvr_api.dll along with your executable which can be found in openvr/bin/win64 +### mingw -HDR support ------------ -OpenVR from version 1.6 onwards is able to support the HDR render buffers Godot uses and you will no longer need to turn HDR off. +Building on Windows under mingw means using the gcc c++ compiler. Because C++ does not have a stable ABI, the resulting binary cannot actually communicate successfully with SteamVR using the OpenVR C++ bindings. The fix for this is a header patch using [a script written by tunabrain](https://gist.github.com/tunabrain/1fc7a4964914d61b5ae751d0c84f2382). This script rewrites the C++ header to call the OpenVR C bindings internally, sidestepping the ABI mismatch. We do not currently attempt to run this script as part of our build, it is up to you to produce a patched header if using the submoduled libopenvr_api. -OpenVR however expects the color buffer to contain color values in linear color space, its build in sRGB support only works for 8bit color buffers. Godot performs all 3D color calculations in linear color space but will do a final conversion to sRGB during post processing. The result is that everything inside of the headset will look far too bright. +When `use_mingw` is set, `USE_OPENVR_MINGW_HEADER` is exported during the build which will cause `openvr_mingw.hpp` to be included where `openvr.h` would be normally. You may place this file anywhere you like in the header search path. -You can work around this by turning `keep_3d_linear` on for our viewport, this will skip the sRGB conversion and result the display inside of the headset to be correct however the output to screen will be too dark. We'll be looking at an interim solution for this soon however a full solution will likely not become available until after Godots rewrite to Vulkan. +As an alternative to manually providing `openvr_mingw.hpp`, the [msys2](https://www.msys2.org/) distribution which can provide mingw-w64 also packages OpenVR along with the patched header. Setting up your mingw toolchain using msys2 (only the UCRT64 environment has been tested) and setting `builtin_openvr=no` will allow the packaged library to be discovered during the build. Setting up an msys2 environment is out of scope for this README, but once it is installed the following command will get the environment ready to build this extension: -``` -func _ready(): - var interface = ARVRServer.find_interface("OpenVR") - if interface and interface.initialize(): - get_viewport().arvr = true - get_viewport().keep_3d_linear = true -``` + pacman -S mingw-w64-ucrt-x86_64-toolchain mingw-w64-ucrt-x86_64-scons mingw-w64-ucrt-x86_64-openvr + +msys2 also packages Godot and godot-cpp, but as of this writing they are still on the 3.x train and thus we must continue to build our own godot-cpp. -Shader hickup ------------------ +As an aside, it would seem necessary to also build Godot itself for the mingw-compiled C++ bindings to work, but I've had no issues running the extension in the official build of Godot 4.2. + +## MacOS +MacOS support in OpenVR was dropped by Valve for a long time. While it appears it has recently made a return without much fanfare in OpenVR 2.0, support has not yet been returned to our build. + +# Shader hickup There are a few moment where OpenVR has a hickup. -One is around the teleporter function which can be solved by adding the `VR_Common_Shader_Cache.tscn` as a child scene to our ARVRCamera. `ovr_first_person.tscn` does this. +One is around the teleporter function which can be solved by adding the `VR_Common_Shader_Cache.tscn` as a child scene to our XRCamera3D. `ovr_first_person.tscn` does this. For the controllers they use a standard material. Adding a mesh instance with a standard material will ensure the shader is pre-compiled. Again we do this in `ovr_first_person.tscn`. However there is still an issue with loading the texture. We need to redo loading of the controller mesh by handing it off to a separate thread. -GLES2 support -------------- -The new GLES2 renderer in Godot 3.1 renders directly to RGBA8 buffers and thus doesn't need the HDR workaround. The GLES2 renderer is also much more lightweight then the GLES3 renderer and thus more suited for VR. +# Rendering -Using the main viewport ------------------------ -The ARVR server module requires a viewport to be configured as the ARVR viewport. If you chose to use the main viewport an aspect ratio corrected copy of the left eye will be rendered to the viewport automatically. +## Using the main viewport +The XR server module requires a viewport to be configured as the XR viewport. If you chose to use the main viewport an aspect ratio corrected copy of the left eye will be rendered to the viewport automatically. You will need to add the following code to a script on your root node: ``` -var interface = ARVRServer.find_interface("OpenVR") +var interface = XRServer.find_interface("OpenVR") if interface and interface.initialize(): - # turn to ARVR mode - get_viewport().arvr = true - - # keep linear color space, not needed with the GLES2 renderer - get_viewport().keep_3d_linear = true + get_viewport().use_xr = true # make sure vsync is disabled or we'll be limited to 60fps - OS.vsync_enabled = false + DisplayServer.window_set_vsync_mode(DisplayServer.VSYNC_DISABLED) - # up our physics to 90fps to get in sync with our rendering + # up our physics to 90fps to get in sync with our rendering (you may want to query the real headset value here instead) Engine.iterations_per_second = 90 ``` -Using a separate viewport -------------------------- -If you want control over the output on screen so you can show something independent on the desktop you can add a viewport to your scene. +## Using a separate viewport +If you want control over the output on screen so you can show something independent on the desktop you can add a SubViewport to your scene and enable "Use XR" on it. -Make sure that you turn the ARVR property and keep_3d_linear property of this viewport to true. -Also make sure that both the clear mode and update mode are set to always. +Also make sure that both the Clear Mode and Update Mode are set to Always, or nothing will be rendered. You can add a normal camera to your scene to render a spectator view or turn the main viewport into a 2D viewport and save some rendering overhead. -You can now simplify you initialisation code on your root node to: +The initialization code on the root node will now look like this: ``` -var interface = ARVRServer.find_interface("OpenVR") -if interface: - interface.initialize() - - # make sure vsync is disabled or we'll be limited to 60fps - OS.vsync_enabled = false - - # up our physics to 90fps to get in sync with our rendering +var interface = XRServer.find_interface("OpenVR") +if interface and interface.initialize(): + DisplayServer.window_set_vsync_mode(DisplayServer.VSYNC_DISABLED) Engine.iterations_per_second = 90 ``` -License -------- +# License Note that the source in this repository is licensed by the MIT license model. This covers only the source code in this repository. @@ -194,8 +174,7 @@ See their respective git repositories for more details. The subfolder `assets` contains third party assets. See license files in those subfolders for additional license details -About this repository ---------------------- +# About this repository This repository was created by and is maintained by Bastiaan Olij a.k.a. Mux213 You can follow me on twitter for regular updates here: diff --git a/SConstruct b/SConstruct index fa2b273..94a4464 100644 --- a/SConstruct +++ b/SConstruct @@ -5,36 +5,44 @@ import os customs = ['../custom.py'] opts = Variables(customs, ARGUMENTS) -# Gets the standart flags CC, CCX, etc. -env = Environment(ENV = os.environ) +# Defer tool intitialization so we can decide which toolchain to use based on our variables. They will be loaded later +# using env.Tool. +env = Environment(ENV=os.environ, tools=[]) -# Define our parameters -opts.Add(EnumVariable('target', "Compilation target", 'release', ['d', 'debug', 'r', 'release'])) -opts.Add(EnumVariable('platform', "Compilation platform", 'windows', ['windows', 'x11', 'linux', 'osx'])) +# Compilation options +# TODO: Use proper path manipulation functions so path variables don't force the user to specify the trailing slash. opts.AddVariables( - PathVariable('openvr_path', 'The path where the OpenVR repo is located.', 'openvr/'), - PathVariable('target_path', 'The path where the lib is installed.', 'demo/addons/godot-openvr/bin/'), - PathVariable('target_name', 'The library name.', 'libgodot_openvr', PathVariable.PathAccept), + EnumVariable('target', "Compilation target", 'release', ['d', 'debug', 'r', 'release']), + EnumVariable('platform', "Compilation platform", 'windows', ['windows', 'x11', 'linux']), + PathVariable('target_path', 'The path where the lib is installed', 'demo/addons/godot-openvr/bin/'), + # TODO: Including the `lib` prefix here causes the ar archive to have it doubled, but need this for DLL. + PathVariable('target_name', 'The library name', 'libgodot_openvr', PathVariable.PathAccept), + BoolVariable('use_mingw', "Use the Mingw compiler, even if MSVC installed", 'no'), + BoolVariable('use_llvm', "Use the LLVM compiler", 'no'), + BoolVariable("use_static_cpp", "Link MinGW/MSVC C++ runtime libraries statically", True), + EnumVariable('bits', "CPU architecture", '64', ['32', '64']), +) + +# Options for locating the OpenVR library +opts.AddVariables( + BoolVariable('builtin_openvr', "Use OpenVR library from submodule instead of system-provided", 'yes'), + PathVariable('openvr_path', 'The path where the OpenVR repo is located, if builtin_openvr is used', 'openvr/'), ) -opts.Add(BoolVariable('use_llvm', "Use the LLVM / Clang compiler", 'no')) -opts.Add(EnumVariable('bits', "CPU architecture", '64', ['32', '64'])) # Other needed paths -godot_headers_path = "godot-cpp/godot-headers/" +godot_headers_path = "godot-cpp/gdextension/" godot_cpp_path = "godot-cpp/" godot_cpp_library = "libgodot-cpp" # Updates the environment with the option variables. opts.Update(env) -# Check some environment settings -if env['use_llvm']: - env['CXX'] = 'clang++' +if env['bits'] == '64': + arch = 'x86_64' +elif env['bits'] == '32': + arch = 'i686' -# fix needed on OSX -def rpath_fix(target, source, env): - os.system('install_name_tool -id @rpath/libgodot_openvr.dylib {0}'.format(target[0])) - os.system('install_name_tool -change @rpath/OpenVR.framework/Versions/A/OpenVR @loader_path/OpenVR.framework/Versions/A/OpenVR {0}'.format(target[0])) +debug = env['target'] in ('debug', 'd') # platform dir for openvr libraries platform_dir = '' @@ -48,22 +56,10 @@ if env['platform'] == 'windows': env['target_path'] += 'win' + env['bits'] + '/' godot_cpp_library += '.windows' platform_dir = 'win' + str(env['bits']) - if not env['use_llvm']: - # This makes sure to keep the session environment variables on windows, - # that way you can run scons in a vs 2017 prompt and it will find all the required tools - env.Append(ENV = os.environ) - env.Append(CPPDEFINES=["WIN32", "_WIN32", "_WINDOWS", "_CRT_SECURE_NO_WARNINGS", "TYPED_METHOD_BIND"]) - env.Append(CCFLAGS=["-W3", "-GR"]) - env.Append(CXXFLAGS=["-std:c++17"]) - if env['target'] in ('debug', 'd'): - env.Append(CPPDEFINES=["_DEBUG"]) - env.Append(CCFLAGS = ['-EHsc', '-MDd', '-ZI', '-FS']) - env.Append(LINKFLAGS = ['-DEBUG']) - else: - env.Append(CCFLAGS = ['-O2', '-EHsc', '-DNDEBUG', '-MD']) - else: + if env['use_llvm']: # untested + env.Tool('clang') env.Append(CPPDEFINES=["WIN32", "_WIN32", "_WINDOWS", "_CRT_SECURE_NO_WARNINGS"]) env.Append(CCFLAGS=["-W3", "-GR"]) env.Append(CXXFLAGS=["-std:c++17"]) @@ -72,25 +68,55 @@ if env['platform'] == 'windows': else: env.Append(CCFLAGS = ['-fPIC', '-g','-O3']) + elif env['use_mingw']: + env.Tool('mingw') + env['CXX'] = f'{arch}-w64-mingw32-g++' + env['AR'] = f'{arch}-w64-mingw32-ar' + env['RANLIB'] = f'{arch}-w64-mingw32-ranlib' + env['LINK'] = f'{arch}-w64-mingw32-g++' + + env.Append(CCFLAGS=['-g', '-O3', '-std=c++17', '-Wwrite-strings']) + env.Append(LINKFLAGS=['-Wl,--no-undefined']) + env.Append(CPPDEFINES=["USE_OPENVR_MINGW_HEADER"]) + + if env["use_static_cpp"]: + env.Append(LINKFLAGS=['-static-libgcc', '-static-libstdc++']) + + else: + env.Tool('default') + # Preserve the environment so that scons can be executed from within Visual Studio and find the correct + # toolchain. TODO: Why is environ duplicated here? + + # Since OpenVR only officially works with binaries compiled by MSVC and the user hasn't set something + # else explicitly, we enforce that we're not accidentally using a fallback toolchain by bailing if MSVC + # isn't chosen here. + env.Append(ENV=os.environ, MSVC_NOTFOUND_POLICY='Error') + + if env["bits"] == "64": + env["TARGET_ARCH"] = "amd64" + elif env["bits"] == "32": + env["TARGET_ARCH"] = "x86" + + env["is_msvc"] = True + env.Append(CPPDEFINES=["WIN32", "_WIN32", "_WINDOWS", "_CRT_SECURE_NO_WARNINGS", "TYPED_METHOD_BIND"]) + env.Append(CCFLAGS=["-W3", "-GR"]) + env.Append(CXXFLAGS=["-std:c++17"]) + if debug: + env.Append(CCFLAGS = ['-EHsc', '-ZI', '-FS']) + env.Append(LINKFLAGS = ['-DEBUG']) + else: + env.Append(CCFLAGS = ['-O2', '-EHsc', '-DNDEBUG']) + + if env["use_static_cpp"]: + env.Append(CCFLAGS=["-MT"]) + else: + env.Append(CCFLAGS=["-MD"]) + openvr_dll_target = env['target_path'] + "openvr_api.dll" openvr_dll_source = env['openvr_path'] + "bin/win" + str(env['bits']) + "/openvr_api.dll" -# no longer supported by OpenVR -#elif env['platform'] == 'osx': -# env['target_path'] += 'osx/' -# godot_cpp_library += '.osx' -# platform_dir = 'osx32' # on OSX this is a universal binary -# if env['target'] in ('debug', 'd'): -# env.Append(CCFLAGS = ['-g','-O2', '-arch', 'x86_64']) -# else: -# env.Append(CCFLAGS = ['-g','-O3', '-arch', 'x86_64']) -# env.Append(CXXFLAGS='-std=c++11') -# env.Append(LINKFLAGS = ['-arch', 'x86_64']) -# -# openvr_dll_target = env['target_path'] + "???" -# openvr_dll_source = env['openvr_path'] + "bin/osx" + str(env['bits']) + "/???" - elif env['platform'] in ('x11', 'linux'): + env.Tool('default') env['target_path'] += 'x11/' godot_cpp_library += '.linux' platform_dir = 'linux' + str(env['bits']) @@ -105,13 +131,13 @@ elif env['platform'] in ('x11', 'linux'): openvr_dll_source = env['openvr_path'] + "bin/linux" + str(env['bits']) + "/libopenvr_api.so" # Complete godot-cpp library path -if env['target'] in ('debug', 'd'): - godot_cpp_library += '.debug' +if debug: + godot_cpp_library += '.template_debug' env.Append(CPPDEFINES=["DEBUG_ENABLED", "DEBUG_METHODS_ENABLED"]) else: - godot_cpp_library += '.release' + godot_cpp_library += '.template_release' -godot_cpp_library += '.' + str(env['bits']) +godot_cpp_library += f'.{arch}' # Update our include search path env.Append(CPPPATH=[ @@ -127,11 +153,22 @@ env.Append(CPPPATH=[ env.Append(LIBPATH=[godot_cpp_path + 'bin/']) env.Append(LIBS=[godot_cpp_library]) -if (os.name == "nt" and os.getenv("VCINSTALLDIR")): +# Add openvr_api, either from the system or the provided path +if not env['builtin_openvr']: + # Discover the system libopenvr if we've been asked to use it. + # `pkg-config` is a Linux-ism, but also may exist in a Windows build environment if e.g. msys2 is in use. + # If the user gave the option, assume they set up the system for it to work. + # Because we won't have the library as a DLL to bundle, build statically. Need to define OPENVR_BUILD_STATIC, + # see https://github.com/ValveSoftware/openvr/issues/1457 + # TODO: Should this use force the other static flags? Is there a better way? + env.ParseConfig('pkg-config openvr --cflags --libs') + env.Append(LINKFLAGS=['-static']) + env.Append(CPPDEFINES=['OPENVR_BUILD_STATIC']) + openvr_dll_target = '' + +elif (os.name == "nt" and os.getenv("VCINSTALLDIR")): env.Append(LIBPATH=[env['openvr_path'] + 'lib/' + platform_dir]) env.Append(LINKFLAGS=['openvr_api.lib']) -elif env['platform'] == "osx": - env.Append(LINKFLAGS = ['-F' + env['openvr_path'] + 'bin/osx32', '-framework', 'OpenVR']) else: env.Append(LIBPATH=[env['openvr_path'] + 'lib/' + platform_dir]) env.Append(LIBS=['openvr_api']) @@ -142,15 +179,13 @@ sources += Glob('src/*.cpp') sources += Glob('src/*/*.c') sources += Glob('src/*/*.cpp') -if env['target'] in ('debug', 'd'): +if debug: env['target_name'] += "_debug" else: env['target_name'] += "_release" # Build our library library = env.SharedLibrary(target=env['target_path'] + env['target_name'], source=sources) -if env['platform'] == "osx": - env.AddPostAction(library, rpath_fix) if openvr_dll_target != '': env.AddPostAction(library, Copy( diff --git a/demo/Main.gd b/demo/Main.gd index 4892b9c..329799a 100644 --- a/demo/Main.gd +++ b/demo/Main.gd @@ -1,18 +1,16 @@ extends Node3D -func _process(delta): +func _process(_delta): # Test for escape to close application, space to reset our reference frame if (Input.is_key_pressed(KEY_ESCAPE)): get_tree().quit() elif (Input.is_key_pressed(KEY_SPACE)): # Calling center_on_hmd will cause the ARVRServer to adjust all tracking data so the player is centered on the origin point looking forward - XRServer.center_on_hmd(true, true) + XRServer.center_on_hmd(XRServer.RESET_FULL_ROTATION, true) # Called when the node enters the scene tree for the first time. func _ready(): - # at the moment we can't seem to extend a gdnative class so we'll do this here - # $Player/Right_Hand/Viewport2Din3D.get_scene_instance().set_controller($Player/Right_Hand) - pass + OpenVRInterface.start_xr() func _on_Right_Hand_action_pressed(action): print("Action pressed " + action) diff --git a/demo/Main.tscn b/demo/Main.tscn index e3814f0..d78ce68 100644 --- a/demo/Main.tscn +++ b/demo/Main.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=23 format=3 uid="uid://ylx5afjemhln"] +[gd_scene load_steps=24 format=3 uid="uid://ylx5afjemhln"] [ext_resource type="Script" path="res://Main.gd" id="1"] [ext_resource type="Material" uid="uid://cok6b068i8j3m" path="res://assets/wahooney.itch.io/green_grid.tres" id="2"] @@ -8,12 +8,13 @@ [ext_resource type="PackedScene" path="res://misc/Table.tscn" id="7"] [ext_resource type="PackedScene" path="res://misc/Box.tscn" id="8"] [ext_resource type="Script" path="res://player/right_controller.gd" id="8_oqay4"] -[ext_resource type="PackedScene" path="res://addons/godot-xr-tools/functions/Function_Teleport.tscn" id="9"] -[ext_resource type="PackedScene" uid="uid://hkoqglc13fsw" path="res://addons/godot-xr-tools/functions/Function_Direct_movement.tscn" id="10"] -[ext_resource type="PackedScene" path="res://misc/Cup.tscn" id="11"] -[ext_resource type="PackedScene" path="res://addons/godot-xr-tools/functions/Function_Pickup.tscn" id="12"] -[ext_resource type="PackedScene" path="res://addons/godot-xr-tools/functions/Function_pointer.tscn" id="14"] -[ext_resource type="PackedScene" uid="uid://dhcsolk3uwmy6" path="res://addons/godot-xr-tools/objects/Viewport_2D_in_3D.tscn" id="15"] +[ext_resource type="PackedScene" path="res://addons/godot-xr-tools/functions/function_teleport.tscn" id="9"] +[ext_resource type="PackedScene" uid="uid://bl2nuu3qhlb5k" path="res://addons/godot-xr-tools/functions/movement_direct.tscn" id="10"] +[ext_resource type="PackedScene" uid="uid://7q2uyb55p6e5" path="res://misc/Cup.tscn" id="11"] +[ext_resource type="PackedScene" path="res://addons/godot-xr-tools/functions/function_pickup.tscn" id="12"] +[ext_resource type="PackedScene" uid="uid://diyu06cw06syv" path="res://addons/godot-xr-tools/player/player_body.tscn" id="12_d8snu"] +[ext_resource type="PackedScene" path="res://addons/godot-xr-tools/functions/function_pointer.tscn" id="14"] +[ext_resource type="PackedScene" path="res://addons/godot-xr-tools/objects/viewport_2d_in_3d.tscn" id="15"] [ext_resource type="PackedScene" uid="uid://bvl8eat4blx3g" path="res://player/ButtonStates.tscn" id="16"] [sub_resource type="QuadMesh" id="QuadMesh_2ndrj"] @@ -32,11 +33,11 @@ size = Vector3(0.01, 0.01, 0.01) albedo_color = Color(0.109804, 0.27451, 1, 1) [sub_resource type="BoxMesh" id="BoxMesh_ynikn"] -material = SubResource( "StandardMaterial3D_8pi1c" ) +material = SubResource("StandardMaterial3D_8pi1c") size = Vector3(0.01, 0.01, 0.01) [sub_resource type="PlaneMesh" id="1"] -material = ExtResource( "2" ) +material = ExtResource("2") size = Vector2(400, 400) subdivide_width = 10 subdivide_depth = 10 @@ -45,7 +46,7 @@ subdivide_depth = 10 size = Vector3(1000, 2, 1000) [node name="Main" type="Node3D"] -script = ExtResource( "1" ) +script = ExtResource("1") [node name="DirectionalLight" type="DirectionalLight3D" parent="."] transform = Transform3D(0.756623, -0.453791, -0.470739, 0.644498, 0.396268, 0.653907, -0.110198, -0.798151, 0.592293, 0, 4, 0) @@ -54,12 +55,15 @@ shadow_bias = 0.01 directional_shadow_max_distance = 50.0 [node name="WorldEnvironment" type="WorldEnvironment" parent="."] -environment = ExtResource( "4" ) +environment = ExtResource("4") -[node name="OVRFirstPerson" parent="." instance=ExtResource( "3_0jmmx" )] +[node name="OVRFirstPerson" parent="." instance=ExtResource("3_0jmmx")] +default_action_set = null +viewport = null +physics_factor = null [node name="HUD_Anchor" parent="OVRFirstPerson" index="1"] -script = ExtResource( "4_n1047" ) +script = ExtResource("4_n1047") [node name="SubViewport" type="SubViewport" parent="OVRFirstPerson/HUD_Anchor" index="0"] disable_3d = true @@ -75,18 +79,17 @@ text = "FPS: 0" [node name="FPSQuad" type="MeshInstance3D" parent="OVRFirstPerson/HUD_Anchor" index="1"] transform = Transform3D(0.965182, 0.11344, 0.235702, -0.0501897, 0.96464, -0.258746, -0.25672, 0.237907, 0.936747, -0.32241, 0.322052, -0.966649) -mesh = SubResource( "QuadMesh_2ndrj" ) -surface_material_override/0 = SubResource( "StandardMaterial3D_ux7rk" ) +mesh = SubResource("QuadMesh_2ndrj") +surface_material_override/0 = SubResource("StandardMaterial3D_ux7rk") [node name="TestCube" type="MeshInstance3D" parent="OVRFirstPerson/Left_Hand" index="1"] -mesh = SubResource( "BoxMesh_jxy6n" ) +mesh = SubResource("BoxMesh_jxy6n") skeleton = NodePath("../../Right_Hand") -[node name="Function_Direct_movement" parent="OVRFirstPerson/Right_Hand" index="0" instance=ExtResource( "10" )] -camera = NodePath("../../XRCamera3D") +[node name="Function_Direct_movement" parent="OVRFirstPerson/Right_Hand" index="0" instance=ExtResource("10")] [node name="TestCube" type="MeshInstance3D" parent="OVRFirstPerson/Right_Hand" index="2"] -mesh = SubResource( "BoxMesh_jxy6n" ) +mesh = SubResource("BoxMesh_jxy6n") [node name="aim_left_hand" type="XRController3D" parent="OVRFirstPerson"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.5, 1.25, 0) @@ -94,58 +97,59 @@ tracker = &"left_hand" pose = &"aim" [node name="TestCube" type="MeshInstance3D" parent="OVRFirstPerson/aim_left_hand"] -mesh = SubResource( "BoxMesh_ynikn" ) +mesh = SubResource("BoxMesh_ynikn") skeleton = NodePath("../../aim_right_hand") -[node name="Function_Teleport" parent="OVRFirstPerson/aim_left_hand" instance=ExtResource( "9" )] +[node name="Function_Teleport" parent="OVRFirstPerson/aim_left_hand" instance=ExtResource("9")] collision_mask = 1022 -camera = NodePath("../../XRCamera3D") -[node name="Function_pointer" parent="OVRFirstPerson/aim_left_hand" instance=ExtResource( "14" )] +[node name="Function_pointer" parent="OVRFirstPerson/aim_left_hand" instance=ExtResource("14")] collision_mask = 2048 [node name="aim_right_hand" type="XRController3D" parent="OVRFirstPerson"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.5, 1.25, 0) tracker = &"right_hand" pose = &"aim" -script = ExtResource( "8_oqay4" ) +script = ExtResource("8_oqay4") [node name="TestCube" type="MeshInstance3D" parent="OVRFirstPerson/aim_right_hand"] -mesh = SubResource( "BoxMesh_ynikn" ) +mesh = SubResource("BoxMesh_ynikn") -[node name="Viewport2Din3D" parent="OVRFirstPerson/aim_right_hand" instance=ExtResource( "15" )] +[node name="Viewport2Din3D" parent="OVRFirstPerson/aim_right_hand" instance=ExtResource("15")] transform = Transform3D(0.960079, 0.211887, -0.182625, -0.163522, 0.954819, 0.248155, 0.226955, -0.208384, 0.95135, 0.167837, 0, 0) screen_size = Vector2(0.3, 0.2) -scene = ExtResource( "16" ) collision_layer = 2048 +scene = ExtResource("16") -[node name="Function_Pickup" parent="OVRFirstPerson/aim_right_hand" instance=ExtResource( "12" )] +[node name="Function_Pickup" parent="OVRFirstPerson/aim_right_hand" instance=ExtResource("12")] + +[node name="PlayerBody" parent="OVRFirstPerson" instance=ExtResource("12_d8snu")] [node name="Floor" type="StaticBody3D" parent="."] collision_layer = 2 collision_mask = 0 [node name="Mesh" type="MeshInstance3D" parent="Floor"] -mesh = SubResource( "1" ) +mesh = SubResource("1") [node name="CollisionShape" type="CollisionShape3D" parent="Floor"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1, 0) -shape = SubResource( "2" ) +shape = SubResource("2") [node name="Objects" type="Node3D" parent="."] -[node name="Table" parent="Objects" instance=ExtResource( "7" )] +[node name="Table" parent="Objects" instance=ExtResource("7")] -[node name="Box01" parent="Objects" instance=ExtResource( "8" )] +[node name="Box01" parent="Objects" instance=ExtResource("8")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1, 1, -2) -[node name="Box02" parent="Objects" instance=ExtResource( "8" )] +[node name="Box02" parent="Objects" instance=ExtResource("8")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -3, 1, 0) -[node name="Box03" parent="Objects" instance=ExtResource( "8" )] +[node name="Box03" parent="Objects" instance=ExtResource("8")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2, 1, -1) -[node name="Cup" parent="Objects" instance=ExtResource( "11" )] +[node name="Cup" parent="Objects" instance=ExtResource("11")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.702487, -6) [connection signal="button_pressed" from="OVRFirstPerson/aim_right_hand" to="OVRFirstPerson/aim_right_hand" method="_on_aim_right_hand_button_pressed"] diff --git a/demo/addons/godot-openvr/EditorPlugin.gd b/demo/addons/godot-openvr/EditorPlugin.gd index 8688a47..5da0172 100644 --- a/demo/addons/godot-openvr/EditorPlugin.gd +++ b/demo/addons/godot-openvr/EditorPlugin.gd @@ -3,6 +3,13 @@ extends EditorPlugin var export_plugin +static var _initialized := false + +func _openvr_init(): + if not _initialized: + add_autoload_singleton("OpenVRInterface", "res://addons/godot-openvr/openvr_autoloader.gd") + _initialized = true + func _enter_tree(): # Initialization of the plugin goes here export_plugin = preload("res://addons/godot-openvr/OpenVRExportPlugin.gd") @@ -19,7 +26,17 @@ func _enter_tree(): #else: # print("Failed to load res://addons/godot-openvr/OpenVRExportPlugin.gd") + _openvr_init() + func _exit_tree(): # Clean-up of the plugin goes here if export_plugin: remove_export_plugin(export_plugin) + +func _enable_plugin(): + _openvr_init() + +func _disable_plugin(): + if _initialized: + remove_autoload_singleton("OpenVRInterface") + _initialized = false diff --git a/demo/addons/godot-openvr/OpenVRExportPlugin.gd b/demo/addons/godot-openvr/OpenVRExportPlugin.gd index 9bdf3ff..7ccdf98 100644 --- a/demo/addons/godot-openvr/OpenVRExportPlugin.gd +++ b/demo/addons/godot-openvr/OpenVRExportPlugin.gd @@ -2,17 +2,17 @@ extends EditorExportPlugin func _export_begin(features: PackedStringArray, is_debug: bool, path: String, flags: int ): - var dir = Directory.new() + var dir = DirAccess.open('res://') # we just want the path var export_to = path.get_base_dir() + "/actions/" # now determine which action files to export var export_from = "" - if dir.file_exists("res://actions/actions.json"): - export_from = "res://actions/" - elif dir.file_exists("res://addons/godot-openvr/actions/actions.json"): - export_from = "res://addons/godot-openvr/actions/" + if dir.file_exists("actions/actions.json"): + export_from = "actions/" + elif dir.file_exists("addons/godot-openvr/actions/actions.json"): + export_from = "addons/godot-openvr/actions/" else: print("WARNING: Couldn't locate actions files to export") return @@ -21,7 +21,8 @@ func _export_begin(features: PackedStringArray, is_debug: bool, path: String, fl if !dir.dir_exists(export_to): dir.make_dir(export_to) - if dir.open(export_from) == OK: + dir = dir.open(export_from) + if dir: dir.include_hidden = false dir.include_navigational = false dir.list_dir_begin() diff --git a/demo/addons/godot-openvr/godot_openvr.gdextension b/demo/addons/godot-openvr/godot_openvr.gdextension index d321dec..3889871 100644 --- a/demo/addons/godot-openvr/godot_openvr.gdextension +++ b/demo/addons/godot-openvr/godot_openvr.gdextension @@ -1,6 +1,7 @@ [configuration] entry_symbol = "openvr_library_init" +compatibility_minimum = 4.1 [libraries] diff --git a/demo/addons/godot-openvr/icon.png.import b/demo/addons/godot-openvr/icon.png.import index 16e6724..e7dedde 100644 --- a/demo/addons/godot-openvr/icon.png.import +++ b/demo/addons/godot-openvr/icon.png.import @@ -1,9 +1,9 @@ [remap] importer="texture" -type="StreamTexture2D" +type="CompressedTexture2D" uid="uid://da8h5o1knx4oe" -path="res://.godot/imported/icon.png-a89ecb8be28ea6c50eeae0c3cb0cd271.stex" +path="res://.godot/imported/icon.png-a89ecb8be28ea6c50eeae0c3cb0cd271.ctex" metadata={ "vram_texture": false } @@ -11,17 +11,16 @@ metadata={ [deps] source_file="res://addons/godot-openvr/icon.png" -dest_files=["res://.godot/imported/icon.png-a89ecb8be28ea6c50eeae0c3cb0cd271.stex"] +dest_files=["res://.godot/imported/icon.png-a89ecb8be28ea6c50eeae0c3cb0cd271.ctex"] [params] compress/mode=0 +compress/high_quality=false compress/lossy_quality=0.7 compress/hdr_compression=1 -compress/bptc_ldr=0 compress/normal_map=0 compress/channel_pack=0 -compress/streamed=false mipmaps/generate=false mipmaps/limit=-1 roughness/mode=0 @@ -29,7 +28,7 @@ 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_as_srgb=false +process/hdr_clamp_exposure=false process/size_limit=0 detect_3d/compress_to=1 -svg/scale=1.0 diff --git a/demo/addons/godot-openvr/meshes/hands_albedo.png.import b/demo/addons/godot-openvr/meshes/hands_albedo.png.import index 1c85070..3ee4147 100644 --- a/demo/addons/godot-openvr/meshes/hands_albedo.png.import +++ b/demo/addons/godot-openvr/meshes/hands_albedo.png.import @@ -1,29 +1,27 @@ [remap] importer="texture" -type="StreamTexture2D" +type="CompressedTexture2D" uid="uid://b0x5noxmh4f3w" -path.s3tc="res://.godot/imported/hands_albedo.png-149a10baba7906560a9f9eab8fadf1d8.s3tc.stex" -path.etc2="res://.godot/imported/hands_albedo.png-149a10baba7906560a9f9eab8fadf1d8.etc2.stex" +path.s3tc="res://.godot/imported/hands_albedo.png-149a10baba7906560a9f9eab8fadf1d8.s3tc.ctex" metadata={ -"imported_formats": ["s3tc", "etc2"], +"imported_formats": ["s3tc_bptc"], "vram_texture": true } [deps] source_file="res://addons/godot-openvr/meshes/hands_albedo.png" -dest_files=["res://.godot/imported/hands_albedo.png-149a10baba7906560a9f9eab8fadf1d8.s3tc.stex", "res://.godot/imported/hands_albedo.png-149a10baba7906560a9f9eab8fadf1d8.etc2.stex"] +dest_files=["res://.godot/imported/hands_albedo.png-149a10baba7906560a9f9eab8fadf1d8.s3tc.ctex"] [params] compress/mode=2 +compress/high_quality=false compress/lossy_quality=0.7 compress/hdr_compression=1 -compress/bptc_ldr=0 compress/normal_map=0 compress/channel_pack=0 -compress/streamed=false mipmaps/generate=true mipmaps/limit=-1 roughness/mode=0 @@ -31,7 +29,7 @@ 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_as_srgb=false +process/hdr_clamp_exposure=false process/size_limit=0 detect_3d/compress_to=0 -svg/scale=1.0 diff --git a/demo/addons/godot-openvr/meshes/hands_normal.png.import b/demo/addons/godot-openvr/meshes/hands_normal.png.import index b1340ce..fdb3040 100644 --- a/demo/addons/godot-openvr/meshes/hands_normal.png.import +++ b/demo/addons/godot-openvr/meshes/hands_normal.png.import @@ -1,29 +1,27 @@ [remap] importer="texture" -type="StreamTexture2D" +type="CompressedTexture2D" uid="uid://csp6exku2abeh" -path.s3tc="res://.godot/imported/hands_normal.png-eab7a86e959f13e1294e8f67904a8873.s3tc.stex" -path.etc2="res://.godot/imported/hands_normal.png-eab7a86e959f13e1294e8f67904a8873.etc2.stex" +path.s3tc="res://.godot/imported/hands_normal.png-eab7a86e959f13e1294e8f67904a8873.s3tc.ctex" metadata={ -"imported_formats": ["s3tc", "etc2"], +"imported_formats": ["s3tc_bptc"], "vram_texture": true } [deps] source_file="res://addons/godot-openvr/meshes/hands_normal.png" -dest_files=["res://.godot/imported/hands_normal.png-eab7a86e959f13e1294e8f67904a8873.s3tc.stex", "res://.godot/imported/hands_normal.png-eab7a86e959f13e1294e8f67904a8873.etc2.stex"] +dest_files=["res://.godot/imported/hands_normal.png-eab7a86e959f13e1294e8f67904a8873.s3tc.ctex"] [params] compress/mode=2 +compress/high_quality=false compress/lossy_quality=0.7 compress/hdr_compression=1 -compress/bptc_ldr=0 compress/normal_map=1 compress/channel_pack=0 -compress/streamed=false mipmaps/generate=true mipmaps/limit=-1 roughness/mode=0 @@ -31,7 +29,7 @@ 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_as_srgb=false +process/hdr_clamp_exposure=false process/size_limit=0 detect_3d/compress_to=0 -svg/scale=1.0 diff --git a/demo/addons/godot-openvr/meshes/vr_glove_left_model_slim.glb.import b/demo/addons/godot-openvr/meshes/vr_glove_left_model_slim.glb.import index 274f862..a3be35d 100644 --- a/demo/addons/godot-openvr/meshes/vr_glove_left_model_slim.glb.import +++ b/demo/addons/godot-openvr/meshes/vr_glove_left_model_slim.glb.import @@ -15,16 +15,20 @@ dest_files=["res://.godot/imported/vr_glove_left_model_slim.glb-8eb4d606fd297e3e nodes/root_type="Node3D" nodes/root_name="Scene Root" +nodes/apply_root_scale=true nodes/root_scale=1.0 meshes/ensure_tangents=true meshes/generate_lods=true meshes/create_shadow_meshes=true meshes/light_baking=0 meshes/lightmap_texel_size=0.1 +meshes/force_disable_compression=false skins/use_named_skins=true animation/import=true -animation/bake_reset_animation=true animation/fps=15 +animation/trimming=false +animation/remove_immutable_tracks=true import_script/path="" -_subresources={ -} +_subresources={} +gltf/naming_version=0 +gltf/embedded_image_handling=1 diff --git a/demo/addons/godot-openvr/meshes/vr_glove_right_model_slim.glb.import b/demo/addons/godot-openvr/meshes/vr_glove_right_model_slim.glb.import index f9da112..51792ec 100644 --- a/demo/addons/godot-openvr/meshes/vr_glove_right_model_slim.glb.import +++ b/demo/addons/godot-openvr/meshes/vr_glove_right_model_slim.glb.import @@ -15,16 +15,20 @@ dest_files=["res://.godot/imported/vr_glove_right_model_slim.glb-c6782795f1fc323 nodes/root_type="Node3D" nodes/root_name="Scene Root" +nodes/apply_root_scale=true nodes/root_scale=1.0 meshes/ensure_tangents=true meshes/generate_lods=true meshes/create_shadow_meshes=true meshes/light_baking=0 meshes/lightmap_texel_size=0.1 +meshes/force_disable_compression=false skins/use_named_skins=true animation/import=true -animation/bake_reset_animation=true animation/fps=15 +animation/trimming=false +animation/remove_immutable_tracks=true import_script/path="" -_subresources={ -} +_subresources={} +gltf/naming_version=0 +gltf/embedded_image_handling=1 diff --git a/demo/addons/godot-openvr/openvr_autoloader.gd b/demo/addons/godot-openvr/openvr_autoloader.gd new file mode 100644 index 0000000..4689151 --- /dev/null +++ b/demo/addons/godot-openvr/openvr_autoloader.gd @@ -0,0 +1,33 @@ +@tool +extends Node + +var _xr_interface_openvr : XRInterfaceOpenVR + +func get_interface(): + return _xr_interface_openvr + +func start_xr(): + if _xr_interface_openvr: + print("Capabilities " + str(_xr_interface_openvr.get_capabilities())) + print("Target size " + str(_xr_interface_openvr.get_render_target_size())) + + if _xr_interface_openvr.initialize(): + get_viewport().use_xr = true + + print("Initialised") + else: + print("Failed to initialise") + else: + print("Interface was not instantiated") + + +func _enter_tree(): + _xr_interface_openvr = XRInterfaceOpenVR.new() + if _xr_interface_openvr: + XRServer.add_interface(_xr_interface_openvr) + + +func _exit_tree(): + if _xr_interface_openvr: + XRServer.remove_interface(_xr_interface_openvr) + _xr_interface_openvr = null diff --git a/demo/addons/godot-openvr/scenes/ovr_render_model.gd b/demo/addons/godot-openvr/scenes/ovr_render_model.gd index a8b8f55..feaa812 100644 --- a/demo/addons/godot-openvr/scenes/ovr_render_model.gd +++ b/demo/addons/godot-openvr/scenes/ovr_render_model.gd @@ -24,7 +24,7 @@ func _load_controller_mesh(controller_name): # Called when the node enters the scene tree for the first time. func _ready(): # instance our render model object - ovr_render_model = OpenVRRenderModel.new() + ovr_render_model = OVRRenderModel3D.new() # we haven't loaded it controller_is_loaded = false diff --git a/demo/addons/godot-xr-tools/CONTRIBUTORS.md b/demo/addons/godot-xr-tools/CONTRIBUTORS.md deleted file mode 100644 index 455da54..0000000 --- a/demo/addons/godot-xr-tools/CONTRIBUTORS.md +++ /dev/null @@ -1,13 +0,0 @@ -Contributors -============ - -The main author of this project is [Bastiaan Olij](https://github.com/BastiaanOlij) who manages the source repository found at: -https://github.com/GodotVR/godot-xr-tools - -Other people who have helped out by submitting fixes, enhancements, etc are: -- [Florian Jung](https://github.com/Windfisch) -- [RMKD](https://github.com/RMKD) -- [Alessandro Schillaci](https://github.com/silverslade) -- [jtank4](https://github.com/jtank4) - -Want to be on this list? We would love your help. diff --git a/demo/addons/godot-xr-tools/LICENSE b/demo/addons/godot-xr-tools/LICENSE deleted file mode 100644 index 9cc3741..0000000 --- a/demo/addons/godot-xr-tools/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2018-2020 Bastiaan Olij - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/demo/addons/godot-xr-tools/VERSIONS.md b/demo/addons/godot-xr-tools/VERSIONS.md deleted file mode 100644 index caf56d5..0000000 --- a/demo/addons/godot-xr-tools/VERSIONS.md +++ /dev/null @@ -1,34 +0,0 @@ -# 3.0 -- Ported XR tools to Godot 4 - -# 2.1 -- added option to highlight object that can be picked up -- added option to snap object to given location (if reset transform is true) -- added callback when shader cache has finished -- using proper UI for layers -- added hand controllers that react on trigger and grip input -- fixed delta on move and slide (breaking change!) -- letting go of an object now adds angular velocity - -# 2.0 -- Renamed add on to **godot-xr-tools** -- Add enums to our export variables -- Add a switch on pickable objects to keep their current positioning when picked up -- Move direct movement player collision slightly backwards based on player radius -- Added switch between step turning and smooth turning -- Fixed sizing issue with teleport -- Added option to change pickup range - -# 1.2 -- Assign button to teleport function and no longer need to set origin -- Added pickable object support -- Fixed positioning of direct movement collision shape -- Added strafe and fly mode for directional -- Added ability to enable/disable the movement functions -- Added 2D in 3D viewport for UI -- Improved throwing by assigning linear velocity - -# 1.1* -- previous versions were not tracked - -* Note that version history before 1.2 was not kept and is thus incomplete diff --git a/demo/addons/godot-xr-tools/assets/LeftHand.gd b/demo/addons/godot-xr-tools/assets/LeftHand.gd deleted file mode 100644 index 9d6aa10..0000000 --- a/demo/addons/godot-xr-tools/assets/LeftHand.gd +++ /dev/null @@ -1,16 +0,0 @@ -extends Node3D - -# Called every frame. 'delta' is the elapsed time since the previous frame. -func _process(delta): - var controller : XRController3D = get_parent() - if controller: - var grip = controller.get_joystick_axis(4) * 2.5 - var trigger = controller.get_joystick_axis(2) * 2.5 - - # print("Grip: " + str(grip) + " Trigger: " + str(trigger)) - - $AnimationTree.set("parameters/SetGrip/seek_position", grip) - $AnimationTree.set("parameters/SetIndex/seek_position", trigger) - - # var grip_state = controller.is_button_pressed(JOY_VR_GRIP) - # print("Pressed: " + str(grip_state)) diff --git a/demo/addons/godot-xr-tools/assets/LeftHand.glb b/demo/addons/godot-xr-tools/assets/LeftHand.glb deleted file mode 100644 index b03a7fc466f68833b67f43fdbc462ff12eb53640..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 153828 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 c<$B2Tq4t~)^jd;GAEeh;M1& diff --git a/demo/addons/godot-xr-tools/assets/LeftHand.glb.import b/demo/addons/godot-xr-tools/assets/LeftHand.glb.import deleted file mode 100644 index 2117c24..0000000 --- a/demo/addons/godot-xr-tools/assets/LeftHand.glb.import +++ /dev/null @@ -1,30 +0,0 @@ -[remap] - -importer="scene" -importer_version=1 -type="PackedScene" -uid="uid://cg3px7tvpwehi" -path="res://.godot/imported/LeftHand.glb-7a289350d7a0389e0068af98c6813b91.scn" - -[deps] - -source_file="res://addons/godot-xr-tools/assets/LeftHand.glb" -dest_files=["res://.godot/imported/LeftHand.glb-7a289350d7a0389e0068af98c6813b91.scn"] - -[params] - -nodes/root_type="Node3D" -nodes/root_name="Scene Root" -nodes/root_scale=1.0 -meshes/ensure_tangents=true -meshes/generate_lods=true -meshes/create_shadow_meshes=true -meshes/light_baking=0 -meshes/lightmap_texel_size=0.1 -skins/use_named_skins=true -animation/import=true -animation/bake_reset_animation=true -animation/fps=15 -import_script/path="" -_subresources={ -} diff --git a/demo/addons/godot-xr-tools/assets/LeftHand.tscn b/demo/addons/godot-xr-tools/assets/LeftHand.tscn deleted file mode 100644 index 85cce31..0000000 --- a/demo/addons/godot-xr-tools/assets/LeftHand.tscn +++ /dev/null @@ -1,500 +0,0 @@ -[gd_scene load_steps=7 format=2] - -[ext_resource path="res://addons/godot-xr-tools/assets/LeftHand.gd" type="Script" id=2] -[ext_resource path="res://addons/godot-xr-tools/assets/LeftHandBlendTree.tres" type="AnimationNodeBlendTree" id=3] - -[sub_resource type="ArrayMesh" id=1] -resource_name = "Hand_Left" -surfaces/0 = { -"aabb": AABB( -0.153109, -0.102447, -0.053098, 0.203424, 0.196795, 0.409204 ), -"array_data": PoolByteArray( 43, 71, 52, 61, 236, 86, 16, 60, 70, 93, 106, 61, 115, 51, 9, 0, 7, 8, 130, 127, 191, 52, 72, 50, 8, 4, 1, 0, 105, 167, 99, 40, 162, 25, 143, 22, 237, 22, 78, 61, 135, 12, 123, 60, 155, 102, 199, 186, 115, 51, 9, 0, 5, 10, 130, 127, 59, 55, 72, 50, 0, 1, 0, 0, 218, 217, 36, 38, 0, 0, 0, 0, 44, 14, 234, 60, 249, 66, 84, 61, 68, 8, 102, 60, 115, 51, 9, 0, 6, 9, 130, 127, 59, 55, 63, 41, 0, 1, 0, 0, 121, 166, 133, 89, 0, 0, 0, 0, 137, 144, 230, 60, 197, 136, 76, 61, 69, 118, 161, 61, 115, 51, 9, 0, 7, 6, 130, 127, 191, 52, 63, 41, 4, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 43, 71, 52, 61, 236, 86, 16, 60, 70, 93, 106, 61, 123, 231, 14, 0, 233, 133, 237, 127, 191, 52, 72, 50, 8, 4, 1, 0, 105, 167, 99, 40, 162, 25, 143, 22, 0, 238, 14, 61, 139, 127, 6, 189, 66, 187, 51, 61, 123, 231, 14, 0, 236, 137, 219, 127, 59, 55, 72, 50, 16, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 184, 211, 49, 61, 2, 127, 233, 188, 70, 68, 205, 186, 123, 231, 14, 0, 233, 133, 241, 127, 59, 55, 63, 41, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 237, 22, 78, 61, 135, 12, 123, 60, 155, 102, 199, 186, 123, 231, 14, 0, 231, 132, 0, 127, 191, 52, 63, 41, 0, 1, 0, 0, 218, 217, 36, 38, 0, 0, 0, 0, 0, 238, 14, 61, 139, 127, 6, 189, 66, 187, 51, 61, 83, 161, 252, 0, 162, 172, 7, 127, 191, 52, 72, 50, 16, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 217, 209, 6, 60, 92, 232, 123, 189, 128, 55, 27, 61, 83, 161, 252, 0, 162, 174, 238, 127, 59, 55, 72, 50, 16, 0, 0, 0, 48, 209, 206, 46, 0, 0, 0, 0, 48, 132, 3, 60, 255, 203, 95, 189, 150, 101, 243, 59, 83, 161, 252, 0, 161, 172, 4, 127, 59, 55, 63, 41, 16, 0, 0, 0, 240, 180, 14, 75, 0, 0, 0, 0, 184, 211, 49, 61, 2, 127, 233, 188, 70, 68, 205, 186, 83, 161, 252, 0, 164, 174, 25, 127, 191, 52, 63, 41, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 217, 209, 6, 60, 92, 232, 123, 189, 128, 55, 27, 61, 4, 137, 215, 0, 130, 249, 8, 127, 191, 52, 72, 50, 16, 0, 0, 0, 48, 209, 206, 46, 0, 0, 0, 0, 220, 144, 154, 188, 115, 30, 136, 189, 168, 219, 30, 61, 4, 137, 215, 0, 130, 249, 9, 127, 59, 55, 72, 50, 16, 0, 0, 0, 54, 212, 200, 43, 0, 0, 0, 0, 114, 117, 156, 188, 147, 48, 88, 189, 89, 99, 39, 60, 4, 137, 215, 0, 130, 249, 8, 127, 59, 55, 63, 41, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 48, 132, 3, 60, 255, 203, 95, 189, 150, 101, 243, 59, 4, 137, 215, 0, 130, 250, 7, 127, 191, 52, 63, 41, 16, 0, 0, 0, 240, 180, 14, 75, 0, 0, 0, 0, 48, 248, 55, 189, 205, 74, 56, 189, 126, 212, 98, 61, 166, 175, 219, 0, 7, 46, 139, 127, 109, 58, 72, 55, 16, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 2, 253, 32, 189, 33, 195, 2, 189, 118, 162, 84, 60, 166, 175, 219, 0, 16, 37, 136, 127, 172, 59, 72, 55, 0, 1, 0, 0, 156, 193, 98, 62, 0, 0, 0, 0, 114, 117, 156, 188, 147, 48, 88, 189, 89, 99, 39, 60, 166, 175, 219, 0, 8, 45, 138, 127, 172, 59, 204, 52, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 220, 144, 154, 188, 115, 30, 136, 189, 168, 219, 30, 61, 166, 175, 219, 0, 255, 54, 142, 127, 109, 58, 204, 52, 16, 0, 0, 0, 54, 212, 200, 43, 0, 0, 0, 0, 151, 86, 174, 189, 130, 147, 138, 61, 93, 145, 146, 61, 207, 81, 172, 0, 77, 90, 42, 127, 191, 52, 72, 50, 1, 2, 3, 0, 67, 176, 37, 54, 149, 25, 0, 0, 69, 96, 83, 189, 175, 57, 193, 61, 124, 215, 194, 61, 207, 81, 172, 0, 77, 90, 42, 127, 59, 55, 72, 50, 1, 2, 0, 0, 52, 152, 202, 103, 0, 0, 0, 0, 162, 250, 144, 188, 67, 207, 138, 61, 86, 80, 4, 61, 207, 81, 172, 0, 77, 90, 42, 127, 59, 55, 63, 41, 1, 2, 4, 0, 121, 189, 220, 37, 169, 28, 0, 0, 197, 98, 87, 189, 182, 94, 111, 60, 245, 89, 152, 60, 207, 81, 172, 0, 78, 90, 42, 127, 191, 52, 63, 41, 1, 0, 0, 0, 222, 172, 32, 83, 0, 0, 0, 0, 172, 71, 15, 61, 88, 98, 70, 61, 44, 255, 17, 62, 125, 19, 3, 0, 254, 248, 126, 127, 191, 52, 72, 50, 4, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 67, 142, 19, 61, 18, 247, 62, 61, 142, 152, 69, 62, 125, 19, 3, 0, 254, 251, 126, 127, 59, 55, 72, 50, 5, 4, 8, 0, 117, 151, 127, 53, 9, 51, 0, 0, 170, 134, 45, 61, 2, 80, 204, 187, 185, 215, 53, 62, 125, 19, 3, 0, 254, 248, 126, 127, 59, 55, 63, 41, 13, 12, 14, 0, 176, 169, 12, 73, 65, 13, 0, 0, 77, 234, 57, 61, 49, 130, 144, 186, 198, 140, 254, 61, 125, 19, 3, 0, 255, 245, 126, 127, 191, 52, 63, 41, 8, 16, 0, 0, 89, 181, 165, 74, 0, 0, 0, 0, 34, 13, 29, 61, 237, 105, 75, 189, 220, 143, 220, 61, 107, 188, 253, 0, 250, 238, 125, 127, 191, 52, 72, 50, 16, 8, 0, 0, 64, 191, 190, 64, 0, 0, 0, 0, 207, 28, 238, 60, 245, 228, 116, 189, 83, 206, 38, 62, 107, 188, 253, 0, 244, 229, 123, 127, 59, 55, 72, 50, 16, 17, 18, 0, 51, 183, 125, 57, 77, 15, 0, 0, 76, 196, 114, 60, 13, 112, 182, 189, 49, 144, 23, 62, 107, 188, 253, 0, 247, 235, 124, 127, 59, 55, 63, 41, 16, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 42, 233, 78, 60, 27, 155, 167, 189, 173, 141, 198, 61, 107, 188, 253, 0, 253, 244, 126, 127, 191, 52, 63, 41, 16, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 76, 196, 114, 60, 13, 112, 182, 189, 49, 144, 23, 62, 6, 131, 237, 0, 130, 249, 5, 127, 191, 52, 72, 50, 16, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 158, 192, 128, 188, 228, 235, 186, 189, 88, 139, 24, 62, 6, 131, 237, 0, 130, 249, 4, 127, 59, 55, 72, 50, 16, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 235, 28, 169, 188, 177, 187, 170, 189, 88, 144, 202, 61, 6, 131, 237, 0, 130, 249, 6, 127, 59, 55, 63, 41, 16, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 42, 233, 78, 60, 27, 155, 167, 189, 173, 141, 198, 61, 6, 131, 237, 0, 130, 249, 7, 127, 191, 52, 63, 41, 16, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 158, 192, 128, 188, 228, 235, 186, 189, 88, 139, 24, 62, 142, 209, 27, 0, 233, 99, 75, 127, 109, 58, 72, 55, 16, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 147, 153, 81, 188, 81, 96, 115, 189, 157, 252, 49, 62, 142, 209, 27, 0, 239, 91, 86, 127, 172, 59, 72, 55, 17, 16, 0, 0, 32, 139, 222, 116, 0, 0, 0, 0, 234, 123, 30, 189, 170, 167, 104, 189, 82, 23, 232, 61, 142, 209, 27, 0, 227, 106, 62, 127, 172, 59, 204, 52, 16, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 235, 28, 169, 188, 177, 187, 170, 189, 88, 144, 202, 61, 142, 209, 27, 0, 220, 112, 46, 127, 109, 58, 204, 52, 16, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 147, 153, 81, 188, 81, 96, 115, 189, 157, 252, 49, 62, 143, 4, 56, 0, 22, 119, 35, 127, 109, 58, 72, 55, 17, 16, 0, 0, 32, 139, 222, 116, 0, 0, 0, 0, 184, 144, 161, 58, 217, 160, 76, 188, 90, 232, 66, 62, 143, 4, 56, 0, 26, 115, 44, 127, 172, 59, 72, 55, 8, 9, 0, 0, 151, 187, 103, 68, 0, 0, 0, 0, 176, 217, 22, 189, 53, 173, 29, 188, 94, 30, 249, 61, 143, 4, 56, 0, 18, 122, 28, 127, 172, 59, 204, 52, 12, 4, 5, 0, 237, 174, 73, 49, 199, 31, 0, 0, 234, 123, 30, 189, 170, 167, 104, 189, 82, 23, 232, 61, 143, 4, 56, 0, 13, 125, 17, 127, 109, 58, 204, 52, 16, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 47, 84, 55, 189, 70, 94, 121, 188, 183, 30, 168, 62, 163, 210, 72, 0, 64, 33, 104, 127, 191, 52, 72, 50, 11, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 247, 65, 9, 189, 121, 229, 26, 188, 223, 211, 177, 62, 163, 210, 72, 0, 64, 33, 104, 127, 59, 55, 72, 50, 11, 10, 0, 0, 109, 233, 145, 22, 0, 0, 0, 0, 140, 217, 37, 189, 48, 238, 81, 60, 151, 49, 180, 62, 163, 210, 72, 0, 64, 33, 104, 127, 59, 55, 63, 41, 11, 10, 0, 0, 233, 233, 21, 22, 0, 0, 0, 0, 99, 173, 85, 189, 147, 112, 216, 59, 63, 220, 170, 62, 163, 210, 72, 0, 64, 34, 104, 127, 191, 52, 63, 41, 11, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 182, 67, 140, 186, 5, 43, 165, 61, 126, 69, 214, 61, 34, 122, 250, 0, 227, 1, 133, 127, 191, 52, 72, 50, 4, 1, 2, 0, 162, 123, 7, 70, 84, 62, 0, 0, 162, 250, 144, 188, 67, 207, 138, 61, 86, 80, 4, 61, 34, 122, 250, 0, 234, 0, 131, 127, 59, 55, 72, 50, 1, 2, 4, 0, 121, 189, 220, 37, 169, 28, 0, 0, 69, 96, 83, 189, 175, 57, 193, 61, 124, 215, 194, 61, 34, 122, 250, 0, 225, 2, 133, 127, 59, 55, 63, 41, 1, 2, 0, 0, 52, 152, 202, 103, 0, 0, 0, 0, 154, 90, 46, 189, 36, 249, 163, 61, 114, 119, 8, 62, 34, 122, 250, 0, 216, 5, 136, 127, 191, 52, 63, 41, 2, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 224, 29, 15, 190, 16, 167, 125, 61, 220, 230, 68, 62, 210, 246, 117, 0, 106, 50, 46, 127, 191, 52, 72, 50, 3, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 168, 27, 244, 189, 191, 129, 151, 61, 76, 49, 78, 62, 210, 246, 117, 0, 102, 59, 45, 127, 59, 55, 72, 50, 3, 2, 0, 0, 46, 221, 208, 34, 0, 0, 0, 0, 103, 84, 4, 190, 220, 250, 183, 61, 166, 190, 75, 62, 210, 246, 117, 0, 105, 53, 46, 127, 59, 55, 63, 41, 3, 2, 0, 0, 71, 251, 183, 4, 0, 0, 0, 0, 169, 200, 28, 190, 120, 219, 163, 61, 97, 15, 65, 62, 210, 246, 117, 0, 109, 44, 47, 127, 191, 52, 63, 41, 3, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 65, 101, 141, 189, 47, 156, 31, 188, 216, 229, 167, 61, 136, 228, 230, 0, 218, 90, 79, 127, 109, 58, 72, 55, 1, 8, 4, 0, 83, 159, 119, 72, 51, 24, 0, 0, 31, 57, 161, 189, 158, 246, 21, 61, 80, 77, 237, 61, 136, 228, 230, 0, 218, 98, 70, 127, 172, 59, 72, 55, 2, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 151, 86, 174, 189, 130, 147, 138, 61, 93, 145, 146, 61, 136, 228, 230, 0, 218, 91, 78, 127, 172, 59, 204, 52, 1, 2, 3, 0, 67, 176, 37, 54, 149, 25, 0, 0, 197, 98, 87, 189, 182, 94, 111, 60, 245, 89, 152, 60, 136, 228, 230, 0, 218, 85, 85, 127, 109, 58, 204, 52, 1, 0, 0, 0, 222, 172, 32, 83, 0, 0, 0, 0, 42, 233, 78, 60, 27, 155, 167, 189, 173, 141, 198, 61, 97, 181, 227, 0, 248, 36, 135, 127, 191, 52, 72, 50, 16, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 217, 209, 6, 60, 92, 232, 123, 189, 128, 55, 27, 61, 97, 181, 227, 0, 251, 38, 136, 127, 59, 55, 72, 50, 16, 0, 0, 0, 48, 209, 206, 46, 0, 0, 0, 0, 0, 238, 14, 61, 139, 127, 6, 189, 66, 187, 51, 61, 97, 181, 227, 0, 249, 37, 135, 127, 59, 55, 63, 41, 16, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 34, 13, 29, 61, 237, 105, 75, 189, 220, 143, 220, 61, 97, 181, 227, 0, 247, 34, 135, 127, 191, 52, 63, 41, 16, 8, 0, 0, 64, 191, 190, 64, 0, 0, 0, 0, 235, 28, 169, 188, 177, 187, 170, 189, 88, 144, 202, 61, 11, 136, 219, 0, 251, 37, 135, 127, 191, 52, 72, 50, 16, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 220, 144, 154, 188, 115, 30, 136, 189, 168, 219, 30, 61, 11, 136, 219, 0, 3, 38, 135, 127, 59, 55, 72, 50, 16, 0, 0, 0, 54, 212, 200, 43, 0, 0, 0, 0, 217, 209, 6, 60, 92, 232, 123, 189, 128, 55, 27, 61, 11, 136, 219, 0, 0, 38, 135, 127, 59, 55, 63, 41, 16, 0, 0, 0, 48, 209, 206, 46, 0, 0, 0, 0, 42, 233, 78, 60, 27, 155, 167, 189, 173, 141, 198, 61, 11, 136, 219, 0, 248, 37, 135, 127, 191, 52, 63, 41, 16, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 234, 123, 30, 189, 170, 167, 104, 189, 82, 23, 232, 61, 159, 177, 241, 0, 252, 29, 133, 127, 109, 58, 72, 55, 16, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 48, 248, 55, 189, 205, 74, 56, 189, 126, 212, 98, 61, 159, 177, 241, 0, 251, 31, 134, 127, 172, 59, 72, 55, 16, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 220, 144, 154, 188, 115, 30, 136, 189, 168, 219, 30, 61, 159, 177, 241, 0, 251, 30, 133, 127, 172, 59, 204, 52, 16, 0, 0, 0, 54, 212, 200, 43, 0, 0, 0, 0, 235, 28, 169, 188, 177, 187, 170, 189, 88, 144, 202, 61, 159, 177, 241, 0, 253, 28, 133, 127, 109, 58, 204, 52, 16, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 193, 149, 82, 189, 225, 157, 131, 189, 95, 91, 156, 62, 132, 1, 24, 0, 9, 118, 45, 127, 191, 52, 72, 50, 15, 14, 0, 0, 156, 239, 98, 16, 0, 0, 0, 0, 158, 73, 60, 189, 22, 1, 56, 189, 13, 131, 160, 62, 132, 1, 24, 0, 11, 115, 52, 127, 59, 55, 72, 50, 15, 14, 0, 0, 54, 249, 200, 6, 0, 0, 0, 0, 240, 122, 90, 189, 79, 11, 35, 189, 77, 183, 150, 62, 132, 1, 24, 0, 10, 117, 47, 127, 59, 55, 63, 41, 15, 14, 0, 0, 226, 226, 28, 29, 0, 0, 0, 0, 162, 252, 83, 189, 161, 36, 135, 189, 30, 199, 145, 62, 132, 1, 24, 0, 9, 119, 41, 127, 191, 52, 63, 41, 15, 14, 0, 0, 101, 231, 153, 24, 0, 0, 0, 0, 77, 234, 57, 61, 49, 130, 144, 186, 198, 140, 254, 61, 123, 229, 10, 0, 242, 239, 125, 127, 191, 52, 72, 50, 8, 16, 0, 0, 89, 181, 165, 74, 0, 0, 0, 0, 170, 134, 45, 61, 2, 80, 204, 187, 185, 215, 53, 62, 123, 229, 10, 0, 244, 246, 125, 127, 59, 55, 72, 50, 13, 12, 14, 0, 176, 169, 12, 73, 65, 13, 0, 0, 207, 28, 238, 60, 245, 228, 116, 189, 83, 206, 38, 62, 123, 229, 10, 0, 242, 239, 125, 127, 59, 55, 63, 41, 16, 17, 18, 0, 51, 183, 125, 57, 77, 15, 0, 0, 34, 13, 29, 61, 237, 105, 75, 189, 220, 143, 220, 61, 123, 229, 10, 0, 241, 233, 123, 127, 191, 52, 63, 41, 16, 8, 0, 0, 64, 191, 190, 64, 0, 0, 0, 0, 0, 238, 14, 61, 139, 127, 6, 189, 66, 187, 51, 61, 125, 237, 248, 0, 21, 118, 39, 127, 191, 52, 72, 50, 16, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 43, 71, 52, 61, 236, 86, 16, 60, 70, 93, 106, 61, 125, 237, 248, 0, 21, 119, 38, 127, 59, 55, 72, 50, 8, 4, 1, 0, 105, 167, 99, 40, 162, 25, 143, 22, 77, 234, 57, 61, 49, 130, 144, 186, 198, 140, 254, 61, 125, 237, 248, 0, 21, 118, 39, 127, 59, 55, 63, 41, 8, 16, 0, 0, 89, 181, 165, 74, 0, 0, 0, 0, 34, 13, 29, 61, 237, 105, 75, 189, 220, 143, 220, 61, 125, 237, 248, 0, 21, 118, 40, 127, 191, 52, 63, 41, 16, 8, 0, 0, 64, 191, 190, 64, 0, 0, 0, 0, 137, 144, 230, 60, 197, 136, 76, 61, 69, 118, 161, 61, 121, 37, 252, 0, 8, 245, 126, 127, 191, 52, 72, 50, 4, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 172, 71, 15, 61, 88, 98, 70, 61, 44, 255, 17, 62, 121, 37, 252, 0, 6, 251, 126, 127, 59, 55, 72, 50, 4, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 77, 234, 57, 61, 49, 130, 144, 186, 198, 140, 254, 61, 121, 37, 252, 0, 7, 247, 126, 127, 59, 55, 63, 41, 8, 16, 0, 0, 89, 181, 165, 74, 0, 0, 0, 0, 43, 71, 52, 61, 236, 86, 16, 60, 70, 93, 106, 61, 121, 37, 252, 0, 9, 240, 125, 127, 191, 52, 63, 41, 8, 4, 1, 0, 105, 167, 99, 40, 162, 25, 143, 22, 219, 227, 252, 58, 125, 188, 171, 61, 252, 29, 23, 62, 100, 75, 243, 0, 16, 0, 125, 127, 191, 52, 72, 50, 4, 2, 0, 0, 9, 223, 245, 32, 0, 0, 0, 0, 67, 239, 90, 60, 92, 225, 175, 61, 221, 152, 67, 62, 100, 75, 243, 0, 19, 253, 125, 127, 59, 55, 72, 50, 5, 6, 0, 0, 33, 204, 221, 51, 0, 0, 0, 0, 67, 142, 19, 61, 18, 247, 62, 61, 142, 152, 69, 62, 100, 75, 243, 0, 16, 0, 125, 127, 59, 55, 63, 41, 5, 4, 8, 0, 117, 151, 127, 53, 9, 51, 0, 0, 172, 71, 15, 61, 88, 98, 70, 61, 44, 255, 17, 62, 100, 75, 243, 0, 14, 3, 126, 127, 191, 52, 63, 41, 4, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 233, 30, 184, 188, 57, 92, 83, 61, 163, 60, 178, 62, 214, 234, 117, 0, 109, 44, 47, 127, 191, 52, 72, 50, 7, 6, 0, 0, 176, 224, 78, 31, 0, 0, 0, 0, 153, 159, 221, 187, 197, 176, 107, 61, 245, 96, 181, 62, 214, 234, 117, 0, 110, 41, 47, 127, 59, 55, 72, 50, 7, 6, 0, 0, 121, 242, 133, 13, 0, 0, 0, 0, 27, 55, 116, 188, 38, 255, 162, 61, 146, 83, 182, 62, 214, 234, 117, 0, 108, 44, 47, 127, 59, 55, 63, 41, 7, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 47, 142, 5, 189, 237, 27, 147, 61, 235, 245, 177, 62, 214, 234, 117, 0, 107, 47, 47, 127, 191, 52, 63, 41, 7, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 35, 60, 84, 189, 21, 183, 157, 189, 111, 80, 111, 62, 136, 29, 27, 0, 221, 139, 224, 127, 191, 52, 72, 50, 19, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 143, 211, 104, 189, 137, 57, 199, 189, 77, 4, 101, 62, 136, 29, 27, 0, 218, 148, 204, 127, 59, 55, 72, 50, 19, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 231, 63, 93, 189, 135, 36, 197, 189, 66, 147, 122, 62, 136, 29, 27, 0, 220, 141, 218, 127, 59, 55, 63, 41, 19, 18, 0, 0, 251, 242, 3, 13, 0, 0, 0, 0, 184, 230, 64, 189, 201, 226, 159, 189, 248, 251, 123, 62, 136, 29, 27, 0, 224, 134, 245, 127, 191, 52, 63, 41, 19, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 58, 104, 16, 61, 94, 156, 135, 59, 33, 185, 127, 62, 125, 14, 12, 0, 11, 6, 130, 127, 191, 52, 72, 50, 9, 10, 0, 0, 27, 233, 227, 22, 0, 0, 0, 0, 170, 134, 45, 61, 2, 80, 204, 187, 185, 215, 53, 62, 125, 14, 12, 0, 14, 239, 132, 127, 59, 55, 72, 50, 13, 12, 14, 0, 176, 169, 12, 73, 65, 13, 0, 0, 67, 142, 19, 61, 18, 247, 62, 61, 142, 152, 69, 62, 125, 14, 12, 0, 13, 250, 130, 127, 59, 55, 63, 41, 5, 4, 8, 0, 117, 151, 127, 53, 9, 51, 0, 0, 187, 94, 243, 60, 171, 55, 13, 61, 141, 170, 132, 62, 125, 14, 12, 0, 9, 22, 132, 127, 191, 52, 63, 41, 10, 9, 8, 0, 213, 138, 115, 116, 181, 0, 0, 0, 109, 13, 40, 60, 53, 149, 157, 187, 196, 14, 121, 62, 29, 134, 17, 0, 1, 239, 131, 127, 191, 52, 72, 50, 9, 8, 0, 0, 242, 226, 12, 29, 0, 0, 0, 0, 184, 144, 161, 58, 217, 160, 76, 188, 90, 232, 66, 62, 29, 134, 17, 0, 236, 234, 133, 127, 59, 55, 72, 50, 8, 9, 0, 0, 151, 187, 103, 68, 0, 0, 0, 0, 170, 134, 45, 61, 2, 80, 204, 187, 185, 215, 53, 62, 29, 134, 17, 0, 246, 236, 132, 127, 59, 55, 63, 41, 13, 12, 14, 0, 176, 169, 12, 73, 65, 13, 0, 0, 58, 104, 16, 61, 94, 156, 135, 59, 33, 185, 127, 62, 29, 134, 17, 0, 11, 242, 131, 127, 191, 52, 63, 41, 9, 10, 0, 0, 27, 233, 227, 22, 0, 0, 0, 0, 182, 133, 38, 184, 10, 247, 251, 60, 1, 78, 130, 62, 136, 223, 20, 0, 236, 255, 131, 127, 109, 58, 72, 55, 9, 5, 13, 0, 231, 203, 75, 46, 204, 5, 0, 0, 68, 233, 248, 187, 157, 232, 21, 61, 102, 77, 82, 62, 136, 223, 20, 0, 232, 13, 133, 127, 172, 59, 72, 55, 5, 4, 0, 0, 208, 181, 46, 74, 0, 0, 0, 0, 184, 144, 161, 58, 217, 160, 76, 188, 90, 232, 66, 62, 136, 223, 20, 0, 235, 1, 131, 127, 172, 59, 204, 52, 8, 9, 0, 0, 151, 187, 103, 68, 0, 0, 0, 0, 109, 13, 40, 60, 53, 149, 157, 187, 196, 14, 121, 62, 136, 223, 20, 0, 240, 240, 132, 127, 109, 58, 204, 52, 9, 8, 0, 0, 242, 226, 12, 29, 0, 0, 0, 0, 187, 94, 243, 60, 171, 55, 13, 61, 141, 170, 132, 62, 235, 123, 19, 0, 252, 18, 131, 127, 191, 52, 72, 50, 10, 9, 8, 0, 213, 138, 115, 116, 181, 0, 0, 0, 67, 142, 19, 61, 18, 247, 62, 61, 142, 152, 69, 62, 235, 123, 19, 0, 12, 21, 132, 127, 59, 55, 72, 50, 5, 4, 8, 0, 117, 151, 127, 53, 9, 51, 0, 0, 68, 233, 248, 187, 157, 232, 21, 61, 102, 77, 82, 62, 235, 123, 19, 0, 3, 20, 131, 127, 59, 55, 63, 41, 5, 4, 0, 0, 208, 181, 46, 74, 0, 0, 0, 0, 182, 133, 38, 184, 10, 247, 251, 60, 1, 78, 130, 62, 235, 123, 19, 0, 237, 16, 132, 127, 191, 52, 63, 41, 9, 5, 13, 0, 231, 203, 75, 46, 204, 5, 0, 0, 187, 150, 195, 58, 227, 167, 203, 188, 168, 127, 102, 62, 133, 8, 28, 0, 230, 22, 134, 127, 109, 58, 72, 55, 13, 14, 0, 0, 213, 167, 41, 88, 0, 0, 0, 0, 184, 144, 161, 58, 217, 160, 76, 188, 90, 232, 66, 62, 133, 8, 28, 0, 233, 44, 140, 127, 172, 59, 72, 55, 8, 9, 0, 0, 151, 187, 103, 68, 0, 0, 0, 0, 147, 153, 81, 188, 81, 96, 115, 189, 157, 252, 49, 62, 133, 8, 28, 0, 230, 22, 134, 127, 172, 59, 204, 52, 17, 16, 0, 0, 32, 139, 222, 116, 0, 0, 0, 0, 244, 199, 157, 59, 190, 88, 114, 189, 243, 107, 97, 62, 133, 8, 28, 0, 228, 255, 133, 127, 109, 58, 204, 52, 13, 14, 12, 0, 53, 213, 146, 24, 54, 18, 0, 0, 143, 150, 227, 60, 143, 181, 252, 188, 30, 89, 119, 62, 254, 119, 44, 0, 14, 44, 138, 127, 191, 52, 72, 50, 13, 14, 8, 0, 67, 126, 67, 126, 119, 3, 0, 0, 170, 134, 45, 61, 2, 80, 204, 187, 185, 215, 53, 62, 254, 119, 44, 0, 26, 43, 140, 127, 59, 55, 72, 50, 13, 12, 14, 0, 176, 169, 12, 73, 65, 13, 0, 0, 184, 144, 161, 58, 217, 160, 76, 188, 90, 232, 66, 62, 254, 119, 44, 0, 20, 44, 139, 127, 59, 55, 63, 41, 8, 9, 0, 0, 151, 187, 103, 68, 0, 0, 0, 0, 187, 150, 195, 58, 227, 167, 203, 188, 168, 127, 102, 62, 254, 119, 44, 0, 0, 44, 137, 127, 191, 52, 63, 41, 13, 14, 0, 0, 213, 167, 41, 88, 0, 0, 0, 0, 184, 4, 210, 60, 93, 63, 109, 189, 55, 32, 110, 62, 123, 229, 12, 0, 17, 25, 133, 127, 191, 52, 72, 50, 13, 14, 0, 0, 120, 175, 134, 80, 0, 0, 0, 0, 207, 28, 238, 60, 245, 228, 116, 189, 83, 206, 38, 62, 123, 229, 12, 0, 11, 252, 130, 127, 59, 55, 72, 50, 16, 17, 18, 0, 51, 183, 125, 57, 77, 15, 0, 0, 170, 134, 45, 61, 2, 80, 204, 187, 185, 215, 53, 62, 123, 229, 12, 0, 14, 8, 131, 127, 59, 55, 63, 41, 13, 12, 14, 0, 176, 169, 12, 73, 65, 13, 0, 0, 143, 150, 227, 60, 143, 181, 252, 188, 30, 89, 119, 62, 123, 229, 12, 0, 21, 45, 140, 127, 191, 52, 63, 41, 13, 14, 8, 0, 67, 126, 67, 126, 119, 3, 0, 0, 244, 199, 157, 59, 190, 88, 114, 189, 243, 107, 97, 62, 1, 130, 2, 0, 247, 254, 130, 127, 191, 52, 72, 50, 13, 14, 12, 0, 53, 213, 146, 24, 54, 18, 0, 0, 147, 153, 81, 188, 81, 96, 115, 189, 157, 252, 49, 62, 1, 130, 2, 0, 211, 254, 138, 127, 59, 55, 72, 50, 17, 16, 0, 0, 32, 139, 222, 116, 0, 0, 0, 0, 207, 28, 238, 60, 245, 228, 116, 189, 83, 206, 38, 62, 1, 130, 2, 0, 225, 254, 133, 127, 59, 55, 63, 41, 16, 17, 18, 0, 51, 183, 125, 57, 77, 15, 0, 0, 184, 4, 210, 60, 93, 63, 109, 189, 55, 32, 110, 62, 1, 130, 2, 0, 6, 254, 130, 127, 191, 52, 63, 41, 13, 14, 0, 0, 120, 175, 134, 80, 0, 0, 0, 0, 1, 173, 250, 60, 11, 218, 130, 61, 59, 212, 130, 62, 110, 62, 248, 0, 1, 237, 131, 127, 191, 52, 72, 50, 5, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 67, 142, 19, 61, 18, 247, 62, 61, 142, 152, 69, 62, 110, 62, 248, 0, 9, 222, 135, 127, 59, 55, 72, 50, 5, 4, 8, 0, 117, 151, 127, 53, 9, 51, 0, 0, 67, 239, 90, 60, 92, 225, 175, 61, 221, 152, 67, 62, 110, 62, 248, 0, 6, 229, 133, 127, 59, 55, 63, 41, 5, 6, 0, 0, 33, 204, 221, 51, 0, 0, 0, 0, 124, 46, 120, 60, 105, 168, 190, 61, 237, 223, 133, 62, 110, 62, 248, 0, 254, 244, 130, 127, 191, 52, 63, 41, 6, 5, 9, 0, 191, 152, 230, 98, 88, 4, 0, 0, 118, 153, 132, 59, 105, 126, 93, 61, 224, 184, 130, 62, 38, 140, 33, 0, 253, 220, 135, 127, 191, 52, 72, 50, 5, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 68, 233, 248, 187, 157, 232, 21, 61, 102, 77, 82, 62, 38, 140, 33, 0, 230, 214, 140, 127, 59, 55, 72, 50, 5, 4, 0, 0, 208, 181, 46, 74, 0, 0, 0, 0, 67, 142, 19, 61, 18, 247, 62, 61, 142, 152, 69, 62, 38, 140, 33, 0, 241, 217, 137, 127, 59, 55, 63, 41, 5, 4, 8, 0, 117, 151, 127, 53, 9, 51, 0, 0, 1, 173, 250, 60, 11, 218, 130, 61, 59, 212, 130, 62, 38, 140, 33, 0, 10, 224, 134, 127, 191, 52, 63, 41, 5, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 45, 47, 223, 187, 254, 148, 159, 61, 225, 101, 131, 62, 140, 218, 33, 0, 230, 232, 135, 127, 109, 58, 72, 55, 6, 7, 0, 0, 198, 249, 56, 6, 0, 0, 0, 0, 83, 183, 171, 188, 119, 137, 156, 61, 15, 77, 70, 62, 140, 218, 33, 0, 223, 252, 134, 127, 172, 59, 72, 55, 4, 5, 0, 0, 175, 190, 79, 65, 0, 0, 0, 0, 68, 233, 248, 187, 157, 232, 21, 61, 102, 77, 82, 62, 140, 218, 33, 0, 226, 243, 134, 127, 172, 59, 204, 52, 5, 4, 0, 0, 208, 181, 46, 74, 0, 0, 0, 0, 118, 153, 132, 59, 105, 126, 93, 61, 224, 184, 130, 62, 140, 218, 33, 0, 236, 218, 137, 127, 109, 58, 204, 52, 5, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 124, 46, 120, 60, 105, 168, 190, 61, 237, 223, 133, 62, 206, 116, 255, 0, 239, 247, 131, 127, 191, 52, 72, 50, 6, 5, 9, 0, 191, 152, 230, 98, 88, 4, 0, 0, 67, 239, 90, 60, 92, 225, 175, 61, 221, 152, 67, 62, 206, 116, 255, 0, 250, 252, 130, 127, 59, 55, 72, 50, 5, 6, 0, 0, 33, 204, 221, 51, 0, 0, 0, 0, 83, 183, 171, 188, 119, 137, 156, 61, 15, 77, 70, 62, 206, 116, 255, 0, 246, 250, 130, 127, 59, 55, 63, 41, 4, 5, 0, 0, 175, 190, 79, 65, 0, 0, 0, 0, 45, 47, 223, 187, 254, 148, 159, 61, 225, 101, 131, 62, 206, 116, 255, 0, 233, 244, 132, 127, 191, 52, 63, 41, 6, 7, 0, 0, 198, 249, 56, 6, 0, 0, 0, 0, 200, 239, 82, 188, 142, 26, 201, 189, 214, 67, 65, 62, 3, 132, 231, 0, 7, 25, 132, 127, 191, 52, 72, 50, 17, 16, 0, 0, 22, 229, 232, 26, 0, 0, 0, 0, 158, 192, 128, 188, 228, 235, 186, 189, 88, 139, 24, 62, 3, 132, 231, 0, 247, 25, 132, 127, 59, 55, 72, 50, 16, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 76, 196, 114, 60, 13, 112, 182, 189, 49, 144, 23, 62, 3, 132, 231, 0, 0, 25, 132, 127, 59, 55, 63, 41, 16, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 0, 219, 13, 60, 183, 65, 204, 189, 66, 208, 69, 62, 3, 132, 231, 0, 16, 25, 133, 127, 191, 52, 63, 41, 17, 18, 19, 0, 33, 135, 51, 117, 169, 3, 0, 0, 153, 14, 48, 188, 140, 125, 149, 189, 191, 246, 73, 62, 130, 4, 11, 0, 247, 43, 137, 127, 109, 58, 72, 55, 17, 16, 0, 0, 201, 245, 53, 10, 0, 0, 0, 0, 147, 153, 81, 188, 81, 96, 115, 189, 157, 252, 49, 62, 130, 4, 11, 0, 249, 63, 147, 127, 172, 59, 72, 55, 17, 16, 0, 0, 32, 139, 222, 116, 0, 0, 0, 0, 158, 192, 128, 188, 228, 235, 186, 189, 88, 139, 24, 62, 130, 4, 11, 0, 247, 43, 138, 127, 172, 59, 204, 52, 16, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 200, 239, 82, 188, 142, 26, 201, 189, 214, 67, 65, 62, 130, 4, 11, 0, 246, 21, 132, 127, 109, 58, 204, 52, 17, 16, 0, 0, 22, 229, 232, 26, 0, 0, 0, 0, 134, 223, 47, 60, 56, 115, 159, 189, 254, 79, 76, 62, 17, 109, 62, 0, 28, 57, 147, 127, 191, 52, 72, 50, 17, 18, 16, 0, 180, 199, 148, 44, 182, 11, 0, 0, 207, 28, 238, 60, 245, 228, 116, 189, 83, 206, 38, 62, 17, 109, 62, 0, 51, 51, 152, 127, 59, 55, 72, 50, 16, 17, 18, 0, 51, 183, 125, 57, 77, 15, 0, 0, 147, 153, 81, 188, 81, 96, 115, 189, 157, 252, 49, 62, 17, 109, 62, 0, 32, 56, 148, 127, 59, 55, 63, 41, 17, 16, 0, 0, 32, 139, 222, 116, 0, 0, 0, 0, 153, 14, 48, 188, 140, 125, 149, 189, 191, 246, 73, 62, 17, 109, 62, 0, 247, 63, 147, 127, 191, 52, 63, 41, 17, 16, 0, 0, 201, 245, 53, 10, 0, 0, 0, 0, 0, 219, 13, 60, 183, 65, 204, 189, 66, 208, 69, 62, 117, 211, 19, 0, 35, 43, 142, 127, 191, 52, 72, 50, 17, 18, 19, 0, 33, 135, 51, 117, 169, 3, 0, 0, 76, 196, 114, 60, 13, 112, 182, 189, 49, 144, 23, 62, 117, 211, 19, 0, 29, 24, 135, 127, 59, 55, 72, 50, 16, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 207, 28, 238, 60, 245, 228, 116, 189, 83, 206, 38, 62, 117, 211, 19, 0, 32, 33, 138, 127, 59, 55, 63, 41, 16, 17, 18, 0, 51, 183, 125, 57, 77, 15, 0, 0, 134, 223, 47, 60, 56, 115, 159, 189, 254, 79, 76, 62, 117, 211, 19, 0, 39, 56, 150, 127, 191, 52, 63, 41, 17, 18, 16, 0, 180, 199, 148, 44, 182, 11, 0, 0, 49, 90, 21, 187, 127, 108, 199, 60, 244, 191, 162, 62, 111, 7, 59, 0, 26, 138, 220, 127, 191, 52, 72, 50, 11, 10, 0, 0, 31, 170, 223, 85, 0, 0, 0, 0, 24, 233, 175, 59, 136, 68, 130, 187, 95, 129, 158, 62, 111, 7, 59, 0, 27, 138, 220, 127, 59, 55, 72, 50, 10, 11, 9, 0, 63, 202, 105, 31, 85, 22, 0, 0, 58, 104, 16, 61, 94, 156, 135, 59, 33, 185, 127, 62, 111, 7, 59, 0, 26, 137, 221, 127, 59, 55, 63, 41, 9, 10, 0, 0, 27, 233, 227, 22, 0, 0, 0, 0, 187, 94, 243, 60, 171, 55, 13, 61, 141, 170, 132, 62, 111, 7, 59, 0, 26, 137, 222, 127, 191, 52, 63, 41, 10, 9, 8, 0, 213, 138, 115, 116, 181, 0, 0, 0, 24, 233, 175, 59, 136, 68, 130, 187, 95, 129, 158, 62, 34, 134, 4, 0, 145, 224, 206, 127, 191, 52, 72, 50, 10, 11, 9, 0, 63, 202, 105, 31, 85, 22, 0, 0, 234, 161, 129, 188, 108, 113, 10, 188, 33, 244, 152, 62, 34, 134, 4, 0, 148, 224, 200, 127, 59, 55, 72, 50, 10, 11, 0, 0, 61, 219, 193, 36, 0, 0, 0, 0, 109, 13, 40, 60, 53, 149, 157, 187, 196, 14, 121, 62, 34, 134, 4, 0, 140, 223, 220, 127, 59, 55, 63, 41, 9, 8, 0, 0, 242, 226, 12, 29, 0, 0, 0, 0, 58, 104, 16, 61, 94, 156, 135, 59, 33, 185, 127, 62, 34, 134, 4, 0, 138, 223, 226, 127, 191, 52, 63, 41, 9, 10, 0, 0, 27, 233, 227, 22, 0, 0, 0, 0, 202, 157, 229, 188, 36, 162, 157, 60, 76, 116, 156, 62, 146, 234, 197, 0, 57, 14, 144, 127, 109, 58, 72, 55, 11, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 182, 133, 38, 184, 10, 247, 251, 60, 1, 78, 130, 62, 146, 234, 197, 0, 55, 23, 145, 127, 172, 59, 72, 55, 9, 5, 13, 0, 231, 203, 75, 46, 204, 5, 0, 0, 109, 13, 40, 60, 53, 149, 157, 187, 196, 14, 121, 62, 146, 234, 197, 0, 56, 18, 144, 127, 172, 59, 204, 52, 9, 8, 0, 0, 242, 226, 12, 29, 0, 0, 0, 0, 234, 161, 129, 188, 108, 113, 10, 188, 33, 244, 152, 62, 146, 234, 197, 0, 58, 8, 144, 127, 109, 58, 204, 52, 10, 11, 0, 0, 61, 219, 193, 36, 0, 0, 0, 0, 49, 90, 21, 187, 127, 108, 199, 60, 244, 191, 162, 62, 233, 124, 11, 0, 60, 21, 147, 127, 191, 52, 72, 50, 11, 10, 0, 0, 31, 170, 223, 85, 0, 0, 0, 0, 187, 94, 243, 60, 171, 55, 13, 61, 141, 170, 132, 62, 233, 124, 11, 0, 59, 21, 146, 127, 59, 55, 72, 50, 10, 9, 8, 0, 213, 138, 115, 116, 181, 0, 0, 0, 182, 133, 38, 184, 10, 247, 251, 60, 1, 78, 130, 62, 233, 124, 11, 0, 59, 21, 147, 127, 59, 55, 63, 41, 9, 5, 13, 0, 231, 203, 75, 46, 204, 5, 0, 0, 202, 157, 229, 188, 36, 162, 157, 60, 76, 116, 156, 62, 233, 124, 11, 0, 60, 21, 147, 127, 191, 52, 63, 41, 11, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 202, 148, 157, 188, 176, 175, 22, 189, 211, 45, 138, 62, 141, 252, 203, 0, 52, 19, 142, 127, 109, 58, 72, 55, 15, 14, 0, 0, 101, 211, 153, 44, 0, 0, 0, 0, 187, 150, 195, 58, 227, 167, 203, 188, 168, 127, 102, 62, 141, 252, 203, 0, 51, 29, 144, 127, 172, 59, 72, 55, 13, 14, 0, 0, 213, 167, 41, 88, 0, 0, 0, 0, 244, 199, 157, 59, 190, 88, 114, 189, 243, 107, 97, 62, 141, 252, 203, 0, 51, 24, 143, 127, 172, 59, 204, 52, 13, 14, 12, 0, 53, 213, 146, 24, 54, 18, 0, 0, 231, 65, 92, 188, 206, 167, 129, 189, 228, 113, 133, 62, 141, 252, 203, 0, 52, 11, 142, 127, 109, 58, 204, 52, 14, 15, 0, 0, 195, 133, 59, 122, 0, 0, 0, 0, 176, 42, 222, 187, 209, 227, 40, 189, 224, 14, 150, 62, 2, 123, 30, 0, 59, 25, 147, 127, 191, 52, 72, 50, 15, 14, 13, 0, 201, 182, 72, 62, 236, 10, 0, 0, 143, 150, 227, 60, 143, 181, 252, 188, 30, 89, 119, 62, 2, 123, 30, 0, 69, 23, 153, 127, 59, 55, 72, 50, 13, 14, 8, 0, 67, 126, 67, 126, 119, 3, 0, 0, 187, 150, 195, 58, 227, 167, 203, 188, 168, 127, 102, 62, 2, 123, 30, 0, 66, 24, 151, 127, 59, 55, 63, 41, 13, 14, 0, 0, 213, 167, 41, 88, 0, 0, 0, 0, 202, 148, 157, 188, 176, 175, 22, 189, 211, 45, 138, 62, 2, 123, 30, 0, 51, 26, 144, 127, 191, 52, 63, 41, 15, 14, 0, 0, 101, 211, 153, 44, 0, 0, 0, 0, 176, 42, 222, 187, 209, 227, 40, 189, 224, 14, 150, 62, 104, 225, 64, 0, 0, 142, 202, 127, 191, 52, 72, 50, 15, 14, 13, 0, 201, 182, 72, 62, 236, 10, 0, 0, 23, 16, 204, 187, 134, 225, 130, 189, 169, 159, 143, 62, 104, 225, 64, 0, 4, 145, 196, 127, 59, 55, 72, 50, 14, 15, 13, 0, 39, 139, 94, 105, 121, 11, 0, 0, 184, 4, 210, 60, 93, 63, 109, 189, 55, 32, 110, 62, 104, 225, 64, 0, 249, 138, 211, 127, 59, 55, 63, 41, 13, 14, 0, 0, 120, 175, 134, 80, 0, 0, 0, 0, 143, 150, 227, 60, 143, 181, 252, 188, 30, 89, 119, 62, 104, 225, 64, 0, 246, 137, 216, 127, 191, 52, 63, 41, 13, 14, 8, 0, 67, 126, 67, 126, 119, 3, 0, 0, 23, 16, 204, 187, 134, 225, 130, 189, 169, 159, 143, 62, 11, 130, 249, 0, 180, 0, 155, 127, 191, 52, 72, 50, 14, 15, 13, 0, 39, 139, 94, 105, 121, 11, 0, 0, 231, 65, 92, 188, 206, 167, 129, 189, 228, 113, 133, 62, 11, 130, 249, 0, 213, 3, 137, 127, 59, 55, 72, 50, 14, 15, 0, 0, 195, 133, 59, 122, 0, 0, 0, 0, 244, 199, 157, 59, 190, 88, 114, 189, 243, 107, 97, 62, 11, 130, 249, 0, 155, 252, 180, 127, 59, 55, 63, 41, 13, 14, 12, 0, 53, 213, 146, 24, 54, 18, 0, 0, 184, 4, 210, 60, 93, 63, 109, 189, 55, 32, 110, 62, 11, 130, 249, 0, 148, 250, 192, 127, 191, 52, 63, 41, 13, 14, 0, 0, 120, 175, 134, 80, 0, 0, 0, 0, 124, 46, 120, 60, 105, 168, 190, 61, 237, 223, 133, 62, 111, 51, 30, 0, 228, 246, 123, 127, 191, 52, 72, 50, 6, 5, 9, 0, 191, 152, 230, 98, 88, 4, 0, 0, 171, 146, 7, 59, 235, 65, 181, 61, 83, 237, 162, 62, 111, 51, 30, 0, 228, 246, 123, 127, 59, 55, 72, 50, 7, 6, 5, 0, 228, 196, 142, 56, 140, 2, 0, 0, 154, 9, 132, 60, 173, 82, 112, 61, 234, 20, 162, 62, 111, 51, 30, 0, 228, 246, 123, 127, 59, 55, 63, 41, 7, 6, 0, 0, 207, 161, 47, 94, 0, 0, 0, 0, 1, 173, 250, 60, 11, 218, 130, 61, 59, 212, 130, 62, 111, 51, 30, 0, 228, 246, 123, 127, 191, 52, 63, 41, 5, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 153, 159, 221, 187, 197, 176, 107, 61, 245, 96, 181, 62, 35, 135, 15, 0, 145, 218, 210, 127, 191, 52, 72, 50, 7, 6, 0, 0, 121, 242, 133, 13, 0, 0, 0, 0, 233, 30, 184, 188, 57, 92, 83, 61, 163, 60, 178, 62, 35, 135, 15, 0, 144, 218, 212, 127, 59, 55, 72, 50, 7, 6, 0, 0, 176, 224, 78, 31, 0, 0, 0, 0, 156, 215, 144, 187, 112, 20, 85, 61, 206, 5, 157, 62, 35, 135, 15, 0, 146, 218, 206, 127, 59, 55, 63, 41, 6, 7, 0, 0, 245, 192, 9, 63, 0, 0, 0, 0, 154, 9, 132, 60, 173, 82, 112, 61, 234, 20, 162, 62, 35, 135, 15, 0, 147, 218, 204, 127, 191, 52, 63, 41, 7, 6, 0, 0, 207, 161, 47, 94, 0, 0, 0, 0, 233, 30, 184, 188, 57, 92, 83, 61, 163, 60, 178, 62, 151, 202, 210, 0, 199, 113, 253, 127, 109, 58, 72, 55, 7, 6, 0, 0, 176, 224, 78, 31, 0, 0, 0, 0, 47, 142, 5, 189, 237, 27, 147, 61, 235, 245, 177, 62, 151, 202, 210, 0, 199, 113, 253, 127, 172, 59, 72, 55, 7, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 87, 60, 133, 188, 239, 201, 153, 61, 185, 184, 156, 62, 151, 202, 210, 0, 199, 113, 254, 127, 172, 59, 204, 52, 6, 7, 0, 0, 159, 168, 95, 87, 0, 0, 0, 0, 156, 215, 144, 187, 112, 20, 85, 61, 206, 5, 157, 62, 151, 202, 210, 0, 199, 113, 254, 127, 109, 58, 204, 52, 6, 7, 0, 0, 245, 192, 9, 63, 0, 0, 0, 0, 45, 47, 223, 187, 254, 148, 159, 61, 225, 101, 131, 62, 185, 104, 249, 0, 229, 247, 123, 127, 191, 52, 72, 50, 6, 7, 0, 0, 198, 249, 56, 6, 0, 0, 0, 0, 87, 60, 133, 188, 239, 201, 153, 61, 185, 184, 156, 62, 185, 104, 249, 0, 233, 250, 124, 127, 59, 55, 72, 50, 6, 7, 0, 0, 159, 168, 95, 87, 0, 0, 0, 0, 171, 146, 7, 59, 235, 65, 181, 61, 83, 237, 162, 62, 185, 104, 249, 0, 231, 248, 124, 127, 59, 55, 63, 41, 7, 6, 5, 0, 228, 196, 142, 56, 140, 2, 0, 0, 124, 46, 120, 60, 105, 168, 190, 61, 237, 223, 133, 62, 185, 104, 249, 0, 228, 246, 123, 127, 191, 52, 63, 41, 6, 5, 9, 0, 191, 152, 230, 98, 88, 4, 0, 0, 152, 122, 8, 189, 157, 35, 202, 189, 179, 191, 85, 62, 247, 131, 239, 0, 85, 6, 162, 127, 191, 52, 72, 50, 19, 18, 17, 0, 246, 127, 120, 115, 144, 12, 0, 0, 200, 239, 82, 188, 142, 26, 201, 189, 214, 67, 65, 62, 247, 131, 239, 0, 91, 5, 168, 127, 59, 55, 72, 50, 17, 16, 0, 0, 22, 229, 232, 26, 0, 0, 0, 0, 0, 219, 13, 60, 183, 65, 204, 189, 66, 208, 69, 62, 247, 131, 239, 0, 86, 6, 164, 127, 59, 55, 63, 41, 17, 18, 19, 0, 33, 135, 51, 117, 169, 3, 0, 0, 194, 60, 120, 188, 136, 207, 209, 189, 165, 41, 98, 62, 247, 131, 239, 0, 82, 7, 160, 127, 191, 52, 63, 41, 18, 19, 0, 0, 247, 174, 7, 81, 0, 0, 0, 0, 152, 122, 8, 189, 157, 35, 202, 189, 179, 191, 85, 62, 168, 40, 175, 0, 13, 118, 44, 127, 109, 58, 72, 55, 19, 18, 17, 0, 246, 127, 120, 115, 144, 12, 0, 0, 88, 170, 245, 188, 84, 125, 156, 189, 133, 63, 95, 62, 168, 40, 175, 0, 13, 118, 44, 127, 172, 59, 72, 55, 19, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 153, 14, 48, 188, 140, 125, 149, 189, 191, 246, 73, 62, 168, 40, 175, 0, 13, 118, 44, 127, 172, 59, 204, 52, 17, 16, 0, 0, 201, 245, 53, 10, 0, 0, 0, 0, 200, 239, 82, 188, 142, 26, 201, 189, 214, 67, 65, 62, 168, 40, 175, 0, 13, 118, 43, 127, 109, 58, 204, 52, 17, 16, 0, 0, 22, 229, 232, 26, 0, 0, 0, 0, 6, 146, 94, 188, 241, 136, 165, 189, 96, 77, 106, 62, 18, 121, 31, 0, 83, 11, 162, 127, 191, 52, 72, 50, 18, 19, 0, 0, 41, 134, 213, 121, 0, 0, 0, 0, 134, 223, 47, 60, 56, 115, 159, 189, 254, 79, 76, 62, 18, 121, 31, 0, 81, 12, 160, 127, 59, 55, 72, 50, 17, 18, 16, 0, 180, 199, 148, 44, 182, 11, 0, 0, 153, 14, 48, 188, 140, 125, 149, 189, 191, 246, 73, 62, 18, 121, 31, 0, 82, 12, 161, 127, 59, 55, 63, 41, 17, 16, 0, 0, 201, 245, 53, 10, 0, 0, 0, 0, 88, 170, 245, 188, 84, 125, 156, 189, 133, 63, 95, 62, 18, 121, 31, 0, 85, 11, 163, 127, 191, 52, 63, 41, 19, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 6, 146, 94, 188, 241, 136, 165, 189, 96, 77, 106, 62, 95, 223, 77, 0, 247, 136, 216, 127, 191, 52, 72, 50, 18, 19, 0, 0, 41, 134, 213, 121, 0, 0, 0, 0, 194, 60, 120, 188, 136, 207, 209, 189, 165, 41, 98, 62, 95, 223, 77, 0, 249, 137, 214, 127, 59, 55, 72, 50, 18, 19, 0, 0, 247, 174, 7, 81, 0, 0, 0, 0, 0, 219, 13, 60, 183, 65, 204, 189, 66, 208, 69, 62, 95, 223, 77, 0, 246, 136, 218, 127, 59, 55, 63, 41, 17, 18, 19, 0, 33, 135, 51, 117, 169, 3, 0, 0, 134, 223, 47, 60, 56, 115, 159, 189, 254, 79, 76, 62, 95, 223, 77, 0, 244, 135, 220, 127, 191, 52, 63, 41, 17, 18, 16, 0, 180, 199, 148, 44, 182, 11, 0, 0, 140, 217, 37, 189, 48, 238, 81, 60, 151, 49, 180, 62, 86, 1, 93, 0, 33, 138, 227, 127, 191, 52, 72, 50, 11, 10, 0, 0, 233, 233, 21, 22, 0, 0, 0, 0, 247, 65, 9, 189, 121, 229, 26, 188, 223, 211, 177, 62, 86, 1, 93, 0, 33, 137, 227, 127, 59, 55, 72, 50, 11, 10, 0, 0, 109, 233, 145, 22, 0, 0, 0, 0, 24, 233, 175, 59, 136, 68, 130, 187, 95, 129, 158, 62, 86, 1, 93, 0, 34, 138, 226, 127, 59, 55, 63, 41, 10, 11, 9, 0, 63, 202, 105, 31, 85, 22, 0, 0, 49, 90, 21, 187, 127, 108, 199, 60, 244, 191, 162, 62, 86, 1, 93, 0, 35, 138, 225, 127, 191, 52, 63, 41, 11, 10, 0, 0, 31, 170, 223, 85, 0, 0, 0, 0, 247, 65, 9, 189, 121, 229, 26, 188, 223, 211, 177, 62, 30, 134, 8, 0, 174, 229, 164, 127, 191, 52, 72, 50, 11, 10, 0, 0, 109, 233, 145, 22, 0, 0, 0, 0, 47, 84, 55, 189, 70, 94, 121, 188, 183, 30, 168, 62, 30, 134, 8, 0, 192, 233, 150, 127, 59, 55, 72, 50, 11, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 234, 161, 129, 188, 108, 113, 10, 188, 33, 244, 152, 62, 30, 134, 8, 0, 155, 226, 187, 127, 59, 55, 63, 41, 10, 11, 0, 0, 61, 219, 193, 36, 0, 0, 0, 0, 24, 233, 175, 59, 136, 68, 130, 187, 95, 129, 158, 62, 30, 134, 8, 0, 147, 225, 200, 127, 191, 52, 63, 41, 10, 11, 9, 0, 63, 202, 105, 31, 85, 22, 0, 0, 234, 161, 129, 188, 108, 113, 10, 188, 33, 244, 152, 62, 166, 242, 169, 0, 174, 223, 90, 127, 109, 58, 72, 55, 10, 11, 0, 0, 61, 219, 193, 36, 0, 0, 0, 0, 47, 84, 55, 189, 70, 94, 121, 188, 183, 30, 168, 62, 166, 242, 169, 0, 171, 236, 91, 127, 172, 59, 72, 55, 11, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 99, 173, 85, 189, 147, 112, 216, 59, 63, 220, 170, 62, 166, 242, 169, 0, 173, 227, 90, 127, 172, 59, 204, 52, 11, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 202, 157, 229, 188, 36, 162, 157, 60, 76, 116, 156, 62, 166, 242, 169, 0, 176, 215, 89, 127, 109, 58, 204, 52, 11, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 202, 157, 229, 188, 36, 162, 157, 60, 76, 116, 156, 62, 216, 120, 5, 0, 168, 222, 84, 127, 191, 52, 72, 50, 11, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 99, 173, 85, 189, 147, 112, 216, 59, 63, 220, 170, 62, 216, 120, 5, 0, 175, 224, 91, 127, 59, 55, 72, 50, 11, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 140, 217, 37, 189, 48, 238, 81, 60, 151, 49, 180, 62, 216, 120, 5, 0, 171, 223, 88, 127, 59, 55, 63, 41, 11, 10, 0, 0, 233, 233, 21, 22, 0, 0, 0, 0, 49, 90, 21, 187, 127, 108, 199, 60, 244, 191, 162, 62, 216, 120, 5, 0, 166, 222, 82, 127, 191, 52, 63, 41, 11, 10, 0, 0, 31, 170, 223, 85, 0, 0, 0, 0, 231, 65, 92, 188, 206, 167, 129, 189, 228, 113, 133, 62, 186, 26, 154, 0, 151, 248, 70, 127, 109, 58, 72, 55, 14, 15, 0, 0, 195, 133, 59, 122, 0, 0, 0, 0, 162, 252, 83, 189, 161, 36, 135, 189, 30, 199, 145, 62, 186, 26, 154, 0, 151, 248, 70, 127, 172, 59, 72, 55, 15, 14, 0, 0, 101, 231, 153, 24, 0, 0, 0, 0, 240, 122, 90, 189, 79, 11, 35, 189, 77, 183, 150, 62, 186, 26, 154, 0, 151, 248, 70, 127, 172, 59, 204, 52, 15, 14, 0, 0, 226, 226, 28, 29, 0, 0, 0, 0, 202, 148, 157, 188, 176, 175, 22, 189, 211, 45, 138, 62, 186, 26, 154, 0, 151, 248, 70, 127, 109, 58, 204, 52, 15, 14, 0, 0, 101, 211, 153, 44, 0, 0, 0, 0, 202, 148, 157, 188, 176, 175, 22, 189, 211, 45, 138, 62, 4, 124, 25, 0, 147, 247, 63, 127, 191, 52, 72, 50, 15, 14, 0, 0, 101, 211, 153, 44, 0, 0, 0, 0, 240, 122, 90, 189, 79, 11, 35, 189, 77, 183, 150, 62, 4, 124, 25, 0, 153, 245, 73, 127, 59, 55, 72, 50, 15, 14, 0, 0, 226, 226, 28, 29, 0, 0, 0, 0, 158, 73, 60, 189, 22, 1, 56, 189, 13, 131, 160, 62, 4, 124, 25, 0, 150, 246, 68, 127, 59, 55, 63, 41, 15, 14, 0, 0, 54, 249, 200, 6, 0, 0, 0, 0, 176, 42, 222, 187, 209, 227, 40, 189, 224, 14, 150, 62, 4, 124, 25, 0, 144, 248, 58, 127, 191, 52, 63, 41, 15, 14, 13, 0, 201, 182, 72, 62, 236, 10, 0, 0, 158, 73, 60, 189, 22, 1, 56, 189, 13, 131, 160, 62, 56, 201, 99, 0, 235, 142, 205, 127, 191, 52, 72, 50, 15, 14, 0, 0, 54, 249, 200, 6, 0, 0, 0, 0, 193, 149, 82, 189, 225, 157, 131, 189, 95, 91, 156, 62, 56, 201, 99, 0, 225, 142, 210, 127, 59, 55, 72, 50, 15, 14, 0, 0, 156, 239, 98, 16, 0, 0, 0, 0, 23, 16, 204, 187, 134, 225, 130, 189, 169, 159, 143, 62, 56, 201, 99, 0, 248, 144, 198, 127, 59, 55, 63, 41, 14, 15, 13, 0, 39, 139, 94, 105, 121, 11, 0, 0, 176, 42, 222, 187, 209, 227, 40, 189, 224, 14, 150, 62, 56, 201, 99, 0, 2, 146, 194, 127, 191, 52, 63, 41, 15, 14, 13, 0, 201, 182, 72, 62, 236, 10, 0, 0, 193, 149, 82, 189, 225, 157, 131, 189, 95, 91, 156, 62, 6, 130, 2, 0, 240, 253, 131, 127, 191, 52, 72, 50, 15, 14, 0, 0, 156, 239, 98, 16, 0, 0, 0, 0, 162, 252, 83, 189, 161, 36, 135, 189, 30, 199, 145, 62, 6, 130, 2, 0, 254, 254, 130, 127, 59, 55, 72, 50, 15, 14, 0, 0, 101, 231, 153, 24, 0, 0, 0, 0, 231, 65, 92, 188, 206, 167, 129, 189, 228, 113, 133, 62, 6, 130, 2, 0, 222, 253, 134, 127, 59, 55, 63, 41, 14, 15, 0, 0, 195, 133, 59, 122, 0, 0, 0, 0, 23, 16, 204, 187, 134, 225, 130, 189, 169, 159, 143, 62, 6, 130, 2, 0, 213, 252, 137, 127, 191, 52, 63, 41, 14, 15, 13, 0, 39, 139, 94, 105, 121, 11, 0, 0, 194, 60, 120, 188, 136, 207, 209, 189, 165, 41, 98, 62, 241, 130, 0, 0, 149, 13, 67, 127, 191, 52, 72, 50, 18, 19, 0, 0, 247, 174, 7, 81, 0, 0, 0, 0, 231, 63, 93, 189, 135, 36, 197, 189, 66, 147, 122, 62, 241, 130, 0, 0, 149, 13, 65, 127, 59, 55, 72, 50, 19, 18, 0, 0, 251, 242, 3, 13, 0, 0, 0, 0, 143, 211, 104, 189, 137, 57, 199, 189, 77, 4, 101, 62, 241, 130, 0, 0, 149, 13, 66, 127, 59, 55, 63, 41, 19, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 152, 122, 8, 189, 157, 35, 202, 189, 179, 191, 85, 62, 241, 130, 0, 0, 150, 12, 68, 127, 191, 52, 63, 41, 19, 18, 17, 0, 246, 127, 120, 115, 144, 12, 0, 0, 143, 211, 104, 189, 137, 57, 199, 189, 77, 4, 101, 62, 193, 55, 161, 0, 22, 113, 51, 127, 109, 58, 72, 55, 19, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 35, 60, 84, 189, 21, 183, 157, 189, 111, 80, 111, 62, 193, 55, 161, 0, 24, 113, 50, 127, 172, 59, 72, 55, 19, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 88, 170, 245, 188, 84, 125, 156, 189, 133, 63, 95, 62, 193, 55, 161, 0, 22, 113, 51, 127, 172, 59, 204, 52, 19, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 152, 122, 8, 189, 157, 35, 202, 189, 179, 191, 85, 62, 193, 55, 161, 0, 20, 113, 52, 127, 109, 58, 204, 52, 19, 18, 17, 0, 246, 127, 120, 115, 144, 12, 0, 0, 88, 170, 245, 188, 84, 125, 156, 189, 133, 63, 95, 62, 14, 125, 16, 0, 145, 4, 61, 127, 191, 52, 72, 50, 19, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 35, 60, 84, 189, 21, 183, 157, 189, 111, 80, 111, 62, 14, 125, 16, 0, 154, 2, 74, 127, 59, 55, 72, 50, 19, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 184, 230, 64, 189, 201, 226, 159, 189, 248, 251, 123, 62, 14, 125, 16, 0, 150, 3, 68, 127, 59, 55, 63, 41, 19, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 6, 146, 94, 188, 241, 136, 165, 189, 96, 77, 106, 62, 14, 125, 16, 0, 143, 5, 57, 127, 191, 52, 63, 41, 18, 19, 0, 0, 41, 134, 213, 121, 0, 0, 0, 0, 184, 230, 64, 189, 201, 226, 159, 189, 248, 251, 123, 62, 56, 219, 107, 0, 219, 137, 235, 127, 191, 52, 72, 50, 19, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 231, 63, 93, 189, 135, 36, 197, 189, 66, 147, 122, 62, 56, 219, 107, 0, 208, 140, 242, 127, 59, 55, 72, 50, 19, 18, 0, 0, 251, 242, 3, 13, 0, 0, 0, 0, 194, 60, 120, 188, 136, 207, 209, 189, 165, 41, 98, 62, 56, 219, 107, 0, 237, 135, 225, 127, 59, 55, 63, 41, 18, 19, 0, 0, 247, 174, 7, 81, 0, 0, 0, 0, 6, 146, 94, 188, 241, 136, 165, 189, 96, 77, 106, 62, 56, 219, 107, 0, 251, 136, 218, 127, 191, 52, 63, 41, 18, 19, 0, 0, 41, 134, 213, 121, 0, 0, 0, 0, 140, 40, 115, 188, 18, 4, 70, 61, 124, 216, 32, 189, 18, 123, 234, 0, 1, 22, 124, 127, 191, 52, 72, 50, 0, 1, 0, 0, 132, 187, 122, 68, 0, 0, 0, 0, 162, 250, 144, 188, 67, 207, 138, 61, 86, 80, 4, 61, 18, 123, 234, 0, 250, 23, 124, 127, 59, 55, 72, 50, 1, 2, 4, 0, 121, 189, 220, 37, 169, 28, 0, 0, 44, 14, 234, 60, 249, 66, 84, 61, 68, 8, 102, 60, 18, 123, 234, 0, 255, 23, 124, 127, 59, 55, 63, 41, 0, 1, 0, 0, 121, 166, 133, 89, 0, 0, 0, 0, 98, 97, 214, 60, 208, 204, 64, 61, 0, 251, 54, 189, 18, 123, 234, 0, 6, 22, 124, 127, 191, 52, 63, 41, 1, 4, 8, 12, 255, 63, 255, 63, 255, 63, 255, 63, 98, 97, 214, 60, 208, 204, 64, 61, 0, 251, 54, 189, 107, 67, 246, 0, 7, 7, 126, 127, 191, 52, 72, 50, 1, 4, 8, 12, 255, 63, 255, 63, 255, 63, 255, 63, 44, 14, 234, 60, 249, 66, 84, 61, 68, 8, 102, 60, 107, 67, 246, 0, 5, 10, 126, 127, 59, 55, 72, 50, 0, 1, 0, 0, 121, 166, 133, 89, 0, 0, 0, 0, 237, 22, 78, 61, 135, 12, 123, 60, 155, 102, 199, 186, 107, 67, 246, 0, 6, 8, 126, 127, 59, 55, 63, 41, 0, 1, 0, 0, 218, 217, 36, 38, 0, 0, 0, 0, 14, 13, 62, 61, 90, 98, 87, 60, 74, 125, 89, 189, 107, 67, 246, 0, 9, 5, 126, 127, 191, 52, 63, 41, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 14, 13, 62, 61, 90, 98, 87, 60, 74, 125, 89, 189, 123, 230, 242, 0, 16, 9, 125, 127, 191, 52, 72, 50, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 237, 22, 78, 61, 135, 12, 123, 60, 155, 102, 199, 186, 123, 230, 242, 0, 15, 4, 125, 127, 59, 55, 72, 50, 0, 1, 0, 0, 218, 217, 36, 38, 0, 0, 0, 0, 184, 211, 49, 61, 2, 127, 233, 188, 70, 68, 205, 186, 123, 230, 242, 0, 16, 8, 125, 127, 59, 55, 63, 41, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 147, 75, 11, 61, 26, 228, 9, 189, 71, 21, 82, 189, 123, 230, 242, 0, 17, 14, 124, 127, 191, 52, 63, 41, 1, 4, 8, 12, 255, 63, 255, 63, 255, 63, 255, 63, 184, 211, 49, 61, 2, 127, 233, 188, 70, 68, 205, 186, 77, 156, 255, 0, 159, 180, 29, 127, 191, 52, 72, 50, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 48, 132, 3, 60, 255, 203, 95, 189, 150, 101, 243, 59, 77, 156, 255, 0, 158, 180, 25, 127, 59, 55, 72, 50, 16, 0, 0, 0, 240, 180, 14, 75, 0, 0, 0, 0, 230, 187, 142, 186, 107, 2, 128, 189, 124, 87, 32, 189, 77, 156, 255, 0, 159, 181, 29, 127, 59, 55, 63, 41, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 147, 75, 11, 61, 26, 228, 9, 189, 71, 21, 82, 189, 77, 156, 255, 0, 160, 181, 32, 127, 191, 52, 63, 41, 1, 4, 8, 12, 255, 63, 255, 63, 255, 63, 255, 63, 48, 132, 3, 60, 255, 203, 95, 189, 150, 101, 243, 59, 237, 132, 17, 0, 133, 21, 19, 127, 191, 52, 72, 50, 16, 0, 0, 0, 240, 180, 14, 75, 0, 0, 0, 0, 114, 117, 156, 188, 147, 48, 88, 189, 89, 99, 39, 60, 237, 132, 17, 0, 132, 20, 11, 127, 59, 55, 72, 50, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 8, 40, 5, 189, 234, 132, 92, 189, 226, 153, 0, 189, 237, 132, 17, 0, 134, 22, 24, 127, 59, 55, 63, 41, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 230, 187, 142, 186, 107, 2, 128, 189, 124, 87, 32, 189, 237, 132, 17, 0, 135, 23, 30, 127, 191, 52, 63, 41, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 8, 40, 5, 189, 234, 132, 92, 189, 226, 153, 0, 189, 151, 188, 17, 0, 25, 249, 124, 127, 191, 52, 72, 50, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 114, 117, 156, 188, 147, 48, 88, 189, 89, 99, 39, 60, 151, 188, 17, 0, 24, 250, 124, 127, 59, 55, 72, 50, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 2, 253, 32, 189, 33, 195, 2, 189, 118, 162, 84, 60, 151, 188, 17, 0, 25, 250, 124, 127, 59, 55, 63, 41, 0, 1, 0, 0, 156, 193, 98, 62, 0, 0, 0, 0, 144, 84, 51, 189, 9, 102, 212, 188, 87, 117, 7, 189, 151, 188, 17, 0, 25, 249, 124, 127, 191, 52, 63, 41, 0, 1, 4, 8, 162, 77, 116, 59, 116, 59, 116, 59, 144, 84, 51, 189, 9, 102, 212, 188, 87, 117, 7, 189, 131, 249, 241, 0, 241, 250, 125, 127, 191, 52, 72, 50, 0, 1, 4, 8, 162, 77, 116, 59, 116, 59, 116, 59, 2, 253, 32, 189, 33, 195, 2, 189, 118, 162, 84, 60, 131, 249, 241, 0, 242, 238, 124, 127, 59, 55, 72, 50, 0, 1, 0, 0, 156, 193, 98, 62, 0, 0, 0, 0, 197, 98, 87, 189, 182, 94, 111, 60, 245, 89, 152, 60, 131, 249, 241, 0, 241, 248, 125, 127, 59, 55, 63, 41, 1, 0, 0, 0, 222, 172, 32, 83, 0, 0, 0, 0, 162, 187, 17, 189, 69, 33, 103, 60, 4, 150, 29, 189, 131, 249, 241, 0, 241, 2, 125, 127, 191, 52, 63, 41, 0, 1, 0, 0, 225, 215, 29, 40, 0, 0, 0, 0, 162, 187, 17, 189, 69, 33, 103, 60, 4, 150, 29, 189, 154, 69, 230, 0, 237, 18, 124, 127, 191, 52, 72, 50, 0, 1, 0, 0, 225, 215, 29, 40, 0, 0, 0, 0, 197, 98, 87, 189, 182, 94, 111, 60, 245, 89, 152, 60, 154, 69, 230, 0, 224, 255, 122, 127, 59, 55, 72, 50, 1, 0, 0, 0, 222, 172, 32, 83, 0, 0, 0, 0, 162, 250, 144, 188, 67, 207, 138, 61, 86, 80, 4, 61, 154, 69, 230, 0, 233, 12, 124, 127, 59, 55, 63, 41, 1, 2, 4, 0, 121, 189, 220, 37, 169, 28, 0, 0, 140, 40, 115, 188, 18, 4, 70, 61, 124, 216, 32, 189, 154, 69, 230, 0, 249, 35, 121, 127, 191, 52, 63, 41, 0, 1, 0, 0, 132, 187, 122, 68, 0, 0, 0, 0, 31, 57, 161, 189, 158, 246, 21, 61, 80, 77, 237, 61, 59, 165, 64, 0, 88, 83, 36, 127, 109, 58, 72, 55, 2, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 154, 90, 46, 189, 36, 249, 163, 61, 114, 119, 8, 62, 59, 165, 64, 0, 83, 84, 43, 127, 172, 59, 72, 55, 2, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 227, 4, 174, 189, 112, 174, 143, 61, 173, 143, 45, 62, 59, 165, 64, 0, 89, 82, 34, 127, 172, 59, 204, 52, 2, 3, 0, 0, 251, 184, 3, 71, 0, 0, 0, 0, 76, 147, 242, 189, 12, 78, 69, 61, 81, 183, 33, 62, 59, 165, 64, 0, 94, 80, 26, 127, 109, 58, 204, 52, 3, 2, 0, 0, 164, 208, 90, 47, 0, 0, 0, 0, 24, 56, 5, 190, 70, 135, 156, 61, 251, 212, 24, 62, 166, 183, 205, 0, 74, 235, 156, 127, 191, 52, 72, 50, 3, 2, 0, 0, 162, 231, 92, 24, 0, 0, 0, 0, 151, 86, 174, 189, 130, 147, 138, 61, 93, 145, 146, 61, 166, 183, 205, 0, 67, 248, 150, 127, 59, 55, 72, 50, 1, 2, 3, 0, 67, 176, 37, 54, 149, 25, 0, 0, 31, 57, 161, 189, 158, 246, 21, 61, 80, 77, 237, 61, 166, 183, 205, 0, 70, 243, 152, 127, 59, 55, 63, 41, 2, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 76, 147, 242, 189, 12, 78, 69, 61, 81, 183, 33, 62, 166, 183, 205, 0, 78, 226, 162, 127, 191, 52, 63, 41, 3, 2, 0, 0, 164, 208, 90, 47, 0, 0, 0, 0, 227, 141, 201, 189, 216, 178, 192, 61, 135, 115, 42, 62, 205, 109, 219, 0, 64, 249, 148, 127, 191, 52, 72, 50, 3, 2, 1, 0, 174, 135, 58, 115, 22, 5, 0, 0, 69, 96, 83, 189, 175, 57, 193, 61, 124, 215, 194, 61, 205, 109, 219, 0, 71, 254, 151, 127, 59, 55, 72, 50, 1, 2, 0, 0, 52, 152, 202, 103, 0, 0, 0, 0, 151, 86, 174, 189, 130, 147, 138, 61, 93, 145, 146, 61, 205, 109, 219, 0, 68, 252, 150, 127, 59, 55, 63, 41, 1, 2, 3, 0, 67, 176, 37, 54, 149, 25, 0, 0, 24, 56, 5, 190, 70, 135, 156, 61, 251, 212, 24, 62, 205, 109, 219, 0, 61, 247, 146, 127, 191, 52, 63, 41, 3, 2, 0, 0, 162, 231, 92, 24, 0, 0, 0, 0, 227, 4, 174, 189, 112, 174, 143, 61, 173, 143, 45, 62, 58, 96, 57, 0, 79, 10, 158, 127, 191, 52, 72, 50, 2, 3, 0, 0, 251, 184, 3, 71, 0, 0, 0, 0, 154, 90, 46, 189, 36, 249, 163, 61, 114, 119, 8, 62, 58, 96, 57, 0, 85, 4, 163, 127, 59, 55, 72, 50, 2, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 69, 96, 83, 189, 175, 57, 193, 61, 124, 215, 194, 61, 58, 96, 57, 0, 82, 7, 161, 127, 59, 55, 63, 41, 1, 2, 0, 0, 52, 152, 202, 103, 0, 0, 0, 0, 227, 141, 201, 189, 216, 178, 192, 61, 135, 115, 42, 62, 58, 96, 57, 0, 77, 12, 157, 127, 191, 52, 63, 41, 3, 2, 1, 0, 174, 135, 58, 115, 22, 5, 0, 0, 224, 29, 15, 190, 16, 167, 125, 61, 220, 230, 68, 62, 41, 154, 61, 0, 79, 231, 161, 127, 109, 58, 72, 55, 3, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 76, 147, 242, 189, 12, 78, 69, 61, 81, 183, 33, 62, 41, 154, 61, 0, 62, 219, 152, 127, 172, 59, 72, 55, 3, 2, 0, 0, 164, 208, 90, 47, 0, 0, 0, 0, 227, 4, 174, 189, 112, 174, 143, 61, 173, 143, 45, 62, 41, 154, 61, 0, 74, 227, 158, 127, 172, 59, 204, 52, 2, 3, 0, 0, 251, 184, 3, 71, 0, 0, 0, 0, 168, 27, 244, 189, 191, 129, 151, 61, 76, 49, 78, 62, 41, 154, 61, 0, 93, 243, 172, 127, 109, 58, 204, 52, 3, 2, 0, 0, 46, 221, 208, 34, 0, 0, 0, 0, 169, 200, 28, 190, 120, 219, 163, 61, 97, 15, 65, 62, 157, 191, 212, 0, 64, 230, 151, 127, 191, 52, 72, 50, 3, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 24, 56, 5, 190, 70, 135, 156, 61, 251, 212, 24, 62, 157, 191, 212, 0, 58, 243, 145, 127, 59, 55, 72, 50, 3, 2, 0, 0, 162, 231, 92, 24, 0, 0, 0, 0, 76, 147, 242, 189, 12, 78, 69, 61, 81, 183, 33, 62, 157, 191, 212, 0, 62, 236, 148, 127, 59, 55, 63, 41, 3, 2, 0, 0, 164, 208, 90, 47, 0, 0, 0, 0, 224, 29, 15, 190, 16, 167, 125, 61, 220, 230, 68, 62, 157, 191, 212, 0, 69, 219, 157, 127, 191, 52, 63, 41, 3, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 103, 84, 4, 190, 220, 250, 183, 61, 166, 190, 75, 62, 214, 115, 226, 0, 74, 0, 154, 127, 191, 52, 72, 50, 3, 2, 0, 0, 71, 251, 183, 4, 0, 0, 0, 0, 227, 141, 201, 189, 216, 178, 192, 61, 135, 115, 42, 62, 214, 115, 226, 0, 88, 8, 166, 127, 59, 55, 72, 50, 3, 2, 1, 0, 174, 135, 58, 115, 22, 5, 0, 0, 24, 56, 5, 190, 70, 135, 156, 61, 251, 212, 24, 62, 214, 115, 226, 0, 79, 3, 158, 127, 59, 55, 63, 41, 3, 2, 0, 0, 162, 231, 92, 24, 0, 0, 0, 0, 169, 200, 28, 190, 120, 219, 163, 61, 97, 15, 65, 62, 214, 115, 226, 0, 62, 250, 146, 127, 191, 52, 63, 41, 3, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 168, 27, 244, 189, 191, 129, 151, 61, 76, 49, 78, 62, 79, 57, 80, 0, 88, 4, 166, 127, 191, 52, 72, 50, 3, 2, 0, 0, 46, 221, 208, 34, 0, 0, 0, 0, 227, 4, 174, 189, 112, 174, 143, 61, 173, 143, 45, 62, 79, 57, 80, 0, 93, 247, 171, 127, 59, 55, 72, 50, 2, 3, 0, 0, 251, 184, 3, 71, 0, 0, 0, 0, 227, 141, 201, 189, 216, 178, 192, 61, 135, 115, 42, 62, 79, 57, 80, 0, 92, 252, 169, 127, 59, 55, 63, 41, 3, 2, 1, 0, 174, 135, 58, 115, 22, 5, 0, 0, 103, 84, 4, 190, 220, 250, 183, 61, 166, 190, 75, 62, 79, 57, 80, 0, 85, 11, 164, 127, 191, 52, 63, 41, 3, 2, 0, 0, 71, 251, 183, 4, 0, 0, 0, 0, 137, 144, 230, 60, 197, 136, 76, 61, 69, 118, 161, 61, 59, 111, 241, 0, 241, 247, 131, 127, 191, 52, 72, 50, 4, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 44, 14, 234, 60, 249, 66, 84, 61, 68, 8, 102, 60, 59, 111, 241, 0, 248, 243, 131, 127, 59, 55, 72, 50, 0, 1, 0, 0, 121, 166, 133, 89, 0, 0, 0, 0, 162, 250, 144, 188, 67, 207, 138, 61, 86, 80, 4, 61, 59, 111, 241, 0, 243, 245, 131, 127, 59, 55, 63, 41, 1, 2, 4, 0, 121, 189, 220, 37, 169, 28, 0, 0, 182, 67, 140, 186, 5, 43, 165, 61, 126, 69, 214, 61, 59, 111, 241, 0, 236, 249, 131, 127, 191, 52, 63, 41, 4, 1, 2, 0, 162, 123, 7, 70, 84, 62, 0, 0, 137, 144, 230, 60, 197, 136, 76, 61, 69, 118, 161, 61, 89, 89, 247, 0, 173, 88, 36, 127, 191, 52, 72, 50, 4, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 182, 67, 140, 186, 5, 43, 165, 61, 126, 69, 214, 61, 89, 89, 247, 0, 184, 80, 65, 127, 59, 55, 72, 50, 4, 1, 2, 0, 162, 123, 7, 70, 84, 62, 0, 0, 219, 227, 252, 58, 125, 188, 171, 61, 252, 29, 23, 62, 89, 89, 247, 0, 172, 88, 33, 127, 59, 55, 63, 41, 4, 2, 0, 0, 9, 223, 245, 32, 0, 0, 0, 0, 172, 71, 15, 61, 88, 98, 70, 61, 44, 255, 17, 62, 89, 89, 247, 0, 168, 90, 13, 127, 191, 52, 63, 41, 4, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 154, 90, 46, 189, 36, 249, 163, 61, 114, 119, 8, 62, 249, 126, 245, 0, 20, 12, 124, 127, 191, 52, 72, 50, 2, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 104, 83, 27, 189, 67, 151, 169, 61, 49, 174, 26, 62, 249, 126, 245, 0, 32, 12, 122, 127, 59, 55, 72, 50, 4, 2, 0, 0, 33, 192, 221, 63, 0, 0, 0, 0, 219, 227, 252, 58, 125, 188, 171, 61, 252, 29, 23, 62, 249, 126, 245, 0, 14, 12, 125, 127, 59, 55, 63, 41, 4, 2, 0, 0, 9, 223, 245, 32, 0, 0, 0, 0, 182, 67, 140, 186, 5, 43, 165, 61, 126, 69, 214, 61, 249, 126, 245, 0, 8, 11, 126, 127, 191, 52, 63, 41, 4, 1, 2, 0, 162, 123, 7, 70, 84, 62, 0, 0, 31, 57, 161, 189, 158, 246, 21, 61, 80, 77, 237, 61, 160, 24, 79, 0, 81, 6, 97, 127, 109, 58, 72, 55, 2, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 85, 182, 58, 189, 223, 32, 23, 61, 79, 94, 18, 62, 160, 24, 79, 0, 81, 5, 97, 127, 172, 59, 72, 55, 1, 4, 8, 0, 150, 110, 184, 85, 175, 59, 0, 0, 104, 83, 27, 189, 67, 151, 169, 61, 49, 174, 26, 62, 160, 24, 79, 0, 81, 7, 96, 127, 172, 59, 204, 52, 4, 2, 0, 0, 33, 192, 221, 63, 0, 0, 0, 0, 154, 90, 46, 189, 36, 249, 163, 61, 114, 119, 8, 62, 160, 24, 79, 0, 81, 8, 96, 127, 109, 58, 204, 52, 2, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 104, 83, 27, 189, 67, 151, 169, 61, 49, 174, 26, 62, 240, 125, 11, 0, 38, 250, 120, 127, 191, 52, 72, 50, 4, 2, 0, 0, 33, 192, 221, 63, 0, 0, 0, 0, 83, 183, 171, 188, 119, 137, 156, 61, 15, 77, 70, 62, 240, 125, 11, 0, 45, 251, 118, 127, 59, 55, 72, 50, 4, 5, 0, 0, 175, 190, 79, 65, 0, 0, 0, 0, 67, 239, 90, 60, 92, 225, 175, 61, 221, 152, 67, 62, 240, 125, 11, 0, 40, 250, 120, 127, 59, 55, 63, 41, 5, 6, 0, 0, 33, 204, 221, 51, 0, 0, 0, 0, 219, 227, 252, 58, 125, 188, 171, 61, 252, 29, 23, 62, 240, 125, 11, 0, 34, 250, 122, 127, 191, 52, 63, 41, 4, 2, 0, 0, 9, 223, 245, 32, 0, 0, 0, 0, 85, 182, 58, 189, 223, 32, 23, 61, 79, 94, 18, 62, 144, 251, 58, 0, 58, 247, 112, 127, 109, 58, 72, 55, 1, 4, 8, 0, 150, 110, 184, 85, 175, 59, 0, 0, 68, 233, 248, 187, 157, 232, 21, 61, 102, 77, 82, 62, 144, 251, 58, 0, 58, 0, 112, 127, 172, 59, 72, 55, 5, 4, 0, 0, 208, 181, 46, 74, 0, 0, 0, 0, 83, 183, 171, 188, 119, 137, 156, 61, 15, 77, 70, 62, 144, 251, 58, 0, 58, 250, 112, 127, 172, 59, 204, 52, 4, 5, 0, 0, 175, 190, 79, 65, 0, 0, 0, 0, 104, 83, 27, 189, 67, 151, 169, 61, 49, 174, 26, 62, 144, 251, 58, 0, 58, 239, 111, 127, 109, 58, 204, 52, 4, 2, 0, 0, 33, 192, 221, 63, 0, 0, 0, 0, 176, 217, 22, 189, 53, 173, 29, 188, 94, 30, 249, 61, 152, 215, 59, 0, 63, 254, 109, 127, 109, 58, 72, 55, 12, 4, 5, 0, 237, 174, 73, 49, 199, 31, 0, 0, 184, 144, 161, 58, 217, 160, 76, 188, 90, 232, 66, 62, 152, 215, 59, 0, 63, 253, 109, 127, 172, 59, 72, 55, 8, 9, 0, 0, 151, 187, 103, 68, 0, 0, 0, 0, 68, 233, 248, 187, 157, 232, 21, 61, 102, 77, 82, 62, 152, 215, 59, 0, 63, 254, 109, 127, 172, 59, 204, 52, 5, 4, 0, 0, 208, 181, 46, 74, 0, 0, 0, 0, 85, 182, 58, 189, 223, 32, 23, 61, 79, 94, 18, 62, 152, 215, 59, 0, 63, 255, 110, 127, 109, 58, 204, 52, 1, 4, 8, 0, 150, 110, 184, 85, 175, 59, 0, 0, 176, 217, 22, 189, 53, 173, 29, 188, 94, 30, 249, 61, 177, 195, 77, 0, 236, 107, 64, 127, 109, 58, 72, 55, 12, 4, 5, 0, 237, 174, 73, 49, 199, 31, 0, 0, 85, 182, 58, 189, 223, 32, 23, 61, 79, 94, 18, 62, 177, 195, 77, 0, 229, 109, 58, 127, 172, 59, 72, 55, 1, 4, 8, 0, 150, 110, 184, 85, 175, 59, 0, 0, 31, 57, 161, 189, 158, 246, 21, 61, 80, 77, 237, 61, 177, 195, 77, 0, 234, 107, 63, 127, 172, 59, 204, 52, 2, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 65, 101, 141, 189, 47, 156, 31, 188, 216, 229, 167, 61, 177, 195, 77, 0, 241, 105, 68, 127, 109, 58, 204, 52, 1, 8, 4, 0, 83, 159, 119, 72, 51, 24, 0, 0, 65, 101, 141, 189, 47, 156, 31, 188, 216, 229, 167, 61, 145, 210, 38, 0, 30, 143, 207, 127, 109, 58, 72, 55, 1, 8, 4, 0, 83, 159, 119, 72, 51, 24, 0, 0, 48, 248, 55, 189, 205, 74, 56, 189, 126, 212, 98, 61, 145, 210, 38, 0, 25, 146, 199, 127, 172, 59, 72, 55, 16, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 234, 123, 30, 189, 170, 167, 104, 189, 82, 23, 232, 61, 145, 210, 38, 0, 30, 143, 209, 127, 172, 59, 204, 52, 16, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 176, 217, 22, 189, 53, 173, 29, 188, 94, 30, 249, 61, 145, 210, 38, 0, 35, 140, 219, 127, 109, 58, 204, 52, 12, 4, 5, 0, 237, 174, 73, 49, 199, 31, 0, 0, 65, 101, 141, 189, 47, 156, 31, 188, 216, 229, 167, 61, 141, 219, 219, 0, 24, 41, 139, 127, 109, 58, 72, 55, 1, 8, 4, 0, 83, 159, 119, 72, 51, 24, 0, 0, 197, 98, 87, 189, 182, 94, 111, 60, 245, 89, 152, 60, 141, 219, 219, 0, 24, 42, 139, 127, 172, 59, 72, 55, 1, 0, 0, 0, 222, 172, 32, 83, 0, 0, 0, 0, 2, 253, 32, 189, 33, 195, 2, 189, 118, 162, 84, 60, 141, 219, 219, 0, 24, 41, 139, 127, 172, 59, 204, 52, 0, 1, 0, 0, 156, 193, 98, 62, 0, 0, 0, 0, 48, 248, 55, 189, 205, 74, 56, 189, 126, 212, 98, 61, 141, 219, 219, 0, 25, 40, 139, 127, 109, 58, 204, 52, 16, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 87, 60, 133, 188, 239, 201, 153, 61, 185, 184, 156, 62, 196, 111, 248, 0, 206, 237, 114, 127, 191, 52, 72, 50, 6, 7, 0, 0, 159, 168, 95, 87, 0, 0, 0, 0, 47, 142, 5, 189, 237, 27, 147, 61, 235, 245, 177, 62, 196, 111, 248, 0, 213, 242, 118, 127, 59, 55, 72, 50, 7, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 27, 55, 116, 188, 38, 255, 162, 61, 146, 83, 182, 62, 196, 111, 248, 0, 210, 240, 116, 127, 59, 55, 63, 41, 7, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 171, 146, 7, 59, 235, 65, 181, 61, 83, 237, 162, 62, 196, 111, 248, 0, 203, 236, 113, 127, 191, 52, 63, 41, 7, 6, 5, 0, 228, 196, 142, 56, 140, 2, 0, 0, 45, 47, 223, 187, 254, 148, 159, 61, 225, 101, 131, 62, 144, 202, 234, 0, 55, 142, 253, 127, 109, 58, 72, 55, 6, 7, 0, 0, 198, 249, 56, 6, 0, 0, 0, 0, 118, 153, 132, 59, 105, 126, 93, 61, 224, 184, 130, 62, 144, 202, 234, 0, 55, 143, 251, 127, 172, 59, 72, 55, 5, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 156, 215, 144, 187, 112, 20, 85, 61, 206, 5, 157, 62, 144, 202, 234, 0, 55, 142, 0, 127, 172, 59, 204, 52, 6, 7, 0, 0, 245, 192, 9, 63, 0, 0, 0, 0, 87, 60, 133, 188, 239, 201, 153, 61, 185, 184, 156, 62, 144, 202, 234, 0, 54, 142, 2, 127, 109, 58, 204, 52, 6, 7, 0, 0, 159, 168, 95, 87, 0, 0, 0, 0, 118, 153, 132, 59, 105, 126, 93, 61, 224, 184, 130, 62, 41, 137, 0, 0, 119, 41, 12, 127, 191, 52, 72, 50, 5, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 1, 173, 250, 60, 11, 218, 130, 61, 59, 212, 130, 62, 41, 137, 0, 0, 119, 41, 0, 127, 59, 55, 72, 50, 5, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 154, 9, 132, 60, 173, 82, 112, 61, 234, 20, 162, 62, 41, 137, 0, 0, 114, 40, 36, 127, 59, 55, 63, 41, 7, 6, 0, 0, 207, 161, 47, 94, 0, 0, 0, 0, 156, 215, 144, 187, 112, 20, 85, 61, 206, 5, 157, 62, 41, 137, 0, 0, 108, 38, 52, 127, 191, 52, 63, 41, 6, 7, 0, 0, 245, 192, 9, 63, 0, 0, 0, 0, 171, 146, 7, 59, 235, 65, 181, 61, 83, 237, 162, 62, 104, 40, 60, 0, 196, 246, 111, 127, 191, 52, 72, 50, 7, 6, 5, 0, 228, 196, 142, 56, 140, 2, 0, 0, 27, 55, 116, 188, 38, 255, 162, 61, 146, 83, 182, 62, 104, 40, 60, 0, 203, 229, 111, 127, 59, 55, 72, 50, 7, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 153, 159, 221, 187, 197, 176, 107, 61, 245, 96, 181, 62, 104, 40, 60, 0, 199, 239, 111, 127, 59, 55, 63, 41, 7, 6, 0, 0, 121, 242, 133, 13, 0, 0, 0, 0, 154, 9, 132, 60, 173, 82, 112, 61, 234, 20, 162, 62, 104, 40, 60, 0, 193, 254, 110, 127, 191, 52, 63, 41, 7, 6, 0, 0, 207, 161, 47, 94, 0, 0, 0, 0, 147, 75, 11, 61, 26, 228, 9, 189, 71, 21, 82, 189, 231, 255, 132, 0, 141, 211, 24, 129, 28, 53, 20, 44, 1, 4, 8, 12, 255, 63, 255, 63, 255, 63, 255, 63, 230, 187, 142, 186, 107, 2, 128, 189, 124, 87, 32, 189, 231, 255, 132, 0, 137, 221, 25, 129, 253, 53, 63, 41, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 8, 40, 5, 189, 234, 132, 92, 189, 226, 153, 0, 189, 231, 255, 132, 0, 139, 216, 24, 129, 222, 54, 20, 44, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 144, 84, 51, 189, 9, 102, 212, 188, 87, 117, 7, 189, 231, 255, 132, 0, 151, 190, 22, 129, 59, 55, 151, 47, 0, 1, 4, 8, 162, 77, 116, 59, 116, 59, 116, 59, 162, 187, 17, 189, 69, 33, 103, 60, 4, 150, 29, 189, 231, 255, 132, 0, 143, 204, 24, 129, 222, 54, 141, 49, 0, 1, 0, 0, 225, 215, 29, 40, 0, 0, 0, 0, 140, 40, 115, 188, 18, 4, 70, 61, 124, 216, 32, 189, 231, 255, 132, 0, 147, 197, 23, 129, 253, 53, 72, 50, 0, 1, 0, 0, 132, 187, 122, 68, 0, 0, 0, 0, 98, 97, 214, 60, 208, 204, 64, 61, 0, 251, 54, 189, 231, 255, 132, 0, 145, 200, 23, 129, 28, 53, 141, 49, 1, 4, 8, 12, 255, 63, 255, 63, 255, 63, 255, 63, 14, 13, 62, 61, 90, 98, 87, 60, 74, 125, 89, 189, 231, 255, 132, 0, 140, 211, 24, 129, 191, 52, 151, 47, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0 ), -"array_index_data": PoolByteArray( 0, 0, 2, 0, 1, 0, 0, 0, 3, 0, 2, 0, 4, 0, 6, 0, 5, 0, 4, 0, 7, 0, 6, 0, 8, 0, 10, 0, 9, 0, 8, 0, 11, 0, 10, 0, 12, 0, 14, 0, 13, 0, 12, 0, 15, 0, 14, 0, 16, 0, 18, 0, 17, 0, 16, 0, 19, 0, 18, 0, 20, 0, 22, 0, 21, 0, 20, 0, 23, 0, 22, 0, 24, 0, 26, 0, 25, 0, 24, 0, 27, 0, 26, 0, 28, 0, 30, 0, 29, 0, 28, 0, 31, 0, 30, 0, 32, 0, 34, 0, 33, 0, 32, 0, 35, 0, 34, 0, 36, 0, 38, 0, 37, 0, 36, 0, 39, 0, 38, 0, 40, 0, 42, 0, 41, 0, 40, 0, 43, 0, 42, 0, 44, 0, 46, 0, 45, 0, 44, 0, 47, 0, 46, 0, 48, 0, 50, 0, 49, 0, 48, 0, 51, 0, 50, 0, 52, 0, 54, 0, 53, 0, 52, 0, 55, 0, 54, 0, 56, 0, 58, 0, 57, 0, 56, 0, 59, 0, 58, 0, 60, 0, 62, 0, 61, 0, 60, 0, 63, 0, 62, 0, 64, 0, 66, 0, 65, 0, 64, 0, 67, 0, 66, 0, 68, 0, 70, 0, 69, 0, 68, 0, 71, 0, 70, 0, 72, 0, 74, 0, 73, 0, 72, 0, 75, 0, 74, 0, 76, 0, 78, 0, 77, 0, 76, 0, 79, 0, 78, 0, 80, 0, 82, 0, 81, 0, 80, 0, 83, 0, 82, 0, 84, 0, 86, 0, 85, 0, 84, 0, 87, 0, 86, 0, 88, 0, 90, 0, 89, 0, 88, 0, 91, 0, 90, 0, 92, 0, 94, 0, 93, 0, 92, 0, 95, 0, 94, 0, 96, 0, 98, 0, 97, 0, 96, 0, 99, 0, 98, 0, 100, 0, 102, 0, 101, 0, 100, 0, 103, 0, 102, 0, 104, 0, 106, 0, 105, 0, 104, 0, 107, 0, 106, 0, 108, 0, 110, 0, 109, 0, 108, 0, 111, 0, 110, 0, 112, 0, 114, 0, 113, 0, 112, 0, 115, 0, 114, 0, 116, 0, 118, 0, 117, 0, 116, 0, 119, 0, 118, 0, 120, 0, 122, 0, 121, 0, 120, 0, 123, 0, 122, 0, 124, 0, 126, 0, 125, 0, 124, 0, 127, 0, 126, 0, 128, 0, 130, 0, 129, 0, 128, 0, 131, 0, 130, 0, 132, 0, 134, 0, 133, 0, 132, 0, 135, 0, 134, 0, 136, 0, 138, 0, 137, 0, 136, 0, 139, 0, 138, 0, 140, 0, 142, 0, 141, 0, 140, 0, 143, 0, 142, 0, 144, 0, 146, 0, 145, 0, 144, 0, 147, 0, 146, 0, 148, 0, 150, 0, 149, 0, 148, 0, 151, 0, 150, 0, 152, 0, 154, 0, 153, 0, 152, 0, 155, 0, 154, 0, 156, 0, 158, 0, 157, 0, 156, 0, 159, 0, 158, 0, 160, 0, 162, 0, 161, 0, 160, 0, 163, 0, 162, 0, 164, 0, 166, 0, 165, 0, 164, 0, 167, 0, 166, 0, 168, 0, 170, 0, 169, 0, 168, 0, 171, 0, 170, 0, 172, 0, 174, 0, 173, 0, 172, 0, 175, 0, 174, 0, 176, 0, 178, 0, 177, 0, 176, 0, 179, 0, 178, 0, 180, 0, 182, 0, 181, 0, 180, 0, 183, 0, 182, 0, 184, 0, 186, 0, 185, 0, 184, 0, 187, 0, 186, 0, 188, 0, 190, 0, 189, 0, 188, 0, 191, 0, 190, 0, 192, 0, 194, 0, 193, 0, 192, 0, 195, 0, 194, 0, 196, 0, 198, 0, 197, 0, 196, 0, 199, 0, 198, 0, 200, 0, 202, 0, 201, 0, 200, 0, 203, 0, 202, 0, 204, 0, 206, 0, 205, 0, 204, 0, 207, 0, 206, 0, 208, 0, 210, 0, 209, 0, 208, 0, 211, 0, 210, 0, 212, 0, 214, 0, 213, 0, 212, 0, 215, 0, 214, 0, 216, 0, 218, 0, 217, 0, 216, 0, 219, 0, 218, 0, 220, 0, 222, 0, 221, 0, 220, 0, 223, 0, 222, 0, 224, 0, 226, 0, 225, 0, 224, 0, 227, 0, 226, 0, 228, 0, 230, 0, 229, 0, 228, 0, 231, 0, 230, 0, 232, 0, 234, 0, 233, 0, 232, 0, 235, 0, 234, 0, 236, 0, 238, 0, 237, 0, 236, 0, 239, 0, 238, 0, 240, 0, 242, 0, 241, 0, 240, 0, 243, 0, 242, 0, 244, 0, 246, 0, 245, 0, 244, 0, 247, 0, 246, 0, 248, 0, 250, 0, 249, 0, 248, 0, 251, 0, 250, 0, 252, 0, 254, 0, 253, 0, 252, 0, 255, 0, 254, 0, 0, 1, 2, 1, 1, 1, 0, 1, 3, 1, 2, 1, 4, 1, 6, 1, 5, 1, 4, 1, 7, 1, 6, 1, 8, 1, 10, 1, 9, 1, 8, 1, 11, 1, 10, 1, 12, 1, 14, 1, 13, 1, 12, 1, 15, 1, 14, 1, 16, 1, 18, 1, 17, 1, 16, 1, 19, 1, 18, 1, 20, 1, 22, 1, 21, 1, 20, 1, 23, 1, 22, 1, 24, 1, 26, 1, 25, 1, 24, 1, 27, 1, 26, 1, 28, 1, 30, 1, 29, 1, 28, 1, 31, 1, 30, 1, 32, 1, 34, 1, 33, 1, 32, 1, 35, 1, 34, 1, 36, 1, 38, 1, 37, 1, 36, 1, 39, 1, 38, 1, 40, 1, 42, 1, 41, 1, 40, 1, 43, 1, 42, 1, 44, 1, 46, 1, 45, 1, 44, 1, 47, 1, 46, 1, 48, 1, 50, 1, 49, 1, 48, 1, 51, 1, 50, 1, 52, 1, 54, 1, 53, 1, 52, 1, 55, 1, 54, 1, 56, 1, 58, 1, 57, 1, 56, 1, 59, 1, 58, 1, 60, 1, 62, 1, 61, 1, 60, 1, 63, 1, 62, 1, 64, 1, 66, 1, 65, 1, 64, 1, 67, 1, 66, 1, 68, 1, 70, 1, 69, 1, 68, 1, 71, 1, 70, 1, 72, 1, 74, 1, 73, 1, 72, 1, 75, 1, 74, 1, 76, 1, 78, 1, 77, 1, 76, 1, 79, 1, 78, 1, 80, 1, 82, 1, 81, 1, 80, 1, 83, 1, 82, 1, 84, 1, 86, 1, 85, 1, 84, 1, 87, 1, 86, 1, 88, 1, 90, 1, 89, 1, 88, 1, 91, 1, 90, 1, 92, 1, 94, 1, 93, 1, 92, 1, 95, 1, 94, 1, 96, 1, 98, 1, 97, 1, 96, 1, 99, 1, 98, 1, 100, 1, 102, 1, 101, 1, 100, 1, 103, 1, 102, 1, 104, 1, 106, 1, 105, 1, 104, 1, 107, 1, 106, 1, 108, 1, 110, 1, 109, 1, 108, 1, 111, 1, 110, 1, 112, 1, 114, 1, 113, 1, 112, 1, 115, 1, 114, 1, 116, 1, 118, 1, 117, 1, 116, 1, 119, 1, 118, 1, 120, 1, 122, 1, 121, 1, 120, 1, 123, 1, 122, 1, 124, 1, 126, 1, 125, 1, 124, 1, 127, 1, 126, 1, 128, 1, 130, 1, 129, 1, 128, 1, 131, 1, 130, 1, 132, 1, 134, 1, 133, 1, 132, 1, 135, 1, 134, 1, 136, 1, 138, 1, 137, 1, 136, 1, 139, 1, 138, 1, 140, 1, 142, 1, 141, 1, 142, 1, 144, 1, 143, 1, 144, 1, 146, 1, 145, 1, 146, 1, 140, 1, 147, 1, 140, 1, 144, 1, 142, 1, 144, 1, 140, 1, 146, 1 ), -"blend_shape_data": [ ], -"format": 97751, -"index_count": 612, -"primitive": 4, -"skeleton_aabb": [ AABB( -0.0525844, -0.0664643, -0.053098, 0.102899, 0.118286, 0.110326 ), AABB( -0.0984152, -0.0336648, -0.0512898, 0.14873, 0.128013, 0.217746 ), AABB( -0.130097, 0.0366121, 0.0323032, 0.132026, 0.0577362, 0.169057 ), AABB( -0.153109, 0.0481701, 0.0715663, 0.0681389, 0.045921, 0.129794 ), AABB( -0.0690408, -0.0336648, -0.0512898, 0.113064, 0.11752, 0.256663 ), AABB( -0.0368287, -0.00962382, 0.12164, 0.072863, 0.102718, 0.196577 ), AABB( -0.0224757, 0.0516016, 0.191013, 0.0385935, 0.041493, 0.163243 ), AABB( -0.0326063, 0.0516016, 0.256637, 0.0487242, 0.036903, 0.0994697 ), AABB( -0.0690408, -0.0496616, -0.0512898, 0.11443, 0.0967319, 0.310404 ), AABB( -3.9702e-05, -0.0124895, 0.190339, 0.0352953, 0.105584, 0.119241 ), AABB( -0.0404907, -0.00945412, 0.24973, 0.0757463, 0.043931, 0.102211 ), AABB( -0.0521673, -0.0152202, 0.298738, 0.0575357, 0.039564, 0.0532033 ), AABB( -0.0368287, -0.0591667, -0.0512898, 0.0792034, 0.106237, 0.271428 ), AABB( -0.00677999, -0.0639067, 0.177581, 0.0491547, 0.0946642, 0.115502 ), AABB( -0.0533399, -0.0659878, 0.177581, 0.0957147, 0.0597627, 0.135919 ), AABB( -0.0533399, -0.0659878, 0.260635, 0.0471124, 0.0291992, 0.0528653 ), AABB( -0.0449144, -0.0981952, 0.00742788, 0.0903039, 0.0970927, 0.192096 ), AABB( -0.03332, -0.0997347, 0.162896, 0.0623965, 0.0403167, 0.0458426 ), AABB( -0.054016, -0.102447, 0.162896, 0.0830925, 0.042668, 0.0818059 ), AABB( -0.0568424, -0.102447, 0.193177, 0.0655006, 0.0260357, 0.0529011 ) ], -"vertex_count": 404 -} - -[sub_resource type="Skin" id=2] -resource_name = "Skin" -bind_count = 20 -bind/0/name = "root" -bind/0/bone = -1 -bind/0/pose = Transform3D( 14.6676, -3.25578e-15, -3.34124e-15, 3.25578e-15, -0.379962, 14.6627, -3.34124e-15, -14.6627, -0.379962, -1.57052e-16, 0.689478, -0.00727978 ) -bind/1/name = "thumb_metacarpal" -bind/1/bone = -1 -bind/1/pose = Transform3D( 12.5908, 5.77169, 4.8269, -7.49463, 8.78929, 9.03981, 0.664731, -10.2262, 10.4939, -0.096063, -0.182017, -0.232635 ) -bind/2/name = "thumb_proximal" -bind/2/bone = -1 -bind/2/pose = Transform3D( 9.58097, 9.35126, 5.99152, -8.44307, 0.992087, 11.9528, 7.21519, -11.2565, 6.03086, -0.646462, -1.72878, 0.668668 ) -bind/3/name = "thumb_distal" -bind/3/bone = -1 -bind/3/pose = Transform3D( 9.4053, 9.19995, 6.48388, -8.36392, 0.0587307, 12.0491, 7.53157, -11.4235, 5.28374, -0.732799, -2.83757, 0.835363 ) -bind/4/name = "index_metacarpal" -bind/4/bone = -1 -bind/4/pose = Transform3D( 14.657, -0.558095, 0.00375232, 0.165674, 4.44501, 13.9769, -0.53295, -13.9667, 4.44809, -0.000662332, -0.290977, -0.108669 ) -bind/5/name = "index_proximal" -bind/5/bone = -1 -bind/5/pose = Transform3D( 14.5744, -0.870475, -1.40312, 1.58655, 3.92887, 14.0423, -0.457524, -14.1048, 3.99806, 0.285342, -2.89927, -0.0153612 ) -bind/6/name = "index_middle" -bind/6/bone = -1 -bind/6/pose = Transform3D( 14.4337, -0.294101, 2.5927, -2.60155, -0.497281, 14.4265, -0.201365, -14.6562, -0.541512, -0.779147, -3.63979, 1.18571 ) -bind/7/name = "index_distal" -bind/7/bone = -1 -bind/7/pose = Transform3D( 13.6042, -0.0718902, 5.48258, -5.47638, -0.901479, 13.577, 0.270417, -14.6397, -0.862963, -1.69648, -4.17576, 1.28513 ) -bind/8/name = "middle_metacarpal" -bind/8/bone = -1 -bind/8/pose = Transform3D( 14.6175, -0.0757868, -1.20941, 1.21008, 1.68968, 14.5196, 0.0642995, -14.5698, 1.69015, 0.0255007, -0.305335, -0.0509669 ) -bind/9/name = "middle_proximal" -bind/9/bone = -1 -bind/9/pose = Transform3D( 14.6563, 0.0310658, -0.576067, 0.576898, -0.719451, 14.6386, 0.00274813, -14.6499, -0.720116, -0.0988201, -2.80872, 0.414763 ) -bind/10/name = "middle_middle" -bind/10/bone = -1 -bind/10/pose = Transform3D( 13.2173, -0.670194, 6.32404, -6.34963, -2.20108, 13.0375, 0.353298, -14.486, -2.27356, -1.80169, -3.14325, 0.797598 ) -bind/11/name = "middle_distal" -bind/11/bone = -1 -bind/11/pose = Transform3D( 10.6125, -2.5317, 9.80327, -10.1248, -2.70381, 10.2624, 0.0357855, -14.1922, -3.70389, -2.8841, -3.23617, 1.2315 ) -bind/12/name = "ring_metacarpal" -bind/12/bone = -1 -bind/12/pose = Transform3D( 14.6531, 0.115638, -0.642376, 0.652627, -2.81377, 14.3804, -0.00985721, -14.3947, -2.81613, 0.0137075, -0.307094, 0.0445267 ) -bind/13/name = "ring_proximal" -bind/13/bone = -1 -bind/13/pose = Transform3D( 14.5674, 0.172977, -1.70275, 1.70869, -2.30774, 14.3838, -0.0982737, -14.4839, -2.31213, 0.20267, -2.61502, -0.0463217 ) -bind/14/name = "ring_middle" -bind/14/bone = -1 -bind/14/pose = Transform3D( 12.6957, -2.43642, 6.92976, -7.31356, -2.90169, 12.3787, -0.685296, -14.1698, -3.72643, -1.87717, -2.88537, 0.302059 ) -bind/15/name = "ring_distal" -bind/15/bone = -1 -bind/15/pose = Transform3D( 6.96749, -7.32827, 10.625, -12.6413, -1.43678, 7.29877, -2.60585, -12.6242, -6.99839, -3.21578, -2.24402, 1.25915 ) -bind/16/name = "pinky_metacarpal" -bind/16/bone = -1 -bind/16/pose = Transform3D( 14.6649, 0.240666, -0.14888, 0.243921, -6.83709, 12.9744, 0.143485, -12.9744, -6.83982, 0.00340029, -0.281558, 0.131114 ) -bind/17/name = "pinky_proximal" -bind/17/bone = -1 -bind/17/pose = Transform3D( 14.5056, -0.766076, 2.03498, -2.16996, -4.22381, 13.8777, -0.13881, -14.0254, -4.29047, -0.415818, -2.50159, -0.348904 ) -bind/18/name = "pinky_middle" -bind/18/bone = -1 -bind/18/pose = Transform3D( 10.8544, -4.52678, 8.76525, -9.65726, -2.21439, 10.8154, -2.01459, -13.7748, -4.61917, -2.06231, -2.33397, -0.269481 ) -bind/19/name = "pinky_distal" -bind/19/bone = -1 -bind/19/pose = Transform3D( 6.79568, -7.5217, 10.601, -12.0636, 0.804824, 8.30428, -4.8402, -12.5664, -5.81345, -2.82289, -2.01484, 0.0332269 ) - -[sub_resource type="Animation" id=3] -resource_name = "Grip" -length = 2.5 -tracks/0/type = "transform" -tracks/0/path = NodePath("Armature_Left/Skeleton:thumb_distal") -tracks/0/interp = 1 -tracks/0/loop_wrap = true -tracks/0/imported = true -tracks/0/enabled = true -tracks/0/keys = PoolRealArray( 0, 1, 0, 0, 0, -1.6263e-19, -9.31323e-10, -2.44472e-09, 1, 1, 1, 1, 2.5, 1, 0, 0, 0, -1.6263e-19, -9.31323e-10, -2.44472e-09, 1, 1, 1, 1 ) -tracks/1/type = "transform" -tracks/1/path = NodePath("Armature_Left/Skeleton:thumb_proximal") -tracks/1/interp = 1 -tracks/1/loop_wrap = true -tracks/1/imported = true -tracks/1/enabled = true -tracks/1/keys = PoolRealArray( 0, 1, 0, 0, 0, -1.49012e-08, 3.72529e-09, -7.45058e-09, 1, 1, 1, 1, 2.5, 1, 0, 0, 0, -1.49012e-08, 3.72529e-09, -7.45058e-09, 1, 1, 1, 1 ) -tracks/2/type = "transform" -tracks/2/path = NodePath("Armature_Left/Skeleton:thumb_metacarpal") -tracks/2/interp = 1 -tracks/2/loop_wrap = true -tracks/2/imported = true -tracks/2/enabled = true -tracks/2/keys = PoolRealArray( 0, 1, 0, 0, 0, 2.98023e-08, -1.49012e-08, 7.45058e-09, 1, 1, 1, 1, 2.5, 1, 0, 0, 0, 2.98023e-08, -1.49012e-08, 7.45058e-09, 1, 1, 1, 1 ) -tracks/3/type = "transform" -tracks/3/path = NodePath("Armature_Left/Skeleton:index_distal") -tracks/3/interp = 1 -tracks/3/loop_wrap = true -tracks/3/imported = true -tracks/3/enabled = true -tracks/3/keys = PoolRealArray( 0, 1, 0, 0, 0, 1.86265e-09, 1.86265e-09, 2.65427e-08, 1, 1, 1, 1, 2.5, 1, 0, 0, 0, 1.86265e-09, 1.86265e-09, 2.65427e-08, 1, 1, 1, 1 ) -tracks/4/type = "transform" -tracks/4/path = NodePath("Armature_Left/Skeleton:index_middle") -tracks/4/interp = 1 -tracks/4/loop_wrap = true -tracks/4/imported = true -tracks/4/enabled = true -tracks/4/keys = PoolRealArray( 0, 1, 0, 0, 0, -5.29091e-17, -1.86264e-09, 9.31323e-09, 1, 1, 1, 1, 2.5, 1, 0, 0, 0, -5.29091e-17, -1.86264e-09, 9.31323e-09, 1, 1, 1, 1 ) -tracks/5/type = "transform" -tracks/5/path = NodePath("Armature_Left/Skeleton:index_proximal") -tracks/5/interp = 1 -tracks/5/loop_wrap = true -tracks/5/imported = true -tracks/5/enabled = true -tracks/5/keys = PoolRealArray( 0, 1, 0, 0, 0, -3.25938e-18, 4.65661e-10, -2.31375e-09, 1, 1, 1, 1, 2.5, 1, 0, 0, 0, -3.25938e-18, 4.65661e-10, -2.31375e-09, 1, 1, 1, 1 ) -tracks/6/type = "transform" -tracks/6/path = NodePath("Armature_Left/Skeleton:index_metacarpal") -tracks/6/interp = 1 -tracks/6/loop_wrap = true -tracks/6/imported = true -tracks/6/enabled = true -tracks/6/keys = PoolRealArray( 0, 1, 0, 0, 0, -1.49012e-08, -1.86265e-09, -2.77556e-17, 1, 1, 1, 1, 2.5, 1, 0, 0, 0, -1.49012e-08, -1.86265e-09, -2.77556e-17, 1, 1, 1, 1 ) -tracks/7/type = "transform" -tracks/7/path = NodePath("Armature_Left/Skeleton:middle_distal") -tracks/7/interp = 1 -tracks/7/loop_wrap = true -tracks/7/imported = true -tracks/7/enabled = true -tracks/7/keys = PoolRealArray( 0, 1, 0, 0, 0, -3.72529e-09, 1.72171e-16, -3.28291e-08, 1, 1, 1, 1, 0.0666667, 1, 2.98023e-08, -1.19209e-07, 0, 2.65813e-05, 2.83944e-05, 0.000149045, 1, 1, 1, 1, 0.133333, 1, 4.17233e-07, -2.38419e-07, -1.04308e-07, 0.000218164, 0.000233005, 0.00122297, 0.999999, 1, 1, 1, 0.2, 1, 7.45058e-07, -2.98023e-07, 9.68575e-08, 0.000626045, 0.00066863, 0.00350955, 0.999993, 1, 1, 1, 0.266667, 1, -1.19209e-07, -2.38419e-07, 7.45058e-08, 0.00123732, 0.00132145, 0.00693625, 0.999974, 1, 1, 1, 0.333333, 1, 4.76837e-07, 0, -7.45058e-09, 0.00202596, 0.00216369, 0.0113572, 0.999931, 1, 1, 1, 1.53333, 1, 3.57628e-07, 1.19209e-07, 0, 0.0345678, 0.0369178, 0.193781, 0.97974, 1, 1, 1, 2.33333, 1, 7.15256e-07, 1.19209e-07, 0, 0.0513518, 0.0548427, 0.287869, 0.954718, 1, 1, 1, 2.4, 1, 4.17233e-07, 0, 0, 0.0517564, 0.0552749, 0.290137, 0.953985, 1, 1, 1, 2.46667, 1, 5.96046e-08, 1.19209e-07, -7.45058e-09, 0.0519717, 0.0555048, 0.291343, 0.953592, 1, 1, 1, 2.5, 1, 2.68221e-07, 0, 0, 0.0520055, 0.0555409, 0.291533, 0.95353, 1, 1, 1 ) -tracks/8/type = "transform" -tracks/8/path = NodePath("Armature_Left/Skeleton:middle_middle") -tracks/8/interp = 1 -tracks/8/loop_wrap = true -tracks/8/imported = true -tracks/8/enabled = true -tracks/8/keys = PoolRealArray( 0, 1, 0, 0, 0, 7.45058e-09, 1.86265e-09, 2.5495e-08, 1, 1, 1, 1, 0.0666667, 1, 1.49012e-07, 2.38419e-07, -7.45058e-09, 7.07822e-06, 2.32404e-05, 0.000152942, 1, 1, 1, 1, 0.133333, 1, -2.38419e-07, 1.78814e-07, -1.49012e-08, 5.80504e-05, 0.000190656, 0.00125477, 0.999999, 1, 1, 1, 0.2, 1, -2.98023e-08, 2.38419e-07, -7.45058e-09, 0.000166589, 0.000547086, 0.00360057, 0.999993, 1, 1, 1, 0.266667, 1, -1.49012e-07, -1.78814e-07, 7.45058e-09, 0.000329233, 0.00108125, 0.00711614, 0.999974, 1, 1, 1, 0.333333, 1, -2.08616e-07, -2.38419e-07, -6.70552e-08, 0.000539059, 0.00177043, 0.0116518, 0.999931, 1, 1, 1, 1.53333, 1, -1.19209e-07, 5.96046e-08, -1.49012e-08, 0.00919863, 0.0302105, 0.198825, 0.979526, 1, 1, 1, 2.33333, 1, 2.68221e-07, 2.38419e-07, 5.21541e-08, 0.0136635, 0.044874, 0.295331, 0.954243, 1, 1, 1, 2.4, 1, 0, 1.78814e-07, -1.49012e-08, 0.0137711, 0.0452275, 0.297657, 0.953502, 1, 1, 1, 2.46667, 1, 1.49012e-07, 4.76837e-07, -7.45058e-09, 0.0138283, 0.0454154, 0.298894, 0.953105, 1, 1, 1, 2.5, 1, -2.08616e-07, 3.57628e-07, -7.45058e-09, 0.0138373, 0.045445, 0.299089, 0.953042, 1, 1, 1 ) -tracks/9/type = "transform" -tracks/9/path = NodePath("Armature_Left/Skeleton:middle_proximal") -tracks/9/interp = 1 -tracks/9/loop_wrap = true -tracks/9/imported = true -tracks/9/enabled = true -tracks/9/keys = PoolRealArray( 0, 1, 0, 0, 0, -7.45058e-09, 3.49246e-10, -1.29512e-09, 1, 1, 1, 1, 0.0666667, 1, 0, 0, 0, -4.04005e-07, 9.06542e-06, 0.000184591, 1, 1, 1, 1, 0.133333, 1, 0, 0, 0, -3.23447e-06, 7.43869e-05, 0.00151474, 0.999999, 1, 1, 1, 0.2, 1, 0, 0, 0, -9.23564e-06, 0.000213497, 0.00434737, 0.999991, 1, 1, 1, 0.266667, 1, 0, 0, 0, -1.82459e-05, 0.000422056, 0.00859418, 0.999963, 1, 1, 1, 0.333333, 1, 0, 0, 0, -2.98645e-05, 0.00069126, 0.0140759, 0.999901, 1, 1, 1, 1.33333, 1, 0, 0, 0, -0.000419086, 0.00970516, 0.197623, 0.98023, 1, 1, 1, 2.5, 1, 0, 0, 0, -0.000765604, 0.0177302, 0.361034, 0.932384, 1, 1, 1 ) -tracks/10/type = "transform" -tracks/10/path = NodePath("Armature_Left/Skeleton:middle_metacarpal") -tracks/10/interp = 1 -tracks/10/loop_wrap = true -tracks/10/imported = true -tracks/10/enabled = true -tracks/10/keys = PoolRealArray( 0, 1, 0, 0, 0, -1.49012e-08, -6.98492e-10, 0, 1, 1, 1, 1, 2.5, 1, 0, 0, 0, -1.49012e-08, -6.98492e-10, 0, 1, 1, 1, 1 ) -tracks/11/type = "transform" -tracks/11/path = NodePath("Armature_Left/Skeleton:ring_distal") -tracks/11/interp = 1 -tracks/11/loop_wrap = true -tracks/11/imported = true -tracks/11/enabled = true -tracks/11/keys = PoolRealArray( 0, 1, 0, 0, 0, 8.84756e-09, -1.49012e-08, 2.35159e-08, 1, 1, 1, 1, 0.0666667, 1, 1.49012e-07, 1.78814e-07, 0, 4.74064e-05, 9.25749e-06, 8.1701e-05, 1, 1, 1, 1, 0.133333, 1, 2.98023e-08, 2.38419e-07, 0, 0.000388909, 7.62565e-05, 0.000669959, 1, 1, 1, 1, 0.2, 1, -1.19209e-07, -1.19209e-07, 8.9407e-08, 0.00111576, 0.000218748, 0.00192207, 0.999997, 1, 1, 1, 0.266667, 1, -3.8743e-07, 0, -2.6077e-07, 0.00220442, 0.000432149, 0.00379746, 0.99999, 1, 1, 1, 0.333333, 1, 0, 4.76837e-07, -1.19209e-07, 0.00360802, 0.000707361, 0.00621548, 0.999974, 1, 1, 1, 2.5, 1, -2.38419e-07, 5.96046e-08, -7.45058e-09, 0.0927168, 0.0181779, 0.159721, 0.98263, 1, 1, 1 ) -tracks/12/type = "transform" -tracks/12/path = NodePath("Armature_Left/Skeleton:ring_middle") -tracks/12/interp = 1 -tracks/12/loop_wrap = true -tracks/12/imported = true -tracks/12/enabled = true -tracks/12/keys = PoolRealArray( 0, 1, 0, 0, 0, 3.72529e-09, -1.07553e-16, -1.44355e-08, 1, 1, 1, 1, 0.0666667, 1, 2.98023e-07, 2.98023e-07, -7.45058e-09, 2.48732e-05, 2.96159e-05, 0.000144602, 1, 1, 1, 1, 0.133333, 1, 4.76837e-07, 2.38419e-07, -7.45058e-09, 0.000204107, 0.000243094, 0.00118704, 0.999999, 1, 1, 1, 0.2, 1, 6.55651e-07, 2.38419e-07, -7.45058e-09, 0.000585731, 0.000697582, 0.00340651, 0.999994, 1, 1, 1, 0.266667, 1, 2.68221e-07, 2.98023e-07, -7.45058e-09, 0.00115762, 0.00137866, 0.00673248, 0.999976, 1, 1, 1, 0.333333, 1, 2.38419e-07, 0, -1.49012e-08, 0.00189538, 0.00225731, 0.0110231, 0.999935, 1, 1, 1, 1.53333, 1, 2.68221e-07, 3.57628e-07, -7.45058e-09, 0.0323235, 0.0384961, 0.187988, 0.980884, 1, 1, 1, 2.33333, 1, 2.38419e-07, 3.57628e-07, 5.21541e-08, 0.0480449, 0.0572197, 0.279421, 0.957257, 1, 1, 1, 2.4, 1, 2.98023e-08, 2.98023e-07, -2.98023e-08, 0.0484245, 0.0576718, 0.281629, 0.956564, 1, 1, 1, 2.46667, 1, 4.47035e-07, 2.38419e-07, -2.98023e-08, 0.0486265, 0.0579123, 0.282803, 0.956192, 1, 1, 1, 2.5, 1, 2.38419e-07, 2.38419e-07, -2.23517e-08, 0.0486582, 0.05795, 0.282988, 0.956134, 1, 1, 1 ) -tracks/13/type = "transform" -tracks/13/path = NodePath("Armature_Left/Skeleton:ring_proximal") -tracks/13/interp = 1 -tracks/13/loop_wrap = true -tracks/13/imported = true -tracks/13/enabled = true -tracks/13/keys = PoolRealArray( 0, 1, 0, 0, 0, -2.81893e-18, 4.65661e-10, -4.5402e-09, 1, 1, 1, 1, 0.0666667, 1, 0, 0, 0, -3.07837e-06, 4.10864e-05, 0.000257872, 1, 1, 1, 1, 0.133333, 1, 0, 0, 0, -2.52729e-05, 0.000337251, 0.00211667, 0.999998, 1, 1, 1, 0.2, 1, 0, 0, 0, -7.25836e-05, 0.000968453, 0.00607824, 0.999981, 1, 1, 1, 0.266667, 1, 0, 0, 0, -0.000143621, 0.00191613, 0.0120261, 0.999926, 1, 1, 1, 0.333333, 1, 0, 0, 0, -0.000235467, 0.00314143, 0.0197163, 0.999801, 1, 1, 1, 1.06667, 1, 0, 0, 0, -0.00234691, 0.0313109, 0.196515, 0.979998, 1, 1, 1, 1.6, 1, 0, 0, 0, -0.00432212, 0.0576628, 0.361905, 0.93042, 1, 1, 1, 2.33333, 1, 0, 0, 0, -0.00595454, 0.0794416, 0.498594, 0.863167, 1, 1, 1, 2.4, 1, 0, 0, 0, -0.00599696, 0.0800073, 0.502145, 0.861054, 1, 1, 1, 2.46667, 1, 0, 0, 0, -0.00601945, 0.0803075, 0.504029, 0.859924, 1, 1, 1, 2.5, 1, 0, 0, 0, -0.00602299, 0.0803546, 0.504324, 0.859746, 1, 1, 1 ) -tracks/14/type = "transform" -tracks/14/path = NodePath("Armature_Left/Skeleton:ring_metacarpal") -tracks/14/interp = 1 -tracks/14/loop_wrap = true -tracks/14/imported = true -tracks/14/enabled = true -tracks/14/keys = PoolRealArray( 0, 1, 0, 0, 0, -2.23517e-08, 9.31322e-10, 4.19095e-09, 1, 1, 1, 1, 2.5, 1, 0, 0, 0, -2.23517e-08, 9.31322e-10, 4.19095e-09, 1, 1, 1, 1 ) -tracks/15/type = "transform" -tracks/15/path = NodePath("Armature_Left/Skeleton:pinky_distal") -tracks/15/interp = 1 -tracks/15/loop_wrap = true -tracks/15/imported = true -tracks/15/enabled = true -tracks/15/keys = PoolRealArray( 0, 1, 0, 0, 0, 0, 6.93889e-18, 9.31323e-10, 1, 1, 1, 1, 0.0666667, 1, 2.83122e-07, -3.8743e-07, 5.40167e-08, 5.07054e-05, -5.42718e-06, 8.46873e-05, 1, 1, 1, 1, 0.133333, 1, 5.96046e-08, -6.25849e-07, -3.72529e-09, 0.000415952, -4.45039e-05, 0.00069494, 1, 1, 1, 1, 0.2, 1, 4.47035e-07, -4.47035e-07, -1.00583e-07, 0.00119337, -0.000127693, 0.00199372, 0.999997, 1, 1, 1, 0.266667, 1, 3.42727e-07, -5.96046e-07, -9.49949e-08, 0.0023578, -0.00025229, 0.00393914, 0.999989, 1, 1, 1, 0.333333, 1, 4.91738e-07, -4.47035e-07, -2.98023e-08, 0.00385916, -0.000412934, 0.00644747, 0.999972, 1, 1, 1, 2.5, 1, 4.91738e-07, -4.47035e-07, -1.17347e-07, 0.0991653, -0.0106107, 0.165675, 0.981125, 1, 1, 1 ) -tracks/16/type = "transform" -tracks/16/path = NodePath("Armature_Left/Skeleton:pinky_middle") -tracks/16/interp = 1 -tracks/16/loop_wrap = true -tracks/16/imported = true -tracks/16/enabled = true -tracks/16/keys = PoolRealArray( 0, 1, 0, 0, 0, 3.72529e-09, 3.72529e-09, 9.31323e-09, 1, 1, 1, 1, 0.0666667, 1, -1.49012e-07, 4.47035e-07, 0, 2.9138e-05, 1.42593e-05, 8.87006e-05, 1, 1, 1, 1, 0.133333, 1, -2.98023e-08, 2.08616e-07, 1.39698e-09, 0.000239038, 0.000116951, 0.00072735, 1, 1, 1, 1, 0.2, 1, 1.78814e-07, 2.38419e-07, 1.39698e-09, 0.000685791, 0.000335475, 0.0020868, 0.999998, 1, 1, 1, 0.266667, 1, -1.49012e-07, 2.38419e-07, 5.02914e-08, 0.00135493, 0.000662805, 0.00412299, 0.99999, 1, 1, 1, 0.333333, 1, -2.98023e-08, 2.08616e-07, 7.45058e-09, 0.00221767, 0.00108484, 0.00674825, 0.999974, 1, 1, 1, 2.5, 1, -2.98023e-08, 1.49012e-07, 7.45058e-09, 0.0569887, 0.0278776, 0.173414, 0.982804, 1, 1, 1 ) -tracks/17/type = "transform" -tracks/17/path = NodePath("Armature_Left/Skeleton:pinky_proximal") -tracks/17/interp = 1 -tracks/17/loop_wrap = true -tracks/17/imported = true -tracks/17/enabled = true -tracks/17/keys = PoolRealArray( 0, 1, 0, 0, 0, -2.23517e-08, 1.39698e-09, 8.3819e-09, 1, 1, 1, 1, 0.0666667, 1, 0, 0, 0, 1.28356e-05, 7.08576e-05, 0.000235278, 1, 1, 1, 1, 0.133333, 1, 0, 0, 0, 0.000105443, 0.000581559, 0.00193108, 0.999998, 1, 1, 1, 0.2, 1, 0, 0, 0, 0.000302807, 0.00166979, 0.00554463, 0.999983, 1, 1, 1, 0.266667, 1, 0, 0, 0, 0.000599047, 0.00330311, 0.0109682, 0.999934, 1, 1, 1, 0.333333, 1, 0, 0, 0, 0.00098193, 0.00541409, 0.0179778, 0.999823, 1, 1, 1, 1.13333, 1, 0, 0, 0, 0.010796, 0.0595247, 0.197655, 0.978403, 1, 1, 1, 1.73333, 1, 0, 0, 0, 0.0197609, 0.108953, 0.361785, 0.925662, 1, 1, 1, 2.2, 1, 0, 0, 0, 0.0242175, 0.133525, 0.443376, 0.886004, 1, 1, 1, 2.26667, 1, 0, 0, 0, 0.0245683, 0.135459, 0.449799, 0.882456, 1, 1, 1, 2.33333, 1, 0, 0, 0, 0.0248424, 0.13697, 0.454818, 0.879638, 1, 1, 1, 2.4, 1, 0, 0, 0, 0.0250227, 0.137964, 0.458119, 0.877762, 1, 1, 1, 2.46667, 1, 0, 0, 0, 0.0251184, 0.138492, 0.459871, 0.87676, 1, 1, 1, 2.5, 1, 0, 0, 0, 0.0251334, 0.138575, 0.460146, 0.876602, 1, 1, 1 ) -tracks/18/type = "transform" -tracks/18/path = NodePath("Armature_Left/Skeleton:pinky_metacarpal") -tracks/18/interp = 1 -tracks/18/loop_wrap = true -tracks/18/imported = true -tracks/18/enabled = true -tracks/18/keys = PoolRealArray( 0, 1, 0, 0, 0, -2.98023e-08, -4.65661e-10, 4.65661e-10, 1, 1, 1, 1, 2.5, 1, 0, 0, 0, -2.98023e-08, -4.65661e-10, 4.65661e-10, 1, 1, 1, 1 ) -tracks/19/type = "transform" -tracks/19/path = NodePath("Armature_Left/Skeleton:root") -tracks/19/interp = 1 -tracks/19/loop_wrap = true -tracks/19/imported = true -tracks/19/enabled = true -tracks/19/keys = PoolRealArray( 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2.5, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 ) - -[sub_resource type="Animation" id=4] -resource_name = "IndexFinger" -length = 2.5 -tracks/0/type = "transform" -tracks/0/path = NodePath("Armature_Left/Skeleton:thumb_distal") -tracks/0/interp = 1 -tracks/0/loop_wrap = true -tracks/0/imported = true -tracks/0/enabled = true -tracks/0/keys = PoolRealArray( 0, 1, 0, 0, 0, -1.6263e-19, -9.31323e-10, -2.44472e-09, 1, 1, 1, 1, 2.5, 1, 0, 0, 0, -1.6263e-19, -9.31323e-10, -2.44472e-09, 1, 1, 1, 1 ) -tracks/1/type = "transform" -tracks/1/path = NodePath("Armature_Left/Skeleton:thumb_proximal") -tracks/1/interp = 1 -tracks/1/loop_wrap = true -tracks/1/imported = true -tracks/1/enabled = true -tracks/1/keys = PoolRealArray( 0, 1, 0, 0, 0, -1.49012e-08, 3.72529e-09, -7.45058e-09, 1, 1, 1, 1, 2.5, 1, 0, 0, 0, -1.49012e-08, 3.72529e-09, -7.45058e-09, 1, 1, 1, 1 ) -tracks/2/type = "transform" -tracks/2/path = NodePath("Armature_Left/Skeleton:thumb_metacarpal") -tracks/2/interp = 1 -tracks/2/loop_wrap = true -tracks/2/imported = true -tracks/2/enabled = true -tracks/2/keys = PoolRealArray( 0, 1, 0, 0, 0, 2.98023e-08, -1.49012e-08, 7.45058e-09, 1, 1, 1, 1, 2.5, 1, 0, 0, 0, 2.98023e-08, -1.49012e-08, 7.45058e-09, 1, 1, 1, 1 ) -tracks/3/type = "transform" -tracks/3/path = NodePath("Armature_Left/Skeleton:index_distal") -tracks/3/interp = 1 -tracks/3/loop_wrap = true -tracks/3/imported = true -tracks/3/enabled = true -tracks/3/keys = PoolRealArray( 0, 1, 0, 0, 0, 1.86265e-09, 1.86265e-09, 2.65427e-08, 1, 1, 1, 1, 0.0666667, 1, -2.98023e-07, -4.76837e-07, -1.41561e-07, 0.00108275, 0.0135773, 0.220491, 0.975294, 1, 1, 1, 0.133333, 1, 7.45058e-08, -7.15256e-07, -2.10479e-07, 0.00180848, 0.0226778, 0.36828, 0.929436, 1, 1, 1, 2.13333, 1, 2.68221e-07, -5.36442e-07, -1.41561e-07, 0.00226251, 0.0283712, 0.46074, 0.887079, 1, 1, 1, 2.33333, 1, -1.49012e-08, -5.36442e-07, -1.17347e-07, 0.002264, 0.0283899, 0.461043, 0.88692, 1, 1, 1, 2.5, 1, -2.98023e-08, -5.36442e-07, -2.36556e-07, 0.00226416, 0.0283918, 0.461075, 0.886904, 1, 1, 1 ) -tracks/4/type = "transform" -tracks/4/path = NodePath("Armature_Left/Skeleton:index_middle") -tracks/4/interp = 1 -tracks/4/loop_wrap = true -tracks/4/imported = true -tracks/4/enabled = true -tracks/4/keys = PoolRealArray( 0, 1, 0, 0, 0, -5.29091e-17, -1.86264e-09, 9.31323e-09, 1, 1, 1, 1, 0.0666667, 1, -1.49012e-07, -3.57628e-07, 0, 0.00274914, 0.00464837, 0.137001, 0.990556, 1, 1, 1, 0.133333, 1, 5.96046e-08, 1.78814e-07, 1.78814e-07, 0.00463382, 0.00783516, 0.230924, 0.972929, 1, 1, 1, 2.13333, 1, 2.08616e-07, -2.38419e-07, 1.78814e-07, 0.00581754, 0.00983664, 0.289913, 0.956985, 1, 1, 1, 2.5, 1, -2.98023e-08, 1.19209e-07, 2.98023e-08, 0.00582196, 0.00984408, 0.290132, 0.956918, 1, 1, 1 ) -tracks/5/type = "transform" -tracks/5/path = NodePath("Armature_Left/Skeleton:index_proximal") -tracks/5/interp = 1 -tracks/5/loop_wrap = true -tracks/5/imported = true -tracks/5/enabled = true -tracks/5/keys = PoolRealArray( 0, 1, 0, 0, 0, -3.25938e-18, 4.65661e-10, -2.31375e-09, 1, 1, 1, 1, 0.0666667, 1, 0, 0, 0, 0.00598072, -0.0269939, 0.0969091, 0.994909, 1, 1, 1, 0.133333, 1, 0, 0, 0, 0.0103883, -0.0468874, 0.168328, 0.984561, 1, 1, 1, 2.13333, 1, 0, 0, 0, 0.0172329, -0.0777801, 0.279234, 0.956913, 1, 1, 1, 2.26667, 1, 0, 0, 0, 0.0172514, -0.0778639, 0.279534, 0.956818, 1, 1, 1, 2.5, 1, 0, 0, 0, 0.017258, -0.0778936, 0.279641, 0.956784, 1, 1, 1 ) -tracks/6/type = "transform" -tracks/6/path = NodePath("Armature_Left/Skeleton:index_metacarpal") -tracks/6/interp = 1 -tracks/6/loop_wrap = true -tracks/6/imported = true -tracks/6/enabled = true -tracks/6/keys = PoolRealArray( 0, 1, 0, 0, 0, -1.49012e-08, -1.86265e-09, -2.77556e-17, 1, 1, 1, 1, 2.5, 1, 0, 0, 0, -1.49012e-08, -1.86265e-09, -2.77556e-17, 1, 1, 1, 1 ) -tracks/7/type = "transform" -tracks/7/path = NodePath("Armature_Left/Skeleton:middle_distal") -tracks/7/interp = 1 -tracks/7/loop_wrap = true -tracks/7/imported = true -tracks/7/enabled = true -tracks/7/keys = PoolRealArray( 0, 1, 2.68221e-07, 0, 0, 0.0520055, 0.0555409, 0.291533, 0.95353, 1, 1, 1, 2.5, 1, 2.68221e-07, 0, 0, 0.0520055, 0.0555409, 0.291533, 0.95353, 1, 1, 1 ) -tracks/8/type = "transform" -tracks/8/path = NodePath("Armature_Left/Skeleton:middle_middle") -tracks/8/interp = 1 -tracks/8/loop_wrap = true -tracks/8/imported = true -tracks/8/enabled = true -tracks/8/keys = PoolRealArray( 0, 1, -2.08616e-07, 3.57628e-07, -7.45058e-09, 0.0138373, 0.045445, 0.299089, 0.953042, 1, 1, 1, 2.5, 1, -2.08616e-07, 3.57628e-07, -7.45058e-09, 0.0138373, 0.045445, 0.299089, 0.953042, 1, 1, 1 ) -tracks/9/type = "transform" -tracks/9/path = NodePath("Armature_Left/Skeleton:middle_proximal") -tracks/9/interp = 1 -tracks/9/loop_wrap = true -tracks/9/imported = true -tracks/9/enabled = true -tracks/9/keys = PoolRealArray( 0, 1, 0, 0, 0, -0.000765604, 0.0177302, 0.361034, 0.932384, 1, 1, 1, 2.5, 1, 0, 0, 0, -0.000765604, 0.0177302, 0.361034, 0.932384, 1, 1, 1 ) -tracks/10/type = "transform" -tracks/10/path = NodePath("Armature_Left/Skeleton:middle_metacarpal") -tracks/10/interp = 1 -tracks/10/loop_wrap = true -tracks/10/imported = true -tracks/10/enabled = true -tracks/10/keys = PoolRealArray( 0, 1, 0, 0, 0, -1.49012e-08, -6.98492e-10, 0, 1, 1, 1, 1, 2.5, 1, 0, 0, 0, -1.49012e-08, -6.98492e-10, 0, 1, 1, 1, 1 ) -tracks/11/type = "transform" -tracks/11/path = NodePath("Armature_Left/Skeleton:ring_distal") -tracks/11/interp = 1 -tracks/11/loop_wrap = true -tracks/11/imported = true -tracks/11/enabled = true -tracks/11/keys = PoolRealArray( 0, 1, -2.38419e-07, 5.96046e-08, -7.45058e-09, 0.0927168, 0.0181779, 0.159721, 0.98263, 1, 1, 1, 2.5, 1, -2.38419e-07, 5.96046e-08, -7.45058e-09, 0.0927168, 0.0181779, 0.159721, 0.98263, 1, 1, 1 ) -tracks/12/type = "transform" -tracks/12/path = NodePath("Armature_Left/Skeleton:ring_middle") -tracks/12/interp = 1 -tracks/12/loop_wrap = true -tracks/12/imported = true -tracks/12/enabled = true -tracks/12/keys = PoolRealArray( 0, 1, 2.38419e-07, 2.38419e-07, -2.23517e-08, 0.0486582, 0.05795, 0.282988, 0.956134, 1, 1, 1, 2.5, 1, 2.38419e-07, 2.38419e-07, -2.23517e-08, 0.0486582, 0.05795, 0.282988, 0.956134, 1, 1, 1 ) -tracks/13/type = "transform" -tracks/13/path = NodePath("Armature_Left/Skeleton:ring_proximal") -tracks/13/interp = 1 -tracks/13/loop_wrap = true -tracks/13/imported = true -tracks/13/enabled = true -tracks/13/keys = PoolRealArray( 0, 1, 0, 0, 0, -0.00602299, 0.0803546, 0.504324, 0.859746, 1, 1, 1, 2.5, 1, 0, 0, 0, -0.00602299, 0.0803546, 0.504324, 0.859746, 1, 1, 1 ) -tracks/14/type = "transform" -tracks/14/path = NodePath("Armature_Left/Skeleton:ring_metacarpal") -tracks/14/interp = 1 -tracks/14/loop_wrap = true -tracks/14/imported = true -tracks/14/enabled = true -tracks/14/keys = PoolRealArray( 0, 1, 0, 0, 0, -2.23517e-08, 9.31322e-10, 4.19095e-09, 1, 1, 1, 1, 2.5, 1, 0, 0, 0, -2.23517e-08, 9.31322e-10, 4.19095e-09, 1, 1, 1, 1 ) -tracks/15/type = "transform" -tracks/15/path = NodePath("Armature_Left/Skeleton:pinky_distal") -tracks/15/interp = 1 -tracks/15/loop_wrap = true -tracks/15/imported = true -tracks/15/enabled = true -tracks/15/keys = PoolRealArray( 0, 1, 4.91738e-07, -4.47035e-07, -1.17347e-07, 0.0991653, -0.0106107, 0.165675, 0.981125, 1, 1, 1, 2.5, 1, 4.91738e-07, -4.47035e-07, -1.17347e-07, 0.0991653, -0.0106107, 0.165675, 0.981125, 1, 1, 1 ) -tracks/16/type = "transform" -tracks/16/path = NodePath("Armature_Left/Skeleton:pinky_middle") -tracks/16/interp = 1 -tracks/16/loop_wrap = true -tracks/16/imported = true -tracks/16/enabled = true -tracks/16/keys = PoolRealArray( 0, 1, -2.98023e-08, 1.49012e-07, 7.45058e-09, 0.0569887, 0.0278776, 0.173414, 0.982804, 1, 1, 1, 2.5, 1, -2.98023e-08, 1.49012e-07, 7.45058e-09, 0.0569887, 0.0278776, 0.173414, 0.982804, 1, 1, 1 ) -tracks/17/type = "transform" -tracks/17/path = NodePath("Armature_Left/Skeleton:pinky_proximal") -tracks/17/interp = 1 -tracks/17/loop_wrap = true -tracks/17/imported = true -tracks/17/enabled = true -tracks/17/keys = PoolRealArray( 0, 1, 0, 0, 0, 0.0251334, 0.138575, 0.460146, 0.876602, 1, 1, 1, 2.5, 1, 0, 0, 0, 0.0251334, 0.138575, 0.460146, 0.876602, 1, 1, 1 ) -tracks/18/type = "transform" -tracks/18/path = NodePath("Armature_Left/Skeleton:pinky_metacarpal") -tracks/18/interp = 1 -tracks/18/loop_wrap = true -tracks/18/imported = true -tracks/18/enabled = true -tracks/18/keys = PoolRealArray( 0, 1, 0, 0, 0, -2.98023e-08, -4.65661e-10, 4.65661e-10, 1, 1, 1, 1, 2.5, 1, 0, 0, 0, -2.98023e-08, -4.65661e-10, 4.65661e-10, 1, 1, 1, 1 ) -tracks/19/type = "transform" -tracks/19/path = NodePath("Armature_Left/Skeleton:root") -tracks/19/interp = 1 -tracks/19/loop_wrap = true -tracks/19/imported = true -tracks/19/enabled = true -tracks/19/keys = PoolRealArray( 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2.5, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 ) - -[node name="LeftHand" type="Node3D"] -script = ExtResource( 2 ) - -[node name="LeftHand" type="Node3D" parent="."] -transform = Transform3D( -0.5, 0, -1.62921e-07, 0, 0.5, 0, 1.62921e-07, 0, -0.5, 0, 0, 0 ) - -[node name="Armature_Left" type="Node3D" parent="LeftHand"] -transform = Transform3D( 0.0681773, 0, 0, 0, -0.00176613, -0.0681545, 0, 0.0681545, -0.00176613, 0, 0.00072155, -0.0470038 ) - -[node name="Skeleton" type="Skeleton" parent="LeftHand/Armature_Left"] -bones/0/name = "root" -bones/0/parent = -1 -bones/0/rest = Transform3D( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 ) -bones/0/enabled = true -bones/0/bound_children = [ ] -bones/1/name = "thumb_metacarpal" -bones/1/parent = 0 -bones/1/rest = Transform3D( 0.858407, -0.510964, 0.0453196, 0.318781, 0.600581, 0.733268, -0.401892, -0.614995, 0.678428, 0, 1, 0 ) -bones/1/enabled = true -bones/1/bound_children = [ ] -bones/2/name = "thumb_proximal" -bones/2/parent = 1 -bones/2/rest = Transform3D( 0.946015, -0.199331, 0.255584, 0.300026, 0.836893, -0.457815, -0.12264, 0.509782, 0.851517, 5.07419e-08, 1.76487, -7.32534e-08 ) -bones/2/enabled = true -bones/2/bound_children = [ ] -bones/3/name = "thumb_distal" -bones/3/parent = 2 -bones/3/rest = Transform3D( 0.999312, -0.0343631, -0.0139769, 0.0335509, 0.997939, -0.0546952, 0.0158275, 0.0541886, 0.998405, 2.44781e-07, 1.17322, 1.39676e-07 ) -bones/3/enabled = true -bones/3/bound_children = [ ] -bones/4/name = "index_metacarpal" -bones/4/parent = 0 -bones/4/rest = Transform3D( 0.999276, 0.0112952, -0.0363351, 0.0012414, 0.944738, 0.327824, 0.03803, -0.327632, 0.94404, 0, 1, 0 ) -bones/4/enabled = true -bones/4/bound_children = [ ] -bones/5/name = "index_proximal" -bones/5/parent = 4 -bones/5/rest = Transform3D( 0.995157, 0.0981415, 0.00548894, -0.0979177, 0.994679, -0.0320321, -0.00860341, 0.0313395, 0.999472, -4.94951e-08, 2.62031, -1.84466e-09 ) -bones/5/enabled = true -bones/5/bound_children = [ ] -bones/6/name = "index_middle" -bones/6/parent = 5 -bones/6/rest = Transform3D( 0.962074, -0.268316, 0.0491911, 0.270298, 0.913362, -0.304482, 0.0367681, 0.306231, 0.951247, 3.13889e-08, 0.996807, -6.54344e-08 ) -bones/6/enabled = true -bones/6/bound_children = [ ] -bones/7/name = "index_distal" -bones/7/parent = 6 -bones/7/rest = Transform3D( 0.978877, -0.202557, 0.0277553, 0.203301, 0.978736, -0.0272986, -0.0216356, 0.0323646, 0.999242, -1.74303e-07, 0.827153, 1.12636e-07 ) -bones/7/enabled = true -bones/7/bound_children = [ ] -bones/8/name = "middle_metacarpal" -bones/8/parent = 0 -bones/8/rest = Transform3D( 0.996581, 0.0825, 0.00438377, -0.0822931, 0.986594, 0.140923, 0.00730118, -0.140802, 0.990011, 0, 1, 0 ) -bones/8/enabled = true -bones/8/bound_children = [ ] -bones/9/name = "middle_proximal" -bones/9/parent = 8 -bones/9/rest = Transform3D( 0.999038, -0.0428412, 0.00939559, 0.0438017, 0.985547, -0.163644, -0.00224911, 0.163898, 0.986475, -1.23168e-08, 2.53499, 6.65335e-08 ) -bones/9/enabled = true -bones/9/bound_children = [ ] -bones/10/name = "middle_middle" -bones/10/parent = 9 -bones/10/rest = Transform3D( 0.883392, -0.467794, 0.0280643, 0.467987, 0.877439, -0.105308, 0.0246379, 0.106162, 0.994044, 1.34057e-07, 0.876447, -3.98485e-08 ) -bones/10/enabled = true -bones/10/bound_children = [ ] -bones/11/name = "middle_distal" -bones/11/parent = 10 -bones/11/rest = Transform3D( 0.948045, -0.311942, -0.0624665, 0.306764, 0.948391, -0.0803131, 0.0842957, 0.0569779, 0.99481, -2.72132e-07, 0.90955, -5.2694e-08 ) -bones/11/enabled = true -bones/11/bound_children = [ ] -bones/12/name = "ring_metacarpal" -bones/12/parent = 0 -bones/12/rest = Transform3D( 0.999009, 0.0444944, -0.000672039, -0.043985, 0.985058, -0.166509, -0.00674672, 0.166374, 0.98604, 0, 1, 0 ) -bones/12/enabled = true -bones/12/bound_children = [ ] -bones/13/name = "ring_proximal" -bones/13/parent = 12 -bones/13/rest = Transform3D( 0.997362, 0.0721903, -0.00757485, -0.0718879, 0.996813, 0.034587, 0.0100476, -0.0339512, 0.999373, 1.85094e-08, 2.31576, -1.40424e-08 ) -bones/13/enabled = true -bones/13/bound_children = [ ] -bones/14/name = "ring_middle" -bones/14/parent = 13 -bones/14/rest = Transform3D( 0.802843, -0.595518, -0.0283019, 0.590278, 0.800654, -0.10259, 0.083754, 0.0656573, 0.994321, -3.22005e-08, 0.8342, -1.08615e-07 ) -bones/14/enabled = true -bones/14/bound_children = [ ] -bones/15/name = "ring_distal" -bones/15/parent = 14 -bones/15/rest = Transform3D( 0.836391, -0.494616, -0.23623, 0.473322, 0.86907, -0.143819, 0.276436, 0.00847591, 0.960995, -3.94881e-07, 0.76803, 3.07336e-08 ) -bones/15/enabled = true -bones/15/bound_children = [ ] -bones/16/name = "pinky_metacarpal" -bones/16/parent = 0 -bones/16/rest = Transform3D( 0.999814, 0.0166299, 0.00978244, -0.0105719, 0.896336, -0.44325, -0.0161395, 0.443064, 0.896345, 0, 1, 0 ) -bones/16/enabled = true -bones/16/bound_children = [ ] -bones/17/name = "pinky_proximal" -bones/17/parent = 16 -bones/17/rest = Transform3D( 0.986501, -0.162243, -0.0221824, 0.163515, 0.96869, 0.186823, -0.00882288, -0.187928, 0.982143, -3.90124e-08, 2.27488, -3.6195e-08 ) -bones/17/enabled = true -bones/17/bound_children = [ ] -bones/18/name = "pinky_middle" -bones/18/parent = 17 -bones/18/rest = Transform3D( 0.830876, -0.540945, -0.130474, 0.5448, 0.838535, -0.0072035, 0.113304, -0.0650971, 0.991426, 1.33669e-07, 0.577131, 3.09511e-08 ) -bones/18/enabled = true -bones/18/bound_children = [ ] -bones/19/name = "pinky_distal" -bones/19/parent = 18 -bones/19/rest = Transform3D( 0.933037, -0.287244, -0.216642, 0.305305, 0.950702, 0.0543616, 0.190347, -0.116863, 0.974737, -7.07541e-07, 0.44158, -2.88803e-07 ) -bones/19/enabled = true -bones/19/bound_children = [ ] - -[node name="Hand_Left" type="MeshInstance3D" parent="LeftHand/Armature_Left/Skeleton"] -mesh = SubResource( 1 ) -skin = SubResource( 2 ) -material/0 = null - -[node name="AnimationPlayer" type="AnimationPlayer" parent="LeftHand"] -anims/Grip = SubResource( 3 ) -anims/IndexFinger = SubResource( 4 ) - -[node name="AnimationTree" type="AnimationTree" parent="."] -tree_root = ExtResource( 3 ) -anim_player = NodePath("../LeftHand/AnimationPlayer") -active = true -parameters/Blend2/blend_amount = 1.0 -parameters/GripTimeScale/scale = 0.0 -parameters/IndexTimeScale/scale = 0.0 -parameters/SetGrip/seek_position = -1.0 -parameters/SetIndex/seek_position = -1.0 diff --git a/demo/addons/godot-xr-tools/assets/LeftHandBlendTree.tres b/demo/addons/godot-xr-tools/assets/LeftHandBlendTree.tres deleted file mode 100644 index 6a62954..0000000 --- a/demo/addons/godot-xr-tools/assets/LeftHandBlendTree.tres +++ /dev/null @@ -1,38 +0,0 @@ -[gd_resource type="AnimationNodeBlendTree" load_steps=8 format=2] - -[sub_resource type="AnimationNodeAnimation" id=1] -animation = "IndexFinger" - -[sub_resource type="AnimationNodeBlend2" id=2] -filter_enabled = true -filters = [ "Armature_Left/Skeleton:index._distal", "Armature_Left/Skeleton:index._middle", "Armature_Left/Skeleton:index._proximal" ] - -[sub_resource type="AnimationNodeAnimation" id=3] -animation = "Grip" - -[sub_resource type="AnimationNodeTimeScale" id=4] - -[sub_resource type="AnimationNodeTimeScale" id=5] - -[sub_resource type="AnimationNodeTimeSeek" id=6] - -[sub_resource type="AnimationNodeTimeSeek" id=7] - -[resource] -graph_offset = Vector2( -144.181, 1.39384 ) -"nodes/Animation 2/node" = SubResource( 1 ) -"nodes/Animation 2/position" = Vector2( 140, 240 ) -nodes/Blend2/node = SubResource( 2 ) -nodes/Blend2/position = Vector2( 800, 80 ) -nodes/GripAnimation/node = SubResource( 3 ) -nodes/GripAnimation/position = Vector2( 140, 40 ) -nodes/GripTimeScale/node = SubResource( 4 ) -nodes/GripTimeScale/position = Vector2( 540, 40 ) -nodes/IndexTimeScale/node = SubResource( 5 ) -nodes/IndexTimeScale/position = Vector2( 540, 240 ) -nodes/SetGrip/node = SubResource( 6 ) -nodes/SetGrip/position = Vector2( 360, 40 ) -nodes/SetIndex/node = SubResource( 7 ) -nodes/SetIndex/position = Vector2( 360, 240 ) -nodes/output/position = Vector2( 1020, 80 ) -node_connections = [ "Blend2", 0, "GripTimeScale", "Blend2", 1, "IndexTimeScale", "GripTimeScale", 0, "SetGrip", "output", 0, "Blend2", "IndexTimeScale", 0, "SetIndex", "SetGrip", 0, "GripAnimation", "SetIndex", 0, "Animation 2" ] diff --git a/demo/addons/godot-xr-tools/assets/RightHand.gd b/demo/addons/godot-xr-tools/assets/RightHand.gd deleted file mode 100644 index da6c232..0000000 --- a/demo/addons/godot-xr-tools/assets/RightHand.gd +++ /dev/null @@ -1,17 +0,0 @@ -extends Node3D - -# Called every frame. 'delta' is the elapsed time since the previous frame. -func _process(delta): - var controller : XRController3D = get_parent() - if controller: - var grip = controller.get_joystick_axis(4) * 2.5 - var trigger = controller.get_joystick_axis(2) * 2.5 - - # print("Grip: " + str(grip) + " Trigger: " + str(trigger)) - - $AnimationTree.set("parameters/SetGrip/seek_position", grip) - $AnimationTree.set("parameters/SetIndex/seek_position", trigger) - - # var grip_state = controller.is_button_pressed(JOY_VR_GRIP) - # print("Pressed: " + str(grip_state)) - diff --git a/demo/addons/godot-xr-tools/assets/RightHand.glb b/demo/addons/godot-xr-tools/assets/RightHand.glb deleted file mode 100644 index 7204086070b6ce62f89b3435444bfe9729569da7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 152704 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 z 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 0.1): # move_type == MOVEMENT_TYPE.MOVE_AND_ROTATE && - if smooth_rotation: - # we rotate around our Camera, but we adjust our origin, so we need a little bit of trickery - var t1 : Transform3D = Transform3D() - var t2 : Transform3D = Transform3D() - var rot : Transform3D = Transform3D() - - t1.origin = -camera_node.transform.origin - t2.origin = camera_node.transform.origin - rot = rot.rotated(Vector3(0.0, -1.0, 0.0), smooth_turn_speed * delta * left_right) - origin_node.transform = (origin_node.transform * t2 * rot * t1).orthonormalized() - - # reset turn step, doesn't apply - turn_step = 0.0 - else: - if left_right > 0.0: - if turn_step < 0.0: - # reset step - turn_step = 0 - - turn_step += left_right * delta - else: - if turn_step > 0.0: - # reset step - turn_step = 0 - - turn_step += left_right * delta - - if abs(turn_step) > step_turn_delay: - # we rotate around our Camera, but we adjust our origin, so we need a little bit of trickery - var t1 = Transform3D() - var t2 = Transform3D() - var rot = Transform3D() - - t1.origin = -camera_node.transform.origin - t2.origin = camera_node.transform.origin - - # Rotating - while abs(turn_step) > step_turn_delay: - if (turn_step > 0.0): - rot = rot.rotated(Vector3(0.0, -1.0, 0.0), step_turn_angle * PI / 180.0) - turn_step -= step_turn_delay - else: - rot = rot.rotated(Vector3(0.0, 1.0, 0.0), step_turn_angle * PI / 180.0) - turn_step += step_turn_delay - - origin_node.transform *= t2 * rot * t1 - else: - # reset turn step, no longer turning - turn_step = 0.0 - - ################################################################ - # now we do our movement - # We start with placing our CharacterBody3D in the right place - # by centering it on the camera but placing it on the ground - var curr_transform = $CharacterBody3D.global_transform - var camera_transform = camera_node.global_transform - curr_transform.origin = camera_transform.origin - curr_transform.origin.y = origin_node.global_transform.origin.y - - # now we move it slightly back - var forward_dir = -camera_transform.basis.z - forward_dir.y = 0.0 - if forward_dir.length() > 0.01: - curr_transform.origin += forward_dir.normalized() * -0.75 * player_radius - - $CharacterBody3D.global_transform = curr_transform - - # we'll handle gravity separately - var gravity_velocity = Vector3(0.0, velocity.y, 0.0) - velocity.y = 0.0 - - # Apply our drag - velocity *= (1.0 - drag_factor) - - if move_type == 0: ## 0 = MOVEMENT_TYPE.MOVE_AND_ROTATE - if (abs(forwards_backwards) > 0.1 and tail.is_colliding()): - var dir = camera_transform.basis.z - dir.y = 0.0 - velocity = dir.normalized() * -forwards_backwards * max_speed * XRServer.world_scale - #velocity = velocity.linear_interpolate(dir, delta * 100.0) - elif move_type == 1: ## 1 = MOVEMENT_TYPE.MOVE_AND_STRAFE - if ((abs(forwards_backwards) > 0.1 || abs(left_right) > 0.1) and tail.is_colliding()): - var dir_forward = camera_transform.basis.z - dir_forward.y = 0.0 - # VR Capsule will strafe left and right - var dir_right = camera_transform.basis.x; - dir_right.y = 0.0 - velocity = (dir_forward * -forwards_backwards + dir_right * left_right).normalized() * max_speed * XRServer.world_scale - - # apply move and slide to our kinematic body - $CharacterBody3D.motion_velocity = velocity - $CharacterBody3D.move_and_slide() - velocity = $CharacterBody3D.motion_velocity - - # apply our gravity - gravity_velocity.y += 0.5 * gravity * delta - $CharacterBody3D.motion_velocity = gravity_velocity - $CharacterBody3D.move_and_slide() - gravity_velocity = $CharacterBody3D.motion_velocity - velocity.y = gravity_velocity.y - - # now use our new position to move our origin point - var movement = ($CharacterBody3D.global_transform.origin - curr_transform.origin) - origin_node.global_transform.origin += movement - - # Return this back to where it was so we can use its collision shape for other things too - # $CharacterBody3D.global_transform.origin = curr_transform.origin diff --git a/demo/addons/godot-xr-tools/functions/Function_Direct_movement.tscn b/demo/addons/godot-xr-tools/functions/Function_Direct_movement.tscn deleted file mode 100644 index a8cf85d..0000000 --- a/demo/addons/godot-xr-tools/functions/Function_Direct_movement.tscn +++ /dev/null @@ -1,24 +0,0 @@ -[gd_scene load_steps=3 format=3 uid="uid://hkoqglc13fsw"] - -[ext_resource type="Script" path="res://addons/godot-xr-tools/functions/Function_Direct_movement.gd" id="1"] - -[sub_resource type="CapsuleShape3D" id="1"] -radius = 0.3 -height = 1.2 - -[node name="Function_Direct_movement" type="Node"] -script = ExtResource( "1" ) - -[node name="CharacterBody3D" type="CharacterBody3D" parent="."] -collision_mask = 1048574 -script = null - -[node name="CollisionShape3D" type="CollisionShape3D" parent="CharacterBody3D"] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.9, 0) -shape = SubResource( "1" ) -script = null - -[node name="Tail" type="RayCast3D" parent="CharacterBody3D"] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0) -collision_mask = 1048574 -script = null diff --git a/demo/addons/godot-xr-tools/functions/Function_Pickup.gd b/demo/addons/godot-xr-tools/functions/Function_Pickup.gd deleted file mode 100644 index 1447c7c..0000000 --- a/demo/addons/godot-xr-tools/functions/Function_Pickup.gd +++ /dev/null @@ -1,150 +0,0 @@ -extends Area3D - -signal has_picked_up(what) -signal has_dropped - -@export var pickup_range = 0.5: - set(new_value): - pickup_range = new_value - _update_pickup_range() - -@export var impulse_factor = 1.0 -@export var pickup_button: String = "grip_click" -@export var action_button: String = "trigger_click" -@export var max_samples = 5 - -var objects_in_area: Array -var closest_object: Variant = null -var picked_up_object: Variant = null - -var last_transform: Transform3D -var linear_velocities: Array -var angular_velocities: Array - -func _update_pickup_range(): - if $CollisionShape3D: - $CollisionShape3D.shape.radius = pickup_range - -func _get_linear_velocity(): - var velocity = Vector3(0.0, 0.0, 0.0) - var count = linear_velocities.size() - - if count > 0: - for v in linear_velocities: - velocity = velocity + v - - velocity = velocity / count - - return velocity - -func _get_angular_velocity(): - var velocity = Vector3(0.0, 0.0, 0.0) - var count = angular_velocities.size() - - if count > 0: - for v in angular_velocities: - velocity = velocity + v - - velocity = velocity / count - - return velocity - -func _on_Function_Pickup_entered(object): - # add our object to our array if required - if object.has_method('pick_up') and objects_in_area.find(object) == -1: - objects_in_area.push_back(object) - _update_closest_object() - -func _on_Function_Pickup_exited(object): - # remove our object from our array - if objects_in_area.find(object) != -1: - objects_in_area.erase(object) - _update_closest_object() - -func _update_closest_object(): - var new_closest_obj: Variant = null - if !picked_up_object and !objects_in_area.is_empty(): - var new_closest_distance: float = 1000.0 - for object in objects_in_area: - # only check objects that aren't already picked up - if object.is_picked_up() == false: - var delta_pos = object.global_transform.origin - global_transform.origin - var distance = delta_pos.length() - if distance < new_closest_distance: - new_closest_obj = object - new_closest_distance = distance - - if closest_object != new_closest_obj: - # remove highlight on old object - if closest_object: - closest_object.decrease_is_closest() - - # add highlight to new object - closest_object = new_closest_obj - if closest_object: - closest_object.increase_is_closest() - -func drop_object(): - if picked_up_object: - # let go of this object - picked_up_object.let_go(_get_linear_velocity() * impulse_factor, _get_angular_velocity()) - picked_up_object = null - emit_signal("has_dropped") - -func _pick_up_object(p_object): - # already holding this object, nothing to do - if picked_up_object == p_object: - return - - # holding something else? drop it - if picked_up_object: - drop_object() - - # and pick up our new object - if p_object: - picked_up_object = p_object - picked_up_object.pick_up(self, get_parent()) - emit_signal("has_picked_up", picked_up_object) - -func _on_button_pressed(p_button): - if p_button == pickup_button: - if picked_up_object and !picked_up_object.press_to_hold: - drop_object() - elif closest_object: - _pick_up_object(closest_object) - elif p_button == action_button: - if picked_up_object and picked_up_object.has_method("action"): - picked_up_object.action() - -func _on_button_released(p_button): - if p_button == pickup_button: - if picked_up_object and picked_up_object.press_to_hold: - drop_object() - -func _ready(): - get_parent().connect("button_pressed", _on_button_pressed) - get_parent().connect("button_released", _on_button_released) - last_transform = global_transform - - # update now that our collision shape has been constructed - _update_pickup_range() - -func _process(delta): - # TODO REWRITE THIS, we now get this info from the XRPose - - # Calculate our linear velocity - var linear_velocity = (global_transform.origin - last_transform.origin) / delta - linear_velocities.push_back(linear_velocity) - if linear_velocities.size() > max_samples: - linear_velocities.pop_front() - - # Calculate our angular velocity - var delta_basis = global_transform.basis * last_transform.basis.inverse() - var angular_velocity = delta_basis.get_euler() / delta - angular_velocities.push_back(angular_velocity) - if angular_velocities.size() > max_samples: - angular_velocities.pop_front() - - last_transform = global_transform - _update_closest_object() - diff --git a/demo/addons/godot-xr-tools/functions/Function_Pickup.tscn b/demo/addons/godot-xr-tools/functions/Function_Pickup.tscn deleted file mode 100644 index dfa7f0c..0000000 --- a/demo/addons/godot-xr-tools/functions/Function_Pickup.tscn +++ /dev/null @@ -1,19 +0,0 @@ -[gd_scene load_steps=3 format=2] - -[ext_resource path="res://addons/godot-xr-tools/functions/Function_Pickup.gd" type="Script" id=1] - -[sub_resource type="SphereShape3D" id=1] -radius = 0.5 - -[node name="Function_Pickup" type="Area3D"] -collision_mask = 4 -script = ExtResource( 1 ) - -[node name="CollisionShape3D" type="CollisionShape3D" parent="."] -shape = SubResource( 1 ) -script = null - -[connection signal="area_entered" from="." to="." method="_on_Function_Pickup_entered"] -[connection signal="area_exited" from="." to="." method="_on_Function_Pickup_exited"] -[connection signal="body_entered" from="." to="." method="_on_Function_Pickup_entered"] -[connection signal="body_exited" from="." to="." method="_on_Function_Pickup_exited"] diff --git a/demo/addons/godot-xr-tools/functions/Function_Teleport.gd b/demo/addons/godot-xr-tools/functions/Function_Teleport.gd deleted file mode 100644 index ea0e728..0000000 --- a/demo/addons/godot-xr-tools/functions/Function_Teleport.gd +++ /dev/null @@ -1,311 +0,0 @@ -@tool -extends CharacterBody3D - -# Add this scene as a sub scene of your XRController3D node to implement a teleport function on that controller. - -# Is this active? -@export var enabled = true: - set(new_value): - enabled = new_value - if enabled: - # make sure our physics process is on - set_physics_process(true) - else: - # we turn this off in physics process just in case we want to do some cleanup - pass - -@export var teleport_button: String = "trigger_click" -@export var can_teleport_color: Color = Color(0.0, 1.0, 0.0, 1.0) -@export var cant_teleport_color: Color = Color(1.0, 0.0, 0.0, 1.0) -@export var no_collision_color: Color = Color(45.0 / 255.0, 80.0 / 255.0, 220.0 / 255.0, 1.0) - -@export var player_height: float = 1.8: - set(new_value): - player_height = new_value - _update_player_height() - -@export var player_radius: float = 0.4: - set(new_value): - player_radius = new_value - _update_player_radius() - -@export var strength: float = 5.0 -@export var max_slope: float = 20.0 - -# once this is no longer a kinematic body, we'll need this.. -# @export_flags_3d_physics var collision_mask = 1 - -# We don't know the name of the camera node... -@export var camera: NodePath = NodePath() - -@onready var ws: float = XRServer.world_scale -var origin_node: XROrigin3D = null -var camera_node: XRCamera3D = null -var is_on_floor = true -var is_teleporting = false -var can_teleport = true -var teleport_rotation = 0.0; -var floor_normal = Vector3(0.0, 1.0, 0.0) -var last_target_transform: Transform3D = Transform3D() -var collision_shape: Shape3D = null -var step_size = 0.5 - -# By default we show a capsule to indicate where the player lands. -# Turn on editable children, -# hide the capsule, -# and add your own player character as child. -@onready var capsule: MeshInstance3D = get_node("Target/Player_figure/Capsule") - -func _update_player_height(): - if collision_shape: - collision_shape.height = player_height # - (2.0 * player_radius) - - if capsule: - capsule.mesh.height = player_height - capsule.position = Vector3(0.0, player_height/2.0, 0.0) - -func _update_player_radius(): - if collision_shape: - # collision_shape.height = player_height # - (2.0 * player_radius) - collision_shape.radius = player_radius - - if capsule: - # capsule.mesh.height = player_height - capsule.mesh.radius = player_radius - -func _get_configuration_warning(): - if camera == NodePath(): - return "You need to assign a camera" - - return "" - -func _ready(): - if !Engine.is_editor_hint(): - # We should be a child of an XRController3D and it should be a child or our XROrigin3D - origin_node = get_node("../..") - - # It's inactive when we start - $Teleport.visible = false - $Target.visible = false - - # Scale to our world scale - $Teleport.mesh.size = Vector2(0.05 * ws, 1.0) - $Target.mesh.size = Vector2(ws, ws) - $Target/Player_figure.scale = Vector3(ws, ws, ws) - - if camera: - camera_node = get_node(camera) - else: - # see if we can find our default - camera_node = origin_node.get_node('XRCamera') - - # get our capsule shape - collision_shape = $CollisionShape3D.shape - $CollisionShape3D.shape = null - - # now remove our collision shape, we are not using our kinematic body - remove_child($CollisionShape3D) - else: - # don't run the physics process in the editor - set_physics_process(false) - - # call set player to ensure our collision shape is sized - _update_player_height() - _update_player_radius() - -func _physics_process(delta): - if !Engine.is_editor_hint(): - # We should be the child or the controller on which the teleport is implemented - var controller = get_parent() - - if !origin_node: - return - - if !camera_node: - return - - # if we're not enabled no point in doing mode - if !enabled: - # reset these - is_teleporting = false; - $Teleport.visible = false - $Target.visible = false - - # and stop this from running until we enable again - set_physics_process(false) - return - - # check if our world scale has changed.. - var new_ws = XRServer.world_scale - if ws != new_ws: - ws = new_ws - $Teleport.mesh.size = Vector2(0.05 * ws, 1.0) - $Target.mesh.size = Vector2(ws, ws) - $Target/Player_figure.scale = Vector3(ws, ws, ws) - - if controller and controller.get_is_active() and controller.is_button_pressed(teleport_button): - if !is_teleporting: - is_teleporting = true - $Teleport.visible = true - $Target.visible = true - teleport_rotation = 0.0 - - # get our physics engine state - var space = PhysicsServer3D.body_get_space(self.get_rid()) - var state = PhysicsServer3D.space_get_direct_state(space) - var query = PhysicsShapeQueryParameters3D.new() - - # init stuff about our query that doesn't change - query.collision_mask = collision_mask - query.margin = get_safe_margin() - query.shape_rid = collision_shape.get_rid() - - # make a transform for offseting our shape - var shape_transform = Transform3D(Basis(), Vector3(0.0, player_height / 2.0, 0.0)) - - # update location - var teleport_global_transform = $Teleport.global_transform - var target_global_origin = teleport_global_transform.origin - var down = Vector3(0.0, -1.0 / ws, 0.0) - - ############################################################ - # New teleport logic - # We're going to use test move in steps to find out where we hit something... - # This can be optimised loads by determining the lenght based on the angle between sections extending the length when we're in a flat part of the arch - # Where we do get a collission we may want to fine tune the collision - var cast_length = 0.0 - var fine_tune = 1.0 - var hit_something = false - var max_slope_cos = cos(deg2rad(max_slope)) - for i in range(1,26): - var new_cast_length = cast_length + (step_size / fine_tune) - var global_target = Vector3(0.0, 0.0, -new_cast_length) - - # our quadratic values - var t = global_target.z / strength - var t2 = t * t - - # target to world space - global_target = teleport_global_transform * global_target - - # adjust for gravity - global_target += down * t2 - - # test our new location for collisions - query.transform = Transform3D(Basis(), global_target) * shape_transform - var cast_result = state.collide_shape(query, 10) - if cast_result.is_empty(): - # we didn't collide with anything so check our next section... - cast_length = new_cast_length - target_global_origin = global_target - elif (fine_tune <= 16.0): - # try again with a small step size - fine_tune *= 2.0 - else: - # if we don't collide make sure we keep using our current origin point - var collided_at = target_global_origin - - # check for collision - if global_target.y > target_global_origin.y: - # if we're moving up, we hit the ceiling of something, we don't really care what - is_on_floor = false - else: - # now we cast a ray downwards to see if we're on a surface - var start_pos = target_global_origin + (Vector3.UP * 0.5 * player_height) - var end_pos = target_global_origin - (Vector3.UP * 1.1 * player_height) - - var params : PhysicsRayQueryParameters3D - params.from = start_pos - params.to = end_pos - params.collision_mask = collision_mask - var intersects = state.intersect_ray(params) - if intersects.is_empty(): - is_on_floor = false - else: - # did we collide with a floor or a wall? - floor_normal = intersects["normal"] - var dot = floor_normal.dot(Vector3.UP) - - if dot > max_slope_cos: - is_on_floor = true - else: - is_on_floor = false - - # Update our collision point if it's moved enough, this solves a little bit of jittering - var diff = collided_at - intersects["position"] - - if diff.length() > 0.1: - collided_at = intersects["position"] - - # we are colliding, find our if we're colliding on a wall or floor, one we can do, the other nope... - cast_length += (collided_at - target_global_origin).length() - target_global_origin = collided_at - hit_something = true - break - - # and just update our shader - var teleport_material = $Teleport.get_surface_override_material(0) - var target_material = $Target.get_surface_override_material(0) - teleport_material.set_shader_param("scale_t", 1.0 / strength) - teleport_material.set_shader_param("ws", ws) - teleport_material.set_shader_param("length", cast_length) - if hit_something: - var color = can_teleport_color - var normal = Vector3.UP - if is_on_floor: - # if we're on the floor we'll reorientate our target to match. - normal = floor_normal - can_teleport = true - else: - can_teleport = false - color = cant_teleport_color - - # check our axis to see if we need to rotate - teleport_rotation += (delta * controller.get_axis("primary").x * -4.0) - - # update target and colour - var target_basis = Basis() - target_basis.z = Vector3(teleport_global_transform.basis.z.x, 0.0, teleport_global_transform.basis.z.z).normalized() - target_basis.y = normal - target_basis.x = target_basis.y.cross(target_basis.z) - target_basis.z = target_basis.x.cross(target_basis.y) - - target_basis = target_basis.rotated(normal, teleport_rotation) - last_target_transform.basis = target_basis - last_target_transform.origin = target_global_origin + Vector3(0.0, 0.001, 0.0) - $Target.global_transform = last_target_transform - - teleport_material.set_shader_param("mix_color", color) - target_material.albedo_color = color - $Target.visible = can_teleport - else: - can_teleport = false - $Target.visible = false - teleport_material.set_shader_param("mix_color", no_collision_color) - elif is_teleporting: - if can_teleport: - - # make our target horizontal again - var new_transform = last_target_transform - new_transform.basis.y = Vector3(0.0, 1.0, 0.0) - new_transform.basis.x = new_transform.basis.y.cross(new_transform.basis.z).normalized() - new_transform.basis.z = new_transform.basis.x.cross(new_transform.basis.y).normalized() - - # find out our user's feet's transformation - var cam_transform = camera_node.transform - var user_feet_transform = Transform3D() - user_feet_transform.origin = cam_transform.origin - user_feet_transform.origin.y = 0 # the feet are on the ground, but have the same X,Z as the camera - - # ensure this transform is upright - user_feet_transform.basis.y = Vector3(0.0, 1.0, 0.0) - user_feet_transform.basis.x = user_feet_transform.basis.y.cross(cam_transform.basis.z).normalized() - user_feet_transform.basis.z = user_feet_transform.basis.x.cross(user_feet_transform.basis.y).normalized() - - # now move the origin such that the new global user_feet_transform would be == new_transform - origin_node.global_transform = new_transform * user_feet_transform.inverse() - - # and disable - is_teleporting = false; - $Teleport.visible = false - $Target.visible = false diff --git a/demo/addons/godot-xr-tools/functions/Function_Teleport.tscn b/demo/addons/godot-xr-tools/functions/Function_Teleport.tscn deleted file mode 100644 index 52d2d5c..0000000 --- a/demo/addons/godot-xr-tools/functions/Function_Teleport.tscn +++ /dev/null @@ -1,49 +0,0 @@ -[gd_scene load_steps=9 format=2] - -[ext_resource path="res://addons/godot-xr-tools/functions/Function_Teleport.gd" type="Script" id=1] -[ext_resource path="res://addons/godot-xr-tools/materials/target.tres" type="Material" id=2] -[ext_resource path="res://addons/godot-xr-tools/materials/capule.tres" type="Material" id=3] -[ext_resource path="res://addons/godot-xr-tools/materials/teleport.tres" type="Material" id=4] - -[sub_resource type="PlaneMesh" id=1] -size = Vector2(0.05, 1) -subdivide_depth = 40 - -[sub_resource type="PlaneMesh" id=2] -size = Vector2(1, 1) - -[sub_resource type="CapsuleMesh" id=3] -radius = 0.4 - -[sub_resource type="CapsuleShape3D" id=4] -radius = 0.1 -height = 0.1 - -[node name="Function_Teleport" type="CharacterBody3D"] -script = ExtResource( 1 ) -no_collision_color = Color(0.176471, 0.313726, 0.862745, 1) - -[node name="Teleport" type="MeshInstance3D" parent="."] -mesh = SubResource( 1 ) -surface_material_override/0 = ExtResource( 4 ) -script = null - -[node name="Target" type="MeshInstance3D" parent="."] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1, -4.92359) -mesh = SubResource( 2 ) -surface_material_override/0 = ExtResource( 2 ) -script = null - -[node name="Player_figure" type="Position3D" parent="Target"] -script = null - -[node name="Capsule" type="MeshInstance3D" parent="Target/Player_figure"] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.9, 0) -visible = false -mesh = SubResource( 3 ) -surface_material_override/0 = ExtResource( 3 ) -script = null - -[node name="CollisionShape3D" type="CollisionShape3D" parent="."] -shape = SubResource( 4 ) -script = null diff --git a/demo/addons/godot-xr-tools/functions/Function_pointer.gd b/demo/addons/godot-xr-tools/functions/Function_pointer.gd deleted file mode 100644 index 2de61fe..0000000 --- a/demo/addons/godot-xr-tools/functions/Function_pointer.gd +++ /dev/null @@ -1,195 +0,0 @@ -extends Node3D - -signal pointer_pressed(on, at) -signal pointer_released(on, at) -signal pointer_moved(on, from, to) - -signal pointer_entered(body) -signal pointer_exited(body) - -@export var enabled = true: - set(new_value): - enabled = new_value - _update_enabled() -@export var show_laser = true: - set(new_value): - show_laser = new_value - _update_show_laser() -@export var show_target = false -@export var ducktyped_body = true -@export var active_button: String = "trigger_click" -@export var action = "" -@export var y_offset = -0.05: - set(new_value): - y_offset = new_value - _update_y_offset() -@export var distance = 10: - set(new_value): - distance = new_value - _update_distance() -@export_flags_3d_physics var collision_mask = 15: - set(new_value): - collision_mask = new_value - _update_collision_mask() -@export var collide_with_bodies = true: - set(new_value): - collide_with_bodies = new_value - _update_collide_with_bodies() -@export var collide_with_areas = false: - set(new_value): - collide_with_areas = new_value - _update_collide_with_areas() - -var target: Variant = null -var last_target: Variant = null -var last_collided_at = Vector3(0, 0, 0) - -var ws = 1.0 - -func _update_enabled(): - # this gets called before our scene is ready, we'll call this again in _ready to enable this - if is_inside_tree(): - $Laser.visible = enabled and show_laser - $RayCast.enabled = enabled - -func _update_show_laser(): - if is_inside_tree(): - $Laser.visible = enabled and show_laser - -func _update_y_offset(): - if is_inside_tree(): - $Laser.position.y = y_offset * ws - $RayCast.position.y = y_offset * ws - -func _update_collision_mask(): - if is_inside_tree(): - $RayCast.collision_mask = collision_mask - -func _update_distance(): - if is_inside_tree(): - $Laser.mesh.size.z = distance - $Laser.position.z = distance * -0.5 - $RayCast.target_position.z = -distance - -func _update_collide_with_bodies(): - if is_inside_tree(): - $RayCast.collide_with_bodies = collide_with_bodies - -func _update_collide_with_areas(): - if is_inside_tree(): - $RayCast.collide_with_areas = collide_with_areas - -func _button_pressed(): - if $RayCast.is_colliding(): - target = $RayCast.get_collider() - last_collided_at = $RayCast.get_collision_point() - - emit_signal("pointer_pressed", target, last_collided_at) - - if ducktyped_body and target.has_method("pointer_pressed"): - target.pointer_pressed(last_collided_at) - -func _button_released(): - if target: - emit_signal("pointer_released", target, last_collided_at) - - if ducktyped_body and target.has_method("pointer_released"): - target.pointer_released(last_collided_at) - - # unset target - target = null - last_collided_at = Vector3(0, 0, 0) - -func _on_button_pressed(p_button): - if p_button == active_button and enabled: - _button_pressed() - -func _on_button_release(p_button): - if p_button == active_button and target: - _button_released() - -func _ready(): - ws = XRServer.world_scale - - if active_button != "trigger_action": - # Get button press feedback from our parent (should be an XRController3D) - get_parent().connect("button_pressed", _on_button_pressed) - get_parent().connect("button_released", _on_button_release) - - # init our state - _update_y_offset() - _update_distance() - _update_collision_mask() - _update_show_laser() - _update_collide_with_bodies() - _update_collide_with_areas() - _update_enabled() - -func _process(delta): - if !is_inside_tree(): - return - - # TODO REIMPLEMENT - #if active_button == "trigger_action" and action != "": - # if Input.is_action_just_pressed(action): - # _button_pressed() - # elif !Input.is_action_pressed(action) and target: - # _button_released() - - var new_ws = XRServer.world_scale - if (ws != new_ws): - ws = new_ws - _update_y_offset() - - if enabled and $RayCast.is_colliding(): - var new_at = $RayCast.get_collision_point() - - if is_instance_valid(target): - # if target is set our mouse must be down, we keep "focus" on our target - if new_at != last_collided_at: - emit_signal("pointer_moved", target, last_collided_at, new_at) - - if ducktyped_body and target.has_method("pointer_moved"): - target.pointer_moved(last_collided_at, new_at) - else: - var new_target = $RayCast.get_collider() - - # are we pointing to a new target? - if new_target != last_target: - # exit the old - if is_instance_valid(last_target): - emit_signal("pointer_exited", last_target) - - if ducktyped_body and last_target.has_method("pointer_exited"): - last_target.pointer_exited() - - # enter the new - if is_instance_valid(new_target): - emit_signal("pointer_entered", new_target) - - if ducktyped_body and new_target.has_method("pointer_entered"): - new_target.pointer_entered() - - last_target = new_target - - if new_at != last_collided_at: - emit_signal("pointer_moved", new_target, last_collided_at, new_at) - - if ducktyped_body and new_target.has_method("pointer_moved"): - new_target.pointer_moved(last_collided_at, new_at) - - if last_target and show_target: - $Target.global_transform.origin = last_collided_at - $Target.visible = true - - # remember our new position - last_collided_at = new_at - else: - if is_instance_valid(last_target): - emit_signal("pointer_exited", last_target) - - if ducktyped_body and last_target.has_method("pointer_exited"): - last_target.pointer_exited() - - last_target = null - $Target.visible = false diff --git a/demo/addons/godot-xr-tools/functions/Function_pointer.tscn b/demo/addons/godot-xr-tools/functions/Function_pointer.tscn deleted file mode 100644 index f7f244b..0000000 --- a/demo/addons/godot-xr-tools/functions/Function_pointer.tscn +++ /dev/null @@ -1,38 +0,0 @@ -[gd_scene load_steps=4 format=2] - -[ext_resource path="res://addons/godot-xr-tools/functions/Function_pointer.gd" type="Script" id=2] - -[sub_resource type="BoxMesh" id=1] -resource_local_to_scene = true -size = Vector3(0.002, 0.002, 10) -subdivide_depth = 20 - -[sub_resource type="SphereMesh" id=2] -radius = 0.05 -height = 0.1 -radial_segments = 16 -rings = 8 - -[node name="Function_pointer" type="Node3D"] -transform = Transform3D(1, 0, 0, 0, 0.707107, 0.707107, 0, -0.707107, 0.707107, 0, 0, 0) -script = ExtResource( 2 ) -collision_mask = 1048575 - -[node name="RayCast" type="RayCast3D" parent="."] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.05, 0) -target_position = Vector3(0, 0, -1) -collision_mask = 1048575 -script = null - -[node name="Laser" type="MeshInstance3D" parent="."] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.05, -5) -cast_shadow = 0 -mesh = SubResource( 1 ) -surface_material_override/0 = null -script = null - -[node name="Target" type="MeshInstance3D" parent="."] -visible = false -mesh = SubResource( 2 ) -surface_material_override/0 = null -script = null diff --git a/demo/addons/godot-xr-tools/images/icon.png b/demo/addons/godot-xr-tools/images/icon.png deleted file mode 100644 index 9aec441087cd75dbacff1b1d110a8bb9bb54ea4b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3498 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 Y|LV|6es%hBO8@`>07*qoM6N<$f`fLUNB{r; diff --git a/demo/addons/godot-xr-tools/images/icon.png.import b/demo/addons/godot-xr-tools/images/icon.png.import deleted file mode 100644 index 2d74849..0000000 --- a/demo/addons/godot-xr-tools/images/icon.png.import +++ /dev/null @@ -1,35 +0,0 @@ -[remap] - -importer="texture" -type="StreamTexture2D" -uid="uid://bmt2yc5uxkiob" -path="res://.godot/imported/icon.png-1d8efcc4c33e64800e22ea3150ef148d.stex" -metadata={ -"vram_texture": false -} - -[deps] - -source_file="res://addons/godot-xr-tools/images/icon.png" -dest_files=["res://.godot/imported/icon.png-1d8efcc4c33e64800e22ea3150ef148d.stex"] - -[params] - -compress/mode=0 -compress/lossy_quality=0.7 -compress/hdr_compression=1 -compress/bptc_ldr=0 -compress/normal_map=0 -compress/channel_pack=0 -compress/streamed=false -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/size_limit=0 -detect_3d/compress_to=1 -svg/scale=1.0 diff --git a/demo/addons/godot-xr-tools/images/teleport_arrow.png b/demo/addons/godot-xr-tools/images/teleport_arrow.png deleted file mode 100644 index cc727309796627c87602f4f18ccee75cde2ed92a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 526 zcmeAS@N?(olHy`uVBq!ia0vp^4nW+%!3HFEH|A#nDYhhUcNZWH1V5d3*8?fe0*}aI z1_q%L5N5oWCSL&*WH0gbb!C6ZBf`nb%Gq7Q&A`Ao+tbA{q~g}wJDzz=jsh-$O7H5^ ztD9Am8JF$OKJoB4<> z<0?m&#C{>iz{lZ=8byD&SX}$(_b%Z1Xe>BIwN9+b=;(QefNei6a-5Q|7jlez?5?O$ z{D*@jwSRxt0fpPA9Iy8m9BT_;ihq%6Gm z|CWPOAKPaZe*N)()*Z!vv9os{*`HOi{KxXObN{=q_+77IcuXR>2S#LX&-eV)+qJY- R4j6?D44$rjF6*2UngBU3&58g3 diff --git a/demo/addons/godot-xr-tools/images/teleport_arrow.png.import b/demo/addons/godot-xr-tools/images/teleport_arrow.png.import deleted file mode 100644 index 0a990f2..0000000 --- a/demo/addons/godot-xr-tools/images/teleport_arrow.png.import +++ /dev/null @@ -1,37 +0,0 @@ -[remap] - -importer="texture" -type="StreamTexture2D" -uid="uid://cuv0tit7ygv83" -path.s3tc="res://.godot/imported/teleport_arrow.png-f1bd44b6f478277692b3fa29171b62d3.s3tc.stex" -path.etc2="res://.godot/imported/teleport_arrow.png-f1bd44b6f478277692b3fa29171b62d3.etc2.stex" -metadata={ -"imported_formats": ["s3tc", "etc2"], -"vram_texture": true -} - -[deps] - -source_file="res://addons/godot-xr-tools/images/teleport_arrow.png" -dest_files=["res://.godot/imported/teleport_arrow.png-f1bd44b6f478277692b3fa29171b62d3.s3tc.stex", "res://.godot/imported/teleport_arrow.png-f1bd44b6f478277692b3fa29171b62d3.etc2.stex"] - -[params] - -compress/mode=2 -compress/lossy_quality=0.7 -compress/hdr_compression=1 -compress/bptc_ldr=0 -compress/normal_map=0 -compress/channel_pack=0 -compress/streamed=false -mipmaps/generate=true -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/size_limit=0 -detect_3d/compress_to=0 -svg/scale=1.0 diff --git a/demo/addons/godot-xr-tools/images/teleport_target.png b/demo/addons/godot-xr-tools/images/teleport_target.png deleted file mode 100644 index 68518ee2fa59cb3eb24e94dfac1f26fc3b351b9b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6903 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 pB7g!QH~ 0: - highlight_mesh_instance_node.set_surface_override_material(i, highlight_material) - else: - highlight_mesh_instance_node.set_surface_override_material(i, original_materials[i]) - else: - # should probably implement this in our subclass - pass - -func increase_is_closest(): - closest_count += 1 - _update_highlight() - -func decrease_is_closest(): - closest_count -= 1 - _update_highlight() - -func drop_and_free(): - if picked_up_by: - picked_up_by.drop_object() - - queue_free() - -# we are being picked up by... -func pick_up(by, with_controller): - if picked_up_by == by: - return - - if picked_up_by: - let_go() - - # remember who picked us up - picked_up_by = by - by_controller = with_controller - - # turn off physics on our pickable object - freeze = true - collision_layer = picked_up_layer - collision_mask = 0 - - # now reparent it - var original_transform = global_transform - original_parent.remove_child(self) - picked_up_by.add_child(self) - - if reset_transform_on_pickup: - if center_pickup_on_node: - transform = center_pickup_on_node.global_transform.inverse() * global_transform - else: - # reset our transform - transform = Transform3D() - else: - # make sure we keep its original position - global_transform = original_transform - -# we are being let go -func let_go(p_linear_velocity = Vector3(0.0, 0.0, 0.0), p_angular_velocity = Vector3(0.0, 0.0, 0.0)): - if picked_up_by: - # get our current global transform - var t = global_transform - - # reparent it - picked_up_by.remove_child(self) - original_parent.add_child(self) - - # reposition it and apply impulse - global_transform = t - freeze = false - collision_mask = original_collision_mask - collision_layer = original_collision_layer - - # set our starting velocity - linear_velocity = p_linear_velocity - angular_velocity = p_angular_velocity - - # we are no longer picked up - picked_up_by = null - by_controller = null - -func _ready(): - if highlight_mesh_instance: - # if we have a highlight mesh instance selected obtain our node - highlight_mesh_instance_node = get_node(highlight_mesh_instance) - if highlight_mesh_instance_node: - # if we can find a node remember which materials are currently set on each surface - for i in range(0, highlight_mesh_instance_node.get_surface_override_material_count()): - original_materials.push_back(highlight_mesh_instance_node.get_surface_override_material(i)) - - if center_pickup_on: - # if we have center pickup on set obtain our node - center_pickup_on_node = get_node(center_pickup_on) diff --git a/demo/addons/godot-xr-tools/objects/Object_pickable.tscn b/demo/addons/godot-xr-tools/objects/Object_pickable.tscn deleted file mode 100644 index 62df723..0000000 --- a/demo/addons/godot-xr-tools/objects/Object_pickable.tscn +++ /dev/null @@ -1,11 +0,0 @@ -[gd_scene load_steps=2 format=2] - -[ext_resource path="res://addons/godot-xr-tools/objects/Object_pickable.gd" type="Script" id=1] - -[node name="PickableObject" type="RigidDynamicBody3D"] -collision_layer = 4 -collision_mask = 6 -script = ExtResource( 1 ) - -[node name="CollisionShape3D" type="CollisionShape3D" parent="."] -script = null diff --git a/demo/addons/godot-xr-tools/objects/Viewport_2D_in_3D.gd b/demo/addons/godot-xr-tools/objects/Viewport_2D_in_3D.gd deleted file mode 100644 index f3643b6..0000000 --- a/demo/addons/godot-xr-tools/objects/Viewport_2D_in_3D.gd +++ /dev/null @@ -1,98 +0,0 @@ -@tool -extends Node3D - -signal pointer_entered -signal pointer_exited - -@export var enabled = true: - set(new_value): - enabled = new_value - _update_enabled() -@export var screen_size = Vector2(3.0, 2.0): - set(new_value): - screen_size = new_value - _update_screen_size() -@export var viewport_size = Vector2(300.0, 200.0): - set(new_value): - viewport_size = new_value - _update_viewport_size() -@export var transparent = true: - set(new_value): - transparent = new_value - _update_transparent() -@export var scene : PackedScene = null: - set(new_value): - scene = new_value - _update_scene() - -# Need to replace this with proper solution once support for layer selection has been added -@export_flags_3d_physics var collision_layer = 15: - set(new_value): - collision_layer = new_value - _update_collision_layer() - -var is_ready = false -var scene_node : Variant = null - -func _update_enabled(): - if is_ready: - $StaticBody/CollisionShape3D.disabled = !enabled - -func _update_screen_size(): - if is_ready: - $Screen.mesh.size = screen_size - $StaticBody.screen_size = screen_size - $StaticBody/CollisionShape3D.shape.extents = Vector3(screen_size.x * 0.5, screen_size.y * 0.5, 0.01) - -func _update_viewport_size(): - if is_ready: - $Viewport.size = viewport_size - $StaticBody.viewport_size = viewport_size - var material : StandardMaterial3D = $Screen.get_surface_override_material(0) - if material: - material.albedo_texture = $Viewport.get_texture() - else: - print_debug("Couldn't access material") - -func _update_transparent(): - if is_ready: - var material : StandardMaterial3D = $Screen.get_surface_override_material(0) - if material: - material.flags_transparent = transparent - else: - print_debug("Couldn't access material") - $Viewport.transparent_bg = transparent - -func _update_collision_layer(): - if is_ready: - $StaticBody.collision_layer = collision_layer - -func _update_scene(): - if is_ready: - # out with the old - if scene_node: - $Viewport.remove_child(scene_node) - scene_node.queue_free() - - # in with the new - if scene: - scene_node = scene.instantiate() - $Viewport.add_child(scene_node) - -func get_scene_instance(): - return scene_node - -func connect_scene_signal(which, on, callback): - if scene_node: - scene_node.connect(which, on, callback) - -# Called when the node enters the scene tree for the first time. -func _ready(): - # apply properties - is_ready = true - _update_enabled() - _update_screen_size() - _update_viewport_size() - _update_scene() - _update_collision_layer() - _update_transparent() diff --git a/demo/addons/godot-xr-tools/objects/Viewport_2D_in_3D.tscn b/demo/addons/godot-xr-tools/objects/Viewport_2D_in_3D.tscn deleted file mode 100644 index e681d53..0000000 --- a/demo/addons/godot-xr-tools/objects/Viewport_2D_in_3D.tscn +++ /dev/null @@ -1,45 +0,0 @@ -[gd_scene load_steps=7 format=3 uid="uid://dhcsolk3uwmy6"] - -[ext_resource type="Script" path="res://addons/godot-xr-tools/objects/Viewport_2D_in_3D.gd" id="1"] -[ext_resource type="Script" path="res://addons/godot-xr-tools/objects/Viewport_2D_in_3D_body.gd" id="2"] - -[sub_resource type="QuadMesh" id="1"] -resource_local_to_scene = true -size = Vector2(3, 2) - -[sub_resource type="ViewportTexture" id="ViewportTexture_371og"] -viewport_path = NodePath("Viewport") - -[sub_resource type="StandardMaterial3D" id="3"] -resource_local_to_scene = true -transparency = 1 -shading_mode = 0 -albedo_texture = SubResource( "ViewportTexture_371og" ) - -[sub_resource type="BoxShape3D" id="2"] -resource_local_to_scene = true -size = Vector3(3, 2, 0.02) - -[node name="Viewport2Din3D" type="Node3D"] -script = ExtResource( "1" ) - -[node name="Viewport" type="SubViewport" parent="."] -transparent_bg = true -size = Vector2i(300, 200) -render_target_update_mode = 3 -script = null - -[node name="Screen" type="MeshInstance3D" parent="."] -mesh = SubResource( "1" ) -surface_material_override/0 = SubResource( "3" ) -script = null - -[node name="StaticBody" type="StaticBody3D" parent="."] -collision_layer = 15 -collision_mask = 0 -script = ExtResource( "2" ) -viewport_size = Vector2(300, 200) - -[node name="CollisionShape3D" type="CollisionShape3D" parent="StaticBody"] -shape = SubResource( "2" ) -script = null diff --git a/demo/addons/godot-xr-tools/objects/Viewport_2D_in_3D_body.gd b/demo/addons/godot-xr-tools/objects/Viewport_2D_in_3D_body.gd deleted file mode 100644 index a0ea323..0000000 --- a/demo/addons/godot-xr-tools/objects/Viewport_2D_in_3D_body.gd +++ /dev/null @@ -1,72 +0,0 @@ -extends StaticBody3D - -@export var screen_size = Vector2(3.0, 2.0) -@export var viewport_size = Vector2(100.0, 100.0) - -var vp : Viewport -var mouse_mask = 0 - -# Called when the node enters the scene tree for the first time. -func _ready(): - vp = get_node("../Viewport") - -# Convert intersection point to screen coordinate -func global_to_viewport(p_at): - var t = $CollisionShape3D.global_transform - var at = t.inverse() * p_at - - # Convert to screen space - at.x = ((at.x / screen_size.x) + 0.5) * viewport_size.x - at.y = (0.5 - (at.y / screen_size.y)) * viewport_size.y - - return Vector2(at.x, at.y) - -func pointer_entered(): - get_parent().emit_signal("pointer_entered") - -func pointer_exited(): - get_parent().emit_signal("pointer_exited") - -func pointer_moved(from, to): - var local_from = global_to_viewport(from) - var local_to = global_to_viewport(to) - - # Let's mimic a mouse - var event = InputEventMouseMotion.new() - event.set_position(local_to) - event.set_global_position(local_to) - event.set_relative(local_to - local_from) # should this be scaled/warped? - event.set_button_mask(mouse_mask) - - if vp: - vp.push_input(event, true) - -func pointer_pressed(at): - var local_at = global_to_viewport(at) - - # Let's mimic a mouse - mouse_mask = 1 - var event = InputEventMouseButton.new() - event.set_button_index(1) - event.set_pressed(true) - event.set_position(local_at) - event.set_global_position(local_at) - event.set_button_mask(mouse_mask) - - if vp: - vp.push_input(event, true) - -func pointer_released(at): - var local_at = global_to_viewport(at) - - # Let's mimic a mouse - mouse_mask = 0 - var event = InputEventMouseButton.new() - event.set_button_index(1) - event.set_pressed(false) - event.set_position(local_at) - event.set_global_position(local_at) - event.set_button_mask(mouse_mask) - - if vp: - vp.push_input(event, true) diff --git a/demo/assets/hdrihaven.com/wasteland_clouds/wasteland_clouds_2k.hdr.import b/demo/assets/hdrihaven.com/wasteland_clouds/wasteland_clouds_2k.hdr.import index fe7c0dd..3ddc32f 100644 --- a/demo/assets/hdrihaven.com/wasteland_clouds/wasteland_clouds_2k.hdr.import +++ b/demo/assets/hdrihaven.com/wasteland_clouds/wasteland_clouds_2k.hdr.import @@ -1,9 +1,9 @@ [remap] importer="texture" -type="StreamTexture2D" +type="CompressedTexture2D" uid="uid://c6lpu4nnl0g4n" -path="res://.godot/imported/wasteland_clouds_2k.hdr-35430424592ade5f398ad4ef94432180.stex" +path="res://.godot/imported/wasteland_clouds_2k.hdr-35430424592ade5f398ad4ef94432180.ctex" metadata={ "vram_texture": false } @@ -11,17 +11,16 @@ metadata={ [deps] source_file="res://assets/hdrihaven.com/wasteland_clouds/wasteland_clouds_2k.hdr" -dest_files=["res://.godot/imported/wasteland_clouds_2k.hdr-35430424592ade5f398ad4ef94432180.stex"] +dest_files=["res://.godot/imported/wasteland_clouds_2k.hdr-35430424592ade5f398ad4ef94432180.ctex"] [params] compress/mode=0 +compress/high_quality=false compress/lossy_quality=0.7 compress/hdr_compression=1 -compress/bptc_ldr=0 compress/normal_map=0 compress/channel_pack=0 -compress/streamed=false mipmaps/generate=false mipmaps/limit=-1 roughness/mode=0 @@ -29,7 +28,7 @@ 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_as_srgb=false +process/hdr_clamp_exposure=false process/size_limit=0 detect_3d/compress_to=1 -svg/scale=1.0 diff --git a/demo/assets/texturehaven.com/brown_planks_03/brown_planks_03_AO_1k.jpg.import b/demo/assets/texturehaven.com/brown_planks_03/brown_planks_03_AO_1k.jpg.import index a4bb22b..defed3a 100644 --- a/demo/assets/texturehaven.com/brown_planks_03/brown_planks_03_AO_1k.jpg.import +++ b/demo/assets/texturehaven.com/brown_planks_03/brown_planks_03_AO_1k.jpg.import @@ -1,9 +1,9 @@ [remap] importer="texture" -type="StreamTexture2D" +type="CompressedTexture2D" uid="uid://rd3jqadxky8n" -path="res://.godot/imported/brown_planks_03_AO_1k.jpg-082c5e9917d7c7607736716dda2c85a8.stex" +path="res://.godot/imported/brown_planks_03_AO_1k.jpg-082c5e9917d7c7607736716dda2c85a8.ctex" metadata={ "vram_texture": false } @@ -11,17 +11,16 @@ metadata={ [deps] source_file="res://assets/texturehaven.com/brown_planks_03/brown_planks_03_AO_1k.jpg" -dest_files=["res://.godot/imported/brown_planks_03_AO_1k.jpg-082c5e9917d7c7607736716dda2c85a8.stex"] +dest_files=["res://.godot/imported/brown_planks_03_AO_1k.jpg-082c5e9917d7c7607736716dda2c85a8.ctex"] [params] compress/mode=0 +compress/high_quality=false compress/lossy_quality=0.7 compress/hdr_compression=1 -compress/bptc_ldr=0 compress/normal_map=0 compress/channel_pack=0 -compress/streamed=false mipmaps/generate=false mipmaps/limit=-1 roughness/mode=0 @@ -29,7 +28,7 @@ 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_as_srgb=false +process/hdr_clamp_exposure=false process/size_limit=0 detect_3d/compress_to=1 -svg/scale=1.0 diff --git a/demo/assets/texturehaven.com/brown_planks_03/brown_planks_03_Disp_1k.jpg.import b/demo/assets/texturehaven.com/brown_planks_03/brown_planks_03_Disp_1k.jpg.import index 1221189..38d2679 100644 --- a/demo/assets/texturehaven.com/brown_planks_03/brown_planks_03_Disp_1k.jpg.import +++ b/demo/assets/texturehaven.com/brown_planks_03/brown_planks_03_Disp_1k.jpg.import @@ -1,9 +1,9 @@ [remap] importer="texture" -type="StreamTexture2D" +type="CompressedTexture2D" uid="uid://mx7uk2hyagjw" -path="res://.godot/imported/brown_planks_03_Disp_1k.jpg-f3a540369537c2dc829e2d4b837713ce.stex" +path="res://.godot/imported/brown_planks_03_Disp_1k.jpg-f3a540369537c2dc829e2d4b837713ce.ctex" metadata={ "vram_texture": false } @@ -11,17 +11,16 @@ metadata={ [deps] source_file="res://assets/texturehaven.com/brown_planks_03/brown_planks_03_Disp_1k.jpg" -dest_files=["res://.godot/imported/brown_planks_03_Disp_1k.jpg-f3a540369537c2dc829e2d4b837713ce.stex"] +dest_files=["res://.godot/imported/brown_planks_03_Disp_1k.jpg-f3a540369537c2dc829e2d4b837713ce.ctex"] [params] compress/mode=0 +compress/high_quality=false compress/lossy_quality=0.7 compress/hdr_compression=1 -compress/bptc_ldr=0 compress/normal_map=0 compress/channel_pack=0 -compress/streamed=false mipmaps/generate=false mipmaps/limit=-1 roughness/mode=0 @@ -29,7 +28,7 @@ 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_as_srgb=false +process/hdr_clamp_exposure=false process/size_limit=0 detect_3d/compress_to=1 -svg/scale=1.0 diff --git a/demo/assets/texturehaven.com/brown_planks_03/brown_planks_03_Nor_1k.jpg.import b/demo/assets/texturehaven.com/brown_planks_03/brown_planks_03_Nor_1k.jpg.import index f250731..e5e067e 100644 --- a/demo/assets/texturehaven.com/brown_planks_03/brown_planks_03_Nor_1k.jpg.import +++ b/demo/assets/texturehaven.com/brown_planks_03/brown_planks_03_Nor_1k.jpg.import @@ -1,29 +1,27 @@ [remap] importer="texture" -type="StreamTexture2D" +type="CompressedTexture2D" uid="uid://1sbfv53go2om" -path.s3tc="res://.godot/imported/brown_planks_03_Nor_1k.jpg-94844aa022c7abafe20787f3ae5ae1a8.s3tc.stex" -path.etc2="res://.godot/imported/brown_planks_03_Nor_1k.jpg-94844aa022c7abafe20787f3ae5ae1a8.etc2.stex" +path.s3tc="res://.godot/imported/brown_planks_03_Nor_1k.jpg-94844aa022c7abafe20787f3ae5ae1a8.s3tc.ctex" metadata={ -"imported_formats": ["s3tc", "etc2"], +"imported_formats": ["s3tc_bptc"], "vram_texture": true } [deps] source_file="res://assets/texturehaven.com/brown_planks_03/brown_planks_03_Nor_1k.jpg" -dest_files=["res://.godot/imported/brown_planks_03_Nor_1k.jpg-94844aa022c7abafe20787f3ae5ae1a8.s3tc.stex", "res://.godot/imported/brown_planks_03_Nor_1k.jpg-94844aa022c7abafe20787f3ae5ae1a8.etc2.stex"] +dest_files=["res://.godot/imported/brown_planks_03_Nor_1k.jpg-94844aa022c7abafe20787f3ae5ae1a8.s3tc.ctex"] [params] compress/mode=2 +compress/high_quality=false compress/lossy_quality=0.7 compress/hdr_compression=1 -compress/bptc_ldr=0 compress/normal_map=1 compress/channel_pack=0 -compress/streamed=false mipmaps/generate=true mipmaps/limit=-1 roughness/mode=0 @@ -31,7 +29,7 @@ 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_as_srgb=false +process/hdr_clamp_exposure=false process/size_limit=0 detect_3d/compress_to=0 -svg/scale=1.0 diff --git a/demo/assets/texturehaven.com/brown_planks_03/brown_planks_03_bump_1k.jpg.import b/demo/assets/texturehaven.com/brown_planks_03/brown_planks_03_bump_1k.jpg.import index 8d3e683..8723e0b 100644 --- a/demo/assets/texturehaven.com/brown_planks_03/brown_planks_03_bump_1k.jpg.import +++ b/demo/assets/texturehaven.com/brown_planks_03/brown_planks_03_bump_1k.jpg.import @@ -1,9 +1,9 @@ [remap] importer="texture" -type="StreamTexture2D" +type="CompressedTexture2D" uid="uid://r18v08n5idv2" -path="res://.godot/imported/brown_planks_03_bump_1k.jpg-58da068964191f849af36cde0bdd167f.stex" +path="res://.godot/imported/brown_planks_03_bump_1k.jpg-58da068964191f849af36cde0bdd167f.ctex" metadata={ "vram_texture": false } @@ -11,17 +11,16 @@ metadata={ [deps] source_file="res://assets/texturehaven.com/brown_planks_03/brown_planks_03_bump_1k.jpg" -dest_files=["res://.godot/imported/brown_planks_03_bump_1k.jpg-58da068964191f849af36cde0bdd167f.stex"] +dest_files=["res://.godot/imported/brown_planks_03_bump_1k.jpg-58da068964191f849af36cde0bdd167f.ctex"] [params] compress/mode=0 +compress/high_quality=false compress/lossy_quality=0.7 compress/hdr_compression=1 -compress/bptc_ldr=0 compress/normal_map=0 compress/channel_pack=0 -compress/streamed=false mipmaps/generate=false mipmaps/limit=-1 roughness/mode=0 @@ -29,7 +28,7 @@ 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_as_srgb=false +process/hdr_clamp_exposure=false process/size_limit=0 detect_3d/compress_to=1 -svg/scale=1.0 diff --git a/demo/assets/texturehaven.com/brown_planks_03/brown_planks_03_diff_1k.jpg.import b/demo/assets/texturehaven.com/brown_planks_03/brown_planks_03_diff_1k.jpg.import index aee4a6d..ef56b2b 100644 --- a/demo/assets/texturehaven.com/brown_planks_03/brown_planks_03_diff_1k.jpg.import +++ b/demo/assets/texturehaven.com/brown_planks_03/brown_planks_03_diff_1k.jpg.import @@ -1,29 +1,27 @@ [remap] importer="texture" -type="StreamTexture2D" +type="CompressedTexture2D" uid="uid://3awgamogameb" -path.s3tc="res://.godot/imported/brown_planks_03_diff_1k.jpg-50cbd888df05ec6f37b77993d1bfc721.s3tc.stex" -path.etc2="res://.godot/imported/brown_planks_03_diff_1k.jpg-50cbd888df05ec6f37b77993d1bfc721.etc2.stex" +path.s3tc="res://.godot/imported/brown_planks_03_diff_1k.jpg-50cbd888df05ec6f37b77993d1bfc721.s3tc.ctex" metadata={ -"imported_formats": ["s3tc", "etc2"], +"imported_formats": ["s3tc_bptc"], "vram_texture": true } [deps] source_file="res://assets/texturehaven.com/brown_planks_03/brown_planks_03_diff_1k.jpg" -dest_files=["res://.godot/imported/brown_planks_03_diff_1k.jpg-50cbd888df05ec6f37b77993d1bfc721.s3tc.stex", "res://.godot/imported/brown_planks_03_diff_1k.jpg-50cbd888df05ec6f37b77993d1bfc721.etc2.stex"] +dest_files=["res://.godot/imported/brown_planks_03_diff_1k.jpg-50cbd888df05ec6f37b77993d1bfc721.s3tc.ctex"] [params] compress/mode=2 +compress/high_quality=false compress/lossy_quality=0.7 compress/hdr_compression=1 -compress/bptc_ldr=0 compress/normal_map=0 compress/channel_pack=0 -compress/streamed=false mipmaps/generate=true mipmaps/limit=-1 roughness/mode=0 @@ -31,7 +29,7 @@ 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_as_srgb=false +process/hdr_clamp_exposure=false process/size_limit=0 detect_3d/compress_to=0 -svg/scale=1.0 diff --git a/demo/assets/texturehaven.com/brown_planks_03/brown_planks_03_rough_1k.jpg.import b/demo/assets/texturehaven.com/brown_planks_03/brown_planks_03_rough_1k.jpg.import index 3ba85f4..1f14bfd 100644 --- a/demo/assets/texturehaven.com/brown_planks_03/brown_planks_03_rough_1k.jpg.import +++ b/demo/assets/texturehaven.com/brown_planks_03/brown_planks_03_rough_1k.jpg.import @@ -1,29 +1,27 @@ [remap] importer="texture" -type="StreamTexture2D" +type="CompressedTexture2D" uid="uid://dnsotgw2grocv" -path.s3tc="res://.godot/imported/brown_planks_03_rough_1k.jpg-c9c58224726f056bff3ba24831ee5c6a.s3tc.stex" -path.etc2="res://.godot/imported/brown_planks_03_rough_1k.jpg-c9c58224726f056bff3ba24831ee5c6a.etc2.stex" +path.s3tc="res://.godot/imported/brown_planks_03_rough_1k.jpg-c9c58224726f056bff3ba24831ee5c6a.s3tc.ctex" metadata={ -"imported_formats": ["s3tc", "etc2"], +"imported_formats": ["s3tc_bptc"], "vram_texture": true } [deps] source_file="res://assets/texturehaven.com/brown_planks_03/brown_planks_03_rough_1k.jpg" -dest_files=["res://.godot/imported/brown_planks_03_rough_1k.jpg-c9c58224726f056bff3ba24831ee5c6a.s3tc.stex", "res://.godot/imported/brown_planks_03_rough_1k.jpg-c9c58224726f056bff3ba24831ee5c6a.etc2.stex"] +dest_files=["res://.godot/imported/brown_planks_03_rough_1k.jpg-c9c58224726f056bff3ba24831ee5c6a.s3tc.ctex"] [params] compress/mode=2 +compress/high_quality=false compress/lossy_quality=0.7 compress/hdr_compression=1 -compress/bptc_ldr=0 compress/normal_map=0 compress/channel_pack=0 -compress/streamed=false mipmaps/generate=true mipmaps/limit=-1 roughness/mode=0 @@ -31,7 +29,7 @@ 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_as_srgb=false +process/hdr_clamp_exposure=false process/size_limit=0 detect_3d/compress_to=0 -svg/scale=1.0 diff --git a/demo/assets/texturehaven.com/brown_planks_03/brown_planks_03_spec_1k.jpg.import b/demo/assets/texturehaven.com/brown_planks_03/brown_planks_03_spec_1k.jpg.import index 03705bb..c777008 100644 --- a/demo/assets/texturehaven.com/brown_planks_03/brown_planks_03_spec_1k.jpg.import +++ b/demo/assets/texturehaven.com/brown_planks_03/brown_planks_03_spec_1k.jpg.import @@ -1,29 +1,27 @@ [remap] importer="texture" -type="StreamTexture2D" +type="CompressedTexture2D" uid="uid://dyoa6te43i7pq" -path.s3tc="res://.godot/imported/brown_planks_03_spec_1k.jpg-4c5d1f28a23bb431df4dff3cf442a9f2.s3tc.stex" -path.etc2="res://.godot/imported/brown_planks_03_spec_1k.jpg-4c5d1f28a23bb431df4dff3cf442a9f2.etc2.stex" +path.s3tc="res://.godot/imported/brown_planks_03_spec_1k.jpg-4c5d1f28a23bb431df4dff3cf442a9f2.s3tc.ctex" metadata={ -"imported_formats": ["s3tc", "etc2"], +"imported_formats": ["s3tc_bptc"], "vram_texture": true } [deps] source_file="res://assets/texturehaven.com/brown_planks_03/brown_planks_03_spec_1k.jpg" -dest_files=["res://.godot/imported/brown_planks_03_spec_1k.jpg-4c5d1f28a23bb431df4dff3cf442a9f2.s3tc.stex", "res://.godot/imported/brown_planks_03_spec_1k.jpg-4c5d1f28a23bb431df4dff3cf442a9f2.etc2.stex"] +dest_files=["res://.godot/imported/brown_planks_03_spec_1k.jpg-4c5d1f28a23bb431df4dff3cf442a9f2.s3tc.ctex"] [params] compress/mode=2 +compress/high_quality=false compress/lossy_quality=0.7 compress/hdr_compression=1 -compress/bptc_ldr=0 compress/normal_map=0 compress/channel_pack=0 -compress/streamed=false mipmaps/generate=true mipmaps/limit=-1 roughness/mode=0 @@ -31,7 +29,7 @@ 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_as_srgb=false +process/hdr_clamp_exposure=false process/size_limit=0 detect_3d/compress_to=0 -svg/scale=1.0 diff --git a/demo/assets/texturehaven.com/green_metal_rust/green_metal_rust_AO_1k.jpg.import b/demo/assets/texturehaven.com/green_metal_rust/green_metal_rust_AO_1k.jpg.import index 440928d..a3125ec 100644 --- a/demo/assets/texturehaven.com/green_metal_rust/green_metal_rust_AO_1k.jpg.import +++ b/demo/assets/texturehaven.com/green_metal_rust/green_metal_rust_AO_1k.jpg.import @@ -1,9 +1,9 @@ [remap] importer="texture" -type="StreamTexture2D" +type="CompressedTexture2D" uid="uid://c83b4oginanow" -path="res://.godot/imported/green_metal_rust_AO_1k.jpg-21d39e8f5036937d77cad1d77353ed68.stex" +path="res://.godot/imported/green_metal_rust_AO_1k.jpg-21d39e8f5036937d77cad1d77353ed68.ctex" metadata={ "vram_texture": false } @@ -11,17 +11,16 @@ metadata={ [deps] source_file="res://assets/texturehaven.com/green_metal_rust/green_metal_rust_AO_1k.jpg" -dest_files=["res://.godot/imported/green_metal_rust_AO_1k.jpg-21d39e8f5036937d77cad1d77353ed68.stex"] +dest_files=["res://.godot/imported/green_metal_rust_AO_1k.jpg-21d39e8f5036937d77cad1d77353ed68.ctex"] [params] compress/mode=0 +compress/high_quality=false compress/lossy_quality=0.7 compress/hdr_compression=1 -compress/bptc_ldr=0 compress/normal_map=0 compress/channel_pack=0 -compress/streamed=false mipmaps/generate=false mipmaps/limit=-1 roughness/mode=0 @@ -29,7 +28,7 @@ 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_as_srgb=false +process/hdr_clamp_exposure=false process/size_limit=0 detect_3d/compress_to=1 -svg/scale=1.0 diff --git a/demo/assets/texturehaven.com/green_metal_rust/green_metal_rust_Disp_1k.jpg.import b/demo/assets/texturehaven.com/green_metal_rust/green_metal_rust_Disp_1k.jpg.import index ef7ed1b..51e34ce 100644 --- a/demo/assets/texturehaven.com/green_metal_rust/green_metal_rust_Disp_1k.jpg.import +++ b/demo/assets/texturehaven.com/green_metal_rust/green_metal_rust_Disp_1k.jpg.import @@ -1,9 +1,9 @@ [remap] importer="texture" -type="StreamTexture2D" +type="CompressedTexture2D" uid="uid://ckqv2onhjgn2x" -path="res://.godot/imported/green_metal_rust_Disp_1k.jpg-29d80e92049d20b257e94cb6d00c0d64.stex" +path="res://.godot/imported/green_metal_rust_Disp_1k.jpg-29d80e92049d20b257e94cb6d00c0d64.ctex" metadata={ "vram_texture": false } @@ -11,17 +11,16 @@ metadata={ [deps] source_file="res://assets/texturehaven.com/green_metal_rust/green_metal_rust_Disp_1k.jpg" -dest_files=["res://.godot/imported/green_metal_rust_Disp_1k.jpg-29d80e92049d20b257e94cb6d00c0d64.stex"] +dest_files=["res://.godot/imported/green_metal_rust_Disp_1k.jpg-29d80e92049d20b257e94cb6d00c0d64.ctex"] [params] compress/mode=0 +compress/high_quality=false compress/lossy_quality=0.7 compress/hdr_compression=1 -compress/bptc_ldr=0 compress/normal_map=0 compress/channel_pack=0 -compress/streamed=false mipmaps/generate=false mipmaps/limit=-1 roughness/mode=0 @@ -29,7 +28,7 @@ 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_as_srgb=false +process/hdr_clamp_exposure=false process/size_limit=0 detect_3d/compress_to=1 -svg/scale=1.0 diff --git a/demo/assets/texturehaven.com/green_metal_rust/green_metal_rust_Nor_1k.jpg.import b/demo/assets/texturehaven.com/green_metal_rust/green_metal_rust_Nor_1k.jpg.import index 1dfdb77..083eabd 100644 --- a/demo/assets/texturehaven.com/green_metal_rust/green_metal_rust_Nor_1k.jpg.import +++ b/demo/assets/texturehaven.com/green_metal_rust/green_metal_rust_Nor_1k.jpg.import @@ -1,29 +1,27 @@ [remap] importer="texture" -type="StreamTexture2D" +type="CompressedTexture2D" uid="uid://72ervvx3vudf" -path.s3tc="res://.godot/imported/green_metal_rust_Nor_1k.jpg-464357613487b3408f8219e4a948a8ad.s3tc.stex" -path.etc2="res://.godot/imported/green_metal_rust_Nor_1k.jpg-464357613487b3408f8219e4a948a8ad.etc2.stex" +path.s3tc="res://.godot/imported/green_metal_rust_Nor_1k.jpg-464357613487b3408f8219e4a948a8ad.s3tc.ctex" metadata={ -"imported_formats": ["s3tc", "etc2"], +"imported_formats": ["s3tc_bptc"], "vram_texture": true } [deps] source_file="res://assets/texturehaven.com/green_metal_rust/green_metal_rust_Nor_1k.jpg" -dest_files=["res://.godot/imported/green_metal_rust_Nor_1k.jpg-464357613487b3408f8219e4a948a8ad.s3tc.stex", "res://.godot/imported/green_metal_rust_Nor_1k.jpg-464357613487b3408f8219e4a948a8ad.etc2.stex"] +dest_files=["res://.godot/imported/green_metal_rust_Nor_1k.jpg-464357613487b3408f8219e4a948a8ad.s3tc.ctex"] [params] compress/mode=2 +compress/high_quality=false compress/lossy_quality=0.7 compress/hdr_compression=1 -compress/bptc_ldr=0 compress/normal_map=1 compress/channel_pack=0 -compress/streamed=false mipmaps/generate=true mipmaps/limit=-1 roughness/mode=0 @@ -31,7 +29,7 @@ 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_as_srgb=false +process/hdr_clamp_exposure=false process/size_limit=0 detect_3d/compress_to=0 -svg/scale=1.0 diff --git a/demo/assets/texturehaven.com/green_metal_rust/green_metal_rust_bump_1k.jpg.import b/demo/assets/texturehaven.com/green_metal_rust/green_metal_rust_bump_1k.jpg.import index eabf879..9e2029b 100644 --- a/demo/assets/texturehaven.com/green_metal_rust/green_metal_rust_bump_1k.jpg.import +++ b/demo/assets/texturehaven.com/green_metal_rust/green_metal_rust_bump_1k.jpg.import @@ -1,9 +1,9 @@ [remap] importer="texture" -type="StreamTexture2D" +type="CompressedTexture2D" uid="uid://beoow6wch7fsx" -path="res://.godot/imported/green_metal_rust_bump_1k.jpg-203dab94ea028e9314a5ed7af613a6d9.stex" +path="res://.godot/imported/green_metal_rust_bump_1k.jpg-203dab94ea028e9314a5ed7af613a6d9.ctex" metadata={ "vram_texture": false } @@ -11,17 +11,16 @@ metadata={ [deps] source_file="res://assets/texturehaven.com/green_metal_rust/green_metal_rust_bump_1k.jpg" -dest_files=["res://.godot/imported/green_metal_rust_bump_1k.jpg-203dab94ea028e9314a5ed7af613a6d9.stex"] +dest_files=["res://.godot/imported/green_metal_rust_bump_1k.jpg-203dab94ea028e9314a5ed7af613a6d9.ctex"] [params] compress/mode=0 +compress/high_quality=false compress/lossy_quality=0.7 compress/hdr_compression=1 -compress/bptc_ldr=0 compress/normal_map=0 compress/channel_pack=0 -compress/streamed=false mipmaps/generate=false mipmaps/limit=-1 roughness/mode=0 @@ -29,7 +28,7 @@ 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_as_srgb=false +process/hdr_clamp_exposure=false process/size_limit=0 detect_3d/compress_to=1 -svg/scale=1.0 diff --git a/demo/assets/texturehaven.com/green_metal_rust/green_metal_rust_diff_1k.jpg.import b/demo/assets/texturehaven.com/green_metal_rust/green_metal_rust_diff_1k.jpg.import index 6128405..5a8b65c 100644 --- a/demo/assets/texturehaven.com/green_metal_rust/green_metal_rust_diff_1k.jpg.import +++ b/demo/assets/texturehaven.com/green_metal_rust/green_metal_rust_diff_1k.jpg.import @@ -1,29 +1,27 @@ [remap] importer="texture" -type="StreamTexture2D" +type="CompressedTexture2D" uid="uid://cacx3a3utpwmn" -path.s3tc="res://.godot/imported/green_metal_rust_diff_1k.jpg-cd91aaca24542896705899ce69c99c54.s3tc.stex" -path.etc2="res://.godot/imported/green_metal_rust_diff_1k.jpg-cd91aaca24542896705899ce69c99c54.etc2.stex" +path.s3tc="res://.godot/imported/green_metal_rust_diff_1k.jpg-cd91aaca24542896705899ce69c99c54.s3tc.ctex" metadata={ -"imported_formats": ["s3tc", "etc2"], +"imported_formats": ["s3tc_bptc"], "vram_texture": true } [deps] source_file="res://assets/texturehaven.com/green_metal_rust/green_metal_rust_diff_1k.jpg" -dest_files=["res://.godot/imported/green_metal_rust_diff_1k.jpg-cd91aaca24542896705899ce69c99c54.s3tc.stex", "res://.godot/imported/green_metal_rust_diff_1k.jpg-cd91aaca24542896705899ce69c99c54.etc2.stex"] +dest_files=["res://.godot/imported/green_metal_rust_diff_1k.jpg-cd91aaca24542896705899ce69c99c54.s3tc.ctex"] [params] compress/mode=2 +compress/high_quality=false compress/lossy_quality=0.7 compress/hdr_compression=1 -compress/bptc_ldr=0 compress/normal_map=0 compress/channel_pack=0 -compress/streamed=false mipmaps/generate=true mipmaps/limit=-1 roughness/mode=0 @@ -31,7 +29,7 @@ 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_as_srgb=false +process/hdr_clamp_exposure=false process/size_limit=0 detect_3d/compress_to=0 -svg/scale=1.0 diff --git a/demo/assets/texturehaven.com/green_metal_rust/green_metal_rust_rough_1k.jpg.import b/demo/assets/texturehaven.com/green_metal_rust/green_metal_rust_rough_1k.jpg.import index ebbc60f..01bebd6 100644 --- a/demo/assets/texturehaven.com/green_metal_rust/green_metal_rust_rough_1k.jpg.import +++ b/demo/assets/texturehaven.com/green_metal_rust/green_metal_rust_rough_1k.jpg.import @@ -1,29 +1,27 @@ [remap] importer="texture" -type="StreamTexture2D" +type="CompressedTexture2D" uid="uid://dn2ot7jsnovpv" -path.s3tc="res://.godot/imported/green_metal_rust_rough_1k.jpg-0f7dc2dad63cce49070e849b6b8604aa.s3tc.stex" -path.etc2="res://.godot/imported/green_metal_rust_rough_1k.jpg-0f7dc2dad63cce49070e849b6b8604aa.etc2.stex" +path.s3tc="res://.godot/imported/green_metal_rust_rough_1k.jpg-0f7dc2dad63cce49070e849b6b8604aa.s3tc.ctex" metadata={ -"imported_formats": ["s3tc", "etc2"], +"imported_formats": ["s3tc_bptc"], "vram_texture": true } [deps] source_file="res://assets/texturehaven.com/green_metal_rust/green_metal_rust_rough_1k.jpg" -dest_files=["res://.godot/imported/green_metal_rust_rough_1k.jpg-0f7dc2dad63cce49070e849b6b8604aa.s3tc.stex", "res://.godot/imported/green_metal_rust_rough_1k.jpg-0f7dc2dad63cce49070e849b6b8604aa.etc2.stex"] +dest_files=["res://.godot/imported/green_metal_rust_rough_1k.jpg-0f7dc2dad63cce49070e849b6b8604aa.s3tc.ctex"] [params] compress/mode=2 +compress/high_quality=false compress/lossy_quality=0.7 compress/hdr_compression=1 -compress/bptc_ldr=0 compress/normal_map=0 compress/channel_pack=0 -compress/streamed=false mipmaps/generate=true mipmaps/limit=-1 roughness/mode=0 @@ -31,7 +29,7 @@ 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_as_srgb=false +process/hdr_clamp_exposure=false process/size_limit=0 detect_3d/compress_to=0 -svg/scale=1.0 diff --git a/demo/assets/texturehaven.com/green_metal_rust/green_metal_rust_spec_1k.jpg.import b/demo/assets/texturehaven.com/green_metal_rust/green_metal_rust_spec_1k.jpg.import index 17cae78..9b45fe3 100644 --- a/demo/assets/texturehaven.com/green_metal_rust/green_metal_rust_spec_1k.jpg.import +++ b/demo/assets/texturehaven.com/green_metal_rust/green_metal_rust_spec_1k.jpg.import @@ -1,29 +1,27 @@ [remap] importer="texture" -type="StreamTexture2D" +type="CompressedTexture2D" uid="uid://c1lir86v3l7om" -path.s3tc="res://.godot/imported/green_metal_rust_spec_1k.jpg-ef0fa78d750e7b79d1bd3c0731c1cbc2.s3tc.stex" -path.etc2="res://.godot/imported/green_metal_rust_spec_1k.jpg-ef0fa78d750e7b79d1bd3c0731c1cbc2.etc2.stex" +path.s3tc="res://.godot/imported/green_metal_rust_spec_1k.jpg-ef0fa78d750e7b79d1bd3c0731c1cbc2.s3tc.ctex" metadata={ -"imported_formats": ["s3tc", "etc2"], +"imported_formats": ["s3tc_bptc"], "vram_texture": true } [deps] source_file="res://assets/texturehaven.com/green_metal_rust/green_metal_rust_spec_1k.jpg" -dest_files=["res://.godot/imported/green_metal_rust_spec_1k.jpg-ef0fa78d750e7b79d1bd3c0731c1cbc2.s3tc.stex", "res://.godot/imported/green_metal_rust_spec_1k.jpg-ef0fa78d750e7b79d1bd3c0731c1cbc2.etc2.stex"] +dest_files=["res://.godot/imported/green_metal_rust_spec_1k.jpg-ef0fa78d750e7b79d1bd3c0731c1cbc2.s3tc.ctex"] [params] compress/mode=2 +compress/high_quality=false compress/lossy_quality=0.7 compress/hdr_compression=1 -compress/bptc_ldr=0 compress/normal_map=0 compress/channel_pack=0 -compress/streamed=false mipmaps/generate=true mipmaps/limit=-1 roughness/mode=0 @@ -31,7 +29,7 @@ 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_as_srgb=false +process/hdr_clamp_exposure=false process/size_limit=0 detect_3d/compress_to=0 -svg/scale=1.0 diff --git a/demo/assets/wahooney.itch.io/blue_grid.png.import b/demo/assets/wahooney.itch.io/blue_grid.png.import index 7bc4a55..68851e4 100644 --- a/demo/assets/wahooney.itch.io/blue_grid.png.import +++ b/demo/assets/wahooney.itch.io/blue_grid.png.import @@ -1,29 +1,27 @@ [remap] importer="texture" -type="StreamTexture2D" +type="CompressedTexture2D" uid="uid://din2dfyevlc45" -path.s3tc="res://.godot/imported/blue_grid.png-785a01a697c0777376608d81454e4958.s3tc.stex" -path.etc2="res://.godot/imported/blue_grid.png-785a01a697c0777376608d81454e4958.etc2.stex" +path.s3tc="res://.godot/imported/blue_grid.png-785a01a697c0777376608d81454e4958.s3tc.ctex" metadata={ -"imported_formats": ["s3tc", "etc2"], +"imported_formats": ["s3tc_bptc"], "vram_texture": true } [deps] source_file="res://assets/wahooney.itch.io/blue_grid.png" -dest_files=["res://.godot/imported/blue_grid.png-785a01a697c0777376608d81454e4958.s3tc.stex", "res://.godot/imported/blue_grid.png-785a01a697c0777376608d81454e4958.etc2.stex"] +dest_files=["res://.godot/imported/blue_grid.png-785a01a697c0777376608d81454e4958.s3tc.ctex"] [params] compress/mode=2 +compress/high_quality=false compress/lossy_quality=0.7 compress/hdr_compression=1 -compress/bptc_ldr=0 compress/normal_map=0 compress/channel_pack=0 -compress/streamed=false mipmaps/generate=true mipmaps/limit=-1 roughness/mode=0 @@ -31,7 +29,7 @@ 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_as_srgb=false +process/hdr_clamp_exposure=false process/size_limit=0 detect_3d/compress_to=0 -svg/scale=1.0 diff --git a/demo/assets/wahooney.itch.io/brown_grid.png.import b/demo/assets/wahooney.itch.io/brown_grid.png.import index 416cf5b..cb1ce15 100644 --- a/demo/assets/wahooney.itch.io/brown_grid.png.import +++ b/demo/assets/wahooney.itch.io/brown_grid.png.import @@ -1,9 +1,9 @@ [remap] importer="texture" -type="StreamTexture2D" +type="CompressedTexture2D" uid="uid://df5ckkwvjnk6f" -path="res://.godot/imported/brown_grid.png-5cbd37038e3ea1da588854d56a43bef6.stex" +path="res://.godot/imported/brown_grid.png-5cbd37038e3ea1da588854d56a43bef6.ctex" metadata={ "vram_texture": false } @@ -11,17 +11,16 @@ metadata={ [deps] source_file="res://assets/wahooney.itch.io/brown_grid.png" -dest_files=["res://.godot/imported/brown_grid.png-5cbd37038e3ea1da588854d56a43bef6.stex"] +dest_files=["res://.godot/imported/brown_grid.png-5cbd37038e3ea1da588854d56a43bef6.ctex"] [params] compress/mode=0 +compress/high_quality=false compress/lossy_quality=0.7 compress/hdr_compression=1 -compress/bptc_ldr=0 compress/normal_map=0 compress/channel_pack=0 -compress/streamed=false mipmaps/generate=false mipmaps/limit=-1 roughness/mode=0 @@ -29,7 +28,7 @@ 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_as_srgb=false +process/hdr_clamp_exposure=false process/size_limit=0 detect_3d/compress_to=1 -svg/scale=1.0 diff --git a/demo/assets/wahooney.itch.io/green_grid.png.import b/demo/assets/wahooney.itch.io/green_grid.png.import index 341e88e..9a87bca 100644 --- a/demo/assets/wahooney.itch.io/green_grid.png.import +++ b/demo/assets/wahooney.itch.io/green_grid.png.import @@ -1,29 +1,27 @@ [remap] importer="texture" -type="StreamTexture2D" +type="CompressedTexture2D" uid="uid://qg5scypev53b" -path.s3tc="res://.godot/imported/green_grid.png-e9d81b3d42c428786d9997769a6729a2.s3tc.stex" -path.etc2="res://.godot/imported/green_grid.png-e9d81b3d42c428786d9997769a6729a2.etc2.stex" +path.s3tc="res://.godot/imported/green_grid.png-e9d81b3d42c428786d9997769a6729a2.s3tc.ctex" metadata={ -"imported_formats": ["s3tc", "etc2"], +"imported_formats": ["s3tc_bptc"], "vram_texture": true } [deps] source_file="res://assets/wahooney.itch.io/green_grid.png" -dest_files=["res://.godot/imported/green_grid.png-e9d81b3d42c428786d9997769a6729a2.s3tc.stex", "res://.godot/imported/green_grid.png-e9d81b3d42c428786d9997769a6729a2.etc2.stex"] +dest_files=["res://.godot/imported/green_grid.png-e9d81b3d42c428786d9997769a6729a2.s3tc.ctex"] [params] compress/mode=2 +compress/high_quality=false compress/lossy_quality=0.7 compress/hdr_compression=1 -compress/bptc_ldr=0 compress/normal_map=0 compress/channel_pack=0 -compress/streamed=false mipmaps/generate=true mipmaps/limit=-1 roughness/mode=0 @@ -31,7 +29,7 @@ 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_as_srgb=false +process/hdr_clamp_exposure=false process/size_limit=0 detect_3d/compress_to=0 -svg/scale=1.0 diff --git a/demo/assets/wahooney.itch.io/white_grid.png.import b/demo/assets/wahooney.itch.io/white_grid.png.import index 95e24e7..05ab1dc 100644 --- a/demo/assets/wahooney.itch.io/white_grid.png.import +++ b/demo/assets/wahooney.itch.io/white_grid.png.import @@ -1,29 +1,27 @@ [remap] importer="texture" -type="StreamTexture2D" +type="CompressedTexture2D" uid="uid://c1lir86v3l7om" -path.s3tc="res://.godot/imported/white_grid.png-c97900fbca7fa76e931b70c777bf36eb.s3tc.stex" -path.etc2="res://.godot/imported/white_grid.png-c97900fbca7fa76e931b70c777bf36eb.etc2.stex" +path.s3tc="res://.godot/imported/white_grid.png-c97900fbca7fa76e931b70c777bf36eb.s3tc.ctex" metadata={ -"imported_formats": ["s3tc", "etc2"], +"imported_formats": ["s3tc_bptc"], "vram_texture": true } [deps] source_file="res://assets/wahooney.itch.io/white_grid.png" -dest_files=["res://.godot/imported/white_grid.png-c97900fbca7fa76e931b70c777bf36eb.s3tc.stex", "res://.godot/imported/white_grid.png-c97900fbca7fa76e931b70c777bf36eb.etc2.stex"] +dest_files=["res://.godot/imported/white_grid.png-c97900fbca7fa76e931b70c777bf36eb.s3tc.ctex"] [params] compress/mode=2 +compress/high_quality=false compress/lossy_quality=0.7 compress/hdr_compression=1 -compress/bptc_ldr=0 compress/normal_map=0 compress/channel_pack=0 -compress/streamed=false mipmaps/generate=true mipmaps/limit=-1 roughness/mode=0 @@ -31,7 +29,7 @@ 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_as_srgb=false +process/hdr_clamp_exposure=false process/size_limit=0 detect_3d/compress_to=0 -svg/scale=1.0 diff --git a/demo/environment.tres b/demo/environment.tres index b378175..578c8da 100644 --- a/demo/environment.tres +++ b/demo/environment.tres @@ -3,11 +3,11 @@ [sub_resource type="PhysicalSkyMaterial" id="1"] [sub_resource type="Sky" id="2"] -sky_material = SubResource( "1" ) +sky_material = SubResource("1") [resource] background_mode = 2 -sky = SubResource( "2" ) +sky = SubResource("2") tonemap_mode = 2 tonemap_exposure = 0.4 tonemap_white = 16.0 diff --git a/demo/icon.png.import b/demo/icon.png.import index a10d9cb..fc4dc10 100644 --- a/demo/icon.png.import +++ b/demo/icon.png.import @@ -1,9 +1,9 @@ [remap] importer="texture" -type="StreamTexture2D" -uid="uid://brgrthvvoevwc" -path="res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" +type="CompressedTexture2D" +uid="uid://dgbxmdyne6gpi" +path="res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.ctex" metadata={ "vram_texture": false } @@ -11,17 +11,16 @@ metadata={ [deps] source_file="res://icon.png" -dest_files=["res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.stex"] +dest_files=["res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.ctex"] [params] compress/mode=0 +compress/high_quality=false compress/lossy_quality=0.7 compress/hdr_compression=1 -compress/bptc_ldr=0 compress/normal_map=0 compress/channel_pack=0 -compress/streamed=false mipmaps/generate=false mipmaps/limit=-1 roughness/mode=0 @@ -29,7 +28,7 @@ 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_as_srgb=false +process/hdr_clamp_exposure=false process/size_limit=0 detect_3d/compress_to=1 -svg/scale=1.0 diff --git a/demo/misc/Cup.tscn b/demo/misc/Cup.tscn index 2aaafb7..8daf40e 100644 --- a/demo/misc/Cup.tscn +++ b/demo/misc/Cup.tscn @@ -1,27 +1,22 @@ -[gd_scene load_steps=4 format=2] +[gd_scene load_steps=4 format=3 uid="uid://7q2uyb55p6e5"] -[ext_resource path="res://addons/godot-xr-tools/objects/Object_pickable.tscn" type="PackedScene" id=1] -[ext_resource path="res://assets/kenney.nl/mug.tres" type="ArrayMesh" id=2] +[ext_resource type="PackedScene" uid="uid://c8l60rnugru40" path="res://addons/godot-xr-tools/objects/pickable.tscn" id="1"] +[ext_resource type="ArrayMesh" path="res://assets/kenney.nl/mug.tres" id="2"] -[sub_resource type="CylinderShape3D" id=1] +[sub_resource type="CylinderShape3D" id="1"] margin = 0.01 -radius = 0.0630744 height = 0.109187 +radius = 0.0630744 -[node name="Cup" instance=ExtResource( 1 )] -center_pickup_on = NodePath("Pickup") -highlight_mesh_instance = NodePath("MeshInstance") +[node name="Cup" instance=ExtResource("1")] picked_up_layer = 1024 [node name="CollisionShape3D" parent="." index="0"] -shape = SubResource( 1 ) +shape = SubResource("1") [node name="MeshInstance" type="MeshInstance3D" parent="." index="1"] transform = Transform3D(2, 0, 0, 0, 2, 0, 0, 0, 2, -0.00689943, -0.0554655, 0) -mesh = ExtResource( 2 ) -surface_material_override/0 = null -script = null +mesh = ExtResource("2") [node name="Pickup" type="Node3D" parent="." index="2"] transform = Transform3D(0.506786, 0, -0.862072, 0, 1, 0, 0.862072, 0, 0.506786, -0.0568881, 0, 0.0334469) -script = null diff --git a/demo/openxr_action_map.tres b/demo/openxr_action_map.tres new file mode 100644 index 0000000..6da8afc --- /dev/null +++ b/demo/openxr_action_map.tres @@ -0,0 +1,885 @@ +[gd_resource type="OpenXRActionMap" load_steps=210 format=3 uid="uid://d2i8j30s7rg58"] + +[sub_resource type="OpenXRAction" id="OpenXRAction_uumoa"] +resource_name = "trigger" +localized_name = "Trigger" +toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right") + +[sub_resource type="OpenXRAction" id="OpenXRAction_gt1jj"] +resource_name = "trigger_click" +localized_name = "Trigger click" +action_type = 0 +toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right") + +[sub_resource type="OpenXRAction" id="OpenXRAction_66a5y"] +resource_name = "trigger_touch" +localized_name = "Trigger touching" +action_type = 0 +toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right") + +[sub_resource type="OpenXRAction" id="OpenXRAction_4kg7f"] +resource_name = "grip" +localized_name = "Grip" +toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right") + +[sub_resource type="OpenXRAction" id="OpenXRAction_iwc7s"] +resource_name = "grip_click" +localized_name = "Grip click" +action_type = 0 +toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right") + +[sub_resource type="OpenXRAction" id="OpenXRAction_m4i3c"] +resource_name = "grip_force" +localized_name = "Grip force" +toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right") + +[sub_resource type="OpenXRAction" id="OpenXRAction_sxoks"] +resource_name = "primary" +localized_name = "Primary joystick/thumbstick/trackpad" +action_type = 2 +toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right") + +[sub_resource type="OpenXRAction" id="OpenXRAction_jy64w"] +resource_name = "primary_click" +localized_name = "Primary joystick/thumbstick/trackpad click" +action_type = 0 +toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right") + +[sub_resource type="OpenXRAction" id="OpenXRAction_il6nd"] +resource_name = "primary_touch" +localized_name = "Primary joystick/thumbstick/trackpad touching" +action_type = 0 +toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right") + +[sub_resource type="OpenXRAction" id="OpenXRAction_xrslk"] +resource_name = "secondary" +localized_name = "Secondary joystick/thumbstick/trackpad" +action_type = 2 +toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right") + +[sub_resource type="OpenXRAction" id="OpenXRAction_scufb"] +resource_name = "secondary_click" +localized_name = "Secondary joystick/thumbstick/trackpad click" +action_type = 0 +toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right") + +[sub_resource type="OpenXRAction" id="OpenXRAction_1a8ko"] +resource_name = "secondary_touch" +localized_name = "Secondary joystick/thumbstick/trackpad touching" +action_type = 0 +toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right") + +[sub_resource type="OpenXRAction" id="OpenXRAction_h0gn7"] +resource_name = "menu_button" +localized_name = "Menu button" +action_type = 0 +toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right") + +[sub_resource type="OpenXRAction" id="OpenXRAction_40u3p"] +resource_name = "select_button" +localized_name = "Select button" +action_type = 0 +toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right") + +[sub_resource type="OpenXRAction" id="OpenXRAction_q2p17"] +resource_name = "ax_button" +localized_name = "A/X button" +action_type = 0 +toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right") + +[sub_resource type="OpenXRAction" id="OpenXRAction_uxpwr"] +resource_name = "ax_touch" +localized_name = "A/X touching" +action_type = 0 +toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right") + +[sub_resource type="OpenXRAction" id="OpenXRAction_v0mnn"] +resource_name = "by_button" +localized_name = "B/Y button" +action_type = 0 +toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right") + +[sub_resource type="OpenXRAction" id="OpenXRAction_tgbvs"] +resource_name = "by_touch" +localized_name = "B/Y touching" +action_type = 0 +toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right") + +[sub_resource type="OpenXRAction" id="OpenXRAction_7q5gg"] +resource_name = "default_pose" +localized_name = "Default pose" +action_type = 3 +toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right", "/user/vive_tracker_htcx/role/left_foot", "/user/vive_tracker_htcx/role/right_foot", "/user/vive_tracker_htcx/role/left_shoulder", "/user/vive_tracker_htcx/role/right_shoulder", "/user/vive_tracker_htcx/role/left_elbow", "/user/vive_tracker_htcx/role/right_elbow", "/user/vive_tracker_htcx/role/left_knee", "/user/vive_tracker_htcx/role/right_knee", "/user/vive_tracker_htcx/role/waist", "/user/vive_tracker_htcx/role/chest", "/user/vive_tracker_htcx/role/camera", "/user/vive_tracker_htcx/role/keyboard", "/user/eyes_ext") + +[sub_resource type="OpenXRAction" id="OpenXRAction_72bih"] +resource_name = "aim_pose" +localized_name = "Aim pose" +action_type = 3 +toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right") + +[sub_resource type="OpenXRAction" id="OpenXRAction_2021i"] +resource_name = "grip_pose" +localized_name = "Grip pose" +action_type = 3 +toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right") + +[sub_resource type="OpenXRAction" id="OpenXRAction_q2d0c"] +resource_name = "palm_pose" +localized_name = "Palm pose" +action_type = 3 +toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right") + +[sub_resource type="OpenXRAction" id="OpenXRAction_1vhn4"] +resource_name = "haptic" +localized_name = "Haptic" +action_type = 4 +toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right", "/user/vive_tracker_htcx/role/left_foot", "/user/vive_tracker_htcx/role/right_foot", "/user/vive_tracker_htcx/role/left_shoulder", "/user/vive_tracker_htcx/role/right_shoulder", "/user/vive_tracker_htcx/role/left_elbow", "/user/vive_tracker_htcx/role/right_elbow", "/user/vive_tracker_htcx/role/left_knee", "/user/vive_tracker_htcx/role/right_knee", "/user/vive_tracker_htcx/role/waist", "/user/vive_tracker_htcx/role/chest", "/user/vive_tracker_htcx/role/camera", "/user/vive_tracker_htcx/role/keyboard") + +[sub_resource type="OpenXRActionSet" id="OpenXRActionSet_nawcp"] +resource_name = "godot" +localized_name = "Godot action set" +actions = [SubResource("OpenXRAction_uumoa"), SubResource("OpenXRAction_gt1jj"), SubResource("OpenXRAction_66a5y"), SubResource("OpenXRAction_4kg7f"), SubResource("OpenXRAction_iwc7s"), SubResource("OpenXRAction_m4i3c"), SubResource("OpenXRAction_sxoks"), SubResource("OpenXRAction_jy64w"), SubResource("OpenXRAction_il6nd"), SubResource("OpenXRAction_xrslk"), SubResource("OpenXRAction_scufb"), SubResource("OpenXRAction_1a8ko"), SubResource("OpenXRAction_h0gn7"), SubResource("OpenXRAction_40u3p"), SubResource("OpenXRAction_q2p17"), SubResource("OpenXRAction_uxpwr"), SubResource("OpenXRAction_v0mnn"), SubResource("OpenXRAction_tgbvs"), SubResource("OpenXRAction_7q5gg"), SubResource("OpenXRAction_72bih"), SubResource("OpenXRAction_2021i"), SubResource("OpenXRAction_q2d0c"), SubResource("OpenXRAction_1vhn4")] + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_exm24"] +action = SubResource("OpenXRAction_7q5gg") +paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_hiefi"] +action = SubResource("OpenXRAction_72bih") +paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_lj60v"] +action = SubResource("OpenXRAction_2021i") +paths = PackedStringArray("/user/hand/left/input/grip/pose", "/user/hand/right/input/grip/pose") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_qftdi"] +action = SubResource("OpenXRAction_q2d0c") +paths = PackedStringArray("/user/hand/left/input/palm_ext/pose", "/user/hand/right/input/palm_ext/pose") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_kqrp0"] +action = SubResource("OpenXRAction_h0gn7") +paths = PackedStringArray("/user/hand/left/input/menu/click", "/user/hand/right/input/menu/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_3njs4"] +action = SubResource("OpenXRAction_40u3p") +paths = PackedStringArray("/user/hand/left/input/select/click", "/user/hand/right/input/select/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_qf2t3"] +action = SubResource("OpenXRAction_1vhn4") +paths = PackedStringArray("/user/hand/left/output/haptic", "/user/hand/right/output/haptic") + +[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_r1jl7"] +interaction_profile_path = "/interaction_profiles/khr/simple_controller" +bindings = [SubResource("OpenXRIPBinding_exm24"), SubResource("OpenXRIPBinding_hiefi"), SubResource("OpenXRIPBinding_lj60v"), SubResource("OpenXRIPBinding_qftdi"), SubResource("OpenXRIPBinding_kqrp0"), SubResource("OpenXRIPBinding_3njs4"), SubResource("OpenXRIPBinding_qf2t3")] + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_e8ssk"] +action = SubResource("OpenXRAction_7q5gg") +paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_l03tj"] +action = SubResource("OpenXRAction_72bih") +paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_arvl3"] +action = SubResource("OpenXRAction_2021i") +paths = PackedStringArray("/user/hand/left/input/grip/pose", "/user/hand/right/input/grip/pose") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_r1mlu"] +action = SubResource("OpenXRAction_q2d0c") +paths = PackedStringArray("/user/hand/left/input/palm_ext/pose", "/user/hand/right/input/palm_ext/pose") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_r5b2e"] +action = SubResource("OpenXRAction_h0gn7") +paths = PackedStringArray("/user/hand/left/input/menu/click", "/user/hand/right/input/menu/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_lcjwk"] +action = SubResource("OpenXRAction_40u3p") +paths = PackedStringArray("/user/hand/left/input/system/click", "/user/hand/right/input/system/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_dbqn8"] +action = SubResource("OpenXRAction_uumoa") +paths = PackedStringArray("/user/hand/left/input/trigger/value", "/user/hand/right/input/trigger/value") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_rjpcl"] +action = SubResource("OpenXRAction_gt1jj") +paths = PackedStringArray("/user/hand/left/input/trigger/click", "/user/hand/right/input/trigger/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_1ip8w"] +action = SubResource("OpenXRAction_4kg7f") +paths = PackedStringArray("/user/hand/left/input/squeeze/click", "/user/hand/right/input/squeeze/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_lpr3e"] +action = SubResource("OpenXRAction_iwc7s") +paths = PackedStringArray("/user/hand/left/input/squeeze/click", "/user/hand/right/input/squeeze/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_v1w7u"] +action = SubResource("OpenXRAction_sxoks") +paths = PackedStringArray("/user/hand/left/input/trackpad", "/user/hand/right/input/trackpad") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_4qa3k"] +action = SubResource("OpenXRAction_jy64w") +paths = PackedStringArray("/user/hand/left/input/trackpad/click", "/user/hand/right/input/trackpad/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_y4uyu"] +action = SubResource("OpenXRAction_il6nd") +paths = PackedStringArray("/user/hand/left/input/trackpad/touch", "/user/hand/right/input/trackpad/touch") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_lw6ip"] +action = SubResource("OpenXRAction_1vhn4") +paths = PackedStringArray("/user/hand/left/output/haptic", "/user/hand/right/output/haptic") + +[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_i5lu6"] +interaction_profile_path = "/interaction_profiles/htc/vive_controller" +bindings = [SubResource("OpenXRIPBinding_e8ssk"), SubResource("OpenXRIPBinding_l03tj"), SubResource("OpenXRIPBinding_arvl3"), SubResource("OpenXRIPBinding_r1mlu"), SubResource("OpenXRIPBinding_r5b2e"), SubResource("OpenXRIPBinding_lcjwk"), SubResource("OpenXRIPBinding_dbqn8"), SubResource("OpenXRIPBinding_rjpcl"), SubResource("OpenXRIPBinding_1ip8w"), SubResource("OpenXRIPBinding_lpr3e"), SubResource("OpenXRIPBinding_v1w7u"), SubResource("OpenXRIPBinding_4qa3k"), SubResource("OpenXRIPBinding_y4uyu"), SubResource("OpenXRIPBinding_lw6ip")] + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_xof48"] +action = SubResource("OpenXRAction_7q5gg") +paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_v1qw5"] +action = SubResource("OpenXRAction_72bih") +paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_tl3e4"] +action = SubResource("OpenXRAction_2021i") +paths = PackedStringArray("/user/hand/left/input/grip/pose", "/user/hand/right/input/grip/pose") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_anogx"] +action = SubResource("OpenXRAction_q2d0c") +paths = PackedStringArray("/user/hand/left/input/palm_ext/pose", "/user/hand/right/input/palm_ext/pose") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_dts1c"] +action = SubResource("OpenXRAction_h0gn7") +paths = PackedStringArray("/user/hand/left/input/menu/click", "/user/hand/right/input/menu/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_u0lj3"] +action = SubResource("OpenXRAction_uumoa") +paths = PackedStringArray("/user/hand/left/input/trigger/value", "/user/hand/right/input/trigger/value") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_h01yv"] +action = SubResource("OpenXRAction_gt1jj") +paths = PackedStringArray("/user/hand/left/input/trigger/value", "/user/hand/right/input/trigger/value") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_kc5a1"] +action = SubResource("OpenXRAction_4kg7f") +paths = PackedStringArray("/user/hand/left/input/squeeze/click", "/user/hand/right/input/squeeze/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_yegll"] +action = SubResource("OpenXRAction_iwc7s") +paths = PackedStringArray("/user/hand/left/input/squeeze/click", "/user/hand/right/input/squeeze/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_d5ahh"] +action = SubResource("OpenXRAction_sxoks") +paths = PackedStringArray("/user/hand/left/input/thumbstick", "/user/hand/right/input/thumbstick") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_qwol8"] +action = SubResource("OpenXRAction_jy64w") +paths = PackedStringArray("/user/hand/left/input/thumbstick/click", "/user/hand/right/input/thumbstick/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_miptf"] +action = SubResource("OpenXRAction_xrslk") +paths = PackedStringArray("/user/hand/left/input/trackpad", "/user/hand/right/input/trackpad") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_1l5qg"] +action = SubResource("OpenXRAction_scufb") +paths = PackedStringArray("/user/hand/left/input/trackpad/click", "/user/hand/right/input/trackpad/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_wru5w"] +action = SubResource("OpenXRAction_1a8ko") +paths = PackedStringArray("/user/hand/left/input/trackpad/touch", "/user/hand/right/input/trackpad/touch") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ujqms"] +action = SubResource("OpenXRAction_1vhn4") +paths = PackedStringArray("/user/hand/left/output/haptic", "/user/hand/right/output/haptic") + +[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_05vth"] +interaction_profile_path = "/interaction_profiles/microsoft/motion_controller" +bindings = [SubResource("OpenXRIPBinding_xof48"), SubResource("OpenXRIPBinding_v1qw5"), SubResource("OpenXRIPBinding_tl3e4"), SubResource("OpenXRIPBinding_anogx"), SubResource("OpenXRIPBinding_dts1c"), SubResource("OpenXRIPBinding_u0lj3"), SubResource("OpenXRIPBinding_h01yv"), SubResource("OpenXRIPBinding_kc5a1"), SubResource("OpenXRIPBinding_yegll"), SubResource("OpenXRIPBinding_d5ahh"), SubResource("OpenXRIPBinding_qwol8"), SubResource("OpenXRIPBinding_miptf"), SubResource("OpenXRIPBinding_1l5qg"), SubResource("OpenXRIPBinding_wru5w"), SubResource("OpenXRIPBinding_ujqms")] + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_3bik3"] +action = SubResource("OpenXRAction_7q5gg") +paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_judum"] +action = SubResource("OpenXRAction_72bih") +paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_n8x6s"] +action = SubResource("OpenXRAction_2021i") +paths = PackedStringArray("/user/hand/left/input/grip/pose", "/user/hand/right/input/grip/pose") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_tx0ao"] +action = SubResource("OpenXRAction_q2d0c") +paths = PackedStringArray("/user/hand/left/input/palm_ext/pose", "/user/hand/right/input/palm_ext/pose") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_emo18"] +action = SubResource("OpenXRAction_h0gn7") +paths = PackedStringArray("/user/hand/left/input/menu/click", "/user/hand/right/input/system/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_2pkyj"] +action = SubResource("OpenXRAction_q2p17") +paths = PackedStringArray("/user/hand/left/input/x/click", "/user/hand/right/input/a/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_5ag21"] +action = SubResource("OpenXRAction_uxpwr") +paths = PackedStringArray("/user/hand/left/input/x/touch", "/user/hand/right/input/a/touch") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_14y8b"] +action = SubResource("OpenXRAction_v0mnn") +paths = PackedStringArray("/user/hand/left/input/y/click", "/user/hand/right/input/b/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_vahqg"] +action = SubResource("OpenXRAction_tgbvs") +paths = PackedStringArray("/user/hand/left/input/y/touch", "/user/hand/right/input/b/touch") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_pbpbd"] +action = SubResource("OpenXRAction_uumoa") +paths = PackedStringArray("/user/hand/left/input/trigger/value", "/user/hand/right/input/trigger/value") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_yuof8"] +action = SubResource("OpenXRAction_gt1jj") +paths = PackedStringArray("/user/hand/left/input/trigger/value", "/user/hand/right/input/trigger/value") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_bxcub"] +action = SubResource("OpenXRAction_66a5y") +paths = PackedStringArray("/user/hand/left/input/trigger/touch", "/user/hand/right/input/trigger/touch") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_nqnn6"] +action = SubResource("OpenXRAction_4kg7f") +paths = PackedStringArray("/user/hand/left/input/squeeze/value", "/user/hand/right/input/squeeze/value") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_3vevo"] +action = SubResource("OpenXRAction_iwc7s") +paths = PackedStringArray("/user/hand/left/input/squeeze/value", "/user/hand/right/input/squeeze/value") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ey1gx"] +action = SubResource("OpenXRAction_sxoks") +paths = PackedStringArray("/user/hand/left/input/thumbstick", "/user/hand/right/input/thumbstick") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_sc0yu"] +action = SubResource("OpenXRAction_jy64w") +paths = PackedStringArray("/user/hand/left/input/thumbstick/click", "/user/hand/right/input/thumbstick/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_nd5nc"] +action = SubResource("OpenXRAction_il6nd") +paths = PackedStringArray("/user/hand/left/input/thumbstick/touch", "/user/hand/right/input/thumbstick/touch") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_2u8p3"] +action = SubResource("OpenXRAction_1vhn4") +paths = PackedStringArray("/user/hand/left/output/haptic", "/user/hand/right/output/haptic") + +[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_6ct6y"] +interaction_profile_path = "/interaction_profiles/oculus/touch_controller" +bindings = [SubResource("OpenXRIPBinding_3bik3"), SubResource("OpenXRIPBinding_judum"), SubResource("OpenXRIPBinding_n8x6s"), SubResource("OpenXRIPBinding_tx0ao"), SubResource("OpenXRIPBinding_emo18"), SubResource("OpenXRIPBinding_2pkyj"), SubResource("OpenXRIPBinding_5ag21"), SubResource("OpenXRIPBinding_14y8b"), SubResource("OpenXRIPBinding_vahqg"), SubResource("OpenXRIPBinding_pbpbd"), SubResource("OpenXRIPBinding_yuof8"), SubResource("OpenXRIPBinding_bxcub"), SubResource("OpenXRIPBinding_nqnn6"), SubResource("OpenXRIPBinding_3vevo"), SubResource("OpenXRIPBinding_ey1gx"), SubResource("OpenXRIPBinding_sc0yu"), SubResource("OpenXRIPBinding_nd5nc"), SubResource("OpenXRIPBinding_2u8p3")] + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_s33ps"] +action = SubResource("OpenXRAction_7q5gg") +paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_5v5w0"] +action = SubResource("OpenXRAction_72bih") +paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_w0k08"] +action = SubResource("OpenXRAction_2021i") +paths = PackedStringArray("/user/hand/left/input/grip/pose", "/user/hand/right/input/grip/pose") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_y4k6u"] +action = SubResource("OpenXRAction_q2d0c") +paths = PackedStringArray("/user/hand/left/input/palm_ext/pose", "/user/hand/right/input/palm_ext/pose") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_3panw"] +action = SubResource("OpenXRAction_40u3p") +paths = PackedStringArray("/user/hand/left/input/system/click", "/user/hand/right/input/system/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_26c36"] +action = SubResource("OpenXRAction_h0gn7") +paths = PackedStringArray("/user/hand/left/input/menu/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_x5rn6"] +action = SubResource("OpenXRAction_q2p17") +paths = PackedStringArray("/user/hand/left/input/x/click", "/user/hand/right/input/a/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_af8gj"] +action = SubResource("OpenXRAction_uxpwr") +paths = PackedStringArray("/user/hand/left/input/x/touch", "/user/hand/right/input/a/touch") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_52ae8"] +action = SubResource("OpenXRAction_v0mnn") +paths = PackedStringArray("/user/hand/left/input/y/click", "/user/hand/right/input/b/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_8g0j3"] +action = SubResource("OpenXRAction_tgbvs") +paths = PackedStringArray("/user/hand/left/input/y/touch", "/user/hand/right/input/b/touch") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_htycy"] +action = SubResource("OpenXRAction_uumoa") +paths = PackedStringArray("/user/hand/left/input/trigger/value", "/user/hand/right/input/trigger/value") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_d20mg"] +action = SubResource("OpenXRAction_gt1jj") +paths = PackedStringArray("/user/hand/left/input/trigger/value", "/user/hand/right/input/trigger/value") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ei2jg"] +action = SubResource("OpenXRAction_66a5y") +paths = PackedStringArray("/user/hand/left/input/trigger/touch", "/user/hand/right/input/trigger/touch") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_0r7sv"] +action = SubResource("OpenXRAction_4kg7f") +paths = PackedStringArray("/user/hand/left/input/squeeze/value", "/user/hand/right/input/squeeze/value") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_mcdlm"] +action = SubResource("OpenXRAction_iwc7s") +paths = PackedStringArray("/user/hand/left/input/squeeze/value", "/user/hand/right/input/squeeze/value") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_l71lb"] +action = SubResource("OpenXRAction_sxoks") +paths = PackedStringArray("/user/hand/left/input/thumbstick", "/user/hand/right/input/thumbstick") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_jeay7"] +action = SubResource("OpenXRAction_jy64w") +paths = PackedStringArray("/user/hand/left/input/thumbstick/click", "/user/hand/right/input/thumbstick/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_qkvnx"] +action = SubResource("OpenXRAction_il6nd") +paths = PackedStringArray("/user/hand/left/input/thumbstick/touch", "/user/hand/right/input/thumbstick/touch") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_asmdo"] +action = SubResource("OpenXRAction_1vhn4") +paths = PackedStringArray("/user/hand/left/output/haptic", "/user/hand/right/output/haptic") + +[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_kd7pr"] +interaction_profile_path = "/interaction_profiles/bytedance/pico4_controller" +bindings = [SubResource("OpenXRIPBinding_s33ps"), SubResource("OpenXRIPBinding_5v5w0"), SubResource("OpenXRIPBinding_w0k08"), SubResource("OpenXRIPBinding_y4k6u"), SubResource("OpenXRIPBinding_3panw"), SubResource("OpenXRIPBinding_26c36"), SubResource("OpenXRIPBinding_x5rn6"), SubResource("OpenXRIPBinding_af8gj"), SubResource("OpenXRIPBinding_52ae8"), SubResource("OpenXRIPBinding_8g0j3"), SubResource("OpenXRIPBinding_htycy"), SubResource("OpenXRIPBinding_d20mg"), SubResource("OpenXRIPBinding_ei2jg"), SubResource("OpenXRIPBinding_0r7sv"), SubResource("OpenXRIPBinding_mcdlm"), SubResource("OpenXRIPBinding_l71lb"), SubResource("OpenXRIPBinding_jeay7"), SubResource("OpenXRIPBinding_qkvnx"), SubResource("OpenXRIPBinding_asmdo")] + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_c222p"] +action = SubResource("OpenXRAction_7q5gg") +paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_vvv5d"] +action = SubResource("OpenXRAction_72bih") +paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ipkke"] +action = SubResource("OpenXRAction_2021i") +paths = PackedStringArray("/user/hand/left/input/grip/pose", "/user/hand/right/input/grip/pose") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_6f0qy"] +action = SubResource("OpenXRAction_q2d0c") +paths = PackedStringArray("/user/hand/left/input/palm_ext/pose", "/user/hand/right/input/palm_ext/pose") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_a5732"] +action = SubResource("OpenXRAction_h0gn7") +paths = PackedStringArray("/user/hand/left/input/system/click", "/user/hand/right/input/system/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_kkrnn"] +action = SubResource("OpenXRAction_q2p17") +paths = PackedStringArray("/user/hand/left/input/a/click", "/user/hand/right/input/a/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_q5doj"] +action = SubResource("OpenXRAction_uxpwr") +paths = PackedStringArray("/user/hand/left/input/a/touch", "/user/hand/right/input/a/touch") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_dgwtw"] +action = SubResource("OpenXRAction_v0mnn") +paths = PackedStringArray("/user/hand/left/input/b/click", "/user/hand/right/input/b/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_vs65q"] +action = SubResource("OpenXRAction_tgbvs") +paths = PackedStringArray("/user/hand/left/input/b/touch", "/user/hand/right/input/b/touch") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_kuyb7"] +action = SubResource("OpenXRAction_uumoa") +paths = PackedStringArray("/user/hand/left/input/trigger/value", "/user/hand/right/input/trigger/value") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_7jyd2"] +action = SubResource("OpenXRAction_gt1jj") +paths = PackedStringArray("/user/hand/left/input/trigger/click", "/user/hand/right/input/trigger/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_tn72x"] +action = SubResource("OpenXRAction_66a5y") +paths = PackedStringArray("/user/hand/left/input/trigger/touch", "/user/hand/right/input/trigger/touch") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_g2yiw"] +action = SubResource("OpenXRAction_4kg7f") +paths = PackedStringArray("/user/hand/left/input/squeeze/value", "/user/hand/right/input/squeeze/value") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_tyqy2"] +action = SubResource("OpenXRAction_iwc7s") +paths = PackedStringArray("/user/hand/left/input/squeeze/value", "/user/hand/right/input/squeeze/value") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_yn08h"] +action = SubResource("OpenXRAction_m4i3c") +paths = PackedStringArray("/user/hand/left/input/squeeze/force", "/user/hand/right/input/squeeze/force") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_mvx4w"] +action = SubResource("OpenXRAction_sxoks") +paths = PackedStringArray("/user/hand/left/input/thumbstick", "/user/hand/right/input/thumbstick") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_im6jc"] +action = SubResource("OpenXRAction_jy64w") +paths = PackedStringArray("/user/hand/left/input/thumbstick/click", "/user/hand/right/input/thumbstick/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_s7bab"] +action = SubResource("OpenXRAction_il6nd") +paths = PackedStringArray("/user/hand/left/input/thumbstick/touch", "/user/hand/right/input/thumbstick/touch") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_om7b1"] +action = SubResource("OpenXRAction_xrslk") +paths = PackedStringArray("/user/hand/left/input/trackpad", "/user/hand/right/input/trackpad") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ol1ve"] +action = SubResource("OpenXRAction_scufb") +paths = PackedStringArray("/user/hand/left/input/trackpad/force", "/user/hand/right/input/trackpad/force") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_yk06m"] +action = SubResource("OpenXRAction_1a8ko") +paths = PackedStringArray("/user/hand/left/input/trackpad/touch", "/user/hand/right/input/trackpad/touch") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_jxb1f"] +action = SubResource("OpenXRAction_1vhn4") +paths = PackedStringArray("/user/hand/left/output/haptic", "/user/hand/right/output/haptic") + +[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_d822s"] +interaction_profile_path = "/interaction_profiles/valve/index_controller" +bindings = [SubResource("OpenXRIPBinding_c222p"), SubResource("OpenXRIPBinding_vvv5d"), SubResource("OpenXRIPBinding_ipkke"), SubResource("OpenXRIPBinding_6f0qy"), SubResource("OpenXRIPBinding_a5732"), SubResource("OpenXRIPBinding_kkrnn"), SubResource("OpenXRIPBinding_q5doj"), SubResource("OpenXRIPBinding_dgwtw"), SubResource("OpenXRIPBinding_vs65q"), SubResource("OpenXRIPBinding_kuyb7"), SubResource("OpenXRIPBinding_7jyd2"), SubResource("OpenXRIPBinding_tn72x"), SubResource("OpenXRIPBinding_g2yiw"), SubResource("OpenXRIPBinding_tyqy2"), SubResource("OpenXRIPBinding_yn08h"), SubResource("OpenXRIPBinding_mvx4w"), SubResource("OpenXRIPBinding_im6jc"), SubResource("OpenXRIPBinding_s7bab"), SubResource("OpenXRIPBinding_om7b1"), SubResource("OpenXRIPBinding_ol1ve"), SubResource("OpenXRIPBinding_yk06m"), SubResource("OpenXRIPBinding_jxb1f")] + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_b4wee"] +action = SubResource("OpenXRAction_7q5gg") +paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_o6uyh"] +action = SubResource("OpenXRAction_72bih") +paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_e83tx"] +action = SubResource("OpenXRAction_2021i") +paths = PackedStringArray("/user/hand/left/input/grip/pose", "/user/hand/right/input/grip/pose") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_n38nr"] +action = SubResource("OpenXRAction_q2d0c") +paths = PackedStringArray("/user/hand/left/input/palm_ext/pose", "/user/hand/right/input/palm_ext/pose") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_nsl3g"] +action = SubResource("OpenXRAction_h0gn7") +paths = PackedStringArray("/user/hand/left/input/menu/click", "/user/hand/right/input/menu/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_msy5i"] +action = SubResource("OpenXRAction_q2p17") +paths = PackedStringArray("/user/hand/left/input/x/click", "/user/hand/right/input/a/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_18vmr"] +action = SubResource("OpenXRAction_v0mnn") +paths = PackedStringArray("/user/hand/left/input/y/click", "/user/hand/right/input/b/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_rwlod"] +action = SubResource("OpenXRAction_uumoa") +paths = PackedStringArray("/user/hand/left/input/trigger/value", "/user/hand/right/input/trigger/value") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_t7q6o"] +action = SubResource("OpenXRAction_gt1jj") +paths = PackedStringArray("/user/hand/left/input/trigger/value", "/user/hand/right/input/trigger/value") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_dypep"] +action = SubResource("OpenXRAction_4kg7f") +paths = PackedStringArray("/user/hand/left/input/squeeze/value", "/user/hand/right/input/squeeze/value") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ajqv7"] +action = SubResource("OpenXRAction_iwc7s") +paths = PackedStringArray("/user/hand/left/input/squeeze/value", "/user/hand/right/input/squeeze/value") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_lw535"] +action = SubResource("OpenXRAction_sxoks") +paths = PackedStringArray("/user/hand/left/input/thumbstick", "/user/hand/right/input/thumbstick") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_pa7l5"] +action = SubResource("OpenXRAction_jy64w") +paths = PackedStringArray("/user/hand/left/input/thumbstick/click", "/user/hand/right/input/thumbstick/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_f48rn"] +action = SubResource("OpenXRAction_1vhn4") +paths = PackedStringArray("/user/hand/left/output/haptic", "/user/hand/right/output/haptic") + +[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_w2iv2"] +interaction_profile_path = "/interaction_profiles/hp/mixed_reality_controller" +bindings = [SubResource("OpenXRIPBinding_b4wee"), SubResource("OpenXRIPBinding_o6uyh"), SubResource("OpenXRIPBinding_e83tx"), SubResource("OpenXRIPBinding_n38nr"), SubResource("OpenXRIPBinding_nsl3g"), SubResource("OpenXRIPBinding_msy5i"), SubResource("OpenXRIPBinding_18vmr"), SubResource("OpenXRIPBinding_rwlod"), SubResource("OpenXRIPBinding_t7q6o"), SubResource("OpenXRIPBinding_dypep"), SubResource("OpenXRIPBinding_ajqv7"), SubResource("OpenXRIPBinding_lw535"), SubResource("OpenXRIPBinding_pa7l5"), SubResource("OpenXRIPBinding_f48rn")] + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ggvbn"] +action = SubResource("OpenXRAction_7q5gg") +paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_pjb7s"] +action = SubResource("OpenXRAction_72bih") +paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_esyyv"] +action = SubResource("OpenXRAction_2021i") +paths = PackedStringArray("/user/hand/left/input/grip/pose", "/user/hand/right/input/grip/pose") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_myvrh"] +action = SubResource("OpenXRAction_q2d0c") +paths = PackedStringArray("/user/hand/left/input/palm_ext/pose", "/user/hand/right/input/palm_ext/pose") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ctk1c"] +action = SubResource("OpenXRAction_h0gn7") +paths = PackedStringArray("/user/hand/left/input/menu/click", "/user/hand/right/input/menu/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_g85g3"] +action = SubResource("OpenXRAction_uumoa") +paths = PackedStringArray("/user/hand/left/input/trigger/value", "/user/hand/right/input/trigger/value") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_w77wu"] +action = SubResource("OpenXRAction_gt1jj") +paths = PackedStringArray("/user/hand/left/input/trigger/value", "/user/hand/right/input/trigger/value") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ngngq"] +action = SubResource("OpenXRAction_4kg7f") +paths = PackedStringArray("/user/hand/left/input/squeeze/click", "/user/hand/right/input/squeeze/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_vba0l"] +action = SubResource("OpenXRAction_iwc7s") +paths = PackedStringArray("/user/hand/left/input/squeeze/click", "/user/hand/right/input/squeeze/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_1vmig"] +action = SubResource("OpenXRAction_sxoks") +paths = PackedStringArray("/user/hand/left/input/thumbstick", "/user/hand/right/input/thumbstick") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_3qxxu"] +action = SubResource("OpenXRAction_jy64w") +paths = PackedStringArray("/user/hand/left/input/thumbstick/click", "/user/hand/right/input/thumbstick/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ncnu2"] +action = SubResource("OpenXRAction_xrslk") +paths = PackedStringArray("/user/hand/left/input/trackpad", "/user/hand/right/input/trackpad") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_5j2di"] +action = SubResource("OpenXRAction_scufb") +paths = PackedStringArray("/user/hand/left/input/trackpad/click", "/user/hand/right/input/trackpad/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_m1qe2"] +action = SubResource("OpenXRAction_1a8ko") +paths = PackedStringArray("/user/hand/left/input/trackpad/touch", "/user/hand/right/input/trackpad/touch") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_aak53"] +action = SubResource("OpenXRAction_1vhn4") +paths = PackedStringArray("/user/hand/left/output/haptic", "/user/hand/right/output/haptic") + +[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_ajp4o"] +interaction_profile_path = "/interaction_profiles/samsung/odyssey_controller" +bindings = [SubResource("OpenXRIPBinding_ggvbn"), SubResource("OpenXRIPBinding_pjb7s"), SubResource("OpenXRIPBinding_esyyv"), SubResource("OpenXRIPBinding_myvrh"), SubResource("OpenXRIPBinding_ctk1c"), SubResource("OpenXRIPBinding_g85g3"), SubResource("OpenXRIPBinding_w77wu"), SubResource("OpenXRIPBinding_ngngq"), SubResource("OpenXRIPBinding_vba0l"), SubResource("OpenXRIPBinding_1vmig"), SubResource("OpenXRIPBinding_3qxxu"), SubResource("OpenXRIPBinding_ncnu2"), SubResource("OpenXRIPBinding_5j2di"), SubResource("OpenXRIPBinding_m1qe2"), SubResource("OpenXRIPBinding_aak53")] + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_aupe5"] +action = SubResource("OpenXRAction_7q5gg") +paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_dfma8"] +action = SubResource("OpenXRAction_72bih") +paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ir5kb"] +action = SubResource("OpenXRAction_2021i") +paths = PackedStringArray("/user/hand/left/input/grip/pose", "/user/hand/right/input/grip/pose") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_2a6jk"] +action = SubResource("OpenXRAction_q2d0c") +paths = PackedStringArray("/user/hand/left/input/palm_ext/pose", "/user/hand/right/input/palm_ext/pose") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_p05to"] +action = SubResource("OpenXRAction_h0gn7") +paths = PackedStringArray("/user/hand/left/input/menu/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_xn6tw"] +action = SubResource("OpenXRAction_40u3p") +paths = PackedStringArray("/user/hand/right/input/system/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ctlpn"] +action = SubResource("OpenXRAction_q2p17") +paths = PackedStringArray("/user/hand/left/input/x/click", "/user/hand/right/input/a/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_sw1y0"] +action = SubResource("OpenXRAction_v0mnn") +paths = PackedStringArray("/user/hand/left/input/y/click", "/user/hand/right/input/b/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_iyhky"] +action = SubResource("OpenXRAction_uumoa") +paths = PackedStringArray("/user/hand/left/input/trigger/value", "/user/hand/right/input/trigger/value") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_1i31s"] +action = SubResource("OpenXRAction_gt1jj") +paths = PackedStringArray("/user/hand/left/input/trigger/click", "/user/hand/right/input/trigger/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_qybot"] +action = SubResource("OpenXRAction_4kg7f") +paths = PackedStringArray("/user/hand/left/input/squeeze/click", "/user/hand/right/input/squeeze/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_dgdik"] +action = SubResource("OpenXRAction_iwc7s") +paths = PackedStringArray("/user/hand/left/input/squeeze/click", "/user/hand/right/input/squeeze/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ea6o1"] +action = SubResource("OpenXRAction_sxoks") +paths = PackedStringArray("/user/hand/left/input/thumbstick", "/user/hand/right/input/thumbstick") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_b0hgd"] +action = SubResource("OpenXRAction_jy64w") +paths = PackedStringArray("/user/hand/left/input/thumbstick/click", "/user/hand/right/input/thumbstick/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_2usi3"] +action = SubResource("OpenXRAction_il6nd") +paths = PackedStringArray("/user/hand/left/input/thumbstick/touch", "/user/hand/right/input/thumbstick/touch") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_1xeqg"] +action = SubResource("OpenXRAction_1vhn4") +paths = PackedStringArray("/user/hand/left/output/haptic", "/user/hand/right/output/haptic") + +[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_5axb0"] +interaction_profile_path = "/interaction_profiles/htc/vive_cosmos_controller" +bindings = [SubResource("OpenXRIPBinding_aupe5"), SubResource("OpenXRIPBinding_dfma8"), SubResource("OpenXRIPBinding_ir5kb"), SubResource("OpenXRIPBinding_2a6jk"), SubResource("OpenXRIPBinding_p05to"), SubResource("OpenXRIPBinding_xn6tw"), SubResource("OpenXRIPBinding_ctlpn"), SubResource("OpenXRIPBinding_sw1y0"), SubResource("OpenXRIPBinding_iyhky"), SubResource("OpenXRIPBinding_1i31s"), SubResource("OpenXRIPBinding_qybot"), SubResource("OpenXRIPBinding_dgdik"), SubResource("OpenXRIPBinding_ea6o1"), SubResource("OpenXRIPBinding_b0hgd"), SubResource("OpenXRIPBinding_2usi3"), SubResource("OpenXRIPBinding_1xeqg")] + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_xoam1"] +action = SubResource("OpenXRAction_7q5gg") +paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_sm3ui"] +action = SubResource("OpenXRAction_72bih") +paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_0n8it"] +action = SubResource("OpenXRAction_2021i") +paths = PackedStringArray("/user/hand/left/input/grip/pose", "/user/hand/right/input/grip/pose") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_i6q6b"] +action = SubResource("OpenXRAction_q2d0c") +paths = PackedStringArray("/user/hand/left/input/palm_ext/pose", "/user/hand/right/input/palm_ext/pose") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_k35u0"] +action = SubResource("OpenXRAction_h0gn7") +paths = PackedStringArray("/user/hand/left/input/menu/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_88rsp"] +action = SubResource("OpenXRAction_40u3p") +paths = PackedStringArray("/user/hand/right/input/system/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_mw18o"] +action = SubResource("OpenXRAction_q2p17") +paths = PackedStringArray("/user/hand/left/input/x/click", "/user/hand/right/input/a/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_6tk78"] +action = SubResource("OpenXRAction_v0mnn") +paths = PackedStringArray("/user/hand/left/input/y/click", "/user/hand/right/input/b/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_pv23d"] +action = SubResource("OpenXRAction_uumoa") +paths = PackedStringArray("/user/hand/left/input/trigger/value", "/user/hand/right/input/trigger/value") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_pu3bj"] +action = SubResource("OpenXRAction_gt1jj") +paths = PackedStringArray("/user/hand/left/input/trigger/click", "/user/hand/right/input/trigger/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_6jq26"] +action = SubResource("OpenXRAction_66a5y") +paths = PackedStringArray("/user/hand/left/input/trigger/touch", "/user/hand/right/input/trigger/touch") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_7co2h"] +action = SubResource("OpenXRAction_4kg7f") +paths = PackedStringArray("/user/hand/left/input/squeeze/click", "/user/hand/right/input/squeeze/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_o7l2c"] +action = SubResource("OpenXRAction_iwc7s") +paths = PackedStringArray("/user/hand/left/input/squeeze/click", "/user/hand/right/input/squeeze/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_8im81"] +action = SubResource("OpenXRAction_sxoks") +paths = PackedStringArray("/user/hand/left/input/thumbstick", "/user/hand/right/input/thumbstick") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_fmo6s"] +action = SubResource("OpenXRAction_jy64w") +paths = PackedStringArray("/user/hand/left/input/thumbstick/click", "/user/hand/right/input/thumbstick/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_y1ki8"] +action = SubResource("OpenXRAction_il6nd") +paths = PackedStringArray("/user/hand/left/input/thumbstick/touch", "/user/hand/right/input/thumbstick/touch") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_k8jub"] +action = SubResource("OpenXRAction_1a8ko") +paths = PackedStringArray("/user/hand/left/input/thumbrest/touch", "/user/hand/right/input/thumbrest/touch") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_gnol3"] +action = SubResource("OpenXRAction_1vhn4") +paths = PackedStringArray("/user/hand/left/output/haptic", "/user/hand/right/output/haptic") + +[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_s60n6"] +interaction_profile_path = "/interaction_profiles/htc/vive_focus3_controller" +bindings = [SubResource("OpenXRIPBinding_xoam1"), SubResource("OpenXRIPBinding_sm3ui"), SubResource("OpenXRIPBinding_0n8it"), SubResource("OpenXRIPBinding_i6q6b"), SubResource("OpenXRIPBinding_k35u0"), SubResource("OpenXRIPBinding_88rsp"), SubResource("OpenXRIPBinding_mw18o"), SubResource("OpenXRIPBinding_6tk78"), SubResource("OpenXRIPBinding_pv23d"), SubResource("OpenXRIPBinding_pu3bj"), SubResource("OpenXRIPBinding_6jq26"), SubResource("OpenXRIPBinding_7co2h"), SubResource("OpenXRIPBinding_o7l2c"), SubResource("OpenXRIPBinding_8im81"), SubResource("OpenXRIPBinding_fmo6s"), SubResource("OpenXRIPBinding_y1ki8"), SubResource("OpenXRIPBinding_k8jub"), SubResource("OpenXRIPBinding_gnol3")] + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_iwqxa"] +action = SubResource("OpenXRAction_7q5gg") +paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_wworr"] +action = SubResource("OpenXRAction_72bih") +paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_eaywx"] +action = SubResource("OpenXRAction_2021i") +paths = PackedStringArray("/user/hand/left/input/grip/pose", "/user/hand/right/input/grip/pose") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_rfb7q"] +action = SubResource("OpenXRAction_q2d0c") +paths = PackedStringArray("/user/hand/left/input/palm_ext/pose", "/user/hand/right/input/palm_ext/pose") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_k7t0e"] +action = SubResource("OpenXRAction_h0gn7") +paths = PackedStringArray("/user/hand/left/input/home/click", "/user/hand/right/input/home/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_1c77j"] +action = SubResource("OpenXRAction_uumoa") +paths = PackedStringArray("/user/hand/left/input/trigger/value", "/user/hand/right/input/trigger/value") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_x07rx"] +action = SubResource("OpenXRAction_gt1jj") +paths = PackedStringArray("/user/hand/left/input/trigger/click", "/user/hand/right/input/trigger/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_yewo5"] +action = SubResource("OpenXRAction_sxoks") +paths = PackedStringArray("/user/hand/left/input/trackpad", "/user/hand/right/input/trackpad") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_sgis2"] +action = SubResource("OpenXRAction_jy64w") +paths = PackedStringArray("/user/hand/left/input/trackpad/click", "/user/hand/right/input/trackpad/click") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_2ajsd"] +action = SubResource("OpenXRAction_il6nd") +paths = PackedStringArray("/user/hand/left/input/trackpad/touch", "/user/hand/right/input/trackpad/touch") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_abakc"] +action = SubResource("OpenXRAction_1vhn4") +paths = PackedStringArray("/user/hand/left/output/haptic", "/user/hand/right/output/haptic") + +[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_07rko"] +interaction_profile_path = "/interaction_profiles/huawei/controller" +bindings = [SubResource("OpenXRIPBinding_iwqxa"), SubResource("OpenXRIPBinding_wworr"), SubResource("OpenXRIPBinding_eaywx"), SubResource("OpenXRIPBinding_rfb7q"), SubResource("OpenXRIPBinding_k7t0e"), SubResource("OpenXRIPBinding_1c77j"), SubResource("OpenXRIPBinding_x07rx"), SubResource("OpenXRIPBinding_yewo5"), SubResource("OpenXRIPBinding_sgis2"), SubResource("OpenXRIPBinding_2ajsd"), SubResource("OpenXRIPBinding_abakc")] + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_cgwo6"] +action = SubResource("OpenXRAction_7q5gg") +paths = PackedStringArray("/user/vive_tracker_htcx/role/left_foot/input/grip/pose", "/user/vive_tracker_htcx/role/right_foot/input/grip/pose", "/user/vive_tracker_htcx/role/left_shoulder/input/grip/pose", "/user/vive_tracker_htcx/role/right_shoulder/input/grip/pose", "/user/vive_tracker_htcx/role/left_elbow/input/grip/pose", "/user/vive_tracker_htcx/role/right_elbow/input/grip/pose", "/user/vive_tracker_htcx/role/left_knee/input/grip/pose", "/user/vive_tracker_htcx/role/right_knee/input/grip/pose", "/user/vive_tracker_htcx/role/waist/input/grip/pose", "/user/vive_tracker_htcx/role/chest/input/grip/pose", "/user/vive_tracker_htcx/role/camera/input/grip/pose", "/user/vive_tracker_htcx/role/keyboard/input/grip/pose") + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_tmtoc"] +action = SubResource("OpenXRAction_1vhn4") +paths = PackedStringArray("/user/vive_tracker_htcx/role/left_foot/output/haptic", "/user/vive_tracker_htcx/role/right_foot/output/haptic", "/user/vive_tracker_htcx/role/left_shoulder/output/haptic", "/user/vive_tracker_htcx/role/right_shoulder/output/haptic", "/user/vive_tracker_htcx/role/left_elbow/output/haptic", "/user/vive_tracker_htcx/role/right_elbow/output/haptic", "/user/vive_tracker_htcx/role/left_knee/output/haptic", "/user/vive_tracker_htcx/role/right_knee/output/haptic", "/user/vive_tracker_htcx/role/waist/output/haptic", "/user/vive_tracker_htcx/role/chest/output/haptic", "/user/vive_tracker_htcx/role/camera/output/haptic", "/user/vive_tracker_htcx/role/keyboard/output/haptic") + +[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_p1jdl"] +interaction_profile_path = "/interaction_profiles/htc/vive_tracker_htcx" +bindings = [SubResource("OpenXRIPBinding_cgwo6"), SubResource("OpenXRIPBinding_tmtoc")] + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_dk6fn"] +action = SubResource("OpenXRAction_7q5gg") +paths = PackedStringArray("/user/eyes_ext/input/gaze_ext/pose") + +[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_hi1xp"] +interaction_profile_path = "/interaction_profiles/ext/eye_gaze_interaction" +bindings = [SubResource("OpenXRIPBinding_dk6fn")] + +[resource] +action_sets = [SubResource("OpenXRActionSet_nawcp")] +interaction_profiles = [SubResource("OpenXRInteractionProfile_r1jl7"), SubResource("OpenXRInteractionProfile_i5lu6"), SubResource("OpenXRInteractionProfile_05vth"), SubResource("OpenXRInteractionProfile_6ct6y"), SubResource("OpenXRInteractionProfile_kd7pr"), SubResource("OpenXRInteractionProfile_d822s"), SubResource("OpenXRInteractionProfile_w2iv2"), SubResource("OpenXRInteractionProfile_ajp4o"), SubResource("OpenXRInteractionProfile_5axb0"), SubResource("OpenXRInteractionProfile_s60n6"), SubResource("OpenXRInteractionProfile_07rko"), SubResource("OpenXRInteractionProfile_p1jdl"), SubResource("OpenXRInteractionProfile_hi1xp")] diff --git a/demo/player/ButtonStates.gd b/demo/player/ButtonStates.gd index 31fba78..3bd14c0 100644 --- a/demo/player/ButtonStates.gd +++ b/demo/player/ButtonStates.gd @@ -10,21 +10,21 @@ func _ready(): pass # Replace with function body. # Called every frame. 'delta' is the elapsed time since the previous frame. -func _process(delta): +func _process(_delta): if controller: - var primary = controller.get_axis("primary") + var primary = controller.get_vector2("primary") $VBoxContainer/PrimaryJoyX/Value.value = 100.0 * primary.x $VBoxContainer/PrimaryJoyY/Value.value = 100.0 * primary.y - var secondary = controller.get_axis("secondary") + var secondary = controller.get_vector2("secondary") $VBoxContainer/SecondaryJoyX/Value.value = 100.0 * secondary.x $VBoxContainer/SecondaryJoyY/Value.value = 100.0 * secondary.y - var trigger = controller.get_value("trigger_value") + var trigger = controller.get_float("trigger_value") $VBoxContainer/Trigger/Value.value = 100.0 * trigger $VBoxContainer/Trigger/Pressed.button_pressed = controller.is_button_pressed("trigger_click") - var grip = controller.get_value("grip_value") + var grip = controller.get_float("grip_value") $VBoxContainer/Grip/Value.value = 100.0 * grip $VBoxContainer/Grip/Pressed.button_pressed = controller.is_button_pressed("grip_click") $VBoxContainer/AX/Pressed.button_pressed = controller.is_button_pressed("ax") diff --git a/demo/player/HUD_Anchor.gd b/demo/player/HUD_Anchor.gd index e21cdcd..43af951 100644 --- a/demo/player/HUD_Anchor.gd +++ b/demo/player/HUD_Anchor.gd @@ -5,6 +5,6 @@ func _ready(): if material: material.albedo_texture = $SubViewport.get_texture() -func _process(delta): +func _process(_delta): var fps = Performance.get_monitor(Performance.TIME_FPS) $SubViewport/FPS.text = "FPS: " + str(fps) diff --git a/demo/player/left_hand_controller.gd b/demo/player/left_hand_controller.gd deleted file mode 100644 index ac01a26..0000000 --- a/demo/player/left_hand_controller.gd +++ /dev/null @@ -1,9 +0,0 @@ -extends "res://addons/godot-openvr/scenes/ovr_controller.gd" - -# Called every frame. 'delta' is the elapsed time since the previous frame. -func _process(delta): - # update our rumble - if is_button_pressed("trigger_click"): - rumble = 1.0 - else: - rumble = 0.0 diff --git a/demo/player/right_controller.gd b/demo/player/right_controller.gd index f5b0936..3ee1417 100644 --- a/demo/player/right_controller.gd +++ b/demo/player/right_controller.gd @@ -4,7 +4,7 @@ extends XRController3D func _ready(): $Viewport2Din3D.get_scene_instance().set_controller(self) -func _on_aim_right_hand_button_pressed(name): - print("Button " + name + " pressed") +func _on_aim_right_hand_button_pressed(button_name): + print("Button " + button_name + " pressed") if name =="trigger_click": trigger_haptic_pulse("haptic", 100.0, 10.0, 0.2, 0.0); diff --git a/demo/project.godot b/demo/project.godot index 5b68335..fb11221 100644 --- a/demo/project.godot +++ b/demo/project.godot @@ -8,46 +8,17 @@ config_version=5 -_global_script_classes=[{ -"base": "Node3D", -"class": &"Framecounter3D", -"language": &"GDScript", -"path": "res://addons/godot-openvr/scenes/framecounter_in_3d.gd" -}, { -"base": "XRController3D", -"class": &"OVRController3D", -"language": &"GDScript", -"path": "res://addons/godot-openvr/scenes/ovr_controller.gd" -}, { -"base": "XROrigin3D", -"class": &"OVRMain3D", -"language": &"GDScript", -"path": "res://addons/godot-openvr/scenes/ovr_main.gd" -}, { -"base": "MeshInstance3D", -"class": &"OVRRenderModel3D", -"language": &"GDScript", -"path": "res://addons/godot-openvr/scenes/ovr_render_model.gd" -}, { -"base": "Node3D", -"class": &"OVRShaderCache", -"language": &"GDScript", -"path": "res://addons/godot-openvr/scenes/ovr_shader_cache.gd" -}] -_global_script_class_icons={ -"Framecounter3D": "", -"OVRController3D": "", -"OVRMain3D": "", -"OVRRenderModel3D": "", -"OVRShaderCache": "" -} - [application] config/name="OpenVR demo" run/main_scene="res://Main.tscn" +config/features=PackedStringArray("4.2") config/icon="res://icon.png" -config/features=PackedStringArray("4.0") + +[autoload] + +XRToolsUserSettings="*res://addons/godot-xr-tools/user_settings/user_settings.gd" +OpenVRInterface="*res://addons/godot-openvr/openvr_autoloader.gd" [display] @@ -57,7 +28,7 @@ window/vsync/use_vsync=false [editor_plugins] -enabled=PackedStringArray("res://addons/godot-openvr/plugin.cfg") +enabled=PackedStringArray("res://addons/godot-openvr/plugin.cfg", "res://addons/godot-xr-tools/plugin.cfg") [layer_names] @@ -81,3 +52,7 @@ vulkan/rendering/back_end=1 xr/enabled=true quality/filters/msaa=1 environment/default_environment="res://default_env.tres" + +[xr] + +shaders/enabled=true diff --git a/godot-cpp b/godot-cpp index 4e2411a..78ffea5 160000 --- a/godot-cpp +++ b/godot-cpp @@ -1 +1 @@ -Subproject commit 4e2411ad98089235eb90ac427354031b8aab70cc +Subproject commit 78ffea5b136f3178c31cddb28f6b963ceaa89420 diff --git a/openvr b/openvr index 4c85abc..15f0838 160000 --- a/openvr +++ b/openvr @@ -1 +1 @@ -Subproject commit 4c85abcb7f7f1f02adaf3812018c99fc593bc341 +Subproject commit 15f0838a0487feb7da60acd39aab8099b994234c diff --git a/src/open_vr/OpenVROverlay.cpp b/src/open_vr/OpenVROverlay.cpp index 35f5a0c..a61f42b 100644 --- a/src/open_vr/OpenVROverlay.cpp +++ b/src/open_vr/OpenVROverlay.cpp @@ -3,6 +3,7 @@ #include "OpenVROverlay.h" +#include #include #include @@ -39,6 +40,9 @@ OpenVROverlay::~OpenVROverlay() { } void OpenVROverlay::_ready() { + if (Engine::get_singleton()->is_editor_hint()) { + return; + } String appname = ProjectSettings::get_singleton()->get_setting("application/config/name"); String overlay_identifier = appname + String::num(ovr->get_overlay_count() + 1); diff --git a/src/open_vr/OpenVROverlay.h b/src/open_vr/OpenVROverlay.h index 43e7b74..1f78436 100644 --- a/src/open_vr/OpenVROverlay.h +++ b/src/open_vr/OpenVROverlay.h @@ -6,11 +6,11 @@ #include "openvr_data.h" #include -#include +#include namespace godot { -class OpenVROverlay : public Viewport { - GDCLASS(OpenVROverlay, Viewport) +class OpenVROverlay : public SubViewport { + GDCLASS(OpenVROverlay, SubViewport) private: openvr_data *ovr; diff --git a/src/open_vr/OpenVRSkeleton.cpp b/src/open_vr/OpenVRSkeleton.cpp index 2ccffd2..927c37f 100644 --- a/src/open_vr/OpenVRSkeleton.cpp +++ b/src/open_vr/OpenVRSkeleton.cpp @@ -187,7 +187,7 @@ void OpenVRSkeleton::_process(double delta) { // TODO This has to be rewritten, we should use the quarternion data as we get it. set_bone_pose_position(i, pose_transform.origin); - set_bone_pose_rotation(i, pose_transform.basis.get_rotation_quat()); + set_bone_pose_rotation(i, pose_transform.basis.get_rotation_quaternion()); } // I guess we're active... diff --git a/src/open_vr/openvr_data.cpp b/src/open_vr/openvr_data.cpp index c6c4fdc..7d9c3ed 100644 --- a/src/open_vr/openvr_data.cpp +++ b/src/open_vr/openvr_data.cpp @@ -226,49 +226,40 @@ bool openvr_data::initialise() { if (success) { OS *os = OS::get_singleton(); - Ref directory; - directory.instantiate(); + ProjectSettings *project_settings = ProjectSettings::get_singleton(); + Ref directory = DirAccess::open("res://"); - String exec_path = os->get_executable_path().get_base_dir().replace("\\", "/"); + String exec_path = os->get_executable_path().replace("\\", "/").get_base_dir(); String manifest_path; - Array arr; - arr.push_back(String(exec_path)); - UtilityFunctions::print(String("Exec path: {0}").format(arr)); - // check 3 locations in order // 1) check if we have an action folder alongside our executable (runtime deployed actions) - arr.push_back(String("/actions/actions.json")); - String path = String("{0}{1}").format(arr); + String path = exec_path.path_join("actions/actions.json"); if (directory->file_exists(path)) { manifest_path = path; } else { - String project_path = ProjectSettings::get_singleton()->globalize_path("res://"); - if (project_path.length() != 0) { - Array arr2; - arr2.push_back(project_path); - UtilityFunctions::print(String("Project path: {0}").format(arr2)); - - // 2) else check if we have an action folder in our project folder (custom user actions in development) - arr2.push_back(String("actions/actions.json")); - path = String("{0}{1}").format(arr2); + // 2) else check if we have an action folder in our project folder (custom user actions in development) + path = "res://actions/actions.json"; + if (directory->file_exists(path)) { + manifest_path = path; + } else { + // 3) else check if we have an action folder in our plugin (if no user overrule) + path = "res://addons/godot-openvr/actions/actions.json"; if (directory->file_exists(path)) { manifest_path = path; - } else { - // 3) else check if we have an action folder in our plugin (if no user overrule) - Array arr3; - arr3.push_back(project_path); - arr3.push_back(String("addons/godot-openvr/actions/actions.json")); - path = String("{0}{1}").format(arr3); - if (directory->file_exists(path)) { - manifest_path = path; - } } } } if (manifest_path.length() != 0) { - vr::EVRInputError err = vr::VRInput()->SetActionManifestPath(manifest_path.utf8().get_data()); + String absolute_path; + if (os->has_feature("editor")) { + absolute_path = project_settings->globalize_path(manifest_path); + } else { + absolute_path = exec_path.path_join(manifest_path); + } + + vr::EVRInputError err = vr::VRInput()->SetActionManifestPath(absolute_path.utf8().get_data()); if (err == vr::VRInputError_None) { Array arr; arr.push_back(manifest_path); @@ -1284,13 +1275,10 @@ void openvr_data::remove_mesh(ArrayMesh *p_mesh) { Transform3D openvr_data::transform_from_matrix(vr::HmdMatrix34_t *p_matrix, double p_world_scale) { Transform3D ret; - float *basis_ptr = (float *)&ret.basis.elements; - int k = 0; - for (int i = 0; i < 3; i++) { - for (int j = 0; j < 3; j++) { - basis_ptr[k++] = p_matrix->m[i][j]; - } - } + ret.basis = Basis( + Vector3(p_matrix->m[0][0], p_matrix->m[1][0], p_matrix->m[2][0]), + Vector3(p_matrix->m[0][1], p_matrix->m[1][1], p_matrix->m[2][1]), + Vector3(p_matrix->m[0][2], p_matrix->m[1][2], p_matrix->m[2][2])); ret.origin.x = (real_t)(p_matrix->m[0][3] * p_world_scale); ret.origin.y = (real_t)(p_matrix->m[1][3] * p_world_scale); diff --git a/src/open_vr/openvr_data.h b/src/open_vr/openvr_data.h index 2c45617..bba549f 100644 --- a/src/open_vr/openvr_data.h +++ b/src/open_vr/openvr_data.h @@ -4,10 +4,16 @@ #ifndef OPENVR_DATA_H #define OPENVR_DATA_H +#ifdef USE_OPENVR_MINGW_HEADER +// When compiling with mingw, we need to use the tunabrain-patched header file +// which is packaged by msys2 with the following name. +#include +#else #include +#endif #include -#include +#include #include #include #include diff --git a/src/register_types.cpp b/src/register_types.cpp index bef6e75..c3a2219 100644 --- a/src/register_types.cpp +++ b/src/register_types.cpp @@ -6,7 +6,7 @@ #include "register_types.h" -#include +#include #include #include @@ -21,46 +21,26 @@ using namespace godot; -Ref xr_interface_openvr; +// Due to godotengine/godot#64975, we can't add our interface to the XR +// server here. Instead, we register an autoload singleton ourselves in +// EditorPlugin.cpp. -void register_types() { - // UtilityFunctions::print("Hello register types!"); +void initialize_gdextension_types(ModuleInitializationLevel p_level) { + if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) { + return; + } ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); - - XRServer *xr_server = XRServer::get_singleton(); - ERR_FAIL_NULL(xr_server); - - xr_interface_openvr.instantiate(); - xr_server->add_interface(xr_interface_openvr); -} - -void unregister_types() { - if (xr_interface_openvr.is_valid()) { - if (xr_interface_openvr->is_initialized()) { - xr_interface_openvr->uninitialize(); - } - - XRServer *xr_server = XRServer::get_singleton(); - ERR_FAIL_NULL(xr_server); - xr_server->remove_interface(xr_interface_openvr); - - xr_interface_openvr.unref(); - } - - // Note: our class will be unregistered automatically } extern "C" { -// Initialization. -GDNativeBool GDN_EXPORT openvr_library_init(const GDNativeInterface *p_interface, const GDNativeExtensionClassLibraryPtr p_library, GDNativeInitialization *r_initialization) { - godot::GDExtensionBinding::InitObject init_obj(p_interface, p_library, r_initialization); - - init_obj.register_driver_initializer(register_types); - init_obj.register_driver_terminator(unregister_types); +GDExtensionBool GDE_EXPORT openvr_library_init(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization) { + GDExtensionBinding::InitObject init_obj(p_get_proc_address, p_library, r_initialization); + init_obj.register_initializer(initialize_gdextension_types); + init_obj.set_minimum_library_initialization_level(MODULE_INITIALIZATION_LEVEL_SCENE); return init_obj.init(); } diff --git a/src/xr_interface_openvr.cpp b/src/xr_interface_openvr.cpp index ce199b3..d69b61a 100644 --- a/src/xr_interface_openvr.cpp +++ b/src/xr_interface_openvr.cpp @@ -175,7 +175,7 @@ StringName XRInterfaceOpenVR::_get_name() const { //////////////////////////////////////////////////////////////// // Returns capabilities for this interface -int64_t XRInterfaceOpenVR::_get_capabilities() const { +uint32_t XRInterfaceOpenVR::_get_capabilities() const { return XR_STEREO + XR_EXTERNAL; } @@ -197,10 +197,6 @@ bool XRInterfaceOpenVR::_initialize() { return false; } - // we only support Vulkan ATM - // video_driver = godot::OS::get_singleton()->get_current_video_driver(); - video_driver = OS::VIDEO_DRIVER_VULKAN; - if (ovr->initialise()) { // go and get our recommended target size ovr->get_recommended_rendertarget_size(&width, &height); @@ -229,7 +225,7 @@ void XRInterfaceOpenVR::_uninitialize() { //////////////////////////////////////////////////////////////// // Returns our current tracking status -int64_t XRInterfaceOpenVR::_get_tracking_status() const { +XRInterface::TrackingStatus XRInterfaceOpenVR::_get_tracking_status() const { // TODO implement this.. return XRInterface::XR_UNKNOWN_TRACKING; } @@ -263,7 +259,7 @@ Vector2 XRInterfaceOpenVR::_get_render_target_size() { //////////////////////////////////////////////////////////////// // Informs Godot how many views are required -int64_t XRInterfaceOpenVR::_get_view_count() { +uint32_t XRInterfaceOpenVR::_get_view_count() { return 2; } @@ -282,7 +278,7 @@ Transform3D XRInterfaceOpenVR::_get_camera_transform() { //////////////////////////////////////////////////////////////// // This is called while rendering to get each view matrix -Transform3D XRInterfaceOpenVR::_get_transform_for_view(int64_t p_view, const Transform3D &p_cam_transform) { +Transform3D XRInterfaceOpenVR::_get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) { if (ovr == nullptr || xr_server == nullptr) { return Transform3D(); } @@ -304,7 +300,7 @@ Transform3D XRInterfaceOpenVR::_get_transform_for_view(int64_t p_view, const Tra //////////////////////////////////////////////////////////////// // This is called while rendering to get each eyes projection matrix -PackedFloat64Array XRInterfaceOpenVR::_get_projection_for_view(int64_t p_view, double p_aspect, double p_z_near, double p_z_far) { +PackedFloat64Array XRInterfaceOpenVR::_get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) { PackedFloat64Array arr; if (ovr == nullptr || xr_server == nullptr) { @@ -333,7 +329,7 @@ void XRInterfaceOpenVR::_post_draw_viewport(const RID &p_render_target, const Re // Note that at this point in time nothing has actually been rendered yet, this entry point gets called by Godot after // all the rendering for our viewport has been prepared, but the queues have yet to be submitted to Vulkan - if (!p_screen_rect.has_no_area()) { + if (p_screen_rect.has_area()) { // just blit left eye out to screen Rect2 src_rect; Rect2 dst_rect = p_screen_rect; @@ -430,12 +426,6 @@ void XRInterfaceOpenVR::_process() { } } -//////////////////////////////////////////////////////////////// -// Receive notifications sent to our ARVROrigin node. -void XRInterfaceOpenVR::_notification(int64_t what) { - // nothing to do here for now but we should implement this. -} - XRInterfaceOpenVR::XRInterfaceOpenVR() { ovr = openvr_data::retain_singleton(); if (ovr == nullptr) { diff --git a/src/xr_interface_openvr.h b/src/xr_interface_openvr.h index b7acfa6..e389a1d 100644 --- a/src/xr_interface_openvr.h +++ b/src/xr_interface_openvr.h @@ -24,7 +24,6 @@ class XRInterfaceOpenVR : public XRInterfaceExtension { uint32_t width = 0; uint32_t height = 0; - OS::VideoDriver video_driver = OS::VIDEO_DRIVER_VULKAN; RID texture_rid; public: @@ -51,27 +50,25 @@ class XRInterfaceOpenVR : public XRInterfaceExtension { // Functions virtual StringName _get_name() const override; - virtual int64_t _get_capabilities() const override; + virtual uint32_t _get_capabilities() const override; virtual bool _is_initialized() const override; virtual bool _initialize() override; virtual void _uninitialize() override; - virtual int64_t _get_tracking_status() const override; + virtual XRInterface::TrackingStatus _get_tracking_status() const override; virtual void _trigger_haptic_pulse(const String &action_name, const StringName &tracker_name, double frequency, double amplitude, double duration_sec, double delay_sec) override; virtual Vector2 _get_render_target_size() override; - virtual int64_t _get_view_count() override; + virtual uint32_t _get_view_count() override; virtual Transform3D _get_camera_transform() override; - virtual Transform3D _get_transform_for_view(int64_t p_view, const Transform3D &p_cam_transform) override; - virtual PackedFloat64Array _get_projection_for_view(int64_t p_view, double p_aspect, double p_z_near, double p_z_far) override; + virtual Transform3D _get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) override; + virtual PackedFloat64Array _get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) override; virtual void _process() override; virtual void _post_draw_viewport(const RID &render_target, const Rect2 &screen_rect) override; virtual void _end_frame() override; - virtual void _notification(int64_t what) override; - XRInterfaceOpenVR(); ~XRInterfaceOpenVR(); };