protected virtual void RemoveCanvas()
        {
            Canvas canvas = GetComponent <Canvas>();

            if (canvas == null)
            {
                return;
            }

            GraphicRaycaster         defaultRaycaster = canvas.gameObject.GetComponent <GraphicRaycaster>();
            VRTK4_UIGraphicRaycaster customRaycaster  = canvas.gameObject.GetComponent <VRTK4_UIGraphicRaycaster>();

            //if a custom raycaster exists then remove it
            if (customRaycaster != null)
            {
                Destroy(customRaycaster);
            }

            //If the default raycaster is disabled, then re-enable it
            if (defaultRaycaster != null && !defaultRaycaster.enabled)
            {
                defaultRaycaster.enabled = true;
            }

            //Check if there is a collider and remove it if there is
            if (canvasBoxCollider != null)
            {
                Destroy(canvasBoxCollider);
            }

            if (canvasRigidBody != null)
            {
                Destroy(canvasRigidBody);
            }

            if (draggablePanelCreation != null)
            {
                StopCoroutine(draggablePanelCreation);
            }

            Transform draggablePanel = canvas.transform.Find(CANVAS_DRAGGABLE_PANEL);

            if (draggablePanel != null)
            {
                Destroy(draggablePanel.gameObject);
            }

            Transform frontTrigger = canvas.transform.Find(ACTIVATOR_FRONT_TRIGGER_GAMEOBJECT);

            if (frontTrigger != null)
            {
                Destroy(frontTrigger.gameObject);
            }
        }
        /// <summary>
        /// Sanity Check for Graphic Raycaster
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        protected virtual bool ValidElement(GameObject obj)
        {
            bool isValid = false;

            if (obj.layer != LayerMask.NameToLayer("UI"))
            {
                var anyHandler = obj.GetComponentInParent <IEventSystemHandler>();
                if (anyHandler != null)
                {
                    isValid = true;
                }
            }

            VRTK4_UIGraphicRaycaster canvasCheck = obj.GetComponentInParent <VRTK4_UIGraphicRaycaster>();

            return(isValid || canvasCheck != null && canvasCheck.enabled);
        }
        protected virtual void SetupCanvas()
        {
            if (this == null || !isActiveAndEnabled || VRTK4_EventSystem.Instance == null)
            {
                return;
            }

            Canvas canvas = GetComponent <Canvas>();

            if (canvas == null || canvas.renderMode != RenderMode.WorldSpace)
            {
                Debug.LogError(
                    string.Format("{0} REQUIRED_COMPONENT_MISSING_FROM_GAMEOBJECT {1} Make sure {2}",
                                  nameof(VRTK4_UICanvas), gameObject.name, "that Canvas is set to `Render Mode = World Space`"),
                    gameObject);
                return;
            }

            RectTransform canvasRectTransform = canvas.GetComponent <RectTransform>();
            Vector2       canvasSize          = canvasRectTransform.sizeDelta;
            //copy public params then disable existing graphic raycaster
            GraphicRaycaster         defaultRaycaster = canvas.gameObject.GetComponent <GraphicRaycaster>();
            VRTK4_UIGraphicRaycaster customRaycaster  =
                canvas.gameObject.GetComponent <VRTK4_UIGraphicRaycaster>();

            //if it doesn't already exist, add the custom raycaster
            if (customRaycaster == null)
            {
                customRaycaster = canvas.gameObject.AddComponent <VRTK4_UIGraphicRaycaster>();
            }

            if (defaultRaycaster != null && defaultRaycaster.enabled)
            {
                customRaycaster.ignoreReversedGraphics = defaultRaycaster.ignoreReversedGraphics;
                customRaycaster.blockingObjects        = defaultRaycaster.blockingObjects;

                //Use Reflection to transfer the BlockingMask
                customRaycaster.GetType()
                .GetField("m_BlockingMask",
                          BindingFlags.Instance | BindingFlags.NonPublic).SetValue(
                    customRaycaster,
                    defaultRaycaster.GetType()
                    .GetField("m_BlockingMask", BindingFlags.Instance | BindingFlags.NonPublic)
                    .GetValue(defaultRaycaster));

                defaultRaycaster.enabled = false;
            }

            //add a box collider and background image to ensure the rays always hit
            if (canvas.gameObject.GetComponent <BoxCollider>() == null)
            {
                Vector2 pivot  = canvasRectTransform.pivot;
                float   zSize  = 0.1f;
                float   zScale = canvasRectTransform.localScale.z > 0 ? zSize / canvasRectTransform.localScale.z : 1;


                canvasBoxCollider        = canvas.gameObject.AddComponent <BoxCollider>();
                canvasBoxCollider.size   = new Vector3(canvasSize.x, canvasSize.y, zScale);
                canvasBoxCollider.center = new Vector3(canvasSize.x / 2 - canvasSize.x * pivot.x,
                                                       canvasSize.y / 2 - canvasSize.y * pivot.y, zScale / 2f);
                canvasBoxCollider.isTrigger        = true;
                canvasBoxCollider.gameObject.layer = UnityEngine.LayerMask.NameToLayer("UI");
            }

            if (canvas.gameObject.GetComponent <Rigidbody>() == null)
            {
                canvasRigidBody             = canvas.gameObject.AddComponent <Rigidbody>();
                canvasRigidBody.isKinematic = true;
            }

            draggablePanelCreation = StartCoroutine(CreateDraggablePanel(canvas, canvasSize));
            CreateActivator(canvas, canvasSize);
        }