rpgx_dioxus/components/
engine.rs1use std::any::Any;
2
3use dioxus::prelude::*;
4use rpgx::{
5 library::Library,
6 prelude::{Direction, RPGXError, Rect},
7};
8
9use crate::{
10 components::{grid::Grid, pawn::Pawn},
11 controller::{use_controller, Command},
12};
13
14#[derive(PartialEq, Props, Clone)]
15pub struct EngineProps {
16 pub engine: Signal<rpgx::prelude::Engine>,
17 pub library: Signal<Library<Box<dyn Any>>>,
18 pub square_size: u32,
19}
20
21#[allow(non_snake_case)]
22pub fn Engine(props: EngineProps) -> Element {
23 let engine = props.engine.clone();
24 let controller = use_controller(engine.clone(), props.library.clone());
25
26 let onclick = move |tile: Rect| -> Result<(), RPGXError> {
27 controller.send(Command::WalkTo(tile.origin));
28 Ok(())
29 };
30
31 let onkeydown = {
32 move |evt: KeyboardEvent| {
33 let direction = match evt.key() {
34 Key::ArrowUp => Some(Direction::Up),
35 Key::ArrowDown => Some(Direction::Down),
36 Key::ArrowLeft => Some(Direction::Left),
37 Key::ArrowRight => Some(Direction::Right),
38 Key::Character(k) => match k.as_str() {
39 "w" | "W" => Some(Direction::Up),
40 "s" | "S" => Some(Direction::Down),
41 "a" | "A" => Some(Direction::Left),
42 "d" | "D" => Some(Direction::Right),
43 _ => None,
44 },
45 _ => None,
46 };
47
48 if let Some(d) = direction {
49 controller.send(Command::Step(d));
50 }
51 }
52 };
53
54 use_effect(move || {
55 let _ = engine(); let _js_code = r#"
58 (() => {
59 console.log('trigger update');
60 const container = document.querySelector('#scroll-container');
61 const pawn = document.querySelector('#pawn');
62 if (!container || !pawn) return;
63 const scrollX = pawn.offsetLeft + pawn.offsetWidth / 2 - container.clientWidth / 2;
64 const scrollY = pawn.offsetTop + pawn.offsetHeight / 2 - container.clientHeight / 2;
65 container.scrollTo({
66 left: scrollX,
67 top: scrollY,
68 behavior: 'smooth'
69 });
70 })();
71 "#;
72
73 #[cfg(feature = "web")]
74 {
75 document::eval(_js_code); }
77
78 #[cfg(feature = "desktop")]
79 {
80 spawn(async move {
81 let eval = document::eval(_js_code);
82 let _ = eval.await; });
84 }
85 });
86
87 rsx! {
88 div {
89 id: "scroll-container",
90 class: "container",
91 tabindex: "0",
92 onkeydown,
93 style: "position: relative; overflow: auto; width: 100vw; height: 100vh;",
94
95 Grid {
96 engine: engine.clone(),
97 library: props.library.clone(),
98 square_size: props.square_size,
99 onclick: EventHandler::new(move |tile: Result<Rect, RPGXError>| {
100 if let Ok(tile) = tile {
101 let _ = onclick(tile);
102 }
103 }),
104 }
105
106 Pawn {
107 engine: engine.clone(),
108 library: props.library.clone(),
109 square_size: props.square_size,
110 }
111 }
112 }
113}