Skip to main content

rpgx_dioxus/components/
grid.rs

1use std::any::Any;
2
3use dioxus::prelude::*;
4use rpgx::{engine::Engine, library::Library, prelude::RPGXError};
5
6#[derive(PartialEq, Props, Clone)]
7pub struct GridProps {
8    pub engine: Signal<Engine>,
9    pub library: Signal<Library<Box<dyn Any>>>,
10    pub square_size: u32,
11    pub onclick: EventHandler<Result<rpgx::prelude::Rect, RPGXError>>,
12}
13
14#[allow(non_snake_case)]
15pub fn Grid(props: GridProps) -> Element {
16    let engine = props.engine.read();
17    let get_background = |texture_id: u32| {
18        if let Some(asset) = props
19            .library
20            .read()
21            .get_by_id(texture_id)
22            .and_then(|boxed| boxed.downcast_ref::<String>())
23        {
24            format!("background-image: url({}); background-size: cover;", asset)
25        } else {
26            "background-size: cover;".to_string()
27        }
28    };
29    if let Some(scene) = engine.get_active_scene() {
30        rsx! {
31            {
32                scene
33                    .map
34                    .layers
35                    .iter()
36                    .flat_map(|layer| {
37                        layer
38                            .masks
39                            .iter()
40                            .flat_map(move |mask| {
41                                let mask_texture = mask.get_texture();
42                                let background = if let Some(texture_id) = mask_texture {
43                                    get_background(texture_id)
44                                } else {
45                                    "background-size: cover;".to_string()
46                                };
47                                mask.tiles
48                                    .iter()
49                                    .flat_map(move |tile| {
50                                        let x = tile.origin.x;
51                                        let y = tile.origin.y;
52
53                                        let base_style = format!(
54                                            "{background} \
55                                            position: absolute; \
56                                            left: {}px; \
57                                            top: {}px; \
58                                            width: {}px; \
59                                            height: {}px; \
60                                            border: solid 1px rgba(255,255,255,0.1); \
61                                            z-index: {}; \
62                                            pointer-events: {}; \
63                                            cursor: pointer;",
64                                            x * props.square_size,
65                                            y * props.square_size,
66                                            tile.shape.width * props.square_size,
67                                            tile.shape.height * props.square_size,
68                                            layer.z,
69                                            "auto"
70                                        );
71
72                                        let onclick_tile = {
73                                            let tile = tile.clone();
74                                            move |_| {
75                                                println!("onclick_tile");
76                                                let _ = props.onclick.call(Ok(tile.clone()));
77                                            }
78                                        };
79
80                                        let library = props.library.read();
81                                            rsx! {
82                                                div {
83                                                    class: "layer-tile",
84                                                    style: "{base_style}",
85                                                    onclick: onclick_tile,
86                                                    {
87                                                        mask
88                                                            .get_render()
89                                                            .and_then(|id| {
90                                                                println!(
91                                                                    "Rendering custom VNode from library {:?}",
92                                                                    library.get_by_id(id),
93                                                                );
94                                                                let f = library.get_by_id(id)?.downcast_ref::<Box<dyn Fn() -> VNode>>()?;
95                                                                Some(f())
96                                                            })
97                                                            .unwrap_or(rsx! {}.unwrap())
98                                                    }
99                                                }
100                                            }
101                                        })
102                                })
103                                .collect::<Vec<_>>()
104                        })
105            }
106        }
107    } else {
108        rsx! {
109            div {}
110        }
111    }
112}