fennel_engine/ecs/
sprite.rs

1use ron::Value;
2use serde::Deserialize;
3use specs::{Entity, Join, ReadStorage, System, World, WorldExt, WriteExpect};
4
5use crate::{app::App, registry::ComponentFactory};
6
7/// A raw pointer wrapper to the application
8pub struct HostPtr(pub *mut App);
9
10unsafe impl Send for HostPtr {}
11unsafe impl Sync for HostPtr {}
12
13/// A simple renderable sprite.
14///
15/// # Fields
16/// - image: identifier or path of the image to draw
17/// - position: tuple (x, y) position on screen
18#[derive(Deserialize, Debug)]
19pub struct Sprite {
20    /// Sprite asset id in the resource manager
21    pub image: String,
22    /// Sprite position on the screen
23    pub position: (f32, f32),
24}
25
26impl specs::Component for Sprite {
27    type Storage = specs::VecStorage<Self>;
28}
29
30/// Factory for [`Sprite`]
31pub struct SpriteFactory;
32
33impl ComponentFactory for SpriteFactory {
34    fn insert(&self, world: &mut World, entity: Entity, value: &Value) {
35        let sprite = ron::value::Value::into_rust::<Sprite>(value.clone());
36        println!("{:#?}", sprite);
37        world.write_storage::<Sprite>().insert(entity, sprite.expect("failed to construct a sprite")).unwrap();
38    }
39}
40
41/// ECS system that renders Sprite components.
42///
43/// The system reads all Sprite components from the world and obtains a mutable
44/// reference to the host App through the HostPtr resource
45pub struct RenderingSystem;
46
47impl<'a> System<'a> for RenderingSystem {
48    type SystemData = (ReadStorage<'a, Sprite>, WriteExpect<'a, HostPtr>);
49
50    fn run(&mut self, (sprites, mut host_ptr): Self::SystemData) {
51        let runtime: &mut App = unsafe { &mut *host_ptr.0 };
52        let window = &mut runtime.window;
53
54        for sprite in (&sprites).join() {
55            window
56                .graphics
57                .draw_image(sprite.image.clone(), sprite.position)
58                .unwrap();
59        }
60    }
61}