use crate::context::AudioContext;
use crate::node::label::InternedNodeLabel;
use crate::prelude::{FirewheelNode, MainBus, NodeLabel};
use bevy_ecs::prelude::*;
use bevy_platform::collections::HashMap;
use firewheel::node::NodeID;
#[cfg(debug_assertions)]
use core::panic::Location;
#[allow(clippy::module_inception)]
mod connect;
mod disconnect;
pub use connect::*;
pub use disconnect::*;
#[derive(NodeLabel, Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "reflect", derive(bevy_reflect::Reflect))]
pub struct AudioGraphInput;
#[derive(NodeLabel, Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "reflect", derive(bevy_reflect::Reflect))]
pub struct AudioGraphOutput;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum EdgeTarget {
Label(InternedNodeLabel),
Entity(Entity),
Node(NodeID),
}
#[derive(Debug, Clone)]
#[non_exhaustive]
pub struct PendingEdge {
pub target: EdgeTarget,
pub ports: Option<Vec<(u32, u32)>>,
#[cfg(debug_assertions)]
pub(crate) origin: &'static Location<'static>,
}
impl PendingEdge {
#[cfg_attr(debug_assertions, track_caller)]
pub fn new(target: impl Into<EdgeTarget>, ports: Option<Vec<(u32, u32)>>) -> Self {
Self {
target: target.into(),
ports,
#[cfg(debug_assertions)]
origin: Location::caller(),
}
}
fn new_with_location(
target: impl Into<EdgeTarget>,
ports: Option<Vec<(u32, u32)>>,
#[cfg(debug_assertions)] location: &'static Location<'static>,
) -> Self {
Self {
target: target.into(),
ports,
#[cfg(debug_assertions)]
origin: location,
}
}
}
impl From<NodeID> for EdgeTarget {
fn from(value: NodeID) -> Self {
Self::Node(value)
}
}
impl<T> From<T> for EdgeTarget
where
T: NodeLabel,
{
fn from(value: T) -> Self {
Self::Label(value.intern())
}
}
impl From<Entity> for EdgeTarget {
fn from(value: Entity) -> Self {
Self::Entity(value)
}
}
const DEFAULT_CONNECTION: &[(u32, u32)] = &[(0, 0), (1, 1)];
#[derive(Default, Debug, Resource)]
pub struct NodeMap(HashMap<InternedNodeLabel, Entity>);
impl core::ops::Deref for NodeMap {
type Target = HashMap<InternedNodeLabel, Entity>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl core::ops::DerefMut for NodeMap {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
pub(crate) fn auto_connect(
nodes: Query<(Entity, &FirewheelNode), Without<PendingConnections>>,
mut context: ResMut<AudioContext>,
mut commands: Commands,
) {
if nodes.iter().len() == 0 {
return;
}
context.with(|context| {
for (entity, node) in nodes.iter() {
let Some(info) = context.node_info(node.0) else {
continue;
};
let outputs = info.info.channel_config.num_outputs.get();
if outputs == 0 {
continue;
}
commands.entity(entity).connect(MainBus);
}
});
}