WIP: More advanced example
This commit is contained in:
parent
8dcaae99e1
commit
a61ee7e0b2
|
@ -26,4 +26,4 @@ bevy_utils = { git = "https://github.com/JMS55/bevy", branch = "query_new_12" }
|
||||||
bevy_window = { git = "https://github.com/JMS55/bevy", branch = "query_new_12" }
|
bevy_window = { git = "https://github.com/JMS55/bevy", branch = "query_new_12" }
|
||||||
|
|
||||||
[[example]]
|
[[example]]
|
||||||
name = "basic"
|
name = "demo"
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
use bevy::{
|
|
||||||
app::{App, Startup},
|
|
||||||
core_pipeline::{clear_color::ClearColor, core_2d::Camera2dBundle},
|
|
||||||
ecs::system::{Commands, ResMut},
|
|
||||||
render::color::Color,
|
|
||||||
ui::node_bundles::NodeBundle,
|
|
||||||
DefaultPlugins,
|
|
||||||
};
|
|
||||||
use bevy_dioxus::{
|
|
||||||
bevy_mod_picking::DefaultPickingPlugins, dioxus::prelude::*, hooks::use_system, DioxusUiBundle,
|
|
||||||
DioxusUiPlugin, DioxusUiRoot,
|
|
||||||
};
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
App::new()
|
|
||||||
.add_plugins((DefaultPlugins, DioxusUiPlugin, DefaultPickingPlugins))
|
|
||||||
.add_systems(Startup, |mut commands: Commands| {
|
|
||||||
commands.spawn(DioxusUiBundle {
|
|
||||||
dioxus_ui_root: DioxusUiRoot::new(ui_root),
|
|
||||||
node_bundle: NodeBundle::default(),
|
|
||||||
});
|
|
||||||
commands.spawn(Camera2dBundle::default());
|
|
||||||
})
|
|
||||||
.run();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn ui_root(cx: Scope) -> Element {
|
|
||||||
let mut count = use_state(cx, || 0);
|
|
||||||
let change_clear_color = use_system(cx, |mut clear_color: ResMut<ClearColor>| {
|
|
||||||
clear_color.0 = Color::RED;
|
|
||||||
});
|
|
||||||
|
|
||||||
render!(
|
|
||||||
div {
|
|
||||||
onclick: move |_| {
|
|
||||||
count += 1;
|
|
||||||
change_clear_color.schedule();
|
|
||||||
},
|
|
||||||
"Count: {count}"
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
73
examples/demo.rs
Normal file
73
examples/demo.rs
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
use bevy::{
|
||||||
|
app::{App, Startup},
|
||||||
|
core::DebugName,
|
||||||
|
core_pipeline::core_2d::Camera2dBundle,
|
||||||
|
ecs::{entity::Entity, query::Without, system::Commands},
|
||||||
|
ui::{node_bundles::NodeBundle, Node},
|
||||||
|
DefaultPlugins,
|
||||||
|
};
|
||||||
|
use bevy_dioxus::{
|
||||||
|
bevy_mod_picking::DefaultPickingPlugins, colors::*, dioxus::prelude::*, hooks::*,
|
||||||
|
DioxusUiBundle, DioxusUiPlugin, DioxusUiRoot,
|
||||||
|
};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
App::new()
|
||||||
|
.add_plugins((DefaultPlugins, DioxusUiPlugin, DefaultPickingPlugins))
|
||||||
|
.add_systems(Startup, |mut commands: Commands| {
|
||||||
|
commands.spawn(DioxusUiBundle {
|
||||||
|
dioxus_ui_root: DioxusUiRoot::new(Editor),
|
||||||
|
node_bundle: NodeBundle::default(),
|
||||||
|
});
|
||||||
|
commands.spawn(Camera2dBundle::default());
|
||||||
|
})
|
||||||
|
.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
fn Editor(cx: Scope) -> Element {
|
||||||
|
let selected_entity = use_state(cx, || Option::<Entity>::None);
|
||||||
|
|
||||||
|
render! {
|
||||||
|
SceneTree { selected_entity: selected_entity }
|
||||||
|
EntityInspector { selected_entity: selected_entity }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
fn SceneTree<'a>(cx: Scope, selected_entity: &'a UseState<Option<Entity>>) -> Element {
|
||||||
|
let entities = use_query_filtered::<(Entity, DebugName), Without<Node>>(cx);
|
||||||
|
let entities = entities.query();
|
||||||
|
let mut entities = entities.into_iter().collect::<Vec<_>>();
|
||||||
|
entities.sort_by_key(|(entity, _)| *entity);
|
||||||
|
|
||||||
|
render! {
|
||||||
|
div {
|
||||||
|
flex_direction: "column",
|
||||||
|
if entities.is_empty() {
|
||||||
|
rsx! { "No entities exist" }
|
||||||
|
} else {
|
||||||
|
rsx! {
|
||||||
|
for (entity, name) in entities {
|
||||||
|
div {
|
||||||
|
onclick: move |_| selected_entity.set(Some(entity)),
|
||||||
|
background_color: if Some(entity) == ***selected_entity { INDIGO_600 } else { NEUTRAL_800 },
|
||||||
|
format!("{name:?}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
fn EntityInspector<'a>(cx: Scope, selected_entity: &'a UseState<Option<Entity>>) -> Element {
|
||||||
|
render! {
|
||||||
|
if selected_entity.is_none() {
|
||||||
|
"Select an entity to view its components"
|
||||||
|
} else {
|
||||||
|
"TODO: Component widgets"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,6 +3,7 @@ use bevy::{
|
||||||
ecs::{entity::Entity, system::Commands},
|
ecs::{entity::Entity, system::Commands},
|
||||||
hierarchy::BuildChildren,
|
hierarchy::BuildChildren,
|
||||||
prelude::default,
|
prelude::default,
|
||||||
|
render::color::Color,
|
||||||
text::{Text, TextStyle},
|
text::{Text, TextStyle},
|
||||||
ui::{
|
ui::{
|
||||||
node_bundles::{NodeBundle, TextBundle},
|
node_bundles::{NodeBundle, TextBundle},
|
||||||
|
@ -111,7 +112,10 @@ pub struct BevyTemplate {
|
||||||
}
|
}
|
||||||
|
|
||||||
enum BevyTemplateNode {
|
enum BevyTemplateNode {
|
||||||
Node { style: Style, children: Box<[Self]> },
|
Node {
|
||||||
|
style: (Style, BackgroundColor),
|
||||||
|
children: Box<[Self]>,
|
||||||
|
},
|
||||||
TextNode(Text),
|
TextNode(Text),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,7 +154,7 @@ impl BevyTemplateNode {
|
||||||
Self::TextNode(Text::from_section(*text, TextStyle::default()))
|
Self::TextNode(Text::from_section(*text, TextStyle::default()))
|
||||||
}
|
}
|
||||||
TemplateNode::Dynamic { id: _ } => Self::Node {
|
TemplateNode::Dynamic { id: _ } => Self::Node {
|
||||||
style: Style::default(),
|
style: Default::default(),
|
||||||
children: Box::new([]),
|
children: Box::new([]),
|
||||||
},
|
},
|
||||||
TemplateNode::DynamicText { id: _ } => {
|
TemplateNode::DynamicText { id: _ } => {
|
||||||
|
@ -166,17 +170,23 @@ impl BevyTemplateNode {
|
||||||
children_to_parent: &mut EntityHashMap<Entity, Entity>,
|
children_to_parent: &mut EntityHashMap<Entity, Entity>,
|
||||||
) -> Entity {
|
) -> Entity {
|
||||||
match self {
|
match self {
|
||||||
BevyTemplateNode::Node { style, children } => {
|
BevyTemplateNode::Node {
|
||||||
|
style: (style, background_color),
|
||||||
|
children,
|
||||||
|
} => {
|
||||||
// TODO: Can probably use with_children() instead
|
// TODO: Can probably use with_children() instead
|
||||||
let children = children
|
let children = children
|
||||||
.iter()
|
.iter()
|
||||||
.map(|child| child.spawn(commands, parent_to_children, children_to_parent))
|
.map(|child| child.spawn(commands, parent_to_children, children_to_parent))
|
||||||
.collect::<Box<[_]>>();
|
.collect::<Box<[_]>>();
|
||||||
let parent = commands
|
let parent = commands
|
||||||
.spawn(NodeBundle {
|
.spawn((
|
||||||
|
NodeBundle {
|
||||||
style: style.clone(),
|
style: style.clone(),
|
||||||
..default()
|
..default()
|
||||||
})
|
},
|
||||||
|
background_color.clone(),
|
||||||
|
))
|
||||||
.push_children(&children)
|
.push_children(&children)
|
||||||
.id();
|
.id();
|
||||||
for (i, child) in children.iter().enumerate() {
|
for (i, child) in children.iter().enumerate() {
|
||||||
|
@ -195,8 +205,9 @@ impl BevyTemplateNode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_style_attributes(attributes: &[TemplateAttribute]) -> Style {
|
fn parse_style_attributes(attributes: &[TemplateAttribute]) -> (Style, BackgroundColor) {
|
||||||
let mut style = Style::default();
|
let mut style = Style::default();
|
||||||
|
let mut backgroud_color = BackgroundColor::default();
|
||||||
for attribute in attributes {
|
for attribute in attributes {
|
||||||
if let TemplateAttribute::Static {
|
if let TemplateAttribute::Static {
|
||||||
name,
|
name,
|
||||||
|
@ -211,9 +222,15 @@ fn parse_style_attributes(attributes: &[TemplateAttribute]) -> Style {
|
||||||
("display", "none") => style.display = Display::None,
|
("display", "none") => style.display = Display::None,
|
||||||
("position", "relative") => style.position_type = PositionType::Relative,
|
("position", "relative") => style.position_type = PositionType::Relative,
|
||||||
("position", "absolute") => style.position_type = PositionType::Absolute,
|
("position", "absolute") => style.position_type = PositionType::Absolute,
|
||||||
|
("flex-direction", "column") => style.flex_direction = FlexDirection::Column,
|
||||||
|
("background-color", hex) => {
|
||||||
|
backgroud_color.0 = Color::hex(hex).expect(&format!(
|
||||||
|
"Encountered unsupported bevy_dioxus background-color `{value}`."
|
||||||
|
))
|
||||||
|
}
|
||||||
_ => panic!("Encountered unsupported bevy_dioxus attribute `{name}: {value}`."),
|
_ => panic!("Encountered unsupported bevy_dioxus attribute `{name}: {value}`."),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
style
|
(style, backgroud_color)
|
||||||
}
|
}
|
||||||
|
|
3
src/colors.rs
Normal file
3
src/colors.rs
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
pub const NEUTRAL_800: &'static str = "#27272a";
|
||||||
|
|
||||||
|
pub const INDIGO_600: &'static str = "#4f46e5";
|
|
@ -1,4 +1,5 @@
|
||||||
mod apply_mutations;
|
mod apply_mutations;
|
||||||
|
pub mod colors;
|
||||||
mod deferred_system;
|
mod deferred_system;
|
||||||
mod events;
|
mod events;
|
||||||
pub mod hooks;
|
pub mod hooks;
|
||||||
|
|
Loading…
Reference in a new issue