Merge pull request #146 from Nitwel/fixes-2

Update Hands to look a lot cleaner
This commit is contained in:
Nitwel 2024-05-06 19:04:00 +02:00 committed by GitHub
commit 91e05f047d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 1278 additions and 145 deletions

View File

@ -0,0 +1,295 @@
extends Node3D
# Settings that can be changed dynamically in the debugger to
# see how they alter the mapping to the hand skeleton
@export var applymiddlefingerfix: bool = true
@export var applyscaling: bool = true
@export var coincidewristorknuckle: bool = true
@export var visiblehandtrackskeleton: bool = true
@export var enableautotracker: bool = true
signal hand_active_changed(hand: int, active: bool)
# Hand tracking data access object
var xr_interface: OpenXRInterface
# Local origin for the hand tracking positions
var xr_origin: XROrigin3D
# Controller and its tracker with the aim pose that we can use when hand-tracking active
var xr_controller_node: XRController3D = null
var tracker_nhand: XRPositionalTracker.TrackerHand = XRPositionalTracker.TrackerHand.TRACKER_HAND_UNKNOWN
var xr_tracker: XRPositionalTracker = null
var xr_aimpose: XRPose = null
var xr_headtracker: XRPositionalTracker = null
var xr_camera_node: XRCamera3D = null
# Note the that the enumerations disagree
# XRPositionalTracker.TrackerHand.TRACKER_HAND_LEFT = 1
# OpenXRInterface.Hand.HAND_LEFT = 0
var hand: OpenXRInterface.Hand
var tracker_name: String
var handtrackingactive = false
var handnode = null
var skel = null
var handanimationtree = null
# values calculated from the hand skeleton itself
var handtoskeltransform
var wristboneindex
var wristboneresttransform
var hstw
var fingerboneindexes
var fingerboneresttransforms
static func basisfromA(a, v):
var vx = a.normalized()
var vy = vx.cross(v.normalized())
var vz = vx.cross(vy)
return Basis(vx, vy, vz)
static func rotationtoalignB(a, b, va, vb):
return basisfromA(b, vb) * basisfromA(a, va).inverse()
static func rotationtoalignScaled(a, b):
var axis = a.cross(b).normalized()
var sca = b.length() / a.length()
if (axis.length_squared() != 0):
var dot = a.dot(b) / (a.length() * b.length())
dot = clamp(dot, -1.0, 1.0)
var angle_rads = acos(dot)
return Basis(axis, angle_rads).scaled(Vector3(sca, sca, sca))
return Basis().scaled(Vector3(sca, sca, sca))
func extractrestfingerbones():
print(handnode.name)
var lr = "L" if hand == 0 else "R"
handtoskeltransform = handnode.global_transform.inverse() * skel.global_transform
wristboneindex = skel.find_bone("Wrist_" + lr)
wristboneresttransform = skel.get_bone_rest(wristboneindex)
hstw = handtoskeltransform * wristboneresttransform
fingerboneindexes = [ ]
fingerboneresttransforms = [ ]
for f in ["Thumb", "Index", "Middle", "Ring", "Little"]:
fingerboneindexes.push_back([ ])
fingerboneresttransforms.push_back([ ])
for b in ["Metacarpal", "Proximal", "Intermediate", "Distal", "Tip"]:
var name = f + "_" + b + "_" + lr
var ix = skel.find_bone(name)
if ix != - 1:
fingerboneindexes[- 1].push_back(ix)
fingerboneresttransforms[- 1].push_back(skel.get_bone_rest(ix) if ix != - 1 else null)
else:
assert(f == "Thumb" and b == "Intermediate")
func _xr_controller_node_tracking_changed(tracking):
var xr_pose = xr_controller_node.get_pose()
print("_xr_controller_node_tracking_changed ", xr_pose.name if xr_pose else "<none>")
func findxrnodes():
# first go up the tree to find the controller and origin
var nd = self
while nd != null and not (nd is XRController3D):
nd = nd.get_parent()
if nd == null:
print("Warning, no controller node detected")
return false
xr_controller_node = nd
tracker_nhand = xr_controller_node.get_tracker_hand()
tracker_name = xr_controller_node.tracker
xr_controller_node.tracking_changed.connect(_xr_controller_node_tracking_changed)
while nd != null and not (nd is XROrigin3D):
nd = nd.get_parent()
if nd == null:
print("Warning, no xrorigin node detected")
return false
xr_origin = nd
# Then look for the hand skeleton that we are going to map to
for cch in xr_origin.get_children():
if cch is XRCamera3D:
xr_camera_node = cch
# Finally decide if it is left or right hand and test consistency in the API
var islefthand = (tracker_name == "left_hand")
assert(tracker_name == ("left_hand" if islefthand else "right_hand"))
hand = OpenXRInterface.Hand.HAND_LEFT if islefthand else OpenXRInterface.Hand.HAND_RIGHT
print("All nodes for %s detected" % tracker_name)
return true
func findhandnodes():
if xr_controller_node == null:
return
for ch in xr_controller_node.get_children():
var lskel = ch.find_child("Skeleton3D")
if lskel:
if lskel.get_bone_count() == 26:
handnode = ch
else:
print("unrecognized skeleton in controller")
if handnode == null:
print("Warning, no handnode (mesh and animationtree) detected")
return false
skel = handnode.find_child("Skeleton3D")
if skel == null:
print("Warning, no Skeleton3D found")
return false
handanimationtree = handnode.get_node_or_null("AnimationTree")
extractrestfingerbones()
func findxrtrackerobjects():
xr_interface = XRServer.find_interface("OpenXR")
if xr_interface == null:
return
var tracker_name = xr_controller_node.tracker
xr_tracker = XRServer.get_tracker(tracker_name)
if xr_tracker == null:
return
assert(xr_tracker.hand == tracker_nhand)
print(xr_tracker.description, " ", xr_tracker.hand, " ", xr_tracker.name, " ", xr_tracker.profile, " ", xr_tracker.type)
xr_headtracker = XRServer.get_tracker("head")
var islefthand = (tracker_name == "left_hand")
assert(tracker_nhand == (XRPositionalTracker.TrackerHand.TRACKER_HAND_LEFT if islefthand else XRPositionalTracker.TrackerHand.TRACKER_HAND_RIGHT))
print(tracker_name, " ", tracker_nhand)
print("action_sets: ", xr_interface.get_action_sets())
$AutoTracker.setupautotracker(tracker_nhand, islefthand, xr_controller_node)
func _ready():
findxrnodes()
findxrtrackerobjects()
# As a transform we are effectively reparenting ourselves directly under the XROrigin3D
if xr_origin != null:
var rt = RemoteTransform3D.new()
rt.remote_path = get_path()
xr_origin.add_child.call_deferred(rt)
findhandnodes()
set_process(xr_interface != null)
func getoxrjointpositions():
var oxrjps = [ ]
for j in range(OpenXRInterface.HAND_JOINT_MAX):
oxrjps.push_back(xr_interface.get_hand_joint_position(hand, j))
return oxrjps
func getoxrjointrotations():
var oxrjrot = [ ]
for j in range(OpenXRInterface.HAND_JOINT_MAX):
oxrjrot.push_back(xr_interface.get_hand_joint_rotation(hand, j))
return oxrjrot
func fixmiddlefingerpositions(oxrjps):
for j in [OpenXRInterface.HAND_JOINT_MIDDLE_TIP, OpenXRInterface.HAND_JOINT_RING_TIP]:
var b = Basis(xr_interface.get_hand_joint_rotation(hand, j))
oxrjps[j] += - 0.01 * b.y + 0.005 * b.z
func calchandnodetransform(oxrjps, xrt):
# solve for handnodetransform where
# avatarwristtrans = handnode.get_parent().global_transform * handnodetransform * handtoskeltransform * wristboneresttransform
# avatarwristpos = avatarwristtrans.origin
# avatarmiddleknucklepos = avatarwristtrans * fingerboneresttransforms[2][0] * fingerboneresttransforms[2][1]
# handwrist = xrorigintransform * oxrjps[OpenXRInterface.HAND_JOINT_WRIST]
# handmiddleknuckle = xrorigintransform * oxrjps[OpenXRInterface.HAND_JOINT_MIDDLE_PROXIMAL]
# so that avatarwristpos->avatarmiddleknucklepos is aligned along handwrist->handmiddleknuckle
# and rotated so that the line between index and ring knuckles are in the same plane
# We want skel.global_transform*wristboneresttransform to have origin xrorigintransform*gg[OpenXRInterface.HAND_JOINT_WRIST].origin
var wristorigin = xrt * oxrjps[OpenXRInterface.HAND_JOINT_WRIST]
var middleknuckle = xrt * oxrjps[OpenXRInterface.HAND_JOINT_MIDDLE_PROXIMAL]
var leftknuckle = xrt * oxrjps[OpenXRInterface.HAND_JOINT_RING_PROXIMAL if hand == 0 else OpenXRInterface.HAND_JOINT_INDEX_PROXIMAL]
var rightknuckle = xrt * oxrjps[OpenXRInterface.HAND_JOINT_INDEX_PROXIMAL if hand == 0 else OpenXRInterface.HAND_JOINT_RING_PROXIMAL]
var middlerestreltransform = fingerboneresttransforms[2][0] * fingerboneresttransforms[2][1]
var leftrestreltransform = fingerboneresttransforms[3 if hand == 0 else 1][0] * fingerboneresttransforms[3 if hand == 0 else 1][1]
var rightrestreltransform = fingerboneresttransforms[1 if hand == 0 else 3][0] * fingerboneresttransforms[1 if hand == 0 else 3][1]
var m2g1 = middlerestreltransform
var skelmiddleknuckle = handnode.transform * hstw * middlerestreltransform
var m2g1g3 = leftrestreltransform.origin - rightrestreltransform.origin
var hnbasis = rotationtoalignB(hstw.basis * m2g1.origin, middleknuckle - wristorigin,
hstw.basis * m2g1g3, leftknuckle - rightknuckle)
var hnorigin = wristorigin - hnbasis * hstw.origin
if not coincidewristorknuckle:
hnorigin = middleknuckle - hnbasis * (hstw * middlerestreltransform).origin
return Transform3D(hnbasis, hnorigin)
const carpallist = [OpenXRInterface.HAND_JOINT_THUMB_METACARPAL,
OpenXRInterface.HAND_JOINT_INDEX_METACARPAL, OpenXRInterface.HAND_JOINT_MIDDLE_METACARPAL,
OpenXRInterface.HAND_JOINT_RING_METACARPAL, OpenXRInterface.HAND_JOINT_LITTLE_METACARPAL]
func calcboneposes(oxrjps, handnodetransform, xrt):
var fingerbonetransformsOut = fingerboneresttransforms.duplicate(true)
for f in range(5):
var mfg = handnodetransform * hstw
# (A.basis, A.origin) * (B.basis, B.origin) = (A.basis*B.basis, A.origin + A.basis*B.origin)
for i in range(len(fingerboneresttransforms[f]) - 1):
mfg = mfg * fingerboneresttransforms[f][i]
# (tIbasis,atIorigin)*fingerboneresttransforms[f][i+1]).origin = mfg.inverse()*kpositions[f][i+1]
# tIbasis*fingerboneresttransforms[f][i+1] = mfg.inverse()*kpositions[f][i+1] - atIorigin
var atIorigin = Vector3(0, 0, 0)
var kpositionsfip1 = xrt * oxrjps[carpallist[f] + i + 1]
var tIbasis = rotationtoalignScaled(fingerboneresttransforms[f][i + 1].origin, mfg.affine_inverse() * kpositionsfip1 - atIorigin)
var tIorigin = mfg.affine_inverse() * kpositionsfip1 - tIbasis * fingerboneresttransforms[f][i + 1].origin # should be 0
var tI = Transform3D(tIbasis, tIorigin)
fingerbonetransformsOut[f][i] = fingerboneresttransforms[f][i] * tI
mfg = mfg * tI
return fingerbonetransformsOut
func copyouttransformstoskel(fingerbonetransformsOut):
for f in range(len(fingerboneindexes)):
for i in range(len(fingerboneindexes[f])):
var ix = fingerboneindexes[f][i]
var t = fingerbonetransformsOut[f][i]
skel.set_bone_pose_rotation(ix, t.basis.get_rotation_quaternion())
if not applyscaling:
t = fingerboneresttransforms[f][i]
skel.set_bone_pose_position(ix, t.origin)
skel.set_bone_pose_scale(ix, t.basis.get_scale())
func _process(delta):
var handjointflagswrist = xr_interface.get_hand_joint_flags(hand, OpenXRInterface.HAND_JOINT_WRIST);
var lhandtrackingactive = (handjointflagswrist&OpenXRInterface.HAND_JOINT_POSITION_VALID) != 0
if handtrackingactive != lhandtrackingactive:
handtrackingactive = lhandtrackingactive
handnode.top_level = handtrackingactive
if handanimationtree:
handanimationtree.active = not handtrackingactive
print("setting hand " + str(hand) + " active: ", handtrackingactive)
hand_active_changed.emit(hand, handtrackingactive)
$VisibleHandTrackSkeleton.visible = visiblehandtrackskeleton and handtrackingactive
if handtrackingactive:
if enableautotracker:
$AutoTracker.activateautotracker(xr_controller_node)
else:
if $AutoTracker.autotrackeractive:
$AutoTracker.deactivateautotracker(xr_controller_node, xr_tracker)
handnode.transform = Transform3D()
if handtrackingactive:
var oxrjps = getoxrjointpositions()
var xrt = xr_origin.global_transform
if $AutoTracker.autotrackeractive:
$AutoTracker.autotrackgestures(oxrjps, xrt, xr_camera_node)
if applymiddlefingerfix:
fixmiddlefingerpositions(oxrjps)
var handnodetransform = calchandnodetransform(oxrjps, xrt)
var fingerbonetransformsOut = calcboneposes(oxrjps, handnodetransform, xrt)
handnode.transform = handnodetransform
copyouttransformstoskel(fingerbonetransformsOut)
if visible and $VisibleHandTrackSkeleton.visible:
var oxrjrot = getoxrjointrotations()
$VisibleHandTrackSkeleton.updatevisiblehandskeleton(oxrjps, oxrjrot, xrt)
if xr_aimpose == null:
xr_aimpose = xr_tracker.get_pose("aim")
print("...xr_aimpose ", xr_aimpose)
if xr_aimpose != null and $AutoTracker.autotrackeractive:
$AutoTracker.xr_autotracker.set_pose(xr_controller_node.pose, xr_aimpose.transform, xr_aimpose.linear_velocity, xr_aimpose.angular_velocity, xr_aimpose.tracking_confidence)

View File

@ -0,0 +1,130 @@
[gd_scene load_steps=20 format=3 uid="uid://bufelcry36rw1"]
[ext_resource type="Script" path="res://addons/xr-autohandtracker/auto_handtracker.gd" id="1_kokq6"]
[ext_resource type="Script" path="res://addons/xr-autohandtracker/visible_handtrack_skeleton.gd" id="2_51p5j"]
[ext_resource type="Script" path="res://addons/xr-autohandtracker/auto_tracker.gd" id="3_6kyde"]
[sub_resource type="BoxMesh" id="BoxMesh_lsd0h"]
size = Vector3(0.1, 0.8, 0.1)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_dawss"]
albedo_color = Color(0.6842, 0.671572, 0.696409, 1)
[sub_resource type="BoxMesh" id="BoxMesh_h2ysa"]
size = Vector3(0.8, 0.8, 0.8)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_kb47o"]
albedo_color = Color(0.188235, 0.6, 0.00392157, 1)
[sub_resource type="CylinderMesh" id="CylinderMesh_ga8xh"]
top_radius = 0.2
bottom_radius = 0.4
height = 1.0
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_2y0qr"]
albedo_color = Color(0, 0.470588, 0.698039, 1)
[sub_resource type="TorusMesh" id="TorusMesh_r0bsl"]
inner_radius = 0.19
outer_radius = 0.2
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_r0qnr"]
transparency = 1
albedo_color = Color(1, 1, 0.00784314, 1)
[sub_resource type="TorusMesh" id="TorusMesh_wsh6v"]
inner_radius = 0.59
outer_radius = 0.6
[sub_resource type="CylinderMesh" id="CylinderMesh_pce3n"]
top_radius = 0.05
bottom_radius = 0.05
height = 0.002
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_2wqtw"]
transparency = 1
shading_mode = 0
albedo_color = Color(1, 1, 0.00784314, 0.235294)
disable_receive_shadows = true
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_53tyc"]
transparency = 1
shading_mode = 0
albedo_color = Color(1, 1, 0.00784314, 0.235294)
disable_receive_shadows = true
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_f71oj"]
albedo_color = Color(1, 1, 0, 1)
[sub_resource type="BoxMesh" id="BoxMesh_epivk"]
material = SubResource("StandardMaterial3D_f71oj")
size = Vector3(0.01, 0.02, 0.01)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_fvumm"]
albedo_color = Color(1, 0.0431373, 0, 1)
[sub_resource type="BoxMesh" id="BoxMesh_ssbes"]
material = SubResource("StandardMaterial3D_fvumm")
size = Vector3(0.005, 0.19, 0.005)
[node name="AutoHandtracker" type="Node3D"]
top_level = true
script = ExtResource("1_kokq6")
[node name="VisibleHandTrackSkeleton" type="Node3D" parent="."]
visible = false
script = ExtResource("2_51p5j")
[node name="ExampleStick" type="Node3D" parent="VisibleHandTrackSkeleton"]
[node name="StemY" type="MeshInstance3D" parent="VisibleHandTrackSkeleton/ExampleStick"]
mesh = SubResource("BoxMesh_lsd0h")
surface_material_override/0 = SubResource("StandardMaterial3D_dawss")
[node name="ExampleJoint" type="Node3D" parent="VisibleHandTrackSkeleton"]
[node name="Box" type="MeshInstance3D" parent="VisibleHandTrackSkeleton/ExampleJoint"]
mesh = SubResource("BoxMesh_h2ysa")
surface_material_override/0 = SubResource("StandardMaterial3D_kb47o")
[node name="AutoTracker" type="Node3D" parent="."]
script = ExtResource("3_6kyde")
[node name="DragRod" type="MeshInstance3D" parent="AutoTracker"]
transform = Transform3D(-8.74228e-09, -1, 0, 0.2, -4.37114e-08, 0, 0, 0, 0.2, -0.5, 0, 0)
mesh = SubResource("CylinderMesh_ga8xh")
surface_material_override/0 = SubResource("StandardMaterial3D_2y0qr")
[node name="ThumbstickBoundaries" type="Node3D" parent="AutoTracker"]
[node name="InnerRing" type="MeshInstance3D" parent="AutoTracker/ThumbstickBoundaries"]
mesh = SubResource("TorusMesh_r0bsl")
skeleton = NodePath("../..")
surface_material_override/0 = SubResource("StandardMaterial3D_r0qnr")
[node name="OuterRing" type="MeshInstance3D" parent="AutoTracker/ThumbstickBoundaries"]
mesh = SubResource("TorusMesh_wsh6v")
skeleton = NodePath("../..")
surface_material_override/0 = SubResource("StandardMaterial3D_r0qnr")
[node name="UpDisc" type="MeshInstance3D" parent="AutoTracker/ThumbstickBoundaries"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0)
cast_shadow = 0
mesh = SubResource("CylinderMesh_pce3n")
skeleton = NodePath("../..")
surface_material_override/0 = SubResource("StandardMaterial3D_2wqtw")
[node name="DownDisc" type="MeshInstance3D" parent="AutoTracker/ThumbstickBoundaries"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.5, 0)
cast_shadow = 0
mesh = SubResource("CylinderMesh_pce3n")
skeleton = NodePath("../..")
surface_material_override/0 = SubResource("StandardMaterial3D_53tyc")
[node name="GraspMarker" type="MeshInstance3D" parent="AutoTracker"]
mesh = SubResource("BoxMesh_epivk")
skeleton = NodePath("../..")
[node name="ControllerMarker" type="MeshInstance3D" parent="AutoTracker"]
mesh = SubResource("BoxMesh_ssbes")
skeleton = NodePath("../..")

View File

@ -0,0 +1,215 @@
extends Node3D
# The autotracker is swapped onto the xr_controller_node when hand-tracking is active
# so that we can insert in our own button and float signals from the hand gestures,
# as well as setting the pose from the xr_aimpose (which is filtered by the system during hand tracking)
# Calling set_pose emits a pose_changed signal that copies its values into the xr_controller_node
var xr_autotracker : XRPositionalTracker = null
var xr_autopose : XRPose = null
var autotrackeractive = false
var graspsqueezer = SqueezeButton.new()
var pinchsqueezer = SqueezeButton.new()
# Called when the node enters the scene tree for the first time.
func _ready():
$ThumbstickBoundaries/InnerRing.mesh.outer_radius = innerringrad
$ThumbstickBoundaries/InnerRing.mesh.inner_radius = 0.95*innerringrad
$ThumbstickBoundaries/OuterRing.mesh.outer_radius = outerringrad
$ThumbstickBoundaries/OuterRing.mesh.inner_radius = 0.95*outerringrad
$ThumbstickBoundaries/UpDisc.transform.origin.y = updowndistbutton
$ThumbstickBoundaries/DownDisc.transform.origin.y = -updowndistbutton
func setupautotracker(tracker_nhand, islefthand, xr_controller_node):
xr_autotracker = XRPositionalTracker.new()
xr_autotracker.hand = tracker_nhand
xr_autotracker.name = "left_autohand" if islefthand else "right_autohand"
xr_autotracker.profile = "/interaction_profiles/autohand" # "/interaction_profiles/none"
xr_autotracker.type = 2
xr_autotracker.set_pose(xr_controller_node.pose, Transform3D(), Vector3(), Vector3(), XRPose.TrackingConfidence.XR_TRACKING_CONFIDENCE_NONE)
xr_autopose = xr_autotracker.get_pose(xr_controller_node.pose)
graspsqueezer.setinputstrings(xr_autotracker, "grip", "", "grip_click")
pinchsqueezer.setinputstrings(xr_autotracker, "trigger", "trigger_touch", "trigger_click")
XRServer.add_tracker(xr_autotracker)
func activateautotracker(xr_controller_node):
xr_controller_node.set_tracker(xr_autotracker.name)
autotrackeractive = true
func deactivateautotracker(xr_controller_node, xr_tracker):
setaxbybuttonstatus(0)
graspsqueezer.applysqueeze(graspsqueezer.touchbuttondistance + 1)
pinchsqueezer.applysqueeze(pinchsqueezer.touchbuttondistance + 1)
xr_controller_node.set_tracker(xr_tracker.name)
autotrackeractive = false
func autotrackgestures(oxrjps, xrt, xr_camera_node):
thumbsticksimulation(oxrjps, xrt, xr_camera_node)
# detect forming a fist
var middleknuckletip = (oxrjps[OpenXRInterface.HAND_JOINT_MIDDLE_TIP] - oxrjps[OpenXRInterface.HAND_JOINT_MIDDLE_PROXIMAL]).length()
var ringknuckletip = (oxrjps[OpenXRInterface.HAND_JOINT_RING_TIP] - oxrjps[OpenXRInterface.HAND_JOINT_RING_PROXIMAL]).length()
var littleknuckletip = (oxrjps[OpenXRInterface.HAND_JOINT_LITTLE_TIP] - oxrjps[OpenXRInterface.HAND_JOINT_LITTLE_PROXIMAL]).length()
var avgknuckletip = (middleknuckletip + ringknuckletip + littleknuckletip)/3
graspsqueezer.applysqueeze(avgknuckletip)
# detect the finger pinch
var pinchdist = (oxrjps[OpenXRInterface.HAND_JOINT_INDEX_TIP] - oxrjps[OpenXRInterface.HAND_JOINT_THUMB_TIP]).length()
pinchsqueezer.applysqueeze(pinchdist*2)
#$GraspMarker.global_transform.origin = xrt*oxrjps[OpenXRInterface.HAND_JOINT_MIDDLE_TIP]
#$GraspMarker.visible = buttoncurrentlyclicked
var thumbstickstartpt = null
const thumbdistancecontact = 0.025
const thumbdistancerelease = 0.045
const innerringrad = 0.05
const outerringrad = 0.22
const updowndisttouch = 0.08
const updowndistbutton = 0.12
var thumbsticktouched = false
var axbybuttonstatus = 0 # -2:by_button, -1:by_touch, 1:ax_touch, 1:ax_button
var by_is_up = true
func setaxbybuttonstatus(newaxbybuttonstatus):
if axbybuttonstatus == newaxbybuttonstatus:
return
if abs(axbybuttonstatus) == 2:
xr_autotracker.set_input("ax_button" if axbybuttonstatus > 0 else "by_button", false)
axbybuttonstatus = 1 if axbybuttonstatus > 0 else -1
if axbybuttonstatus == newaxbybuttonstatus:
return
xr_autotracker.set_input("ax_touch" if axbybuttonstatus > 0 else "by_touch", false)
axbybuttonstatus = 0
if axbybuttonstatus == newaxbybuttonstatus:
return
xr_autotracker.set_input("ax_touch" if newaxbybuttonstatus > 0 else "by_touch", true)
axbybuttonstatus = 1 if newaxbybuttonstatus > 0 else -1
if axbybuttonstatus == newaxbybuttonstatus:
return
xr_autotracker.set_input("ax_button" if newaxbybuttonstatus > 0 else "by_button", true)
axbybuttonstatus = newaxbybuttonstatus
func thumbsticksimulation(oxrjps, xrt, xr_camera_node):
var middletip = oxrjps[OpenXRInterface.HAND_JOINT_MIDDLE_TIP]
var thumbtip = oxrjps[OpenXRInterface.HAND_JOINT_THUMB_TIP]
var ringtip = oxrjps[OpenXRInterface.HAND_JOINT_RING_TIP]
var tipcen = (middletip + thumbtip + ringtip)/3.0
var middleknuckle = oxrjps[OpenXRInterface.HAND_JOINT_MIDDLE_PROXIMAL]
var thumbdistance = max((middletip - tipcen).length(), (thumbtip - tipcen).length(), (ringtip - tipcen).length())
if thumbstickstartpt == null:
if thumbdistance < thumbdistancecontact and middleknuckle.y < tipcen.y - 0.029:
thumbstickstartpt = tipcen
visible = true
global_transform.origin = xrt*tipcen
$ThumbstickBoundaries.global_transform.origin = xrt*thumbstickstartpt
else:
if thumbdistance > thumbdistancerelease:
thumbstickstartpt = null
if thumbsticktouched:
xr_autotracker.set_input("primary", Vector2(0.0, 0.0))
xr_autotracker.set_input("primary_touch", true)
thumbsticktouched = false
setaxbybuttonstatus(0)
visible = (thumbstickstartpt != null)
if thumbstickstartpt != null:
$DragRod.global_transform = sticktransformB(xrt*thumbstickstartpt, xrt*tipcen)
var facingangle = Vector2(xr_camera_node.transform.basis.z.x, xr_camera_node.transform.basis.z.z).angle() if xr_camera_node != null else 0.0
var hvec = Vector2(tipcen.x - thumbstickstartpt.x, tipcen.z - thumbstickstartpt.z)
var hv = hvec.rotated(deg_to_rad(90) - facingangle)
var hvlen = hv.length()
if not thumbsticktouched:
var frat = hvlen/max(hvlen, innerringrad)
frat = frat*frat*frat
$ThumbstickBoundaries/InnerRing.get_surface_override_material(0).albedo_color.a = frat
$ThumbstickBoundaries/OuterRing.get_surface_override_material(0).albedo_color.a = frat
if hvlen > innerringrad:
xr_autotracker.set_input("primary_touch", true)
thumbsticktouched = true
if thumbsticktouched:
var hvN = hv/max(hvlen, outerringrad)
xr_autotracker.set_input("primary", Vector2(hvN.x, -hvN.y))
var ydist = (tipcen.y - thumbstickstartpt.y)
var rawnewaxbybuttonstatus = 0
if ydist > updowndisttouch:
$ThumbstickBoundaries/UpDisc.visible = true
$ThumbstickBoundaries/UpDisc.get_surface_override_material(0).albedo_color.a = (ydist - updowndisttouch)/(updowndistbutton - updowndisttouch)*0.5 if ydist < updowndistbutton else 1.0
rawnewaxbybuttonstatus = 2 if ydist > updowndistbutton else 1
else:
$ThumbstickBoundaries/UpDisc.visible = false
if ydist < -updowndisttouch:
$ThumbstickBoundaries/DownDisc.visible = true
$ThumbstickBoundaries/DownDisc.get_surface_override_material(0).albedo_color.a = (-ydist - updowndisttouch)/(updowndistbutton - updowndisttouch)*0.5 if -ydist < updowndistbutton else 1.0
rawnewaxbybuttonstatus = -2 if -ydist > updowndistbutton else -1
else:
$ThumbstickBoundaries/DownDisc.visible = false
setaxbybuttonstatus(rawnewaxbybuttonstatus*(1 if by_is_up else -1))
class SqueezeButton:
const touchbuttondistance = 0.07
const depressbuttondistance = 0.04
const clickbuttononratio = 0.6
const clickbuttonoffratio = 0.4
var xr_autotracker = null
var squeezestring = ""
var touchstring = ""
var clickstring = ""
var buttoncurrentlyclicked = false
var buttoncurrentlytouched = false
func setinputstrings(lxr_autotracker, lsqueezestring, ltouchstring, lclickstring):
xr_autotracker = lxr_autotracker
squeezestring = lsqueezestring
touchstring = ltouchstring
clickstring = lclickstring
func xrsetinput(name, value):
if xr_autotracker and name:
xr_autotracker.set_input(name, value)
func applysqueeze(squeezedistance):
var buttonratio = min(inverse_lerp(touchbuttondistance, depressbuttondistance, squeezedistance), 1.0)
if buttonratio < 0.0:
if buttoncurrentlytouched:
xrsetinput(squeezestring, 0.0)
xrsetinput(touchstring, false)
buttoncurrentlytouched = false
else:
xrsetinput(squeezestring, buttonratio)
if not buttoncurrentlytouched:
xrsetinput(touchstring, true)
buttoncurrentlytouched = true
var buttonclicked = (buttonratio > (clickbuttonoffratio if buttoncurrentlyclicked else clickbuttononratio))
if buttonclicked != buttoncurrentlyclicked:
xrsetinput(clickstring, buttonclicked)
buttoncurrentlyclicked = buttonclicked
const stickradius = 0.01
static func sticktransformB(j1, j2):
var v = j2 - j1
var vlen = v.length()
var b
if vlen != 0:
var vy = v/vlen
var vyunaligned = Vector3(0,1,0) if abs(vy.y) < abs(vy.x) + abs(vy.z) else Vector3(1,0,0)
var vz = vy.cross(vyunaligned)
var vx = vy.cross(vz)
b = Basis(vx*stickradius, v, vz*stickradius)
else:
b = Basis().scaled(Vector3(0.01, 0.0, 0.01))
return Transform3D(b, (j1 + j2)*0.5)

View File

@ -0,0 +1,60 @@
extends Node3D
const hjsticks = [ [ OpenXRInterface.HAND_JOINT_WRIST, OpenXRInterface.HAND_JOINT_THUMB_METACARPAL, OpenXRInterface.HAND_JOINT_THUMB_PROXIMAL, OpenXRInterface.HAND_JOINT_THUMB_DISTAL, OpenXRInterface.HAND_JOINT_THUMB_TIP ],
[ OpenXRInterface.HAND_JOINT_WRIST, OpenXRInterface.HAND_JOINT_INDEX_METACARPAL, OpenXRInterface.HAND_JOINT_INDEX_PROXIMAL, OpenXRInterface.HAND_JOINT_INDEX_INTERMEDIATE, OpenXRInterface.HAND_JOINT_INDEX_DISTAL, OpenXRInterface.HAND_JOINT_INDEX_TIP ],
[ OpenXRInterface.HAND_JOINT_WRIST, OpenXRInterface.HAND_JOINT_MIDDLE_METACARPAL, OpenXRInterface.HAND_JOINT_MIDDLE_PROXIMAL, OpenXRInterface.HAND_JOINT_MIDDLE_INTERMEDIATE, OpenXRInterface.HAND_JOINT_MIDDLE_DISTAL, OpenXRInterface.HAND_JOINT_MIDDLE_TIP ],
[ OpenXRInterface.HAND_JOINT_WRIST, OpenXRInterface.HAND_JOINT_RING_METACARPAL, OpenXRInterface.HAND_JOINT_RING_PROXIMAL, OpenXRInterface.HAND_JOINT_RING_INTERMEDIATE, OpenXRInterface.HAND_JOINT_RING_DISTAL, OpenXRInterface.HAND_JOINT_RING_TIP ],
[ OpenXRInterface.HAND_JOINT_WRIST, OpenXRInterface.HAND_JOINT_LITTLE_METACARPAL, OpenXRInterface.HAND_JOINT_LITTLE_PROXIMAL, OpenXRInterface.HAND_JOINT_LITTLE_INTERMEDIATE, OpenXRInterface.HAND_JOINT_LITTLE_DISTAL, OpenXRInterface.HAND_JOINT_LITTLE_TIP ]
]
func _ready():
var sticknode = $ExampleStick
remove_child(sticknode)
var jointnode = $ExampleJoint
remove_child(jointnode)
for j in range(OpenXRInterface.HAND_JOINT_MAX):
var rj = jointnode.duplicate()
rj.name = "J%d" % j
rj.scale = Vector3(0.01, 0.01, 0.01)
add_child(rj)
for hjstick in hjsticks:
for i in range(0, len(hjstick)-1):
var rstick = sticknode.duplicate()
var j1 = hjstick[i]
var j2 = hjstick[i+1]
rstick.name = "S%d_%d" % [j1, j2]
rstick.scale = Vector3(0.01, 0.01, 0.01)
add_child(rstick)
#get_node("J%d" % hjstick[i+1]).get_node("Sphere").visible = (i > 0)
const knuckleradius = 0.01
func updatevisiblehandskeleton(oxrjps, oxrjrot, xrt):
for j in range(OpenXRInterface.HAND_JOINT_MAX):
get_node("J%d" % j).global_transform = Transform3D(xrt.basis*Basis(oxrjrot[j]).scaled(Vector3(knuckleradius, knuckleradius, knuckleradius)), xrt*oxrjps[j])
for hjstick in hjsticks:
for i in range(0, len(hjstick)-1):
var j1 = hjstick[i]
var j2 = hjstick[i+1]
var rstick = get_node("S%d_%d" % [j1, j2])
rstick.global_transform = sticktransformB(xrt*oxrjps[j1], xrt*oxrjps[j2])
const stickradius = 0.01
static func sticktransformB(j1, j2):
var v = j2 - j1
var vlen = v.length()
var b
if vlen != 0:
var vy = v/vlen
var vyunaligned = Vector3(0,1,0) if abs(vy.y) < abs(vy.x) + abs(vy.z) else Vector3(1,0,0)
var vz = vy.cross(vyunaligned)
var vx = vy.cross(vz)
b = Basis(vx*stickradius, v, vz*stickradius)
else:
b = Basis().scaled(Vector3(0.01, 0.0, 0.01))
return Transform3D(b, (j1 + j2)*0.5)

View File

@ -0,0 +1,25 @@
shader_type spatial;
uniform vec4 albedo: source_color = vec4(1.0, 1.0, 1.0, 0.4);
uniform float fade_offset : hint_range(-0.1, 0.1, 0.001) = 0.0;
uniform float fade_sharpness : hint_range(0.0, 35.0, 0.01) = 15.00;
varying vec3 vertex_pos;
void vertex() {
vertex_pos = VERTEX;
}
float fresnel(float amount, vec3 normal, vec3 view)
{
return pow((1.0 - clamp(dot(normalize(normal), normalize(view)), 0.0, 1.0 )), amount);
}
void fragment()
{
float basic_fresnel = fresnel(3.0, NORMAL, VIEW);
ALBEDO = albedo.xyz + basic_fresnel;
ALPHA = albedo.w + basic_fresnel;
ALPHA = clamp((-vertex_pos.z - fade_offset) * fade_sharpness, 0.00, ALPHA);
}

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d258e8207dcf0824402a184007086eb4e1ae599996ee855549321536a35cf494
size 70342

View File

@ -0,0 +1,34 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://dv6vpdc0ia05i"
path="res://.godot/imported/Hand_low_L.gltf-9c10b05e7c0ffd2a3c3b8d44362b6cfb.scn"
[deps]
source_file="res://assets/models/hands/Hand_low_L.gltf"
dest_files=["res://.godot/imported/Hand_low_L.gltf-9c10b05e7c0ffd2a3c3b8d44362b6cfb.scn"]
[params]
nodes/root_type=""
nodes/root_name=""
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=1
meshes/lightmap_texel_size=0.2
meshes/force_disable_compression=false
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=false
animation/remove_immutable_tracks=true
import_script/path=""
_subresources={}
gltf/naming_version=1
gltf/embedded_image_handling=1

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:19cbbf3c2fd3b8f0a1319056854975b99cdb6dfe3caa9b09018bb865a3964de1
size 70346

View File

@ -0,0 +1,34 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://dy70ty8fowgbf"
path="res://.godot/imported/Hand_low_R.gltf-dae5df2e2e7666d45bce4f244fa11afb.scn"
[deps]
source_file="res://assets/models/hands/Hand_low_R.gltf"
dest_files=["res://.godot/imported/Hand_low_R.gltf-dae5df2e2e7666d45bce4f244fa11afb.scn"]
[params]
nodes/root_type=""
nodes/root_name=""
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=1
meshes/lightmap_texel_size=0.2
meshes/force_disable_compression=false
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=false
animation/remove_immutable_tracks=true
import_script/path=""
_subresources={}
gltf/naming_version=1
gltf/embedded_image_handling=1

View File

@ -10,7 +10,7 @@
[sub_resource type="BoxShape3D" id="BoxShape3D_3qyo4"] [sub_resource type="BoxShape3D" id="BoxShape3D_3qyo4"]
size = Vector3(0.32, 0.16, 0.02) size = Vector3(0.32, 0.16, 0.02)
[sub_resource type="ShaderMaterial" id="ShaderMaterial_cw188"] [sub_resource type="ShaderMaterial" id="ShaderMaterial_nktla"]
resource_local_to_scene = true resource_local_to_scene = true
render_priority = 10 render_priority = 10
shader = ExtResource("6_40cd1") shader = ExtResource("6_40cd1")
@ -25,7 +25,7 @@ shader_parameter/corner_radius = 0.8
shader_parameter/roughness = 0.3 shader_parameter/roughness = 0.3
shader_parameter/grain_amount = 0.02 shader_parameter/grain_amount = 0.02
[sub_resource type="QuadMesh" id="QuadMesh_ryeda"] [sub_resource type="QuadMesh" id="QuadMesh_mqjqg"]
size = Vector2(0.32, 0.16) size = Vector2(0.32, 0.16)
[node name="Timer" type="StaticBody3D" groups=["entity"]] [node name="Timer" type="StaticBody3D" groups=["entity"]]
@ -78,7 +78,7 @@ label = "stop"
icon = true icon = true
[node name="Panel" parent="." instance=ExtResource("5_j3gsb")] [node name="Panel" parent="." instance=ExtResource("5_j3gsb")]
material_override = SubResource("ShaderMaterial_cw188") material_override = SubResource("ShaderMaterial_nktla")
mesh = SubResource("QuadMesh_ryeda") mesh = SubResource("QuadMesh_mqjqg")
size = Vector2(0.32, 0.16) size = Vector2(0.32, 0.16)
corner_radius = 0.8 corner_radius = 0.8

View File

@ -86,6 +86,10 @@ func _on_grab_move(event: EventPointer):
if lock_rotation: if lock_rotation:
get_parent().global_transform = TransformTools.rotate_around_point(get_parent().global_transform, get_parent().to_global(initial_point), initial_rotation - get_parent().global_rotation) get_parent().global_transform = TransformTools.rotate_around_point(get_parent().global_transform, get_parent().to_global(initial_point), initial_rotation - get_parent().global_rotation)
if restrict_movement:
get_parent().global_position = restrict_movement.call(get_parent().global_position)
on_move.emit(get_parent().global_position, get_parent().global_rotation)
func _on_grab_up(event: EventPointer): func _on_grab_up(event: EventPointer):
if event.initiator == initiator2: if event.initiator == initiator2:
initiator2 = null initiator2 = null

View File

@ -1,25 +1,17 @@
[gd_scene load_steps=15 format=3 uid="uid://eecv28y6jxk4"] [gd_scene load_steps=12 format=3 uid="uid://eecv28y6jxk4"]
[ext_resource type="PackedScene" uid="uid://clc5dre31iskm" path="res://addons/godot-xr-tools/xr/start_xr.tscn" id="1_i4c04"] [ext_resource type="PackedScene" uid="uid://clc5dre31iskm" path="res://addons/godot-xr-tools/xr/start_xr.tscn" id="1_i4c04"]
[ext_resource type="Script" path="res://content/main.gd" id="1_uvrd4"] [ext_resource type="Script" path="res://content/main.gd" id="1_uvrd4"]
[ext_resource type="PackedScene" uid="uid://b30w6tywfj4fp" path="res://content/system/controller_left/controller_left.tscn" id="2_2lraw"] [ext_resource type="PackedScene" uid="uid://b30w6tywfj4fp" path="res://content/system/controller_left/controller_left.tscn" id="2_2lraw"]
[ext_resource type="Environment" uid="uid://cfm0g4r0h2n1p" path="res://assets/environment.tres" id="2_lsndp"] [ext_resource type="Environment" uid="uid://cfm0g4r0h2n1p" path="res://assets/environment.tres" id="2_lsndp"]
[ext_resource type="PackedScene" uid="uid://dscp8x0ari57n" path="res://content/system/raycast/raycast.tscn" id="3_67lii"]
[ext_resource type="PackedScene" uid="uid://b2kjh1fpjptdr" path="res://content/system/camera/camera.tscn" id="3_rj4ac"] [ext_resource type="PackedScene" uid="uid://b2kjh1fpjptdr" path="res://content/system/camera/camera.tscn" id="3_rj4ac"]
[ext_resource type="PackedScene" uid="uid://bsx12q23v8apy" path="res://content/system/hands/hands.tscn" id="4_v8xu6"]
[ext_resource type="PackedScene" uid="uid://ctltchlf2j2r4" path="res://addons/xr-simulator/XRSimulator.tscn" id="5_3qc8g"] [ext_resource type="PackedScene" uid="uid://ctltchlf2j2r4" path="res://addons/xr-simulator/XRSimulator.tscn" id="5_3qc8g"]
[ext_resource type="PackedScene" uid="uid://biu66ihmvmku3" path="res://content/system/controller_right/controller_right.tscn" id="7_0b3tc"]
[ext_resource type="PackedScene" uid="uid://c3kdssrmv84kv" path="res://content/ui/menu/menu.tscn" id="8_du83w"] [ext_resource type="PackedScene" uid="uid://c3kdssrmv84kv" path="res://content/ui/menu/menu.tscn" id="8_du83w"]
[ext_resource type="PackedScene" uid="uid://lrehk38exd5n" path="res://content/system/keyboard/keyboard.tscn" id="9_e5n3p"] [ext_resource type="PackedScene" uid="uid://lrehk38exd5n" path="res://content/system/keyboard/keyboard.tscn" id="9_e5n3p"]
[ext_resource type="PackedScene" uid="uid://cbemihbxkd4ll" path="res://content/system/house/house.tscn" id="9_np6mw"] [ext_resource type="PackedScene" uid="uid://cbemihbxkd4ll" path="res://content/system/house/house.tscn" id="9_np6mw"]
[ext_resource type="PackedScene" uid="uid://bhyddd1f0ry1x" path="res://content/ui/onboarding/onboarding.tscn" id="12_uq2nj"] [ext_resource type="PackedScene" uid="uid://bhyddd1f0ry1x" path="res://content/ui/onboarding/onboarding.tscn" id="12_uq2nj"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_m58yb"]
ao_enabled = true
[sub_resource type="BoxMesh" id="BoxMesh_ir3co"]
material = SubResource("StandardMaterial3D_m58yb")
size = Vector3(0.01, 0.01, 0.01)
[node name="Main" type="Node3D"] [node name="Main" type="Node3D"]
transform = Transform3D(1, -0.000296142, 0.000270963, 0.000296143, 1, -4.5899e-06, -0.000270962, 4.67014e-06, 1, 0, 0, 0) transform = Transform3D(1, -0.000296142, 0.000270963, 0.000296143, 1, -4.5899e-06, -0.000270962, 4.67014e-06, 1, 0, 0, 0)
script = ExtResource("1_uvrd4") script = ExtResource("1_uvrd4")
@ -41,20 +33,20 @@ enable_passthrough = true
[node name="XRControllerLeft" parent="XROrigin3D" instance=ExtResource("2_2lraw")] [node name="XRControllerLeft" parent="XROrigin3D" instance=ExtResource("2_2lraw")]
transform = Transform3D(0.999999, -1.39633e-11, 0, 9.48075e-12, 1, 0, 0, 0, 1, -0.355145, 0.550439, -0.477945) transform = Transform3D(0.999999, -1.39633e-11, 0, 9.48075e-12, 1, 0, 0, 0, 1, -0.355145, 0.550439, -0.477945)
[node name="XRControllerRight" type="XRController3D" parent="XROrigin3D"] [node name="IndexTip" parent="XROrigin3D/XRControllerLeft" index="6"]
transform = Transform3D(0.999999, -1.39633e-11, 0, 9.48075e-12, 1, 0, 0, 0, 1, 0.272616, 0.559282, -0.468369) transform = Transform3D(0.967526, 0.252326, -0.0150302, -0.0150302, 0.116784, 0.993043, 0.252326, -0.960569, 0.116784, -0.00665808, 0.0427912, -0.169868)
tracker = &"right_hand"
pose = &"aim"
[node name="MeshInstance3D" type="MeshInstance3D" parent="XROrigin3D/XRControllerRight"] [node name="ThumbTip" parent="XROrigin3D/XRControllerLeft" index="7"]
mesh = SubResource("BoxMesh_ir3co") transform = Transform3D(0.967043, 0.24582, -0.0663439, -0.0663439, 0.494837, 0.86645, 0.24582, -0.833492, 0.494837, 0.0261569, 0.0891963, -0.0934418)
[node name="Raycast" parent="XROrigin3D/XRControllerRight" instance=ExtResource("3_67lii")] [node name="MiddleTip" parent="XROrigin3D/XRControllerLeft" index="8"]
transform = Transform3D(0.98042, 0.196912, 0.00149799, 0.001498, -0.015065, 0.999885, 0.196912, -0.980305, -0.0150651, -0.00327212, -0.00771427, -0.176318)
[node name="Hands" parent="XROrigin3D" node_paths=PackedStringArray("ray_left", "ray_right") instance=ExtResource("4_v8xu6")] [node name="Palm" parent="XROrigin3D/XRControllerLeft" index="9"]
transform = Transform3D(0.999968, -1.39576e-11, 0, 9.52038e-12, 0.999984, -2.59206e-11, -2.91038e-11, 5.22959e-11, 0.999984, 0, 0, 0) transform = Transform3D(1, 3.12361e-06, -3.13859e-06, -3.12371e-06, 1, -1.97886e-05, 3.13859e-06, 1.97889e-05, 1, 0.0307807, -0.0419722, -0.0399505)
ray_left = NodePath("../XRControllerLeft/Raycast")
ray_right = NodePath("../XRControllerRight/Raycast") [node name="XRControllerRight" parent="XROrigin3D" instance=ExtResource("7_0b3tc")]
transform = Transform3D(0.999999, -1.39635e-11, 0, 1.31553e-10, 1, 0, 0, 0, 1, 0.336726, 0.575093, -0.437942)
[node name="XRSimulator" parent="." instance=ExtResource("5_3qc8g")] [node name="XRSimulator" parent="." instance=ExtResource("5_3qc8g")]
min_camera_height = 0.01 min_camera_height = 0.01
@ -74,3 +66,4 @@ transform = Transform3D(0.5, 5.24309e-05, 0.000144384, -0.000139169, 0.353553, 0
transform = Transform3D(1, -1.39636e-11, 0, 4.42413e-11, 1, 0, 0, 0, 1, -0.576793, 0.820168, -0.60016) transform = Transform3D(1, -1.39636e-11, 0, 4.42413e-11, 1, 0, 0, 0, 1, -0.576793, 0.820168, -0.60016)
[editable path="XROrigin3D/XRControllerLeft"] [editable path="XROrigin3D/XRControllerLeft"]
[editable path="XROrigin3D/XRControllerLeft/hand_l"]

View File

@ -1,10 +1,42 @@
extends XRController3D extends XRController3D
const Entity = preload ("res://content/entities/entity.gd") const Entity = preload ("res://content/entities/entity.gd")
const Pointer = preload ("res://lib/utils/pointer/pointer.gd")
const Initiator = preload ("res://lib/utils/pointer/initiator.gd")
const Finger = preload ("res://lib/utils/touch/finger.gd")
const Touch = preload ("res://lib/utils/touch/touch.gd")
const Collide = preload ("res://lib/utils/touch/collide.gd")
const Miniature = preload ("res://content/system/house/mini/miniature.gd")
@onready var main = $"/root/Main"
@onready var hand = $hand_l
@onready var hand_mesh = $hand_l/Armature/Skeleton3D/mesh_Hand_L
@onready var auto_hand = $AutoHandtracker
@onready var index_tip = $IndexTip
@onready var thumb_tip = $ThumbTip
@onready var middle_tip = $MiddleTip
@onready var mini_view_button = $Palm/QuickActions/MiniView
@onready var temperature_button = $Palm/QuickActions/Temperature
@onready var humidity_button = $Palm/QuickActions/Humidity
@onready var palm = $Palm
@onready var ray: RayCast3D = $Raycast
@onready var area = $trash_bin/Area3D @onready var area = $trash_bin/Area3D
@onready var trash_bin = $trash_bin @onready var trash_bin = $trash_bin
@onready var animation = $AnimationPlayer @onready var animation = $AnimationPlayer
@onready var quick_actions = $Palm/QuickActions
var hand_active = false
var initiator: Initiator = Initiator.new()
var collide: Collide
var pointer: Pointer
var press_distance = 0.02
var grip_distance = 0.02
var pressed = false
var grabbed = false
var to_delete = [] var to_delete = []
var trash_bin_visible: bool = true: var trash_bin_visible: bool = true:
@ -36,6 +68,8 @@ var trash_bin_large: bool = false:
func _ready(): func _ready():
trash_bin_visible = false trash_bin_visible = false
_setup_hand()
EventSystem.on_grab_down.connect(func(event: EventPointer): EventSystem.on_grab_down.connect(func(event: EventPointer):
trash_bin_visible=_get_entity(event.target) != null trash_bin_visible=_get_entity(event.target) != null
) )
@ -70,6 +104,39 @@ func _ready():
House.body.save_all_entities() House.body.save_all_entities()
) )
func _process(_delta):
if !hand_active:
if quick_actions.is_inside_tree(): palm.remove_child(quick_actions)
return
if main.camera.global_transform.basis.z.dot(palm.global_transform.basis.x) > 0.85:
if quick_actions.is_inside_tree() == false: palm.add_child(quick_actions)
else:
if quick_actions.is_inside_tree(): palm.remove_child(quick_actions)
func _physics_process(_delta):
if !hand_active: return
var distance_trigger = index_tip.global_position.distance_to(thumb_tip.global_position)
var distance_grab = middle_tip.global_position.distance_to(thumb_tip.global_position)
var trigger_close = distance_trigger <= press_distance
var grab_close = distance_grab <= grip_distance
if trigger_close&&!pressed:
initiator.on_press.emit(Initiator.EventType.TRIGGER)
pressed = true
elif !trigger_close&&pressed:
initiator.on_release.emit(Initiator.EventType.TRIGGER)
pressed = false
if grab_close&&!grabbed:
initiator.on_press.emit(Initiator.EventType.GRIP)
grabbed = true
elif !grab_close&&grabbed:
initiator.on_release.emit(Initiator.EventType.GRIP)
grabbed = false
func _get_entity(node: Node): func _get_entity(node: Node):
if node is Entity: if node is Entity:
return node return node
@ -78,3 +145,42 @@ func _get_entity(node: Node):
return null return null
return _get_entity(node.get_parent()) return _get_entity(node.get_parent())
func _setup_hand():
TouchManager.add_finger(Finger.Type.INDEX_LEFT, $IndexTip/TouchArea)
collide = Collide.new(hand, hand_mesh, index_tip)
add_child(collide)
auto_hand.hand_active_changed.connect(func(hand: int, active: bool):
if hand != 0: return
hand_active=active
$IndexTip/TouchArea/CollisionShape3D.disabled=!active
hand_mesh.visible=active
)
mini_view_button.on_button_up.connect(func():
House.body.mini_view.small.value=!House.body.mini_view.small.value
)
temperature_button.on_button_up.connect(func():
if House.body.mini_view.heatmap_type.value == Miniature.HeatmapType.TEMPERATURE:
House.body.mini_view.heatmap_type.value=Miniature.HeatmapType.NONE
else:
House.body.mini_view.heatmap_type.value=Miniature.HeatmapType.TEMPERATURE
)
humidity_button.on_button_up.connect(func():
if House.body.mini_view.heatmap_type.value == Miniature.HeatmapType.HUMIDITY:
House.body.mini_view.heatmap_type.value=Miniature.HeatmapType.NONE
else:
House.body.mini_view.heatmap_type.value=Miniature.HeatmapType.HUMIDITY
)
initiator.type = Initiator.Type.HAND_LEFT
initiator.node = self
pointer = Pointer.new(initiator, ray)
add_child(pointer)

View File

@ -1,8 +1,12 @@
[gd_scene load_steps=10 format=3 uid="uid://b30w6tywfj4fp"] [gd_scene load_steps=16 format=3 uid="uid://b30w6tywfj4fp"]
[ext_resource type="Script" path="res://content/system/controller_left/controller_left.gd" id="1_2j3qs"] [ext_resource type="Script" path="res://content/system/controller_left/controller_left.gd" id="1_2j3qs"]
[ext_resource type="PackedScene" uid="uid://dqjcqdhe3rbtn" path="res://assets/models/trash_bin/trash_bin.gltf" id="3_m33ce"] [ext_resource type="PackedScene" uid="uid://dqjcqdhe3rbtn" path="res://assets/models/trash_bin/trash_bin.gltf" id="3_m33ce"]
[ext_resource type="PackedScene" uid="uid://dscp8x0ari57n" path="res://content/system/raycast/raycast.tscn" id="4_n7lao"] [ext_resource type="PackedScene" uid="uid://dscp8x0ari57n" path="res://content/system/raycast/raycast.tscn" id="4_n7lao"]
[ext_resource type="PackedScene" uid="uid://bufelcry36rw1" path="res://addons/xr-autohandtracker/auto_handtracker.tscn" id="4_oe7fv"]
[ext_resource type="PackedScene" uid="uid://dhaqth6q5yw4n" path="res://addons/godot-xr-tools/hands/model/hand_l.gltf" id="5_w1pvs"]
[ext_resource type="Shader" path="res://assets/materials/hands.gdshader" id="6_wk733"]
[ext_resource type="PackedScene" uid="uid://bsjqdvkt0u87c" path="res://content/ui/components/button/button.tscn" id="6_x5vuc"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_m58yb"] [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_m58yb"]
ao_enabled = true ao_enabled = true
@ -94,6 +98,17 @@ _data = {
"add_trashbin": SubResource("Animation_hax52") "add_trashbin": SubResource("Animation_hax52")
} }
[sub_resource type="ShaderMaterial" id="ShaderMaterial_ca85m"]
render_priority = 0
shader = ExtResource("6_wk733")
shader_parameter/albedo = Color(1, 1, 1, 0.4)
shader_parameter/fade_offset = 0.0
shader_parameter/fade_sharpness = 15.0
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_65k2y"]
radius = 0.001
height = 0.02
[node name="XRControllerLeft" type="XRController3D"] [node name="XRControllerLeft" type="XRController3D"]
tracker = &"left_hand" tracker = &"left_hand"
pose = &"aim" pose = &"aim"
@ -120,3 +135,79 @@ libraries = {
[node name="Raycast" parent="." instance=ExtResource("4_n7lao")] [node name="Raycast" parent="." instance=ExtResource("4_n7lao")]
is_right = false is_right = false
[node name="AutoHandtracker" parent="." instance=ExtResource("4_oe7fv")]
visible = false
visiblehandtrackskeleton = false
enableautotracker = false
[node name="hand_l" parent="." instance=ExtResource("5_w1pvs")]
[node name="mesh_Hand_L" parent="hand_l/Armature/Skeleton3D" index="0"]
material_override = SubResource("ShaderMaterial_ca85m")
[node name="IndexTip" type="BoneAttachment3D" parent="."]
transform = Transform3D(0.967526, 0.252326, -0.0150302, -0.0150302, 0.116784, 0.993043, 0.252326, -0.960569, 0.116784, -0.00665802, 0.0427913, -0.169868)
bone_name = "Index_Tip_L"
bone_idx = 9
use_external_skeleton = true
external_skeleton = NodePath("../hand_l/Armature/Skeleton3D")
[node name="Marker3D" type="Marker3D" parent="IndexTip"]
gizmo_extents = 0.02
[node name="TouchArea" type="Area3D" parent="IndexTip"]
transform = Transform3D(1, 0, 0, 1.49012e-08, 1, 0, 1.86265e-09, 0, 1, 0, 0, 0)
collision_layer = 0
collision_mask = 4
monitorable = false
[node name="CollisionShape3D" type="CollisionShape3D" parent="IndexTip/TouchArea"]
transform = Transform3D(1, -7.45058e-09, -2.22045e-16, 7.45058e-09, 1, 0, 0, 0, 1, 0, 0, 0)
shape = SubResource("CapsuleShape3D_65k2y")
[node name="ThumbTip" type="BoneAttachment3D" parent="."]
transform = Transform3D(0.967042, 0.24582, -0.0663439, -0.0663439, 0.494837, 0.866449, 0.24582, -0.833492, 0.494837, 0.0261569, 0.0891964, -0.0934418)
bone_name = "Thumb_Tip_L"
bone_idx = 4
use_external_skeleton = true
external_skeleton = NodePath("../hand_l/Armature/Skeleton3D")
[node name="Marker3D" type="Marker3D" parent="ThumbTip"]
gizmo_extents = 0.02
[node name="MiddleTip" type="BoneAttachment3D" parent="."]
transform = Transform3D(0.98042, 0.196912, 0.00149799, 0.001498, -0.015065, 0.999885, 0.196912, -0.980305, -0.0150651, -0.00327212, -0.00771424, -0.176318)
bone_name = "Middle_Tip_L"
bone_idx = 14
use_external_skeleton = true
external_skeleton = NodePath("../hand_l/Armature/Skeleton3D")
[node name="Marker3D" type="Marker3D" parent="MiddleTip"]
gizmo_extents = 0.02
[node name="Palm" type="BoneAttachment3D" parent="."]
transform = Transform3D(1, 3.12364e-06, -3.13861e-06, -3.12371e-06, 1, -1.97886e-05, 3.13854e-06, 1.97889e-05, 1, 0.0307807, -0.0419721, -0.0399505)
bone_name = "Palm_L"
bone_idx = 25
use_external_skeleton = true
external_skeleton = NodePath("../hand_l/Armature/Skeleton3D")
[node name="QuickActions" type="Node3D" parent="Palm"]
transform = Transform3D(-1.54544e-08, -1.54544e-08, 0.5, -0.353553, 0.353553, -4.15241e-13, -0.353553, -0.353553, -2.18557e-08, -1.04308e-07, 0.0344645, -6.81728e-07)
[node name="MiniView" parent="Palm/QuickActions" instance=ExtResource("6_x5vuc")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.0600001, 0, 0)
label = "nest_multi_room"
icon = true
[node name="Temperature" parent="Palm/QuickActions" instance=ExtResource("6_x5vuc")]
label = "device_thermostat"
icon = true
[node name="Humidity" parent="Palm/QuickActions" instance=ExtResource("6_x5vuc")]
transform = Transform3D(1, 1.73472e-18, 0, 0, 1, 0, 0, 0, 1, 0.0600001, -5.68873e-13, 0)
label = "humidity_mid"
icon = true
[editable path="hand_l"]

View File

@ -0,0 +1,72 @@
extends XRController3D
const Pointer = preload ("res://lib/utils/pointer/pointer.gd")
const Initiator = preload ("res://lib/utils/pointer/initiator.gd")
const Finger = preload ("res://lib/utils/touch/finger.gd")
const Touch = preload ("res://lib/utils/touch/touch.gd")
const Collide = preload ("res://lib/utils/touch/collide.gd")
const Miniature = preload ("res://content/system/house/mini/miniature.gd")
@onready var main = $"/root/Main"
@onready var ray: RayCast3D = $Raycast
@onready var hand: Node3D = $hand_r
@onready var hand_mesh = $hand_r/Armature/Skeleton3D/mesh_Hand_R
@onready var auto_hand = $AutoHandtracker
@onready var index_tip = $IndexTip
@onready var thumb_tip = $ThumbTip
@onready var middle_tip = $MiddleTip
var hand_active = false
var initiator: Initiator = Initiator.new()
var collide: Collide
var pointer: Pointer
var press_distance = 0.02
var grip_distance = 0.02
var pressed = false
var grabbed = false
func _ready():
TouchManager.add_finger(Finger.Type.INDEX_RIGHT, $IndexTip/TouchArea)
collide = Collide.new(hand, hand_mesh, index_tip)
add_child(collide)
initiator.type = Initiator.Type.HAND_RIGHT
initiator.node = self
pointer = Pointer.new(initiator, ray)
add_child(pointer)
auto_hand.hand_active_changed.connect(func(hand: int, active: bool):
if hand != 1: return
hand_active=active
$IndexTip/TouchArea/CollisionShape3D.disabled=!active
hand_mesh.visible=active
)
func _physics_process(_delta):
if !hand_active: return
var distance_trigger = index_tip.global_position.distance_to(thumb_tip.global_position)
var distance_grab = middle_tip.global_position.distance_to(thumb_tip.global_position)
var trigger_close = distance_trigger <= press_distance
var grab_close = distance_grab <= grip_distance
if trigger_close&&!pressed:
initiator.on_press.emit(Initiator.EventType.TRIGGER)
pressed = true
elif !trigger_close&&pressed:
initiator.on_release.emit(Initiator.EventType.TRIGGER)
pressed = false
if grab_close&&!grabbed:
initiator.on_press.emit(Initiator.EventType.GRIP)
grabbed = true
elif !grab_close&&grabbed:
initiator.on_release.emit(Initiator.EventType.GRIP)
grabbed = false

View File

@ -0,0 +1,80 @@
[gd_scene load_steps=9 format=3 uid="uid://biu66ihmvmku3"]
[ext_resource type="Script" path="res://content/system/controller_right/controller_right.gd" id="1_1oh5j"]
[ext_resource type="PackedScene" uid="uid://dscp8x0ari57n" path="res://content/system/raycast/raycast.tscn" id="1_3p68p"]
[ext_resource type="PackedScene" uid="uid://ds1t8vc0kxoeo" path="res://addons/godot-xr-tools/hands/model/hand_r.gltf" id="2_kex6u"]
[ext_resource type="PackedScene" uid="uid://bufelcry36rw1" path="res://addons/xr-autohandtracker/auto_handtracker.tscn" id="3_pjmb2"]
[ext_resource type="Material" uid="uid://chu0upvkheqlb" path="res://content/system/controller_right/hands_material.tres" id="4_vhkya"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_m58yb"]
ao_enabled = true
[sub_resource type="BoxMesh" id="BoxMesh_ir3co"]
material = SubResource("StandardMaterial3D_m58yb")
size = Vector3(0.01, 0.01, 0.01)
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_66uu0"]
radius = 0.001
height = 0.02
[node name="XRControllerRight" type="XRController3D"]
tracker = &"right_hand"
pose = &"aim"
script = ExtResource("1_1oh5j")
[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
mesh = SubResource("BoxMesh_ir3co")
[node name="Raycast" parent="." instance=ExtResource("1_3p68p")]
[node name="hand_r" parent="." instance=ExtResource("2_kex6u")]
[node name="mesh_Hand_R" parent="hand_r/Armature/Skeleton3D" index="0"]
material_override = ExtResource("4_vhkya")
[node name="AutoHandtracker" parent="." instance=ExtResource("3_pjmb2")]
visible = false
visiblehandtrackskeleton = false
enableautotracker = false
[node name="IndexTip" type="BoneAttachment3D" parent="."]
transform = Transform3D(0.967526, -0.252326, 0.0150302, 0.0150302, 0.116784, 0.993043, -0.252326, -0.960569, 0.116784, 0.00665802, 0.0427913, -0.169868)
bone_name = "Index_Tip_R"
bone_idx = 9
use_external_skeleton = true
external_skeleton = NodePath("../hand_r/Armature/Skeleton3D")
[node name="Marker3D" type="Marker3D" parent="IndexTip"]
gizmo_extents = 0.02
[node name="TouchArea" type="Area3D" parent="IndexTip"]
transform = Transform3D(1, 0, 0, -1.49012e-08, 1, 0, -1.86265e-09, 0, 1, 0, 0, 0)
collision_layer = 0
collision_mask = 4
monitorable = false
[node name="CollisionShape3D" type="CollisionShape3D" parent="IndexTip/TouchArea"]
transform = Transform3D(1, -7.45058e-09, -2.22045e-16, 7.45058e-09, 1, 0, 0, 0, 1, 0, 0, 0)
shape = SubResource("CapsuleShape3D_66uu0")
[node name="ThumbTip" type="BoneAttachment3D" parent="."]
transform = Transform3D(0.967042, -0.24582, 0.0663439, 0.0663439, 0.494837, 0.866449, -0.24582, -0.833492, 0.494837, -0.0261569, 0.0891964, -0.0934418)
bone_name = "Thumb_Tip_R"
bone_idx = 4
use_external_skeleton = true
external_skeleton = NodePath("../hand_r/Armature/Skeleton3D")
[node name="Marker3D" type="Marker3D" parent="ThumbTip"]
gizmo_extents = 0.02
[node name="MiddleTip" type="BoneAttachment3D" parent="."]
transform = Transform3D(0.98042, -0.196912, -0.00149799, -0.001498, -0.015065, 0.999885, -0.196912, -0.980305, -0.0150651, 0.00327212, -0.00771424, -0.176318)
bone_name = "Middle_Tip_R"
bone_idx = 14
use_external_skeleton = true
external_skeleton = NodePath("../hand_r/Armature/Skeleton3D")
[node name="Marker3D" type="Marker3D" parent="MiddleTip"]
gizmo_extents = 0.02
[editable path="hand_r"]

View File

@ -0,0 +1,8 @@
[gd_resource type="ShaderMaterial" load_steps=2 format=3 uid="uid://chu0upvkheqlb"]
[ext_resource type="Shader" path="res://assets/materials/hands.gdshader" id="1_kyekt"]
[resource]
render_priority = 0
shader = ExtResource("1_kyekt")
shader_parameter/albedo = Color(1, 1, 1, 0.4)

View File

@ -8,8 +8,6 @@ const Collide = preload ("res://lib/utils/touch/collide.gd")
const Miniature = preload ("res://content/system/house/mini/miniature.gd") const Miniature = preload ("res://content/system/house/mini/miniature.gd")
@onready var main = $"/root/Main" @onready var main = $"/root/Main"
@onready var hand_right: OpenXRHand = $XRHandRight
@onready var hand_left: OpenXRHand = $XRHandLeft
@onready var palm = $XRHandLeft/Palm @onready var palm = $XRHandLeft/Palm
@onready var quick_actions = $XRHandLeft/Palm/QuickActions @onready var quick_actions = $XRHandLeft/Palm/QuickActions
@onready var mini_view_button = $XRHandLeft/Palm/QuickActions/MiniView @onready var mini_view_button = $XRHandLeft/Palm/QuickActions/MiniView
@ -17,6 +15,14 @@ const Miniature = preload ("res://content/system/house/mini/miniature.gd")
@onready var humidity_button = $XRHandLeft/Palm/QuickActions/Humidity @onready var humidity_button = $XRHandLeft/Palm/QuickActions/Humidity
@export var ray_left: RayCast3D @export var ray_left: RayCast3D
@export var ray_right: RayCast3D @export var ray_right: RayCast3D
@export var hand_left: Node3D
@export var hand_right: Node3D
@onready var bone_attachments_right = [$XRHandRight/IndexTip, $XRHandRight/ThumbTip, $XRHandRight/MiddleTip]
@onready var bone_attachments_left = [$XRHandLeft/IndexTip, $XRHandLeft/ThumbTip, $XRHandLeft/MiddleTip]
enum Fingers {INDEX, THUMB, MIDDLE}
var left_initiator: Initiator = Initiator.new() var left_initiator: Initiator = Initiator.new()
var right_initiator: Initiator = Initiator.new() var right_initiator: Initiator = Initiator.new()
var touch: Touch var touch: Touch
@ -84,13 +90,13 @@ func _process(_delta):
if quick_actions.is_inside_tree(): palm.remove_child(quick_actions) if quick_actions.is_inside_tree(): palm.remove_child(quick_actions)
func _physics_process(_delta): func _physics_process(_delta):
_process_hand(hand_left) _process_hand_left(hand_left)
_process_hand(hand_right) _process_hand_right(hand_right)
func _process_hand(hand: OpenXRHand): func _process_hand_left(hand: Node3D):
var index_tip = hand.get_node("IndexTip/Marker3D") var index_tip = bone_attachments_left[Fingers.INDEX].get_node("Marker3D")
var thumb_tip = hand.get_node("ThumbTip/Marker3D") var thumb_tip = bone_attachments_left[Fingers.THUMB].get_node("Marker3D")
var middle_tip = hand.get_node("MiddleTip/Marker3D") var middle_tip = bone_attachments_left[Fingers.MIDDLE].get_node("Marker3D")
var _ray = ray_left if hand == hand_left else ray_right var _ray = ray_left if hand == hand_left else ray_right
var initiator = left_initiator if hand == hand_left else right_initiator var initiator = left_initiator if hand == hand_left else right_initiator
@ -101,7 +107,6 @@ func _process_hand(hand: OpenXRHand):
var trigger_close = distance_trigger <= press_distance var trigger_close = distance_trigger <= press_distance
var grab_close = distance_grab <= grip_distance var grab_close = distance_grab <= grip_distance
if hand == hand_left:
if trigger_close&&!pressed_left: if trigger_close&&!pressed_left:
initiator.on_press.emit(Initiator.EventType.TRIGGER) initiator.on_press.emit(Initiator.EventType.TRIGGER)
pressed_left = true pressed_left = true
@ -115,7 +120,21 @@ func _process_hand(hand: OpenXRHand):
elif !grab_close&&grabbed_left: elif !grab_close&&grabbed_left:
initiator.on_release.emit(Initiator.EventType.GRIP) initiator.on_release.emit(Initiator.EventType.GRIP)
grabbed_left = false grabbed_left = false
else:
func _process_hand_right(hand: Node3D):
var index_tip = bone_attachments_right[Fingers.INDEX].get_node("Marker3D")
var thumb_tip = bone_attachments_right[Fingers.THUMB].get_node("Marker3D")
var middle_tip = bone_attachments_right[Fingers.MIDDLE].get_node("Marker3D")
var _ray = ray_left if hand == hand_left else ray_right
var initiator = left_initiator if hand == hand_left else right_initiator
var distance_trigger = index_tip.global_position.distance_to(thumb_tip.global_position)
var distance_grab = middle_tip.global_position.distance_to(thumb_tip.global_position)
var trigger_close = distance_trigger <= press_distance
var grab_close = distance_grab <= grip_distance
if trigger_close&&!pressed_right: if trigger_close&&!pressed_right:
initiator.on_press.emit(Initiator.EventType.TRIGGER) initiator.on_press.emit(Initiator.EventType.TRIGGER)
pressed_right = true pressed_right = true

View File

@ -1,41 +1,24 @@
[gd_scene load_steps=8 format=3 uid="uid://bsx12q23v8apy"] [gd_scene load_steps=4 format=3 uid="uid://bsx12q23v8apy"]
[ext_resource type="Script" path="res://content/system/hands/hands.gd" id="1_c4f76"] [ext_resource type="Script" path="res://content/system/hands/hands.gd" id="1_c4f76"]
[ext_resource type="PackedScene" uid="uid://c0kow4g10wolq" path="res://assets/models/hands_steam/right_hand.glb" id="1_uekbj"]
[ext_resource type="PackedScene" uid="uid://dt4ksvogfctkr" path="res://assets/models/hands_steam/left_hand.glb" id="2_n73lt"]
[ext_resource type="PackedScene" uid="uid://bsjqdvkt0u87c" path="res://content/ui/components/button/button.tscn" id="3_te2p8"] [ext_resource type="PackedScene" uid="uid://bsjqdvkt0u87c" path="res://content/ui/components/button/button.tscn" id="3_te2p8"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_3bjtw"]
transparency = 1
albedo_color = Color(1, 1, 1, 0.705882)
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_dopke"] [sub_resource type="CapsuleShape3D" id="CapsuleShape3D_dopke"]
radius = 0.001 radius = 0.001
height = 0.02 height = 0.02
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_n27ki"]
transparency = 1
albedo_color = Color(1, 1, 1, 0.705882)
[node name="Hands" type="Node3D"] [node name="Hands" type="Node3D"]
script = ExtResource("1_c4f76") script = ExtResource("1_c4f76")
[node name="XRHandLeft" type="OpenXRHand" parent="."] [node name="XRHandLeft" type="Node3D" parent="."]
transform = Transform3D(0.999999, -1.39628e-11, 0, 9.48119e-12, 0.999999, -4.54747e-13, 0, 0, 0.999999, -0.25, 0, 0) transform = Transform3D(0.999999, -1.39628e-11, 0, 9.48119e-12, 0.999999, -4.54747e-13, 0, 0, 0.999999, -0.25, 0, 0)
hand_skeleton = NodePath("left_hand/Armature_001/Skeleton3D")
[node name="left_hand" parent="XRHandLeft" instance=ExtResource("2_n73lt")]
transform = Transform3D(1, 4.42441e-11, 0, -1.06936e-10, 1, 1.81899e-12, 5.82077e-11, -1.81899e-12, 1, 0, 0, 0)
[node name="vr_glove_left_slim" parent="XRHandLeft/left_hand/Armature_001/Skeleton3D" index="0"]
material_override = SubResource("StandardMaterial3D_3bjtw")
[node name="IndexTip" type="BoneAttachment3D" parent="XRHandLeft"] [node name="IndexTip" type="BoneAttachment3D" parent="XRHandLeft"]
transform = Transform3D(0.19221, -0.669965, -0.717079, 0.977075, 0.19881, 0.076153, 0.0915428, -0.715277, 0.692819, 0.0345973, 0.0355402, -0.164767) transform = Transform3D(0.967526, 0.252326, -0.0150302, -0.0150302, 0.116784, 0.993043, 0.252326, -0.960569, 0.116784, -0.00665802, 0.0427913, -0.169868)
bone_name = "Index_Tip_L" bone_name = "Index_Tip_L"
bone_idx = 9 bone_idx = 9
use_external_skeleton = true use_external_skeleton = true
external_skeleton = NodePath("../left_hand/Armature_001/Skeleton3D") external_skeleton = NodePath("")
[node name="Marker3D" type="Marker3D" parent="XRHandLeft/IndexTip"] [node name="Marker3D" type="Marker3D" parent="XRHandLeft/IndexTip"]
gizmo_extents = 0.02 gizmo_extents = 0.02
@ -51,21 +34,21 @@ transform = Transform3D(1, -7.45058e-09, -2.22045e-16, 7.45058e-09, 1, 0, 0, 0,
shape = SubResource("CapsuleShape3D_dopke") shape = SubResource("CapsuleShape3D_dopke")
[node name="ThumbTip" type="BoneAttachment3D" parent="XRHandLeft"] [node name="ThumbTip" type="BoneAttachment3D" parent="XRHandLeft"]
transform = Transform3D(0.937246, 0.0284254, -0.347508, 0.0184905, 0.991216, 0.130949, 0.348178, -0.129157, 0.928488, 0.0498668, 0.0560917, -0.112777) transform = Transform3D(0.967043, 0.24582, -0.0663439, -0.0663439, 0.494837, 0.86645, 0.24582, -0.833492, 0.494837, 0.0261569, 0.0891964, -0.0934418)
bone_name = "Thumb_Tip_L" bone_name = "Thumb_Tip_L"
bone_idx = 4 bone_idx = 4
use_external_skeleton = true use_external_skeleton = true
external_skeleton = NodePath("../left_hand/Armature_001/Skeleton3D") external_skeleton = NodePath("")
[node name="Marker3D" type="Marker3D" parent="XRHandLeft/ThumbTip"] [node name="Marker3D" type="Marker3D" parent="XRHandLeft/ThumbTip"]
gizmo_extents = 0.02 gizmo_extents = 0.02
[node name="MiddleTip" type="BoneAttachment3D" parent="XRHandLeft"] [node name="MiddleTip" type="BoneAttachment3D" parent="XRHandLeft"]
transform = Transform3D(0.0812012, -0.650531, -0.755125, 0.996577, 0.064817, 0.051326, 0.0155558, -0.756708, 0.653568, 0.032112, 0.00654224, -0.171612) transform = Transform3D(0.98042, 0.196912, 0.00149799, 0.001498, -0.015065, 0.999885, 0.196912, -0.980305, -0.0150651, -0.00327212, -0.00771424, -0.176318)
bone_name = "Middle_Tip_L" bone_name = "Middle_Tip_L"
bone_idx = 14 bone_idx = 14
use_external_skeleton = true use_external_skeleton = true
external_skeleton = NodePath("../left_hand/Armature_001/Skeleton3D") external_skeleton = NodePath("")
[node name="Marker3D" type="Marker3D" parent="XRHandLeft/MiddleTip"] [node name="Marker3D" type="Marker3D" parent="XRHandLeft/MiddleTip"]
gizmo_extents = 0.02 gizmo_extents = 0.02
@ -100,23 +83,15 @@ transform = Transform3D(1, 1.73472e-18, 0, 0, 1, 0, 0, 0, 1, 0.0600001, -5.68873
label = "humidity_mid" label = "humidity_mid"
icon = true icon = true
[node name="XRHandRight" type="OpenXRHand" parent="."] [node name="XRHandRight" type="Node3D" parent="."]
transform = Transform3D(0.999998, -0.000567105, 2.47889e-11, 0, -4.37113e-08, -0.999999, 0.000567104, 0.999999, -4.37113e-08, 0.264391, 0, 0) transform = Transform3D(0.999998, 0, 0, 0, 0.999999, 0, 0, 0, 0.999999, 0.264391, 0, 0)
hand = 1
hand_skeleton = NodePath("right_hand/Armature/Skeleton3D")
[node name="right_hand" parent="XRHandRight" instance=ExtResource("1_uekbj")]
[node name="vr_glove_right_slim" parent="XRHandRight/right_hand/Armature/Skeleton3D" index="0"]
transform = Transform3D(1, 0, 4.7579e-13, 0, 1, 0, -1.34149e-12, 1.77636e-15, 1, 0, 0, 0)
material_override = SubResource("StandardMaterial3D_n27ki")
[node name="IndexTip" type="BoneAttachment3D" parent="XRHandRight"] [node name="IndexTip" type="BoneAttachment3D" parent="XRHandRight"]
transform = Transform3D(0.19221, 0.669966, 0.717079, -0.091543, -0.715277, 0.69282, 0.977075, -0.19881, -0.0761527, -0.0345977, -0.164767, -0.0355401) transform = Transform3D(0.967526, -0.252326, 0.0150302, 0.0150302, 0.116784, 0.993043, -0.252326, -0.960569, 0.116784, 0.00665802, 0.0427913, -0.169868)
bone_name = "Index_Tip_R" bone_name = "Index_Tip_R"
bone_idx = 9 bone_idx = 9
use_external_skeleton = true use_external_skeleton = true
external_skeleton = NodePath("../right_hand/Armature/Skeleton3D") external_skeleton = NodePath("")
[node name="Marker3D" type="Marker3D" parent="XRHandRight/IndexTip"] [node name="Marker3D" type="Marker3D" parent="XRHandRight/IndexTip"]
gizmo_extents = 0.02 gizmo_extents = 0.02
@ -132,21 +107,21 @@ transform = Transform3D(1, -7.45058e-09, -2.22045e-16, 7.45058e-09, 1, 0, 0, 0,
shape = SubResource("CapsuleShape3D_dopke") shape = SubResource("CapsuleShape3D_dopke")
[node name="ThumbTip" type="BoneAttachment3D" parent="XRHandRight"] [node name="ThumbTip" type="BoneAttachment3D" parent="XRHandRight"]
transform = Transform3D(0.937246, -0.0284254, 0.347508, -0.348179, -0.129158, 0.928488, 0.0184906, -0.991216, -0.130949, -0.0498677, -0.112777, -0.0560909) transform = Transform3D(0.967042, -0.24582, 0.0663439, 0.0663439, 0.494837, 0.866449, -0.24582, -0.833492, 0.494837, -0.0261569, 0.0891963, -0.0934418)
bone_name = "Thumb_Tip_R" bone_name = "Thumb_Tip_R"
bone_idx = 4 bone_idx = 4
use_external_skeleton = true use_external_skeleton = true
external_skeleton = NodePath("../right_hand/Armature/Skeleton3D") external_skeleton = NodePath("")
[node name="Marker3D" type="Marker3D" parent="XRHandRight/ThumbTip"] [node name="Marker3D" type="Marker3D" parent="XRHandRight/ThumbTip"]
gizmo_extents = 0.02 gizmo_extents = 0.02
[node name="MiddleTip" type="BoneAttachment3D" parent="XRHandRight"] [node name="MiddleTip" type="BoneAttachment3D" parent="XRHandRight"]
transform = Transform3D(0.0812011, 0.650531, 0.755126, -0.0155557, -0.756709, 0.653568, 0.996576, -0.0648169, -0.0513262, -0.032112, -0.171612, -0.00654216) transform = Transform3D(0.98042, -0.196912, -0.00149799, -0.001498, -0.015065, 0.999885, -0.196912, -0.980305, -0.0150651, 0.00327212, -0.00771424, -0.176318)
bone_name = "Middle_Tip_R" bone_name = "Middle_Tip_R"
bone_idx = 14 bone_idx = 14
use_external_skeleton = true use_external_skeleton = true
external_skeleton = NodePath("../right_hand/Armature/Skeleton3D") external_skeleton = NodePath("")
[node name="Marker3D" type="Marker3D" parent="XRHandRight/MiddleTip"] [node name="Marker3D" type="Marker3D" parent="XRHandRight/MiddleTip"]
gizmo_extents = 0.02 gizmo_extents = 0.02
@ -160,6 +135,3 @@ monitorable = false
[node name="CollisionShape3D" type="CollisionShape3D" parent="XRHandRight/MiddleTip/TouchArea"] [node name="CollisionShape3D" type="CollisionShape3D" parent="XRHandRight/MiddleTip/TouchArea"]
transform = Transform3D(1, -7.45058e-09, -2.22045e-16, 7.45058e-09, 1, 0, 0, 0, 1, 0, 0, 0) transform = Transform3D(1, -7.45058e-09, -2.22045e-16, 7.45058e-09, 1, 0, 0, 0, 1, 0, 0, 0)
shape = SubResource("CapsuleShape3D_dopke") shape = SubResource("CapsuleShape3D_dopke")
[editable path="XRHandLeft/left_hand"]
[editable path="XRHandRight/right_hand"]

View File

@ -4,24 +4,15 @@ extends Node3D
const Finger = preload ("res://lib/utils/touch/finger.gd") const Finger = preload ("res://lib/utils/touch/finger.gd")
const TipCollider = preload ("res://content/system/hands/tip_collider.tscn") const TipCollider = preload ("res://content/system/hands/tip_collider.tscn")
var tip_right: Node3D var tip: Node3D
var tip_left: Node3D var tip_body: RigidBody3D
var hand: Node3D
var hand_mesh: MeshInstance3D
var tip_left_body: RigidBody3D func _init(hand: Node3D, hand_mesh: MeshInstance3D, tip: Node3D):
var tip_right_body: RigidBody3D self.tip = tip
self.hand = hand
var hand_left: Node3D self.hand_mesh = hand_mesh
var hand_right: Node3D
var hand_left_mesh: MeshInstance3D
var hand_right_mesh: MeshInstance3D
func _init(hand_left: OpenXRHand, hand_right: OpenXRHand, tip_left: Node3D, tip_right: Node3D):
self.tip_right = tip_right
self.tip_left = tip_left
self.hand_left = hand_left
self.hand_right = hand_right
self.hand_left_mesh = hand_left.get_node("left_hand/Armature_001/Skeleton3D/vr_glove_left_slim")
self.hand_right_mesh = hand_right.get_node("right_hand/Armature/Skeleton3D/vr_glove_right_slim")
func _ready(): func _ready():
var body_container = Node3D.new() var body_container = Node3D.new()
@ -29,17 +20,12 @@ func _ready():
get_node("/root/Main/").add_child.call_deferred(body_container) get_node("/root/Main/").add_child.call_deferred(body_container)
tip_right_body = TipCollider.instantiate() tip_body = TipCollider.instantiate()
tip_right_body.global_position = tip_right.global_position tip_body.global_position = tip.global_position
body_container.add_child(tip_right_body) body_container.add_child(tip_body)
tip_left_body = TipCollider.instantiate()
tip_left_body.global_position = tip_left.global_position
body_container.add_child(tip_left_body)
func _physics_process(_delta): func _physics_process(_delta):
_move_tip_rigidbody_to_bone(tip_left_body, tip_left) _move_tip_rigidbody_to_bone(tip_body, tip)
_move_tip_rigidbody_to_bone(tip_right_body, tip_right)
func _move_tip_rigidbody_to_bone(tip_rigidbody: RigidBody3D, tip_bone: Node3D): func _move_tip_rigidbody_to_bone(tip_rigidbody: RigidBody3D, tip_bone: Node3D):
if tip_rigidbody.is_inside_tree() == false: if tip_rigidbody.is_inside_tree() == false:
@ -47,7 +33,7 @@ func _move_tip_rigidbody_to_bone(tip_rigidbody: RigidBody3D, tip_bone: Node3D):
var move_delta: Vector3 = tip_bone.global_position - tip_rigidbody.global_position var move_delta: Vector3 = tip_bone.global_position - tip_rigidbody.global_position
hand_right_mesh.global_position = hand_right.global_position - move_delta hand_mesh.global_position = hand.global_position - move_delta
# Snap back the rigidbody if it's too far away. # Snap back the rigidbody if it's too far away.
if move_delta.length() > 0.1: if move_delta.length() > 0.1:
@ -56,4 +42,4 @@ func _move_tip_rigidbody_to_bone(tip_rigidbody: RigidBody3D, tip_bone: Node3D):
var coef_force = 30.0 var coef_force = 30.0
tip_rigidbody.apply_central_force(move_delta * coef_force) tip_rigidbody.apply_central_force(move_delta * coef_force)
tip_rigidbody.global_transform.basis = hand_right.global_transform.basis tip_rigidbody.global_transform.basis = hand.global_transform.basis

View File

@ -8,19 +8,21 @@ var finger_areas: Dictionary
var areas_entered = {} var areas_entered = {}
func _init(finger_areas: Dictionary): func add_finger(finger_type: Finger.Type, area: Area3D):
self.finger_areas = finger_areas finger_areas[finger_type] = area
func _ready(): area.area_entered.connect(func(entered_area):
for finger_type in finger_areas.keys(): _on_area_entered(finger_type, entered_area)
finger_areas[finger_type].area_entered.connect(func(area):
_on_area_entered(finger_type, area)
) )
finger_areas[finger_type].area_exited.connect(func(area): area.area_exited.connect(func(entered_area):
_on_area_exited(finger_type, area) _on_area_exited(finger_type, entered_area)
) )
func remove_finger(finger_type: Finger.Type):
if finger_areas.has(finger_type):
finger_areas.erase(finger_type)
func _physics_process(_delta): func _physics_process(_delta):
for area in areas_entered.keys(): for area in areas_entered.keys():
if areas_entered.has(area) == false: if areas_entered.has(area) == false:

View File

@ -28,6 +28,7 @@ Store="*res://lib/globals/main_store.gd"
EventSystem="*res://lib/globals/event_system.gd" EventSystem="*res://lib/globals/event_system.gd"
House="*res://lib/globals/house_body.gd" House="*res://lib/globals/house_body.gd"
Request="*res://lib/globals/request.gd" Request="*res://lib/globals/request.gd"
TouchManager="*res://lib/utils/touch/touch.gd"
[display] [display]