use bevy_ecs::prelude::Entity;
use crate::{
AddBranchToForkClone, AddOperation, Builder, Chain, ForkClone, ForkTargetStorage,
SingleInputStorage, StreamPack, UnusedTarget,
};
#[derive(Debug)]
#[must_use]
pub struct Node<Request, Response, Streams: StreamPack = ()> {
pub input: InputSlot<Request>,
pub output: Output<Response>,
pub streams: Streams::StreamOutputPack,
}
#[must_use]
pub struct InputSlot<Request> {
scope: Entity,
source: Entity,
_ignore: std::marker::PhantomData<fn(Request)>,
}
impl<T> Clone for InputSlot<T> {
fn clone(&self) -> Self {
*self
}
}
impl<T> Copy for InputSlot<T> {}
impl<Request> std::fmt::Debug for InputSlot<Request> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct(format!("Input<{}>", std::any::type_name::<Request>()).as_str())
.field("scope", &self.scope)
.field("source", &self.source)
.finish()
}
}
impl<Request> InputSlot<Request> {
pub fn id(&self) -> Entity {
self.source
}
pub fn scope(&self) -> Entity {
self.scope
}
pub(crate) fn new(scope: Entity, source: Entity) -> Self {
Self {
scope,
source,
_ignore: Default::default(),
}
}
}
#[must_use]
pub struct Output<Response> {
scope: Entity,
target: Entity,
_ignore: std::marker::PhantomData<fn(Response)>,
}
impl<Response> std::fmt::Debug for Output<Response> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct(format!("Output<{}>", std::any::type_name::<Response>()).as_str())
.field("scope", &self.scope)
.field("target", &self.target)
.finish()
}
}
impl<Response: 'static + Send + Sync> Output<Response> {
pub fn chain<'w, 's, 'a, 'b>(
self,
builder: &'b mut Builder<'w, 's, 'a>,
) -> Chain<'w, 's, 'a, 'b, Response>
where
Response: 'static + Send + Sync,
{
assert_eq!(self.scope, builder.scope);
Chain::new(self.target, builder)
}
pub fn fork_clone(self, builder: &mut Builder) -> ForkCloneOutput<Response>
where
Response: Clone,
{
assert_eq!(self.scope, builder.scope);
builder.commands.add(AddOperation::new(
Some(self.scope),
self.target,
ForkClone::<Response>::new(ForkTargetStorage::new()),
));
ForkCloneOutput::new(self.scope, self.target)
}
pub fn id(&self) -> Entity {
self.target
}
pub fn scope(&self) -> Entity {
self.scope
}
pub(crate) fn new(scope: Entity, target: Entity) -> Self {
Self {
scope,
target,
_ignore: Default::default(),
}
}
}
#[must_use]
pub struct ForkCloneOutput<Response> {
scope: Entity,
source: Entity,
_ignore: std::marker::PhantomData<fn(Response)>,
}
impl<Response: 'static + Send + Sync> ForkCloneOutput<Response> {
pub fn clone_output(&self, builder: &mut Builder) -> Output<Response> {
assert_eq!(self.scope, builder.scope);
let target = builder
.commands
.spawn((SingleInputStorage::new(self.id()), UnusedTarget))
.id();
builder.commands.add(AddBranchToForkClone {
source: self.source,
target,
});
Output::new(self.scope, target)
}
pub fn clone_chain<'w, 's, 'a, 'b>(
&self,
builder: &'b mut Builder<'w, 's, 'a>,
) -> Chain<'w, 's, 'a, 'b, Response> {
let output = self.clone_output(builder);
output.chain(builder)
}
pub fn id(&self) -> Entity {
self.source
}
pub fn scope(&self) -> Entity {
self.scope
}
pub(crate) fn new(scope: Entity, source: Entity) -> Self {
Self {
scope,
source,
_ignore: Default::default(),
}
}
}