|
|
|
@ -48,9 +48,30 @@ var triggers = { |
|
|
|
|
"TransgenderPride" : [ 0.35, pride("transgender") ], |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const HAND_CLOSE_THRESHOLD : float = 12.0 |
|
|
|
|
const HAND_OPEN_TRHESHOLD : float = 8.0 |
|
|
|
|
var hands := { |
|
|
|
|
RightHand = { closed = false, collider = null }, |
|
|
|
|
LeftHand = { closed = false, collider = null }, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var queue: Array[RigidBody3D] = [] |
|
|
|
|
var queue_delay := 0.0 |
|
|
|
|
|
|
|
|
|
func scene_init() -> void: |
|
|
|
|
# Reset collider values, in case hands aren't found. |
|
|
|
|
for hand in hands.values(): hand.collider = null |
|
|
|
|
|
|
|
|
|
var skeleton := get_skeleton() |
|
|
|
|
if not skeleton: return |
|
|
|
|
|
|
|
|
|
for child in skeleton.get_children(): |
|
|
|
|
var collider := child as AvatarCollider |
|
|
|
|
if not collider: continue |
|
|
|
|
var hand = hands.get(collider.bone_name) |
|
|
|
|
if not hand: continue |
|
|
|
|
hand.collider = collider |
|
|
|
|
|
|
|
|
|
func handle_channel_chat_message( |
|
|
|
|
_cheerer_username: String, |
|
|
|
|
_cheerer_display_name: String, |
|
|
|
@ -90,6 +111,7 @@ func handle_channel_chat_message( |
|
|
|
|
func _process(delta: float) -> void: |
|
|
|
|
_apply_bumping(delta) |
|
|
|
|
_throw_hearts_in_queue(delta) |
|
|
|
|
_grab_with_hands() |
|
|
|
|
|
|
|
|
|
## Applies body and head "bumping" that causes |
|
|
|
|
## the avatar to "shake" in response to being hit. |
|
|
|
@ -156,6 +178,45 @@ func _throw_hearts_in_queue(delta: float) -> void: |
|
|
|
|
|
|
|
|
|
object.global_position = pos |
|
|
|
|
object.linear_velocity = vel |
|
|
|
|
object.add_to_group("copyThrower/objects") |
|
|
|
|
|
|
|
|
|
func _grab_with_hands() -> void: |
|
|
|
|
for hand in hands.values(): |
|
|
|
|
if not hand.collider: continue |
|
|
|
|
var closedness = _hand_closedness(hand.collider) |
|
|
|
|
# When hand has just been closed, grab nearby hearts and reparent. |
|
|
|
|
if (not hand.closed) and (closedness > HAND_CLOSE_THRESHOLD): |
|
|
|
|
var body: CharacterBody3D = hand.collider.get_node("CharacterBody3D") |
|
|
|
|
var hand_center = body.to_global(Vector3(0, 0, 0.08)) |
|
|
|
|
for object: RigidBody3D in get_tree().get_nodes_in_group("copyThrower/objects"): |
|
|
|
|
if object.global_position.distance_to(hand_center) < 0.16: |
|
|
|
|
object.reparent(hand.collider) |
|
|
|
|
object.global_position = hand_center |
|
|
|
|
object.freeze = true |
|
|
|
|
hand.closed = true |
|
|
|
|
# When hand has just been opened, throw any grabbed hearts. |
|
|
|
|
elif hand.closed and (closedness < HAND_OPEN_TRHESHOLD): |
|
|
|
|
for hand_child in hand.collider.get_children(): |
|
|
|
|
var object := hand_child as RigidBody3D |
|
|
|
|
if not object: continue |
|
|
|
|
object.reparent(object.original_parent) |
|
|
|
|
object.linear_velocity = Vector3(0, 1.5, 3.0) * hand.collider.global_basis + Vector3.UP |
|
|
|
|
object.freeze = false |
|
|
|
|
hand.closed = false |
|
|
|
|
|
|
|
|
|
static func _hand_closedness(collider: AvatarCollider) -> float: |
|
|
|
|
var total := 0.0 |
|
|
|
|
var skeleton := collider.get_skeleton() |
|
|
|
|
var fingers := skeleton.get_bone_children(collider.bone_idx) |
|
|
|
|
for finger in fingers: total += _get_total_curl(skeleton, finger) |
|
|
|
|
return total |
|
|
|
|
|
|
|
|
|
static func _get_total_curl(skeleton: Skeleton3D, bone: int, current := 0.0) -> float: |
|
|
|
|
current += skeleton.get_bone_pose_rotation(bone).get_euler().x |
|
|
|
|
var children := skeleton.get_bone_children(bone) |
|
|
|
|
if children.size() == 1: |
|
|
|
|
return _get_total_curl(skeleton, children[0], current) |
|
|
|
|
else: return current |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func on_collide(object: RigidBody3D, body: CharacterBody3D) -> void: |
|
|
|
|