Skip to content

Conversation

@dizzyi
Copy link

@dizzyi dizzyi commented Aug 15, 2025

Development Workflow

  • cargo clippy
  • cargo build
  • cargo fmt
  • cargo rustdoc
  • cargo test

Added

examples/rect_map.rs

An example of using RectMap.

cargo run --example rect_map --features "bevy"
image

src/storage/rect.rs

  • unit test

A hex storage map that internally use an 1D Vec, and index by converting to offset coordinate.

pub struct RectMap<T> {
    inner: Vec<T>,
    meta: RectMetadata,
}

The meta data for RectMap, but also act as the builder.

pub struct RectMetadata {
    hex_layout: HexLayout,
    offset_mode: OffsetHexMode,
    half_size: IVec2,
    wrap_strategies: [WrapStrategy; 2],
}

Wrapping Strategy when trying to wrap hex coordinate to ensure it contain inside the map.

pub enum WrapStrategy {
    Clamp,
    Cycle,
}

Example

let rect_hex_map = RectMetadata::default()
    .with_hex_layout(HexLayout::pointy().with_hex_size(1.0))
    .with_half_size(IVec2::new(8,12))
    .with_offset_mode(OffsetHexMode::Odd)
    .with_wrap_strategies([WrapStrategy::Cycle, WrapStrategy::Clamp])
    .build_default::<i32>();

feature bevy_ecs

Added feature to derive Resource and Component for hexx's types.

#[cfg_attr(
    feature = "bevy_ecs",
    derive(bevy_ecs::resource::Resource, bevy_ecs::component::Component)
)]
#[derive(Clone)]
pub struct RectMap<T> {
    /* ... */
}

Copy link
Owner

@ManevilleF ManevilleF left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot for this PR, this is a useful feature and I appreciate the amount of tests and documentation, especially a fully fledged bevy example !

I did a first review, as I wish for some API changes, I did not test the code or the example yet

Comment on lines 450 to 455
impl<T> std::ops::Deref for RectMap<T> {
type Target = RectMetadata;
fn deref(&self) -> &Self::Target {
&self.meta
}
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this Deref needed ?

Copy link
Author

@dizzyi dizzyi Aug 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this Deref expose function inside RectMetadata function that take reference &RectMetadata: len, is_empty, iter_hex, contains_hex, wrap_hex, while avoiding exposing builder pattern function that take ownership RectMetadata, making a getter ->RectMetadata will expose builder pattern function, and getter -> &RectMetadata is just a more verbose version of this Deref

dizzyi and others added 9 commits August 16, 2025 23:39
Co-authored-by: Félix Lescaudey de Maneville <felix.maneville@gmail.com>
Co-authored-by: Félix Lescaudey de Maneville <felix.maneville@gmail.com>
@dizzyi
Copy link
Author

dizzyi commented Aug 17, 2025

Added more api to create size of map

pub fn from_half_size(half_size: UVec2) -> Self {}
pub fn from_start_end(start: IVec2, end IVec2) -> Self {}
pub const fn from_start_dim(start: IVec2, dim: UVec2) -> Self {}
image image

Copy link
Owner

@ManevilleF ManevilleF left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for all the improvements made,

I can see there is a bunch of tests, but they test the index logic without constructing a map
Could you add tests that check that:

  • RectMap::iter().count() == RectMap::len()
  • RectMap::new(.., |h| h) can be constructed and queried properly and the value is the correct one ?
  • Test that querying out of bounds does return None if no wrapping is set

Comment on lines +174 to +219
/// builder patter, set half size
///
/// # Param
/// * `half_size`: the half span of the map
///
/// the resulting map will have:
/// - columns: `-half_size[0]..(half_size[0] - 1)`, and
/// - rows: `-half_size[1]..(half_size[1] - 1)`, and
#[must_use]
pub fn with_half_size(mut self, half_size: IVec2) -> Self {
// self.half_size = half_size.abs();
self.start = -half_size.abs();
self.dim = (2 * half_size.abs()).as_uvec2();
self
}
/// builder patter, set start and end
///
/// # Param
/// * `start`: the element wise minimum offset coordinate in the map
/// * `end`: the element wise maximum offset coordinate in the map
///
/// the resulting map will have:
/// - columns: `start[0]..max(start[0], end[0])`
/// - rows: `start[1]..max(start[1], end[1])`
#[must_use]
pub fn with_start_end(mut self, start: IVec2, end: IVec2) -> Self {
// self.half_size = half_size.abs();
self.start = start;
self.dim = (end.max(start) - start).as_uvec2();
self
}
/// builder pattern, set start and dimension
///
/// # Param
/// * `start`: the element wise minimum offset coordinate in the map
/// * `dim`: the dimension of the map
///
/// the resulting map will have:
/// - columns: `start[0]..(start[0] + dim[0])`
/// - rows: `start[1]..(start[1] + dim[1])`
#[must_use]
pub const fn with_start_dim(mut self, start: IVec2, dim: UVec2) -> Self {
self.start = start;
self.dim = dim;
self
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are those methods needed ? The only usage I can think of would be to overwrite a cloned metadata with a different size

wrap_strategies: [WrapStrategy::Cycle, WrapStrategy::Clamp],
}
}
/// builder patter, set half size
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// builder patter, set half size
/// builder pattern, set half size

self.dim = (2 * half_size.abs()).as_uvec2();
self
}
/// builder patter, set start and end
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// builder patter, set start and end
/// builder pattern, set start and end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants