use crate::effect_node::EffectNodeProps;
use crate::graph::{Graph, NodeId};
use crate::image_node::ImageNodeProps;
pub use crate::mir::AudioLevels;
#[cfg(feature = "mpv")]
use crate::movie_node::MovieNodeProps;
use crate::placeholder_node::PlaceholderNodeProps;
use crate::projection_mapped_output_node::ProjectionMappedOutputNodeProps;
use crate::screen_output_node::ScreenOutputNodeProps;
use crate::ui_bg_node::UiBgNodeProps;
use serde::{Deserialize, Serialize};
use std::collections::{HashMap, HashSet};
#[derive(Debug, Clone, Serialize, Deserialize, derive_more::TryInto)]
#[serde(tag = "type")]
#[try_into(owned, ref, ref_mut)]
pub enum NodeProps {
EffectNode(EffectNodeProps),
ScreenOutputNode(ScreenOutputNodeProps),
UiBgNode(UiBgNodeProps),
ImageNode(ImageNodeProps),
PlaceholderNode(PlaceholderNodeProps),
#[cfg(feature = "mpv")]
MovieNode(MovieNodeProps),
ProjectionMappedOutputNode(ProjectionMappedOutputNodeProps),
}
pub struct CommonNodeProps {
pub input_count: Option<u32>,
}
impl From<&NodeProps> for CommonNodeProps {
fn from(props: &NodeProps) -> Self {
match props {
NodeProps::EffectNode(p) => p.into(),
NodeProps::ScreenOutputNode(p) => p.into(),
NodeProps::UiBgNode(p) => p.into(),
NodeProps::ImageNode(p) => p.into(),
NodeProps::PlaceholderNode(p) => p.into(),
#[cfg(feature = "mpv")]
NodeProps::MovieNode(p) => p.into(),
NodeProps::ProjectionMappedOutputNode(p) => p.into(),
}
}
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct Props {
pub graph: Graph,
pub node_props: HashMap<NodeId, NodeProps>,
#[serde(default)]
pub time: f32,
#[serde(default)]
pub dt: f32,
#[serde(default)]
pub audio: AudioLevels,
}
impl Props {
pub fn fix(&mut self) {
let graph_nodes_to_remove: HashSet<NodeId> = self
.graph
.nodes
.iter()
.filter(|n| !self.node_props.contains_key(n))
.cloned()
.collect();
self.graph.delete_nodes(&graph_nodes_to_remove);
let nodes_without_props = graph_nodes_to_remove.len();
if nodes_without_props > 0 {
println!("Removed {} nodes without props", nodes_without_props);
}
let save_nodes: HashSet<NodeId> = self.graph.nodes.iter().cloned().collect();
let orig_nodes_len = self.graph.nodes.len();
self.node_props.retain(|id, _| save_nodes.contains(id));
let props_not_in_graph = orig_nodes_len - self.node_props.len();
if props_not_in_graph > 0 {
println!(
"Removed {} node props that weren't in the graph",
props_not_in_graph
);
}
let orig_edges_len = self.graph.edges.len();
self.graph.edges.retain(|edge| {
save_nodes.contains(&edge.from)
&& save_nodes.contains(&edge.to)
&& match CommonNodeProps::from(self.node_props.get(&edge.to).unwrap()).input_count {
None => true, Some(count) => edge.input < count,
}
});
let edges_to_nonexistant_inputs = orig_edges_len - self.graph.edges.len();
if edges_to_nonexistant_inputs > 0 {
println!(
"Removed {} edges to nonexistant inputs",
edges_to_nonexistant_inputs
);
}
}
}