From cad620fe11774be8b88881a5ffbf738eda013a48 Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Sun, 10 Dec 2023 12:35:19 -0800 Subject: [PATCH] WIP mutations: Enough for an extremely basic example --- Cargo.lock | 290 ++++++++++++++++++++++++++++++++++++++++- Cargo.toml | 6 +- examples/basic.rs | 25 ++++ src/apply_mutations.rs | 137 ++++++++++--------- src/hooks.rs | 2 +- src/lib.rs | 16 ++- src/tick.rs | 2 +- 7 files changed, 399 insertions(+), 79 deletions(-) create mode 100644 examples/basic.rs diff --git a/Cargo.lock b/Cargo.lock index 16606ea..24cf106 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -281,6 +281,17 @@ version = "4.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4eb2cdb97421e01129ccb49169d8279ed21e829929144f4a22a6e54ac549ca1" +[[package]] +name = "async-trait" +version = "0.1.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", +] + [[package]] name = "atomic-waker" version = "1.1.2" @@ -495,7 +506,8 @@ name = "bevy_dioxus" version = "0.1.0" dependencies = [ "bevy", - "dioxus-core", + "dioxus", + "smallvec", ] [[package]] @@ -1284,6 +1296,12 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" +[[package]] +name = "constcat" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd7e35aee659887cbfb97aaf227ac12cad1a9d7c71e55ff3376839ed4e282d08" + [[package]] name = "constgebra" version = "0.1.3" @@ -1417,6 +1435,40 @@ dependencies = [ "winapi", ] +[[package]] +name = "darling" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "syn 2.0.39", +] + +[[package]] +name = "darling_macro" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.39", +] + [[package]] name = "dasp_sample" version = "0.11.0" @@ -1429,6 +1481,20 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" +[[package]] +name = "dioxus" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d9e3b0725e520250bf23213f996d241cca29cea4360a9bf08a44e0033f8e569" +dependencies = [ + "dioxus-core", + "dioxus-core-macro", + "dioxus-hooks", + "dioxus-hot-reload", + "dioxus-html", + "dioxus-rsx", +] + [[package]] name = "dioxus-core" version = "0.4.3" @@ -1440,11 +1506,92 @@ dependencies = [ "futures-util", "longest-increasing-subsequence", "rustc-hash", + "serde", "slab", "smallbox", "tracing", ] +[[package]] +name = "dioxus-core-macro" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21afaccb28587aed0ba98856335912f5ce7052c0aafa74b213829a3b8bfd2345" +dependencies = [ + "constcat", + "dioxus-core", + "dioxus-rsx", + "prettyplease", + "proc-macro2", + "quote", + "syn 2.0.39", +] + +[[package]] +name = "dioxus-debug-cell" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ea539174bb236e0e7dc9c12b19b88eae3cb574dedbd0252a2d43ea7e6de13e2" + +[[package]] +name = "dioxus-hooks" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bb23ce82df4fb13e9ddaa01d1469f1f32d683dd4636204bd0a0eaf434b65946" +dependencies = [ + "dioxus-core", + "dioxus-debug-cell", + "futures-channel", + "slab", + "thiserror", + "tracing", +] + +[[package]] +name = "dioxus-hot-reload" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7d8c9e89e866a6b84b8ad696f0ff2f6f6563d2235eb99acc6952f19e516cc09" +dependencies = [ + "dioxus-core", + "dioxus-html", + "dioxus-rsx", + "interprocess-docfix", + "serde", + "serde_json", +] + +[[package]] +name = "dioxus-html" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "828a42a2d70688a2412a8538c8b5a5eceadf68f682f899dc4455a0169db39dfd" +dependencies = [ + "async-channel 1.9.0", + "async-trait", + "dioxus-core", + "enumset", + "euclid", + "keyboard-types", + "serde", + "serde-value", + "serde_json", + "serde_repr", + "web-sys", +] + +[[package]] +name = "dioxus-rsx" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c974133c7c95497a486d587e40449927711430b308134b9cd374b8d35eceafb3" +dependencies = [ + "dioxus-core", + "proc-macro2", + "quote", + "syn 2.0.39", +] + [[package]] name = "dispatch" version = "0.2.0" @@ -1489,6 +1636,27 @@ dependencies = [ "syn 2.0.39", ] +[[package]] +name = "enumset" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "226c0da7462c13fb57e5cc9e0dc8f0635e7d27f276a3a7fd30054647f669007d" +dependencies = [ + "enumset_derive", +] + +[[package]] +name = "enumset_derive" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08b6c6ab82d70f08844964ba10c7babb716de2ecaeab9be5717918a5177d3af" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.39", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -1511,6 +1679,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87f253bc5c813ca05792837a0ff4b3a580336b224512d48f7eda1d7dd9210787" dependencies = [ "num-traits", + "serde", ] [[package]] @@ -1914,6 +2083,12 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "image" version = "0.24.7" @@ -1986,6 +2161,32 @@ dependencies = [ "web-sys", ] +[[package]] +name = "interprocess-docfix" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b84ee245c606aeb0841649a9288e3eae8c61b853a8cd5c0e14450e96d53d28f" +dependencies = [ + "blocking", + "cfg-if", + "futures-core", + "futures-io", + "intmap", + "libc", + "once_cell", + "rustc_version", + "spinning", + "thiserror", + "to_method", + "winapi", +] + +[[package]] +name = "intmap" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae52f28f45ac2bc96edb7714de995cffc174a395fb0abf5bff453587c980d7b9" + [[package]] name = "io-kit-sys" version = "0.4.0" @@ -2054,6 +2255,17 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "keyboard-types" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b750dcadc39a09dbadd74e118f6dd6598df77fa01df0cfcdc52c28dece74528a" +dependencies = [ + "bitflags 2.4.1", + "serde", + "unicode-segmentation", +] + [[package]] name = "khronos-egl" version = "4.1.0" @@ -2553,6 +2765,15 @@ dependencies = [ "libredox", ] +[[package]] +name = "ordered-float" +version = "2.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c" +dependencies = [ + "num-traits", +] + [[package]] name = "overload" version = "0.1.1" @@ -2676,6 +2897,16 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "prettyplease" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae005bd773ab59b4725093fd7df83fd7892f7d8eafb48dbd7de6e024e4215f9d" +dependencies = [ + "proc-macro2", + "syn 2.0.39", +] + [[package]] name = "proc-macro-crate" version = "1.3.1" @@ -2842,6 +3073,15 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + [[package]] name = "ruzstd" version = "0.4.0" @@ -2874,6 +3114,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "semver" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" + [[package]] name = "serde" version = "1.0.193" @@ -2883,6 +3129,16 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde-value" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c" +dependencies = [ + "ordered-float", + "serde", +] + [[package]] name = "serde_derive" version = "1.0.193" @@ -2905,6 +3161,17 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_repr" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3081f5ffbb02284dda55132aa26daecedd7372a42417bbbab6f14ab7d6bb9145" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -2968,6 +3235,15 @@ dependencies = [ "serde", ] +[[package]] +name = "spinning" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d4f0e86297cad2658d92a707320d87bf4e6ae1050287f51d19b67ef3f153a7b" +dependencies = [ + "lock_api", +] + [[package]] name = "spirv" version = "0.2.0+1.5.4" @@ -3112,6 +3388,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" +[[package]] +name = "to_method" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7c4ceeeca15c8384bbc3e011dbd8fccb7f068a440b752b7d9b32ceb0ca0e2e8" + [[package]] name = "toml_datetime" version = "0.6.5" @@ -3245,6 +3527,12 @@ version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +[[package]] +name = "unicode-segmentation" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" + [[package]] name = "unicode-width" version = "0.1.11" diff --git a/Cargo.toml b/Cargo.toml index f7d1c44..73d31df 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,4 +5,8 @@ edition = "2021" [dependencies] bevy = { git = "https://github.com/JMS55/bevy", branch = "query_new" } -dioxus-core = "0.4" +dioxus = "0.4" +smallvec = "1.0" + +[[example]] +name = "basic" diff --git a/examples/basic.rs b/examples/basic.rs new file mode 100644 index 0000000..0d08835 --- /dev/null +++ b/examples/basic.rs @@ -0,0 +1,25 @@ +use bevy::{ + app::{App, Startup}, + core_pipeline::core_2d::Camera2dBundle, + ecs::system::Commands, + ui::node_bundles::NodeBundle, + DefaultPlugins, +}; +use bevy_dioxus::{dioxus::prelude::*, DioxusUiBundle, DioxusUiPlugin, DioxusUiRoot}; + +fn main() { + App::new() + .add_plugins((DefaultPlugins, DioxusUiPlugin)) + .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 { + render!("Hello") +} diff --git a/src/apply_mutations.rs b/src/apply_mutations.rs index 5fdf2b4..91db87a 100644 --- a/src/apply_mutations.rs +++ b/src/apply_mutations.rs @@ -1,27 +1,26 @@ use bevy::{ - ecs::{ - entity::Entity, - reflect::{AppTypeRegistry, ReflectComponent}, - system::{Command, Commands}, - world::Mut, - }, - hierarchy::{BuildChildren, DespawnRecursiveExt}, - prelude::World, - reflect::Reflect, + ecs::{entity::Entity, system::Commands}, + hierarchy::BuildChildren, + prelude::default, + text::{Text, TextStyle}, + ui::node_bundles::TextBundle, utils::HashMap, }; -use dioxus_core::{BorrowedAttributeValue, ElementId, Mutation, Mutations}; -use std::sync::Arc; +use dioxus::core::{ElementId, Mutation, Mutations, Template, TemplateNode}; +use smallvec::SmallVec; pub fn apply_mutations( mutations: Mutations, element_id_to_bevy_ui_entity: &mut HashMap, - templates: &mut HashMap, + templates: &mut HashMap, root_entity: Entity, commands: &mut Commands, ) { for new_template in mutations.templates { - templates.insert(new_template.name.to_owned(), todo!()); + templates.insert( + new_template.name.to_owned(), + BevyTemplate::from_dioxus(&new_template), + ); } let map = element_id_to_bevy_ui_entity; @@ -37,16 +36,14 @@ pub fn apply_mutations( } } Mutation::AssignId { path, id } => todo!(), - Mutation::CreatePlaceholder { id } => { - map.insert(id, commands.spawn(()).id()); + Mutation::CreatePlaceholder { id } => todo!(), + Mutation::CreateTextNode { value, id } => todo!(), + Mutation::HydrateText { path, value, id } => todo!(), + Mutation::LoadTemplate { name, index, id } => { + let entity = templates[name].roots[index].spawn(commands); + map.insert(id, entity); + stack.push(entity); } - Mutation::CreateTextNode { .. } => { - unreachable!("Should not be used by bevy_dioxus elements"); - } - Mutation::HydrateText { .. } => { - unreachable!("Should not be used by bevy_dioxus elements"); - } - Mutation::LoadTemplate { name, index, id } => todo!(), Mutation::ReplaceWith { id, m } => todo!(), Mutation::ReplacePlaceholder { path, m } => todo!(), Mutation::InsertAfter { id, m } => todo!(), @@ -55,63 +52,61 @@ pub fn apply_mutations( name, value, id, - ns: _, - } => commands.add(SetReflectedComponent { - entity: map[&id], - component_type_path: name.to_owned(), - component_value: match value { - BorrowedAttributeValue::Any(value) => Some(Arc::clone( - value - .as_any() - .downcast_ref::>() - .expect(&format!( - "Encountered an attribute with name {name} that did not impl Reflect" - )), - )), - BorrowedAttributeValue::None => None, - _ => unreachable!("Should not be used by bevy_dioxus elements"), - }, - }), - Mutation::SetText { .. } => unreachable!("Should not be used by bevy_dioxus elements"), + ns, + } => todo!(), + Mutation::SetText { value, id } => todo!(), Mutation::NewEventListener { name, id } => todo!(), Mutation::RemoveEventListener { name, id } => todo!(), - Mutation::Remove { id } => { - commands - .entity(map.remove(&id).unwrap()) - .despawn_recursive(); - } - Mutation::PushRoot { id } => stack.push(map[&id]), + Mutation::Remove { id } => todo!(), + Mutation::PushRoot { id } => todo!(), } } } -struct SetReflectedComponent { - entity: Entity, - component_type_path: String, - component_value: Option>, +pub struct BevyTemplate { + roots: SmallVec<[BevyTemplateNode; 4]>, } -impl Command for SetReflectedComponent { - fn apply(self, world: &mut World) { - world.resource_scope(|world: &mut World, type_registry: Mut| { - let type_registry = type_registry.read(); - let reflected_component = type_registry - .get_with_type_path(&self.component_type_path) - .expect(&format!( - "Encountered an attribute with name {} that was not registered for reflection", - self.component_type_path - )) - .data::() - .expect(&format!( - "Encountered an attribute with name {} that did not reflect Component", - self.component_type_path - )); +enum BevyTemplateNode { + Text(Text), +} - let entity_mut = &mut world.entity_mut(self.entity); - match self.component_value { - Some(value) => reflected_component.insert(entity_mut, &*value), - None => reflected_component.remove(entity_mut), - } - }); +impl BevyTemplate { + fn from_dioxus(template: &Template) -> Self { + Self { + roots: template + .roots + .iter() + .map(BevyTemplateNode::from_dioxus) + .collect(), + } + } +} + +impl BevyTemplateNode { + fn from_dioxus(node: &TemplateNode) -> Self { + match node { + TemplateNode::Element { + tag, + namespace, + attrs, + children, + } => todo!(), + TemplateNode::Text { text } => { + Self::Text(Text::from_section(*text, TextStyle::default())) + } + TemplateNode::Dynamic { id } => todo!(), + TemplateNode::DynamicText { id } => todo!(), + } + } + + fn spawn(&self, commands: &mut Commands) -> Entity { + match self { + Self::Text(text) => commands.spawn(TextBundle { + text: text.clone(), + ..default() + }), + } + .id() } } diff --git a/src/hooks.rs b/src/hooks.rs index d36d748..4389b02 100644 --- a/src/hooks.rs +++ b/src/hooks.rs @@ -7,7 +7,7 @@ use bevy::ecs::{ system::{IntoSystem, Query, Resource}, world::{unsafe_world_cell::UnsafeWorldCell, World}, }; -use dioxus_core::ScopeState; +use dioxus::core::ScopeState; pub trait DioxusUiHooks { fn use_world<'a>(&'a self) -> &'a World; diff --git a/src/lib.rs b/src/lib.rs index 461f3d3..febb5a7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,21 +4,23 @@ mod hooks; mod tick; use self::{ + apply_mutations::BevyTemplate, deferred_system::DeferredSystemRegistry, tick::{tick_dioxus_ui, VirtualDomUnsafe}, }; use bevy::{ app::{App, Plugin, Update}, - ecs::{component::Component, entity::Entity}, + ecs::{bundle::Bundle, component::Component, entity::Entity}, + ui::node_bundles::NodeBundle, utils::HashMap, }; -use dioxus_core::ElementId; +use dioxus::core::{Element, ElementId, Scope}; pub use self::{ deferred_system::DeferredSystem, hooks::{DioxusUiHooks, DioxusUiQuery}, }; -pub use dioxus_core::{Element, Scope}; +pub use dioxus; pub struct DioxusUiPlugin; @@ -29,11 +31,17 @@ impl Plugin for DioxusUiPlugin { } } +#[derive(Bundle)] +pub struct DioxusUiBundle { + pub dioxus_ui_root: DioxusUiRoot, + pub node_bundle: NodeBundle, +} + #[derive(Component)] pub struct DioxusUiRoot { virtual_dom: VirtualDomUnsafe, element_id_to_bevy_ui_entity: HashMap, - templates: HashMap, + templates: HashMap, needs_rebuild: bool, } diff --git a/src/tick.rs b/src/tick.rs index db60be0..a099193 100644 --- a/src/tick.rs +++ b/src/tick.rs @@ -10,7 +10,7 @@ use bevy::{ prelude::{Deref, DerefMut}, utils::synccell::SyncCell, }; -use dioxus_core::{Element, Scope, ScopeState, VirtualDom}; +use dioxus::core::{Element, Scope, ScopeState, VirtualDom}; use std::{mem, sync::Arc}; pub fn tick_dioxus_ui(world: &mut World) {