1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
use std::borrow::Cow; use crate::ecs::{world::LazyBuilder, Component, DenseVecStorage, EntityBuilder, WriteStorage}; use serde::{Deserialize, Serialize}; /// A component that gives a name to an [`Entity`]. /// /// There are two ways you can get a name for an entity: /// /// * Hard-coding the entity name in code, in which case the name would be a [`&'static str`][str]. /// * Dynamically generating the string or loading it from a data file, in which case the name /// would be a `String`. /// /// To support both of these cases smoothly, `Named` stores the name as [`Cow<'static, str>`]. /// You can pass either a [`&'static str`][str] or a [`String`] to [`Named::new`], and your code /// can generally treat the `name` field as a [`&str`][str] without needing to know whether the /// name is actually an owned or borrowed string. /// /// [`Entity`]: https://docs.rs/specs/*/specs/struct.Entity.html /// [`Cow<'static, str>`]: https://doc.rust-lang.org/std/borrow/enum.Cow.html /// [`String`]: https://doc.rust-lang.org/std/string/struct.String.html /// [str]: https://doc.rust-lang.org/std/primitive.str.html /// [`Named::new`]: #method.new /// /// # Examples /// /// Creating a name from string constant: /// /// ``` /// use amethyst::core::{Named, WithNamed}; /// use amethyst::ecs::prelude::*; /// /// let mut world = World::new(); /// world.register::<Named>(); /// /// world /// .create_entity() /// .named("Super Cool Entity") /// .build(); /// ``` /// /// Creating a name from a dynamically generated string: /// /// ``` /// use amethyst::core::{Named, WithNamed}; /// use amethyst::ecs::prelude::*; /// /// let mut world = World::new(); /// world.register::<Named>(); /// /// for entity_num in 0..10 { /// world /// .create_entity() /// .named(format!("Entity Number {}", entity_num)) /// .build(); /// } /// ``` /// /// Accessing a named entity in a system: /// /// ``` /// use amethyst::core::Named; /// use amethyst::ecs::prelude::*; /// /// pub struct NameSystem; /// /// impl<'s> System<'s> for NameSystem { /// type SystemData = ( /// Entities<'s>, /// ReadStorage<'s, Named>, /// ); /// /// fn run(&mut self, (entities, names): Self::SystemData) { /// for (entity, name) in (&*entities, &names).join() { /// println!("Entity {:?} is named {}", entity, name.name); /// } /// } /// } /// ``` #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Named { /// The name of the entity this component is attached to. pub name: Cow<'static, str>, } impl Named { /// Constructs a new `Named` from a string. /// /// # Examples /// /// From a string constant: /// /// ``` /// use amethyst::core::Named; /// /// let name_component = Named::new("Super Cool Entity"); /// ``` /// /// From a dynamic string: /// /// ``` /// use amethyst::core::Named; /// /// let entity_num = 7; /// let name_component = Named::new(format!("Entity Number {}", entity_num)); /// ``` pub fn new<S>(name: S) -> Self where S: Into<Cow<'static, str>>, { Named { name: name.into() } } } impl Component for Named { type Storage = DenseVecStorage<Self>; } /// An easy way to name an `Entity` and give it a `Named` `Component`. pub trait WithNamed where Self: Sized, { /// Adds a name to the entity being built. fn named<S>(self, name: S) -> Self where S: Into<Cow<'static, str>>; } impl<'a> WithNamed for EntityBuilder<'a> { fn named<S>(self, name: S) -> Self where S: Into<Cow<'static, str>>, { self.world .system_data::<(WriteStorage<'a, Named>,)>() .0 .insert(self.entity, Named::new(name)) .expect("Unreachable: Entities should always be valid when just created"); self } } impl<'a> WithNamed for LazyBuilder<'a> { fn named<S>(self, name: S) -> Self where S: Into<Cow<'static, str>>, { self.lazy.insert::<Named>(self.entity, Named::new(name)); self } }