add vr template project

This commit is contained in:
Guillaume Vern
2025-10-08 11:10:13 +02:00
parent 2cda32f24c
commit 97f183e59f
613 changed files with 37826 additions and 1499 deletions
+17
View File
@@ -0,0 +1,17 @@
The Hand Mesh was made using the Makehuman Community Edition
It was slightly modified inside Blender 3D and textured inside Substance Painter
If there should be concerns regarding License issues
https://github.com/makehumancommunity/makehuman/blob/master/LICENSE.md
under point D of the makehuman communtiy edition license
https://github.com/makehumancommunity/makehuman/blob/master/LICENSE.md#d-concerning-the-output-from-makehuman
As the assets have been released under CC0, there is no limitation on what you can do with this combined output.
The MakeHuman project makes no claim whatsoever over output such as:
Exports to files (FBX, OBJ, DAE, MHX2...)
Exports via direct integration (import via MPFB)
Graphical data generated via scripting or plugins
Renderings
Screenshots
Saved model files
+126
View File
@@ -0,0 +1,126 @@
To the extent possible under law, DigitalN8m4r3 aka Miodrag Sejic
has waived all copyright and related or neighboring rights to Hand Models for the Godot XR Tools.
This work is published from: Austria.
Date: 7th November 2022
Creative Commons Legal Code
CC0 1.0 Universal
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
HEREUNDER.
Statement of Purpose
The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator
and subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").
Certain owners wish to permanently relinquish those rights to a Work for
the purpose of contributing to a commons of creative, cultural and
scientific works ("Commons") that the public can reliably and without fear
of later claims of infringement build upon, modify, incorporate in other
works, reuse and redistribute as freely as possible in any form whatsoever
and for any purposes, including without limitation commercial purposes.
These owners may contribute to the Commons to promote the ideal of a free
culture and the further production of creative, cultural and scientific
works, or to gain reputation or greater distribution for their Work in
part through the use and efforts of others.
For these and/or other purposes and motivations, and without any
expectation of additional consideration or compensation, the person
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
is an owner of Copyright and Related Rights in the Work, voluntarily
elects to apply CC0 to the Work and publicly distribute the Work under its
terms, with knowledge of his or her Copyright and Related Rights in the
Work and the meaning and intended legal effect of CC0 on those rights.
1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not
limited to, the following:
i. the right to reproduce, adapt, distribute, perform, display,
communicate, and translate a Work;
ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person's image or
likeness depicted in a Work;
iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;
v. rights protecting the extraction, dissemination, use and reuse of data
in a Work;
vi. database rights (such as those arising under Directive 96/9/EC of the
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation
thereof, including any amended or successor version of such
directive); and
vii. other similar, equivalent or corresponding rights throughout the
world based on applicable law or treaty, and any national
implementations thereof.
2. Waiver. To the greatest extent permitted by, but not in contravention
of, applicable law, Affirmer hereby overtly, fully, permanently,
irrevocably and unconditionally waives, abandons, and surrenders all of
Affirmer's Copyright and Related Rights and associated claims and causes
of action, whether now known or unknown (including existing as well as
future claims and causes of action), in the Work (i) in all territories
worldwide, (ii) for the maximum duration provided by applicable law or
treaty (including future time extensions), (iii) in any current or future
medium and for any number of copies, and (iv) for any purpose whatsoever,
including without limitation commercial, advertising or promotional
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
member of the public at large and to the detriment of Affirmer's heirs and
successors, fully intending that such Waiver shall not be subject to
revocation, rescission, cancellation, termination, or any other legal or
equitable action to disrupt the quiet enjoyment of the Work by the public
as contemplated by Affirmer's express Statement of Purpose.
3. Public License Fallback. Should any part of the Waiver for any reason
be judged legally invalid or ineffective under applicable law, then the
Waiver shall be preserved to the maximum extent permitted taking into
account Affirmer's express Statement of Purpose. In addition, to the
extent the Waiver is so judged Affirmer hereby grants to each affected
person a royalty-free, non transferable, non sublicensable, non exclusive,
irrevocable and unconditional license to exercise Affirmer's Copyright and
Related Rights in the Work (i) in all territories worldwide, (ii) for the
maximum duration provided by applicable law or treaty (including future
time extensions), (iii) in any current or future medium and for any number
of copies, and (iv) for any purpose whatsoever, including without
limitation commercial, advertising or promotional purposes (the
"License"). The License shall be deemed effective as of the date CC0 was
applied by Affirmer to the Work. Should any part of the License for any
reason be judged legally invalid or ineffective under applicable law, such
partial invalidity or ineffectiveness shall not invalidate the remainder
of the License, and in such case Affirmer hereby affirms that he or she
will not (i) exercise any of his or her remaining Copyright and Related
Rights in the Work or (ii) assert any associated claims and causes of
action with respect to the Work, in either case contrary to Affirmer's
express Statement of Purpose.
4. Limitations and Disclaimers.
a. No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document.
b. Affirmer offers the Work as-is and makes no representations or
warranties of any kind concerning the Work, express, implied,
statutory or otherwise, including without limitation warranties of
title, merchantability, fitness for a particular purpose, non
infringement, or the absence of latent or other defects, accuracy, or
the present or absence of errors, whether or not discoverable, all to
the greatest extent permissible under applicable law.
c. Affirmer disclaims responsibility for clearing rights of other persons
that may apply to the Work or any use thereof, including without
limitation any person's Copyright and Related Rights in the Work.
Further, Affirmer disclaims responsibility for obtaining any necessary
consents, permissions or other rights required for any use of the
Work.
d. Affirmer understands and acknowledges that Creative Commons is not a
party to this document and has no duty or obligation with respect to
this CC0 or use of the Work.
@@ -0,0 +1,81 @@
[gd_scene load_steps=37 format=3 uid="uid://the6y7swe6j0"]
[ext_resource type="Animation" uid="uid://dgfeikrugfewi" path="res://addons/godot-xr-tools/hands/animations/left/Cup.res" id="1_7svyl"]
[ext_resource type="Animation" uid="uid://dlxa6f6hwurka" path="res://addons/godot-xr-tools/hands/animations/left/Default pose.res" id="2_ykhfd"]
[ext_resource type="Animation" uid="uid://dqa0h82y3qn1t" path="res://addons/godot-xr-tools/hands/animations/left/Grip 1.res" id="3_y80ds"]
[ext_resource type="Animation" uid="uid://di384xtde8ydf" path="res://addons/godot-xr-tools/hands/animations/left/Grip 2.res" id="4_1nbr8"]
[ext_resource type="Animation" uid="uid://dd67rufxwj2u" path="res://addons/godot-xr-tools/hands/animations/left/Grip 3.res" id="5_28lp1"]
[ext_resource type="Animation" uid="uid://db62hs5s4n2b3" path="res://addons/godot-xr-tools/hands/animations/left/Grip 4.res" id="6_uj648"]
[ext_resource type="Animation" uid="uid://bediglpx0rj7i" path="res://addons/godot-xr-tools/hands/animations/left/Grip 5.res" id="7_yxjeh"]
[ext_resource type="Animation" uid="uid://nq3xh1olqipq" path="res://addons/godot-xr-tools/hands/animations/left/Grip Shaft.res" id="8_i0ro5"]
[ext_resource type="Animation" uid="uid://plad1r85f7ws" path="res://addons/godot-xr-tools/hands/animations/left/Grip.res" id="9_811qe"]
[ext_resource type="Animation" uid="uid://bi1l6lre2w2lp" path="res://addons/godot-xr-tools/hands/animations/left/Hold.res" id="10_o5u3q"]
[ext_resource type="Animation" uid="uid://c3e6h0rv2uw2d" path="res://addons/godot-xr-tools/hands/animations/left/Horns.res" id="11_i2b8g"]
[ext_resource type="Animation" uid="uid://dfekure1r6q13" path="res://addons/godot-xr-tools/hands/animations/left/Metal.res" id="12_yoig6"]
[ext_resource type="Animation" uid="uid://b0rhk4r0r0t32" path="res://addons/godot-xr-tools/hands/animations/left/Middle.res" id="13_kvhwh"]
[ext_resource type="Animation" uid="uid://f5k0gh4qnmv5" path="res://addons/godot-xr-tools/hands/animations/left/OK.res" id="14_ofab3"]
[ext_resource type="Animation" uid="uid://1nlkfvitq7ku" path="res://addons/godot-xr-tools/hands/animations/left/Peace.res" id="15_a4q3y"]
[ext_resource type="Animation" uid="uid://dhjb0e334tfwl" path="res://addons/godot-xr-tools/hands/animations/left/Pinch Flat.res" id="16_ixe2d"]
[ext_resource type="Animation" uid="uid://dkjsnihi81b7p" path="res://addons/godot-xr-tools/hands/animations/left/Pinch Large.res" id="17_oifug"]
[ext_resource type="Animation" uid="uid://bn0fdhe2jwq3h" path="res://addons/godot-xr-tools/hands/animations/left/Pinch Middle.res" id="18_2ic2e"]
[ext_resource type="Animation" uid="uid://bo1b8w0s4ci81" path="res://addons/godot-xr-tools/hands/animations/left/Pinch Ring.res" id="19_4a8v4"]
[ext_resource type="Animation" uid="uid://m5x2m8x3tcel" path="res://addons/godot-xr-tools/hands/animations/left/Pinch Tight.res" id="20_ugc01"]
[ext_resource type="Animation" uid="uid://fi23m6i7orhw" path="res://addons/godot-xr-tools/hands/animations/left/Pinch Up.res" id="21_l3kgg"]
[ext_resource type="Animation" uid="uid://c8qmcuyaltdnw" path="res://addons/godot-xr-tools/hands/animations/left/PingPong.res" id="22_j83er"]
[ext_resource type="Animation" uid="uid://bqnoubqq7ogwu" path="res://addons/godot-xr-tools/hands/animations/left/Pinky.res" id="23_sm4sd"]
[ext_resource type="Animation" uid="uid://ddbo6ioa282en" path="res://addons/godot-xr-tools/hands/animations/left/Pistol.res" id="24_r4kss"]
[ext_resource type="Animation" uid="uid://brkptjihht3ae" path="res://addons/godot-xr-tools/hands/animations/left/Ring.res" id="25_2ncut"]
[ext_resource type="Animation" uid="uid://cnng6xumhw7cx" path="res://addons/godot-xr-tools/hands/animations/left/Rounded.res" id="26_02lfv"]
[ext_resource type="Animation" uid="uid://cevirj0eagdrq" path="res://addons/godot-xr-tools/hands/animations/left/Sign 1.res" id="27_o5si3"]
[ext_resource type="Animation" uid="uid://cc6phxovf1ban" path="res://addons/godot-xr-tools/hands/animations/left/Sign 2.res" id="28_ble5k"]
[ext_resource type="Animation" uid="uid://ohthjp8qbcc4" path="res://addons/godot-xr-tools/hands/animations/left/Sign 3.res" id="29_twq1x"]
[ext_resource type="Animation" uid="uid://dmx42g64577g5" path="res://addons/godot-xr-tools/hands/animations/left/Sign 4.res" id="30_eyeuv"]
[ext_resource type="Animation" uid="uid://dhsoxntrktx0p" path="res://addons/godot-xr-tools/hands/animations/left/Sign 5.res" id="31_50jrs"]
[ext_resource type="Animation" uid="uid://c0u2a3yc2vhg8" path="res://addons/godot-xr-tools/hands/animations/left/Sign_Point.res" id="32_7v122"]
[ext_resource type="Animation" uid="uid://4g211my0hoiw" path="res://addons/godot-xr-tools/hands/animations/left/Straight.res" id="33_m3lif"]
[ext_resource type="Animation" uid="uid://d06l7hygl4qt3" path="res://addons/godot-xr-tools/hands/animations/left/Surfer.res" id="34_b3p10"]
[ext_resource type="Animation" uid="uid://bxei4oebd4hu3" path="res://addons/godot-xr-tools/hands/animations/left/Thumb.res" id="35_huikq"]
[sub_resource type="AnimationLibrary" id="AnimationLibrary_kw48d"]
_data = {
"Cup": ExtResource("1_7svyl"),
"Default pose": ExtResource("2_ykhfd"),
"Grip": ExtResource("9_811qe"),
"Grip 1": ExtResource("3_y80ds"),
"Grip 2": ExtResource("4_1nbr8"),
"Grip 3": ExtResource("5_28lp1"),
"Grip 4": ExtResource("6_uj648"),
"Grip 5": ExtResource("7_yxjeh"),
"Grip Shaft": ExtResource("8_i0ro5"),
"Hold": ExtResource("10_o5u3q"),
"Horns": ExtResource("11_i2b8g"),
"Metal": ExtResource("12_yoig6"),
"Middle": ExtResource("13_kvhwh"),
"OK": ExtResource("14_ofab3"),
"Peace": ExtResource("15_a4q3y"),
"Pinch Flat": ExtResource("16_ixe2d"),
"Pinch Large": ExtResource("17_oifug"),
"Pinch Middle": ExtResource("18_2ic2e"),
"Pinch Ring": ExtResource("19_4a8v4"),
"Pinch Tight": ExtResource("20_ugc01"),
"Pinch Up": ExtResource("21_l3kgg"),
"PingPong": ExtResource("22_j83er"),
"Pinky": ExtResource("23_sm4sd"),
"Pistol": ExtResource("24_r4kss"),
"Ring": ExtResource("25_2ncut"),
"Rounded": ExtResource("26_02lfv"),
"Sign 1": ExtResource("27_o5si3"),
"Sign 2": ExtResource("28_ble5k"),
"Sign 3": ExtResource("29_twq1x"),
"Sign 4": ExtResource("30_eyeuv"),
"Sign 5": ExtResource("31_50jrs"),
"Sign_Point": ExtResource("32_7v122"),
"Straight": ExtResource("33_m3lif"),
"Surfer": ExtResource("34_b3p10"),
"Thumb": ExtResource("35_huikq")
}
[node name="AnimationPlayer" type="AnimationPlayer"]
libraries = {
"": SubResource("AnimationLibrary_kw48d")
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,32 @@
[gd_resource type="AnimationNodeBlendTree" load_steps=6 format=3 uid="uid://dl8yf7ipqotd1"]
[sub_resource type="AnimationNodeAnimation" id="1"]
animation = &"Grip"
[sub_resource type="AnimationNodeAnimation" id="2"]
animation = &"Grip"
[sub_resource type="AnimationNodeBlend2" id="3"]
filter_enabled = true
filters = ["Armature/Skeleton3D:Little_Distal_L", "Armature/Skeleton3D:Little_Intermediate_L", "Armature/Skeleton3D:Little_Metacarpal_L", "Armature/Skeleton3D:Little_Proximal_L", "Armature/Skeleton3D:Middle_Distal_L", "Armature/Skeleton3D:Middle_Intermediate_L", "Armature/Skeleton3D:Middle_Metacarpal_L", "Armature/Skeleton3D:Middle_Proximal_L", "Armature/Skeleton3D:Ring_Distal_L", "Armature/Skeleton3D:Ring_Intermediate_L", "Armature/Skeleton3D:Ring_Metacarpal_L", "Armature/Skeleton3D:Ring_Proximal_L", "Armature/Skeleton3D:Thumb_Distal_L", "Armature/Skeleton3D:Thumb_Metacarpal_L", "Armature/Skeleton3D:Thumb_Proximal_L", "Armature/Skeleton:Little_Distal_L", "Armature/Skeleton:Little_Intermediate_L", "Armature/Skeleton:Little_Proximal_L", "Armature/Skeleton:Middle_Distal_L", "Armature/Skeleton:Middle_Intermediate_L", "Armature/Skeleton:Middle_Proximal_L", "Armature/Skeleton:Ring_Distal_L", "Armature/Skeleton:Ring_Intermediate_L", "Armature/Skeleton:Ring_Proximal_L", "Armature/Skeleton:Thumb_Distal_L", "Armature/Skeleton:Thumb_Proximal_L"]
[sub_resource type="AnimationNodeAnimation" id="4"]
animation = &"Grip 5"
[sub_resource type="AnimationNodeBlend2" id="5"]
filter_enabled = true
filters = ["Armature/Skeleton3D:Index_Distal_L", "Armature/Skeleton3D:Index_Intermediate_L", "Armature/Skeleton3D:Index_Metacarpal_L", "Armature/Skeleton3D:Index_Proximal_L", "Armature/Skeleton:Index_Distal_L", "Armature/Skeleton:Index_Intermediate_L", "Armature/Skeleton:Index_Proximal_L"]
[resource]
graph_offset = Vector2(-536, 11)
nodes/ClosedHand1/node = SubResource("1")
nodes/ClosedHand1/position = Vector2(-600, 300)
nodes/ClosedHand2/node = SubResource("2")
nodes/ClosedHand2/position = Vector2(-360, 300)
nodes/Grip/node = SubResource("3")
nodes/Grip/position = Vector2(0, 20)
nodes/OpenHand/node = SubResource("4")
nodes/OpenHand/position = Vector2(-600, 100)
nodes/Trigger/node = SubResource("5")
nodes/Trigger/position = Vector2(-360, 20)
node_connections = [&"output", 0, &"Grip", &"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1"]
@@ -0,0 +1,81 @@
[gd_scene load_steps=37 format=3 uid="uid://bxipj7hyjwy6f"]
[ext_resource type="Animation" uid="uid://do01jton6rk42" path="res://addons/godot-xr-tools/hands/animations/right/Cup.res" id="1_mq7eu"]
[ext_resource type="Animation" uid="uid://ky28birj4su6" path="res://addons/godot-xr-tools/hands/animations/right/Default pose.res" id="2_kxlaj"]
[ext_resource type="Animation" uid="uid://daqddcrbpam0c" path="res://addons/godot-xr-tools/hands/animations/right/Grip 1.res" id="3_5xubn"]
[ext_resource type="Animation" uid="uid://r8hleealhrqt" path="res://addons/godot-xr-tools/hands/animations/right/Grip 2.res" id="4_y3ovo"]
[ext_resource type="Animation" uid="uid://rs7vpclot07o" path="res://addons/godot-xr-tools/hands/animations/right/Grip 3.res" id="5_0d4pg"]
[ext_resource type="Animation" uid="uid://d1xnpyc08njjx" path="res://addons/godot-xr-tools/hands/animations/right/Grip 4.res" id="6_nabm2"]
[ext_resource type="Animation" uid="uid://s1vqcxyqcvea" path="res://addons/godot-xr-tools/hands/animations/right/Grip 5.res" id="7_gy2yb"]
[ext_resource type="Animation" uid="uid://c8dghcftg1thx" path="res://addons/godot-xr-tools/hands/animations/right/Grip Shaft.res" id="8_ffwxq"]
[ext_resource type="Animation" uid="uid://ccds2u22gbxn7" path="res://addons/godot-xr-tools/hands/animations/right/Grip.res" id="9_y16mo"]
[ext_resource type="Animation" uid="uid://bv5tuc1kjv0k5" path="res://addons/godot-xr-tools/hands/animations/right/Hold.res" id="10_g8e21"]
[ext_resource type="Animation" uid="uid://cdjfhqnr4n2mr" path="res://addons/godot-xr-tools/hands/animations/right/Horns.res" id="11_b3lks"]
[ext_resource type="Animation" uid="uid://b1kqsodcr1til" path="res://addons/godot-xr-tools/hands/animations/right/Metal.res" id="12_p14fk"]
[ext_resource type="Animation" uid="uid://cg6fsqb2iuuih" path="res://addons/godot-xr-tools/hands/animations/right/Middle.res" id="13_4i278"]
[ext_resource type="Animation" uid="uid://c3isimdlxg54a" path="res://addons/godot-xr-tools/hands/animations/right/OK.res" id="14_qk7tg"]
[ext_resource type="Animation" uid="uid://bxmc3vlfih764" path="res://addons/godot-xr-tools/hands/animations/right/Peace.res" id="15_ejppt"]
[ext_resource type="Animation" uid="uid://dg4v7rqiaje2h" path="res://addons/godot-xr-tools/hands/animations/right/Pinch Flat.res" id="16_7cyln"]
[ext_resource type="Animation" uid="uid://cuwwpxi44vwpm" path="res://addons/godot-xr-tools/hands/animations/right/Pinch Large.res" id="17_amtgc"]
[ext_resource type="Animation" uid="uid://c6vghurk7t5yb" path="res://addons/godot-xr-tools/hands/animations/right/Pinch Middle.res" id="18_pnqcq"]
[ext_resource type="Animation" uid="uid://mjotm5uukoo3" path="res://addons/godot-xr-tools/hands/animations/right/Pinch Ring.res" id="19_aeaff"]
[ext_resource type="Animation" uid="uid://ca21ej1p3g2yt" path="res://addons/godot-xr-tools/hands/animations/right/Pinch Tight.res" id="20_mghnf"]
[ext_resource type="Animation" uid="uid://cseojxi8rrqc" path="res://addons/godot-xr-tools/hands/animations/right/Pinch Up.res" id="21_1v6tw"]
[ext_resource type="Animation" uid="uid://c8hn123uon74u" path="res://addons/godot-xr-tools/hands/animations/right/PingPong.res" id="22_ueac0"]
[ext_resource type="Animation" uid="uid://b6ra3rqia1gvb" path="res://addons/godot-xr-tools/hands/animations/right/Pinky.res" id="23_7vyi4"]
[ext_resource type="Animation" uid="uid://csp3fdknowmi5" path="res://addons/godot-xr-tools/hands/animations/right/Pistol.res" id="24_nc600"]
[ext_resource type="Animation" uid="uid://2ttepgvf634h" path="res://addons/godot-xr-tools/hands/animations/right/Ring.res" id="25_20nj0"]
[ext_resource type="Animation" uid="uid://wcwa3p1qrhwr" path="res://addons/godot-xr-tools/hands/animations/right/Rounded.res" id="26_648rb"]
[ext_resource type="Animation" uid="uid://bcwx6a6mhsoj2" path="res://addons/godot-xr-tools/hands/animations/right/Sign 1.res" id="27_liq3y"]
[ext_resource type="Animation" uid="uid://btnsp36fjkldf" path="res://addons/godot-xr-tools/hands/animations/right/Sign 2.res" id="28_vdv8x"]
[ext_resource type="Animation" uid="uid://c35i6glt1ov2m" path="res://addons/godot-xr-tools/hands/animations/right/Sign 3.res" id="29_uairn"]
[ext_resource type="Animation" uid="uid://b8mmk2ufmlyf" path="res://addons/godot-xr-tools/hands/animations/right/Sign 4.res" id="30_351lm"]
[ext_resource type="Animation" uid="uid://ddgl3lsnlfiny" path="res://addons/godot-xr-tools/hands/animations/right/Sign 5.res" id="31_o4yst"]
[ext_resource type="Animation" uid="uid://ccy3e7a0hvxyl" path="res://addons/godot-xr-tools/hands/animations/right/Sign_Point.res" id="32_02kj7"]
[ext_resource type="Animation" uid="uid://d3h36bkauutoq" path="res://addons/godot-xr-tools/hands/animations/right/Straight.res" id="33_gpxgh"]
[ext_resource type="Animation" uid="uid://bq7cjxdn28jcv" path="res://addons/godot-xr-tools/hands/animations/right/Surfer.res" id="34_ldn4j"]
[ext_resource type="Animation" uid="uid://d2ukhr3n2r1u8" path="res://addons/godot-xr-tools/hands/animations/right/Thumb.res" id="35_xnxq3"]
[sub_resource type="AnimationLibrary" id="AnimationLibrary_reqae"]
_data = {
"Cup": ExtResource("1_mq7eu"),
"Default pose": ExtResource("2_kxlaj"),
"Grip": ExtResource("9_y16mo"),
"Grip 1": ExtResource("3_5xubn"),
"Grip 2": ExtResource("4_y3ovo"),
"Grip 3": ExtResource("5_0d4pg"),
"Grip 4": ExtResource("6_nabm2"),
"Grip 5": ExtResource("7_gy2yb"),
"Grip Shaft": ExtResource("8_ffwxq"),
"Hold": ExtResource("10_g8e21"),
"Horns": ExtResource("11_b3lks"),
"Metal": ExtResource("12_p14fk"),
"Middle": ExtResource("13_4i278"),
"OK": ExtResource("14_qk7tg"),
"Peace": ExtResource("15_ejppt"),
"Pinch Flat": ExtResource("16_7cyln"),
"Pinch Large": ExtResource("17_amtgc"),
"Pinch Middle": ExtResource("18_pnqcq"),
"Pinch Ring": ExtResource("19_aeaff"),
"Pinch Tight": ExtResource("20_mghnf"),
"Pinch Up": ExtResource("21_1v6tw"),
"PingPong": ExtResource("22_ueac0"),
"Pinky": ExtResource("23_7vyi4"),
"Pistol": ExtResource("24_nc600"),
"Ring": ExtResource("25_20nj0"),
"Rounded": ExtResource("26_648rb"),
"Sign 1": ExtResource("27_liq3y"),
"Sign 2": ExtResource("28_vdv8x"),
"Sign 3": ExtResource("29_uairn"),
"Sign 4": ExtResource("30_351lm"),
"Sign 5": ExtResource("31_o4yst"),
"Sign_Point": ExtResource("32_02kj7"),
"Straight": ExtResource("33_gpxgh"),
"Surfer": ExtResource("34_ldn4j"),
"Thumb": ExtResource("35_xnxq3")
}
[node name="AnimationPlayer" type="AnimationPlayer"]
libraries = {
"": SubResource("AnimationLibrary_reqae")
}
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,32 @@
[gd_resource type="AnimationNodeBlendTree" load_steps=6 format=3 uid="uid://m85b1gogdums"]
[sub_resource type="AnimationNodeAnimation" id="1"]
animation = &"Grip"
[sub_resource type="AnimationNodeAnimation" id="2"]
animation = &"Grip"
[sub_resource type="AnimationNodeBlend2" id="4"]
filter_enabled = true
filters = ["Armature/Skeleton3D:Little_Distal_R", "Armature/Skeleton3D:Little_Intermediate_R", "Armature/Skeleton3D:Little_Metacarpal_R", "Armature/Skeleton3D:Little_Proximal_R", "Armature/Skeleton3D:Middle_Distal_R", "Armature/Skeleton3D:Middle_Intermediate_R", "Armature/Skeleton3D:Middle_Metacarpal_R", "Armature/Skeleton3D:Middle_Proximal_R", "Armature/Skeleton3D:Ring_Distal_R", "Armature/Skeleton3D:Ring_Intermediate_R", "Armature/Skeleton3D:Ring_Metacarpal_R", "Armature/Skeleton3D:Ring_Proximal_R", "Armature/Skeleton3D:Thumb_Distal_R", "Armature/Skeleton3D:Thumb_Metacarpal_R", "Armature/Skeleton3D:Thumb_Proximal_R", "Armature/Skeleton:Little_Distal_R", "Armature/Skeleton:Little_Intermediate_R", "Armature/Skeleton:Little_Proximal_R", "Armature/Skeleton:Middle_Distal_R", "Armature/Skeleton:Middle_Intermediate_R", "Armature/Skeleton:Middle_Proximal_R", "Armature/Skeleton:Ring_Distal_R", "Armature/Skeleton:Ring_Intermediate_R", "Armature/Skeleton:Ring_Proximal_R", "Armature/Skeleton:Thumb_Distal_R", "Armature/Skeleton:Thumb_Proximal_R"]
[sub_resource type="AnimationNodeAnimation" id="3"]
animation = &"Grip 5"
[sub_resource type="AnimationNodeBlend2" id="5"]
filter_enabled = true
filters = ["Armature/Skeleton3D:Index_Distal_R", "Armature/Skeleton3D:Index_Intermediate_R", "Armature/Skeleton3D:Index_Metacarpal_R", "Armature/Skeleton3D:Index_Proximal_R", "Armature/Skeleton:Index_Distal_R", "Armature/Skeleton:Index_Intermediate_R", "Armature/Skeleton:Index_Proximal_R"]
[resource]
graph_offset = Vector2(-552.664, 107.301)
nodes/ClosedHand1/node = SubResource("1")
nodes/ClosedHand1/position = Vector2(-600, 300)
nodes/ClosedHand2/node = SubResource("2")
nodes/ClosedHand2/position = Vector2(-360, 300)
nodes/Grip/node = SubResource("4")
nodes/Grip/position = Vector2(0, 40)
nodes/OpenHand/node = SubResource("3")
nodes/OpenHand/position = Vector2(-600, 100)
nodes/Trigger/node = SubResource("5")
nodes/Trigger/position = Vector2(-360, 40)
node_connections = [&"output", 0, &"Grip", &"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1"]
@@ -0,0 +1,3 @@
[remap]
importer="keep"
@@ -0,0 +1,3 @@
[remap]
importer="keep"
Binary file not shown.
@@ -0,0 +1,3 @@
[remap]
importer="keep"
Binary file not shown.
@@ -0,0 +1,3 @@
[remap]
importer="keep"
@@ -0,0 +1,231 @@
@tool
class_name XRToolsCollisionHand
extends XRToolsForceBody
## XRTools Collision Hand Container Script
##
## This script implements logic for collision hands. Specifically it tracks
## its ancestor [XRController3D], and can act as a container for hand models
## and pickup functions.
## Modes for collision hand
enum CollisionHandMode {
## Hand is disabled and must be moved externally
DISABLED,
## Hand teleports to controller
TELEPORT,
## Hand collides with world (based on mask)
COLLIDE
}
# Default layer of 18:player-hands
const DEFAULT_LAYER := 0b0000_0000_0000_0010_0000_0000_0000_0000
# Default mask of 0xFFFF (1..16)
# - 1:static-world
# - 2:dynamic-world
# - 3:pickable-objects
# - 4:wall-walking
# - 5:grappling-target
const DEFAULT_MASK := 0b0000_0000_0000_0000_1111_1111_1111_1111
# How much displacement is required for the hand to start orienting to a surface
const ORIENT_DISPLACEMENT := 0.05
# Distance to teleport hands
const TELEPORT_DISTANCE := 1.0
## Controls the hand collision mode
@export var mode : CollisionHandMode = CollisionHandMode.COLLIDE
# Controller to target (if no target overrides)
var _controller : XRController3D
# Sorted stack of TargetOverride
var _target_overrides := []
# Current target (controller or override)
var _target : Node3D
## Target-override class
class TargetOverride:
## Target of the override
var target : Node3D
## Target priority
var priority : int
## Target-override constructor
func _init(t : Node3D, p : int):
target = t
priority = p
# Add support for is_xr_class on XRTools classes
func is_xr_class(name : String) -> bool:
return name == "XRToolsCollisionHand"
# Called when the node enters the scene tree for the first time.
func _ready():
# Do not initialise if in the editor
if Engine.is_editor_hint():
return
# Disconnect from parent transform as we move to it in the physics step,
# and boost the physics priority above any grab-drivers or hands.
top_level = true
process_physics_priority = -90
# Populate nodes
_controller = XRTools.find_xr_ancestor(self, "*", "XRController3D")
# Update the target
_update_target()
# Handle physics processing
func _physics_process(_delta):
# Do not process if in the editor
if Engine.is_editor_hint():
return
# Move to the current target
_move_to_target()
## This function adds a target override. The collision hand will attempt to
## move to the highest priority target, or the [XRController3D] if no override
## is specified.
func add_target_override(target : Node3D, priority : int) -> void:
# Remove any existing target override from this source
var modified := _remove_target_override(target)
# Insert the target override
_insert_target_override(target, priority)
modified = true
# Update the target
if modified:
_update_target()
## This function remove a target override.
func remove_target_override(target : Node3D) -> void:
# Remove the target override
var modified := _remove_target_override(target)
# Update the pose
if modified:
_update_target()
## This function searches from the specified node for an [XRToolsCollisionHand]
## assuming the node is a sibling of the hand under an [XRController3D].
static func find_instance(node : Node) -> XRToolsCollisionHand:
return XRTools.find_xr_child(
XRHelpers.get_xr_controller(node),
"*",
"XRToolsCollisionHand") as XRToolsCollisionHand
## This function searches from the specified node for the left controller
## [XRToolsCollisionHand] assuming the node is a sibling of the [XROrigin3D].
static func find_left(node : Node) -> XRToolsCollisionHand:
return XRTools.find_xr_child(
XRHelpers.get_left_controller(node),
"*",
"XRToolsCollisionHand") as XRToolsCollisionHand
## This function searches from the specified node for the right controller
## [XRToolsCollisionHand] assuming the node is a sibling of the [XROrigin3D].
static func find_right(node : Node) -> XRToolsCollisionHand:
return XRTools.find_xr_child(
XRHelpers.get_right_controller(node),
"*",
"XRToolsCollisionHand") as XRToolsCollisionHand
# This function moves the collision hand to the target node.
func _move_to_target():
# Handle DISABLED or no target
if mode == CollisionHandMode.DISABLED or not _target:
return
# Handle TELEPORT
if mode == CollisionHandMode.TELEPORT:
global_transform = _target.global_transform
return
# Handle too far from target
if global_position.distance_to(_target.global_position) > TELEPORT_DISTANCE:
global_transform = _target.global_transform
return
# Orient the hand then move
global_transform.basis = _target.global_transform.basis
move_and_slide(_target.global_position - global_position)
force_update_transform()
# This function inserts a target override into the overrides list by priority
# order.
func _insert_target_override(target : Node3D, priority : int) -> void:
# Construct the target override
var override := TargetOverride.new(target, priority)
# Iterate over all target overrides in the list
for pos in _target_overrides.size():
# Get the target override
var o : TargetOverride = _target_overrides[pos]
# Insert as early as possible to not invalidate sorting
if o.priority <= priority:
_target_overrides.insert(pos, override)
return
# Insert at the end
_target_overrides.push_back(override)
# This function removes a target from the overrides list
func _remove_target_override(target : Node) -> bool:
var pos := 0
var length := _target_overrides.size()
var modified := false
# Iterate over all pose overrides in the list
while pos < length:
# Get the target override
var o : TargetOverride = _target_overrides[pos]
# Check for a match
if o.target == target:
# Remove the override
_target_overrides.remove_at(pos)
modified = true
length -= 1
else:
# Advance down the list
pos += 1
# Return the modified indicator
return modified
# This function updates the target for hand movement.
func _update_target() -> void:
# Start by assuming the controller
_target = _controller
# Use first target override if specified
if _target_overrides.size():
_target = _target_overrides[0].target
@@ -0,0 +1 @@
uid://cl3m8mx54ejs3
+477
View File
@@ -0,0 +1,477 @@
@tool
@icon("res://addons/godot-xr-tools/editor/icons/hand.svg")
class_name XRToolsHand
extends Node3D
## XR Tools Hand Script
##
## This script manages a godot-xr-tools hand. It animates the hand blending
## grip and trigger animations based on controller input.
##
## Additionally the hand script detects world-scale changes in the XRServer
## and re-scales the hand appropriately so the hand stays scaled to the
## physical hand of the user.
## Signal emitted when the hand scale changes
signal hand_scale_changed(scale)
## Blend tree to use
@export var hand_blend_tree : AnimationNodeBlendTree: set = set_hand_blend_tree
## Override the hand material
@export var hand_material_override : Material: set = set_hand_material_override
## Default hand pose
@export var default_pose : XRToolsHandPoseSettings: set = set_default_pose
## Name of the Grip action in the OpenXR Action Map.
@export var grip_action : String = "grip"
## Name of the Trigger action in the OpenXR Action Map.
@export var trigger_action : String = "trigger"
## Last world scale (for scaling hands)
var _last_world_scale : float = 1.0
## Controller used for input/tracking
var _controller : XRController3D
## Initial hand transform (from controller) - used for scaling hands
var _initial_transform : Transform3D
## Current hand transform (from controller) - after scale
var _transform : Transform3D
## Hand mesh
var _hand_mesh : MeshInstance3D
## Hand animation player
var _animation_player : AnimationPlayer
## Hand animation tree
var _animation_tree : AnimationTree
## Animation blend tree
var _tree_root : AnimationNodeBlendTree
## Sorted stack of PoseOverride
var _pose_overrides := []
## Force grip value (< 0 for no force)
var _force_grip := -1.0
## Force trigger value (< 0 for no force)
var _force_trigger := -1.0
# Sorted stack of TargetOverride
var _target_overrides := []
# Current target (controller or override)
var _target : Node3D
## Pose-override class
class PoseOverride:
## Who requested the override
var who : Node
## Pose priority
var priority : int
## Pose settings
var settings : XRToolsHandPoseSettings
## Pose-override constructor
func _init(w : Node, p : int, s : XRToolsHandPoseSettings):
who = w
priority = p
settings = s
## Target-override class
class TargetOverride:
## Target of the override
var target : Node3D
## Target priority
var priority : int
## Target-override constructor
func _init(t : Node3D, p : int):
target = t
priority = p
# Add support for is_xr_class on XRTools classes
func is_xr_class(name : String) -> bool:
return name == "XRToolsHand"
## Called when the node enters the scene tree for the first time.
func _ready() -> void:
# Save the initial hand transform
_initial_transform = transform
_transform = _initial_transform
# Disconnect from parent transform as we move to it in the physics step,
# and boost the physics priority after any grab-drivers but before other
# processing.
if not Engine.is_editor_hint():
top_level = true
process_physics_priority = -70
# Find our controller
_controller = XRTools.find_xr_ancestor(self, "*", "XRController3D")
# Find the relevant hand nodes
_hand_mesh = _find_child(self, "MeshInstance3D")
_animation_player = _find_child(self, "AnimationPlayer")
_animation_tree = _find_child(self, "AnimationTree")
# Apply all updates
_update_hand_blend_tree()
_update_hand_material_override()
_update_pose()
_update_target()
## This method checks for world-scale changes and scales itself causing the
## hand mesh and skeleton to scale appropriately. It then reads the grip and
## trigger action values to animate the hand.
func _physics_process(_delta: float) -> void:
# Do not run physics if in the editor
if Engine.is_editor_hint():
return
# Scale the hand mesh with the world scale.
if XRServer.world_scale != _last_world_scale:
_last_world_scale = XRServer.world_scale
_transform = _initial_transform.scaled(Vector3.ONE * _last_world_scale)
emit_signal("hand_scale_changed", _last_world_scale)
# Animate the hand mesh with the controller inputs
if _controller:
var grip : float = _controller.get_float(grip_action)
var trigger : float = _controller.get_float(trigger_action)
# Allow overriding of grip and trigger
if _force_grip >= 0.0: grip = _force_grip
if _force_trigger >= 0.0: trigger = _force_trigger
$AnimationTree.set("parameters/Grip/blend_amount", grip)
$AnimationTree.set("parameters/Trigger/blend_amount", trigger)
# Move to target
global_transform = _target.global_transform * _transform
force_update_transform()
# This method verifies the hand has a valid configuration.
func _get_configuration_warnings() -> PackedStringArray:
var warnings := PackedStringArray()
# Check hand for mesh instance
if not _find_child(self, "MeshInstance3D"):
warnings.append("Hand does not have a MeshInstance3D")
# Check hand for animation player
if not _find_child(self, "AnimationPlayer"):
warnings.append("Hand does not have a AnimationPlayer")
# Check hand for animation tree
var tree : AnimationTree = _find_child(self, "AnimationTree")
if not tree:
warnings.append("Hand does not have a AnimationTree")
elif not tree.tree_root:
warnings.append("Hand AnimationTree has no root")
# Return warnings
return warnings
## Find an [XRToolsHand] node.
##
## This function searches from the specified node for an [XRToolsHand] assuming
## the node is a sibling of the hand under an [XROrigin3D].
static func find_instance(node : Node) -> XRToolsHand:
return XRTools.find_xr_child(
XRHelpers.get_xr_controller(node),
"*",
"XRToolsHand") as XRToolsHand
## This function searches from the specified node for the left controller
## [XRToolsHand] assuming the node is a sibling of the [XROrigin3D].
static func find_left(node : Node) -> XRToolsHand:
return XRTools.find_xr_child(
XRHelpers.get_left_controller(node),
"*",
"XRToolsHand") as XRToolsHand
## This function searches from the specified node for the right controller
## [XRToolsHand] assuming the node is a sibling of the [XROrigin3D].
static func find_right(node : Node) -> XRToolsHand:
return XRTools.find_xr_child(
XRHelpers.get_right_controller(node),
"*",
"XRToolsHand") as XRToolsHand
## Set the blend tree
func set_hand_blend_tree(blend_tree : AnimationNodeBlendTree) -> void:
hand_blend_tree = blend_tree
if is_inside_tree():
_update_hand_blend_tree()
_update_pose()
## Set the hand material override
func set_hand_material_override(material : Material) -> void:
hand_material_override = material
if is_inside_tree():
_update_hand_material_override()
## Set the default open-hand pose
func set_default_pose(pose : XRToolsHandPoseSettings) -> void:
default_pose = pose
if is_inside_tree():
_update_pose()
## Add a pose override
func add_pose_override(who : Node, priority : int, settings : XRToolsHandPoseSettings) -> void:
# Remove any existing pose override from this source
var modified := _remove_pose_override(who)
# Insert the pose override
if settings:
_insert_pose_override(who, priority, settings)
modified = true
# Update the pose
if modified:
_update_pose()
## Remove a pose override
func remove_pose_override(who : Node) -> void:
# Remove the pose override
var modified := _remove_pose_override(who)
# Update the pose
if modified:
_update_pose()
## Force the grip and trigger values (primarily for preview)
func force_grip_trigger(grip : float = -1.0, trigger : float = -1.0) -> void:
# Save the forced values
_force_grip = grip
_force_trigger = trigger
# Update the animation if forcing to specific values
if grip >= 0.0: $AnimationTree.set("parameters/Grip/blend_amount", grip)
if trigger >= 0.0: $AnimationTree.set("parameters/Trigger/blend_amount", trigger)
## This function adds a target override. The collision hand will attempt to
## move to the highest priority target, or the [XRController3D] if no override
## is specified.
func add_target_override(target : Node3D, priority : int) -> void:
# Remove any existing target override from this source
var modified := _remove_target_override(target)
# Insert the target override
_insert_target_override(target, priority)
modified = true
# Update the target
if modified:
_update_target()
## This function remove a target override.
func remove_target_override(target : Node3D) -> void:
# Remove the target override
var modified := _remove_target_override(target)
# Update the pose
if modified:
_update_target()
func _update_hand_blend_tree() -> void:
# As we're going to make modifications to our animation tree, we need to do
# a deep copy, simply setting resource local to scene does not seem to be enough
if _animation_tree and hand_blend_tree:
_tree_root = hand_blend_tree.duplicate(true)
_animation_tree.tree_root = _tree_root
func _update_hand_material_override() -> void:
if _hand_mesh:
_hand_mesh.material_override = hand_material_override
func _update_pose() -> void:
# Skip if no blend tree
if !_tree_root:
return
# Select the pose settings
var pose_settings : XRToolsHandPoseSettings = default_pose
if _pose_overrides.size():
pose_settings = _pose_overrides[0].settings
# Get the open and closed pose animations
var open_pose : Animation = pose_settings.open_pose
var closed_pose : Animation = pose_settings.closed_pose
# Apply the open hand pose in the player and blend tree
if open_pose:
var open_name = _animation_player.find_animation(open_pose)
if open_name == "":
open_name = "open_hand"
if _animation_player.has_animation(open_name):
_animation_player.remove_animation(open_name)
_animation_player.get_animation_library("").add_animation(open_name, open_pose)
var open_hand_obj : AnimationNodeAnimation = _tree_root.get_node("OpenHand")
if open_hand_obj:
open_hand_obj.animation = open_name
# Apply the closed hand pose in the player and blend tree
if closed_pose:
var closed_name = _animation_player.find_animation(closed_pose)
if closed_name == "":
closed_name = "closed_hand"
if _animation_player.has_animation(closed_name):
_animation_player.remove_animation(closed_name)
_animation_player.get_animation_library("").add_animation(closed_name, closed_pose)
var closed_hand_obj : AnimationNodeAnimation = _tree_root.get_node("ClosedHand1")
if closed_hand_obj:
closed_hand_obj.animation = closed_name
closed_hand_obj = _tree_root.get_node("ClosedHand2")
if closed_hand_obj:
closed_hand_obj.animation = closed_name
func _insert_pose_override(who : Node, priority : int, settings : XRToolsHandPoseSettings) -> void:
# Construct the pose override
var override := PoseOverride.new(who, priority, settings)
# Iterate over all pose overrides in the list
for pos in _pose_overrides.size():
# Get the pose override
var pose : PoseOverride = _pose_overrides[pos]
# Insert as early as possible to not invalidate sorting
if pose.priority <= priority:
_pose_overrides.insert(pos, override)
return
# Insert at the end
_pose_overrides.push_back(override)
func _remove_pose_override(who : Node) -> bool:
var pos := 0
var length := _pose_overrides.size()
var modified := false
# Iterate over all pose overrides in the list
while pos < length:
# Get the pose override
var pose : PoseOverride = _pose_overrides[pos]
# Check for a match
if pose.who == who:
# Remove the override
_pose_overrides.remove_at(pos)
modified = true
length -= 1
else:
# Advance down the list
pos += 1
# Return the modified indicator
return modified
# This function inserts a target override into the overrides list by priority
# order.
func _insert_target_override(target : Node3D, priority : int) -> void:
# Construct the target override
var override := TargetOverride.new(target, priority)
# Iterate over all target overrides in the list
for pos in _target_overrides.size():
# Get the target override
var o : TargetOverride = _target_overrides[pos]
# Insert as early as possible to not invalidate sorting
if o.priority <= priority:
_target_overrides.insert(pos, override)
return
# Insert at the end
_target_overrides.push_back(override)
# This function removes a target from the overrides list
func _remove_target_override(target : Node) -> bool:
var pos := 0
var length := _target_overrides.size()
var modified := false
# Iterate over all pose overrides in the list
while pos < length:
# Get the target override
var o : TargetOverride = _target_overrides[pos]
# Check for a match
if o.target == target:
# Remove the override
_target_overrides.remove_at(pos)
modified = true
length -= 1
else:
# Advance down the list
pos += 1
# Return the modified indicator
return modified
# This function updates the target for hand movement.
func _update_target() -> void:
if _target_overrides.size():
_target = _target_overrides[0].target
else:
_target = get_parent()
static func _find_child(node : Node, type : String) -> Node:
# Iterate through all children
for child in node.get_children():
# If the child is a match then return it
if child.is_class(type):
return child
# Recurse into child
var found := _find_child(child, type)
if found:
return found
# No child found matching type
return null
+1
View File
@@ -0,0 +1 @@
uid://ckpqvvubybmtc
@@ -0,0 +1,154 @@
@tool
class_name XRToolsHandPhysicsBone
extends BoneAttachment3D
## XR Tools Physics Hand Bone
##
## This script adds a physics-bone to a godot-xr-tools physics hand.
##
## It extends from [BoneAttachment3D] to track the position of the bone in
## the hand skeleton, and uses this position to move a [CharacterBody3D]
## physics-bone with a [CapsuleShape3D] collider.
##
## The physics-bone is manually driven with to the position and rotation of the
## skeletal-bone. The physics-bone is set as top-level to prevent the
## physics-bone from inheriting any hand scaling as this would scale the
## collider which the physics engine cannot tolerate.
##
## To handle scaling, this script subscribes to the hand_scale_changed signal
## emitted by the [XRToolsHand] script and manually adjusts the [CapsuleShape3D]
## collider of the physics-bone to keep it sized appropriately.
##
## There are additional collision and group settings for this specific
## bone, which allows per-bone collision detection.
## Length of the physics-bone
@export var length : float = 0.03
## Ratio of bone length to width
@export var width_ratio : float = 0.3
## Additional collision layer for this one bone
@export_flags_3d_physics var collision_layer : int = 0
## Additional bone group for this one bone
@export var bone_group : String = ""
# Physics-bone collider shape
var _bone_shape : CapsuleShape3D
# Physics-bone body node
var _physics_bone : CharacterBody3D
# Node attached to the skeletal-bone, and the target of the physics-bone
var _skeletal_bone : Node3D
# Add support for is_xr_class on XRTools classes
func is_xr_class(name : String) -> bool:
return name == "XRToolsHandPhysicsBone"
# Called when the node enters the scene tree. This constructs the physics-bone
# nodes and performs initial positioning.
func _ready():
# Skip if in the editor
if Engine.is_editor_hint():
return
# Connect the 'hand_scale_changed' signal
var physics_hand := XRToolsHand.find_instance(self) as XRToolsPhysicsHand
if physics_hand:
physics_hand.hand_scale_changed.connect(_on_hand_scale_changed)
# Construct the physics-bone shape
_bone_shape = CapsuleShape3D.new()
_bone_shape.margin = physics_hand.margin
_on_hand_scale_changed(XRServer.world_scale)
# Construct the physics-bone collision shape
var bone_collision := CollisionShape3D.new()
bone_collision.set_name("BoneCollision")
bone_collision.shape = _bone_shape
#bone_collision.transform.basis = Basis(Vector3.RIGHT, PI/2)
# Construct the physics-bone body
_physics_bone = CharacterBody3D.new()
_physics_bone.set_name("BoneBody")
_physics_bone.set_as_top_level(true)
_physics_bone.collision_layer = physics_hand.collision_layer | collision_layer
_physics_bone.collision_mask = 0
_physics_bone.add_child(bone_collision)
# Set the optional bone group for all bones in the hand
if not physics_hand.bone_group.is_empty():
_physics_bone.add_to_group(physics_hand.bone_group)
# Set the optional bone group for this one bone
if not bone_group.is_empty():
_physics_bone.add_to_group(bone_group)
# Construct the bone middle spatial
_skeletal_bone = Node3D.new()
_skeletal_bone.transform.origin = Vector3.UP * length / 2
# Add the physics-bone body to this hand bone
add_child(_physics_bone)
add_child(_skeletal_bone)
# Perform initial teleport of the phsysics-bone to the skeletal-bone
_teleport_bone()
# Called during the physics process and moves the physics-bone to follow the
# skeletal-bone.
func _physics_process(delta: float) -> void:
# Skip if in the editor
if Engine.is_editor_hint():
return
_move_bone(delta)
# This method moves the physics-bone to the skeletal-bone by first doing a
# move_and_slide as this works well for collision-interactions. It then
# rotates the physics-bone to match the skeletal-bone.
func _move_bone(delta: float) -> void:
# Get the skeletal-bone transform
var bone_xform := _skeletal_bone.global_transform
# Get the required velocity to move the physics-bone to the skeletal-bone
var bone_vel := (bone_xform.origin - _physics_bone.global_transform.origin) / delta
# Move the physics-bone into position
_physics_bone.velocity = bone_vel
_physics_bone.move_and_slide()
# Rotate the physics-bone into the correct rotation
_physics_bone.global_transform.basis = bone_xform.basis
# This method teleports the physics-bone to the skeletal-bone.
func _teleport_bone() -> void:
# Get the bone transform
var bone_xform := _skeletal_bone.global_transform
# Set the bone position
_physics_bone.global_transform = Transform3D(
Basis(bone_xform.basis.get_rotation_quaternion()),
bone_xform.origin)
# This method handles changes to the hand scale by adjusting the
# physics-bone collider shape to match.
func _on_hand_scale_changed(scale: float) -> void:
# Get the scaled length and width
var length_scaled := length * scale
var width_scaled := length_scaled * width_ratio
# Adjust the shape
_bone_shape.radius = width_scaled
_bone_shape.height = length_scaled
@@ -0,0 +1 @@
uid://ni0l2pe18x3j
@@ -0,0 +1,8 @@
[gd_resource type="ORMMaterial3D" load_steps=3 format=3 uid="uid://bde1c58rcajee"]
[ext_resource type="Texture2D" uid="uid://cs7m7m0k2506g" path="res://addons/godot-xr-tools/hands/textures/african_baseColor.png" id="1_dn1i6"]
[ext_resource type="Texture2D" uid="uid://h3sjbnu6uplb" path="res://addons/godot-xr-tools/hands/textures/hands_occlusionRoughnessMetallic.png" id="2_di2ux"]
[resource]
albedo_texture = ExtResource("1_dn1i6")
orm_texture = ExtResource("2_di2ux")
@@ -0,0 +1,12 @@
[gd_resource type="ORMMaterial3D" load_steps=4 format=3 uid="uid://26qy0lwlws4a"]
[ext_resource type="Texture2D" uid="uid://dk8o82rjww802" path="res://addons/godot-xr-tools/hands/textures/african_realistic_baseColor.png" id="1_seyus"]
[ext_resource type="Texture2D" uid="uid://b6tgv6ucbgv3r" path="res://addons/godot-xr-tools/hands/textures/hands_normal.png" id="2_s3yd2"]
[ext_resource type="Texture2D" uid="uid://h3sjbnu6uplb" path="res://addons/godot-xr-tools/hands/textures/hands_occlusionRoughnessMetallic.png" id="3_p3lxw"]
[resource]
albedo_texture = ExtResource("1_seyus")
orm_texture = ExtResource("3_p3lxw")
normal_enabled = true
normal_scale = 0.25
normal_texture = ExtResource("2_s3yd2")
@@ -0,0 +1,8 @@
[gd_resource type="ORMMaterial3D" load_steps=3 format=3 uid="uid://dy6nhifvvmm73"]
[ext_resource type="Texture2D" uid="uid://c506svon268ms" path="res://addons/godot-xr-tools/hands/textures/caucasian_baseColor.png" id="1_si4on"]
[ext_resource type="Texture2D" uid="uid://h3sjbnu6uplb" path="res://addons/godot-xr-tools/hands/textures/hands_occlusionRoughnessMetallic.png" id="2_agvfk"]
[resource]
albedo_texture = ExtResource("1_si4on")
orm_texture = ExtResource("2_agvfk")
@@ -0,0 +1,12 @@
[gd_resource type="ORMMaterial3D" load_steps=4 format=3 uid="uid://rwfrc1fdcjsj"]
[ext_resource type="Texture2D" uid="uid://n1xq4cm67o07" path="res://addons/godot-xr-tools/hands/textures/caucasian_realistic_baseColor.png" id="1_c8nm1"]
[ext_resource type="Texture2D" uid="uid://b6tgv6ucbgv3r" path="res://addons/godot-xr-tools/hands/textures/hands_normal.png" id="2_ax2k6"]
[ext_resource type="Texture2D" uid="uid://h3sjbnu6uplb" path="res://addons/godot-xr-tools/hands/textures/hands_occlusionRoughnessMetallic.png" id="3_6wg12"]
[resource]
albedo_texture = ExtResource("1_c8nm1")
orm_texture = ExtResource("3_6wg12")
normal_enabled = true
normal_scale = 0.25
normal_texture = ExtResource("2_ax2k6")
@@ -0,0 +1,14 @@
[gd_resource type="ORMMaterial3D" load_steps=4 format=3 uid="uid://cdb40djkihelq"]
[ext_resource type="Texture2D" uid="uid://dv711ytktesj2" path="res://addons/godot-xr-tools/hands/textures/cleaning_glove_baseColor.png" id="1_k2x02"]
[ext_resource type="Texture2D" uid="uid://dt6k4nuvpo38o" path="res://addons/godot-xr-tools/hands/textures/glove_normal.png" id="2_uiqlw"]
[ext_resource type="Texture2D" uid="uid://yslwgnpbpeen" path="res://addons/godot-xr-tools/hands/textures/glove_occlusionRoughnessMetallic.png" id="3_8ux4v"]
[resource]
albedo_texture = ExtResource("1_k2x02")
orm_texture = ExtResource("3_8ux4v")
normal_enabled = true
normal_scale = 0.1
normal_texture = ExtResource("2_uiqlw")
clearcoat_enabled = true
ao_light_affect = 1.0
@@ -0,0 +1,18 @@
[gd_resource type="StandardMaterial3D" load_steps=4 format=3 uid="uid://p0q2df2dmy62"]
[ext_resource type="Texture2D" uid="uid://dgkfppran5j1f" path="res://addons/godot-xr-tools/hands/textures/glove_caucasian_green_camo.png" id="1_rbe3r"]
[ext_resource type="Texture2D" uid="uid://d2iocwfr47kqp" path="res://addons/godot-xr-tools/hands/textures/glove_fingerless_occlusionRoughnessMetallic.png" id="2_qqman"]
[sub_resource type="ORMMaterial3D" id="ORMMaterial3D_wu6j1"]
transparency = 1
depth_draw_mode = 1
albedo_texture = ExtResource("1_rbe3r")
orm_texture = ExtResource("2_qqman")
[resource]
render_priority = -1
next_pass = SubResource("ORMMaterial3D_wu6j1")
transparency = 1
no_depth_test = true
shading_mode = 0
albedo_color = Color(0, 1, 1, 0.25098)
@@ -0,0 +1,14 @@
[gd_resource type="ORMMaterial3D" load_steps=4 format=3 uid="uid://di8q50ljmjoar"]
[ext_resource type="Texture2D" uid="uid://cocorrka3dtq3" path="res://addons/godot-xr-tools/hands/textures/glove_african_dark_camo.png" id="1_5khcc"]
[ext_resource type="Texture2D" uid="uid://bw8rmigwt5pr4" path="res://addons/godot-xr-tools/hands/textures/glove_fingerless_normal.png" id="2_qghm4"]
[ext_resource type="Texture2D" uid="uid://d2iocwfr47kqp" path="res://addons/godot-xr-tools/hands/textures/glove_fingerless_occlusionRoughnessMetallic.png" id="3_dt1up"]
[resource]
albedo_texture = ExtResource("1_5khcc")
orm_texture = ExtResource("3_dt1up")
normal_enabled = true
normal_scale = 0.25
normal_texture = ExtResource("2_qghm4")
ao_light_affect = 0.05
ao_on_uv2 = true
@@ -0,0 +1,14 @@
[gd_resource type="ORMMaterial3D" load_steps=4 format=3 uid="uid://txs6yqlmnpi2"]
[ext_resource type="Texture2D" uid="uid://bidphehpipwhg" path="res://addons/godot-xr-tools/hands/textures/glove_african_green_camo.png" id="1_cinrp"]
[ext_resource type="Texture2D" uid="uid://bw8rmigwt5pr4" path="res://addons/godot-xr-tools/hands/textures/glove_fingerless_normal.png" id="2_64ndb"]
[ext_resource type="Texture2D" uid="uid://d2iocwfr47kqp" path="res://addons/godot-xr-tools/hands/textures/glove_fingerless_occlusionRoughnessMetallic.png" id="3_lwjmv"]
[resource]
albedo_texture = ExtResource("1_cinrp")
orm_texture = ExtResource("3_lwjmv")
normal_enabled = true
normal_scale = 0.25
normal_texture = ExtResource("2_64ndb")
ao_light_affect = 0.05
ao_on_uv2 = true
@@ -0,0 +1,14 @@
[gd_resource type="ORMMaterial3D" load_steps=4 format=3 uid="uid://dogla70w8hvo8"]
[ext_resource type="Texture2D" uid="uid://c7jutkax2fd1k" path="res://addons/godot-xr-tools/hands/textures/glove_caucasian_dark_camo.png" id="1_cyild"]
[ext_resource type="Texture2D" uid="uid://bw8rmigwt5pr4" path="res://addons/godot-xr-tools/hands/textures/glove_fingerless_normal.png" id="2_2k7pb"]
[ext_resource type="Texture2D" uid="uid://d2iocwfr47kqp" path="res://addons/godot-xr-tools/hands/textures/glove_fingerless_occlusionRoughnessMetallic.png" id="3_6vkcl"]
[resource]
albedo_texture = ExtResource("1_cyild")
orm_texture = ExtResource("3_6vkcl")
normal_enabled = true
normal_scale = 0.25
normal_texture = ExtResource("2_2k7pb")
ao_light_affect = 0.05
ao_on_uv2 = true
@@ -0,0 +1,14 @@
[gd_resource type="ORMMaterial3D" load_steps=4 format=3 uid="uid://f2uhcqq8s2jx"]
[ext_resource type="Texture2D" uid="uid://dgkfppran5j1f" path="res://addons/godot-xr-tools/hands/textures/glove_caucasian_green_camo.png" id="1_hy1aq"]
[ext_resource type="Texture2D" uid="uid://bw8rmigwt5pr4" path="res://addons/godot-xr-tools/hands/textures/glove_fingerless_normal.png" id="2_iwp46"]
[ext_resource type="Texture2D" uid="uid://d2iocwfr47kqp" path="res://addons/godot-xr-tools/hands/textures/glove_fingerless_occlusionRoughnessMetallic.png" id="3_gyrju"]
[resource]
albedo_texture = ExtResource("1_hy1aq")
orm_texture = ExtResource("3_gyrju")
normal_enabled = true
normal_scale = 0.25
normal_texture = ExtResource("2_iwp46")
ao_light_affect = 0.05
ao_on_uv2 = true

Some files were not shown because too many files have changed in this diff Show More