diff --git a/Cargo.lock b/Cargo.lock index d467789..ca6a253 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1631,7 +1631,6 @@ dependencies = [ "dioxus-core-macro", "dioxus-hooks", "dioxus-hot-reload", - "dioxus-html", "dioxus-rsx", ] diff --git a/Cargo.toml b/Cargo.toml index 3144108..ab73565 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,11 @@ edition = "2021" [dependencies] bevy = { git = "https://github.com/JMS55/bevy", branch = "query_new_12" } -dioxus = "0.4" +dioxus = { version = "0.4", default-features = false, features = [ + "macro", + "hooks", + "hot-reload", +] } bevy_mod_picking = { version = "0.17", default-features = false, features = [ "backend_bevy_ui", ] } diff --git a/examples/demo.rs b/examples/demo.rs index 445fb71..75dc0d2 100644 --- a/examples/demo.rs +++ b/examples/demo.rs @@ -6,10 +6,8 @@ use bevy::{ ui::{node_bundles::NodeBundle, Node}, DefaultPlugins, }; -use bevy_dioxus::{ - bevy_mod_picking::DefaultPickingPlugins, colors::*, dioxus::prelude::*, hooks::*, - DioxusUiBundle, DioxusUiPlugin, DioxusUiRoot, -}; +use bevy_dioxus::{colors::*, prelude::*}; +use bevy_mod_picking::DefaultPickingPlugins; fn main() { App::new() @@ -30,7 +28,7 @@ fn Editor(cx: Scope) -> Element { let selected_entity = use_state(cx, || Option::::None); render! { - div { + node { width: "100vw", height: "100vh", justify_content: "space-between", @@ -52,7 +50,7 @@ fn SceneTree<'a>(cx: Scope, selected_entity: &'a UseState>) -> El }); render! { - div { + node { onclick: move |_| selected_entity.set(None), flex_direction: "column", if entities.is_empty() { @@ -60,7 +58,7 @@ fn SceneTree<'a>(cx: Scope, selected_entity: &'a UseState>) -> El } else { rsx! { for (entity, name) in entities { - div { + node { onclick: move |_| { if Some(entity) == ***selected_entity { selected_entity.set(None); @@ -78,7 +76,7 @@ fn SceneTree<'a>(cx: Scope, selected_entity: &'a UseState>) -> El } } } - div { + node { onclick: move |_| spawn_entity(), padding: "8", background_color: NEUTRAL_800, @@ -117,14 +115,14 @@ fn EntityInspector<'a>(cx: Scope, selected_entity: &'a UseState>) } } else { rsx! { - div { + node { flex_direction: "column", for (name, _component_id, _type_id, _size) in components { - div { + node { padding: "8", background_color: NEUTRAL_800, - div { + node { "Component: {name}" } } diff --git a/src/apply_mutations.rs b/src/apply_mutations.rs index ddfcdcf..ef46e2f 100644 --- a/src/apply_mutations.rs +++ b/src/apply_mutations.rs @@ -221,21 +221,14 @@ impl BevyTemplateNode { fn from_dioxus(node: &TemplateNode) -> Self { match node { TemplateNode::Element { - tag, - namespace: _, + tag: "node", + namespace: Some("bevy_ui"), attrs, children, - } => { - if *tag != "div" { - panic!( - "Encountered unsupported bevy_dioxus tag `{tag}`. Only `div` is supported." - ); - } - Self::Node { - style: parse_style_attributes(attrs), - children: children.iter().map(Self::from_dioxus).collect(), - } - } + } => Self::Node { + style: parse_style_attributes(attrs), + children: children.iter().map(Self::from_dioxus).collect(), + }, TemplateNode::Text { text } => { Self::TextNode(Text::from_section(*text, TextStyle::default())) } @@ -246,6 +239,20 @@ impl BevyTemplateNode { TemplateNode::DynamicText { id: _ } => { Self::TextNode(Text::from_section("", TextStyle::default())) } + TemplateNode::Element { + tag, + namespace: None, + .. + } => { + panic!("Encountered unsupported bevy_dioxus tag `{tag}`.") + } + TemplateNode::Element { + tag, + namespace: Some(namespace), + .. + } => { + panic!("Encountered unsupported bevy_dioxus tag `{namespace}::{tag}`.") + } } } diff --git a/src/elements.rs b/src/elements.rs new file mode 100644 index 0000000..4eb2b92 --- /dev/null +++ b/src/elements.rs @@ -0,0 +1,20 @@ +#[allow(non_camel_case_types, non_upper_case_globals)] +pub mod dioxus_elements { + pub use crate::events::events; + + pub type AttributeDescription = (&'static str, Option<&'static str>, bool); + + pub struct node; + impl node { + pub const TAG_NAME: &'static str = "node"; + pub const NAME_SPACE: Option<&'static str> = Some("bevy_ui"); + + // TODO: The rest of Style + pub const width: AttributeDescription = ("width", None, false); + pub const height: AttributeDescription = ("height", None, false); + pub const justify_content: AttributeDescription = ("justify-content", None, false); + pub const flex_direction: AttributeDescription = ("flex-direction", None, false); + pub const padding: AttributeDescription = ("padding", None, false); + pub const background_color: AttributeDescription = ("background-color", None, false); + } +} diff --git a/src/events.rs b/src/events.rs index 15dc78f..291a611 100644 --- a/src/events.rs +++ b/src/events.rs @@ -4,7 +4,7 @@ use bevy::ecs::{ system::Resource, }; use bevy_mod_picking::events::{Click, Pointer}; -use dioxus::html::MouseData; +use dioxus::core::ScopeState; use std::{any::Any, rc::Rc}; // TODO: Other events @@ -22,7 +22,7 @@ impl EventReaders { let mut events: Vec<(Entity, &'static str, Rc)> = Vec::new(); for event in self.clicks.read(clicks) { - events.push((event.target, "click", Rc::new(MouseData::default()))); + events.push((event.target, "click", Rc::new(()))); } events @@ -32,3 +32,43 @@ impl EventReaders { pub fn is_supported_event(event: &str) -> bool { event == "click" } + +pub mod events { + super::impl_event! [ + (); + onclick + ]; +} + +pub trait EventReturn

: Sized { + fn spawn(self, _cx: &ScopeState) {} +} + +impl EventReturn<()> for () {} + +macro_rules! impl_event { + ( + $data:ty; + $( + $( #[$attr:meta] )* + $name:ident + )* + ) => { + $( + $( #[$attr] )* + #[inline] + pub fn $name<'a, E: crate::events::EventReturn, T>(_cx: &'a dioxus::core::ScopeState, mut _f: impl FnMut(dioxus::core::Event<$data>) -> E + 'a) -> dioxus::core::Attribute<'a> { + dioxus::core::Attribute::new( + stringify!($name), + _cx.listener(move |e: dioxus::core::Event<$data>| { + _f(e).spawn(_cx); + }), + None, + false, + ) + } + )* + }; + +} +pub(self) use impl_event; diff --git a/src/lib.rs b/src/lib.rs index 6635d34..175f04a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,8 +1,10 @@ mod apply_mutations; pub mod colors; mod deferred_system; +mod elements; +#[macro_use] mod events; -pub mod hooks; +mod hooks; mod tick; use self::{ @@ -18,8 +20,13 @@ use bevy::{ }; use dioxus::core::{Element, ElementId, Scope, VirtualDom}; -pub use bevy_mod_picking; -pub use dioxus; +pub mod prelude { + pub use super::elements::*; + pub use super::hooks::*; + pub use super::{DioxusUiBundle, DioxusUiPlugin, DioxusUiRoot}; + pub use dioxus; + pub use dioxus::prelude::*; +} pub struct DioxusUiPlugin;