Start of custom elements
This commit is contained in:
parent
9d5b0408c0
commit
d8a08b56cc
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -1631,7 +1631,6 @@ dependencies = [
|
||||||
"dioxus-core-macro",
|
"dioxus-core-macro",
|
||||||
"dioxus-hooks",
|
"dioxus-hooks",
|
||||||
"dioxus-hot-reload",
|
"dioxus-hot-reload",
|
||||||
"dioxus-html",
|
|
||||||
"dioxus-rsx",
|
"dioxus-rsx",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,11 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bevy = { git = "https://github.com/JMS55/bevy", branch = "query_new_12" }
|
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 = [
|
bevy_mod_picking = { version = "0.17", default-features = false, features = [
|
||||||
"backend_bevy_ui",
|
"backend_bevy_ui",
|
||||||
] }
|
] }
|
||||||
|
|
|
@ -6,10 +6,8 @@ use bevy::{
|
||||||
ui::{node_bundles::NodeBundle, Node},
|
ui::{node_bundles::NodeBundle, Node},
|
||||||
DefaultPlugins,
|
DefaultPlugins,
|
||||||
};
|
};
|
||||||
use bevy_dioxus::{
|
use bevy_dioxus::{colors::*, prelude::*};
|
||||||
bevy_mod_picking::DefaultPickingPlugins, colors::*, dioxus::prelude::*, hooks::*,
|
use bevy_mod_picking::DefaultPickingPlugins;
|
||||||
DioxusUiBundle, DioxusUiPlugin, DioxusUiRoot,
|
|
||||||
};
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
App::new()
|
App::new()
|
||||||
|
@ -30,7 +28,7 @@ fn Editor(cx: Scope) -> Element {
|
||||||
let selected_entity = use_state(cx, || Option::<Entity>::None);
|
let selected_entity = use_state(cx, || Option::<Entity>::None);
|
||||||
|
|
||||||
render! {
|
render! {
|
||||||
div {
|
node {
|
||||||
width: "100vw",
|
width: "100vw",
|
||||||
height: "100vh",
|
height: "100vh",
|
||||||
justify_content: "space-between",
|
justify_content: "space-between",
|
||||||
|
@ -52,7 +50,7 @@ fn SceneTree<'a>(cx: Scope, selected_entity: &'a UseState<Option<Entity>>) -> El
|
||||||
});
|
});
|
||||||
|
|
||||||
render! {
|
render! {
|
||||||
div {
|
node {
|
||||||
onclick: move |_| selected_entity.set(None),
|
onclick: move |_| selected_entity.set(None),
|
||||||
flex_direction: "column",
|
flex_direction: "column",
|
||||||
if entities.is_empty() {
|
if entities.is_empty() {
|
||||||
|
@ -60,7 +58,7 @@ fn SceneTree<'a>(cx: Scope, selected_entity: &'a UseState<Option<Entity>>) -> El
|
||||||
} else {
|
} else {
|
||||||
rsx! {
|
rsx! {
|
||||||
for (entity, name) in entities {
|
for (entity, name) in entities {
|
||||||
div {
|
node {
|
||||||
onclick: move |_| {
|
onclick: move |_| {
|
||||||
if Some(entity) == ***selected_entity {
|
if Some(entity) == ***selected_entity {
|
||||||
selected_entity.set(None);
|
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(),
|
onclick: move |_| spawn_entity(),
|
||||||
padding: "8",
|
padding: "8",
|
||||||
background_color: NEUTRAL_800,
|
background_color: NEUTRAL_800,
|
||||||
|
@ -117,14 +115,14 @@ fn EntityInspector<'a>(cx: Scope, selected_entity: &'a UseState<Option<Entity>>)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
rsx! {
|
rsx! {
|
||||||
div {
|
node {
|
||||||
flex_direction: "column",
|
flex_direction: "column",
|
||||||
for (name, _component_id, _type_id, _size) in components {
|
for (name, _component_id, _type_id, _size) in components {
|
||||||
div {
|
node {
|
||||||
padding: "8",
|
padding: "8",
|
||||||
background_color: NEUTRAL_800,
|
background_color: NEUTRAL_800,
|
||||||
|
|
||||||
div {
|
node {
|
||||||
"Component: {name}"
|
"Component: {name}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -221,21 +221,14 @@ impl BevyTemplateNode {
|
||||||
fn from_dioxus(node: &TemplateNode) -> Self {
|
fn from_dioxus(node: &TemplateNode) -> Self {
|
||||||
match node {
|
match node {
|
||||||
TemplateNode::Element {
|
TemplateNode::Element {
|
||||||
tag,
|
tag: "node",
|
||||||
namespace: _,
|
namespace: Some("bevy_ui"),
|
||||||
attrs,
|
attrs,
|
||||||
children,
|
children,
|
||||||
} => {
|
} => Self::Node {
|
||||||
if *tag != "div" {
|
style: parse_style_attributes(attrs),
|
||||||
panic!(
|
children: children.iter().map(Self::from_dioxus).collect(),
|
||||||
"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(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
TemplateNode::Text { text } => {
|
TemplateNode::Text { text } => {
|
||||||
Self::TextNode(Text::from_section(*text, TextStyle::default()))
|
Self::TextNode(Text::from_section(*text, TextStyle::default()))
|
||||||
}
|
}
|
||||||
|
@ -246,6 +239,20 @@ impl BevyTemplateNode {
|
||||||
TemplateNode::DynamicText { id: _ } => {
|
TemplateNode::DynamicText { id: _ } => {
|
||||||
Self::TextNode(Text::from_section("", TextStyle::default()))
|
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
20
src/elements.rs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,7 +4,7 @@ use bevy::ecs::{
|
||||||
system::Resource,
|
system::Resource,
|
||||||
};
|
};
|
||||||
use bevy_mod_picking::events::{Click, Pointer};
|
use bevy_mod_picking::events::{Click, Pointer};
|
||||||
use dioxus::html::MouseData;
|
use dioxus::core::ScopeState;
|
||||||
use std::{any::Any, rc::Rc};
|
use std::{any::Any, rc::Rc};
|
||||||
|
|
||||||
// TODO: Other events
|
// TODO: Other events
|
||||||
|
@ -22,7 +22,7 @@ impl EventReaders {
|
||||||
let mut events: Vec<(Entity, &'static str, Rc<dyn Any>)> = Vec::new();
|
let mut events: Vec<(Entity, &'static str, Rc<dyn Any>)> = Vec::new();
|
||||||
|
|
||||||
for event in self.clicks.read(clicks) {
|
for event in self.clicks.read(clicks) {
|
||||||
events.push((event.target, "click", Rc::new(MouseData::default())));
|
events.push((event.target, "click", Rc::new(())));
|
||||||
}
|
}
|
||||||
|
|
||||||
events
|
events
|
||||||
|
@ -32,3 +32,43 @@ impl EventReaders {
|
||||||
pub fn is_supported_event(event: &str) -> bool {
|
pub fn is_supported_event(event: &str) -> bool {
|
||||||
event == "click"
|
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;
|
||||||
|
|
13
src/lib.rs
13
src/lib.rs
|
@ -1,8 +1,10 @@
|
||||||
mod apply_mutations;
|
mod apply_mutations;
|
||||||
pub mod colors;
|
pub mod colors;
|
||||||
mod deferred_system;
|
mod deferred_system;
|
||||||
|
mod elements;
|
||||||
|
#[macro_use]
|
||||||
mod events;
|
mod events;
|
||||||
pub mod hooks;
|
mod hooks;
|
||||||
mod tick;
|
mod tick;
|
||||||
|
|
||||||
use self::{
|
use self::{
|
||||||
|
@ -18,8 +20,13 @@ use bevy::{
|
||||||
};
|
};
|
||||||
use dioxus::core::{Element, ElementId, Scope, VirtualDom};
|
use dioxus::core::{Element, ElementId, Scope, VirtualDom};
|
||||||
|
|
||||||
pub use bevy_mod_picking;
|
pub mod prelude {
|
||||||
pub use dioxus;
|
pub use super::elements::*;
|
||||||
|
pub use super::hooks::*;
|
||||||
|
pub use super::{DioxusUiBundle, DioxusUiPlugin, DioxusUiRoot};
|
||||||
|
pub use dioxus;
|
||||||
|
pub use dioxus::prelude::*;
|
||||||
|
}
|
||||||
|
|
||||||
pub struct DioxusUiPlugin;
|
pub struct DioxusUiPlugin;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue