public static T[] ToArrayPooled <T>(this IEnumerable <T> source)
    {
        var array = ArrayPool <T> .New(source.Count());

        var i = 0;

        foreach (var item in source)
        {
            array[i++] = item;
        }

        return(array);
    }
        public static Rect?BoundsToGUIRect(this SceneView sceneView, Bounds worldBounds)
        {
            var worldPoints = ArrayPool <Vector3> .New(8);

            worldBounds.GetPointsNoAlloc(worldPoints);

            Rect?guiRect = null;

            foreach (var worldPoint in worldPoints)
            {
                var guiPoint = sceneView.WorldToGUIPoint(worldPoint);

                if (guiPoint.z < 0)
                {
                    continue;
                }

                guiRect = guiRect.Encompass(guiPoint);
            }

            worldPoints.Free();

            return(guiRect);
        }
Beispiel #3
0
        public static void PickAllNonAlloc(List <ProbeHit> hits, ProbeFilter filter, SceneView sceneView, Vector2 guiPosition, int limit = DefaultLimit)
        {
            var screenPosition = HandleUtility.GUIPointToScreenPixelCoordinate(guiPosition);
            var ray3D          = HandleUtility.GUIPointToWorldRay(guiPosition);
            var worldPosition  = sceneView.camera.ScreenToWorldPoint(screenPosition);
            var layerMask      = PeekPlugin.Configuration.probeLayerMask;

            var raycastHits = ArrayPool <RaycastHit> .New(limit);

            var overlapHits = ArrayPool <Collider2D> .New(limit);

            var handleHits = HashSetPool <GameObject> .New();

            var ancestorHits = HashSetPool <ProbeHit> .New();

#if PROBUILDER_4_OR_NEWER
            var proBuilderHits = ListPool <ProbeHit> .New();
#endif

            var gameObjectHits = DictionaryPool <GameObject, ProbeHit> .New();

            try
            {
                // Raycast (3D)
                if (filter.raycast)
                {
                    var raycastHitCount = Physics.RaycastNonAlloc(ray3D, raycastHits, Mathf.Infinity, layerMask);

                    for (var i = 0; i < raycastHitCount; i++)
                    {
                        var raycastHit = raycastHits[i];

#if UNITY_2019_2_OR_NEWER
                        if (SceneVisibilityManager.instance.IsHidden(raycastHit.transform.gameObject))
                        {
                            continue;
                        }
#endif

                        var gameObject = raycastHit.transform.gameObject;

                        if (!gameObjectHits.TryGetValue(gameObject, out var hit))
                        {
                            hit = new ProbeHit(gameObject);
                        }

                        hit.point    = raycastHit.point;
                        hit.distance = raycastHit.distance;

                        gameObjectHits[gameObject] = hit;
                    }
                }

                // Overlap (2D)
                if (filter.overlap)
                {
                    var overlapHitCount = Physics2D.OverlapPointNonAlloc(worldPosition, overlapHits, layerMask);

                    for (var i = 0; i < overlapHitCount; i++)
                    {
                        var overlapHit = overlapHits[i];

#if UNITY_2019_2_OR_NEWER
                        if (SceneVisibilityManager.instance.IsHidden(overlapHit.transform.gameObject))
                        {
                            continue;
                        }
#endif

                        var gameObject = overlapHit.transform.gameObject;

                        if (!gameObjectHits.TryGetValue(gameObject, out var hit))
                        {
                            hit = new ProbeHit(gameObject);
                        }

                        hit.distance = hit.distance ?? Vector3.Distance(overlapHit.transform.position, worldPosition);

                        gameObjectHits[gameObject] = hit;
                    }
                }

                // Handles (Editor Default)
                if (filter.handles && canPickHandles)
                {
                    PickAllHandlesNonAlloc(handleHits, guiPosition, limit);

                    foreach (var handleHit in handleHits)
                    {
                        var gameObject = handleHit;

                        if (!gameObjectHits.TryGetValue(gameObject, out var hit))
                        {
                            hit = new ProbeHit(gameObject);
                        }

                        hit.distance = hit.distance ?? Vector3.Distance(handleHit.transform.position, worldPosition);

                        gameObjectHits[gameObject] = hit;
                    }
                }

                // Ancestors
                foreach (var gameObjectHit in gameObjectHits)
                {
                    var gameObject = gameObjectHit.Key;
                    var hit        = gameObjectHit.Value;

                    var parent = gameObject.transform.parent;

                    int depth = 0;

                    while (parent != null)
                    {
                        var parentGameObject = parent.gameObject;

                        var parentHit = new ProbeHit(parentGameObject);
                        parentHit.groupGameObject = gameObject;
                        parentHit.distance        = hit.distance ?? Vector3.Distance(parentHit.transform.position, worldPosition);
                        parentHit.groupOrder      = 1000 + depth;

                        ancestorHits.Add(parentHit);

                        parent = parent.parent;
                        depth++;
                    }
                }

#if PROBUILDER_4_OR_NEWER
                // ProBuilder
                if (filter.proBuilder && ProBuilderEditor.instance != null)
                {
                    var proBuilderMeshes = ListPool <ProBuilderMesh> .New();

                    try
                    {
                        foreach (var gameObjectHit in gameObjectHits.Values)
                        {
                            var proBuilderMesh = gameObjectHit.gameObject.GetComponent <ProBuilderMesh>();

                            if (proBuilderMesh != null)
                            {
                                proBuilderMeshes.Add(proBuilderMesh);
                            }
                        }

                        PickProBuilderElementsNonAlloc(proBuilderHits, proBuilderMeshes, sceneView, guiPosition);
                    }
                    finally
                    {
                        proBuilderMeshes.Free();
                    }
                }
#endif

                // Prepare final hits
                hits.Clear();

                // Add hits
                foreach (var gameObjectHit in gameObjectHits.Values)
                {
                    hits.Add(gameObjectHit);
                }

                foreach (var ancestorHit in ancestorHits)
                {
                    hits.Add(ancestorHit);
                }

#if PROBUILDER_4_OR_NEWER
                foreach (var proBuilderHit in proBuilderHits)
                {
                    hits.Add(proBuilderHit);
                }
#endif

                // Sort by distance
                hits.Sort(compareHits);
            }
            finally
            {
                raycastHits.Free();
                overlapHits.Free();
                handleHits.Free();
                ancestorHits.Free();

#if PROBUILDER_4_OR_NEWER
                proBuilderHits.Free();
#endif

                gameObjectHits.Free();
            }
        }
Beispiel #4
0
        public static bool CalculateBounds
        (
            this GameObject root,
            out Bounds bounds,
            Space space,
            bool renderers = true,
            bool colliders = true,
            bool meshes    = false,
            bool graphics  = true,
            bool particles = false)
        {
            bounds = new Bounds();

            var first = true;

            if (space == Space.Self)
            {
                if (renderers)
                {
                    var _renderers = ListPool <Renderer> .New();

                    root.GetComponentsInChildren(_renderers);

                    foreach (var renderer in _renderers)
                    {
                        if (!renderer.enabled)
                        {
                            continue;
                        }

                        if (!particles && renderer is ParticleSystemRenderer)
                        {
                            continue;
                        }

                        var rendererBounds = renderer.bounds;

                        rendererBounds.SetMinMax
                        (
                            root.transform.InverseTransformPoint(rendererBounds.min),
                            root.transform.InverseTransformPoint(rendererBounds.max)
                        );

                        if (first)
                        {
                            bounds = rendererBounds;
                            first  = false;
                        }
                        else
                        {
                            bounds.Encapsulate(rendererBounds);
                        }
                    }

                    _renderers.Free();
                }

                if (meshes)
                {
                    var _meshFilters = ListPool <MeshFilter> .New();

                    root.GetComponentsInChildren(_meshFilters);

                    foreach (var meshFilter in _meshFilters)
                    {
                        var mesh = meshFilter.sharedMesh;

                        if (mesh == null)
                        {
                            continue;
                        }

                        var meshBounds = mesh.bounds;

                        meshBounds.SetMinMax
                        (
                            root.transform.InverseTransformPoint(meshFilter.transform.TransformPoint(meshBounds.min)),
                            root.transform.InverseTransformPoint(meshFilter.transform.TransformPoint(meshBounds.max))
                        );

                        if (first)
                        {
                            bounds = meshBounds;
                            first  = false;
                        }
                        else
                        {
                            bounds.Encapsulate(meshBounds);
                        }
                    }

                    _meshFilters.Free();
                }

                if (graphics)
                {
                    var _graphics = ListPool <Graphic> .New();

                    root.GetComponentsInChildren(_graphics);

                    foreach (var graphic in _graphics)
                    {
                        if (!graphic.enabled)
                        {
                            continue;
                        }

                        var graphicCorners = ArrayPool <Vector3> .New(4);

                        graphic.rectTransform.GetLocalCorners(graphicCorners);
                        var graphicsBounds = BoundsFromCorners(graphicCorners);
                        graphicCorners.Free();

                        if (first)
                        {
                            bounds = graphicsBounds;
                            first  = false;
                        }
                        else
                        {
                            bounds.Encapsulate(graphicsBounds);
                        }
                    }

                    _graphics.Free();
                }

                if (colliders && first)
                {
                    var _colliders = ListPool <Collider> .New();

                    root.GetComponentsInChildren(_colliders);

                    foreach (var collider in _colliders)
                    {
                        if (!collider.enabled)
                        {
                            continue;
                        }

                        var colliderBounds = collider.bounds;

                        colliderBounds.SetMinMax
                        (
                            root.transform.InverseTransformPoint(colliderBounds.min),
                            root.transform.InverseTransformPoint(colliderBounds.max)
                        );

                        if (first)
                        {
                            bounds = colliderBounds;
                            first  = false;
                        }
                        else
                        {
                            bounds.Encapsulate(colliderBounds);
                        }
                    }

                    _colliders.Free();
                }

                return(!first);
            }
            else             // if (space == Space.World)
            {
                if (renderers)
                {
                    var _renderers = ListPool <Renderer> .New();

                    root.GetComponentsInChildren(_renderers);

                    foreach (var renderer in _renderers)
                    {
                        if (!renderer.enabled)
                        {
                            continue;
                        }

                        if (!particles && renderer is ParticleSystemRenderer)
                        {
                            continue;
                        }

                        if (first)
                        {
                            bounds = renderer.bounds;
                            first  = false;
                        }
                        else
                        {
                            bounds.Encapsulate(renderer.bounds);
                        }
                    }

                    _renderers.Free();
                }

                if (meshes)
                {
                    var _meshFilters = ListPool <MeshFilter> .New();

                    root.GetComponentsInChildren(_meshFilters);

                    foreach (var meshFilter in _meshFilters)
                    {
                        var mesh = meshFilter.sharedMesh;

                        if (mesh == null)
                        {
                            continue;
                        }

                        var meshBounds = mesh.bounds;

                        meshBounds.SetMinMax
                        (
                            root.transform.TransformPoint(meshBounds.min),
                            root.transform.TransformPoint(meshBounds.max)
                        );

                        if (first)
                        {
                            bounds = meshBounds;
                            first  = false;
                        }
                        else
                        {
                            bounds.Encapsulate(meshBounds);
                        }
                    }

                    _meshFilters.Free();
                }

                if (graphics)
                {
                    var _graphics = ListPool <Graphic> .New();

                    root.GetComponentsInChildren(_graphics);

                    foreach (var graphic in _graphics)
                    {
                        if (!graphic.enabled)
                        {
                            continue;
                        }

                        var graphicCorners = ArrayPool <Vector3> .New(4);

                        graphic.rectTransform.GetWorldCorners(graphicCorners);
                        var graphicsBounds = BoundsFromCorners(graphicCorners);
                        graphicCorners.Free();

                        if (first)
                        {
                            bounds = graphicsBounds;
                            first  = false;
                        }
                        else
                        {
                            bounds.Encapsulate(graphicsBounds);
                        }
                    }

                    _graphics.Free();
                }

                if (colliders && first)
                {
                    var _colliders = ListPool <Collider> .New();

                    root.GetComponentsInChildren(_colliders);

                    foreach (var collider in _colliders)
                    {
                        if (!collider.enabled)
                        {
                            continue;
                        }

                        if (first)
                        {
                            bounds = collider.bounds;
                            first  = false;
                        }
                        else
                        {
                            bounds.Encapsulate(collider.bounds);
                        }
                    }

                    _colliders.Free();
                }
            }

            return(!first);
        }
        protected override void UpdateTools(IList <ITool> tools)
        {
            if (mainTool != null)
            {
                tools.Add(mainTool);
            }

            if (hasPrefabTarget)
            {
                return;
            }

            mergedScriptsTool.tools.Clear();

            foreach (var components in ComponentCache.GetSharedComponents(targets))
            {
                // Being extra picky about allocation here
                var targets = ArrayPool <UnityObject> .New(components.Count);

                try
                {
                    var hide = false;

                    for (var i = 0; i < components.Count; i++)
                    {
                        targets[i] = components[i];

                        if (!ShouldShowComponent(components[i]))
                        {
                            hide = true;
                            break;
                        }
                    }

                    if (hide)
                    {
                        continue;
                    }

                    var componentStrip = ObjectToolbarProvider.GetToolbar(targets);

                    if (componentStrip.isValid)
                    {
                        componentStrip.Update();

                        foreach (var componentTool in componentStrip)
                        {
                            if (componentTool is IEditorTool componentEditorTool && typeof(MonoBehaviour).IsAssignableFrom(componentEditorTool.targetType))
                            {
                                var hasIcon = componentEditorTool.targetType.Icon()?[IconSize.Small] != PeekPlugin.Icons.script?[IconSize.Small];
                                var merge   = PeekPlugin.Configuration.scriptsMerging.Merge(hasIcon);

                                if (merge)
                                {
                                    mergedScriptsTool.tools.Add(componentEditorTool);
                                }
                                else
                                {
                                    tools.Add(componentEditorTool);
                                }
                            }
                            else
                            {
                                tools.Add(componentTool);
                            }
                        }
                    }
                }