From fabc03b701b0210a40f616021429fd3b06a7bdf4 Mon Sep 17 00:00:00 2001 From: Mikhail Mitrofanov Date: Sat, 27 Jun 2026 10:37:45 +0300 Subject: [PATCH] Change table type of subplate_automation --- src/basic.rs | 18 +++++ src/hex_table.rs | 41 +++++++++--- src/main.rs | 1 + src/plate_automation.rs | 5 +- src/subplate_automation.rs | 130 +++++++++++++++++++++++++++++-------- 5 files changed, 155 insertions(+), 40 deletions(-) diff --git a/src/basic.rs b/src/basic.rs index 9444126..834030b 100644 --- a/src/basic.rs +++ b/src/basic.rs @@ -134,6 +134,24 @@ impl IntoImage for Table { } } +impl IntoImage for Table { + fn get_image_data(&self) -> Vec { + let mut data: Vec = vec![0; self.side * self.side * 4]; + self.data + .iter() + .zip((0..self.data.len()).collect::>()) + .for_each(|(color, idx)| { + let idx = idx * 4; + + data[idx] = *color; + data[idx + 1] = *color; + data[idx + 2] = *color; + data[idx + 3] = if *color != 0 { 255 } else { 0 }; + }); + data + } +} + impl Index for Table { type Output = T; diff --git a/src/hex_table.rs b/src/hex_table.rs index 3ead781..8c58441 100644 --- a/src/hex_table.rs +++ b/src/hex_table.rs @@ -1,16 +1,15 @@ pub struct HexTable { len: usize, + scale: f32, } const VERTICAL_OFFSET: f32 = 0.866025; impl HexTable { - pub fn new(len: usize) -> Self{ - Self{ - len - } + pub fn new(len: usize, scale: f32) -> Self { + Self { len, scale } } - pub fn calculate(&self) -> Vec<(f32, f32)>{ + pub fn calculate(&self) -> Vec<(f32, f32)> { let mut vec = Vec::with_capacity(self.len * self.len); let mut index = 0; loop { @@ -18,14 +17,38 @@ impl HexTable { let y = index / self.len; let y_point = y as f32 * VERTICAL_OFFSET; - if y_point as usize > self.len { + if y_point as usize >= self.len { break; } let mut x_point = x as f32; - if y % 2 == 1 { x_point += 0.5; } - vec.push((x_point, y_point)); + if y % 2 == 1 { + x_point += 0.5; + } + vec.push((x_point * self.scale, y_point * self.scale)); index += 1; } vec } -} \ No newline at end of file + + pub fn around(&self, x: f32, y: f32) -> Vec<(f32, f32)> { + let around = vec![ + (x + self.scale, y), + (x - self.scale, y), + (x + 0.5 * self.scale, y + VERTICAL_OFFSET * self.scale), + (x - 0.5 * self.scale, y + VERTICAL_OFFSET * self.scale), + (x + 0.5 * self.scale, y - VERTICAL_OFFSET * self.scale), + (x - 0.5 * self.scale, y - VERTICAL_OFFSET * self.scale), + ]; + + around + .iter() + .filter(|(x, y)| { + *x >= 0.0 + && *x < self.scale * self.len as f32 + && *y >= 0.0 + && *y < self.scale * self.len as f32 + }) + .map(|(x, y)| (*x, *y)) + .collect() + } +} diff --git a/src/main.rs b/src/main.rs index ab90b52..915072d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -39,6 +39,7 @@ fn main() { .add_systems(Update, subplate_automation::update_automation) .add_systems(Update, subplate_automation::update_automation_view) .add_systems(Update, subplate_automation::setup_hex_matrix) + .add_systems(Update, subplate_automation::update_hex_matrix_view) .run(); } diff --git a/src/plate_automation.rs b/src/plate_automation.rs index e0f1f84..a2b798b 100644 --- a/src/plate_automation.rs +++ b/src/plate_automation.rs @@ -64,8 +64,8 @@ pub fn update_automation( if keys.just_pressed(KeyCode::Enter) { println!("Switching to SubPlateAutomation"); - let mut new_table = Table::::new(Color::NONE, automation.world.side); - automation.world.convert_copy(&mut new_table, |value| { if value { Color::WHITE } else { Color::NONE} }); + let mut new_table = Table::::new(0, automation.world.side); + automation.world.convert_copy(&mut new_table, |value| { if value { u8::MAX } else { 0 } }); commands.entity(entity).remove::().insert(SubPlateAutomation{ world: new_table }); @@ -104,6 +104,5 @@ impl PlateAutomation { self.world.data = updated; - println!("Time elapsed: {:?} ms", time.elapsed().as_millis()); } } diff --git a/src/subplate_automation.rs b/src/subplate_automation.rs index d2c307a..9d67a45 100644 --- a/src/subplate_automation.rs +++ b/src/subplate_automation.rs @@ -1,17 +1,15 @@ use crate::basic::{IntoImage, Table}; use crate::hex_table::HexTable; -use crate::{RECTANGLE_SIDE, SeededRng}; +use crate::SeededRng; use bevy::asset::{Assets, RenderAssetUsages}; use bevy::image::{BevyDefault, Image}; use bevy::input::ButtonInput; -use bevy::math::Vec2; -use bevy::prelude::{Color, Commands, Component, Entity, KeyCode, Query, Res, ResMut, Sprite, With}; +use bevy::prelude::{Color, Commands, Component, Entity, KeyCode, Query, Res, ResMut, Sprite, Text, With}; use bevy::render::render_resource::{Extent3d, TextureDimension, TextureFormat}; use bevy::tasks::futures_lite::StreamExt; use rand::RngExt; use rand_chacha::ChaCha8Rng; -use rayon::iter::IntoParallelIterator; -use rayon::iter::ParallelIterator; +use std::collections::HashMap; use std::time::Instant; pub fn update_automation_view( @@ -42,9 +40,10 @@ pub fn update_automation_view( pub fn update_automation( mut query: Query<(&mut SubPlateAutomation, Entity)>, + mut hex_query: Query<&HexMatrixBuild>, mut seeded_rng: ResMut, keys: Res>, - commands: Commands, + mut commands: Commands, ) { if query.is_empty() { return; @@ -60,17 +59,27 @@ pub fn update_automation( if keys.just_pressed(KeyCode::AltLeft) { let random = &mut seeded_rng.0; - automation.seed(random); + for _ in 0..16 { + automation.seed(random); + } } - if keys.just_pressed(KeyCode::AltRight) { - automation.smooth(); + // if keys.just_pressed(KeyCode::AltRight) { + // automation.smooth(); + // } + + if keys.just_pressed(KeyCode::KeyS) { + automation.calculate_subplates(&mut commands); + } + + if keys.just_pressed(KeyCode::KeyF) { + automation.calculate_front_lines(&mut commands, hex_query); } } #[derive(Component)] pub struct SubPlateAutomation { - pub(crate) world: Table, + pub(crate) world: Table, } impl SubPlateAutomation { @@ -79,7 +88,7 @@ impl SubPlateAutomation { for index in 0..self.world.side * self.world.side { let current_color = *self.world.get(index); - if current_color == Color::NONE || current_color != Color::WHITE { + if current_color == 0 || current_color != u8::MAX { continue; } @@ -91,7 +100,7 @@ impl SubPlateAutomation { .world .around_line(index) .iter() - .filter(|v| ***v != Color::WHITE && ***v != Color::NONE) + .filter(|v| ***v != u8::MAX && ***v != 0) .map(|color| (*color).clone()) .collect::>(); @@ -103,14 +112,13 @@ impl SubPlateAutomation { self.world.set(index, color); } - println!("Time elapsed: {:?} ms", time.elapsed().as_millis()); } fn smooth(&mut self) { let range = 0..self.world.side * self.world.side; for index in range { let around = self.world.around_line(index); - let mut counts: Vec<(Color, u8)> = vec![]; + let mut counts: Vec<(u8, u8)> = vec![]; for p in around { for count_index in 0..counts.len() { if counts[count_index].0 == *p { @@ -129,15 +137,44 @@ impl SubPlateAutomation { let len = (self.world.side * self.world.side) as f32; loop { let index = (rng.random::() * len) as usize; - if *self.world.get(index) == Color::NONE { + if *self.world.get(index) == 0 { continue; } self.world - .set(index, Color::hsv(rng.random::() * 360.0, 1.0, 1.0)); + .set(index, rng.random::()); break; } } + + fn calculate_front_lines(&self, commands: &mut Commands, hex_query: Query<&HexMatrixBuild>) { + + let generator = &hex_query.iter().next().unwrap().hex_matrix; + let all_points = generator.calculate(); + + let own_points = all_points.iter().map(|(x, y)| { + let x_table = *x as usize; + let y_table = *y as usize; + + (*self.world.get_dim(x_table, y_table), x, y) + }).filter(|(v, _, _)| { + *v != 0 + }); + + commands.spawn((HexMatrixRedrawRequest)); + } + fn calculate_subplates(&self, commands: &mut Commands) { + let mut list : HashMap> = HashMap::new(); + self.world.iter().zip(0..self.world.data.len()).for_each(|(world, index)| { + if list.contains_key(world) { + list.get_mut(world).unwrap().push(index); + } + else { + list.insert(world.clone(), vec![index]); + } + }); + println!("{:?}", list.iter().map(|(c, v)| (c.clone(), v.len())).collect::>()); + } } pub fn setup_hex_matrix( @@ -159,17 +196,13 @@ pub fn setup_hex_matrix( let resolution = automation.world.side / 4; - let generator = HexTable::new(resolution); + let generator = HexTable::new(resolution, 4.0); let mut table = Table::new(false, automation.world.side); generator.calculate().iter().for_each(|(x, y)| { - let x = (x * 4.0) as usize; - let y = (y * 4.0) as usize; + let x = *x as usize; + let y = *y as usize; - if x + y * table.side >= table.data.len() { - return; - } - - if *automation.world.get_dim(x, y) == Color::NONE { + if *automation.world.get_dim(x, y) == 0 { return; } @@ -195,17 +228,58 @@ pub fn setup_hex_matrix( images.remove(sprite.image.id()); images.insert(sprite.image.id(), image).unwrap(); commands.spawn((HexMatrixBuild{ - points: table - },)); + points: table, + hex_matrix: generator, + })); } + +pub fn update_hex_matrix_view( + mut data_query: Query<&HexMatrixBuild>, + mut request_query: Query>, + mut view_query: Query<&Sprite, With>, + mut commands: Commands, + mut images: ResMut>, +){ + if request_query.is_empty() { + return; + } + + let req = request_query.iter_mut().next().unwrap(); + commands.entity(req).despawn(); + println!("Update hex matrix view"); + let table = data_query.iter_mut().next().unwrap(); + let data = table.points.get_image_data(); + + let image = Image::new( + Extent3d { + width: table.points.side as u32, + height: table.points.side as u32, + depth_or_array_layers: 1, + }, + TextureDimension::D2, + data, + TextureFormat::bevy_default(), + RenderAssetUsages::default(), + ); + + let sprite = view_query.iter().next().unwrap(); + + + images.remove(sprite.image.id()); + images.insert(sprite.image.id(), image).unwrap(); +} #[derive(Component)] pub struct HexMatrixRequest; +#[derive(Component)] +pub struct HexMatrixRedrawRequest; + #[derive(Component)] pub struct HexMatrixView; #[derive(Component)] pub struct HexMatrixBuild{ - points: Table -} + points: Table, + hex_matrix: HexTable +} \ No newline at end of file