Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement basic collision hands #490

Merged
merged 1 commit into from
Aug 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions VERSIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
- Environments can now be set normally in scenes loaded through the staging system.
- Fixed issue with not being able to push rigid bodies when colliding with them.
- Fixed player movement on slopes.
- Fixed lag in finger-poke.
- Added initial collision hand support.

# 4.1.0
- Enhanced grappling to support collision and target layers
Expand Down
130 changes: 84 additions & 46 deletions addons/godot-xr-tools/functions/movement_climb.gd
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,14 @@ const SNAP_DISTANCE : float = 1.0
@export var velocity_averages : int = 5


## Left climbable
var _left_climbable : XRToolsClimbable
# Left climbing handle
var _left_handle : Node3D

## Right climbable
var _right_climbable : XRToolsClimbable
# Right climbing handle
var _right_handle : Node3D

## Dominant pickup (moving the player)
var _dominant : XRToolsFunctionPickup
# Dominant handle (moving the player)
var _dominant : Node3D


# Velocity averager
Expand All @@ -62,6 +62,18 @@ var _dominant : XRToolsFunctionPickup
# Right pickup node
@onready var _right_pickup_node := XRToolsFunctionPickup.find_right(self)

# Left controller
@onready var _left_controller := XRHelpers.get_left_controller(self)

# Right controller
@onready var _right_controller := XRHelpers.get_right_controller(self)

# Left collision hand
@onready var _left_collision_hand := XRToolsCollisionHand.find_left(self)

# Right collision hand
@onready var _right_collision_hand := XRToolsCollisionHand.find_right(self)


# Add support for is_xr_class on XRTools classes
func is_xr_class(name : String) -> bool:
Expand All @@ -73,6 +85,10 @@ func _ready():
# In Godot 4 we must now manually call our super class ready function
super()

# Do not initialise if in the editor
if Engine.is_editor_hint():
return

# Connect pickup funcitons
if _left_pickup_node.connect("has_picked_up", _on_left_picked_up):
push_error("Unable to connect left picked up signal")
Expand All @@ -91,15 +107,23 @@ func physics_movement(delta: float, player_body: XRToolsPlayerBody, disabled: bo
_set_climbing(false, player_body)
return

# Check for climbing handles being deleted while held
if not is_instance_valid(_left_handle):
_left_handle = null
if not is_instance_valid(_right_handle):
_right_handle = null
if not is_instance_valid(_dominant):
_dominant = null

# Snap grabs if too far
if is_instance_valid(_left_climbable):
var left_pickup_pos := _left_pickup_node.global_transform.origin
var left_grab_pos := _left_climbable.get_grab_location(_left_pickup_node)
if _left_handle:
var left_pickup_pos := _left_controller.global_position
var left_grab_pos = _left_handle.global_position
if left_pickup_pos.distance_to(left_grab_pos) > SNAP_DISTANCE:
_left_pickup_node.drop_object()
if is_instance_valid(_right_climbable):
var right_pickup_pos := _right_pickup_node.global_transform.origin
var right_grab_pos := _right_climbable.get_grab_location(_right_pickup_node)
if _right_handle:
var right_pickup_pos := _right_controller.global_position
var right_grab_pos := _right_handle.global_position
if right_pickup_pos.distance_to(right_grab_pos) > SNAP_DISTANCE:
_right_pickup_node.drop_object()

Expand All @@ -112,22 +136,22 @@ func physics_movement(delta: float, player_body: XRToolsPlayerBody, disabled: bo

# Calculate how much the player has moved
var offset := Vector3.ZERO
if _dominant == _left_pickup_node:
var left_pickup_pos := _left_pickup_node.global_transform.origin
var left_grab_pos := _left_climbable.get_grab_location(_left_pickup_node)
if _dominant == _left_handle:
var left_pickup_pos := _left_controller.global_position
var left_grab_pos := _left_handle.global_position
offset = left_pickup_pos - left_grab_pos
elif _dominant == _right_pickup_node:
var right_pickup_pos := _right_pickup_node.global_transform.origin
var right_grab_pos := _right_climbable.get_grab_location(_right_pickup_node)
elif _dominant == _right_handle:
var right_pickup_pos := _right_controller.global_position
var right_grab_pos := _right_handle.global_position
offset = right_pickup_pos - right_grab_pos

# Move the player by the offset
var old_position := player_body.global_transform.origin
var old_position := player_body.global_position
player_body.move_and_collide(-offset)
player_body.velocity = Vector3.ZERO

# Update the players average-velocity data
var distance := player_body.global_transform.origin - old_position
var distance := player_body.global_position - old_position
_averager.add_distance(delta, distance)

# Report exclusive motion performed (to bypass gravity)
Expand Down Expand Up @@ -165,49 +189,63 @@ func _set_climbing(active: bool, player_body: XRToolsPlayerBody) -> void:
## Handler for left controller picked up
func _on_left_picked_up(what : Node3D) -> void:
# Get the climbable
_left_climbable = what as XRToolsClimbable
var climbable = what as XRToolsClimbable
if not climbable:
return

# Transfer climb dominance
if is_instance_valid(_left_climbable):
_dominant = _left_pickup_node
else:
_left_climbable = null
# Get the handle
_left_handle = climbable.get_grab_handle(_left_pickup_node)
if not _left_handle:
return

# Switch dominance to the left handle
_dominant = _left_handle

# If collision hands present then target the handle
if _left_collision_hand:
_left_collision_hand.add_target_override(_left_handle, 0)


## Handler for right controller picked up
func _on_right_picked_up(what : Node3D) -> void:
# Get the climbable
_right_climbable = what as XRToolsClimbable
var climbable = what as XRToolsClimbable
if not climbable:
return

# Transfer climb dominance
if is_instance_valid(_right_climbable):
_dominant = _right_pickup_node
else:
_right_climbable = null
# Get the handle
_right_handle = climbable.get_grab_handle(_right_pickup_node)
if not _right_handle:
return

# Switch dominance to the right handle
_dominant = _right_handle

# If collision hands present then target the handle
if _right_collision_hand:
_right_collision_hand.add_target_override(_right_handle, 0)


## Handler for left controller dropped
func _on_left_dropped() -> void:
# Release climbable
_left_climbable = null
# If collision hands present then clear handle target
if _left_collision_hand:
_left_collision_hand.remove_target_override(_left_handle)

# Transfer climb dominance
if is_instance_valid(_right_climbable):
_dominant = _right_pickup_node
else:
_dominant = null
# Release handle and transfer dominance
_left_handle = null
_dominant = _right_handle


## Handler for righ controller dropped
func _on_right_dropped() -> void:
# Release climbable
_right_climbable = null
# If collision hands present then clear handle target
if _right_collision_hand:
_right_collision_hand.remove_target_override(_right_handle)

# Transfer climb dominance
if is_instance_valid(_left_climbable):
_dominant = _left_pickup_node
else:
_dominant = null
# Release handle and transfer dominance
_right_handle = null
_dominant = _left_handle


# This method verifies the movement provider has a valid configuration.
Expand Down
Loading
Loading