bevy_copperfield 0.2.2

Procedural mesh editor, based on Half-Edge-Mesh datastructure
Documentation
use bevy_utils::hashbrown::{hash_set::Iter, HashSet};

use super::{traversal::Traversal, FaceId, HalfEdgeId, HalfEdgeMesh, MeshPosition, VertexId};

#[derive(Clone, PartialEq, Eq)]
/// A mononotous selection on a mesh, several edges, vertices, or faces, but not a mix.
pub enum MeshSelection {
    Vertices(HashSet<VertexId>),
    HalfEdges(HashSet<HalfEdgeId>),
    Faces(HashSet<FaceId>),
}

impl MeshSelection {
    pub fn len(&self) -> usize {
        match self {
            MeshSelection::Vertices(vec) => vec.len(),
            MeshSelection::HalfEdges(vec) => vec.len(),
            MeshSelection::Faces(vec) => vec.len(),
        }
    }
}

#[derive(Clone)]
/// This structure keeps track of selecting multiple mesh items at a time to enable some more-complex operations
/// to act differently based on if they are applied to one item or multiple.
pub struct Selection<'m> {
    mesh: &'m HalfEdgeMesh,
    selection: MeshSelection,
}

impl From<MeshPosition> for MeshSelection {
    fn from(value: MeshPosition) -> Self {
        match value {
            MeshPosition::Vertex(vertex_id) => Self::Vertices(HashSet::from([vertex_id])),
            MeshPosition::HalfEdge(half_edge_id) => Self::HalfEdges(HashSet::from([half_edge_id])),
            MeshPosition::Face(face_id) => Self::Faces(HashSet::from([face_id])),
        }
    }
}

enum SelectionIteratorKeys<'m> {
    Vertices(Iter<'m, VertexId>),
    Edges(Iter<'m, HalfEdgeId>),
    Faces(Iter<'m, FaceId>),
}

pub struct SelectionIterator<'m> {
    mesh: &'m HalfEdgeMesh,
    selection: SelectionIteratorKeys<'m>,
    // selection_index:usize
}

impl<'m> Selection<'m> {
    pub(crate) fn new(mesh: &'m HalfEdgeMesh, position: MeshPosition) -> Self {
        Self {
            mesh,
            selection: position.into(),
        }
    }
    pub fn build(self) -> MeshSelection {
        self.selection
    }

    pub fn append(&mut self, halfedge: HalfEdgeId) -> bool {
        match &mut self.selection {
            MeshSelection::Vertices(vec) => vec.insert(self.mesh[halfedge].vertex),
            MeshSelection::HalfEdges(vec) => vec.insert(halfedge),
            MeshSelection::Faces(vec) => vec.insert(self.mesh[halfedge].face.unwrap()),
        }
    }

    pub fn iter(&'m self) -> SelectionIterator<'m> {
        let selection = match &self.selection {
            MeshSelection::Vertices(hash_set) => SelectionIteratorKeys::Vertices(hash_set.iter()),
            MeshSelection::HalfEdges(hash_set) => SelectionIteratorKeys::Edges(hash_set.iter()),
            MeshSelection::Faces(hash_set) => SelectionIteratorKeys::Faces(hash_set.iter()),
        };
        SelectionIterator {
            mesh: self.mesh,
            selection,
        }
    }

    pub fn select_vertices(self) -> Self {
        let selection = match &self.selection {
            MeshSelection::Vertices(_) => return self,
            MeshSelection::HalfEdges(vec) => MeshSelection::Vertices(
                vec.iter()
                    .map(|e| self.mesh.goto(*e).vertex())
                    .collect::<HashSet<_>>(),
            ),
            MeshSelection::Faces(vec) => MeshSelection::Vertices(
                vec.iter()
                    .flat_map(|f| self.mesh.goto(*f).iter_loop().map(|t| t.vertex()))
                    .collect::<HashSet<_>>(),
            ),
        };
        Selection {
            mesh: self.mesh,
            selection,
        }
    }

    pub fn select_edges(self) -> Self {
        let selection = match &self.selection {
            MeshSelection::Vertices(vec) => MeshSelection::HalfEdges(
                vec.iter()
                    .map(|&v| self.mesh[v].halfedge)
                    .collect::<HashSet<_>>(),
            ),
            MeshSelection::HalfEdges(_) => return self,
            MeshSelection::Faces(vec) => MeshSelection::HalfEdges(
                vec.iter()
                    .flat_map(|&f| self.mesh.goto(f).iter_loop().map(|t| t.halfedge()))
                    .collect::<HashSet<_>>(),
            ),
        };
        Selection {
            mesh: self.mesh,
            selection,
        }
    }

    /// Selects adjacent faces of vertices and exact faces of halfedges
    pub fn select_faces(self) -> Self {
        let selection = match &self.selection {
            MeshSelection::Vertices(vec) => MeshSelection::Faces(
                vec.iter()
                    .flat_map(|&v| {
                        self.mesh
                            .goto(v)
                            .adjacent_faces()
                            .map(|t| t.face().unwrap())
                    })
                    .collect::<HashSet<_>>(),
            ),
            MeshSelection::HalfEdges(vec) => MeshSelection::Faces(
                vec.iter()
                    .map(|&e| self.mesh[e].face.unwrap())
                    .collect::<HashSet<_>>(),
            ),
            MeshSelection::Faces(_) => return self,
        };
        Selection {
            mesh: self.mesh,
            selection,
        }
    }
}

impl<'m> Iterator for SelectionIterator<'m> {
    type Item = Traversal<'m>;

    fn next(&mut self) -> Option<Self::Item> {
        match &mut self.selection {
            SelectionIteratorKeys::Vertices(iter) => iter.next().map(|&v| self.mesh.goto(v)),
            SelectionIteratorKeys::Edges(iter) => iter.next().map(|&v| self.mesh.goto(v)),
            SelectionIteratorKeys::Faces(iter) => iter.next().map(|&v| self.mesh.goto(v)),
        }
    }
}