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
use crate::resources::renderables::*;
use oxygengine_core::{
    ecs::{Entity, Universe},
    scripting::intuicio::{core as intuicio_core, data as intuicio_data, derive::*, prelude::*},
};
use oxygengine_ha_renderer::{components::transform::*, math::*};

#[derive(Debug, Default)]
pub enum SpriteNodeRegion {
    #[default]
    None,
    Rect(Rect),
    AnimationFrame {
        frame: usize,
        cols: usize,
        rows: usize,
    },
    TileCell {
        col: usize,
        row: usize,
        cols: usize,
        rows: usize,
    },
}

#[derive(IntuicioStruct, Debug)]
#[intuicio(name = "SpriteNode", module_name = "renderable")]
pub struct SpriteNode {
    #[intuicio(ignore)]
    pub image: String,
    #[intuicio(ignore)]
    pub tint: Rgba,
    #[intuicio(ignore)]
    pub tiling: Vec2,
    #[intuicio(ignore)]
    pub size: Vec2,
    #[intuicio(ignore)]
    pub mirror_x: bool,
    #[intuicio(ignore)]
    pub mirror_y: bool,
    #[intuicio(ignore)]
    pub region: SpriteNodeRegion,
}

impl Default for SpriteNode {
    fn default() -> Self {
        Self {
            image: Default::default(),
            tint: Rgba::white(),
            tiling: 1.0.into(),
            size: 1.0.into(),
            mirror_x: false,
            mirror_y: false,
            region: Default::default(),
        }
    }
}

impl SpriteNode {
    pub fn install(registry: &mut Registry) {
        registry.add_struct(SpriteNode::define_struct(registry));
        registry.add_function(SpriteNode::event_draw__define_function(registry));
    }
}

#[intuicio_methods(module_name = "renderable")]
impl SpriteNode {
    #[intuicio_method(transformer = "DynamicManagedValueTransformer")]
    pub fn event_draw(
        this: &mut Self,
        transform: &mut HaTransform,
        universe: &Universe,
        _entity: Entity,
    ) {
        let mut renderables = universe.expect_resource_mut::<Renderables>();
        let scale = vec2(
            if this.mirror_x { -1.0 } else { 1.0 },
            if this.mirror_y { -1.0 } else { 1.0 },
        );
        let renderable = SpriteRenderable::new(&this.image)
            .tint(this.tint)
            .tiling(this.tiling)
            .position(transform.get_world_origin())
            .rotation(transform.get_world_rotation_lossy().eulers().yaw)
            .size(this.size * scale * transform.get_world_scale_lossy());
        let renderable = match &this.region {
            SpriteNodeRegion::None => renderable,
            SpriteNodeRegion::Rect(rect) => renderable.region(*rect),
            SpriteNodeRegion::AnimationFrame { frame, cols, rows } => {
                renderable.region_from_animation_frame(*frame, *cols, *rows)
            }
            SpriteNodeRegion::TileCell {
                col,
                row,
                cols,
                rows,
            } => renderable.region_from_tile_cell(*col, *row, *cols, *rows),
        };
        renderables.draw(renderable);
    }
}