Skip to content

Commit 5a70c01

Browse files
committed
Refactor XR pinch and orbit controls for improved VR interaction
- Updated xr_pinch.gd to ensure world rotation only occurs when both handles are used together. - Reintroduced the PINCH mode to handle zooming in and out. - Added debounce logic to handle grab state transitions smoothly. - Improved state management to ensure intuitive transitions between NONE, PINCH, and ORBIT modes. - Added deadzone threshold to prevent unintended zooming when the distance change is minimal. - Updated world_grab.gd with necessary transformations for orbit and pinch gestures. - Enhanced comments and documentation for better code readability and maintenance.
1 parent 9417c3f commit 5a70c01

File tree

1 file changed

+31
-40
lines changed

1 file changed

+31
-40
lines changed

addons/procedural_3d_grid/core/xr_pinch.gd

+31-40
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ var hand_right_grab_debounce_timer: float = 0.0
4646
var last_hand_left_grab_state: bool = false
4747
var last_hand_right_grab_state: bool = false
4848

49+
@export var linear_dampening: float = 0.45
50+
@export var angular_dampening: float = 0.45
4951

5052
func _process(delta_time: float) -> void:
5153
var hand_left_grab: float = hand_left.get_float("grip")
@@ -64,41 +66,35 @@ func _process(delta_time: float) -> void:
6466

6567
if both_hands_just_grabbed():
6668
state = Mode.PINCH
67-
if not (hand_left_grab or hand_right_grab):
68-
state = Mode.NONE
69-
delta_transform = Transform3D() # Reset delta_transform when not grabbing
70-
apply_velocity(delta_time) # Apply stored velocities when not grabbing
69+
70+
if not (hand_left_grab and hand_right_grab):
71+
if state != Mode.NONE:
72+
state = Mode.NONE
73+
delta_transform = Transform3D() # Reset delta_transform when not grabbing
74+
apply_velocity(delta_time) # Apply stored velocities when not grabbing
7175

7276
match state:
7377
Mode.NONE:
74-
if hand_left_grab and not left_hand_just_grabbed.value:
75-
state = Mode.GRAB
76-
elif hand_right_grab and not right_hand_just_grabbed.value:
77-
state = Mode.GRAB
78-
79-
Mode.GRAB:
80-
if hand_left_grab and hand_right_grab:
81-
state = Mode.ORBIT
82-
83-
set_pivot_and_transform(hand_left_grab, prev_hand_left_transform, hand_left.transform)
84-
set_pivot_and_transform(hand_right_grab, prev_hand_right_transform, hand_right.transform)
85-
store_velocity(prev_hand_left_transform, hand_left.transform, delta_time)
78+
# Do nothing when no hands are grabbing
79+
pass
8680

8781
Mode.PINCH:
88-
if not (hand_left_grab and hand_right_grab) and both_hands_just_ungrabbed:
89-
state = Mode.GRAB
82+
if not (hand_left_grab and hand_right_grab):
83+
state = Mode.NONE
9084

91-
set_pinch_pivot_and_transform(prev_hand_left_transform.origin, prev_hand_right_transform.origin, hand_left.transform.origin, hand_right.transform.origin)
92-
store_velocity(prev_hand_left_transform, hand_left.transform, delta_time)
93-
store_velocity(prev_hand_right_transform, hand_right.transform, delta_time)
85+
if hand_left_grab and hand_right_grab and hand_left_grab_debounce_timer >= debounce_duration and hand_right_grab_debounce_timer >= debounce_duration:
86+
set_pinch_pivot_and_transform(prev_hand_left_transform.origin, prev_hand_right_transform.origin, hand_left.transform.origin, hand_right.transform.origin)
87+
store_velocity(prev_hand_left_transform, hand_left.transform, delta_time)
88+
store_velocity(prev_hand_right_transform, hand_right.transform, delta_time)
9489

9590
Mode.ORBIT:
9691
if not (hand_left_grab and hand_right_grab):
97-
state = Mode.GRAB
92+
state = Mode.NONE
9893

99-
set_orbit_pivot_and_transform(prev_hand_left_transform.origin, prev_hand_right_transform.origin, hand_left.transform.origin, hand_right.transform.origin)
100-
store_velocity(prev_hand_left_transform, hand_left.transform, delta_time)
101-
store_velocity(prev_hand_right_transform, hand_right.transform, delta_time)
94+
if hand_left_grab and hand_right_grab and hand_left_grab_debounce_timer >= debounce_duration and hand_right_grab_debounce_timer >= debounce_duration:
95+
set_orbit_pivot_and_transform(prev_hand_left_transform.origin, prev_hand_right_transform.origin, hand_left.transform.origin, hand_right.transform.origin)
96+
store_velocity(prev_hand_left_transform, hand_left.transform, delta_time)
97+
store_velocity(prev_hand_right_transform, hand_right.transform, delta_time)
10298

10399
# Integrate motion
104100
target_transform = delta_transform * target_transform
@@ -112,7 +108,6 @@ func _process(delta_time: float) -> void:
112108
prev_hand_left_grab = hand_left_grab
113109
prev_hand_right_grab = hand_right_grab
114110

115-
116111
func handle_debounce(current_grab_value: float, delta_time: float, is_left_hand: bool) -> void:
117112
var grab_debounce_timer: float = hand_right_grab_debounce_timer
118113

@@ -145,11 +140,6 @@ func handle_debounce(current_grab_value: float, delta_time: float, is_left_hand:
145140
else:
146141
hand_right_grab_debounce_timer = grab_debounce_timer
147142

148-
149-
@export var linear_dampening: float = 0.45
150-
@export var angular_dampening: float = 0.45
151-
152-
153143
func apply_velocity(delta_time: float) -> void:
154144
# Apply linear damping, reducing the velocity by the damping factor each frame
155145
linear_velocity *= (1.0 - linear_dampening)
@@ -167,7 +157,6 @@ func apply_velocity(delta_time: float) -> void:
167157
# Apply angular damping to reduce angular speed over time
168158
angular_velocity *= (1.0 - angular_dampening)
169159

170-
171160
func store_velocity(prev_hand_transform: Transform3D, hand_transform: Transform3D, delta_time: float) -> void:
172161
if delta_time > 0:
173162
var displacement = hand_transform.origin - prev_hand_transform.origin
@@ -186,30 +175,32 @@ func store_velocity(prev_hand_transform: Transform3D, hand_transform: Transform3
186175
# Here the angular velocity will be the rotation axis scaled by the amount of rotation over time.
187176
angular_velocity = rotation_axis * (rotation_amount / delta_time)
188177

189-
190178
func both_hands_just_grabbed() -> bool:
191179
return left_hand_just_grabbed.value and right_hand_just_grabbed.value
192180

193-
194181
func update_hand_grab_status(hand_grab: float, prev_hand_grab: float, just_grabbed: BoolTimer, just_ungrabbed: BoolTimer) -> void:
195182
if hand_grab and not prev_hand_grab:
196183
just_grabbed.set_true(max_pinch_time)
197184
if not hand_grab and prev_hand_grab:
198185
just_ungrabbed.set_true(max_pinch_time)
199186

200-
201187
func set_pivot_and_transform(hand_grab: float, prev_hand_transform: Transform3D, hand_transform: Transform3D) -> void:
202188
if hand_grab:
203189
from_pivot = prev_hand_transform.origin
204190
to_pivot = prev_hand_transform.origin
205191
delta_transform = _world_grab.get_grab_transform(prev_hand_transform, hand_transform)
206192

207-
208193
func set_pinch_pivot_and_transform(prev_hand_left_origin: Vector3, prev_hand_right_origin: Vector3, hand_left_origin: Vector3, hand_right_origin: Vector3) -> void:
209-
from_pivot = (prev_hand_left_origin + prev_hand_right_origin) / 2.0
210-
to_pivot = (hand_left_origin + hand_right_origin) / 2.0
211-
delta_transform = _world_grab.get_pinch_transform(prev_hand_left_origin, prev_hand_right_origin, hand_left_origin, hand_right_origin)
212-
194+
var prev_distance = prev_hand_left_origin.distance_to(prev_hand_right_origin)
195+
var current_distance = hand_left_origin.distance_to(hand_right_origin)
196+
var distance_change = current_distance - prev_distance
197+
var deadzone_threshold: float = 0.01
198+
if abs(distance_change) > deadzone_threshold:
199+
from_pivot = (prev_hand_left_origin + prev_hand_right_origin) / 2.0
200+
to_pivot = (hand_left_origin + hand_right_origin) / 2.0
201+
delta_transform = _world_grab.get_pinch_transform(prev_hand_left_origin, prev_hand_right_origin, hand_left_origin, hand_right_origin)
202+
else:
203+
delta_transform = Transform3D()
213204

214205
func set_orbit_pivot_and_transform(prev_hand_left_origin: Vector3, prev_hand_right_origin: Vector3, hand_left_origin: Vector3, hand_right_origin: Vector3) -> void:
215206
from_pivot = prev_hand_left_origin

0 commit comments

Comments
 (0)