# HG changeset patch # User unC0Rr # Date 1738680796 -3600 # Node ID ee8b894272d0ff367b475d7cfb07b7ab2d8686e1 # Parent f79c6c7151323d6710379e81ba2caeaa0ded1628 Implement shoppa border generation diff -r f79c6c715132 -r ee8b894272d0 qmlfrontend/engine_instance.cpp --- a/qmlfrontend/engine_instance.cpp Tue Feb 04 15:52:02 2025 +0100 +++ b/qmlfrontend/engine_instance.cpp Tue Feb 04 15:53:16 2025 +0100 @@ -110,7 +110,7 @@ void EngineInstance::setOpenGLContext(QOpenGLContext* context) { currentOpenglContext = context; - auto size = context->surface()->size(); + const auto size = context->surface()->size(); setup_current_gl_context(m_instance.get(), static_cast(size.width()), static_cast(size.height()), &getProcAddress); diff -r f79c6c715132 -r ee8b894272d0 rust/mapgen/src/lib.rs --- a/rust/mapgen/src/lib.rs Tue Feb 04 15:52:02 2025 +0100 +++ b/rust/mapgen/src/lib.rs Tue Feb 04 15:53:16 2025 +0100 @@ -23,6 +23,7 @@ use rand::prelude::IndexedRandom; use std::{borrow::Borrow, collections::hash_map::HashMap}; +use std::fmt::Debug; use vec2d::Vec2D; #[derive(PartialEq, Eq, Hash, Clone, Debug)] @@ -66,7 +67,10 @@ let mut texture = Vec2D::new(&land.size().size(), 0); if let Some(land_sprite) = theme.land_texture() { - for (sprite_row, (land_row, tex_row)) in land_sprite.rows().cycle().zip(land.rows().zip(texture.rows_mut())) + for (sprite_row, (land_row, tex_row)) in land_sprite + .rows() + .cycle() + .zip(land.rows().zip(texture.rows_mut())) { let mut x_offset = 0; while sprite_row.len() < land.width() - x_offset { @@ -91,39 +95,44 @@ ); } } + } else { + eprintln!("No land texture, expect empty land"); } - if let Some(border_sprite) = theme.border_texture() { - assert!(border_sprite.height() <= 512); - let border_width = (border_sprite.height() / 2) as u8; - let border_sprite = border_sprite.to_tiled(); + if true { + shoppa_border(parameters.basic(), &land, &mut texture, 8); + } else { + if let Some(border_sprite) = theme.border_texture() { + assert!(border_sprite.height() <= 512); + let border_width = (border_sprite.height() / 2) as u8; + let border_sprite = border_sprite.to_tiled(); - let mut offsets = vec![255u8; land.width()]; + let mut offsets = vec![255u8; land.width()]; - land_border_pass( - parameters.basic(), - land.rows().rev().zip(texture.rows_mut().rev()), - &mut offsets, - border_width, - |x, y| { - border_sprite.get_pixel( - x % border_sprite.width() as usize, - border_sprite.height() as usize - 1 - y, - ) - }, - ); + land_border_pass( + parameters.basic(), + land.rows().rev().zip(texture.rows_mut().rev()), + &mut offsets, + border_width, + |x, y| { + border_sprite.get_pixel( + x % border_sprite.width() as usize, + border_sprite.height() as usize - 1 - y, + ) + }, + ); - offsets.iter_mut().for_each(|v| *v = 255); + offsets.iter_mut().for_each(|v| *v = 255); - land_border_pass( - parameters.basic(), - land.rows().zip(texture.rows_mut()), - &mut offsets, - border_width, - |x, y| border_sprite.get_pixel(x % border_sprite.width() as usize, y), - ); + land_border_pass( + parameters.basic(), + land.rows().zip(texture.rows_mut()), + &mut offsets, + border_width, + |x, y| border_sprite.get_pixel(x % border_sprite.width() as usize, y), + ); + } } - texture } } @@ -276,6 +285,88 @@ } } +fn shoppa_border( + basic_value: LandT, + land: &Land2D, + texture: &mut Vec2D, + depth: u8, +) where + LandT: Copy + Default + PartialEq, +{ + //land.rows().rev().zip(texture.rows_mut().rev()), + let mut depth_field = Vec2D::new(&land.size().size(), 0u8); + + for (d, l) in depth_field + .as_mut_slice() + .iter_mut() + .zip(land.raw_pixels().iter()) + { + *d = if *l == basic_value { depth } else { 0 }; + } + + let chunk_size = depth_field.width(); + for i in 1..depth_field.height() { + let split_index = i * chunk_size; + let (left, right) = depth_field.as_mut_slice().split_at_mut(split_index); + + let prev_chunk = &left[(i - 1) * chunk_size..i * chunk_size]; + let cur_chunk = &mut right[..chunk_size]; + process_shoppa_row_pair(prev_chunk, cur_chunk); + } + + for i in (1..depth_field.height()).rev() { + let split_index = i * chunk_size; + let (left, right) = depth_field.as_mut_slice().split_at_mut(split_index); + + let cur_chunk = &mut left[(i - 1) * chunk_size..i * chunk_size]; + let prev_chunk = &right[..chunk_size]; + process_shoppa_row_pair(prev_chunk, cur_chunk); + } + + for r in depth_field.rows_mut() { + let mut it = r.iter_mut(); + let mut p = *it.next().unwrap(); + for c in it { + if p < *c { + *c = p + 1; + } + + p = *c + } + + let mut it = r.iter_mut().rev(); + let mut p = *it.next().unwrap(); + for c in it { + if p < *c { + *c = p + 1; + } + + p = *c + } + } + + for (row_index, (tex_row, depth_row)) in texture.rows_mut().zip(depth_field.rows()).enumerate() + { + for (column_index, (tex, &d)) in tex_row.iter_mut().zip(depth_row.iter()).enumerate() { + if d > 0 && d < depth { + *tex = if ((row_index + column_index) / 8) & 1 != 0 { + 0xff00ffff + } else { + 0xff000000 + }; + } + } + } +} + +fn process_shoppa_row_pair(prev_chunk: &[u8], cur_chunk: &mut [u8]) { + for (&p, c) in prev_chunk.iter().zip(cur_chunk.iter_mut()) { + if p < *c { + *c = p + 1; + } + } +} + fn tex_row_copy( basic_value: LandT, land_row: &[LandT], diff -r f79c6c715132 -r ee8b894272d0 rust/mapgen/src/theme.rs --- a/rust/mapgen/src/theme.rs Tue Feb 04 15:52:02 2025 +0100 +++ b/rust/mapgen/src/theme.rs Tue Feb 04 15:53:16 2025 +0100 @@ -1,5 +1,7 @@ +use integral_geometry::Size; use integral_geometry::{Point, Rect}; use png::{ColorType, Decoder, DecodingError}; +use std::slice::ChunksExact; use std::{ fs::{read_dir, File}, io, @@ -7,8 +9,6 @@ path::Path, slice::{from_raw_parts, from_raw_parts_mut}, }; -use std::slice::ChunksExact; -use integral_geometry::Size; use vec2d::Vec2D; pub struct ThemeSprite {