From a61ee7e0b231f73da62eaae0d5d950c48db27ea9 Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Tue, 12 Dec 2023 19:47:14 -0800 Subject: [PATCH] WIP: More advanced example --- Cargo.toml | 2 +- examples/basic.rs | 42 ------------------------ examples/demo.rs | 73 ++++++++++++++++++++++++++++++++++++++++++ src/apply_mutations.rs | 35 ++++++++++++++------ src/colors.rs | 3 ++ src/lib.rs | 1 + 6 files changed, 104 insertions(+), 52 deletions(-) delete mode 100644 examples/basic.rs create mode 100644 examples/demo.rs create mode 100644 src/colors.rs diff --git a/Cargo.toml b/Cargo.toml index 1d2f8ea..3144108 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" } [[example]] -name = "basic" +name = "demo" diff --git a/examples/basic.rs b/examples/basic.rs deleted file mode 100644 index 35c8337..0000000 --- a/examples/basic.rs +++ /dev/null @@ -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| { - clear_color.0 = Color::RED; - }); - - render!( - div { - onclick: move |_| { - count += 1; - change_clear_color.schedule(); - }, - "Count: {count}" - } - ) -} diff --git a/examples/demo.rs b/examples/demo.rs new file mode 100644 index 0000000..b590769 --- /dev/null +++ b/examples/demo.rs @@ -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::::None); + + render! { + SceneTree { selected_entity: selected_entity } + EntityInspector { selected_entity: selected_entity } + } +} + +#[component] +fn SceneTree<'a>(cx: Scope, selected_entity: &'a UseState>) -> Element { + let entities = use_query_filtered::<(Entity, DebugName), Without>(cx); + let entities = entities.query(); + let mut entities = entities.into_iter().collect::>(); + 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>) -> Element { + render! { + if selected_entity.is_none() { + "Select an entity to view its components" + } else { + "TODO: Component widgets" + } + } +} diff --git a/src/apply_mutations.rs b/src/apply_mutations.rs index ac5f804..21a694e 100644 --- a/src/apply_mutations.rs +++ b/src/apply_mutations.rs @@ -3,6 +3,7 @@ use bevy::{ ecs::{entity::Entity, system::Commands}, hierarchy::BuildChildren, prelude::default, + render::color::Color, text::{Text, TextStyle}, ui::{ node_bundles::{NodeBundle, TextBundle}, @@ -111,7 +112,10 @@ pub struct BevyTemplate { } enum BevyTemplateNode { - Node { style: Style, children: Box<[Self]> }, + Node { + style: (Style, BackgroundColor), + children: Box<[Self]>, + }, TextNode(Text), } @@ -150,7 +154,7 @@ impl BevyTemplateNode { Self::TextNode(Text::from_section(*text, TextStyle::default())) } TemplateNode::Dynamic { id: _ } => Self::Node { - style: Style::default(), + style: Default::default(), children: Box::new([]), }, TemplateNode::DynamicText { id: _ } => { @@ -166,17 +170,23 @@ impl BevyTemplateNode { children_to_parent: &mut EntityHashMap, ) -> Entity { match self { - BevyTemplateNode::Node { style, children } => { + BevyTemplateNode::Node { + style: (style, background_color), + children, + } => { // TODO: Can probably use with_children() instead let children = children .iter() .map(|child| child.spawn(commands, parent_to_children, children_to_parent)) .collect::>(); let parent = commands - .spawn(NodeBundle { - style: style.clone(), - ..default() - }) + .spawn(( + NodeBundle { + style: style.clone(), + ..default() + }, + background_color.clone(), + )) .push_children(&children) .id(); 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 backgroud_color = BackgroundColor::default(); for attribute in attributes { if let TemplateAttribute::Static { name, @@ -211,9 +222,15 @@ fn parse_style_attributes(attributes: &[TemplateAttribute]) -> Style { ("display", "none") => style.display = Display::None, ("position", "relative") => style.position_type = PositionType::Relative, ("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}`."), } } } - style + (style, backgroud_color) } diff --git a/src/colors.rs b/src/colors.rs new file mode 100644 index 0000000..1ea956b --- /dev/null +++ b/src/colors.rs @@ -0,0 +1,3 @@ +pub const NEUTRAL_800: &'static str = "#27272a"; + +pub const INDIGO_600: &'static str = "#4f46e5"; diff --git a/src/lib.rs b/src/lib.rs index 314786a..dc88b7c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,5 @@ mod apply_mutations; +pub mod colors; mod deferred_system; mod events; pub mod hooks;