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    pub image: String,
21    pub position: (f32, f32),
22}
23
24impl specs::Component for Sprite {
25    type Storage = specs::VecStorage<Self>;
26}
27
28pub struct SpriteFactory;
29
30impl ComponentFactory for SpriteFactory {
31    fn insert(&self, world: &mut World, entity: Entity, value: &Value) {
32        let sprite = ron::value::Value::into_rust::<Sprite>(value.clone());
33        println!("{:#?}", sprite);
34        world.write_storage::<Sprite>().insert(entity, sprite.expect("failed to construct a sprite")).unwrap();
35    }
36}
37
38/// ECS system that renders Sprite components.
39///
40/// The system reads all Sprite components from the world and obtains a mutable
41/// reference to the host App through the HostPtr resource
42pub struct RenderingSystem;
43
44impl<'a> System<'a> for RenderingSystem {
45    type SystemData = (ReadStorage<'a, Sprite>, WriteExpect<'a, HostPtr>);
46
47    fn run(&mut self, (sprites, mut host_ptr): Self::SystemData) {
48        let runtime: &mut App = unsafe { &mut *host_ptr.0 };
49        let window = &mut runtime.window;
50
51        for sprite in (&sprites).join() {
52            window
53                .graphics
54                .draw_image(sprite.image.clone(), sprite.position)
55                .unwrap();
56        }
57    }
58}