Exemplo n.º 1
0
        public void BuildNavigation(SelectableGroup group)
        {
            Vector3 position;
            Vector3 direction;
            Vector3 localDir;
            float   maxScore;

            foreach (SelectableOptionBase option in group.options)
            {
                Transform transform = option.GetTransform();

                for (int i = 0; i < option.navigationArray.Length; i++)
                {
                    maxScore = Mathf.NegativeInfinity;

                    direction = SelectableNavigationUtils.GetDirectionVector((SelectableNavigationDirection)i);
                    localDir  = Quaternion.Inverse(transform.rotation) * direction;
                    position  = transform.TransformPoint(SelectableNavigationUtils.GetPointOnRectEdge(transform as RectTransform, localDir));

                    SelectableOptionBase bestPick = null;
                    foreach (SelectableOptionBase other in group.options)
                    {
                        SelectableOptionBase sel = other;

                        if (sel == option || sel == null)
                        {
                            continue;
                        }

                        var     selRect   = sel.GetTransform() as RectTransform;
                        Vector3 selCenter = selRect != null ? (Vector3)selRect.rect.center : Vector3.zero;
                        Vector3 myVector  = sel.GetTransform().TransformPoint(selCenter) - position;

                        // Value that is the distance out along the direction.
                        float dot = Vector3.Dot(direction, myVector);

                        // Skip elements that are in the wrong direction or which have zero or too much distance.
                        // This also ensures that the scoring formula below will not have a division by zero error.
                        if (dot <= 0)
                        {
                            continue;
                        }

                        // This scoring function has two priorities:
                        // - Score higher for positions that are closer.
                        // - Score higher for positions that are located in the right direction.
                        // This scoring function combines both of these criteria.
                        float score = dot / myVector.sqrMagnitude;

                        if (score > maxScore)
                        {
                            maxScore = score;
                            bestPick = sel;
                        }
                    }

                    option.navigationArray[i] = bestPick;
                }
            }
        }
    private static void DrawNavigationArrow(Vector2 direction, SelectableOptionBase fromObj, SelectableOptionBase toObj)
    {
        if (fromObj == null || toObj == null)
        {
            return;
        }
        Transform fromTransform = fromObj.transform;
        Transform toTransform   = toObj.transform;

        Vector2 sideDir   = new Vector2(direction.y, -direction.x);
        Vector3 fromPoint = fromTransform.TransformPoint(SelectableNavigationUtils.GetPointOnRectEdge(fromTransform as RectTransform, direction));
        Vector3 toPoint   = toTransform.TransformPoint(SelectableNavigationUtils.GetPointOnRectEdge(toTransform as RectTransform, -direction));
        float   fromSize  = HandleUtility.GetHandleSize(fromPoint) * 0.05f;
        float   toSize    = HandleUtility.GetHandleSize(toPoint) * 0.05f;

        fromPoint += fromTransform.TransformDirection(sideDir) * fromSize;
        toPoint   += toTransform.TransformDirection(sideDir) * toSize;
        float   length      = Vector3.Distance(fromPoint, toPoint);
        Vector3 fromTangent = fromTransform.rotation * direction * length * 0.3f;
        Vector3 toTangent   = toTransform.rotation * -direction * length * 0.3f;

        Handles.DrawBezier(fromPoint, toPoint, fromPoint + fromTangent, toPoint + toTangent, Handles.color, null, kArrowThickness);
        Handles.DrawAAPolyLine(kArrowThickness, toPoint, toPoint + toTransform.rotation * (-direction - sideDir) * toSize * kArrowHeadSize);
        Handles.DrawAAPolyLine(kArrowThickness, toPoint, toPoint + toTransform.rotation * (-direction + sideDir) * toSize * kArrowHeadSize);
    }
Exemplo n.º 3
0
        private static void BuildSmartNavigation(List <SelectableOptionBase> options, float[] maxSearchDistances)
        {
            List <BoxCollider2D> cachedColliders    = new List <BoxCollider2D>();
            List <RectTransform> cachedTransforms   = new List <RectTransform>();
            List <int>           cachedLayerIndices = new List <int>();

            //Attach BoxCollider2Ds to every option and set to to default layer to allow Raycasts to work
            foreach (SelectableOptionBase option in options)
            {
                BoxCollider2D collider            = option.gameObject.AddComponent <BoxCollider2D>();
                RectTransform optionRectTransform = option.GetComponent <RectTransform>();

                collider.size = optionRectTransform.sizeDelta;
                cachedColliders.Add(collider);
                cachedTransforms.Add(optionRectTransform);
                cachedLayerIndices.Add(option.gameObject.layer);

                option.gameObject.layer = 0;
            }

            //Raycast from each control border to a direction for the given distance for the direction
            for (int i = 0; i < options.Count; i++)
            {
                for (int j = 0; j < maxSearchDistances.Length; j++)
                {
                    SelectableNavigationDirection direction = (SelectableNavigationDirection)j;
                    RectTransform optionRectTransform       = cachedTransforms[i];

                    RaycastHit2D hit = Physics2D.Raycast(GetRaycastOrigin(direction, optionRectTransform), SelectableNavigationUtils.GetDirectionVector(direction), maxSearchDistances[j]);

                    if (hit.transform != null)
                    {
                        SelectableOptionBase hitOption = hit.transform.GetComponent <SelectableOptionBase>();
                        if (hitOption != null)
                        {
                            options[i].SetNextOption(direction, hitOption);
                        }
                    }
                }
            }

            //Destroy the previously created BoxColliders and restore previous layer
            for (int i = 0; i < options.Count; i++)
            {
                if (Application.isPlaying)
                {
                    Object.Destroy(cachedColliders[i]);
                }
                else
                {
                    Object.DestroyImmediate(cachedColliders[i]);
                }
                options[i].gameObject.layer = cachedLayerIndices[i];
            }
        }
    public static void DrawNavigationForSelectable(SelectableOptionBase option)
    {
        if (option == null)
        {
            return;
        }

        Transform transform = option.transform;
        bool      active    = Selection.transforms.Any(e => e == transform);

        Handles.color = new Color(1.0f, 0.9f, 0.1f, active ? 1.0f : 0.4f);
        DrawNavigationArrow(-Vector2.right, option, option.GetNextOption(SelectableNavigationDirection.LEFT));
        DrawNavigationArrow(Vector2.right, option, option.GetNextOption(SelectableNavigationDirection.RIGHT));
        DrawNavigationArrow(Vector2.up, option, option.GetNextOption(SelectableNavigationDirection.UP));
        DrawNavigationArrow(-Vector2.up, option, option.GetNextOption(SelectableNavigationDirection.DOWN));
    }
 private void OnEnable()
 {
     option = (SelectableOptionBase)target;
 }