Example #1
0
        /**
         * Initialize a new instance of Quick Edit, taking care of caching and setting up the appropriate stores.
         */
        void Initialize()
        {
            SceneView.onSceneGUIDelegate += OnSceneGUI;
            Undo.undoRedoPerformed       += UndoRedoPerformed;

            if (selection == null)
            {
                selection           = ScriptableObject.CreateInstance <ElementCache>();
                selection.hideFlags = HideFlags.DontSave;
            }

            if (selection.mesh == null)
            {
                MeshFilter mf = Selection.transforms.Select(x => x.GetComponentInChildren <MeshFilter>()).FirstOrDefault();

                if (mf == null)
                {
                    SkinnedMeshRenderer mr = Selection.transforms.Select(x => x.GetComponentInChildren <SkinnedMeshRenderer>()).FirstOrDefault();
                    if (mr == null || mr.sharedMesh == null)
                    {
                        qe_Editor_Utility.ShowNotification("No Mesh Selected");
                        EditorApplication.delayCall += Close;
                    }
                    else
                    {
                        SetSelection(mr.gameObject);
                    }
                }
                else
                {
                    SetSelection(mf.gameObject);
                }
            }
            else
            {
                SceneView.RepaintAll();
            }

            LoadIcons();
        }
        public static bool VertexRaycast(Vector2 mousePosition, int rectSize, ElementCache selection, out int index)
        {
            qe_Mesh mesh = selection.mesh;

            float bestDistance = Mathf.Infinity;
            float distance = 0f;
            index = -1;

            GameObject go = HandleUtility.PickGameObject(mousePosition, false);

            if( go == null || go != selection.transform.gameObject )
            {
                Camera cam = SceneView.lastActiveSceneView.camera;
                int width = Screen.width;
                int height = Screen.height;

                Rect mouseRect = new Rect(mousePosition.x - (rectSize/2f), mousePosition.y - (rectSize/2f), rectSize, rectSize);
                List<int> user = (List<int>) selection.mesh.GetUserIndices();

                for(int i = 0; i < user.Count; i++)
                {
                    if( mouseRect.Contains( HandleUtility.WorldToGUIPoint(selection.verticesInWorldSpace[user[i]]) ) )
                    {
                        Vector3 v = cam.WorldToScreenPoint(selection.verticesInWorldSpace[user[i]]);

                        distance = Vector2.Distance(mousePosition, v);

                        if( distance < bestDistance )
                        {
                            if( v.z <= 0 || v.x < 0 || v.y < 0 || v.x > width || v.y > height )
                                continue;

                            if( PointIsOccluded(mesh, selection.verticesInWorldSpace[user[i]]) )
                                continue;

                            index = user[i];
                            bestDistance = Vector2.Distance(v, mousePosition);
                        }
                    }
                }
            }
            else
            {
                // Test culling
                List<qe_RaycastHit> hits;
                Ray ray = HandleUtility.GUIPointToWorldRay(mousePosition);

                if( MeshRaycast(ray, mesh, out hits, Mathf.Infinity, Culling.FrontBack) )
                {
                    // Sort from nearest hit to farthest
                    hits.Sort( (x, y) => x.Distance.CompareTo(y.Distance) );

                    // Find the nearest edge in the hit faces
                    Vector3[] v = mesh.vertices;

                    for(int i = 0; i < hits.Count; i++)
                    {
                        if(  PointIsOccluded(mesh, mesh.transform.TransformPoint(hits[i].Point)) )
                            continue;

                        foreach(int tri in mesh.faces[hits[i].FaceIndex].indices)
                        {
                            float d = Vector3.Distance(hits[i].Point, v[tri]);

                            if(d < bestDistance)
                            {
                                bestDistance = d;
                                index = tri;
                            }
                        }

                        if( Vector3.Dot(ray.direction, mesh.transform.TransformDirection(hits[i].Normal)) < 0f )
                            break;
                    }

                    if(index > -1 && Vector2.Distance(mousePosition, HandleUtility.WorldToGUIPoint(selection.verticesInWorldSpace[index])) > rectSize * 1.3f)
                    {
                        index = -1;
                    }
                }
            }

            if( index > -1 )
                index = mesh.ToUserIndex(index);

            return index > -1;
        }
Example #3
0
        public static bool VertexRaycast(Vector2 mousePosition, int rectSize, ElementCache selection, out int index)
        {
            qe_Mesh mesh = selection.mesh;

            float bestDistance = Mathf.Infinity;
            float distance     = 0f;

            index = -1;

            GameObject go = HandleUtility.PickGameObject(mousePosition, false);

            if (go == null || go != selection.transform.gameObject)
            {
                Camera cam    = SceneView.lastActiveSceneView.camera;
                int    width  = Screen.width;
                int    height = Screen.height;

                Rect       mouseRect = new Rect(mousePosition.x - (rectSize / 2f), mousePosition.y - (rectSize / 2f), rectSize, rectSize);
                List <int> user      = (List <int>)selection.mesh.GetUserIndices();

                for (int i = 0; i < user.Count; i++)
                {
                    if (mouseRect.Contains(HandleUtility.WorldToGUIPoint(selection.verticesInWorldSpace[user[i]])))
                    {
                        Vector3 v = cam.WorldToScreenPoint(selection.verticesInWorldSpace[user[i]]);

                        distance = Vector2.Distance(mousePosition, v);

                        if (distance < bestDistance)
                        {
                            if (v.z <= 0 || v.x < 0 || v.y < 0 || v.x > width || v.y > height)
                            {
                                continue;
                            }

                            if (PointIsOccluded(mesh, selection.verticesInWorldSpace[user[i]]))
                            {
                                continue;
                            }

                            index        = user[i];
                            bestDistance = Vector2.Distance(v, mousePosition);
                        }
                    }
                }
            }
            else
            {
                // Test culling
                List <qe_RaycastHit> hits;
                Ray ray = HandleUtility.GUIPointToWorldRay(mousePosition);

                if (MeshRaycast(ray, mesh, out hits, Mathf.Infinity, Culling.FrontBack))
                {
                    // Sort from nearest hit to farthest
                    hits.Sort((x, y) => x.Distance.CompareTo(y.Distance));

                    // Find the nearest edge in the hit faces
                    Vector3[] v = mesh.vertices;

                    for (int i = 0; i < hits.Count; i++)
                    {
                        if (PointIsOccluded(mesh, mesh.transform.TransformPoint(hits[i].Point)))
                        {
                            continue;
                        }

                        foreach (int tri in mesh.faces[hits[i].FaceIndex].indices)
                        {
                            float d = Vector3.Distance(hits[i].Point, v[tri]);

                            if (d < bestDistance)
                            {
                                bestDistance = d;
                                index        = tri;
                            }
                        }

                        if (Vector3.Dot(ray.direction, mesh.transform.TransformDirection(hits[i].Normal)) < 0f)
                        {
                            break;
                        }
                    }

                    if (index > -1 && Vector2.Distance(mousePosition, HandleUtility.WorldToGUIPoint(selection.verticesInWorldSpace[index])) > rectSize * 1.3f)
                    {
                        index = -1;
                    }
                }
            }

            if (index > -1)
            {
                index = mesh.ToUserIndex(index);
            }

            return(index > -1);
        }
        /**
         * Checks if mouse is over an edge, and if so, returns true setting @edge.
         */
        public static bool EdgeRaycast(Vector2 mousePosition, ElementCache selection, out qe_Edge edge)
        {
            qe_Mesh mesh = selection.mesh;

            Vector3 v0, v1;
            float bestDistance = Mathf.Infinity;
            float distance = 0f;
            edge = null;

            GameObject go = HandleUtility.PickGameObject(mousePosition, false);

            if( go == null || go != selection.transform.gameObject)
            {
                qe_Edge[] edges = mesh.userEdges;

                int width = Screen.width;
                int height = Screen.height;

                for(int i = 0; i < edges.Length; i++)
                {
                    v0 = selection.verticesInWorldSpace[edges[i].x];
                    v1 = selection.verticesInWorldSpace[edges[i].y];

                    distance = HandleUtility.DistanceToLine(v0, v1);

                    if ( distance < bestDistance && distance < MAX_EDGE_SELECT_DISTANCE )// && !PointIsOccluded(mesh, (v0+v1)*.5f) )
                    {
                        Vector3 vs0 = SceneView.lastActiveSceneView.camera.WorldToScreenPoint(v0);

                        // really simple frustum check (will fail on edges that have vertices outside the frustum but is visible)
                        if( vs0.z <= 0 || vs0.x < 0 || vs0.y < 0 || vs0.x > width || vs0.y > height )
                            continue;

                        Vector3 vs1 = SceneView.lastActiveSceneView.camera.WorldToScreenPoint(v1);

                        if( vs1.z <= 0 || vs1.x < 0 || vs1.y < 0 || vs1.x > width || vs1.y > height )
                            continue;

                        bestDistance = distance;
                        edge = edges[i];
                    }
                }
            }
            else
            {
                // Test culling
                List<qe_RaycastHit> hits;
                Ray ray = HandleUtility.GUIPointToWorldRay(mousePosition);

                if( MeshRaycast(ray, mesh, out hits, Mathf.Infinity, Culling.FrontBack) )
                {
                    // Sort from nearest hit to farthest
                    hits.Sort( (x, y) => x.Distance.CompareTo(y.Distance) );

                    // Find the nearest edge in the hit faces
                    Vector3[] v = mesh.vertices;

                    for(int i = 0; i < hits.Count; i++)
                    {
                        if(  PointIsOccluded(mesh, mesh.transform.TransformPoint(hits[i].Point)) )
                            continue;

                        foreach(qe_Edge e in mesh.faces[hits[i].FaceIndex].GetEdges())
                        {
                            float d = HandleUtility.DistancePointLine(hits[i].Point, v[e.x], v[e.y]);

                            if(d < bestDistance)
                            {
                                bestDistance = d;
                                edge = e;
                            }
                        }

                        if( Vector3.Dot(ray.direction, mesh.transform.TransformDirection(hits[i].Normal)) < 0f )
                            break;
                    }

                    if(edge != null && HandleUtility.DistanceToLine(mesh.transform.TransformPoint(v[edge.x]), mesh.transform.TransformPoint(v[edge.y])) > MAX_EDGE_SELECT_DISTANCE)
                    {
                        edge = null;
                    }
                    else
                    {
                        edge.x = mesh.ToUserIndex(edge.x);
                        edge.y = mesh.ToUserIndex(edge.y);
                    }
                }
            }

            return edge != null;
        }
Example #5
0
        /**
         * Checks if mouse is over an edge, and if so, returns true setting @edge.
         */
        public static bool EdgeRaycast(Vector2 mousePosition, ElementCache selection, out qe_Edge edge)
        {
            qe_Mesh mesh = selection.mesh;

            Vector3 v0, v1;
            float   bestDistance = Mathf.Infinity;
            float   distance     = 0f;

            edge = null;

            GameObject go = HandleUtility.PickGameObject(mousePosition, false);

            if (go == null || go != selection.transform.gameObject)
            {
                qe_Edge[] edges = mesh.userEdges;

                int width  = Screen.width;
                int height = Screen.height;

                for (int i = 0; i < edges.Length; i++)
                {
                    v0 = selection.verticesInWorldSpace[edges[i].x];
                    v1 = selection.verticesInWorldSpace[edges[i].y];

                    distance = HandleUtility.DistanceToLine(v0, v1);

                    if (distance < bestDistance && distance < MAX_EDGE_SELECT_DISTANCE)                      // && !PointIsOccluded(mesh, (v0+v1)*.5f) )
                    {
                        Vector3 vs0 = SceneView.lastActiveSceneView.camera.WorldToScreenPoint(v0);

                        // really simple frustum check (will fail on edges that have vertices outside the frustum but is visible)
                        if (vs0.z <= 0 || vs0.x < 0 || vs0.y < 0 || vs0.x > width || vs0.y > height)
                        {
                            continue;
                        }

                        Vector3 vs1 = SceneView.lastActiveSceneView.camera.WorldToScreenPoint(v1);

                        if (vs1.z <= 0 || vs1.x < 0 || vs1.y < 0 || vs1.x > width || vs1.y > height)
                        {
                            continue;
                        }


                        bestDistance = distance;
                        edge         = edges[i];
                    }
                }
            }
            else
            {
                // Test culling
                List <qe_RaycastHit> hits;
                Ray ray = HandleUtility.GUIPointToWorldRay(mousePosition);

                if (MeshRaycast(ray, mesh, out hits, Mathf.Infinity, Culling.FrontBack))
                {
                    // Sort from nearest hit to farthest
                    hits.Sort((x, y) => x.Distance.CompareTo(y.Distance));

                    // Find the nearest edge in the hit faces
                    Vector3[] v = mesh.vertices;

                    for (int i = 0; i < hits.Count; i++)
                    {
                        if (PointIsOccluded(mesh, mesh.transform.TransformPoint(hits[i].Point)))
                        {
                            continue;
                        }

                        foreach (qe_Edge e in mesh.faces[hits[i].FaceIndex].GetEdges())
                        {
                            float d = HandleUtility.DistancePointLine(hits[i].Point, v[e.x], v[e.y]);

                            if (d < bestDistance)
                            {
                                bestDistance = d;
                                edge         = e;
                            }
                        }

                        if (Vector3.Dot(ray.direction, mesh.transform.TransformDirection(hits[i].Normal)) < 0f)
                        {
                            break;
                        }
                    }

                    if (edge != null && HandleUtility.DistanceToLine(mesh.transform.TransformPoint(v[edge.x]), mesh.transform.TransformPoint(v[edge.y])) > MAX_EDGE_SELECT_DISTANCE)
                    {
                        edge = null;
                    }
                    else
                    {
                        edge.x = mesh.ToUserIndex(edge.x);
                        edge.y = mesh.ToUserIndex(edge.y);
                    }
                }
            }

            return(edge != null);
        }