Add use_state_send()
This commit is contained in:
parent
5a4b1d60e9
commit
9776f179f9
|
@ -28,7 +28,7 @@ fn main() {
|
|||
#[component]
|
||||
fn Editor(cx: Scope) -> Element {
|
||||
// TODO: When selected entity is despawned, need to reset this to None
|
||||
let selected_entity = use_state(cx, || Option::<Entity>::None);
|
||||
let selected_entity = use_state_send(cx, || Option::<Entity>::None);
|
||||
|
||||
render! {
|
||||
node {
|
||||
|
@ -42,19 +42,23 @@ fn Editor(cx: Scope) -> Element {
|
|||
}
|
||||
|
||||
#[component]
|
||||
fn SceneTree<'a>(cx: Scope, selected_entity: &'a UseState<Option<Entity>>) -> Element {
|
||||
fn SceneTree<'a>(cx: Scope, selected_entity: &'a UseStateSend<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);
|
||||
|
||||
let spawn_entity = use_system(cx, |world: &mut World| {
|
||||
world.spawn_empty();
|
||||
let spawn_entity = use_system(cx, {
|
||||
let selected_entity = (*selected_entity).clone();
|
||||
move |world: &mut World| {
|
||||
let new_entity = world.spawn_empty();
|
||||
selected_entity.write(Some(new_entity.id()));
|
||||
}
|
||||
});
|
||||
|
||||
render! {
|
||||
node {
|
||||
onclick: move |_| selected_entity.set(None),
|
||||
onclick: move |_| selected_entity.write(None),
|
||||
flex_direction: "column",
|
||||
if entities.is_empty() {
|
||||
rsx! { "No entities exist" }
|
||||
|
@ -63,16 +67,16 @@ fn SceneTree<'a>(cx: Scope, selected_entity: &'a UseState<Option<Entity>>) -> El
|
|||
for (entity, name) in entities {
|
||||
Button {
|
||||
onclick: move |event: Event<PointerButton>| if *event.data == PointerButton::Primary {
|
||||
if Some(entity) == ***selected_entity {
|
||||
selected_entity.set(None);
|
||||
if Some(entity) == *selected_entity.read() {
|
||||
selected_entity.write(None);
|
||||
} else {
|
||||
selected_entity.set(Some(entity));
|
||||
selected_entity.write(Some(entity));
|
||||
}
|
||||
event.stop_propagation();
|
||||
},
|
||||
base_color: if Some(entity) == ***selected_entity { Some(VIOLET_700) } else { None },
|
||||
click_color: if Some(entity) == ***selected_entity { Some(VIOLET_400) } else { None },
|
||||
hover_color: if Some(entity) == ***selected_entity { Some(VIOLET_500) } else { None },
|
||||
base_color: if Some(entity) == *selected_entity.read() { Some(VIOLET_700) } else { None },
|
||||
click_color: if Some(entity) == *selected_entity.read() { Some(VIOLET_400) } else { None },
|
||||
hover_color: if Some(entity) == *selected_entity.read() { Some(VIOLET_500) } else { None },
|
||||
match name.name {
|
||||
Some(name) => format!("{name}"),
|
||||
_ => format!("Entity ({:?})", name.entity)
|
||||
|
@ -93,11 +97,11 @@ fn SceneTree<'a>(cx: Scope, selected_entity: &'a UseState<Option<Entity>>) -> El
|
|||
}
|
||||
|
||||
#[component]
|
||||
fn EntityInspector<'a>(cx: Scope, selected_entity: &'a UseState<Option<Entity>>) -> Element {
|
||||
fn EntityInspector<'a>(cx: Scope, selected_entity: &'a UseStateSend<Option<Entity>>) -> Element {
|
||||
let world = use_world(cx);
|
||||
let type_registry = use_resource::<AppTypeRegistry>(cx).read();
|
||||
let components = selected_entity
|
||||
.get()
|
||||
.read()
|
||||
.map(|selected_entity| {
|
||||
let entity_ref = world.get_entity(selected_entity).unwrap();
|
||||
let mut components = entity_ref
|
||||
|
@ -118,7 +122,7 @@ fn EntityInspector<'a>(cx: Scope, selected_entity: &'a UseState<Option<Entity>>)
|
|||
.unwrap_or_default();
|
||||
|
||||
render! {
|
||||
if selected_entity.is_none() {
|
||||
if selected_entity.read().is_none() {
|
||||
rsx! {
|
||||
node {
|
||||
margin: "8",
|
||||
|
|
|
@ -9,6 +9,7 @@ mod events;
|
|||
mod hot_reload;
|
||||
mod parse_attributes;
|
||||
mod tick;
|
||||
mod use_state_send;
|
||||
|
||||
use self::{
|
||||
apply_mutations::BevyTemplate,
|
||||
|
@ -29,6 +30,7 @@ use dioxus::core::{Element, ElementId, Scope, VirtualDom};
|
|||
pub mod prelude {
|
||||
pub use super::ecs_hooks::*;
|
||||
pub use super::elements::*;
|
||||
pub use super::use_state_send::*;
|
||||
pub use super::{DioxusUiBundle, DioxusUiPlugin, DioxusUiRoot};
|
||||
pub use bevy_mod_picking::pointer::PointerButton;
|
||||
pub use dioxus;
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
// https://github.com/DioxusLabs/dioxus-std/blob/8db5b1e8a3b8c81f3174a0c9cb951c87058289ca/std/src/utils/rw/use_rw.rs
|
||||
|
||||
use dioxus::prelude::ScopeState;
|
||||
use std::sync::{Arc, RwLock, RwLockReadGuard};
|
||||
|
||||
pub fn use_state_send<T: Send + Sync + 'static>(
|
||||
cx: &ScopeState,
|
||||
init_rw: impl FnOnce() -> T,
|
||||
) -> &mut UseStateSend<T> {
|
||||
let hook = cx.use_hook(|| UseStateSend {
|
||||
update: cx.schedule_update(),
|
||||
value: Arc::new(RwLock::new(init_rw())),
|
||||
});
|
||||
|
||||
hook
|
||||
}
|
||||
|
||||
pub struct UseStateSend<T> {
|
||||
update: Arc<dyn Fn() + Send + Sync + 'static>,
|
||||
value: Arc<RwLock<T>>,
|
||||
}
|
||||
|
||||
impl<T> Clone for UseStateSend<T> {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
update: self.update.clone(),
|
||||
value: self.value.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> UseStateSend<T> {
|
||||
pub fn read(&self) -> RwLockReadGuard<'_, T> {
|
||||
self.value.read().expect("Lock poisoned")
|
||||
}
|
||||
|
||||
pub fn write(&self, new_value: T) {
|
||||
let mut lock = self.value.write().expect("Lock poisoned");
|
||||
*lock = new_value;
|
||||
self.needs_update();
|
||||
}
|
||||
|
||||
pub fn needs_update(&self) {
|
||||
(self.update)()
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue