rabidus-test/Assets/BNG Framework/Scripts/Components/GrabPointTrigger.cs

228 lines
8.2 KiB
C#
Raw Permalink Normal View History

2023-07-24 16:38:13 +03:00
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace BNG {
public class GrabPointTrigger : MonoBehaviour {
public enum HandMovement {
Instant,
Lerp,
None
}
[Header("Hand Movement")]
[Tooltip("How to move the hand to the nearest grab point. If set to 'None', the hand model will remain at the controller.")]
public HandMovement MoveInStyle = HandMovement.Instant;
[Tooltip("How to move the hand back to the grabber")]
public HandMovement MoveOutStyle = HandMovement.Instant;
[Tooltip("How to fast to move the hand if MovementStyle = 'Lerp' or 'Linear'")]
public float HandSpeed = 20f;
[Tooltip("If true the hand model will continue to move towards the closest grab point. If false, the hand will only move towards the closest grab point once upon entering the trigger.")]
public bool LiveUpdateNearestGrabPoint = true;
[Header("Grabbable Options")]
[Tooltip("If specified this Grabbable will be grabbed if the user holds down the grab button while this preview is active")]
public Grabbable GrabObject;
[Tooltip("If specified this Grabbable must be held for this component to work")]
public Grabbable OtherGrabbableMustBeHeld;
[Tooltip("Grab Points to move towards when the grabber is within the Trigger area.")]
public List<GrabPoint> GrabPoints;
Grabber currentGrabber;
Grabbable dummyGrabbable;
GrabPoint closestPoint;
Grabber grabberInTrigger;
void Start() {
if(dummyGrabbable == null) {
var go = new GameObject("Dummy Grabbable");
dummyGrabbable = go.AddComponent<Grabbable>();
dummyGrabbable.transform.parent = transform;
dummyGrabbable.transform.localPosition = Vector3.zero;
dummyGrabbable.transform.localRotation = Quaternion.identity;
// Copy over grab points
List<Transform> grabs = new List<Transform>();
for (int x = 0; x < GrabPoints.Count; x++) {
GrabPoint g = GrabPoints[x];
grabs.Add(g.transform);
}
dummyGrabbable.GrabPoints = grabs;
dummyGrabbable.GrabMechanic = GrabType.Snap;
dummyGrabbable.ParentHandModel = false;
dummyGrabbable.CanBeDropped = false;
// Copy settings over from reference object if available
if(GrabObject != null) {
dummyGrabbable.GrabButton = GrabObject.GrabButton;
dummyGrabbable.Grabtype = GrabObject.Grabtype;
}
}
}
void Update() {
// holding this object
if(dummyGrabbable != null && currentGrabber != null) {
// Do we need to drop this object?
if(OtherGrabbableMustBeHeld != null && !OtherGrabbableMustBeHeld.BeingHeld) {
ReleaseGrabber();
return;
}
// Is there a new grab point that's closer?
if(LiveUpdateNearestGrabPoint) {
// dummyGrabbable.transform.position =
Transform closestGrab = dummyGrabbable.GetClosestGrabPoint(currentGrabber);
if (closestGrab != null) {
var newPoint = closestGrab.GetComponent<GrabPoint>();
if(newPoint != null && newPoint != closestPoint) {
UpdateGrabPoint(newPoint);
}
}
}
// Move the hand
if (MoveInStyle == HandMovement.Lerp) {
currentGrabber.HandsGraphics.localPosition = Vector3.Lerp(currentGrabber.HandsGraphics.localPosition, currentGrabber.handsGraphicsGrabberOffset, Time.deltaTime * HandSpeed);
currentGrabber.HandsGraphics.localRotation = Quaternion.Slerp(currentGrabber.HandsGraphics.localRotation, Quaternion.identity, Time.deltaTime * HandSpeed);
}
// User pressed grab key while holding object
if (currentGrabber.GetInputDownForGrabbable(dummyGrabbable)) {
if(GrabObject != null) {
var prevGrabber = currentGrabber;
ReleaseGrabber();
prevGrabber.GrabGrabbable(GrabObject);
}
}
}
// Are we back in the trigger?
if(grabberInTrigger != null && !grabberInTrigger.HoldingItem && currentGrabber == null) {
setGrabber(grabberInTrigger);
}
}
public virtual void UpdateGrabPoint(GrabPoint newPoint) {
closestPoint = newPoint;
// Update hand animation
// dummyGrabbable.CustomHandPose = newPoint.HandPose;
dummyGrabbable.handPoseType = newPoint.handPoseType;
dummyGrabbable.SelectedHandPose = newPoint.SelectedHandPose;
// Move Hand Graphics if they are available
if (currentGrabber != null && currentGrabber.HandsGraphics != null) {
if (MoveInStyle != HandMovement.None) {
currentGrabber.HandsGraphics.parent = closestPoint.transform;
}
// Move hands in place
if (MoveInStyle == HandMovement.Instant) {
currentGrabber.HandsGraphics.localPosition = currentGrabber.handsGraphicsGrabberOffset;
currentGrabber.HandsGraphics.localEulerAngles = Vector3.zero;
}
}
}
void OnTriggerEnter(Collider other) {
// Object isn't being held, ignore this
if(OtherGrabbableMustBeHeld != null && !OtherGrabbableMustBeHeld.BeingHeld) {
return;
}
// Already have something in the trigger
if(grabberInTrigger != null) {
return;
}
// Our component has been disabled
if(!this.isActiveAndEnabled || dummyGrabbable == null) {
return;
}
Grabber grab = other.GetComponent<Grabber>();
if (grab != null && !grab.HoldingItem && currentGrabber == null) {
// Check if any Grab Points have been found
Transform closestGrab = dummyGrabbable.GetClosestGrabPoint(grab);
if(closestGrab != null) {
closestPoint = closestGrab.GetComponent<GrabPoint>();
}
else {
closestPoint = null;
}
grabberInTrigger = grab;
// Update Grabber
if (closestPoint != null) {
dummyGrabbable.ActiveGrabPoint = closestPoint;
setGrabber(grab);
}
}
}
void OnTriggerExit(Collider other) {
Grabber grab = other.GetComponent<Grabber>();
// No longer inside trigger
if (grab != null && grab == grabberInTrigger) {
grabberInTrigger = null;
}
// Release grabber if out
if (grab != null && grab == currentGrabber) {
ReleaseGrabber();
}
}
void setGrabber(Grabber theGrabber) {
currentGrabber = theGrabber;
dummyGrabbable.CanBeDropped = false;
dummyGrabbable.BeingHeld = true;
currentGrabber.HeldGrabbable = dummyGrabbable;
UpdateGrabPoint(closestPoint);
}
public virtual void ReleaseGrabber() {
if (currentGrabber != null) {
dummyGrabbable.CanBeDropped = true;
dummyGrabbable.BeingHeld = false;
currentGrabber.HeldGrabbable = null;
if (MoveOutStyle == HandMovement.Instant) {
currentGrabber.ResetHandGraphics();
}
else if (MoveOutStyle == HandMovement.Lerp) {
currentGrabber.ResetHandGraphics();
}
currentGrabber = null;
}
}
}
}