Brandons-MassiveLoop-CSharp-Scripts / DynamicSize_Threshold.cs
DynamicSize_Threshold.cs
Raw
using ML.SDK;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class DynamicSize_Threshold : MonoBehaviour
{
    public MLGrab grabComponent;

    // Size limits for size change (relative change)
    [SerializeField] private float minSize = 0.5f; // Minimum scale factor
    [SerializeField] private float maxSize = 2.0f; // Maximum scale factor

    // Absolute size limits for local scale
    [SerializeField] private float absoluteMinSize = 0.3f;
    [SerializeField] private float absoluteMaxSize = 3.0f;

    [SerializeField] private float throwForceMultiplier = 10.0f; // Multiplier for throw force
    [SerializeField] private float maxThrowForce = 100.0f; // Cap for throw force magnitude

    [SerializeField] private float throwVelocityThreshold = 0.5f; // Minimum hand velocity to throw

    private Vector3 initialScale;
    private float initialDistance;
    private bool isSizeChangeEnabled = false;
    private bool isHeld = false;

    [SerializeField] private GameObject objectToChange;
    private Rigidbody objectRigidbody;
    private Vector3 lastPosition;

    const string EVENT_ID_Throw = "ThrowEvent";
    private EventToken tokenThrow;
    public MLPlayer player;
    private bool isThrown = false;

    private void Start()
    {
        // Setup event listeners
        grabComponent.OnPrimaryGrabBegin.AddListener(OnPrimaryGrabBegin);
        grabComponent.OnPrimaryGrabEnd.AddListener(OnPrimaryGrabEnd);
        grabComponent.OnSecondaryGrabBegin.AddListener(OnSecondaryGrabBegin);
        grabComponent.OnSecondaryGrabEnd.AddListener(OnSecondaryGrabEnd);
        grabComponent.OnPrimaryTriggerDown.AddListener(OnPrimaryTriggerDown);

        tokenThrow = this.AddEventHandler(EVENT_ID_Throw, OnThrowEvent);

        // Ensure Rigidbody is attached
        objectRigidbody = objectToChange.GetComponent<Rigidbody>();
        if (objectRigidbody == null)
        {
            Debug.LogError("No Rigidbody component found on the object!");
        }
    }

    private void FixedUpdate()
    {
        // Handle size change during secondary grab
        if (isSizeChangeEnabled && grabComponent.PrimaryHand && grabComponent.SecondaryHand)
        {
            AdjustSizeBasedOnGrab();
        }

        // Update last position while object is held
        if (isHeld && grabComponent.PrimaryHand)
        {
            lastPosition = grabComponent.PrimaryHand.transform.position;
        }

        if (isThrown)
        {


            // Scale the release force
            Vector3 throwForce = this.gameObject.transform.forward * throwForceMultiplier;

            // Clamp the force to a maximum value
            if (throwForce.magnitude > maxThrowForce)
            {
                throwForce = throwForce.normalized * maxThrowForce * 10;
            }

            Debug.Log("Throw event triggered.");
            Debug.Log($"Object thrown with impulse force: {throwForce}");
            objectRigidbody.AddForce(throwForce, ForceMode.Impulse);

            isThrown = false;
        }

    }

    private void OnPrimaryTriggerDown()
    {

        float storeThreshold = throwVelocityThreshold;
        throwVelocityThreshold = 0;

        grabComponent.ForceRelease();

        isThrown = true;

        throwVelocityThreshold = storeThreshold;


    }

    private void OnPrimaryGrabBegin()
    {
        if (grabComponent.CurrentUser != null)
        {
            isHeld = true;
            lastPosition = grabComponent.PrimaryHand.transform.position;

            if (grabComponent.GrabMechanic == SDKGrabMechanicsBehaviorV2.Custom)
            {
                objectToChange.transform.parent = grabComponent.PrimaryHand.transform;
            }
        }
    }

    private void OnPrimaryGrabEnd()
    {
        // Unparent the object if using custom grab mechanics
        if (grabComponent.GrabMechanic == SDKGrabMechanicsBehaviorV2.Custom)
        {
            transform.parent = null;
        }

        if (isHeld && objectRigidbody != null)
        {
            // Ensure Rigidbody is dynamic
            objectRigidbody.isKinematic = false;

            // Calculate hand velocity
            Vector3 handVelocity = (grabComponent.PrimaryHand.transform.position - lastPosition) / Time.fixedDeltaTime;

            // Check if velocity exceeds the threshold

            if (handVelocity.magnitude >= throwVelocityThreshold)
            {
                // Calculate the release direction based on the hand's orientation
                Vector3 releaseDirection = grabComponent.PrimaryHand.transform.forward;

                // Apply the force as an impulse
                // objectRigidbody.AddForce(throwForce, ForceMode.Impulse);
                if (grabComponent.CurrentUser == MassiveLoopRoom.GetLocalPlayer())
                {
                    this.InvokeNetwork(EVENT_ID_Throw, EventTarget.Master, null, releaseDirection);
                }


                // Debug visualization for force direction

            }
            else
            {
                Debug.Log("Hand velocity too low, object not thrown.");
            }
        }

        isHeld = false; // Reset the held flag
    }

    private void OnSecondaryGrabBegin()
    {
        if (grabComponent.PrimaryHand && grabComponent.SecondaryHand)
        {
            isSizeChangeEnabled = true;
            initialDistance = Vector3.Distance(
                grabComponent.PrimaryHand.transform.position,
                grabComponent.SecondaryHand.transform.position
            );
            initialScale = objectToChange.transform.localScale;
        }
    }

    private void OnSecondaryGrabEnd()
    {
        isSizeChangeEnabled = false;
    }

    private void AdjustSizeBasedOnGrab()
    {
        // Calculate current distance between hands
        float currentDistance = Vector3.Distance(
            grabComponent.PrimaryHand.transform.position,
            grabComponent.SecondaryHand.transform.position
        );

        // Calculate scale factor and new scale
        float scaleFactor = Mathf.Clamp(currentDistance / initialDistance, minSize, maxSize);
        Vector3 newScale = initialScale * scaleFactor;

        // Clamp to absolute scale limits
        newScale.x = Mathf.Clamp(newScale.x, absoluteMinSize, absoluteMaxSize);
        newScale.y = Mathf.Clamp(newScale.y, absoluteMinSize, absoluteMaxSize);
        newScale.z = Mathf.Clamp(newScale.z, absoluteMinSize, absoluteMaxSize);

        objectToChange.transform.localScale = newScale;
    }

    private void OnThrowEvent(object[] args)
    {

        isThrown = true;
    }
}