use crate::{
core::hierarchy::components::{children, parent},
global::{EntityId, Vec3},
internal::{
component::{Component, Entity, SupportedValue, UntypedComponent},
conversion::{FromBindgen, IntoBindgen},
generated::ambient_core::hierarchy::components::unmanaged_children,
wit,
},
prelude::block_until,
};
pub fn spawn(components: &Entity) -> EntityId {
wit::entity::spawn(&components.clone().into_bindgen()).from_bindgen()
}
#[must_use]
pub async fn wait_for_component<T: SupportedValue>(
entity: EntityId,
component: Component<T>,
) -> Option<T> {
block_until(move || !exists(entity) || has_component(entity, component)).await;
get_component(entity, component)
}
pub fn despawn(entity: EntityId) -> Option<Entity> {
wit::entity::despawn(entity.into_bindgen()).from_bindgen()
}
pub fn despawn_recursive(entity: EntityId) {
if let Some(res) = despawn(entity) {
if let Some(children) = res.get_ref(children()) {
for c in children {
despawn_recursive(*c);
}
}
}
}
pub struct RawTransforms {
transforms: Vec<wit::types::Mat4>,
}
impl RawTransforms {
pub fn into_mat4(self) -> Vec<glam::Mat4> {
self.transforms.from_bindgen()
}
pub fn iter_mat4(&self) -> impl ExactSizeIterator<Item = glam::Mat4> + '_ {
self.transforms.iter().map(|&x| x.from_bindgen())
}
}
pub fn get_transforms_relative_to(list: &[EntityId], origin: EntityId) -> RawTransforms {
let entities: Vec<wit::types::EntityId> = list.iter().map(|x| x.into_bindgen()).collect();
RawTransforms {
transforms: wit::entity::get_transforms_relative_to(&entities, origin.into_bindgen()),
}
}
pub fn exists(entity: EntityId) -> bool {
wit::entity::exists(entity.into_bindgen())
}
pub fn get_all<T>(component: Component<T>) -> Vec<EntityId> {
wit::entity::get_all(component.index()).from_bindgen()
}
pub fn in_area(position: Vec3, radius: f32) -> Vec<EntityId> {
wit::entity::in_area(position.into_bindgen(), radius).from_bindgen()
}
pub fn get_component<T: SupportedValue>(entity: EntityId, component: Component<T>) -> Option<T> {
T::from_result(wit::component::get_component(
entity.into_bindgen(),
component.index(),
)?)
}
pub fn get_components(entity: EntityId, components: &[&dyn UntypedComponent]) -> Entity {
let components: Vec<_> = components.iter().map(|c| c.index()).collect();
wit::component::get_components(entity.into_bindgen(), &components).from_bindgen()
}
pub fn get_all_components(entity: EntityId) -> Entity {
wit::component::get_all_components(entity.into_bindgen()).from_bindgen()
}
pub fn add_component<T: SupportedValue>(entity: EntityId, component: Component<T>, value: T) {
wit::component::add_component(
entity.into_bindgen(),
component.index(),
&value.into_result(),
)
}
pub fn add_components(entity: EntityId, components: impl Into<Entity>) {
wit::component::add_components(entity.into_bindgen(), &components.into().into_bindgen())
}
pub fn set_component<T: SupportedValue>(entity: EntityId, component: Component<T>, value: T) {
wit::component::set_component(
entity.into_bindgen(),
component.index(),
&value.into_result(),
)
}
pub fn set_component_if_changed<T: SupportedValue + PartialEq>(
entity: EntityId,
component: Component<T>,
value: T,
) {
let old = get_component(entity, component).expect("Component must exist on entity");
if old != value {
set_component(entity, component, value)
}
}
pub fn set_components(entity: EntityId, components: Entity) {
wit::component::set_components(entity.into_bindgen(), &components.into_bindgen())
}
pub fn has_component<T: SupportedValue>(entity: EntityId, component: Component<T>) -> bool {
wit::component::has_component(entity.into_bindgen(), component.index())
}
pub fn has_components(entity: EntityId, components: &[&dyn UntypedComponent]) -> bool {
let components: Vec<_> = components.iter().map(|c| c.index()).collect();
wit::component::has_components(entity.into_bindgen(), &components)
}
pub fn add_component_if_required<T: SupportedValue + SupportedValue>(
entity: EntityId,
component: Component<T>,
value: T,
) {
if !has_component(entity, component) {
add_component(entity, component, value)
}
}
pub fn remove_component<T>(entity: EntityId, component: Component<T>) {
wit::component::remove_component(entity.into_bindgen(), component.index())
}
pub fn remove_components(entity: EntityId, components: &[&dyn UntypedComponent]) {
let components: Vec<_> = components.iter().map(|c| c.index()).collect();
wit::component::remove_components(entity.into_bindgen(), &components)
}
pub fn mutate_component<T: SupportedValue + Clone + PartialEq>(
entity: EntityId,
component: Component<T>,
mutator: impl FnOnce(&mut T),
) -> Option<T> {
let mut value: T = get_component(entity, component)?;
let orig_value = value.clone();
mutator(&mut value);
if value != orig_value {
set_component(entity, component, value.clone());
}
Some(value)
}
pub fn mutate_component_with_default<T: SupportedValue + Clone + PartialEq>(
entity: EntityId,
component: Component<T>,
default: T,
mutator: impl FnOnce(&mut T),
) -> T {
let value = mutate_component(entity, component, mutator);
if let Some(value) = value {
value
} else {
add_component(entity, component, default.clone());
default
}
}
pub fn add_child(entity: EntityId, child: EntityId) {
if has_component(entity, unmanaged_children()) {
if has_component(entity, children()) {
mutate_component(entity, children(), |children| children.push(child));
} else {
add_component(entity, children(), vec![child]);
}
}
add_component(child, parent(), entity);
}
pub fn remove_child(entity: EntityId, child: EntityId) {
if has_component(entity, unmanaged_children()) {
mutate_component(entity, children(), |children| {
children.retain(|x| *x != child)
});
}
remove_component(child, parent());
}
pub fn resources() -> EntityId {
EntityId::resources()
}
pub fn synchronized_resources() -> EntityId {
wit::entity::synchronized_resources().from_bindgen()
}
pub fn persisted_resources() -> EntityId {
wit::entity::persisted_resources().from_bindgen()
}