Start of custom elements

This commit is contained in:
JMS55 2023-12-18 21:24:06 -08:00
parent 9d5b0408c0
commit d8a08b56cc
7 changed files with 106 additions and 31 deletions

1
Cargo.lock generated
View file

@ -1631,7 +1631,6 @@ dependencies = [
"dioxus-core-macro",
"dioxus-hooks",
"dioxus-hot-reload",
"dioxus-html",
"dioxus-rsx",
]

View file

@ -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",
] }

View file

@ -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::<Entity>::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<Option<Entity>>) -> 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<Option<Entity>>) -> 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<Option<Entity>>) -> 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<Option<Entity>>)
}
} 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}"
}
}

View file

@ -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}`.")
}
}
}

20
src/elements.rs Normal file
View file

@ -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);
}
}

View file

@ -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<dyn Any>)> = 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<P>: 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>, 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;

View file

@ -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;