diff --git a/rust-pvz-genetics/src/genetics/manipulations.rs b/rust-pvz-genetics/src/genetics/manipulations.rs index b341635..c38c418 100644 --- a/rust-pvz-genetics/src/genetics/manipulations.rs +++ b/rust-pvz-genetics/src/genetics/manipulations.rs @@ -30,7 +30,7 @@ impl PairGenomeModificator { generator: StdRng::seed_from_u64(seed) }; } - pub fn allelic_crossingover(mut self,chance: Option) -> (Genome, Genome) { + pub fn allelic_crossingover(&mut self,chance: Option) -> (Genome, Genome) { let amount: usize = *[self.genome_a.graph.len(),self.genome_b.graph.len()].iter().min().unwrap_or(&0); for i in 0..amount { @@ -39,9 +39,9 @@ impl PairGenomeModificator { swap(&mut self.genome_a.graph[i].0, &mut self.genome_b.graph[i].0); } - (self.genome_a,self.genome_b) + (self.genome_a.clone(),self.genome_b.clone()) } - pub fn categoric_crossingover(mut self, chance: Option) -> (Genome,Genome) { + pub fn categoric_crossingover(&mut self, chance: Option) -> (Genome,Genome) { let threshold = chance.unwrap_or(2).max(2); let mut categories_a: HashMap> = HashMap::new(); @@ -68,13 +68,13 @@ impl PairGenomeModificator { self.genome_a.graph[fi].0 = gene_b; self.genome_b.graph[si].0 = gene_a; } - (self.genome_a,self.genome_b) + (self.genome_a.clone(),self.genome_b.clone()) } - pub fn combine(mut self) -> (Genome,Genome){ - (self.genome_a,self.genome_b) + pub fn combine(&mut self) -> (Genome,Genome){ + (self.genome_a.clone(),self.genome_b.clone()) } - pub fn cancel(self) -> (Genome,Genome) { - (self.genome_a,self.genome_b) + pub fn cancel(&self) -> (Genome,Genome) { + (self.genome_a.clone(),self.genome_b.clone()) } } diff --git a/rust-pvz-genetics/src/godot_wrapper/copy_modifiers.rs b/rust-pvz-genetics/src/godot_wrapper/copy_modifiers.rs new file mode 100644 index 0000000..e69de29 diff --git a/rust-pvz-genetics/src/godot_wrapper/godot_genome.rs b/rust-pvz-genetics/src/godot_wrapper/godot_genome.rs index a7cbd6a..ffcfd58 100644 --- a/rust-pvz-genetics/src/godot_wrapper/godot_genome.rs +++ b/rust-pvz-genetics/src/godot_wrapper/godot_genome.rs @@ -44,8 +44,18 @@ impl INode for GodotGenome { } +#[godot_api] +impl GodotGenome { + #[signal] + pub fn genome_updated(); +} + impl GodotGenome { pub fn get_genome(&self) -> Option { self.genome.clone() } + pub fn set_genome(&mut self, genome: Genome) { + self.genome = Some(genome); + self.signals().genome_updated().emit(); + } } diff --git a/rust-pvz-genetics/src/godot_wrapper/mod.rs b/rust-pvz-genetics/src/godot_wrapper/mod.rs index 515dca2..aaf0dd2 100644 --- a/rust-pvz-genetics/src/godot_wrapper/mod.rs +++ b/rust-pvz-genetics/src/godot_wrapper/mod.rs @@ -1,2 +1,4 @@ pub mod godot_genome; pub mod plant; +pub mod reference_modifiers; +pub mod copy_modifiers; diff --git a/rust-pvz-genetics/src/godot_wrapper/plant.rs b/rust-pvz-genetics/src/godot_wrapper/plant.rs index 1f7b47a..ef2306d 100644 --- a/rust-pvz-genetics/src/godot_wrapper/plant.rs +++ b/rust-pvz-genetics/src/godot_wrapper/plant.rs @@ -15,6 +15,50 @@ pub struct Plant { impl INode2D for Plant { fn ready(&mut self) { let Some(godot_genome) = self.genome.clone() else { return; }; + + godot_genome.signals().genome_updated().connect_other(&*self, Self::restructure); + + let Some(genome)= godot_genome.bind().get_genome() else { return; }; + + let mut children = { + let mut result = Vec::new(); + for i in 0..genome.graph.len() { + result.push((Sprite2D::new_alloc(),&genome.graph[i])); + } + result + }; + + for i in 0..genome.graph.len() { + children[i].0.set_name(&genome.graph[i].0.place.to_string()); + // Setting up genes + if let Some(sprite) = genome.graph[i].0.sprite.clone() { + children[i].0.set_texture(&load::(&("res://assets/sprites/".to_string() + &sprite))); + } + + // Setting up children + for edge in &genome.graph[i].1 { + let mut gene_sprite = children[*edge].0.clone(); + + gene_sprite.set_position((children[i].1.0.get_child_position)(children[*edge].1.0.place.clone())); + + children[i].0.add_child(&gene_sprite); + } + } + + self.base_mut().add_child(&children[0].0); + } + +} + +#[godot_api] +impl Plant { + #[func] + fn restructure(&mut self) { + if let Some(mut child) = self.base().get_child(0) { + child.queue_free(); + } + + let Some(godot_genome) = self.genome.clone() else { return; }; let Some(genome)= godot_genome.bind().get_genome() else { return; }; diff --git a/rust-pvz-genetics/src/godot_wrapper/reference_modifiers.rs b/rust-pvz-genetics/src/godot_wrapper/reference_modifiers.rs new file mode 100644 index 0000000..4df5341 --- /dev/null +++ b/rust-pvz-genetics/src/godot_wrapper/reference_modifiers.rs @@ -0,0 +1,57 @@ +use godot::prelude::*; +use crate::{genetics::manipulations::{PairGenomeModificator,SingleGenomeModificator}, godot_wrapper::godot_genome::GodotGenome}; + +#[derive(GodotClass)] +#[class(base=Node)] +pub struct ReferencePairModifier { + #[export] + godot_genome_a: Option>, + #[export] + godot_genome_b: Option>, + modifier: Option, + base: Base, +} + +#[godot_api] +impl INode for ReferencePairModifier{ + fn init(base: Base) -> Self { + Self { + godot_genome_a: None, + godot_genome_b: None, + modifier: None, + base + } + } + fn ready(&mut self) { + if self.godot_genome_a.is_none() || self.godot_genome_b.is_none() { + godot_warn!("One of the genomes is not specified!"); + return; + } + let (genome_a, genome_b) = (self.godot_genome_a.as_ref().unwrap().bind().get_genome(),self.godot_genome_b.as_ref().unwrap().bind().get_genome()); + + if genome_a.is_none() || genome_b.is_none() { + godot_warn!("One of genomes does not contain a genome!"); + return; + } + + self.modifier = Some(PairGenomeModificator::new(genome_a.unwrap(),genome_b.unwrap())); + } + +} + +#[godot_api] +impl ReferencePairModifier { + #[func] + fn allelic_crossingover(&mut self) { + if let Some(pair) = self.modifier.as_mut() { + let (genome_a,genome_b) = pair.allelic_crossingover(None); + self.godot_genome_a.as_mut().unwrap().bind_mut().set_genome(genome_a); + self.godot_genome_b.as_mut().unwrap().bind_mut().set_genome(genome_b); + godot_print!("Kukayan"); + } + else { + godot_error!("Modifier is not initialized!"); + } + } +} +