diff --git a/crates/bevy_ecs/src/system/query.rs b/crates/bevy_ecs/src/system/query.rs index a98f5cd36c63d..d19056b86c42f 100644 --- a/crates/bevy_ecs/src/system/query.rs +++ b/crates/bevy_ecs/src/system/query.rs @@ -7,7 +7,7 @@ use crate::{ world::{Mut, World}, }; use bevy_tasks::TaskPool; -use std::any::TypeId; +use std::{any::TypeId, fmt::Debug}; use thiserror::Error; /// Provides scoped access to a World according to a given [WorldQuery] and query filter @@ -212,6 +212,38 @@ where Err(QueryComponentError::MissingWriteAccess) } } + + pub fn single(&self) -> Result<>::Item, QuerySingleError> + where + Q::Fetch: ReadOnlyFetch, + { + let mut query = self.iter(); + let first = query.next(); + let extra = query.next().is_some(); + + match (first, extra) { + (Some(r), false) => Ok(r), + (None, _) => Err(QuerySingleError::NoEntities(std::any::type_name::())), + (Some(_), _) => Err(QuerySingleError::MultipleEntities(std::any::type_name::< + Self, + >())), + } + } + + /// See [`Query::single`] + pub fn single_mut(&mut self) -> Result<>::Item, QuerySingleError> { + let mut query = self.iter_mut(); + let first = query.next(); + let extra = query.next().is_some(); + + match (first, extra) { + (Some(r), false) => Ok(r), + (None, _) => Err(QuerySingleError::NoEntities(std::any::type_name::())), + (Some(_), _) => Err(QuerySingleError::MultipleEntities(std::any::type_name::< + Self, + >())), + } + } } /// An error that occurs when retrieving a specific [Entity]'s component from a [Query] @@ -226,3 +258,11 @@ pub enum QueryComponentError { #[error("The requested entity does not exist.")] NoSuchEntity, } + +#[derive(Debug, Error)] +pub enum QuerySingleError { + #[error("No entities fit the query {0}")] + NoEntities(&'static str), + #[error("Multiple entities fit the query {0}!")] + MultipleEntities(&'static str), +} diff --git a/examples/game/alien_cake_addict.rs b/examples/game/alien_cake_addict.rs index 3c50a992a6b4a..d1b0546c6552f 100644 --- a/examples/game/alien_cake_addict.rs +++ b/examples/game/alien_cake_addict.rs @@ -357,9 +357,8 @@ fn rotate_bonus(game: Res, time: Res