use core::fmt;
use std::{collections::HashMap, collections::HashSet, sync::Arc};
#[cfg(feature = "bevy")]
use bevy::ecs::component::Component;
use crate::grid::{
coordinate_system::CoordinateSystem,
grid::{Grid, GridData, NodeRef},
};
use crate::{GeneratorError, NodeIndex, NodeSetError};
use self::{
builder::{GeneratorBuilder, Unset},
internal_generator::{InternalGenerator, InternalGeneratorStatus},
model::{ModelIndex, ModelInstance, ModelRotation, ModelVariantIndex},
node_heuristic::NodeSelectionHeuristic,
observer::GenerationUpdate,
rules::{ModelInfo, ModelVariantRef, Rules},
};
pub mod builder;
pub mod model;
pub mod node_heuristic;
pub mod observer;
pub mod rules;
pub mod socket;
pub(crate) mod internal_generator;
#[derive(Default, Clone, Copy)]
pub enum ModelSelectionHeuristic {
#[default]
WeightedProbability,
}
#[derive(Default, Clone, Copy)]
pub enum RngMode {
Seeded(u64),
#[default]
RandomSeed,
}
#[derive(Default, Clone, Copy, Eq, PartialEq, Debug)]
pub enum GenerationStatus {
#[default]
Ongoing,
Done,
}
#[derive(Clone, Copy, Debug)]
pub struct GeneratedNode {
pub node_index: NodeIndex,
pub model_instance: ModelInstance,
}
#[derive(Clone, Copy, Debug)]
pub struct GenInfo {
pub try_count: u32,
}
enum NodeSetStatus {
AlreadySet,
CanBeSet,
}
type Collector<'a> = Option<&'a mut Vec<GeneratedNode>>;
#[cfg_attr(feature = "bevy", derive(Component))]
pub struct Generator<C: CoordinateSystem, G: Grid<C>> {
max_retry_count: u32,
initial_nodes: Vec<(NodeIndex, ModelVariantIndex)>,
internal: InternalGenerator<C, G>,
}
impl<C: CoordinateSystem, G: Grid<C>> Generator<C, G> {
pub fn builder() -> GeneratorBuilder<Unset, Unset, C, G> {
GeneratorBuilder::new()
}
fn create(
rules: Arc<Rules<C>>,
grid: G,
initial_nodes: Vec<(NodeIndex, ModelVariantIndex)>,
max_retry_count: u32,
node_selection_heuristic: NodeSelectionHeuristic,
model_selection_heuristic: ModelSelectionHeuristic,
rng_mode: RngMode,
observers: Vec<crossbeam_channel::Sender<GenerationUpdate>>,
border_zones: HashSet<(usize, usize)>,
collector: &mut Collector,
) -> Result<Self, NodeSetError> {
let mut generator = Self {
max_retry_count,
initial_nodes,
internal: InternalGenerator::new(
rules,
grid,
node_selection_heuristic,
model_selection_heuristic,
rng_mode,
observers,
border_zones,
),
};
match generator
.internal
.pregen(collector, &generator.initial_nodes)
{
Ok(_status) => Ok(generator),
Err(err) => Err(err),
}
}
pub fn max_retry_count(&self) -> u32 {
self.max_retry_count
}
pub fn set_max_retry_count(&mut self, max_retry_count: u32) {
self.max_retry_count = max_retry_count;
}
pub fn seed(&self) -> u64 {
self.internal.seed
}
pub fn grid(&self) -> &G {
&self.internal.grid
}
pub fn rules(&self) -> &Rules<C> {
&self.internal.rules
}
pub fn nodes_left(&self) -> usize {
self.internal.nodes_left_to_generate
}
pub fn to_grid_data(&self) -> Option<GridData<C, ModelInstance, G>> {
match self.internal.status {
InternalGeneratorStatus::Ongoing => None,
InternalGeneratorStatus::Failed(_) => None,
InternalGeneratorStatus::Done => Some(self.internal.to_grid_data()),
}
}
pub fn generate_grid(
&mut self,
) -> Result<(GenInfo, GridData<C, ModelInstance, G>), GeneratorError> {
let gen_info = self
.internal
.generate(self.max_retry_count, &self.initial_nodes)?;
Ok((gen_info, self.internal.to_grid_data()))
}
pub fn generate(&mut self) -> Result<GenInfo, GeneratorError> {
let gen_info = self
.internal
.generate(self.max_retry_count, &self.initial_nodes)?;
Ok(gen_info)
}
pub fn select_and_propagate(&mut self) -> Result<GenerationStatus, GeneratorError> {
self.internal.select_and_propagate(&mut None)
}
pub fn select_and_propagate_collected(
&mut self,
) -> Result<(GenerationStatus, Vec<GeneratedNode>), GeneratorError> {
let mut generated_nodes = Vec::new();
let status = self
.internal
.select_and_propagate(&mut Some(&mut generated_nodes))?;
Ok((status, generated_nodes))
}
pub fn set_and_propagate<N: NodeRef<C, G>, M: ModelVariantRef<C>>(
&mut self,
node_ref: N,
model_variant_ref: M,
memorized: bool,
) -> Result<GenerationStatus, NodeSetError> {
let node_index = node_ref.to_index(&self.internal.grid);
let model_variant_index = model_variant_ref.to_index(&self.internal.rules)?;
let status = self
.internal
.set_and_propagate(node_index, model_variant_index, &mut None)?;
if memorized {
self.initial_nodes.push((node_index, model_variant_index));
}
Ok(status)
}
pub fn set_and_propagate_collected<N: NodeRef<C, G>, M: ModelVariantRef<C>>(
&mut self,
node_ref: N,
model_variant_ref: M,
memorized: bool,
) -> Result<(GenerationStatus, Vec<GeneratedNode>), NodeSetError> {
let mut generated_nodes = Vec::new();
let node_index = node_ref.to_index(&self.internal.grid);
let model_variant_index = model_variant_ref.to_index(&self.internal.rules)?;
let status = self.internal.set_and_propagate(
node_index,
model_variant_index,
&mut Some(&mut generated_nodes),
)?;
if memorized {
self.initial_nodes.push((node_index, model_variant_index));
}
Ok((status, generated_nodes))
}
pub fn reinitialize(&mut self) -> GenerationStatus {
self.internal.reinitialize(&mut None, &self.initial_nodes)
}
pub fn reinitialize_collected(&mut self) -> (GenerationStatus, Vec<GeneratedNode>) {
let mut generated_nodes = Vec::new();
let res = self
.internal
.reinitialize(&mut Some(&mut generated_nodes), &self.initial_nodes);
(res, generated_nodes)
}
pub fn get_models_on(&self, node_index: NodeIndex) -> Vec<ModelInstance> {
let mut models = Vec::new();
if !self.internal.is_valid_node_index(node_index) {
return models;
}
for model_variant_index in self.internal.possible_model_indexes(node_index) {
models.push(self.internal.rules.model(model_variant_index).clone());
}
models
}
pub fn get_models_variations_on(&self, node_index: NodeIndex) -> (Vec<ModelVariations>, u32) {
let mut model_variations = Vec::new();
let mut total_models_count = 0;
if !self.internal.is_valid_node_index(node_index) {
return (model_variations, total_models_count);
}
let mut id_mapping = HashMap::new();
for model_variant_index in self.internal.possible_model_indexes(node_index) {
total_models_count += 1;
let model = self.internal.rules.model(model_variant_index);
let group_id = id_mapping
.entry(model.model_index)
.or_insert(model_variations.len());
if *group_id == model_variations.len() {
model_variations.push(ModelVariations {
index: model.model_index,
info: self.internal.rules.model_info(model_variant_index),
rotations: vec![model.rotation],
});
} else {
model_variations[*group_id].rotations.push(model.rotation);
}
}
(model_variations, total_models_count)
}
fn create_observer_queue(&mut self) -> crossbeam_channel::Receiver<GenerationUpdate> {
let (sender, receiver) = crossbeam_channel::unbounded();
self.internal.observers.push(sender);
receiver
}
}
#[derive(Debug, Clone)]
pub struct ModelVariations {
pub index: ModelIndex,
pub info: ModelInfo,
pub rotations: Vec<ModelRotation>,
}
impl fmt::Display for ModelVariations {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.rotations.len() == 1 {
write!(
f,
"id: {}, {}, rotation: {:?}",
self.index, self.info, self.rotations[0]
)
} else {
write!(
f,
"id: {}, {}, rotations: {:?}",
self.index, self.info, self.rotations
)
}
}
}