rpgx_wasm/map/
mod.rs

1pub mod effect;
2pub mod layer;
3pub mod mask;
4
5use layer::WasmLayer;
6
7use rpgx::prelude::*;
8use wasm_bindgen::prelude::*;
9
10use crate::{
11    prelude::{WasmCoordinates, WasmDirection, WasmShape},
12    traits::WasmWrapper,
13};
14
15#[wasm_bindgen(js_name = Map)]
16pub struct WasmMap {
17    inner: Map,
18}
19
20impl WasmWrapper<Map> for WasmMap {
21    /// Consume and get the inner Map
22    fn into_inner(self) -> Map {
23        self.inner
24    }
25
26    /// Create from an inner Map directly
27    fn from_inner(inner: Map) -> WasmMap {
28        WasmMap { inner }
29    }
30
31    fn inner(&self) -> &Map {
32        &self.inner
33    }
34}
35
36#[wasm_bindgen(js_class = Map)]
37impl WasmMap {
38    #[wasm_bindgen(constructor)]
39    pub fn new(name: String, layers: Vec<WasmLayer>, spawn: &WasmCoordinates) -> WasmMap {
40        let inner_layers = layers.into_iter().map(|l| l.into_inner()).collect();
41        WasmMap {
42            inner: Map::new(name, inner_layers, *spawn.inner()),
43        }
44    }
45
46    /* TODO #[wasm_bindgen(js_name = compose)]
47    pub fn compose(
48        name: String,
49        maps: Vec<JsValue>, // JS array of [WasmMap, WasmCoordinates]
50        layers: Vec<WasmLayer>,
51        spawn: WasmCoordinates,
52    ) -> Result<WasmMap, JsValue> {
53        let mut rust_maps: Vec<(Map, Coordinates)> = Vec::with_capacity(maps.len());
54
55        for js_val in maps {
56            // Convert JsValue into JS array (tuple expected)
57            let arr = js_val
58                .dyn_into::<Array>()
59                .map_err(|_| JsValue::from_str("Each map entry must be a tuple (array)"))?;
60
61            if arr.length() != 2 {
62                return Err(JsValue::from_str(
63                    "Each map entry must be a tuple of length 2",
64                ));
65            }
66
67            // Extract first element: WasmMap
68            let wasm_map = arr.get(0);
69
70            // Extract second element: WasmCoordinates
71            let wasm_coord = arr.get(1);
72
73            rust_maps.push((wasm_map, wasm_coord));
74        }
75
76        let inner_layers = layers.into_iter().map(|l| l.into_inner()).collect();
77
78        Ok(WasmMap {
79            inner: Map::compose(name, rust_maps, inner_layers, *spawn.inner()),
80        })
81    }*/
82
83    #[wasm_bindgen(getter)]
84    pub fn name(&self) -> String {
85        self.inner.name.clone()
86    }
87
88    #[wasm_bindgen(getter)]
89    pub fn spawn(&self) -> WasmCoordinates {
90        WasmCoordinates::from_inner(self.inner.spawn)
91    }
92
93    #[wasm_bindgen(getter)]
94    pub fn layers(&self) -> Vec<WasmLayer> {
95        self.inner
96            .layers
97            .iter()
98            .cloned()
99            .map(WasmLayer::from_inner)
100            .collect()
101    }
102
103    /// Load a new layer into the map.
104    #[wasm_bindgen(js_name = loadLayer)]
105    pub fn load_layer(&mut self, layer: WasmLayer) {
106        self.inner.load_layer(layer.into_inner());
107    }
108
109    /// Returns a JS object mapping layer names to WasmLayer instances.
110    #[wasm_bindgen(js_name = layersByName)]
111    pub fn layers_by_name(&self) -> js_sys::Object {
112        // Use the core Map method `layers_by_name` directly, which returns IndexMap<String, Layer>
113        let core_map = self.inner.layers_by_name();
114
115        let obj = js_sys::Object::new();
116        for (name, layer) in core_map.into_iter() {
117            let wasm_layer = WasmLayer::from_inner(layer);
118            js_sys::Reflect::set(&obj, &JsValue::from_str(&name), &JsValue::from(wasm_layer))
119                .unwrap_throw();
120        }
121        obj
122    }
123
124    /// Merge another map at a given offset; optionally update spawn.
125    #[wasm_bindgen(js_name = mergeAt)]
126    pub fn merge_at(
127        &mut self,
128        other: WasmMap,
129        top_left: WasmCoordinates,
130        spawn: Option<WasmCoordinates>,
131    ) {
132        let spawn_opt = spawn.map(|s| *s.inner());
133        self.inner
134            .merge_at(&other.inner, *top_left.inner(), spawn_opt);
135    }
136
137    /// Duplicate this map in a direction; optionally update spawn.
138    #[wasm_bindgen(js_name = duplicateToThe)]
139    pub fn duplicate_to_the(&mut self, direction: WasmDirection, spawn: Option<WasmCoordinates>) {
140        let spawn_opt = spawn.map(|s| *s.inner());
141        self.inner
142            .duplicate_to_the(direction.into_inner(), spawn_opt);
143    }
144
145    /// Returns the bounding shape of the map.
146    #[wasm_bindgen(js_name = getShape)]
147    pub fn get_shape(&self) -> WasmShape {
148        WasmShape::from_inner(self.inner.get_shape())
149    }
150
151    /// Returns all action IDs at a coordinate from all layers.
152    #[wasm_bindgen(js_name = getActionsAt)]
153    pub fn get_actions_at(&self, pointer: &WasmCoordinates) -> Vec<u32> {
154        self.inner.get_actions_at(pointer.inner())
155    }
156}