public void Synchronize(Vector3 centerOfMass, Vector3 lastPosition)
        {
            foreach (KeyValuePair <ProBuilderMesh, FaceList> kvp in m_meshToFaces)
            {
                ProBuilderMesh mesh  = kvp.Key;
                FaceList       faces = kvp.Value;

                for (int f = 0; f < faces.Faces.Count; ++f)
                {
                    int[] faceIndexes   = faces.FaceIndexes[f];
                    Face  selectionFace = faces.SelectionFaces[f];

                    Vertex[]    vertices         = mesh.GetVertices(faceIndexes);
                    IList <int> selectionIndexes = selectionFace.indexes;
                    for (int i = 0; i < vertices.Length; ++i)
                    {
                        int selectionIndex = selectionIndexes[i];
                        m_selectionVertices[selectionIndex] = transform.InverseTransformPoint(mesh.transform.TransformPoint(vertices[i].position));
                    }
                }
            }

            m_centerOfMass = transform.InverseTransformPoint(centerOfMass);
            m_lastPosition = transform.InverseTransformPoint(lastPosition);
            m_lastNormal   = m_selectionFaces.Count == 0 ? Vector3.forward : GetNormal(m_selectionFaces[m_selectionFaces.Count - 1]); // transform.InverseTransformDirection(lastNormal.normalized);
            RebuildSelectionMesh();
        }
        public void Remove(ProBuilderMesh mesh, int faceIndex)
        {
            Face selectionFace;
            Dictionary <int, Face> faceToSelection;

            if (m_faceToSelectionFace.TryGetValue(mesh, out faceToSelection))
            {
                if (!faceToSelection.TryGetValue(faceIndex, out selectionFace))
                {
                    return;
                }
            }
            else
            {
                return;
            }

            Face face = mesh.faces[faceIndex];

            faceToSelection.Remove(faceIndex);
            if (faceToSelection.Count == 0)
            {
                m_faceToSelectionFace.Remove(mesh);
            }

            m_selectionFaceToMesh.Remove(selectionFace);

            FaceList    faceList = m_meshToFaces[mesh];
            IList <int> indexes  = face.indexes;

            for (int i = 0; i < indexes.Count; ++i)
            {
                int index = indexes[i];
                if (faceList.Indexes.ContainsKey(index))
                {
                    faceList.Indexes[index]--;
                    if (faceList.Indexes[index] == 0)
                    {
                        faceList.Indexes.Remove(index);
                    }
                }
            }

            if (faceList.Faces.Count == 0)
            {
                m_meshToFaces.Remove(mesh);

                PBMesh pbMesh = mesh.GetComponent <PBMesh>();
                if (pbMesh != null)
                {
                    pbMesh.RaiseUnselected();
                }

                m_pbMeshes.Remove(pbMesh);
            }

            int flidx = faceList.Faces.IndexOf(faceIndex);

            faceList.Faces.RemoveAt(flidx);
            faceList.FaceIndexes.RemoveAt(flidx);
            faceList.SelectionFaces.Remove(selectionFace);

            Vector3 removedFaceCenterOfMass = GetCenterOfMass(selectionFace);

            int[] indices = selectionFace.distinctIndexes.OrderByDescending(i => i).ToArray();
            for (int i = 0; i < indices.Length; ++i)
            {
                m_selectionVertices.RemoveAt(indices[i]);
            }

            int selectionFaceIndex = m_selectionFaces.IndexOf(selectionFace);
            int count = selectionFace.indexes.Count;

            m_selectionFaces.RemoveAt(selectionFaceIndex);
            for (int i = selectionFaceIndex; i < m_selectionFaces.Count; ++i)
            {
                m_selectionFaces[i].ShiftIndexes(-count);
            }

            if (!m_isChanging)
            {
                RebuildSelectionMesh();
            }

            if (m_selectionFaces.Count == 0)
            {
                m_centerOfMass = Vector3.zero;
                m_lastPosition = Vector3.zero;
                m_lastNormal   = Vector3.forward;
                m_lastMesh     = null;
            }
            else if (m_selectionFaces.Count == 1)
            {
                m_centerOfMass = GetCenterOfMass(m_selectionFaces[0]);
                m_lastPosition = m_centerOfMass;
                m_lastNormal   = GetNormal(m_selectionFaces[0]);
                m_lastMesh     = m_selectionFaceToMesh[m_selectionFaces[0]];
            }
            else
            {
                m_centerOfMass -= removedFaceCenterOfMass / (m_selectionFaces.Count + 1);
                m_centerOfMass *= (m_selectionFaces.Count + 1) / (float)m_selectionFaces.Count;
                m_lastPosition  = GetCenterOfMass(m_selectionFaces.Last());
                m_lastNormal    = GetNormal(m_selectionFaces.Last());
                m_lastMesh      = m_selectionFaceToMesh[m_selectionFaces.Last()];
            }
        }
        public void Add(ProBuilderMesh mesh, int faceIndex)
        {
            Face face = mesh.faces[faceIndex];

            Dictionary <int, Face> faceToSelection;

            if (m_faceToSelectionFace.TryGetValue(mesh, out faceToSelection))
            {
                if (faceToSelection.ContainsKey(faceIndex))
                {
                    return;
                }
            }
            else
            {
                faceToSelection = new Dictionary <int, Face>();
                m_faceToSelectionFace.Add(mesh, faceToSelection);
            }


            int[] indices = new int[face.indexes.Count];
            for (int i = 0; i < indices.Length; ++i)
            {
                indices[i] = m_selectionVertices.Count + i;
            }

            Face selectionFace = new Face(indices);

            faceToSelection.Add(faceIndex, selectionFace);
            m_selectionFaceToMesh.Add(selectionFace, mesh);

            IList <int> indexes = face.indexes;

            Vertex[] vertices = mesh.GetVertices(indexes);
            for (int i = 0; i < vertices.Length; ++i)
            {
                m_selectionVertices.Add(transform.InverseTransformPoint(mesh.transform.TransformPoint(vertices[i].position)));
            }

            m_selectionFaces.Add(selectionFace);
            if (!m_isChanging)
            {
                RebuildSelectionMesh();
            }

            FaceList faceList;

            if (!m_meshToFaces.TryGetValue(mesh, out faceList))
            {
                faceList = new FaceList();
                m_meshToFaces.Add(mesh, faceList);

                PBMesh pbMesh = mesh.GetComponent <PBMesh>();
                if (pbMesh != null)
                {
                    pbMesh.RaiseSelected(false);
                }
                m_pbMeshes.Add(pbMesh);
            }

            for (int i = 0; i < indexes.Count; ++i)
            {
                int index = indexes[i];
                if (!faceList.Indexes.ContainsKey(index))
                {
                    faceList.Indexes.Add(index, 1);
                }
                else
                {
                    faceList.Indexes[index]++;
                }
            }

            faceList.Faces.Add(faceIndex);
            faceList.FaceIndexes.Add(face.indexes.ToArray());
            faceList.SelectionFaces.Add(selectionFace);

            m_lastMesh     = mesh;
            m_lastPosition = GetCenterOfMass(selectionFace);
            m_lastNormal   = GetNormal(selectionFace);

            if (m_selectionFaces.Count == 1)
            {
                m_centerOfMass = m_lastPosition;
            }
            else
            {
                m_centerOfMass *= (m_selectionFaces.Count - 1) / (float)m_selectionFaces.Count;
                m_centerOfMass += m_lastPosition / m_selectionFaces.Count;
            }
        }