2023-12-27 19:19:02 +00:00
|
|
|
use crate::UiContext;
|
2023-12-13 00:22:54 +00:00
|
|
|
use bevy::{
|
|
|
|
ecs::{
|
|
|
|
component::ComponentId,
|
2023-12-27 19:56:36 +00:00
|
|
|
event::{Event, EventIterator, Events, ManualEventReader},
|
2024-03-25 02:38:08 +00:00
|
|
|
query::{QueryData, QueryFilter, ReadOnlyQueryData, WorldQuery},
|
2024-01-21 07:12:14 +00:00
|
|
|
system::{Query, Resource, SystemState},
|
|
|
|
world::World,
|
2023-12-13 00:22:54 +00:00
|
|
|
},
|
|
|
|
utils::{HashMap, HashSet},
|
|
|
|
};
|
|
|
|
use dioxus::{
|
2023-12-23 05:36:05 +00:00
|
|
|
core::{ScopeId, ScopeState},
|
|
|
|
hooks::use_on_destroy,
|
2023-12-07 02:46:50 +00:00
|
|
|
};
|
2023-12-28 07:04:45 +00:00
|
|
|
use std::any::TypeId;
|
2023-12-07 02:46:50 +00:00
|
|
|
|
2023-12-17 04:19:41 +00:00
|
|
|
#[derive(Default)]
|
2023-12-13 00:22:54 +00:00
|
|
|
pub(crate) struct EcsSubscriptions {
|
|
|
|
pub resources: Box<HashMap<ComponentId, HashSet<ScopeId>>>,
|
2024-01-02 21:52:18 +00:00
|
|
|
#[allow(clippy::type_complexity)]
|
2023-12-28 07:04:45 +00:00
|
|
|
pub events: Box<HashMap<TypeId, (Box<dyn Fn(&World) -> bool>, HashSet<ScopeId>)>>,
|
2023-12-13 00:22:54 +00:00
|
|
|
pub world_and_queries: Box<HashSet<ScopeId>>,
|
|
|
|
}
|
2023-12-07 21:51:55 +00:00
|
|
|
|
2023-12-15 20:36:53 +00:00
|
|
|
#[derive(Clone)]
|
|
|
|
pub(crate) struct EcsContext {
|
|
|
|
pub world: *mut World,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl EcsContext {
|
2024-01-02 21:47:21 +00:00
|
|
|
#[allow(clippy::mut_from_ref)]
|
2023-12-27 19:19:02 +00:00
|
|
|
pub fn get_world(cx: &ScopeState) -> &mut World {
|
2023-12-15 20:36:53 +00:00
|
|
|
unsafe {
|
|
|
|
&mut *cx
|
|
|
|
.consume_context::<EcsContext>()
|
|
|
|
.expect("Must be used from a dioxus component within a DioxusUiRoot bevy component")
|
|
|
|
.world
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-02 21:49:15 +00:00
|
|
|
pub fn use_world(cx: &ScopeState) -> &World {
|
2023-12-13 00:22:54 +00:00
|
|
|
let world = EcsContext::get_world(cx);
|
|
|
|
|
|
|
|
let scope_id = cx.scope_id();
|
|
|
|
let subscription_manager = *cx.use_hook(|| {
|
2023-12-17 04:19:41 +00:00
|
|
|
let subscription_manager = &mut world
|
|
|
|
.non_send_resource_mut::<UiContext>()
|
|
|
|
.subscriptions
|
|
|
|
.world_and_queries;
|
2023-12-13 00:22:54 +00:00
|
|
|
subscription_manager.insert(scope_id);
|
|
|
|
Box::as_mut(subscription_manager) as *mut HashSet<ScopeId>
|
|
|
|
});
|
|
|
|
use_on_destroy(cx, move || {
|
|
|
|
unsafe { &mut *subscription_manager }.remove(&scope_id);
|
|
|
|
});
|
|
|
|
|
|
|
|
world
|
2023-12-07 02:46:50 +00:00
|
|
|
}
|
|
|
|
|
2024-01-02 21:49:15 +00:00
|
|
|
pub fn use_resource<T: Resource>(cx: &ScopeState) -> &T {
|
2023-12-13 00:22:54 +00:00
|
|
|
let world = EcsContext::get_world(cx);
|
|
|
|
|
|
|
|
let resource_id = world.components().resource_id::<T>().unwrap();
|
|
|
|
let scope_id = cx.scope_id();
|
|
|
|
let subscription_manager = *cx.use_hook(|| {
|
2023-12-17 04:19:41 +00:00
|
|
|
let subscription_manager = &mut world
|
|
|
|
.non_send_resource_mut::<UiContext>()
|
|
|
|
.subscriptions
|
|
|
|
.resources;
|
2023-12-13 00:22:54 +00:00
|
|
|
subscription_manager
|
|
|
|
.entry(resource_id)
|
|
|
|
.or_default()
|
|
|
|
.insert(scope_id);
|
|
|
|
Box::as_mut(subscription_manager) as *mut HashMap<ComponentId, HashSet<ScopeId>>
|
|
|
|
});
|
|
|
|
use_on_destroy(cx, move || {
|
|
|
|
let subscription_manager = &mut unsafe { &mut *subscription_manager };
|
|
|
|
let resource_subscriptions = subscription_manager.get_mut(&resource_id).unwrap();
|
|
|
|
resource_subscriptions.remove(&scope_id);
|
|
|
|
if resource_subscriptions.is_empty() {
|
|
|
|
subscription_manager.remove(&resource_id);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
world.resource()
|
2023-12-10 23:53:50 +00:00
|
|
|
}
|
2023-12-07 02:46:50 +00:00
|
|
|
|
2024-01-02 21:49:15 +00:00
|
|
|
pub fn use_query<Q>(cx: &ScopeState) -> UseQuery<'_, Q, ()>
|
2023-12-10 23:53:50 +00:00
|
|
|
where
|
2024-03-25 02:38:08 +00:00
|
|
|
Q: ReadOnlyQueryData,
|
2023-12-10 23:53:50 +00:00
|
|
|
{
|
|
|
|
use_query_filtered(cx)
|
|
|
|
}
|
2023-12-07 21:51:55 +00:00
|
|
|
|
2024-01-02 21:49:15 +00:00
|
|
|
pub fn use_query_filtered<Q, F>(cx: &ScopeState) -> UseQuery<'_, Q, F>
|
2023-12-10 23:53:50 +00:00
|
|
|
where
|
2024-03-25 02:38:08 +00:00
|
|
|
Q: ReadOnlyQueryData,
|
|
|
|
F: ReadOnlyQueryData + QueryFilter,
|
2023-12-10 23:53:50 +00:00
|
|
|
{
|
|
|
|
let world = EcsContext::get_world(cx);
|
2023-12-13 00:22:54 +00:00
|
|
|
|
|
|
|
let scope_id = cx.scope_id();
|
|
|
|
let subscription_manager = *cx.use_hook(|| {
|
2023-12-17 04:19:41 +00:00
|
|
|
let subscription_manager = &mut world
|
|
|
|
.non_send_resource_mut::<UiContext>()
|
|
|
|
.subscriptions
|
|
|
|
.world_and_queries;
|
2023-12-13 00:22:54 +00:00
|
|
|
subscription_manager.insert(scope_id);
|
|
|
|
Box::as_mut(subscription_manager) as *mut HashSet<ScopeId>
|
|
|
|
});
|
|
|
|
use_on_destroy(cx, move || {
|
|
|
|
unsafe { &mut *subscription_manager }.remove(&scope_id);
|
|
|
|
});
|
|
|
|
|
2023-12-27 19:24:36 +00:00
|
|
|
UseQuery {
|
2024-01-21 07:12:14 +00:00
|
|
|
system_state: SystemState::new(world),
|
|
|
|
world_ref: world,
|
2023-12-07 21:51:55 +00:00
|
|
|
}
|
2023-12-10 23:53:50 +00:00
|
|
|
}
|
2023-12-07 21:51:55 +00:00
|
|
|
|
2024-01-02 21:49:15 +00:00
|
|
|
pub fn use_event_reader<E: Event>(cx: &ScopeState) -> EventIterator<'_, E> {
|
2023-12-28 07:04:45 +00:00
|
|
|
// TODO: Register the subscription
|
|
|
|
|
2024-01-02 21:53:45 +00:00
|
|
|
let event_reader = cx.use_hook(ManualEventReader::default);
|
2023-12-27 19:56:36 +00:00
|
|
|
let events = EcsContext::get_world(cx).resource::<Events<E>>();
|
2023-12-28 07:04:45 +00:00
|
|
|
event_reader.read(events)
|
2023-12-27 19:56:36 +00:00
|
|
|
}
|
|
|
|
|
2024-03-25 02:38:08 +00:00
|
|
|
pub struct UseQuery<'a, Q: ReadOnlyQueryData + 'static, F: ReadOnlyQueryData + QueryFilter + 'static> {
|
2024-01-21 07:12:14 +00:00
|
|
|
system_state: SystemState<Query<'static, 'static, Q, F>>,
|
|
|
|
world_ref: &'a World,
|
2023-12-07 21:51:55 +00:00
|
|
|
}
|
|
|
|
|
2023-12-27 19:24:36 +00:00
|
|
|
impl<'a, Q, F> UseQuery<'a, Q, F>
|
2023-12-07 21:51:55 +00:00
|
|
|
where
|
2024-03-25 02:38:08 +00:00
|
|
|
Q: ReadOnlyQueryData,
|
|
|
|
F: ReadOnlyQueryData + QueryFilter,
|
2023-12-07 21:51:55 +00:00
|
|
|
{
|
2024-01-21 07:12:14 +00:00
|
|
|
pub fn query(&mut self) -> Query<Q, F> {
|
|
|
|
self.system_state.get(self.world_ref)
|
2023-12-07 21:51:55 +00:00
|
|
|
}
|
|
|
|
}
|