From 7562e07c6e902b23949f418c667a5d909352d844 Mon Sep 17 00:00:00 2001 From: Bill Doyle Date: Thu, 18 Jan 2024 10:33:09 -0500 Subject: [PATCH 01/26] Remove long-useless macOS support from SConstruct --- README.md | 2 +- SConstruct | 24 ------------------------ 2 files changed, 1 insertion(+), 25 deletions(-) diff --git a/README.md b/README.md index 89cc0f6..a7174c4 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ You can compile this module by executing: scons platform=windows target=release ``` -Platform can be windows, linux or osx. OSX is untested. +Platform can be `windows` or `linux`. Note that for extensions the dll needs to be compiled with `target=release_debug` when used with the editor. diff --git a/SConstruct b/SConstruct index fa2b273..a407ab7 100644 --- a/SConstruct +++ b/SConstruct @@ -31,11 +31,6 @@ opts.Update(env) if env['use_llvm']: env['CXX'] = 'clang++' -# 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])) - # platform dir for openvr libraries platform_dir = '' @@ -75,21 +70,6 @@ if env['platform'] == 'windows': 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['target_path'] += 'x11/' godot_cpp_library += '.linux' @@ -130,8 +110,6 @@ env.Append(LIBS=[godot_cpp_library]) if (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']) @@ -149,8 +127,6 @@ else: # 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( From b95335ee2ca2a28953d45747049c8167b3eeddef Mon Sep 17 00:00:00 2001 From: Bill Doyle Date: Thu, 18 Jan 2024 12:30:23 -0500 Subject: [PATCH 02/26] Update godot-cpp to track 4.2 --- .gitmodules | 1 + godot-cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) 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/godot-cpp b/godot-cpp index 4e2411a..78ffea5 160000 --- a/godot-cpp +++ b/godot-cpp @@ -1 +1 @@ -Subproject commit 4e2411ad98089235eb90ac427354031b8aab70cc +Subproject commit 78ffea5b136f3178c31cddb28f6b963ceaa89420 From 1ed89791383ec91d9a1055eb198b3d07a34c956d Mon Sep 17 00:00:00 2001 From: Bill Doyle Date: Thu, 18 Jan 2024 12:32:40 -0500 Subject: [PATCH 03/26] Update openvr to 2.0.10 --- openvr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openvr b/openvr index 4c85abc..15f0838 160000 --- a/openvr +++ b/openvr @@ -1 +1 @@ -Subproject commit 4c85abcb7f7f1f02adaf3812018c99fc593bc341 +Subproject commit 15f0838a0487feb7da60acd39aab8099b994234c From 2af4250bd905c0db42686b6fcc673e0053dbba71 Mon Sep 17 00:00:00 2001 From: Bill Doyle Date: Thu, 18 Jan 2024 14:22:40 -0500 Subject: [PATCH 04/26] Add support for mingw and finding system libopenvr --- SConstruct | 76 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 52 insertions(+), 24 deletions(-) diff --git a/SConstruct b/SConstruct index a407ab7..0b0b063 100644 --- a/SConstruct +++ b/SConstruct @@ -5,22 +5,28 @@ import os customs = ['../custom.py'] opts = Variables(customs, ARGUMENTS) -# Gets the standart flags CC, CCX, etc. -env = Environment(ENV = os.environ) +# Gets the standard flags CC, CCX, etc. +env = Environment(ENV=os.environ) -# 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 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/'), + 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'), + 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" @@ -43,9 +49,34 @@ 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 + + if env['use_llvm']: + # untested + env.Append(CPPDEFINES=["WIN32", "_WIN32", "_WINDOWS", "_CRT_SECURE_NO_WARNINGS"]) + env.Append(CCFLAGS=["-W3", "-GR"]) + env.Append(CXXFLAGS=["-std:c++17"]) + if env['target'] in ('debug', 'd'): + env.Append(CCFLAGS = ['-fPIC', '-g3','-Og']) + else: + env.Append(CCFLAGS = ['-fPIC', '-g','-O3']) + + elif env['use_mingw']: + if env['bits'] == '64': + arch = 'x86_64' + elif env['bits'] == '32': + arch = 'i686' + + 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=['--static', '-Wl,--no-undefined', '-static-libgcc', '-static-libstdc++']) + + else: + # Preserve the environment so that scons can be executed from within Visual Studio and find the correct + # toolchain. env.Append(ENV = os.environ) env.Append(CPPDEFINES=["WIN32", "_WIN32", "_WINDOWS", "_CRT_SECURE_NO_WARNINGS", "TYPED_METHOD_BIND"]) @@ -57,15 +88,6 @@ if env['platform'] == 'windows': env.Append(LINKFLAGS = ['-DEBUG']) else: env.Append(CCFLAGS = ['-O2', '-EHsc', '-DNDEBUG', '-MD']) - else: - # untested - env.Append(CPPDEFINES=["WIN32", "_WIN32", "_WINDOWS", "_CRT_SECURE_NO_WARNINGS"]) - env.Append(CCFLAGS=["-W3", "-GR"]) - env.Append(CXXFLAGS=["-std:c++17"]) - if env['target'] in ('debug', 'd'): - env.Append(CCFLAGS = ['-fPIC', '-g3','-Og']) - else: - env.Append(CCFLAGS = ['-fPIC', '-g','-O3']) openvr_dll_target = env['target_path'] + "openvr_api.dll" openvr_dll_source = env['openvr_path'] + "bin/win" + str(env['bits']) + "/openvr_api.dll" @@ -107,7 +129,13 @@ 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. + env.ParseConfig('pkg-config openvr --cflags --libs') +elif (os.name == "nt" and os.getenv("VCINSTALLDIR")): env.Append(LIBPATH=[env['openvr_path'] + 'lib/' + platform_dir]) env.Append(LINKFLAGS=['openvr_api.lib']) else: From 66085c0aed253b6cb0ed0e26d728dc114626bead Mon Sep 17 00:00:00 2001 From: Bill Doyle Date: Thu, 18 Jan 2024 14:40:36 -0500 Subject: [PATCH 05/26] Update extension interface for 4.1+ --- .../godot-openvr/godot_openvr.gdextension | 1 + src/open_vr/openvr_data.h | 2 +- src/register_types.cpp | 40 +++++++++++-------- 3 files changed, 26 insertions(+), 17 deletions(-) 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/src/open_vr/openvr_data.h b/src/open_vr/openvr_data.h index 2c45617..4db0609 100644 --- a/src/open_vr/openvr_data.h +++ b/src/open_vr/openvr_data.h @@ -7,7 +7,7 @@ #include #include -#include +#include #include #include #include diff --git a/src/register_types.cpp b/src/register_types.cpp index bef6e75..3a454a7 100644 --- a/src/register_types.cpp +++ b/src/register_types.cpp @@ -6,7 +6,7 @@ #include "register_types.h" -#include +#include #include #include @@ -23,8 +23,12 @@ using namespace godot; Ref xr_interface_openvr; -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(); @@ -38,7 +42,11 @@ void register_types() { xr_server->add_interface(xr_interface_openvr); } -void unregister_types() { +void uninitialize_gdextension_types(ModuleInitializationLevel p_level) { + if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) { + return; + } + if (xr_interface_openvr.is_valid()) { if (xr_interface_openvr->is_initialized()) { xr_interface_openvr->uninitialize(); @@ -50,18 +58,18 @@ void unregister_types() { 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); - - return init_obj.init(); -} +extern "C" +{ + // Initialization + GDExtensionBool GDE_EXPORT example_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.register_terminator(uninitialize_gdextension_types); + init_obj.set_minimum_library_initialization_level(MODULE_INITIALIZATION_LEVEL_SCENE); + + return init_obj.init(); + } } From 5db5aa862b56e4280be3012584d519cebbe8d886 Mon Sep 17 00:00:00 2001 From: Bill Doyle Date: Thu, 18 Jan 2024 14:56:29 -0500 Subject: [PATCH 06/26] Update to current GDExtension and godot-cpp APIs This may not actually work yet, but it compiles. --- src/open_vr/OpenVRSkeleton.cpp | 2 +- src/open_vr/openvr_data.cpp | 55 ++++++++++++---------------------- src/register_types.cpp | 2 +- src/xr_interface_openvr.cpp | 22 ++++---------- src/xr_interface_openvr.h | 13 ++++---- 5 files changed, 32 insertions(+), 62 deletions(-) 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..64b94a1 100644 --- a/src/open_vr/openvr_data.cpp +++ b/src/open_vr/openvr_data.cpp @@ -226,45 +226,30 @@ bool openvr_data::initialise() { if (success) { OS *os = OS::get_singleton(); - Ref directory; - directory.instantiate(); + Ref directory = DirAccess::open("res://"); String exec_path = os->get_executable_path().get_base_dir().replace("\\", "/"); String manifest_path; - Array arr; - arr.push_back(String(exec_path)); - UtilityFunctions::print(String("Exec path: {0}").format(arr)); + UtilityFunctions::print(String("Exec path: ") + exec_path); // 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 + String("/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); - 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; - } - } - } + // 2) else check if we have an action folder in our project folder (custom user actions in development) + path = "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 = "addons/godot-openvr/actions/actions.json"; + if (directory->file_exists(path)) { + manifest_path = path; + } + } } if (manifest_path.length() != 0) { @@ -1284,13 +1269,11 @@ 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[0][1], p_matrix->m[0][2]), + Vector3(p_matrix->m[1][0], p_matrix->m[1][1], p_matrix->m[1][2]), + Vector3(p_matrix->m[2][0], p_matrix->m[2][1], 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/register_types.cpp b/src/register_types.cpp index 3a454a7..bb824ab 100644 --- a/src/register_types.cpp +++ b/src/register_types.cpp @@ -63,7 +63,7 @@ void uninitialize_gdextension_types(ModuleInitializationLevel p_level) { extern "C" { // Initialization - GDExtensionBool GDE_EXPORT example_library_init(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization) + 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); 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(); }; From 49b0ff737d5b667a2351c9f60986fbb0fbe89870 Mon Sep 17 00:00:00 2001 From: Bill Doyle Date: Thu, 18 Jan 2024 17:33:14 -0500 Subject: [PATCH 07/26] Finish getting it to compile against latest godot-cpp I've only tested building within the msys2 UCRT env for now. Forcing static linking for builtin_openvr=no isn't ideal but I'm not sure how to get the DLL path without assuming it's msys2 and not just somewhere that happens to have pkg-config. Building with an openvr submodule also works. --- README.md | 2 +- SConstruct | 24 ++++++++++++++++-------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index a7174c4..37c5e7f 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ Scons is used for compiling this module. I made the assumption that scons is ins You must compile `godot-cpp` first by executing: ``` cd godot-cpp -scons platform=windows target=release generate_bindings=yes bits=64 +scons platform=windows target=template_release generate_bindings=yes architecture=x86_64 cd .. ``` diff --git a/SConstruct b/SConstruct index 0b0b063..9fa3b83 100644 --- a/SConstruct +++ b/SConstruct @@ -13,6 +13,7 @@ opts.AddVariables( 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'), @@ -33,6 +34,11 @@ godot_cpp_library = "libgodot-cpp" # Updates the environment with the option variables. opts.Update(env) +if env['bits'] == '64': + arch = 'x86_64' +elif env['bits'] == '32': + arch = 'i686' + # Check some environment settings if env['use_llvm']: env['CXX'] = 'clang++' @@ -61,10 +67,6 @@ if env['platform'] == 'windows': env.Append(CCFLAGS = ['-fPIC', '-g','-O3']) elif env['use_mingw']: - if env['bits'] == '64': - arch = 'x86_64' - elif env['bits'] == '32': - arch = 'i686' env['CXX'] = f'{arch}-w64-mingw32-g++' env['AR'] = f'{arch}-w64-mingw32-ar' @@ -72,7 +74,7 @@ if env['platform'] == 'windows': env['LINK'] = f'{arch}-w64-mingw32-g++' env.Append(CCFLAGS=['-g', '-O3', '-std=c++17', '-Wwrite-strings']) - env.Append(LINKFLAGS=['--static', '-Wl,--no-undefined', '-static-libgcc', '-static-libstdc++']) + env.Append(LINKFLAGS=['-Wl,--no-undefined', '-static-libgcc', '-static-libstdc++']) else: # Preserve the environment so that scons can be executed from within Visual Studio and find the correct @@ -108,12 +110,12 @@ elif env['platform'] in ('x11', 'linux'): # Complete godot-cpp library path if env['target'] in ('debug', 'd'): - godot_cpp_library += '.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=[ @@ -134,7 +136,13 @@ 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 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']) From cc9ca9d60c81041e2abeae88a3b055dd29ed5697 Mon Sep 17 00:00:00 2001 From: Bill Doyle Date: Thu, 18 Jan 2024 18:06:00 -0500 Subject: [PATCH 08/26] Remove bundled godot-xr-tools Rather than get this up to date in here, just require it to be installed separately. --- .gitignore | 1 + README.md | 4 + 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 --- 42 files changed, 5 insertions(+), 2945 deletions(-) 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 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/README.md b/README.md index 37c5e7f..6b7d10b 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,10 @@ The godot_openvr.dll or libgodot_openvr.so file should be placed in the location 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 +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/). + 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. 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) From 9cf2581a8662cc61ac6670b61ae47019071b09c6 Mon Sep 17 00:00:00 2001 From: Bill Doyle Date: Thu, 18 Jan 2024 18:11:39 -0500 Subject: [PATCH 09/26] Get demo loading most of the way in 4.2 Lots of broken code, but the extension loads. --- demo/Main.gd | 2 +- demo/Main.tscn | 74 ++++++++++--------- .../addons/godot-openvr/OpenVRExportPlugin.gd | 13 ++-- 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 ++- .../godot-openvr/scenes/ovr_render_model.gd | 2 +- .../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/project.godot | 42 ++--------- 32 files changed, 230 insertions(+), 288 deletions(-) diff --git a/demo/Main.gd b/demo/Main.gd index 4892b9c..e7aa409 100644 --- a/demo/Main.gd +++ b/demo/Main.gd @@ -6,7 +6,7 @@ func _process(delta): 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(): 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/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/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/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/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/project.godot b/demo/project.godot index 5b68335..deb9c45 100644 --- a/demo/project.godot +++ b/demo/project.godot @@ -8,46 +8,16 @@ 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" [display] @@ -57,7 +27,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] From fcc0b181a259e64f466f8aef572ea9ba3e512a8f Mon Sep 17 00:00:00 2001 From: Bill Doyle Date: Thu, 18 Jan 2024 20:16:56 -0500 Subject: [PATCH 10/26] Fix getter names in ButtonStates I kind of guessed at these, I couldn't figure out where the old names were defined. --- demo/player/ButtonStates.gd | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/demo/player/ButtonStates.gd b/demo/player/ButtonStates.gd index 31fba78..fb529f8 100644 --- a/demo/player/ButtonStates.gd +++ b/demo/player/ButtonStates.gd @@ -12,19 +12,19 @@ func _ready(): # Called every frame. 'delta' is the elapsed time since the previous frame. 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") From b1d4adc637fc21bfc570f0dad7fea03fc47c7a86 Mon Sep 17 00:00:00 2001 From: Bill Doyle Date: Thu, 18 Jan 2024 21:07:59 -0500 Subject: [PATCH 11/26] Inherit overlay from SubViewport Viewport is abstract and we can't inherit from it in an extension. I'm not sure if this is the correct fix, but it was the only obvious path forward. --- src/open_vr/OpenVROverlay.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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; From 588de0cc4b74fd686a80cae866644516c0a5af4e Mon Sep 17 00:00:00 2001 From: Bill Doyle Date: Sun, 4 Feb 2024 18:53:05 -0500 Subject: [PATCH 12/26] Use patched openvr header when compiling with mingw This isn't really optimal, because the header name was just made up by the msys2 project. --- SConstruct | 1 + src/open_vr/openvr_data.h | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/SConstruct b/SConstruct index 9fa3b83..5d46e69 100644 --- a/SConstruct +++ b/SConstruct @@ -75,6 +75,7 @@ if env['platform'] == 'windows': env.Append(CCFLAGS=['-g', '-O3', '-std=c++17', '-Wwrite-strings']) env.Append(LINKFLAGS=['-Wl,--no-undefined', '-static-libgcc', '-static-libstdc++']) + env.Append(CPPDEFINES=["USE_OPENVR_MINGW_HEADER"]) else: # Preserve the environment so that scons can be executed from within Visual Studio and find the correct diff --git a/src/open_vr/openvr_data.h b/src/open_vr/openvr_data.h index 4db0609..bba549f 100644 --- a/src/open_vr/openvr_data.h +++ b/src/open_vr/openvr_data.h @@ -4,7 +4,13 @@ #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 From 3e6c3785382b50a13ac7e8f3ada8111a4bdb8daf Mon Sep 17 00:00:00 2001 From: Bill Doyle Date: Sun, 4 Feb 2024 18:57:17 -0500 Subject: [PATCH 13/26] Enable XR shaders in demo project --- demo/project.godot | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/demo/project.godot b/demo/project.godot index deb9c45..408b622 100644 --- a/demo/project.godot +++ b/demo/project.godot @@ -51,3 +51,7 @@ vulkan/rendering/back_end=1 xr/enabled=true quality/filters/msaa=1 environment/default_environment="res://default_env.tres" + +[xr] + +shaders/enabled=true From d12c32930a7a946b3ab82ac73b9e7a0b688e50de Mon Sep 17 00:00:00 2001 From: Bill Doyle Date: Sun, 4 Feb 2024 19:50:27 -0500 Subject: [PATCH 14/26] 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. --- demo/Main.gd | 4 +-- demo/addons/godot-openvr/EditorPlugin.gd | 17 ++++++++++ demo/addons/godot-openvr/openvr_autoloader.gd | 33 +++++++++++++++++++ demo/project.godot | 1 + src/register_types.cpp | 31 ++--------------- 5 files changed, 55 insertions(+), 31 deletions(-) create mode 100644 demo/addons/godot-openvr/openvr_autoloader.gd diff --git a/demo/Main.gd b/demo/Main.gd index e7aa409..3a6ad5c 100644 --- a/demo/Main.gd +++ b/demo/Main.gd @@ -10,9 +10,7 @@ func _process(delta): # 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/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/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/project.godot b/demo/project.godot index 408b622..fb11221 100644 --- a/demo/project.godot +++ b/demo/project.godot @@ -18,6 +18,7 @@ config/icon="res://icon.png" [autoload] XRToolsUserSettings="*res://addons/godot-xr-tools/user_settings/user_settings.gd" +OpenVRInterface="*res://addons/godot-openvr/openvr_autoloader.gd" [display] diff --git a/src/register_types.cpp b/src/register_types.cpp index bb824ab..9d8dab5 100644 --- a/src/register_types.cpp +++ b/src/register_types.cpp @@ -21,8 +21,9 @@ 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 initialize_gdextension_types(ModuleInitializationLevel p_level) { @@ -34,40 +35,14 @@ void initialize_gdextension_types(ModuleInitializationLevel p_level) 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 uninitialize_gdextension_types(ModuleInitializationLevel p_level) { - if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) { - return; - } - - 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(); - } } extern "C" { - // Initialization 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.register_terminator(uninitialize_gdextension_types); init_obj.set_minimum_library_initialization_level(MODULE_INITIALIZATION_LEVEL_SCENE); return init_obj.init(); From 7247f835f9fec37c867d0b7279fec462d68669bf Mon Sep 17 00:00:00 2001 From: Bill Doyle Date: Sun, 4 Feb 2024 20:39:26 -0500 Subject: [PATCH 15/26] Add openxr action map --- demo/openxr_action_map.tres | 885 ++++++++++++++++++++++++++++++++++++ 1 file changed, 885 insertions(+) create mode 100644 demo/openxr_action_map.tres 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")] From 60b56c2ab99b7e34e729c228c1add9179a36ef7b Mon Sep 17 00:00:00 2001 From: Bill Doyle Date: Mon, 5 Feb 2024 14:08:37 -0500 Subject: [PATCH 16/26] Fix accidentally-transposed transform matrix Messed up columns/rows when making this compile again. --- src/open_vr/openvr_data.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/open_vr/openvr_data.cpp b/src/open_vr/openvr_data.cpp index 64b94a1..2a68db0 100644 --- a/src/open_vr/openvr_data.cpp +++ b/src/open_vr/openvr_data.cpp @@ -1269,11 +1269,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; - ret.basis = Basis( - Vector3(p_matrix->m[0][0], p_matrix->m[0][1], p_matrix->m[0][2]), - Vector3(p_matrix->m[1][0], p_matrix->m[1][1], p_matrix->m[1][2]), - Vector3(p_matrix->m[2][0], p_matrix->m[2][1], p_matrix->m[2][2]) - ); + 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); From 725a8dcc93073aea6b366d73fc8254e3023f2349 Mon Sep 17 00:00:00 2001 From: Bill Doyle Date: Sun, 11 Feb 2024 22:41:39 -0500 Subject: [PATCH 17/26] Fix editor crash on overlay node creation There's no actual openvr connection in the editor, so stop trying to create the overlay there. --- src/open_vr/OpenVROverlay.cpp | 4 ++++ 1 file changed, 4 insertions(+) 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); From 463e496b4c5fab5067bb2251eddf38cd1945a95f Mon Sep 17 00:00:00 2001 From: Bill Doyle Date: Thu, 22 Feb 2024 18:18:46 -0500 Subject: [PATCH 18/26] Fix up action manifest loading Use res:// paths to find actions within the project, and use the proper globalizing function depending on whether we're running in the editor. --- src/open_vr/openvr_data.cpp | 38 +++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/src/open_vr/openvr_data.cpp b/src/open_vr/openvr_data.cpp index 2a68db0..7d9c3ed 100644 --- a/src/open_vr/openvr_data.cpp +++ b/src/open_vr/openvr_data.cpp @@ -226,34 +226,40 @@ bool openvr_data::initialise() { if (success) { OS *os = OS::get_singleton(); + 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; - UtilityFunctions::print(String("Exec path: ") + exec_path); - // check 3 locations in order // 1) check if we have an action folder alongside our executable (runtime deployed actions) - String path = exec_path + String("/actions/actions.json"); + String path = exec_path.path_join("actions/actions.json"); if (directory->file_exists(path)) { manifest_path = path; } else { - // 2) else check if we have an action folder in our project folder (custom user actions in development) - path = "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 = "addons/godot-openvr/actions/actions.json"; - if (directory->file_exists(path)) { - manifest_path = path; - } - } + // 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; + } + } } 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); From f6519e1a67f3201623dc95a991178b3d80a33ce2 Mon Sep 17 00:00:00 2001 From: Bill Doyle Date: Thu, 22 Feb 2024 19:56:05 -0500 Subject: [PATCH 19/26] Miscellaneous parameter cleanups in demo --- demo/Main.gd | 2 +- demo/player/ButtonStates.gd | 2 +- demo/player/HUD_Anchor.gd | 2 +- demo/player/left_hand_controller.gd | 9 --------- demo/player/right_controller.gd | 4 ++-- 5 files changed, 5 insertions(+), 14 deletions(-) delete mode 100644 demo/player/left_hand_controller.gd diff --git a/demo/Main.gd b/demo/Main.gd index 3a6ad5c..329799a 100644 --- a/demo/Main.gd +++ b/demo/Main.gd @@ -1,6 +1,6 @@ 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() diff --git a/demo/player/ButtonStates.gd b/demo/player/ButtonStates.gd index fb529f8..3bd14c0 100644 --- a/demo/player/ButtonStates.gd +++ b/demo/player/ButtonStates.gd @@ -10,7 +10,7 @@ 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_vector2("primary") $VBoxContainer/PrimaryJoyX/Value.value = 100.0 * primary.x 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); From 59566fb6367c08a014d5504384643eeacc7a7240 Mon Sep 17 00:00:00 2001 From: Bill Doyle Date: Sat, 24 Feb 2024 21:56:50 -0500 Subject: [PATCH 20/26] Default to static libc++ to match godot-cpp Didn't run into this earlier because I was forcing it static for all mingw builds, now both compilers are controlled by a new build variable. The name of the variable was chosen to match godot-cpp. As of this commit, building with MSVC appears to be fully working. It does produce a lot of type mismatch warnings which need to be investigated, I'm not sure if mingw is actually producing a different result or if it's just quieter about it. --- SConstruct | 44 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/SConstruct b/SConstruct index 5d46e69..a04e41e 100644 --- a/SConstruct +++ b/SConstruct @@ -6,9 +6,17 @@ customs = ['../custom.py'] opts = Variables(customs, ARGUMENTS) # Gets the standard flags CC, CCX, etc. +# +# TODO: Since OpenVR only officially works with binaries compiled by MSVC, we +# should enforce that we're not accidentally using mingw. SCons will fall back +# by default. If we defer tool loading by setting tools=[] here and changing +# them later after checking our build flags, we can use +# MSVC_NOTFOUND_POLICY='Error' to bail out if we're not using the expected +# compiler. env = Environment(ENV=os.environ) # Compilation options +# TODO: Use proper path manipulation functions so path variables don't force the user to specify the trailing slash. opts.AddVariables( EnumVariable('target', "Compilation target", 'release', ['d', 'debug', 'r', 'release']), EnumVariable('platform', "Compilation platform", 'windows', ['windows', 'x11', 'linux']), @@ -17,6 +25,7 @@ opts.AddVariables( 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']), ) @@ -41,8 +50,11 @@ elif env['bits'] == '32': # Check some environment settings if env['use_llvm']: + # TODO: Set tools['clang'] by deferring tool loading env['CXX'] = 'clang++' +debug = env['target'] in ('debug', 'd') + # platform dir for openvr libraries platform_dir = '' @@ -68,29 +80,44 @@ if env['platform'] == 'windows': elif env['use_mingw']: + # TODO: Set tools=['mingw'] by deferring tool loading 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', '-static-libgcc', '-static-libstdc++']) + env.Append(LINKFLAGS=['-Wl,--no-undefined']) env.Append(CPPDEFINES=["USE_OPENVR_MINGW_HEADER"]) + if env["use_static_cpp"]: + env.Append(LINKFLAGS=['-static', '-static-libgcc', '-static-libstdc++']) + else: # Preserve the environment so that scons can be executed from within Visual Studio and find the correct - # toolchain. + # toolchain. TODO: Why is this duplicated here? env.Append(ENV = os.environ) + 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 env['target'] in ('debug', 'd'): - env.Append(CPPDEFINES=["_DEBUG"]) - env.Append(CCFLAGS = ['-EHsc', '-MDd', '-ZI', '-FS']) + if debug: + env.Append(CCFLAGS = ['-EHsc', '-ZI', '-FS']) env.Append(LINKFLAGS = ['-DEBUG']) else: - env.Append(CCFLAGS = ['-O2', '-EHsc', '-DNDEBUG', '-MD']) + env.Append(CCFLAGS = ['-O2', '-EHsc', '-DNDEBUG']) + + runtime_debug = 'd' if debug else '' + if env["use_static_cpp"]: + env.Append(CCFLAGS=["-MT" + runtime_debug]) + else: + env.Append(CCFLAGS=["-MD" + runtime_debug]) openvr_dll_target = env['target_path'] + "openvr_api.dll" openvr_dll_source = env['openvr_path'] + "bin/win" + str(env['bits']) + "/openvr_api.dll" @@ -110,7 +137,7 @@ 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'): +if debug: godot_cpp_library += '.template_debug' env.Append(CPPDEFINES=["DEBUG_ENABLED", "DEBUG_METHODS_ENABLED"]) else: @@ -139,6 +166,7 @@ if not env['builtin_openvr']: # 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']) @@ -157,7 +185,7 @@ 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" From 59e531be94eff1f79461e985a8f565b7a04913db Mon Sep 17 00:00:00 2001 From: Bill Doyle Date: Sun, 25 Feb 2024 12:00:20 -0500 Subject: [PATCH 21/26] Update README Document new build flags (and old), remove old context about updates within the Godot 3.x train and old OpenVR, update example GDScript. I also added a lot of notes about requirements for successfully building with mingw/msys2. --- README.md | 201 +++++++++++++++++++++++------------------------------- 1 file changed, 87 insertions(+), 114 deletions(-) diff --git a/README.md b/README.md index 6b7d10b..c91f5d0 100644 --- a/README.md +++ b/README.md @@ -9,80 +9,75 @@ 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=template_release generate_bindings=yes architecture=x86_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` or `linux`. +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: -Running the demo ----------------- +* `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. -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: @@ -90,105 +85,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. @@ -198,8 +172,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: From cf918c07e98dc0c418fd04f3875fa1116753e776 Mon Sep 17 00:00:00 2001 From: Bill Doyle Date: Mon, 26 Feb 2024 20:58:52 -0500 Subject: [PATCH 22/26] Clean up most build TODOs with deferred tool initialization. Building with mingw while MSVC is installed didn't actually work because SCons generates the incorrect arguments. The easiest fix was just to do these TODOs now. --- SConstruct | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/SConstruct b/SConstruct index a04e41e..dcba214 100644 --- a/SConstruct +++ b/SConstruct @@ -5,15 +5,9 @@ import os customs = ['../custom.py'] opts = Variables(customs, ARGUMENTS) -# Gets the standard flags CC, CCX, etc. -# -# TODO: Since OpenVR only officially works with binaries compiled by MSVC, we -# should enforce that we're not accidentally using mingw. SCons will fall back -# by default. If we defer tool loading by setting tools=[] here and changing -# them later after checking our build flags, we can use -# MSVC_NOTFOUND_POLICY='Error' to bail out if we're not using the expected -# compiler. -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=[]) # Compilation options # TODO: Use proper path manipulation functions so path variables don't force the user to specify the trailing slash. @@ -25,7 +19,7 @@ opts.AddVariables( 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)), + BoolVariable("use_static_cpp", "Link MinGW/MSVC C++ runtime libraries statically", True), EnumVariable('bits', "CPU architecture", '64', ['32', '64']), ) @@ -48,11 +42,6 @@ if env['bits'] == '64': elif env['bits'] == '32': arch = 'i686' -# Check some environment settings -if env['use_llvm']: - # TODO: Set tools['clang'] by deferring tool loading - env['CXX'] = 'clang++' - debug = env['target'] in ('debug', 'd') # platform dir for openvr libraries @@ -70,6 +59,7 @@ if env['platform'] == 'windows': 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"]) @@ -79,8 +69,7 @@ if env['platform'] == 'windows': env.Append(CCFLAGS = ['-fPIC', '-g','-O3']) elif env['use_mingw']: - - # TODO: Set tools=['mingw'] by deferring tool loading + env.Tool('mingw') env['CXX'] = f'{arch}-w64-mingw32-g++' env['AR'] = f'{arch}-w64-mingw32-ar' env['RANLIB'] = f'{arch}-w64-mingw32-ranlib' @@ -94,9 +83,14 @@ if env['platform'] == 'windows': env.Append(LINKFLAGS=['-static', '-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 this duplicated here? - env.Append(ENV = os.environ) + # 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" From 4e7cee98f017938e53d60600d489c8292127d517 Mon Sep 17 00:00:00 2001 From: Bill Doyle Date: Fri, 1 Mar 2024 21:23:13 -0500 Subject: [PATCH 23/26] Remove CRT debug flag to match godot and godot-cpp Godot has a debug_crt flag to put this back, but it conflicts with use_static_cpp so just punting until someone needs it. --- SConstruct | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/SConstruct b/SConstruct index dcba214..682f729 100644 --- a/SConstruct +++ b/SConstruct @@ -107,11 +107,10 @@ if env['platform'] == 'windows': else: env.Append(CCFLAGS = ['-O2', '-EHsc', '-DNDEBUG']) - runtime_debug = 'd' if debug else '' if env["use_static_cpp"]: - env.Append(CCFLAGS=["-MT" + runtime_debug]) + env.Append(CCFLAGS=["-MT"]) else: - env.Append(CCFLAGS=["-MD" + runtime_debug]) + 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" From af07c5f8928d56f576853ba2f1b26a0c2a9e2caa Mon Sep 17 00:00:00 2001 From: Bill Doyle Date: Fri, 1 Mar 2024 22:50:08 -0500 Subject: [PATCH 24/26] Fix up formatting in register_types --- src/register_types.cpp | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/register_types.cpp b/src/register_types.cpp index 9d8dab5..c3a2219 100644 --- a/src/register_types.cpp +++ b/src/register_types.cpp @@ -25,8 +25,7 @@ using namespace godot; // server here. Instead, we register an autoload singleton ourselves in // EditorPlugin.cpp. -void initialize_gdextension_types(ModuleInitializationLevel p_level) -{ +void initialize_gdextension_types(ModuleInitializationLevel p_level) { if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) { return; } @@ -37,14 +36,12 @@ void initialize_gdextension_types(ModuleInitializationLevel p_level) ClassDB::register_class(); } -extern "C" -{ - 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); +extern "C" { +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(); - } + return init_obj.init(); +} } From 67175f6b062d4cca7180f1d59c1e356b16869fc7 Mon Sep 17 00:00:00 2001 From: Bill Doyle Date: Tue, 23 Apr 2024 22:08:39 -0400 Subject: [PATCH 25/26] Fix linux built by setting default tool --- SConstruct | 1 + 1 file changed, 1 insertion(+) diff --git a/SConstruct b/SConstruct index 682f729..acdfa68 100644 --- a/SConstruct +++ b/SConstruct @@ -116,6 +116,7 @@ if env['platform'] == 'windows': openvr_dll_source = env['openvr_path'] + "bin/win" + str(env['bits']) + "/openvr_api.dll" elif env['platform'] in ('x11', 'linux'): + env.Tool('default') env['target_path'] += 'x11/' godot_cpp_library += '.linux' platform_dir = 'linux' + str(env['bits']) From 80e9e45d76c1ae7f7740b5b7d28a46d0f03a9b5a Mon Sep 17 00:00:00 2001 From: Bill Doyle Date: Tue, 23 Apr 2024 21:07:55 -0400 Subject: [PATCH 26/26] Update github workflow - Update scons to 4.x - Bump github action versions to eliminate node 12 deprecation warning. v4 of the asset actions contains breaking changes, so I stopped at v3 for now. - Combine build steps to be platform-agnostic where possible. - Remove dead macOS config - Add TODOs for outstanding tech debt --- .github/workflows/build-on-push.yml | 88 ++++++++++------------------- .github/workflows/static_checks.yml | 2 +- 2 files changed, 30 insertions(+), 60 deletions(-) diff --git a/.github/workflows/build-on-push.yml b/.github/workflows/build-on-push.yml index 7bf7138..5d003d7 100644 --- a/.github/workflows/build-on-push.yml +++ b/.github/workflows/build-on-push.yml @@ -1,15 +1,13 @@ - -# Workflow to automatically compile a Linux/Windows/OSX library on commit/push name: Build on push +# TODO: Update asset actions from v3 to v4. There are breaking changes, need to verify that our config will still work. +# 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,57 +19,37 @@ 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 + sudo apt-get update -qq + sudo apt-get install -qqq build-essential pkg-config if: matrix.os == 'ubuntu-20.04' - - 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 + - name: Upload build files (artifacts) (Linux) + uses: actions/upload-artifact@v3 with: name: build-files-linux path: | @@ -79,23 +57,15 @@ jobs: openvr/bin/linux64/libopenvr_api.so if: matrix.os == 'ubuntu-20.04' - # - 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 build files (artifacts) (Windows) + uses: actions/upload-artifact@v3 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' + # This job collects the build output and assembles the final asset (artifact) asset: name: Assembling the asset (artifact) @@ -105,12 +75,12 @@ jobs: # 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' path: godot_openvr - name: Download all workflow run artifacts - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 - name: Copy files to destination run: | mkdir godot_openvr_plugin @@ -118,8 +88,6 @@ jobs: 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 - name: Calculate GIT short ref @@ -135,7 +103,6 @@ jobs: - 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 }} @@ -151,6 +118,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 +135,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: |