/// <summary>Displays the tooltip.</summary>
        /// <remarks>
        /// This method first waits a couple frames before sizing and positioning the tooltip.
        /// This is necessary in order to get an accurate preferredWidth property of the dynamic text field.
        /// </remarks>
        public IEnumerator Show(TooltipTrigger trigger)
        {
            if (trigger.tooltipStyle == null)
            {
                Debug.LogWarning("TooltipTrigger \"" + trigger.name + "\" has no associated TooltipStyle. Cannot show tooltip.");
                yield break;
            }

            Tooltip tooltip       = trigger.Tooltip;
            Image   tooltipBkgImg = tooltip.BackgroundImage;

            // Move the tooltip to the No Angle container if it should never be rotated.
            if (tooltip.NeverRotate)
            {
                tooltip.GameObject.transform.SetParent(TooltipContainerNoAngle.transform, false);
            }

            // Replace dynamic image placeholders with the correct images.
            if (trigger.dynamicImageFields != null)
            {
                for (int i = 0; i < trigger.dynamicImageFields.Count; i++)
                {
                    for (int j = 0; j < tooltip.ImageFields.Count; j++)
                    {
                        if (tooltip.ImageFields[j].Name == trigger.dynamicImageFields[i].name)
                        {
                            if (trigger.dynamicImageFields[i].replacementSprite == null)
                            {
                                tooltip.ImageFields[j].Image.sprite = tooltip.ImageFields[j].Original;
                            }
                            else
                            {
                                tooltip.ImageFields[j].Image.sprite = trigger.dynamicImageFields[i].replacementSprite;
                            }
                        }
                    }
                }
            }

            // Toggle dynamic sections on or off.
            if (trigger.dynamicSectionFields != null)
            {
                for (int i = 0; i < trigger.dynamicSectionFields.Count; i++)
                {
                    for (int j = 0; j < tooltip.SectionFields.Count; j++)
                    {
                        if (tooltip.SectionFields[j].Name == trigger.dynamicSectionFields[i].name)
                        {
                            tooltip.SectionFields[j].GameObject.SetActive(trigger.dynamicSectionFields[i].isOn);
                        }
                    }
                }
            }

            // Wait for 2 frames so we get an accurate PreferredWidth on the Text component.
            yield return(WaitFor.Frames(2));

            // Get the parent canvas for this tooltip trigger.
            GuiCanvas = trigger.GetComponentInParent <Canvas>();

            // If no parent canvas is found for the trigger object, use the main canvas.
            if (GuiCanvas == null)
            {
                GuiCanvas = CanvasHelper.GetRootCanvas();
            }

            // Parent the tooltip container under the correct canvas.
            TooltipContainer.transform.SetParent(GuiCanvas.transform, false);

            // Set the position of the tooltip.
            tooltip.SetPosition(trigger, GuiCanvas, guiCamera);

            // Set the tint color of the tooltip panel and tips.
            tooltipBkgImg.color = trigger.backgroundTint;

            // If this is a blocking tooltip, assign it as such.
            if (tooltip.IsBlocking)
            {
                BlockingTooltip = tooltip;
            }

            // Display the tooltip.
            tooltip.Display(fadeDuration);
        }
        /// <summary>Sets the position of the tooltip container.</summary>
        public static void SetPosition(this Tooltip tooltip, TooltipTrigger trigger, Canvas canvas, Camera camera)
        {
            Vector3[]     triggerCorners   = new Vector3[4];
            RectTransform triggerRectTrans = trigger.gameObject.GetComponent <RectTransform>();

            if (triggerRectTrans != null)
            {
                triggerRectTrans.GetWorldCorners(triggerCorners);
            }
            else
            {
                // We're not using a trigger from a Canvas, so that means it's a regular world space game object.
                // So, find the collider bounds of the object and use that for the four corners.
                Collider coll    = trigger.GetComponent <Collider>();
                Vector3  center  = coll.bounds.center;
                Vector3  extents = coll.bounds.extents;

                Vector3 frontBottomLeftCorner  = new Vector3(center.x - extents.x, center.y - extents.y, center.z - extents.z);
                Vector3 frontTopLeftCorner     = new Vector3(center.x - extents.x, center.y + extents.y, center.z - extents.z);
                Vector3 frontTopRightCorner    = new Vector3(center.x + extents.x, center.y + extents.y, center.z - extents.z);
                Vector3 frontBottomRightCorner = new Vector3(center.x + extents.x, center.y - extents.y, center.z - extents.z);

                triggerCorners[0] = camera.WorldToScreenPoint(frontBottomLeftCorner);
                triggerCorners[1] = camera.WorldToScreenPoint(frontTopLeftCorner);
                triggerCorners[2] = camera.WorldToScreenPoint(frontTopRightCorner);
                triggerCorners[3] = camera.WorldToScreenPoint(frontBottomRightCorner);
            }

            // Set the initial tooltip position.
            tooltip.SetPosition(trigger.tipPosition, trigger.tooltipStyle, triggerCorners, tooltip.BackgroundImage, tooltip.RectTransform, canvas, camera);

            // If overflow protection is disabled, exit.
            if (!TooltipManager.Instance.overflowProtection)
            {
                return;
            }

            // Check for overflow.
            Vector3[] tooltipCorners = new Vector3[4];
            tooltip.RectTransform.GetWorldCorners(tooltipCorners);

            if (canvas.renderMode == RenderMode.ScreenSpaceCamera || canvas.renderMode == RenderMode.WorldSpace)
            {
                for (int i = 0; i < tooltipCorners.Length; i++)
                {
                    tooltipCorners[i] = RectTransformUtility.WorldToScreenPoint(camera, tooltipCorners[i]);
                }
            }
            else if (canvas.renderMode == RenderMode.ScreenSpaceOverlay)
            {
                for (int i = 0; i < tooltipCorners.Length; i++)
                {
                    tooltipCorners[i] = RectTransformUtility.WorldToScreenPoint(null, tooltipCorners[i]);
                }
            }

            Rect            screenRect = new Rect(0, 0, Screen.width, Screen.height);
            TooltipOverflow overflow   = new TooltipOverflow
            {
                BottomLeftCorner = !screenRect.Contains(tooltipCorners[0]),
                // is the tooltip out of bounds on the Bottom Left?
                TopLeftCorner = !screenRect.Contains(tooltipCorners[1]),
                // is the tooltip out of bounds on the Top Left?
                TopRightCorner = !screenRect.Contains(tooltipCorners[2]),
                // is the tooltip out of bounds on the Top Right?
                BottomRightCorner = !screenRect.Contains(tooltipCorners[3])
                                    // is the tooltip out of bounds on the Bottom Right?
            };

            // If the tooltip overflows its boundary rectange, reposition it.
            if (overflow.IsAny)
            {
                tooltip.SetPosition(overflow.SuggestNewPosition(trigger.tipPosition), trigger.tooltipStyle,
                                    triggerCorners, tooltip.BackgroundImage, tooltip.RectTransform, canvas, camera);
            }
        }