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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
//! Simple entity-component system. Pure Rust (macro-free)!
//!
//! # Example
//! ```
//! extern crate recs;
//! use recs::{Ecs, EntityId};
//!
//! #[derive(Clone, PartialEq)]
//! struct Age{years: u32}
//!
//! #[derive(Clone, PartialEq)]
//! struct Brain{iq: i32}
//!
//! fn main() {
//!     // Create an ECS instance
//!     let mut ecs: Ecs = Ecs::new();
//!     // Add entity to the system
//!     let me: EntityId = ecs.create_entity();
//!     // Attach component to the entity
//!     ecs.set(me, &Age{years: 22});
//!     // Get attached component data from entity
//!     let older = ecs.get::<Age>(me).unwrap().years + 1;
//!     // Modify an entity's component
//!     ecs.set(me, &Age{years: older});
//!     // It works!
//!     assert!(ecs.get::<Age>(me) == Some(Age{years: 23}));
//!     assert!(ecs.get::<Brain>(me) == None); // Aw man...
//! }
//! ```
// TODO iterate every E/C pair
// TODO iterate every E and its C's
use std::any::{TypeId, Any};
use std::collections::HashMap;
use std::collections::hash_map::{Iter, IterMut, Keys};
use std::ops::{Deref, DerefMut};

/// Value type representing an entry in the entity-component system.
///
/// `EntityId` is an alias to `u64`. When storing Entity IDs, `EntityId`
/// should always be used in place of `u64` to ensure forwards compatiblity
/// with potential implementation changes.
pub type EntityId = u64;

/// Primary data structure containing entity and component data.
///
/// Notice that `Ecs` itself has no type parameters. Its methods to interact
/// with components do, but runtime reflection (via `std::any::TypeId`) is
/// used to retrieve components from an internal `HashMap`. Therefore, you
/// can create and use any data structure you want for components, provided
/// that they implement `Clone`.
///
/// Tip: `#[derive(Clone)]` will make your life a little easier :-)
pub struct Ecs {
  ids: EntityId,
  data: HashMap<EntityId, ComponentSet>,
}

struct ComponentSet {
  map: HashMap<TypeId, Box<Any>>,
}

/// Iterator for entity IDs.
pub struct EntityIdIter<'a> {
  iter: Keys<'a, EntityId, ComponentSet>
}

/// Iterator that yields references to ECS components.
pub struct ComponentIter<'a> {
  iter: Iter<'a, TypeId, Box<Any>>
}

/// Iterator that yields mutable references to ECS components.
pub struct ComponentIterMut<'a> {
  iter: IterMut<'a, TypeId, Box<Any>>
}

impl<'a> Iterator for EntityIdIter<'a> {
  type Item = EntityId;
  fn next(&mut self) -> Option<Self::Item> {
    self.iter.next().map(|id| *id)
  }
}

impl<'a> Iterator for ComponentIter<'a> {
  type Item = &'a Any;
  fn next(&mut self) -> Option<Self::Item> {
    self.iter.next().map(|(_, v)| v.deref())
  }
}

impl<'a> Iterator for ComponentIterMut<'a> {
  type Item = &'a mut Any;
  fn next(&mut self) -> Option<Self::Item> {
    self.iter.next().map(|(_, v)| v.deref_mut())
  }
}

impl Default for ComponentSet {
  fn default() -> Self {
    ComponentSet {
      map: HashMap::new(),
    }
  }
}

impl ComponentSet {
  fn set<C: Any + Clone>(&mut self, component: &C) -> Option<C> {
    self.map.insert(TypeId::of::<C>(), Box::new(component.clone())).map(|old| {
      *old.downcast::<C>().ok().expect(
        "ComponentSet.set: internal downcast error")
    })
  }
  fn get<C: Any + Clone>(&self) -> Option<C> {
    self.borrow::<C>().map(Clone::clone)
  }
  fn contains<C: Any + Clone>(&self) -> bool {
    self.map.contains_key(&TypeId::of::<C>())
  }
  fn borrow<C: Any + Clone>(&self) -> Option<&C> {
    self.map.get(&TypeId::of::<C>()).map(|c| {
      c.downcast_ref()
        .expect("ComponentSet.borrow: internal downcast error")
    })
  }
  fn borrow_mut<C: Any + Clone>(&mut self) -> Option<&mut C> {
    match self.map.get_mut(&TypeId::of::<C>()) {
      Some(c) => Some(c.downcast_mut()
        .expect("ComponentSet.get_mut: internal downcast error")),
      None => None,
    }
  }
  fn iter(&self) -> ComponentIter {
    ComponentIter{iter: self.map.iter()}
  }
  fn iter_mut(&mut self) -> ComponentIterMut {
    ComponentIterMut{iter: self.map.iter_mut()}
  }
}

impl Default for Ecs {
  fn default() -> Self {
    Ecs {
      ids: 0,
      data: HashMap::new(),
    }
  }
}

impl Ecs {
  /// Create a new and empty entity-component system (ECS).
  pub fn new() -> Self { Self::default() }
  /// Create a new entity in the ECS with no components, and return its ID.
  pub fn create_entity(&mut self) -> EntityId {
    self.ids += 1;
    self.data.insert(self.ids, Default::default());
    self.ids
  }
  /// Return `true` if the provided entity exists in this system.
  pub fn has_entity(&self, id: EntityId) -> bool {
    self.data.contains_key(&id)
  }
  /// Destroy the provided entity, automatically removing any of its
  /// components.
  ///
  /// Return `true` if the entity existed and was successfully deleted;
  /// return `false` if the provided entity ID was not found in the system.
  pub fn destroy_entity(&mut self, id: EntityId) -> bool {
    self.data.remove(&id).is_some()
  }
  /// For the specified entity, add a component of type `C` to the system.
  ///
  /// If the entity already has a component of type `C`, it is returned
  /// and overwritten.
  ///
  /// To modify a component in place, see `borrow_mut`.
  ///
  /// # Panics
  /// Panics if the requested entity does not exist.
  pub fn set<C: Any + Clone>(&mut self, id: EntityId, comp: &C)
    -> Option<C>
  {
    self.data.get_mut(&id)
      .expect(&format!("Ecs.set: nil entity {}", id))
      .set(comp)
  }
  /// Return a clone of the requested entity's component of type `C`, or
  /// `None` if the entity does not have that component.
  ///
  /// To examine a component without copying, see `borrow`.
  ///
  /// # Panics
  /// Panics if the requested entity does not exist.
  pub fn get<C: Any + Clone>(&self, id: EntityId) -> Option<C> {
    self.data.get(&id)
      .expect(&format!("Ecs.get: nil entity {}", id))
      .get::<C>()
  }
  /// Return `true` Panics if the requested entity has a component of type `C`.
  pub fn has<C: Any + Clone>(&self, id: EntityId) -> bool {
    self.data.get(&id)
      .expect(&format!("Ecs.has: nil entity {}", id))
      .contains::<C>()
  }
  /// Return a reference to the requested entity's component of type `C`, or
  /// `None` if the entity does not have that component.
  ///
  /// # Panics
  /// Panics if the requested entity does not exist.
  pub fn borrow<C: Any + Clone>(&self, id: EntityId) -> Option<&C> {
    self.data.get(&id)
      .expect(&format!("Ecs.borrow: nil entity {}", id))
      .borrow()
  }
  /// Return a mutable reference to the requested entity's component of type
  /// `C`, or `None` if the entity does not have that component.
  ///
  /// # Panics
  /// Panics if the requested entity does not exist.
  pub fn borrow_mut<C: Any + Clone>(&mut self, id: EntityId)
    -> Option<&mut C>
  {
    self.data.get_mut(&id)
      .expect(&format!("Ecs.borrow: nil entity {}", id))
      .borrow_mut()
  }
  /// Return an iterator over every ID in the system.
  pub fn iter_ids(&self) -> EntityIdIter {
    EntityIdIter{iter: self.data.keys()}
  }
  /// Return a vector containing copies of every ID in the system.
  ///
  /// Useful for accessing entity IDs without borrowing the ECS.
  pub fn collect_ids(&self) -> Vec<EntityId> {
    self.iter_ids().collect()
  }
  /// Return an iterator yielding references to all components of the
  /// requested entity.
  ///
  /// # Panics
  /// Panics if the requested entity does not exist.
  pub fn iter_components(&self, id: EntityId) -> ComponentIter {
    match self.data.get(&id) {
      Some(components) => components.iter(),
      None => panic!("Ecs.iter_components: nil entity {}", id),
    }
  }
  /// Return an iterator yielding mutable references to all components of the
  /// requested entity.
  ///
  /// # Panics
  /// Panics if the requested entity does not exist.
  pub fn iter_components_mut(&mut self, id: EntityId) -> ComponentIterMut
  {
    match self.data.get_mut(&id) {
      Some(components) => components.iter_mut(),
      None => panic!("Ecs.iter_components_mut: nil entity {}", id),
    }
  }
}