private void CreatePreviewFor(VR_Grabbable grabbable)
        {
            previewOwner = grabbable.gameObject;
            DropZoneInfo dropZoneInfo = grabbable.GetComponent <DropZoneInfo>();

            preview = new GameObject(grabbable.gameObject.name + "_Preview");


            MeshFilter[]      meshFilters = grabbable.GetComponentsInChildren <MeshFilter>();
            CombineInstance[] combine     = new CombineInstance[meshFilters.Length];
            int i = 0;

            while (i < meshFilters.Length)
            {
                combine[i].mesh      = meshFilters[i].sharedMesh;
                combine[i].transform = grabbable.transform.worldToLocalMatrix * meshFilters[i].transform.localToWorldMatrix;

                i++;
            }

            MeshFilter filter = preview.AddComponent <MeshFilter>();

            filter.mesh = new Mesh();
            filter.mesh.CombineMeshes(combine);

            MeshRenderer renderer = preview.AddComponent <MeshRenderer>();

            renderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
            renderer.receiveShadows    = false;
            renderer.material          = transparentMat;
            renderer.material.color    = new Color(1.0f, 1.0f, 1.0f, 0.5f);


            preview.transform.position = CalculateDropEndPosition(grabbable);
            preview.transform.rotation = CalculateDropEndRotation(grabbable);

            if (dropZoneInfo != null)
            {
                Vector3 scale = dropZoneInfo == null ? grabbable.transform.localScale : dropZoneInfo.OriginalScale;
                scale *= dropZoneInfo.ScaleModifier;
                preview.transform.localScale = scale;
            }
            else
            {
                preview.transform.localScale = grabbable.transform.lossyScale;
            }

            preview.transform.parent = dropPoint;
        }
        private bool ShouldModifyScale(VR_Grabbable grabbable)
        {
            DropZoneInfo info = grabbable.GetComponent <DropZoneInfo>();

            return(info != null && info.ScaleModifier != 1.0f);
        }
        private void OnGrabStateChange(GrabState state, VR_Grabbable grabbable)
        {
            if (state == GrabState.Drop && CanDropGrabbable(grabbable))
            {
                Rigidbody rb = grabbable.GetComponent <Rigidbody>();

                if (rb != null)
                {
                    rb.isKinematic = true;
                }

                ProcessDrop(grabbable);

                DropZoneInfo dropZoneInfo = grabbable.GetComponent <DropZoneInfo>();


                Vector3 dropScale = grabbable.transform.localScale;

                if (dropZoneInfo != null)
                {
                    dropScale = grabbable.transform.localScale * dropZoneInfo.ScaleModifier;
                }

                if (shouldFly)
                {
                    grabbable.enabled = false;

                    if (dropZoneInfo != null && dropZoneInfo.ScaleModifier != 1.0f)
                    {
                        StartCoroutine(ModifyScaleRoutine(grabbable.transform, dropScale, flyTime));
                    }

                    StartCoroutine(FlyRoutine(grabbable));
                }
                else
                {
                    onDrop.Invoke(grabbable);

                    if (syncronizePosition)
                    {
                        grabbable.transform.position = CalculateDropEndPosition(grabbable);
                    }
                    if (syncronizeRot)
                    {
                        grabbable.transform.rotation = CalculateDropEndRotation(grabbable);
                    }

                    if (preview != null)
                    {
                        preview.gameObject.SetActive(false);
                    }

                    if (dropZoneInfo != null)
                    {
                        grabbable.transform.localScale = dropScale;
                    }
                }
            }
            else if (droppedGrabbableList.Contains(grabbable) && state == GrabState.Grab)
            {
                if (preview != null)
                {
                    preview.SetActive(true);
                }

                OnGrabbableExit(grabbable);
            }

            else if (droppedGrabbableList.Contains(grabbable) && state == GrabState.Flying)
            {
                if (ShouldModifyScale(grabbable))
                {
                    DropZoneInfo dropzoneInfo = grabbable.GetComponent <DropZoneInfo>();

                    StartCoroutine(ModifyScaleRoutine(grabbable.transform, dropzoneInfo.OriginalScale, grabbable.GrabFlyTime));
                }
            }
        }
        private Quaternion CalculateDropEndRotation(VR_Grabbable grabbable)
        {
            DropZoneInfo info = grabbable.GetComponent <DropZoneInfo>();

            return(info == null ? dropPoint.rotation : dropPoint.rotation *Quaternion.Euler(info.RotationOffset));
        }
        private Vector3 CalculateDropEndPosition(VR_Grabbable grabbable)
        {
            DropZoneInfo info = grabbable.GetComponent <DropZoneInfo>();

            return(info == null ? dropPoint.position : dropPoint.position + info.PositionOffset);
        }
        private Vector3 CalculateOriginalScale(VR_Grabbable grabbable)
        {
            DropZoneInfo info = grabbable.GetComponent <DropZoneInfo>();

            return(info == null ? grabbable.transform.localScale : info.OriginalScale);
        }