4/28/21

Quad Tree – Oct Tree – Hexa Tree

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using ArgosTweenSpacePuppy;

public class Spoke_Handler : MonoBehaviour
{
    public bool setLastHeld = false;
    public bool isInFulgurite = false;  
    public bool isBeingHeld = false;

    public float maxFJForce = 1000f; 

    private Vector3     targetPos;
    private Quaternion  targetRot;
    
    // +x,+y,+z,-x,-y,-z
    public List<Spoke_AllShape> spoke_AS = new List<Spoke_AllShape>();
    public Rigidbody rb;

    private AF_Instance af_Instance;

    public SphereCollider sphereCollider;

    public AF_Network_Grabable netGrabbable;

    public Touch_Lighting_and_Sound tls;

    public Spoke_AllShape SAS1 { get; private set; }
    public Spoke_AllShape SAS2 { get; private set; }

    private GameObject AllShape_1;
    private GameObject AllShape_2;
    private GameObject objectToStay;
    private GameObject objectToMove;
    private Spoke_Handler spokeHandler_Object_to_Move;
    private Spoke_Handler spokeHandler_Object_to_Stay;

    private float tAccum_ST = 0f;
    private float tDurr_ST = 1.5f;
    private float tweenVAL = 0f;

    private Vector3[] axisFLIPPER = {  new Vector3 { x = 1,  y = 0,  z = 0 },
                                       new Vector3 { x = 0,  y = 1,  z = 0 },
                                       new Vector3 { x = 0,  y = 0,  z = 1 },
                                       new Vector3 { x = -1, y = 0,  z = 0 },
                                       new Vector3 { x = 0,  y =-1,  z = 0 },
                                       new Vector3 { x = 0,  y = 0,  z = -1},
                                    };

    public void Awake()
    {
        af_Instance = AF_Instance.Instance;
        tls = GetComponent<Touch_Lighting_and_Sound>();
        //TAG Spokes to access target transforms
        for (int i = 0; i<spoke_AS.Count; i++)
        {
            spoke_AS[i].SetParent_AllShape(this, i);
            tls.initializeColors_in_Spoke(spoke_AS[i]);
        }
    }

    void Start()
    {

    }

    public void Set_Target_Transform(Transform targ)
    {
        Vector3 center = (objectToMove.transform.position + objectToStay.transform.position) / 2f;
        int idx1 = spokeHandler_Object_to_Move.Closest_Fin(center);
        int idx2 = spokeHandler_Object_to_Stay.Closest_Fin(center);

        Vector3 vin = spokeHandler_Object_to_Stay.spoke_AS[idx2].trans_to.vIN[idx1];
        Vector3 vup = spokeHandler_Object_to_Stay.spoke_AS[idx2].trans_to.vUP[idx1];

        Vector3 vInTrans = objectToStay.transform.TransformDirection(vin);
        Vector3 vUpTrans = objectToStay.transform.TransformDirection(vup);

        targetPos = targ.position;
        targetRot = Quaternion.LookRotation(vInTrans, vUpTrans);

        //Flip it - for minimal rotation to bonding FIN
        if (Vector3.Dot(vUpTrans, objectToMove.transform.up) < 0 || Vector3.Dot(vInTrans, objectToMove.transform.forward) < 0)
        {
            Quaternion qRota = Quaternion.AngleAxis(180, axisFLIPPER[idx1]);
            targetRot *= qRota;
        }
    }

    public void SpokeTriggered(int idx, Spoke_AllShape sourceSpoke)
    {
        GameObject AS1 = spoke_AS[idx].myALL_SHAPE.gameObject;
        Transform targ1 = spoke_AS[idx].targTransform;
        GameObject AS2 = sourceSpoke.myALL_SHAPE.gameObject;
        Transform targ2 = sourceSpoke.targTransform;

        Determine_Target_Movement(AS1, targ1, AS2, targ2);
    }

    public void Determine_Target_Movement(GameObject AS1, Transform targ1, GameObject AS2, Transform targ2)
    {
        //Two calls - only take this one
        if (AS1 == af_Instance.last_Held_AllShape /*|| (AS1.GetComponent<Spoke_Handler>().isBeingHeld)*/)
        {
            objectToMove = AS1;
            objectToStay = AS2;

            spokeHandler_Object_to_Move = objectToMove.GetComponent<Spoke_Handler>();
            spokeHandler_Object_to_Stay = objectToStay.GetComponent<Spoke_Handler>();

            spokeHandler_Object_to_Move.netGrabbable.DropItem(null, true, true);
            spokeHandler_Object_to_Stay.netGrabbable.DropItem(null, true, true);

            Set_Target_Transform(targ2);

            tAccum_ST = 0.0f;
            Debug.Log("Start COROUTINE:" + Time.time.ToString("F3"));
            StartCoroutine(Move_to_Connect());
        }
    }

    private IEnumerator Move_to_Connect()
    {
        spokeHandler_Object_to_Move.SetAllActive_Colliders(false, false);
        spokeHandler_Object_to_Stay.SetAllActive_Colliders(false, false);

        int i = 0; //Sanity check for infinite loops

        float linProg = tAccum_ST / tDurr_ST;

        while (i < 180 && linProg < 1)
        {
            tAccum_ST += Time.deltaTime;
            linProg = tAccum_ST / tDurr_ST;
            Mathf.Clamp(tAccum_ST, 0, tDurr_ST);

            tweenVAL = EaseMethods.ExpoEaseInOut(tAccum_ST, 0, 1, tDurr_ST);
            Move_AllShape_Into_Place(tweenVAL);

            yield return true;
            i++;
        }
        tAccum_ST = tDurr_ST;
        tweenVAL = 1;

        Move_AllShape_Into_Place(tweenVAL);

        Set_Occupied_These_Spokes();

        FixedJoint fj = objectToStay.AddComponent<FixedJoint>();
        fj.autoConfigureConnectedAnchor = true;
        fj.connectedBody = objectToMove.GetComponent<Rigidbody>();

        spokeHandler_Object_to_Move.SetAllActive_Colliders(true, true);
        spokeHandler_Object_to_Stay.SetAllActive_Colliders(true, true);

        StopCoroutine("Move_to_Connect");
    }

    private void Move_AllShape_Into_Place(float val)
    {
        objectToMove.transform.position = Vector3.Lerp(objectToMove.transform.position, targetPos, val);
        objectToMove.transform.rotation = Quaternion.Slerp(objectToMove.transform.rotation, targetRot, val);
    }

    private void Set_Occupied_These_Spokes()
    {
        Vector3 center = (objectToMove.transform.position + objectToStay.transform.position) / 2f;
        int idx1 = spokeHandler_Object_to_Move.Closest_Fin(center);
        int idx2 = spokeHandler_Object_to_Stay.Closest_Fin(center);

        spokeHandler_Object_to_Move.setOccupied(idx1, true, spokeHandler_Object_to_Stay.spoke_AS[idx2]);
        spokeHandler_Object_to_Stay.setOccupied(idx2, true, spokeHandler_Object_to_Move.spoke_AS[idx1]);
    }

    public void setOccupied(int spokeIDX, bool bOccupied, Spoke_AllShape connectedSpoke)
    {
        spoke_AS[spokeIDX].bOccupied = bOccupied;
        tls.Light_Occupied(spoke_AS[spokeIDX], bOccupied);

        spoke_AS[spokeIDX].connectedSpoke = connectedSpoke;
    }

    public void SetAllActive_Colliders(bool bOn, bool bSphereCollider)
    {
        sphereCollider.enabled = bSphereCollider;
        rb.isKinematic = false; //MORE CONSIDERATIONS HERE
        for (int i = 0; i < spoke_AS.Count; i++)
        {
            if (spoke_AS[i].bOccupied)
            {
                spoke_AS[i].enableCollider(false);
            }
            else
            {
                spoke_AS[i].enableCollider(bOn);
            }
        }
    }

    public int Closest_Fin(Vector3 testPos)
    {
        int idxMin = 0;
        float minDistance = 1000000f;
        float dist;
        for (int i = 0; i < spoke_AS.Count; i++)
        {
            dist = (spoke_AS[i].fin_LOC.position - testPos).sqrMagnitude;
            if(dist<minDistance)
            {
                idxMin = i;
                minDistance = dist;
            }
        }
        return idxMin;
    }

    public void SetAllColliders(bool bOn)
    {
        sphereCollider.enabled = bOn;
        rb.isKinematic = true; //MORE CONSIDERATIONS HERE
        for (int i = 0; i < spoke_AS.Count; i++)
        {
            spoke_AS[i].bOccupied = false;
            spoke_AS[i].enableCollider(bOn);          
        }
    }

    public void Reset_Spokes_On_Grab()
    {
        for (int i = 0; i < spoke_AS.Count; i++)
        {
            if (spoke_AS[i].bOccupied)
            {
                spoke_AS[i].setOccupied(false);
            }
        }
    }

    void Update()
    {

        FixedJoint fj = GetComponent<FixedJoint>();
        if(fj)
        {
            if(Vector3.Magnitude(fj.currentForce) > maxFJForce)
            {
                fj.connectedBody = null;
                Destroy(fj);
            }
        }



        if (setLastHeld)
        {
            af_Instance.last_Held_AllShape = this.gameObject;
            setLastHeld = false;
        }
    }
}