예제 #1
0
        /// <summary>
        /// Renders a pulsing ripple effect over a target.
        /// </summary>
        /// <param name="target">Location to put ripple effect.</param>
        /// <param name="mouseDown">If a mouse has been pressed, but not yet released.</param>
        public void TriggerPulseOnTarget(Vector3 target, bool isMouseDown)
        {
            if (!AutomatedQARuntimeSettings.ActivatePlaybackVisualFx ||
                !AutomatedQARuntimeSettings.ActivateClickFeedbackFx)
            {
                return;
            }

            // Drag events also use mouseup logic, so if we were dragging and just released the click, don't also create a click pulse.
            if (lastFxEventType == FxEventType.Drag && !isMouseDown && ActivePulseManagers.Any())
            {
                ActivePulseManagers.Last().KillEarly(true); // Remove the IsMouseDown pulse that is currently holding (waiting for mouse release).
                return;                                     // We don't want a pulse/ripple effect either at the mousedown location or mouseup location of a drag event.
            }
            lastFxEventType = FxEventType.Click;

            if (ActivePulseManagers.Any() && ActivePulseManagers.Last().IsMouseDown)
            {
                ActivePulseManagers.Last().Init(target, false);
            }
            else
            {
                // The number of pulses to immediately remove is the difference between the total active pulses and the requested count, plus the one pulse we are about to create. Or plus zero if we are not creating a new pulse, but triggering the last one to animate.
                int killImmediateCount = ActivePulseManagers.Count + 1 - maxPulsesOnScreenAtOnce;
                int index = 0;
                // Stop pulsing of any existing PulseManagers.
                while (index < ActivePulseManagers.Count)
                {
                    PulseManager pm = ActivePulseManagers[index];
                    if (pm == null || !pm)
                    {
                        ActivePulseManagers.RemoveAt(index);
                        continue;
                    }

                    bool killImmediately = killImmediateCount > 0 && index + 1 <= killImmediateCount;
                    if (killImmediately)
                    {
                        pm.GetComponent <PulseManager>().KillEarly(true);
                        killImmediateCount--;
                    }
                    else
                    {
                        pm.GetComponent <PulseManager>().KillEarly(false);
                        index++;
                    }
                }

                GameObject pulseManagerGo = VisualFxCanvases[0];
                pulseManagerGo.SetActive(true);
                pulseManagerGo.transform.SetParent(visualFxGo.transform, false);
                PulseManager pulseManager = pulseManagerGo.GetComponent <PulseManager>();
                pulseManager.enabled = true;
                pulseManager.Init(target, isMouseDown);
                ActivePulseManagers.Add(pulseManager);
                VisualFxCanvases.RemoveAt(0);
            }
        }
예제 #2
0
        /// <summary>
        /// Return ring GameObject to the pool for later use.
        /// </summary>
        /// <param name="ring"></param>
        public static void ReturnVisualFxCanvas(GameObject canvasObj)
        {
            PulseManager pm = canvasObj.GetComponent <PulseManager>();

            pm.enabled = false;
            canvasObj.transform.SetParent(canvasPoolGo.transform);
            canvasObj.SetActive(false);
            if (ActivePulseManagers.FindAll(x => x == pm).Any())
            {
                ActivePulseManagers.Remove(ActivePulseManagers.Find(x => x == pm));
            }
            VisualFxCanvases.Add(canvasObj);
        }
예제 #3
0
        public static void SetUp(Transform parentTransform)
        {
            visualFxGo = new GameObject("VisualFx");
            visualFxGo.transform.SetParent(parentTransform);
            Instance = visualFxGo.AddComponent <VisualFxManager>();
            if (!Application.isPlaying ||
                !AutomatedQARuntimeSettings.ActivatePlaybackVisualFx)
            {
                return;
            }

            canvasPoolGo = new GameObject("VisualFxCanvasObjectPool");
            canvasPoolGo.transform.SetParent(visualFxGo.transform);

            if (AutomatedQARuntimeSettings.ActivateClickFeedbackFx)
            {
                // Pre-make [preMakeRingCount] ring pulses to negate any performance impact from generating/destroying a lot of GameObjects in a short period.
                circleObjPoolGo = new GameObject("ClickPulseObjectPool");
                circleObjPoolGo.transform.SetParent(visualFxGo.transform);
                ringTexture2d = new Texture2D(2, 2);
                ringTexture2d.LoadImage(Convert.FromBase64String(ringBase64));
                for (int i = 0; i < preMakeRingCount; i++)
                {
                    PulseRings.Add(MakePulseRing());
                }

                // Also make canvas container objects. Around a fifth the total of pulse rings will be plenty.
                for (int i = 0; i < preMakeRingCount / 5; i++)
                {
                    VisualFxCanvases.Add(MakeVisualFxCanvas());
                }
            }

            if (AutomatedQARuntimeSettings.ActivateHighlightFeedbackFx)
            {
                // Pre-make [preMakeSquareCount] squares to negate any performance impact from generating/destroying a lot of GameObjects in a short period.
                squareObjPoolGo = new GameObject("HighlightSquareObjectPool");
                squareObjPoolGo.transform.SetParent(visualFxGo.transform);
                squareTexture2D = new Texture2D(2, 2);
                squareTexture2D.LoadImage(Convert.FromBase64String(squareBase64));
                for (int i = 0; i < preMakeSquareCount; i++)
                {
                    HighlightSquares.Add(MakeHighlightSquare());
                    VisualFxCanvases.Add(MakeVisualFxCanvas());
                }
            }
        }
예제 #4
0
        public void TriggerHighlightAroundTarget(GameObject target)
        {
            if (!AutomatedQARuntimeSettings.ActivatePlaybackVisualFx ||
                !AutomatedQARuntimeSettings.ActivateHighlightFeedbackFx)
            {
                return;
            }

            lastFxEventType = FxEventType.Highlight;
            if (target == null || !target.GetComponent <RectTransform>())
            {
                return;                                                          // TODO: Handle non UI elments
            }
            GameObject highlighterGo = VisualFxCanvases[0];

            highlighterGo.transform.SetParent(visualFxGo.transform);
            highlighterGo.SetActive(true);

            GameObject square = HighlightSquares[0];

            square.transform.SetParent(highlighterGo.transform);
            //square.GetComponent<HighlightElement>().Init(target);

            RectTransform squareRect = square.GetComponent <RectTransform>();

            squareRect.anchorMin = squareRect.anchorMax = new Vector2(0, 0);

            // TODO: This works for some UI's, but not all. Due to some RectTransforms supplying a world position, and others not; with seemingly no way to check if it is one or the other.
            RectTransform targetRect = target.GetComponent <RectTransform>();
            Vector3       centerPointOfObjectOnScreen = targetRect.TransformPoint(targetRect.position);

            centerPointOfObjectOnScreen = !Camera.main.orthographic ? Camera.main.WorldToScreenPoint(centerPointOfObjectOnScreen) : targetRect.position;

            Vector2 sizeOfTarget = new Vector2();

            // If the calculated delta size is negative, the current transform is not dictating the size of the element. Look in parents for size.
            if (targetRect.sizeDelta.x < 0 || targetRect.sizeDelta.y < 0)
            {
                bool      validSizeDelta = false;
                Transform currentTarget  = targetRect.parent;
                while (!validSizeDelta && currentTarget != null)
                {
                    sizeOfTarget = targetRect.parent.GetComponent <RectTransform>().sizeDelta;
                    if (targetRect.sizeDelta.x < 0 && targetRect.sizeDelta.y < 0)
                    {
                        validSizeDelta = true;
                    }
                    currentTarget = currentTarget.parent;
                }
            }

            if (sizeOfTarget.x == 0 || sizeOfTarget.y == 0)
            {
                sizeOfTarget = targetRect.sizeDelta;
            }

            int stretchBiasY = sizeOfTarget.y > sizeOfTarget.x ? 40 : 0;
            int stretchBiasX = sizeOfTarget.x > sizeOfTarget.y ? 40 : 0;

            squareRect.sizeDelta = new Vector2(sizeOfTarget.x + 50 + stretchBiasX, sizeOfTarget.y + 50 + stretchBiasY);
            squareRect.position  = new Vector3(centerPointOfObjectOnScreen.x, centerPointOfObjectOnScreen.y, 0);
            RawImage img = square.GetComponent <RawImage>();

            img.color = new Color32(0, 255, 255, 200);
            square.SetActive(true);
            StartCoroutine(HandleHighlightRemoval(square, target, highlighterGo));
            VisualFxCanvases.RemoveAt(0);
            HighlightSquares.RemoveAt(0);
        }