Esempio n. 1
0
        /// <summary>Searches the second vertex needed for Find2VerticesForVertexSnapping method amongst SELECTED GameObject PIVOTS.</summary>
        /// <param name="transform">The parent</param>
        /// <param name="lastClosestDistanceGUIspace">The distance to cursor from the closest vertex in GUI space so far</param>
        /// <param name="meshFilter">The reusable mesh filter variable</param>
        /// <param name="renderer">The reusable renderer variable</param>
        /// <param name="vertices">The reusable vertices array</param>
        /// <param name="closestVertexGUISpace">INPUT, the previously found closest vertex to the mouse cursor amongst NON-selected meshes</param>
        /// <param name="closestSelectedVertexWorldSpace">OUTPUT Is returned as the closest vertex to the mouse cursor amongst SELECTED
        /// models world space</param>
        public static void IterateChildGameObjects(Transform transform, ref GameObject ClosestGO,
                                                   ref float lastClosestDistanceGUIspace, MeshFilter meshFilter,
                                                   MeshRenderer renderer, Vector3[] vertices, ref Vector2 closestVertexGUISpace, ref Vector3 closestSelectedVertexWorldSpace,
                                                   ref VertexSnappingResult methodResult)
        {
            //#colreg(red*0.3);
            if (transform != null && transform.gameObject != null && transform.gameObject.activeInHierarchy && transform.gameObject.activeSelf)
            {
                Vector3 worldPoint = transform.position;
                float   distance   = Vector2.SqrMagnitude(closestVertexGUISpace - HandleUtility.WorldToGUIPoint(worldPoint));

                if (lastClosestDistanceGUIspace < 0 || distance < lastClosestDistanceGUIspace)                  // find the closest pivot GUI-space
                {
                    lastClosestDistanceGUIspace = distance;
                    ClosestGO = transform.gameObject;
                    closestSelectedVertexWorldSpace = worldPoint;                       // our second ultimate goal
                    methodResult = VertexSnappingResult.BothVectorsFound;
                }

                int children = transform.childCount;
                for (int i = 0; i < children; ++i)
                {
                    IterateChildGameObjects(transform.GetChild(i), ref ClosestGO,
                                            ref lastClosestDistanceGUIspace, meshFilter, renderer, vertices,
                                            ref closestVertexGUISpace, ref closestSelectedVertexWorldSpace, ref methodResult);
                }
            }
            //#endcolreg
        }
Esempio n. 2
0
        /// <summary>Finds 2 3d points in World space, where 1st is the closest vertex to the mouse cursor
        /// amongst NON-selected models, and the 2nd one is the closest vertex to the mouse cursor amongst
        /// SELECTED models.</summary>
        /// <param name="sceneCam">The camera of the editor window</param>
        /// <param name="mousePos">The screen space position of the mouse</param>
        /// <param name="closestVertexWorldSpace">Is returned as the closest vertex to the mouse cursor amongst NON-selected models</param>
        /// <param name="closestSelectedVertexWorldSpace">Is returned as the closest vertex to the mouse cursor amongst SELECTED models</param>
        /// <param name="returnOnly1stVertex">If set, ignores whether there is any selected models and only searches for 1 vertex
        /// which is the closest vertex to the mouse cursor amongst ALL models</param>
        /// <param name="ignoreZeroesOnX">When searching for a vertex among SELECTED models,
        /// ignore those that have zero values in x variable in local space</param>
        /// <param name="ignoreZeroesOnY">When searching for a vertex among SELECTED models,
        /// ignore those that have zero values in y variable in local space</param>
        /// <param name="ignoreZeroesOnZ">When searching for a vertex among SELECTED models,
        /// ignore those that have zero values in z variable in local space</param>
        /// <param name="pivot">Transformation pivot moved to local space which is subtracted before we check for zeroes</param>
        public static VertexSnappingResult Find2VerticesForVertexSnapping(Camera sceneCam, Vector2 mousePos,
                                                                          out Vector3 closestVertexWorldSpace, out Vector3 closestSelectedVertexWorldSpace, out GameObject ClosestGO,
                                                                          bool returnOnly1stVertex = false,
                                                                          bool ignoreZeroesOnX     = false, bool ignoreZeroesOnY = false, bool ignoreZeroesOnZ = false, Vector3 pivot = default(Vector3))
        {
            //#colreg(red*0.3);
            ClosestGO = null;
            VertexSnappingResult methodResult = VertexSnappingResult.NoVectorsFound;

            closestVertexWorldSpace         = Vector3.zero;
            closestSelectedVertexWorldSpace = Vector3.zero;

            Object[] allMeshRenderers = Object.FindObjectsOfType(typeof(MeshRenderer)) as Object[];
            Object[] allSkinnedMeshes = Object.FindObjectsOfType(typeof(SkinnedMeshRenderer)) as Object[];
            Object[] allMeshes        = new Object[allMeshRenderers.Length + allSkinnedMeshes.Length];
            allMeshRenderers.CopyTo(allMeshes, 0);
            allSkinnedMeshes.CopyTo(allMeshes, allMeshRenderers.Length);

            // Find world space things
            Ray    mouseRayWorldSpace    = sceneCam.ScreenPointToRay(mousePos);
            Bounds mouseBoundsWorldSpace = new Bounds(mouseRayWorldSpace.origin, new Vector3(1f, 1f, 1f));

            // Find GUI space things
            Vector2 mouseGUIPos = HandleUtility.WorldToGUIPoint(mouseRayWorldSpace.origin);
            Rect    mouseRect   = WorldSpaceBoundsToGUISpaceRect(mouseBoundsWorldSpace);

            mouseRect.xMin -= sceneCam.pixelWidth * 0.01f;
            mouseRect.yMin -= sceneCam.pixelHeight * 0.01f;

            mouseRect.xMax += sceneCam.pixelWidth * 0.01f;
            mouseRect.yMax += sceneCam.pixelHeight * 0.01f;


            Vector3[]           vertices = null;
            MeshFilter          filter   = null;
            Rect                rect;
            MeshRenderer        meshRenderer     = null;
            SkinnedMeshRenderer skinnedRenderer  = null;
            Transform           currentTransform = null;

            Vector2 closestVertexGUISpace       = Vector2.zero;
            float   lastClosestDistanceGUIspace = 700;              // This is the radius of the search. Hardcoded, no need to make it modular.

            Vector3 vertex = Vector3.zero;



            // Find a vertex, among non-selected meshes, that is closest to the mouse.
            for (int i = 0; i < allMeshes.Length; i++)
            {
                meshRenderer = allMeshes[i] as MeshRenderer;

                bool checkSuccessful = false;

                if (meshRenderer != null && meshRenderer.gameObject != null &&
                    meshRenderer.gameObject.transform != null && meshRenderer.enabled && meshRenderer.isVisible &&
                    meshRenderer.gameObject.activeInHierarchy && meshRenderer.gameObject.activeSelf &&
                    (!Selection.Contains(meshRenderer.gameObject) || returnOnly1stVertex))
                {
                    filter = null;
                    filter = meshRenderer.gameObject.GetComponent <MeshFilter>();
                    if (filter != null && filter.sharedMesh != null)
                    {
                        rect = WorldSpaceBoundsToGUISpaceRect(meshRenderer.bounds);

                        if (rect.Overlaps(mouseRect, true))
                        {
                            vertices = null;
                            vertices = filter.sharedMesh.vertices;                              // Get local-space vertices
                            if (vertices != null && vertices.Length > 0)
                            {
                                currentTransform = null;
                                currentTransform = filter.transform;
                                if (currentTransform != null)
                                {
                                    checkSuccessful = true;
                                }
                            }
                        }
                    }
                }

                if (!checkSuccessful)
                {
                    skinnedRenderer = allMeshes[i] as SkinnedMeshRenderer;

                    if (skinnedRenderer != null && skinnedRenderer.gameObject != null &&
                        skinnedRenderer.gameObject.transform != null && skinnedRenderer.enabled && skinnedRenderer.isVisible &&
                        skinnedRenderer.gameObject.activeInHierarchy && skinnedRenderer.gameObject.activeSelf &&
                        (!Selection.Contains(skinnedRenderer.gameObject) || returnOnly1stVertex) &&
                        skinnedRenderer.sharedMesh != null)
                    {
                        rect = WorldSpaceBoundsToGUISpaceRect(skinnedRenderer.bounds);

                        if (rect.Overlaps(mouseRect, true))
                        {
                            vertices = null;
                            vertices = skinnedRenderer.sharedMesh.vertices;                              // Get local-space vertices
                            if (vertices != null && vertices.Length > 0)
                            {
                                currentTransform = null;
                                currentTransform = skinnedRenderer.transform;
                                if (currentTransform != null)
                                {
                                    checkSuccessful = true;
                                }
                            }
                        }
                        checkSuccessful = true;
                    }
                }

                if (checkSuccessful)
                {
                    if (vertices != null)
                    {
                        int n = vertices.Length;
                        while (--n > -1)
                        {
                            vertex = vertices[n];
                            Vector3 worldPoint     = currentTransform.TransformPoint(vertex);                            // transform world-space
                            Vector2 vertexGUISpace = HandleUtility.WorldToGUIPoint(worldPoint);                          // transform GUI-space

                            float distance = Vector2.SqrMagnitude(mouseGUIPos - vertexGUISpace);

                            // Check if it's close enough to the mouse in GUI space. All comparisons
                            //	are in GUI space because that's how the user sees the working area.
                            if (distance < lastClosestDistanceGUIspace)
                            {
                                lastClosestDistanceGUIspace = distance;
                                closestVertexWorldSpace     = worldPoint;                                // our first ultimate goal.
                                closestVertexGUISpace       = vertexGUISpace;                            // save for later
                                methodResult = VertexSnappingResult.FirstVectorFound;
                            }
                        }
                    }
                }
            }


            // ONLY if the first (NON-selected) vertex is found we search for the second (SELECTED) vertex
            if (!returnOnly1stVertex && Selection.gameObjects.Length > 0 &&
                // We have a vertex from a non-selected mesh near our mouse.
                lastClosestDistanceGUIspace < 700)
            {
                lastClosestDistanceGUIspace = -1;                   // Reuse this variable
                for (int i = 0; i < Selection.gameObjects.Length; i++)
                {
                    if (Selection.gameObjects[i] != null)
                    {
                        IterateChildMeshes(Selection.gameObjects[i].transform, ref ClosestGO, ref lastClosestDistanceGUIspace, meshRenderer,
                                           filter, skinnedRenderer, vertices, currentTransform, ref closestVertexGUISpace,
                                           ref closestSelectedVertexWorldSpace, ref methodResult, ignoreZeroesOnX, ignoreZeroesOnY, ignoreZeroesOnZ, pivot);
                    }
                }

                if (lastClosestDistanceGUIspace < 0)                    // We have no MeshFilter-s. Use GameObjects' pivots instead
                {
                    lastClosestDistanceGUIspace = -1;                   // Reuse this variable
                    for (int i = 0; i < Selection.gameObjects.Length; i++)
                    {
                        if (Selection.gameObjects[i] != null)
                        {
                            IterateChildGameObjects(Selection.gameObjects[i].transform, ref ClosestGO, ref lastClosestDistanceGUIspace, filter,
                                                    meshRenderer, vertices, ref closestVertexGUISpace, ref closestSelectedVertexWorldSpace, ref methodResult);
                        }
                    }
                }
            }

            return(methodResult);
            //#endcolreg
        }
Esempio n. 3
0
        /// <summary>Searches the second vertex needed for Find2VerticesForVertexSnapping method amongst SELECTED MESHES.</summary>
        /// <param name="transform">The parent</param>
        /// <param name="lastClosestDistanceGUIspace">The distance to cursor from the closest vertex in GUI space so far</param>
        /// <param name="meshRenderer">The reusable mesh renderer variable</param>
        /// <param name="meshFilter">The reusable mesh filter variable</param>
        /// <param name="skinnedMesh">The reusable skinned mesh renderer variable</param>
        /// <param name="vertices">The reusable vertices array</param>
        /// <param name="curTransform">The reusable transform variable that is used to translate vertices from local to world space</param>
        /// <param name="closestVertexGUISpace">INPUT, the previously found closest vertex to the mouse cursor amongst NON-selected meshes</param>
        /// <param name="closestSelectedVertexWorldSpace">OUTPUT Is returned as the closest vertex to the mouse cursor amongst SELECTED
        /// models world space</param>
        /// <param name="ignoreZeroesOnX">When searching for a vertex among SELECTED models,
        /// ignore those that have zero values in x variable in local space</param>
        /// <param name="ignoreZeroesOnY">When searching for a vertex among SELECTED models,
        /// ignore those that have zero values in y variable in local space</param>
        /// <param name="ignoreZeroesOnZ">When searching for a vertex among SELECTED models,
        /// ignore those that have zero values in z variable in local space</param>
        /// <param name="pivot">Transformation pivot moved to local space which is subtracted before we check for zeroes</param>
        public static void IterateChildMeshes(Transform transform, ref GameObject ClosestGO,
                                              ref float lastClosestDistanceGUIspace, MeshRenderer meshRenderer,
                                              MeshFilter meshFilter, SkinnedMeshRenderer skinnedMesh, Vector3[] vertices, Transform curTransform,
                                              ref Vector2 closestVertexGUISpace, ref Vector3 closestSelectedVertexWorldSpace, ref VertexSnappingResult methodResult,
                                              bool ignoreZeroesOnX = false, bool ignoreZeroesOnY = false, bool ignoreZeroesOnZ = false, Vector3 pivot = default(Vector3))
        {
            //#colreg(red*0.3);
            if (transform != null && transform.gameObject != null && transform.gameObject.activeInHierarchy && transform.gameObject.activeSelf)
            {
                bool checkSuccesfull = false;

                Vector3 vertex = Vector3.zero;
                meshFilter   = null;
                meshFilter   = transform.gameObject.GetComponent <MeshFilter>();
                meshRenderer = transform.gameObject.GetComponent <MeshRenderer>();

                // We don't check for mouse Rect here, because it is intentional that the
                //	tool works even from across the globe for SELECTED meshes

                if (meshFilter != null && meshRenderer != null && meshRenderer.enabled && meshRenderer.isVisible &&
                    meshFilter.sharedMesh != null)
                {
                    vertices = null;
                    vertices = meshFilter.sharedMesh.vertices;                      // Get local-space vertices

                    if (vertices != null && vertices.Length > 0)
                    {
                        curTransform = null;
                        curTransform = meshFilter.transform;
                        if (curTransform != null)
                        {
                            checkSuccesfull = true;
                        }
                    }
                }

                if (!checkSuccesfull)
                {
                    skinnedMesh = transform.gameObject.GetComponent <SkinnedMeshRenderer>();

                    if (skinnedMesh != null && skinnedMesh.enabled && skinnedMesh.isVisible &&
                        skinnedMesh.sharedMesh != null)
                    {
                        vertices = null;
                        vertices = skinnedMesh.sharedMesh.vertices;                          // Get local-space vertices

                        if (vertices != null && vertices.Length > 0)
                        {
                            curTransform = null;
                            curTransform = skinnedMesh.transform;
                            if (curTransform != null)
                            {
                                checkSuccesfull = true;
                            }
                        }
                    }
                }

                if (checkSuccesfull)
                {
                    if (vertices != null)
                    {
                        int n = vertices.Length;
                        while (--n > -1)
                        {
                            vertex = vertices[n];

                            // Zero values in vertices in local space can produce glitches during scaling
                            //	when there is a transform lock set. This way we try to filter them out.
                            //	Blender does this better somehow, this is my way of doing it.
                            if ((!ignoreZeroesOnX || Mathf.Abs((vertex - pivot).x) > 0.000001f) &&
                                (!ignoreZeroesOnY || Mathf.Abs((vertex - pivot).y) > 0.000001f) &&
                                (!ignoreZeroesOnZ || Mathf.Abs((vertex - pivot).z) > 0.000001f))
                            {
                                Vector3 worldPoint = curTransform.TransformPoint(vertex);                                    // transform world-space
                                float   distance   = Vector2.SqrMagnitude(closestVertexGUISpace - HandleUtility.WorldToGUIPoint(worldPoint));

                                // find the closest vertex GUI-space
                                if (lastClosestDistanceGUIspace < 0 || distance < lastClosestDistanceGUIspace)
                                {
                                    lastClosestDistanceGUIspace = distance;
                                    ClosestGO = transform.gameObject;
                                    closestSelectedVertexWorldSpace = worldPoint;                                       // our second ultimate goal
                                    methodResult = VertexSnappingResult.BothVectorsFound;
                                }
                            }
                        }
                    }
                }

                int children = transform.childCount;
                for (int i = 0; i < children; ++i)
                {
                    IterateChildMeshes(transform.GetChild(i), ref ClosestGO,
                                       ref lastClosestDistanceGUIspace, meshRenderer, meshFilter, skinnedMesh,
                                       vertices, curTransform, ref closestVertexGUISpace, ref closestSelectedVertexWorldSpace, ref methodResult);
                }
            }
            //#endcolreg
        }