Add support for click events
This commit is contained in:
parent
efb9ec93e5
commit
37774fb3e3
18
Cargo.lock
generated
18
Cargo.lock
generated
|
@ -802,8 +802,10 @@ dependencies = [
|
|||
"bevy_math",
|
||||
"bevy_picking_core",
|
||||
"bevy_picking_input",
|
||||
"bevy_picking_ui",
|
||||
"bevy_reflect",
|
||||
"bevy_render",
|
||||
"bevy_ui",
|
||||
"bevy_utils",
|
||||
"bevy_window",
|
||||
]
|
||||
|
@ -868,6 +870,22 @@ dependencies = [
|
|||
"bevy_window",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bevy_picking_ui"
|
||||
version = "0.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a020364f01021b1faf9cc4de85b592505440d5b6274fb39c9d9a916b7639872b"
|
||||
dependencies = [
|
||||
"bevy_app",
|
||||
"bevy_ecs",
|
||||
"bevy_math",
|
||||
"bevy_picking_core",
|
||||
"bevy_render",
|
||||
"bevy_transform",
|
||||
"bevy_ui",
|
||||
"bevy_window",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bevy_ptr"
|
||||
version = "0.12.0"
|
||||
|
|
|
@ -6,10 +6,13 @@ edition = "2021"
|
|||
[dependencies]
|
||||
bevy = { git = "https://github.com/JMS55/bevy", branch = "query_new_12" }
|
||||
dioxus = "0.4"
|
||||
bevy_mod_picking = { version = "0.17", default-features = false }
|
||||
bevy_mod_picking = { version = "0.17", default-features = false, features = [
|
||||
"backend_bevy_ui",
|
||||
] }
|
||||
|
||||
[patch.crates-io]
|
||||
bevy_app = { git = "https://github.com/JMS55/bevy", branch = "query_new_12" }
|
||||
bevy_asset = { git = "https://github.com/JMS55/bevy", branch = "query_new_12" }
|
||||
bevy_core = { git = "https://github.com/JMS55/bevy", branch = "query_new_12" }
|
||||
bevy_ecs = { git = "https://github.com/JMS55/bevy", branch = "query_new_12" }
|
||||
bevy_hierarchy = { git = "https://github.com/JMS55/bevy", branch = "query_new_12" }
|
||||
|
@ -17,6 +20,8 @@ bevy_input = { git = "https://github.com/JMS55/bevy", branch = "query_new_12" }
|
|||
bevy_math = { git = "https://github.com/JMS55/bevy", branch = "query_new_12" }
|
||||
bevy_reflect = { git = "https://github.com/JMS55/bevy", branch = "query_new_12" }
|
||||
bevy_render = { git = "https://github.com/JMS55/bevy", branch = "query_new_12" }
|
||||
bevy_transform = { git = "https://github.com/JMS55/bevy", branch = "query_new_12" }
|
||||
bevy_ui = { git = "https://github.com/JMS55/bevy", branch = "query_new_12" }
|
||||
bevy_utils = { git = "https://github.com/JMS55/bevy", branch = "query_new_12" }
|
||||
bevy_window = { git = "https://github.com/JMS55/bevy", branch = "query_new_12" }
|
||||
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
use bevy::{
|
||||
app::{App, Startup},
|
||||
core_pipeline::core_2d::Camera2dBundle,
|
||||
ecs::system::Commands,
|
||||
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::*, DioxusUiBundle, DioxusUiPlugin,
|
||||
DioxusUiRoot,
|
||||
bevy_mod_picking::DefaultPickingPlugins, dioxus::prelude::*, hooks::use_system, DioxusUiBundle,
|
||||
DioxusUiPlugin, DioxusUiRoot,
|
||||
};
|
||||
|
||||
fn main() {
|
||||
|
@ -24,5 +25,18 @@ fn main() {
|
|||
}
|
||||
|
||||
fn ui_root(cx: Scope) -> Element {
|
||||
render!("Hello")
|
||||
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}"
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use crate::events::is_supported_event;
|
||||
use bevy::{
|
||||
ecs::{entity::Entity, system::Commands},
|
||||
hierarchy::BuildChildren,
|
||||
|
@ -7,7 +8,7 @@ use bevy::{
|
|||
node_bundles::{NodeBundle, TextBundle},
|
||||
*,
|
||||
},
|
||||
utils::{HashMap, HashSet},
|
||||
utils::{EntityHashMap, HashMap},
|
||||
};
|
||||
use dioxus::core::{ElementId, Mutation, Mutations, Template, TemplateAttribute, TemplateNode};
|
||||
|
||||
|
@ -15,7 +16,7 @@ pub fn apply_mutations(
|
|||
mutations: Mutations,
|
||||
hierarchy: &mut HashMap<(Entity, u8), Entity>,
|
||||
element_id_to_bevy_ui_entity: &mut HashMap<ElementId, Entity>,
|
||||
event_listeners: &mut HashSet<(Event, ElementId)>,
|
||||
bevy_ui_entity_to_element_id: &mut EntityHashMap<Entity, ElementId>,
|
||||
templates: &mut HashMap<String, BevyTemplate>,
|
||||
root_entity: Entity,
|
||||
commands: &mut Commands,
|
||||
|
@ -28,6 +29,7 @@ pub fn apply_mutations(
|
|||
}
|
||||
|
||||
element_id_to_bevy_ui_entity.insert(ElementId(0), root_entity);
|
||||
bevy_ui_entity_to_element_id.insert(root_entity, ElementId(0));
|
||||
let mut stack = vec![root_entity];
|
||||
|
||||
for edit in mutations.edits {
|
||||
|
@ -50,6 +52,7 @@ pub fn apply_mutations(
|
|||
let entity = BevyTemplateNode::from_dioxus(&TemplateNode::Text { text: value })
|
||||
.spawn(commands, hierarchy);
|
||||
element_id_to_bevy_ui_entity.insert(id, entity);
|
||||
bevy_ui_entity_to_element_id.insert(entity, id);
|
||||
stack.push(entity);
|
||||
}
|
||||
Mutation::HydrateText { path, value, id } => {
|
||||
|
@ -61,10 +64,12 @@ pub fn apply_mutations(
|
|||
.entity(entity)
|
||||
.insert(Text::from_section(value, TextStyle::default()));
|
||||
element_id_to_bevy_ui_entity.insert(id, entity);
|
||||
bevy_ui_entity_to_element_id.insert(entity, id);
|
||||
}
|
||||
Mutation::LoadTemplate { name, index, id } => {
|
||||
let entity = templates[name].roots[index].spawn(commands, hierarchy);
|
||||
element_id_to_bevy_ui_entity.insert(id, entity);
|
||||
bevy_ui_entity_to_element_id.insert(entity, id);
|
||||
stack.push(entity);
|
||||
}
|
||||
Mutation::ReplaceWith { id, m } => todo!(),
|
||||
|
@ -77,13 +82,17 @@ pub fn apply_mutations(
|
|||
id,
|
||||
ns,
|
||||
} => todo!(),
|
||||
Mutation::SetText { value, id } => todo!(),
|
||||
Mutation::NewEventListener { name, id } => {
|
||||
event_listeners.insert((Event::from_dioxus(name), id));
|
||||
Mutation::SetText { value, id } => {
|
||||
commands
|
||||
.entity(element_id_to_bevy_ui_entity[&id])
|
||||
.insert(Text::from_section(value, TextStyle::default()));
|
||||
}
|
||||
Mutation::RemoveEventListener { name, id } => {
|
||||
event_listeners.remove(&(Event::from_dioxus(name), id));
|
||||
Mutation::NewEventListener { name, id: _ } => {
|
||||
if !is_supported_event(name) {
|
||||
panic!("Encountered unsupported bevy_dioxus event `{name}`.");
|
||||
}
|
||||
}
|
||||
Mutation::RemoveEventListener { .. } => {}
|
||||
Mutation::Remove { id } => todo!(),
|
||||
Mutation::PushRoot { id } => stack.push(element_id_to_bevy_ui_entity[&id]),
|
||||
}
|
||||
|
@ -177,20 +186,6 @@ impl BevyTemplateNode {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Hash, Clone, Copy)]
|
||||
pub enum Event {
|
||||
Click,
|
||||
}
|
||||
|
||||
impl Event {
|
||||
pub fn from_dioxus(event: &str) -> Self {
|
||||
match event {
|
||||
"click" => Self::Click,
|
||||
_ => panic!("Encountered unsupported bevy_dioxus event `{event}`."),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_style_attributes(attributes: &[TemplateAttribute]) -> Style {
|
||||
let mut style = Style::default();
|
||||
for attribute in attributes {
|
||||
|
|
32
src/events.rs
Normal file
32
src/events.rs
Normal file
|
@ -0,0 +1,32 @@
|
|||
use bevy::ecs::{
|
||||
entity::Entity,
|
||||
event::{Events, ManualEventReader},
|
||||
system::Resource,
|
||||
};
|
||||
use bevy_mod_picking::events::{Click, Pointer};
|
||||
use dioxus::html::MouseData;
|
||||
use std::{any::Any, rc::Rc};
|
||||
|
||||
#[derive(Resource, Default)]
|
||||
pub struct EventReaders {
|
||||
clicks: ManualEventReader<Pointer<Click>>,
|
||||
}
|
||||
|
||||
impl EventReaders {
|
||||
pub fn get_dioxus_events(
|
||||
&mut self,
|
||||
clicks: &Events<Pointer<Click>>,
|
||||
) -> Vec<(Entity, &'static str, Rc<dyn Any>)> {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_supported_event(event: &str) -> bool {
|
||||
event == "click"
|
||||
}
|
11
src/lib.rs
11
src/lib.rs
|
@ -1,18 +1,20 @@
|
|||
mod apply_mutations;
|
||||
mod deferred_system;
|
||||
mod events;
|
||||
pub mod hooks;
|
||||
mod tick;
|
||||
|
||||
use self::{
|
||||
apply_mutations::{BevyTemplate, Event},
|
||||
apply_mutations::BevyTemplate,
|
||||
deferred_system::DeferredSystemRegistry,
|
||||
events::EventReaders,
|
||||
tick::{tick_dioxus_ui, VirtualDomUnsafe},
|
||||
};
|
||||
use bevy::{
|
||||
app::{App, Plugin, Update},
|
||||
ecs::{bundle::Bundle, component::Component, entity::Entity},
|
||||
ui::node_bundles::NodeBundle,
|
||||
utils::{HashMap, HashSet},
|
||||
utils::{EntityHashMap, HashMap},
|
||||
};
|
||||
use dioxus::core::{Element, ElementId, Scope};
|
||||
|
||||
|
@ -25,6 +27,7 @@ pub struct DioxusUiPlugin;
|
|||
impl Plugin for DioxusUiPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.init_resource::<DeferredSystemRegistry>()
|
||||
.init_resource::<EventReaders>()
|
||||
.add_systems(Update, tick_dioxus_ui);
|
||||
}
|
||||
}
|
||||
|
@ -40,7 +43,7 @@ pub struct DioxusUiRoot {
|
|||
virtual_dom: VirtualDomUnsafe,
|
||||
hierarchy: HashMap<(Entity, u8), Entity>,
|
||||
element_id_to_bevy_ui_entity: HashMap<ElementId, Entity>,
|
||||
event_listeners: HashSet<(Event, ElementId)>,
|
||||
bevy_ui_entity_to_element_id: EntityHashMap<Entity, ElementId>,
|
||||
templates: HashMap<String, BevyTemplate>,
|
||||
needs_rebuild: bool,
|
||||
}
|
||||
|
@ -51,7 +54,7 @@ impl DioxusUiRoot {
|
|||
virtual_dom: VirtualDomUnsafe::new(root_component),
|
||||
hierarchy: HashMap::new(),
|
||||
element_id_to_bevy_ui_entity: HashMap::new(),
|
||||
event_listeners: HashSet::new(),
|
||||
bevy_ui_entity_to_element_id: EntityHashMap::default(),
|
||||
templates: HashMap::new(),
|
||||
needs_rebuild: true,
|
||||
}
|
||||
|
|
24
src/tick.rs
24
src/tick.rs
|
@ -1,5 +1,6 @@
|
|||
use crate::{
|
||||
apply_mutations::apply_mutations, deferred_system::DeferredSystemRegistry, DioxusUiRoot,
|
||||
apply_mutations::apply_mutations, deferred_system::DeferredSystemRegistry,
|
||||
events::EventReaders, DioxusUiRoot,
|
||||
};
|
||||
use bevy::{
|
||||
ecs::{
|
||||
|
@ -11,11 +12,17 @@ use bevy::{
|
|||
utils::synccell::SyncCell,
|
||||
};
|
||||
use dioxus::core::{Element, Scope, ScopeState, VirtualDom};
|
||||
use std::{mem, sync::Arc};
|
||||
use std::{mem, rc::Rc, sync::Arc};
|
||||
|
||||
pub fn tick_dioxus_ui(world: &mut World) {
|
||||
let world_ptr: *mut World = world;
|
||||
let world_cell = world.as_unsafe_world_cell();
|
||||
let events = unsafe {
|
||||
world_cell
|
||||
.get_resource_mut::<EventReaders>()
|
||||
.unwrap()
|
||||
.get_dioxus_events(world_cell.get_resource().unwrap())
|
||||
};
|
||||
let mut command_queue = CommandQueue::default();
|
||||
let mut commands = Commands::new_from_entities(&mut command_queue, world_cell.entities());
|
||||
|
||||
|
@ -29,7 +36,7 @@ pub fn tick_dioxus_ui(world: &mut World) {
|
|||
virtual_dom,
|
||||
hierarchy,
|
||||
element_id_to_bevy_ui_entity,
|
||||
event_listeners,
|
||||
bevy_ui_entity_to_element_id,
|
||||
templates,
|
||||
needs_rebuild,
|
||||
} = &mut *dioxus_ui_root;
|
||||
|
@ -39,15 +46,18 @@ pub fn tick_dioxus_ui(world: &mut World) {
|
|||
.base_scope()
|
||||
.provide_context(EcsContext { world: world_ptr });
|
||||
|
||||
// TODO: Handle events from winit
|
||||
// virtual_dom.handle_event(todo!(), todo!(), todo!(), todo!());
|
||||
for (target, name, data) in &events {
|
||||
if let Some(target) = bevy_ui_entity_to_element_id.get(target) {
|
||||
virtual_dom.handle_event(name, Rc::clone(data), *target, true);
|
||||
}
|
||||
}
|
||||
|
||||
if *needs_rebuild {
|
||||
apply_mutations(
|
||||
virtual_dom.rebuild(),
|
||||
hierarchy,
|
||||
element_id_to_bevy_ui_entity,
|
||||
event_listeners,
|
||||
bevy_ui_entity_to_element_id,
|
||||
templates,
|
||||
root_entity,
|
||||
&mut commands,
|
||||
|
@ -59,7 +69,7 @@ pub fn tick_dioxus_ui(world: &mut World) {
|
|||
virtual_dom.render_immediate(),
|
||||
hierarchy,
|
||||
element_id_to_bevy_ui_entity,
|
||||
event_listeners,
|
||||
bevy_ui_entity_to_element_id,
|
||||
templates,
|
||||
root_entity,
|
||||
&mut commands,
|
||||
|
|
Loading…
Reference in a new issue